Give the IPX dissector dissector hash tables for the IPX type and socket
[obnox/wireshark/wip.git] / packet-smb-browse.c
1 /* packet-smb-browse.c
2  * Routines for smb packet dissection
3  * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
4  *
5  * $Id: packet-smb-browse.c,v 1.3 2000/05/11 08:15:44 gram Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@zing.org>
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 <time.h>
43 #include <string.h>
44 #include <glib.h>
45 #include <ctype.h>
46 #include "packet.h"
47 #include "conversation.h"
48 #include "smb.h"
49 #include "alignment.h"
50
51 static int proto_smb_browse = -1;
52
53 static gint ett_browse = -1;
54 static gint ett_browse_flags = -1;
55 static gint ett_browse_election_criteria = -1;
56 static gint ett_browse_election_os = -1;
57 static gint ett_browse_election_desire = -1;
58
59
60
61 char *browse_commands[] = 
62 { "Error, No such command!",       /* Value 0 */
63   "Host Announcement",             /* Value 1 */
64   "Request Announcement",          /* Value 2 */
65   "Error, No such command!",       /* Value 3 */
66   "Error, No such command!",       /* Value 4 */
67   "Error, No such command!",       /* Value 5 */
68   "Error, No such command!",       /* Value 6 */
69   "Error, No such command!",       /* Value 7 */
70   "Browser Election Request",      /* Value 8 */
71   "Get Backup List Request",       /* Value 9 */
72   "Get Backup List Response",      /* Value 10 */
73   "Become Backup Browser",         /* Value 11 */
74   "Domain/Workgroup Announcement", /* Value 12 */
75   "Master Announcement",           /* Value 13 */
76   "Error! No such command",        /* Value 14 */
77   "Local Master Announcement"      /* Value 15 */
78 };
79
80 #define HOST_ANNOUNCE        1
81 #define REQUEST_ANNOUNCE     2
82 #define BROWSER_ELECTION     8
83 #define GETBACKUPLISTREQ     9
84 #define GETBACKUPLISTRESP   10
85 #define BECOMEBACKUPBROWSER 11
86 #define DOMAINANNOUNCEMENT  12
87 #define MASTERANNOUNCEMENT  13
88 #define LOCALMASTERANNOUNC  15
89
90 char *svr_types[32] = {
91   "Workstation",
92   "Server",
93   "SQL Server",
94   "Domain Controller",
95   "Backup Controller",
96   "Time Source",
97   "Apple Server",
98   "Novell Server",
99   "Domain Member Server",
100   "Print Queue Server",
101   "Dialin Server",
102   "Xenix Server",
103   "NT Workstation",
104   "Windows for Workgroups",
105   "Unknown Server - FIXME",
106   "NT Server",
107   "Potential Browser",
108   "Backup Browser",
109   "Master Browser",
110   "Domain Master Browser",
111   "OSF",
112   "VMS",
113   "Windows 95 or above",
114   "Unused",
115   "Unused",
116   "Unused",
117   "Unused",
118   "Unused",
119   "Unused",
120   "Unused",
121   "Local List Only",
122   "Domain Enum"
123 };
124
125 guint32 
126 dissect_mailslot_browse(const u_char *pd, int offset, frame_data *fd, proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data, int SMB_offset, int errcode, int dirn, const u_char *command, int DataOffset, int DataCount)
127 {
128   guint8               OpCode;
129   guint8               UpdateCount;
130   guint8               VersionMajor;
131   guint8               VersionMinor;
132   guint32              Periodicity;
133   guint32              ServerType;
134   guint16              SigConstant;
135   guint32              Token;
136   guint8               BackupServerCount;
137   guint8               Flags;
138   guint32              MBZ;
139   guint8               ElectionVersion;
140   guint32              ElectionCriteria;
141   guint8               ElectionOS;
142   guint8               ElectionDesire;
143   guint16              ElectionRevision;
144   guint32              ServerUpTime;
145   const char           *ServerName;
146   const char           *ServerComment;
147   proto_tree           *browse_tree = NULL, *flags_tree = NULL, 
148                        *OSflags = NULL, *DesireFlags = NULL;
149   proto_item           *ti, *ec;
150   guint32              loc_offset = DataOffset, count = 0;
151   int                  i;
152
153   if (check_col(fd, COL_PROTOCOL))
154     col_add_str(fd, COL_PROTOCOL, "BROWSER");
155
156   if (check_col(fd, COL_INFO)) /* Put in something, and replace it later */
157     col_add_str(fd, COL_INFO, "Browse Announcement");
158
159   /*
160    * Now, decode the browse request 
161    */
162
163   OpCode = GBYTE(pd, loc_offset);
164
165   if (check_col(fd, COL_INFO))
166     col_add_fstr(fd, COL_INFO, (OpCode > (sizeof(browse_commands)/sizeof(char *))) ? "Error, No Such Command:%u" : browse_commands[OpCode], OpCode);
167     
168   if (tree) {  /* Add the browse tree */
169
170     ti = proto_tree_add_item(parent, proto_smb_browse, NullTVB, DataOffset, DataCount, NULL);
171     browse_tree = proto_item_add_subtree(ti, ett_browse);
172
173     proto_tree_add_text(browse_tree, NullTVB, loc_offset, 1, "OpCode: %s", (OpCode > (sizeof(browse_commands)/sizeof(char *))) ? "Error, No Such Command" : browse_commands[OpCode]);
174
175   }
176
177   loc_offset += 1;    /* Skip the OpCode */
178
179   switch (OpCode) {
180
181   case DOMAINANNOUNCEMENT:
182   case LOCALMASTERANNOUNC:
183   case HOST_ANNOUNCE:
184
185     UpdateCount = GBYTE(pd, loc_offset);
186
187     if (tree) {
188
189       proto_tree_add_text(browse_tree, NullTVB, loc_offset, 1, "Update Count: %u", UpdateCount);
190
191     }
192
193     loc_offset += 1;  /* Skip the Update Count */
194
195     Periodicity = GWORD(pd, loc_offset);
196
197     if (tree) {
198
199       proto_tree_add_text(browse_tree, NullTVB, loc_offset, 4, "Update Periodicity: %u Sec", Periodicity/1000 );
200
201     }
202
203     loc_offset += 4;
204
205     ServerName = pd + loc_offset;
206
207     if (check_col(fd, COL_INFO)) {
208
209       col_append_fstr(fd, COL_INFO, " %s", ServerName);
210
211     }
212
213     if (tree) {
214
215       proto_tree_add_text(browse_tree, NullTVB, loc_offset, 16, (OpCode == DOMAINANNOUNCEMENT) ? "Domain/WorkGroup: %s": "Host Name: %s", ServerName);
216
217     }
218
219     loc_offset += 16;
220
221     VersionMajor = GBYTE(pd, loc_offset);
222
223     if (tree) {
224
225       proto_tree_add_text(browse_tree, NullTVB, loc_offset, 1, "Major Version: %u", VersionMajor);
226
227     }
228
229     loc_offset += 1;
230
231     VersionMinor = GBYTE(pd, loc_offset);
232
233     if (tree) {
234
235       proto_tree_add_text(browse_tree, NullTVB, loc_offset, 1, "Minor Version: %u", VersionMinor);
236
237     }
238
239     loc_offset += 1;
240
241     ServerType = GWORD(pd, loc_offset);
242
243     if (check_col(fd, COL_INFO)) {
244
245       /* Append the type(s) of the system to the COL_INFO line ... */
246
247       for (i = 0; i < 32; i++) {
248
249         if (ServerType & (1 << i) && (strcmp("Unused", svr_types[i]) != 0))
250             col_append_fstr(fd, COL_INFO, ", %s", svr_types[i]);
251         
252       }
253       
254     }
255
256     if (tree) {
257
258       ti = proto_tree_add_text(browse_tree, NullTVB, loc_offset, 4, "Server Type: 0x%04x", ServerType);
259       flags_tree = proto_item_add_subtree(ti, ett_browse_flags);
260       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
261                           decode_boolean_bitfield(ServerType, 0x0001, 32, "Workstation", "Not Workstation"));
262       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
263                           decode_boolean_bitfield(ServerType, 0x0002, 32, "Server", "Not Server"));
264       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
265                           decode_boolean_bitfield(ServerType, 0x0004, 32, "SQL Server", "Not SQL Server"));
266       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
267                           decode_boolean_bitfield(ServerType, 0x0008, 32, "Domain Controller", "Not Domain Controller"));
268       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
269                           decode_boolean_bitfield(ServerType, 0x0010, 32, "Backup Controller", "Not Backup Controller"));
270       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
271                           decode_boolean_bitfield(ServerType, 0x0020, 32, "Time Source", "Not Time Source"));
272       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
273                           decode_boolean_bitfield(ServerType, 0x0040, 32, "Apple Server", "Not Apple Server"));
274       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
275                           decode_boolean_bitfield(ServerType, 0x0080, 32, "Novell Server", "Not Novell Server"));
276       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
277                           decode_boolean_bitfield(ServerType, 0x0100, 32, "Domain Member Server", "Not Domain Member Server"));
278       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
279                           decode_boolean_bitfield(ServerType, 0x0200, 32, "Print Queue Server", "Not Print Queue Server"));      
280       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
281                           decode_boolean_bitfield(ServerType, 0x0400, 32, "Dialin Server", "Not Dialin Server"));
282       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
283                           decode_boolean_bitfield(ServerType, 0x0800, 32, "Xenix Server", "Not Xenix Server"));
284       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
285                           decode_boolean_bitfield(ServerType, 0x1000, 32, "NT Workstation", "Not NT Workstation"));
286       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
287                           decode_boolean_bitfield(ServerType, 0x2000, 32, "Windows for Workgroups", "Not Windows for Workgroups"));
288       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
289                           decode_boolean_bitfield(ServerType, 0x8000, 32, "NT Server", "Not NT Server"));
290       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
291                           decode_boolean_bitfield(ServerType, 0x10000, 32, "Potential Browser", "Not Potential Browser"));
292       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
293                           decode_boolean_bitfield(ServerType, 0x20000, 32, "Backup Browser", "Not Backup Browser"));
294       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
295                           decode_boolean_bitfield(ServerType, 0x40000, 32, "Master Browser", "Not Master Browser"));
296       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
297                           decode_boolean_bitfield(ServerType, 0x80000, 32, "Domain Master Browser", "Not Domain Master Browser"));
298       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
299                           decode_boolean_bitfield(ServerType, 0x100000, 32, "OSF", "Not OSF"));
300       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
301                           decode_boolean_bitfield(ServerType, 0x200000, 32, "VMS", "Not VMS"));
302       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
303                           decode_boolean_bitfield(ServerType, 0x400000, 32, "Windows 95 or above", "Not Windows 95 or above"));
304       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
305                           decode_boolean_bitfield(ServerType, 0x40000000, 32, "Local List Only", "Not Local List Only"));
306       proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
307                           decode_boolean_bitfield(ServerType, 0x80000000, 32, "Domain Enum", "Not Domain Enum"));
308     }
309     loc_offset += 4;
310     
311     ElectionVersion = GSHORT(pd, loc_offset);
312     
313     if (tree) {
314       
315       proto_tree_add_text(browse_tree, NullTVB, loc_offset, 2, "Election Version: %u", ElectionVersion);
316
317     }
318
319     loc_offset += 2;
320
321     SigConstant = GSHORT(pd, loc_offset);
322
323     if (tree) {
324
325       proto_tree_add_text(browse_tree, NullTVB, loc_offset, 2, "Signature: %u (0x%04X)", SigConstant, SigConstant);
326
327     }
328
329     loc_offset += 2;
330
331     ServerComment = pd + loc_offset;
332
333     if (tree) {
334
335       proto_tree_add_text(browse_tree, NullTVB, loc_offset, strlen(ServerComment) + 1, "Host Comment: %s", ServerComment);
336
337     }
338
339     break;
340
341   case REQUEST_ANNOUNCE:
342
343     Flags = GBYTE(pd, loc_offset);
344
345     if (tree) {
346
347       proto_tree_add_text(browse_tree, NullTVB, loc_offset, 1, "Unused Flags: %u", Flags);
348
349     }
350
351     loc_offset += 1;
352
353     ServerName = pd + loc_offset;
354
355     if (tree) {
356
357       proto_tree_add_text(browse_tree, NullTVB, loc_offset, strlen(ServerName) + 1, "Send List To: %s", ServerName);
358
359     }
360
361     break;
362
363   case BROWSER_ELECTION:
364
365     ElectionVersion = GBYTE(pd, loc_offset);
366
367     if (tree) {
368
369       proto_tree_add_text(browse_tree, NullTVB, loc_offset, 1, "Election Version = %u", ElectionVersion);
370
371     }
372
373     loc_offset += 1;
374
375     ElectionCriteria = GWORD(pd, loc_offset);
376     ElectionOS       = GBYTE(pd, loc_offset + 3);
377     ElectionRevision = GSHORT(pd, loc_offset + 1);
378     ElectionDesire   = GBYTE(pd, loc_offset);
379
380     if (tree) {
381
382       ti = proto_tree_add_text(browse_tree, NullTVB, loc_offset, 4, "Election Criteria = %u (0x%08X)", ElectionCriteria, ElectionCriteria);
383
384       ec = proto_item_add_subtree(ti, ett_browse_election_criteria);
385
386       ti = proto_tree_add_text(ec, NullTVB, loc_offset + 3, 1, "Election OS Summary: %u (0x%02X)", ElectionOS, ElectionOS);
387
388       OSflags = proto_item_add_subtree(ti, ett_browse_election_os);
389
390       proto_tree_add_text(OSflags, NullTVB, loc_offset + 3, 1, "%s",
391                             decode_boolean_bitfield(ElectionOS, 0x01, 8, "Windows for Workgroups", "Not Windows for Workgroups"));
392       
393       proto_tree_add_text(OSflags, NullTVB, loc_offset + 3, 1, "%s",
394                           decode_boolean_bitfield(ElectionOS, 0x02, 8, "Unknown", "Not used"));
395
396       proto_tree_add_text(OSflags, NullTVB, loc_offset + 3, 1, "%s",
397                           decode_boolean_bitfield(ElectionOS, 0x04, 8, "Unknown", "Not used"));
398
399       proto_tree_add_text(OSflags, NullTVB, loc_offset + 3, 1, "%s",
400                           decode_boolean_bitfield(ElectionOS, 0x08, 8, "Unknown", "Not used"));
401       
402       proto_tree_add_text(OSflags, NullTVB, loc_offset + 3, 1, "%s",
403                           decode_boolean_bitfield(ElectionOS, 0x10, 8, "Windows NT Workstation", "Not Windows NT Workstation"));
404       
405       proto_tree_add_text(OSflags, NullTVB, loc_offset + 3, 1, "%s",
406                           decode_boolean_bitfield(ElectionOS, 0x20, 8, "Windows NT Server", "Not Windows NT Server"));
407
408       proto_tree_add_text(OSflags, NullTVB, loc_offset + 3, 1, "%s",
409                           decode_boolean_bitfield(ElectionOS, 0x40, 8, "Unknown", "Not used"));
410
411       proto_tree_add_text(OSflags, NullTVB, loc_offset + 3, 1, "%s",
412                           decode_boolean_bitfield(ElectionOS, 0x80, 8, "Unknown", "Not used"));
413
414       proto_tree_add_text(ec, NullTVB, loc_offset + 1, 2, "Election Revision: %u (0x%04X)", ElectionRevision, ElectionRevision);
415
416       ti = proto_tree_add_text(ec, NullTVB, loc_offset, 1, "Election Desire Summary: %u (0x%02X)", ElectionDesire, ElectionDesire);
417
418       DesireFlags = proto_item_add_subtree(ti, ett_browse_election_desire);
419
420       proto_tree_add_text(DesireFlags, NullTVB, loc_offset, 1, "%s",
421                           decode_boolean_bitfield(ElectionDesire, 0x01, 8, "Backup Browse Server", "Not Backup Browse Server"));
422       
423       proto_tree_add_text(DesireFlags, NullTVB, loc_offset, 1, "%s",
424                           decode_boolean_bitfield(ElectionDesire, 0x02, 8, "Standby Browse Server", "Not Standby Browse Server"));
425
426       proto_tree_add_text(DesireFlags, NullTVB, loc_offset, 1, "%s",
427                           decode_boolean_bitfield(ElectionDesire, 0x04, 8, "Master Browser", "Not Master Browser"));
428
429       proto_tree_add_text(DesireFlags, NullTVB, loc_offset, 1, "%s",
430                           decode_boolean_bitfield(ElectionDesire, 0x08, 8, "Domain Master Browse Server", "Not Domain Master Browse Server"));
431
432       proto_tree_add_text(DesireFlags, NullTVB, loc_offset, 1, "%s",
433                           decode_boolean_bitfield(ElectionDesire, 0x10, 8, "Unknown", "Not used"));
434
435       proto_tree_add_text(DesireFlags, NullTVB, loc_offset, 1, "%s",
436                           decode_boolean_bitfield(ElectionDesire, 0x20, 8, "WINS Client", "Not WINS Client"));
437
438       proto_tree_add_text(DesireFlags, NullTVB, loc_offset, 1, "%s",
439                           decode_boolean_bitfield(ElectionDesire, 0x40, 8, "Unknown", "Not used"));
440
441       proto_tree_add_text(DesireFlags, NullTVB, loc_offset, 1, "%s",
442                           decode_boolean_bitfield(ElectionDesire, 0x80, 8, "Windows NT Advanced Server", "Not Windows NT Advanced Server"));
443
444     }
445
446     loc_offset += 4;
447
448     ServerUpTime = GWORD(pd, loc_offset);
449
450     if (tree) {
451
452       proto_tree_add_text(browse_tree, NullTVB, loc_offset, 4, "Server Up Time: %u Sec (%ums)", ServerUpTime/1000, ServerUpTime);
453
454     }
455
456     loc_offset += 4;
457
458     MBZ = GWORD(pd, loc_offset);
459
460     loc_offset += 4;
461
462     ServerName = pd + loc_offset;
463
464     if (tree) {
465
466       proto_tree_add_text(browse_tree, NullTVB, loc_offset, strlen(ServerName) + 1, "Election Server Name: %s", ServerName);
467
468     }
469
470     break;
471
472   case GETBACKUPLISTREQ:
473
474     BackupServerCount = GBYTE(pd, loc_offset);
475
476     if (tree) {
477
478       proto_tree_add_text(browse_tree, NullTVB, loc_offset, 1, "Backup List Requested Count: %u", BackupServerCount);
479
480     }
481
482     loc_offset += 1;
483
484     Token = GWORD(pd, loc_offset);
485
486     if (tree) {
487
488       proto_tree_add_text(browse_tree, NullTVB, loc_offset, 4, "Backup Request Token: %u", Token);
489
490     }
491
492     break;
493
494   case GETBACKUPLISTRESP:
495
496     BackupServerCount = GBYTE(pd, loc_offset);
497
498     if (tree) {
499
500       proto_tree_add_text(browse_tree, NullTVB, loc_offset, 1, "Backup Server Count: %u", BackupServerCount);
501
502     }
503
504     loc_offset += 1;
505
506     Token = GWORD(pd, loc_offset);
507
508     if (tree) {
509
510       proto_tree_add_text(browse_tree, NullTVB, loc_offset, 4, "Backup Response Token: %u", Token);
511
512     }
513
514     loc_offset += 4;
515
516     ServerName = pd + loc_offset;
517
518     for (count = 1; count <= BackupServerCount; count++) {
519
520       if (tree) {
521
522         proto_tree_add_text(browse_tree, NullTVB, loc_offset, strlen(ServerName) + 1, "Backup Server: %s", ServerName);
523
524       }
525
526       loc_offset += strlen(ServerName) + 1;
527
528       ServerName = pd + loc_offset;
529
530     }
531
532     break;
533
534   case BECOMEBACKUPBROWSER:
535
536     ServerName = pd + loc_offset;
537
538     if (tree) {
539
540       proto_tree_add_text(browse_tree, NullTVB, loc_offset, strlen(ServerName) + 1, "Browser to Promote: %s", ServerName);
541
542     }
543
544     break;
545
546   case MASTERANNOUNCEMENT:
547
548     ServerName = pd + loc_offset;
549
550     if (tree) {
551
552       proto_tree_add_text(browse_tree, NullTVB, loc_offset, strlen(ServerName) + 1, "Server Name: %s", ServerName);
553
554     }
555
556     break;
557
558   default:
559     break;
560   }
561   
562   return 1;  /* Success */
563
564 }
565
566
567 void
568 register_proto_smb_browse( void){
569
570
571         static gint *ett[] = {
572                 &ett_browse,
573                 &ett_browse_flags,
574                 &ett_browse_election_criteria,
575                 &ett_browse_election_os,
576                 &ett_browse_election_desire
577         };
578
579         proto_smb_browse = proto_register_protocol("Microsoft Windows Browser Protocol", "browser");           
580
581         proto_register_subtree_array(ett, array_length(ett));          
582 }