#include #include #include #include #include typedef struct SunMsgUdp SunMsgUdp; struct SunMsgUdp { SunMsg msg; Udphdr udp; }; typedef struct Arg Arg; struct Arg { SunSrv *srv; Channel *creply; Channel *csync; int fd; }; enum { UdpMaxRead = 65536+Udphdrsize }; static void sunudpread(void *v) { int n, paraport, port; uchar *buf; Arg arg = *(Arg*)v; SunMsgUdp *msg; SunSrv *srv; Udphdr udp; uchar localip[IPaddrlen]; sendp(arg.csync, 0); srv = arg.srv; paraport = -1; /* 127.1 */ memmove(localip, v4prefix, IPaddrlen); localip[12] = 127; localip[15] = 1; buf = emalloc(UdpMaxRead); while((n = udpread(arg.fd, &udp, buf, UdpMaxRead)) > 0){ if(arg.srv->chatty) fprint(2, "udpread got %d (%d) from %I\n", n, Udphdrsize, udp.raddr); msg = emalloc(sizeof(SunMsgUdp)); msg->udp = udp; msg->msg.data = emalloc(n); msg->msg.count = n; memmove(msg->msg.data, buf, n); msg->msg.creply = arg.creply; msg->msg.srv = arg.srv; if(arg.srv->chatty) fprint(2, "message %p count %d\n", msg, msg->msg.count); if((srv->localonly || srv->localparanoia) && ipcmp(udp.raddr, localip) != 0){ fprint(2, "dropping message from %I: not local\n", udp.raddr); sunmsgreplyerror(&msg->msg, SunAuthTooWeak); continue; } if(srv->localparanoia){ port = nhgets(udp.rport); if(paraport == -1){ fprint(2, "paranoid mode: only %I/%d allowed\n", localip, port); paraport = port; }else if(paraport != port){ fprint(2, "dropping message from %I: not port %d\n", udp.raddr, port); sunmsgreplyerror(&msg->msg, SunAuthTooWeak); continue; } } if(srv->ipokay && !srv->ipokay(udp.raddr, nhgets(udp.rport))) msg->msg.rpc.status = SunProgUnavail; sendp(arg.srv->crequest, msg); } } static void sunudpwrite(void *v) { Arg arg = *(Arg*)v; SunMsgUdp *msg; sendp(arg.csync, 0); while((msg = recvp(arg.creply)) != nil){ if(udpwrite(arg.fd, &msg->udp, msg->msg.data, msg->msg.count) != msg->msg.count) fprint(2, "udpwrite: %r\n"); sunmsgdrop(&msg->msg); } } int sunsrvudp(SunSrv *srv, char *address) { int fd; char adir[40]; Arg *arg; fd = announce(address, adir); if(fd < 0) return -1; arg = emalloc(sizeof(Arg)); arg->fd = fd; arg->srv = srv; arg->creply = chancreate(sizeof(SunMsg*), 10); arg->csync = chancreate(sizeof(void*), 10); proccreate(sunudpread, arg, SunStackSize); proccreate(sunudpwrite, arg, SunStackSize); recvp(arg->csync); recvp(arg->csync); chanfree(arg->csync); free(arg); return 0; }