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 int
decodehex(char c)8*8ccd4a63SDavid du Colombier decodehex(char c)
9*8ccd4a63SDavid du Colombier {
10*8ccd4a63SDavid du Colombier if (c >= '0' && c <= '9')
11*8ccd4a63SDavid du Colombier return c - '0';
12*8ccd4a63SDavid du Colombier else if (c >= 'A' && c <= 'F')
13*8ccd4a63SDavid du Colombier return c - 'A' + 10;
14*8ccd4a63SDavid du Colombier else if (c >= 'a' && c <= 'f')
15*8ccd4a63SDavid du Colombier return c - 'a' + 10;
16*8ccd4a63SDavid du Colombier return 0;
17*8ccd4a63SDavid du Colombier }
18*8ccd4a63SDavid du Colombier
19*8ccd4a63SDavid du Colombier static char
encodehex(int n)20*8ccd4a63SDavid du Colombier encodehex(int n)
21*8ccd4a63SDavid du Colombier {
22*8ccd4a63SDavid du Colombier if (n >= 0 && n <= 9)
23*8ccd4a63SDavid du Colombier return '0' + n;
24*8ccd4a63SDavid du Colombier if (n >= 10 && n <= 15)
25*8ccd4a63SDavid du Colombier return 'a' + (n - 10);
26*8ccd4a63SDavid du Colombier return '?';
27*8ccd4a63SDavid du Colombier }
28*8ccd4a63SDavid du Colombier
29*8ccd4a63SDavid du Colombier static int
_nameextract(uchar * base,uchar * p,uchar * ep,int k,uchar * outbuf,int outbufmaxlen,int * outbuflenp)30*8ccd4a63SDavid du Colombier _nameextract(uchar *base, uchar *p, uchar *ep, int k, uchar *outbuf, int outbufmaxlen, int *outbuflenp)
31*8ccd4a63SDavid du Colombier {
32*8ccd4a63SDavid du Colombier uchar *op, *oep, *savep;
33*8ccd4a63SDavid du Colombier savep = p;
34*8ccd4a63SDavid du Colombier op = outbuf;
35*8ccd4a63SDavid du Colombier oep = outbuf + outbufmaxlen;
36*8ccd4a63SDavid du Colombier for (;;) {
37*8ccd4a63SDavid du Colombier uchar b;
38*8ccd4a63SDavid du Colombier int n;
39*8ccd4a63SDavid du Colombier if (p >= ep)
40*8ccd4a63SDavid du Colombier return 0;
41*8ccd4a63SDavid du Colombier b = *p++;
42*8ccd4a63SDavid du Colombier if (b == 0)
43*8ccd4a63SDavid du Colombier break;
44*8ccd4a63SDavid du Colombier if (k) {
45*8ccd4a63SDavid du Colombier if (op >= oep)
46*8ccd4a63SDavid du Colombier return 0;
47*8ccd4a63SDavid du Colombier *op++ = '.';
48*8ccd4a63SDavid du Colombier }
49*8ccd4a63SDavid du Colombier if ((b & 0xc0) == 0xc0) {
50*8ccd4a63SDavid du Colombier ushort off;
51*8ccd4a63SDavid du Colombier if (ep - p < 2)
52*8ccd4a63SDavid du Colombier return 0;
53*8ccd4a63SDavid du Colombier off = nhgets(p - 1) & 0x3fff; p++;
54*8ccd4a63SDavid du Colombier if (_nameextract(base, base + off, p, k, op, oep - ep, &n) == 0)
55*8ccd4a63SDavid du Colombier return 0;
56*8ccd4a63SDavid du Colombier op += n;
57*8ccd4a63SDavid du Colombier }
58*8ccd4a63SDavid du Colombier else if ((b & 0xc0) != 0x00)
59*8ccd4a63SDavid du Colombier return 0;
60*8ccd4a63SDavid du Colombier else if (b != 0x20)
61*8ccd4a63SDavid du Colombier return 0;
62*8ccd4a63SDavid du Colombier else {
63*8ccd4a63SDavid du Colombier int x;
64*8ccd4a63SDavid du Colombier if (p + b > ep)
65*8ccd4a63SDavid du Colombier return 0;
66*8ccd4a63SDavid du Colombier if (op + b / 2 > oep)
67*8ccd4a63SDavid du Colombier return 0;
68*8ccd4a63SDavid du Colombier for (x = 0; x < b; x += 2) {
69*8ccd4a63SDavid du Colombier uchar hn, ln;
70*8ccd4a63SDavid du Colombier if (*p < 'A' || *p >= 'A' + 16)
71*8ccd4a63SDavid du Colombier return 0;
72*8ccd4a63SDavid du Colombier hn = *p++ - 'A';
73*8ccd4a63SDavid du Colombier if (*p < 'A' || *p >= 'A' + 16)
74*8ccd4a63SDavid du Colombier return 0;
75*8ccd4a63SDavid du Colombier ln = *p++ - 'A';
76*8ccd4a63SDavid du Colombier *op++ = (hn << 4) | ln;
77*8ccd4a63SDavid du Colombier }
78*8ccd4a63SDavid du Colombier }
79*8ccd4a63SDavid du Colombier k++;
80*8ccd4a63SDavid du Colombier }
81*8ccd4a63SDavid du Colombier *outbuflenp = op - outbuf;
82*8ccd4a63SDavid du Colombier return p - savep;
83*8ccd4a63SDavid du Colombier }
84*8ccd4a63SDavid du Colombier
85*8ccd4a63SDavid du Colombier int
nbnamedecode(uchar * base,uchar * p,uchar * ep,NbName nbname)86*8ccd4a63SDavid du Colombier nbnamedecode(uchar *base, uchar *p, uchar *ep, NbName nbname)
87*8ccd4a63SDavid du Colombier {
88*8ccd4a63SDavid du Colombier int n;
89*8ccd4a63SDavid du Colombier int rv = _nameextract(base, p, ep, 0, nbname, NbNameLen, &n);
90*8ccd4a63SDavid du Colombier if (rv == 0)
91*8ccd4a63SDavid du Colombier return rv;
92*8ccd4a63SDavid du Colombier if (n != NbNameLen)
93*8ccd4a63SDavid du Colombier return 0;
94*8ccd4a63SDavid du Colombier return rv;
95*8ccd4a63SDavid du Colombier }
96*8ccd4a63SDavid du Colombier
97*8ccd4a63SDavid du Colombier int
nbnameencode(uchar * ap,uchar * ep,NbName name)98*8ccd4a63SDavid du Colombier nbnameencode(uchar *ap, uchar *ep, NbName name)
99*8ccd4a63SDavid du Colombier {
100*8ccd4a63SDavid du Colombier uchar *p = ap;
101*8ccd4a63SDavid du Colombier int i;
102*8ccd4a63SDavid du Colombier if (p + 1 + 2 * NbNameLen + 1 > ep)
103*8ccd4a63SDavid du Colombier return 0;
104*8ccd4a63SDavid du Colombier *p++ = NbNameLen * 2;
105*8ccd4a63SDavid du Colombier for (i = 0; i < NbNameLen; i++) {
106*8ccd4a63SDavid du Colombier *p++ = 'A' + ((name[i] >> 4) & 0xf);
107*8ccd4a63SDavid du Colombier *p++ = 'A' + (name[i] & 0xf);
108*8ccd4a63SDavid du Colombier }
109*8ccd4a63SDavid du Colombier *p++ = 0;
110*8ccd4a63SDavid du Colombier return p - ap;
111*8ccd4a63SDavid du Colombier }
112*8ccd4a63SDavid du Colombier
113*8ccd4a63SDavid du Colombier void
nbnamecpy(NbName n1,NbName n2)114*8ccd4a63SDavid du Colombier nbnamecpy(NbName n1, NbName n2)
115*8ccd4a63SDavid du Colombier {
116*8ccd4a63SDavid du Colombier memcpy(n1, n2, NbNameLen);
117*8ccd4a63SDavid du Colombier }
118*8ccd4a63SDavid du Colombier
119*8ccd4a63SDavid du Colombier void
nbmknamefromstring(NbName nbname,char * s)120*8ccd4a63SDavid du Colombier nbmknamefromstring(NbName nbname, char *s)
121*8ccd4a63SDavid du Colombier {
122*8ccd4a63SDavid du Colombier int i;
123*8ccd4a63SDavid du Colombier memset(nbname, ' ', NbNameLen - 1);
124*8ccd4a63SDavid du Colombier nbname[NbNameLen - 1] = 0;
125*8ccd4a63SDavid du Colombier i = 0;
126*8ccd4a63SDavid du Colombier while (*s) {
127*8ccd4a63SDavid du Colombier if (*s == '\\' && *(s + 1) == 'x') {
128*8ccd4a63SDavid du Colombier s += 2;
129*8ccd4a63SDavid du Colombier if (*s == 0 || *(s + 1) == 0)
130*8ccd4a63SDavid du Colombier return;
131*8ccd4a63SDavid du Colombier nbname[NbNameLen - 1] = (decodehex(s[0]) << 4) | decodehex(s[1]);
132*8ccd4a63SDavid du Colombier return;
133*8ccd4a63SDavid du Colombier } else {
134*8ccd4a63SDavid du Colombier if (i < NbNameLen - 1)
135*8ccd4a63SDavid du Colombier nbname[i++] = toupper(*s);
136*8ccd4a63SDavid du Colombier s++;
137*8ccd4a63SDavid du Colombier }
138*8ccd4a63SDavid du Colombier }
139*8ccd4a63SDavid du Colombier }
140*8ccd4a63SDavid du Colombier
141*8ccd4a63SDavid du Colombier void
nbmknamefromstringandtype(NbName nbname,char * s,uchar type)142*8ccd4a63SDavid du Colombier nbmknamefromstringandtype(NbName nbname, char *s, uchar type)
143*8ccd4a63SDavid du Colombier {
144*8ccd4a63SDavid du Colombier nbmknamefromstring(nbname, s);
145*8ccd4a63SDavid du Colombier nbname[NbNameLen - 1] = type;
146*8ccd4a63SDavid du Colombier }
147*8ccd4a63SDavid du Colombier
148*8ccd4a63SDavid du Colombier void
nbmkstringfromname(char * buf,int buflen,NbName name)149*8ccd4a63SDavid du Colombier nbmkstringfromname(char *buf, int buflen, NbName name)
150*8ccd4a63SDavid du Colombier {
151*8ccd4a63SDavid du Colombier int x;
152*8ccd4a63SDavid du Colombier for (x = 0; x < NbNameLen - 1; x++) {
153*8ccd4a63SDavid du Colombier if (name[x] == ' ')
154*8ccd4a63SDavid du Colombier break;
155*8ccd4a63SDavid du Colombier if (buflen > 1) {
156*8ccd4a63SDavid du Colombier *buf++ = tolower(name[x]);
157*8ccd4a63SDavid du Colombier buflen--;
158*8ccd4a63SDavid du Colombier }
159*8ccd4a63SDavid du Colombier }
160*8ccd4a63SDavid du Colombier if (name[NbNameLen - 1] != 0) {
161*8ccd4a63SDavid du Colombier if (buflen > 1) {
162*8ccd4a63SDavid du Colombier *buf++ = '\\';
163*8ccd4a63SDavid du Colombier buflen--;
164*8ccd4a63SDavid du Colombier }
165*8ccd4a63SDavid du Colombier if (buflen > 1) {
166*8ccd4a63SDavid du Colombier *buf++ = 'x';
167*8ccd4a63SDavid du Colombier buflen--;
168*8ccd4a63SDavid du Colombier }
169*8ccd4a63SDavid du Colombier if (buflen > 1) {
170*8ccd4a63SDavid du Colombier *buf++ = encodehex(name[NbNameLen - 1] >> 4);
171*8ccd4a63SDavid du Colombier buflen--;
172*8ccd4a63SDavid du Colombier }
173*8ccd4a63SDavid du Colombier if (buflen > 1)
174*8ccd4a63SDavid du Colombier *buf++ = encodehex(name[NbNameLen - 1] & 0x0f);
175*8ccd4a63SDavid du Colombier }
176*8ccd4a63SDavid du Colombier *buf = 0;
177*8ccd4a63SDavid du Colombier }
178*8ccd4a63SDavid du Colombier
179*8ccd4a63SDavid du Colombier int
nbnameisany(NbName name)180*8ccd4a63SDavid du Colombier nbnameisany(NbName name)
181*8ccd4a63SDavid du Colombier {
182*8ccd4a63SDavid du Colombier return name[0] == '*';
183*8ccd4a63SDavid du Colombier }
184*8ccd4a63SDavid du Colombier
185*8ccd4a63SDavid du Colombier int
nbnameequal(NbName name1,NbName name2)186*8ccd4a63SDavid du Colombier nbnameequal(NbName name1, NbName name2)
187*8ccd4a63SDavid du Colombier {
188*8ccd4a63SDavid du Colombier if (name1[NbNameLen - 1] != name2[NbNameLen - 1])
189*8ccd4a63SDavid du Colombier return 0;
190*8ccd4a63SDavid du Colombier if (nbnameisany(name1))
191*8ccd4a63SDavid du Colombier return 1;
192*8ccd4a63SDavid du Colombier if (nbnameisany(name2))
193*8ccd4a63SDavid du Colombier return 1;
194*8ccd4a63SDavid du Colombier return memcmp(name1, name2, NbNameLen - 1) == 0;
195*8ccd4a63SDavid du Colombier }
196*8ccd4a63SDavid du Colombier
197*8ccd4a63SDavid du Colombier int
nbnamefmt(Fmt * f)198*8ccd4a63SDavid du Colombier nbnamefmt(Fmt *f)
199*8ccd4a63SDavid du Colombier {
200*8ccd4a63SDavid du Colombier uchar *n;
201*8ccd4a63SDavid du Colombier char buf[100];
202*8ccd4a63SDavid du Colombier n = va_arg(f->args, uchar *);
203*8ccd4a63SDavid du Colombier nbmkstringfromname(buf, sizeof(buf), n);
204*8ccd4a63SDavid du Colombier return fmtstrcpy(f, buf);
205*8ccd4a63SDavid du Colombier }
206*8ccd4a63SDavid du Colombier
207*8ccd4a63SDavid du Colombier typedef struct NbNameTableEntry NbNameTableEntry;
208*8ccd4a63SDavid du Colombier struct NbNameTableEntry {
209*8ccd4a63SDavid du Colombier NbName name;
210*8ccd4a63SDavid du Colombier NbNameTableEntry *next;
211*8ccd4a63SDavid du Colombier };
212*8ccd4a63SDavid du Colombier
213*8ccd4a63SDavid du Colombier static struct {
214*8ccd4a63SDavid du Colombier QLock;
215*8ccd4a63SDavid du Colombier NbNameTableEntry *head;
216*8ccd4a63SDavid du Colombier } nbnametable;
217*8ccd4a63SDavid du Colombier
218*8ccd4a63SDavid du Colombier int
nbnametablefind(NbName name,int add)219*8ccd4a63SDavid du Colombier nbnametablefind(NbName name, int add)
220*8ccd4a63SDavid du Colombier {
221*8ccd4a63SDavid du Colombier int rv;
222*8ccd4a63SDavid du Colombier NbNameTableEntry *p;
223*8ccd4a63SDavid du Colombier qlock(&nbnametable);
224*8ccd4a63SDavid du Colombier for (p = nbnametable.head; p; p = p->next) {
225*8ccd4a63SDavid du Colombier if (nbnameequal(p->name, name)) {
226*8ccd4a63SDavid du Colombier qunlock(&nbnametable);
227*8ccd4a63SDavid du Colombier return 1;
228*8ccd4a63SDavid du Colombier }
229*8ccd4a63SDavid du Colombier }
230*8ccd4a63SDavid du Colombier if (add) {
231*8ccd4a63SDavid du Colombier p = nbemalloc(sizeof(*p));
232*8ccd4a63SDavid du Colombier nbnamecpy(p->name, name);
233*8ccd4a63SDavid du Colombier p->next = nbnametable.head;
234*8ccd4a63SDavid du Colombier nbnametable.head = p;
235*8ccd4a63SDavid du Colombier rv = 1;
236*8ccd4a63SDavid du Colombier }
237*8ccd4a63SDavid du Colombier else
238*8ccd4a63SDavid du Colombier rv = 0;
239*8ccd4a63SDavid du Colombier qunlock(&nbnametable);
240*8ccd4a63SDavid du Colombier return rv;
241*8ccd4a63SDavid du Colombier }
242*8ccd4a63SDavid du Colombier
243*8ccd4a63SDavid du Colombier typedef struct NbRemoteNameTableEntry NbRemoteNameTableEntry;
244*8ccd4a63SDavid du Colombier struct NbRemoteNameTableEntry {
245*8ccd4a63SDavid du Colombier NbName name;
246*8ccd4a63SDavid du Colombier char ipaddr[IPaddrlen];
247*8ccd4a63SDavid du Colombier long expire;
248*8ccd4a63SDavid du Colombier NbRemoteNameTableEntry *next;
249*8ccd4a63SDavid du Colombier };
250*8ccd4a63SDavid du Colombier
251*8ccd4a63SDavid du Colombier static struct {
252*8ccd4a63SDavid du Colombier QLock;
253*8ccd4a63SDavid du Colombier NbRemoteNameTableEntry *head;
254*8ccd4a63SDavid du Colombier } nbremotenametable;
255*8ccd4a63SDavid du Colombier
256*8ccd4a63SDavid du Colombier int
nbremotenametablefind(NbName name,uchar * ipaddr)257*8ccd4a63SDavid du Colombier nbremotenametablefind(NbName name, uchar *ipaddr)
258*8ccd4a63SDavid du Colombier {
259*8ccd4a63SDavid du Colombier NbRemoteNameTableEntry *p, **pp;
260*8ccd4a63SDavid du Colombier long now = time(nil);
261*8ccd4a63SDavid du Colombier qlock(&nbremotenametable);
262*8ccd4a63SDavid du Colombier for (pp = &nbremotenametable.head; (p = *pp) != nil;) {
263*8ccd4a63SDavid du Colombier if (p->expire <= now) {
264*8ccd4a63SDavid du Colombier //print("nbremotenametablefind: expired %B\n", p->name);
265*8ccd4a63SDavid du Colombier *pp = p->next;
266*8ccd4a63SDavid du Colombier free(p);
267*8ccd4a63SDavid du Colombier continue;
268*8ccd4a63SDavid du Colombier }
269*8ccd4a63SDavid du Colombier if (nbnameequal(p->name, name)) {
270*8ccd4a63SDavid du Colombier ipmove(ipaddr, p->ipaddr);
271*8ccd4a63SDavid du Colombier qunlock(&nbremotenametable);
272*8ccd4a63SDavid du Colombier return 1;
273*8ccd4a63SDavid du Colombier }
274*8ccd4a63SDavid du Colombier pp = &p->next;
275*8ccd4a63SDavid du Colombier }
276*8ccd4a63SDavid du Colombier qunlock(&nbremotenametable);
277*8ccd4a63SDavid du Colombier return 0;
278*8ccd4a63SDavid du Colombier }
279*8ccd4a63SDavid du Colombier
280*8ccd4a63SDavid du Colombier int
nbremotenametableadd(NbName name,uchar * ipaddr,ulong ttl)281*8ccd4a63SDavid du Colombier nbremotenametableadd(NbName name, uchar *ipaddr, ulong ttl)
282*8ccd4a63SDavid du Colombier {
283*8ccd4a63SDavid du Colombier NbRemoteNameTableEntry *p;
284*8ccd4a63SDavid du Colombier qlock(&nbremotenametable);
285*8ccd4a63SDavid du Colombier for (p = nbremotenametable.head; p; p = p->next)
286*8ccd4a63SDavid du Colombier if (nbnameequal(p->name, name))
287*8ccd4a63SDavid du Colombier break;
288*8ccd4a63SDavid du Colombier if (p == nil) {
289*8ccd4a63SDavid du Colombier p = nbemalloc(sizeof(*p));
290*8ccd4a63SDavid du Colombier p->next = nbremotenametable.head;
291*8ccd4a63SDavid du Colombier nbremotenametable.head = p;
292*8ccd4a63SDavid du Colombier nbnamecpy(p->name, name);
293*8ccd4a63SDavid du Colombier }
294*8ccd4a63SDavid du Colombier ipmove(p->ipaddr, ipaddr);
295*8ccd4a63SDavid du Colombier p->expire = time(nil) + ttl;
296*8ccd4a63SDavid du Colombier //print("nbremotenametableadd: %B ttl %lud expire %ld\n", p->name, ttl, p->expire);
297*8ccd4a63SDavid du Colombier qunlock(&nbremotenametable);
298*8ccd4a63SDavid du Colombier return 1;
299*8ccd4a63SDavid du Colombier }
300