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