Added support for compiling on win32 with Visual C and 'nmake'. It compiles,
[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.19 1999/07/13 02:52:56 gram 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 <string.h>
43 #include <glib.h>
44 #include "packet.h"
45 #include "etypes.h"
46 #include "smb.h"
47 #include "alignment.h"
48
49 extern packet_info pi;
50
51 char *decode_smb_name(unsigned char);
52 void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, int, int);
53
54 char *SMB_names[256] = {
55   "SMBcreatedirectory",
56   "SMBdeletedirectory",
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   "SMBcloseandtreedisc",
105   "SMBtrans2",
106   "SMBtrans2secondary",
107   "SMBfindclose2",
108   "SMBfindnotifyclose",
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   "SMBlogoffX",
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   "SMBnttransact",
216   "SMBnttransactsecondary",
217   "SMBntcreateX",
218   "unknown-0xA3",
219   "SMBntcancel",
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   "SMBreadbulk",
272   "SMBwritebulk",
273   "SMBwritebulkdata",
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_text(tree, offset, END_OF_FRAME, "Data (%u bytes)", 
320                         END_OF_FRAME); 
321
322   }
323
324 }
325
326 /*
327  * Dissect a DOS-format date.
328  */
329 static char *
330 dissect_dos_date(guint16 date)
331 {
332         static char datebuf[4+2+2+1];
333
334         sprintf(datebuf, "%04d-%02d-%02d",
335             ((date>>9)&0x7F) + 1980, (date>>5)&0x0F, date&0x1F);
336         return datebuf;
337 }
338
339 /*
340  * Dissect a DOS-format time.
341  */
342 static char *
343 dissect_dos_time(guint16 time)
344 {
345         static char timebuf[2+2+2+1];
346
347         sprintf(timebuf, "%02d:%02d:%02d",
348             (time>>11)&0x1F, (time>>5)&0x3F, (time&0x1F)*2);
349         return timebuf;
350 }
351
352 /* Max string length for displaying Unicode strings.  */
353 #define MAX_UNICODE_STR_LEN     256
354
355 /* Turn a little-endian Unicode '\0'-terminated string into a string we
356    can display.
357    XXX - for now, we just handle the ISO 8859-1 characters. */
358 static gchar *
359 unicode_to_str(const guint8 *us, int *us_lenp) {
360   static gchar  str[3][MAX_UNICODE_STR_LEN+3+1];
361   static gchar *cur;
362   gchar        *p;
363   int           len;
364   int           us_len;
365   int           overflow = 0;
366
367   if (cur == &str[0][0]) {
368     cur = &str[1][0];
369   } else if (cur == &str[1][0]) {  
370     cur = &str[2][0];
371   } else {  
372     cur = &str[0][0];
373   }
374   p = cur;
375   len = MAX_UNICODE_STR_LEN;
376   us_len = 0;
377   while (*us != 0 || *(us + 1) != 0) {
378     if (len > 0) {
379       *p++ = *us;
380       len--;
381     } else
382       overflow = 1;
383     us += 2;
384     us_len += 2;
385   }
386   if (overflow) {
387     /* Note that we're not showing the full string.  */
388     *p++ = '.';
389     *p++ = '.';
390     *p++ = '.';
391   }
392   *p = '\0';
393   *us_lenp = us_len;
394   return cur;
395 }
396
397 /*
398  * Each dissect routine is passed an offset to wct and works from there 
399  */
400
401 void
402 dissect_treecon_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data, int dirn)
403
404 {
405   guint8        WordCount;
406   guint8        BufferFormat3;
407   guint8        BufferFormat2;
408   guint8        BufferFormat1;
409   guint16       TID;
410   guint16       MaxBufferSize;
411   guint16       ByteCount;
412   const char    *SharePath;
413   const char    *Service;
414   const char    *Password;
415
416   if (dirn == 1) { /* Request(s) dissect code */
417
418     /* Build display for: Word Count (WCT) */
419
420     WordCount = GBYTE(pd, offset);
421
422     if (tree) {
423
424       proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
425
426     }
427
428     offset += 1; /* Skip Word Count (WCT) */
429
430     /* Build display for: Byte Count (BCC) */
431
432     ByteCount = GSHORT(pd, offset);
433
434     if (tree) {
435
436       proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
437
438     }
439
440     offset += 2; /* Skip Byte Count (BCC) */
441
442     /* Build display for: BufferFormat1 */
443
444     BufferFormat1 = GBYTE(pd, offset);
445
446     if (tree) {
447
448       proto_tree_add_text(tree, offset, 1, "BufferFormat1: %u", BufferFormat1);
449
450     }
451
452     offset += 1; /* Skip BufferFormat1 */
453
454     /* Build display for: Share Path */
455
456     SharePath = pd + offset;
457
458     if (tree) {
459
460       proto_tree_add_text(tree, offset, strlen(SharePath) + 1, "Share Path: %s", SharePath);
461
462     }
463
464     offset += strlen(SharePath) + 1; /* Skip Share Path */
465
466     /* Build display for: BufferFormat2 */
467
468     BufferFormat2 = GBYTE(pd, offset);
469
470     if (tree) {
471
472       proto_tree_add_text(tree, offset, 1, "BufferFormat2: %u", BufferFormat2);
473
474     }
475
476     offset += 1; /* Skip BufferFormat2 */
477
478     /* Build display for: Password */
479
480     Password = pd + offset;
481
482     if (tree) {
483
484       proto_tree_add_text(tree, offset, strlen(Password) + 1, "Password: %s", Password);
485
486     }
487
488     offset += strlen(Password) + 1; /* Skip Password */
489
490     /* Build display for: BufferFormat3 */
491
492     BufferFormat3 = GBYTE(pd, offset);
493
494     if (tree) {
495
496       proto_tree_add_text(tree, offset, 1, "BufferFormat3: %u", BufferFormat3);
497
498     }
499
500     offset += 1; /* Skip BufferFormat3 */
501
502     /* Build display for: Service */
503
504     Service = pd + offset;
505
506     if (tree) {
507
508       proto_tree_add_text(tree, offset, strlen(Service) + 1, "Service: %s", Service);
509
510     }
511
512     offset += strlen(Service) + 1; /* Skip Service */
513
514   }
515
516   if (dirn == 0) { /* Response(s) dissect code */
517
518     /* Build display for: Word Count (WCT) */
519
520     WordCount = GBYTE(pd, offset);
521
522     if (tree) {
523
524       proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
525
526     }
527
528     offset += 1; /* Skip Word Count (WCT) */
529
530     /* Build display for: Max Buffer Size */
531
532     MaxBufferSize = GSHORT(pd, offset);
533
534     if (tree) {
535
536       proto_tree_add_text(tree, offset, 2, "Max Buffer Size: %u", MaxBufferSize);
537
538     }
539
540     offset += 2; /* Skip Max Buffer Size */
541
542     /* Build display for: TID */
543
544     TID = GSHORT(pd, offset);
545
546     if (tree) {
547
548       proto_tree_add_text(tree, offset, 2, "TID: %u", TID);
549
550     }
551
552     offset += 2; /* Skip TID */
553
554     /* Build display for: Byte Count (BCC) */
555
556     ByteCount = GSHORT(pd, offset);
557
558     if (tree) {
559
560       proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
561
562     }
563
564     offset += 2; /* Skip Byte Count (BCC) */
565
566   }
567
568 }
569
570 /* Generated by build-dissect.pl Vesion 0.6 27-Jun-1999, ACT */
571 void
572 dissect_ssetup_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data, int dirn)
573
574 {
575   proto_tree    *Capabilities_tree;
576   proto_item    *ti;
577   guint8        WordCount;
578   guint8        AndXReserved;
579   guint8        AndXCommand;
580   guint32       SessionKey;
581   guint32       Reserved;
582   guint32       Capabilities;
583   guint16       VcNumber;
584   guint16       UNICODEAccountPasswordLength;
585   guint16       PasswordLen;
586   guint16       MaxMpxCount;
587   guint16       MaxBufferSize;
588   guint16       ByteCount;
589   guint16       AndXOffset;
590   guint16       Action;
591   guint16       ANSIAccountPasswordLength;
592   const char    *UNICODEPassword;
593   const char    *PrimaryDomain;
594   const char    *NativeOS;
595   const char    *NativeLanManType;
596   const char    *NativeLanMan;
597   const char    *AccountName;
598   const char    *ANSIPassword;
599
600   if (dirn == 1) { /* Request(s) dissect code */
601
602     WordCount = GBYTE(pd, offset);
603
604     switch (WordCount) {
605
606     case 10:
607
608       /* Build display for: Word Count (WCT) */
609
610       WordCount = GBYTE(pd, offset);
611
612       if (tree) {
613
614         proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
615
616       }
617
618       offset += 1; /* Skip Word Count (WCT) */
619
620       /* Build display for: AndXCommand */
621
622       AndXCommand = GBYTE(pd, offset);
623
624       if (tree) {
625
626         proto_tree_add_text(tree, offset, 1, "AndXCommand: %u", AndXCommand);
627
628       }
629
630       offset += 1; /* Skip AndXCommand */
631
632       /* Build display for: AndXReserved */
633
634       AndXReserved = GBYTE(pd, offset);
635
636       if (tree) {
637
638         proto_tree_add_text(tree, offset, 1, "AndXReserved: %u", AndXReserved);
639
640       }
641
642       offset += 1; /* Skip AndXReserved */
643
644       /* Build display for: AndXOffset */
645
646       AndXOffset = GSHORT(pd, offset);
647
648       if (tree) {
649
650         proto_tree_add_text(tree, offset, 2, "AndXOffset: %u", AndXOffset);
651
652       }
653
654       offset += 2; /* Skip AndXOffset */
655
656       /* Build display for: MaxBufferSize */
657
658       MaxBufferSize = GSHORT(pd, offset);
659
660       if (tree) {
661
662         proto_tree_add_text(tree, offset, 2, "MaxBufferSize: %u", MaxBufferSize);
663
664       }
665
666       offset += 2; /* Skip MaxBufferSize */
667
668       /* Build display for: MaxMpxCount */
669
670       MaxMpxCount = GSHORT(pd, offset);
671
672       if (tree) {
673
674         proto_tree_add_text(tree, offset, 2, "MaxMpxCount: %u", MaxMpxCount);
675
676       }
677
678       offset += 2; /* Skip MaxMpxCount */
679
680       /* Build display for: VcNumber */
681
682       VcNumber = GSHORT(pd, offset);
683
684       if (tree) {
685
686         proto_tree_add_text(tree, offset, 2, "VcNumber: %u", VcNumber);
687
688       }
689
690       offset += 2; /* Skip VcNumber */
691
692       /* Build display for: SessionKey */
693
694       SessionKey = GWORD(pd, offset);
695
696       if (tree) {
697
698         proto_tree_add_text(tree, offset, 4, "SessionKey: %u", SessionKey);
699
700       }
701
702       offset += 4; /* Skip SessionKey */
703
704       /* Build display for: PasswordLen */
705
706       PasswordLen = GSHORT(pd, offset);
707
708       if (tree) {
709
710         proto_tree_add_text(tree, offset, 2, "PasswordLen: %u", PasswordLen);
711
712       }
713
714       offset += 2; /* Skip PasswordLen */
715
716       /* Build display for: Reserved */
717
718       Reserved = GWORD(pd, offset);
719
720       if (tree) {
721
722         proto_tree_add_text(tree, offset, 4, "Reserved: %u", Reserved);
723
724       }
725
726       offset += 4; /* Skip Reserved */
727
728       /* Build display for: Byte Count (BCC) */
729
730       ByteCount = GSHORT(pd, offset);
731
732       if (tree) {
733
734         proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
735
736       }
737
738       offset += 2; /* Skip Byte Count (BCC) */
739
740       /* Build display for: AccountName */
741
742       AccountName = pd + offset;
743
744       if (tree) {
745
746         proto_tree_add_text(tree, offset, strlen(AccountName) + 1, "AccountName: %s", AccountName);
747
748       }
749
750       offset += strlen(AccountName) + 1; /* Skip AccountName */
751
752       /* Build display for: PrimaryDomain */
753
754       PrimaryDomain = pd + offset;
755
756       if (tree) {
757
758         proto_tree_add_text(tree, offset, strlen(PrimaryDomain) + 1, "PrimaryDomain: %s", PrimaryDomain);
759
760       }
761
762       offset += strlen(PrimaryDomain) + 1; /* Skip PrimaryDomain */
763
764       /* Build display for: NativeOS */
765
766       NativeOS = pd + offset;
767
768       if (tree) {
769
770         proto_tree_add_text(tree, offset, strlen(NativeOS) + 1, "NativeOS: %s", NativeOS);
771
772       }
773
774       offset += strlen(NativeOS) + 1; /* Skip NativeOS */
775
776     break;
777
778     case 13:
779
780       /* Build display for: Word Count (WCT) */
781
782       WordCount = GBYTE(pd, offset);
783
784       if (tree) {
785
786         proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
787
788       }
789
790       offset += 1; /* Skip Word Count (WCT) */
791
792       /* Build display for: AndXCommand */
793
794       AndXCommand = GBYTE(pd, offset);
795
796       if (tree) {
797
798         proto_tree_add_text(tree, offset, 1, "AndXCommand: %u", AndXCommand);
799
800       }
801
802       offset += 1; /* Skip AndXCommand */
803
804       /* Build display for: AndXReserved */
805
806       AndXReserved = GBYTE(pd, offset);
807
808       if (tree) {
809
810         proto_tree_add_text(tree, offset, 1, "AndXReserved: %u", AndXReserved);
811
812       }
813
814       offset += 1; /* Skip AndXReserved */
815
816       /* Build display for: AndXOffset */
817
818       AndXOffset = GSHORT(pd, offset);
819
820       if (tree) {
821
822         proto_tree_add_text(tree, offset, 2, "AndXOffset: %u", AndXOffset);
823
824       }
825
826       offset += 2; /* Skip AndXOffset */
827
828       /* Build display for: MaxBufferSize */
829
830       MaxBufferSize = GSHORT(pd, offset);
831
832       if (tree) {
833
834         proto_tree_add_text(tree, offset, 2, "MaxBufferSize: %u", MaxBufferSize);
835
836       }
837
838       offset += 2; /* Skip MaxBufferSize */
839
840       /* Build display for: MaxMpxCount */
841
842       MaxMpxCount = GSHORT(pd, offset);
843
844       if (tree) {
845
846         proto_tree_add_text(tree, offset, 2, "MaxMpxCount: %u", MaxMpxCount);
847
848       }
849
850       offset += 2; /* Skip MaxMpxCount */
851
852       /* Build display for: VcNumber */
853
854       VcNumber = GSHORT(pd, offset);
855
856       if (tree) {
857
858         proto_tree_add_text(tree, offset, 2, "VcNumber: %u", VcNumber);
859
860       }
861
862       offset += 2; /* Skip VcNumber */
863
864       /* Build display for: SessionKey */
865
866       SessionKey = GWORD(pd, offset);
867
868       if (tree) {
869
870         proto_tree_add_text(tree, offset, 4, "SessionKey: %u", SessionKey);
871
872       }
873
874       offset += 4; /* Skip SessionKey */
875
876       /* Build display for: ANSI Account Password Length */
877
878       ANSIAccountPasswordLength = GSHORT(pd, offset);
879
880       if (tree) {
881
882         proto_tree_add_text(tree, offset, 2, "ANSI Account Password Length: %u", ANSIAccountPasswordLength);
883
884       }
885
886       offset += 2; /* Skip ANSI Account Password Length */
887
888       /* Build display for: UNICODE Account Password Length */
889
890       UNICODEAccountPasswordLength = GSHORT(pd, offset);
891
892       if (tree) {
893
894         proto_tree_add_text(tree, offset, 2, "UNICODE Account Password Length: %u", UNICODEAccountPasswordLength);
895
896       }
897
898       offset += 2; /* Skip UNICODE Account Password Length */
899
900       /* Build display for: Reserved */
901
902       Reserved = GWORD(pd, offset);
903
904       if (tree) {
905
906         proto_tree_add_text(tree, offset, 4, "Reserved: %u", Reserved);
907
908       }
909
910       offset += 4; /* Skip Reserved */
911
912       /* Build display for: Capabilities */
913
914       Capabilities = GWORD(pd, offset);
915
916       if (tree) {
917
918         ti = proto_tree_add_text(tree, offset, 4, "Capabilities: 0x%04x", Capabilities);
919         Capabilities_tree = proto_item_add_subtree(ti, ETT_SMB_CAPABILITIES);
920         proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
921                             decode_boolean_bitfield(Capabilities, 0x0001, 32, " Raw Mode supported", " Raw Mode not supported"));
922         proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
923                             decode_boolean_bitfield(Capabilities, 0x0002, 32, " Raw Mode supported", " MPX Mode not supported"));
924         proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
925                             decode_boolean_bitfield(Capabilities, 0x0004, 32," Unicode supported", " Unicode not supported"));
926         proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
927                             decode_boolean_bitfield(Capabilities, 0x0008, 32, " Large Files supported", " Large Files not supported"));
928         proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
929                             decode_boolean_bitfield(Capabilities, 0x0010, 32, " NT LM 0.12 SMBs supported", " NT LM 0.12 SMBs not supported"));
930         proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
931                             decode_boolean_bitfield(Capabilities, 0x0020, 32, " RPC Remote APIs supported", " RPC Remote APIs not supported"));
932         proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
933                             decode_boolean_bitfield(Capabilities, 0x0040, 32, " NT Status Codes supported", " NT Status Codes not supported"));
934         proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
935                             decode_boolean_bitfield(Capabilities, 0x0080, 32, " Level 2 OpLocks supported", " Level 2 OpLocks not supported"));
936         proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
937                             decode_boolean_bitfield(Capabilities, 0x0100, 32, " Lock&Read supported", " Lock&Read not supported"));
938         proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
939                             decode_boolean_bitfield(Capabilities, 0x0200, 32, " NT Find supported", " NT Find not supported"));
940         proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
941                             decode_boolean_bitfield(Capabilities, 0x1000, 32, " DFS supported", " DFS not supported"));
942         proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
943                             decode_boolean_bitfield(Capabilities, 0x4000, 32, " Large READX supported", " Large READX not supported"));
944         proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
945                             decode_boolean_bitfield(Capabilities, 0x8000, 32, " Large WRITEX supported", " Large WRITEX not supported"));
946         proto_tree_add_text(Capabilities_tree, offset, 4, "%s",
947                             decode_boolean_bitfield(Capabilities, 0x80000000, 32, " Extended Security Exchanges supported", " Extended Security Exchanges not supported"));
948       
949 }
950
951       offset += 4; /* Skip Capabilities */
952
953       /* Build display for: Byte Count */
954
955       ByteCount = GSHORT(pd, offset);
956
957       if (tree) {
958
959         proto_tree_add_text(tree, offset, 2, "Byte Count: %u", ByteCount);
960
961       }
962
963       offset += 2; /* Skip Byte Count */
964
965       /* Build display for: ANSI Password */
966
967       ANSIPassword = pd + offset;
968
969       if (tree) {
970
971         proto_tree_add_text(tree, offset, strlen(ANSIPassword) + 1, "ANSI Password: %s", ANSIPassword);
972
973       }
974
975       offset += ANSIAccountPasswordLength; /* Skip ANSI Password */
976
977       /* Build display for: UNICODE Password */
978
979       UNICODEPassword = pd + offset;
980
981       if (UNICODEAccountPasswordLength > 0) {
982
983         if (tree) {
984
985           proto_tree_add_text(tree, offset, strlen(UNICODEPassword) + 1, "UNICODE Password: %s", UNICODEPassword);
986
987         }
988
989         offset += strlen(UNICODEPassword) + 1; /* Skip UNICODE Password */
990
991       }
992
993       /* Build display for: Account Name */
994
995       AccountName = pd + offset;
996
997       if (tree) {
998
999         proto_tree_add_text(tree, offset, strlen(AccountName) + 1, "Account Name: %s", AccountName);
1000
1001       }
1002
1003       offset += strlen(AccountName) + 1; /* Skip Account Name */
1004
1005       /* Build display for: Primary Domain */
1006
1007       PrimaryDomain = pd + offset;
1008
1009       if (tree) {
1010
1011         proto_tree_add_text(tree, offset, strlen(PrimaryDomain) + 1, "Primary Domain: %s", PrimaryDomain);
1012
1013       }
1014
1015       offset += strlen(PrimaryDomain) + 1; /* Skip Primary Domain */
1016
1017       /* Build display for: Native OS */
1018
1019       NativeOS = pd + offset;
1020
1021       if (tree) {
1022
1023         proto_tree_add_text(tree, offset, strlen(NativeOS) + 1, "Native OS: %s", NativeOS);
1024
1025       }
1026
1027       offset += strlen(NativeOS) + 1; /* Skip Native OS */
1028
1029       /* Build display for: Native LanMan Type */
1030
1031       NativeLanManType = pd + offset;
1032
1033       if (tree) {
1034
1035         proto_tree_add_text(tree, offset, strlen(NativeLanManType) + 1, "Native LanMan Type: %s", NativeLanManType);
1036
1037       }
1038
1039       offset += strlen(NativeLanManType) + 1; /* Skip Native LanMan Type */
1040
1041     break;
1042
1043     }
1044
1045
1046     if (AndXCommand != 0xFF) {
1047
1048       (dissect[AndXCommand])(pd, offset, fd, tree, max_data, dirn);
1049
1050     }
1051
1052   }
1053
1054   if (dirn == 0) { /* Response(s) dissect code */
1055
1056     /* Build display for: Word Count (WCT) */
1057
1058     WordCount = GBYTE(pd, offset);
1059
1060     if (tree) {
1061
1062       proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
1063
1064     }
1065
1066     offset += 1; /* Skip Word Count (WCT) */
1067
1068     /* Build display for: AndXCommand */
1069
1070     AndXCommand = GBYTE(pd, offset);
1071
1072     if (tree) {
1073
1074       proto_tree_add_text(tree, offset, 1, "AndXCommand: %u", AndXCommand);
1075
1076     }
1077
1078     offset += 1; /* Skip AndXCommand */
1079
1080     /* Build display for: AndXReserved */
1081
1082     AndXReserved = GBYTE(pd, offset);
1083
1084     if (tree) {
1085
1086       proto_tree_add_text(tree, offset, 1, "AndXReserved: %u", AndXReserved);
1087
1088     }
1089
1090     offset += 1; /* Skip AndXReserved */
1091
1092     /* Build display for: AndXOffset */
1093
1094     AndXOffset = GSHORT(pd, offset);
1095
1096     if (tree) {
1097
1098       proto_tree_add_text(tree, offset, 2, "AndXOffset: %u", AndXOffset);
1099
1100     }
1101
1102     offset += 2; /* Skip AndXOffset */
1103
1104     /* Build display for: Action */
1105
1106     Action = GSHORT(pd, offset);
1107
1108     if (tree) {
1109
1110       proto_tree_add_text(tree, offset, 2, "Action: %u", Action);
1111
1112     }
1113
1114     offset += 2; /* Skip Action */
1115
1116     /* Build display for: Byte Count (BCC) */
1117
1118     ByteCount = GSHORT(pd, offset);
1119
1120     if (tree) {
1121
1122       proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
1123
1124     }
1125
1126     offset += 2; /* Skip Byte Count (BCC) */
1127
1128     /* Build display for: NativeOS */
1129
1130     NativeOS = pd + offset;
1131
1132     if (tree) {
1133
1134       proto_tree_add_text(tree, offset, strlen(NativeOS) + 1, "NativeOS: %s", NativeOS);
1135
1136     }
1137
1138     offset += strlen(NativeOS) + 1; /* Skip NativeOS */
1139
1140     /* Build display for: NativeLanMan */
1141
1142     NativeLanMan = pd + offset;
1143
1144     if (tree) {
1145
1146       proto_tree_add_text(tree, offset, strlen(NativeLanMan) + 1, "NativeLanMan: %s", NativeLanMan);
1147
1148     }
1149
1150     offset += strlen(NativeLanMan) + 1; /* Skip NativeLanMan */
1151
1152     /* Build display for: PrimaryDomain */
1153
1154     PrimaryDomain = pd + offset;
1155
1156     if (tree) {
1157
1158       proto_tree_add_text(tree, offset, strlen(PrimaryDomain) + 1, "PrimaryDomain: %s", PrimaryDomain);
1159
1160     }
1161
1162     offset += strlen(PrimaryDomain) + 1; /* Skip PrimaryDomain */
1163
1164
1165     if (AndXCommand != 0xFF) {
1166
1167       (dissect[AndXCommand])(pd, offset, fd, tree, max_data, dirn);
1168
1169     }
1170
1171   }
1172
1173 }
1174
1175 void
1176 dissect_tcon_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data, int dirn)
1177
1178 {
1179   guint8      wct, andxcmd;
1180   guint16     andxoffs, flags, passwdlen, bcc, optionsup;
1181   const char  *str;
1182   proto_tree  *flags_tree;
1183   proto_item  *ti;
1184
1185   wct = pd[offset];
1186
1187   /* Now figure out what format we are talking about, 2, 3, or 4 response
1188    * words ...
1189    */
1190
1191   if (!((dirn == 1) && (wct == 4)) && !((dirn == 0) && (wct == 2)) &&
1192       !((dirn == 0) && (wct == 3))) {
1193
1194     if (tree) {
1195
1196       proto_tree_add_text(tree, offset, 1, "Invalid TCON_ANDX format. WCT should be 2, 3, or 4 ..., not %u", wct);
1197
1198       proto_tree_add_text(tree, offset, END_OF_FRAME, "Data");
1199
1200       return;
1201
1202     }
1203     
1204   }
1205
1206   if (tree) {
1207
1208     proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", wct);
1209
1210   }
1211
1212   offset += 1;
1213
1214   andxcmd = pd[offset];
1215
1216   if (tree) {
1217
1218     proto_tree_add_text(tree, offset, 1, "Next Command: %s",
1219                         (andxcmd == 0xFF) ? "No further commands":
1220                         decode_smb_name(andxcmd));
1221                 
1222     proto_tree_add_text(tree, offset + 1, 1, "Reserved (MBZ): %u", pd[offset+1]);
1223
1224   }
1225
1226   offset += 2;
1227
1228   andxoffs = GSHORT(pd, offset);
1229
1230   if (tree) {
1231
1232     proto_tree_add_text(tree, offset, 2, "Offset to next command: %u", andxoffs);
1233
1234   }
1235
1236   offset += 2;
1237
1238   switch (wct) {
1239
1240   case 4:
1241
1242     flags = GSHORT(pd, offset);
1243
1244     if (tree) {
1245
1246       ti = proto_tree_add_text(tree, offset, 2, "Additional Flags: 0x%02x", flags);
1247       flags_tree = proto_item_add_subtree(ti, ETT_SMB_AFLAGS);
1248       proto_tree_add_text(flags_tree, offset, 2, "%s", 
1249                           decode_boolean_bitfield(flags, 0x01, 16,
1250                                                   "Disconnect TID",
1251                                                   "Don't disconnect TID"));
1252
1253     }
1254
1255     offset += 2;
1256
1257     passwdlen = GSHORT(pd, offset);
1258
1259     if (tree) {
1260
1261       proto_tree_add_text(tree, offset, 2, "Password Length: %u", passwdlen);
1262
1263     }
1264
1265     offset += 2;
1266
1267     bcc = GSHORT(pd, offset);
1268
1269     if (tree) {
1270
1271       proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", bcc);
1272
1273     }
1274
1275     offset += 2;
1276
1277     str = pd + offset;
1278
1279     if (tree) {
1280
1281       proto_tree_add_text(tree, offset, strlen(str) + 1, "Password: %s", str);
1282
1283     }
1284
1285     offset += strlen(str) + 1;
1286
1287     str = pd + offset;
1288
1289     if (tree) {
1290
1291       proto_tree_add_text(tree, offset, strlen(str) + 1, "Path: %s", str);
1292
1293     }
1294
1295     offset += strlen(str) + 1;
1296
1297     str = pd + offset;
1298
1299     if (tree) {
1300
1301       proto_tree_add_text(tree, offset, strlen(str) + 1, "Service: %s", str);
1302
1303     }
1304
1305     break;
1306
1307   case 2:
1308
1309     offset += 2;
1310
1311     bcc = GSHORT(pd, offset);
1312
1313     if (tree) {
1314
1315       proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", bcc);
1316
1317     }
1318
1319     offset += 2;
1320
1321     str = pd + offset;
1322
1323     if (tree) {
1324
1325       proto_tree_add_text(tree, offset, strlen(str) + 1, "Service Type: %s",
1326                           str);
1327
1328     }
1329
1330     offset += strlen(str) + 1;
1331
1332     break;
1333
1334   case 3:
1335
1336     optionsup = GSHORT(pd, offset);
1337
1338     if (tree) {  /* Should break out the bits */
1339
1340       proto_tree_add_text(tree, offset, 2, "Optional Support: 0x%04x", 
1341                           optionsup);
1342
1343     }
1344
1345     offset += 2;
1346
1347     bcc = GSHORT(pd, offset);
1348
1349     if (tree) {
1350
1351       proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", bcc);
1352
1353     }
1354
1355     offset += 2;
1356
1357     str = pd + offset;
1358
1359     if (tree) {
1360
1361       proto_tree_add_text(tree, offset, strlen(str) + 1, "Service: %s", str);
1362
1363     }
1364
1365     offset += strlen(str) + 1;
1366
1367     str = pd + offset;
1368
1369     if (tree) {
1370
1371       proto_tree_add_text(tree, offset, strlen(str) + 1, "Native File System: %s", str);
1372
1373     }
1374
1375     offset += strlen(str) + 1;
1376
1377     
1378     break;
1379
1380   default:
1381         ; /* nothing */
1382         break;
1383   }
1384
1385   if (andxcmd != 0xFF) /* Process that next command ... ??? */
1386
1387     (dissect[andxcmd])(pd, offset, fd, tree, max_data - offset, dirn);
1388
1389 }
1390
1391 void 
1392 dissect_negprot_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data, int dirn)
1393 {
1394   guint8        wct, enckeylen;
1395   guint16       bcc, mode, rawmode, dialect;
1396   guint32       caps;
1397   proto_tree    *dialects = NULL, *mode_tree, *caps_tree, *rawmode_tree;
1398   proto_item    *ti;
1399   const char    *str;
1400   char          *ustr;
1401   int           ustr_len;
1402
1403   wct = pd[offset];    /* Should be 0, 1 or 13 or 17, I think */
1404
1405   if (!((wct == 0) && (dirn == 1)) && !((wct == 1) && (dirn == 0)) &&
1406       !((wct == 13) && (dirn == 0)) && !((wct == 17) && (dirn == 0))) {
1407     if (tree) {
1408
1409       proto_tree_add_text(tree, offset, 1, "Invalid Negotiate Protocol format. WCT should be zero or 1 or 13 or 17 ..., not %u", wct);
1410
1411       proto_tree_add_text(tree, offset, END_OF_FRAME, "Data");
1412
1413       return;
1414     }
1415   }
1416
1417   if (tree) {
1418
1419     proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %d", wct);
1420
1421   }
1422
1423   offset += 1; 
1424
1425   /* Now decode the various formats ... */
1426
1427   switch (wct) {
1428
1429   case 0:     /* A request */
1430
1431     bcc = GSHORT(pd, offset);
1432
1433     if (tree) {
1434
1435       proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", bcc);
1436
1437     }
1438
1439     offset += 2;
1440
1441     if (tree) {
1442
1443       ti = proto_tree_add_text(tree, offset, END_OF_FRAME, "Dialects");
1444       dialects = proto_item_add_subtree(ti, ETT_SMB_DIALECTS);
1445
1446     }
1447
1448     while (fd->cap_len > offset) {
1449       const char *str;
1450
1451       if (tree) {
1452
1453         proto_tree_add_text(dialects, offset, 1, "Dialect Marker: %d", pd[offset]);
1454
1455       }
1456
1457       offset += 1;
1458
1459       str = pd + offset;
1460
1461       if (tree) {
1462
1463         proto_tree_add_text(dialects, offset, strlen(str)+1, "Dialect: %s", str);
1464
1465       }
1466
1467       offset += strlen(str) + 1;
1468
1469     }
1470     break;
1471
1472   case 1:     /* PC NETWORK PROGRAM 1.0 */
1473
1474     dialect = GSHORT(pd, offset);
1475
1476     if (tree) {  /* Hmmmm, what if none of the dialects is recognized */
1477
1478       if (dialect == 0xFFFF) { /* Server didn't like them dialects */
1479
1480         proto_tree_add_text(tree, offset, 2, "Supplied dialects not recognized");
1481
1482       }
1483       else {
1484
1485         proto_tree_add_text(tree, offset, 2, "Dialect Index: %u, PC NETWORK PROTGRAM 1.0", dialect);
1486
1487       }
1488
1489     }
1490
1491     offset += 2;
1492
1493     bcc = GSHORT(pd, offset);
1494
1495     if (tree) {
1496
1497       proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", bcc);
1498
1499     }
1500
1501     break;
1502
1503   case 13:    /* Greater than Core and up to and incl LANMAN2.1  */
1504
1505     if (tree) {
1506
1507       proto_tree_add_text(tree, offset, 2, "Dialect Index: %u, Greater than CORE PROTOCOL and up to LANMAN2.1", GSHORT(pd, offset));
1508
1509     }
1510
1511     /* Much of this is similar to response 17 below */
1512
1513     offset += 2;
1514
1515     mode = GSHORT(pd, offset);
1516
1517     if (tree) {
1518
1519       ti = proto_tree_add_text(tree, offset, 2, "Security Mode: 0x%04x", mode);
1520       mode_tree = proto_item_add_subtree(ti, ETT_SMB_MODE);
1521       proto_tree_add_text(mode_tree, offset, 2, "%s",
1522                           decode_boolean_bitfield(mode, 0x0001, 16,
1523                                                   "Security  = User",
1524                                                   "Security  = Share"));
1525       proto_tree_add_text(mode_tree, offset, 2, "%s",
1526                           decode_boolean_bitfield(mode, 0x0002, 16,
1527                                                   "Passwords = Encrypted",
1528                                                   "Passwords = Plaintext"));
1529
1530     }
1531
1532     offset += 2;
1533
1534     if (tree) {
1535
1536       proto_tree_add_text(tree, offset, 2, "Max buffer size:     %u", GSHORT(pd, offset));
1537
1538     }
1539
1540     offset += 2;
1541
1542     if (tree) {
1543
1544       proto_tree_add_text(tree, offset, 2, "Max multiplex count: %u", GSHORT(pd, offset));
1545
1546     }
1547     
1548     offset += 2;
1549
1550     if (tree) {
1551
1552       proto_tree_add_text(tree, offset, 2, "Max vcs:             %u", GSHORT(pd, offset));
1553
1554     }
1555
1556     offset += 2;
1557
1558     rawmode = GSHORT(pd, offset);
1559
1560     if (tree) {
1561
1562       ti = proto_tree_add_text(tree, offset, 2, "Raw Mode: 0x%04x", rawmode);
1563       rawmode_tree = proto_item_add_subtree(ti, ETT_SMB_RAWMODE);
1564       proto_tree_add_text(rawmode_tree, offset, 2, "%s",
1565                           decode_boolean_bitfield(rawmode, 0x01, 16,
1566                                                   "Read Raw supported",
1567                                                   "Read Raw not supported"));
1568       proto_tree_add_text(rawmode_tree, offset, 2, "%s",
1569                           decode_boolean_bitfield(rawmode, 0x02, 16,
1570                                                   "Write Raw supported",
1571                                                   "Write Raw not supported"));
1572
1573     }
1574
1575     offset += 2;
1576
1577     if (tree) {
1578
1579       proto_tree_add_text(tree, offset, 4, "Session key:         %08x", GWORD(pd, offset));
1580
1581     }
1582
1583     offset += 4;
1584
1585     /* Now the server time, two short parameters ... */
1586
1587     if (tree) {
1588
1589       proto_tree_add_text(tree, offset, 2, "Server Time: %s",
1590                         dissect_dos_time(GSHORT(pd, offset)));
1591       proto_tree_add_text(tree, offset + 2, 2, "Server Date: %s",
1592                         dissect_dos_date(GSHORT(pd, offset + 2)));
1593
1594     }
1595
1596     offset += 4;
1597
1598     /* Server Time Zone, SHORT */
1599
1600     if (tree) {
1601
1602       proto_tree_add_text(tree, offset, 2, "Server time zone: %i min from UTC",
1603                           (signed)GSSHORT(pd, offset));
1604
1605     }
1606
1607     offset += 2;
1608
1609     /* Challenge Length */
1610
1611     enckeylen = GSHORT(pd, offset);
1612
1613     if (tree) {
1614
1615       proto_tree_add_text(tree, offset, 2, "Challenge Length: %u", enckeylen);
1616
1617     }
1618
1619     offset += 2;
1620
1621     if (tree) {
1622
1623       proto_tree_add_text(tree, offset, 2, "Reserved: %u (MBZ)", GSHORT(pd, offset));
1624
1625     }
1626
1627     offset += 2;
1628
1629     bcc = GSHORT(pd, offset);
1630
1631     if (tree) {
1632
1633       proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", bcc);
1634
1635     }
1636
1637     offset += 2;
1638
1639     if (enckeylen) { /* only if non-zero key len */
1640
1641       str = pd + offset;
1642
1643       if (tree) {
1644
1645         proto_tree_add_text(tree, offset, enckeylen, "Challenge: %s",
1646                                 bytes_to_str(str, enckeylen));
1647       }
1648
1649       offset += enckeylen;
1650
1651     }
1652
1653     /* Primary Domain ... */
1654
1655     str = pd + offset;
1656
1657     if (tree) {
1658
1659       proto_tree_add_text(tree, offset, strlen(str)+1, "Primary Domain: %s", str);
1660
1661     }
1662
1663     break;
1664
1665   case 17:    /* Greater than LANMAN2.1 */
1666
1667     if (tree) {
1668
1669       proto_tree_add_text(tree, offset, 2, "Dialect Index: %u, Greater than LANMAN2.1", GSHORT(pd, offset));
1670
1671     }
1672
1673     offset += 2;
1674
1675     mode = GBYTE(pd, offset);
1676
1677     if (tree) {
1678
1679       ti = proto_tree_add_text(tree, offset, 1, "Security Mode: 0x%02x", mode);
1680       mode_tree = proto_item_add_subtree(ti, ETT_SMB_MODE);
1681       proto_tree_add_text(mode_tree, offset, 1, "%s",
1682                           decode_boolean_bitfield(mode, 0x01, 8,
1683                                                   "Security  = User",
1684                                                   "Security  = Share"));
1685       proto_tree_add_text(mode_tree, offset, 1, "%s",
1686                           decode_boolean_bitfield(mode, 0x02, 8,
1687                                                   "Passwords = Encrypted",
1688                                                   "Passwords = Plaintext"));
1689       proto_tree_add_text(mode_tree, offset, 1, "%s",
1690                           decode_boolean_bitfield(mode, 0x04, 8,
1691                                                   "Security signatures enabled",
1692                                                   "Security signatures not enabled"));
1693       proto_tree_add_text(mode_tree, offset, 1, "%s",
1694                           decode_boolean_bitfield(mode, 0x08, 8,
1695                                                   "Security signatures required",
1696                                                   "Security signatures not required"));
1697
1698     }
1699
1700     offset += 1;
1701
1702     if (tree) {
1703
1704       proto_tree_add_text(tree, offset, 2, "Max multiplex count: %u", GSHORT(pd, offset));
1705
1706     }
1707     
1708     offset += 2;
1709
1710     if (tree) {
1711
1712       proto_tree_add_text(tree, offset, 2, "Max vcs:             %u", GSHORT(pd, offset));
1713
1714     }
1715
1716     offset += 2;
1717
1718     if (tree) {
1719
1720       proto_tree_add_text(tree, offset, 2, "Max buffer size:     %u", GWORD(pd, offset));
1721
1722     }
1723
1724     offset += 4;
1725
1726     if (tree) {
1727
1728       proto_tree_add_text(tree, offset, 4, "Max raw size:        %u", GWORD(pd, offset));
1729
1730     }
1731
1732     offset += 4;
1733
1734     if (tree) {
1735
1736       proto_tree_add_text(tree, offset, 4, "Session key:         %08x", GWORD(pd, offset));
1737
1738     }
1739
1740     offset += 4;
1741
1742     caps = GWORD(pd, offset);
1743
1744     if (tree) {
1745
1746       ti = proto_tree_add_text(tree, offset, 4, "Capabilities: 0x%04x", caps);
1747       caps_tree = proto_item_add_subtree(ti, ETT_SMB_CAPABILITIES);
1748       proto_tree_add_text(caps_tree, offset, 4, "%s",
1749                           decode_boolean_bitfield(caps, 0x0001, 32,
1750                                                   "Raw Mode supported",
1751                                                   "Raw Mode not supported"));
1752       proto_tree_add_text(caps_tree, offset, 4, "%s",
1753                           decode_boolean_bitfield(caps, 0x0002, 32,
1754                                                   "MPX Mode supported",
1755                                                   "MPX Mode not supported"));
1756       proto_tree_add_text(caps_tree, offset, 4, "%s",
1757                           decode_boolean_bitfield(caps, 0x0004, 32,
1758                                                   "Unicode supported",
1759                                                   "Unicode not supported"));
1760       proto_tree_add_text(caps_tree, offset, 4, "%s",
1761                           decode_boolean_bitfield(caps, 0x0008, 32,
1762                                                   "Large files supported",
1763                                                   "Large files not supported"));
1764       proto_tree_add_text(caps_tree, offset, 4, "%s",
1765                           decode_boolean_bitfield(caps, 0x0010, 32, 
1766                                                   "NT LM 0.12 SMBs supported",
1767                                                   "NT LM 0.12 SMBs not supported"));
1768       proto_tree_add_text(caps_tree, offset, 4, "%s",
1769                           decode_boolean_bitfield(caps, 0x0020, 32,
1770                                                   "RPC remote APIs supported",
1771                                                   "RPC remote APIs not supported"));
1772       proto_tree_add_text(caps_tree, offset, 4, "%s",
1773                           decode_boolean_bitfield(caps, 0x0040, 32,
1774                                                   "NT status codes supported",
1775                                                   "NT status codes  not supported"));
1776       proto_tree_add_text(caps_tree, offset, 4, "%s",
1777                           decode_boolean_bitfield(caps, 0x0080, 32,
1778                                                   "Level 2 OpLocks supported",
1779                                                   "Level 2 OpLocks not supported"));
1780       proto_tree_add_text(caps_tree, offset, 4, "%s",
1781                           decode_boolean_bitfield(caps, 0x0100, 32,
1782                                                   "Lock&Read supported",
1783                                                   "Lock&Read not supported"));
1784       proto_tree_add_text(caps_tree, offset, 4, "%s",
1785                           decode_boolean_bitfield(caps, 0x0200, 32,
1786                                                   "NT Find supported",
1787                                                   "NT Find not supported"));
1788       proto_tree_add_text(caps_tree, offset, 4, "%s",
1789                           decode_boolean_bitfield(caps, 0x1000, 32,
1790                                                   "DFS supported",
1791                                                   "DFS not supported"));
1792       proto_tree_add_text(caps_tree, offset, 4, "%s",
1793                           decode_boolean_bitfield(caps, 0x4000, 32,
1794                                                   "Large READX supported",
1795                                                   "Large READX not supported"));
1796       proto_tree_add_text(caps_tree, offset, 4, "%s",
1797                           decode_boolean_bitfield(caps, 0x8000, 32,
1798                                                   "Large WRITEX supported",
1799                                                   "Large WRITEX not supported"));
1800       proto_tree_add_text(caps_tree, offset, 4, "%s",
1801                           decode_boolean_bitfield(caps, 0x80000000, 32,
1802                                                   "Extended security exchanges supported",
1803                                                   "Extended security exchanges not supported"));
1804     }
1805
1806     offset += 4;
1807
1808     /* Server time, 2 WORDS */
1809
1810     if (tree) {
1811
1812       proto_tree_add_text(tree, offset, 4, "System Time Low: 0x%08x", GWORD(pd, offset));
1813       proto_tree_add_text(tree, offset + 4, 4, "System Time High: 0x%08x", GWORD(pd, offset + 4)); 
1814
1815     }
1816
1817     offset += 8;
1818
1819     /* Server Time Zone, SHORT */
1820
1821     if (tree) {
1822
1823       proto_tree_add_text(tree, offset, 2, "Server time zone: %i min from UTC",
1824                           (signed)GSSHORT(pd, offset));
1825
1826     }
1827
1828     offset += 2;
1829
1830     /* Encryption key len */
1831
1832     enckeylen = pd[offset];
1833
1834     if (tree) {
1835
1836       proto_tree_add_text(tree, offset, 1, "Encryption key len: %u", enckeylen);
1837
1838     }
1839
1840     offset += 1;
1841
1842     bcc = GSHORT(pd, offset);
1843
1844     if (tree) {
1845
1846       proto_tree_add_text(tree, offset, 2, "Byte count (BCC): %u", bcc);
1847
1848     }
1849
1850     offset += 2;
1851
1852     if (enckeylen) { /* only if non-zero key len */
1853
1854       /* Encryption challenge key */
1855
1856       str = pd + offset;
1857
1858       if (tree) {
1859
1860         proto_tree_add_text(tree, offset, enckeylen, "Challenge encryption key: %s",
1861                                 bytes_to_str(str, enckeylen));
1862
1863       }
1864
1865       offset += enckeylen;
1866
1867     }
1868
1869     /* The domain, a null terminated string; Unicode if "caps" has
1870        the 0x0004 bit set, ASCII (OEM character set) otherwise.
1871        XXX - for now, we just handle the ISO 8859-1 subset of Unicode. */
1872
1873     str = pd + offset;
1874
1875     if (tree) {
1876
1877       if (caps & 0x0004) {
1878         ustr = unicode_to_str(str, &ustr_len);
1879         proto_tree_add_text(tree, offset, ustr_len+2, "OEM domain name: %s", ustr);
1880       } else {
1881         proto_tree_add_text(tree, offset, strlen(str)+1, "OEM domain name: %s", str);
1882       }
1883
1884     }
1885
1886     break;
1887
1888   default:    /* Baddd */
1889
1890     if (tree)
1891       proto_tree_add_text(tree, offset, 1, "Bad format, should never get here");
1892     return;
1893
1894   }
1895
1896 }
1897
1898 void
1899 dissect_deletedir_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data, int dirn)
1900
1901 {
1902   guint8        WordCount;
1903   guint8        BufferFormat;
1904   guint16       ByteCount;
1905   const char    *DirectoryName;
1906
1907   if (dirn == 1) { /* Request(s) dissect code */
1908
1909     /* Build display for: Word Count (WCT) */
1910
1911     WordCount = GBYTE(pd, offset);
1912
1913     if (tree) {
1914
1915       proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
1916
1917     }
1918
1919     offset += 1; /* Skip Word Count (WCT) */
1920
1921     /* Build display for: Byte Count (BCC) */
1922
1923     ByteCount = GSHORT(pd, offset);
1924
1925     if (tree) {
1926
1927       proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
1928
1929     }
1930
1931     offset += 2; /* Skip Byte Count (BCC) */
1932
1933     /* Build display for: Buffer Format */
1934
1935     BufferFormat = GBYTE(pd, offset);
1936
1937     if (tree) {
1938
1939       proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
1940
1941     }
1942
1943     offset += 1; /* Skip Buffer Format */
1944
1945     /* Build display for: Directory Name */
1946
1947     DirectoryName = pd + offset;
1948
1949     if (tree) {
1950
1951       proto_tree_add_text(tree, offset, strlen(DirectoryName) + 1, "Directory Name: %s", DirectoryName);
1952
1953     }
1954
1955     offset += strlen(DirectoryName) + 1; /* Skip Directory Name */
1956
1957   }
1958
1959   if (dirn == 0) { /* Response(s) dissect code */
1960
1961     /* Build display for: Word Count (WCT) */
1962
1963     WordCount = GBYTE(pd, offset);
1964
1965     if (tree) {
1966
1967       proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
1968
1969     }
1970
1971     offset += 1; /* Skip Word Count (WCT) */
1972
1973     /* Build display for: Byte Count (BCC) */
1974
1975     ByteCount = GSHORT(pd, offset);
1976
1977     if (tree) {
1978
1979       proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
1980
1981     }
1982
1983     offset += 2; /* Skip Byte Count (BCC) */
1984
1985   }
1986
1987 }
1988
1989 void
1990 dissect_createdir_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data, int dirn)
1991
1992 {
1993   guint8        WordCount;
1994   guint8        BufferFormat;
1995   guint16       ByteCount;
1996   const char    *DirectoryName;
1997
1998   if (dirn == 1) { /* Request(s) dissect code */
1999
2000     /* Build display for: Word Count (WCT) */
2001
2002     WordCount = GBYTE(pd, offset);
2003
2004     if (tree) {
2005
2006       proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
2007
2008     }
2009
2010     offset += 1; /* Skip Word Count (WCT) */
2011
2012     /* Build display for: Byte Count (BCC) */
2013
2014     ByteCount = GSHORT(pd, offset);
2015
2016     if (tree) {
2017
2018       proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
2019
2020     }
2021
2022     offset += 2; /* Skip Byte Count (BCC) */
2023
2024     /* Build display for: Buffer Format */
2025
2026     BufferFormat = GBYTE(pd, offset);
2027
2028     if (tree) {
2029
2030       proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
2031
2032     }
2033
2034     offset += 1; /* Skip Buffer Format */
2035
2036     /* Build display for: Directory Name */
2037
2038     DirectoryName = pd + offset;
2039
2040     if (tree) {
2041
2042       proto_tree_add_text(tree, offset, strlen(DirectoryName) + 1, "Directory Name: %s", DirectoryName);
2043
2044     }
2045
2046     offset += strlen(DirectoryName) + 1; /* Skip Directory Name */
2047
2048   }
2049
2050   if (dirn == 0) { /* Response(s) dissect code */
2051
2052     /* Build display for: Word Count (WCT) */
2053
2054     WordCount = GBYTE(pd, offset);
2055
2056     if (tree) {
2057
2058       proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
2059
2060     }
2061
2062     offset += 1; /* Skip Word Count (WCT) */
2063
2064     /* Build display for: Byte Count (BCC) */
2065
2066     ByteCount = GSHORT(pd, offset);
2067
2068     if (tree) {
2069
2070       proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
2071
2072     }
2073
2074     offset += 2; /* Skip Byte Count (BCC) */
2075
2076   }
2077
2078 }
2079
2080 void
2081 dissect_checkdir_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data, int dirn)
2082
2083 {
2084   guint8        WordCount;
2085   guint8        BufferFormat;
2086   guint16       ByteCount;
2087   const char    *DirectoryName;
2088
2089   if (dirn == 1) { /* Request(s) dissect code */
2090
2091     /* Build display for: Word Count (WCT) */
2092
2093     WordCount = GBYTE(pd, offset);
2094
2095     if (tree) {
2096
2097       proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
2098
2099     }
2100
2101     offset += 1; /* Skip Word Count (WCT) */
2102
2103     /* Build display for: Byte Count (BCC) */
2104
2105     ByteCount = GSHORT(pd, offset);
2106
2107     if (tree) {
2108
2109       proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
2110
2111     }
2112
2113     offset += 2; /* Skip Byte Count (BCC) */
2114
2115     /* Build display for: Buffer Format */
2116
2117     BufferFormat = GBYTE(pd, offset);
2118
2119     if (tree) {
2120
2121       proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
2122
2123     }
2124
2125     offset += 1; /* Skip Buffer Format */
2126
2127     /* Build display for: Directory Name */
2128
2129     DirectoryName = pd + offset;
2130
2131     if (tree) {
2132
2133       proto_tree_add_text(tree, offset, strlen(DirectoryName) + 1, "Directory Name: %s", DirectoryName);
2134
2135     }
2136
2137     offset += strlen(DirectoryName) + 1; /* Skip Directory Name */
2138
2139   }
2140
2141   if (dirn == 0) { /* Response(s) dissect code */
2142
2143     /* Build display for: Word Count (WCT) */
2144
2145     WordCount = GBYTE(pd, offset);
2146
2147     if (tree) {
2148
2149       proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
2150
2151     }
2152
2153     offset += 1; /* Skip Word Count (WCT) */
2154
2155     /* Build display for: Byte Count (BCC) */
2156
2157     ByteCount = GSHORT(pd, offset);
2158
2159     if (tree) {
2160
2161       proto_tree_add_text(tree, offset, 2, "Byte Count (BCC): %u", ByteCount);
2162
2163     }
2164
2165     offset += 2; /* Skip Byte Count (BCC) */
2166
2167   }
2168
2169 }
2170
2171 void
2172 dissect_open_andx_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data, int dirn)
2173
2174 {
2175   static const value_string OpenFunction_0x10[] = {
2176         { 0, "Fail if file does not exist"},
2177         { 16, "Create file if it does not exist"},
2178         { 0, NULL}
2179   };
2180   static const value_string OpenFunction_0x03[] = {
2181         { 0, "Fail if file exists"},
2182         { 1, "Open file if it exists"},
2183         { 2, "Truncate File if it exists"},
2184         { 0, NULL}
2185   };
2186   static const value_string FileType_0xFFFF[] = {
2187         { 0, "Disk file or directory"},
2188         { 1, "Named pipe in byte mode"},
2189         { 2, "Named pipe in message mode"},
2190         { 3, "Spooled printer"},
2191         { 0, NULL}
2192   };
2193   static const value_string DesiredAccess_0x70[] = {
2194         { 00, "Compatibility mode"},
2195         { 16, "Deny read/write/execute (exclusive)"},
2196         { 32, "Deny write"},
2197         { 48, "Deny read/execute"},
2198         { 64, "Deny none"},
2199         { 0, NULL}
2200   };
2201   static const value_string DesiredAccess_0x700[] = {
2202         { 0, "Locality of reference unknown"},
2203         { 256, "Mainly sequential access"},
2204         { 512, "Mainly random access"},
2205         { 768, "Random access with some locality"},
2206         {0, NULL}
2207   };
2208   static const value_string DesiredAccess_0x4000[] = {
2209         { 0, "Write through mode disabled"},
2210         { 16384, "Write through mode enabled"},
2211         {0, NULL}
2212   };
2213   static const value_string DesiredAccess_0x1000[] = {
2214         { 0, "Normal file (caching permitted)"},
2215         { 4096, "Do not cache this file"},
2216         {0, NULL}
2217   };
2218   static const value_string DesiredAccess_0x07[] = {
2219         { 0, "Open for reading"},
2220         { 1, "Open for writing"},
2221         { 2, "Open for reading and writing"},
2222         { 3, "Open for execute"},
2223         {0, NULL}
2224   };
2225   static const value_string Action_0x8000[] = {
2226         { 0, "File opened by another user (or mode not supported by server)"},
2227         { 32768, "File is opened only by this user at present"},
2228         {0, NULL}
2229   };
2230   static const value_string Action_0x0003[] = {
2231         { 0, "No action taken?"},
2232         { 1, "The file existed and was opened"},
2233         { 2, "The file did not exist but was created"},
2234         { 3, "The file existed and was truncated"},
2235         {0, NULL}
2236   };
2237   proto_tree    *Search_tree;
2238   proto_tree    *OpenFunction_tree;
2239   proto_tree    *Flags_tree;
2240   proto_tree    *File_tree;
2241   proto_tree    *FileType_tree;
2242   proto_tree    *FileAttributes_tree;
2243   proto_tree    *DesiredAccess_tree;
2244   proto_tree    *Action_tree;
2245   proto_item    *ti;
2246   guint8        WordCount;
2247   guint8        BufferFormat;
2248   guint8        AndXReserved;
2249   guint8        AndXCommand;
2250   guint32       ServerFID;
2251   guint32       Reserved2;
2252   guint32       Reserved1;
2253   guint32       DataSize;
2254   guint32       AllocatedSize;
2255   guint16       Search;
2256   guint16       Reserved;
2257   guint16       OpenFunction;
2258   guint16       LastWriteTime;
2259   guint16       LastWriteDate;
2260   guint16       GrantedAccess;
2261   guint16       Flags;
2262   guint16       FileType;
2263   guint16       FileAttributes;
2264   guint16       File;
2265   guint16       FID;
2266   guint16       DeviceState;
2267   guint16       DesiredAccess;
2268   guint16       CreationTime;
2269   guint16       CreationDate;
2270   guint16       ByteCount;
2271   guint16       AndXOffset;
2272   guint16       Action;
2273   const char    *FileName;
2274
2275   if (dirn == 1) { /* Request(s) dissect code */
2276
2277     /* Build display for: Word Count (WCT) */
2278
2279     WordCount = GBYTE(pd, offset);
2280
2281     if (tree) {
2282
2283       proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
2284
2285     }
2286
2287     offset += 1; /* Skip Word Count (WCT) */
2288
2289     /* Build display for: AndXCommand */
2290
2291     AndXCommand = GBYTE(pd, offset);
2292
2293     if (tree) {
2294
2295       proto_tree_add_text(tree, offset, 1, "AndXCommand: %u", AndXCommand);
2296
2297     }
2298
2299     offset += 1; /* Skip AndXCommand */
2300
2301     /* Build display for: AndXReserved */
2302
2303     AndXReserved = GBYTE(pd, offset);
2304
2305     if (tree) {
2306
2307       proto_tree_add_text(tree, offset, 1, "AndXReserved: %u", AndXReserved);
2308
2309     }
2310
2311     offset += 1; /* Skip AndXReserved */
2312
2313     /* Build display for: AndXOffset */
2314
2315     AndXOffset = GSHORT(pd, offset);
2316
2317     if (tree) {
2318
2319       proto_tree_add_text(tree, offset, 2, "AndXOffset: %u", AndXOffset);
2320
2321     }
2322
2323     offset += 2; /* Skip AndXOffset */
2324
2325     /* Build display for: Flags */
2326
2327     Flags = GSHORT(pd, offset);
2328
2329     if (tree) {
2330
2331       ti = proto_tree_add_text(tree, offset, 2, "Flags: 0x%02x", Flags);
2332       Flags_tree = proto_item_add_subtree(ti, ETT_SMB_FLAGS);
2333       proto_tree_add_text(Flags_tree, offset, 2, "%s",
2334                           decode_boolean_bitfield(Flags, 0x01, 16, "Dont Return Additional Info", "Return Additional Info"));
2335       proto_tree_add_text(Flags_tree, offset, 2, "%s",
2336                           decode_boolean_bitfield(Flags, 0x02, 16, "Exclusive OpLock not Requested", "Exclusive OpLock Requested"));
2337       proto_tree_add_text(Flags_tree, offset, 2, "%s",
2338                           decode_boolean_bitfield(Flags, 0x04, 16, "Batch OpLock not Requested", "Batch OpLock Requested"));
2339     
2340 }
2341
2342     offset += 2; /* Skip Flags */
2343
2344     /* Build display for: Desired Access */
2345
2346     DesiredAccess = GSHORT(pd, offset);
2347
2348     if (tree) {
2349
2350       ti = proto_tree_add_text(tree, offset, 2, "Desired Access: 0x%02x", DesiredAccess);
2351       DesiredAccess_tree = proto_item_add_subtree(ti, ETT_SMB_DESIREDACCESS);
2352       proto_tree_add_text(DesiredAccess_tree, offset, 2, "%s",
2353                           decode_enumerated_bitfield(DesiredAccess, 0x07, 16, DesiredAccess_0x07, "%s"));
2354       proto_tree_add_text(DesiredAccess_tree, offset, 2, "%s",
2355                           decode_enumerated_bitfield(DesiredAccess, 0x70, 16, DesiredAccess_0x70, "%s"));
2356       proto_tree_add_text(DesiredAccess_tree, offset, 2, "%s",
2357                           decode_enumerated_bitfield(DesiredAccess, 0x700, 16, DesiredAccess_0x700, "%s"));
2358       proto_tree_add_text(DesiredAccess_tree, offset, 2, "%s",
2359                           decode_enumerated_bitfield(DesiredAccess, 0x1000, 16, DesiredAccess_0x1000, "%s"));
2360       proto_tree_add_text(DesiredAccess_tree, offset, 2, "%s",
2361                           decode_enumerated_bitfield(DesiredAccess, 0x4000, 16, DesiredAccess_0x4000, "%s"));
2362     
2363 }
2364
2365     offset += 2; /* Skip Desired Access */
2366
2367     /* Build display for: Search */
2368
2369     Search = GSHORT(pd, offset);
2370
2371     if (tree) {
2372
2373       ti = proto_tree_add_text(tree, offset, 2, "Search: 0x%02x", Search);
2374       Search_tree = proto_item_add_subtree(ti, ETT_SMB_SEARCH);
2375       proto_tree_add_text(Search_tree, offset, 2, "%s",
2376                           decode_boolean_bitfield(Search, 0x01, 16, "Read only file", "Not a read only file"));
2377       proto_tree_add_text(Search_tree, offset, 2, "%s",
2378                           decode_boolean_bitfield(Search, 0x02, 16, "Hidden file", "Not a hidden file"));
2379       proto_tree_add_text(Search_tree, offset, 2, "%s",
2380                           decode_boolean_bitfield(Search, 0x04, 16, "System file", "Not a system file"));
2381       proto_tree_add_text(Search_tree, offset, 2, "%s",
2382                           decode_boolean_bitfield(Search, 0x08, 16, " Volume", "Not a volume"));
2383       proto_tree_add_text(Search_tree, offset, 2, "%s",
2384                           decode_boolean_bitfield(Search, 0x10, 16, " Directory", "Not a directory"));
2385       proto_tree_add_text(Search_tree, offset, 2, "%s",
2386                           decode_boolean_bitfield(Search, 0x20, 16, "Archive file", "Do not archive file"));
2387     
2388 }
2389
2390     offset += 2; /* Skip Search */
2391
2392     /* Build display for: File */
2393
2394     File = GSHORT(pd, offset);
2395
2396     if (tree) {
2397
2398       ti = proto_tree_add_text(tree, offset, 2, "File: 0x%02x", File);
2399       File_tree = proto_item_add_subtree(ti, ETT_SMB_FILE);
2400       proto_tree_add_text(File_tree, offset, 2, "%s",
2401                           decode_boolean_bitfield(File, 0x01, 16, "Read only file", "Not a read only file"));
2402       proto_tree_add_text(File_tree, offset, 2, "%s",
2403                           decode_boolean_bitfield(File, 0x02, 16, "Hidden file", "Not a hidden file"));
2404       proto_tree_add_text(File_tree, offset, 2, "%s",
2405                           decode_boolean_bitfield(File, 0x04, 16, "System file", "Not a system file"));
2406       proto_tree_add_text(File_tree, offset, 2, "%s",
2407                           decode_boolean_bitfield(File, 0x08, 16, " Volume", "Not a volume"));
2408       proto_tree_add_text(File_tree, offset, 2, "%s",
2409                           decode_boolean_bitfield(File, 0x10, 16, " Directory", "Not a directory"));
2410       proto_tree_add_text(File_tree, offset, 2, "%s",
2411                           decode_boolean_bitfield(File, 0x20, 16, "Archive file", "Do not archive file"));
2412     
2413 }
2414
2415     offset += 2; /* Skip File */
2416
2417     /* Build display for: Creation Time */
2418
2419     CreationTime = GSHORT(pd, offset);
2420
2421     if (tree) {
2422
2423       proto_tree_add_text(tree, offset, 2, "Creation Time: %s", dissect_dos_time(CreationTime));
2424
2425     }
2426
2427     offset += 2; /* Skip Creation Time */
2428
2429     /* Build display for: Creation Date */
2430
2431     CreationDate = GSHORT(pd, offset);
2432
2433     if (tree) {
2434
2435       proto_tree_add_text(tree, offset, 2, "Creation Date: %s", dissect_dos_date(CreationDate));
2436
2437     }
2438
2439     offset += 2; /* Skip Creation Date */
2440
2441     /* Build display for: Open Function */
2442
2443     OpenFunction = GSHORT(pd, offset);
2444
2445     if (tree) {
2446
2447       ti = proto_tree_add_text(tree, offset, 2, "Open Function: 0x%02x", OpenFunction);
2448       OpenFunction_tree = proto_item_add_subtree(ti, ETT_SMB_OPENFUNCTION);
2449       proto_tree_add_text(OpenFunction_tree, offset, 2, "%s",
2450                           decode_enumerated_bitfield(OpenFunction, 0x10, 16, OpenFunction_0x10, "%s"));
2451       proto_tree_add_text(OpenFunction_tree, offset, 2, "%s",
2452                           decode_enumerated_bitfield(OpenFunction, 0x03, 16, OpenFunction_0x03, "%s"));
2453     
2454 }
2455
2456     offset += 2; /* Skip Open Function */
2457
2458     /* Build display for: Allocated Size */
2459
2460     AllocatedSize = GWORD(pd, offset);
2461
2462     if (tree) {
2463
2464       proto_tree_add_text(tree, offset, 4, "Allocated Size: %u", AllocatedSize);
2465
2466     }
2467
2468     offset += 4; /* Skip Allocated Size */
2469
2470     /* Build display for: Reserved1 */
2471
2472     Reserved1 = GWORD(pd, offset);
2473
2474     if (tree) {
2475
2476       proto_tree_add_text(tree, offset, 4, "Reserved1: %u", Reserved1);
2477
2478     }
2479
2480     offset += 4; /* Skip Reserved1 */
2481
2482     /* Build display for: Reserved2 */
2483
2484     Reserved2 = GWORD(pd, offset);
2485
2486     if (tree) {
2487
2488       proto_tree_add_text(tree, offset, 4, "Reserved2: %u", Reserved2);
2489
2490     }
2491
2492     offset += 4; /* Skip Reserved2 */
2493
2494     /* Build display for: Byte Count */
2495
2496     ByteCount = GSHORT(pd, offset);
2497
2498     if (tree) {
2499
2500       proto_tree_add_text(tree, offset, 2, "Byte Count: %u", ByteCount);
2501
2502     }
2503
2504     offset += 2; /* Skip Byte Count */
2505
2506     /* Build display for: Buffer Format */
2507
2508     BufferFormat = GBYTE(pd, offset);
2509
2510     if (tree) {
2511
2512       proto_tree_add_text(tree, offset, 1, "Buffer Format: %u", BufferFormat);
2513
2514     }
2515
2516     offset += 1; /* Skip Buffer Format */
2517
2518     /* Build display for: File Name */
2519
2520     FileName = pd + offset;
2521
2522     if (tree) {
2523
2524       proto_tree_add_text(tree, offset, strlen(FileName) + 1, "File Name: %s", FileName);
2525
2526     }
2527
2528     offset += strlen(FileName) + 1; /* Skip File Name */
2529
2530
2531     if (AndXCommand != 0xFF) {
2532
2533       (dissect[AndXCommand])(pd, offset, fd, tree, max_data, dirn);
2534
2535     }
2536
2537   }
2538
2539   if (dirn == 0) { /* Response(s) dissect code */
2540
2541     /* Build display for: Word Count (WCT) */
2542
2543     WordCount = GBYTE(pd, offset);
2544
2545     if (tree) {
2546
2547       proto_tree_add_text(tree, offset, 1, "Word Count (WCT): %u", WordCount);
2548
2549     }
2550
2551     offset += 1; /* Skip Word Count (WCT) */
2552
2553     /* Build display for: AndXCommand */
2554
2555     AndXCommand = GBYTE(pd, offset);
2556
2557     if (tree) {
2558
2559       proto_tree_add_text(tree, offset, 1, "AndXCommand: %u", AndXCommand);
2560
2561     }
2562
2563     offset += 1; /* Skip AndXCommand */
2564
2565     /* Build display for: AndXReserved */
2566
2567     AndXReserved = GBYTE(pd, offset);
2568
2569     if (tree) {
2570
2571       proto_tree_add_text(tree, offset, 1, "AndXReserved: %u", AndXReserved);
2572
2573     }
2574
2575     offset += 1; /* Skip AndXReserved */
2576
2577     /* Build display for: AndXOffset */
2578
2579     AndXOffset = GSHORT(pd, offset);
2580
2581     if (tree) {
2582
2583       proto_tree_add_text(tree, offset, 2, "AndXOffset: %u", AndXOffset);
2584
2585     }
2586
2587     offset += 2; /* Skip AndXOffset */
2588
2589     /* Build display for: FID */
2590
2591     FID = GSHORT(pd, offset);
2592
2593     if (tree) {
2594
2595       proto_tree_add_text(tree, offset, 2, "FID: %u", FID);
2596
2597     }
2598
2599     offset += 2; /* Skip FID */
2600
2601     /* Build display for: FileAttributes */
2602
2603     FileAttributes = GSHORT(pd, offset);
2604
2605     if (tree) {
2606
2607       ti = proto_tree_add_text(tree, offset, 2, "FileAttributes: 0x%02x", FileAttributes);
2608       FileAttributes_tree = proto_item_add_subtree(ti, ETT_SMB_FILEATTRIBUTES);
2609       proto_tree_add_text(FileAttributes_tree, offset, 2, "%s",
2610                           decode_boolean_bitfield(FileAttributes, 0x01, 16, "Read only file", "Not a read only file"));
2611       proto_tree_add_text(FileAttributes_tree, offset, 2, "%s",
2612                           decode_boolean_bitfield(FileAttributes, 0x02, 16, "Hidden file", "Not a hidden file"));
2613       proto_tree_add_text(FileAttributes_tree, offset, 2, "%s",
2614                           decode_boolean_bitfield(FileAttributes, 0x04, 16, "System file", "Not a system file"));
2615       proto_tree_add_text(FileAttributes_tree, offset, 2, "%s",
2616                           decode_boolean_bitfield(FileAttributes, 0x08, 16, " Volume", "Not a volume"));
2617       proto_tree_add_text(FileAttributes_tree, offset, 2, "%s",
2618                           decode_boolean_bitfield(FileAttributes, 0x10, 16, " Directory", "Not a directory"));
2619       proto_tree_add_text(FileAttributes_tree, offset, 2, "%s",
2620                           decode_boolean_bitfield(FileAttributes, 0x20, 16, "Archive file", "Do not archive file"));
2621     
2622 }
2623
2624     offset += 2; /* Skip FileAttributes */
2625
2626     /* Build display for: Last Write Time */
2627
2628     LastWriteTime = GSHORT(pd, offset);
2629
2630     if (tree) {
2631
2632       proto_tree_add_text(tree, offset, 2, "Last Write Time: %s", dissect_dos_time(LastWriteTime));
2633
2634     }
2635
2636     offset += 2; /* Skip Last Write Time */
2637
2638     /* Build display for: Last Write Date */
2639
2640     LastWriteDate = GSHORT(pd, offset);
2641
2642     if (tree) {
2643
2644       proto_tree_add_text(tree, offset, 2, "Last Write Date: %s", dissect_dos_date(LastWriteDate));
2645
2646     }
2647
2648     offset += 2; /* Skip Last Write Date */
2649
2650     /* Build display for: Data Size */
2651
2652     DataSize = GWORD(pd, offset);
2653
2654     if (tree) {
2655
2656       proto_tree_add_text(tree, offset, 4, "Data Size: %u", DataSize);
2657
2658     }
2659
2660     offset += 4; /* Skip Data Size */
2661
2662     /* Build display for: Granted Access */
2663
2664     GrantedAccess = GSHORT(pd, offset);
2665
2666     if (tree) {
2667
2668       proto_tree_add_text(tree, offset, 2, "Granted Access: %u", GrantedAccess);
2669
2670     }
2671
2672     offset += 2; /* Skip Granted Access */
2673
2674     /* Build display for: File Type */
2675
2676     FileType = GSHORT(pd, offset);
2677
2678     if (tree) {
2679
2680       ti = proto_tree_add_text(tree, offset, 2, "File Type: 0x%02x", FileType);
2681       FileType_tree = proto_item_add_subtree(ti, ETT_SMB_FILETYPE);
2682       proto_tree_add_text(FileType_tree, offset, 2, "%s",
2683                           decode_enumerated_bitfield(FileType, 0xFFFF, 16, FileType_0xFFFF, "%s"));
2684     
2685 }
2686
2687     offset += 2; /* Skip File Type */
2688
2689     /* Build display for: Device State */
2690
2691     DeviceState = GSHORT(pd, offset);
2692
2693     if (tree) {
2694
2695       proto_tree_add_text(tree, offset, 2, "Device State: %u", DeviceState);
2696
2697     }
2698
2699     offset += 2; /* Skip Device State */
2700
2701     /* Build display for: Action */
2702
2703     Action = GSHORT(pd, offset);
2704
2705     if (tree) {
2706
2707       ti = proto_tree_add_text(tree, offset, 2, "Action: 0x%02x", Action);
2708       Action_tree = proto_item_add_subtree(ti, ETT_SMB_ACTION);
2709       proto_tree_add_text(Action_tree, offset, 2, "%s",
2710                           decode_enumerated_bitfield(Action, 0x8000, 16, Action_0x8000, "%s"));
2711       proto_tree_add_text(Action_tree, offset, 2, "%s",
2712                           decode_enumerated_bitfield(Action, 0x0003, 16, Action_0x0003, "%s"));
2713     
2714 }
2715
2716     offset += 2; /* Skip Action */
2717
2718     /* Build display for: Server FID */
2719
2720     ServerFID = GWORD(pd, offset);
2721
2722     if (tree) {
2723
2724       proto_tree_add_text(tree, offset, 4, "Server FID: %u", ServerFID);
2725
2726     }
2727
2728     offset += 4; /* Skip Server FID */
2729
2730     /* Build display for: Reserved */
2731
2732     Reserved = GSHORT(pd, offset);
2733
2734     if (tree) {
2735
2736       proto_tree_add_text(tree, offset, 2, "Reserved: %u", Reserved);
2737
2738     }
2739
2740     offset += 2; /* Skip Reserved */
2741
2742     /* Build display for: Byte Count */
2743
2744     ByteCount = GSHORT(pd, offset);
2745
2746     if (tree) {
2747
2748       proto_tree_add_text(tree, offset, 2, "Byte Count: %u", ByteCount);
2749
2750     }
2751
2752     offset += 2; /* Skip Byte Count */
2753
2754
2755     if (AndXCommand != 0xFF) {
2756
2757       (dissect[AndXCommand])(pd, offset, fd, tree, max_data, dirn);
2758
2759     }
2760
2761   }
2762
2763 }
2764
2765 void (*dissect[256])(const u_char *, int, frame_data *, proto_tree *, int, int) = {
2766
2767   dissect_unknown_smb,      /* unknown SMB 0x00 */
2768   dissect_unknown_smb,      /* unknown SMB 0x01 */
2769   dissect_unknown_smb,      /* SMBopen open a file */
2770   dissect_unknown_smb,      /* SMBcreate create a file */
2771   dissect_unknown_smb,      /* SMBclose close a file */
2772   dissect_unknown_smb,      /* SMBflush flush a file */
2773   dissect_unknown_smb,      /* SMBunlink delete a file */
2774   dissect_unknown_smb,      /* SMBmv rename a file */
2775   dissect_unknown_smb,      /* SMBgetatr get file attributes */
2776   dissect_unknown_smb,      /* SMBsetatr set file attributes */
2777   dissect_unknown_smb,      /* SMBread read from a file */
2778   dissect_unknown_smb,      /* SMBwrite write to a file */
2779   dissect_unknown_smb,      /* SMBlock lock a byte range */
2780   dissect_unknown_smb,      /* SMBunlock unlock a byte range */
2781   dissect_unknown_smb,      /* SMBctemp create a temporary file */
2782   dissect_unknown_smb,      /* SMBmknew make a new file */
2783   dissect_unknown_smb,      /* SMBchkpth check a directory path */
2784   dissect_unknown_smb,      /* SMBexit process exit */
2785   dissect_unknown_smb,      /* SMBlseek seek */
2786   dissect_unknown_smb,      /* SMBlockread Lock a range and read it */
2787   dissect_unknown_smb,      /* SMBwriteunlock Unlock a range and then write */
2788   dissect_unknown_smb,      /* unknown SMB 0x15 */
2789   dissect_unknown_smb,      /* unknown SMB 0x16 */
2790   dissect_unknown_smb,      /* unknown SMB 0x17 */
2791   dissect_unknown_smb,      /* unknown SMB 0x18 */
2792   dissect_unknown_smb,      /* unknown SMB 0x19 */
2793   dissect_unknown_smb,      /* SMBreadBraw read block raw */
2794   dissect_unknown_smb,      /* SMBreadBmpx read block multiplexed */
2795   dissect_unknown_smb,      /* SMBreadBs read block (secondary response) */
2796   dissect_unknown_smb,      /* SMBwriteBraw write block raw */
2797   dissect_unknown_smb,      /* SMBwriteBmpx write block multiplexed */
2798   dissect_unknown_smb,      /* SMBwriteBs write block (secondary request) */
2799   dissect_unknown_smb,      /* SMBwriteC write complete response */
2800   dissect_unknown_smb,      /* unknown SMB 0x21 */
2801   dissect_unknown_smb,      /* SMBsetattrE set file attributes expanded */
2802   dissect_unknown_smb,      /* SMBgetattrE get file attributes expanded */
2803   dissect_unknown_smb,      /* SMBlockingX lock/unlock byte ranges and X */
2804   dissect_unknown_smb,      /* SMBtrans transaction - name, bytes in/out */
2805   dissect_unknown_smb,      /* SMBtranss transaction (secondary request/response) */
2806   dissect_unknown_smb,      /* SMBioctl IOCTL */
2807   dissect_unknown_smb,      /* SMBioctls IOCTL (secondary request/response) */
2808   dissect_unknown_smb,      /* SMBcopy copy */
2809   dissect_unknown_smb,      /* SMBmove move */
2810   dissect_unknown_smb,      /* SMBecho echo */
2811   dissect_unknown_smb,      /* SMBwriteclose write a file and then close it */
2812   dissect_open_andx_smb,      /* SMBopenX open and X */
2813   dissect_unknown_smb,      /* SMBreadX read and X */
2814   dissect_unknown_smb,      /* SMBwriteX write and X */
2815   dissect_unknown_smb,      /* unknown SMB 0x30 */
2816   dissect_unknown_smb,      /* unknown SMB 0x31 */
2817   dissect_unknown_smb,      /* unknown SMB 0x32 */
2818   dissect_unknown_smb,      /* unknown SMB 0x33 */
2819   dissect_unknown_smb,      /* unknown SMB 0x34 */
2820   dissect_unknown_smb,      /* unknown SMB 0x35 */
2821   dissect_unknown_smb,      /* unknown SMB 0x36 */
2822   dissect_unknown_smb,      /* unknown SMB 0x37 */
2823   dissect_unknown_smb,      /* unknown SMB 0x38 */
2824   dissect_unknown_smb,      /* unknown SMB 0x39 */
2825   dissect_unknown_smb,      /* unknown SMB 0x3a */
2826   dissect_unknown_smb,      /* unknown SMB 0x3b */
2827   dissect_unknown_smb,      /* unknown SMB 0x3c */
2828   dissect_unknown_smb,      /* unknown SMB 0x3d */
2829   dissect_unknown_smb,      /* unknown SMB 0x3e */
2830   dissect_unknown_smb,      /* unknown SMB 0x3f */
2831   dissect_unknown_smb,      /* unknown SMB 0x40 */
2832   dissect_unknown_smb,      /* unknown SMB 0x41 */
2833   dissect_unknown_smb,      /* unknown SMB 0x42 */
2834   dissect_unknown_smb,      /* unknown SMB 0x43 */
2835   dissect_unknown_smb,      /* unknown SMB 0x44 */
2836   dissect_unknown_smb,      /* unknown SMB 0x45 */
2837   dissect_unknown_smb,      /* unknown SMB 0x46 */
2838   dissect_unknown_smb,      /* unknown SMB 0x47 */
2839   dissect_unknown_smb,      /* unknown SMB 0x48 */
2840   dissect_unknown_smb,      /* unknown SMB 0x49 */
2841   dissect_unknown_smb,      /* unknown SMB 0x4a */
2842   dissect_unknown_smb,      /* unknown SMB 0x4b */
2843   dissect_unknown_smb,      /* unknown SMB 0x4c */
2844   dissect_unknown_smb,      /* unknown SMB 0x4d */
2845   dissect_unknown_smb,      /* unknown SMB 0x4e */
2846   dissect_unknown_smb,      /* unknown SMB 0x4f */
2847   dissect_unknown_smb,      /* unknown SMB 0x50 */
2848   dissect_unknown_smb,      /* unknown SMB 0x51 */
2849   dissect_unknown_smb,      /* unknown SMB 0x52 */
2850   dissect_unknown_smb,      /* unknown SMB 0x53 */
2851   dissect_unknown_smb,      /* unknown SMB 0x54 */
2852   dissect_unknown_smb,      /* unknown SMB 0x55 */
2853   dissect_unknown_smb,      /* unknown SMB 0x56 */
2854   dissect_unknown_smb,      /* unknown SMB 0x57 */
2855   dissect_unknown_smb,      /* unknown SMB 0x58 */
2856   dissect_unknown_smb,      /* unknown SMB 0x59 */
2857   dissect_unknown_smb,      /* unknown SMB 0x5a */
2858   dissect_unknown_smb,      /* unknown SMB 0x5b */
2859   dissect_unknown_smb,      /* unknown SMB 0x5c */
2860   dissect_unknown_smb,      /* unknown SMB 0x5d */
2861   dissect_unknown_smb,      /* unknown SMB 0x5e */
2862   dissect_unknown_smb,      /* unknown SMB 0x5f */
2863   dissect_unknown_smb,      /* unknown SMB 0x60 */
2864   dissect_unknown_smb,      /* unknown SMB 0x61 */
2865   dissect_unknown_smb,      /* unknown SMB 0x62 */
2866   dissect_unknown_smb,      /* unknown SMB 0x63 */
2867   dissect_unknown_smb,      /* unknown SMB 0x64 */
2868   dissect_unknown_smb,      /* unknown SMB 0x65 */
2869   dissect_unknown_smb,      /* unknown SMB 0x66 */
2870   dissect_unknown_smb,      /* unknown SMB 0x67 */
2871   dissect_unknown_smb,      /* unknown SMB 0x68 */
2872   dissect_unknown_smb,      /* unknown SMB 0x69 */
2873   dissect_unknown_smb,      /* unknown SMB 0x6a */
2874   dissect_unknown_smb,      /* unknown SMB 0x6b */
2875   dissect_unknown_smb,      /* unknown SMB 0x6c */
2876   dissect_unknown_smb,      /* unknown SMB 0x6d */
2877   dissect_unknown_smb,      /* unknown SMB 0x6e */
2878   dissect_unknown_smb,      /* unknown SMB 0x6f */
2879   dissect_treecon_smb,      /* SMBtcon tree connect */
2880   dissect_unknown_smb,      /* SMBtdis tree disconnect */
2881   dissect_negprot_smb,      /* SMBnegprot negotiate a protocol */
2882   dissect_ssetup_andx_smb,      /* SMBsesssetupX Session Set Up & X (including User Logon) */
2883   dissect_unknown_smb,      /* unknown SMB 0x74 */
2884   dissect_tcon_andx_smb,    /* SMBtconX tree connect and X */
2885   dissect_unknown_smb,      /* unknown SMB 0x76 */
2886   dissect_unknown_smb,      /* unknown SMB 0x77 */
2887   dissect_unknown_smb,      /* unknown SMB 0x78 */
2888   dissect_unknown_smb,      /* unknown SMB 0x79 */
2889   dissect_unknown_smb,      /* unknown SMB 0x7a */
2890   dissect_unknown_smb,      /* unknown SMB 0x7b */
2891   dissect_unknown_smb,      /* unknown SMB 0x7c */
2892   dissect_unknown_smb,      /* unknown SMB 0x7d */
2893   dissect_unknown_smb,      /* unknown SMB 0x7e */
2894   dissect_unknown_smb,      /* unknown SMB 0x7f */
2895   dissect_unknown_smb,      /* SMBdskattr get disk attributes */
2896   dissect_unknown_smb,      /* SMBsearch search a directory */
2897   dissect_unknown_smb,      /* SMBffirst find first */
2898   dissect_unknown_smb,      /* SMBfunique find unique */
2899   dissect_unknown_smb,      /* SMBfclose find close */
2900   dissect_unknown_smb,      /* unknown SMB 0x85 */
2901   dissect_unknown_smb,      /* unknown SMB 0x86 */
2902   dissect_unknown_smb,      /* unknown SMB 0x87 */
2903   dissect_unknown_smb,      /* unknown SMB 0x88 */
2904   dissect_unknown_smb,      /* unknown SMB 0x89 */
2905   dissect_unknown_smb,      /* unknown SMB 0x8a */
2906   dissect_unknown_smb,      /* unknown SMB 0x8b */
2907   dissect_unknown_smb,      /* unknown SMB 0x8c */
2908   dissect_unknown_smb,      /* unknown SMB 0x8d */
2909   dissect_unknown_smb,      /* unknown SMB 0x8e */
2910   dissect_unknown_smb,      /* unknown SMB 0x8f */
2911   dissect_unknown_smb,      /* unknown SMB 0x90 */
2912   dissect_unknown_smb,      /* unknown SMB 0x91 */
2913   dissect_unknown_smb,      /* unknown SMB 0x92 */
2914   dissect_unknown_smb,      /* unknown SMB 0x93 */
2915   dissect_unknown_smb,      /* unknown SMB 0x94 */
2916   dissect_unknown_smb,      /* unknown SMB 0x95 */
2917   dissect_unknown_smb,      /* unknown SMB 0x96 */
2918   dissect_unknown_smb,      /* unknown SMB 0x97 */
2919   dissect_unknown_smb,      /* unknown SMB 0x98 */
2920   dissect_unknown_smb,      /* unknown SMB 0x99 */
2921   dissect_unknown_smb,      /* unknown SMB 0x9a */
2922   dissect_unknown_smb,      /* unknown SMB 0x9b */
2923   dissect_unknown_smb,      /* unknown SMB 0x9c */
2924   dissect_unknown_smb,      /* unknown SMB 0x9d */
2925   dissect_unknown_smb,      /* unknown SMB 0x9e */
2926   dissect_unknown_smb,      /* unknown SMB 0x9f */
2927   dissect_unknown_smb,      /* unknown SMB 0xa0 */
2928   dissect_unknown_smb,      /* unknown SMB 0xa1 */
2929   dissect_unknown_smb,      /* unknown SMB 0xa2 */
2930   dissect_unknown_smb,      /* unknown SMB 0xa3 */
2931   dissect_unknown_smb,      /* unknown SMB 0xa4 */
2932   dissect_unknown_smb,      /* unknown SMB 0xa5 */
2933   dissect_unknown_smb,      /* unknown SMB 0xa6 */
2934   dissect_unknown_smb,      /* unknown SMB 0xa7 */
2935   dissect_unknown_smb,      /* unknown SMB 0xa8 */
2936   dissect_unknown_smb,      /* unknown SMB 0xa9 */
2937   dissect_unknown_smb,      /* unknown SMB 0xaa */
2938   dissect_unknown_smb,      /* unknown SMB 0xab */
2939   dissect_unknown_smb,      /* unknown SMB 0xac */
2940   dissect_unknown_smb,      /* unknown SMB 0xad */
2941   dissect_unknown_smb,      /* unknown SMB 0xae */
2942   dissect_unknown_smb,      /* unknown SMB 0xaf */
2943   dissect_unknown_smb,      /* unknown SMB 0xb0 */
2944   dissect_unknown_smb,      /* unknown SMB 0xb1 */
2945   dissect_unknown_smb,      /* unknown SMB 0xb2 */
2946   dissect_unknown_smb,      /* unknown SMB 0xb3 */
2947   dissect_unknown_smb,      /* unknown SMB 0xb4 */
2948   dissect_unknown_smb,      /* unknown SMB 0xb5 */
2949   dissect_unknown_smb,      /* unknown SMB 0xb6 */
2950   dissect_unknown_smb,      /* unknown SMB 0xb7 */
2951   dissect_unknown_smb,      /* unknown SMB 0xb8 */
2952   dissect_unknown_smb,      /* unknown SMB 0xb9 */
2953   dissect_unknown_smb,      /* unknown SMB 0xba */
2954   dissect_unknown_smb,      /* unknown SMB 0xbb */
2955   dissect_unknown_smb,      /* unknown SMB 0xbc */
2956   dissect_unknown_smb,      /* unknown SMB 0xbd */
2957   dissect_unknown_smb,      /* unknown SMB 0xbe */
2958   dissect_unknown_smb,      /* unknown SMB 0xbf */
2959   dissect_unknown_smb,      /* SMBsplopen open a print spool file */
2960   dissect_unknown_smb,      /* SMBsplwr write to a print spool file */
2961   dissect_unknown_smb,      /* SMBsplclose close a print spool file */
2962   dissect_unknown_smb,      /* SMBsplretq return print queue */
2963   dissect_unknown_smb,      /* unknown SMB 0xc4 */
2964   dissect_unknown_smb,      /* unknown SMB 0xc5 */
2965   dissect_unknown_smb,      /* unknown SMB 0xc6 */
2966   dissect_unknown_smb,      /* unknown SMB 0xc7 */
2967   dissect_unknown_smb,      /* unknown SMB 0xc8 */
2968   dissect_unknown_smb,      /* unknown SMB 0xc9 */
2969   dissect_unknown_smb,      /* unknown SMB 0xca */
2970   dissect_unknown_smb,      /* unknown SMB 0xcb */
2971   dissect_unknown_smb,      /* unknown SMB 0xcc */
2972   dissect_unknown_smb,      /* unknown SMB 0xcd */
2973   dissect_unknown_smb,      /* unknown SMB 0xce */
2974   dissect_unknown_smb,      /* unknown SMB 0xcf */
2975   dissect_unknown_smb,      /* SMBsends send a single block message */
2976   dissect_unknown_smb,      /* SMBsendb send a broadcast message */
2977   dissect_unknown_smb,      /* SMBfwdname forward user name */
2978   dissect_unknown_smb,      /* SMBcancelf cancel forward */
2979   dissect_unknown_smb,      /* SMBgetmac get a machine name */
2980   dissect_unknown_smb,      /* SMBsendstrt send start of multi-block message */
2981   dissect_unknown_smb,      /* SMBsendend send end of multi-block message */
2982   dissect_unknown_smb,      /* SMBsendtxt send text of multi-block message */
2983   dissect_unknown_smb,      /* unknown SMB 0xd8 */
2984   dissect_unknown_smb,      /* unknown SMB 0xd9 */
2985   dissect_unknown_smb,      /* unknown SMB 0xda */
2986   dissect_unknown_smb,      /* unknown SMB 0xdb */
2987   dissect_unknown_smb,      /* unknown SMB 0xdc */
2988   dissect_unknown_smb,      /* unknown SMB 0xdd */
2989   dissect_unknown_smb,      /* unknown SMB 0xde */
2990   dissect_unknown_smb,      /* unknown SMB 0xdf */
2991   dissect_unknown_smb,      /* unknown SMB 0xe0 */
2992   dissect_unknown_smb,      /* unknown SMB 0xe1 */
2993   dissect_unknown_smb,      /* unknown SMB 0xe2 */
2994   dissect_unknown_smb,      /* unknown SMB 0xe3 */
2995   dissect_unknown_smb,      /* unknown SMB 0xe4 */
2996   dissect_unknown_smb,      /* unknown SMB 0xe5 */
2997   dissect_unknown_smb,      /* unknown SMB 0xe6 */
2998   dissect_unknown_smb,      /* unknown SMB 0xe7 */
2999   dissect_unknown_smb,      /* unknown SMB 0xe8 */
3000   dissect_unknown_smb,      /* unknown SMB 0xe9 */
3001   dissect_unknown_smb,      /* unknown SMB 0xea */
3002   dissect_unknown_smb,      /* unknown SMB 0xeb */
3003   dissect_unknown_smb,      /* unknown SMB 0xec */
3004   dissect_unknown_smb,      /* unknown SMB 0xed */
3005   dissect_unknown_smb,      /* unknown SMB 0xee */
3006   dissect_unknown_smb,      /* unknown SMB 0xef */
3007   dissect_unknown_smb,      /* unknown SMB 0xf0 */
3008   dissect_unknown_smb,      /* unknown SMB 0xf1 */
3009   dissect_unknown_smb,      /* unknown SMB 0xf2 */
3010   dissect_unknown_smb,      /* unknown SMB 0xf3 */
3011   dissect_unknown_smb,      /* unknown SMB 0xf4 */
3012   dissect_unknown_smb,      /* unknown SMB 0xf5 */
3013   dissect_unknown_smb,      /* unknown SMB 0xf6 */
3014   dissect_unknown_smb,      /* unknown SMB 0xf7 */
3015   dissect_unknown_smb,      /* unknown SMB 0xf8 */
3016   dissect_unknown_smb,      /* unknown SMB 0xf9 */
3017   dissect_unknown_smb,      /* unknown SMB 0xfa */
3018   dissect_unknown_smb,      /* unknown SMB 0xfb */
3019   dissect_unknown_smb,      /* unknown SMB 0xfc */
3020   dissect_unknown_smb,      /* unknown SMB 0xfd */
3021   dissect_unknown_smb,      /* SMBinvalid invalid command */
3022   dissect_unknown_smb       /* unknown SMB 0xff */
3023
3024 };
3025
3026 static const value_string errcls_types[] = {
3027   { SMB_SUCCESS, "Success"},
3028   { SMB_ERRDOS, "DOS Error"},
3029   { SMB_ERRSRV, "Server Error"},
3030   { SMB_ERRHRD, "Hardware Error"},
3031   { SMB_ERRCMD, "Command Error - Not an SMB format command"},
3032   { 0, 0}
3033 };
3034
3035 char *decode_smb_name(unsigned char cmd)
3036 {
3037
3038   return(SMB_names[cmd]);
3039
3040 }
3041
3042 static const value_string DOS_errors[] = {
3043   {SMBE_badfunc, "Invalid function (or system call)"},
3044   {SMBE_badfile, "File not found (pathname error)"},
3045   {SMBE_badpath, "Directory not found"},
3046   {SMBE_nofids, "Too many open files"},
3047   {SMBE_noaccess, "Access denied"},
3048   {SMBE_badfid, "Invalid fid"},
3049   {SMBE_nomem,  "Out of memory"},
3050   {SMBE_badmem, "Invalid memory block address"},
3051   {SMBE_badenv, "Invalid environment"},
3052   {SMBE_badaccess, "Invalid open mode"},
3053   {SMBE_baddata, "Invalid data (only from ioctl call)"},
3054   {SMBE_res, "Reserved error code?"}, 
3055   {SMBE_baddrive, "Invalid drive"},
3056   {SMBE_remcd, "Attempt to delete current directory"},
3057   {SMBE_diffdevice, "Rename/move across different filesystems"},
3058   {SMBE_nofiles, "no more files found in file search"},
3059   {SMBE_badshare, "Share mode on file conflict with open mode"},
3060   {SMBE_lock, "Lock request conflicts with existing lock"},
3061   {SMBE_unsup, "Request unsupported, returned by Win 95"},
3062   {SMBE_filexists, "File in operation already exists"},
3063   {SMBE_cannotopen, "Cannot open the file specified"},
3064   {SMBE_unknownlevel, "Unknown level??"},
3065   {SMBE_badpipe, "Named pipe invalid"},
3066   {SMBE_pipebusy, "All instances of pipe are busy"},
3067   {SMBE_pipeclosing, "Named pipe close in progress"},
3068   {SMBE_notconnected, "No process on other end of named pipe"},
3069   {SMBE_moredata, "More data to be returned"},
3070   {SMBE_baddirectory,  "Invalid directory name in a path."},
3071   {SMBE_eas_didnt_fit, "Extended attributes didn't fit"},
3072   {SMBE_eas_nsup, "Extended attributes not supported"},
3073   {SMBE_notify_buf_small, "Buffer too small to return change notify."},
3074   {SMBE_unknownipc, "Unknown IPC Operation"},
3075   {SMBE_noipc, "Don't support ipc"},
3076   {0, 0}
3077   };
3078
3079 /* Error codes for the ERRSRV class */
3080
3081 static const value_string SRV_errors[] = {
3082   {SMBE_error, "Non specific error code"},
3083   {SMBE_badpw, "Bad password"},
3084   {SMBE_badtype, "Reserved"},
3085   {SMBE_access, "No permissions to perform the requested operation"},
3086   {SMBE_invnid, "TID invalid"},
3087   {SMBE_invnetname, "Invalid servername"},
3088   {SMBE_invdevice, "Invalid device"},
3089   {SMBE_unknownsmb, "Unknown SMB, from NT 3.5 response"},
3090   {SMBE_qfull, "Print queue full"},
3091   {SMBE_qtoobig, "Queued item too big"},
3092   {SMBE_qeof, "EOF on print queue dump"},
3093   {SMBE_invpfid, "Invalid print file in smb_fid"},
3094   {SMBE_smbcmd, "Unrecognised command"},
3095   {SMBE_srverror, "SMB server internal error"},
3096   {SMBE_filespecs, "Fid and pathname invalid combination"},
3097   {SMBE_badlink, "Bad link in request ???"},
3098   {SMBE_badpermits, "Access specified for a file is not valid"},
3099   {SMBE_badpid, "Bad process id in request"},
3100   {SMBE_setattrmode, "Attribute mode invalid"},
3101   {SMBE_paused, "Message server paused"},
3102   {SMBE_msgoff, "Not receiving messages"},
3103   {SMBE_noroom, "No room for message"},
3104   {SMBE_rmuns, "Too many remote usernames"},
3105   {SMBE_timeout, "Operation timed out"},
3106   {SMBE_noresource, "No resources currently available for request."},
3107   {SMBE_toomanyuids, "Too many userids"},
3108   {SMBE_baduid, "Bad userid"},
3109   {SMBE_useMPX, "Temporarily unable to use raw mode, use MPX mode"},
3110   {SMBE_useSTD, "Temporarily unable to use raw mode, use standard mode"},
3111   {SMBE_contMPX, "Resume MPX mode"},
3112   {SMBE_badPW, "Bad Password???"},
3113   {SMBE_nosupport, "Operation not supported???"},
3114   { 0, 0}
3115 };
3116
3117 /* Error codes for the ERRHRD class */
3118
3119 static const value_string HRD_errors[] = {
3120   {SMBE_nowrite, "read only media"},
3121   {SMBE_badunit, "Unknown device"},
3122   {SMBE_notready, "Drive not ready"},
3123   {SMBE_badcmd, "Unknown command"},
3124   {SMBE_data, "Data (CRC) error"},
3125   {SMBE_badreq, "Bad request structure length"},
3126   {SMBE_seek, "Seek error???"},
3127   {SMBE_badmedia, "Bad media???"},
3128   {SMBE_badsector, "Bad sector???"},
3129   {SMBE_nopaper, "No paper in printer???"},
3130   {SMBE_write, "Write error???"},
3131   {SMBE_read, "Read error???"},
3132   {SMBE_general, "General error???"},
3133   {SMBE_badshare, "A open conflicts with an existing open"},
3134   {SMBE_lock, "Lock/unlock error"},
3135   {SMBE_wrongdisk,  "Wrong disk???"},
3136   {SMBE_FCBunavail, "FCB unavailable???"},
3137   {SMBE_sharebufexc, "Share buffer excluded???"},
3138   {SMBE_diskfull, "Disk full???"},
3139   {0, 0}
3140 };
3141
3142 char *decode_smb_error(guint8 errcls, guint8 errcode)
3143 {
3144
3145   switch (errcls) {
3146
3147   case SMB_SUCCESS:
3148
3149     return("No Error");   /* No error ??? */
3150     break;
3151
3152   case SMB_ERRDOS:
3153
3154     return(val_to_str(errcode, DOS_errors, "Unknown DOS error (%x)"));
3155     break;
3156
3157   case SMB_ERRSRV:
3158
3159     return(val_to_str(errcode, SRV_errors, "Unknown SRV error (%x)"));
3160     break;
3161
3162   case SMB_ERRHRD:
3163
3164     return(val_to_str(errcode, HRD_errors, "Unknown HRD error (%x)"));
3165     break;
3166
3167   default:
3168
3169     return("Unknown error class!");
3170
3171   }
3172
3173 }
3174
3175 #define SMB_FLAGS_DIRN 0x80
3176
3177 void
3178 dissect_smb(const u_char *pd, int offset, frame_data *fd, proto_tree *tree, int max_data)
3179 {
3180         proto_tree      *smb_tree = tree, *flags_tree, *flags2_tree;
3181         proto_item      *ti, *tf;
3182         guint8          cmd, errcls, errcode1, flags;
3183         guint16         flags2, errcode, tid, pid, uid, mid;
3184
3185         cmd = pd[offset + SMB_hdr_com_offset];
3186
3187         if (check_col(fd, COL_PROTOCOL))
3188                 col_add_str(fd, COL_PROTOCOL, "SMB");
3189
3190         /* Hmmm, poor coding here ... Also, should check the type */
3191
3192         if (check_col(fd, COL_INFO)) {
3193
3194           col_add_fstr(fd, COL_INFO, "%s %s", decode_smb_name(cmd), (pi.match_port == pi.destport)? "Request" : "Response");
3195
3196         }
3197
3198         if (tree) {
3199
3200           ti = proto_tree_add_text(tree, offset, END_OF_FRAME,
3201                                 "Server Message Block Protocol");
3202           smb_tree = proto_item_add_subtree(ti, ETT_SMB);
3203
3204           /* 0xFFSMB is actually a 1 byte msg type and 3 byte server
3205            * component ... SMB is only one used
3206            */
3207
3208           proto_tree_add_text(smb_tree, offset, 1, "Message Type: 0xFF");
3209           proto_tree_add_text(smb_tree, offset+1, 3, "Server Component: SMB");
3210
3211         }
3212
3213         offset += 4;  /* Skip the marker */
3214
3215         if (tree) {
3216
3217           proto_tree_add_text(smb_tree, offset, 1, "Command: %s", decode_smb_name(cmd));
3218
3219         }
3220
3221         offset += 1;
3222
3223         /* Next, look at the error class, SMB_RETCLASS */
3224
3225         errcls = pd[offset];
3226
3227         if (tree) {
3228
3229           proto_tree_add_text(smb_tree, offset, 1, "Error Class: %s", 
3230                               val_to_str((guint8)pd[offset], errcls_types, "Unknown Error Class (%x)"));
3231         }
3232
3233         offset += 1;
3234
3235         /* Error code, SMB_HEINFO ... */
3236
3237         errcode1 = pd[offset];
3238
3239         if (tree) {
3240
3241           proto_tree_add_text(smb_tree, offset, 1, "Reserved: %i", errcode1); 
3242
3243         }
3244
3245         offset += 1;
3246
3247         errcode = GSHORT(pd, offset); 
3248
3249         if (tree) {
3250
3251           proto_tree_add_text(smb_tree, offset, 2, "Error Code: %s",
3252                               decode_smb_error(errcls, errcode));
3253
3254         }
3255
3256         offset += 2;
3257
3258         /* Now for the flags: Bit 0 = 0 means cmd, 0 = 1 means resp */
3259
3260         flags = pd[offset];
3261
3262         if (tree) {
3263
3264           tf = proto_tree_add_text(smb_tree, offset, 1, "Flags: 0x%02x", flags);
3265
3266           flags_tree = proto_item_add_subtree(tf, ETT_SMB_FLAGS);
3267           proto_tree_add_text(flags_tree, offset, 1, "%s",
3268                               decode_boolean_bitfield(flags, 0x01, 8,
3269                                                       "Lock&Read, Write&Unlock supported",
3270                                                       "Lock&Read, Write&Unlock not supported"));
3271           proto_tree_add_text(flags_tree, offset, 1, "%s",
3272                               decode_boolean_bitfield(flags, 0x02, 8,
3273                                                       "Receive buffer posted",
3274                                                       "Receive buffer not posted"));
3275           proto_tree_add_text(flags_tree, offset, 1, "%s",
3276                               decode_boolean_bitfield(flags, 0x08, 8, 
3277                                                       "Path names caseless",
3278                                                       "Path names case sensitive"));
3279           proto_tree_add_text(flags_tree, offset, 1, "%s",
3280                               decode_boolean_bitfield(flags, 0x10, 8,
3281                                                       "Pathnames canonicalized",
3282                                                       "Pathnames not canonicalized"));
3283           proto_tree_add_text(flags_tree, offset, 1, "%s",
3284                               decode_boolean_bitfield(flags, 0x20, 8,
3285                                                       "OpLocks requested/granted",
3286                                                       "OpLocks not requested/granted"));
3287           proto_tree_add_text(flags_tree, offset, 1, "%s",
3288                               decode_boolean_bitfield(flags, 0x40, 8, 
3289                                                       "Notify all",
3290                                                       "Notify open only"));
3291
3292           proto_tree_add_text(flags_tree, offset, 1, "%s",
3293                               decode_boolean_bitfield(flags, SMB_FLAGS_DIRN,
3294                                                       8, "Response to client/redirector", "Request to server"));
3295
3296         }
3297
3298         offset += 1;
3299
3300         flags2 = GSHORT(pd, offset);
3301
3302         if (tree) {
3303
3304           tf = proto_tree_add_text(smb_tree, offset, 1, "Flags2: 0x%04x", flags2);
3305
3306           flags2_tree = proto_item_add_subtree(tf, ETT_SMB_FLAGS2);
3307           proto_tree_add_text(flags2_tree, offset, 1, "%s",
3308                               decode_boolean_bitfield(flags2, 0x0001, 16,
3309                                                       "Long file names supported",
3310                                                       "Long file names not supported"));
3311           proto_tree_add_text(flags2_tree, offset, 1, "%s",
3312                               decode_boolean_bitfield(flags2, 0x0002, 16,
3313                                                       "Extended attributes supported",
3314                                                       "Extended attributes not supported"));
3315           proto_tree_add_text(flags2_tree, offset, 1, "%s",
3316                               decode_boolean_bitfield(flags2, 0x0004, 16,
3317                                                       "Security signatures supported",
3318                                                       "Security signatures not supported"));
3319           proto_tree_add_text(flags2_tree, offset, 1, "%s",
3320                               decode_boolean_bitfield(flags2, 0x0800, 16,
3321                                                       "Extended security negotiation supported",
3322                                                       "Extended security negotiation not supported"));
3323           proto_tree_add_text(flags2_tree, offset, 1, "%s",
3324                               decode_boolean_bitfield(flags2, 0x1000, 16, 
3325                                                       "Resolve pathnames with DFS",
3326                                                       "Don't resolve pathnames with DFS"));
3327           proto_tree_add_text(flags2_tree, offset, 1, "%s",
3328                               decode_boolean_bitfield(flags2, 0x2000, 16,
3329                                                       "Permit reads if execute-only",
3330                                                       "Don't permit reads if execute-only"));
3331           proto_tree_add_text(flags2_tree, offset, 1, "%s",
3332                               decode_boolean_bitfield(flags2, 0x4000, 16,
3333                                                       "Error codes are NT error codes",
3334                                                       "Error codes are DOS error codes"));
3335           proto_tree_add_text(flags2_tree, offset, 1, "%s",
3336                               decode_boolean_bitfield(flags2, 0x8000, 16, 
3337                                                       "Strings are Unicode",
3338                                                       "Strings are ASCII"));
3339
3340         }
3341
3342         offset += 2;
3343
3344         if (tree) {
3345
3346           proto_tree_add_text(smb_tree, offset, 12, "Reserved: 6 WORDS");
3347
3348         }
3349
3350         offset += 12;
3351
3352         /* Now the TID, tree ID */
3353
3354         tid = GSHORT(pd, offset);
3355
3356         if (tree) {
3357
3358           proto_tree_add_text(smb_tree, offset, 2, "Network Path/Tree ID (TID): %i (%04x)", tid, tid); 
3359
3360         }
3361
3362         offset += 2;
3363
3364         /* Now the PID, Process ID */
3365
3366         pid = GSHORT(pd, offset);
3367
3368         if (tree) {
3369
3370           proto_tree_add_text(smb_tree, offset, 2, "Process ID (PID): %i (%04x)", pid, pid); 
3371
3372         }
3373
3374         offset += 2;
3375
3376         /* Now the UID, User ID */
3377
3378         uid = GSHORT(pd, offset);
3379
3380         if (tree) {
3381
3382           proto_tree_add_text(smb_tree, offset, 2, "User ID (UID): %i (%04x)", uid, uid); 
3383
3384         }
3385         
3386         offset += 2;
3387
3388         /* Now the MID, Multiplex ID */
3389
3390         mid = GSHORT(pd, offset);
3391
3392         if (tree) {
3393
3394           proto_tree_add_text(smb_tree, offset, 2, "Multiplex ID (MID): %i (%04x)", mid, mid); 
3395
3396         }
3397
3398         offset += 2;
3399
3400         /* Now vector through the table to dissect them */
3401
3402         (dissect[cmd])(pd, offset, fd, smb_tree, max_data, 
3403                        ((flags & 0x80) == 0));
3404
3405
3406 }