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