1*8ccd4a63SDavid du Colombier #include <u.h>
2*8ccd4a63SDavid du Colombier #include <libc.h>
3*8ccd4a63SDavid du Colombier #include <ip.h>
4*8ccd4a63SDavid du Colombier #include <thread.h>
5*8ccd4a63SDavid du Colombier #include "netbios.h"
6*8ccd4a63SDavid du Colombier
7*8ccd4a63SDavid du Colombier static struct {
8*8ccd4a63SDavid du Colombier int thread;
9*8ccd4a63SDavid du Colombier QLock;
10*8ccd4a63SDavid du Colombier int fd;
11*8ccd4a63SDavid du Colombier } udp = { -1 };
12*8ccd4a63SDavid du Colombier
13*8ccd4a63SDavid du Colombier typedef struct Listen Listen;
14*8ccd4a63SDavid du Colombier
15*8ccd4a63SDavid du Colombier struct Listen {
16*8ccd4a63SDavid du Colombier NbName to;
17*8ccd4a63SDavid du Colombier int (*deliver)(void *magic, NbDgram *s);
18*8ccd4a63SDavid du Colombier void *magic;
19*8ccd4a63SDavid du Colombier Listen *next;
20*8ccd4a63SDavid du Colombier };
21*8ccd4a63SDavid du Colombier
22*8ccd4a63SDavid du Colombier static struct {
23*8ccd4a63SDavid du Colombier QLock;
24*8ccd4a63SDavid du Colombier Listen *head;
25*8ccd4a63SDavid du Colombier } listens;
26*8ccd4a63SDavid du Colombier
27*8ccd4a63SDavid du Colombier static void
udplistener(void *)28*8ccd4a63SDavid du Colombier udplistener(void *)
29*8ccd4a63SDavid du Colombier {
30*8ccd4a63SDavid du Colombier //print("udplistener - starting\n");
31*8ccd4a63SDavid du Colombier for (;;) {
32*8ccd4a63SDavid du Colombier uchar msg[Udphdrsize + 576];
33*8ccd4a63SDavid du Colombier int len = read(udp.fd, msg, sizeof(msg));
34*8ccd4a63SDavid du Colombier if (len < 0)
35*8ccd4a63SDavid du Colombier break;
36*8ccd4a63SDavid du Colombier if (len >= nbudphdrsize) {
37*8ccd4a63SDavid du Colombier NbDgram s;
38*8ccd4a63SDavid du Colombier // Udphdr *uh;
39*8ccd4a63SDavid du Colombier uchar *p;
40*8ccd4a63SDavid du Colombier int n;
41*8ccd4a63SDavid du Colombier
42*8ccd4a63SDavid du Colombier // uh = (Udphdr*)msg;
43*8ccd4a63SDavid du Colombier p = msg + nbudphdrsize;
44*8ccd4a63SDavid du Colombier len -= nbudphdrsize;
45*8ccd4a63SDavid du Colombier n = nbdgramconvM2S(&s, p, p + len);
46*8ccd4a63SDavid du Colombier if (n) {
47*8ccd4a63SDavid du Colombier switch (s.type) {
48*8ccd4a63SDavid du Colombier case NbDgramError:
49*8ccd4a63SDavid du Colombier print("nbdgramlisten: error: ip %I port %d code 0x%.2ux\n", s.srcip, s.srcport, s.error.code);
50*8ccd4a63SDavid du Colombier break;
51*8ccd4a63SDavid du Colombier case NbDgramDirectUnique:
52*8ccd4a63SDavid du Colombier case NbDgramDirectGroup:
53*8ccd4a63SDavid du Colombier case NbDgramBroadcast: {
54*8ccd4a63SDavid du Colombier int delivered = 0;
55*8ccd4a63SDavid du Colombier Listen **lp, *l;
56*8ccd4a63SDavid du Colombier if ((s.flags & NbDgramMore) || s.datagram.offset != 0)
57*8ccd4a63SDavid du Colombier break;
58*8ccd4a63SDavid du Colombier if (!nbnameisany(s.datagram.dstname)
59*8ccd4a63SDavid du Colombier && !nbnametablefind(s.datagram.dstname, 0)) {
60*8ccd4a63SDavid du Colombier /* - only do this if a broadcast node, and can tell when packets are broadcast...
61*8ccd4a63SDavid du Colombier s.flags &= 3;
62*8ccd4a63SDavid du Colombier ipmove(s.srcip, nbglobals.myipaddr);
63*8ccd4a63SDavid du Colombier s.srcport = NbDgramPort;
64*8ccd4a63SDavid du Colombier s.type = NbDgramError;
65*8ccd4a63SDavid du Colombier s.error.code = NbDgramErrorDestinationNameNotPresent;
66*8ccd4a63SDavid du Colombier nbdgramsendto(uh->raddr, nhgets(uh->rport), &s);
67*8ccd4a63SDavid du Colombier */
68*8ccd4a63SDavid du Colombier break;
69*8ccd4a63SDavid du Colombier }
70*8ccd4a63SDavid du Colombier qlock(&listens);
71*8ccd4a63SDavid du Colombier for (lp = &listens.head; (l = *lp) != nil;) {
72*8ccd4a63SDavid du Colombier if (nbnameisany(l->to) || nbnameequal(l->to, s.datagram.dstname)) {
73*8ccd4a63SDavid du Colombier switch ((*l->deliver)(l->magic, &s)) {
74*8ccd4a63SDavid du Colombier case 0:
75*8ccd4a63SDavid du Colombier delivered = 1;
76*8ccd4a63SDavid du Colombier /* fall through */
77*8ccd4a63SDavid du Colombier case -1:
78*8ccd4a63SDavid du Colombier *lp = l->next;
79*8ccd4a63SDavid du Colombier free(l);
80*8ccd4a63SDavid du Colombier continue;
81*8ccd4a63SDavid du Colombier default:
82*8ccd4a63SDavid du Colombier delivered = 1;
83*8ccd4a63SDavid du Colombier break;
84*8ccd4a63SDavid du Colombier }
85*8ccd4a63SDavid du Colombier }
86*8ccd4a63SDavid du Colombier lp = &l->next;
87*8ccd4a63SDavid du Colombier }
88*8ccd4a63SDavid du Colombier qunlock(&listens);
89*8ccd4a63SDavid du Colombier USED(delivered);
90*8ccd4a63SDavid du Colombier }
91*8ccd4a63SDavid du Colombier default:
92*8ccd4a63SDavid du Colombier ;
93*8ccd4a63SDavid du Colombier }
94*8ccd4a63SDavid du Colombier }
95*8ccd4a63SDavid du Colombier }
96*8ccd4a63SDavid du Colombier }
97*8ccd4a63SDavid du Colombier print("udplistener - exiting\n");
98*8ccd4a63SDavid du Colombier qlock(&udp);
99*8ccd4a63SDavid du Colombier udp.thread = -1;
100*8ccd4a63SDavid du Colombier qunlock(&udp);
101*8ccd4a63SDavid du Colombier }
102*8ccd4a63SDavid du Colombier
103*8ccd4a63SDavid du Colombier static char *
startlistener(void)104*8ccd4a63SDavid du Colombier startlistener(void)
105*8ccd4a63SDavid du Colombier {
106*8ccd4a63SDavid du Colombier qlock(&udp);
107*8ccd4a63SDavid du Colombier if (udp.thread < 0) {
108*8ccd4a63SDavid du Colombier char *e;
109*8ccd4a63SDavid du Colombier e = nbudpannounce(NbDgramPort, &udp.fd);
110*8ccd4a63SDavid du Colombier if (e) {
111*8ccd4a63SDavid du Colombier qunlock(&udp);
112*8ccd4a63SDavid du Colombier return e;
113*8ccd4a63SDavid du Colombier }
114*8ccd4a63SDavid du Colombier udp.thread = proccreate(udplistener, nil, 16384);
115*8ccd4a63SDavid du Colombier }
116*8ccd4a63SDavid du Colombier qunlock(&udp);
117*8ccd4a63SDavid du Colombier return nil;
118*8ccd4a63SDavid du Colombier }
119*8ccd4a63SDavid du Colombier
120*8ccd4a63SDavid du Colombier char *
nbdgramlisten(NbName to,int (* deliver)(void * magic,NbDgram * s),void * magic)121*8ccd4a63SDavid du Colombier nbdgramlisten(NbName to, int (*deliver)(void *magic, NbDgram *s), void *magic)
122*8ccd4a63SDavid du Colombier {
123*8ccd4a63SDavid du Colombier Listen *l;
124*8ccd4a63SDavid du Colombier char *e;
125*8ccd4a63SDavid du Colombier nbnametablefind(to, 1);
126*8ccd4a63SDavid du Colombier e = startlistener();
127*8ccd4a63SDavid du Colombier if (e)
128*8ccd4a63SDavid du Colombier return e;
129*8ccd4a63SDavid du Colombier l = nbemalloc(sizeof(Listen));
130*8ccd4a63SDavid du Colombier nbnamecpy(l->to, to);
131*8ccd4a63SDavid du Colombier l->deliver = deliver;
132*8ccd4a63SDavid du Colombier l->magic = magic;
133*8ccd4a63SDavid du Colombier qlock(&listens);
134*8ccd4a63SDavid du Colombier l->next = listens.head;
135*8ccd4a63SDavid du Colombier listens.head = l;
136*8ccd4a63SDavid du Colombier qunlock(&listens);
137*8ccd4a63SDavid du Colombier return 0;
138*8ccd4a63SDavid du Colombier }
139*8ccd4a63SDavid du Colombier
140*8ccd4a63SDavid du Colombier int
nbdgramsendto(uchar * ipaddr,ushort port,NbDgram * s)141*8ccd4a63SDavid du Colombier nbdgramsendto(uchar *ipaddr, ushort port, NbDgram *s)
142*8ccd4a63SDavid du Colombier {
143*8ccd4a63SDavid du Colombier Udphdr *u;
144*8ccd4a63SDavid du Colombier uchar msg[NbDgramMaxPacket + Udphdrsize];
145*8ccd4a63SDavid du Colombier int l;
146*8ccd4a63SDavid du Colombier int rv;
147*8ccd4a63SDavid du Colombier char *e;
148*8ccd4a63SDavid du Colombier
149*8ccd4a63SDavid du Colombier e = startlistener();
150*8ccd4a63SDavid du Colombier if (e != nil)
151*8ccd4a63SDavid du Colombier return 0;
152*8ccd4a63SDavid du Colombier
153*8ccd4a63SDavid du Colombier l = nbdgramconvS2M(msg + nbudphdrsize, msg + sizeof(msg), s);
154*8ccd4a63SDavid du Colombier if (l == 0) {
155*8ccd4a63SDavid du Colombier print("conv failed\n");
156*8ccd4a63SDavid du Colombier return 0;
157*8ccd4a63SDavid du Colombier }
158*8ccd4a63SDavid du Colombier u = (Udphdr *)msg;
159*8ccd4a63SDavid du Colombier ipmove(u->laddr, nbglobals.myipaddr);
160*8ccd4a63SDavid du Colombier hnputs(u->lport, NbDgramPort);
161*8ccd4a63SDavid du Colombier ipmove(u->raddr, ipaddr);
162*8ccd4a63SDavid du Colombier hnputs(u->rport, port);
163*8ccd4a63SDavid du Colombier //nbdumpdata(msg, l + nbudphdrsize);
164*8ccd4a63SDavid du Colombier //print("transmitting\n");
165*8ccd4a63SDavid du Colombier rv = write(udp.fd, msg, l + nbudphdrsize);
166*8ccd4a63SDavid du Colombier //print("rv %d l %d hdrsize %d error %r\n", rv, l, nbudphdrsize);
167*8ccd4a63SDavid du Colombier return rv == l + nbudphdrsize;
168*8ccd4a63SDavid du Colombier }
169*8ccd4a63SDavid du Colombier
170*8ccd4a63SDavid du Colombier static struct {
171*8ccd4a63SDavid du Colombier Lock;
172*8ccd4a63SDavid du Colombier ushort id;
173*8ccd4a63SDavid du Colombier } id;
174*8ccd4a63SDavid du Colombier
175*8ccd4a63SDavid du Colombier static ushort
nextdgramid(void)176*8ccd4a63SDavid du Colombier nextdgramid(void)
177*8ccd4a63SDavid du Colombier {
178*8ccd4a63SDavid du Colombier ushort v;
179*8ccd4a63SDavid du Colombier lock(&id);
180*8ccd4a63SDavid du Colombier v = id.id++;
181*8ccd4a63SDavid du Colombier unlock(&id);
182*8ccd4a63SDavid du Colombier return v;
183*8ccd4a63SDavid du Colombier }
184*8ccd4a63SDavid du Colombier
185*8ccd4a63SDavid du Colombier int
nbdgramsend(NbDgramSendParameters * p,uchar * data,long datalen)186*8ccd4a63SDavid du Colombier nbdgramsend(NbDgramSendParameters *p, uchar *data, long datalen)
187*8ccd4a63SDavid du Colombier {
188*8ccd4a63SDavid du Colombier NbDgram s;
189*8ccd4a63SDavid du Colombier uchar dstip[IPaddrlen];
190*8ccd4a63SDavid du Colombier s.type = p->type;
191*8ccd4a63SDavid du Colombier switch (p->type) {
192*8ccd4a63SDavid du Colombier case NbDgramBroadcast:
193*8ccd4a63SDavid du Colombier case NbDgramDirectGroup:
194*8ccd4a63SDavid du Colombier ipmove(dstip, nbglobals.bcastaddr);
195*8ccd4a63SDavid du Colombier break;
196*8ccd4a63SDavid du Colombier case NbDgramDirectUnique:
197*8ccd4a63SDavid du Colombier if (!nbnameresolve(p->to, dstip)) {
198*8ccd4a63SDavid du Colombier werrstr("nbdgramsend: name resolution failed");
199*8ccd4a63SDavid du Colombier return 0;
200*8ccd4a63SDavid du Colombier }
201*8ccd4a63SDavid du Colombier break;
202*8ccd4a63SDavid du Colombier default:
203*8ccd4a63SDavid du Colombier werrstr("nbdgramsend: illegal datagram type");
204*8ccd4a63SDavid du Colombier return 0;
205*8ccd4a63SDavid du Colombier }
206*8ccd4a63SDavid du Colombier s.flags = NbDgramFirst;
207*8ccd4a63SDavid du Colombier s.id = nextdgramid();
208*8ccd4a63SDavid du Colombier ipmove(s.srcip, nbglobals.myipaddr);
209*8ccd4a63SDavid du Colombier s.srcport = NbDgramPort;
210*8ccd4a63SDavid du Colombier s.datagram.offset = 0;
211*8ccd4a63SDavid du Colombier s.datagram.data = data;
212*8ccd4a63SDavid du Colombier s.datagram.length = datalen;
213*8ccd4a63SDavid du Colombier nbnamecpy(s.datagram.dstname, p->to);
214*8ccd4a63SDavid du Colombier nbnamecpy(s.datagram.srcname, nbglobals.myname);
215*8ccd4a63SDavid du Colombier return nbdgramsendto(dstip, NbDgramPort, &s);
216*8ccd4a63SDavid du Colombier }
217