Coverage Report

Created: 2026-05-14 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-nbt.c
Line
Count
Source
1
/* packet-nbt.c
2
 * Routines for NetBIOS-over-TCP packet disassembly
3
 * Guy Harris <guy@alum.mit.edu>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
#include "config.h"
13
14
#include <epan/packet.h>
15
#include <epan/expert.h>
16
#include <epan/exceptions.h>
17
#include <epan/prefs.h>
18
#include <epan/show_exception.h>
19
#include <epan/to_str.h>
20
#include <epan/charsets.h>
21
#include <epan/tfs.h>
22
#include <epan/unit_strings.h>
23
24
#include <wsutil/array.h>
25
#include <wsutil/str_util.h>
26
27
#include "packet-dns.h"
28
#include "packet-netbios.h"
29
#include "packet-tcp.h"
30
31
void proto_register_nbt(void);
32
void proto_reg_handoff_nbt(void);
33
34
static dissector_handle_t nbns_handle, nbdgm_handle, nbss_handle;
35
36
static int proto_nbns;
37
static int hf_nbns_flags;
38
static int hf_nbns_flags_response;
39
static int hf_nbns_flags_opcode;
40
static int hf_nbns_flags_authoritative;
41
static int hf_nbns_flags_truncated;
42
static int hf_nbns_flags_recdesired;
43
static int hf_nbns_flags_recavail;
44
static int hf_nbns_flags_broadcast;
45
static int hf_nbns_flags_rcode;
46
static int hf_nbns_transaction_id;
47
static int hf_nbns_count_questions;
48
static int hf_nbns_count_answers;
49
static int hf_nbns_count_auth_rr;
50
static int hf_nbns_count_add_rr;
51
static int hf_nbns_name_flags;
52
static int hf_nbns_name_flags_group;
53
static int hf_nbns_name_flags_ont;
54
static int hf_nbns_name_flags_drg;
55
static int hf_nbns_name_flags_cnf;
56
static int hf_nbns_name_flags_act;
57
static int hf_nbns_name_flags_prm;
58
static int hf_nbns_nb_flags;
59
static int hf_nbns_nb_flags_group;
60
static int hf_nbns_nb_flags_ont;
61
static int hf_nbns_name;
62
static int hf_nbns_type;
63
static int hf_nbns_class;
64
65
/* Generated from convert_proto_tree_add_text.pl */
66
static int hf_nbns_num_alignment_errors;
67
static int hf_nbns_data;
68
static int hf_nbns_unit_id;
69
static int hf_nbns_num_command_blocks;
70
static int hf_nbns_num_retransmits;
71
static int hf_nbns_period_of_statistics;
72
static int hf_nbns_addr;
73
static int hf_nbns_test_result;
74
static int hf_nbns_num_pending_sessions;
75
static int hf_nbns_num_no_resource_conditions;
76
static int hf_nbns_session_data_packet_size;
77
static int hf_nbns_version_number;
78
static int hf_nbns_max_num_pending_sessions;
79
static int hf_nbns_num_collisions;
80
static int hf_nbns_num_good_sends;
81
static int hf_nbns_num_send_aborts;
82
static int hf_nbns_number_of_names;
83
static int hf_nbns_num_crcs;
84
static int hf_nbns_num_good_receives;
85
static int hf_nbns_max_total_sessions_possible;
86
static int hf_nbns_jumpers;
87
static int hf_nbns_netbios_name;
88
static int hf_nbns_ttl;
89
static int hf_nbns_data_length;
90
91
static int ett_nbns;
92
static int ett_nbns_qd;
93
static int ett_nbns_flags;
94
static int ett_nbns_nb_flags;
95
static int ett_nbns_name_flags;
96
static int ett_nbns_rr;
97
static int ett_nbns_qry;
98
static int ett_nbns_ans;
99
100
static expert_field ei_nbns_incomplete_entry;
101
102
static int proto_nbdgm;
103
static int hf_nbdgm_type;
104
static int hf_nbdgm_flags;
105
static int hf_nbdgm_fragment;
106
static int hf_nbdgm_first;
107
static int hf_nbdgm_node_type;
108
static int hf_nbdgm_datagram_id;
109
static int hf_nbdgm_src_ip;
110
static int hf_nbdgm_src_port;
111
static int hf_nbdgm_datagram_length;
112
static int hf_nbdgm_packet_offset;
113
static int hf_nbdgm_error_code;
114
static int hf_nbdgm_source_name;
115
static int hf_nbdgm_destination_name;
116
117
static int ett_nbdgm;
118
static int ett_nbdgm_flags;
119
120
static int proto_nbss;
121
static int hf_nbss_type;
122
static int hf_nbss_flags;
123
static int hf_nbss_flags_e;
124
static int hf_nbss_length;
125
static int hf_nbss_cifs_length;
126
static int hf_nbss_error_code;
127
static int hf_nbss_retarget_ip_address;
128
static int hf_nbss_retarget_port;
129
static int hf_nbss_continuation_data;
130
static int hf_nbss_called_name;
131
static int hf_nbss_calling_name;
132
133
static int ett_nbss;
134
static int ett_nbss_flags;
135
136
/* desegmentation of NBSS over TCP */
137
static bool nbss_desegment = true;
138
139
/* See RFC 1001 and 1002 for information on the first three, and see
140
141
   http://www.cifs.com/specs/draft-leach-cifs-v1-spec-01.txt
142
143
   Appendix B, and various messages on the CIFS mailing list such as
144
145
   http://discuss.microsoft.com/SCRIPTS/WA-MSD.EXE?A2=ind9811A&L=cifs&P=R386
146
147
   for information on the fourth. */
148
15
#define UDP_PORT_NBNS   137
149
15
#define UDP_PORT_NBDGM  138
150
#define TCP_PORT_NBSS   139
151
14
#define TCP_PORT_CIFS   445
152
15
#define TCP_NBSS_PORT_RANGE  "139,445"
153
154
/* Packet structure taken from RFC 1002. See also RFC 1001.
155
 * Opcode, flags, and rcode treated as "flags", similarly to DNS,
156
 * to make it easier to lift the dissection code from "packet-dns.c". */
157
158
/* Offsets of fields in the NBNS header. */
159
184
#define NBNS_ID         0
160
184
#define NBNS_FLAGS      2
161
92
#define NBNS_QUEST      4
162
92
#define NBNS_ANS        6
163
92
#define NBNS_AUTH       8
164
92
#define NBNS_ADD        10
165
166
/* Length of NBNS header. */
167
92
#define NBNS_HDRLEN     12
168
169
/* type values  */
170
12
#define T_NB            32              /* NetBIOS name service RR */
171
38
#define T_NBSTAT        33              /* NetBIOS node status RR */
172
173
/* Bit fields in the flags */
174
360
#define F_RESPONSE      (1<<15)         /* packet is response */
175
107
#define F_OPCODE        (0xF<<11)       /* query opcode */
176
92
#define OPCODE_SHIFT    11
177
15
#define F_AUTHORITATIVE (1<<10)         /* response is authoritative */
178
15
#define F_TRUNCATED     (1<<9)          /* response is truncated */
179
15
#define F_RECDESIRED    (1<<8)          /* recursion desired */
180
15
#define F_RECAVAIL      (1<<7)          /* recursion available */
181
15
#define F_BROADCAST     (1<<4)          /* broadcast/multicast packet */
182
15
#define F_RCODE         (0xF<<0)        /* reply code */
183
184
static const true_false_string tfs_flags_response = {
185
    "Message is a response",
186
    "Message is a query"
187
};
188
189
static const true_false_string tfs_flags_authoritative = {
190
    "Server is an authority for domain",
191
    "Server is not an authority for domain"
192
};
193
194
static const true_false_string tfs_flags_truncated = {
195
    "Message is truncated",
196
    "Message is not truncated"
197
};
198
199
static const true_false_string tfs_flags_recdesired = {
200
    "Do query recursively",
201
    "Don't do query recursively"
202
};
203
204
static const true_false_string tfs_flags_recavail = {
205
    "Server can do recursive queries",
206
    "Server can't do recursive queries"
207
};
208
209
static const true_false_string tfs_flags_broadcast = {
210
    "Broadcast packet",
211
    "Not a broadcast packet"
212
};
213
214
static const true_false_string tfs_nbss_flags_e = {
215
    "Add 65536 to length",
216
    "Add 0 to length"
217
};
218
219
/* Opcodes */
220
#define OPCODE_QUERY          0         /* standard query */
221
#define OPCODE_REGISTRATION   5         /* registration */
222
#define OPCODE_RELEASE        6         /* release name */
223
326
#define OPCODE_WACK           7         /* wait for acknowledgement */
224
#define OPCODE_REFRESH        8         /* refresh registration */
225
#define OPCODE_REFRESHALT     9         /* refresh registration (alternate opcode) */
226
#define OPCODE_MHREGISTRATION 15        /* multi-homed registration */
227
228
static const value_string opcode_vals[] = {
229
    { OPCODE_QUERY,          "Name query"                 },
230
    { OPCODE_REGISTRATION,   "Registration"               },
231
    { OPCODE_RELEASE,        "Release"                    },
232
    { OPCODE_WACK,           "Wait for acknowledgment"    },
233
    { OPCODE_REFRESH,        "Refresh"                    },
234
    { OPCODE_REFRESHALT,     "Refresh (alternate opcode)" },
235
    { OPCODE_MHREGISTRATION, "Multi-homed registration"   },
236
    { 0,                     NULL                         }
237
};
238
239
/* Reply codes */
240
#define RCODE_NOERROR   0
241
#define RCODE_FMTERROR  1
242
#define RCODE_SERVFAIL  2
243
#define RCODE_NAMEERROR 3
244
#define RCODE_NOTIMPL   4
245
#define RCODE_REFUSED   5
246
#define RCODE_ACTIVE    6
247
#define RCODE_CONFLICT  7
248
249
static const value_string rcode_vals[] = {
250
    { RCODE_NOERROR,   "No error"                        },
251
    { RCODE_FMTERROR,  "Request was invalidly formatted" },
252
    { RCODE_SERVFAIL,  "Server failure"                  },
253
    { RCODE_NAMEERROR, "Requested name does not exist"   },
254
    { RCODE_NOTIMPL,   "Request is not implemented"      },
255
    { RCODE_REFUSED,   "Request was refused"             },
256
    { RCODE_ACTIVE,    "Name is owned by another node"   },
257
    { RCODE_CONFLICT,  "Name is in conflict"             },
258
    { 0,               NULL                              }
259
};
260
261
/* Values for the "NB_FLAGS" field of RR data.  From RFC 1001 and 1002,
262
 * except for NB_FLAGS_ONT_H_NODE, which was discovered by looking at
263
 * packet traces. */
264
231
#define NB_FLAGS_ONT            (3<<(15-2))     /* bits for node type */
265
#define NB_FLAGS_ONT_B_NODE     (0<<(15-2))     /* B-mode node */
266
#define NB_FLAGS_ONT_P_NODE     (1<<(15-2))     /* P-mode node */
267
#define NB_FLAGS_ONT_M_NODE     (2<<(15-2))     /* M-mode node */
268
#define NB_FLAGS_ONT_H_NODE     (3<<(15-2))     /* H-mode node */
269
270
231
#define NB_FLAGS_G              (1<<(15-0))     /* group name */
271
272
/* Values for the "NAME_FLAGS" field of a NODE_NAME entry in T_NBSTAT
273
 * RR data.  From RFC 1001 and 1002; as I remember, the "NAME_FLAGS"
274
 * field doesn't include any special values for H-mode nodes, even
275
 * though one can register them (if so, perhaps that was done to
276
 * avoid surprising clients that don't know about H-mode nodes). */
277
15
#define NAME_FLAGS_PRM          (1<<(15-6))     /* name is permanent node name */
278
279
15
#define NAME_FLAGS_ACT          (1<<(15-5))     /* name is active */
280
281
15
#define NAME_FLAGS_CNF          (1<<(15-4))     /* name is in conflict */
282
283
15
#define NAME_FLAGS_DRG          (1<<(15-3))     /* name is being deregistered */
284
285
15
#define NAME_FLAGS_ONT          (3<<(15-2))     /* bits for node type */
286
#define NAME_FLAGS_ONT_B_NODE   (0<<(15-2))     /* B-mode node */
287
#define NAME_FLAGS_ONT_P_NODE   (1<<(15-2))     /* P-mode node */
288
#define NAME_FLAGS_ONT_M_NODE   (2<<(15-2))     /* M-mode node */
289
290
15
#define NAME_FLAGS_G            (1<<(15-0))     /* group name */
291
292
static const value_string name_flags_ont_vals[] = {
293
    { NAME_FLAGS_ONT_B_NODE, "B-node" },
294
    { NAME_FLAGS_ONT_P_NODE, "P-node" },
295
    { NAME_FLAGS_ONT_M_NODE, "M-node" },
296
    { 0,                     NULL     }
297
};
298
299
static const value_string nb_flags_ont_vals[] = {
300
    { NB_FLAGS_ONT_B_NODE, "B-node" },
301
    { NB_FLAGS_ONT_P_NODE, "P-node" },
302
    { NB_FLAGS_ONT_M_NODE, "M-node" },
303
    { NB_FLAGS_ONT_H_NODE, "H-node" },
304
    { 0,                   NULL     }
305
};
306
307
static const value_string nb_type_name_vals[] = {
308
    { T_NB,     "NB" },
309
    { T_NBSTAT, "NBSTAT" },
310
    { 0,        NULL     }
311
};
312
313
428
#define NBNAME_BUF_LEN 128
314
315
static void
316
add_rr_to_tree(proto_tree *rr_tree, packet_info *pinfo, tvbuff_t *tvb, int offset,
317
               const char *name, int namelen,
318
               int type, int class_val,
319
               unsigned ttl, uint16_t data_len)
320
150
{
321
150
    proto_tree_add_string(rr_tree, hf_nbns_name, tvb, offset+1, namelen-1, name);
322
150
    offset += namelen;
323
150
    proto_tree_add_uint(rr_tree, hf_nbns_type, tvb, offset, 2, type);
324
150
    offset += 2;
325
150
    proto_tree_add_uint(rr_tree, hf_nbns_class, tvb, offset, 2, class_val);
326
150
    offset += 2;
327
150
    proto_tree_add_uint_format_value(rr_tree, hf_nbns_ttl, tvb, offset, 4, ttl, "%s",
328
150
                        signed_time_secs_to_str(pinfo->pool, ttl));
329
150
    offset += 4;
330
150
    proto_tree_add_uint(rr_tree, hf_nbns_data_length, tvb, offset, 2, data_len);
331
150
}
332
333
static int
334
get_nbns_name(tvbuff_t *tvb, wmem_allocator_t* allocator, int offset, int nbns_data_offset,
335
              char *name_ret, int name_ret_len, int *name_type_ret)
336
428
{
337
428
    int           name_len;
338
428
    const char   *name;
339
428
    const char   *nbname;
340
428
    char         *nbname_buf;
341
428
    const char   *pname;
342
428
    char          cname, cnbname;
343
428
    int           name_type;
344
428
    char         *pname_ret;
345
428
    size_t        idx = 0;
346
428
    unsigned      used_bytes;
347
348
428
    nbname_buf = (char *)wmem_alloc(allocator, NBNAME_BUF_LEN);
349
428
    nbname = nbname_buf;
350
428
    used_bytes = get_dns_name(allocator, tvb, offset, 0, nbns_data_offset, &name, &name_len);
351
352
    /* OK, now undo the first-level encoding. */
353
428
    pname = &name[0];
354
428
    pname_ret = name_ret;
355
356
428
    for (;;) {
357
        /* Every two characters of the first level-encoded name
358
         * turn into one character in the decoded name. */
359
399
        cname = *pname;
360
399
        if (cname == '\0')
361
8
            break;              /* no more characters */
362
391
        if (cname == '.')
363
0
            break;              /* scope ID follows */
364
391
        if (cname < 'A' || cname > 'Z') {
365
            /* Not legal. */
366
383
            nbname = "Illegal NetBIOS name (1st character not between A and Z in first-level encoding)";
367
383
            goto bad;
368
383
        }
369
8
        cname -= 'A';
370
8
        cnbname = cname << 4;
371
8
        pname++;
372
373
8
        cname = *pname;
374
8
        if (cname == '\0' || cname == '.') {
375
            /* No more characters in the name - but we're in
376
             * the middle of a pair.  Not legal. */
377
1
            nbname = "Illegal NetBIOS name (odd number of bytes)";
378
1
            goto bad;
379
1
        }
380
7
        if (cname < 'A' || cname > 'Z') {
381
            /* Not legal. */
382
3
            nbname = "Illegal NetBIOS name (2nd character not between A and Z in first-level encoding)";
383
3
            goto bad;
384
3
        }
385
4
        cname -= 'A';
386
4
        cnbname |= cname;
387
4
        pname++;
388
389
        /* Do we have room to store the character? */
390
4
        if (idx < NETBIOS_NAME_LEN) {
391
            /* Yes - store the character. */
392
4
            nbname_buf[idx++] = cnbname;
393
4
        }
394
4
    }
395
396
    /* NetBIOS names are supposed to be exactly 16 bytes long. */
397
41
    if (idx != NETBIOS_NAME_LEN) {
398
        /* It's not. */
399
8
        snprintf(nbname_buf, NBNAME_BUF_LEN, "Illegal NetBIOS name (%lu bytes long)",
400
8
                   (unsigned long)idx);
401
8
        goto bad;
402
8
    }
403
404
    /* This one is; make its name printable. */
405
33
    name_type = process_netbios_name((const uint8_t*)nbname, name_ret, name_ret_len);
406
33
    pname_ret += MIN(strlen(name_ret), (size_t) name_ret_len);
407
33
    snprintf(pname_ret, name_ret_len-(pname_ret-name_ret), "<%02x>", name_type);
408
33
    if (cname == '.') {
409
        /* We have a scope ID, starting at "pname"; append that to
410
         * the decoded host name. */
411
        /* RFC 1001 says that scope IDs "meet the restricted character set
412
         * of the domain system and has a leading period." Convert it from
413
         * ASCII before appending it to our NBName, so we have a valid
414
         * UTF-8 string.
415
         */
416
0
        const char* scope_id = (char*)get_ascii_string(allocator, (const uint8_t*)pname, strlen(pname));
417
0
        int bytes_attempted = (int)g_strlcat(name_ret, scope_id, name_ret_len);
418
0
        if (bytes_attempted >= name_ret_len) {
419
0
            ws_utf8_truncate(name_ret, name_ret_len - 1);
420
0
        }
421
0
    }
422
33
    if (name_type_ret != NULL)
423
0
        *name_type_ret = name_type;
424
33
    return used_bytes;
425
426
395
bad:
427
395
    if (name_type_ret != NULL)
428
395
        *name_type_ret = -1;
429
    /* This is only valid because nbname is always assigned an error string
430
     * before jumping to bad: Otherwise nbname wouldn't be \0 terminated */
431
395
    snprintf(pname_ret, name_ret_len-(pname_ret-name_ret), "%s", nbname);
432
395
    return used_bytes;
433
41
}
434
435
436
static int
437
get_nbns_name_type_class(tvbuff_t *tvb, wmem_allocator_t* allocator, int offset, int nbns_data_offset,
438
                         char *name_ret, int *name_len_ret, int *name_type_ret,
439
                         int *type_ret, int *class_ret)
440
284
{
441
284
    int name_len;
442
284
    int type;
443
284
    int rr_class;
444
445
284
    name_len = get_nbns_name(tvb, allocator, offset, nbns_data_offset, name_ret,
446
284
                             *name_len_ret, name_type_ret);
447
284
    offset += name_len;
448
449
284
    type = tvb_get_ntohs(tvb, offset);
450
284
    offset += 2;
451
452
284
    rr_class = tvb_get_ntohs(tvb, offset);
453
454
284
    *type_ret = type;
455
284
    *class_ret = rr_class;
456
284
    *name_len_ret = name_len;
457
458
284
    return name_len + 4;
459
284
}
460
461
static void
462
add_name_and_type(proto_tree *tree, tvbuff_t *tvb, int offset, int len,
463
                  int hf_tag, const char *name, int name_type)
464
238
{
465
238
    if (name_type != -1) {
466
0
        proto_tree_add_string_format_value(tree, hf_tag, tvb, offset, len, name, "%s (%s)",
467
0
                            name, netbios_name_type_descr(name_type));
468
238
    } else {
469
238
        proto_tree_add_string(tree, hf_tag, tvb, offset, len, name);
470
238
    }
471
238
}
472
473
1.05k
#define MAX_NAME_LEN (NETBIOS_NAME_LEN - 1)*4 + MAX_DNAME_LEN + 64
474
475
static int
476
dissect_nbns_query(tvbuff_t *tvb, packet_info* pinfo, int offset, int nbns_data_offset,
477
                   proto_tree *nbns_tree, bool add_column_data)
478
115
{
479
115
    int         len;
480
115
    char       *name;
481
115
    int         name_len;
482
115
    int         name_type;
483
115
    int         type;
484
115
    int         dns_class;
485
115
    const char *type_name;
486
115
    int         data_offset;
487
115
    int         data_start;
488
115
    proto_tree *q_tree;
489
490
115
    name = (char *)wmem_alloc(pinfo->pool, MAX_NAME_LEN);
491
115
    data_start = data_offset = offset;
492
493
115
    name_len = MAX_NAME_LEN;
494
115
    len = get_nbns_name_type_class(tvb, pinfo->pool, offset, nbns_data_offset, name,
495
115
                                   &name_len, &name_type, &type, &dns_class);
496
115
    data_offset += len;
497
498
115
    type_name = val_to_str_const(type, nb_type_name_vals, "Unknown");
499
500
115
    if (add_column_data)
501
45
        col_append_fstr(pinfo->cinfo, COL_INFO, " %s %s", type_name, name);
502
503
115
    if (nbns_tree != NULL) {
504
96
        q_tree = proto_tree_add_subtree_format(nbns_tree, tvb, offset, len,
505
96
                                 ett_nbns_qd, NULL, "%s: type %s, class %s",  name, type_name,
506
96
                                 val_to_str_const(dns_class, dns_classes, "Unknown"));
507
508
96
        add_name_and_type(q_tree, tvb, offset, name_len, hf_nbns_name, name,
509
96
                          name_type);
510
96
        offset += name_len;
511
512
96
        proto_tree_add_uint(q_tree, hf_nbns_type, tvb, offset, 2, type);
513
96
        offset += 2;
514
515
96
        proto_tree_add_uint(q_tree, hf_nbns_class, tvb, offset, 2, dns_class);
516
        /*offset += 2;*/
517
96
    }
518
519
115
    return data_offset - data_start;
520
115
}
521
522
static void
523
nbns_add_nbns_flags(column_info *cinfo, proto_tree *nbns_tree, tvbuff_t *tvb, int offset, int is_wack)
524
201
{
525
201
    uint16_t    flag;
526
201
    static int * const req_flags[] = {
527
201
        &hf_nbns_flags_response,
528
201
        &hf_nbns_flags_opcode,
529
201
        &hf_nbns_flags_truncated,
530
201
        &hf_nbns_flags_recdesired,
531
201
        &hf_nbns_flags_broadcast,
532
201
        NULL
533
201
    };
534
535
201
    static int * const resp_flags[] = {
536
201
        &hf_nbns_flags_response,
537
201
        &hf_nbns_flags_opcode,
538
201
        &hf_nbns_flags_authoritative,
539
201
        &hf_nbns_flags_truncated,
540
201
        &hf_nbns_flags_recdesired,
541
201
        &hf_nbns_flags_recavail,
542
201
        &hf_nbns_flags_broadcast,
543
201
        &hf_nbns_flags_rcode,
544
201
        NULL
545
201
    };
546
547
201
    static int * const resp_wack_flags[] = {
548
201
        &hf_nbns_flags_response,
549
201
        &hf_nbns_flags_opcode,
550
201
        &hf_nbns_flags_authoritative,
551
201
        &hf_nbns_flags_truncated,
552
201
        &hf_nbns_flags_recdesired,
553
201
        &hf_nbns_flags_recavail,
554
201
        &hf_nbns_flags_broadcast,
555
201
        NULL
556
201
    };
557
558
201
    flag = tvb_get_ntohs(tvb, offset);
559
201
    if (cinfo) {
560
0
        if (flag & F_RESPONSE && !is_wack) {
561
0
            if ((flag & F_RCODE))
562
0
                col_append_fstr(cinfo, COL_INFO, ", %s",
563
0
                                val_to_str_const(flag & F_RCODE, rcode_vals,
564
0
                                                 "Unknown error"));
565
0
        }
566
0
    }
567
568
201
    if (!nbns_tree)
569
0
        return;
570
571
201
    if (flag & F_RESPONSE) {
572
34
        if (!is_wack) {
573
14
            proto_tree_add_bitmask(nbns_tree, tvb, offset, hf_nbns_flags, ett_nbns_flags, resp_flags, ENC_BIG_ENDIAN);
574
20
        } else {
575
20
            proto_tree_add_bitmask(nbns_tree, tvb, offset, hf_nbns_flags, ett_nbns_flags, resp_wack_flags, ENC_BIG_ENDIAN);
576
20
        }
577
167
    } else {
578
167
        proto_tree_add_bitmask(nbns_tree, tvb, offset, hf_nbns_flags, ett_nbns_flags, req_flags, ENC_BIG_ENDIAN);
579
167
    }
580
201
}
581
582
static void
583
nbns_add_nb_flags(proto_tree *rr_tree, tvbuff_t *tvb, int offset)
584
216
{
585
216
    proto_item *tf;
586
216
    uint16_t flag;
587
216
    static int * const flags[] = {
588
216
        &hf_nbns_nb_flags_group,
589
216
        &hf_nbns_nb_flags_ont,
590
216
        NULL
591
216
    };
592
593
216
    tf = proto_tree_add_bitmask(rr_tree, tvb, offset, hf_nbns_nb_flags, ett_nbns_nb_flags, flags, ENC_BIG_ENDIAN);
594
595
216
    flag = tvb_get_ntohs(tvb, offset);
596
216
    proto_item_append_text(tf, " (%s, %s)",
597
216
                val_to_str_const(flag & NB_FLAGS_ONT, nb_flags_ont_vals, "Unknown"),
598
216
                (flag & NB_FLAGS_G) ? "group" : "unique");
599
216
}
600
601
static void
602
nbns_add_name_flags(proto_tree *rr_tree, tvbuff_t *tvb, int offset)
603
472
{
604
472
    static int * const flags[] = {
605
472
        &hf_nbns_name_flags_group,
606
472
        &hf_nbns_name_flags_ont,
607
472
        &hf_nbns_name_flags_drg,
608
472
        &hf_nbns_name_flags_cnf,
609
472
        &hf_nbns_name_flags_act,
610
472
        &hf_nbns_name_flags_prm,
611
472
        NULL
612
472
    };
613
614
472
    proto_tree_add_bitmask(rr_tree, tvb, offset, hf_nbns_name_flags, ett_nbns_name_flags, flags, ENC_BIG_ENDIAN);
615
472
}
616
617
static int
618
dissect_nbns_answer(tvbuff_t *tvb, packet_info *pinfo, int offset, int nbns_data_offset,
619
                    column_info *cinfo, proto_tree *nbns_tree, int opcode)
620
169
{
621
169
    int         len;
622
169
    char       *name;
623
169
    int         name_len;
624
169
    int         name_type;
625
169
    int         type;
626
169
    int         dns_class;
627
169
    const char *class_name;
628
169
    const char *type_name;
629
169
    int         cur_offset;
630
169
    unsigned    ttl;
631
169
    uint16_t    data_len;
632
169
    proto_tree *rr_tree = NULL;
633
169
    char       *name_str;
634
169
    unsigned    num_names;
635
169
    uint8_t    *nbname;
636
637
169
    cur_offset = offset;
638
639
169
    name     = (char *)wmem_alloc(pinfo->pool, MAX_NAME_LEN);
640
169
    name_str = (char *)wmem_alloc(pinfo->pool, MAX_NAME_LEN);
641
169
    nbname   = (uint8_t *)wmem_alloc(pinfo->pool, 16+4+1); /* 4 for [<last char>] */
642
643
169
    name_len = MAX_NAME_LEN;
644
169
    len      = get_nbns_name_type_class(tvb, pinfo->pool, offset, nbns_data_offset, name,
645
169
                                        &name_len, &name_type, &type, &dns_class);
646
169
    cur_offset  += len;
647
648
169
    type_name  = val_to_str_const(type, nb_type_name_vals, "Unknown");
649
169
    class_name = val_to_str_const(dns_class, dns_classes, "Unknown");
650
651
169
    ttl = tvb_get_ntohl(tvb, cur_offset);
652
169
    cur_offset  += 4;
653
654
169
    data_len = tvb_get_ntohs(tvb, cur_offset);
655
169
    cur_offset  += 2;
656
657
    /* XXX: This code should be simplified */
658
169
    switch (type) {
659
12
    case T_NB:          /* "NB" record */
660
12
        if (cinfo != NULL) {
661
0
            if (opcode != OPCODE_WACK) {
662
0
                col_append_fstr(cinfo, COL_INFO, " %s %s",
663
0
                                type_name,
664
0
                                tvb_ip_to_str(pinfo->pool, tvb, cur_offset+2));
665
0
            }
666
0
        }
667
668
12
        if (nbns_tree) {
669
12
            rr_tree = proto_tree_add_subtree_format(nbns_tree, tvb, offset,
670
12
                                      (cur_offset - offset) + data_len,
671
12
                                      ett_nbns_rr, NULL, "%s: type %s, class %s",
672
12
                                      name, type_name, class_name);
673
12
            (void) g_strlcat(name, " (", MAX_NAME_LEN);
674
12
            (void) g_strlcat(name, netbios_name_type_descr(name_type), MAX_NAME_LEN);
675
12
            (void) g_strlcat(name, ")", MAX_NAME_LEN);
676
12
            add_rr_to_tree(rr_tree, pinfo, tvb, offset, name,
677
12
                                 name_len, type, dns_class, ttl, data_len);
678
12
        }
679
337
        while (data_len > 0) {
680
326
            if (opcode == OPCODE_WACK) {
681
                /* WACK response.  This doesn't contain the
682
                 * same type of RR data as other T_NB
683
                 * responses.  */
684
109
                if (data_len < 2) {
685
0
                    proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
686
0
                    break;
687
0
                }
688
109
                nbns_add_nbns_flags(cinfo, rr_tree, tvb, cur_offset, 1);
689
109
                cur_offset += 2;
690
109
                data_len   -= 2;
691
217
            } else {
692
217
                if (data_len < 2) {
693
1
                    proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
694
1
                    break;
695
1
                }
696
216
                nbns_add_nb_flags(rr_tree, tvb, cur_offset);
697
216
                cur_offset += 2;
698
216
                data_len   -= 2;
699
700
216
                if (data_len < 4) {
701
0
                    proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
702
0
                    break;
703
0
                }
704
216
                proto_tree_add_item(rr_tree, hf_nbns_addr, tvb, cur_offset, 4, ENC_BIG_ENDIAN);
705
216
                cur_offset += 4;
706
216
                data_len   -= 4;
707
216
            }
708
326
        }
709
12
        break;
710
711
38
    case T_NBSTAT:      /* "NBSTAT" record */
712
38
        if (cinfo != NULL)
713
0
            col_append_fstr(cinfo, COL_INFO, " %s", type_name);
714
715
38
        if (nbns_tree) {
716
38
            rr_tree = proto_tree_add_subtree_format(nbns_tree, tvb, offset,
717
38
                                      (cur_offset - offset) + data_len,
718
38
                                      ett_nbns_rr, NULL, "%s: type %s, class %s",
719
38
                                      name, type_name, class_name);
720
38
            add_rr_to_tree(rr_tree, pinfo, tvb, offset, name,
721
38
                                     name_len, type, dns_class, ttl, data_len);
722
38
        }
723
724
38
        if (data_len < 1) {
725
1
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
726
1
            break;
727
1
        }
728
729
37
        num_names = tvb_get_uint8(tvb, cur_offset);
730
37
        proto_tree_add_item(rr_tree, hf_nbns_number_of_names, tvb, cur_offset, 1, ENC_BIG_ENDIAN);
731
37
        cur_offset += 1;
732
733
530
        while (num_names != 0) {
734
500
            if (data_len < NETBIOS_NAME_LEN) {
735
6
                proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
736
6
                goto out;
737
6
            }
738
494
            if (rr_tree) {
739
494
                tvb_memcpy(tvb, nbname, cur_offset,
740
494
                           NETBIOS_NAME_LEN);
741
494
                name_type = process_netbios_name(nbname,
742
494
                                                 name_str, name_len);
743
494
                proto_tree_add_string_format_value(rr_tree, hf_nbns_netbios_name, tvb, cur_offset,
744
494
                                    NETBIOS_NAME_LEN, name_str, "%s<%02x> (%s)",
745
494
                                    name_str, name_type,
746
494
                                    netbios_name_type_descr(name_type));
747
494
            }
748
494
            cur_offset += NETBIOS_NAME_LEN;
749
494
            data_len   -= NETBIOS_NAME_LEN;
750
751
494
            if (data_len < 2) {
752
1
                proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
753
1
                goto out;
754
1
            }
755
493
            if (rr_tree) {
756
472
                nbns_add_name_flags(rr_tree, tvb, cur_offset);
757
472
            }
758
493
            cur_offset += 2;
759
493
            data_len   -= 2;
760
761
493
            num_names--;
762
493
        }
763
764
30
        if (data_len < 6) {
765
1
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
766
1
            break;
767
1
        }
768
769
29
        proto_tree_add_item(rr_tree, hf_nbns_unit_id, tvb, cur_offset, 6, ENC_NA);
770
29
        cur_offset += 6;
771
29
        data_len   -= 6;
772
773
29
        if (data_len < 1) {
774
0
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
775
0
            break;
776
0
        }
777
778
29
        proto_tree_add_item(rr_tree, hf_nbns_jumpers, tvb, cur_offset, 1, ENC_BIG_ENDIAN);
779
29
        cur_offset += 1;
780
29
        data_len   -= 1;
781
782
29
        if (data_len < 1) {
783
0
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
784
0
            break;
785
0
        }
786
787
29
        proto_tree_add_item(rr_tree, hf_nbns_test_result, tvb, cur_offset, 1, ENC_BIG_ENDIAN);
788
29
        cur_offset += 1;
789
29
        data_len   -= 1;
790
791
29
        if (data_len < 2) {
792
0
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
793
0
            break;
794
0
        }
795
796
29
        proto_tree_add_item(rr_tree, hf_nbns_version_number, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
797
29
        cur_offset += 2;
798
29
        data_len   -= 2;
799
800
29
        if (data_len < 2) {
801
0
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
802
0
            break;
803
0
        }
804
805
29
        proto_tree_add_item(rr_tree, hf_nbns_period_of_statistics, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
806
29
        cur_offset += 2;
807
29
        data_len   -= 2;
808
809
29
        if (data_len < 2) {
810
0
           proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
811
0
            break;
812
0
        }
813
814
29
        proto_tree_add_item(rr_tree, hf_nbns_num_crcs, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
815
29
        cur_offset += 2;
816
29
        data_len   -= 2;
817
818
29
        if (data_len < 2) {
819
0
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
820
0
            break;
821
0
        }
822
823
29
        proto_tree_add_item(rr_tree, hf_nbns_num_alignment_errors, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
824
29
        cur_offset += 2;
825
29
        data_len   -= 2;
826
827
29
        if (data_len < 2) {
828
0
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
829
0
            break;
830
0
        }
831
832
29
        proto_tree_add_item(rr_tree, hf_nbns_num_collisions, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
833
29
        cur_offset += 2;
834
29
        data_len   -= 2;
835
836
29
        if (data_len < 2) {
837
0
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
838
0
            break;
839
0
        }
840
841
29
        proto_tree_add_item(rr_tree, hf_nbns_num_send_aborts, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
842
29
        cur_offset += 2;
843
29
        data_len   -= 2;
844
845
29
        if (data_len < 4) {
846
0
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
847
0
            break;
848
0
        }
849
850
29
        proto_tree_add_item(rr_tree, hf_nbns_num_good_sends, tvb, cur_offset, 4, ENC_BIG_ENDIAN);
851
29
        cur_offset += 4;
852
29
        data_len   -= 4;
853
854
29
        if (data_len < 4) {
855
0
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
856
0
            break;
857
0
        }
858
859
29
        proto_tree_add_item(rr_tree, hf_nbns_num_good_receives, tvb, cur_offset, 4, ENC_BIG_ENDIAN);
860
29
        cur_offset += 4;
861
29
        data_len   -= 4;
862
863
29
        if (data_len < 2) {
864
0
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
865
0
            break;
866
0
        }
867
868
29
        proto_tree_add_item(rr_tree, hf_nbns_num_retransmits, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
869
29
        cur_offset += 2;
870
29
        data_len   -= 2;
871
872
29
        if (data_len < 2) {
873
0
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
874
0
            break;
875
0
        }
876
877
29
        proto_tree_add_item(rr_tree, hf_nbns_num_no_resource_conditions, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
878
29
        cur_offset += 2;
879
29
        data_len   -= 2;
880
881
29
        if (data_len < 2) {
882
0
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
883
0
            break;
884
0
        }
885
886
29
        proto_tree_add_item(rr_tree, hf_nbns_num_command_blocks, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
887
29
        cur_offset += 2;
888
29
        data_len   -= 2;
889
890
29
        if (data_len < 2) {
891
0
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
892
0
            break;
893
0
        }
894
895
29
        proto_tree_add_item(rr_tree, hf_nbns_num_pending_sessions, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
896
29
        cur_offset += 2;
897
29
        data_len   -= 2;
898
899
29
        if (data_len < 2) {
900
0
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
901
0
            break;
902
0
        }
903
904
29
        proto_tree_add_item(rr_tree, hf_nbns_max_num_pending_sessions, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
905
29
        cur_offset += 2;
906
29
        data_len   -= 2;
907
908
29
        if (data_len < 2) {
909
0
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
910
0
            break;
911
0
        }
912
913
29
        proto_tree_add_item(rr_tree, hf_nbns_max_total_sessions_possible, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
914
29
        cur_offset += 2;
915
29
        data_len   -= 2;
916
917
29
        if (data_len < 2) {
918
0
            proto_tree_add_expert(rr_tree, pinfo, &ei_nbns_incomplete_entry, tvb, cur_offset, data_len);
919
0
            break;
920
0
        }
921
922
29
        proto_tree_add_item(rr_tree, hf_nbns_session_data_packet_size, tvb, cur_offset, 2, ENC_BIG_ENDIAN);
923
29
        cur_offset += 2;
924
        /*data_len -= 2;*/
925
29
    out:
926
9
        break;
927
928
100
    default:
929
100
        if (cinfo != NULL)
930
0
            col_append_fstr(cinfo, COL_INFO, " %s", type_name);
931
932
100
        if (nbns_tree) {
933
100
            rr_tree = proto_tree_add_subtree_format(nbns_tree, tvb, offset,
934
100
                                      (cur_offset - offset) + data_len,
935
100
                                      ett_nbns_rr, NULL, "%s: type %s, class %s",
936
100
                                      name, type_name, class_name);
937
100
            add_rr_to_tree(rr_tree, pinfo, tvb, offset, name,
938
100
                                     name_len, type, dns_class, ttl, data_len);
939
100
            proto_tree_add_item(rr_tree, hf_nbns_data, tvb, cur_offset, data_len, ENC_NA);
940
100
        }
941
100
        cur_offset += data_len;
942
100
        break;
943
169
    }
944
945
101
    return cur_offset - offset;
946
169
}
947
948
static int
949
dissect_query_records(tvbuff_t *tvb, packet_info* pinfo, int cur_off, int nbns_data_offset,
950
                      int count, proto_tree *nbns_tree, bool add_column_data)
951
21
{
952
21
    int         start_off, add_off;
953
21
    proto_tree *qatree;
954
21
    proto_item *ti;
955
956
21
    start_off = cur_off;
957
21
    qatree = proto_tree_add_subtree(nbns_tree, tvb, start_off, -1, ett_nbns_qry, &ti, "Queries");
958
959
136
    while (count-- > 0) {
960
115
        add_off = dissect_nbns_query(tvb, pinfo, cur_off, nbns_data_offset, qatree, add_column_data);
961
115
        cur_off += add_off;
962
115
    }
963
964
21
    proto_item_set_len(ti, cur_off - start_off);
965
966
21
    return cur_off - start_off;
967
21
}
968
969
static int
970
dissect_answer_records(tvbuff_t *tvb, packet_info *pinfo, int cur_off, int nbns_data_offset,
971
                       int count, column_info *cinfo, proto_tree *nbns_tree,
972
                       int opcode, const char *name)
973
72
{
974
72
    int         start_off, add_off;
975
72
    proto_tree *qatree;
976
72
    proto_item *ti;
977
978
72
    start_off = cur_off;
979
72
    qatree = proto_tree_add_subtree(nbns_tree, tvb, start_off, -1, ett_nbns_ans, &ti, name);
980
981
241
    while (count-- > 0) {
982
169
        add_off = dissect_nbns_answer(tvb, pinfo, cur_off, nbns_data_offset,
983
169
                                      cinfo, qatree, opcode);
984
169
        cur_off += add_off;
985
169
    }
986
987
72
    proto_item_set_len(ti, cur_off - start_off);
988
72
    return cur_off - start_off;
989
72
}
990
991
static int
992
dissect_nbns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
993
92
{
994
92
    int          offset    = 0;
995
92
    int          nbns_data_offset;
996
92
    proto_tree  *nbns_tree = NULL;
997
92
    proto_item  *ti;
998
92
    uint32_t     id, flags, opcode, quest, ans, auth, add;
999
92
    int          cur_off;
1000
1001
92
    nbns_data_offset = offset;
1002
1003
92
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBNS");
1004
92
    col_clear(pinfo->cinfo, COL_INFO);
1005
1006
    /* To do: check for runts, errs, etc. */
1007
92
    id     = tvb_get_ntohs(tvb, offset + NBNS_ID);
1008
92
    flags  = tvb_get_ntohs(tvb, offset + NBNS_FLAGS);
1009
92
    opcode = (uint16_t) ((flags & F_OPCODE) >> OPCODE_SHIFT);
1010
1011
92
    col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s",
1012
92
                    val_to_str(pinfo->pool, opcode, opcode_vals, "Unknown operation (%u)"),
1013
92
                    (flags & F_RESPONSE) ? " response" : "");
1014
1015
92
    ti = proto_tree_add_item(tree, proto_nbns, tvb, offset, -1, ENC_NA);
1016
92
    nbns_tree = proto_item_add_subtree(ti, ett_nbns);
1017
1018
92
    proto_tree_add_uint(nbns_tree, hf_nbns_transaction_id, tvb,
1019
92
                        offset + NBNS_ID, 2, id);
1020
1021
92
    nbns_add_nbns_flags(pinfo->cinfo, nbns_tree, tvb, offset + NBNS_FLAGS, 0);
1022
1023
92
    proto_tree_add_item_ret_uint(nbns_tree, hf_nbns_count_questions, tvb,
1024
92
                            offset + NBNS_QUEST, 2, ENC_BIG_ENDIAN, &quest);
1025
92
    proto_tree_add_item_ret_uint(nbns_tree, hf_nbns_count_answers, tvb,
1026
92
                            offset + NBNS_ANS, 2, ENC_BIG_ENDIAN, &ans);
1027
92
    proto_tree_add_item_ret_uint(nbns_tree, hf_nbns_count_auth_rr, tvb,
1028
92
                            offset + NBNS_AUTH, 2, ENC_BIG_ENDIAN, &auth);
1029
92
    proto_tree_add_item_ret_uint(nbns_tree, hf_nbns_count_add_rr, tvb,
1030
92
                            offset + NBNS_ADD, 2, ENC_BIG_ENDIAN, &add);
1031
1032
92
    cur_off = offset + NBNS_HDRLEN;
1033
1034
92
    if (quest > 0) {
1035
        /* If this is a response, don't add information about the
1036
           queries to the summary, just add information about the
1037
           answers. */
1038
21
        cur_off += dissect_query_records(tvb, pinfo, cur_off,
1039
21
                                         nbns_data_offset, quest,
1040
21
                                         nbns_tree, !(flags & F_RESPONSE));
1041
21
    }
1042
1043
92
    if (ans > 0) {
1044
        /* If this is a request, don't add information about the
1045
           answers to the summary, just add information about the
1046
           queries. */
1047
31
        cur_off += dissect_answer_records(tvb, pinfo, cur_off,
1048
31
                                          nbns_data_offset, ans,
1049
31
                                          ((flags & F_RESPONSE) ? pinfo->cinfo : NULL), nbns_tree,
1050
31
                                          opcode, "Answers");
1051
31
    }
1052
1053
    /* Don't add information about the authoritative name
1054
       servers, or the additional records, to the summary. */
1055
92
    if (auth > 0)
1056
39
        cur_off += dissect_answer_records(tvb, pinfo, cur_off,
1057
39
                                          nbns_data_offset,
1058
39
                                          auth, NULL, nbns_tree, opcode,
1059
39
                                          "Authoritative nameservers");
1060
1061
92
    if (add > 0)
1062
2
        /*cur_off += */dissect_answer_records(tvb, pinfo, cur_off,
1063
2
                                              nbns_data_offset,
1064
2
                                              add, NULL, nbns_tree, opcode,
1065
2
                                              "Additional records");
1066
1067
92
    return tvb_captured_length(tvb);
1068
92
}
1069
1070
static heur_dissector_list_t netbios_heur_subdissector_list;
1071
1072
static void
1073
dissect_netbios_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1074
122
{
1075
122
    heur_dtbl_entry_t *hdtbl_entry;
1076
1077
    /*
1078
     * Try the heuristic dissectors for NetBIOS; if none of them
1079
     * accept the packet, dissect it as data.
1080
     */
1081
122
    if (!dissector_try_heuristic(netbios_heur_subdissector_list,
1082
122
                                 tvb, pinfo, tree, &hdtbl_entry, NULL))
1083
57
        call_data_dissector(tvb, pinfo, tree);
1084
122
}
1085
1086
/*
1087
 * NBDS message types.
1088
 */
1089
0
#define NBDS_DIRECT_UNIQUE      0x10
1090
0
#define NBDS_DIRECT_GROUP       0x11
1091
70
#define NBDS_BROADCAST          0x12
1092
0
#define NBDS_ERROR              0x13
1093
1
#define NBDS_QUERY_REQUEST      0x14
1094
2
#define NBDS_POS_QUERY_RESPONSE 0x15
1095
2
#define NBDS_NEG_QUERY_RESPONSE 0x16
1096
1097
static const value_string nbds_msgtype_vals[] = {
1098
    { NBDS_DIRECT_UNIQUE,      "Direct_unique datagram" },
1099
    { NBDS_DIRECT_GROUP,       "Direct_group datagram" },
1100
    { NBDS_BROADCAST,          "Broadcast datagram" },
1101
    { NBDS_ERROR,              "Datagram error" },
1102
    { NBDS_QUERY_REQUEST,      "Datagram query request" },
1103
    { NBDS_POS_QUERY_RESPONSE, "Datagram positive query response" },
1104
    { NBDS_NEG_QUERY_RESPONSE, "Datagram negative query response" },
1105
    { 0,                       NULL }
1106
};
1107
1108
static const value_string node_type_vals[] = {
1109
    { 0, "B node" },
1110
    { 1, "P node" },
1111
    { 2, "M node" },
1112
    { 3, "NBDD" },
1113
    { 0, NULL }
1114
};
1115
1116
static const value_string nbds_error_codes[] = {
1117
    { 0x82, "Destination name not present" },
1118
    { 0x83, "Invalid source name format" },
1119
    { 0x84, "Invalid destination name format" },
1120
    { 0x00, NULL }
1121
};
1122
1123
static int
1124
dissect_nbdgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1125
75
{
1126
75
    int                  offset     = 0;
1127
75
    proto_tree          *nbdgm_tree;
1128
75
    proto_item          *ti;
1129
75
    tvbuff_t            *next_tvb;
1130
75
    uint32_t             msg_type;
1131
1132
75
    char *name;
1133
75
    int name_type;
1134
75
    int len;
1135
1136
75
    static int * const flags[] = {
1137
75
        &hf_nbdgm_fragment,
1138
75
        &hf_nbdgm_first,
1139
75
        &hf_nbdgm_node_type,
1140
75
        NULL
1141
75
    };
1142
1143
75
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBDS");
1144
75
    col_clear(pinfo->cinfo, COL_INFO);
1145
1146
75
    ti = proto_tree_add_item(tree, proto_nbdgm, tvb, offset, -1, ENC_NA);
1147
75
    nbdgm_tree = proto_item_add_subtree(ti, ett_nbdgm);
1148
1149
75
    proto_tree_add_item_ret_uint(nbdgm_tree, hf_nbdgm_type, tvb,
1150
75
                            offset, 1, ENC_NA, &msg_type);
1151
1152
75
    col_add_str(pinfo->cinfo, COL_INFO,
1153
75
                val_to_str(pinfo->pool, msg_type, nbds_msgtype_vals,
1154
75
                           "Unknown message type (0x%02X)"));
1155
1156
75
    proto_tree_add_bitmask(nbdgm_tree, tvb, offset+1, hf_nbdgm_flags, ett_nbdgm_flags, flags, ENC_BIG_ENDIAN);
1157
1158
75
    proto_tree_add_item(nbdgm_tree, hf_nbdgm_datagram_id, tvb, offset+2, 2, ENC_BIG_ENDIAN);
1159
1160
75
    proto_tree_add_item(nbdgm_tree, hf_nbdgm_src_ip, tvb, offset+4, 4, ENC_BIG_ENDIAN);
1161
1162
75
    proto_tree_add_item(nbdgm_tree, hf_nbdgm_src_port, tvb, offset+8, 2, ENC_BIG_ENDIAN);
1163
1164
75
    offset += 10;
1165
1166
75
    switch (msg_type) {
1167
1168
0
    case NBDS_DIRECT_UNIQUE:
1169
0
    case NBDS_DIRECT_GROUP:
1170
70
    case NBDS_BROADCAST:
1171
70
        proto_tree_add_item(nbdgm_tree, hf_nbdgm_datagram_length,
1172
70
                                            tvb, offset, 2, ENC_BIG_ENDIAN);
1173
70
        offset += 2;
1174
1175
70
        proto_tree_add_item(nbdgm_tree, hf_nbdgm_packet_offset,
1176
70
                                            tvb, offset, 2, ENC_BIG_ENDIAN);
1177
70
        offset += 2;
1178
1179
70
        name = (char *)wmem_alloc(pinfo->pool, MAX_NAME_LEN);
1180
1181
        /* Source name */
1182
70
        len = get_nbns_name(tvb, pinfo->pool, offset, offset, name, MAX_NAME_LEN, &name_type);
1183
1184
70
        add_name_and_type(nbdgm_tree, tvb, offset, len, hf_nbdgm_source_name, name, name_type);
1185
70
        offset += len;
1186
1187
        /* Destination name */
1188
70
        len = get_nbns_name(tvb, pinfo->pool, offset, offset, name, MAX_NAME_LEN, &name_type);
1189
1190
70
        add_name_and_type(nbdgm_tree, tvb, offset, len, hf_nbdgm_destination_name, name, name_type);
1191
70
        offset += len;
1192
1193
        /*
1194
         * Here we can pass the packet off to the next protocol.
1195
         * Set the length of our top-level tree item to include
1196
         * only our stuff.
1197
         *
1198
         * XXX - take the datagram length into account, including
1199
         * doing datagram reassembly?
1200
         */
1201
70
        proto_item_set_len(ti, offset);
1202
70
        next_tvb = tvb_new_subset_remaining(tvb, offset);
1203
70
        dissect_netbios_payload(next_tvb, pinfo, tree);
1204
70
        break;
1205
1206
0
    case NBDS_ERROR:
1207
0
        proto_tree_add_item(nbdgm_tree, hf_nbdgm_error_code, tvb, offset,
1208
0
                                1, ENC_BIG_ENDIAN);
1209
0
        offset += 1;
1210
0
        proto_item_set_len(ti, offset);
1211
0
        break;
1212
1213
1
    case NBDS_QUERY_REQUEST:
1214
2
    case NBDS_POS_QUERY_RESPONSE:
1215
2
    case NBDS_NEG_QUERY_RESPONSE:
1216
2
        name = (char *)wmem_alloc(pinfo->pool, MAX_NAME_LEN);
1217
1218
        /* Destination name */
1219
2
        len = get_nbns_name(tvb, pinfo->pool, offset, offset, name, MAX_NAME_LEN, &name_type);
1220
1221
2
        add_name_and_type(nbdgm_tree, tvb, offset, len,
1222
2
                              hf_nbdgm_destination_name, name, name_type);
1223
2
        offset += len;
1224
2
        proto_item_set_len(ti, offset);
1225
2
        break;
1226
75
    }
1227
18
    return tvb_captured_length(tvb);
1228
75
}
1229
1230
/*
1231
 * NetBIOS Session Service message types (RFC 1002).
1232
 */
1233
87
#define SESSION_MESSAGE                 0x00
1234
1
#define SESSION_REQUEST                 0x81
1235
0
#define POSITIVE_SESSION_RESPONSE       0x82
1236
0
#define NEGATIVE_SESSION_RESPONSE       0x83
1237
0
#define RETARGET_SESSION_RESPONSE       0x84
1238
0
#define SESSION_KEEP_ALIVE              0x85
1239
1240
static const value_string message_types[] = {
1241
    { SESSION_MESSAGE,           "Session message" },
1242
    { SESSION_REQUEST,           "Session request" },
1243
    { POSITIVE_SESSION_RESPONSE, "Positive session response" },
1244
    { NEGATIVE_SESSION_RESPONSE, "Negative session response" },
1245
    { RETARGET_SESSION_RESPONSE, "Retarget session response" },
1246
    { SESSION_KEEP_ALIVE,        "Session keep-alive" },
1247
    { 0x0,                       NULL }
1248
};
1249
1250
/*
1251
 * NetBIOS Session Service flags.
1252
 */
1253
165
#define NBSS_FLAGS_E                    0x1
1254
1255
static const value_string nbss_error_codes[] = {
1256
    { 0x80, "Not listening on called name" },
1257
    { 0x81, "Not listening for calling name" },
1258
    { 0x82, "Called name not present" },
1259
    { 0x83, "Called name present, but insufficient resources" },
1260
    { 0x8F, "Unspecified error" },
1261
    { 0x0,  NULL }
1262
};
1263
1264
/*
1265
 * Dissect a single NBSS packet (there may be more than one in a given
1266
 * TCP segment).
1267
 *
1268
 * [ Hmmm, in my experience, I have never seen more than one NBSS in a
1269
 * single segment, since they mostly contain SMBs which are essentially
1270
 * a request response type protocol (RJS). ]
1271
 *
1272
 * [ However, under heavy load with many requests multiplexed on one
1273
 * session it is not unusual to see multiple requests in one TCP
1274
 * segment. Unfortunately, in this case a single session message is
1275
 * frequently split over multiple segments, which frustrates decoding
1276
 * (MMM). ]
1277
 */
1278
static void
1279
dissect_nbss_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1280
                    int is_cifs)
1281
62
{
1282
62
    int          offset = 0;
1283
62
    proto_tree   *nbss_tree = NULL;
1284
62
    proto_item   *ti        = NULL;
1285
62
    uint8_t       msg_type;
1286
62
    uint8_t       flags;
1287
62
    uint32_t      length;
1288
62
    int           len;
1289
62
    char         *name;
1290
62
    int           name_type;
1291
62
    uint8_t       error_code;
1292
62
    tvbuff_t     *next_tvb;
1293
62
    const char   *saved_proto;
1294
62
    static int * const nbss_flags[] = {
1295
62
        &hf_nbss_flags_e,
1296
62
        NULL
1297
62
    };
1298
1299
62
    name = (char *)wmem_alloc(pinfo->pool, MAX_NAME_LEN);
1300
1301
62
    msg_type = tvb_get_uint8(tvb, offset);
1302
1303
62
    ti = proto_tree_add_item(tree, proto_nbss, tvb, offset, -1, ENC_NA);
1304
62
    nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1305
1306
62
    proto_tree_add_item(nbss_tree, hf_nbss_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1307
1308
62
    offset += 1;
1309
1310
62
    if (is_cifs) {
1311
0
        proto_tree_add_item(nbss_tree, hf_nbss_cifs_length, tvb, offset, 3, ENC_BIG_ENDIAN);
1312
0
        offset += 3;
1313
62
    } else {
1314
62
        flags = tvb_get_uint8(tvb, offset);
1315
62
        proto_tree_add_bitmask(nbss_tree, tvb, offset, hf_nbss_flags, ett_nbss_flags, nbss_flags, ENC_BIG_ENDIAN);
1316
1317
62
        length = tvb_get_ntohs(tvb, offset + 1);
1318
62
        if (flags & NBSS_FLAGS_E)
1319
5
            length += 0x10000;
1320
62
        proto_tree_add_uint(nbss_tree, hf_nbss_length, tvb, offset, 3, length);
1321
1322
62
        offset += 3;
1323
62
    }
1324
1325
62
    switch (msg_type) {
1326
1327
1
    case SESSION_REQUEST:
1328
1
        len = get_nbns_name(tvb, pinfo->pool, offset, offset, name, MAX_NAME_LEN, &name_type);
1329
1
        if (tree)
1330
1
            add_name_and_type(nbss_tree, tvb, offset, len,
1331
1
                              hf_nbss_called_name, name, name_type);
1332
1
        offset += len;
1333
1334
1
        col_append_fstr(pinfo->cinfo, COL_INFO, ", to %s ", name);
1335
1336
1
        len = get_nbns_name(tvb, pinfo->pool, offset, offset, name, MAX_NAME_LEN, &name_type);
1337
1338
1
        if (tree)
1339
0
            add_name_and_type(nbss_tree, tvb, offset, len,
1340
0
                              hf_nbss_calling_name, name, name_type);
1341
1342
1
        col_append_fstr(pinfo->cinfo, COL_INFO, "from %s", name);
1343
1344
1
        break;
1345
1346
0
    case NEGATIVE_SESSION_RESPONSE:
1347
0
        error_code = tvb_get_uint8(tvb, offset);
1348
0
        proto_tree_add_uint(nbss_tree, hf_nbss_error_code, tvb, offset, 1,
1349
0
                                error_code);
1350
1351
0
        col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
1352
0
                        val_to_str(pinfo->pool, error_code, nbss_error_codes, "Unknown (%x)"));
1353
1354
0
        break;
1355
1356
0
    case RETARGET_SESSION_RESPONSE:
1357
0
        proto_tree_add_item(nbss_tree, hf_nbss_retarget_ip_address,
1358
0
                                tvb, offset, 4, ENC_BIG_ENDIAN);
1359
1360
0
        offset += 4;
1361
1362
0
        proto_tree_add_item(nbss_tree, hf_nbss_retarget_port,
1363
0
                                tvb, offset, 2, ENC_BIG_ENDIAN);
1364
1365
0
        break;
1366
1367
52
    case SESSION_MESSAGE:
1368
        /*
1369
         * Here we can pass the message off to the next protocol.
1370
         * Set the length of our top-level tree item to include
1371
         * only our stuff.
1372
         */
1373
52
        next_tvb = tvb_new_subset_remaining(tvb, offset);
1374
1375
        /*
1376
         * Dissect the message.
1377
         *
1378
         * If it gets an error that means there's no point in
1379
         * dissecting any more PDUs, rethrow the exception in
1380
         * question.
1381
         *
1382
         * If it gets any other error, report it and continue, as that
1383
         * means that PDU got an error, but that doesn't mean we should
1384
         * stop dissecting PDUs within this frame or chunk of reassembled
1385
         * data.
1386
         */
1387
52
        saved_proto = pinfo->current_proto;
1388
52
        TRY {
1389
52
            dissect_netbios_payload(next_tvb, pinfo, tree);
1390
52
        }
1391
52
        CATCH_NONFATAL_ERRORS {
1392
1
            show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
1393
1
            pinfo->current_proto = saved_proto;
1394
1
        }
1395
52
        ENDTRY;
1396
52
        break;
1397
1398
62
    }
1399
62
}
1400
1401
static int
1402
dissect_continuation_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1403
3
{
1404
3
    proto_tree     *nbss_tree;
1405
3
    proto_item     *ti;
1406
1407
    /*
1408
     * It looks like a continuation.
1409
     */
1410
3
    col_set_str(pinfo->cinfo, COL_INFO, "NBSS Continuation Message");
1411
1412
3
    if (tree) {
1413
3
        ti = proto_tree_add_item(tree, proto_nbss, tvb, 0, -1, ENC_NA);
1414
3
        nbss_tree = proto_item_add_subtree(ti, ett_nbss);
1415
3
        proto_tree_add_item(nbss_tree, hf_nbss_continuation_data, tvb, 0, -1, ENC_NA);
1416
3
    }
1417
1418
3
    return tvb_captured_length(tvb);
1419
3
}
1420
1421
static int
1422
dissect_nbss(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1423
14
{
1424
14
    struct tcpinfo *tcpinfo;
1425
14
    int             offset  = 0;
1426
14
    unsigned        length_remaining;
1427
14
    unsigned        plen;
1428
14
    int             max_data;
1429
14
    uint8_t         msg_type;
1430
14
    uint8_t         flags;
1431
14
    uint32_t        length;
1432
14
    bool            is_cifs;
1433
14
    tvbuff_t       *next_tvb;
1434
1435
    /* Reject the packet if data is NULL */
1436
14
    if (data == NULL)
1437
0
        return 0;
1438
14
    tcpinfo = (struct tcpinfo *)data;
1439
1440
14
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBSS");
1441
14
    col_clear(pinfo->cinfo, COL_INFO);
1442
1443
14
    max_data = tvb_captured_length(tvb);
1444
1445
14
    msg_type = tvb_get_uint8(tvb, offset);
1446
1447
14
    if (pinfo->match_uint == TCP_PORT_CIFS) {
1448
        /*
1449
         * Windows 2000 CIFS clients can dispense completely
1450
         * with the NETBIOS encapsulation and directly use CIFS
1451
         * over TCP. As would be expected, the framing is
1452
         * identical, except that the length is 24 bits instead
1453
         * of 17. The only message types used are
1454
         * SESSION_MESSAGE and SESSION_KEEP_ALIVE.
1455
         */
1456
1
        is_cifs = true;
1457
13
    } else {
1458
13
        is_cifs = false;
1459
13
    }
1460
1461
    /*
1462
     * This might be a continuation of an earlier message.
1463
     * (Yes, that might be true even if we're doing TCP reassembly,
1464
     * as the first TCP segment in the capture might start in the
1465
     * middle of an NBNS message.)
1466
     */
1467
1468
    /*
1469
     * If this isn't reassembled data, check to see whether it
1470
     * looks like a continuation of a message.
1471
     * (If it is reassembled data, it shouldn't be a continuation,
1472
     * as reassembly should've gathered the continuations together
1473
     * into a message.)
1474
     * XXX: Unless it was reassembled because we didn't have enough
1475
     * data for a NBSS header, it had a first byte that looked like a
1476
     * message type, but it turned out not to be a message but continuation
1477
     * data after all. Perhaps we should check even reassembled data,
1478
     * at least if it's the first message in the conversation.
1479
     */
1480
14
    if (!tcpinfo->is_reassembled) {
1481
14
        if (max_data < 4) {
1482
            /*
1483
             * Not enough data for an NBSS header. It could be a message
1484
             * split into a very small payload, or a continuation of a message.
1485
             */
1486
1
            if (try_val_to_str(msg_type, message_types)) {
1487
                /*
1488
                 * The first byte looks like a valid message type.
1489
                 * Can we do reassembly?
1490
                 */
1491
0
                if (nbss_desegment && pinfo->can_desegment) {
1492
                    /*
1493
                     * Yes.  Tell the TCP dissector where the data for this message
1494
                     * starts in the data it handed us and that we need "some more
1495
                     * data."  Don't tell it exactly how many bytes we need because
1496
                     * if/when we ask for even more (after the header) that will
1497
                     * break reassembly.
1498
                     */
1499
0
                    pinfo->desegment_offset = offset;
1500
0
                    pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
1501
0
                    return tvb_captured_length(tvb);
1502
0
                }
1503
0
            }
1504
            /*
1505
             * Either we can't do reassembly, or this doesn't look
1506
             * like a valid message type. Mark it as continuation.
1507
             */
1508
1
            return dissect_continuation_packet(tvb, pinfo, tree);
1509
1
        }
1510
1511
        /*
1512
         * The largest size in for non-SMB NBSS traffic is
1513
         * 17 bits (0x1FFFF).
1514
         *
1515
         * The SMB1 unix extensions and the SMB2 multi credit
1516
         * feature allow more than 17 bits (0x1FFFF), they allow
1517
         * 24 bits (0xFFFFFF).
1518
         *
1519
         * So if it is a SESSION_MESSAGE and SMB1 or SMB2
1520
         * mark it as is_cifs.
1521
         */
1522
13
        if (tvb_captured_length_remaining(tvb, offset) >= 8
1523
11
            && tvb_get_uint8(tvb,offset+0) == SESSION_MESSAGE
1524
10
            && tvb_get_uint8(tvb,offset+5) == 'S'
1525
1
            && tvb_get_uint8(tvb,offset+6) == 'M'
1526
0
            && tvb_get_uint8(tvb,offset+7) == 'B') {
1527
0
            is_cifs = true;
1528
13
        } else {
1529
13
            is_cifs = false;
1530
13
        }
1531
1532
        /*
1533
         * We have enough data for an NBSS header.
1534
         * Get the flags and length of the message,
1535
         * and see if they're sane.
1536
         */
1537
13
        if (is_cifs) {
1538
0
            flags = 0;
1539
0
            length = tvb_get_ntoh24(tvb, offset + 1);
1540
13
        } else {
1541
13
            flags  = tvb_get_uint8(tvb, offset + 1);
1542
13
            length = tvb_get_ntohs(tvb, offset + 2);
1543
13
            if (flags & NBSS_FLAGS_E)
1544
2
                length += 0x10000;
1545
13
        }
1546
13
        if ((flags & (~NBSS_FLAGS_E)) != 0) {
1547
            /*
1548
             * A bogus flag was set; assume it's a continuation.
1549
             */
1550
2
            return dissect_continuation_packet(tvb, pinfo, tree);
1551
2
        }
1552
1553
11
        switch (msg_type) {
1554
1555
11
        case SESSION_MESSAGE:
1556
            /*
1557
             * This is variable-length.
1558
             * All we know is that it shouldn't be zero.
1559
             * (XXX - can we get zero-length messages?
1560
             * Not with SMB, but perhaps other NetBIOS-based
1561
             * protocols have them.)
1562
             */
1563
11
            if (length == 0)
1564
0
                return dissect_continuation_packet(tvb, pinfo, tree);
1565
1566
11
            break;
1567
1568
11
        case SESSION_REQUEST:
1569
            /*
1570
             * This is variable-length.
1571
             * The names are DNS-encoded 32-byte values;
1572
             * we need at least 2 bytes (one for each name;
1573
             * actually, we should have more for the first
1574
             * name, as there's no name preceding it so
1575
             * there should be no compression), and we
1576
             * shouldn't have more than 128 bytes (actually,
1577
             * we shouldn't have that many).
1578
             *
1579
             * XXX - actually, Mac OS X 10.1 (yes, that's
1580
             * redundant, but that's what Apple calls it,
1581
             * not Mac OS X.1) puts names longer than 16
1582
             * characters into session request messages,
1583
             * so we can have more than 32 bytes of
1584
             * name value, so we can have more than 128
1585
             * bytes of data.
1586
             */
1587
0
            if (length < 2 || length > 256)
1588
0
                return dissect_continuation_packet(tvb, pinfo, tree);
1589
0
            break;
1590
1591
0
        case POSITIVE_SESSION_RESPONSE:
1592
            /*
1593
             * This has no data, so the length must be zero.
1594
             */
1595
0
            if (length != 0)
1596
0
                return dissect_continuation_packet(tvb, pinfo, tree);
1597
0
            break;
1598
1599
0
        case NEGATIVE_SESSION_RESPONSE:
1600
            /*
1601
             * This has 1 byte of data.
1602
             */
1603
0
            if (length != 1)
1604
0
                return dissect_continuation_packet(tvb, pinfo, tree);
1605
0
            break;
1606
1607
0
        case RETARGET_SESSION_RESPONSE:
1608
            /*
1609
             * This has 6 bytes of data.
1610
             */
1611
0
            if (length != 6)
1612
0
                return dissect_continuation_packet(tvb, pinfo, tree);
1613
0
            break;
1614
1615
0
        case SESSION_KEEP_ALIVE:
1616
            /*
1617
             * This has no data, so the length must be zero.
1618
             */
1619
0
            if (length != 0)
1620
0
                return dissect_continuation_packet(tvb, pinfo, tree);
1621
0
            break;
1622
1623
0
        default:
1624
            /*
1625
             * Unknown message type; assume it's a continuation.
1626
             */
1627
0
            return dissect_continuation_packet(tvb, pinfo, tree);
1628
11
        }
1629
11
    }
1630
1631
11
    col_add_str(pinfo->cinfo, COL_INFO,
1632
11
                val_to_str(pinfo->pool, msg_type, message_types, "Unknown (%02x)"));
1633
1634
73
    while ((length_remaining = tvb_reported_length_remaining(tvb, offset)) > 0) {
1635
        /*
1636
         * Can we do reassembly?
1637
         */
1638
62
        if (nbss_desegment && pinfo->can_desegment) {
1639
            /*
1640
             * Yes - is the NBSS header split across segment boundaries?
1641
             */
1642
0
            if (length_remaining < 4) {
1643
                /*
1644
                 * Yes.  Tell the TCP dissector where the data for this message
1645
                 * starts in the data it handed us and that we need "some more
1646
                 * data."  Don't tell it exactly how many bytes we need because
1647
                 * if/when we ask for even more (after the header) that will
1648
                 * break reassembly.
1649
                 */
1650
0
                pinfo->desegment_offset = offset;
1651
0
                pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
1652
0
                return tvb_captured_length(tvb);
1653
0
            }
1654
0
        }
1655
1656
        /*
1657
         * Get the length of the NBSS message.
1658
         */
1659
62
        if (is_cifs) {
1660
0
            length = tvb_get_ntoh24(tvb, offset + 1);
1661
62
        } else {
1662
62
            flags  = tvb_get_uint8(tvb, offset + 1);
1663
62
            length = tvb_get_ntohs(tvb, offset + 2);
1664
62
            if (flags & NBSS_FLAGS_E)
1665
5
                length += 65536;
1666
62
        }
1667
62
        plen = length + 4; /* Include length of NBSS header */
1668
1669
        /* give a hint to TCP where the next PDU starts
1670
         * so that it can attempt to find it in case it starts
1671
         * somewhere in the middle of a segment.
1672
         */
1673
62
        if(!pinfo->fd->visited){
1674
            /* 'Only' SMB is transported on top of this, so make sure
1675
             * there is an SMB header there ...
1676
             */
1677
62
            if( (plen>tvb_reported_length_remaining(tvb, offset))
1678
11
                &&(tvb_captured_length_remaining(tvb, offset) >= 8)
1679
8
                &&(tvb_get_uint8(tvb,offset+5) == 'S')
1680
0
                &&(tvb_get_uint8(tvb,offset+6) == 'M')
1681
0
                &&(tvb_get_uint8(tvb,offset+7) == 'B') ){
1682
0
                pinfo->want_pdu_tracking = 2;
1683
0
                pinfo->bytes_until_next_pdu = (length+4)-tvb_reported_length_remaining(tvb, offset);
1684
0
            }
1685
62
        }
1686
1687
        /*
1688
         * Can we do reassembly?
1689
         */
1690
62
        if (nbss_desegment && pinfo->can_desegment) {
1691
            /*
1692
             * Yes - is the NBSS message split across segment boundaries?
1693
             */
1694
0
            if (length_remaining < plen) {
1695
                /*
1696
                 * Yes.  Tell the TCP dissector where the data for this message
1697
                 * starts in the data it handed us, and how many more bytes we
1698
                 * need, and return.
1699
                 */
1700
0
                pinfo->desegment_offset = offset;
1701
0
                pinfo->desegment_len = plen - length_remaining;
1702
0
                return tvb_captured_length(tvb);
1703
0
            }
1704
0
        }
1705
1706
        /*
1707
         * Construct a tvbuff containing the amount of the payload we have
1708
         * available.  Make its reported length the amount of data in the PDU.
1709
         */
1710
62
        next_tvb = tvb_new_subset_length(tvb, offset, plen);
1711
1712
62
        dissect_nbss_packet(next_tvb, pinfo, tree, is_cifs);
1713
1714
62
        offset += plen;
1715
62
    }
1716
1717
11
    return tvb_captured_length(tvb);
1718
11
}
1719
1720
void
1721
proto_register_nbt(void)
1722
15
{
1723
1724
15
    static hf_register_info hf_nbns[] = {
1725
15
        { &hf_nbns_flags,
1726
15
          { "Flags",            "nbns.flags",
1727
15
            FT_UINT16, BASE_HEX, NULL, 0x0,
1728
15
            NULL, HFILL }},
1729
15
        { &hf_nbns_flags_response,
1730
15
          { "Response",         "nbns.flags.response",
1731
15
            FT_BOOLEAN, 16, TFS(&tfs_flags_response), F_RESPONSE,
1732
15
            "Is the message a response?", HFILL }},
1733
15
        { &hf_nbns_flags_opcode,
1734
15
          { "Opcode",           "nbns.flags.opcode",
1735
15
            FT_UINT16, BASE_DEC, VALS(opcode_vals), F_OPCODE,
1736
15
            "Operation code", HFILL }},
1737
15
        { &hf_nbns_flags_authoritative,
1738
15
          { "Authoritative",    "nbns.flags.authoritative",
1739
15
            FT_BOOLEAN, 16, TFS(&tfs_flags_authoritative), F_AUTHORITATIVE,
1740
15
            "Is the server is an authority for the domain?", HFILL }},
1741
15
        { &hf_nbns_flags_truncated,
1742
15
          { "Truncated",        "nbns.flags.truncated",
1743
15
            FT_BOOLEAN, 16, TFS(&tfs_flags_truncated), F_TRUNCATED,
1744
15
            "Is the message truncated?", HFILL }},
1745
15
        { &hf_nbns_flags_recdesired,
1746
15
          { "Recursion desired",        "nbns.flags.recdesired",
1747
15
            FT_BOOLEAN, 16, TFS(&tfs_flags_recdesired), F_RECDESIRED,
1748
15
            "Do query recursively?", HFILL }},
1749
15
        { &hf_nbns_flags_recavail,
1750
15
          { "Recursion available",      "nbns.flags.recavail",
1751
15
            FT_BOOLEAN, 16, TFS(&tfs_flags_recavail), F_RECAVAIL,
1752
15
            "Can the server do recursive queries?", HFILL }},
1753
15
        { &hf_nbns_flags_broadcast,
1754
15
          { "Broadcast",                "nbns.flags.broadcast",
1755
15
            FT_BOOLEAN, 16, TFS(&tfs_flags_broadcast), F_BROADCAST,
1756
15
            "Is this a broadcast packet?", HFILL }},
1757
15
        { &hf_nbns_flags_rcode,
1758
15
          { "Reply code",               "nbns.flags.rcode",
1759
15
            FT_UINT16, BASE_DEC, VALS(rcode_vals), F_RCODE,
1760
15
            NULL, HFILL }},
1761
15
        { &hf_nbns_transaction_id,
1762
15
          { "Transaction ID",           "nbns.id",
1763
15
            FT_UINT16, BASE_HEX, NULL, 0x0,
1764
15
            "Identification of transaction", HFILL }},
1765
15
        { &hf_nbns_count_questions,
1766
15
          { "Questions",                "nbns.count.queries",
1767
15
            FT_UINT16, BASE_DEC, NULL, 0x0,
1768
15
            "Number of queries in packet", HFILL }},
1769
15
        { &hf_nbns_count_answers,
1770
15
          { "Answer RRs",               "nbns.count.answers",
1771
15
            FT_UINT16, BASE_DEC, NULL, 0x0,
1772
15
            "Number of answers in packet", HFILL }},
1773
15
        { &hf_nbns_count_auth_rr,
1774
15
          { "Authority RRs",            "nbns.count.auth_rr",
1775
15
            FT_UINT16, BASE_DEC, NULL, 0x0,
1776
15
            "Number of authoritative records in packet", HFILL }},
1777
15
        { &hf_nbns_count_add_rr,
1778
15
          { "Additional RRs",           "nbns.count.add_rr",
1779
15
            FT_UINT16, BASE_DEC, NULL, 0x0,
1780
15
            "Number of additional records in packet", HFILL }},
1781
15
        { &hf_nbns_name_flags,
1782
15
          { "Name flags",       "nbns.name_flags",
1783
15
            FT_UINT16, BASE_HEX, NULL, 0x0,
1784
15
            NULL, HFILL }},
1785
15
        { &hf_nbns_name_flags_group,
1786
15
          { "Name type",        "nbns.name_flags.group",
1787
15
            FT_BOOLEAN, 16, TFS(&tfs_group_unique_name), NAME_FLAGS_G,
1788
15
            NULL, HFILL }},
1789
15
        { &hf_nbns_name_flags_ont,
1790
15
          { "ONT",              "nbns.name_flags.ont",
1791
15
            FT_UINT16, BASE_DEC, VALS(name_flags_ont_vals), NAME_FLAGS_ONT,
1792
15
            NULL, HFILL }},
1793
15
        { &hf_nbns_name_flags_drg,
1794
15
          { "Name is being deregistered",       "nbns.name_flags.drg",
1795
15
            FT_BOOLEAN, 16, TFS(&tfs_yes_no), NAME_FLAGS_DRG,
1796
15
            NULL, HFILL }},
1797
15
        { &hf_nbns_name_flags_cnf,
1798
15
          { "Name is in conflict",              "nbns.name_flags.cnf",
1799
15
            FT_BOOLEAN, 16, TFS(&tfs_yes_no), NAME_FLAGS_CNF,
1800
15
            NULL, HFILL }},
1801
15
        { &hf_nbns_name_flags_act,
1802
15
          { "Name is active",           "nbns.name_flags.act",
1803
15
            FT_BOOLEAN, 16, TFS(&tfs_yes_no), NAME_FLAGS_ACT,
1804
15
            NULL, HFILL }},
1805
15
        { &hf_nbns_name_flags_prm,
1806
15
          { "Permanent node name",              "nbns.name_flags.prm",
1807
15
            FT_BOOLEAN, 16, TFS(&tfs_yes_no), NAME_FLAGS_PRM,
1808
15
            NULL, HFILL }},
1809
15
        { &hf_nbns_nb_flags,
1810
15
          { "Name flags",       "nbns.nb_flags",
1811
15
            FT_UINT16, BASE_HEX, NULL, 0x0,
1812
15
            NULL, HFILL }},
1813
15
        { &hf_nbns_nb_flags_group,
1814
15
          { "Name type",        "nbns.nb_flags.group",
1815
15
            FT_BOOLEAN, 16, TFS(&tfs_group_unique_name), NB_FLAGS_G,
1816
15
            NULL, HFILL }},
1817
15
        { &hf_nbns_nb_flags_ont,
1818
15
          { "ONT",              "nbns.nb_flags.ont",
1819
15
            FT_UINT16, BASE_DEC, VALS(nb_flags_ont_vals), NB_FLAGS_ONT,
1820
15
            NULL, HFILL }},
1821
15
        { &hf_nbns_type,
1822
15
          { "Type",              "nbns.type",
1823
15
            FT_UINT16, BASE_DEC, VALS(nb_type_name_vals), 0x0,
1824
15
            NULL, HFILL }},
1825
15
        { &hf_nbns_class,
1826
15
          { "Class",              "nbns.class",
1827
15
            FT_UINT16, BASE_DEC, VALS(dns_classes), 0x0,
1828
15
            NULL, HFILL }},
1829
15
        { &hf_nbns_name,
1830
15
          { "Name",            "nbns.name",
1831
15
            FT_STRING, BASE_NONE, NULL, 0x0,
1832
15
            NULL, HFILL }},
1833
1834
      /* Generated from convert_proto_tree_add_text.pl */
1835
15
      { &hf_nbns_addr, { "Addr", "nbns.addr", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1836
15
      { &hf_nbns_number_of_names, { "Number of names", "nbns.number_of_names", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1837
15
      { &hf_nbns_unit_id, { "Unit ID", "nbns.unit_id", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1838
15
      { &hf_nbns_jumpers, { "Jumpers", "nbns.jumpers", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1839
15
      { &hf_nbns_test_result, { "Test result", "nbns.test_result", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1840
15
      { &hf_nbns_version_number, { "Version number", "nbns.version_number", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1841
15
      { &hf_nbns_period_of_statistics, { "Period of statistics", "nbns.period_of_statistics", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
1842
15
      { &hf_nbns_num_crcs, { "Number of CRCs", "nbns.num_crcs", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1843
15
      { &hf_nbns_num_alignment_errors, { "Number of alignment errors", "nbns.num_alignment_errors", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1844
15
      { &hf_nbns_num_collisions, { "Number of collisions", "nbns.num_collisions", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1845
15
      { &hf_nbns_num_send_aborts, { "Number of send aborts", "nbns.num_send_aborts", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1846
15
      { &hf_nbns_num_good_sends, { "Number of good sends", "nbns.num_good_sends", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1847
15
      { &hf_nbns_num_good_receives, { "Number of good receives", "nbns.num_good_receives", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1848
15
      { &hf_nbns_num_retransmits, { "Number of retransmits", "nbns.numretransmits", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1849
15
      { &hf_nbns_num_no_resource_conditions, { "Number of no resource conditions", "nbns.num_no_resource_conditions", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1850
15
      { &hf_nbns_num_command_blocks, { "Number of command blocks", "nbns.numcommand_blocks", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1851
15
      { &hf_nbns_num_pending_sessions, { "Number of pending sessions", "nbns.numpending_sessions", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1852
15
      { &hf_nbns_max_num_pending_sessions, { "Max number of pending sessions", "nbns.max_num_pending_sessions", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1853
15
      { &hf_nbns_max_total_sessions_possible, { "Max total sessions possible", "nbns.max_total_sessions_possible", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1854
15
      { &hf_nbns_session_data_packet_size, { "Session data packet size", "nbns.session_data_packet_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1855
15
      { &hf_nbns_data, { "Data", "nbns.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1856
15
      { &hf_nbns_netbios_name, { "Name", "nbns.netbios_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1857
15
      { &hf_nbns_ttl, { "Time to live", "nbns.ttl", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1858
15
      { &hf_nbns_data_length, { "Data length", "nbns.data_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1859
15
    };
1860
1861
15
    static hf_register_info hf_nbdgm[] = {
1862
15
        { &hf_nbdgm_type,
1863
15
          { "Message Type",             "nbdgm.type",
1864
15
            FT_UINT8, BASE_DEC, VALS(nbds_msgtype_vals), 0x0,
1865
15
            "NBDGM message type", HFILL }},
1866
15
        { &hf_nbdgm_flags,
1867
15
          { "Flags",             "nbdgm.flags",
1868
15
            FT_UINT8, BASE_HEX, NULL, 0x0,
1869
15
            NULL, HFILL }},
1870
15
        { &hf_nbdgm_fragment,
1871
15
          { "More fragments follow",    "nbdgm.next",
1872
15
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
1873
15
            "true if more fragments follow", HFILL }},
1874
15
        { &hf_nbdgm_first,
1875
15
          { "This is first fragment",   "nbdgm.first",
1876
15
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
1877
15
            "true if first fragment", HFILL }},
1878
15
        { &hf_nbdgm_node_type,
1879
15
          { "Node Type",                "nbdgm.node_type",
1880
15
            FT_UINT8, BASE_DEC, VALS(node_type_vals), 0x0C,
1881
15
            NULL, HFILL }},
1882
15
        { &hf_nbdgm_datagram_id,
1883
15
          { "Datagram ID",              "nbdgm.dgram_id",
1884
15
            FT_UINT16, BASE_HEX, NULL, 0x0,
1885
15
            "Datagram identifier", HFILL }},
1886
15
        { &hf_nbdgm_src_ip,
1887
15
          { "Source IP",                "nbdgm.src.ip",
1888
15
            FT_IPv4, BASE_NONE, NULL, 0x0,
1889
15
            "Source IPv4 address", HFILL }},
1890
15
        { &hf_nbdgm_src_port,
1891
15
          { "Source Port",              "nbdgm.src.port",
1892
15
            FT_UINT16, BASE_DEC, NULL, 0x0,
1893
15
            NULL, HFILL }},
1894
15
        { &hf_nbdgm_datagram_length,
1895
15
          { "Datagram length",          "nbdgm.dgram_len",
1896
15
            FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0,
1897
15
            NULL, HFILL }},
1898
15
        { &hf_nbdgm_packet_offset,
1899
15
          { "Packet offset",            "nbdgm.pkt_offset",
1900
15
            FT_UINT16, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0,
1901
15
            NULL, HFILL }},
1902
15
        { &hf_nbdgm_error_code,
1903
15
          { "Error code",               "nbdgm.error_code",
1904
15
            FT_UINT8, BASE_HEX, VALS(nbds_error_codes), 0x0,
1905
15
            NULL, HFILL }},
1906
15
        { &hf_nbdgm_source_name,
1907
15
          { "Source name",            "nbdgm.source_name",
1908
15
            FT_STRING, BASE_NONE, NULL, 0x0,
1909
15
            NULL, HFILL }},
1910
15
        { &hf_nbdgm_destination_name,
1911
15
          { "Destination name",            "nbdgm.destination_name",
1912
15
            FT_STRING, BASE_NONE, NULL, 0x0,
1913
15
            NULL, HFILL }},
1914
15
    };
1915
1916
15
    static hf_register_info hf_nbss[] = {
1917
15
        { &hf_nbss_type,
1918
15
          { "Message Type",             "nbss.type",
1919
15
            FT_UINT8, BASE_HEX, VALS(message_types), 0x0,
1920
15
            "NBSS message type", HFILL }},
1921
15
        { &hf_nbss_flags,
1922
15
          { "Flags",            "nbss.flags",
1923
15
            FT_UINT8, BASE_HEX, NULL, 0x0,
1924
15
            "NBSS message flags", HFILL }},
1925
15
        { &hf_nbss_flags_e,
1926
15
          { "Extend",           "nbss.flags.e",
1927
15
            FT_BOOLEAN, 8, TFS(&tfs_nbss_flags_e), NBSS_FLAGS_E,
1928
15
            NULL, HFILL }},
1929
15
        { &hf_nbss_length,
1930
15
          { "Length",           "nbss.length",
1931
15
            FT_UINT24, BASE_DEC, NULL, 0x0,
1932
15
            "Length of trailer (payload) following this field in bytes", HFILL }},
1933
15
        { &hf_nbss_cifs_length,
1934
15
          { "Length",           "nbss.length",
1935
15
            FT_UINT24, BASE_DEC, NULL, 0x0,
1936
15
            "Length trailer (payload) following this field in bytes", HFILL }},
1937
15
        { &hf_nbss_error_code,
1938
15
          { "Error code",       "nbss.error_code",
1939
15
            FT_UINT8, BASE_HEX, VALS(nbss_error_codes), 0x0,
1940
15
            NULL, HFILL }},
1941
15
        { &hf_nbss_retarget_ip_address,
1942
15
          { "Retarget IP address",      "nbss.retarget_ip_address",
1943
15
            FT_IPv4, BASE_NONE, NULL, 0x0,
1944
15
            NULL, HFILL }},
1945
15
        { &hf_nbss_retarget_port,
1946
15
          { "Retarget port",    "nbss.retarget_port",
1947
15
            FT_UINT16, BASE_DEC, NULL, 0x0,
1948
15
            NULL, HFILL }},
1949
15
        { &hf_nbss_continuation_data,
1950
15
          { "Continuation data", "nbss.continuation_data",
1951
15
             FT_BYTES, BASE_NONE, NULL, 0x0,
1952
15
             NULL, HFILL }},
1953
15
        { &hf_nbss_called_name,
1954
15
          { "Called name", "nbss.called_name",
1955
15
             FT_STRING, BASE_NONE, NULL, 0x0,
1956
15
             NULL, HFILL }},
1957
15
        { &hf_nbss_calling_name,
1958
15
          { "Calling name", "nbss.calling_name",
1959
15
             FT_STRING, BASE_NONE, NULL, 0x0,
1960
15
             NULL, HFILL }},
1961
15
    };
1962
15
    static int *ett[] = {
1963
15
        &ett_nbns,
1964
15
        &ett_nbns_qd,
1965
15
        &ett_nbns_flags,
1966
15
        &ett_nbns_nb_flags,
1967
15
        &ett_nbns_name_flags,
1968
15
        &ett_nbns_rr,
1969
15
        &ett_nbns_qry,
1970
15
        &ett_nbns_ans,
1971
15
        &ett_nbdgm,
1972
15
        &ett_nbdgm_flags,
1973
15
        &ett_nbss,
1974
15
        &ett_nbss_flags,
1975
15
    };
1976
1977
15
    static ei_register_info ei[] = {
1978
15
        { &ei_nbns_incomplete_entry, { "nbns.incomplete_entry", PI_MALFORMED, PI_ERROR, "incomplete entry", EXPFILL }},
1979
15
    };
1980
1981
15
    module_t *nbss_module;
1982
15
    expert_module_t* expert_nbns;
1983
1984
15
    proto_nbns = proto_register_protocol("NetBIOS Name Service", "NBNS", "nbns");
1985
15
    nbns_handle = register_dissector("nbns", dissect_nbns, proto_nbns);
1986
15
    proto_register_field_array(proto_nbns, hf_nbns, array_length(hf_nbns));
1987
15
    expert_nbns = expert_register_protocol(proto_nbns);
1988
15
    expert_register_field_array(expert_nbns, ei, array_length(ei));
1989
1990
15
    proto_nbdgm = proto_register_protocol("NetBIOS Datagram Service",
1991
15
                                          "NBDS", "nbdgm");
1992
15
    nbdgm_handle = register_dissector("nbds", dissect_nbdgm, proto_nbdgm);
1993
15
    proto_register_field_array(proto_nbdgm, hf_nbdgm, array_length(hf_nbdgm));
1994
1995
15
    proto_nbss = proto_register_protocol("NetBIOS Session Service",
1996
15
                                         "NBSS", "nbss");
1997
15
    nbss_handle  = register_dissector("nbss", dissect_nbss, proto_nbss);
1998
15
    proto_register_field_array(proto_nbss, hf_nbss, array_length(hf_nbss));
1999
2000
15
    proto_register_subtree_array(ett, array_length(ett));
2001
2002
15
    nbss_module = prefs_register_protocol(proto_nbss, NULL);
2003
15
    prefs_register_bool_preference(nbss_module, "desegment_nbss_commands",
2004
15
                                   "Reassemble NBSS packets spanning multiple TCP segments",
2005
15
                                   "Whether the NBSS dissector should reassemble packets spanning multiple TCP segments."
2006
15
                                   " To use this option, you must also enable"
2007
15
                                   " \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2008
15
                                   &nbss_desegment);
2009
15
}
2010
2011
void
2012
proto_reg_handoff_nbt(void)
2013
15
{
2014
15
    dissector_add_uint_with_preference("udp.port", UDP_PORT_NBNS, nbns_handle);
2015
15
    dissector_add_uint_with_preference("udp.port", UDP_PORT_NBDGM, nbdgm_handle);
2016
15
    dissector_add_uint_range_with_preference("tcp.port", TCP_NBSS_PORT_RANGE, nbss_handle);
2017
2018
15
    netbios_heur_subdissector_list = find_heur_dissector_list("netbios");
2019
2020
15
    dissector_add_string("quic.proto", "smb", nbss_handle);
2021
15
}
2022
2023
/*
2024
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
2025
 *
2026
 * Local variables:
2027
 * c-basic-offset: 4
2028
 * tab-width: 8
2029
 * indent-tabs-mode: nil
2030
 * End:
2031
 *
2032
 * vi: set shiftwidth=4 tabstop=8 expandtab:
2033
 * :indentSize=4:tabSize=8:noTabs=true:
2034
 */