Decode the "flags2" field in the SMB header.
[obnox/wireshark/wip.git] / packet-smb.c
1 /* packet-smb.c
2  * Routines for smb packet dissection
3  * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
4  *
5  * $Id: packet-smb.c,v 1.4 1999/05/10 20:30:27 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@unicom.net>
9  * Copyright 1998 Gerald Combs
10  *
11  * Copied from packet-pop.c
12  * 
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <stdio.h>
33
34 #ifdef HAVE_SYS_TYPES_H
35 # include <sys/types.h>
36 #endif
37
38 #ifdef HAVE_NETINET_IN_H
39 # include <netinet/in.h>
40 #endif
41
42 #include <arpa/tftp.h>
43 #include <string.h>
44 #include <glib.h>
45 #include "packet.h"
46 #include "etypes.h"
47 #include "smb.h"
48 #include "alignment.h"
49
50 extern packet_info pi;
51
52 char *decode_smb_name(unsigned char);
53
54 char *SMB_names[256] = {
55   "unknown-0x00",
56   "unknown-0x01",
57   "SMBopen",
58   "SMBcreate",
59   "SMBclose",
60   "SMBflush",
61   "SMBunlink",
62   "SMBmv",
63   "SMBgetatr",
64   "SMBsetatr",
65   "SMBread",
66   "SMBwrite",
67   "SMBlock",
68   "SMBunlock",
69   "SMBctemp",
70   "SMBmknew",
71   "SMBchkpth",
72   "SMBexit",
73   "SMBlseek",
74   "SMBlockread",
75   "SMBwriteunlock",
76   "unknown-0x15",
77   "unknown-0x16",
78   "unknown-0x17",
79   "unknown-0x18",
80   "unknown-0x19",
81   "SMBreadBraw",
82   "SMBreadBmpx",
83   "SMBreadBs",
84   "SMBwriteBraw",
85   "SMBwriteBmpx",
86   "SMBwriteBs",
87   "SMBwriteC",
88   "unknown-0x21",
89   "SMBsetattrE",
90   "SMBgetattrE",
91   "SMBlockingX",
92   "SMBtrans",
93   "SMBtranss",
94   "SMBioctl",
95   "SMBioctls",
96   "SMBcopy",
97   "SMBmove",
98   "SMBecho",
99   "SMBwriteclose",
100   "SMBopenX",
101   "SMBreadX",
102   "SMBwriteX",
103   "unknown-0x30",
104   "unknown-0x31",
105   "unknown-0x32",
106   "unknown-0x33",
107   "unknown-0x34",
108   "unknown-0x35",
109   "unknown-0x36",
110   "unknown-0x37",
111   "unknown-0x38",
112   "unknown-0x39",
113   "unknown-0x3A",
114   "unknown-0x3B",
115   "unknown-0x3C",
116   "unknown-0x3D",
117   "unknown-0x3E",
118   "unknown-0x3F",
119   "unknown-0x40",
120   "unknown-0x41",
121   "unknown-0x42",
122   "unknown-0x43",
123   "unknown-0x44",
124   "unknown-0x45",
125   "unknown-0x46",
126   "unknown-0x47",
127   "unknown-0x48",
128   "unknown-0x49",
129   "unknown-0x4A",
130   "unknown-0x4B",
131   "unknown-0x4C",
132   "unknown-0x4D",
133   "unknown-0x4E",
134   "unknown-0x4F",
135   "unknown-0x50",
136   "unknown-0x51",
137   "unknown-0x52",
138   "unknown-0x53",
139   "unknown-0x54",
140   "unknown-0x55",
141   "unknown-0x56",
142   "unknown-0x57",
143   "unknown-0x58",
144   "unknown-0x59",
145   "unknown-0x5A",
146   "unknown-0x5B",
147   "unknown-0x5C",
148   "unknown-0x5D",
149   "unknown-0x5E",
150   "unknown-0x5F",
151   "unknown-0x60",
152   "unknown-0x61",
153   "unknown-0x62",
154   "unknown-0x63",
155   "unknown-0x64",
156   "unknown-0x65",
157   "unknown-0x66",
158   "unknown-0x67",
159   "unknown-0x68",
160   "unknown-0x69",
161   "unknown-0x6A",
162   "unknown-0x6B",
163   "unknown-0x6C",
164   "unknown-0x6D",
165   "unknown-0x6E",
166   "unknown-0x6F",
167   "SMBtcon",
168   "SMBtdis",
169   "SMBnegprot",
170   "SMBsesssetupX",
171   "unknown-0x74",
172   "SMBtconX",
173   "unknown-0x76",
174   "unknown-0x77",
175   "unknown-0x78",
176   "unknown-0x79",
177   "unknown-0x7A",
178   "unknown-0x7B",
179   "unknown-0x7C",
180   "unknown-0x7D",
181   "unknown-0x7E",
182   "unknown-0x7F",
183   "SMBdskattr",
184   "SMBsearch",
185   "SMBffirst",
186   "SMBfunique",
187   "SMBfclose",
188   "unknown-0x85",
189   "unknown-0x86",
190   "unknown-0x87",
191   "unknown-0x88",
192   "unknown-0x89",
193   "unknown-0x8A",
194   "unknown-0x8B",
195   "unknown-0x8C",
196   "unknown-0x8D",
197   "unknown-0x8E",
198   "unknown-0x8F",
199   "unknown-0x90",
200   "unknown-0x91",
201   "unknown-0x92",
202   "unknown-0x93",
203   "unknown-0x94",
204   "unknown-0x95",
205   "unknown-0x96",
206   "unknown-0x97",
207   "unknown-0x98",
208   "unknown-0x99",
209   "unknown-0x9A",
210   "unknown-0x9B",
211   "unknown-0x9C",
212   "unknown-0x9D",
213   "unknown-0x9E",
214   "unknown-0x9F",
215   "unknown-0xA0",
216   "unknown-0xA1",
217   "unknown-0xA2",
218   "unknown-0xA3",
219   "unknown-0xA4",
220   "unknown-0xA5",
221   "unknown-0xA6",
222   "unknown-0xA7",
223   "unknown-0xA8",
224   "unknown-0xA9",
225   "unknown-0xAA",
226   "unknown-0xAB",
227   "unknown-0xAC",
228   "unknown-0xAD",
229   "unknown-0xAE",
230   "unknown-0xAF",
231   "unknown-0xB0",
232   "unknown-0xB1",
233   "unknown-0xB2",
234   "unknown-0xB3",
235   "unknown-0xB4",
236   "unknown-0xB5",
237   "unknown-0xB6",
238   "unknown-0xB7",
239   "unknown-0xB8",
240   "unknown-0xB9",
241   "unknown-0xBA",
242   "unknown-0xBB",
243   "unknown-0xBC",
244   "unknown-0xBD",
245   "unknown-0xBE",
246   "unknown-0xBF",
247   "SMBsplopen",
248   "SMBsplwr",
249   "SMBsplclose",
250   "SMBsplretq",
251   "unknown-0xC4",
252   "unknown-0xC5",
253   "unknown-0xC6",
254   "unknown-0xC7",
255   "unknown-0xC8",
256   "unknown-0xC9",
257   "unknown-0xCA",
258   "unknown-0xCB",
259   "unknown-0xCC",
260   "unknown-0xCD",
261   "unknown-0xCE",
262   "unknown-0xCF",
263   "SMBsends",
264   "SMBsendb",
265   "SMBfwdname",
266   "SMBcancelf",
267   "SMBgetmac",
268   "SMBsendstrt",
269   "SMBsendend",
270   "SMBsendtxt",
271   "unknown-0xD8",
272   "unknown-0xD9",
273   "unknown-0xDA",
274   "unknown-0xDB",
275   "unknown-0xDC",
276   "unknown-0xDD",
277   "unknown-0xDE",
278   "unknown-0xDF",
279   "unknown-0xE0",
280   "unknown-0xE1",
281   "unknown-0xE2",
282   "unknown-0xE3",
283   "unknown-0xE4",
284   "unknown-0xE5",
285   "unknown-0xE6",
286   "unknown-0xE7",
287   "unknown-0xE8",
288   "unknown-0xE9",
289   "unknown-0xEA",
290   "unknown-0xEB",
291   "unknown-0xEC",
292   "unknown-0xED",
293   "unknown-0xEE",
294   "unknown-0xEF",
295   "unknown-0xF0",
296   "unknown-0xF1",
297   "unknown-0xF2",
298   "unknown-0xF3",
299   "unknown-0xF4",
300   "unknown-0xF5",
301   "unknown-0xF6",
302   "unknown-0xF7",
303   "unknown-0xF8",
304   "unknown-0xF9",
305   "unknown-0xFA",
306   "unknown-0xFB",
307   "unknown-0xFC",
308   "unknown-0xFD",
309   "SMBinvalid",
310   "unknown-0xFF"
311 };
312
313 void 
314 dissect_unknown_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data, int dirn)
315 {
316
317   if (tree) {
318
319     proto_tree_add_item(tree, offset, END_OF_FRAME, "Data (%d bytes)", 
320                         END_OF_FRAME); 
321
322   }
323
324 }
325
326 /*
327  * Each dissect routine is passed an offset to wct and works from there 
328  */
329
330 void
331 dissect_tcon_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data, int dirn)
332
333 {
334   guint8      wct, andxcmd;
335   guint16     andxoffs, flags, passwdlen, bcc;
336   const char  *str;
337   proto_tree  *flags_tree;
338   proto_item  *ti;
339
340   wct = pd[offset];
341
342   /* Now figure out what format we are talking about, 2, 3, or 4 response
343    * words ...
344    */
345
346   if (!((dirn == 1) && (wct == 4)) && !((dirn == 0) && (wct == 2)) &&
347       !((dirn == 0) && (wct == 3))) {
348
349     if (tree) {
350
351       proto_tree_add_item(tree, offset, 1, "Invalid TCON_ANDX format. WCT should be 2, 3, or 4 ..., not %d", wct);
352
353       proto_tree_add_item(tree, offset, END_OF_FRAME, "Data");
354
355       return;
356
357     }
358     
359   }
360
361   if (tree) {
362
363     proto_tree_add_item(tree, offset, 1, "Word Count (WCT): %d", wct);
364
365   }
366
367   offset += 1;
368
369   andxcmd = pd[offset];
370
371   if (tree) {
372
373     proto_tree_add_item(tree, offset, 1, "Next Command: %s",
374                         (andxcmd == 0xFF) ? "No further commands":
375                         decode_smb_name(andxcmd));
376                 
377     proto_tree_add_item(tree, offset + 1, 1, "Reserved (MBZ): %d", pd[offset+1]);
378
379   }
380
381   offset += 2;
382
383   andxoffs = GSHORT(pd, offset);
384
385   if (tree) {
386
387     proto_tree_add_item(tree, offset, 2, "Offset to next command: %d", andxoffs);
388
389   }
390
391   offset += 2;
392
393   switch (wct) {
394
395   case 4:
396
397     flags = GSHORT(pd, offset);
398
399     if (tree) {
400
401       ti = proto_tree_add_item(tree, offset, 2, "Additional Flags: 0x%02x", flags);
402       flags_tree = proto_tree_new();
403       proto_item_add_subtree(ti, flags_tree, ETT_SMB_AFLAGS);
404       proto_tree_add_item(flags_tree, offset, 2, "%s", 
405                           decode_boolean_bitfield(flags, 0x01, 16,
406                                                   "Disconnect TID",
407                                                   "Don't disconnect TID"));
408
409     }
410
411     offset += 2;
412
413     passwdlen = GSHORT(pd, offset);
414
415     if (tree) {
416
417       proto_tree_add_item(tree, offset, 2, "Password Length: %d", passwdlen);
418
419     }
420
421     offset += 2;
422
423     bcc = GSHORT(pd, offset);
424
425     if (tree) {
426
427       proto_tree_add_item(tree, offset, 2, "Byte Count (BCC): %d", bcc);
428
429     }
430
431     offset += 2;
432
433     str = pd + offset;
434
435     if (tree) {
436
437       proto_tree_add_item(tree, offset, strlen(str) + 1, "Password: %s", str);
438
439     }
440
441     offset += strlen(str) + 1;
442
443     str = pd + offset;
444
445     if (tree) {
446
447       proto_tree_add_item(tree, offset, strlen(str) + 1, "Path: %s", str);
448
449     }
450
451     offset += strlen(str) + 1;
452
453     str = pd + offset;
454
455     if (tree) {
456
457       proto_tree_add_item(tree, offset, strlen(str) + 1, "Service: %s", str);
458
459     }
460
461     break;
462
463   case 2:
464
465     break;
466
467   case 3:
468
469     break;
470
471   default:
472
473   }
474
475 }
476
477 void 
478 dissect_negprot_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data, int dirn)
479 {
480   guint8        wct, enckeylen;
481   guint16       bcc, mode, rawmode;
482   guint32       caps;
483   proto_tree    *dialects = NULL, *mode_tree, *caps_tree, *rawmode_tree;
484   proto_item    *ti;
485   const char    *str;
486
487   wct = pd[offset];    /* Should be 0, 1 or 13 or 17, I think */
488
489   if (!((wct == 0) && (dirn == 1)) && !((wct == 1) && (dirn == 0)) &&
490       !((wct == 13) && (dirn == 0)) && !((wct == 17) && (dirn == 0))) {
491     if (tree) {
492
493       proto_tree_add_item(tree, offset, 1, "Invalid Negotiate Protocol format. WCT should be zero or 1 or 13 or 17 ..., not %d", wct);
494
495       proto_tree_add_item(tree, offset, END_OF_FRAME, "Data");
496
497       return;
498     }
499   }
500
501   if (tree) {
502
503     proto_tree_add_item(tree, offset, 1, "Word Count (WCT): %d", wct);
504
505   }
506
507   offset += 1; 
508
509   /* Now decode the various formats ... */
510
511   switch (wct) {
512
513   case 0:     /* A request */
514
515     bcc = GSHORT(pd, offset);
516
517     if (tree) {
518
519       proto_tree_add_item(tree, offset, 2, "Byte Count (BCC): %d", bcc);
520
521     }
522
523     offset += 2;
524
525     if (tree) {
526
527       ti = proto_tree_add_item(tree, offset, END_OF_FRAME, "Dialects");
528       dialects = proto_tree_new();
529       proto_item_add_subtree(ti, dialects, ETT_SMB_DIALECTS);
530
531     }
532
533     while (END_OF_FRAME > 0) {
534       const char *str;
535
536       if (tree) {
537
538         proto_tree_add_item(dialects, offset, 1, "Dialect Marker: %d", pd[offset]);
539
540       }
541
542       offset += 1;
543
544       str = pd + offset;
545
546       if (tree) {
547
548         proto_tree_add_item(dialects, offset, strlen(str)+1, "Dialect: %s", str);
549
550       }
551
552       offset += strlen(str) + 1;
553
554     }
555     break;
556
557   case 1:     /* PC NETWORK PROGRAM 1.0 */
558
559     if (tree) {
560
561       proto_tree_add_item(tree, offset, 2, "Dialect Index: %d, PC NETWORK PROTGRAM 1.0", GSHORT(pd, offset));
562
563     }
564
565     offset += 2;
566
567     bcc = GSHORT(pd, offset);
568
569     if (tree) {
570
571       proto_tree_add_item(tree, offset, 2, "Byte Count (BCC): %d", bcc);
572
573     }
574
575     break;
576
577   case 13:    /* Greater than Core and up to and incl LANMAN2.1  */
578
579     if (tree) {
580
581       proto_tree_add_item(tree, offset, 2, "Dialect Index: %d, Greater than CORE PROTOCOL and up to LANMAN2.1", GSHORT(pd, offset));
582
583     }
584
585     /* Much of this is similar to response 17 below */
586
587     offset += 2;
588
589     mode = GBYTE(pd, offset);
590
591     if (tree) {
592
593       ti = proto_tree_add_item(tree, offset, 1, "Security Mode: 0x%02x", mode);
594       mode_tree = proto_tree_new();
595       proto_item_add_subtree(ti, mode_tree, ETT_SMB_MODE);
596       proto_tree_add_item(mode_tree, offset, 1, "%s",
597                           decode_boolean_bitfield(mode, 0x01, 8,
598                                                   "Security  = User",
599                                                   "Security  = Share"));
600       proto_tree_add_item(mode_tree, offset, 1, "%s",
601                           decode_boolean_bitfield(mode, 0x02, 8,
602                                                   "Passwords = Encrypted",
603                                                   "Passwords = Plaintext"));
604
605     }
606
607     offset += 1;
608
609     if (tree) {
610
611       proto_tree_add_item(tree, offset, 2, "Max multiplex count: %d", GSHORT(pd, offset));
612
613     }
614     
615     offset += 2;
616
617     if (tree) {
618
619       proto_tree_add_item(tree, offset, 2, "Max vcs:             %d", GSHORT(pd, offset));
620
621     }
622
623     offset += 2;
624
625     rawmode = GSHORT(pd, offset);
626
627     if (tree) {
628
629       ti = proto_tree_add_item(tree, offset, 2, "Raw Mode: 0x%04x", rawmode);
630       rawmode_tree = proto_tree_new();
631       proto_item_add_subtree(ti, rawmode_tree, ETT_SMB_RAWMODE);
632       proto_tree_add_item(rawmode_tree, offset, 2, "%s",
633                           decode_boolean_bitfield(rawmode, 0x01, 16,
634                                                   "Read Raw supported",
635                                                   "Read Raw not supported"));
636       proto_tree_add_item(rawmode_tree, offset, 2, "%s",
637                           decode_boolean_bitfield(rawmode, 0x02, 16,
638                                                   "Write Raw supported",
639                                                   "Write Raw not supported"));
640
641     }
642
643     offset += 2;
644
645     /* Now the server time ... skip 8 bytes ... pick up later */
646
647     offset += 8;
648
649     /* Encryption Key Length, should be zero */
650
651     if (tree) {
652
653       proto_tree_add_item(tree, offset, 2, "Encryption Key Length: %d (should be zero)", GSHORT(pd, offset));
654
655     }
656
657     offset += 2;
658
659     if (tree) {
660
661       proto_tree_add_item(tree, offset, 2, "Reserved: %d (MBZ)", GSHORT(pd, offset));
662
663     }
664
665     offset += 2;
666
667     bcc = GSHORT(pd, offset);
668
669     if (tree) {
670
671       proto_tree_add_item(tree, offset, 2, "Byte Count (BCC): %d", bcc);
672
673     }
674
675     offset += 2;
676
677     /* Encryption key, might be a null string ??? Not sure */
678
679     str = pd + offset;
680
681     if (tree) {
682
683       proto_tree_add_item(tree, offset, strlen(str)+1, "Encryption Key: %s", str);
684
685     }
686
687     offset += strlen(str) + 1;
688
689     /* Primary Domain ... */
690
691     str = pd + offset;
692
693     if (tree) {
694
695       proto_tree_add_item(tree, offset, strlen(str)+1, "Primary Domain: %s", str);
696
697     }
698
699     break;
700
701   case 17:    /* Greater than LANMAN2.1 */
702
703     if (tree) {
704
705       proto_tree_add_item(tree, offset, 2, "Dialect Index: %d, Greater than LANMAN2.1", GSHORT(pd, offset));
706
707     }
708
709     offset += 2;
710
711     mode = GBYTE(pd, offset);
712
713     if (tree) {
714
715       ti = proto_tree_add_item(tree, offset, 1, "Security Mode: 0x%02x", mode);
716       mode_tree = proto_tree_new();
717       proto_item_add_subtree(ti, mode_tree, ETT_SMB_MODE);
718       proto_tree_add_item(mode_tree, offset, 1, "%s",
719                           decode_boolean_bitfield(mode, 0x01, 8,
720                                                   "Security  = User",
721                                                   "Security  = Share"));
722       proto_tree_add_item(mode_tree, offset, 1, "%s",
723                           decode_boolean_bitfield(mode, 0x02, 8,
724                                                   "Passwords = Encrypted",
725                                                   "Passwords = Plaintext"));
726
727     }
728
729     offset += 1;
730
731     if (tree) {
732
733       proto_tree_add_item(tree, offset, 2, "Max multiplex count: %d", GSHORT(pd, offset));
734
735     }
736     
737     offset += 2;
738
739     if (tree) {
740
741       proto_tree_add_item(tree, offset, 2, "Max vcs:             %d", GSHORT(pd, offset));
742
743     }
744
745     offset += 2;
746
747     if (tree) {
748
749       proto_tree_add_item(tree, offset, 2, "Max buffer size:     %d", GWORD(pd, offset));
750
751     }
752
753     offset += 4;
754
755     if (tree) {
756
757       proto_tree_add_item(tree, offset, 4, "Max raw size:        %d", GWORD(pd, offset));
758
759     }
760
761     offset += 4;
762
763     if (tree) {
764
765       proto_tree_add_item(tree, offset, 4, "Session key:         %08x", GWORD(pd, offset));
766
767     }
768
769     offset += 4;
770
771     caps = GWORD(pd, offset);
772
773     if (tree) {
774
775       ti = proto_tree_add_item(tree, offset, 4, "Capabilities: 0x%04x", caps);
776       caps_tree = proto_tree_new();
777       proto_item_add_subtree(ti, caps_tree, ETT_SMB_CAPS);
778       proto_tree_add_item(caps_tree, offset, 4, "%s",
779                           decode_boolean_bitfield(caps, 0x0001, 32,
780                                                   "Raw Mode supported",
781                                                   "Raw Mode not supported"));
782       proto_tree_add_item(caps_tree, offset, 4, "%s",
783                           decode_boolean_bitfield(caps, 0x0002, 32,
784                                                   "MPX Mode supported",
785                                                   "MPX Mode not supported"));
786       proto_tree_add_item(caps_tree, offset, 4, "%s",
787                           decode_boolean_bitfield(caps, 0x0004, 32,
788                                                   "Unicode supported",
789                                                   "Unicode not supported"));
790       proto_tree_add_item(caps_tree, offset, 4, "%s",
791                           decode_boolean_bitfield(caps, 0x0008, 32,
792                                                   "Large files supported",
793                                                   "Large files not supported"));
794       proto_tree_add_item(caps_tree, offset, 4, "%s",
795                           decode_boolean_bitfield(caps, 0x0010, 32, 
796                                                   "NT LM 0.12 SMBs supported",
797                                                   "NT LM 0.12 SMBs not supported"));
798       proto_tree_add_item(caps_tree, offset, 4, "%s",
799                           decode_boolean_bitfield(caps, 0x0020, 32,
800                                                   "RPC remote APIs supported",
801                                                   "RPC remote APIs not supported"));
802       proto_tree_add_item(caps_tree, offset, 4, "%s",
803                           decode_boolean_bitfield(caps, 0x0040, 32,
804                                                   "NT status codes supported",
805                                                   "NT status codes  not supported"));
806       proto_tree_add_item(caps_tree, offset, 4, "%s",
807                           decode_boolean_bitfield(caps, 0x0080, 32,
808                                                   "Level 2 OpLocks supported",
809                                                   "Level 2 OpLocks not supported"));
810       proto_tree_add_item(caps_tree, offset, 4, "%s",
811                           decode_boolean_bitfield(caps, 0x0100, 32,
812                                                   "Lock&Read supported",
813                                                   "Lock&Read not supported"));
814       proto_tree_add_item(caps_tree, offset, 4, "%s",
815                           decode_boolean_bitfield(caps, 0x0200, 32,
816                                                   "NT Find supported",
817                                                   "NT Find not supported"));
818       proto_tree_add_item(caps_tree, offset, 4, "%s",
819                           decode_boolean_bitfield(caps, 0x1000, 32,
820                                                   "DFS supported",
821                                                   "DFS not supported"));
822       proto_tree_add_item(caps_tree, offset, 4, "%s",
823                           decode_boolean_bitfield(caps, 0x4000, 32,
824                                                   "Large READX supported",
825                                                   "Large READX not supported"));
826     }
827
828     offset += 4;
829
830     /* Server time, 2 WORDS */
831
832     offset += 8;
833
834     /* Server Time Zone, SHORT */
835
836     if (tree) {
837
838       proto_tree_add_item(tree, offset, 2, "Server time zone: %i min from UTC",
839                           (signed)GSSHORT(pd, offset));
840
841     }
842
843     offset += 2;
844
845     /* Encryption key len */
846
847     enckeylen = pd[offset];
848
849     if (tree) {
850
851       proto_tree_add_item(tree, offset, 1, "Encryption key len: %d", enckeylen);
852
853     }
854
855     offset += 1;
856
857     bcc = GSHORT(pd, offset);
858
859     if (tree) {
860
861       proto_tree_add_item(tree, offset, 2, "Byte count (BCC): %d", bcc);
862
863     }
864
865     offset += 2;
866
867     if (enckeylen) { /* only if non-zero key len */
868
869       /* Encryption challenge key, a NULL terminated string */
870
871       str = pd + offset;
872
873       if (tree) {
874
875         proto_tree_add_item(tree, offset, strlen(str)+1, "Challenge encryption key: %s", str);
876
877       }
878
879       offset += strlen(str) + 1;
880
881     }
882
883     /* The domain, another null terminated string */
884
885     str = pd + offset;
886
887     if (tree) {
888
889       proto_tree_add_item(tree, offset, strlen(str)+1, "OEM domain name: %s", str);
890
891     }
892
893     break;
894
895   default:    /* Baddd */
896
897     if (tree)
898       proto_tree_add_item(tree, offset, 1, "Bad format, should never get here");
899     return;
900
901   }
902
903 }
904
905 void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, int, int) = {
906
907   dissect_unknown_smb,      /* unknown SMB 0x00 */
908   dissect_unknown_smb,      /* unknown SMB 0x01 */
909   dissect_unknown_smb,      /* SMBopen open a file */
910   dissect_unknown_smb,      /* SMBcreate create a file */
911   dissect_unknown_smb,      /* SMBclose close a file */
912   dissect_unknown_smb,      /* SMBflush flush a file */
913   dissect_unknown_smb,      /* SMBunlink delete a file */
914   dissect_unknown_smb,      /* SMBmv rename a file */
915   dissect_unknown_smb,      /* SMBgetatr get file attributes */
916   dissect_unknown_smb,      /* SMBsetatr set file attributes */
917   dissect_unknown_smb,      /* SMBread read from a file */
918   dissect_unknown_smb,      /* SMBwrite write to a file */
919   dissect_unknown_smb,      /* SMBlock lock a byte range */
920   dissect_unknown_smb,      /* SMBunlock unlock a byte range */
921   dissect_unknown_smb,      /* SMBctemp create a temporary file */
922   dissect_unknown_smb,      /* SMBmknew make a new file */
923   dissect_unknown_smb,      /* SMBchkpth check a directory path */
924   dissect_unknown_smb,      /* SMBexit process exit */
925   dissect_unknown_smb,      /* SMBlseek seek */
926   dissect_unknown_smb,      /* SMBlockread Lock a range and read it */
927   dissect_unknown_smb,      /* SMBwriteunlock Unlock a range and then write */
928   dissect_unknown_smb,      /* unknown SMB 0x15 */
929   dissect_unknown_smb,      /* unknown SMB 0x16 */
930   dissect_unknown_smb,      /* unknown SMB 0x17 */
931   dissect_unknown_smb,      /* unknown SMB 0x18 */
932   dissect_unknown_smb,      /* unknown SMB 0x19 */
933   dissect_unknown_smb,      /* SMBreadBraw read block raw */
934   dissect_unknown_smb,      /* SMBreadBmpx read block multiplexed */
935   dissect_unknown_smb,      /* SMBreadBs read block (secondary response) */
936   dissect_unknown_smb,      /* SMBwriteBraw write block raw */
937   dissect_unknown_smb,      /* SMBwriteBmpx write block multiplexed */
938   dissect_unknown_smb,      /* SMBwriteBs write block (secondary request) */
939   dissect_unknown_smb,      /* SMBwriteC write complete response */
940   dissect_unknown_smb,      /* unknown SMB 0x21 */
941   dissect_unknown_smb,      /* SMBsetattrE set file attributes expanded */
942   dissect_unknown_smb,      /* SMBgetattrE get file attributes expanded */
943   dissect_unknown_smb,      /* SMBlockingX lock/unlock byte ranges and X */
944   dissect_unknown_smb,      /* SMBtrans transaction - name, bytes in/out */
945   dissect_unknown_smb,      /* SMBtranss transaction (secondary request/response) */
946   dissect_unknown_smb,      /* SMBioctl IOCTL */
947   dissect_unknown_smb,      /* SMBioctls IOCTL (secondary request/response) */
948   dissect_unknown_smb,      /* SMBcopy copy */
949   dissect_unknown_smb,      /* SMBmove move */
950   dissect_unknown_smb,      /* SMBecho echo */
951   dissect_unknown_smb,      /* SMBwriteclose write a file and then close it */
952   dissect_unknown_smb,      /* SMBopenX open and X */
953   dissect_unknown_smb,      /* SMBreadX read and X */
954   dissect_unknown_smb,      /* SMBwriteX write and X */
955   dissect_unknown_smb,      /* unknown SMB 0x30 */
956   dissect_unknown_smb,      /* unknown SMB 0x31 */
957   dissect_unknown_smb,      /* unknown SMB 0x32 */
958   dissect_unknown_smb,      /* unknown SMB 0x33 */
959   dissect_unknown_smb,      /* unknown SMB 0x34 */
960   dissect_unknown_smb,      /* unknown SMB 0x35 */
961   dissect_unknown_smb,      /* unknown SMB 0x36 */
962   dissect_unknown_smb,      /* unknown SMB 0x37 */
963   dissect_unknown_smb,      /* unknown SMB 0x38 */
964   dissect_unknown_smb,      /* unknown SMB 0x39 */
965   dissect_unknown_smb,      /* unknown SMB 0x3a */
966   dissect_unknown_smb,      /* unknown SMB 0x3b */
967   dissect_unknown_smb,      /* unknown SMB 0x3c */
968   dissect_unknown_smb,      /* unknown SMB 0x3d */
969   dissect_unknown_smb,      /* unknown SMB 0x3e */
970   dissect_unknown_smb,      /* unknown SMB 0x3f */
971   dissect_unknown_smb,      /* unknown SMB 0x40 */
972   dissect_unknown_smb,      /* unknown SMB 0x41 */
973   dissect_unknown_smb,      /* unknown SMB 0x42 */
974   dissect_unknown_smb,      /* unknown SMB 0x43 */
975   dissect_unknown_smb,      /* unknown SMB 0x44 */
976   dissect_unknown_smb,      /* unknown SMB 0x45 */
977   dissect_unknown_smb,      /* unknown SMB 0x46 */
978   dissect_unknown_smb,      /* unknown SMB 0x47 */
979   dissect_unknown_smb,      /* unknown SMB 0x48 */
980   dissect_unknown_smb,      /* unknown SMB 0x49 */
981   dissect_unknown_smb,      /* unknown SMB 0x4a */
982   dissect_unknown_smb,      /* unknown SMB 0x4b */
983   dissect_unknown_smb,      /* unknown SMB 0x4c */
984   dissect_unknown_smb,      /* unknown SMB 0x4d */
985   dissect_unknown_smb,      /* unknown SMB 0x4e */
986   dissect_unknown_smb,      /* unknown SMB 0x4f */
987   dissect_unknown_smb,      /* unknown SMB 0x50 */
988   dissect_unknown_smb,      /* unknown SMB 0x51 */
989   dissect_unknown_smb,      /* unknown SMB 0x52 */
990   dissect_unknown_smb,      /* unknown SMB 0x53 */
991   dissect_unknown_smb,      /* unknown SMB 0x54 */
992   dissect_unknown_smb,      /* unknown SMB 0x55 */
993   dissect_unknown_smb,      /* unknown SMB 0x56 */
994   dissect_unknown_smb,      /* unknown SMB 0x57 */
995   dissect_unknown_smb,      /* unknown SMB 0x58 */
996   dissect_unknown_smb,      /* unknown SMB 0x59 */
997   dissect_unknown_smb,      /* unknown SMB 0x5a */
998   dissect_unknown_smb,      /* unknown SMB 0x5b */
999   dissect_unknown_smb,      /* unknown SMB 0x5c */
1000   dissect_unknown_smb,      /* unknown SMB 0x5d */
1001   dissect_unknown_smb,      /* unknown SMB 0x5e */
1002   dissect_unknown_smb,      /* unknown SMB 0x5f */
1003   dissect_unknown_smb,      /* unknown SMB 0x60 */
1004   dissect_unknown_smb,      /* unknown SMB 0x61 */
1005   dissect_unknown_smb,      /* unknown SMB 0x62 */
1006   dissect_unknown_smb,      /* unknown SMB 0x63 */
1007   dissect_unknown_smb,      /* unknown SMB 0x64 */
1008   dissect_unknown_smb,      /* unknown SMB 0x65 */
1009   dissect_unknown_smb,      /* unknown SMB 0x66 */
1010   dissect_unknown_smb,      /* unknown SMB 0x67 */
1011   dissect_unknown_smb,      /* unknown SMB 0x68 */
1012   dissect_unknown_smb,      /* unknown SMB 0x69 */
1013   dissect_unknown_smb,      /* unknown SMB 0x6a */
1014   dissect_unknown_smb,      /* unknown SMB 0x6b */
1015   dissect_unknown_smb,      /* unknown SMB 0x6c */
1016   dissect_unknown_smb,      /* unknown SMB 0x6d */
1017   dissect_unknown_smb,      /* unknown SMB 0x6e */
1018   dissect_unknown_smb,      /* unknown SMB 0x6f */
1019   dissect_unknown_smb,      /* SMBtcon tree connect */
1020   dissect_unknown_smb,      /* SMBtdis tree disconnect */
1021   dissect_negprot_smb,      /* SMBnegprot negotiate a protocol */
1022   dissect_unknown_smb,      /* SMBsesssetupX Session Set Up & X (including User Logon) */
1023   dissect_unknown_smb,      /* unknown SMB 0x74 */
1024   dissect_tcon_andx_smb,    /* SMBtconX tree connect and X */
1025   dissect_unknown_smb,      /* unknown SMB 0x76 */
1026   dissect_unknown_smb,      /* unknown SMB 0x77 */
1027   dissect_unknown_smb,      /* unknown SMB 0x78 */
1028   dissect_unknown_smb,      /* unknown SMB 0x79 */
1029   dissect_unknown_smb,      /* unknown SMB 0x7a */
1030   dissect_unknown_smb,      /* unknown SMB 0x7b */
1031   dissect_unknown_smb,      /* unknown SMB 0x7c */
1032   dissect_unknown_smb,      /* unknown SMB 0x7d */
1033   dissect_unknown_smb,      /* unknown SMB 0x7e */
1034   dissect_unknown_smb,      /* unknown SMB 0x7f */
1035   dissect_unknown_smb,      /* SMBdskattr get disk attributes */
1036   dissect_unknown_smb,      /* SMBsearch search a directory */
1037   dissect_unknown_smb,      /* SMBffirst find first */
1038   dissect_unknown_smb,      /* SMBfunique find unique */
1039   dissect_unknown_smb,      /* SMBfclose find close */
1040   dissect_unknown_smb,      /* unknown SMB 0x85 */
1041   dissect_unknown_smb,      /* unknown SMB 0x86 */
1042   dissect_unknown_smb,      /* unknown SMB 0x87 */
1043   dissect_unknown_smb,      /* unknown SMB 0x88 */
1044   dissect_unknown_smb,      /* unknown SMB 0x89 */
1045   dissect_unknown_smb,      /* unknown SMB 0x8a */
1046   dissect_unknown_smb,      /* unknown SMB 0x8b */
1047   dissect_unknown_smb,      /* unknown SMB 0x8c */
1048   dissect_unknown_smb,      /* unknown SMB 0x8d */
1049   dissect_unknown_smb,      /* unknown SMB 0x8e */
1050   dissect_unknown_smb,      /* unknown SMB 0x8f */
1051   dissect_unknown_smb,      /* unknown SMB 0x90 */
1052   dissect_unknown_smb,      /* unknown SMB 0x91 */
1053   dissect_unknown_smb,      /* unknown SMB 0x92 */
1054   dissect_unknown_smb,      /* unknown SMB 0x93 */
1055   dissect_unknown_smb,      /* unknown SMB 0x94 */
1056   dissect_unknown_smb,      /* unknown SMB 0x95 */
1057   dissect_unknown_smb,      /* unknown SMB 0x96 */
1058   dissect_unknown_smb,      /* unknown SMB 0x97 */
1059   dissect_unknown_smb,      /* unknown SMB 0x98 */
1060   dissect_unknown_smb,      /* unknown SMB 0x99 */
1061   dissect_unknown_smb,      /* unknown SMB 0x9a */
1062   dissect_unknown_smb,      /* unknown SMB 0x9b */
1063   dissect_unknown_smb,      /* unknown SMB 0x9c */
1064   dissect_unknown_smb,      /* unknown SMB 0x9d */
1065   dissect_unknown_smb,      /* unknown SMB 0x9e */
1066   dissect_unknown_smb,      /* unknown SMB 0x9f */
1067   dissect_unknown_smb,      /* unknown SMB 0xa0 */
1068   dissect_unknown_smb,      /* unknown SMB 0xa1 */
1069   dissect_unknown_smb,      /* unknown SMB 0xa2 */
1070   dissect_unknown_smb,      /* unknown SMB 0xa3 */
1071   dissect_unknown_smb,      /* unknown SMB 0xa4 */
1072   dissect_unknown_smb,      /* unknown SMB 0xa5 */
1073   dissect_unknown_smb,      /* unknown SMB 0xa6 */
1074   dissect_unknown_smb,      /* unknown SMB 0xa7 */
1075   dissect_unknown_smb,      /* unknown SMB 0xa8 */
1076   dissect_unknown_smb,      /* unknown SMB 0xa9 */
1077   dissect_unknown_smb,      /* unknown SMB 0xaa */
1078   dissect_unknown_smb,      /* unknown SMB 0xab */
1079   dissect_unknown_smb,      /* unknown SMB 0xac */
1080   dissect_unknown_smb,      /* unknown SMB 0xad */
1081   dissect_unknown_smb,      /* unknown SMB 0xae */
1082   dissect_unknown_smb,      /* unknown SMB 0xaf */
1083   dissect_unknown_smb,      /* unknown SMB 0xb0 */
1084   dissect_unknown_smb,      /* unknown SMB 0xb1 */
1085   dissect_unknown_smb,      /* unknown SMB 0xb2 */
1086   dissect_unknown_smb,      /* unknown SMB 0xb3 */
1087   dissect_unknown_smb,      /* unknown SMB 0xb4 */
1088   dissect_unknown_smb,      /* unknown SMB 0xb5 */
1089   dissect_unknown_smb,      /* unknown SMB 0xb6 */
1090   dissect_unknown_smb,      /* unknown SMB 0xb7 */
1091   dissect_unknown_smb,      /* unknown SMB 0xb8 */
1092   dissect_unknown_smb,      /* unknown SMB 0xb9 */
1093   dissect_unknown_smb,      /* unknown SMB 0xba */
1094   dissect_unknown_smb,      /* unknown SMB 0xbb */
1095   dissect_unknown_smb,      /* unknown SMB 0xbc */
1096   dissect_unknown_smb,      /* unknown SMB 0xbd */
1097   dissect_unknown_smb,      /* unknown SMB 0xbe */
1098   dissect_unknown_smb,      /* unknown SMB 0xbf */
1099   dissect_unknown_smb,      /* SMBsplopen open a print spool file */
1100   dissect_unknown_smb,      /* SMBsplwr write to a print spool file */
1101   dissect_unknown_smb,      /* SMBsplclose close a print spool file */
1102   dissect_unknown_smb,      /* SMBsplretq return print queue */
1103   dissect_unknown_smb,      /* unknown SMB 0xc4 */
1104   dissect_unknown_smb,      /* unknown SMB 0xc5 */
1105   dissect_unknown_smb,      /* unknown SMB 0xc6 */
1106   dissect_unknown_smb,      /* unknown SMB 0xc7 */
1107   dissect_unknown_smb,      /* unknown SMB 0xc8 */
1108   dissect_unknown_smb,      /* unknown SMB 0xc9 */
1109   dissect_unknown_smb,      /* unknown SMB 0xca */
1110   dissect_unknown_smb,      /* unknown SMB 0xcb */
1111   dissect_unknown_smb,      /* unknown SMB 0xcc */
1112   dissect_unknown_smb,      /* unknown SMB 0xcd */
1113   dissect_unknown_smb,      /* unknown SMB 0xce */
1114   dissect_unknown_smb,      /* unknown SMB 0xcf */
1115   dissect_unknown_smb,      /* SMBsends send a single block message */
1116   dissect_unknown_smb,      /* SMBsendb send a broadcast message */
1117   dissect_unknown_smb,      /* SMBfwdname forward user name */
1118   dissect_unknown_smb,      /* SMBcancelf cancel forward */
1119   dissect_unknown_smb,      /* SMBgetmac get a machine name */
1120   dissect_unknown_smb,      /* SMBsendstrt send start of multi-block message */
1121   dissect_unknown_smb,      /* SMBsendend send end of multi-block message */
1122   dissect_unknown_smb,      /* SMBsendtxt send text of multi-block message */
1123   dissect_unknown_smb,      /* unknown SMB 0xd8 */
1124   dissect_unknown_smb,      /* unknown SMB 0xd9 */
1125   dissect_unknown_smb,      /* unknown SMB 0xda */
1126   dissect_unknown_smb,      /* unknown SMB 0xdb */
1127   dissect_unknown_smb,      /* unknown SMB 0xdc */
1128   dissect_unknown_smb,      /* unknown SMB 0xdd */
1129   dissect_unknown_smb,      /* unknown SMB 0xde */
1130   dissect_unknown_smb,      /* unknown SMB 0xdf */
1131   dissect_unknown_smb,      /* unknown SMB 0xe0 */
1132   dissect_unknown_smb,      /* unknown SMB 0xe1 */
1133   dissect_unknown_smb,      /* unknown SMB 0xe2 */
1134   dissect_unknown_smb,      /* unknown SMB 0xe3 */
1135   dissect_unknown_smb,      /* unknown SMB 0xe4 */
1136   dissect_unknown_smb,      /* unknown SMB 0xe5 */
1137   dissect_unknown_smb,      /* unknown SMB 0xe6 */
1138   dissect_unknown_smb,      /* unknown SMB 0xe7 */
1139   dissect_unknown_smb,      /* unknown SMB 0xe8 */
1140   dissect_unknown_smb,      /* unknown SMB 0xe9 */
1141   dissect_unknown_smb,      /* unknown SMB 0xea */
1142   dissect_unknown_smb,      /* unknown SMB 0xeb */
1143   dissect_unknown_smb,      /* unknown SMB 0xec */
1144   dissect_unknown_smb,      /* unknown SMB 0xed */
1145   dissect_unknown_smb,      /* unknown SMB 0xee */
1146   dissect_unknown_smb,      /* unknown SMB 0xef */
1147   dissect_unknown_smb,      /* unknown SMB 0xf0 */
1148   dissect_unknown_smb,      /* unknown SMB 0xf1 */
1149   dissect_unknown_smb,      /* unknown SMB 0xf2 */
1150   dissect_unknown_smb,      /* unknown SMB 0xf3 */
1151   dissect_unknown_smb,      /* unknown SMB 0xf4 */
1152   dissect_unknown_smb,      /* unknown SMB 0xf5 */
1153   dissect_unknown_smb,      /* unknown SMB 0xf6 */
1154   dissect_unknown_smb,      /* unknown SMB 0xf7 */
1155   dissect_unknown_smb,      /* unknown SMB 0xf8 */
1156   dissect_unknown_smb,      /* unknown SMB 0xf9 */
1157   dissect_unknown_smb,      /* unknown SMB 0xfa */
1158   dissect_unknown_smb,      /* unknown SMB 0xfb */
1159   dissect_unknown_smb,      /* unknown SMB 0xfc */
1160   dissect_unknown_smb,      /* unknown SMB 0xfd */
1161   dissect_unknown_smb,      /* SMBinvalid invalid command */
1162   dissect_unknown_smb       /* unknown SMB 0xff */
1163
1164 };
1165
1166 static const value_string errcls_types[] = {
1167   { SMB_SUCCESS, "Success"},
1168   { SMB_ERRDOS, "DOS Error"},
1169   { SMB_ERRSRV, "Server Error"},
1170   { SMB_ERRHRD, "Hardware Error"},
1171   { SMB_ERRCMD, "Command Error - Not an SMB format command"},
1172   { 0, 0}
1173 };
1174
1175 char *decode_smb_name(unsigned char cmd)
1176 {
1177
1178   return(SMB_names[cmd]);
1179
1180 }
1181
1182 static const value_string DOS_errors[] = {
1183   {SMBE_badfunc, "Invalid function (or system call)"},
1184   {SMBE_badfile, "File not found (pathname error)"},
1185   {SMBE_badpath, "Directory not found"},
1186   {SMBE_nofids, "Too many open files"},
1187   {SMBE_noaccess, "Access denied"},
1188   {SMBE_badfid, "Invalid fid"},
1189   {SMBE_nomem,  "Out of memory"},
1190   {SMBE_badmem, "Invalid memory block address"},
1191   {SMBE_badenv, "Invalid environment"},
1192   {SMBE_badaccess, "Invalid open mode"},
1193   {SMBE_baddata, "Invalid data (only from ioctl call)"},
1194   {SMBE_res, "Reserved error code?"}, 
1195   {SMBE_baddrive, "Invalid drive"},
1196   {SMBE_remcd, "Attempt to delete current directory"},
1197   {SMBE_diffdevice, "Rename/move across different filesystems"},
1198   {SMBE_nofiles, "no more files found in file search"},
1199   {SMBE_badshare, "Share mode on file conflict with open mode"},
1200   {SMBE_lock, "Lock request conflicts with existing lock"},
1201   {SMBE_unsup, "Request unsupported, returned by Win 95"},
1202   {SMBE_filexists, "File in operation already exists"},
1203   {SMBE_cannotopen, "Cannot open the file specified"},
1204   {SMBE_unknownlevel, "Unknown level??"},
1205   {SMBE_badpipe, "Named pipe invalid"},
1206   {SMBE_pipebusy, "All instances of pipe are busy"},
1207   {SMBE_pipeclosing, "Named pipe close in progress"},
1208   {SMBE_notconnected, "No process on other end of named pipe"},
1209   {SMBE_moredata, "More data to be returned"},
1210   {SMBE_baddirectory,  "Invalid directory name in a path."},
1211   {SMBE_eas_didnt_fit, "Extended attributes didn't fit"},
1212   {SMBE_eas_nsup, "Extended attributes not supported"},
1213   {SMBE_notify_buf_small, "Buffer too small to return change notify."},
1214   {SMBE_unknownipc, "Unknown IPC Operation"},
1215   {SMBE_noipc, "Don't support ipc"},
1216   {0, 0}
1217   };
1218
1219 /* Error codes for the ERRSRV class */
1220
1221 static const value_string SRV_errors[] = {
1222   {SMBE_error, "Non specific error code"},
1223   {SMBE_badpw, "Bad password"},
1224   {SMBE_badtype, "Reserved"},
1225   {SMBE_access, "No permissions to perform the requested operation"},
1226   {SMBE_invnid, "TID invalid"},
1227   {SMBE_invnetname, "Invalid servername"},
1228   {SMBE_invdevice, "Invalid device"},
1229   {SMBE_unknownsmb, "Unknown SMB, from NT 3.5 response"},
1230   {SMBE_qfull, "Print queue full"},
1231   {SMBE_qtoobig, "Queued item too big"},
1232   {SMBE_invpfid, "Invalid print file in smb_fid"},
1233   {SMBE_smbcmd, "Unrecognised command"},
1234   {SMBE_srverror, "SMB server internal error"},
1235   {SMBE_filespecs, "Fid and pathname invalid combination"},
1236   {SMBE_badlink, "Bad link in request ???"},
1237   {SMBE_badpermits, "Access specified for a file is not valid"},
1238   {SMBE_badpid, "Bad process id in request"},
1239   {SMBE_setattrmode, "Attribute mode invalid"},
1240   {SMBE_paused, "Message server paused"},
1241   {SMBE_msgoff, "Not receiving messages"},
1242   {SMBE_noroom, "No room for message"},
1243   {SMBE_rmuns, "Too many remote usernames"},
1244   {SMBE_timeout, "Operation timed out"},
1245   {SMBE_noresource, "No resources currently available for request."},
1246   {SMBE_toomanyuids, "Too many userids"},
1247   {SMBE_baduid, "Bad userid"},
1248   {SMBE_useMPX, "Temporarily unable to use raw mode, use MPX mode"},
1249   {SMBE_useSTD, "Temporarily unable to use raw mode, use standard mode"},
1250   {SMBE_contMPX, "Resume MPX mode"},
1251   {SMBE_badPW, "Bad Password???"},
1252   {SMBE_nosupport, "Operation not supported???"},
1253   { 0, 0}
1254 };
1255
1256 /* Error codes for the ERRHRD class */
1257
1258 static const value_string HRD_errors[] = {
1259   {SMBE_nowrite, "read only media"},
1260   {SMBE_badunit, "Unknown device"},
1261   {SMBE_notready, "Drive not ready"},
1262   {SMBE_badcmd, "Unknown command"},
1263   {SMBE_data, "Data (CRC) error"},
1264   {SMBE_badreq, "Bad request structure length"},
1265   {SMBE_seek, "Seek error???"},
1266   {SMBE_badmedia, "Bad media???"},
1267   {SMBE_badsector, "Bad sector???"},
1268   {SMBE_nopaper, "No paper in printer???"},
1269   {SMBE_write, "Write error???"},
1270   {SMBE_read, "Read error???"},
1271   {SMBE_general, "General error???"},
1272   {SMBE_wrongdisk,  "Wrong disk???"},
1273   {SMBE_FCBunavail, "FCB unavailable???"},
1274   {SMBE_sharebufexc, "Share buffer excluded???"},
1275   {SMBE_diskfull, "Disk full???"},
1276   {0, 0}
1277 };
1278
1279 char *decode_smb_error(guint8 errcls, guint8 errcode)
1280 {
1281
1282   switch (errcls) {
1283
1284   case SMB_SUCCESS:
1285
1286     return("No Error");   /* No error ??? */
1287     break;
1288
1289   case SMB_ERRDOS:
1290
1291     return(val_to_str(errcode, DOS_errors, "Unknown DOS error (%x)"));
1292     break;
1293
1294   case SMB_ERRSRV:
1295
1296     return(val_to_str(errcode, SRV_errors, "Unknown SRV error (%x)"));
1297     break;
1298
1299   case SMB_ERRHRD:
1300
1301     return(val_to_str(errcode, HRD_errors, "Unknown HRD error(%x)"));
1302     break;
1303
1304   default:
1305
1306     return("Unknown error class!");
1307
1308   }
1309
1310 }
1311
1312 #define SMB_FLAGS_DIRN 0x80
1313
1314 void
1315 dissect_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data)
1316 {
1317         proto_tree      *smb_tree = tree, *flags_tree, *flags2_tree;
1318         proto_item      *ti, *tf;
1319         guint8          cmd, errcls, errcode1, flags;
1320         guint16         flags2, errcode, tid, pid, uid, mid;
1321
1322         cmd = pd[offset + SMB_hdr_com_offset];
1323
1324         if (check_col(fd, COL_PROTOCOL))
1325                 col_add_str(fd, COL_PROTOCOL, "SMB");
1326
1327         /* Hmmm, poor coding here ... Also, should check the type */
1328
1329         if (check_col(fd, COL_INFO)) {
1330
1331           col_add_fstr(fd, COL_INFO, "%s %s", decode_smb_name(cmd), (pi.match_port == pi.destport)? "Request" : "Response");
1332
1333         }
1334
1335         if (tree) {
1336
1337           ti = proto_tree_add_item(tree, offset, END_OF_FRAME,
1338                                 "Server Message Block Protocol");
1339           smb_tree = proto_tree_new();
1340           proto_item_add_subtree(ti, smb_tree, ETT_SMB);
1341
1342           /* 0xFFSMB is actually a 1 byte msg type and 3 byte server
1343            * component ... SMB is only one used
1344            */
1345
1346           proto_tree_add_item(smb_tree, offset, 1, "Message Type: 0xFF");
1347           proto_tree_add_item(smb_tree, offset+1, 3, "Server Component: SMB");
1348
1349         }
1350
1351         offset += 4;  /* Skip the marker */
1352
1353         if (tree) {
1354
1355           proto_tree_add_item(smb_tree, offset, 1, "Command: %s", decode_smb_name(cmd));
1356
1357         }
1358
1359         offset += 1;
1360
1361         /* Next, look at the error class, SMB_RETCLASS */
1362
1363         errcls = pd[offset];
1364
1365         if (tree) {
1366
1367           proto_tree_add_item(smb_tree, offset, 1, "Error Class: %s", 
1368                               val_to_str((guint8)pd[offset], errcls_types, "Unknown Error Class (%x)"));
1369         }
1370
1371         offset += 1;
1372
1373         /* Error code, SMB_HEINFO ... */
1374
1375         errcode1 = pd[offset];
1376
1377         if (tree) {
1378
1379           proto_tree_add_item(smb_tree, offset, 1, "Reserved: %i", errcode1); 
1380
1381         }
1382
1383         offset += 1;
1384
1385         errcode = GSHORT(pd, offset); 
1386
1387         if (tree) {
1388
1389           proto_tree_add_item(smb_tree, offset, 2, "Error Code: %s",
1390                               decode_smb_error(errcls, errcode));
1391
1392         }
1393
1394         offset += 2;
1395
1396         /* Now for the flags: Bit 0 = 0 means cmd, 0 = 1 means resp */
1397
1398         flags = pd[offset];
1399
1400         if (tree) {
1401
1402           tf = proto_tree_add_item(smb_tree, offset, 1, "Flags: 0x%02x", flags);
1403
1404           flags_tree = proto_tree_new();
1405           proto_item_add_subtree(tf, flags_tree, ETT_SMB_FLAGS);
1406           proto_tree_add_item(flags_tree, offset, 1, "%s",
1407                               decode_boolean_bitfield(flags, 0x01, 8,
1408                                                       "Lock&Read, Write&Unlock supported",
1409                                                       "Lock&Read, Write&Unlock not supported"));
1410           proto_tree_add_item(flags_tree, offset, 1, "%s",
1411                               decode_boolean_bitfield(flags, 0x02, 8,
1412                                                       "Receive buffer posted",
1413                                                       "Receive buffer not posted"));
1414           proto_tree_add_item(flags_tree, offset, 1, "%s",
1415                               decode_boolean_bitfield(flags, 0x08, 8, 
1416                                                       "Path names caseless",
1417                                                       "Path names case sensitive"));
1418           proto_tree_add_item(flags_tree, offset, 1, "%s",
1419                               decode_boolean_bitfield(flags, 0x10, 8,
1420                                                       "Pathnames canonicalized",
1421                                                       "Pathnames not canonicalized"));
1422           proto_tree_add_item(flags_tree, offset, 1, "%s",
1423                               decode_boolean_bitfield(flags, 0x20, 8,
1424                                                       "OpLocks requested/granted",
1425                                                       "OpLocks not requested/granted"));
1426           proto_tree_add_item(flags_tree, offset, 1, "%s",
1427                               decode_boolean_bitfield(flags, 0x40, 8, 
1428                                                       "Notify all",
1429                                                       "Notify open only"));
1430
1431           proto_tree_add_item(flags_tree, offset, 1, "%s",
1432                               decode_boolean_bitfield(flags, SMB_FLAGS_DIRN,
1433                                                       8, "Response to client/redirector", "Request to server"));
1434
1435         }
1436
1437         offset += 1;
1438
1439         flags2 = GSHORT(pd, offset);
1440
1441         if (tree) {
1442
1443           tf = proto_tree_add_item(smb_tree, offset, 1, "Flags2: 0x%04x", flags2);
1444
1445           flags2_tree = proto_tree_new();
1446           proto_item_add_subtree(tf, flags2_tree, ETT_SMB_FLAGS2);
1447           proto_tree_add_item(flags2_tree, offset, 1, "%s",
1448                               decode_boolean_bitfield(flags2, 0x0001, 16,
1449                                                       "Long file names supported",
1450                                                       "Long file names not supported"));
1451           proto_tree_add_item(flags2_tree, offset, 1, "%s",
1452                               decode_boolean_bitfield(flags2, 0x0002, 16,
1453                                                       "Extended attributes supported",
1454                                                       "Extended attributes not supported"));
1455           proto_tree_add_item(flags2_tree, offset, 1, "%s",
1456                               decode_boolean_bitfield(flags2, 0x1000, 16, 
1457                                                       "Resolve pathnames with Dfs",
1458                                                       "Don't resolve pathnames with Dfs"));
1459           proto_tree_add_item(flags2_tree, offset, 1, "%s",
1460                               decode_boolean_bitfield(flags2, 0x2000, 16,
1461                                                       "Permit reads if execute-only",
1462                                                       "Don't permit reads if execute-only"));
1463           proto_tree_add_item(flags2_tree, offset, 1, "%s",
1464                               decode_boolean_bitfield(flags2, 0x4000, 16,
1465                                                       "Error codes are NT error codes",
1466                                                       "Error codes are DOS error codes"));
1467           proto_tree_add_item(flags2_tree, offset, 1, "%s",
1468                               decode_boolean_bitfield(flags2, 0x8000, 16, 
1469                                                       "Strings are Unicode",
1470                                                       "Strings are ASCII"));
1471
1472         }
1473
1474         offset += 2;
1475
1476         if (tree) {
1477
1478           proto_tree_add_item(smb_tree, offset, 12, "Reserved: 6 WORDS");
1479
1480         }
1481
1482         offset += 12;
1483
1484         /* Now the TID, tree ID */
1485
1486         tid = GSHORT(pd, offset);
1487
1488         if (tree) {
1489
1490           proto_tree_add_item(smb_tree, offset, 2, "Network Path/Tree ID (TID): %i (%04x)", tid, tid); 
1491
1492         }
1493
1494         offset += 2;
1495
1496         /* Now the PID, Process ID */
1497
1498         pid = GSHORT(pd, offset);
1499
1500         if (tree) {
1501
1502           proto_tree_add_item(smb_tree, offset, 2, "Process ID (PID): %i (%04x)", pid, pid); 
1503
1504         }
1505
1506         offset += 2;
1507
1508         /* Now the UID, User ID */
1509
1510         uid = GSHORT(pd, offset);
1511
1512         if (tree) {
1513
1514           proto_tree_add_item(smb_tree, offset, 2, "User ID (UID): %i (%04x)", uid, uid); 
1515
1516         }
1517         
1518         offset += 2;
1519
1520         /* Now the MID, Multiplex ID */
1521
1522         mid = GSHORT(pd, offset);
1523
1524         if (tree) {
1525
1526           proto_tree_add_item(smb_tree, offset, 2, "Multiplex ID (MID): %i (%04x)", mid, mid); 
1527
1528         }
1529
1530         offset += 2;
1531
1532         /* Now vector through the table to dissect them */
1533
1534         (dissect[cmd])(pd, offset, fd, smb_tree, max_data, 
1535                        ((flags & 0x80) == 0));
1536
1537
1538 }