Squelch an MSVC++ complaint.
[obnox/wireshark/wip.git] / packet-netbios.c
1 /* packet-netbios.c
2  * Routines for NetBIOS protocol packet disassembly
3  * Jeff Foster <jfoste@woodward.com>            
4  * Copyright 1999 Jeffrey C. Foster
5  * 
6  * derived from the packet-nbns.c
7  *
8  * $Id: packet-netbios.c,v 1.39 2001/09/29 20:32:29 guy Exp $
9  *
10  * Ethereal - Network traffic analyzer
11  * By Gerald Combs <gerald@ethereal.com>
12  * Copyright 1998 Gerald Combs
13  * 
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  * 
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * 
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #ifdef HAVE_SYS_TYPES_H
34 # include <sys/types.h>
35 #endif
36
37 #include <stdio.h>
38 #include <string.h>
39 #include <glib.h>
40
41 #include "packet.h"
42 #include "llcsaps.h"
43 #include "packet-netbios.h"
44
45 /* Netbios command numbers */
46 #define NB_ADD_GROUP            0x00
47 #define NB_ADD_NAME             0x01
48 #define NB_NAME_IN_CONFLICT     0x02
49 #define NB_STATUS_QUERY         0x03
50 #define NB_TERMINATE_TRACE_R    0x07
51 #define NB_DATAGRAM             0x08
52 #define NB_DATAGRAM_BCAST       0x09
53 #define NB_NAME_QUERY           0x0a
54 #define NB_ADD_NAME_RESP        0x0d
55 #define NB_NAME_RESP            0x0e
56 #define NB_STATUS_RESP          0x0f
57 #define NB_TERMINATE_TRACE_LR   0x13
58 #define NB_DATA_ACK             0x14
59 #define NB_DATA_FIRST_MIDDLE    0x15
60 #define NB_DATA_ONLY_LAST       0x16
61 #define NB_SESSION_CONFIRM      0x17
62 #define NB_SESSION_END          0x18
63 #define NB_SESSION_INIT         0x19
64 #define NB_NO_RECEIVE           0x1a
65 #define NB_RECEIVE_OUTSTANDING  0x1b
66 #define NB_RECEIVE_CONTINUE     0x1c
67 #define NB_KEEP_ALIVE           0x1f
68
69 /* Offsets of fields in the NetBIOS header. */
70 #define NB_LENGTH               0
71 #define NB_DELIMITER            2
72 #define NB_COMMAND              4
73 #define NB_FLAGS                5
74 #define NB_DATA1                5
75 #define NB_RESYNC               6
76 #define NB_DATA2                6
77 #define NB_CALL_NAME_TYPE       7
78 #define NB_XMIT_CORL            8
79 #define NB_RESP_CORL            10
80 #define NB_RMT_SES              12
81 #define NB_LOCAL_SES            13
82 #define NB_RECVER_NAME          12
83 #define NB_SENDER_NAME          28
84
85
86 static int proto_netbios = -1;
87 static int hf_netb_cmd = -1;
88 static int hf_netb_hdr_len = -1;
89 static int hf_netb_xmit_corrl = -1;
90 static int hf_netb_resp_corrl = -1;
91 static int hf_netb_call_name_type = -1;
92 static int hf_netb_ack = -1;
93 static int hf_netb_ack_with_data = -1;
94 static int hf_netb_ack_expected = -1;
95 static int hf_netb_recv_cont_req = -1;
96 static int hf_netb_send_no_ack = -1;
97 static int hf_netb_version = -1;
98 static int hf_netb_largest_frame = -1;
99 static int hf_netb_name = -1;
100 static int hf_netb_name_type = -1;
101 static int hf_netb_local_ses_no = -1;
102 static int hf_netb_remote_ses_no = -1;
103 static int hf_netb_data2 = -1;
104
105 static gint ett_netb = -1;
106 static gint ett_netb_name = -1;
107 static gint ett_netb_flags = -1;
108 static gint ett_netb_status = -1;
109
110 /* The strings for the station type, used by get_netbios_name function;
111    many of them came from the file "NetBIOS.txt" in the Zip archive at
112
113         http://www.net3group.com/ftp/browser.zip
114  */
115
116 static const value_string name_type_vals[] = {
117         {0x00,  "Workstation/Redirector"},
118         {0x01,  "Browser"},
119         {0x02,  "Workstation/Redirector"}, 
120                 /* not sure what 0x02 is, I'm seeing alot of them however */
121                 /* i'm seeing them with workstation/redirection host 
122                         announcements */
123         {0x03,  "Messenger service/Main name"},
124         {0x05,  "Forwarded name"},
125         {0x06,  "RAS Server service"},
126         {0x1b,  "Domain Master Browser"},
127         {0x1c,  "Domain Controllers"},
128         {0x1d,  "Local Master Browser"},
129         {0x1e,  "Browser Election Service"},
130         {0x1f,  "Net DDE Service"},
131         {0x20,  "Server service"},
132         {0x21,  "RAS client service"},
133         {0x22,  "Exchange Interchange (MSMail Connector)"},
134         {0x23,  "Exchange Store"},
135         {0x24,  "Exchange Directory"},
136         {0x2b,  "Lotus Notes Server service"},
137         {0x30,  "Modem sharing server service"},
138         {0x31,  "Modem sharing client service"},
139         {0x43,  "SMS Clients Remote Control"},
140         {0x44,  "SMS Administrators Remote Control Tool"},
141         {0x45,  "SMS Clients Remote Chat"},
142         {0x46,  "SMS Clients Remote Transfer"},
143         {0x4c,  "DEC Pathworks TCP/IP Service on Windows NT"},
144         {0x52,  "DEC Pathworks TCP/IP Service on Windows NT"},
145         {0x6a,  "Microsoft Exchange IMC"},
146         {0x87,  "Microsoft Exchange MTA"},
147         {0xbe,  "Network Monitor Agent"},
148         {0xbf,  "Network Monitor Analyzer"},
149         {0x00,  NULL}
150 };
151
152 /* See
153    
154         http://www.s390.ibm.com/bookmgr-cgi/bookmgr.cmd/BOOKS/BK8P7001/CCONTENTS
155
156    and
157
158         http://ourworld.compuserve.com/homepages/TimothyDEvans/contents.htm
159
160    for information about the NetBIOS Frame Protocol (which is what this
161    module dissects). */
162
163 /* the strings for the command types  */
164
165 static char *CommandName[] = {
166         "Add Group Name Query", /* 0x00 */
167         "Add Name Query",       /* 0x01 */
168         "Name In Conflict",     /* 0x02 */
169         "Status Query",         /* 0x03 */
170         "Unknown",
171         "Unknown",
172         "Unknown",
173         "Terminate Trace",      /* 0x07 */
174         "Datagram",             /* 0x08 */
175         "Broadcast Datagram",   /* 0x09 */
176         "Name Query",           /* 0x0A */
177         "Unknown",
178         "Unknown",
179         "Add Name Response",    /* 0x0D */
180         "Name Recognized",      /* 0x0E */
181         "Status Response",      /* 0x0F */
182         "Unknown",
183         "Unknown",
184         "Unknown",
185         "Terminate Trace",      /* 0x13 */
186         "Data Ack",             /* 0x14 */
187         "Data First Middle",    /* 0x15 */
188         "Data Only Last",       /* 0x16 */
189         "Session Confirm",      /* 0x17 */
190         "Session End",          /* 0x18 */
191         "Session Initialize",   /* 0x19 */
192         "No Receive",           /* 0x1a */
193         "Receive Outstanding",  /* 0x1b */
194         "Receive Continue",     /* 0x1c */
195         "Unknown",
196         "Unknown",
197         "Session Alive",        /* 0x1f */
198         "Unknown",
199 };
200
201
202 static const true_false_string flags_set = {
203         "Set",
204         "Not set"
205 };
206 static const true_false_string flags_allowed = {
207         "Allowed",
208         "Not allowrd"
209 };
210 static const true_false_string flags_yes_no = {
211         "Yes",
212         "No"
213 };
214
215 static const true_false_string netb_version_str = {
216         "2.00 or higher",
217         "1.xx"
218 };
219
220
221 void capture_netbios(const u_char *pd, int offset, packet_counts *ld)
222 {
223         ld->netbios++;
224 }
225
226
227 int
228 process_netbios_name(const u_char *name_ptr, char *name_ret)
229 {
230         int i;
231         int name_type = *(name_ptr + NETBIOS_NAME_LEN - 1);
232         u_char name_char;
233         static const char hex_digits[16] = "0123456789abcdef";
234
235         for (i = 0; i < NETBIOS_NAME_LEN - 1; i++) {
236                 name_char = *name_ptr++;
237                 if (name_char >= ' ' && name_char <= '~')
238                         *name_ret++ = name_char;
239                 else {
240                         /* It's not printable; show it as <XX>, where
241                            XX is the value in hex. */
242                         *name_ret++ = '<';
243                         *name_ret++ = hex_digits[(name_char >> 4)];
244                         *name_ret++ = hex_digits[(name_char & 0x0F)];
245                         *name_ret++ = '>';
246                 }
247         }
248         *name_ret = '\0';
249         return name_type;
250 }
251
252
253 int get_netbios_name( tvbuff_t *tvb, int offset, char *name_ret)
254
255 {/*  Extract the name string and name type.  Return the name string in  */
256  /* name_ret and return the name_type. */
257
258         return process_netbios_name( tvb_get_ptr( tvb, offset, NETBIOS_NAME_LEN ), name_ret);
259 }
260
261
262 /*
263  * Get a string describing the type of a NetBIOS name.
264  */
265 char *
266 netbios_name_type_descr(int name_type)
267 {
268         return val_to_str(name_type, name_type_vals, "Unknown");
269 }
270
271 void netbios_add_name(char* label, tvbuff_t *tvb, int offset,
272     proto_tree *tree)
273
274 {/* add a name field display tree. Display the name and station type in sub-tree */
275  
276         proto_tree *field_tree;
277         proto_item *tf;
278         char  name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
279         int   name_type;
280         char  *name_type_str;
281
282                                         /* decode the name field */
283         name_type = get_netbios_name( tvb, offset, name_str);
284         name_type_str = netbios_name_type_descr(name_type);
285         tf = proto_tree_add_text( tree, tvb, offset, NETBIOS_NAME_LEN,
286                 "%s: %s<%02x> (%s)", label, name_str, name_type, name_type_str);
287
288         field_tree = proto_item_add_subtree( tf, ett_netb_name);
289         proto_tree_add_string_format( field_tree, hf_netb_name, tvb, offset,
290                 15, name_str, "%s", name_str);
291         proto_tree_add_uint_format( field_tree, hf_netb_name_type, tvb, offset + 15, 1, name_type,
292             "0x%02x (%s)", name_type, name_type_str);
293 }
294
295
296 static void netbios_data_first_middle_flags( tvbuff_t *tvb, proto_tree *tree, int offset)
297
298 {
299         proto_tree *field_tree;
300         proto_item *tf;
301         guint flags = tvb_get_guint8( tvb, offset);
302
303                 /* decode the flag field for Data First Middle packet*/
304
305         tf = proto_tree_add_text(tree, tvb, offset, 1,
306                         "Flags: 0x%02x", flags);
307         field_tree = proto_item_add_subtree(tf, ett_netb_flags);
308
309         proto_tree_add_boolean( field_tree, hf_netb_ack, tvb, offset, 1, flags);
310
311         proto_tree_add_boolean( field_tree, hf_netb_ack_expected, tvb, offset, 1, flags);
312
313         proto_tree_add_boolean( field_tree, hf_netb_recv_cont_req, tvb, offset, 1, flags);
314 }
315
316 static void netbios_data_only_flags( tvbuff_t *tvb, proto_tree *tree,
317    int offset)
318 {
319         proto_tree *field_tree;
320         proto_item *tf;
321         guint flags = tvb_get_guint8( tvb, offset);
322
323                 /* decode the flag field for Data Only Last packet*/
324
325         tf = proto_tree_add_text(tree, tvb, offset, 1,
326                         "Flags: 0x%02x", flags);
327         field_tree = proto_item_add_subtree(tf, ett_netb_flags);
328
329         proto_tree_add_boolean( field_tree, hf_netb_ack, tvb, offset, 1, flags);
330
331         proto_tree_add_boolean( field_tree, hf_netb_ack_with_data, tvb, offset, 1, flags);
332
333         proto_tree_add_boolean( field_tree, hf_netb_ack_expected, tvb, offset, 1, flags);
334 }
335
336
337
338 static void netbios_add_ses_confirm_flags( tvbuff_t *tvb, proto_tree *tree,
339         int offset)
340 {
341         proto_tree *field_tree;
342         proto_item *tf;
343         guint flags = tvb_get_guint8( tvb, offset);
344
345                 /* decode the flag field for Session Confirm packet */
346         tf = proto_tree_add_text(tree, tvb, offset, 1,
347                         "Flags: 0x%02x", flags);
348         field_tree = proto_item_add_subtree( tf, ett_netb_flags);
349
350         proto_tree_add_boolean( field_tree, hf_netb_send_no_ack, tvb, offset, 1, flags);
351
352         proto_tree_add_boolean( field_tree, hf_netb_version, tvb, offset, 1, flags);
353 }
354
355
356 static void netbios_add_session_init_flags( tvbuff_t *tvb, proto_tree *tree,
357         int offset)
358 {
359         proto_tree *field_tree;
360         proto_item *tf;
361         guint flags = tvb_get_guint8( tvb, offset);
362                 /* decode the flag field for Session Init packet */
363
364         tf = proto_tree_add_text(tree, tvb, offset, 1,
365                         "Flags: 0x%02x", flags);
366         field_tree = proto_item_add_subtree(tf, ett_netb_flags);
367
368         proto_tree_add_boolean( field_tree, hf_netb_send_no_ack, tvb, offset, 1, flags);
369
370         proto_tree_add_uint( field_tree, hf_netb_largest_frame, tvb, offset, 1,
371                 flags);
372
373         proto_tree_add_boolean( field_tree, hf_netb_version, tvb, offset, 1, flags);
374 }
375
376
377 static void netbios_no_receive_flags( tvbuff_t *tvb, proto_tree *tree,
378     int offset)
379
380 {
381         proto_tree *field_tree;
382         proto_item *tf;
383         guint flags = tvb_get_guint8( tvb, offset);
384
385                 /* decode the flag field for No Receive packet*/
386
387         tf = proto_tree_add_text(tree, tvb, offset, 1,
388                         "Flags: 0x%02x", flags);
389
390         if (flags & 0x02) {
391                 field_tree = proto_item_add_subtree(tf, ett_netb_flags);
392                 proto_tree_add_text(field_tree, tvb, offset, 1, "%s",
393                     decode_boolean_bitfield(flags, 0x02, 8,
394                         "SEND.NO.ACK data not received", NULL));
395         }
396 }
397
398
399 /************************************************************************/
400 /*                                                                      */
401 /*  The routines to display the netbios field values in the tree        */
402 /*                                                                      */
403 /************************************************************************/
404
405
406 static void nb_xmit_corrl( tvbuff_t *tvb, int offset, proto_tree *tree)
407
408 {/* display the transmit correlator */
409
410         proto_tree_add_int( tree, hf_netb_xmit_corrl, tvb, offset + NB_XMIT_CORL, 
411                 2, tvb_get_letohs( tvb, offset + NB_XMIT_CORL));
412 }
413
414
415 static void nb_resp_corrl( tvbuff_t *tvb, int offset, proto_tree *tree)
416
417 {/* display the response correlator */
418
419         proto_tree_add_int( tree, hf_netb_resp_corrl, tvb, offset + NB_RESP_CORL,
420                 2, tvb_get_letohs( tvb, offset + NB_RESP_CORL));
421 }
422
423
424 static void nb_call_name_type( tvbuff_t *tvb, int offset, proto_tree *tree)
425
426 {/* display the call name type */
427
428
429         int name_type_value =   tvb_get_guint8( tvb, offset + NB_CALL_NAME_TYPE);
430
431         switch (name_type_value) {
432
433         case 0x00:
434                 proto_tree_add_int_format( tree, hf_netb_call_name_type, tvb, offset + NB_CALL_NAME_TYPE,
435                         2, tvb_get_letohs( tvb, offset + NB_CALL_NAME_TYPE), "Caller's Name Type: Unique name");
436                 break;
437
438         case 0x01:
439                 proto_tree_add_int_format( tree, hf_netb_call_name_type, tvb, offset + NB_CALL_NAME_TYPE,
440                         2, tvb_get_letohs( tvb, offset + NB_CALL_NAME_TYPE), "Caller's Name Type: Group name");
441                 break;
442
443         default:
444                 proto_tree_add_int_format( tree, hf_netb_call_name_type, tvb, offset + NB_CALL_NAME_TYPE,
445                         2, tvb_get_letohs( tvb, offset + NB_CALL_NAME_TYPE),
446                         "Caller's Name Type: 0x%02x (should be 0 or 1)", name_type_value);
447                 break;
448         }
449 }
450
451
452 static void nb_local_session( tvbuff_t *tvb, int offset, proto_tree *tree)
453
454 {/* add the local session to tree */
455
456         proto_tree_add_uint( tree, hf_netb_local_ses_no, tvb, offset + NB_LOCAL_SES, 1, 
457                 tvb_get_guint8( tvb, offset + NB_LOCAL_SES));
458
459 }
460
461
462 static void nb_remote_session( tvbuff_t *tvb, int offset, proto_tree *tree)
463
464 {/* add the remote session to tree */
465
466         proto_tree_add_uint( tree, hf_netb_remote_ses_no, tvb, offset + NB_RMT_SES, 1,
467                 tvb_get_guint8( tvb, offset + NB_RMT_SES));
468
469 }
470
471
472 static void nb_data2(char *label, int len, tvbuff_t *tvb, int offset,
473     proto_tree *tree)
474
475 {/* add the DATA2 to tree with format string = label and length of len */
476
477         int value = (len == 1 ? tvb_get_guint8( tvb, offset + NB_DATA2)
478                         : tvb_get_letohs( tvb, offset + NB_DATA2));
479         
480         proto_tree_add_uint( tree, hf_netb_data2, tvb, offset + NB_DATA2, 2, value);
481
482 }
483
484
485 static void nb_resync_indicator( tvbuff_t *tvb, int offset, proto_tree *tree, char *cmd_str)
486 {
487         guint16 resync_indicator = tvb_get_letohs( tvb, offset + NB_DATA2);
488
489
490         switch (resync_indicator) {
491
492         case 0x0000:
493                 proto_tree_add_text(tree, tvb, offset + NB_DATA2, 2,
494                     "Re-sync indicator: No re-sync");
495                 break;
496
497         case 0x0001:
498                 proto_tree_add_text(tree, tvb, offset + NB_DATA2, 2,
499                     "Re-sync indicator: First '%s' following 'Receive Outstanding'", cmd_str);
500                 break;
501
502         default:
503                 proto_tree_add_text(tree, tvb, offset + NB_DATA2, 2,
504                     "Re-sync indicator: 0x%04x", resync_indicator);
505                 break;
506         }
507 }
508
509 /************************************************************************/
510 /*                                                                      */
511 /*  The routines called by the top level to handle individual commands  */
512 /*                                                                      */
513 /************************************************************************/
514
515 static void dissect_netb_unknown( tvbuff_t *tvb, int offset, proto_tree *tree)
516
517 {/* Handle any unknow commands, do nothing */
518
519 /*      dissect_data( tvb, offset + NB_COMMAND + 1, pinfo, tree); */
520 }
521
522
523 static void  dissect_netb_add_group_name( tvbuff_t *tvb, int offset,
524     proto_tree *tree)
525
526 {/* Handle the ADD GROUP NAME QUERY command */
527
528         nb_resp_corrl( tvb, offset, tree); 
529
530         netbios_add_name("Group name to add", tvb, offset + NB_SENDER_NAME,
531             tree);
532 }
533
534
535 static void  dissect_netb_add_name( tvbuff_t *tvb, int offset, 
536     proto_tree *tree)
537
538 {/* Handle the ADD NAME QUERY command */
539
540         nb_resp_corrl( tvb, offset, tree); 
541
542         netbios_add_name("Name to add", tvb, offset + NB_SENDER_NAME, tree);
543 }
544
545
546 static void  dissect_netb_name_in_conflict( tvbuff_t *tvb, int offset,
547      proto_tree *tree)
548
549 {/* Handle the NAME IN CONFLICT command */
550
551         netbios_add_name("Name In Conflict", tvb, offset + NB_RECVER_NAME,
552             tree);
553         netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME, tree);
554 }
555
556
557 static void  dissect_netb_status_query( tvbuff_t *tvb, int offset, proto_tree *tree)
558
559 {/* Handle the STATUS QUERY command */
560
561         guint8 status_request = tvb_get_guint8( tvb, offset + NB_DATA1);
562
563         switch (status_request) {
564
565         case 0:
566                 proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
567                     "Status request: NetBIOS 1.x or 2.0");
568                 break;
569
570         case 1:
571                 proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
572                     "Status request: NetBIOS 2.1, initial status request");
573                 break;
574
575         default:
576                 proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
577                     "Status request: NetBIOS 2.1, %u names received so far",
578                     status_request);
579                 break;
580         }
581         nb_data2("Length of status buffer: %u", 2, tvb, offset, tree);
582         nb_resp_corrl( tvb, offset, tree); 
583         netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
584         netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
585             tree);
586 }
587
588
589 static u_char zeroes[10];
590
591 static void  dissect_netb_datagram( tvbuff_t *tvb, int offset, proto_tree *tree)
592
593 {/* Handle the DATAGRAM command */
594
595         netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
596         /* Weird.  In some datagrams, this is 10 octets of 0, followed
597            by a MAC address.... */
598
599         if (memcmp( tvb_get_ptr( tvb,offset + NB_SENDER_NAME, 10), zeroes, 10) == 0) {
600                 proto_tree_add_text( tree, tvb, offset + NB_SENDER_NAME + 10, 6,
601                     "Sender's MAC Address: %s",
602                     ether_to_str( tvb_get_ptr( tvb,offset + NB_SENDER_NAME + 10, 6)));
603         } else {
604                 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
605                     tree);
606         }
607 }
608
609
610 static void  dissect_netb_datagram_bcast( tvbuff_t *tvb, int offset,
611     proto_tree *tree)
612
613 {/* Handle the DATAGRAM BROADCAST command */
614
615         /* We assume the same weirdness can happen here.... */
616         if ( memcmp( tvb_get_ptr( tvb,offset + NB_SENDER_NAME + 10, 6), zeroes, 10) == 0) {
617                 proto_tree_add_text( tree, tvb, offset + NB_SENDER_NAME + 10, 6,
618                     "Sender's Node Address: %s",
619                     ether_to_str( tvb_get_ptr( tvb,offset + NB_SENDER_NAME + 10, 6)));
620         } else {
621                 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
622                     tree);
623         }
624 }
625
626
627 static void  dissect_netb_name_query( tvbuff_t *tvb, int offset, proto_tree *tree)
628
629 {/* Handle the NAME QUERY command */
630         guint8 local_session_number = tvb_get_guint8( tvb, offset + NB_DATA2);
631
632         if (local_session_number == 0) {
633                 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
634                     "Local Session No.: 0 (FIND.NAME request)");
635         } else {
636                 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
637                     "Local Session No.: 0x%02x", local_session_number);
638         }
639         nb_call_name_type( tvb, offset, tree);
640         nb_resp_corrl( tvb, offset, tree);
641         netbios_add_name("Query Name", tvb, offset + NB_RECVER_NAME, tree);
642         if (local_session_number != 0) {
643                 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
644                     tree);
645         }
646 }
647
648
649 static void  dissect_netb_add_name_resp( tvbuff_t *tvb, int offset,
650     proto_tree *tree)
651
652 {/* Handle the ADD NAME RESPONSE command */
653         guint8 status = tvb_get_guint8( tvb, offset + NB_DATA1);
654         guint16 name_type = tvb_get_letohs( tvb, offset + NB_DATA2);
655
656         switch (status) {
657
658         case 0:
659                 proto_tree_add_text( tree, tvb, offset + NB_DATA1, 1,
660                     "Status: Add name not in process");
661                 break;
662
663         case 1:
664                 proto_tree_add_text( tree, tvb, offset + NB_DATA1, 1,
665                     "Status: Add name in process");
666                 break;
667
668         default:
669                 proto_tree_add_text( tree, tvb, offset + NB_DATA1, 1,
670                     "Status: 0x%02x (should be 0 or 1)", status);
671                 break;
672         }
673
674         switch (name_type) {
675
676         case 0:
677                 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 2,
678                     "Name type: Unique name");
679                 break;
680
681         case 1:
682                 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 2,
683                     "Name type: Group name");
684                 break;
685
686         default:
687                 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 2,
688                     "Name type: 0x%04x (should be 0 or 1)", name_type);
689                 break;
690         }
691
692         nb_xmit_corrl( tvb, offset, tree); 
693         netbios_add_name("Name to be added", tvb, offset + NB_RECVER_NAME,
694             tree);
695         netbios_add_name("Name to be added", tvb, offset + NB_SENDER_NAME,
696             tree);
697 }
698
699
700 static void  dissect_netb_name_resp( tvbuff_t *tvb, int offset,
701     proto_tree *tree)
702
703 {/* Handle the NAME RECOGNIZED command */
704         guint8 local_session_number = tvb_get_guint8( tvb, offset + NB_DATA2);
705
706         switch (local_session_number) {
707
708         case 0x00:
709                 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
710                     "State of name: No LISTEN pending, or FIND.NAME response");
711                 break;
712
713         case 0xFF:
714                 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
715                     "State of name: LISTEN pending, but insufficient resources to establish session");
716                 break;
717
718         default:
719                 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 1,
720                     "Local Session No.: 0x%02x", local_session_number);
721                 break;
722         }
723         nb_call_name_type( tvb, offset, tree);
724         nb_xmit_corrl( tvb, offset, tree);
725         if (local_session_number != 0x00 && local_session_number != 0xFF)
726                 nb_resp_corrl(tvb, offset, tree);
727         netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
728         if (local_session_number != 0x00 && local_session_number != 0xFF) {
729                 netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
730                     tree);
731         }
732 }
733
734
735 static void  dissect_netb_status_resp( tvbuff_t *tvb, int offset, proto_tree *tree)
736
737 {/* Handle the STATUS RESPONSE command */
738         guint8 status_response = tvb_get_guint8( tvb, offset + NB_DATA1);
739         proto_item *td2;
740         proto_tree *data2_tree;
741         guint16 data2;
742
743         nb_call_name_type( tvb, offset, tree);
744         if (status_response == 0) {
745                 proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
746                     "Status response: NetBIOS 1.x or 2.0");
747         } else {
748                 proto_tree_add_text(tree, tvb, offset + NB_DATA1, 1,
749                     "Status response: NetBIOS 2.1, %u names sent so far",
750                     status_response);
751         }
752         data2 = tvb_get_letohs( tvb, offset + NB_DATA2);
753
754         td2 = proto_tree_add_text(tree, tvb, offset + NB_DATA2, 2, "Status: 0x%04x",
755             data2);
756         data2_tree = proto_item_add_subtree(td2, ett_netb_status);
757         if (data2 & 0x8000) {
758                 proto_tree_add_text(data2_tree, tvb, offset, 2, "%s",
759                     decode_boolean_bitfield(data2, 0x8000, 8*2,
760                         "Data length exceeds maximum frame size", NULL));
761         }
762         if (data2 & 0x4000) {
763                 proto_tree_add_text(data2_tree, tvb, offset, 2, "%s",
764                     decode_boolean_bitfield(data2, 0x4000, 8*2,
765                         "Data length exceeds user's buffer", NULL));
766         }
767         proto_tree_add_text(data2_tree, tvb, offset, 2, "%s",
768             decode_numeric_bitfield(data2, 0x3FFF, 2*8,
769                         "Status data length = %u"));
770         nb_xmit_corrl( tvb, offset, tree); 
771         netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
772         netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
773             tree);
774 }
775
776
777 static void  dissect_netb_data_ack( tvbuff_t* tvb, int offset, proto_tree *tree)
778
779 {/* Handle the DATA ACK command */
780
781         nb_xmit_corrl( tvb, offset, tree);
782         nb_remote_session( tvb, offset, tree);
783         nb_local_session( tvb, offset, tree);
784 }
785
786
787 static void  dissect_netb_data_first_middle( tvbuff_t *tvb, int offset,
788     proto_tree *tree)
789
790 {/* Handle the DATA FIRST MIDDLE command */
791
792         netbios_data_first_middle_flags( tvb, tree, offset + NB_FLAGS);
793
794         nb_resync_indicator( tvb, offset, tree, "DATA FIRST MIDDLE");
795         nb_xmit_corrl( tvb, offset, tree);
796         nb_resp_corrl( tvb, offset, tree);
797         nb_remote_session( tvb, offset, tree);
798         nb_local_session( tvb, offset, tree);
799 }
800
801
802 static void  dissect_netb_data_only_last( tvbuff_t *tvb, int offset,
803     proto_tree *tree)
804
805 {/* Handle the DATA ONLY LAST command */
806
807         netbios_data_only_flags( tvb, tree, offset + NB_FLAGS);
808
809         nb_resync_indicator( tvb, offset, tree, "DATA ONLY LAST");
810         nb_xmit_corrl( tvb, offset, tree);
811         nb_resp_corrl( tvb, offset, tree);
812         nb_remote_session( tvb, offset, tree);
813         nb_local_session( tvb, offset, tree);
814 }
815
816
817 static void  dissect_netb_session_confirm( tvbuff_t *tvb, int offset,
818     proto_tree *tree)
819
820 {/* Handle the SESSION CONFIRM command */
821
822         netbios_add_ses_confirm_flags( tvb, tree, offset + NB_FLAGS);
823
824         nb_data2("Max data recv size: %u", 2, tvb, offset, tree);
825         nb_xmit_corrl( tvb, offset, tree);
826         nb_resp_corrl( tvb, offset, tree);
827         nb_remote_session( tvb, offset, tree);
828         nb_local_session( tvb, offset, tree);
829 }
830
831
832 static void  dissect_netb_session_end( tvbuff_t *tvb, int offset,
833     proto_tree *tree)
834
835 {/* Handle the SESSION END command */
836         guint16 termination_indicator = tvb_get_letohs( tvb, offset + NB_DATA2);
837
838         switch (termination_indicator) {
839
840         case 0x0000:
841                 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 2,
842                     "Termination indicator: Normal session end");
843                 break;
844
845         case 0x0001:
846                 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 2,
847                     "Termination indicator: Abormal session end");
848                 break;
849
850         default:
851                 proto_tree_add_text( tree, tvb, offset + NB_DATA2, 2,
852                     "Termination indicator: 0x%04x (should be 0x0000 or 0x0001)",
853                     termination_indicator);
854                 break;
855         }
856
857         nb_remote_session( tvb, offset, tree);
858         nb_local_session( tvb, offset, tree);
859 }
860
861
862 static void  dissect_netb_session_init( tvbuff_t *tvb, int offset,
863     proto_tree *tree)
864
865 {/* Handle the SESSION INITIALIZE command */
866
867         netbios_add_session_init_flags( tvb, tree, offset + NB_FLAGS);
868
869         nb_data2("Max data recv size: %u", 2, tvb, offset, tree);
870         nb_resp_corrl( tvb, offset, tree);
871         nb_xmit_corrl( tvb, offset, tree);
872         nb_remote_session( tvb, offset, tree);
873         nb_local_session( tvb, offset, tree);
874 }
875
876 static void  dissect_netb_no_receive( tvbuff_t *tvb, int offset,
877     proto_tree *tree)
878
879 {/* Handle the NO RECEIVE command */
880
881         netbios_no_receive_flags( tvb, tree, offset + NB_FLAGS);
882
883         nb_data2("Number of data bytes accepted: %u", 2, tvb, offset, tree);
884         nb_remote_session( tvb, offset, tree);
885         nb_local_session( tvb, offset, tree);
886 }
887
888
889 static void  dissect_netb_receive_outstanding( tvbuff_t *tvb, int offset,
890     proto_tree *tree)
891
892 {/* Handle the RECEIVE OUTSTANDING command */
893
894         nb_data2("Number of data bytes accepted: %u", 2, tvb, offset, tree);
895         nb_remote_session( tvb, offset, tree);
896         nb_local_session( tvb, offset, tree);
897 }
898
899
900 static void  dissect_netb_receive_continue( tvbuff_t *tvb, int offset,
901     proto_tree *tree)
902
903 {/* Handle the RECEIVE CONTINUE command */
904
905         nb_xmit_corrl( tvb, offset, tree);
906         nb_remote_session( tvb, offset, tree);
907         nb_local_session( tvb, offset, tree);
908 }
909
910
911 /************************************************************************/
912 /*                                                                      */
913 /*  The table routines called by the top level to handle commands       */
914 /*                                                                      */
915 /************************************************************************/
916
917
918 void (*dissect_netb[])(tvbuff_t *, int, proto_tree *) = {
919
920   dissect_netb_add_group_name,  /* Add Group Name       0x00 */
921   dissect_netb_add_name,        /* Add Name             0x01 */
922   dissect_netb_name_in_conflict,/* Name In Conflict     0x02 */
923   dissect_netb_status_query,    /* Status Query         0x03 */
924   dissect_netb_unknown,         /* unknown              0x04 */
925   dissect_netb_unknown,         /* unknown              0x05 */
926   dissect_netb_unknown,         /* unknown              0x06 */
927   dissect_netb_unknown,         /* Terminate Trace      0x07 */
928   dissect_netb_datagram,        /* Datagram             0x08 */
929   dissect_netb_datagram_bcast,  /* Datagram Broadcast   0x09 */
930   dissect_netb_name_query,      /* Name Query           0x0A */
931   dissect_netb_unknown,         /* unknown              0x0B */
932   dissect_netb_unknown,         /* unknown              0x0C */
933   dissect_netb_add_name_resp,   /* Add Name Response    0x0D */
934   dissect_netb_name_resp,       /* Name Recognized      0x0E */
935   dissect_netb_status_resp,     /* Status Response      0x0F */
936   dissect_netb_unknown,         /* unknown              0x10 */
937   dissect_netb_unknown,         /* unknown              0x11 */
938   dissect_netb_unknown,         /* unknown              0x12 */
939   dissect_netb_unknown,         /* Terminate Trace      0x13 */
940   dissect_netb_data_ack,        /* Data Ack             0x14 */
941   dissect_netb_data_first_middle,/* Data First Middle   0x15 */
942   dissect_netb_data_only_last,  /* Data Only Last       0x16 */
943   dissect_netb_session_confirm, /* Session Confirm      0x17 */
944   dissect_netb_session_end,     /* Session End          0x18 */
945   dissect_netb_session_init,    /* Session Initialize   0x19 */
946   dissect_netb_no_receive,      /* No Receive           0x1A */
947   dissect_netb_receive_outstanding,/* Receive Outstanding 0x1B */
948   dissect_netb_receive_continue,/* Receive Continue     0x1C */
949   dissect_netb_unknown,         /* unknown              0x1D */
950   dissect_netb_unknown,         /* unknown              0x1E */
951
952   dissect_netb_unknown,         /* Session Alive        0x1f (nothing to do) */
953   dissect_netb_unknown, 
954 };
955
956 static heur_dissector_list_t netbios_heur_subdissector_list;
957
958 void
959 dissect_netbios_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
960 {
961         /*
962          * Try the heuristic dissectors for NetBIOS; if none of them
963          * accept the packet, dissect it as data.
964          */
965         if (!dissector_try_heuristic(netbios_heur_subdissector_list,
966                                     tvb, pinfo, tree))
967                 dissect_data(tvb, 0, pinfo, tree);
968 }
969
970 static void
971 dissect_netbios(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
972
973 {
974         proto_tree              *netb_tree;
975         proto_item              *ti;
976         guint16                 hdr_len, command;
977         char                    name[(NETBIOS_NAME_LEN - 1)*4 + 1];
978         int                     name_type;
979         tvbuff_t                *next_tvb;
980
981         int offset = 0;
982
983                                         /* load the display labels      */
984         if (check_col(pinfo->fd, COL_PROTOCOL))
985                 col_set_str(pinfo->fd, COL_PROTOCOL, "NetBIOS");
986
987
988 /* Find NetBIOS marker EFFF, this is done because I have seen an extra LLC */
989 /* byte on our network. This only checks for one extra LLC byte. */
990
991         if ( 0xefff != tvb_get_letohs(tvb, 2)){
992                 ++offset;
993                 if ( 0xefff != tvb_get_letohs(tvb, 3)){
994
995                         if (check_col( pinfo->fd, COL_INFO))    /* print bad packet */
996                                 col_set_str( pinfo->fd, COL_INFO, "Bad packet, no 0xEFFF marker");
997
998                         return;         /* this is an unknow packet, no marker */
999                 }
1000         }
1001
1002
1003         hdr_len = tvb_get_letohs(tvb, offset + NB_LENGTH);
1004         command = tvb_get_guint8( tvb, offset + NB_COMMAND);
1005                                         /* limit command so no table overflows */
1006         command = MIN( command, sizeof( dissect_netb)/ sizeof(void *));
1007
1008         if (check_col( pinfo->fd, COL_INFO)) {              /* print command name */
1009                 switch ( command ) {
1010                 case NB_NAME_QUERY:
1011                         name_type = get_netbios_name( tvb, offset + 12, name);
1012                         col_add_fstr( pinfo->fd, COL_INFO, "%s for %s<%02x>",
1013                             CommandName[ command], name, name_type);
1014                         break;
1015
1016                 case NB_NAME_RESP:
1017                 case NB_ADD_NAME:
1018                 case NB_ADD_GROUP:
1019                         name_type = get_netbios_name( tvb, offset + 28, name);
1020                         col_add_fstr( pinfo->fd, COL_INFO, "%s - %s<%02x>",
1021                             CommandName[ command], name, name_type);
1022                         break;
1023
1024                 default:
1025                         col_add_fstr( pinfo->fd, COL_INFO, "%s", CommandName[ command]);
1026                         break;
1027                 }
1028         }
1029
1030         if ( tree) {
1031                 ti = proto_tree_add_item(tree, proto_netbios, tvb, 0, hdr_len, FALSE);
1032                 netb_tree = proto_item_add_subtree(ti, ett_netb);
1033
1034                 proto_tree_add_uint_format(netb_tree, hf_netb_hdr_len, tvb, offset, 2, hdr_len,
1035                         "Length: %d bytes", hdr_len);
1036
1037                 proto_tree_add_text(netb_tree, tvb, offset + 2, 2,
1038                         "Delimiter: EFFF (NetBIOS)");
1039
1040                 proto_tree_add_uint_format(netb_tree, hf_netb_cmd, tvb, offset + NB_COMMAND, 1, command,
1041                         "Command: 0x%02x (%s)", command, CommandName[ command]);
1042
1043                                                 /* if command in table range */
1044                 if ( command < sizeof( dissect_netb)/ sizeof(void *))
1045
1046                                                 /* branch to handle commands */
1047                         (dissect_netb[ command])( tvb, offset, netb_tree);              
1048         }
1049
1050         offset += hdr_len;                      /* move past header */
1051
1052         next_tvb = tvb_new_subset(tvb, offset, -1, -1);
1053         dissect_netbios_payload(next_tvb, pinfo, tree);
1054 }
1055
1056
1057 void proto_register_netbios(void)
1058 {
1059         static gint *ett[] = {
1060                 &ett_netb,
1061                 &ett_netb_name,
1062                 &ett_netb_flags,
1063                 &ett_netb_status,
1064         };
1065
1066         static hf_register_info hf_netb[] = {
1067                 { &hf_netb_cmd,
1068                 { "Command", "netbios.command", FT_UINT16, BASE_HEX, NULL, 0x0,
1069                         "", HFILL }},
1070                 { &hf_netb_hdr_len,
1071                 { "Header Length", "netbios.hdr_len", FT_UINT16, BASE_DEC, NULL, 0x0,
1072                         "", HFILL }},
1073
1074                 { &hf_netb_xmit_corrl,
1075                 { "Transmit Correlator", "netbios.xmit_corrl", FT_INT16, BASE_HEX, NULL, 0x0,
1076                         "", HFILL }},
1077
1078                 { &hf_netb_resp_corrl,
1079                 { "Response Correlator", "netbios.resp_corrl", FT_INT16, BASE_HEX, NULL, 0x0,
1080                         "", HFILL }},
1081                 { &hf_netb_call_name_type,
1082                 { "Call Name Type", "netbios.call_name_type", FT_INT16, BASE_HEX, NULL, 0x0,
1083                         "", HFILL }},
1084                 { &hf_netb_name_type,
1085                 { "Netbios Name Type", "netbios.name_type", FT_UINT16, BASE_HEX, NULL, 0x0,
1086                         "", HFILL }},
1087                 { &hf_netb_name,
1088                 { "Netbios Name", "netbios.name", FT_STRING, BASE_NONE, NULL, 0x0,
1089                         "", HFILL }},
1090
1091                 { &hf_netb_ack,
1092                 { "Acknowledge", "netbios.ack", FT_BOOLEAN, 8, TFS( &flags_set), 0x08,
1093                         "", HFILL }},
1094
1095                 { &hf_netb_ack_with_data,
1096                 { "Acknowledge with data", "netbios.ack_with_data", FT_BOOLEAN, 8, TFS( &flags_allowed), 0x04, 
1097                         "", HFILL }},
1098
1099                 { &hf_netb_ack_expected,
1100                 { "Acknowledge expected", "netbios.ack_expected", FT_BOOLEAN,  8,
1101                         TFS( &flags_yes_no), 0x02, "", HFILL }},
1102
1103                 { &hf_netb_recv_cont_req,
1104                 { "RECEIVE_CONTINUE requested", "netbios.recv_cont_req", FT_BOOLEAN,  8,
1105                         TFS( &flags_yes_no), 0x01, "", HFILL }},
1106
1107                 { &hf_netb_send_no_ack,
1108                 { "Handle SEND.NO.ACK", "netbios.send_no_ack", FT_BOOLEAN,  8,
1109                         TFS( &flags_yes_no), 0x80, "", HFILL }},
1110
1111                 { &hf_netb_version,
1112                 { "NetBIOS Version", "netbios.version", FT_BOOLEAN,  8,
1113                         TFS( &netb_version_str), 0x01, "", HFILL }},
1114
1115                 { &hf_netb_largest_frame,
1116                 { "Largest Frame", "netbios.largest_frame", FT_UINT8, BASE_HEX, NULL, 0x0E,
1117                         "", HFILL }},
1118
1119                 { &hf_netb_local_ses_no,
1120                 { "Local Session No. ", "netbios.local_session", FT_UINT8, BASE_HEX, NULL, 0x0,
1121                         "", HFILL }},
1122
1123                 { &hf_netb_remote_ses_no,
1124                 { "Remote Session No. ", "netbios.remote_session", FT_UINT8, BASE_HEX, NULL, 0x0,
1125                         "", HFILL }},
1126
1127                 { &hf_netb_data2,
1128                 { "DATA2 value ", "netbios.data2", FT_UINT16, BASE_HEX, NULL, 0x0,
1129                         "", HFILL }},
1130                 };
1131
1132         proto_netbios = proto_register_protocol("NetBIOS", "NetBIOS", "netbios");
1133         proto_register_subtree_array(ett, array_length(ett));                 
1134         proto_register_field_array(proto_netbios, hf_netb, array_length(hf_netb));
1135
1136         register_heur_dissector_list("netbios", &netbios_heur_subdissector_list);
1137 }
1138
1139 void
1140 proto_reg_handoff_netbios(void)
1141 {
1142         dissector_add("llc.dsap", SAP_NETBIOS, dissect_netbios, proto_netbios);
1143 }