blob: 2e107e658bc29bab1d890f9e496d52749bdb5e76 [file] [log] [blame]
rsc551445b2004-04-21 03:04:30 +00001#include <u.h>
2#include <libc.h>
3#include <ip.h>
4#include <thread.h>
5#include <sunrpc.h>
6
7typedef struct SunMsgUdp SunMsgUdp;
8struct SunMsgUdp
9{
10 SunMsg msg;
11 Udphdr udp;
12};
13
14typedef struct Arg Arg;
15struct Arg
16{
17 SunSrv *srv;
18 Channel *creply;
19 Channel *csync;
20 int fd;
21};
22
23enum
24{
25 UdpMaxRead = 65536+Udphdrsize
26};
27static void
28sunudpread(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);
rsc4c06b8e2005-05-19 14:39:10 +000051 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);
rsc551445b2004-04-21 03:04:30 +000060 if((srv->localonly || srv->localparanoia) && ipcmp(udp.raddr, localip) != 0){
61 fprint(2, "dropping message from %I: not local\n", udp.raddr);
rsc4c06b8e2005-05-19 14:39:10 +000062 sunmsgreplyerror(&msg->msg, SunAuthTooWeak);
rsc551445b2004-04-21 03:04:30 +000063 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);
rsc4c06b8e2005-05-19 14:39:10 +000072 sunmsgreplyerror(&msg->msg, SunAuthTooWeak);
rsc551445b2004-04-21 03:04:30 +000073 continue;
74 }
75 }
rsc4c06b8e2005-05-19 14:39:10 +000076 if(srv->ipokay && !srv->ipokay(udp.raddr, nhgets(udp.rport)))
77 msg->msg.rpc.status = SunProgUnavail;
rsc551445b2004-04-21 03:04:30 +000078 sendp(arg.srv->crequest, msg);
79 }
80}
81
82static void
83sunudpwrite(void *v)
84{
85 uchar *buf;
86 Arg arg = *(Arg*)v;
87 SunMsgUdp *msg;
88
89 sendp(arg.csync, 0);
90
91 buf = emalloc(UdpMaxRead);
92 while((msg = recvp(arg.creply)) != nil){
93 if(udpwrite(arg.fd, &msg->udp, msg->msg.data, msg->msg.count) != msg->msg.count)
94 fprint(2, "udpwrite: %r\n");
95 free(msg->msg.data);
96 free(msg);
97 }
98}
99
100int
101sunsrvudp(SunSrv *srv, char *address)
102{
103 int fd;
104 char adir[40];
105 Arg *arg;
106
107 fd = announce(address, adir);
108 if(fd < 0)
109 return -1;
110
111 arg = emalloc(sizeof(Arg));
112 arg->fd = fd;
113 arg->srv = srv;
114 arg->creply = chancreate(sizeof(SunMsg*), 10);
115 arg->csync = chancreate(sizeof(void*), 10);
116
117 proccreate(sunudpread, arg, SunStackSize);
118 proccreate(sunudpwrite, arg, SunStackSize);
119 recvp(arg->csync);
120 recvp(arg->csync);
121 chanfree(arg->csync);
122 free(arg);
123
124 return 0;
125}