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