Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature-vt/sys/src/cmd/cifs/netbios.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * netbios dial, read, write
3
 */
4
 
5
#include <u.h>
6
#include <libc.h>
7
#include <ctype.h>
8
#include <fcall.h>
9
#include <thread.h>
10
#include <9p.h>
11
#include "cifs.h"
12
 
13
enum {
14
	MAXNBPKT		= 8096,		/* max netbios packet size */
15
	NBquery			= 0,		/* packet type - query */
16
 
17
	NBAdapterStatus		= 0x21,		/* get host interface info */
18
	NBInternet		= 1,		/* scope for info */
19
 
20
	NBmessage 		= 0x00,		/* Netbios packet types */
21
	NBrequest 		= 0x81,
22
	NBpositive,
23
	NBnegative,
24
	NBretarget,
25
	NBkeepalive,
26
 
27
	ISgroup			= 0x8000,
28
};
29
 
30
 
31
static char *NBerr[] = {
32
	[0]	"not listening on called name",
33
	[1]	"not listening for calling name",
34
	[2]	"called name not present",
35
	[3]	"insufficient resources",
36
	[15]	"unspecified error"
37
};
38
 
39
 
40
static ulong
41
GL32(uchar **p)
42
{
43
	ulong n;
44
 
45
	n  = *(*p)++;
46
	n |= *(*p)++ << 8;
47
	n |= *(*p)++ << 16;
48
	n |= *(*p)++ << 24;
49
	return n;
50
}
51
 
52
static ushort
53
GL16(uchar **p)
54
{
55
	ushort n;
56
 
57
	n  = *(*p)++;
58
	n |= *(*p)++ << 8;
59
	return n;
60
}
61
 
62
void
63
Gmem(uchar **p, void *v, int n)
64
{
65
	uchar *str = v;
66
 
67
	while(n--)
68
		*str++ = *(*p)++;
69
}
70
 
71
 
72
static ulong
73
GB32(uchar **p)
74
{
75
	ulong n;
76
 
77
	n  = *(*p)++ << 24;
78
	n |= *(*p)++ << 16;
79
	n |= *(*p)++ << 8;
80
	n |= *(*p)++;
81
	return n;
82
}
83
 
84
static ushort
85
GB16(uchar **p)
86
{
87
	ushort n;
88
 
89
	n  = *(*p)++ << 8;
90
	n |= *(*p)++;
91
	return n;
92
}
93
 
94
static uchar
95
G8(uchar **p)
96
{
97
	return *(*p)++;
98
}
99
 
100
static void
101
PB16(uchar **p, uint n)
102
{
103
	*(*p)++ = n >> 8;
104
	*(*p)++ = n;
105
}
106
 
107
static void
108
P8(uchar **p, uint n)
109
{
110
	*(*p)++ = n;
111
}
112
 
113
 
114
static void
115
nbname(uchar **p, char *name, char pad)
116
{
117
	char c;
118
	int i;
119
	int done = 0;
120
 
121
	*(*p)++ = 0x20;
122
	for(i = 0; i < 16; i++) {
123
		c = pad;
124
		if(!done && name[i] == '\0')
125
			done = 1;
126
		if(!done)
127
			c = toupper(name[i]);
128
		*(*p)++ = ((uchar)c >> 4) + 'A';
129
		*(*p)++ = (c & 0xf) + 'A';
130
	}
131
	*(*p)++ = 0;
132
}
133
 
134
int
135
calledname(char *host, char *name)
136
{
137
	char *addr;
138
	uchar buf[1024], *p;
139
	static char tmp[20];
140
	int num, flg, svs, j, i, fd, trn;
141
 
142
	trn = (getpid() ^ time(0)) & 0xffff;
143
	if((addr = netmkaddr(host, "udp", "137")) == nil)
144
		return -1;
145
 
146
	if((fd = dial(addr, "137", 0, 0)) < 0)
147
		return -1;
148
	p = buf;
149
 
150
	PB16(&p, trn);			/* TRNid */
151
	P8(&p, 0);			/* flags */
152
	P8(&p, 0x10);			/* type */
153
	PB16(&p, 1);			/* # questions */
154
	PB16(&p, 0);			/* # answers */
155
	PB16(&p, 0);			/* # authority RRs */
156
	PB16(&p, 0);			/* # Aditional RRs */
157
	nbname(&p, "*", 0);
158
	PB16(&p, NBAdapterStatus);
159
	PB16(&p, NBInternet);
160
 
161
	if(Debug && strstr(Debug, "dump"))
162
		xd(nil, buf, p-buf);
163
 
164
	if(write(fd, buf, p-buf) != p-buf)
165
		return -1;
166
 
167
	p = buf;
168
	for(i = 0; i < 3; i++){
169
		memset(buf, 0, sizeof(buf));
170
		alarm(NBNSTOUT);
171
		read(fd, buf, sizeof(buf));
172
		alarm(0);
173
		if(GB16(&p) == trn)
174
			break;
175
	}
176
	close(fd);
177
	if(i >= 3)
178
		return -1;
179
 
180
	p = buf +56;
181
	num = G8(&p);			/* number of names */
182
 
183
	for(i = 0; i < num; i++){
184
		memset(tmp, 0, sizeof(tmp));
185
		Gmem(&p, tmp, 15);
186
		svs = G8(&p);
187
		flg = GB16(&p);
188
		for(j = 14; j >= 0 && tmp[j] == ' '; j--)
189
			tmp[j] = 0;
190
		if(svs == 0 && !(flg & ISgroup))
191
			strcpy(name, tmp);
192
	}
193
	return 0;
194
}
195
 
196
 
197
int
198
nbtdial(char *addr, char *called, char *sysname)
199
{
200
	char redir[20];
201
	uchar *p, *lenp, buf[1024];
202
	int type, len, err, fd, nkeepalive, nretarg;
203
 
204
	nretarg = 0;
205
	nkeepalive = 0;
206
Redial:
207
	if((addr = netmkaddr(addr, "tcp", "139")) == nil ||
208
	    (fd = dial(addr, 0, 0, 0)) < 0)
209
		return -1;
210
 
211
	memset(buf, 0, sizeof(buf));
212
 
213
	p = buf;
214
	P8(&p, NBrequest);		/* type */
215
	P8(&p, 0);			/* flags */
216
	lenp = p; PB16(&p, 0);		/* length placeholder */
217
	nbname(&p, called, ' ');	/* remote NetBios name */
218
	nbname(&p, sysname, ' ');	/* our machine name */
219
	PB16(&lenp, p-lenp -2);		/* length re-write */
220
 
221
	if(Debug && strstr(Debug, "dump"))
222
		xd(nil, buf, p-buf);
223
	if(write(fd, buf, p-buf) != p-buf)
224
		goto Error;
225
Reread:
226
	p = buf;
227
	memset(buf, 0, sizeof(buf));
228
	if(readn(fd, buf, 4) < 4)
229
		goto Error;
230
 
231
	type = G8(&p);
232
	G8(&p);				/* flags */
233
	len = GB16(&p);
234
 
235
	if(readn(fd, buf +4, len -4) < len -4)
236
		goto Error;
237
 
238
	if(Debug && strstr(Debug, "dump"))
239
		xd(nil, buf, len+4);
240
 
241
	switch(type) {
242
	case NBpositive:
243
		return fd;
244
	case NBnegative:
245
		if(len < 1) {
246
			werrstr("nbdial: bad error pkt");
247
			goto Error;
248
		}
249
		err = G8(&p);
250
		if(err < 0 || err > nelem(NBerr) || NBerr[err] == nil)
251
			werrstr("NBT: %d - unknown error", err);
252
		else
253
			werrstr("NBT: %s", NBerr[err]);
254
 
255
		goto Error;
256
	case NBkeepalive:
257
		if(++nkeepalive >= 16){
258
			werrstr("nbdial: too many keepalives");
259
			goto Error;
260
		}
261
		goto Reread;
262
 
263
	case NBretarget:
264
		if(++nretarg >= 16) {
265
			werrstr("nbdial: too many redirects");
266
			goto Error;
267
		}
268
		if(len < 4) {
269
			werrstr("nbdial: bad redirect pkt");
270
			goto Error;
271
		}
272
		sprint(redir, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
273
		addr = redir;
274
		goto Redial;
275
 
276
	default:
277
		werrstr("nbdial: 0x%x - unknown packet in netbios handshake", type);
278
		goto Error;
279
	}
280
Error:
281
	close(fd);
282
	return -1;
283
}
284
 
285
void
286
nbthdr(Pkt *p)
287
{
288
	p->pos = p->buf;
289
	memset(p->buf, 0xa5, MTU);
290
 
291
	p8(p, NBmessage);		/* type */
292
	p8(p, 0);			/* flags */
293
	pb16(p, 0);			/* length (filled in later) */
294
}
295
 
296
int
297
nbtrpc(Pkt *p)
298
{
299
	int len, got, type, nkeep;
300
 
301
	len = p->pos - p->buf;
302
 
303
	p->pos = p->buf +2;
304
	pb16(p, len - NBHDRLEN);	/* length */
305
 
306
	if(Debug && strstr(Debug, "dump"))
307
		xd("tx", p->buf, len);
308
 
309
	alarm(NBRPCTOUT);
310
	if(write(p->s->fd, p->buf, len) != len){
311
		werrstr("nbtrpc: write failed - %r");
312
		alarm(0);
313
		return -1;
314
	}
315
 
316
	nkeep = 0;
317
retry:
318
	p->pos = p->buf;
319
	memset(p->buf, 0xa5, MTU);
320
 
321
	got = readn(p->s->fd, p->buf, NBHDRLEN);
322
 
323
	if(got < NBHDRLEN){
324
		werrstr("nbtrpc: short read - %r");
325
		alarm(0);
326
		return -1;
327
	}
328
	p->eop = p->buf + got;
329
 
330
	type = g8(p);			/* NBT type (session) */
331
	if(type == NBkeepalive){
332
		if(++nkeep > 16) {
333
			werrstr("nbtrpc: too many keepalives (%d attempts)", nkeep);
334
			alarm(0);
335
			return -1;
336
		}
337
		goto retry;
338
	}
339
 
340
	g8(p);				/* NBT flags (none) */
341
 
342
	len = gb16(p);			/* NBT payload length */
343
	if((len +NBHDRLEN) > MTU){
344
		werrstr("nbtrpc: packet bigger than MTU, (%d > %d)", len, MTU);
345
		alarm(0);
346
		return -1;
347
	}
348
 
349
	got = readn(p->s->fd, p->buf +NBHDRLEN, len);
350
	alarm(0);
351
 
352
	if(Debug && strstr(Debug, "dump"))
353
		xd("rx", p->buf, got +NBHDRLEN);
354
 
355
	if(got < 0)
356
		return -1;
357
	p->eop = p->buf + got +NBHDRLEN;
358
	return got+NBHDRLEN;
359
}
360
 
361
 
362
void
363
xd(char *str, void *buf, int n)
364
{
365
	int fd, flg, flags2, cmd;
366
	uint sum;
367
	long err;
368
	uchar *p, *end;
369
 
370
	if(n == 0)
371
		return;
372
 
373
	p = buf;
374
	end = (uchar *)buf +n;
375
 
376
	if(Debug && strstr(Debug, "log") != nil){
377
		if((fd = open("pkt.log", ORDWR)) == -1)
378
			return;
379
		seek(fd, 0, 2);
380
		fprint(fd, "%d	", 0);
381
		while(p < end)
382
			fprint(fd, "%02x ", *p++);
383
		fprint(fd, "\n");
384
		close(fd);
385
		return;
386
	}
387
 
388
	if(!str)
389
		goto Raw;
390
 
391
	p = (uchar *)buf + 4;
392
	if(GL32(&p) == 0x424d53ff){
393
		buf = (uchar *)buf + 4;
394
		n -= 4;
395
	}
396
	end = (uchar *)buf + n;
397
 
398
	sum = 0;
399
	p = buf;
400
	while(p < end)
401
		sum += *p++;
402
	p = buf;
403
 
404
	fprint(2, "%s : len=%ud sum=%d\n", str, n, sum);
405
 
406
	fprint(2, "mag=0x%ulx ", GL32(&p));
407
	fprint(2, "cmd=0x%ux ", cmd = G8(&p));
408
	fprint(2, "err=0x%ulx ", err=GL32(&p));
409
	fprint(2, "flg=0x%02ux ", flg = G8(&p));
410
	fprint(2, "flg2=0x%04ux\n", flags2= GL16(&p));
411
	fprint(2, "dfs=%s\n", (flags2 & FL2_DFS)? "y": "n");
412
 
413
	fprint(2, "pidl=%ud ", GL16(&p));
414
	fprint(2, "res=%uld ", GL32(&p));
415
	fprint(2, "sid=%ud ", GL16(&p));
416
	fprint(2, "seq=0x%ux ", GL16(&p));
417
	fprint(2, "pad=%ud ", GL16(&p));
418
 
419
	fprint(2, "tid=%ud ", GL16(&p));
420
	fprint(2, "pid=%ud ", GL16(&p));
421
	fprint(2, "uid=%ud ", GL16(&p));
422
	fprint(2, "mid=%ud\n", GL16(&p));
423
 
424
	if(cmd == 0x32 && (flg & 0x80) == 0){		/* TRANS 2, TX */
425
		fprint(2, "words=%ud ", G8(&p));
426
		fprint(2, "totparams=%ud ", GL16(&p));
427
		fprint(2, "totdata=%ud ", GL16(&p));
428
		fprint(2, "maxparam=%ud ", GL16(&p));
429
		fprint(2, "maxdata=%ud\n", GL16(&p));
430
		fprint(2, "maxsetup=%ud ", G8(&p));
431
		fprint(2, "reserved=%ud ", G8(&p));
432
		fprint(2, "flags=%ud ", GL16(&p));
433
		fprint(2, "timeout=%uld\n", GL32(&p));
434
		fprint(2, "reserved=%ud ", GL16(&p));
435
		fprint(2, "paramcnt=%ud ", GL16(&p));
436
		fprint(2, "paramoff=%ud ", GL16(&p));
437
		fprint(2, "datacnt=%ud ", GL16(&p));
438
		fprint(2, "dataoff=%ud ", GL16(&p));
439
		fprint(2, "setupcnt=%ud ", G8(&p));
440
		fprint(2, "reserved=%ud\n", G8(&p));
441
		fprint(2, "trans2=0x%02x ", GL16(&p));
442
		fprint(2, "data-words=%d ", G8(&p));
443
		fprint(2, "padding=%d\n", G8(&p));
444
	}
445
	if(cmd == 0x32 && (flg & 0x80) == 0x80){	/* TRANS 2, RX */
446
		fprint(2, "words=%ud ", G8(&p));
447
		fprint(2, "totparams=%ud ", GL16(&p));
448
		fprint(2, "totdata=%ud ", GL16(&p));
449
		fprint(2, "reserved=%ud ", GL16(&p));
450
		fprint(2, "paramcnt=%ud\n", GL16(&p));
451
		fprint(2, "paramoff=%ud ", GL16(&p));
452
		fprint(2, "paramdisp=%ud ", GL16(&p));
453
		fprint(2, "datacnt=%ud\n", GL16(&p));
454
		fprint(2, "dataoff=%ud ", GL16(&p));
455
		fprint(2, "datadisp=%ud ", GL16(&p));
456
		fprint(2, "setupcnt=%ud ", G8(&p));
457
		fprint(2, "reserved=%ud\n", G8(&p));
458
	}
459
	if(err)
460
		if(flags2 & FL2_NT_ERRCODES)
461
			fprint(2, "err=%s\n", nterrstr(err));
462
		else
463
			fprint(2, "err=%s\n", doserrstr(err));
464
Raw:
465
	fprint(2, "\n");
466
	for(; p < end; p++){
467
		if((p - (uchar *)buf) % 16 == 0)
468
			fprint(2, "\n%06lx\t", p - (uchar *)buf);
469
		if(isprint((char)*p))
470
			fprint(2, "%c  ", (char )*p);
471
		else
472
			fprint(2, "%02ux ", *p);
473
	}
474
	fprint(2, "\n");
475
}