This source file includes following definitions.
- smb_encode_word
- smb_decode_word
- smb_decode_dword
- smb_encode_smb_length
- smb_encode_dialect
- smb_encode_ascii
- smb_encode_vblock
- smb_decode_data
- smb_name_mangle
- utc2local
- local2utc
- date_dos2unix
- date_unix2dos
- smb_len
- smb_bcc
- smb_valid_packet
- smb_verify
- smb_errno
- print_char
- smb_dump_packet
- smb_lock_server
- smb_unlock_server
- smb_request_ok
- smb_retry
- smb_request_ok_unlock
- smb_setup_header
- smb_setup_header_exclusive
- smb_proc_open
- smb_proc_close
- smb_proc_read
- smb_proc_write
- smb_proc_do_create
- smb_proc_create
- smb_proc_mknew
- smb_proc_mv
- smb_proc_mkdir
- smb_proc_rmdir
- smb_proc_unlink
- smb_proc_trunc
- smb_decode_dirent
- smb_proc_readdir_short
- smb_decode_long_dirent
- smb_proc_readdir_long
- smb_proc_readdir
- smb_proc_getattr_core
- smb_proc_getattrE
- smb_proc_getattr
- smb_proc_setattr_core
- smb_proc_setattrE
- smb_proc_setattr
- smb_proc_dskattr
- smb_proc_reconnect
- smb_proc_connect
- smb_proc_disconnect
- smb_printerr
1
2
3
4
5
6
7
8 #include <linux/config.h>
9 #ifdef MODULE
10 #include <linux/module.h>
11 #include <linux/version.h>
12 #endif
13
14
15 #include <linux/fs.h>
16 #include <linux/smbno.h>
17 #include <linux/smb_fs.h>
18 #include <linux/types.h>
19 #include <linux/errno.h>
20 #include <linux/malloc.h>
21 #include <linux/stat.h>
22 #include <linux/fcntl.h>
23 #include <asm/segment.h>
24 #include <asm/string.h>
25
26 #define ARCH i386
27 #define SMB_VWV(packet) ((packet) + SMB_HEADER_LEN)
28 #define SMB_CMD(packet) ((packet)[8])
29 #define SMB_WCT(packet) ((packet)[SMB_HEADER_LEN - 1])
30 #define SMB_BCC(packet) smb_bcc(packet)
31 #define SMB_BUF(packet) ((packet) + SMB_HEADER_LEN + SMB_WCT(packet) * 2 + 2)
32
33 #define SMB_DIRINFO_SIZE 43
34 #define SMB_STATUS_SIZE 21
35
36 #define HI_WORD(l) ((word)(l >> 16))
37 #define LO_WORD(l) ((word)(l % 0xFFFF))
38
39 void smb_printerr(int class, int num);
40 static int smb_request_ok(struct smb_server *s, int command, int wct, int bcc);
41
42
43
44
45
46
47
48 static byte *
49 smb_encode_word(byte *p, word data)
50 {
51 #if (ARCH == i386)
52 *((word *)p) = data;
53 #else
54 p[0] = data & 0x00ffU;
55 p[1] = (data & 0xff00U) >> 8;
56 #error "Non-Intel"
57 #endif
58 return &p[2];
59 }
60
61 static byte *
62 smb_decode_word(byte *p, word *data)
63 {
64 #if (ARCH == i386)
65 *data = *(word *)p;
66 #else
67 *data = (word) p[0] | p[1] << 8;
68 #endif
69 return &p[2];
70 }
71
72 static byte *
73 smb_decode_dword(byte *p, dword *data)
74 {
75 #if (ARCH == i386)
76 *data = *((dword *)p);
77 #else
78 *data = (dword)p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
79 #endif
80 return &p[4];
81 }
82
83 static byte *
84 smb_encode_smb_length(byte *p, dword len)
85 {
86 p[0] = p[1] = 0;
87 p[2] = (len & 0xFF00) >> 8;
88 p[3] = (len & 0xFF);
89 if (len > 0xFFFF)
90 p[1] |= 0x01;
91 return &p[4];
92 }
93
94 static byte *
95 smb_encode_dialect(byte *p, const byte *name, int len)
96 {
97 *p ++ = 2;
98 strcpy(p, name);
99 return p + len + 1;
100 }
101
102 static byte *
103 smb_encode_ascii(byte *p, const byte *name, int len)
104 {
105 *p ++ = 4;
106 strcpy(p, name);
107 return p + len + 1;
108 }
109
110 static byte *
111 smb_encode_vblock(byte *p, const byte *data, word len, int fs)
112 {
113 *p ++ = 5;
114 p = smb_encode_word(p, len);
115 if (fs)
116 memcpy_fromfs(p, data, len);
117 else
118 memcpy(p, data, len);
119 return p + len;
120 }
121
122 static byte *
123 smb_decode_data(byte *p, byte *data, word *data_len, int fs)
124 {
125 word len;
126
127 if (!(*p == 1 || *p == 5)) {
128 printk("smb_decode_data: Warning! Data block not starting "
129 "with 1 or 5\n");
130 }
131
132 len = WVAL(p, 1);
133 p += 3;
134
135 if (fs)
136 memcpy_tofs(data, p, len);
137 else
138 memcpy(data, p, len);
139
140 *data_len = len;
141
142 return p + len;
143 }
144
145 static byte *
146 smb_name_mangle(byte *p, const byte *name)
147 {
148 int len, pad = 0;
149
150 len = strlen(name);
151
152 if (len < 16)
153 pad = 16 - len;
154
155 *p ++ = 2 * (len + pad);
156
157 while (*name) {
158 *p ++ = (*name >> 4) + 'A';
159 *p ++ = (*name & 0x0F) + 'A';
160 name ++;
161 }
162 while (pad --) {
163 *p ++ = 'C';
164 *p ++ = 'A';
165 }
166 *p++ = '\0';
167
168 return p;
169 }
170
171
172
173
174
175 static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
176
177
178
179 extern struct timezone sys_tz;
180
181 static int
182 utc2local(int time)
183 {
184 return time - sys_tz.tz_minuteswest*60;
185 }
186
187 static int
188 local2utc(int time)
189 {
190 return time + sys_tz.tz_minuteswest*60;
191 }
192
193
194
195 static int
196 date_dos2unix(unsigned short time,unsigned short date)
197 {
198 int month,year,secs;
199
200 month = ((date >> 5) & 15)-1;
201 year = date >> 9;
202 secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
203 ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
204 month < 2 ? 1 : 0)+3653);
205
206 return local2utc(secs);
207 }
208
209
210
211
212 static void
213 date_unix2dos(int unix_date,unsigned short *time, unsigned short *date)
214 {
215 int day,year,nl_day,month;
216
217 unix_date = utc2local(unix_date);
218 *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
219 (((unix_date/3600) % 24) << 11);
220 day = unix_date/86400-3652;
221 year = day/365;
222 if ((year+3)/4+365*year > day) year--;
223 day -= (year+3)/4+365*year;
224 if (day == 59 && !(year & 3)) {
225 nl_day = day;
226 month = 2;
227 }
228 else {
229 nl_day = (year & 3) || day <= 59 ? day : day-1;
230 for (month = 0; month < 12; month++)
231 if (day_n[month] > nl_day) break;
232 }
233 *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);
234 }
235
236
237
238
239
240
241
242
243
244 dword
245 smb_len(byte *packet)
246 {
247 return ((packet[1] & 0x1) << 16L) | (packet[2] << 8L) | (packet[3]);
248 }
249
250 static word
251 smb_bcc(byte *packet)
252 {
253 int pos = SMB_HEADER_LEN + SMB_WCT(packet) * sizeof(word);
254 #if (ARCH == i386)
255 return *((word *)((byte *)packet + pos));
256 #else
257 return packet[pos] | packet[pos+1] << 8;
258 #endif
259 }
260
261
262
263
264 static int
265 smb_valid_packet(byte *packet)
266 {
267 DDPRINTK("len: %ld, wct: %d, bcc: %d\n",
268 smb_len(packet), SMB_WCT(packet), SMB_BCC(packet));
269 return ( packet[4] == 0xff
270 && packet[5] == 'S'
271 && packet[6] == 'M'
272 && packet[7] == 'B'
273 && (smb_len(packet) + 4 == SMB_HEADER_LEN
274 + SMB_WCT(packet) * 2 + SMB_BCC(packet)));
275 }
276
277
278
279
280 static int
281 smb_verify(byte *packet, int command, int wct, int bcc)
282 {
283 return (SMB_CMD(packet) == command &&
284 SMB_WCT(packet) >= wct &&
285 (bcc == -1 || SMB_BCC(packet) == bcc)) ? 0 : -EIO;
286 }
287
288 static int
289 smb_errno(int errcls, int error)
290 {
291
292 #if DEBUG_SMB > 1
293 if (errcls) {
294 printk("smb_errno: ");
295 smb_printerr(errcls, error);
296 printk("\n");
297 }
298 #endif
299
300 if (errcls == ERRDOS)
301 switch (error) {
302 case ERRbadfunc: return EINVAL;
303 case ERRbadfile: return ENOENT;
304 case ERRbadpath: return ENOENT;
305 case ERRnofids: return EMFILE;
306 case ERRnoaccess: return EACCES;
307 case ERRbadfid: return EBADF;
308 case ERRbadmcb: return EREMOTEIO;
309 case ERRnomem: return ENOMEM;
310 case ERRbadmem: return EFAULT;
311 case ERRbadenv: return EREMOTEIO;
312 case ERRbadformat: return EREMOTEIO;
313 case ERRbadaccess: return EACCES;
314 case ERRbaddata: return E2BIG;
315 case ERRbaddrive: return ENXIO;
316 case ERRremcd: return EREMOTEIO;
317 case ERRdiffdevice: return EXDEV;
318 case ERRnofiles: return 0;
319 case ERRbadshare: return ETXTBSY;
320 case ERRlock: return EDEADLOCK;
321 case ERRfilexists: return EEXIST;
322 case 87: return 0;
323 default: return EIO;
324 }
325 else if (errcls == ERRSRV)
326 switch (error) {
327 case ERRerror: return ENFILE;
328 case ERRbadpw: return EINVAL;
329 case ERRbadtype: return EIO;
330 case ERRaccess: return EACCES;
331 default: return EIO;
332 }
333 else if (errcls == ERRHRD)
334 switch (error) {
335 case ERRnowrite: return EROFS;
336 case ERRbadunit: return ENODEV;
337 case ERRnotready: return EUCLEAN;
338 case ERRbadcmd: return EIO;
339 case ERRdata: return EIO;
340 case ERRbadreq: return ERANGE;
341 case ERRbadshare: return ETXTBSY;
342 case ERRlock: return EDEADLOCK;
343 default: return EIO;
344 }
345 else if (errcls == ERRCMD)
346 return EIO;
347 return 0;
348 }
349
350 #if DEBUG_SMB > 0
351 static char
352 print_char(char c)
353 {
354 if ((c < ' ') || (c > '~'))
355 return '.';
356 return c;
357 }
358
359 static void
360 smb_dump_packet(byte *packet) {
361 int i, j, len;
362 int errcls, error;
363
364 errcls = (int)packet[9];
365 error = (int)(int)(packet[11]|packet[12]<<8);
366
367 printk("smb_len = %d valid = %d \n",
368 len = smb_len(packet), smb_valid_packet(packet));
369 printk("smb_cmd = %d smb_wct = %d smb_bcc = %d\n",
370 packet[8], SMB_WCT(packet), SMB_BCC(packet));
371 printk("smb_rcls = %d smb_err = %d\n", errcls, error);
372
373 if (errcls) {
374 smb_printerr(errcls, error);
375 printk("\n");
376 }
377
378 if (len > 100)
379 len = 100;
380
381 for (i = 0; i < len; i += 10) {
382 printk("%03d:", i);
383 for (j = i; j < i+10; j++)
384 if (j < len)
385 printk("%02x ", packet[j]);
386 else
387 printk(" ");
388 printk(": ");
389 for (j = i; j < i+10; j++)
390 if (j < len)
391 printk("%c", print_char(packet[j]));
392 printk("\n");
393 }
394 }
395 #endif
396
397 static void
398 smb_lock_server(struct smb_server *server)
399 {
400 while (server->lock)
401 sleep_on(&server->wait);
402 server->lock = 1;
403 }
404
405 static void
406 smb_unlock_server(struct smb_server *server)
407 {
408 if (server->lock != 1) {
409 printk("smb_unlock_server: was not locked!\n");
410 }
411
412 server->lock = 0;
413 wake_up(&server->wait);
414 }
415
416
417
418
419
420
421 static int
422 smb_request_ok(struct smb_server *s, int command, int wct, int bcc)
423 {
424 int result = 0;
425 s->rcls = 0;
426 s->err = 0;
427
428 if (smb_request(s) < 0) {
429 DPRINTK("smb_request failed\n");
430 result = -EIO;
431 }
432 else if (smb_valid_packet(s->packet) != 0) {
433 DPRINTK("not a valid packet!\n");
434 result = -EIO;
435 }
436 else if (s->rcls != 0) {
437 result = -smb_errno(s->rcls, s->err);
438 }
439 else if (smb_verify(s->packet, command, wct, bcc) != 0) {
440 DPRINTK("smb_verify failed\n");
441 result = -EIO;
442 }
443
444 return result;
445 }
446
447
448
449
450
451
452
453 static int
454 smb_retry(struct smb_server *server)
455 {
456 if (server->state != CONN_INVALID) {
457 return 0;
458 }
459
460 if (smb_release(server) < 0) {
461 DPRINTK("smb_retry: smb_release failed\n");
462 server->state = CONN_RETRIED;
463 return 0;
464 }
465 if(smb_proc_reconnect(server) < 0) {
466 DPRINTK("smb_proc_reconnect failed\n");
467 server->state = CONN_RETRIED;
468 return 0;
469 }
470
471 server->state = CONN_VALID;
472 return 1;
473 }
474
475 static int
476 smb_request_ok_unlock(struct smb_server *s, int command, int wct, int bcc)
477 {
478 int result = smb_request_ok(s, command, wct, bcc);
479
480 smb_unlock_server(s);
481
482 return result;
483 }
484
485
486
487
488 static byte *
489 smb_setup_header(struct smb_server *server, byte command, word wct, word bcc)
490 {
491 dword xmit_len = SMB_HEADER_LEN + wct * sizeof(word) + bcc + 2;
492 byte *p = server->packet;
493 byte *buf = server->packet;
494
495 p = smb_encode_smb_length(p, xmit_len);
496
497 BSET(p,0,0xff);
498 BSET(p,1,'S');
499 BSET(p,2,'M');
500 BSET(p,3,'B');
501 BSET(p,4,command);
502
503 p += 5;
504 memset(p, '\0', 19);
505 p += 19;
506 p += 8;
507
508 WSET(buf, smb_tid, server->tid);
509 WSET(buf, smb_pid, server->pid);
510 WSET(buf, smb_uid, server->server_uid);
511 WSET(buf, smb_mid, server->mid);
512
513 if (server->protocol > PROTOCOL_CORE) {
514 BSET(buf, smb_flg, 0x8);
515 WSET(buf, smb_flg2, 0x3);
516 }
517
518 *p++ = wct;
519 p += 2*wct;
520 WSET(p, 0, bcc);
521 return p+2;
522 }
523
524
525
526
527
528 static byte *
529 smb_setup_header_exclusive(struct smb_server *server,
530 byte command, word wct, word bcc)
531 {
532 smb_lock_server(server);
533 return smb_setup_header(server, command, wct, bcc);
534 }
535
536
537
538
539
540
541
542
543 int
544 smb_proc_open(struct smb_server *server, const char *pathname, int len,
545 struct smb_dirent *entry)
546 {
547 int error;
548 char* p;
549 char* buf = server->packet;
550 const word o_attr = aSYSTEM | aHIDDEN | aDIR;
551
552 DPRINTK("smb_proc_open: path=%s\n", pathname);
553
554 smb_lock_server(server);
555
556 retry:
557 p = smb_setup_header(server, SMBopen, 2, 2 + len);
558 WSET(buf, smb_vwv0, 0x42);
559 WSET(buf, smb_vwv1, o_attr);
560 smb_encode_ascii(p, pathname, len);
561
562 if ((error = smb_request_ok(server, SMBopen, 7, 0)) != 0) {
563
564 if (smb_retry(server)) {
565 goto retry;
566 }
567
568 if (error != -EACCES) {
569 smb_unlock_server(server);
570 return error;
571 }
572
573 p = smb_setup_header(server, SMBopen, 2, 2 + len);
574 WSET(buf, smb_vwv0, 0x40);
575 WSET(buf, smb_vwv1, o_attr);
576 smb_encode_ascii(p, pathname, len);
577
578 if ((error = smb_request_ok(server, SMBopen, 7, 0)) != 0) {
579 if (smb_retry(server)) {
580 goto retry;
581 }
582 smb_unlock_server(server);
583 return error;
584 }
585 }
586
587
588
589 entry->fileid = WVAL(buf, smb_vwv0);
590 entry->attr = WVAL(buf, smb_vwv1);
591 entry->ctime = entry->atime =
592 entry->mtime = local2utc(DVAL(buf, smb_vwv2));
593 entry->size = DVAL(buf, smb_vwv4);
594 entry->access = WVAL(buf, smb_vwv6);
595
596 smb_unlock_server(server);
597
598 entry->access &= 3;
599 DPRINTK("smb_proc_open: entry->access = %d\n", entry->access);
600 return 0;
601 }
602
603
604
605 int
606 smb_proc_close(struct smb_server *server, struct smb_dirent *finfo)
607 {
608 char *buf = server->packet;
609
610 smb_setup_header_exclusive(server, SMBclose, 3, 0);
611 WSET(buf, smb_vwv0, finfo->fileid);
612 DSET(buf, smb_vwv1, utc2local(finfo->mtime));
613
614 return smb_request_ok_unlock(server, SMBclose, 0, 0);
615 }
616
617
618
619
620
621
622
623 int
624 smb_proc_read(struct smb_server *server, struct smb_dirent *finfo,
625 off_t offset, long count, char *data, int fs)
626 {
627 word returned_count, data_len;
628 char *buf = server->packet;
629 int error;
630
631 smb_setup_header_exclusive(server, SMBread, 5, 0);
632
633 WSET(buf, smb_vwv0, finfo->fileid);
634 WSET(buf, smb_vwv1, count);
635 DSET(buf, smb_vwv2, offset);
636 WSET(buf, smb_vwv4, 0);
637
638 if ((error = smb_request_ok(server, SMBread, 5, -1)) < 0) {
639 smb_unlock_server(server);
640 return error;
641 }
642
643 returned_count = WVAL(buf, smb_vwv0);
644
645 smb_decode_data(SMB_BUF(server->packet), data, &data_len, fs);
646
647 smb_unlock_server(server);
648
649 if (returned_count != data_len) {
650 printk("smb_proc_read: Warning, returned_count != data_len\n");
651 printk("smb_proc_read: ret_c=%d, data_len=%d\n",
652 returned_count, data_len);
653 }
654
655 return data_len;
656 }
657
658 int
659 smb_proc_write(struct smb_server *server, struct smb_dirent *finfo,
660 off_t offset, int count, const char *data)
661 {
662 int res = 0;
663 char *buf = server->packet;
664 byte *p;
665
666 p = smb_setup_header_exclusive(server, SMBwrite, 5, count + 3);
667 WSET(buf, smb_vwv0, finfo->fileid);
668 WSET(buf, smb_vwv1, count);
669 DSET(buf, smb_vwv2, offset);
670 WSET(buf, smb_vwv4, 0);
671
672 *p++ = 1;
673 WSET(p, 0, count);
674 memcpy_fromfs(p+2, data, count);
675
676 if ((res = smb_request_ok(server, SMBwrite, 1, 0)) >= 0) {
677 res = WVAL(buf, smb_vwv0);
678 }
679
680 smb_unlock_server(server);
681
682 return res;
683 }
684
685
686
687 static int
688 smb_proc_do_create(struct smb_server *server, const char *path, int len,
689 struct smb_dirent *entry, word command)
690 {
691 int error;
692 char *p;
693 char *buf = server->packet;
694
695 smb_lock_server(server);
696 retry:
697 p = smb_setup_header(server, command, 3, len + 2);
698 WSET(buf, smb_vwv0, entry->attr);
699 DSET(buf, smb_vwv1, utc2local(entry->ctime));
700 smb_encode_ascii(p, path, len);
701
702 if ((error = smb_request_ok(server, command, 1, 0)) < 0) {
703 if (smb_retry(server)) {
704 goto retry;
705 }
706 smb_unlock_server(server);
707 return error;
708 }
709
710 entry->opened = 1;
711 entry->fileid = WVAL(buf, smb_vwv0);
712 smb_unlock_server(server);
713
714 smb_proc_close(server, entry);
715
716 return 0;
717 }
718
719 int
720 smb_proc_create(struct smb_server *server, const char *path, int len,
721 struct smb_dirent *entry)
722 {
723 return smb_proc_do_create(server, path, len, entry, SMBcreate);
724 }
725
726 int
727 smb_proc_mknew(struct smb_server *server, const char *path, int len,
728 struct smb_dirent *entry)
729 {
730 return smb_proc_do_create(server, path, len, entry, SMBmknew);
731 }
732
733 int
734 smb_proc_mv(struct smb_server *server,
735 const char *opath, const int olen,
736 const char *npath, const int nlen)
737 {
738 char *p;
739 char *buf = server->packet;
740 int result;
741
742 smb_lock_server(server);
743
744 retry:
745 p = smb_setup_header(server, SMBmv, 1, olen + nlen + 4);
746 WSET(buf, smb_vwv0, 0);
747 p = smb_encode_ascii(p, opath, olen);
748 smb_encode_ascii(p, npath, olen);
749
750 if ((result = smb_request_ok(server, SMBmv, 0, 0)) < 0) {
751 if (smb_retry(server)) {
752 goto retry;
753 }
754 }
755 smb_unlock_server(server);
756 return result;
757 }
758
759 int
760 smb_proc_mkdir(struct smb_server *server, const char *path, const int len)
761 {
762 char *p;
763 int result;
764
765 smb_lock_server(server);
766
767 retry:
768 p = smb_setup_header(server, SMBmkdir, 0, 2 + len);
769 smb_encode_ascii(p, path, len);
770
771 if ((result = smb_request_ok(server, SMBmkdir, 0, 0)) < 0) {
772 if (smb_retry(server)) {
773 goto retry;
774 }
775 }
776 smb_unlock_server(server);
777 return result;
778 }
779
780 int
781 smb_proc_rmdir(struct smb_server *server, const char *path, const int len)
782 {
783 char *p;
784 int result;
785
786 smb_lock_server(server);
787
788 retry:
789 p = smb_setup_header(server, SMBrmdir, 0, 2 + len);
790 smb_encode_ascii(p, path, len);
791
792 if ((result = smb_request_ok(server, SMBrmdir, 0, 0)) < 0) {
793 if (smb_retry(server)) {
794 goto retry;
795 }
796 }
797 smb_unlock_server(server);
798 return result;
799 }
800
801 int
802 smb_proc_unlink(struct smb_server *server, const char *path, const int len)
803 {
804 char *p;
805 char *buf = server->packet;
806 int result;
807
808 smb_lock_server(server);
809
810 retry:
811 p = smb_setup_header(server, SMBunlink, 1, 2 + len);
812 WSET(buf, smb_vwv0, 0);
813 smb_encode_ascii(p, path, len);
814
815 if ((result = smb_request_ok(server, SMBunlink, 0, 0)) < 0) {
816 if (smb_retry(server)) {
817 goto retry;
818 }
819 }
820 smb_unlock_server(server);
821 return result;
822 }
823
824 int
825 smb_proc_trunc(struct smb_server *server, word fid, dword length)
826 {
827 char *p;
828 char *buf = server->packet;
829 int result;
830
831 smb_lock_server(server);
832
833 retry:
834 p = smb_setup_header(server, SMBwrite, 5, 3);
835 WSET(buf, smb_vwv0, fid);
836 WSET(buf, smb_vwv1, 0);
837 DSET(buf, smb_vwv2, length);
838 WSET(buf, smb_vwv4, 0);
839 smb_encode_ascii(p, "", 0);
840
841 if ((result = smb_request_ok(server, SMBwrite, 1, 0)) < 0) {
842 if (smb_retry(server)) {
843 goto retry;
844 }
845 }
846 smb_unlock_server(server);
847 return result;
848 }
849
850 static char *
851 smb_decode_dirent(char *p, struct smb_dirent *entry)
852 {
853 p += SMB_STATUS_SIZE;
854 entry->attr = BVAL(p, 0);
855 entry->mtime = entry->atime = entry->ctime =
856 date_dos2unix(WVAL(p, 1), WVAL(p, 3));
857 entry->size = DVAL(p, 5);
858 memcpy(entry->path, p+9, 13);
859 DDPRINTK("smb_decode_dirent: path = %s\n", entry->path);
860 return p + 22;
861 }
862
863
864
865
866
867 static int
868 smb_proc_readdir_short(struct smb_server *server, struct inode *dir, int fpos,
869 int cache_size, struct smb_dirent *entry)
870 {
871 char *p;
872 char *buf;
873 int error;
874 int result;
875 int i;
876 int first, total_count;
877 struct smb_dirent *current_entry;
878 word bcc;
879 word count;
880 char status[SMB_STATUS_SIZE];
881 int entries_asked = (server->max_xmit - 100) / SMB_DIRINFO_SIZE;
882 int dirlen = strlen(SMB_FINFO(dir)->path);
883 char mask[dirlen + 5];
884
885 strcpy(mask, SMB_FINFO(dir)->path);
886 strcat(mask, "\\*.*");
887
888 DPRINTK("SMB call readdir %d @ %d\n", cache_size, fpos);
889 DPRINTK(" mask = %s\n", mask);
890
891 buf = server->packet;
892
893 smb_lock_server(server);
894
895 retry:
896 first = 1;
897 total_count = 0;
898 current_entry = entry;
899
900 while (1) {
901 if (first == 1) {
902 p = smb_setup_header(server, SMBsearch, 2,
903 5 + strlen(mask));
904 WSET(buf, smb_vwv0, entries_asked);
905 WSET(buf, smb_vwv1, aDIR);
906 p = smb_encode_ascii(p, mask, strlen(mask));
907 *p ++ = 5;
908 p = smb_encode_word(p, 0);
909 } else {
910 p = smb_setup_header(server, SMBsearch, 2,
911 5 + SMB_STATUS_SIZE);
912 WSET(buf, smb_vwv0, entries_asked);
913 WSET(buf, smb_vwv1, aDIR);
914 p = smb_encode_ascii(p, "", 0);
915 p = smb_encode_vblock(p, status, SMB_STATUS_SIZE, 0);
916 }
917
918 if ((error = smb_request_ok(server, SMBsearch, 1, -1)) < 0) {
919 if ( (server->rcls == ERRDOS)
920 && (server->err == ERRnofiles)) {
921 result = total_count - fpos;
922 goto unlock_return;
923 }
924 else
925 {
926 if (smb_retry(server)) {
927 goto retry;
928 }
929 result = error;
930 goto unlock_return;
931 }
932 }
933
934 p = SMB_VWV(server->packet);
935 p = smb_decode_word(p, &count);
936 p = smb_decode_word(p, &bcc);
937
938 first = 0;
939
940 if (count <= 0) {
941 result = total_count - fpos;
942 goto unlock_return;
943 }
944 if (bcc != count * SMB_DIRINFO_SIZE + 3) {
945 result = -EIO;
946 goto unlock_return;
947 }
948
949 p += 3;
950
951
952 memcpy(status,
953 SMB_BUF(server->packet) + 3 +
954 (count - 1) * SMB_DIRINFO_SIZE,
955 SMB_STATUS_SIZE);
956
957
958
959 for (i = 0; i < count; i ++) {
960 if (total_count < fpos) {
961 p += SMB_DIRINFO_SIZE;
962 DDPRINTK("smb_proc_readdir: skipped entry.\n");
963 DDPRINTK(" total_count = %d\n"
964 " i = %d, fpos = %d\n",
965 total_count, i, fpos);
966 }
967 else if (total_count >= fpos + cache_size) {
968 result = total_count - fpos;
969 goto unlock_return;
970 }
971 else {
972 p = smb_decode_dirent(p, current_entry);
973 current_entry->f_pos = total_count;
974 DDPRINTK("smb_proc_readdir: entry->f_pos = "
975 "%lu\n", entry->f_pos);
976 current_entry += 1;
977 }
978 total_count += 1;
979 }
980 }
981 unlock_return:
982 smb_unlock_server(server);
983 return result;
984 }
985
986
987
988
989
990
991 static char *
992 smb_decode_long_dirent(char *p, struct smb_dirent *finfo, int level)
993 {
994 char *result;
995
996 if (finfo) {
997
998
999 finfo->ctime = finfo->mtime = finfo->atime = 0;
1000 }
1001
1002 switch (level)
1003 {
1004 case 1:
1005 if (finfo)
1006 {
1007 DPRINTK("received entry\n");
1008 strcpy(finfo->path,p+27);
1009 finfo->len = strlen(finfo->path);
1010 finfo->size = DVAL(p,16);
1011 finfo->attr = BVAL(p,24);
1012
1013 finfo->ctime = date_dos2unix(WVAL(p, 6), WVAL(p, 4));
1014 finfo->atime = date_dos2unix(WVAL(p, 10), WVAL(p, 8));
1015 finfo->mtime = date_dos2unix(WVAL(p, 14), WVAL(p, 12));
1016 }
1017 result = p + 28 + BVAL(p,26);
1018 break;
1019
1020 case 2:
1021 if (finfo)
1022 {
1023 strcpy(finfo->path,p+31);
1024 finfo->len = strlen(finfo->path);
1025 finfo->size = DVAL(p,16);
1026 finfo->attr = BVAL(p,24);
1027 #if 0
1028 finfo->atime = make_unix_date2(p+8);
1029 finfo->mtime = make_unix_date2(p+12);
1030 #endif
1031 }
1032 result = p + 32 + BVAL(p,30);
1033 break;
1034
1035 case 260:
1036 result = p + WVAL(p,0);
1037 if (finfo)
1038 {
1039 int namelen;
1040 p += 4;
1041 p += 4;
1042
1043 p += 8;
1044
1045 p += 8;
1046 p += 8;
1047
1048 p += 8;
1049 finfo->size = DVAL(p,0);
1050 p += 8;
1051 p += 8;
1052 finfo->attr = BVAL(p,0);
1053 p += 4;
1054 namelen = min(DVAL(p,0), SMB_MAXNAMELEN);
1055 p += 4;
1056 p += 4;
1057 p += 2;
1058 p += 24;
1059 strncpy(finfo->path,p,namelen);
1060 finfo->len = namelen;
1061 }
1062 break;
1063
1064 default:
1065 DPRINTK("Unknown long filename format %d\n",level);
1066 result = p + WVAL(p,0);
1067 }
1068 return result;
1069 }
1070
1071 int
1072 smb_proc_readdir_long(struct smb_server *server, struct inode *dir, int fpos,
1073 int cache_size, struct smb_dirent *entry)
1074 {
1075 int max_matches = 512;
1076
1077
1078 int info_level = 1;
1079
1080 char *p;
1081 int i;
1082 int first, total_count;
1083 struct smb_dirent *current_entry;
1084
1085 char *resp_data;
1086 char *resp_param;
1087 int resp_data_len = 0;
1088 int resp_param_len=0;
1089
1090 int attribute = aSYSTEM | aHIDDEN | aDIR;
1091 int result;
1092
1093 int ff_resume_key = 0;
1094 int ff_searchcount=0;
1095 int ff_eos=0;
1096 int ff_lastname=0;
1097 int ff_dir_handle=0;
1098 int loop_count = 0;
1099
1100 int dirlen = strlen(SMB_FINFO(dir)->path);
1101 char mask[dirlen + 5];
1102
1103 strcpy(mask, SMB_FINFO(dir)->path);
1104 strcat(mask, "\\*");
1105
1106 DPRINTK("SMB call lreaddir %d @ %d\n", cache_size, fpos);
1107 DPRINTK(" mask = %s\n", mask);
1108
1109 resp_param = NULL;
1110 resp_data = NULL;
1111
1112 smb_lock_server(server);
1113
1114 retry:
1115
1116 first = 1;
1117 total_count = 0;
1118 current_entry = entry;
1119
1120 while (ff_eos == 0)
1121 {
1122 int masklen = strlen(mask);
1123 unsigned char *outbuf = server->packet;
1124
1125 loop_count += 1;
1126 if (loop_count > 200)
1127 {
1128 printk("smb_proc_readdir_long: "
1129 "Looping in FIND_NEXT??\n");
1130 break;
1131 }
1132
1133 smb_setup_header(server, SMBtrans2, 15,
1134 5 + 12 + masklen + 1);
1135
1136 WSET(outbuf,smb_tpscnt,12 + masklen +1);
1137 WSET(outbuf,smb_tdscnt,0);
1138 WSET(outbuf,smb_mprcnt,10);
1139 WSET(outbuf,smb_mdrcnt,TRANS2_MAX_TRANSFER);
1140 WSET(outbuf,smb_msrcnt,0);
1141 WSET(outbuf,smb_flags,0);
1142 DSET(outbuf,smb_timeout,0);
1143 WSET(outbuf,smb_pscnt,WVAL(outbuf,smb_tpscnt));
1144 WSET(outbuf,smb_psoff,((SMB_BUF(outbuf)+3) - outbuf)-4);
1145 WSET(outbuf,smb_dscnt,0);
1146 WSET(outbuf,smb_dsoff,0);
1147 WSET(outbuf,smb_suwcnt,1);
1148 WSET(outbuf,smb_setup0,
1149 first == 1 ? TRANSACT2_FINDFIRST : TRANSACT2_FINDNEXT);
1150
1151 p = SMB_BUF(outbuf);
1152 *p++=0;
1153 *p++='D'; *p++ = ' ';
1154
1155 if (first != 0)
1156 {
1157 WSET(p,0,attribute);
1158 WSET(p,2,max_matches);
1159 WSET(p,4,8+4+2);
1160
1161 WSET(p,6,info_level);
1162 DSET(p,8,0);
1163 p += 12;
1164 strncpy(p, mask, masklen);
1165 p += masklen;
1166 *p++ = 0; *p++ = 0;
1167 }
1168 else
1169 {
1170 DPRINTK("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
1171 ff_dir_handle,ff_resume_key,ff_lastname,mask);
1172 WSET(p,0,ff_dir_handle);
1173 WSET(p,2,max_matches);
1174 WSET(p,4,info_level);
1175 DSET(p,6,ff_resume_key);
1176 WSET(p,10,8+4+2);
1177
1178 p += 12;
1179 strncpy(p, mask, masklen);
1180 p += masklen;
1181 *p++ = 0; *p++ = 0;
1182 }
1183
1184 result = smb_trans2_request(server,
1185 &resp_data_len,&resp_param_len,
1186 &resp_data,&resp_param);
1187
1188 if (result < 0) {
1189 if (smb_retry(server)) {
1190 goto retry;
1191 }
1192 DPRINTK("smb_proc_readdir_long: "
1193 "got error from trans2_request\n");
1194 break;
1195 }
1196
1197 if (server->rcls != 0)
1198 {
1199 result = -EIO;
1200 break;
1201 }
1202
1203
1204 p = resp_param;
1205 if (first != 0)
1206 {
1207 ff_dir_handle = WVAL(p,0);
1208 ff_searchcount = WVAL(p,2);
1209 ff_eos = WVAL(p,4);
1210 ff_lastname = WVAL(p,8);
1211 }
1212 else
1213 {
1214 ff_searchcount = WVAL(p,0);
1215 ff_eos = WVAL(p,2);
1216 ff_lastname = WVAL(p,6);
1217 }
1218
1219 if (ff_searchcount == 0)
1220 break;
1221
1222
1223 p = resp_data;
1224
1225
1226 if (ff_lastname > 0)
1227 {
1228 switch(info_level)
1229 {
1230 case 260:
1231 ff_resume_key =0;
1232 strcpy(mask,p+ff_lastname+94);
1233 break;
1234 case 1:
1235 strcpy(mask,p + ff_lastname + 1);
1236 ff_resume_key = 0;
1237 break;
1238 }
1239 }
1240 else
1241 strcpy(mask,"");
1242
1243
1244
1245 for (i = 0; i < ff_searchcount; i ++) {
1246 if (total_count < fpos) {
1247 p = smb_decode_long_dirent(p, NULL,
1248 info_level);
1249 DPRINTK("smb_proc_readdir: skipped entry.\n");
1250 DDPRINTK(" total_count = %d\n"
1251 " i = %d, fpos = %d\n",
1252 total_count, i, fpos);
1253 }
1254 else if (total_count >= fpos + cache_size) {
1255 goto finished;
1256 }
1257 else {
1258 p = smb_decode_long_dirent(p, current_entry,
1259 info_level);
1260 current_entry->f_pos = total_count;
1261 DDPRINTK("smb_proc_readdir: entry->f_pos = "
1262 "%lu\n", entry->f_pos);
1263 current_entry += 1;
1264 }
1265 total_count += 1;
1266 }
1267
1268 if (resp_data != NULL) {
1269 smb_kfree_s(resp_data, 0);
1270 resp_data = NULL;
1271 }
1272 if (resp_param != NULL) {
1273 smb_kfree_s(resp_param, 0);
1274 resp_param = NULL;
1275 }
1276
1277 DPRINTK("received %d entries (eos=%d resume=%d)\n",
1278 ff_searchcount,ff_eos,ff_resume_key);
1279
1280 first = 0;
1281 }
1282
1283 finished:
1284 if (resp_data != NULL) {
1285 smb_kfree_s(resp_data, 0);
1286 resp_data = NULL;
1287 }
1288 if (resp_param != NULL) {
1289 smb_kfree_s(resp_param, 0);
1290 resp_param = NULL;
1291 }
1292
1293 smb_unlock_server(server);
1294
1295 return total_count - fpos;
1296 }
1297
1298 int
1299 smb_proc_readdir(struct smb_server *server, struct inode *dir, int fpos,
1300 int cache_size, struct smb_dirent *entry)
1301 {
1302 if (server->protocol >= PROTOCOL_LANMAN2)
1303 return smb_proc_readdir_long(server, dir, fpos, cache_size,
1304 entry);
1305 else
1306 return smb_proc_readdir_short(server, dir, fpos, cache_size,
1307 entry);
1308 }
1309
1310 static int
1311 smb_proc_getattr_core(struct smb_server *server, const char *path, int len,
1312 struct smb_dirent *entry)
1313 {
1314 int result;
1315 char *p;
1316 char *buf = server->packet;
1317
1318 smb_lock_server(server);
1319
1320 DDPRINTK("smb_proc_getattr: %s\n", path);
1321
1322 retry:
1323 p = smb_setup_header(server, SMBgetatr, 0, 2 + len);
1324 smb_encode_ascii(p, path, len);
1325
1326 if ((result = smb_request_ok(server, SMBgetatr, 10, 0)) < 0) {
1327 if (smb_retry(server)) {
1328 goto retry;
1329 }
1330 smb_unlock_server(server);
1331 return result;
1332 }
1333
1334 entry->attr = WVAL(buf, smb_vwv0);
1335 entry->ctime = entry->atime =
1336 entry->mtime = local2utc(DVAL(buf, smb_vwv1));
1337
1338 entry->size = DVAL(buf, smb_vwv3);
1339 smb_unlock_server(server);
1340 return 0;
1341 }
1342
1343
1344
1345 static int
1346 smb_proc_getattrE(struct smb_server *server, struct smb_dirent *entry)
1347 {
1348 char* buf = server->packet;
1349 int result;
1350
1351 smb_setup_header_exclusive(server, SMBgetattrE, 1, 0);
1352 WSET(buf, smb_vwv0, entry->fileid);
1353
1354 if ((result = smb_request_ok(server, SMBgetattrE, 11, 0)) != 0) {
1355 smb_unlock_server(server);
1356 return result;
1357 }
1358
1359 entry->ctime = date_dos2unix(WVAL(buf, smb_vwv1), WVAL(buf, smb_vwv0));
1360 entry->atime = date_dos2unix(WVAL(buf, smb_vwv3), WVAL(buf, smb_vwv2));
1361 entry->mtime = date_dos2unix(WVAL(buf, smb_vwv5), WVAL(buf, smb_vwv4));
1362 entry->size = DVAL(buf, smb_vwv6);
1363 entry->attr = WVAL(buf, smb_vwv10);
1364
1365 smb_unlock_server(server);
1366 return 0;
1367 }
1368
1369 int
1370 smb_proc_getattr(struct smb_server *server, const char *path, int len,
1371 struct smb_dirent *entry)
1372 {
1373 if (server->protocol >= PROTOCOL_LANMAN1) {
1374
1375 int result = 0;
1376 struct smb_dirent temp_entry;
1377
1378 if ((result=smb_proc_open(server,path,len,
1379 &temp_entry)) < 0) {
1380
1381
1382 return smb_proc_getattr_core(server,path,len,entry);
1383 }
1384
1385 if ((result=smb_proc_getattrE(server, &temp_entry)) >= 0) {
1386 entry->attr = temp_entry.attr;
1387 entry->atime = temp_entry.atime;
1388 entry->mtime = temp_entry.mtime;
1389 entry->ctime = temp_entry.ctime;
1390 entry->size = temp_entry.size;
1391 }
1392
1393 smb_proc_close(server, &temp_entry);
1394 return result;
1395
1396 } else {
1397 return smb_proc_getattr_core(server, path, len, entry);
1398 }
1399 }
1400
1401
1402
1403
1404 static int
1405 smb_proc_setattr_core(struct smb_server *server,
1406 const char *path, int len,
1407 struct smb_dirent *new_finfo)
1408 {
1409 char *p;
1410 char *buf = server->packet;
1411 int result;
1412
1413 smb_lock_server(server);
1414
1415 retry:
1416 p = smb_setup_header(server, SMBsetatr, 8, 4 + len);
1417 WSET(buf, smb_vwv0, new_finfo->attr);
1418 DSET(buf, smb_vwv1, utc2local(new_finfo->mtime));
1419 p = smb_encode_ascii(p, path, len);
1420 p = smb_encode_ascii(p, "", 0);
1421
1422 if ((result = smb_request_ok(server, SMBsetatr, 0, 0)) < 0) {
1423 if (smb_retry(server)) {
1424 goto retry;
1425 }
1426 }
1427 smb_unlock_server(server);
1428 return result;
1429 }
1430
1431
1432
1433 static int
1434 smb_proc_setattrE(struct smb_server *server, word fid,
1435 struct smb_dirent *new_entry)
1436 {
1437 char *buf = server->packet;
1438 word date, time;
1439
1440 smb_setup_header_exclusive(server, SMBsetattrE, 7, 0);
1441
1442 WSET(buf, smb_vwv0, fid);
1443
1444 date_unix2dos(new_entry->ctime, &time, &date);
1445 WSET(buf, smb_vwv1, date);
1446 WSET(buf, smb_vwv2, time);
1447
1448 date_unix2dos(new_entry->atime, &time, &date);
1449 WSET(buf, smb_vwv3, date);
1450 WSET(buf, smb_vwv4, time);
1451
1452 date_unix2dos(new_entry->mtime, &time, &date);
1453 WSET(buf, smb_vwv5, date);
1454 WSET(buf, smb_vwv6, time);
1455
1456 return smb_request_ok_unlock(server, SMBsetattrE, 0, 0);
1457 }
1458
1459
1460
1461 int
1462 smb_proc_setattr(struct smb_server *server, struct inode *inode,
1463 struct smb_dirent *new_finfo)
1464 {
1465 struct smb_dirent *finfo = SMB_FINFO(inode);
1466 int result;
1467
1468 if (server->protocol >= PROTOCOL_LANMAN1) {
1469 if ((result = smb_make_open(inode, O_RDWR)) < 0)
1470 return result;
1471 return smb_proc_setattrE(server, finfo->fileid, new_finfo);
1472 } else {
1473 return smb_proc_setattr_core(server, finfo->path, finfo->len,
1474 new_finfo);
1475 }
1476 }
1477
1478 int
1479 smb_proc_dskattr(struct super_block *super, struct smb_dskattr *attr)
1480 {
1481 int error;
1482 char *p;
1483 struct smb_server *server = &(SMB_SBP(super)->s_server);
1484
1485 smb_lock_server(server);
1486
1487 retry:
1488 smb_setup_header(server, SMBdskattr, 0, 0);
1489
1490 if ((error = smb_request_ok(server, SMBdskattr, 5, 0)) < 0) {
1491 if (smb_retry(server)) {
1492 goto retry;
1493 }
1494 smb_unlock_server(server);
1495 return error;
1496 }
1497
1498 p = SMB_VWV(server->packet);
1499 p = smb_decode_word(p, &attr->total);
1500 p = smb_decode_word(p, &attr->allocblocks);
1501 p = smb_decode_word(p, &attr->blocksize);
1502 p = smb_decode_word(p, &attr->free);
1503 smb_unlock_server(server);
1504 return 0;
1505 }
1506
1507
1508
1509
1510
1511
1512
1513 struct smb_prots {
1514 enum smb_protocol prot;
1515 const char *name;
1516 };
1517
1518
1519
1520
1521
1522
1523 int
1524 smb_proc_reconnect(struct smb_server *server)
1525 {
1526 struct smb_prots prots[] =
1527 { { PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"},
1528 { PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
1529 #ifdef LANMAN1
1530 { PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
1531 { PROTOCOL_LANMAN1,"LANMAN1.0"},
1532 #endif
1533 #ifdef LANMAN2
1534 { PROTOCOL_LANMAN2,"LM1.2X002"},
1535 #endif
1536 {-1, NULL} };
1537 char dev[] = "A:";
1538 int i, plength;
1539 int max_xmit = 1024;
1540 int given_max_xmit = server->m.max_xmit;
1541 int result;
1542 byte *p;
1543
1544 if ((result = smb_connect(server)) < 0) {
1545 DPRINTK("smb_proc_reconnect: could not smb_connect\n");
1546 goto fail;
1547 }
1548
1549
1550 server->state = CONN_VALID;
1551
1552 if (server->packet != NULL) {
1553 smb_kfree_s(server->packet, server->max_xmit);
1554 }
1555
1556 server->packet = smb_kmalloc(max_xmit, GFP_KERNEL);
1557
1558 if (server->packet == NULL) {
1559 printk("smb_proc_connect: No memory! Bailing out.\n");
1560 result = -ENOMEM;
1561 goto fail;
1562 }
1563
1564 server->max_xmit = max_xmit;
1565
1566
1567
1568
1569 p = server->packet + 4;
1570
1571 p = smb_name_mangle(p, server->m.server_name);
1572 p = smb_name_mangle(p, server->m.client_name);
1573
1574 smb_encode_smb_length(server->packet,
1575 (void *)p - (void *)(server->packet));
1576
1577 server->packet[0] = 0x81;
1578
1579 if (smb_catch_keepalive(server) < 0) {
1580 printk("smb_proc_connect: could not catch_keepalives\n");
1581 }
1582
1583 if ((result = smb_request(server)) < 0) {
1584 printk("smb_proc_connect: Failed to send SESSION REQUEST.\n");
1585 smb_dont_catch_keepalive(server);
1586 goto fail;
1587 }
1588
1589 if (server->packet[0] != 0x82) {
1590 printk("smb_proc_connect: Did not recieve positive response "
1591 "(err = %x)\n",
1592 server->packet[0]);
1593 smb_dont_catch_keepalive(server);
1594 #if DEBUG_SMB > 0
1595 smb_dump_packet(server->packet);
1596 #endif
1597 result = -EIO;
1598 goto fail;
1599 }
1600
1601 DPRINTK("smb_proc_connect: Passed SESSION REQUEST.\n");
1602
1603
1604 memset(server->packet, 0, SMB_HEADER_LEN);
1605
1606 plength = 0;
1607 for (i = 0; prots[i].name != NULL; i++) {
1608 plength += strlen(prots[i].name) + 2;
1609 }
1610
1611 smb_setup_header(server, SMBnegprot, 0, plength);
1612
1613 p = SMB_BUF(server->packet);
1614
1615 for (i = 0; prots[i].name != NULL; i++) {
1616 p = smb_encode_dialect(p,prots[i].name, strlen(prots[i].name));
1617 }
1618
1619 if ((result = smb_request_ok(server, SMBnegprot, 1, -1)) < 0) {
1620 printk("smb_proc_connect: Failure requesting SMBnegprot\n");
1621 smb_dont_catch_keepalive(server);
1622 goto fail;
1623 } else {
1624 DDPRINTK("smb_proc_connect: Request SMBnegprot..");
1625 }
1626
1627 DDPRINTK("Verified!\n");
1628
1629 p = SMB_VWV(server->packet);
1630 p = smb_decode_word(p, (word *)&i);
1631 server->protocol = prots[i].prot;
1632
1633 DPRINTK("smb_proc_connect: Server wants %s protocol.\n",
1634 prots[i].name);
1635
1636 if (server->protocol > PROTOCOL_LANMAN1) {
1637
1638 word passlen = strlen(server->m.password);
1639 word userlen = strlen(server->m.username);
1640
1641 DPRINTK("smb_proc_connect: password = %s\n",
1642 server->m.password);
1643 DPRINTK("smb_proc_connect: usernam = %s\n",
1644 server->m.username);
1645
1646 p = smb_decode_word(p, &(server->maxxmt));
1647 p = smb_decode_word(p, &(server->maxmux));
1648 p = smb_decode_word(p, &(server->maxvcs));
1649 p = smb_decode_word(p, &(server->blkmode));
1650 p = smb_decode_dword(p, &(server->sesskey));
1651
1652 smb_setup_header(server, SMBsesssetupX, 10,
1653 2 + userlen + passlen);
1654
1655 WSET(server->packet, smb_vwv0, 0x00ff);
1656 WSET(server->packet, smb_vwv1, 0);
1657 WSET(server->packet, smb_vwv2, given_max_xmit);
1658 WSET(server->packet, smb_vwv3, 2);
1659 WSET(server->packet, smb_vwv4, server->pid);
1660 DSET(server->packet, smb_vwv5, server->sesskey);
1661 WSET(server->packet, smb_vwv7, passlen + 1);
1662 WSET(server->packet, smb_vwv8, 0);
1663 WSET(server->packet, smb_vwv9, 0);
1664
1665 p = SMB_BUF(server->packet);
1666 strcpy(p, server->m.password);
1667 p += passlen + 1;
1668 strcpy(p, server->m.username);
1669
1670 if ((result = smb_request_ok(server,SMBsesssetupX,3,0)) < 0) {
1671 DPRINTK("smb_proc_connect: SMBsessetupX failed\n");
1672 smb_dont_catch_keepalive(server);
1673 goto fail;
1674 }
1675 smb_decode_word(server->packet+32, &(server->server_uid));
1676 }
1677
1678
1679
1680 smb_setup_header(server, SMBtcon, 0,
1681 6 + strlen(server->m.service) +
1682 strlen(server->m.password) + strlen(dev));
1683 p = SMB_BUF(server->packet);
1684 p = smb_encode_ascii(p, server->m.service, strlen(server->m.service));
1685 p = smb_encode_ascii(p,server->m.password, strlen(server->m.password));
1686 p = smb_encode_ascii(p, dev, strlen(dev));
1687
1688 if ((result = smb_request_ok(server, SMBtcon, 2, 0)) < 0) {
1689 DPRINTK("smb_proc_connect: SMBtcon not verified.\n");
1690 smb_dont_catch_keepalive(server);
1691 goto fail;
1692 }
1693
1694 DDPRINTK("OK! Managed to set up SMBtcon!\n");
1695
1696 p = SMB_VWV(server->packet);
1697 p = smb_decode_word(p, &server->max_xmit);
1698
1699 if (server->max_xmit > given_max_xmit)
1700 server->max_xmit = given_max_xmit;
1701
1702 p = smb_decode_word(p, &server->tid);
1703
1704
1705
1706 server->max_xmit += 4;
1707
1708 DPRINTK("max_xmit = %d, tid = %d\n", server->max_xmit, server->tid);
1709
1710
1711 smb_kfree_s(server->packet, max_xmit);
1712
1713 server->packet = smb_kmalloc(server->max_xmit, GFP_KERNEL);
1714 if (server->packet == NULL) {
1715 printk("smb_proc_connect: No memory left in end of "
1716 "connection phase :-(\n");
1717 smb_dont_catch_keepalive(server);
1718 goto fail;
1719 }
1720
1721 DPRINTK("smb_proc_connect: Normal exit\n");
1722 return 0;
1723
1724 fail:
1725 server->state = CONN_INVALID;
1726 return result;
1727 }
1728
1729
1730
1731 int
1732 smb_proc_connect(struct smb_server *server)
1733 {
1734 int result;
1735 smb_lock_server(server);
1736 result = smb_proc_reconnect(server);
1737 if ((result < 0) && (server->packet != NULL)) {
1738 smb_kfree_s(server->packet, server->max_xmit);
1739 server->packet = NULL;
1740 }
1741 smb_unlock_server(server);
1742 return result;
1743 }
1744
1745 int
1746 smb_proc_disconnect(struct smb_server *server)
1747 {
1748 smb_setup_header_exclusive(server, SMBtdis, 0, 0);
1749 return smb_request_ok_unlock(server, SMBtdis, 0, 0);
1750 }
1751
1752
1753
1754
1755 #if DEBUG_SMB > 0
1756
1757 typedef struct {
1758 char *name;
1759 int code;
1760 char *message;
1761 } err_code_struct;
1762
1763
1764 err_code_struct dos_msgs[] = {
1765 { "ERRbadfunc",1,"Invalid function."},
1766 { "ERRbadfile",2,"File not found."},
1767 { "ERRbadpath",3,"Directory invalid."},
1768 { "ERRnofids",4,"No file descriptors available"},
1769 { "ERRnoaccess",5,"Access denied."},
1770 { "ERRbadfid",6,"Invalid file handle."},
1771 { "ERRbadmcb",7,"Memory control blocks destroyed."},
1772 { "ERRnomem",8,"Insufficient server memory to perform the requested function."},
1773 { "ERRbadmem",9,"Invalid memory block address."},
1774 { "ERRbadenv",10,"Invalid environment."},
1775 { "ERRbadformat",11,"Invalid format."},
1776 { "ERRbadaccess",12,"Invalid open mode."},
1777 { "ERRbaddata",13,"Invalid data."},
1778 { "ERR",14,"reserved."},
1779 { "ERRbaddrive",15,"Invalid drive specified."},
1780 { "ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."},
1781 { "ERRdiffdevice",17,"Not same device."},
1782 { "ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
1783 { "ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."},
1784 { "ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
1785 { "ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."},
1786 { "ERRbadpipe",230,"Pipe invalid."},
1787 { "ERRpipebusy",231,"All instances of the requested pipe are busy."},
1788 { "ERRpipeclosing",232,"Pipe close in progress."},
1789 { "ERRnotconnected",233,"No process on other end of pipe."},
1790 { "ERRmoredata",234,"There is more data to be returned."},
1791 { NULL,-1,NULL}};
1792
1793
1794 err_code_struct server_msgs[] = {
1795 { "ERRerror",1,"Non-specific error code."},
1796 { "ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
1797 { "ERRbadtype",3,"reserved."},
1798 { "ERRaccess",4,"The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."},
1799 { "ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
1800 { "ERRinvnetname",6,"Invalid network name in tree connect."},
1801 { "ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
1802 { "ERRqfull",49,"Print queue full (files) -- returned by open print file."},
1803 { "ERRqtoobig",50,"Print queue full -- no space."},
1804 { "ERRqeof",51,"EOF on print queue dump."},
1805 { "ERRinvpfid",52,"Invalid print file FID."},
1806 { "ERRsmbcmd",64,"The server did not recognize the command received."},
1807 { "ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
1808 { "ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."},
1809 { "ERRreserved",68,"reserved."},
1810 { "ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
1811 { "ERRreserved",70,"reserved."},
1812 { "ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
1813 { "ERRpaused",81,"Server is paused."},
1814 { "ERRmsgoff",82,"Not receiving messages."},
1815 { "ERRnoroom",83,"No room to buffer message."},
1816 { "ERRrmuns",87,"Too many remote user names."},
1817 { "ERRtimeout",88,"Operation timed out."},
1818 { "ERRnoresource",89,"No resources currently available for request."},
1819 { "ERRtoomanyuids",90,"Too many UIDs active on this session."},
1820 { "ERRbaduid",91,"The UID is not known as a valid ID on this session."},
1821 { "ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
1822 { "ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
1823 { "ERRcontmpx",252,"Continue in MPX mode."},
1824 { "ERRreserved",253,"reserved."},
1825 { "ERRreserved",254,"reserved."},
1826 { "ERRnosupport",0xFFFF,"Function not supported."},
1827 { NULL,-1,NULL}};
1828
1829
1830 err_code_struct hard_msgs[] = {
1831 { "ERRnowrite",19,"Attempt to write on write-protected diskette."},
1832 { "ERRbadunit",20,"Unknown unit."},
1833 { "ERRnotready",21,"Drive not ready."},
1834 { "ERRbadcmd",22,"Unknown command."},
1835 { "ERRdata",23,"Data error (CRC)."},
1836 { "ERRbadreq",24,"Bad request structure length."},
1837 { "ERRseek",25 ,"Seek error."},
1838 { "ERRbadmedia",26,"Unknown media type."},
1839 { "ERRbadsector",27,"Sector not found."},
1840 { "ERRnopaper",28,"Printer out of paper."},
1841 { "ERRwrite",29,"Write fault."},
1842 { "ERRread",30,"Read fault."},
1843 { "ERRgeneral",31,"General failure."},
1844 { "ERRbadshare",32,"A open conflicts with an existing open."},
1845 { "ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
1846 { "ERRwrongdisk",34,"The wrong disk was found in a drive."},
1847 { "ERRFCBUnavail",35,"No FCBs are available to process request."},
1848 { "ERRsharebufexc",36,"A sharing buffer has been exceeded."},
1849 { NULL,-1,NULL}
1850 };
1851
1852
1853 struct {
1854 int code;
1855 char *class;
1856 err_code_struct *err_msgs;
1857 } err_classes[] = {
1858 { 0,"SUCCESS",NULL},
1859 { 0x01,"ERRDOS",dos_msgs},
1860 { 0x02,"ERRSRV",server_msgs},
1861 { 0x03,"ERRHRD",hard_msgs},
1862 { 0x04,"ERRXOS",NULL},
1863 { 0xE1,"ERRRMX1",NULL},
1864 { 0xE2,"ERRRMX2",NULL},
1865 { 0xE3,"ERRRMX3",NULL},
1866 { 0xFF,"ERRCMD",NULL},
1867 { -1,NULL,NULL}
1868 };
1869
1870 void
1871 smb_printerr(int class, int num)
1872 {
1873 int i,j;
1874 err_code_struct *err;
1875
1876 for (i=0; err_classes[i].class; i++) {
1877 if (err_classes[i].code != class)
1878 continue;
1879 if (!err_classes[i].err_msgs) {
1880 printk("%s - %d", err_classes[i].class, num);
1881 return;
1882 }
1883
1884 err = err_classes[i].err_msgs;
1885 for (j=0; err[j].name; j++) {
1886 if (num != err[j].code)
1887 continue;
1888 printk("%s - %s (%s)",
1889 err_classes[i].class, err[j].name,
1890 err[j].message);
1891 return;
1892 }
1893 }
1894
1895 printk("Unknown error - (%d,%d)", class, num);
1896 return;
1897 }
1898
1899 #endif
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916