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_posix/sys/src/cmd/cifs/trans2.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
#include <u.h>
2
#include <libc.h>
3
#include <fcall.h>
4
#include <thread.h>
5
#include <9p.h>
6
#include "cifs.h"
7
 
8
static Pkt *
9
t2hdr(Session *s, Share *sp, int cmd)
10
{
11
	Pkt *p;
12
 
13
	p = cifshdr(s, sp, SMB_COM_TRANSACTION2);
14
 
15
	p->tbase = pl16(p, 0);	/* 0  Total parameter bytes to be sent, filled later */
16
	pl16(p, 0);		/* 2  Total data bytes to be sent, filled later */
17
	pl16(p, 64);			/* 4  Max parameter to return */
18
	pl16(p, (MTU - T2HDRLEN)-64);	/* 6  Max data to return */
19
	p8(p, 0);			/* 8  Max setup count to return */
20
	p8(p, 0);			/* 9  Reserved */
21
	pl16(p, 0);			/* 10 Flags */
22
	pl32(p, 1000);			/* 12 Timeout (ms) */
23
	pl16(p, 0);			/* 16 Reserved */
24
	pl16(p, 0);			/* 18 Parameter count, filled later */
25
	pl16(p, 0);			/* 20 Parameter offset, filled later */
26
	pl16(p, 0);			/* 22 Data count, filled later */
27
	pl16(p, 0);			/* 24 Data offset, filled later */
28
	p8(p, 1);			/* 26 Setup count (in words) */
29
	p8(p, 0);			/* 27 Reserved */
30
	pl16(p, cmd);			/* setup[0] */
31
	pbytes(p);
32
	p8(p, 0);			/* padding ??!?!? */
33
 
34
	return p;
35
}
36
 
37
static void
38
pt2param(Pkt *p)
39
{
40
	uchar *pos = p->pos;
41
 
42
	assert(p->tbase != 0);
43
	p->pos = p->tbase + 20;
44
	pl16(p, (pos - p->buf) - NBHDRLEN); /* param offset */
45
 
46
	p->tparam = p->pos = pos;
47
}
48
 
49
static void
50
pt2data(Pkt *p)
51
{
52
	uchar *pos = p->pos;
53
 
54
	assert(p->tbase != 0);
55
	assert(p->tparam != 0);
56
 
57
	p->pos = p->tbase +0;
58
	pl16(p, pos - p->tparam);		/* total param count */
59
 
60
	p->pos = p->tbase +18;
61
	pl16(p, pos - p->tparam);		/* param count */
62
 
63
	p->pos = p->tbase +24;
64
	pl16(p, (pos - p->buf) - NBHDRLEN);	/* data offset */
65
 
66
	p->tdata = p->pos = pos;
67
}
68
 
69
static int
70
t2rpc(Pkt *p)
71
{
72
	int got;
73
	uchar *pos;
74
 
75
	assert(p->tbase != 0);
76
	assert(p->tdata != 0);
77
 
78
	pos = p->pos;
79
 
80
	p->pos = p->tbase +2;
81
	pl16(p, pos - p->tdata);		/* total data count */
82
 
83
	p->pos = p->tbase +22;
84
	pl16(p, pos - p->tdata);		/* data count */
85
 
86
	p->pos = pos;
87
	if((got = cifsrpc(p)) == -1)
88
		return -1;
89
 
90
	gl16(p);			/* Total parameter count */
91
	gl16(p);			/* Total data count */
92
	gl16(p);			/* Reserved */
93
	gl16(p);			/* Parameter count in this buffer */
94
	p->tparam = p->buf +NBHDRLEN +gl16(p); /* Parameter offset */
95
	gl16(p);			/* Parameter displacement */
96
	gl16(p);			/* Data count (this buffer); */
97
	p->tdata = p->buf +NBHDRLEN +gl16(p); /* Data offset */
98
	gl16(p);			/* Data displacement */
99
	g8(p);				/* Setup count */
100
	g8(p);				/* Reserved */
101
 
102
	return got;
103
}
104
 
105
static void
106
gt2param(Pkt *p)
107
{
108
	p->pos = p->tparam;
109
}
110
 
111
static void
112
gt2data(Pkt *p)
113
{
114
	p->pos = p->tdata;
115
}
116
 
117
 
118
int
119
T2findfirst(Session *s, Share *sp, int slots, char *path, int *got,
120
	long *resume, FInfo *fip)
121
{
122
	int pktlen, i, n, sh;
123
	uchar *next;
124
	Pkt *p;
125
 
126
	p = t2hdr(s, sp, TRANS2_FIND_FIRST2);
127
	p8(p, 'D');			/* OS/2 */
128
	p8(p, ' ');			/* OS/2 */
129
 
130
	pt2param(p);
131
	pl16(p, ATTR_HIDDEN|ATTR_SYSTEM|ATTR_DIRECTORY); /* Search attributes */
132
	pl16(p, slots);			/* Search count */
133
	pl16(p, CIFS_SEARCH_RETURN_RESUME); /* Flags */
134
	pl16(p, SMB_FIND_FILE_FULL_DIRECTORY_INFO); /* Information level */
135
	pl32(p, 0);			/* SearchStorage type (?) */
136
	ppath(p, path);			/* path */
137
 
138
	pt2data(p);
139
	if((pktlen = t2rpc(p)) == -1){
140
		free(p);
141
		return -1;
142
	}
143
 
144
	s->lastfind = nsec();
145
	gt2param(p);
146
 
147
	sh = gl16(p);			/* Sid (search handle) */
148
	*got = gl16(p);			/* number of slots received */
149
	gl16(p);			/* End of search flag */
150
	gl16(p);			/* Offset into EA list if EA error */
151
	gl16(p);			/* Offset into data to file name of last entry */
152
 
153
	gt2data(p);
154
	memset(fip, 0, slots * sizeof(FInfo));
155
	for(i = 0; i < *got; i++){
156
		next = p->pos;
157
		next += gl32(p);	/* offset to next entry */
158
		/*
159
		 * bug in Windows - somtimes it lies about how many
160
		 * directory entries it has put in the packet
161
		 */
162
		if(next - p->buf > pktlen){
163
			*got = i;
164
			break;
165
		}
166
 
167
		*resume = gl32(p);		/* resume key for search */
168
		fip[i].created = gvtime(p);	/* creation time */
169
		fip[i].accessed = gvtime(p);	/* last access time */
170
		fip[i].written = gvtime(p);	/* last written time */
171
		fip[i].changed = gvtime(p);	/* change time */
172
		fip[i].size = gl64(p);		/* file size */
173
		gl64(p);			/* bytes allocated */
174
		fip[i].attribs = gl32(p);	/* extended attributes */
175
		n = gl32(p);			/* name length */
176
		gl32(p);			/* EA size */
177
		gstr(p, fip[i].name, n); 	/* name */
178
		p->pos = next;
179
	}
180
 
181
	free(p);
182
	return sh;
183
 
184
}
185
 
186
int
187
T2findnext(Session *s, Share *sp, int slots, char *path, int *got,
188
	long *resume, FInfo *fip, int sh)
189
{
190
	Pkt *p;
191
	int i, n;
192
	uchar *next;
193
 
194
	/*
195
	 * So I believe from comp.protocols.smb if you send
196
	 * TRANS2_FIND_NEXT2 requests too quickly to windows 95, it can
197
	 * get confused and fail to reply, so we slow up a bit in these
198
	 * circumstances.
199
	 */
200
	if(!(s->caps & CAP_NT_SMBS) && nsec() - s->lastfind < 200000000LL)
201
		sleep(200);
202
 
203
	p = t2hdr(s, sp, TRANS2_FIND_NEXT2);
204
	p8(p, 'D');			/* OS/2 */
205
	p8(p, ' ');			/* OS/2 */
206
 
207
	pt2param(p);
208
	pl16(p, sh);				/* search handle */
209
	pl16(p, slots);				/* Search count */
210
	pl16(p, SMB_FIND_FILE_FULL_DIRECTORY_INFO); /* Information level */
211
	pl32(p, *resume);			/* resume key */
212
	pl16(p, CIFS_SEARCH_CONTINUE_FROM_LAST); /* Flags */
213
	ppath(p, path);				/* file+path to resume */
214
 
215
	pt2data(p);
216
	if(t2rpc(p) == -1){
217
		free(p);
218
		return -1;
219
	}
220
 
221
	s->lastfind = nsec();
222
 
223
	gt2param(p);
224
	*got = gl16(p);		/* number of slots received */
225
	gl16(p);		/* End of search flag */
226
	gl16(p);		/* Offset into EA list if EA error */
227
	gl16(p);		/* Offset into data to file name of last entry */
228
 
229
	gt2data(p);
230
	memset(fip, 0, slots * sizeof(FInfo));
231
	for(i = 0; i < *got; i++){
232
		next = p->pos;
233
		next += gl32(p);		/* offset to next entry */
234
		*resume = gl32(p);		/* resume key for search */
235
		fip[i].created = gvtime(p);	/* creation time */
236
		fip[i].accessed = gvtime(p);	/* last access time */
237
		fip[i].written = gvtime(p);	/* last written time */
238
		fip[i].changed = gvtime(p);	/* change time */
239
		fip[i].size = gl64(p);		/* file size */
240
		gl64(p);			/* bytes allocated */
241
		fip[i].attribs = gl32(p);	/* extended attributes */
242
		n = gl32(p);			/* name length */
243
		gl32(p);			/* EA size */
244
		gstr(p, fip[i].name, n); 	/* name */
245
		p->pos = next;
246
	}
247
	free(p);
248
	return 0;
249
}
250
 
251
 
252
/* supported by 2k/XP/NT4 */
253
int
254
T2queryall(Session *s, Share *sp, char *path, FInfo *fip)
255
{
256
	int n;
257
	Pkt *p;
258
 
259
	p = t2hdr(s, sp, TRANS2_QUERY_PATH_INFORMATION);
260
	pt2param(p);
261
	pl16(p, SMB_QUERY_FILE_ALL_INFO); /* Information level	 */
262
	pl32(p, 0);			/* reserved */
263
	ppath(p, path);			/* path */
264
 
265
	pt2data(p);
266
	if(t2rpc(p) == -1){
267
		free(p);
268
		return -1;
269
	}
270
	gt2data(p);
271
 
272
	/*
273
	 * The layout of this struct is wrong in the SINA
274
	 * document, this layout gained by inspection.
275
	 */
276
	memset(fip, 0, sizeof(FInfo));
277
	fip->created = gvtime(p);	/* creation time */
278
	fip->accessed = gvtime(p);	/* last access time */
279
	fip->written = gvtime(p);	/* last written time */
280
	fip->changed = gvtime(p);	/* change time */
281
	fip->attribs = gl32(p);		/* attributes */
282
	gl32(p);			/* reserved */
283
	gl64(p);			/* bytes allocated */
284
	fip->size = gl64(p);		/* file size */
285
	gl32(p);			/* number of hard links */
286
	g8(p);				/* delete pending */
287
	g8(p);				/* is a directory */
288
	gl16(p);			/* reserved */
289
	gl32(p);			/* EA size */
290
 
291
	n = gl32(p);
292
	if(n >= sizeof fip->name)
293
		n = sizeof fip->name - 1;
294
	gstr(p, fip->name, n);
295
 
296
	free(p);
297
	return 0;
298
}
299
 
300
/* supported by 95/98/ME */
301
int
302
T2querystandard(Session *s, Share *sp, char *path, FInfo *fip)
303
{
304
	Pkt *p;
305
 
306
	p = t2hdr(s, sp, TRANS2_QUERY_PATH_INFORMATION);
307
	pt2param(p);
308
	pl16(p, SMB_INFO_STANDARD);	/* Information level */
309
	pl32(p, 0);			/* reserved */
310
	ppath(p, path);			/* path */
311
 
312
	pt2data(p);
313
	if(t2rpc(p) == -1){
314
		free(p);
315
		return -1;
316
	}
317
	gt2data(p);
318
	memset(fip, 0, sizeof(FInfo));
319
	fip->created = gdatetime(p);	/* creation time */
320
	fip->accessed = gdatetime(p);	/* last access time */
321
	fip->written = gdatetime(p);	/* last written time */
322
	fip->changed = fip->written;	/* change time */
323
	fip->size = gl32(p);		/* file size */
324
	gl32(p);			/* bytes allocated */
325
	fip->attribs = gl16(p);		/* attributes */
326
	gl32(p);			/* EA size */
327
 
328
	free(p);
329
	return 0;
330
}
331
 
332
int
333
T2setpathinfo(Session *s, Share *sp, char *path, FInfo *fip)
334
{
335
	int rc;
336
	Pkt *p;
337
 
338
	p = t2hdr(s, sp, TRANS2_SET_PATH_INFORMATION);
339
	pt2param(p);
340
	pl16(p, SMB_INFO_STANDARD);	/* Information level */
341
	pl32(p, 0);			/* reserved */
342
	ppath(p, path);			/* path */
343
 
344
	pt2data(p);
345
	pdatetime(p, fip->created);	/* created */
346
	pdatetime(p, fip->accessed);	/* accessed */
347
	pdatetime(p, fip->written);	/* written */
348
	pl32(p, fip->size);		/* size */
349
	pl32(p, 0);			/* allocated */
350
	pl16(p, fip->attribs);		/* attributes */
351
	pl32(p, 0);			/* EA size */
352
	pl16(p, 0);			/* reserved */
353
 
354
	rc = t2rpc(p);
355
	free(p);
356
	return rc;
357
 
358
}
359
 
360
int
361
T2setfilelength(Session *s, Share *sp, int fh, FInfo *fip) /* FIXME: maybe broken, needs testing */
362
{
363
	int rc;
364
	Pkt *p;
365
 
366
	p = t2hdr(s, sp, TRANS2_SET_FILE_INFORMATION);
367
	pt2param(p);
368
	pl16(p, fh);			/* file handle */
369
	pl16(p, SMB_SET_FILE_END_OF_FILE_INFO); /* Information level */
370
	pl16(p, 0);			/* reserved */
371
 
372
	pt2data(p);
373
	pl64(p, fip->size);
374
	pl32(p, 0);			/* padding ?! */
375
	pl16(p, 0);
376
 
377
	rc = t2rpc(p);
378
	free(p);
379
	return rc;
380
}
381
 
382
 
383
int
384
T2fsvolumeinfo(Session *s, Share *sp, long *created, long *serialno,
385
	char *label, int labellen)
386
{
387
	Pkt *p;
388
	long ct, sn, n;
389
 
390
	p = t2hdr(s, sp, TRANS2_QUERY_FS_INFORMATION);
391
	pt2param(p);
392
	pl16(p, SMB_QUERY_FS_VOLUME_INFO);	/* Information level */
393
 
394
	pt2data(p);
395
 
396
	if(t2rpc(p) == -1){
397
		free(p);
398
		return -1;
399
	}
400
 
401
	gt2data(p);
402
	ct = gvtime(p);			/* creation time */
403
	sn = gl32(p);			/* serial number */
404
	n = gl32(p);			/* label name length */
405
	g8(p);				/* reserved */
406
	g8(p);				/* reserved */
407
 
408
	memset(label, 0, labellen);
409
	if(n < labellen && n > 0)
410
		gstr(p, label, n);	/* file system label */
411
	if(created)
412
		*created = ct;
413
	if(serialno)
414
		*serialno = sn;
415
 
416
	free(p);
417
	return 0;
418
}
419
 
420
int
421
T2fssizeinfo(Session *s, Share *sp, uvlong *total, uvlong *unused)
422
{
423
	Pkt *p;
424
	uvlong t, f, n, b;
425
 
426
	p = t2hdr(s, sp, TRANS2_QUERY_FS_INFORMATION);
427
	pt2param(p);
428
	pl16(p, SMB_QUERY_FS_SIZE_INFO);	/* Information level */
429
 
430
	pt2data(p);
431
 
432
	if(t2rpc(p) == -1){
433
		free(p);
434
		return -1;
435
	}
436
 
437
	gt2data(p);
438
	t = gl64(p);		/* total blocks */
439
	f = gl64(p);		/* free blocks */
440
	n = gl32(p);		/* sectors per block */
441
	b = gl32(p);		/* bytes per sector */
442
 
443
	if(free)
444
		*unused = f * n * b;
445
	if(total)
446
		*total = t * n * b;
447
 
448
	free(p);
449
	return 0;
450
}
451
 
452
int
453
T2getdfsreferral(Session *s, Share *sp, char *path, int *gflags, int *used,
454
	Refer *re, int nent)
455
{
456
	int i, vers, nret, len;
457
	char tmp[1024];
458
	uchar *base;
459
	Pkt *p;
460
 
461
	p = t2hdr(s, sp, TRANS2_GET_DFS_REFERRAL);
462
	pt2param(p);
463
	pl16(p, 3); /* max info level we understand, must be >= 3 for domain requests */
464
	ppath(p, path);
465
 
466
	pt2data(p);
467
 
468
	if(t2rpc(p) == -1){
469
		free(p);
470
		return -1;
471
	}
472
 
473
	memset(re, 0, sizeof *re * nent);
474
	gt2data(p);
475
 
476
	*used = gl16(p) / 2;	/* length used (/2 as Windows counts in runes) */
477
	nret = gl16(p);		/* number of referrals returned */
478
	*gflags = gl32(p);	/* global flags */
479
 
480
	for(i = 0; i < nret && i < nent && i < 16; i++){
481
		base = p->pos;
482
		vers = gl16(p);		/* version of records */
483
		len = gl16(p);		/* length of records */
484
		re[i].type = gl16(p);	/* server type */
485
		re[i].flags = gl16(p);	/* referal flags */
486
		switch(vers){
487
		case 1:
488
			re[i].prox = 0;	/* nearby */
489
			re[i].ttl = 5*60;	/* 5 mins */
490
			gstr(p, tmp, sizeof tmp);
491
			re[i].addr = estrdup9p(tmp);
492
			re[i].path = estrdup9p(tmp);
493
			break;
494
		case 2:
495
			re[i].prox = gl32(p);	/* not implemented in v2 */
496
			re[i].ttl = gl32(p);
497
			goff(p, base, re[i].path, sizeof tmp);
498
			re[i].path = estrdup9p(tmp);
499
			goff(p, base, re[i].path, sizeof tmp);/* spurious 8.3 path */
500
			goff(p, base, tmp, sizeof tmp);
501
			re[i].addr = estrdup9p(tmp);
502
			break;
503
		case 3:
504
			if(re[i].flags & DFS_REFERAL_LIST){
505
				re[i].prox = 0;
506
				re[i].ttl = gl32(p);
507
				goff(p, base, tmp, sizeof tmp);
508
				re[i].path = estrdup9p(tmp);
509
				gl16(p);
510
				goff(p, base, tmp, sizeof tmp);
511
				re[i].addr = estrdup9p(tmp);
512
			}
513
			else{
514
				re[i].prox = 0;
515
				re[i].ttl = gl32(p);
516
				goff(p, base, tmp, sizeof tmp);
517
				re[i].path = estrdup9p(tmp);
518
				gl16(p);	/* spurious 8.3 path */
519
				goff(p, base, tmp, sizeof tmp);
520
				re[i].addr = estrdup9p(tmp);
521
				gl16(p);	/* GUID (historic) */
522
			}
523
			break;
524
		default:
525
			/*
526
			 * this should never happen as we specify our maximum
527
			 * understood level in the request (above)
528
			 */
529
			fprint(2, "%d - unsupported DFS infolevel\n", vers);
530
			re[i].path = estrdup9p(tmp);
531
			re[i].addr = estrdup9p(tmp);
532
			break;
533
		}
534
		p->pos = base+len;
535
	}
536
 
537
	free(p);
538
	return i;
539
}