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