Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-nhrp.c
blob69337e19257858e06e41e02da0ed345c7607d470
1 /* packet-nhrp.c
2 * Routines for NBMA Next Hop Resolution Protocol
3 * RFC 2332 plus Cisco extensions:
4 * I-D draft-detienne-dmvpn-01: Flexible Dynamic Mesh VPN
5 * others? (documented where?)
6 * plus extensions from:
7 * RFC 2520: NHRP with Mobile NHCs
8 * RFC 2735: NHRP Support for Virtual Private Networks
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 Gerald Combs
14 * SPDX-License-Identifier: GPL-2.0-or-later
16 * CIE decoding for extensions and Cisco 12.4T extensions
17 * added by Timo Teras <timo.teras@iki.fi>
20 #include "config.h"
23 #include <epan/packet.h>
24 #include <epan/prefs.h>
25 #include <epan/addr_resolv.h>
26 #include <epan/expert.h>
27 #include <epan/etypes.h>
28 #include <epan/ipproto.h>
29 #include <epan/nlpid.h>
30 #include <epan/afn.h>
31 #include <epan/in_cksum.h>
32 #include "packet-iana-oui.h"
33 #include "packet-llc.h"
34 #include "packet-gre.h"
36 void proto_register_nhrp(void);
37 void proto_reg_handoff_nhrp(void);
39 static dissector_handle_t nhrp_handle;
41 /* forward reference */
42 static void _dissect_nhrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
43 bool nested, bool codeinfo);
45 static int proto_nhrp;
46 static int hf_nhrp_hdr_afn;
47 static int hf_nhrp_hdr_pro_type;
48 static int hf_nhrp_hdr_pro_snap_oui;
49 static int hf_nhrp_hdr_pro_snap_pid;
50 static int hf_nhrp_hdr_hopcnt;
51 static int hf_nhrp_hdr_pktsz;
52 static int hf_nhrp_hdr_chksum;
53 static int hf_nhrp_hdr_chksum_status;
54 static int hf_nhrp_hdr_extoff;
55 static int hf_nhrp_hdr_version;
56 static int hf_nhrp_hdr_op_type;
57 static int hf_nhrp_hdr_shtl;
58 static int hf_nhrp_hdr_shtl_type;
59 static int hf_nhrp_hdr_shtl_len;
60 static int hf_nhrp_hdr_sstl;
61 static int hf_nhrp_hdr_sstl_type;
62 static int hf_nhrp_hdr_sstl_len;
64 static int hf_nhrp_src_proto_len;
65 static int hf_nhrp_dst_proto_len;
66 static int hf_nhrp_flags;
67 static int hf_nhrp_flag_Q;
68 static int hf_nhrp_flag_N;
69 static int hf_nhrp_flag_A;
70 static int hf_nhrp_flag_D;
71 static int hf_nhrp_flag_U1;
72 static int hf_nhrp_flag_U2;
73 static int hf_nhrp_flag_S;
74 static int hf_nhrp_flag_NAT;
75 static int hf_nhrp_src_nbma_addr;
76 static int hf_nhrp_src_nbma_saddr;
77 static int hf_nhrp_src_prot_addr;
78 static int hf_nhrp_dst_prot_addr;
79 static int hf_nhrp_request_id;
81 static int hf_nhrp_code;
82 static int hf_nhrp_prefix_len;
83 static int hf_nhrp_unused;
84 static int hf_nhrp_mtu;
85 static int hf_nhrp_holding_time;
86 static int hf_nhrp_cli_addr_tl;
87 static int hf_nhrp_cli_addr_tl_type;
88 static int hf_nhrp_cli_addr_tl_len;
89 static int hf_nhrp_cli_saddr_tl;
90 static int hf_nhrp_cli_saddr_tl_type;
91 static int hf_nhrp_cli_saddr_tl_len;
92 static int hf_nhrp_cli_prot_len;
93 static int hf_nhrp_pref;
94 static int hf_nhrp_client_nbma_addr;
95 static int hf_nhrp_client_nbma_saddr;
96 static int hf_nhrp_client_prot_addr;
97 static int hf_nhrp_ext_C;
98 static int hf_nhrp_ext_type;
99 static int hf_nhrp_ext_len;
100 /* static int hf_nhrp_ext_value; */ /* TBD: Not used */
101 static int hf_nhrp_error_code;
102 static int hf_nhrp_error_offset;
103 static int hf_nhrp_traffic_code;
104 /* static int hf_nhrp_error_packet; */ /* TBD: Not used */
106 static int hf_nhrp_auth_ext_reserved;
107 static int hf_nhrp_auth_ext_spi;
108 static int hf_nhrp_auth_ext_src_addr;
109 static int hf_nhrp_vendor_ext_id;
110 static int hf_nhrp_devcap_ext_srccap;
111 static int hf_nhrp_devcap_ext_srccap_V;
112 static int hf_nhrp_devcap_ext_dstcap;
113 static int hf_nhrp_devcap_ext_dstcap_V;
114 static int hf_nhrp_unknown_ext_value;
116 /* Generated from convert_proto_tree_add_text.pl */
117 static int hf_nhrp_dst_prot_addr_bytes;
118 static int hf_nhrp_auth_ext_src_addr_bytes;
119 static int hf_nhrp_vendor_ext_data;
120 static int hf_nhrp_protocol_type;
121 static int hf_nhrp_src_nbma_addr_bytes;
122 static int hf_nhrp_client_nbma_address_bytes;
123 static int hf_nhrp_client_prot_addr_bytes;
124 static int hf_nhrp_auth_data;
125 static int hf_nhrp_src_prot_addr_bytes;
127 static int ett_nhrp;
128 static int ett_nhrp_hdr;
129 static int ett_nhrp_hdr_shtl;
130 static int ett_nhrp_hdr_sstl;
131 static int ett_nhrp_mand;
132 static int ett_nhrp_ext;
133 static int ett_nhrp_mand_flag;
134 static int ett_nhrp_cie;
135 static int ett_nhrp_cie_cli_addr_tl;
136 static int ett_nhrp_cie_cli_saddr_tl;
137 static int ett_nhrp_indication;
138 static int ett_nhrp_auth_ext;
139 static int ett_nhrp_vendor_ext;
140 static int ett_nhrp_devcap_ext;
141 static int ett_nhrp_devcap_ext_srccap;
142 static int ett_nhrp_devcap_ext_dstcap;
144 static expert_field ei_nhrp_hdr_pktsz;
145 static expert_field ei_nhrp_hdr_extoff;
146 static expert_field ei_nhrp_hdr_chksum;
147 static expert_field ei_nhrp_ext_not_allowed;
148 static expert_field ei_nhrp_ext_malformed;
149 static expert_field ei_nhrp_ext_extra;
151 static bool pref_auth_ext_has_addr = true;
153 /* NHRP Packet Types */
154 #define NHRP_RESOLUTION_REQ 1
155 #define NHRP_RESOLUTION_REPLY 2
156 #define NHRP_REGISTRATION_REQ 3
157 #define NHRP_REGISTRATION_REPLY 4
158 #define NHRP_PURGE_REQ 5
159 #define NHRP_PURGE_REPLY 6
160 #define NHRP_ERROR_INDICATION 7
161 #define NHRP_TRAFFIC_INDICATION 8
163 /* NHRP Extension Types */
164 #define NHRP_EXT_NULL 0 /* End of Extension */
165 #define NHRP_EXT_RESP_ADDR 3 /* Responder Address Extension */
166 #define NHRP_EXT_FWD_RECORD 4 /* NHRP Forward Transit NHS Record Extension */
167 #define NHRP_EXT_REV_RECORD 5 /* NHRP Reverse Transit NHS Record Extension */
168 #define NHRP_EXT_AUTH 7 /* NHRP Authentication Extension */
169 #define NHRP_EXT_VENDOR_PRIV 8 /* NHRP Vendor Private Extension */
170 #define NHRP_EXT_NAT_ADDRESS 9 /* Cisco NAT Address Extension */
171 #define NHRP_EXT_DEV_CAPABILITIES 9 /* RFC 2735: Device Capabilities Extension */
172 #define NHRP_EXT_MOBILE_AUTH 10 /* RFC 2520: NHRP Mobile NHC Authentication Extension */
174 /* NHRP Error Codes */
175 #define NHRP_ERR_UNRECOGNIZED_EXT 0x0001
176 #define NHRP_ERR_NHRP_LOOP_DETECT 0x0003
177 #define NHRP_ERR_PROT_ADDR_UNREACHABLE 0x0006
178 #define NHRP_ERR_PROT_ERROR 0x0007
179 #define NHRP_ERR_SDU_SIZE_EXCEEDED 0x0008
180 #define NHRP_ERR_INV_EXT 0x0009
181 #define NHRP_ERR_INV_RESOLUTION_REPLY 0x000a
182 #define NHRP_ERR_AUTH_FAILURE 0x000b
183 #define NHRP_ERR_HOP_COUNT_EXCEEDED 0x000f
184 #define NHRP_ERR_VPN_MISMATCH 0x0010 /* RFC 2735 */
185 #define NHRP_ERR_VPN_UNSUPPORTED 0x0011 /* RFC 2735 */
187 /* NHRP CIE codes */
188 #define NHRP_CODE_SUCCESS 0x00
189 #define NHRP_CODE_ADMIN_PROHIBITED 0x04
190 #define NHRP_CODE_INSUFFICIENT_RESOURCES 0x05
191 #define NHRP_CODE_NO_BINDING_EXISTS 0x0c
192 #define NHRP_CODE_NON_UNIQUE_BINDING 0x0d
193 #define NHRP_CODE_ALREADY_REGISTERED 0x0e
195 /* NHRP Subnetwork layer address type/length */
196 #define NHRP_SHTL_TYPE_MASK 0x40
197 #define NHRP_SHTL_LEN_MASK 0x3F
198 #define NHRP_SHTL_TYPE(val) (((val) & (NHRP_SHTL_TYPE_MASK)) >> 6)
199 #define NHRP_SHTL_LEN(val) ((val) & (NHRP_SHTL_LEN_MASK))
201 #define NHRP_SHTL_TYPE_NSAP 0
202 #define NHRP_SHTL_TYPE_E164 1
204 static const value_string nhrp_shtl_type_vals[] = {
205 { NHRP_SHTL_TYPE_NSAP, "NSAP format" },
206 { NHRP_SHTL_TYPE_E164, "Native E.164 format" },
207 { 0, NULL }
210 static const value_string nhrp_op_type_vals[] = {
211 { NHRP_RESOLUTION_REQ, "NHRP Resolution Request" },
212 { NHRP_RESOLUTION_REPLY, "NHRP Resolution Reply" },
213 { NHRP_REGISTRATION_REQ, "NHRP Registration Request" },
214 { NHRP_REGISTRATION_REPLY, "NHRP Registration Reply" },
215 { NHRP_PURGE_REQ, "NHRP Purge Request" },
216 { NHRP_PURGE_REPLY, "NHRP Purge Reply" },
217 { NHRP_ERROR_INDICATION, "NHRP Error Indication" },
218 { NHRP_TRAFFIC_INDICATION, "NHRP Traffic Indication" },
219 { 0, NULL }
222 static const value_string ext_type_vals[] = {
223 { NHRP_EXT_NULL, "End of Extension" },
224 { NHRP_EXT_RESP_ADDR, "Responder Address Extension" },
225 { NHRP_EXT_FWD_RECORD, "Forward Transit NHS Record Extension" },
226 { NHRP_EXT_REV_RECORD, "Reverse Transit NHS Record Extension" },
227 { NHRP_EXT_AUTH, "NHRP Authentication Extension" },
228 { NHRP_EXT_VENDOR_PRIV, "NHRP Vendor Private Extension" },
229 { NHRP_EXT_NAT_ADDRESS, "Cisco NAT Address Extension" },
230 #if 0 /* Dup (which is handled in the code) */
231 { NHRP_EXT_DEV_CAPABILITIES,"Device Capabilities Extension" },
232 #endif
233 { NHRP_EXT_MOBILE_AUTH, "Mobile NHC Authentication Extension" },
234 { 0, NULL }
237 static const value_string nhrp_error_code_vals[] = {
238 { NHRP_ERR_UNRECOGNIZED_EXT, "Unrecognized Extension" },
239 { NHRP_ERR_NHRP_LOOP_DETECT, "NHRP Loop Detected" },
240 { NHRP_ERR_PROT_ADDR_UNREACHABLE, "Protocol Address Unreachable" },
241 { NHRP_ERR_PROT_ERROR, "Protocol Error" },
242 { NHRP_ERR_SDU_SIZE_EXCEEDED, "NHRP SDU Size Exceeded" },
243 { NHRP_ERR_INV_EXT, "Invalid Extension" },
244 { NHRP_ERR_INV_RESOLUTION_REPLY, "Invalid NHRP Resolution Reply Received" },
245 { NHRP_ERR_AUTH_FAILURE, "Authentication Failure" },
246 { NHRP_ERR_HOP_COUNT_EXCEEDED, "Hop Count Exceeded" },
247 { NHRP_ERR_VPN_MISMATCH, "VPN Mismatch" },
248 { NHRP_ERR_VPN_UNSUPPORTED, "VPN Unsupported" },
249 { 0, NULL }
252 static const value_string nhrp_traffic_code_vals[] = {
253 { 0, "NHRP traffic redirect/indirection" },
254 { 0, NULL }
257 static const value_string nhrp_cie_code_vals[] = {
258 { NHRP_CODE_SUCCESS, "Success" },
259 { NHRP_CODE_ADMIN_PROHIBITED, "Administratively Prohibited" },
260 { NHRP_CODE_INSUFFICIENT_RESOURCES, "Insufficient Resources" },
261 { NHRP_CODE_NO_BINDING_EXISTS, "No Interworking Layer Address to NBMA Address Binding Exists" },
262 { NHRP_CODE_NON_UNIQUE_BINDING, "Binding Exists But Is Not Unique" },
263 { NHRP_CODE_ALREADY_REGISTERED, "Unique Internetworking Layer Address Already Registered" },
264 { 0, NULL }
267 static dissector_table_t osinl_incl_subdissector_table;
268 static dissector_table_t osinl_excl_subdissector_table;
269 static dissector_table_t ethertype_subdissector_table;
272 * The header fields needed outside of dissect_nhrp_hdr().
273 * This is not all of the fields.
275 typedef struct _e_nhrp {
276 uint16_t ar_afn;
277 uint16_t ar_pro_type;
278 uint32_t ar_pro_type_oui;
279 uint16_t ar_pro_type_pid;
280 uint8_t ar_op_type;
281 uint8_t ar_shtl;
282 uint8_t ar_sstl;
283 } e_nhrp_hdr;
285 static bool dissect_nhrp_hdr(tvbuff_t *tvb,
286 packet_info *pinfo,
287 proto_tree *tree,
288 int *pOffset,
289 int *pMandLen,
290 int *pExtLen,
291 oui_info_t **pOuiInfo,
292 e_nhrp_hdr *hdr)
294 int offset = *pOffset;
295 const char *pro_type_str;
297 proto_tree *nhrp_tree;
298 proto_item *nhrp_item;
299 proto_item *shtl_tree_item;
300 proto_tree *shtl_tree;
301 proto_item *sstl_tree_item;
302 proto_tree *sstl_tree;
303 proto_item *ti, *ti_extoff;
304 uint32_t afn;
305 uint32_t oui;
306 uint32_t pid;
307 uint32_t pktsz;
308 uint32_t extoff;
309 uint8_t version;
311 nhrp_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_nhrp_hdr, &nhrp_item, "NHRP Fixed Header");
313 proto_tree_add_item_ret_uint(nhrp_tree, hf_nhrp_hdr_afn, tvb, offset, 2, ENC_BIG_ENDIAN, &afn);
314 hdr->ar_afn = (uint16_t)afn;
315 offset += 2;
317 /* XXX - range_string? */
318 hdr->ar_pro_type = tvb_get_ntohs(tvb, offset);
319 if (hdr->ar_pro_type <= 0xFF) {
320 /* It's an NLPID */
321 pro_type_str = val_to_str_const(hdr->ar_pro_type, nlpid_vals,
322 "Unknown NLPID");
323 } else if (hdr->ar_pro_type <= 0x3FF) {
324 /* Reserved for future use by the IETF */
325 pro_type_str = "Reserved for future use by the IETF";
326 } else if (hdr->ar_pro_type <= 0x04FF) {
327 /* Allocated for use by the ATM Forum */
328 pro_type_str = "Allocated for use by the ATM Forum";
329 } else if (hdr->ar_pro_type <= 0x05FF) {
330 /* Experimental/Local use */
331 pro_type_str = "Experimental/Local use";
332 } else {
333 pro_type_str = val_to_str_const(hdr->ar_pro_type, etype_vals,
334 "Unknown Ethertype");
336 proto_tree_add_uint_format_value(nhrp_tree, hf_nhrp_hdr_pro_type, tvb, offset, 2,
337 hdr->ar_pro_type, "%s (0x%04x)",
338 pro_type_str, hdr->ar_pro_type);
339 offset += 2;
341 if (hdr->ar_pro_type == NLPID_SNAP) {
343 * The long form protocol type is a SNAP OUI and PID.
345 proto_tree_add_item_ret_uint(nhrp_tree, hf_nhrp_hdr_pro_snap_oui,
346 tvb, offset, 3, hdr->ar_pro_type_oui, &oui);
347 offset += 3;
348 hdr->ar_pro_type_oui = oui;
350 *pOuiInfo = get_snap_oui_info(hdr->ar_pro_type_oui);
351 if (*pOuiInfo != NULL) {
352 proto_tree_add_item_ret_uint(nhrp_tree,
353 *(*pOuiInfo)->field_info->p_id,
354 tvb, offset, 2, ENC_BIG_ENDIAN, &pid);
355 } else {
356 proto_tree_add_item_ret_uint(nhrp_tree, hf_nhrp_hdr_pro_snap_pid,
357 tvb, offset, 2, ENC_BIG_ENDIAN, &pid);
359 hdr->ar_pro_type_pid = (uint16_t)pid;
360 } else {
362 * XXX - we should check that this is zero, as RFC 2332
363 * says it should be zero.
365 proto_tree_add_item(nhrp_tree, hf_nhrp_protocol_type, tvb, offset, 5, ENC_NA);
366 offset += 5;
369 proto_tree_add_item(nhrp_tree, hf_nhrp_hdr_hopcnt, tvb, offset, 1, ENC_BIG_ENDIAN);
370 offset += 1;
372 ti = proto_tree_add_item_ret_uint(nhrp_tree, hf_nhrp_hdr_pktsz, tvb, offset, 2, ENC_BIG_ENDIAN, &pktsz);
373 if (pktsz < 20) {
375 * The total packet size isn't large enough for a full header.
377 expert_add_info(pinfo, ti, &ei_nhrp_hdr_pktsz);
378 proto_item_set_end(nhrp_item, tvb, offset + 2);
379 return false;
381 offset += 2;
383 if (tvb_bytes_exist(tvb, 0, pktsz)) {
384 vec_t cksum_vec[1];
385 SET_CKSUM_VEC_TVB(cksum_vec[0], tvb, 0, pktsz);
387 proto_tree_add_checksum(nhrp_tree, tvb, offset, hf_nhrp_hdr_chksum, hf_nhrp_hdr_chksum_status, &ei_nhrp_hdr_chksum,
388 pinfo, in_cksum(&cksum_vec[0], 1), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
389 } else {
390 proto_tree_add_checksum(nhrp_tree, tvb, offset, hf_nhrp_hdr_chksum, hf_nhrp_hdr_chksum_status, &ei_nhrp_hdr_chksum,
391 pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
393 offset += 2;
395 ti_extoff = proto_tree_add_item_ret_uint(nhrp_tree, hf_nhrp_hdr_extoff, tvb, offset, 2, ENC_BIG_ENDIAN, &extoff);
396 if (extoff != 0) {
397 if (extoff < 20 || extoff > pktsz) {
398 /* Bogus value; keep dissecting the header */
399 expert_add_info(pinfo, ti_extoff, &ei_nhrp_hdr_extoff);
401 switch (hdr->ar_op_type)
403 case NHRP_ERROR_INDICATION:
404 /* According to RFC 2332, section 5.2.7, there shouldn't be any
405 * extensions in the Error Indication packet. */
406 expert_add_info(pinfo, ti_extoff, &ei_nhrp_ext_not_allowed);
407 break;
408 default:
409 break;
412 offset += 2;
414 version = tvb_get_uint8(tvb, offset);
415 proto_tree_add_uint_format_value(nhrp_tree, hf_nhrp_hdr_version, tvb, offset, 1,
416 version, "%u (%s)", version,
417 (version == 1) ? "NHRP - rfc2332" : "Unknown");
418 offset += 1;
419 proto_tree_add_item(nhrp_tree, hf_nhrp_hdr_op_type, tvb, offset, 1, ENC_BIG_ENDIAN);
420 offset += 1;
422 hdr->ar_shtl = tvb_get_uint8(tvb, offset);
423 shtl_tree_item = proto_tree_add_uint_format_value(nhrp_tree, hf_nhrp_hdr_shtl,
424 tvb, offset, 1, hdr->ar_shtl, "%s/%u",
425 val_to_str_const(NHRP_SHTL_TYPE(hdr->ar_shtl), nhrp_shtl_type_vals, "Unknown Type"),
426 NHRP_SHTL_LEN(hdr->ar_shtl));
427 shtl_tree = proto_item_add_subtree(shtl_tree_item, ett_nhrp_hdr_shtl);
428 proto_tree_add_item(shtl_tree, hf_nhrp_hdr_shtl_type, tvb, offset, 1, ENC_BIG_ENDIAN);
429 proto_tree_add_item(shtl_tree, hf_nhrp_hdr_shtl_len, tvb, offset, 1, ENC_BIG_ENDIAN);
430 offset += 1;
432 hdr->ar_sstl = tvb_get_uint8(tvb, offset);
433 sstl_tree_item = proto_tree_add_uint_format_value(nhrp_tree, hf_nhrp_hdr_sstl,
434 tvb, offset, 1, hdr->ar_sstl, "%s/%u",
435 val_to_str_const(NHRP_SHTL_TYPE(hdr->ar_sstl), nhrp_shtl_type_vals, "Unknown Type"),
436 NHRP_SHTL_LEN(hdr->ar_sstl));
437 sstl_tree = proto_item_add_subtree(sstl_tree_item, ett_nhrp_hdr_sstl);
438 proto_tree_add_item(sstl_tree, hf_nhrp_hdr_sstl_type, tvb, offset, 1, ENC_BIG_ENDIAN);
439 proto_tree_add_item(sstl_tree, hf_nhrp_hdr_sstl_len, tvb, offset, 1, ENC_BIG_ENDIAN);
440 offset += 1;
442 proto_item_set_end(nhrp_item, tvb, offset);
443 *pOffset = offset;
444 if (extoff != 0) {
445 if (extoff < 20 || extoff > pktsz) {
446 /* Bogus value */
447 return false;
449 *pMandLen = extoff - 20;
450 *pExtLen = pktsz - extoff;
452 else {
453 *pMandLen = pktsz - 20;
454 *pExtLen = 0;
456 return true;
459 static void dissect_cie_list(tvbuff_t *tvb,
460 packet_info *pinfo,
461 proto_tree *tree,
462 int offset,
463 int cieEnd,
464 e_nhrp_hdr *hdr,
465 int isReq,
466 bool codeinfo)
468 proto_item *cli_addr_tree_item;
469 proto_tree *cli_addr_tree;
470 proto_item *cli_saddr_tree_item;
471 proto_tree *cli_saddr_tree;
472 uint8_t val;
474 while ((offset + 12) <= cieEnd) {
475 unsigned cli_addr_len = tvb_get_uint8(tvb, offset + 8);
476 unsigned cli_saddr_len = tvb_get_uint8(tvb, offset + 9);
477 unsigned cli_prot_len = tvb_get_uint8(tvb, offset + 10);
478 unsigned cie_len = 12 + cli_addr_len + cli_saddr_len + cli_prot_len;
479 proto_tree *cie_tree = proto_tree_add_subtree(tree, tvb, offset, cie_len, ett_nhrp_cie, NULL, "Client Information Entry");
481 if (isReq) {
482 proto_tree_add_item(cie_tree, hf_nhrp_code, tvb, offset, 1, ENC_BIG_ENDIAN);
484 else {
485 uint8_t code = tvb_get_uint8(tvb, offset);
486 if ( codeinfo ) {
487 col_append_fstr(pinfo->cinfo, COL_INFO, ", Code=%s",
488 val_to_str(code, nhrp_cie_code_vals, "Unknown (%u)"));
490 proto_tree_add_item(cie_tree, hf_nhrp_code, tvb, offset, 1, ENC_BIG_ENDIAN);
492 offset += 1;
494 proto_tree_add_item(cie_tree, hf_nhrp_prefix_len, tvb, offset, 1, ENC_BIG_ENDIAN);
495 offset += 1;
497 proto_tree_add_item(cie_tree, hf_nhrp_unused, tvb, offset, 2, ENC_BIG_ENDIAN);
498 offset += 2;
500 proto_tree_add_item(cie_tree, hf_nhrp_mtu, tvb, offset, 2, ENC_BIG_ENDIAN);
501 offset += 2;
503 proto_tree_add_item(cie_tree, hf_nhrp_holding_time, tvb, offset, 2, ENC_BIG_ENDIAN);
504 offset += 2;
506 val = tvb_get_uint8(tvb, offset);
507 cli_addr_tree_item = proto_tree_add_uint_format_value(cie_tree,
508 hf_nhrp_cli_addr_tl, tvb, offset, 1, val, "%s/%u",
509 val_to_str_const(NHRP_SHTL_TYPE(val), nhrp_shtl_type_vals, "Unknown Type"),
510 NHRP_SHTL_LEN(val));
511 cli_addr_tree = proto_item_add_subtree(cli_addr_tree_item, ett_nhrp_cie_cli_addr_tl);
512 proto_tree_add_item(cli_addr_tree, hf_nhrp_cli_addr_tl_type, tvb, offset, 1, ENC_BIG_ENDIAN);
513 proto_tree_add_item(cli_addr_tree, hf_nhrp_cli_addr_tl_len, tvb, offset, 1, ENC_BIG_ENDIAN);
514 offset += 1;
516 val = tvb_get_uint8(tvb, offset);
517 cli_saddr_tree_item = proto_tree_add_uint_format_value(cie_tree,
518 hf_nhrp_cli_saddr_tl, tvb, offset, 1, val, "%s/%u",
519 val_to_str_const(NHRP_SHTL_TYPE(val), nhrp_shtl_type_vals, "Unknown Type"),
520 NHRP_SHTL_LEN(val));
521 cli_saddr_tree = proto_item_add_subtree(cli_saddr_tree_item, ett_nhrp_cie_cli_saddr_tl);
522 proto_tree_add_item(cli_saddr_tree, hf_nhrp_cli_saddr_tl_type, tvb, offset, 1, ENC_BIG_ENDIAN);
523 proto_tree_add_item(cli_saddr_tree, hf_nhrp_cli_saddr_tl_len, tvb, offset, 1, ENC_BIG_ENDIAN);
524 offset += 1;
526 proto_tree_add_item(cie_tree, hf_nhrp_cli_prot_len, tvb, offset, 1, ENC_BIG_ENDIAN);
527 offset += 1;
529 proto_tree_add_item(cie_tree, hf_nhrp_pref, tvb, offset, 1, ENC_BIG_ENDIAN);
530 offset += 1;
532 if (cli_addr_len) {
533 switch (hdr->ar_afn) {
535 case AFNUM_INET:
536 if (cli_addr_len == 4)
537 proto_tree_add_item(cie_tree, hf_nhrp_client_nbma_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
538 else {
539 proto_tree_add_item(cie_tree, hf_nhrp_client_nbma_address_bytes, tvb, offset, cli_addr_len, ENC_NA);
541 break;
543 default:
544 proto_tree_add_item(cie_tree, hf_nhrp_client_nbma_address_bytes, tvb, offset, cli_addr_len, ENC_NA);
545 break;
547 offset += cli_addr_len;
550 if (cli_saddr_len) {
551 proto_tree_add_item(cie_tree, hf_nhrp_client_nbma_saddr, tvb, offset, cli_saddr_len, ENC_NA);
554 if (cli_prot_len) {
555 if (cli_prot_len == 4)
556 proto_tree_add_item(cie_tree, hf_nhrp_client_prot_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
557 else {
558 proto_tree_add_item(cie_tree, hf_nhrp_client_prot_addr_bytes, tvb, offset, cli_prot_len, ENC_NA);
560 offset += cli_prot_len;
565 // NOLINTNEXTLINE(misc-no-recursion)
566 static void dissect_nhrp_mand(tvbuff_t *tvb,
567 packet_info *pinfo,
568 proto_tree *tree,
569 oui_info_t *oui_info,
570 e_nhrp_hdr *hdr,
571 unsigned *srcLen,
572 bool codeinfo)
574 int offset = 0;
575 int mandEnd = tvb_reported_length(tvb);
576 uint8_t ssl, shl;
577 unsigned dstLen;
579 proto_tree *nhrp_tree;
580 proto_item *nhrp_item;
582 proto_tree *ind_tree;
583 proto_item *ind_item;
584 bool save_in_error_pkt;
585 int dissected;
586 tvbuff_t *sub_tvb;
588 nhrp_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_nhrp_mand, &nhrp_item, "NHRP Mandatory Part");
590 /* Src Proto Len, present in all current packet types */
591 *srcLen = tvb_get_uint8(tvb, offset);
592 proto_tree_add_item(nhrp_tree, hf_nhrp_src_proto_len, tvb, offset, 1, ENC_BIG_ENDIAN);
593 offset += 1;
595 /* Dst Proto Len, present in all current packet types */
596 dstLen = tvb_get_uint8(tvb, offset);
597 proto_tree_add_item(nhrp_tree, hf_nhrp_dst_proto_len, tvb, offset, 1, ENC_BIG_ENDIAN);
598 offset += 1;
601 * Flags: different flags are used for different packet types, and
602 * aren't even present in all packet types.
604 * Next 4 bytes: request ID in most packet types, error code and
605 * offset in Error Indication, traffic code and unused field in
606 * Traffic Indication.
608 switch (hdr->ar_op_type)
610 case NHRP_RESOLUTION_REQ:
611 case NHRP_RESOLUTION_REPLY:
613 static int * const flags[] = {
614 &hf_nhrp_flag_Q,
615 &hf_nhrp_flag_A,
616 &hf_nhrp_flag_D,
617 &hf_nhrp_flag_U1,
618 &hf_nhrp_flag_S,
619 &hf_nhrp_flag_NAT,
620 NULL
622 proto_tree_add_bitmask(nhrp_tree, tvb, offset, hf_nhrp_flags, ett_nhrp_mand_flag, flags, ENC_BIG_ENDIAN);
623 offset += 2;
625 col_append_fstr(pinfo->cinfo, COL_INFO, ", ID=%u", tvb_get_ntohl(tvb, offset));
626 proto_tree_add_item(nhrp_tree, hf_nhrp_request_id, tvb, offset, 4, ENC_BIG_ENDIAN);
627 offset += 4;
629 break;
630 case NHRP_REGISTRATION_REQ:
631 case NHRP_REGISTRATION_REPLY:
633 static int * const flags[] = {
634 &hf_nhrp_flag_U2,
635 &hf_nhrp_flag_NAT,
636 NULL
638 proto_tree_add_bitmask(nhrp_tree, tvb, offset, hf_nhrp_flags, ett_nhrp_mand_flag, flags, ENC_BIG_ENDIAN);
639 offset += 2;
641 col_append_fstr(pinfo->cinfo, COL_INFO, ", ID=%u", tvb_get_ntohl(tvb, offset));
642 proto_tree_add_item(nhrp_tree, hf_nhrp_request_id, tvb, offset, 4, ENC_BIG_ENDIAN);
643 offset += 4;
645 break;
647 case NHRP_PURGE_REQ:
648 case NHRP_PURGE_REPLY:
650 static int * const flags[] = {
651 &hf_nhrp_flag_N,
652 &hf_nhrp_flag_NAT,
653 NULL
655 proto_tree_add_bitmask(nhrp_tree, tvb, offset, hf_nhrp_flags, ett_nhrp_mand_flag, flags, ENC_BIG_ENDIAN);
656 offset += 2;
658 col_append_fstr(pinfo->cinfo, COL_INFO, ", ID=%u", tvb_get_ntohl(tvb, offset));
659 proto_tree_add_item(nhrp_tree, hf_nhrp_request_id, tvb, offset, 4, ENC_BIG_ENDIAN);
660 offset += 4;
662 break;
663 case NHRP_ERROR_INDICATION:
665 /* Skip unused field */
666 offset += 2;
668 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
669 val_to_str(tvb_get_ntohs(tvb, offset), nhrp_error_code_vals, "Unknown Error (%u)"));
670 proto_tree_add_item(nhrp_tree, hf_nhrp_error_code, tvb, offset, 2, ENC_BIG_ENDIAN);
671 offset += 2;
673 proto_tree_add_item(nhrp_tree, hf_nhrp_error_offset, tvb, offset, 2, ENC_BIG_ENDIAN);
674 offset += 2;
676 break;
677 case NHRP_TRAFFIC_INDICATION:
679 /* Skip unused field */
680 offset += 2;
682 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
683 val_to_str(tvb_get_ntohs(tvb, offset), nhrp_traffic_code_vals, "Unknown traffic code (%u)"));
684 proto_tree_add_item(nhrp_tree, hf_nhrp_traffic_code, tvb, offset, 2, ENC_BIG_ENDIAN);
685 offset += 2;
687 /* Skip unused field */
688 offset += 2;
690 break;
691 default:
692 /* Unknown packet type */
693 offset += 6;
694 break;
697 shl = NHRP_SHTL_LEN(hdr->ar_shtl);
698 if (shl) {
699 switch (hdr->ar_afn) {
701 case AFNUM_INET:
702 if (shl == 4)
703 proto_tree_add_item(nhrp_tree, hf_nhrp_src_nbma_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
704 else {
705 proto_tree_add_item(nhrp_tree, hf_nhrp_src_nbma_addr_bytes, tvb, offset, shl, ENC_NA);
707 break;
709 default:
710 proto_tree_add_item(nhrp_tree, hf_nhrp_src_nbma_addr_bytes, tvb, offset, shl, ENC_NA);
711 break;
713 offset += shl;
716 ssl = NHRP_SHTL_LEN(hdr->ar_sstl);
717 if (ssl) {
718 proto_tree_add_item(nhrp_tree, hf_nhrp_src_nbma_saddr, tvb, offset, ssl, ENC_NA);
719 offset += ssl;
722 if (*srcLen == 4) {
723 proto_tree_add_item(nhrp_tree, hf_nhrp_src_prot_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
724 offset += 4;
726 else if (*srcLen) {
727 proto_tree_add_item(nhrp_tree, hf_nhrp_src_prot_addr_bytes, tvb, offset, *srcLen, ENC_NA);
728 offset += *srcLen;
731 if (dstLen == 4) {
732 proto_tree_add_item(nhrp_tree, hf_nhrp_dst_prot_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
733 offset += 4;
735 else if (dstLen) {
736 proto_tree_add_item(nhrp_tree, hf_nhrp_dst_prot_addr_bytes, tvb, offset, dstLen, ENC_NA);
737 offset += dstLen;
741 * CIE list in most packet types, NHRP packet in error in Error
742 * Indication, data packet in Traffic Indication.
744 switch (hdr->ar_op_type)
746 case NHRP_RESOLUTION_REQ:
747 case NHRP_REGISTRATION_REQ:
748 case NHRP_PURGE_REQ:
749 dissect_cie_list(tvb, pinfo, nhrp_tree, offset, mandEnd, hdr, true, codeinfo);
750 break;
751 case NHRP_RESOLUTION_REPLY:
752 case NHRP_REGISTRATION_REPLY:
753 case NHRP_PURGE_REPLY:
754 dissect_cie_list(tvb, pinfo, nhrp_tree, offset, mandEnd, hdr, false, codeinfo);
755 break;
756 case NHRP_ERROR_INDICATION:
757 ind_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_nhrp_indication, &ind_item, "Packet Causing Indication");
758 save_in_error_pkt = pinfo->flags.in_error_pkt;
759 pinfo->flags.in_error_pkt = true;
760 sub_tvb = tvb_new_subset_remaining(tvb, offset);
761 // We recurse here, but we'll run out of packet before we run out of stack.
762 _dissect_nhrp(sub_tvb, pinfo, ind_tree, true, false);
763 pinfo->flags.in_error_pkt = save_in_error_pkt;
764 break;
765 case NHRP_TRAFFIC_INDICATION:
766 ind_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_nhrp_indication, &ind_item, "Packet Causing Indication");
767 save_in_error_pkt = pinfo->flags.in_error_pkt;
768 pinfo->flags.in_error_pkt = true;
769 sub_tvb = tvb_new_subset_remaining(tvb, offset);
770 if (hdr->ar_pro_type <= 0xFF) {
771 /* It's an NLPID */
772 if (hdr->ar_pro_type == NLPID_SNAP) {
774 * Dissect based on the SNAP OUI and PID.
776 if (hdr->ar_pro_type_oui == 0x000000) {
778 * "Should not happen", as the protocol type should
779 * be the Ethertype, but....
781 dissected = dissector_try_uint(
782 ethertype_subdissector_table,
783 hdr->ar_pro_type_pid,
784 sub_tvb, pinfo, ind_tree);
785 } else {
787 * If we have a dissector table, use it, otherwise
788 * just dissect as data.
790 if (oui_info != NULL) {
791 dissected = dissector_try_uint(
792 oui_info->table,
793 hdr->ar_pro_type_pid,
794 sub_tvb, pinfo,
795 ind_tree);
796 } else
797 dissected = 0;
799 } else {
801 * Dissect based on the NLPID.
803 dissected = dissector_try_uint(
804 osinl_incl_subdissector_table,
805 hdr->ar_pro_type, sub_tvb, pinfo,
806 ind_tree) ||
807 dissector_try_uint(
808 osinl_excl_subdissector_table,
809 hdr->ar_pro_type, sub_tvb, pinfo,
810 ind_tree);
812 } else if (hdr->ar_pro_type <= 0x3FF) {
813 /* Reserved for future use by the IETF */
814 dissected = 0;
815 } else if (hdr->ar_pro_type <= 0x04FF) {
816 /* Allocated for use by the ATM Forum */
817 dissected = 0;
818 } else if (hdr->ar_pro_type <= 0x05FF) {
819 /* Experimental/Local use */
820 dissected = 0;
821 } else {
822 dissected = dissector_try_uint(
823 ethertype_subdissector_table,
824 hdr->ar_pro_type, sub_tvb, pinfo, ind_tree);
826 if (!dissected) {
827 call_data_dissector(sub_tvb, pinfo, ind_tree);
829 pinfo->flags.in_error_pkt = save_in_error_pkt;
830 break;
831 default:
832 break;
836 static void dissect_nhrp_ext(tvbuff_t *tvb,
837 packet_info *pinfo,
838 proto_tree *tree,
839 int *pOffset,
840 int extLen,
841 e_nhrp_hdr *hdr,
842 unsigned srcLen,
843 bool nested)
845 int offset = *pOffset;
846 int extEnd = offset + extLen;
848 while ((offset + 4) <= extEnd)
850 proto_tree *nhrp_tree;
851 proto_item *nhrp_item;
852 int extTypeC = tvb_get_ntohs(tvb, offset);
853 int extType = extTypeC & 0x3FFF;
854 unsigned len = tvb_get_ntohs(tvb, offset+2);
856 if ((extType == NHRP_EXT_NAT_ADDRESS) && (len == 8)) {
857 /* Assume it's not really a Cisco NAT extension, but a device
858 * capabilities extension instead (see RFC 2735). */
859 nhrp_tree = proto_tree_add_subtree(tree, tvb, offset,
860 -1, ett_nhrp_ext, &nhrp_item, "Device Capabilities Extension");
862 else {
863 nhrp_tree = proto_tree_add_subtree(tree, tvb, offset,
864 -1, ett_nhrp_ext, &nhrp_item,
865 val_to_str(extType, ext_type_vals, "Unknown (%u)"));
867 proto_tree_add_boolean(nhrp_tree, hf_nhrp_ext_C, tvb, offset, 2, extTypeC);
868 proto_tree_add_item(nhrp_tree, hf_nhrp_ext_type, tvb, offset, 2, ENC_BIG_ENDIAN);
869 offset += 2;
871 proto_tree_add_item(nhrp_tree, hf_nhrp_ext_len, tvb, offset, 2, ENC_BIG_ENDIAN);
872 offset += 2;
874 if (len && (extType != NHRP_EXT_NULL)) {
875 if ((extType == NHRP_EXT_NAT_ADDRESS) && (len == 8)) {
876 /* Assume it's not really a Cisco NAT extension, but a device
877 * capabilities extension instead (see RFC 2735). */
878 proto_tree *devcap_tree;
879 proto_item *cap_item;
880 proto_tree *cap_tree;
882 devcap_tree = proto_tree_add_subtree_format(nhrp_tree, tvb, offset, len,
883 ett_nhrp_devcap_ext, NULL, "Extension Data: Src is %sVPN-aware; Dst is %sVPN-aware",
884 tvb_get_ntohl(tvb, offset) & 1 ? "" : "non-",
885 tvb_get_ntohl(tvb, offset + 4) & 1 ? "" : "non-");
886 cap_item = proto_tree_add_item(devcap_tree, hf_nhrp_devcap_ext_srccap, tvb, offset, 4, ENC_BIG_ENDIAN);
887 cap_tree = proto_item_add_subtree(cap_item, ett_nhrp_devcap_ext_srccap);
888 proto_tree_add_item(cap_tree, hf_nhrp_devcap_ext_srccap_V, tvb, offset, 4, ENC_BIG_ENDIAN);
890 cap_item = proto_tree_add_item(devcap_tree, hf_nhrp_devcap_ext_dstcap, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
891 cap_tree = proto_item_add_subtree(cap_item, ett_nhrp_devcap_ext_dstcap);
892 proto_tree_add_item(cap_tree, hf_nhrp_devcap_ext_dstcap_V, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
893 goto skip_switch;
896 switch (extType) {
897 case NHRP_EXT_RESP_ADDR:
898 case NHRP_EXT_FWD_RECORD:
899 case NHRP_EXT_REV_RECORD:
900 case NHRP_EXT_NAT_ADDRESS:
901 dissect_cie_list(tvb, pinfo, nhrp_tree,
902 offset, offset + len, hdr, 0, false);
903 break;
905 case NHRP_EXT_AUTH:
906 /* This is ugly, but this is the only place srcLen is actually
907 * used so we manipulate it here.
909 if (!pref_auth_ext_has_addr)
910 srcLen = 0;
911 /* fallthrough */
912 case NHRP_EXT_MOBILE_AUTH:
913 if (len < (4 + srcLen)) {
914 proto_tree_add_expert_format(nhrp_tree, pinfo, &ei_nhrp_ext_malformed, tvb, offset, len,
915 "Incomplete Authentication Extension");
917 else {
918 proto_tree *auth_tree;
919 proto_item *auth_item;
920 uint32_t spi;
922 auth_tree = proto_tree_add_subtree_format(nhrp_tree, tvb, offset, -1,
923 ett_nhrp_auth_ext, &auth_item, "Extension Data");
924 proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
925 proto_tree_add_item_ret_uint(auth_tree, hf_nhrp_auth_ext_spi, tvb, offset + 2, 2, ENC_BIG_ENDIAN, &spi);
926 proto_item_append_text(auth_item, ": SPI=%u", spi);
927 if (srcLen == 4)
928 proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_src_addr, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
929 else if (srcLen) {
930 proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_src_addr_bytes, tvb, offset + 4, srcLen, ENC_NA);
932 if (len > (4 + srcLen)) {
933 proto_tree_add_item(auth_tree, hf_nhrp_auth_data, tvb, offset + 4 + srcLen, len - (4 + srcLen), ENC_NA);
934 proto_item_append_text(auth_item, ": Data=%s",
935 tvb_bytes_to_str(pinfo->pool, tvb, offset + 4 + srcLen, len - (4 + srcLen)));
937 proto_item_set_len(auth_item, len);
939 break;
941 case NHRP_EXT_VENDOR_PRIV:
942 if (len < 3) {
943 proto_tree_add_expert_format(nhrp_tree, pinfo, &ei_nhrp_ext_malformed, tvb, offset, len,
944 "Incomplete Vendor-Private Extension");
946 else {
947 proto_tree *vendor_tree;
948 proto_item *vendor_item;
949 uint32_t manuf;
950 const char* oui;
952 vendor_tree = proto_tree_add_subtree(nhrp_tree, tvb, offset, len,
953 ett_nhrp_vendor_ext, &vendor_item, "Extension Data:");
954 proto_tree_add_item_ret_uint(vendor_tree, hf_nhrp_vendor_ext_id, tvb, offset, 3, ENC_BIG_ENDIAN, &manuf);
955 oui = uint_get_manuf_name_if_known(manuf);
956 if (oui != NULL) {
957 proto_item_append_text(vendor_item, " Vendor ID=%s", oui);
958 } else {
959 proto_item_append_text(vendor_item, " Vendor ID=Unknown");
961 if (len > 3) {
962 proto_tree_add_item(vendor_tree, hf_nhrp_vendor_ext_data, tvb, offset + 3, len - 3, ENC_NA);
963 proto_item_append_text(vendor_item, ", Data=%s", tvb_bytes_to_str(pinfo->pool, tvb, offset + 3, len - 3));
964 } else {
965 proto_item_append_text(vendor_item, ", Data=<none>");
968 break;
970 default:
971 proto_tree_add_item(nhrp_tree, hf_nhrp_unknown_ext_value, tvb,
972 offset, len, ENC_NA);
973 break;
975 skip_switch:
976 offset += len;
978 proto_item_set_end(nhrp_item, tvb, offset);
980 if (!nested) {
981 len = tvb_reported_length_remaining(tvb, offset);
982 if ((extType == NHRP_EXT_NULL) && len) {
983 proto_tree_add_expert_format(tree, pinfo, &ei_nhrp_ext_extra, tvb, offset, len,
984 "Unknown Data (%d bytes)", len);
985 break;
990 *pOffset = extEnd;
993 static int dissect_nhrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
995 _dissect_nhrp(tvb, pinfo, tree, false, true);
996 return tvb_captured_length(tvb);
999 // NOLINTNEXTLINE(misc-no-recursion)
1000 static void _dissect_nhrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1001 bool nested, bool codeinfo)
1003 e_nhrp_hdr hdr;
1004 int mandLen = 0;
1005 int extLen = 0;
1006 int offset = 0;
1007 proto_item *ti;
1008 proto_tree *nhrp_tree;
1009 oui_info_t *oui_info = NULL;
1010 unsigned srcLen = 0;
1012 if (!nested) {
1013 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NHRP");
1014 col_clear(pinfo->cinfo, COL_INFO);
1017 memset(&hdr, 0, sizeof(e_nhrp_hdr));
1018 hdr.ar_op_type = tvb_get_uint8(tvb, 17);
1020 if (!nested) {
1021 col_add_str(pinfo->cinfo, COL_INFO,
1022 val_to_str(hdr.ar_op_type, nhrp_op_type_vals,
1023 "0x%02X - unknown"));
1026 ti = proto_tree_add_protocol_format(tree, proto_nhrp, tvb, 0, -1,
1027 "Next Hop Resolution Protocol (%s)",
1028 val_to_str(hdr.ar_op_type, nhrp_op_type_vals, "0x%02X - unknown"));
1029 nhrp_tree = proto_item_add_subtree(ti, ett_nhrp);
1031 if (!dissect_nhrp_hdr(tvb, pinfo, nhrp_tree, &offset, &mandLen, &extLen,
1032 &oui_info, &hdr)) {
1034 * Header is bogus in a way that we can't dissect any further.
1036 return;
1038 if (mandLen) {
1039 tvbuff_t *mand_tvb = tvb_new_subset_length(tvb, offset, mandLen);
1040 // We recurse here, but we'll run out of packet before we run out of stack.
1041 dissect_nhrp_mand(mand_tvb, pinfo, nhrp_tree, oui_info, &hdr, &srcLen,
1042 codeinfo);
1043 offset += mandLen;
1046 if (extLen) {
1047 dissect_nhrp_ext(tvb, pinfo, nhrp_tree, &offset, extLen, &hdr, srcLen, nested);
1051 void
1052 proto_register_nhrp(void)
1054 static hf_register_info hf[] = {
1056 { &hf_nhrp_hdr_afn,
1057 { "Address Family Number", "nhrp.hdr.afn",
1058 FT_UINT16, BASE_HEX_DEC, VALS(afn_vals), 0x0,
1059 NULL, HFILL }
1061 { &hf_nhrp_hdr_pro_type,
1062 { "Protocol Type (short form)", "nhrp.hdr.pro.type",
1063 FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
1064 NULL, HFILL }
1066 { &hf_nhrp_hdr_pro_snap_oui,
1067 { "Protocol Type (long form) - OUI", "nhrp.hdr.pro.snap.oui",
1068 FT_UINT24, BASE_OUI, NULL, 0x0,
1069 NULL, HFILL }
1071 { &hf_nhrp_hdr_pro_snap_pid,
1072 { "Protocol Type (long form) - PID", "nhrp.hdr.pro.snap.pid",
1073 FT_UINT16, BASE_HEX, NULL, 0x0,
1074 NULL, HFILL }
1076 { &hf_nhrp_hdr_hopcnt,
1077 { "Hop Count", "nhrp.hdr.hopcnt",
1078 FT_UINT8, BASE_DEC, NULL, 0x0,
1079 NULL, HFILL }
1081 { &hf_nhrp_hdr_pktsz,
1082 { "Packet Length", "nhrp.hdr.pktsz",
1083 FT_UINT16, BASE_DEC, NULL, 0x0,
1084 NULL, HFILL }
1086 { &hf_nhrp_hdr_chksum,
1087 { "NHRP Packet Checksum", "nhrp.hdr.chksum",
1088 FT_UINT16, BASE_HEX, NULL, 0x0,
1089 NULL, HFILL }
1091 { &hf_nhrp_hdr_chksum_status,
1092 { "NHRP Packet Checksum Status", "nhrp.hdr.chksum.status",
1093 FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
1094 NULL, HFILL }
1096 { &hf_nhrp_hdr_extoff,
1097 { "Extension Offset", "nhrp.hdr.extoff",
1098 FT_UINT16, BASE_DEC, NULL, 0x0,
1099 NULL, HFILL }
1101 { &hf_nhrp_hdr_version,
1102 { "Version", "nhrp.hdr.version",
1103 FT_UINT8, BASE_DEC, NULL, 0x0,
1104 NULL, HFILL }
1106 { &hf_nhrp_hdr_op_type,
1107 { "NHRP Packet Type", "nhrp.hdr.op.type",
1108 FT_UINT8, BASE_DEC, VALS(nhrp_op_type_vals), 0x0,
1109 NULL, HFILL }
1111 { &hf_nhrp_hdr_shtl,
1112 { "Source Address Type/Len", "nhrp.hdr.shtl",
1113 FT_UINT8, BASE_DEC, NULL, 0x0,
1114 NULL, HFILL }
1116 { &hf_nhrp_hdr_shtl_type,
1117 { "Type", "nhrp.hdr.shtl.type",
1118 FT_UINT8, BASE_DEC, VALS(nhrp_shtl_type_vals), NHRP_SHTL_TYPE_MASK,
1119 NULL, HFILL }
1121 { &hf_nhrp_hdr_shtl_len,
1122 { "Length", "nhrp.hdr.shtl.len",
1123 FT_UINT8, BASE_DEC, NULL, NHRP_SHTL_LEN_MASK,
1124 NULL, HFILL }
1126 { &hf_nhrp_hdr_sstl,
1127 { "Source SubAddress Type/Len", "nhrp.hdr.sstl",
1128 FT_UINT8, BASE_DEC, NULL, 0x0,
1129 NULL, HFILL }
1131 { &hf_nhrp_hdr_sstl_type,
1132 { "Type", "nhrp.hdr.sstl.type",
1133 FT_UINT8, BASE_DEC, VALS(nhrp_shtl_type_vals), NHRP_SHTL_TYPE_MASK,
1134 NULL, HFILL }
1136 { &hf_nhrp_hdr_sstl_len,
1137 { "Length", "nhrp.hdr.sstl.len",
1138 FT_UINT8, BASE_DEC, NULL, NHRP_SHTL_LEN_MASK,
1139 NULL, HFILL }
1142 { &hf_nhrp_src_proto_len,
1143 { "Source Protocol Len", "nhrp.src.prot.len",
1144 FT_UINT16, BASE_DEC, NULL, 0x0,
1145 NULL, HFILL }
1147 { &hf_nhrp_dst_proto_len,
1148 { "Destination Protocol Len", "nhrp.dst.prot.len",
1149 FT_UINT16, BASE_DEC, NULL, 0x0,
1150 NULL, HFILL }
1152 { &hf_nhrp_flags,
1153 { "Flags", "nhrp.flags",
1154 FT_UINT16, BASE_HEX, NULL, 0x0,
1155 NULL, HFILL }
1157 { &hf_nhrp_flag_Q,
1158 { "Is Router", "nhrp.flag.q",
1159 FT_BOOLEAN, 16, NULL, 0x8000,
1160 NULL, HFILL }
1162 { &hf_nhrp_flag_N,
1163 { "Expected Purge Reply", "nhrp.flag.n",
1164 FT_BOOLEAN, 16, NULL, 0x8000,
1165 NULL, HFILL }
1167 { &hf_nhrp_flag_A,
1168 { "Authoritative", "nhrp.flag.a",
1169 FT_BOOLEAN, 16, NULL, 0x4000,
1170 "A bit", HFILL }
1172 { &hf_nhrp_flag_D,
1173 { "Stable Association", "nhrp.flag.d",
1174 FT_BOOLEAN, 16, NULL, 0x2000,
1175 "D bit", HFILL }
1177 { &hf_nhrp_flag_U1,
1178 { "Uniqueness Bit", "nhrp.flag.u",
1179 FT_BOOLEAN, 16, NULL, 0x1000,
1180 "U bit", HFILL }
1182 { &hf_nhrp_flag_U2,
1183 { "Uniqueness Bit", "nhrp.flag.u",
1184 FT_BOOLEAN, 16, NULL, 0x8000,
1185 "U bit", HFILL }
1187 { &hf_nhrp_flag_S,
1188 { "Stable Binding", "nhrp.flag.s",
1189 FT_BOOLEAN, 16, NULL, 0x0800,
1190 "S bit", HFILL }
1192 { &hf_nhrp_flag_NAT,
1193 { "Cisco NAT Supported", "nhrp.flag.nat",
1194 FT_BOOLEAN, 16, NULL, 0x0002,
1195 "NAT bit", HFILL }
1197 { &hf_nhrp_request_id,
1198 { "Request ID", "nhrp.reqid",
1199 FT_UINT32, BASE_HEX_DEC, NULL, 0x0,
1200 NULL, HFILL }
1202 { &hf_nhrp_src_nbma_addr,
1203 { "Source NBMA Address", "nhrp.src.nbma.addr",
1204 FT_IPv4, BASE_NONE, NULL, 0x0,
1205 NULL, HFILL }
1207 { &hf_nhrp_src_nbma_saddr,
1208 { "Source NBMA Sub Address", "nhrp.src.nbma.saddr",
1209 FT_BYTES, BASE_NONE, NULL, 0x0,
1210 NULL, HFILL }
1212 { &hf_nhrp_src_prot_addr,
1213 { "Source Protocol Address", "nhrp.src.prot.addr",
1214 FT_IPv4, BASE_NONE, NULL, 0x0,
1215 NULL, HFILL }
1217 { &hf_nhrp_dst_prot_addr,
1218 { "Destination Protocol Address", "nhrp.dst.prot.addr",
1219 FT_IPv4, BASE_NONE, NULL, 0x0,
1220 NULL, HFILL }
1223 { &hf_nhrp_code,
1224 { "Code", "nhrp.code",
1225 FT_UINT8, BASE_DEC, VALS(nhrp_cie_code_vals), 0x0,
1226 NULL, HFILL }
1228 { &hf_nhrp_prefix_len,
1229 { "Prefix Length", "nhrp.prefix",
1230 FT_UINT8, BASE_DEC, NULL, 0x0,
1231 NULL, HFILL }
1233 { &hf_nhrp_unused,
1234 { "Unused", "nhrp.unused",
1235 FT_UINT16, BASE_DEC, NULL, 0x0,
1236 NULL, HFILL }
1238 { &hf_nhrp_mtu,
1239 { "Max Transmission Unit", "nhrp.mtu",
1240 FT_UINT16, BASE_DEC, NULL, 0x0,
1241 NULL, HFILL }
1243 { &hf_nhrp_holding_time,
1244 { "Holding Time (s)", "nhrp.htime",
1245 FT_UINT16, BASE_DEC, NULL, 0x0,
1246 NULL, HFILL }
1248 { &hf_nhrp_cli_addr_tl,
1249 { "Client Address Type/Len", "nhrp.cli.addr_tl",
1250 FT_UINT8, BASE_DEC, NULL, 0x0,
1251 NULL, HFILL }
1253 { &hf_nhrp_cli_addr_tl_type,
1254 { "Type", "nhrp.cli.addr_tl.type",
1255 FT_UINT8, BASE_DEC, VALS(nhrp_shtl_type_vals), NHRP_SHTL_TYPE_MASK,
1256 NULL, HFILL }
1258 { &hf_nhrp_cli_addr_tl_len,
1259 { "Length", "nhrp.cli.addr_tl.len",
1260 FT_UINT8, BASE_DEC, NULL, NHRP_SHTL_LEN_MASK,
1261 NULL, HFILL }
1263 { &hf_nhrp_cli_saddr_tl,
1264 { "Client Sub Address Type/Len", "nhrp.cli.saddr_tl",
1265 FT_UINT8, BASE_DEC, NULL, 0x0,
1266 NULL, HFILL }
1268 { &hf_nhrp_cli_saddr_tl_type,
1269 { "Type", "nhrp.cli.saddr_tl.type",
1270 FT_UINT8, BASE_DEC, VALS(nhrp_shtl_type_vals), NHRP_SHTL_TYPE_MASK,
1271 NULL, HFILL }
1273 { &hf_nhrp_cli_saddr_tl_len,
1274 { "Length", "nhrp.cli.saddr_tl.len",
1275 FT_UINT8, BASE_DEC, NULL, NHRP_SHTL_LEN_MASK,
1276 NULL, HFILL }
1278 { &hf_nhrp_cli_prot_len,
1279 { "Client Protocol Length", "nhrp.prot.len",
1280 FT_UINT8, BASE_DEC, NULL, 0x0,
1281 NULL, HFILL }
1283 { &hf_nhrp_pref,
1284 { "CIE Preference Value", "nhrp.pref",
1285 FT_UINT8, BASE_DEC, NULL, 0x0,
1286 NULL, HFILL }
1288 { &hf_nhrp_client_nbma_addr,
1289 { "Client NBMA Address", "nhrp.client.nbma.addr",
1290 FT_IPv4, BASE_NONE, NULL, 0x0,
1291 NULL, HFILL }
1293 { &hf_nhrp_client_nbma_saddr,
1294 { "Client NBMA Sub Address", "nhrp.client.nbma.saddr",
1295 FT_BYTES, BASE_NONE, NULL, 0x0,
1296 NULL, HFILL }
1298 { &hf_nhrp_client_prot_addr,
1299 { "Client Protocol Address", "nhrp.client.prot.addr",
1300 FT_IPv4, BASE_NONE, NULL, 0x0,
1301 NULL, HFILL }
1304 { &hf_nhrp_ext_C,
1305 { "Compulsory Flag", "nhrp.ext.c",
1306 FT_BOOLEAN, 16, NULL, 0x8000,
1307 NULL, HFILL }
1309 { &hf_nhrp_ext_type,
1310 { "Extension Type", "nhrp.ext.type",
1311 FT_UINT16, BASE_HEX, VALS(ext_type_vals), 0x3FFF,
1312 NULL, HFILL }
1314 { &hf_nhrp_ext_len,
1315 { "Extension length", "nhrp.ext.len",
1316 FT_UINT16, BASE_DEC, NULL, 0x0,
1317 NULL, HFILL }
1319 #if 0
1320 { &hf_nhrp_ext_value,
1321 { "Extension Value", "nhrp.ext.val",
1322 FT_UINT_BYTES, BASE_NONE, NULL, 0x0,
1323 NULL, HFILL }
1325 #endif
1327 { &hf_nhrp_error_code,
1328 { "Error Code", "nhrp.err.code",
1329 FT_UINT16, BASE_DEC, VALS(nhrp_error_code_vals), 0x0,
1330 NULL, HFILL }
1332 { &hf_nhrp_error_offset,
1333 { "Error Offset", "nhrp.err.offset",
1334 FT_UINT16, BASE_DEC, NULL, 0x0,
1335 NULL, HFILL }
1337 #if 0
1338 { &hf_nhrp_error_packet,
1339 { "Errored Packet", "nhrp.err.pkt",
1340 FT_UINT_BYTES, BASE_NONE, NULL, 0x0,
1341 NULL, HFILL }
1343 #endif
1344 { &hf_nhrp_traffic_code,
1345 { "Traffic Code", "nhrp.tind.code",
1346 FT_UINT16, BASE_DEC, VALS(nhrp_traffic_code_vals), 0x0,
1347 NULL, HFILL }
1349 { &hf_nhrp_auth_ext_reserved,
1350 { "Reserved", "nhrp.auth_ext.reserved",
1351 FT_UINT16, BASE_DEC, NULL, 0x0,
1352 NULL, HFILL }
1354 { &hf_nhrp_auth_ext_spi,
1355 { "SPI", "nhrp.auth_ext.spi",
1356 FT_UINT16, BASE_DEC, NULL, 0x0,
1357 "Security Parameter Index", HFILL }
1359 { &hf_nhrp_auth_ext_src_addr,
1360 { "Source Address", "nhrp.auth_ext.src_addr",
1361 FT_IPv4, BASE_NONE, NULL, 0x0,
1362 NULL, HFILL }
1364 { &hf_nhrp_vendor_ext_id ,
1365 { "Vendor ID", "nhrp.vendor_ext.id",
1366 FT_UINT24, BASE_DEC, NULL, 0x0,
1367 NULL, HFILL }
1369 { &hf_nhrp_devcap_ext_srccap,
1370 { "Source Capabilities", "nhrp.devcap_ext.srccap",
1371 FT_UINT32, BASE_HEX, NULL, 0x0,
1372 NULL, HFILL }
1374 { &hf_nhrp_devcap_ext_srccap_V,
1375 { "VPN-aware", "nhrp.devcap_ext.srccap.V",
1376 FT_BOOLEAN, 32, NULL, 0x00000001,
1377 NULL, HFILL }
1379 { &hf_nhrp_devcap_ext_dstcap,
1380 { "Destination Capabilities", "nhrp.devcap_ext.dstcap",
1381 FT_UINT32, BASE_HEX, NULL, 0x0,
1382 NULL, HFILL }
1384 { &hf_nhrp_devcap_ext_dstcap_V,
1385 { "VPN-aware", "nhrp.devcap_ext.dstcap.V",
1386 FT_BOOLEAN, 32, NULL, 0x00000001,
1387 NULL, HFILL }
1389 { &hf_nhrp_unknown_ext_value,
1390 { "Extension Value", "nhrp.unknown_ext.value",
1391 FT_BYTES, BASE_NONE, NULL, 0x0,
1392 NULL, HFILL }
1395 /* Generated from convert_proto_tree_add_text.pl */
1396 { &hf_nhrp_protocol_type, { "Protocol Type (long form)", "nhrp.protocol_type", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1397 { &hf_nhrp_client_nbma_address_bytes, { "Client NBMA Address", "nhrp.client.nbma.addr_bytes", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1398 { &hf_nhrp_client_prot_addr_bytes, { "Client Protocol Address", "nhrp.client.prot.addr_bytes", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1399 { &hf_nhrp_src_nbma_addr_bytes, { "Source NBMA Address", "nhrp.src.nbma.addr_bytes", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1400 { &hf_nhrp_src_prot_addr_bytes, { "Source Protocol Address", "nhrp.src.prot.addr_bytes", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1401 { &hf_nhrp_dst_prot_addr_bytes, { "Destination Protocol Address", "nhrp.dst.prot.addr_byets", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1402 { &hf_nhrp_auth_ext_src_addr_bytes, { "Source Address", "nhrp.auth_ext.src_addr_bytes", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1403 { &hf_nhrp_auth_data, { "Data", "nhrp.auth_ext.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1404 { &hf_nhrp_vendor_ext_data, { "Data", "nhrp.vendor_ext.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1407 static int *ett[] = {
1408 &ett_nhrp,
1409 &ett_nhrp_hdr,
1410 &ett_nhrp_hdr_shtl,
1411 &ett_nhrp_hdr_sstl,
1412 &ett_nhrp_mand,
1413 &ett_nhrp_ext,
1414 &ett_nhrp_mand_flag,
1415 &ett_nhrp_cie,
1416 &ett_nhrp_cie_cli_addr_tl,
1417 &ett_nhrp_cie_cli_saddr_tl,
1418 &ett_nhrp_indication,
1419 &ett_nhrp_auth_ext,
1420 &ett_nhrp_vendor_ext,
1421 &ett_nhrp_devcap_ext,
1422 &ett_nhrp_devcap_ext_srccap,
1423 &ett_nhrp_devcap_ext_dstcap
1426 static ei_register_info ei[] = {
1427 { &ei_nhrp_hdr_pktsz, { "nhrp.hdr.pktsz.invalid", PI_MALFORMED, PI_ERROR, "Packet length is less than the fixed header length", EXPFILL }},
1428 { &ei_nhrp_hdr_extoff, { "nhrp.hdr.extoff.invalid", PI_MALFORMED, PI_ERROR, "Extension offset is less than the fixed header length or larger than the packet size", EXPFILL }},
1429 { &ei_nhrp_hdr_chksum, { "nhrp.hdr.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
1430 { &ei_nhrp_ext_not_allowed, { "nhrp.ext.not_allowed", PI_MALFORMED, PI_ERROR, "Extensions not allowed per RFC2332 section 5.2.7", EXPFILL }},
1431 { &ei_nhrp_ext_malformed, { "nhrp.ext.malformed", PI_MALFORMED, PI_ERROR, "Incomplete Authentication Extension", EXPFILL }},
1432 { &ei_nhrp_ext_extra, { "nhrp.ext.extra", PI_MALFORMED, PI_ERROR, "Superfluous data follows End Extension", EXPFILL }},
1435 module_t *nhrp_module;
1436 expert_module_t* expert_nhrp;
1438 proto_nhrp = proto_register_protocol("NBMA Next Hop Resolution Protocol", "NHRP", "nhrp");
1439 proto_register_field_array(proto_nhrp, hf, array_length(hf));
1440 proto_register_subtree_array(ett, array_length(ett));
1441 nhrp_module = prefs_register_protocol(proto_nhrp, NULL);
1442 prefs_register_bool_preference(nhrp_module, "auth_ext_has_addr",
1443 "Authentication Extension data contains the source address",
1444 "Whether the Authentication Extension data contains the source address. "
1445 "Some Cisco IOS implementations forgo this part of RFC2332.",
1446 &pref_auth_ext_has_addr);
1447 expert_nhrp = expert_register_protocol(proto_nhrp);
1448 expert_register_field_array(expert_nhrp, ei, array_length(ei));
1450 nhrp_handle = register_dissector("nhrp", dissect_nhrp, proto_nhrp);
1453 void
1454 proto_reg_handoff_nhrp(void)
1456 osinl_incl_subdissector_table = find_dissector_table("osinl.incl");
1457 osinl_excl_subdissector_table = find_dissector_table("osinl.excl");
1458 ethertype_subdissector_table = find_dissector_table("ethertype");
1460 dissector_add_uint("ip.proto", IP_PROTO_NARP, nhrp_handle);
1461 dissector_add_uint("gre.proto", GRE_NHRP, nhrp_handle);
1462 dissector_add_uint("llc.iana_pid", IANA_PID_MARS_NHRP_CONTROL, nhrp_handle);
1466 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1468 * Local variables:
1469 * c-basic-offset: 4
1470 * tab-width: 8
1471 * indent-tabs-mode: nil
1472 * End:
1474 * vi: set shiftwidth=4 tabstop=8 expandtab:
1475 * :indentSize=4:tabSize=8:noTabs=true: