1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#include <u.h>
#include <libc.h>
#include <ip.h>
#include <thread.h>
#include <sunrpc.h>
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)
{
uchar *buf;
Arg arg = *(Arg*)v;
SunMsgUdp *msg;
sendp(arg.csync, 0);
buf = emalloc(UdpMaxRead);
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");
free(msg->msg.data);
free(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;
}
|