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 Lock;
24*8ccd4a63SDavid du Colombier ushort id;
25*8ccd4a63SDavid du Colombier } id;
26*8ccd4a63SDavid du Colombier
27*8ccd4a63SDavid du Colombier struct {
28*8ccd4a63SDavid du Colombier QLock;
29*8ccd4a63SDavid du Colombier NbnsTransaction *head;
30*8ccd4a63SDavid du Colombier } transactionlist;
31*8ccd4a63SDavid du Colombier
32*8ccd4a63SDavid du Colombier static void
udplistener(void *)33*8ccd4a63SDavid du Colombier udplistener(void *)
34*8ccd4a63SDavid du Colombier {
35*8ccd4a63SDavid du Colombier for (;;) {
36*8ccd4a63SDavid du Colombier uchar msg[Udphdrsize + 576];
37*8ccd4a63SDavid du Colombier int len = read(udp.fd, msg, sizeof(msg));
38*8ccd4a63SDavid du Colombier if (len < 0)
39*8ccd4a63SDavid du Colombier break;
40*8ccd4a63SDavid du Colombier if (len >= nbudphdrsize) {
41*8ccd4a63SDavid du Colombier NbnsMessage *s;
42*8ccd4a63SDavid du Colombier // Udphdr *uh;
43*8ccd4a63SDavid du Colombier uchar *p;
44*8ccd4a63SDavid du Colombier
45*8ccd4a63SDavid du Colombier // uh = (Udphdr*)msg;
46*8ccd4a63SDavid du Colombier p = msg + nbudphdrsize;
47*8ccd4a63SDavid du Colombier len -= nbudphdrsize;
48*8ccd4a63SDavid du Colombier s = nbnsconvM2S(p, len);
49*8ccd4a63SDavid du Colombier if (s) {
50*8ccd4a63SDavid du Colombier //print("%I:%d -> %I:%d\n", uh->raddr, nhgets(uh->rport), uh->laddr, nhgets(uh->lport));
51*8ccd4a63SDavid du Colombier //nbnsdumpmessage(s);
52*8ccd4a63SDavid du Colombier if (s->response) {
53*8ccd4a63SDavid du Colombier NbnsTransaction *t;
54*8ccd4a63SDavid du Colombier qlock(&transactionlist);
55*8ccd4a63SDavid du Colombier for (t = transactionlist.head; t; t = t->next)
56*8ccd4a63SDavid du Colombier if (t->id == s->id)
57*8ccd4a63SDavid du Colombier break;
58*8ccd4a63SDavid du Colombier if (t)
59*8ccd4a63SDavid du Colombier sendp(t->c, s);
60*8ccd4a63SDavid du Colombier else
61*8ccd4a63SDavid du Colombier nbnsmessagefree(&s);
62*8ccd4a63SDavid du Colombier qunlock(&transactionlist);
63*8ccd4a63SDavid du Colombier }
64*8ccd4a63SDavid du Colombier else
65*8ccd4a63SDavid du Colombier nbnsmessagefree(&s);
66*8ccd4a63SDavid du Colombier }
67*8ccd4a63SDavid du Colombier }
68*8ccd4a63SDavid du Colombier }
69*8ccd4a63SDavid du Colombier }
70*8ccd4a63SDavid du Colombier
71*8ccd4a63SDavid du Colombier static char *
startlistener(void)72*8ccd4a63SDavid du Colombier startlistener(void)
73*8ccd4a63SDavid du Colombier {
74*8ccd4a63SDavid du Colombier qlock(&udp);
75*8ccd4a63SDavid du Colombier if (udp.thread < 0) {
76*8ccd4a63SDavid du Colombier char *e;
77*8ccd4a63SDavid du Colombier e = nbudpannounce(NbnsPort, &udp.fd);
78*8ccd4a63SDavid du Colombier if (e) {
79*8ccd4a63SDavid du Colombier qunlock(&udp);
80*8ccd4a63SDavid du Colombier return e;
81*8ccd4a63SDavid du Colombier }
82*8ccd4a63SDavid du Colombier udp.thread = proccreate(udplistener, nil, 16384);
83*8ccd4a63SDavid du Colombier }
84*8ccd4a63SDavid du Colombier qunlock(&udp);
85*8ccd4a63SDavid du Colombier return nil;
86*8ccd4a63SDavid du Colombier }
87*8ccd4a63SDavid du Colombier
88*8ccd4a63SDavid du Colombier ushort
nbnsnextid(void)89*8ccd4a63SDavid du Colombier nbnsnextid(void)
90*8ccd4a63SDavid du Colombier {
91*8ccd4a63SDavid du Colombier ushort rv;
92*8ccd4a63SDavid du Colombier lock(&id);
93*8ccd4a63SDavid du Colombier rv = id.id++;
94*8ccd4a63SDavid du Colombier unlock(&id);
95*8ccd4a63SDavid du Colombier return rv;
96*8ccd4a63SDavid du Colombier }
97*8ccd4a63SDavid du Colombier
98*8ccd4a63SDavid du Colombier NbnsTransaction *
nbnstransactionnew(NbnsMessage * s,uchar * ipaddr)99*8ccd4a63SDavid du Colombier nbnstransactionnew(NbnsMessage *s, uchar *ipaddr)
100*8ccd4a63SDavid du Colombier {
101*8ccd4a63SDavid du Colombier NbnsTransaction *t;
102*8ccd4a63SDavid du Colombier uchar msg[Udphdrsize + 576];
103*8ccd4a63SDavid du Colombier Udphdr *u;
104*8ccd4a63SDavid du Colombier int len;
105*8ccd4a63SDavid du Colombier
106*8ccd4a63SDavid du Colombier startlistener();
107*8ccd4a63SDavid du Colombier len = nbnsconvS2M(s, msg + nbudphdrsize, sizeof(msg) - nbudphdrsize);
108*8ccd4a63SDavid du Colombier if (len == 0)
109*8ccd4a63SDavid du Colombier return 0;
110*8ccd4a63SDavid du Colombier t = mallocz(sizeof(*t), 1);
111*8ccd4a63SDavid du Colombier if (t == nil)
112*8ccd4a63SDavid du Colombier return nil;
113*8ccd4a63SDavid du Colombier t->id = s->id;
114*8ccd4a63SDavid du Colombier t->c = chancreate(sizeof(NbnsMessage *), 3);
115*8ccd4a63SDavid du Colombier if (t->c == nil) {
116*8ccd4a63SDavid du Colombier free(t);
117*8ccd4a63SDavid du Colombier return nil;
118*8ccd4a63SDavid du Colombier }
119*8ccd4a63SDavid du Colombier qlock(&transactionlist);
120*8ccd4a63SDavid du Colombier t->next = transactionlist.head;
121*8ccd4a63SDavid du Colombier transactionlist.head = t;
122*8ccd4a63SDavid du Colombier qunlock(&transactionlist);
123*8ccd4a63SDavid du Colombier u = (Udphdr *)msg;
124*8ccd4a63SDavid du Colombier ipmove(u->laddr, nbglobals.myipaddr);
125*8ccd4a63SDavid du Colombier hnputs(u->lport, NbnsPort);
126*8ccd4a63SDavid du Colombier if (s->broadcast || ipaddr == nil)
127*8ccd4a63SDavid du Colombier ipmove(u->raddr, nbglobals.bcastaddr);
128*8ccd4a63SDavid du Colombier else
129*8ccd4a63SDavid du Colombier ipmove(u->raddr, ipaddr);
130*8ccd4a63SDavid du Colombier hnputs(u->rport, NbnsPort);
131*8ccd4a63SDavid du Colombier write(udp.fd, msg, len + nbudphdrsize);
132*8ccd4a63SDavid du Colombier return t;
133*8ccd4a63SDavid du Colombier }
134*8ccd4a63SDavid du Colombier
135*8ccd4a63SDavid du Colombier void
nbnstransactionfree(NbnsTransaction ** tp)136*8ccd4a63SDavid du Colombier nbnstransactionfree(NbnsTransaction **tp)
137*8ccd4a63SDavid du Colombier {
138*8ccd4a63SDavid du Colombier NbnsTransaction **tp2;
139*8ccd4a63SDavid du Colombier NbnsMessage *s;
140*8ccd4a63SDavid du Colombier NbnsTransaction *t;
141*8ccd4a63SDavid du Colombier
142*8ccd4a63SDavid du Colombier t = *tp;
143*8ccd4a63SDavid du Colombier if (t) {
144*8ccd4a63SDavid du Colombier qlock(&transactionlist);
145*8ccd4a63SDavid du Colombier while ((s = nbrecvp(t->c)) != nil)
146*8ccd4a63SDavid du Colombier nbnsmessagefree(&s);
147*8ccd4a63SDavid du Colombier for (tp2 = &transactionlist.head; *tp2 && *tp2 != t; tp2 = &(*tp2)->next)
148*8ccd4a63SDavid du Colombier ;
149*8ccd4a63SDavid du Colombier if (*tp2) {
150*8ccd4a63SDavid du Colombier *tp2 = t->next;
151*8ccd4a63SDavid du Colombier free(t);
152*8ccd4a63SDavid du Colombier }
153*8ccd4a63SDavid du Colombier qunlock(&transactionlist);
154*8ccd4a63SDavid du Colombier *tp = nil;
155*8ccd4a63SDavid du Colombier }
156*8ccd4a63SDavid du Colombier }
157