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