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