Coverage Report

Created: 2026-07-12 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-nbipx.c
Line
Count
Source
1
/* packet-nbipx.c
2
 * Routines for NetBIOS over IPX packet disassembly
3
 * Gilbert Ramirez <gram@alumni.rice.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/tfs.h>
16
#include <wsutil/array.h>
17
#include "packet-ipx.h"
18
#include "packet-netbios.h"
19
20
void proto_register_nbipx(void);
21
void proto_reg_handoff_nbipx(void);
22
void proto_register_nmpi(void);
23
void proto_reg_handoff_nmpi(void);
24
25
static dissector_handle_t nbipx_handle;
26
static dissector_handle_t nmpi_handle;
27
28
static int proto_nbipx;
29
static int hf_nbipx_packettype;
30
static int hf_nbipx_name_flags;
31
static int hf_nbipx_name_flags_group;
32
static int hf_nbipx_name_flags_in_use;
33
static int hf_nbipx_name_flags_registered;
34
static int hf_nbipx_name_flags_duplicated;
35
static int hf_nbipx_name_flags_deregistered;
36
static int hf_nbipx_conn_control;
37
static int hf_nbipx_conn_control_sys_packet;
38
static int hf_nbipx_conn_control_ack;
39
static int hf_nbipx_conn_control_attention;
40
static int hf_nbipx_conn_control_end_msg;
41
static int hf_nbipx_conn_control_resend;
42
static int hf_nbipx_session_src_conn_id;
43
static int hf_nbipx_session_dest_conn_id;
44
static int hf_nbipx_session_send_seq_number;
45
static int hf_nbipx_session_total_data_length;
46
static int hf_nbipx_session_offset;
47
static int hf_nbipx_session_data_length;
48
static int hf_nbipx_session_recv_seq_number;
49
static int hf_nbipx_session_bytes_received;
50
static int hf_nbipx_ipx_network;
51
static int hf_nbipx_opcode;
52
static int hf_nbipx_name_type;
53
static int hf_nbipx_messageid;
54
55
static int ett_nbipx;
56
static int ett_nbipx_conn_ctrl;
57
static int ett_nbipx_name_type_flags;
58
59
static void dissect_conn_control(tvbuff_t *tvb, unsigned offset, proto_tree *tree);
60
61
static heur_dissector_list_t netbios_heur_subdissector_list;
62
63
/* There is no RFC or public specification of Netware or Microsoft
64
 * NetBIOS over IPX packets. I have had to decode the protocol myself,
65
 * so there are holes and perhaps errors in this code. (gram)
66
 *
67
 * A list of "NovelNetBIOS" packet types can be found at
68
 *
69
 *  http://web.archive.org/web/20150319134837/http://www.protocols.com/pbook/novel.htm#NetBIOS
70
 *
71
 * and at least some of those packet types appear to match what's in
72
 * some NBIPX packets.
73
 *
74
 * Note, however, that it appears that sometimes NBIPX packets have
75
 * 8 IPX addresses at the beginning, and sometimes they don't.
76
 *
77
 * In the section on "NetBIOS Broadcasts", the document at
78
 *
79
 *  http://www.microsoft.com/technet/network/ipxrout.asp
80
 *
81
 * says that "the NetBIOS over IPX Broadcast header" contains 8 IPX
82
 * network numbers in the "IPX WAN broadcast header", and that it's
83
 * followed by a "Name Type Flags" byte (giving information about the
84
 * name being registered, deregistered, or checked), a "Data Stream
85
 * Type 2" byte giving the type of operation (NBIPX_FIND_NAME,
86
 * NBIPX_NAME_RECOGNIZED, or NBIPX_CHECK_NAME - the latter is called
87
 * "Add Name"), and a 16-byte NetBIOS name.
88
 *
89
 * It also says that "NetBIOS over IPX Broadcast packets" have a
90
 * packet type of 0x14 (20, or IPX_PACKET_TYPE_WANBCAST) and a
91
 * socket number of 0x455 (IPX_SOCKET_NETBIOS).
92
 *
93
 * However, there are also non-broadcast packets that *also* contain
94
 * the 8 IPX network numbers; they appear to be replies to broadcast
95
 * packets, and have a packet type of 0x4 (IPX_PACKET_TYPE_PEP).
96
 *
97
 * Other IPX_PACKET_TYPE_PEP packets to and from the IPX_SOCKET_NETBIOS
98
 * socket, however, *don't* have the 8 IPX network numbers; there does
99
 * not seem to be any obvious algorithm to determine whether the packet
100
 * has the addresses or not.  Microsoft Knowledge Base article Q128335
101
 * appears to show some code from the NBIPX implementation in NT that
102
 * tries to determine the packet type - and it appears to use heuristics
103
 * based on the packet length and on looking at what might be the NBIPX
104
 * "Data Stream Type" byte depending on whether the packet has the 8
105
 * IPX network numbers or not.
106
 *
107
 * So, for now, we treat *all* NBIPX packets as having a "Data Stream
108
 * Type" byte, preceded by another byte of NBIPX information and
109
 * followed by more NBIPX stuff, and assume that it's preceded by
110
 * 8 IPX network numbers iff:
111
 *
112
 *  the packet is a WAN Broadcast packet
113
 *
114
 * or
115
 *
116
 *  the packet is the right size for one of those PEP name replies
117
 *  (50 bytes) *and* has a name packet type as the Data Stream
118
 *  Type byte at the offset where that byte would be if the packet
119
 *  does have the 8 IPX network numbers at the beginning.
120
 *
121
 * The page at
122
 *
123
 *  http://ourworld.compuserve.com/homepages/TimothyDEvans/encap.htm
124
 *
125
 * indicates, under "NBIPX session packets", that "NBIPX session packets"
126
 * have
127
 *
128
 *  1 byte of NBIPX connection control flag
129
 *  1 byte of data stream type
130
 *  2 bytes of source connection ID
131
 *  2 bytes of destination connection ID
132
 *  2 bytes of send sequence number
133
 *  2 bytes of total data length
134
 *  2 bytes of offset
135
 *  2 bytes of data length
136
 *  2 bytes of receive sequence number
137
 *  2 bytes of "bytes received"
138
 *
139
 * followed by data.
140
 *
141
 * Packets with a data stream type of NBIPX_DIRECTED_DATAGRAM appear to
142
 * have, following the data stream type, two NetBIOS names, the first
143
 * of which is the receiver's NetBIOS name and the second of which is
144
 * the sender's NetBIOS name.  The page at
145
 *
146
 *  http://support.microsoft.com/support/kb/articles/q203/0/51.asp
147
 *
148
 * speaks of type 4 (PEP) packets as being used for "SAP, NetBIOS sessions
149
 * and directed datagrams" and type 20 (WAN Broadcast) as being used for
150
 * "NetBIOS name resolution broadcasts" (but nothing about the non-broadcast
151
 * type 4 name resolution stuff).
152
 *
153
 * We assume that this means that, once you get past the 8 IPX network
154
 * numbers if present:
155
 *
156
 *  the first byte is a name type byte for the name packets
157
 *  and a connection control flag for the other packets;
158
 *
159
 *  the second byte is a data stream type;
160
 *
161
 *  the rest of the bytes are:
162
 *
163
 *    the NetBIOS name being registered/deregistered/etc.,
164
 *    for name packets;
165
 *
166
 *    the two NetBIOS names, followed by the NetBIOS
167
 *    datagram, for NBIPX_DIRECTED_DATAGRAM packets;
168
 *
169
 *    the session packet header, possibly followed by
170
 *    session data, for session packets.
171
 *
172
 * We don't know yet how to interpret NBIPX_STATUS_QUERY or
173
 * NBIPX_STATUS_RESPONSE.
174
 *
175
 * For now, we treat the datagrams and session data as SMB stuff.
176
 */
177
0
#define NBIPX_FIND_NAME   1
178
0
#define NBIPX_NAME_RECOGNIZED 2
179
0
#define NBIPX_CHECK_NAME  3
180
0
#define NBIPX_NAME_IN_USE 4
181
5
#define NBIPX_DEREGISTER_NAME 5
182
0
#define NBIPX_SESSION_DATA  6
183
0
#define NBIPX_SESSION_END 7
184
0
#define NBIPX_SESSION_END_ACK 8
185
#define NBIPX_STATUS_QUERY  9
186
#define NBIPX_STATUS_RESPONSE 10
187
0
#define NBIPX_DIRECTED_DATAGRAM 11
188
189
static const value_string nbipx_data_stream_type_vals[] = {
190
  {NBIPX_FIND_NAME,   "Find name"},
191
  {NBIPX_NAME_RECOGNIZED,   "Name recognized"},
192
  {NBIPX_CHECK_NAME,    "Check name"},
193
  {NBIPX_NAME_IN_USE,   "Name in use"},
194
  {NBIPX_DEREGISTER_NAME,   "Deregister name"},
195
  {NBIPX_SESSION_DATA,    "Session data"},
196
  {NBIPX_SESSION_END,   "Session end"},
197
  {NBIPX_SESSION_END_ACK,   "Session end ACK"},
198
  {NBIPX_STATUS_QUERY,    "Status query"},
199
  {NBIPX_STATUS_RESPONSE,   "Status response"},
200
  {NBIPX_DIRECTED_DATAGRAM, "Directed datagram"},
201
  {0,       NULL}
202
};
203
204
/*
205
 * Opcodes.
206
 */
207
0
#define INAME_CLAIM 0xf1
208
1
#define INAME_DELETE  0xf2
209
1
#define INAME_QUERY 0xf3
210
1
#define INAME_FOUND 0xf4
211
2
#define IMSG_HANGUP 0xf5
212
105
#define IMSLOT_SEND 0xfc
213
1
#define IMSLOT_FIND 0xfd
214
6
#define IMSLOT_NAME 0xfe
215
216
static const value_string nmpi_opcode_vals[] = {
217
  {INAME_CLAIM, "Claim name"},
218
  {INAME_DELETE,  "Delete name"},
219
  {INAME_QUERY, "Query name"},
220
  {INAME_FOUND, "Name found"},
221
  {IMSG_HANGUP, "Messenger hangup"},
222
  {IMSLOT_SEND, "Mailslot write"},
223
  {IMSLOT_FIND, "Find mailslot name"},
224
  {IMSLOT_NAME, "Mailslot name found"},
225
  {0,   NULL}
226
};
227
228
/*
229
 * Name types.
230
 */
231
#define INTYPE_MACHINE    1
232
#define INTYPE_WORKGROUP  2
233
#define INTYPE_BROWSER    3
234
235
static const value_string nmpi_name_type_vals[] = {
236
  {INTYPE_MACHINE,  "Machine"},
237
  {INTYPE_WORKGROUP,  "Workgroup"},
238
  {INTYPE_BROWSER,  "Browser"},
239
  {0,     NULL}
240
};
241
242
static const true_false_string tfs_system_non_system = { "System packet", "Non-system packet" };
243
244
static void
245
add_routers(proto_tree *tree, tvbuff_t *tvb, unsigned offset)
246
108
{
247
108
  int   i;
248
249
  /* Eight routers are listed */
250
941
  for (i = 0; i < 8; i++) {
251
833
    if (tvb_get_ntohl(tvb, offset) != 0) {
252
705
      proto_tree_add_item(tree, hf_nbipx_ipx_network, tvb, offset, 4, ENC_NA);
253
705
    }
254
833
    offset += 4;
255
833
  }
256
108
}
257
258
static void
259
dissect_netbios_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
260
3
{
261
3
  heur_dtbl_entry_t *hdtbl_entry;
262
263
  /*
264
   * Try the heuristic dissectors for NetBIOS; if none of them
265
   * accept the packet, dissect it as data.
266
   */
267
3
  if (!dissector_try_heuristic(netbios_heur_subdissector_list,
268
3
            tvb, pinfo, tree, &hdtbl_entry, NULL))
269
3
    call_data_dissector(tvb, pinfo, tree);
270
3
}
271
272
static int
273
dissect_nbipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
274
9
{
275
9
  bool  has_routes;
276
9
  proto_tree  *nbipx_tree = NULL;
277
9
  proto_item  *ti = NULL;
278
9
  unsigned  offset = 0;
279
9
  uint8_t   packet_type;
280
9
  proto_tree  *name_type_flag_tree;
281
9
  proto_item  *tf;
282
9
  char    name[(NETBIOS_NAME_LEN - 1)*4 + 1];
283
9
  int   name_type;
284
9
  bool  has_payload;
285
9
  tvbuff_t  *next_tvb;
286
9
  ipxhdr_t *ipxh;
287
288
  /* Reject the packet if data is NULL */
289
9
  if (data == NULL)
290
0
    return 0;
291
9
  ipxh = (ipxhdr_t*)data;
292
293
9
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "NBIPX");
294
9
  col_clear(pinfo->cinfo, COL_INFO);
295
296
9
  if (ipxh->ipx_type == IPX_PACKET_TYPE_WANBCAST) {
297
    /*
298
     * This is a WAN Broadcast packet; we assume it will have
299
     * 8 IPX addresses at the beginning.
300
     */
301
0
    has_routes = true;
302
9
  } else {
303
    /*
304
     * This isn't a WAN Broadcast packet, but it still might
305
     * have the 8 addresses.
306
     *
307
     * If it's the right length for a name operation,
308
     * and, if we assume it has routes, the packet type
309
     * is a name operation, assume it has routes.
310
     *
311
     * NOTE: this will throw an exception if the byte that
312
     * would be the packet type byte if this has the 8
313
     * addresses isn't present; if that's the case, we don't
314
     * know how to interpret this packet, so we can't dissect
315
     * it anyway.
316
     */
317
9
    has_routes = false;  /* start out assuming it doesn't */
318
9
    if (tvb_reported_length(tvb) == 50) {
319
3
      packet_type = tvb_get_uint8(tvb, offset + 32 + 1);
320
3
      switch (packet_type) {
321
322
0
      case NBIPX_FIND_NAME:
323
0
      case NBIPX_NAME_RECOGNIZED:
324
0
      case NBIPX_CHECK_NAME:
325
0
      case NBIPX_NAME_IN_USE:
326
0
      case NBIPX_DEREGISTER_NAME:
327
0
        has_routes = true;
328
0
        break;
329
3
      }
330
3
    }
331
9
  }
332
333
9
  if (tree) {
334
9
    ti = proto_tree_add_item(tree, proto_nbipx, tvb, 0,
335
9
        -1, ENC_NA);
336
9
    nbipx_tree = proto_item_add_subtree(ti, ett_nbipx);
337
9
  }
338
339
9
  if (has_routes) {
340
0
    if (tree)
341
0
      add_routers(nbipx_tree, tvb, 0);
342
0
    offset += 32;
343
0
  }
344
345
9
  packet_type = tvb_get_uint8(tvb, offset + 1);
346
347
9
  switch (packet_type) {
348
349
0
  case NBIPX_FIND_NAME:
350
0
  case NBIPX_NAME_RECOGNIZED:
351
0
  case NBIPX_CHECK_NAME:
352
0
  case NBIPX_NAME_IN_USE:
353
5
  case NBIPX_DEREGISTER_NAME:
354
5
    name_type = get_netbios_name(tvb, offset+2, name, (NETBIOS_NAME_LEN - 1)*4 + 1);
355
5
    col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s<%02x>",
356
5
        val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown"),
357
5
        name, name_type);
358
359
5
    if (nbipx_tree) {
360
5
      tf = proto_tree_add_item(nbipx_tree, hf_nbipx_name_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
361
5
      name_type_flag_tree = proto_item_add_subtree(tf, ett_nbipx_name_type_flags);
362
363
5
      proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_group, tvb, offset, 1, ENC_LITTLE_ENDIAN);
364
5
      proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_in_use, tvb, offset, 1, ENC_LITTLE_ENDIAN);
365
5
      proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_registered, tvb, offset, 1, ENC_LITTLE_ENDIAN);
366
5
      proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_duplicated, tvb, offset, 1, ENC_LITTLE_ENDIAN);
367
5
      proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_deregistered, tvb, offset, 1, ENC_LITTLE_ENDIAN);
368
5
    }
369
5
    offset += 1;
370
371
5
    proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type);
372
5
    offset += 1;
373
374
5
    if (nbipx_tree)
375
5
      netbios_add_name("Name", tvb, offset, nbipx_tree);
376
5
    offset += NETBIOS_NAME_LEN;
377
378
    /*
379
     * No payload to be interpreted by another protocol.
380
     */
381
5
    has_payload = false;
382
5
    break;
383
384
0
  case NBIPX_SESSION_DATA:
385
0
  case NBIPX_SESSION_END:
386
0
  case NBIPX_SESSION_END_ACK:
387
0
    col_set_str(pinfo->cinfo, COL_INFO,
388
0
        val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown"));
389
390
0
    dissect_conn_control(tvb, offset, nbipx_tree);
391
0
    offset += 1;
392
393
0
    proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type);
394
0
    offset += 1;
395
396
0
    proto_tree_add_item(nbipx_tree, hf_nbipx_session_src_conn_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
397
0
    offset += 2;
398
399
0
    proto_tree_add_item(nbipx_tree, hf_nbipx_session_dest_conn_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
400
0
    offset += 2;
401
402
0
    proto_tree_add_item(nbipx_tree, hf_nbipx_session_send_seq_number, tvb, offset, 2, ENC_LITTLE_ENDIAN);
403
0
    offset += 2;
404
405
0
    proto_tree_add_item(nbipx_tree, hf_nbipx_session_total_data_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
406
0
    offset += 2;
407
408
0
    proto_tree_add_item(nbipx_tree, hf_nbipx_session_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
409
0
    offset += 2;
410
411
0
    proto_tree_add_item(nbipx_tree, hf_nbipx_session_data_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
412
0
    offset += 2;
413
414
0
    proto_tree_add_item(nbipx_tree, hf_nbipx_session_recv_seq_number, tvb, offset, 2, ENC_LITTLE_ENDIAN);
415
0
    offset += 2;
416
417
0
    proto_tree_add_item(nbipx_tree, hf_nbipx_session_bytes_received, tvb, offset, 2, ENC_LITTLE_ENDIAN);
418
0
    offset += 2;
419
420
    /*
421
     * We may have payload to dissect.
422
     */
423
0
    has_payload = true;
424
0
    break;
425
426
0
  case NBIPX_DIRECTED_DATAGRAM:
427
0
    col_set_str(pinfo->cinfo, COL_INFO,
428
0
        val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown"));
429
430
0
    dissect_conn_control(tvb, offset, nbipx_tree);
431
0
    offset += 1;
432
433
0
    proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type);
434
0
    offset += 1;
435
436
0
    if (nbipx_tree)
437
0
      netbios_add_name("Receiver's Name", tvb, offset,
438
0
          nbipx_tree);
439
0
    offset += NETBIOS_NAME_LEN;
440
441
0
    if (nbipx_tree)
442
0
      netbios_add_name("Sender's Name", tvb, offset,
443
0
          nbipx_tree);
444
0
    offset += NETBIOS_NAME_LEN;
445
446
    /*
447
     * We may have payload to dissect.
448
     */
449
0
    has_payload = true;
450
0
    break;
451
452
4
  default:
453
4
    col_set_str(pinfo->cinfo, COL_INFO,
454
4
        val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown"));
455
456
    /*
457
     * We don't know what the first byte is.
458
     */
459
4
    offset += 1;
460
461
    /*
462
     * The second byte is a data stream type byte.
463
     */
464
4
    proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type);
465
4
    offset += 1;
466
467
    /*
468
     * We don't know what the rest of the packet is.
469
     */
470
4
    has_payload = false;
471
9
  }
472
473
  /*
474
   * Set the length of the NBIPX tree item.
475
   */
476
9
  if (ti != NULL)
477
9
    proto_item_set_len(ti, offset);
478
479
9
  if (has_payload && tvb_offset_exists(tvb, offset)) {
480
0
    next_tvb = tvb_new_subset_remaining(tvb, offset);
481
0
    dissect_netbios_payload(next_tvb, pinfo, tree);
482
0
  }
483
484
9
  return tvb_captured_length(tvb);
485
9
}
486
487
static void
488
dissect_conn_control(tvbuff_t *tvb, unsigned offset, proto_tree *tree)
489
0
{
490
0
  proto_item  *ti;
491
0
  proto_tree  *cc_tree;
492
493
0
  if (tree) {
494
0
    ti = proto_tree_add_item(tree, hf_nbipx_conn_control, tvb, offset, 1, ENC_LITTLE_ENDIAN);
495
0
    cc_tree = proto_item_add_subtree(ti, ett_nbipx_conn_ctrl);
496
0
    proto_tree_add_item(cc_tree, hf_nbipx_conn_control_sys_packet, tvb, offset, 1, ENC_LITTLE_ENDIAN);
497
0
    proto_tree_add_item(cc_tree, hf_nbipx_conn_control_ack, tvb, offset, 1, ENC_LITTLE_ENDIAN);
498
0
    proto_tree_add_item(cc_tree, hf_nbipx_conn_control_attention, tvb, offset, 1, ENC_LITTLE_ENDIAN);
499
0
    proto_tree_add_item(cc_tree, hf_nbipx_conn_control_end_msg, tvb, offset, 1, ENC_LITTLE_ENDIAN);
500
0
    proto_tree_add_item(cc_tree, hf_nbipx_conn_control_resend, tvb, offset, 1, ENC_LITTLE_ENDIAN);
501
0
  }
502
0
}
503
504
void
505
proto_register_nbipx(void)
506
15
{
507
15
  static hf_register_info hf[] = {
508
15
    { &hf_nbipx_packettype,
509
15
      { "Packet Type",   "nmpi.packettype",
510
15
      FT_UINT8, BASE_HEX, VALS(nbipx_data_stream_type_vals), 0,
511
15
      NULL, HFILL }
512
15
    },
513
15
    { &hf_nbipx_name_flags,
514
15
      { "Name type flag",   "nmpi.name_flags",
515
15
      FT_UINT8, BASE_HEX, NULL, 0,
516
15
      NULL, HFILL }
517
15
    },
518
15
    { &hf_nbipx_name_flags_group,
519
15
      { "Name",   "nmpi.name_flags.group",
520
15
      FT_BOOLEAN, 8, TFS(&tfs_group_unique_name), 0x80,
521
15
      NULL, HFILL }
522
15
    },
523
15
    { &hf_nbipx_name_flags_in_use,
524
15
      { "In use",   "nmpi.name_flags.in_use",
525
15
      FT_BOOLEAN, 8, TFS(&tfs_used_notused), 0x40,
526
15
      NULL, HFILL }
527
15
    },
528
15
    { &hf_nbipx_name_flags_registered,
529
15
      { "Registered",   "nmpi.name_flags.registered",
530
15
      FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
531
15
      NULL, HFILL }
532
15
    },
533
15
    { &hf_nbipx_name_flags_duplicated,
534
15
      { "Duplicated",   "nmpi.name_flags.duplicated",
535
15
      FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
536
15
      NULL, HFILL }
537
15
    },
538
15
    { &hf_nbipx_name_flags_deregistered,
539
15
      { "Deregistered",   "nmpi.name_flags.deregistered",
540
15
      FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
541
15
      NULL, HFILL }
542
15
    },
543
15
    { &hf_nbipx_conn_control,
544
15
      { "Connection control",   "nmpi.conn_control",
545
15
      FT_UINT8, BASE_HEX, NULL, 0,
546
15
      NULL, HFILL }
547
15
    },
548
15
    { &hf_nbipx_conn_control_sys_packet,
549
15
      { "Packet",   "nmpi.conn_control.sys_packet",
550
15
      FT_BOOLEAN, 8, TFS(&tfs_system_non_system), 0x80,
551
15
      NULL, HFILL }
552
15
    },
553
15
    { &hf_nbipx_conn_control_ack,
554
15
      { "Acknowledgement",   "nmpi.conn_control.ack",
555
15
      FT_BOOLEAN, 8, TFS(&tfs_required_not_required), 0x40,
556
15
      NULL, HFILL }
557
15
    },
558
15
    { &hf_nbipx_conn_control_attention,
559
15
      { "Attention",   "nmpi.conn_control.attention",
560
15
      FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x20,
561
15
      NULL, HFILL }
562
15
    },
563
15
    { &hf_nbipx_conn_control_end_msg,
564
15
      { "End of message",   "nmpi.conn_control.end_msg",
565
15
      FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x10,
566
15
      NULL, HFILL }
567
15
    },
568
15
    { &hf_nbipx_conn_control_resend,
569
15
      { "Resend",   "nmpi.conn_control.resend",
570
15
      FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
571
15
      NULL, HFILL }
572
15
    },
573
15
    { &hf_nbipx_session_src_conn_id,
574
15
      { "Source connection ID",   "nmpi.session.src_conn_id",
575
15
      FT_UINT16, BASE_HEX, NULL, 0,
576
15
      NULL, HFILL }
577
15
    },
578
15
    { &hf_nbipx_session_dest_conn_id,
579
15
      { "Destination connection ID",   "nmpi.session.dest_conn_id",
580
15
      FT_UINT16, BASE_HEX, NULL, 0,
581
15
      NULL, HFILL }
582
15
    },
583
15
    { &hf_nbipx_session_send_seq_number,
584
15
      { "Send sequence number",   "nmpi.session.send_seq_number",
585
15
      FT_UINT16, BASE_DEC, NULL, 0,
586
15
      NULL, HFILL }
587
15
    },
588
15
    { &hf_nbipx_session_total_data_length,
589
15
      { "Total data length",   "nmpi.session.total_data_length",
590
15
      FT_UINT16, BASE_DEC, NULL, 0,
591
15
      NULL, HFILL }
592
15
    },
593
15
    { &hf_nbipx_session_offset,
594
15
      { "Offset",   "nmpi.session.offset",
595
15
      FT_UINT16, BASE_DEC, NULL, 0,
596
15
      NULL, HFILL }
597
15
    },
598
15
    { &hf_nbipx_session_data_length,
599
15
      { "Data length",   "nmpi.session.data_length",
600
15
      FT_UINT16, BASE_DEC, NULL, 0,
601
15
      NULL, HFILL }
602
15
    },
603
15
    { &hf_nbipx_session_recv_seq_number,
604
15
      { "Receive sequence number",   "nmpi.session.recv_seq_number",
605
15
      FT_UINT16, BASE_DEC, NULL, 0,
606
15
      NULL, HFILL }
607
15
    },
608
15
    { &hf_nbipx_session_bytes_received,
609
15
      { "Bytes received",   "nmpi.session.bytes_received",
610
15
      FT_UINT16, BASE_DEC, NULL, 0,
611
15
      NULL, HFILL }
612
15
    },
613
15
    { &hf_nbipx_ipx_network,
614
15
      { "IPX Network",   "nmpi.ipx_network",
615
15
      FT_IPXNET, BASE_NONE, NULL, 0,
616
15
      NULL, HFILL }
617
15
    },
618
15
    { &hf_nbipx_opcode,
619
15
      { "Opcode",   "nmpi.opcode",
620
15
      FT_UINT8, BASE_HEX, VALS(nmpi_opcode_vals), 0,
621
15
      NULL, HFILL }
622
15
    },
623
15
    { &hf_nbipx_name_type,
624
15
      { "Name Type",   "nmpi.name_type",
625
15
      FT_UINT8, BASE_HEX, VALS(nmpi_name_type_vals), 0,
626
15
      NULL, HFILL }
627
15
    },
628
15
    { &hf_nbipx_messageid,
629
15
      { "Message ID",   "nmpi.messageid",
630
15
      FT_UINT16, BASE_HEX, NULL, 0,
631
15
      NULL, HFILL }
632
15
    },
633
15
  };
634
635
15
  static int *ett[] = {
636
15
    &ett_nbipx,
637
15
    &ett_nbipx_conn_ctrl,
638
15
    &ett_nbipx_name_type_flags,
639
15
  };
640
641
15
  proto_nbipx = proto_register_protocol("NetBIOS over IPX", "NBIPX", "nbipx");
642
15
  proto_register_field_array(proto_nbipx, hf, array_length(hf));
643
15
  proto_register_subtree_array(ett, array_length(ett));
644
645
15
  nbipx_handle = register_dissector("nbipx", dissect_nbipx, proto_nbipx);
646
15
}
647
648
void
649
proto_reg_handoff_nbipx(void)
650
15
{
651
15
  dissector_add_uint("ipx.socket", IPX_SOCKET_NETBIOS, nbipx_handle);
652
15
  netbios_heur_subdissector_list = find_heur_dissector_list("netbios");
653
15
}
654
655
/*
656
 * Microsoft appear to have something they call "direct hosting", where
657
 * SMB - and, I infer, related stuff, such as name resolution - runs
658
 * directly over IPX.  (In Windows 2000, they also run SMB directly over
659
 * TCP, on port 445, and that also appears to be called "direct hosting".
660
 * Wireshark handles SMB-over-TCP.)
661
 *
662
 * The document at
663
 *
664
 *  http://support.microsoft.com/support/kb/articles/q203/0/51.asp
665
 *
666
 * speaks of NMPI - the "Name Management Protocol on IPX" - as being
667
 * "Microsoft's protocol for name management support when you use IPX
668
 * without the NetBIOS interface," and says that "This process of routing
669
 * the SMB protocol directly through IPX is known as Direct Hosting."
670
 *
671
 * It speaks of IPX socket 0x551 as being for NMPI; we define it as
672
 * IPX_SOCKET_NWLINK_SMB_NAMEQUERY.
673
 *
674
 * We also define IPX_SOCKET_NWLINK_SMB_DGRAM as 0x0553 and define
675
 * IPX_SOCKET_NWLINK_SMB_BROWSE as 0x0555 (with a "? not sure on this"
676
 * comment after the latter one).
677
 *
678
 * We have seen at least some browser announcements on IPX socket 0x553;
679
 * those are WAN broadcast packets, complete with 8 IPX network
680
 * numbers, and with the header containing the usual two NetBIOS names
681
 * that show up in NetBIOS datagrams.
682
 *
683
 * Network Monitor calls those packets NMPI packets, even though they're
684
 * on socket 0x553, not socket 0x551, and contain SMB datagrams, not name
685
 * resolution packets.
686
 *
687
 * At least some of this is discussed in the "SMBPUB.DOC" Word document
688
 * stored in
689
 *
690
 *  ftp://ftp.microsoft.com/developr/drg/CIFS/smbpub.zip
691
 *
692
 * which can also be found in text form at
693
 *
694
 *  http://www.samba.org/samba/ftp/specs/smbpub.txt
695
 *
696
 * which says that for "connectionless IPX transport" the sockets that
697
 * are used are:
698
 *
699
 *  SMB_SERVER_SOCKET (0x550) - SMB requests from clients
700
 *  SMB_NAME_SOCKET (0x551) - name claims and name query messages
701
 *  REDIR_SOCKET (0x552) - used by the redirector (client) for
702
 *    sending SMB requests and receiving SMB replies
703
 *  MAILSLOT_SOCKET (0x553) - used by the redirector and browser
704
 *    for mailslot datagrams
705
 *  MESSENGER_SOCKET (0x554) - used by the redirector to send
706
 *    messages from client to client
707
 *
708
 * Name claim/query packets, and mailslot datagrams, are:
709
 *
710
 *  8 IPX network addresses
711
 *  1 byte of opcode
712
 *  1 byte of name type
713
 *  2 bytes of message ID
714
 *  16 bytes of name being sought or claimed
715
 *  16 bytes of requesting machine
716
 *
717
 * The opcode is one of:
718
 *
719
 *  INAME_CLAIM (0xf1) - server name claim message
720
 *  INAME_DELETE (0xf2) - relinquish server name
721
 *  INAME_QUERY (0xf3) - locate server name
722
 *  INAME_FOUND (0xf4) - response to INAME_QUERY
723
 *  IMSG_HANGUP (0xf5) - messenger hangup
724
 *  IMSLOT_SEND (0xfc) - mailslot write
725
 *  IMSLOT_FIND (0xfd) - find name for mailslot write
726
 *  IMSLOT_NAME (0xfe) - response to IMSLOT_FIND
727
 *
728
 * The name type is one of:
729
 *
730
 *  INTYPE_MACHINE  1
731
 *  INTYPE_WKGROUP  2
732
 *  INTYPE_BROWSER  3
733
 */
734
static int proto_nmpi;
735
736
static int ett_nmpi;
737
static int ett_nmpi_name_type_flags;
738
739
740
static int
741
dissect_nmpi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
742
108
{
743
108
  proto_tree  *nmpi_tree = NULL;
744
108
  proto_item  *ti;
745
108
  int   offset = 0;
746
108
  uint8_t   opcode;
747
108
  char    name[(NETBIOS_NAME_LEN - 1)*4 + 1];
748
108
  int   name_type;
749
108
  char    node_name[(NETBIOS_NAME_LEN - 1)*4 + 1];
750
  /*int   node_name_type = 0;*/
751
108
  tvbuff_t  *next_tvb;
752
753
108
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "NMPI");
754
108
  col_clear(pinfo->cinfo, COL_INFO);
755
756
108
  if (tree) {
757
108
    ti = proto_tree_add_item(tree, proto_nmpi, tvb, offset, 68,
758
108
        ENC_NA);
759
108
    nmpi_tree = proto_item_add_subtree(ti, ett_nmpi);
760
761
108
    add_routers(nmpi_tree, tvb, offset);
762
108
  }
763
108
  offset += 32;
764
765
  /*
766
   * XXX - we don't use "node_name" or "node_name_type".
767
   */
768
108
  opcode = tvb_get_uint8(tvb, offset);
769
108
  name_type = get_netbios_name(tvb, offset+4, name, (NETBIOS_NAME_LEN - 1)*4 + 1);
770
108
  /*node_name_type = */get_netbios_name(tvb, offset+20, node_name, (NETBIOS_NAME_LEN - 1)*4 + 1);
771
772
108
  switch (opcode) {
773
774
0
  case INAME_CLAIM:
775
0
    col_add_fstr(pinfo->cinfo, COL_INFO, "Claim name %s<%02x>",
776
0
          name, name_type);
777
0
    break;
778
779
1
  case INAME_DELETE:
780
1
    col_add_fstr(pinfo->cinfo, COL_INFO, "Delete name %s<%02x>",
781
1
          name, name_type);
782
1
    break;
783
784
1
  case INAME_QUERY:
785
1
    col_add_fstr(pinfo->cinfo, COL_INFO, "Query name %s<%02x>",
786
1
          name, name_type);
787
1
    break;
788
789
1
  case INAME_FOUND:
790
1
    col_add_fstr(pinfo->cinfo, COL_INFO, "Name %s<%02x> found",
791
1
          name, name_type);
792
1
    break;
793
794
2
  case IMSG_HANGUP:
795
2
    col_add_fstr(pinfo->cinfo, COL_INFO,
796
2
          "Messenger hangup on %s<%02x>", name, name_type);
797
2
    break;
798
799
3
  case IMSLOT_SEND:
800
3
    col_add_fstr(pinfo->cinfo, COL_INFO,
801
3
          "Mailslot write to %s<%02x>", name, name_type);
802
3
    break;
803
804
1
  case IMSLOT_FIND:
805
1
    col_add_fstr(pinfo->cinfo, COL_INFO,
806
1
          "Find mailslot name %s<%02x>", name, name_type);
807
1
    break;
808
809
6
  case IMSLOT_NAME:
810
6
    col_add_fstr(pinfo->cinfo, COL_INFO,
811
6
          "Mailslot name %s<%02x> found", name, name_type);
812
6
    break;
813
814
36
  default:
815
36
    col_add_fstr(pinfo->cinfo, COL_INFO,
816
36
          "Unknown NMPI op 0x%02x: name %s<%02x>",
817
36
          opcode, name, name_type);
818
36
    break;
819
108
  }
820
821
51
  if (tree) {
822
51
    proto_tree_add_item(nmpi_tree, hf_nbipx_opcode, tvb, offset, 1, ENC_LITTLE_ENDIAN);
823
51
    proto_tree_add_item(nmpi_tree, hf_nbipx_name_type, tvb, offset+1, 1, ENC_LITTLE_ENDIAN);
824
51
    proto_tree_add_item(nmpi_tree, hf_nbipx_messageid, tvb, offset+2, 2, ENC_LITTLE_ENDIAN);
825
51
    netbios_add_name("Requested name", tvb, offset+4, nmpi_tree);
826
51
    netbios_add_name("Source name", tvb, offset+20, nmpi_tree);
827
51
  }
828
829
51
  offset += 1 + 1 + 2 + NETBIOS_NAME_LEN + NETBIOS_NAME_LEN;
830
831
51
  if (opcode == IMSLOT_SEND && tvb_offset_exists(tvb, offset)) {
832
3
    next_tvb = tvb_new_subset_remaining(tvb, offset);
833
3
    dissect_netbios_payload(next_tvb, pinfo, tree);
834
3
  }
835
51
  return tvb_captured_length(tvb);
836
108
}
837
838
void
839
proto_register_nmpi(void)
840
15
{
841
/*
842
  static hf_register_info hf[] = {
843
    { &variable,
844
    { "Name",           "nmpi.abbreviation", TYPE, VALS_POINTER }},
845
  }; */
846
15
  static int *ett[] = {
847
15
    &ett_nmpi,
848
15
    &ett_nmpi_name_type_flags,
849
15
  };
850
851
15
  proto_nmpi = proto_register_protocol("Name Management Protocol over IPX",
852
15
      "NMPI", "nmpi");
853
  /*       proto_register_field_array(proto_nmpi, hf, array_length(hf));*/
854
15
  proto_register_subtree_array(ett, array_length(ett));
855
856
15
  nmpi_handle = register_dissector("nmpi", dissect_nmpi, proto_nmpi);
857
15
}
858
859
void
860
proto_reg_handoff_nmpi(void)
861
15
{
862
15
  dissector_add_uint("ipx.socket", IPX_SOCKET_NWLINK_SMB_NAMEQUERY,
863
15
      nmpi_handle);
864
15
  dissector_add_uint("ipx.socket", IPX_SOCKET_NWLINK_SMB_MAILSLOT,
865
15
      nmpi_handle);
866
15
}
867
868
/*
869
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
870
 *
871
 * Local variables:
872
 * c-basic-offset: 8
873
 * tab-width: 8
874
 * indent-tabs-mode: t
875
 * End:
876
 *
877
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
878
 * :indentSize=8:tabSize=8:noTabs=false:
879
 */