Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-netbios.c
Line
Count
Source
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
 * Wireshark - Network traffic analyzer
9
 * By Gerald Combs <gerald@wireshark.org>
10
 * Copyright 1998 Gerald Combs
11
 *
12
 * SPDX-License-Identifier: GPL-2.0-or-later
13
 */
14
15
#include "config.h"
16
17
#include <epan/packet.h>
18
#include <epan/capture_dissectors.h>
19
#include <epan/reassemble.h>
20
#include <epan/prefs.h>
21
#include <epan/expert.h>
22
#include <epan/tfs.h>
23
#include <wsutil/array.h>
24
#include "packet-netbios.h"
25
#include "packet-llc.h"
26
27
28
void proto_register_netbios(void);
29
void proto_reg_handoff_netbios(void);
30
31
static dissector_handle_t netbios_handle;
32
static capture_dissector_handle_t netbios_cap_handle;
33
34
/* Netbios command numbers */
35
0
#define NB_ADD_GROUP    0x00
36
0
#define NB_ADD_NAME   0x01
37
#define NB_NAME_IN_CONFLICT 0x02
38
#define NB_STATUS_QUERY   0x03
39
#define NB_TERMINATE_TRACE_R  0x07
40
0
#define NB_DATAGRAM   0x08
41
0
#define NB_DATAGRAM_BCAST 0x09
42
0
#define NB_NAME_QUERY   0x0a
43
#define NB_ADD_NAME_RESP  0x0d
44
0
#define NB_NAME_RESP    0x0e
45
#define NB_STATUS_RESP    0x0f
46
#define NB_TERMINATE_TRACE_LR 0x13
47
#define NB_DATA_ACK   0x14
48
0
#define NB_DATA_FIRST_MIDDLE  0x15
49
0
#define NB_DATA_ONLY_LAST 0x16
50
#define NB_SESSION_CONFIRM  0x17
51
#define NB_SESSION_END    0x18
52
#define NB_SESSION_INIT   0x19
53
#define NB_NO_RECEIVE   0x1a
54
#define NB_RECEIVE_OUTSTANDING  0x1b
55
#define NB_RECEIVE_CONTINUE 0x1c
56
#define NB_KEEP_ALIVE   0x1f
57
58
/* Offsets of fields in the NetBIOS header. */
59
1
#define NB_LENGTH    0
60
#define NB_DELIMITER     2
61
1
#define NB_COMMAND     4
62
0
#define NB_FLAGS     5
63
0
#define NB_DATA1     5
64
#define NB_RESYNC    6
65
0
#define NB_DATA2     6
66
0
#define NB_CALL_NAME_TYPE  7
67
0
#define NB_XMIT_CORL     8
68
0
#define NB_RESP_CORL    10
69
0
#define NB_RMT_SES    12
70
0
#define NB_LOCAL_SES    13
71
0
#define NB_RECVER_NAME    12
72
0
#define NB_SENDER_NAME    28
73
74
75
static int proto_netbios;
76
static int hf_netb_cmd;
77
static int hf_netb_hdr_len;
78
static int hf_netb_delimiter;
79
static int hf_netb_xmit_corrl;
80
static int hf_netb_resp_corrl;
81
static int hf_netb_call_name_type;
82
static int hf_netb_version;
83
static int hf_netbios_no_receive_flags;
84
static int hf_netbios_no_receive_flags_send_no_ack;
85
static int hf_netb_largest_frame;
86
static int hf_netb_nb_name;
87
static int hf_netb_nb_name_type;
88
static int hf_netb_status_buffer_len;
89
static int hf_netb_status;
90
static int hf_netb_name_type;
91
static int hf_netb_max_data_recv_size;
92
static int hf_netb_termination_indicator;
93
static int hf_netb_num_data_bytes_accepted;
94
static int hf_netb_local_ses_no;
95
static int hf_netb_remote_ses_no;
96
static int hf_netb_flags;
97
static int hf_netb_flags_send_no_ack;
98
static int hf_netb_flags_ack;
99
static int hf_netb_flags_ack_with_data;
100
static int hf_netb_flags_ack_expected;
101
static int hf_netb_flags_recv_cont_req;
102
static int hf_netb_data2;
103
static int hf_netb_data2_frame;
104
static int hf_netb_data2_user;
105
static int hf_netb_data2_status;
106
static int hf_netb_datagram_mac;
107
static int hf_netb_datagram_bcast_mac;
108
static int hf_netb_resync_indicator;
109
static int hf_netb_status_request;
110
static int hf_netb_local_session_no;
111
static int hf_netb_state_of_name;
112
static int hf_netb_status_response;
113
static int hf_netb_fragments;
114
static int hf_netb_fragment;
115
static int hf_netb_fragment_overlap;
116
static int hf_netb_fragment_overlap_conflict;
117
static int hf_netb_fragment_multiple_tails;
118
static int hf_netb_fragment_too_long_fragment;
119
static int hf_netb_fragment_error;
120
static int hf_netb_fragment_count;
121
static int hf_netb_reassembled_length;
122
123
static int ett_netb;
124
static int ett_netb_name;
125
static int ett_netb_flags;
126
static int ett_netb_status;
127
static int ett_netb_fragments;
128
static int ett_netb_fragment;
129
130
static expert_field ei_netb_unknown_command_data;
131
132
static const fragment_items netbios_frag_items = {
133
  &ett_netb_fragment,
134
  &ett_netb_fragments,
135
  &hf_netb_fragments,
136
  &hf_netb_fragment,
137
  &hf_netb_fragment_overlap,
138
  &hf_netb_fragment_overlap_conflict,
139
  &hf_netb_fragment_multiple_tails,
140
  &hf_netb_fragment_too_long_fragment,
141
  &hf_netb_fragment_error,
142
  &hf_netb_fragment_count,
143
  NULL,
144
  &hf_netb_reassembled_length,
145
  /* Reassembled data field */
146
  NULL,
147
  "fragments"
148
};
149
150
/* The strings for the station type, used by get_netbios_name function;
151
   many of them came from the file "NetBIOS.txt" in the Zip archive at
152
153
  http://www.net3group.com/ftp/browser.zip
154
 */
155
156
static const value_string nb_name_type_vals[] = {
157
  {0x00,  "Workstation/Redirector"},
158
  {0x01,  "Browser"},
159
  {0x02,  "Workstation/Redirector"},
160
    /* not sure what 0x02 is, I'm seeing a lot of them however */
161
    /* I'm seeing them with workstation/redirection host
162
      announcements */
163
  {0x03,  "Messenger service/Main name"},
164
  {0x05,  "Forwarded name"},
165
  {0x06,  "RAS Server service"},
166
  {0x1b,  "Domain Master Browser"},
167
  {0x1c,  "Domain Controllers"},
168
  {0x1d,  "Local Master Browser"},
169
  {0x1e,  "Browser Election Service"},
170
  {0x1f,  "Net DDE Service"},
171
  {0x20,  "Server service"},
172
  {0x21,  "RAS client service"},
173
  {0x22,  "Exchange Interchange (MSMail Connector)"},
174
  {0x23,  "Exchange Store"},
175
  {0x24,  "Exchange Directory"},
176
  {0x2b,  "Lotus Notes Server service"},
177
  {0x30,  "Modem sharing server service"},
178
  {0x31,  "Modem sharing client service"},
179
  {0x43,  "SMS Clients Remote Control"},
180
  {0x44,  "SMS Administrators Remote Control Tool"},
181
  {0x45,  "SMS Clients Remote Chat"},
182
  {0x46,  "SMS Clients Remote Transfer"},
183
  {0x4c,  "DEC Pathworks TCP/IP Service on Windows NT"},
184
  {0x52,  "DEC Pathworks TCP/IP Service on Windows NT"},
185
  {0x6a,  "Microsoft Exchange IMC"},
186
  {0x87,  "Microsoft Exchange MTA"},
187
  {0xbe,  "Network Monitor Agent"},
188
  {0xbf,  "Network Monitor Analyzer"},
189
  {0x00,  NULL}
190
};
191
static value_string_ext nb_name_type_vals_ext = VALUE_STRING_EXT_INIT(nb_name_type_vals);
192
193
/* Table for reassembly of fragments. */
194
static reassembly_table netbios_reassembly_table;
195
196
/* defragmentation of NetBIOS Frame */
197
static bool netbios_defragment = true;
198
199
/* See
200
201
  http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/BK8P7001/CCONTENTS
202
203
   and
204
205
  http://ourworld.compuserve.com/homepages/TimothyDEvans/contents.htm
206
207
   for information about the NetBIOS Frame Protocol (which is what this
208
   module dissects). */
209
210
/* the strings for the command types  */
211
212
static const value_string cmd_vals[] = {
213
  { NB_ADD_GROUP,     "Add Group Name Query" },
214
  { NB_ADD_NAME,      "Add Name Query" },
215
  { NB_NAME_IN_CONFLICT,    "Name In Conflict" },
216
  { NB_STATUS_QUERY,    "Status Query" },
217
  { NB_TERMINATE_TRACE_R,   "Terminate Trace" },
218
  { NB_DATAGRAM,      "Datagram" },
219
  { NB_DATAGRAM_BCAST,    "Broadcast Datagram" },
220
  { NB_NAME_QUERY,    "Name Query" },
221
  { NB_ADD_NAME_RESP,   "Add Name Response" },
222
  { NB_NAME_RESP,     "Name Recognized" },
223
  { NB_STATUS_RESP,   "Status Response" },
224
  { NB_TERMINATE_TRACE_LR,  "Terminate Trace" },
225
  { NB_DATA_ACK,      "Data Ack" },
226
  { NB_DATA_FIRST_MIDDLE,   "Data First Middle" },
227
  { NB_DATA_ONLY_LAST,    "Data Only Last" },
228
  { NB_SESSION_CONFIRM,   "Session Confirm" },
229
  { NB_SESSION_END,   "Session End" },
230
  { NB_SESSION_INIT,    "Session Initialize" },
231
  { NB_NO_RECEIVE,    "No Receive" },
232
  { NB_RECEIVE_OUTSTANDING, "Receive Outstanding" },
233
  { NB_RECEIVE_CONTINUE,    "Receive Continue" },
234
  { NB_KEEP_ALIVE,    "Session Alive" },
235
  { 0,        NULL }
236
};
237
static value_string_ext cmd_vals_ext = VALUE_STRING_EXT_INIT(cmd_vals);
238
239
static const value_string name_types[] = {
240
  { 0, "Unique name" },
241
  { 1, "Group name" },
242
  { 0, NULL }
243
};
244
245
246
static const true_false_string netb_version_str = {
247
  "2.00 or higher",
248
  "1.xx"
249
};
250
251
static const value_string termination_indicator_vals[] = {
252
  { 0x0000, "Normal session end" },
253
  { 0x0001, "Abnormal session end" },
254
  { 0,      NULL }
255
};
256
257
static const value_string status_vals[] = {
258
  { 0, "Add name not in process" },
259
  { 1, "Add name in process" },
260
  { 0, NULL }
261
};
262
263
static const value_string max_frame_size_vals[] = {
264
  { 0,  "516" },
265
  { 1,  "1500" },
266
  { 2,  "2052" },
267
  { 3,  "4472" },
268
  { 4,  "8144" },
269
  { 5,  "11407" },
270
  { 6,  "17800" },  /* 17800 in TR spec, 17749 in NBF spec */
271
  { 7,  "65535" },
272
  { 0,  NULL }
273
};
274
275
276
static bool
277
capture_netbios(const unsigned char *pd _U_, int offset _U_, int len _U_, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header _U_)
278
0
{
279
0
  capture_dissector_increment_count(cpinfo, proto_netbios);
280
0
  return true;
281
0
}
282
283
284
unsigned
285
process_netbios_name(const unsigned char *name_ptr, char *name_ret, unsigned name_ret_len)
286
705
{
287
705
  int    i;
288
705
  int    name_type = *(name_ptr + NETBIOS_NAME_LEN - 1);
289
705
  unsigned char name_char;
290
705
  char  *name_ret_orig = name_ret;
291
705
  static const char hex_digits[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
292
293
11.2k
  for (i = 0; i < NETBIOS_NAME_LEN - 1; i++) {
294
10.5k
    name_char = *name_ptr++;
295
10.5k
    if (name_char >= ' ' && name_char <= '~') {
296
3.25k
      if (--name_ret_len > 0)
297
3.16k
        *name_ret++ = name_char;
298
7.31k
    } else {
299
      /* It's not printable; show it as <XX>, where
300
         XX is the value in hex. */
301
7.31k
      if (--name_ret_len > 0)
302
7.18k
        *name_ret++ = '<';
303
7.31k
      if (--name_ret_len > 0)
304
7.25k
        *name_ret++ = hex_digits[(name_char >> 4)];
305
7.31k
      if (--name_ret_len > 0)
306
7.12k
        *name_ret++ = hex_digits[(name_char & 0x0F)];
307
7.31k
      if (--name_ret_len > 0)
308
7.29k
        *name_ret++ = '>';
309
7.31k
    }
310
10.5k
  }
311
705
  *name_ret = '\0';
312
313
  /* Remove trailing space characters from name. */
314
315
705
  name_ret--;
316
317
1.19k
  while (name_ret >= name_ret_orig) {
318
1.16k
    if (*name_ret != ' ') {
319
681
      *(name_ret + 1) = 0;
320
681
      break;
321
681
    }
322
486
    name_ret--;
323
486
  }
324
325
705
  return name_type;
326
705
}
327
328
329
unsigned
330
get_netbios_name( tvbuff_t *tvb, unsigned offset, char *name_ret, unsigned name_ret_len)
331
332
219
{/*  Extract the name string and name type.  Return the name string in  */
333
 /* name_ret and return the name_type. */
334
335
219
  return process_netbios_name( tvb_get_ptr( tvb, offset, NETBIOS_NAME_LEN ), name_ret, name_ret_len);
336
219
}
337
338
339
/*
340
 * Get a string describing the type of a NetBIOS name.
341
 */
342
const char *
343
netbios_name_type_descr(int name_type)
344
345
613
{
346
613
  return val_to_str_ext_const(name_type, &nb_name_type_vals_ext, "Unknown");
347
613
}
348
349
void
350
netbios_add_name(const char* label, tvbuff_t *tvb, unsigned offset, proto_tree *tree)
351
352
89
{/* add a name field display tree. Display the name and station type in sub-tree */
353
354
89
  proto_tree *field_tree;
355
89
  char        name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
356
89
  int         name_type;
357
89
  const char *name_type_str;
358
359
          /* decode the name field */
360
89
  name_type = get_netbios_name( tvb, offset, name_str, (NETBIOS_NAME_LEN - 1)*4 + 1);
361
89
  name_type_str = netbios_name_type_descr(name_type);
362
89
  field_tree = proto_tree_add_subtree_format( tree, tvb, offset, NETBIOS_NAME_LEN,
363
89
      ett_netb_name, NULL, "%s: %s<%02x> (%s)", label, name_str, name_type, name_type_str);
364
365
89
  proto_tree_add_string_format( field_tree, hf_netb_nb_name, tvb, offset,
366
89
    15, name_str, "%s", name_str);
367
89
  proto_tree_add_uint_format( field_tree, hf_netb_nb_name_type, tvb, offset + 15, 1, name_type,
368
89
    "0x%02x (%s)", name_type, name_type_str);
369
89
}
370
371
372
static void
373
netbios_data_first_middle_flags( tvbuff_t *tvb, proto_tree *tree, unsigned offset)
374
375
0
{
376
0
  proto_tree *field_tree;
377
0
  proto_item *tf;
378
379
    /* decode the flag field for Data First Middle packet*/
380
381
0
  tf = proto_tree_add_item(tree, hf_netb_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
382
0
  field_tree = proto_item_add_subtree(tf, ett_netb_flags);
383
384
0
  proto_tree_add_item( field_tree, hf_netb_flags_ack, tvb, offset, 1, ENC_LITTLE_ENDIAN);
385
386
0
  proto_tree_add_item( field_tree, hf_netb_flags_ack_expected, tvb, offset, 1, ENC_LITTLE_ENDIAN);
387
388
0
  proto_tree_add_item( field_tree, hf_netb_flags_recv_cont_req, tvb, offset, 1, ENC_LITTLE_ENDIAN);
389
0
}
390
391
static void
392
netbios_data_only_flags( tvbuff_t *tvb, proto_tree *tree, unsigned offset)
393
394
0
{
395
0
  proto_tree *field_tree;
396
0
  proto_item *tf;
397
398
  /* decode the flag field for Data Only Last packet*/
399
0
  tf = proto_tree_add_item(tree, hf_netb_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
400
0
  field_tree = proto_item_add_subtree(tf, ett_netb_flags);
401
402
0
  proto_tree_add_item( field_tree, hf_netb_flags_ack, tvb, offset, 1, ENC_LITTLE_ENDIAN);
403
404
0
  proto_tree_add_item( field_tree, hf_netb_flags_ack_with_data, tvb, offset, 1, ENC_LITTLE_ENDIAN);
405
406
0
  proto_tree_add_item( field_tree, hf_netb_flags_ack_expected, tvb, offset, 1, ENC_LITTLE_ENDIAN);
407
0
}
408
409
410
411
static void
412
netbios_add_ses_confirm_flags( tvbuff_t *tvb, proto_tree *tree, unsigned offset)
413
414
0
{
415
0
  proto_tree *field_tree;
416
0
  proto_item *tf;
417
418
  /* decode the flag field for Session Confirm packet */
419
0
  tf = proto_tree_add_item(tree, hf_netb_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
420
0
  field_tree = proto_item_add_subtree( tf, ett_netb_flags);
421
422
0
  proto_tree_add_item( field_tree, hf_netb_flags_send_no_ack, tvb, offset, 1, ENC_LITTLE_ENDIAN);
423
424
0
  proto_tree_add_item( field_tree, hf_netb_version, tvb, offset, 1, ENC_LITTLE_ENDIAN);
425
0
}
426
427
428
static void
429
netbios_add_session_init_flags( tvbuff_t *tvb, proto_tree *tree, unsigned offset)
430
431
0
{
432
0
  proto_tree *field_tree;
433
0
  proto_item *tf;
434
435
  /* decode the flag field for Session Init packet */
436
0
  tf = proto_tree_add_item(tree, hf_netb_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
437
0
  field_tree = proto_item_add_subtree(tf, ett_netb_flags);
438
439
0
  proto_tree_add_item( field_tree, hf_netb_flags_send_no_ack, tvb, offset, 1, ENC_LITTLE_ENDIAN);
440
441
0
  proto_tree_add_item( field_tree, hf_netb_largest_frame, tvb, offset, 1, ENC_LITTLE_ENDIAN);
442
443
0
  proto_tree_add_item( field_tree, hf_netb_version, tvb, offset, 1, ENC_LITTLE_ENDIAN);
444
0
}
445
446
447
static void
448
netbios_no_receive_flags( tvbuff_t *tvb, proto_tree *tree, unsigned offset)
449
450
0
{
451
0
  proto_tree *field_tree;
452
0
  proto_item *tf;
453
454
  /* decode the flag field for No Receive packet*/
455
0
  tf = proto_tree_add_item(tree, hf_netbios_no_receive_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
456
0
  field_tree = proto_item_add_subtree(tf, ett_netb_flags);
457
0
  proto_tree_add_item(field_tree, hf_netbios_no_receive_flags_send_no_ack, tvb, offset, 1, ENC_LITTLE_ENDIAN);
458
0
}
459
460
461
/************************************************************************/
462
/*                  */
463
/*  The routines to display the netbios field values in the tree  */
464
/*                  */
465
/************************************************************************/
466
467
468
static void
469
nb_xmit_corrl( tvbuff_t *tvb, unsigned offset, proto_tree *tree)
470
471
0
{/* display the transmit correlator */
472
473
0
  proto_tree_add_item( tree, hf_netb_xmit_corrl, tvb, offset + NB_XMIT_CORL,
474
0
    2, ENC_LITTLE_ENDIAN);
475
0
}
476
477
478
static void
479
nb_resp_corrl( tvbuff_t *tvb, unsigned offset, proto_tree *tree)
480
481
0
{/* display the response correlator */
482
483
0
  proto_tree_add_item( tree, hf_netb_resp_corrl, tvb, offset + NB_RESP_CORL,
484
0
    2, ENC_LITTLE_ENDIAN);
485
0
}
486
487
488
static void
489
nb_call_name_type( tvbuff_t *tvb, unsigned offset, proto_tree *tree)
490
491
0
{/* display the call name type */
492
493
0
  proto_tree_add_item( tree, hf_netb_call_name_type, tvb, offset + NB_CALL_NAME_TYPE,
494
0
    1, ENC_LITTLE_ENDIAN);
495
496
0
}
497
498
499
static uint8_t
500
nb_local_session( tvbuff_t *tvb, unsigned offset, proto_tree *tree)
501
502
0
{/* add the local session to tree, and return its value */
503
504
0
  uint8_t local_session = tvb_get_uint8( tvb, offset + NB_LOCAL_SES);
505
506
0
  proto_tree_add_uint( tree, hf_netb_local_ses_no, tvb, offset + NB_LOCAL_SES, 1,
507
0
    local_session);
508
509
0
  return local_session;
510
0
}
511
512
513
static uint8_t
514
nb_remote_session( tvbuff_t *tvb, unsigned offset, proto_tree *tree)
515
516
0
{/* add the remote session to tree, and return its value */
517
518
0
  uint8_t remote_session = tvb_get_uint8( tvb, offset + NB_RMT_SES);
519
520
0
  proto_tree_add_uint( tree, hf_netb_remote_ses_no, tvb, offset + NB_RMT_SES, 1,
521
0
    remote_session);
522
523
0
  return remote_session;
524
0
}
525
526
527
static void
528
nb_data1(int hf, tvbuff_t *tvb, unsigned offset, proto_tree *tree)
529
530
0
{/* add the DATA1 to tree with specified hf_ value */
531
532
0
  proto_tree_add_item( tree, hf, tvb, offset + NB_DATA1, 1, ENC_LITTLE_ENDIAN);
533
534
0
}
535
536
537
static void
538
nb_data2(int hf, tvbuff_t *tvb, unsigned offset, proto_tree *tree)
539
540
0
{/* add the DATA2 to tree with specified hf_ value */
541
542
0
  proto_tree_add_item( tree, hf, tvb, offset + NB_DATA2, 2, ENC_LITTLE_ENDIAN);
543
544
0
}
545
546
547
static void
548
nb_resync_indicator( tvbuff_t *tvb, unsigned offset, proto_tree *tree, const char *cmd_str)
549
550
0
{
551
0
  uint16_t resync_indicator = tvb_get_letohs( tvb, offset + NB_DATA2);
552
553
554
0
  switch (resync_indicator) {
555
556
0
  case 0x0000:
557
0
    proto_tree_add_uint_format_value(tree, hf_netb_resync_indicator, tvb, offset + NB_DATA2, 2,
558
0
        resync_indicator, "No re-sync");
559
0
    break;
560
561
0
  case 0x0001:
562
0
    proto_tree_add_uint_format_value(tree, hf_netb_resync_indicator, tvb, offset + NB_DATA2, 2,
563
0
        resync_indicator, "First '%s' following 'Receive Outstanding'", cmd_str);
564
0
    break;
565
566
0
  default:
567
0
    proto_tree_add_item(tree, hf_netb_resync_indicator, tvb, offset + NB_DATA2, 2, ENC_LITTLE_ENDIAN);
568
0
    break;
569
0
  }
570
0
}
571
572
/************************************************************************/
573
/*                  */
574
/*  The routines called by the top level to handle individual commands  */
575
/*                  */
576
/************************************************************************/
577
578
static uint32_t
579
dissect_netb_unknown( tvbuff_t *tvb, packet_info *pinfo, unsigned offset, proto_tree *tree)
580
581
0
{/* Handle any unknown commands, do nothing */
582
583
0
  proto_tree_add_expert_remaining(tree, pinfo, &ei_netb_unknown_command_data, tvb, offset + NB_COMMAND + 1);
584
585
0
  return 0;
586
0
}
587
588
589
static uint32_t
590
dissect_netb_add_group_name( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
591
592
0
{/* Handle the ADD GROUP NAME QUERY command */
593
594
0
  nb_resp_corrl( tvb, offset, tree);
595
596
0
  netbios_add_name("Group name to add", tvb, offset + NB_SENDER_NAME,
597
0
      tree);
598
599
0
  return 0;
600
0
}
601
602
603
static uint32_t
604
dissect_netb_add_name( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
605
606
0
{/* Handle the ADD NAME QUERY command */
607
608
0
  nb_resp_corrl( tvb, offset, tree);
609
610
0
  netbios_add_name("Name to add", tvb, offset + NB_SENDER_NAME, tree);
611
612
0
  return 0;
613
0
}
614
615
616
static uint32_t
617
dissect_netb_name_in_conflict( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
618
619
0
{/* Handle the NAME IN CONFLICT command */
620
621
0
  netbios_add_name("Name In Conflict", tvb, offset + NB_RECVER_NAME,
622
0
      tree);
623
0
  netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME, tree);
624
625
0
  return 0;
626
0
}
627
628
629
static uint32_t
630
dissect_netb_status_query( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
631
632
0
{/* Handle the STATUS QUERY command */
633
0
  uint8_t status_request = tvb_get_uint8( tvb, offset + NB_DATA1);
634
635
0
  switch (status_request) {
636
637
0
  case 0:
638
0
    proto_tree_add_uint_format_value(tree, hf_netb_status_request, tvb, offset + NB_DATA1, 1,
639
0
        status_request, "NetBIOS 1.x or 2.0");
640
0
    break;
641
642
0
  case 1:
643
0
    proto_tree_add_uint_format_value(tree, hf_netb_status_request, tvb, offset + NB_DATA1, 1,
644
0
        status_request, "NetBIOS 2.1, initial status request");
645
0
    break;
646
647
0
  default:
648
0
    proto_tree_add_uint_format_value(tree, hf_netb_status_request, tvb, offset + NB_DATA1, 1,
649
0
        status_request, "NetBIOS 2.1, %u names received so far",
650
0
        status_request);
651
0
    break;
652
0
  }
653
0
  nb_data2( hf_netb_status_buffer_len, tvb, offset, tree);
654
0
  nb_resp_corrl( tvb, offset, tree);
655
0
  netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
656
0
  netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME, tree);
657
658
0
  return 0;
659
0
}
660
661
662
static uint32_t
663
dissect_netb_terminate_trace( tvbuff_t *tvb _U_, packet_info *pinfo _U_, unsigned offset _U_, proto_tree *tree _U_)
664
665
0
{/* Handle the TERMINATE TRACE command */
666
667
  /*
668
   * XXX - are any of the fields in this message significant?
669
   * The IBM NetBIOS document shows them as "Reserved".
670
   */
671
672
0
  return 0;
673
0
}
674
675
676
static const unsigned char zeroes[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
677
678
static uint32_t
679
dissect_netb_datagram( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
680
681
0
{/* Handle the DATAGRAM command */
682
683
0
  netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
684
  /* Weird.  In some datagrams, this is 10 octets of 0, followed
685
     by a MAC address.... */
686
687
0
  if (tvb_memeql(tvb, offset + NB_SENDER_NAME, zeroes, 10) == 0) {
688
0
    proto_tree_add_item(tree, hf_netb_datagram_mac,
689
0
              tvb, offset + NB_SENDER_NAME + 10, 6, ENC_NA );
690
0
  } else {
691
0
    netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
692
0
        tree);
693
0
  }
694
695
0
  return 0;
696
0
}
697
698
699
static uint32_t
700
dissect_netb_datagram_bcast( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
701
702
0
{/* Handle the DATAGRAM BROADCAST command */
703
704
  /* We assume the same weirdness can happen here.... */
705
0
  if (tvb_memeql(tvb, offset + NB_SENDER_NAME, zeroes, 10) == 0) {
706
0
    proto_tree_add_item(tree, hf_netb_datagram_bcast_mac,
707
0
              tvb, offset + NB_SENDER_NAME + 10, 6, ENC_NA );
708
0
  } else {
709
0
    netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
710
0
        tree);
711
0
  }
712
713
0
  return 0;
714
0
}
715
716
717
static uint32_t
718
dissect_netb_name_query( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
719
720
0
{/* Handle the NAME QUERY command */
721
0
  uint8_t local_session_number = tvb_get_uint8( tvb, offset + NB_DATA2);
722
723
0
  if (local_session_number == 0) {
724
0
    proto_tree_add_uint_format_value( tree, hf_netb_local_session_no, tvb, offset + NB_DATA2, 1,
725
0
        local_session_number, "0 (FIND.NAME request)");
726
0
  } else {
727
0
    proto_tree_add_item( tree, hf_netb_local_session_no, tvb, offset + NB_DATA2, 1, ENC_LITTLE_ENDIAN);
728
0
  }
729
0
  nb_call_name_type( tvb, offset, tree);
730
0
  nb_resp_corrl( tvb, offset, tree);
731
0
  netbios_add_name("Query Name", tvb, offset + NB_RECVER_NAME, tree);
732
0
  if (local_session_number != 0) {
733
0
    netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
734
0
        tree);
735
0
  }
736
737
0
  return 0;
738
0
}
739
740
741
static uint32_t
742
dissect_netb_add_name_resp( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
743
744
0
{/* Handle the ADD NAME RESPONSE command */
745
746
0
  nb_data1( hf_netb_status, tvb, offset, tree);
747
0
  nb_data2( hf_netb_name_type, tvb, offset, tree);
748
0
  nb_xmit_corrl( tvb, offset, tree);
749
0
  netbios_add_name("Name to be added", tvb, offset + NB_RECVER_NAME,
750
0
      tree);
751
0
  netbios_add_name("Name to be added", tvb, offset + NB_SENDER_NAME,
752
0
      tree);
753
754
0
  return 0;
755
0
}
756
757
758
static uint32_t
759
dissect_netb_name_resp( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
760
761
0
{/* Handle the NAME RECOGNIZED command */
762
0
  uint8_t local_session_number = tvb_get_uint8( tvb, offset + NB_DATA2);
763
764
0
  switch (local_session_number) {
765
766
0
  case 0x00:
767
0
    proto_tree_add_uint_format_value( tree, hf_netb_state_of_name, tvb, offset + NB_DATA2, 1,
768
0
        local_session_number, "No LISTEN pending, or FIND.NAME response");
769
0
    break;
770
771
0
  case 0xFF:
772
0
    proto_tree_add_uint_format_value( tree, hf_netb_state_of_name, tvb, offset + NB_DATA2, 1,
773
0
        local_session_number, "LISTEN pending, but insufficient resources to establish session");
774
0
    break;
775
776
0
  default:
777
0
    proto_tree_add_item( tree, hf_netb_local_session_no, tvb, offset + NB_DATA2, 1, ENC_LITTLE_ENDIAN);
778
0
    break;
779
0
  }
780
0
  nb_call_name_type( tvb, offset, tree);
781
0
  nb_xmit_corrl( tvb, offset, tree);
782
0
  if (local_session_number != 0x00 && local_session_number != 0xFF)
783
0
    nb_resp_corrl(tvb, offset, tree);
784
0
  netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
785
0
  if (local_session_number != 0x00 && local_session_number != 0xFF) {
786
0
    netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
787
0
        tree);
788
0
  }
789
790
0
  return 0;
791
0
}
792
793
794
static uint32_t
795
dissect_netb_status_resp( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
796
797
0
{/* Handle the STATUS RESPONSE command */
798
0
  uint8_t     status_response = tvb_get_uint8( tvb, offset + NB_DATA1);
799
0
  proto_item *td2;
800
0
  proto_tree *data2_tree;
801
802
0
  nb_call_name_type( tvb, offset, tree);
803
0
  if (status_response == 0) {
804
0
    proto_tree_add_uint_format_value(tree, hf_netb_status_response, tvb, offset + NB_DATA1, 1,
805
0
        status_response, "NetBIOS 1.x or 2.0");
806
0
  } else {
807
0
    proto_tree_add_uint_format_value(tree, hf_netb_status_response, tvb, offset + NB_DATA1, 1,
808
0
        status_response, "NetBIOS 2.1, %u names sent so far",
809
0
        status_response);
810
0
  }
811
812
0
  td2 = proto_tree_add_item(tree, hf_netb_data2, tvb, offset + NB_DATA2, 2, ENC_LITTLE_ENDIAN);
813
0
  data2_tree = proto_item_add_subtree(td2, ett_netb_status);
814
0
  proto_tree_add_item(data2_tree, hf_netb_data2_frame, tvb, offset + NB_DATA2, 2, ENC_LITTLE_ENDIAN);
815
0
  proto_tree_add_item(data2_tree, hf_netb_data2_user, tvb, offset + NB_DATA2, 2, ENC_LITTLE_ENDIAN);
816
0
  proto_tree_add_item(data2_tree, hf_netb_data2_status, tvb, offset + NB_DATA2, 2, ENC_LITTLE_ENDIAN);
817
818
0
  nb_xmit_corrl( tvb, offset, tree);
819
0
  netbios_add_name("Receiver's Name", tvb, offset + NB_RECVER_NAME, tree);
820
0
  netbios_add_name("Sender's Name", tvb, offset + NB_SENDER_NAME,
821
0
      tree);
822
823
0
  return 0;
824
0
}
825
826
827
static uint32_t
828
dissect_netb_data_ack( tvbuff_t* tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
829
830
0
{/* Handle the DATA ACK command */
831
832
0
  nb_xmit_corrl( tvb, offset, tree);
833
0
  nb_remote_session( tvb, offset, tree);
834
0
  nb_local_session( tvb, offset, tree);
835
836
0
  return 0;
837
0
}
838
839
840
static uint32_t
841
dissect_netb_data_first_middle( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
842
843
0
{/* Handle the DATA FIRST MIDDLE command */
844
845
0
  uint8_t remote_session, local_session;
846
847
  /*
848
   * This is the first frame, or the middle frame, of a fragmented
849
   * packet.
850
   *
851
   * XXX - there are no sequence numbers, so we have to assume
852
   * that fragments arrive in order with no duplicates.
853
   * In fact, 802.2 LLC is supposed to handle that, so we
854
   * might have to have the LLC dissector do so (but the TCP
855
   * dissector doesn't currently handle out-of-order or duplicate
856
   * data, either).
857
   */
858
859
0
  netbios_data_first_middle_flags( tvb, tree, offset + NB_FLAGS);
860
861
0
  nb_resync_indicator( tvb, offset, tree, "DATA FIRST MIDDLE");
862
0
  nb_xmit_corrl( tvb, offset, tree);
863
0
  nb_resp_corrl( tvb, offset, tree);
864
0
  remote_session = nb_remote_session( tvb, offset, tree);
865
0
  local_session = nb_local_session( tvb, offset, tree);
866
867
  /*
868
   * Return a combination of the remote and local session numbers,
869
   * for use when reassembling.
870
   */
871
0
  return (remote_session << 8) + local_session;
872
0
}
873
874
875
static uint32_t
876
dissect_netb_data_only_last( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
877
878
0
{/* Handle the DATA ONLY LAST command */
879
880
0
  uint8_t remote_session, local_session;
881
882
  /*
883
   * This is a complete packet, or the last frame of a fragmented
884
   * packet.
885
   */
886
887
0
  netbios_data_only_flags( tvb, tree, offset + NB_FLAGS);
888
889
0
  nb_resync_indicator( tvb, offset, tree, "DATA ONLY LAST");
890
0
  nb_xmit_corrl( tvb, offset, tree);
891
0
  nb_resp_corrl( tvb, offset, tree);
892
0
  remote_session = nb_remote_session( tvb, offset, tree);
893
0
  local_session = nb_local_session( tvb, offset, tree);
894
895
  /*
896
   * Return a combination of the remote and local session numbers,
897
   * for use when reassembling.
898
   */
899
0
  return (remote_session << 8) + local_session;
900
0
}
901
902
903
static uint32_t
904
dissect_netb_session_confirm( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
905
906
0
{/* Handle the SESSION CONFIRM command */
907
908
0
  netbios_add_ses_confirm_flags( tvb, tree, offset + NB_FLAGS);
909
910
0
  nb_data2( hf_netb_max_data_recv_size, tvb, offset, tree);
911
0
  nb_xmit_corrl( tvb, offset, tree);
912
0
  nb_resp_corrl( tvb, offset, tree);
913
0
  nb_remote_session( tvb, offset, tree);
914
0
  nb_local_session( tvb, offset, tree);
915
916
0
  return 0;
917
0
}
918
919
920
static uint32_t
921
dissect_netb_session_end( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
922
923
0
{/* Handle the SESSION END command */
924
925
0
  nb_data2( hf_netb_termination_indicator, tvb, offset, tree);
926
0
  nb_remote_session( tvb, offset, tree);
927
0
  nb_local_session( tvb, offset, tree);
928
929
0
  return 0;
930
0
}
931
932
933
static uint32_t
934
dissect_netb_session_init( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
935
936
0
{/* Handle the SESSION INITIALIZE command */
937
938
0
  netbios_add_session_init_flags( tvb, tree, offset + NB_FLAGS);
939
940
0
  nb_data2( hf_netb_max_data_recv_size, tvb, offset, tree);
941
0
  nb_resp_corrl( tvb, offset, tree);
942
0
  nb_xmit_corrl( tvb, offset, tree);
943
0
  nb_remote_session( tvb, offset, tree);
944
0
  nb_local_session( tvb, offset, tree);
945
946
0
  return 0;
947
0
}
948
949
static uint32_t
950
dissect_netb_no_receive( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
951
952
0
{/* Handle the NO RECEIVE command */
953
954
0
  netbios_no_receive_flags( tvb, tree, offset + NB_FLAGS);
955
956
0
  nb_data2( hf_netb_num_data_bytes_accepted, tvb, offset, tree);
957
0
  nb_remote_session( tvb, offset, tree);
958
0
  nb_local_session( tvb, offset, tree);
959
960
0
  return 0;
961
0
}
962
963
964
static uint32_t
965
dissect_netb_receive_outstanding( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
966
967
0
{/* Handle the RECEIVE OUTSTANDING command */
968
969
0
  nb_data2( hf_netb_num_data_bytes_accepted, tvb, offset, tree);
970
0
  nb_remote_session( tvb, offset, tree);
971
0
  nb_local_session( tvb, offset, tree);
972
973
0
  return 0;
974
0
}
975
976
977
static uint32_t
978
dissect_netb_receive_continue( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
979
980
0
{/* Handle the RECEIVE CONTINUE command */
981
982
0
  nb_xmit_corrl( tvb, offset, tree);
983
0
  nb_remote_session( tvb, offset, tree);
984
0
  nb_local_session( tvb, offset, tree);
985
986
0
  return 0;
987
0
}
988
989
990
static uint32_t
991
dissect_netb_session_alive( tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree)
992
993
0
{/* Handle the SESSION ALIVE command */
994
995
  /*
996
   * XXX - all the fields are claimed to be "Reserved", but
997
   * the session numbers appear to be non-zero in at least
998
   * one capture, and they do appear to match session numbers
999
   * in other messages, and I'd expect that you had to identify
1000
   * sessions in this message in any case.
1001
   *
1002
   * We show only those fields.
1003
   */
1004
0
  nb_remote_session( tvb, offset, tree);
1005
0
  nb_local_session( tvb, offset, tree);
1006
1007
0
  return 0;
1008
0
}
1009
1010
1011
/************************************************************************/
1012
/*                  */
1013
/*  The table routines called by the top level to handle commands   */
1014
/*                  */
1015
/************************************************************************/
1016
1017
static uint32_t (*const dissect_netb[])(tvbuff_t *, packet_info *, unsigned, proto_tree *) = {
1018
1019
  dissect_netb_add_group_name,    /* Add Group Name  0x00 */
1020
  dissect_netb_add_name,      /* Add Name    0x01 */
1021
  dissect_netb_name_in_conflict,    /* Name In Conflict  0x02 */
1022
  dissect_netb_status_query,    /* Status Query  0x03 */
1023
  dissect_netb_unknown,     /* unknown     0x04 */
1024
  dissect_netb_unknown,     /* unknown     0x05 */
1025
  dissect_netb_unknown,     /* unknown     0x06 */
1026
  dissect_netb_terminate_trace,   /* Terminate Trace   0x07 */
1027
  dissect_netb_datagram,      /* Datagram    0x08 */
1028
  dissect_netb_datagram_bcast,    /* Datagram Broadcast  0x09 */
1029
  dissect_netb_name_query,    /* Name Query    0x0A */
1030
  dissect_netb_unknown,     /* unknown     0x0B */
1031
  dissect_netb_unknown,     /* unknown     0x0C */
1032
  dissect_netb_add_name_resp,   /* Add Name Response   0x0D */
1033
  dissect_netb_name_resp,     /* Name Recognized   0x0E */
1034
  dissect_netb_status_resp,   /* Status Response   0x0F */
1035
  dissect_netb_unknown,     /* unknown     0x10 */
1036
  dissect_netb_unknown,     /* unknown     0x11 */
1037
  dissect_netb_unknown,     /* unknown     0x12 */
1038
  dissect_netb_terminate_trace,   /* Terminate Trace   0x13 */
1039
  dissect_netb_data_ack,      /* Data Ack    0x14 */
1040
  dissect_netb_data_first_middle,   /* Data First Middle   0x15 */
1041
  dissect_netb_data_only_last,    /* Data Only Last  0x16 */
1042
  dissect_netb_session_confirm,   /* Session Confirm   0x17 */
1043
  dissect_netb_session_end,   /* Session End   0x18 */
1044
  dissect_netb_session_init,    /* Session Initialize  0x19 */
1045
  dissect_netb_no_receive,    /* No Receive    0x1A */
1046
  dissect_netb_receive_outstanding, /* Receive Outstanding 0x1B */
1047
  dissect_netb_receive_continue,    /* Receive Continue  0x1C */
1048
  dissect_netb_unknown,     /* unknown     0x1D */
1049
  dissect_netb_unknown,     /* unknown     0x1E */
1050
  dissect_netb_session_alive,   /* Session Alive   0x1f */
1051
  dissect_netb_unknown,
1052
};
1053
1054
static heur_dissector_list_t netbios_heur_subdissector_list;
1055
1056
static void
1057
dissect_netbios_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1058
0
{
1059
0
  heur_dtbl_entry_t *hdtbl_entry;
1060
1061
  /*
1062
   * Try the heuristic dissectors for NetBIOS; if none of them
1063
   * accept the packet, dissect it as data.
1064
   */
1065
0
  if (!dissector_try_heuristic(netbios_heur_subdissector_list,
1066
0
            tvb, pinfo, tree, &hdtbl_entry, NULL))
1067
0
    call_data_dissector(tvb, pinfo, tree);
1068
0
}
1069
1070
static int
1071
dissect_netbios(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1072
14
{
1073
14
  proto_tree    *netb_tree = NULL;
1074
14
  proto_item    *ti;
1075
14
  uint16_t         hdr_len, command;
1076
14
  const char    *command_name;
1077
14
  char         name[(NETBIOS_NAME_LEN - 1)*4 + 1];
1078
14
  int        name_type;
1079
14
  uint16_t         session_id;
1080
14
  bool           save_fragmented;
1081
14
  int        len;
1082
14
  fragment_head *fd_head;
1083
14
  tvbuff_t      *next_tvb;
1084
1085
14
  unsigned offset = 0;
1086
1087
          /* load the display labels  */
1088
14
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "NetBIOS");
1089
1090
1091
/* Find NetBIOS marker EFFF, this is done because I have seen an extra LLC */
1092
/* byte on our network. This only checks for one extra LLC byte. */
1093
1094
14
  if ( 0xefff != tvb_get_letohs(tvb, 2)){
1095
14
    ++offset;
1096
14
    if ( 0xefff != tvb_get_letohs(tvb, 3)){
1097
1098
      /* print bad packet */
1099
13
      col_set_str( pinfo->cinfo, COL_INFO, "Bad packet, no 0xEFFF marker");
1100
1101
13
      return 3;   /* this is an unknown packet, no marker */
1102
13
    }
1103
14
  }
1104
1105
1106
1
  hdr_len = tvb_get_letohs(tvb, offset + NB_LENGTH);
1107
1
  command = tvb_get_uint8( tvb, offset + NB_COMMAND);
1108
          /* limit command so no table overflows */
1109
1
  command = MIN(command, array_length(dissect_netb));
1110
1111
    /* print command name */
1112
1
  command_name = val_to_str_ext(pinfo->pool, command, &cmd_vals_ext, "Unknown (0x%02x)");
1113
1
  switch ( command ) {
1114
0
    case NB_NAME_QUERY:
1115
0
      name_type = get_netbios_name( tvb, offset + 12, name, (NETBIOS_NAME_LEN - 1)*4 + 1);
1116
0
      col_add_fstr( pinfo->cinfo, COL_INFO, "%s for %s<%02x>", command_name, name, name_type);
1117
0
      break;
1118
1119
0
    case NB_NAME_RESP:
1120
0
    case NB_ADD_NAME:
1121
0
    case NB_ADD_GROUP:
1122
0
      name_type = get_netbios_name( tvb, offset + 28, name, (NETBIOS_NAME_LEN - 1)*4 + 1);
1123
0
      col_add_fstr( pinfo->cinfo, COL_INFO, "%s - %s<%02x>", command_name, name, name_type);
1124
0
    break;
1125
1126
0
    default:
1127
0
      col_add_str( pinfo->cinfo, COL_INFO, command_name);
1128
0
      break;
1129
1
  }
1130
1131
0
  if ( tree) {
1132
0
    ti = proto_tree_add_item(tree, proto_netbios, tvb, 0, hdr_len, ENC_NA);
1133
0
    netb_tree = proto_item_add_subtree(ti, ett_netb);
1134
1135
0
    proto_tree_add_uint_format_value(netb_tree, hf_netb_hdr_len, tvb, offset, 2, hdr_len,
1136
0
      "%d bytes", hdr_len);
1137
1138
0
    proto_tree_add_uint_format_value(netb_tree, hf_netb_delimiter, tvb, offset + 2, 2,
1139
0
      tvb_get_letohs(tvb, offset + 2), "EFFF (NetBIOS)");
1140
1141
0
    proto_tree_add_uint(netb_tree, hf_netb_cmd, tvb, offset + NB_COMMAND, 1, command);
1142
0
  }
1143
1144
          /* if command in table range */
1145
0
  if ( command < array_length(dissect_netb)) {
1146
1147
          /* branch to handle commands */
1148
0
    session_id = (dissect_netb[ command])( tvb, pinfo, offset, netb_tree);
1149
1150
0
    offset += hdr_len;      /* move past header */
1151
1152
0
    save_fragmented = pinfo->fragmented;
1153
1154
    /*
1155
     * Process user data in frames that have it.
1156
     */
1157
0
    switch (command) {
1158
1159
0
    case NB_DATAGRAM:
1160
0
    case NB_DATAGRAM_BCAST:
1161
      /*
1162
       * No fragmentation here.
1163
       */
1164
0
      next_tvb = tvb_new_subset_remaining(tvb, offset);
1165
0
      dissect_netbios_payload(next_tvb, pinfo, tree);
1166
0
      break;
1167
1168
0
    case NB_DATA_FIRST_MIDDLE:
1169
0
    case NB_DATA_ONLY_LAST:
1170
      /*
1171
       * Possibly fragmented.
1172
       */
1173
0
      len = tvb_reported_length_remaining(tvb, offset);
1174
0
      if (netbios_defragment &&
1175
0
          tvb_bytes_exist(tvb, offset, len)) {
1176
0
        fd_head = fragment_add_seq_next(&netbios_reassembly_table,
1177
0
            tvb, offset,
1178
0
            pinfo, session_id, NULL,
1179
0
            len, command == NB_DATA_FIRST_MIDDLE);
1180
0
        if (fd_head != NULL) {
1181
0
          if (fd_head->next != NULL) {
1182
0
            next_tvb = tvb_new_chain(tvb, fd_head->tvb_data);
1183
0
            add_new_data_source(pinfo,
1184
0
                next_tvb,
1185
0
                "Reassembled NetBIOS");
1186
            /* Show all fragments. */
1187
0
            if (tree) {
1188
0
              proto_item *frag_tree_item;
1189
1190
0
              show_fragment_seq_tree(fd_head,
1191
0
                  &netbios_frag_items,
1192
0
                  netb_tree, pinfo,
1193
0
                  next_tvb, &frag_tree_item);
1194
0
            }
1195
0
          } else {
1196
0
            next_tvb = tvb_new_subset_remaining(tvb,
1197
0
                offset);
1198
0
          }
1199
0
        } else {
1200
0
          next_tvb = NULL;
1201
0
        }
1202
0
      } else {
1203
        /*
1204
         * Dissect this, regardless of whether
1205
         * it's NB_DATA_FIRST_MIDDLE or
1206
         * NB_DATA_ONLY_LAST.
1207
         *
1208
         * XXX - it'd be nice to show
1209
         * NB_DATA_FIRST_MIDDLE as a fragment
1210
         * if it's not the first fragment (i.e.,
1211
         * MIDDLE rather than FIRST), and show
1212
         * NB_DATA_ONLY_LAST as a fragment if
1213
         * it's part of a fragmented datagram
1214
         * (i.e, LAST rather than ONLY), but
1215
         * we'd have to do reassembly to
1216
         * be able to determine that.
1217
         */
1218
0
        next_tvb = tvb_new_subset_remaining(tvb, offset);
1219
0
      }
1220
0
      if (next_tvb != NULL)
1221
0
        dissect_netbios_payload(next_tvb, pinfo, tree);
1222
0
      else {
1223
0
        next_tvb = tvb_new_subset_remaining (tvb, offset);
1224
0
        call_data_dissector(next_tvb, pinfo, tree);
1225
0
      }
1226
0
      break;
1227
0
    }
1228
0
    pinfo->fragmented = save_fragmented;
1229
0
  }
1230
0
  return tvb_captured_length(tvb);
1231
0
}
1232
1233
void
1234
proto_register_netbios(void)
1235
14
{
1236
14
  static int *ett[] = {
1237
14
    &ett_netb,
1238
14
    &ett_netb_name,
1239
14
    &ett_netb_flags,
1240
14
    &ett_netb_status,
1241
14
    &ett_netb_fragments,
1242
14
    &ett_netb_fragment,
1243
14
  };
1244
1245
14
  static hf_register_info hf_netb[] = {
1246
14
    { &hf_netb_cmd,
1247
14
      { "Command", "netbios.command", FT_UINT8, BASE_HEX | BASE_EXT_STRING,
1248
14
        &cmd_vals_ext, 0x0, NULL, HFILL }},
1249
1250
14
    { &hf_netb_hdr_len,
1251
14
      { "Length", "netbios.hdr_len", FT_UINT16, BASE_DEC,
1252
14
        NULL, 0x0, "Header Length", HFILL }},
1253
1254
14
    { &hf_netb_delimiter,
1255
14
      { "Delimiter", "netbios.delimiter", FT_UINT16, BASE_HEX,
1256
14
        NULL, 0x0, NULL, HFILL }},
1257
1258
14
    { &hf_netb_xmit_corrl,
1259
14
      { "Transmit Correlator", "netbios.xmit_corrl", FT_UINT16, BASE_HEX,
1260
14
        NULL, 0x0, NULL, HFILL }},
1261
1262
14
    { &hf_netb_resp_corrl,
1263
14
      { "Response Correlator", "netbios.resp_corrl", FT_UINT16, BASE_HEX,
1264
14
        NULL, 0x0, NULL, HFILL }},
1265
1266
14
    { &hf_netb_call_name_type,
1267
14
      { "Caller's Name Type", "netbios.call_name_type", FT_UINT8, BASE_HEX,
1268
14
        VALS(name_types), 0x0, NULL, HFILL }},
1269
1270
14
    { &hf_netb_nb_name_type,
1271
14
      { "NetBIOS Name Type", "netbios.nb_name_type", FT_UINT8, BASE_HEX |BASE_EXT_STRING,
1272
14
        &nb_name_type_vals_ext, 0x0, NULL, HFILL }},
1273
1274
14
    { &hf_netb_nb_name,
1275
14
      { "NetBIOS Name", "netbios.nb_name", FT_STRING, BASE_NONE,
1276
14
        NULL, 0x0, NULL, HFILL }},
1277
1278
14
    { &hf_netb_version,
1279
14
      { "NetBIOS Version", "netbios.version", FT_BOOLEAN,  8,
1280
14
        TFS( &netb_version_str), 0x01, NULL, HFILL }},
1281
1282
14
    { &hf_netbios_no_receive_flags,
1283
14
      { "Flags", "netbios.no_receive_flags", FT_UINT8, BASE_HEX, NULL, 0x0,
1284
14
        NULL, HFILL }},
1285
1286
14
    { &hf_netbios_no_receive_flags_send_no_ack,
1287
14
      { "SEND.NO.ACK data received", "netbios.no_receive_flags.send_no_ack", FT_BOOLEAN,  8,
1288
14
        TFS( &tfs_no_yes), 0x02, NULL, HFILL }},
1289
1290
14
    { &hf_netb_largest_frame,
1291
14
      { "Largest Frame", "netbios.largest_frame", FT_UINT8, BASE_DEC,
1292
14
        VALS(max_frame_size_vals), 0x0E, NULL, HFILL }},
1293
1294
14
    { &hf_netb_status_buffer_len,
1295
14
      { "Length of status buffer", "netbios.status_buffer_len", FT_UINT16, BASE_DEC,
1296
14
        NULL, 0x0, NULL, HFILL }},
1297
1298
14
    { &hf_netb_status,
1299
14
      { "Status", "netbios.status", FT_UINT8, BASE_DEC,
1300
14
        VALS(status_vals), 0x0, NULL, HFILL }},
1301
1302
14
    { &hf_netb_name_type,
1303
14
      { "Name type", "netbios.name_type", FT_UINT16, BASE_DEC,
1304
14
        VALS(name_types), 0x0, NULL, HFILL }},
1305
1306
14
    { &hf_netb_max_data_recv_size,
1307
14
      { "Maximum data receive size", "netbios.max_data_recv_size", FT_UINT16, BASE_DEC,
1308
14
        NULL, 0x0, NULL, HFILL }},
1309
1310
14
    { &hf_netb_termination_indicator,
1311
14
      { "Termination indicator", "netbios.termination_indicator", FT_UINT16, BASE_HEX,
1312
14
        VALS(termination_indicator_vals), 0x0, NULL, HFILL }},
1313
1314
14
    { &hf_netb_num_data_bytes_accepted,
1315
14
      { "Number of data bytes accepted", "netbios.num_data_bytes_accepted", FT_UINT16, BASE_DEC,
1316
14
        NULL, 0x0, NULL, HFILL }},
1317
1318
14
    { &hf_netb_local_ses_no,
1319
14
      { "Local Session No.", "netbios.local_session", FT_UINT8, BASE_HEX,
1320
14
        NULL, 0x0, NULL, HFILL }},
1321
1322
14
    { &hf_netb_remote_ses_no,
1323
14
      { "Remote Session No.", "netbios.remote_session", FT_UINT8, BASE_HEX,
1324
14
        NULL, 0x0, NULL, HFILL }},
1325
1326
14
    { &hf_netb_flags,
1327
14
      { "Flags", "netbios.flags", FT_UINT8, BASE_HEX,
1328
14
        NULL, 0x0, NULL, HFILL }},
1329
1330
14
    { &hf_netb_flags_send_no_ack,
1331
14
      { "Handle SEND.NO.ACK", "netbios.flags.send_no_ack", FT_BOOLEAN,  8,
1332
14
        TFS( &tfs_yes_no), 0x80, NULL, HFILL }},
1333
1334
14
    { &hf_netb_flags_ack,
1335
14
      { "Acknowledge", "netbios.flags.ack", FT_BOOLEAN, 8,
1336
14
        TFS( &tfs_set_notset), 0x08, NULL, HFILL }},
1337
1338
14
    { &hf_netb_flags_ack_with_data,
1339
14
      { "Acknowledge with data", "netbios.flags.ack_with_data", FT_BOOLEAN, 8,
1340
14
        TFS( &tfs_allowed_not_allowed), 0x04, NULL, HFILL }},
1341
1342
14
    { &hf_netb_flags_ack_expected,
1343
14
      { "Acknowledge expected", "netbios.flags.ack_expected", FT_BOOLEAN,  8,
1344
14
        TFS( &tfs_yes_no), 0x02, NULL, HFILL }},
1345
1346
14
    { &hf_netb_flags_recv_cont_req,
1347
14
      { "RECEIVE_CONTINUE requested", "netbios.flags.recv_cont_req", FT_BOOLEAN,  8,
1348
14
        TFS( &tfs_yes_no), 0x01, NULL, HFILL }},
1349
1350
14
    { &hf_netb_data2,
1351
14
      { "DATA2 value", "netbios.data2", FT_UINT16, BASE_HEX,
1352
14
        NULL, 0x0, NULL, HFILL }},
1353
1354
14
    { &hf_netb_data2_frame,
1355
14
      { "Data length exceeds maximum frame size", "netbios.data2.frame", FT_BOOLEAN, 16,
1356
14
        TFS(&tfs_yes_no), 0x8000, NULL, HFILL }},
1357
1358
14
    { &hf_netb_data2_user,
1359
14
      { "Data length exceeds user's buffer", "netbios.data2.user", FT_BOOLEAN, 16,
1360
14
        TFS(&tfs_yes_no), 0x4000, NULL, HFILL }},
1361
1362
14
    { &hf_netb_data2_status,
1363
14
      { "Status data length", "netbios.data2.status", FT_UINT16, BASE_DEC,
1364
14
        NULL, 0x3FFF, NULL, HFILL }},
1365
1366
14
    { &hf_netb_datagram_mac,
1367
14
      { "Sender's MAC Address", "netbios.datagram_mac", FT_ETHER, BASE_NONE,
1368
14
        NULL, 0x0, NULL, HFILL }},
1369
1370
14
    { &hf_netb_datagram_bcast_mac,
1371
14
      { "Sender's Node Address",  "netbios.datagram_bcast_mac", FT_ETHER, BASE_NONE,
1372
14
        NULL, 0x0, NULL, HFILL }},
1373
1374
14
    { &hf_netb_resync_indicator,
1375
14
      { "Re-sync indicator", "netbios.resync_indicator", FT_UINT16, BASE_HEX,
1376
14
        NULL, 0x0, NULL, HFILL }},
1377
1378
14
    { &hf_netb_status_request,
1379
14
      { "Status request", "netbios.status_request", FT_UINT8, BASE_DEC,
1380
14
        NULL, 0x0, NULL, HFILL }},
1381
1382
14
    { &hf_netb_local_session_no,
1383
14
      { "Local Session No.", "netbios.local_session_no", FT_UINT8, BASE_HEX,
1384
14
        NULL, 0x0, NULL, HFILL }},
1385
1386
14
    { &hf_netb_state_of_name,
1387
14
      { "State of name", "netbios.state_of_name", FT_UINT8, BASE_HEX,
1388
14
        NULL, 0x0, NULL, HFILL }},
1389
1390
14
    { &hf_netb_status_response,
1391
14
      { "Status response", "netbios.status_response", FT_UINT8, BASE_DEC,
1392
14
        NULL, 0x0, NULL, HFILL }},
1393
1394
14
    { &hf_netb_fragment_overlap,
1395
14
      { "Fragment overlap", "netbios.fragment.overlap", FT_BOOLEAN, BASE_NONE,
1396
14
        NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
1397
1398
14
    { &hf_netb_fragment_overlap_conflict,
1399
14
      { "Conflicting data in fragment overlap", "netbios.fragment.overlap.conflict",
1400
14
        FT_BOOLEAN, BASE_NONE,
1401
14
        NULL, 0x0, "Overlapping fragments contained conflicting data", HFILL }},
1402
1403
14
    { &hf_netb_fragment_multiple_tails,
1404
14
      { "Multiple tail fragments found", "netbios.fragment.multipletails",
1405
14
        FT_BOOLEAN, BASE_NONE,
1406
14
        NULL, 0x0, "Several tails were found when defragmenting the packet", HFILL }},
1407
1408
14
    { &hf_netb_fragment_too_long_fragment,
1409
14
      { "Fragment too long",  "netbios.fragment.toolongfragment", FT_BOOLEAN, BASE_NONE,
1410
14
        NULL, 0x0, "Fragment contained data past end of packet", HFILL }},
1411
1412
14
    { &hf_netb_fragment_error,
1413
14
      { "Defragmentation error",  "netbios.fragment.error", FT_FRAMENUM, BASE_NONE,
1414
14
        NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
1415
1416
14
    { &hf_netb_fragment_count,
1417
14
      { "Fragment count", "netbios.fragment.count", FT_UINT32, BASE_DEC,
1418
14
        NULL, 0x0, NULL, HFILL }},
1419
1420
14
    { &hf_netb_fragment,
1421
14
      { "NetBIOS Fragment",   "netbios.fragment", FT_FRAMENUM, BASE_NONE,
1422
14
        NULL, 0x0, NULL, HFILL }},
1423
1424
14
    { &hf_netb_fragments,
1425
14
      { "NetBIOS Fragments",  "netbios.fragments", FT_NONE, BASE_NONE,
1426
14
        NULL, 0x0, NULL, HFILL }},
1427
1428
14
    { &hf_netb_reassembled_length,
1429
14
      {"Reassembled NetBIOS length",  "netbios.reassembled.length", FT_UINT32, BASE_DEC,
1430
14
       NULL, 0x0, "The total length of the reassembled payload", HFILL }},
1431
14
  };
1432
1433
14
  static ei_register_info ei[] = {
1434
14
    { &ei_netb_unknown_command_data, { "netbios.unknown_command_data", PI_UNDECODED, PI_WARN, "Unknown NetBIOS command data", EXPFILL }},
1435
14
  };
1436
1437
14
  module_t *netbios_module;
1438
14
  expert_module_t* expert_netbios;
1439
1440
14
  proto_netbios = proto_register_protocol("NetBIOS", "NetBIOS", "netbios");
1441
14
  proto_register_subtree_array(ett, array_length(ett));
1442
14
  proto_register_field_array(proto_netbios, hf_netb, array_length(hf_netb));
1443
14
  expert_netbios = expert_register_protocol(proto_netbios);
1444
14
  expert_register_field_array(expert_netbios, ei, array_length(ei));
1445
1446
14
  netbios_handle = register_dissector("netbios", dissect_netbios, proto_netbios);
1447
14
  netbios_cap_handle = register_capture_dissector("netbios", capture_netbios, proto_netbios);
1448
1449
14
  netbios_heur_subdissector_list = register_heur_dissector_list_with_description("netbios", "NetBIOS payload", proto_netbios);
1450
1451
14
  netbios_module = prefs_register_protocol(proto_netbios, NULL);
1452
14
  prefs_register_bool_preference(netbios_module, "defragment",
1453
14
      "Reassemble fragmented NetBIOS messages spanning multiple frames",
1454
14
      "Whether the NetBIOS dissector should defragment messages spanning multiple frames",
1455
14
      &netbios_defragment);
1456
1457
14
  reassembly_table_register(&netbios_reassembly_table,
1458
14
      &addresses_reassembly_table_functions);
1459
14
}
1460
1461
void
1462
proto_reg_handoff_netbios(void)
1463
14
{
1464
14
  dissector_add_uint("llc.dsap", SAP_NETBIOS, netbios_handle);
1465
14
  capture_dissector_add_uint("llc.dsap", SAP_NETBIOS, netbios_cap_handle);
1466
14
}
1467
1468
1469
/*
1470
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1471
 *
1472
 * Local variables:
1473
 * c-basic-offset: 8
1474
 * tab-width: 8
1475
 * indent-tabs-mode: t
1476
 * End:
1477
 *
1478
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1479
 * :indentSize=8:tabSize=8:noTabs=false:
1480
 */