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