plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }