Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <ip.h>
4
#include <thread.h>
5
#include "netbios.h"
6
 
7
static int
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
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
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
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
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
114
nbnamecpy(NbName n1, NbName n2)
115
{
116
	memcpy(n1, n2, NbNameLen);
117
}
118
 
119
void
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
142
nbmknamefromstringandtype(NbName nbname, char *s, uchar type)
143
{
144
	nbmknamefromstring(nbname, s);
145
	nbname[NbNameLen - 1] = type;
146
}
147
 
148
void
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
180
nbnameisany(NbName name)
181
{
182
	return name[0] == '*';
183
}
184
 
185
int
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
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
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
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
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
}