udp.c (2544B)
1 #include <u.h> 2 #include <libc.h> 3 #include <ip.h> 4 #include <thread.h> 5 #include <sunrpc.h> 6 7 typedef struct SunMsgUdp SunMsgUdp; 8 struct SunMsgUdp 9 { 10 SunMsg msg; 11 Udphdr udp; 12 }; 13 14 typedef struct Arg Arg; 15 struct Arg 16 { 17 SunSrv *srv; 18 Channel *creply; 19 Channel *csync; 20 int fd; 21 }; 22 23 enum 24 { 25 UdpMaxRead = 65536+Udphdrsize 26 }; 27 static void 28 sunudpread(void *v) 29 { 30 int n, paraport, port; 31 uchar *buf; 32 Arg arg = *(Arg*)v; 33 SunMsgUdp *msg; 34 SunSrv *srv; 35 Udphdr udp; 36 uchar localip[IPaddrlen]; 37 38 sendp(arg.csync, 0); 39 srv = arg.srv; 40 paraport = -1; 41 42 /* 127.1 */ 43 memmove(localip, v4prefix, IPaddrlen); 44 localip[12] = 127; 45 localip[15] = 1; 46 47 buf = emalloc(UdpMaxRead); 48 while((n = udpread(arg.fd, &udp, buf, UdpMaxRead)) > 0){ 49 if(arg.srv->chatty) 50 fprint(2, "udpread got %d (%d) from %I\n", n, Udphdrsize, udp.raddr); 51 msg = emalloc(sizeof(SunMsgUdp)); 52 msg->udp = udp; 53 msg->msg.data = emalloc(n); 54 msg->msg.count = n; 55 memmove(msg->msg.data, buf, n); 56 msg->msg.creply = arg.creply; 57 msg->msg.srv = arg.srv; 58 if(arg.srv->chatty) 59 fprint(2, "message %p count %d\n", msg, msg->msg.count); 60 if((srv->localonly || srv->localparanoia) && ipcmp(udp.raddr, localip) != 0){ 61 fprint(2, "dropping message from %I: not local\n", udp.raddr); 62 sunmsgreplyerror(&msg->msg, SunAuthTooWeak); 63 continue; 64 } 65 if(srv->localparanoia){ 66 port = nhgets(udp.rport); 67 if(paraport == -1){ 68 fprint(2, "paranoid mode: only %I/%d allowed\n", localip, port); 69 paraport = port; 70 }else if(paraport != port){ 71 fprint(2, "dropping message from %I: not port %d\n", udp.raddr, port); 72 sunmsgreplyerror(&msg->msg, SunAuthTooWeak); 73 continue; 74 } 75 } 76 if(srv->ipokay && !srv->ipokay(udp.raddr, nhgets(udp.rport))) 77 msg->msg.rpc.status = SunProgUnavail; 78 sendp(arg.srv->crequest, msg); 79 } 80 } 81 82 static void 83 sunudpwrite(void *v) 84 { 85 Arg arg = *(Arg*)v; 86 SunMsgUdp *msg; 87 88 sendp(arg.csync, 0); 89 90 while((msg = recvp(arg.creply)) != nil){ 91 if(udpwrite(arg.fd, &msg->udp, msg->msg.data, msg->msg.count) != msg->msg.count) 92 fprint(2, "udpwrite: %r\n"); 93 sunmsgdrop(&msg->msg); 94 } 95 } 96 97 int 98 sunsrvudp(SunSrv *srv, char *address) 99 { 100 int fd; 101 char adir[40]; 102 Arg *arg; 103 104 fd = announce(address, adir); 105 if(fd < 0) 106 return -1; 107 108 arg = emalloc(sizeof(Arg)); 109 arg->fd = fd; 110 arg->srv = srv; 111 arg->creply = chancreate(sizeof(SunMsg*), 10); 112 arg->csync = chancreate(sizeof(void*), 10); 113 114 proccreate(sunudpread, arg, SunStackSize); 115 proccreate(sunudpwrite, arg, SunStackSize); 116 recvp(arg->csync); 117 recvp(arg->csync); 118 chanfree(arg->csync); 119 free(arg); 120 121 return 0; 122 }