2 * Routines for SMB Browser packet dissection
3 * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
5 * $Id: packet-smb-browse.c,v 1.8 2001/03/18 03:34:22 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@zing.org>
9 * Copyright 1998 Gerald Combs
11 * Copied from packet-pop.c
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.
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.
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.
34 #ifdef HAVE_SYS_TYPES_H
35 # include <sys/types.h>
38 #ifdef HAVE_NETINET_IN_H
39 # include <netinet/in.h>
47 #include "conversation.h"
49 #include "alignment.h"
51 #include "packet-smb-browse.h"
53 static int proto_smb_browse = -1;
55 static gint ett_browse = -1;
56 static gint ett_browse_flags = -1;
57 static gint ett_browse_election_criteria = -1;
58 static gint ett_browse_election_os = -1;
59 static gint ett_browse_election_desire = -1;
63 static char *browse_commands[] =
64 { "Error, No such command!", /* Value 0 */
65 "Host Announcement", /* Value 1 */
66 "Request Announcement", /* Value 2 */
67 "Error, No such command!", /* Value 3 */
68 "Error, No such command!", /* Value 4 */
69 "Error, No such command!", /* Value 5 */
70 "Error, No such command!", /* Value 6 */
71 "Error, No such command!", /* Value 7 */
72 "Browser Election Request", /* Value 8 */
73 "Get Backup List Request", /* Value 9 */
74 "Get Backup List Response", /* Value 10 */
75 "Become Backup Browser", /* Value 11 */
76 "Domain/Workgroup Announcement", /* Value 12 */
77 "Master Announcement", /* Value 13 */
78 "Error! No such command", /* Value 14 */
79 "Local Master Announcement" /* Value 15 */
82 #define HOST_ANNOUNCE 1
83 #define REQUEST_ANNOUNCE 2
84 #define BROWSER_ELECTION 8
85 #define GETBACKUPLISTREQ 9
86 #define GETBACKUPLISTRESP 10
87 #define BECOMEBACKUPBROWSER 11
88 #define DOMAINANNOUNCEMENT 12
89 #define MASTERANNOUNCEMENT 13
90 #define LOCALMASTERANNOUNC 15
92 static char *svr_types[32] = {
101 "Domain Member Server",
102 "Print Queue Server",
106 "Windows for Workgroups",
107 "Unknown Server - FIXME",
112 "Domain Master Browser",
115 "Windows 95 or above",
128 dissect_mailslot_browse(const u_char *pd, int offset, frame_data *fd,
129 proto_tree *parent, proto_tree *tree, struct smb_info si, int max_data,
130 int SMB_offset, int errcode, int dirn, const u_char *command,
131 int DataOffset, int DataCount)
141 guint8 BackupServerCount;
144 guint8 ElectionVersion;
145 guint32 ElectionCriteria;
147 guint8 ElectionDesire;
148 guint16 ElectionRevision;
149 guint32 ServerUpTime;
150 const char *ServerName;
151 const char *ServerComment;
152 proto_tree *browse_tree = NULL, *flags_tree = NULL,
153 *OSflags = NULL, *DesireFlags = NULL;
155 guint32 loc_offset = DataOffset, count = 0;
158 if (!proto_is_protocol_enabled(proto_smb_browse))
161 if (check_col(fd, COL_PROTOCOL))
162 col_set_str(fd, COL_PROTOCOL, "BROWSER");
164 if (check_col(fd, COL_INFO)) /* Put in something, and replace it later */
165 col_set_str(fd, COL_INFO, "Browse Announcement");
168 * Now, decode the browse request
171 OpCode = GBYTE(pd, loc_offset);
173 if (check_col(fd, COL_INFO))
174 col_add_fstr(fd, COL_INFO, (OpCode > (sizeof(browse_commands)/sizeof(char *))) ? "Error, No Such Command:%u" : browse_commands[OpCode], OpCode);
176 if (tree) { /* Add the browse tree */
178 ti = proto_tree_add_item(parent, proto_smb_browse, NullTVB, DataOffset, DataCount, FALSE);
179 browse_tree = proto_item_add_subtree(ti, ett_browse);
181 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]);
185 loc_offset += 1; /* Skip the OpCode */
189 case DOMAINANNOUNCEMENT:
190 case LOCALMASTERANNOUNC:
193 UpdateCount = GBYTE(pd, loc_offset);
197 proto_tree_add_text(browse_tree, NullTVB, loc_offset, 1, "Update Count: %u", UpdateCount);
201 loc_offset += 1; /* Skip the Update Count */
203 Periodicity = GWORD(pd, loc_offset);
207 proto_tree_add_text(browse_tree, NullTVB, loc_offset, 4, "Update Periodicity: %u Sec", Periodicity/1000 );
213 ServerName = pd + loc_offset;
215 if (check_col(fd, COL_INFO)) {
217 col_append_fstr(fd, COL_INFO, " %s", ServerName);
223 proto_tree_add_text(browse_tree, NullTVB, loc_offset, 16, (OpCode == DOMAINANNOUNCEMENT) ? "Domain/WorkGroup: %s": "Host Name: %s", ServerName);
229 VersionMajor = GBYTE(pd, loc_offset);
233 proto_tree_add_text(browse_tree, NullTVB, loc_offset, 1, "Major Version: %u", VersionMajor);
239 VersionMinor = GBYTE(pd, loc_offset);
243 proto_tree_add_text(browse_tree, NullTVB, loc_offset, 1, "Minor Version: %u", VersionMinor);
249 ServerType = GWORD(pd, loc_offset);
251 if (check_col(fd, COL_INFO)) {
253 /* Append the type(s) of the system to the COL_INFO line ... */
255 for (i = 0; i < 32; i++) {
257 if (ServerType & (1 << i) && (strcmp("Unused", svr_types[i]) != 0))
258 col_append_fstr(fd, COL_INFO, ", %s", svr_types[i]);
266 ti = proto_tree_add_text(browse_tree, NullTVB, loc_offset, 4, "Server Type: 0x%04x", ServerType);
267 flags_tree = proto_item_add_subtree(ti, ett_browse_flags);
268 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
269 decode_boolean_bitfield(ServerType, 0x0001, 32, "Workstation", "Not Workstation"));
270 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
271 decode_boolean_bitfield(ServerType, 0x0002, 32, "Server", "Not Server"));
272 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
273 decode_boolean_bitfield(ServerType, 0x0004, 32, "SQL Server", "Not SQL Server"));
274 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
275 decode_boolean_bitfield(ServerType, 0x0008, 32, "Domain Controller", "Not Domain Controller"));
276 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
277 decode_boolean_bitfield(ServerType, 0x0010, 32, "Backup Controller", "Not Backup Controller"));
278 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
279 decode_boolean_bitfield(ServerType, 0x0020, 32, "Time Source", "Not Time Source"));
280 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
281 decode_boolean_bitfield(ServerType, 0x0040, 32, "Apple Server", "Not Apple Server"));
282 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
283 decode_boolean_bitfield(ServerType, 0x0080, 32, "Novell Server", "Not Novell Server"));
284 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
285 decode_boolean_bitfield(ServerType, 0x0100, 32, "Domain Member Server", "Not Domain Member Server"));
286 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
287 decode_boolean_bitfield(ServerType, 0x0200, 32, "Print Queue Server", "Not Print Queue Server"));
288 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
289 decode_boolean_bitfield(ServerType, 0x0400, 32, "Dialin Server", "Not Dialin Server"));
290 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
291 decode_boolean_bitfield(ServerType, 0x0800, 32, "Xenix Server", "Not Xenix Server"));
292 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
293 decode_boolean_bitfield(ServerType, 0x1000, 32, "NT Workstation", "Not NT Workstation"));
294 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
295 decode_boolean_bitfield(ServerType, 0x2000, 32, "Windows for Workgroups", "Not Windows for Workgroups"));
296 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
297 decode_boolean_bitfield(ServerType, 0x8000, 32, "NT Server", "Not NT Server"));
298 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
299 decode_boolean_bitfield(ServerType, 0x10000, 32, "Potential Browser", "Not Potential Browser"));
300 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
301 decode_boolean_bitfield(ServerType, 0x20000, 32, "Backup Browser", "Not Backup Browser"));
302 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
303 decode_boolean_bitfield(ServerType, 0x40000, 32, "Master Browser", "Not Master Browser"));
304 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
305 decode_boolean_bitfield(ServerType, 0x80000, 32, "Domain Master Browser", "Not Domain Master Browser"));
306 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
307 decode_boolean_bitfield(ServerType, 0x100000, 32, "OSF", "Not OSF"));
308 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
309 decode_boolean_bitfield(ServerType, 0x200000, 32, "VMS", "Not VMS"));
310 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
311 decode_boolean_bitfield(ServerType, 0x400000, 32, "Windows 95 or above", "Not Windows 95 or above"));
312 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
313 decode_boolean_bitfield(ServerType, 0x40000000, 32, "Local List Only", "Not Local List Only"));
314 proto_tree_add_text(flags_tree, NullTVB, loc_offset, 4, "%s",
315 decode_boolean_bitfield(ServerType, 0x80000000, 32, "Domain Enum", "Not Domain Enum"));
319 ElectionVersion = GSHORT(pd, loc_offset);
323 proto_tree_add_text(browse_tree, NullTVB, loc_offset, 2, "Election Version: %u", ElectionVersion);
329 SigConstant = GSHORT(pd, loc_offset);
333 proto_tree_add_text(browse_tree, NullTVB, loc_offset, 2, "Signature: %u (0x%04X)", SigConstant, SigConstant);
339 ServerComment = pd + loc_offset;
343 proto_tree_add_text(browse_tree, NullTVB, loc_offset, strlen(ServerComment) + 1, "Host Comment: %s", ServerComment);
349 case REQUEST_ANNOUNCE:
351 Flags = GBYTE(pd, loc_offset);
355 proto_tree_add_text(browse_tree, NullTVB, loc_offset, 1, "Unused Flags: %u", Flags);
361 ServerName = pd + loc_offset;
365 proto_tree_add_text(browse_tree, NullTVB, loc_offset, strlen(ServerName) + 1, "Send List To: %s", ServerName);
371 case BROWSER_ELECTION:
373 ElectionVersion = GBYTE(pd, loc_offset);
377 proto_tree_add_text(browse_tree, NullTVB, loc_offset, 1, "Election Version = %u", ElectionVersion);
383 ElectionCriteria = GWORD(pd, loc_offset);
384 ElectionOS = GBYTE(pd, loc_offset + 3);
385 ElectionRevision = GSHORT(pd, loc_offset + 1);
386 ElectionDesire = GBYTE(pd, loc_offset);
390 ti = proto_tree_add_text(browse_tree, NullTVB, loc_offset, 4, "Election Criteria = %u (0x%08X)", ElectionCriteria, ElectionCriteria);
392 ec = proto_item_add_subtree(ti, ett_browse_election_criteria);
394 ti = proto_tree_add_text(ec, NullTVB, loc_offset + 3, 1, "Election OS Summary: %u (0x%02X)", ElectionOS, ElectionOS);
396 OSflags = proto_item_add_subtree(ti, ett_browse_election_os);
398 proto_tree_add_text(OSflags, NullTVB, loc_offset + 3, 1, "%s",
399 decode_boolean_bitfield(ElectionOS, 0x01, 8, "Windows for Workgroups", "Not Windows for Workgroups"));
401 proto_tree_add_text(OSflags, NullTVB, loc_offset + 3, 1, "%s",
402 decode_boolean_bitfield(ElectionOS, 0x02, 8, "Unknown", "Not used"));
404 proto_tree_add_text(OSflags, NullTVB, loc_offset + 3, 1, "%s",
405 decode_boolean_bitfield(ElectionOS, 0x04, 8, "Unknown", "Not used"));
407 proto_tree_add_text(OSflags, NullTVB, loc_offset + 3, 1, "%s",
408 decode_boolean_bitfield(ElectionOS, 0x08, 8, "Unknown", "Not used"));
410 proto_tree_add_text(OSflags, NullTVB, loc_offset + 3, 1, "%s",
411 decode_boolean_bitfield(ElectionOS, 0x10, 8, "Windows NT Workstation", "Not Windows NT Workstation"));
413 proto_tree_add_text(OSflags, NullTVB, loc_offset + 3, 1, "%s",
414 decode_boolean_bitfield(ElectionOS, 0x20, 8, "Windows NT Server", "Not Windows NT Server"));
416 proto_tree_add_text(OSflags, NullTVB, loc_offset + 3, 1, "%s",
417 decode_boolean_bitfield(ElectionOS, 0x40, 8, "Unknown", "Not used"));
419 proto_tree_add_text(OSflags, NullTVB, loc_offset + 3, 1, "%s",
420 decode_boolean_bitfield(ElectionOS, 0x80, 8, "Unknown", "Not used"));
422 proto_tree_add_text(ec, NullTVB, loc_offset + 1, 2, "Election Revision: %u (0x%04X)", ElectionRevision, ElectionRevision);
424 ti = proto_tree_add_text(ec, NullTVB, loc_offset, 1, "Election Desire Summary: %u (0x%02X)", ElectionDesire, ElectionDesire);
426 DesireFlags = proto_item_add_subtree(ti, ett_browse_election_desire);
428 proto_tree_add_text(DesireFlags, NullTVB, loc_offset, 1, "%s",
429 decode_boolean_bitfield(ElectionDesire, 0x01, 8, "Backup Browse Server", "Not Backup Browse Server"));
431 proto_tree_add_text(DesireFlags, NullTVB, loc_offset, 1, "%s",
432 decode_boolean_bitfield(ElectionDesire, 0x02, 8, "Standby Browse Server", "Not Standby Browse Server"));
434 proto_tree_add_text(DesireFlags, NullTVB, loc_offset, 1, "%s",
435 decode_boolean_bitfield(ElectionDesire, 0x04, 8, "Master Browser", "Not Master Browser"));
437 proto_tree_add_text(DesireFlags, NullTVB, loc_offset, 1, "%s",
438 decode_boolean_bitfield(ElectionDesire, 0x08, 8, "Domain Master Browse Server", "Not Domain Master Browse Server"));
440 proto_tree_add_text(DesireFlags, NullTVB, loc_offset, 1, "%s",
441 decode_boolean_bitfield(ElectionDesire, 0x10, 8, "Unknown", "Not used"));
443 proto_tree_add_text(DesireFlags, NullTVB, loc_offset, 1, "%s",
444 decode_boolean_bitfield(ElectionDesire, 0x20, 8, "WINS Client", "Not WINS Client"));
446 proto_tree_add_text(DesireFlags, NullTVB, loc_offset, 1, "%s",
447 decode_boolean_bitfield(ElectionDesire, 0x40, 8, "Unknown", "Not used"));
449 proto_tree_add_text(DesireFlags, NullTVB, loc_offset, 1, "%s",
450 decode_boolean_bitfield(ElectionDesire, 0x80, 8, "Windows NT Advanced Server", "Not Windows NT Advanced Server"));
456 ServerUpTime = GWORD(pd, loc_offset);
460 proto_tree_add_text(browse_tree, NullTVB, loc_offset, 4, "Server Up Time: %u Sec (%ums)", ServerUpTime/1000, ServerUpTime);
466 MBZ = GWORD(pd, loc_offset);
470 ServerName = pd + loc_offset;
474 proto_tree_add_text(browse_tree, NullTVB, loc_offset, strlen(ServerName) + 1, "Election Server Name: %s", ServerName);
480 case GETBACKUPLISTREQ:
482 BackupServerCount = GBYTE(pd, loc_offset);
486 proto_tree_add_text(browse_tree, NullTVB, loc_offset, 1, "Backup List Requested Count: %u", BackupServerCount);
492 Token = GWORD(pd, loc_offset);
496 proto_tree_add_text(browse_tree, NullTVB, loc_offset, 4, "Backup Request Token: %u", Token);
502 case GETBACKUPLISTRESP:
504 BackupServerCount = GBYTE(pd, loc_offset);
508 proto_tree_add_text(browse_tree, NullTVB, loc_offset, 1, "Backup Server Count: %u", BackupServerCount);
514 Token = GWORD(pd, loc_offset);
518 proto_tree_add_text(browse_tree, NullTVB, loc_offset, 4, "Backup Response Token: %u", Token);
524 ServerName = pd + loc_offset;
526 for (count = 1; count <= BackupServerCount; count++) {
530 proto_tree_add_text(browse_tree, NullTVB, loc_offset, strlen(ServerName) + 1, "Backup Server: %s", ServerName);
534 loc_offset += strlen(ServerName) + 1;
536 ServerName = pd + loc_offset;
542 case BECOMEBACKUPBROWSER:
544 ServerName = pd + loc_offset;
548 proto_tree_add_text(browse_tree, NullTVB, loc_offset, strlen(ServerName) + 1, "Browser to Promote: %s", ServerName);
554 case MASTERANNOUNCEMENT:
556 ServerName = pd + loc_offset;
560 proto_tree_add_text(browse_tree, NullTVB, loc_offset, strlen(ServerName) + 1, "Server Name: %s", ServerName);
570 return TRUE; /* Success */
576 register_proto_smb_browse( void){
579 static gint *ett[] = {
582 &ett_browse_election_criteria,
583 &ett_browse_election_os,
584 &ett_browse_election_desire
587 proto_smb_browse = proto_register_protocol("Microsoft Windows Browser Protocol",
588 "BROWSER", "browser");
590 proto_register_subtree_array(ett, array_length(ett));