Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-nwp.c
blobd21070bbc574b41ce6bdacb4786aa60e027345e6
1 /* packet-nwp.c
2 * Routines for NWP dissection
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
10 * Neighborhood Watch Protocol (NWP) is an XIA protocol for resolving network
11 * addresses to link-layer addresses. Hosts on a LAN send NWP Announcement
12 * packets with their host identifiers (HIDs), and neighbors in the LAN
13 * respond with NWP Neighbor List packets containing their HIDs and associated
14 * link-layer addresses.
17 #include "config.h"
18 #include <epan/packet.h>
19 #include <epan/expert.h>
21 void proto_register_nwp(void);
22 void proto_reg_handoff_nwp(void);
24 static int proto_nwp;
26 /* Header fields for all NWP headers. */
27 static int hf_nwp_version;
28 static int hf_nwp_type;
29 static int hf_nwp_hid_count;
30 static int hf_nwp_haddr_len;
32 /* Header fields for NWP Announcement packets. */
33 static int hf_nwp_ann_haddr;
34 static int hf_nwp_ann_hids;
35 static int hf_nwp_ann_hid;
37 /* Header fields for NWP Neighbor List packets. */
38 static int hf_nwp_neigh_list;
39 static int hf_nwp_neigh;
40 static int hf_nwp_neigh_hid;
41 static int hf_nwp_neigh_num;
42 static int hf_nwp_neigh_haddr;
44 static int ett_nwp_tree;
45 static int ett_nwp_ann_hid_tree;
46 static int ett_nwp_neigh_list_tree;
47 static int ett_nwp_neigh_tree;
49 static expert_field ei_nwp_bad_type;
51 static dissector_handle_t nwp_handle;
53 #define NWP_XID_CHUNK_LEN 4
54 #define NWP_XID_LEN 20
55 /* Two characters for every byte + 4 for "hid-" + 1 for "\0" */
56 #define NWP_HID_STR_LEN ((NWP_XID_LEN * 2) + 5)
58 /* Room for a string of hardware addresses of the form:
60 * XX:...:XX; XX:...:XX; ...
62 * (2 * LEN) bytes for each hardware address, plus (LEN - 1) bytes for colons,
63 * plus 2 bytes for "; ". Multiply that by the COUNT of hardware addresses
64 * that are present.
66 #define NWP_HADDRS_STR_LEN(LEN, COUNT) (((2 * LEN) + (LEN - 1) + 2) * COUNT)
68 #define NWPH_MIN_LEN 4
69 #define ETHERTYPE_NWP 0xC0DF
70 #define NWP_VERSION 0x01
72 #define NWP_TYPE_ANNOUNCEMENT 0x01
73 #define NWP_TYPE_NEIGH_LIST 0x02
75 /* Offsets of fields in NWP Announcements/Neighbor Lists. */
76 #define NWPH_VERS 0
77 #define NWPH_TYPE 1
78 #define NWPH_HIDC 2
79 #define NWPH_HLEN 3
81 #define NWPH_NLST 4
82 #define NWPH_HWAD 4
84 static const value_string nwp_type_vals[] = {
85 { NWP_TYPE_ANNOUNCEMENT, "NWP Announcement" },
86 { NWP_TYPE_NEIGH_LIST, "NWP Neighbor List" },
87 { 0, NULL }
90 static void
91 add_hid_to_strbuf(tvbuff_t *tvb, wmem_strbuf_t *hid_buf, int offset)
93 int i;
94 for (i = 0; i < NWP_XID_LEN / NWP_XID_CHUNK_LEN; i++) {
95 wmem_strbuf_append_printf(hid_buf, "%08x",
96 tvb_get_ntohl(tvb, offset));
97 offset += NWP_XID_CHUNK_LEN;
101 static void
102 dissect_nwp_ann(tvbuff_t *tvb, proto_tree *nwp_tree, uint8_t hid_count,
103 uint8_t ha_len)
105 proto_tree *hid_tree = NULL;
106 proto_item *ti = NULL;
108 wmem_strbuf_t *buf;
109 unsigned i;
110 int offset;
112 /* Add hardware address. */
113 proto_tree_add_item(nwp_tree, hf_nwp_ann_haddr, tvb, NWPH_HWAD,
114 ha_len, ENC_NA);
116 /* Add tree for HIDs. */
117 ti = proto_tree_add_item(nwp_tree, hf_nwp_ann_hids, tvb,
118 NWPH_HWAD + ha_len, hid_count * NWP_XID_LEN, ENC_NA);
119 hid_tree = proto_item_add_subtree(ti, ett_nwp_ann_hid_tree);
121 buf = wmem_strbuf_new_sized(wmem_packet_scope(), NWP_HID_STR_LEN);
123 /* Add HIDs. */
124 offset = NWPH_HWAD + ha_len;
125 for (i = 0; i < hid_count; i++) {
126 const char *hid_str;
128 wmem_strbuf_append(buf, "hid-");
129 add_hid_to_strbuf(tvb, buf, offset);
130 hid_str = wmem_strbuf_get_str(buf);
132 proto_tree_add_string_format(hid_tree, hf_nwp_ann_hid, tvb,
133 offset, NWP_XID_LEN, hid_str, "%s", hid_str);
134 wmem_strbuf_truncate(buf, 0);
136 offset += NWP_XID_LEN;
140 /* Neighbor list is of the form:
141 * HID_1 NUM_1 HA_11 HA_12 ... HA_1NUM_1
142 * HID_2 NUM_2 HA_21 HA_22 ... HA_2NUM_2
143 * ...
144 * HID_count NUM_count HA_count1 HA_count2 ... HA_countNUM_count
146 * count == hid_count.
148 static void
149 dissect_nwp_nl(tvbuff_t *tvb, proto_tree *nwp_tree, uint8_t hid_count,
150 uint8_t ha_len)
152 proto_tree *neigh_list_tree = NULL;
153 proto_tree *neigh_tree = NULL;
154 proto_item *pi = NULL;
156 unsigned i;
157 int offset = NWPH_NLST;
159 wmem_strbuf_t *hid_buf = wmem_strbuf_new_sized(wmem_packet_scope(),
160 NWP_HID_STR_LEN);
162 /* Set up tree for neighbor list. */
163 pi = proto_tree_add_item(nwp_tree, hf_nwp_neigh_list,
164 tvb, NWPH_NLST, -1, ENC_NA);
165 neigh_list_tree = proto_item_add_subtree(pi, ett_nwp_neigh_list_tree);
167 for (i = 0; i < hid_count; i++) {
168 const char *hid_str;
169 unsigned j;
170 uint8_t ha_count = tvb_get_uint8(tvb, offset + NWP_XID_LEN);
172 /* Set up tree for this individual neighbor. */
173 pi = proto_tree_add_none_format(neigh_list_tree, hf_nwp_neigh,
174 tvb, offset, NWP_XID_LEN + 1 + ha_len * ha_count,
175 "Neighbor %d", i + 1);
176 neigh_tree = proto_item_add_subtree(pi, ett_nwp_neigh_tree);
178 /* Add HID for this neighbor. */
179 wmem_strbuf_append(hid_buf, "hid-");
180 add_hid_to_strbuf(tvb, hid_buf, offset);
181 hid_str = wmem_strbuf_get_str(hid_buf);
182 proto_tree_add_string(neigh_tree, hf_nwp_neigh_hid, tvb,
183 offset, NWP_XID_LEN, hid_str);
184 wmem_strbuf_truncate(hid_buf, 0);
185 offset += NWP_XID_LEN;
187 /* Add number of devices this neighbor has. */
188 proto_tree_add_item(neigh_tree, hf_nwp_neigh_num, tvb,
189 offset, 1, ENC_BIG_ENDIAN);
190 offset++;
192 /* Add hardware addresses for the neighbor's devices. */
193 for (j = 0; j < ha_count; j++)
194 proto_tree_add_item(neigh_tree, hf_nwp_neigh_haddr,
195 tvb, offset + (j * ha_len), ha_len, ENC_NA);
197 offset += (ha_len * ha_count);
201 static int
202 dissect_nwp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
203 void *data _U_)
205 proto_tree *nwp_tree = NULL;
207 proto_item *ti = NULL;
208 proto_item *type_ti = NULL;
210 const char *type_str;
211 uint8_t type, hid_count, ha_len;
213 if (tvb_reported_length(tvb) < NWPH_MIN_LEN)
214 return 0;
216 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NWP");
218 col_clear(pinfo->cinfo, COL_INFO);
219 type = tvb_get_uint8(tvb, NWPH_TYPE);
220 type_str = val_to_str(type, nwp_type_vals,
221 "Unknown NWP packet type (0x%02x)");
222 col_add_str(pinfo->cinfo, COL_INFO, type_str);
224 /* Construct protocol tree. */
225 ti = proto_tree_add_item(tree, proto_nwp, tvb, 0, -1, ENC_NA);
226 nwp_tree = proto_item_add_subtree(ti, ett_nwp_tree);
228 /* Add NWP version. */
229 proto_tree_add_item(nwp_tree, hf_nwp_version, tvb,
230 NWPH_VERS, 1, ENC_BIG_ENDIAN);
232 /* Add NWP type. */
233 type_ti = proto_tree_add_item(nwp_tree, hf_nwp_type, tvb,
234 NWPH_TYPE, 1, ENC_BIG_ENDIAN);
235 if (!try_val_to_str(type, nwp_type_vals))
236 expert_add_info_format(pinfo, type_ti, &ei_nwp_bad_type,
237 "%s", type_str);
239 /* Get # of HIDs represented in this packet to use later and add it. */
240 hid_count = tvb_get_uint8(tvb, NWPH_HIDC);
241 proto_tree_add_item(nwp_tree, hf_nwp_hid_count, tvb,
242 NWPH_HIDC, 1, ENC_BIG_ENDIAN);
244 /* Get hardware address length to use later and add it. */
245 ha_len = tvb_get_uint8(tvb, NWPH_HLEN);
246 proto_tree_add_item(nwp_tree, hf_nwp_haddr_len, tvb,
247 NWPH_HLEN, 1, ENC_BIG_ENDIAN);
249 switch (type) {
250 case NWP_TYPE_ANNOUNCEMENT:
251 dissect_nwp_ann(tvb, nwp_tree, hid_count, ha_len);
252 break;
253 case NWP_TYPE_NEIGH_LIST:
254 dissect_nwp_nl(tvb, nwp_tree, hid_count, ha_len);
255 break;
256 default:
257 break;
260 return tvb_captured_length(tvb);
263 void
264 proto_register_nwp(void)
266 static hf_register_info hf[] = {
268 { &hf_nwp_version,
269 { "Version", "nwp.version", FT_UINT8,
270 BASE_DEC, NULL, 0x0, NULL, HFILL }},
272 { &hf_nwp_type,
273 { "Type", "nwp.type", FT_UINT8,
274 BASE_HEX, VALS(nwp_type_vals), 0x0, NULL, HFILL }},
276 { &hf_nwp_hid_count,
277 { "HID Count", "nwp.hid_count", FT_UINT8,
278 BASE_DEC, NULL, 0x0, NULL, HFILL }},
280 { &hf_nwp_haddr_len,
281 { "Hardware Address Length", "nwp.haddr_len", FT_UINT8,
282 BASE_DEC, NULL, 0x0, NULL, HFILL }},
284 { &hf_nwp_ann_haddr,
285 { "Hardware Address", "nwp.ann_haddr", FT_BYTES,
286 SEP_COLON, NULL, 0x0, NULL, HFILL }},
288 { &hf_nwp_ann_hids,
289 { "HIDs", "nwp.ann_hids", FT_NONE,
290 BASE_NONE, NULL, 0x0, NULL, HFILL }},
292 { &hf_nwp_ann_hid,
293 { "HID", "nwp.ann_hid", FT_STRING,
294 BASE_NONE, NULL, 0x0, NULL, HFILL }},
296 { &hf_nwp_neigh_list,
297 { "Neighbor List", "nwp.neigh_list", FT_NONE,
298 BASE_NONE, NULL, 0x0, NULL, HFILL }},
300 { &hf_nwp_neigh,
301 { "Neighbor", "nwp.neigh", FT_NONE,
302 BASE_NONE, NULL, 0x0, NULL, HFILL }},
304 { &hf_nwp_neigh_hid,
305 { "HID", "nwp.neigh_hid", FT_STRING,
306 BASE_NONE, NULL, 0x0, NULL, HFILL }},
308 { &hf_nwp_neigh_num,
309 { "Number of Devices", "nwp.neigh_num", FT_UINT8,
310 BASE_DEC, NULL, 0x0, NULL, HFILL }},
312 { &hf_nwp_neigh_haddr,
313 { "Hardware Address", "nwp.neigh_haddr", FT_BYTES,
314 SEP_COLON, NULL, 0x0, NULL, HFILL }}
317 static int *ett[] = {
318 &ett_nwp_tree,
319 &ett_nwp_ann_hid_tree,
320 &ett_nwp_neigh_list_tree,
321 &ett_nwp_neigh_tree
324 static ei_register_info ei[] = {
325 { &ei_nwp_bad_type,
326 { "nwp.bad_type", PI_MALFORMED, PI_ERROR,
327 "Invalid type", EXPFILL }}
330 expert_module_t *expert_nwp;
332 proto_nwp = proto_register_protocol("Neighborhood Watch Protocol", "NWP", "nwp");
334 nwp_handle = register_dissector("nwp", dissect_nwp, proto_nwp);
335 proto_register_field_array(proto_nwp, hf, array_length(hf));
336 proto_register_subtree_array(ett, array_length(ett));
338 expert_nwp = expert_register_protocol(proto_nwp);
339 expert_register_field_array(expert_nwp, ei, array_length(ei));
342 void
343 proto_reg_handoff_nwp(void)
345 dissector_add_uint("ethertype", ETHERTYPE_NWP, nwp_handle);
349 * Editor modelines - https://www.wireshark.org/tools/modelines.html
351 * Local variables:
352 * c-basic-offset: 8
353 * tab-width: 8
354 * indent-tabs-mode: t
355 * End:
357 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
358 * :indentSize=8:tabSize=8:noTabs=false: