HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-nhrp.c
blobec8d85858051ab1f8b49d75b48584f60a96f020a
1 /* packet-nhrp.c
2 * Routines for NBMA Next Hop Resolution Protocol
3 * RFC 2332 plus Cisco extensions (documented where?), plus extensions from:
4 * RFC 2520: NHRP with Mobile NHCs
5 * RFC 2735: NHRP Support for Virtual Private Networks
7 * $Id$
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 * CIE decoding for extensions and Cisco 12.4T extensions
28 * added by Timo Teras <timo.teras@iki.fi>
31 #include "config.h"
33 #include <string.h>
35 #include <glib.h>
37 #include <epan/packet.h>
38 #include <epan/addr_resolv.h>
39 #include <epan/expert.h>
40 #include <epan/etypes.h>
41 #include <epan/ipproto.h>
42 #include <epan/greproto.h>
43 #include <epan/nlpid.h>
44 #include <epan/oui.h>
45 #include <epan/afn.h>
46 #include <epan/in_cksum.h>
47 #include <epan/iana_snap_pid.h>
48 #include <epan/dissectors/packet-llc.h>
49 #include "packet-nhrp.h"
51 /* forward reference */
52 static void _dissect_nhrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
53 gboolean nested, gboolean codeinfo);
55 static int proto_nhrp = -1;
56 static int hf_nhrp_hdr_afn = -1;
57 static int hf_nhrp_hdr_pro_type = -1;
58 static int hf_nhrp_hdr_pro_snap_oui = -1;
59 static int hf_nhrp_hdr_pro_snap_pid = -1;
60 static int hf_nhrp_hdr_hopcnt = -1;
61 static int hf_nhrp_hdr_pktsz = -1;
62 static int hf_nhrp_hdr_chksum = -1;
63 static int hf_nhrp_hdr_extoff = -1;
64 static int hf_nhrp_hdr_version = -1;
65 static int hf_nhrp_hdr_op_type = -1;
66 static int hf_nhrp_hdr_shtl = -1;
67 static int hf_nhrp_hdr_shtl_type = -1;
68 static int hf_nhrp_hdr_shtl_len = -1;
69 static int hf_nhrp_hdr_sstl = -1;
70 static int hf_nhrp_hdr_sstl_type = -1;
71 static int hf_nhrp_hdr_sstl_len = -1;
73 static int hf_nhrp_src_proto_len = -1;
74 static int hf_nhrp_dst_proto_len = -1;
75 static int hf_nhrp_flags = -1;
76 static int hf_nhrp_flag_Q = -1;
77 static int hf_nhrp_flag_N = -1;
78 static int hf_nhrp_flag_A = -1;
79 static int hf_nhrp_flag_D = -1;
80 static int hf_nhrp_flag_U1 = -1;
81 static int hf_nhrp_flag_U2 = -1;
82 static int hf_nhrp_flag_S = -1;
83 static int hf_nhrp_flag_NAT = -1;
84 static int hf_nhrp_src_nbma_addr = -1;
86 /* static int hf_nhrp_src_nbma_saddr = -1; */ /* TBD: Not used */
87 static int hf_nhrp_src_prot_addr = -1;
88 static int hf_nhrp_dst_prot_addr = -1;
89 static int hf_nhrp_request_id = -1;
91 static int hf_nhrp_code = -1;
92 static int hf_nhrp_prefix_len = -1;
93 static int hf_nhrp_unused = -1;
94 static int hf_nhrp_mtu = -1;
95 static int hf_nhrp_holding_time = -1;
96 static int hf_nhrp_cli_addr_tl = -1;
97 static int hf_nhrp_cli_addr_tl_type = -1;
98 static int hf_nhrp_cli_addr_tl_len = -1;
99 static int hf_nhrp_cli_saddr_tl = -1;
100 static int hf_nhrp_cli_saddr_tl_type = -1;
101 static int hf_nhrp_cli_saddr_tl_len = -1;
102 static int hf_nhrp_cli_prot_len = -1;
103 static int hf_nhrp_pref = -1;
104 static int hf_nhrp_client_nbma_addr = -1;
105 /* static int hf_nhrp_client_nbma_saddr = -1; */ /* TBD: Not used */
106 static int hf_nhrp_client_prot_addr = -1;
107 static int hf_nhrp_ext_C = -1;
108 static int hf_nhrp_ext_type = -1;
109 static int hf_nhrp_ext_len = -1;
110 /* static int hf_nhrp_ext_value = -1; */ /* TBD: Not used */
111 static int hf_nhrp_error_code = -1;
112 static int hf_nhrp_error_offset = -1;
113 /* static int hf_nhrp_error_packet = -1; */ /* TBD: Not used */
115 static int hf_nhrp_auth_ext_reserved = -1;
116 static int hf_nhrp_auth_ext_spi = -1;
117 static int hf_nhrp_auth_ext_src_addr = -1;
118 static int hf_nhrp_vendor_ext_id = -1;
119 static int hf_nhrp_devcap_ext_srccap = -1;
120 static int hf_nhrp_devcap_ext_srccap_V = -1;
121 static int hf_nhrp_devcap_ext_dstcap = -1;
122 static int hf_nhrp_devcap_ext_dstcap_V = -1;
123 static int hf_nhrp_unknown_ext_value = -1;
125 static gint ett_nhrp = -1;
126 static gint ett_nhrp_hdr = -1;
127 static gint ett_nhrp_hdr_shtl = -1;
128 static gint ett_nhrp_hdr_sstl = -1;
129 static gint ett_nhrp_mand = -1;
130 static gint ett_nhrp_ext = -1;
131 static gint ett_nhrp_mand_flag = -1;
132 static gint ett_nhrp_cie = -1;
133 static gint ett_nhrp_cie_cli_addr_tl = -1;
134 static gint ett_nhrp_cie_cli_saddr_tl = -1;
135 static gint ett_nhrp_indication = -1;
136 static gint ett_nhrp_auth_ext = -1;
137 static gint ett_nhrp_vendor_ext = -1;
138 static gint ett_nhrp_devcap_ext = -1;
139 static gint ett_nhrp_devcap_ext_srccap = -1;
140 static gint ett_nhrp_devcap_ext_dstcap = -1;
142 static expert_field ei_nhrp_ext_not_allowed = EI_INIT;
143 static expert_field ei_nhrp_hdr_extoff = EI_INIT;
144 static expert_field ei_nhrp_ext_malformed = EI_INIT;
145 static expert_field ei_nhrp_ext_extra = EI_INIT;
147 /* NHRP Packet Types */
148 #define NHRP_RESOLUTION_REQ 1
149 #define NHRP_RESOLUTION_REPLY 2
150 #define NHRP_REGISTRATION_REQ 3
151 #define NHRP_REGISTRATION_REPLY 4
152 #define NHRP_PURGE_REQ 5
153 #define NHRP_PURGE_REPLY 6
154 #define NHRP_ERROR_INDICATION 7
155 #define NHRP_TRAFFIC_INDICATION 8
157 /* NHRP Extension Types */
158 #define NHRP_EXT_NULL 0 /* End of Extension */
159 #define NHRP_EXT_RESP_ADDR 3 /* Responder Address Extension */
160 #define NHRP_EXT_FWD_RECORD 4 /* NHRP Forward Transit NHS Record Extension */
161 #define NHRP_EXT_REV_RECORD 5 /* NHRP Reverse Transit NHS Record Extension */
162 #define NHRP_EXT_AUTH 7 /* NHRP Authentication Extension */
163 #define NHRP_EXT_VENDOR_PRIV 8 /* NHRP Vendor Private Extension */
164 #define NHRP_EXT_NAT_ADDRESS 9 /* Cisco NAT Address Extension */
165 #define NHRP_EXT_DEV_CAPABILITIES 9 /* RFC 2735: Device Capabilities Extension */
166 #define NHRP_EXT_MOBILE_AUTH 10 /* RFC 2520: NHRP Mobile NHC Authentication Extension */
168 /* NHRP Error Codes */
169 #define NHRP_ERR_UNRECOGNIZED_EXT 0x0001
170 #define NHRP_ERR_NHRP_LOOP_DETECT 0x0003
171 #define NHRP_ERR_PROT_ADDR_UNREACHABLE 0x0006
172 #define NHRP_ERR_PROT_ERROR 0x0007
173 #define NHRP_ERR_SDU_SIZE_EXCEEDED 0x0008
174 #define NHRP_ERR_INV_EXT 0x0009
175 #define NHRP_ERR_INV_RESOLUTION_REPLY 0x000a
176 #define NHRP_ERR_AUTH_FAILURE 0x000b
177 #define NHRP_ERR_HOP_COUNT_EXCEEDED 0x000f
178 #define NHRP_ERR_VPN_MISMATCH 0x0010 /* RFC 2735 */
179 #define NHRP_ERR_VPN_UNSUPPORTED 0x0011 /* RFC 2735 */
181 /* NHRP CIE codes */
182 #define NHRP_CODE_SUCCESS 0x00
183 #define NHRP_CODE_ADMIN_PROHIBITED 0x04
184 #define NHRP_CODE_INSUFFICIENT_RESOURCES 0x05
185 #define NHRP_CODE_NO_BINDING_EXISTS 0x0c
186 #define NHRP_CODE_NON_UNIQUE_BINDING 0x0d
187 #define NHRP_CODE_ALREADY_REGISTERED 0x0e
189 /* NHRP Subnetwork layer address type/length */
190 #define NHRP_SHTL_TYPE_MASK 0x40
191 #define NHRP_SHTL_LEN_MASK 0x3F
192 #define NHRP_SHTL_TYPE(val) (((val) & (NHRP_SHTL_TYPE_MASK)) >> 6)
193 #define NHRP_SHTL_LEN(val) ((val) & (NHRP_SHTL_LEN_MASK))
195 #define NHRP_SHTL_TYPE_NSAP 0
196 #define NHRP_SHTL_TYPE_E164 1
198 static const value_string nhrp_shtl_type_vals[] = {
199 { NHRP_SHTL_TYPE_NSAP, "NSAP format" },
200 { NHRP_SHTL_TYPE_E164, "Native E.164 format" },
201 { 0, NULL }
204 static const value_string nhrp_op_type_vals[] = {
205 { NHRP_RESOLUTION_REQ, "NHRP Resolution Request" },
206 { NHRP_RESOLUTION_REPLY, "NHRP Resolution Reply" },
207 { NHRP_REGISTRATION_REQ, "NHRP Registration Request" },
208 { NHRP_REGISTRATION_REPLY, "NHRP Registration Reply" },
209 { NHRP_PURGE_REQ, "NHRP Purge Request" },
210 { NHRP_PURGE_REPLY, "NHRP Purge Reply" },
211 { NHRP_ERROR_INDICATION, "NHRP Error Indication" },
212 { NHRP_TRAFFIC_INDICATION, "NHRP Traffic Indication" },
213 { 0, NULL }
216 static const value_string ext_type_vals[] = {
217 { NHRP_EXT_NULL, "End of Extension" },
218 { NHRP_EXT_RESP_ADDR, "Responder Address Extension" },
219 { NHRP_EXT_FWD_RECORD, "Forward Transit NHS Record Extension" },
220 { NHRP_EXT_REV_RECORD, "Reverse Transit NHS Record Extension" },
221 { NHRP_EXT_AUTH, "NHRP Authentication Extension" },
222 { NHRP_EXT_VENDOR_PRIV, "NHRP Vendor Private Extension" },
223 { NHRP_EXT_NAT_ADDRESS, "Cisco NAT Address Extension" },
224 #if 0 /* Dup (which is handled in the code) */
225 { NHRP_EXT_DEV_CAPABILITIES,"Device Capabilities Extension" },
226 #endif
227 { NHRP_EXT_MOBILE_AUTH, "Mobile NHC Authentication Extension" },
228 { 0, NULL }
231 static const value_string nhrp_error_code_vals[] = {
232 { NHRP_ERR_UNRECOGNIZED_EXT, "Unrecognized Extension" },
233 { NHRP_ERR_NHRP_LOOP_DETECT, "NHRP Loop Detected" },
234 { NHRP_ERR_PROT_ADDR_UNREACHABLE, "Protocol Address Unreachable" },
235 { NHRP_ERR_PROT_ERROR, "Protocol Error" },
236 { NHRP_ERR_SDU_SIZE_EXCEEDED, "NHRP SDU Size Exceeded" },
237 { NHRP_ERR_INV_EXT, "Invalid Extension" },
238 { NHRP_ERR_INV_RESOLUTION_REPLY, "Invalid NHRP Resolution Reply Received" },
239 { NHRP_ERR_AUTH_FAILURE, "Authentication Failure" },
240 { NHRP_ERR_HOP_COUNT_EXCEEDED, "Hop Count Exceeded" },
241 { NHRP_ERR_VPN_MISMATCH, "VPN Mismatch" },
242 { NHRP_ERR_VPN_UNSUPPORTED, "VPN Unsupported" },
243 { 0, NULL }
246 static const value_string nhrp_cie_code_vals[] = {
247 { NHRP_CODE_SUCCESS, "Success" },
248 { NHRP_CODE_ADMIN_PROHIBITED, "Administratively Prohibited" },
249 { NHRP_CODE_INSUFFICIENT_RESOURCES, "Insufficient Resources" },
250 { NHRP_CODE_NO_BINDING_EXISTS, "No Interworking Layer Address to NBMA Address Binding Exists" },
251 { NHRP_CODE_NON_UNIQUE_BINDING, "Binding Exists But Is Not Unique" },
252 { NHRP_CODE_ALREADY_REGISTERED, "Unique Internetworking Layer Address Already Registered" },
253 { 0, NULL }
256 static dissector_table_t osinl_incl_subdissector_table;
257 static dissector_table_t osinl_excl_subdissector_table;
258 static dissector_table_t ethertype_subdissector_table;
260 static dissector_handle_t data_handle;
262 typedef struct _e_nhrp {
263 guint16 ar_afn;
264 guint16 ar_pro_type;
265 guint32 ar_pro_type_oui;
266 guint16 ar_pro_type_pid;
267 guint8 ar_hopCnt;
268 guint16 ar_pktsz;
269 guint16 ar_chksum;
270 guint16 ar_extoff;
271 guint8 ar_op_version;
272 guint8 ar_op_type;
273 guint8 ar_shtl;
274 guint8 ar_sstl;
275 } e_nhrp_hdr;
277 static guint16 nhrp_checksum(const guint8 *ptr, int len)
279 vec_t cksum_vec[1];
281 cksum_vec[0].ptr = ptr;
282 cksum_vec[0].len = len;
283 return in_cksum(&cksum_vec[0], 1);
286 void dissect_nhrp_hdr(tvbuff_t *tvb,
287 packet_info *pinfo,
288 proto_tree *tree,
289 gint *pOffset,
290 gint *pMandLen,
291 gint *pExtLen,
292 oui_info_t **pOuiInfo,
293 e_nhrp_hdr *hdr)
295 gint offset = *pOffset;
296 const gchar *pro_type_str;
297 guint total_len = tvb_reported_length(tvb);
298 guint16 ipcsum, rx_chksum;
300 proto_item *nhrp_tree_item;
301 proto_tree *nhrp_tree;
302 proto_item *shtl_tree_item;
303 proto_tree *shtl_tree;
304 proto_item *sstl_tree_item;
305 proto_tree *sstl_tree;
306 proto_item *ti;
308 nhrp_tree_item = proto_tree_add_text(tree, tvb, offset, 20, "NHRP Fixed Header");
309 nhrp_tree = proto_item_add_subtree(nhrp_tree_item, ett_nhrp_hdr);
311 hdr->ar_pktsz = tvb_get_ntohs(tvb, 10);
312 if (total_len > hdr->ar_pktsz) {
313 total_len = hdr->ar_pktsz;
316 hdr->ar_afn = tvb_get_ntohs(tvb, offset);
317 proto_tree_add_item(nhrp_tree, hf_nhrp_hdr_afn, tvb, offset, 2, ENC_BIG_ENDIAN);
318 offset += 2;
320 hdr->ar_pro_type = tvb_get_ntohs(tvb, offset);
321 if (hdr->ar_pro_type <= 0xFF) {
322 /* It's an NLPID */
323 pro_type_str = val_to_str_const(hdr->ar_pro_type, nlpid_vals,
324 "Unknown NLPID");
325 } else if (hdr->ar_pro_type <= 0x3FF) {
326 /* Reserved for future use by the IETF */
327 pro_type_str = "Reserved for future use by the IETF";
328 } else if (hdr->ar_pro_type <= 0x04FF) {
329 /* Allocated for use by the ATM Forum */
330 pro_type_str = "Allocated for use by the ATM Forum";
331 } else if (hdr->ar_pro_type <= 0x05FF) {
332 /* Experimental/Local use */
333 pro_type_str = "Experimental/Local use";
334 } else {
335 pro_type_str = val_to_str_const(hdr->ar_pro_type, etype_vals,
336 "Unknown Ethertype");
338 proto_tree_add_uint_format_value(nhrp_tree, hf_nhrp_hdr_pro_type, tvb, offset, 2,
339 hdr->ar_pro_type, "%s (0x%04x)",
340 pro_type_str, hdr->ar_pro_type);
341 offset += 2;
343 if (hdr->ar_pro_type == NLPID_SNAP) {
345 * The long form protocol type is a SNAP OUI and PID.
347 hdr->ar_pro_type_oui = tvb_get_ntoh24(tvb, offset);
348 proto_tree_add_uint(nhrp_tree, hf_nhrp_hdr_pro_snap_oui,
349 tvb, offset, 3, hdr->ar_pro_type_oui);
350 offset += 3;
352 hdr->ar_pro_type_pid = tvb_get_ntohs(tvb, offset);
353 *pOuiInfo = get_snap_oui_info(hdr->ar_pro_type_oui);
354 if (*pOuiInfo != NULL) {
355 proto_tree_add_uint(nhrp_tree,
356 *(*pOuiInfo)->field_info->p_id,
357 tvb, offset, 2, hdr->ar_pro_type_pid);
358 } else {
359 proto_tree_add_uint(nhrp_tree, hf_nhrp_hdr_pro_snap_pid,
360 tvb, offset, 2, hdr->ar_pro_type_pid);
362 } else {
364 * XXX - we should check that this is zero, as RFC 2332
365 * says it should be zero.
367 proto_tree_add_text(nhrp_tree, tvb, offset, 5,
368 "Protocol Type (long form): %s",
369 tvb_bytes_to_str(tvb, offset, 5));
370 offset += 5;
373 proto_tree_add_item(nhrp_tree, hf_nhrp_hdr_hopcnt, tvb, offset, 1, ENC_BIG_ENDIAN);
374 offset += 1;
376 proto_tree_add_item(nhrp_tree, hf_nhrp_hdr_pktsz, tvb, offset, 2, ENC_BIG_ENDIAN);
377 offset += 2;
379 rx_chksum = tvb_get_ntohs(tvb, offset);
380 if (tvb_bytes_exist(tvb, 0, total_len)) {
381 ipcsum = nhrp_checksum(tvb_get_ptr(tvb, 0, total_len),
382 total_len);
383 if (ipcsum == 0) {
384 proto_tree_add_uint_format_value(nhrp_tree, hf_nhrp_hdr_chksum, tvb, offset, 2, rx_chksum,
385 "0x%04x [correct]", rx_chksum);
386 } else {
387 proto_tree_add_uint_format_value(nhrp_tree, hf_nhrp_hdr_chksum, tvb, offset, 2, rx_chksum,
388 "0x%04x [incorrect, should be 0x%04x]", rx_chksum,
389 in_cksum_shouldbe(rx_chksum, ipcsum));
391 } else {
392 proto_tree_add_uint_format_value(nhrp_tree, hf_nhrp_hdr_chksum, tvb, offset, 2, rx_chksum,
393 "0x%04x [not all data available]", rx_chksum);
395 offset += 2;
397 hdr->ar_extoff = tvb_get_ntohs(tvb, offset);
398 ti = proto_tree_add_item(nhrp_tree, hf_nhrp_hdr_extoff, tvb, offset, 2, ENC_BIG_ENDIAN);
399 if (hdr->ar_extoff != 0 && hdr->ar_extoff < 20) {
400 expert_add_info(pinfo, ti, &ei_nhrp_hdr_extoff);
402 offset += 2;
404 hdr->ar_op_version = tvb_get_guint8(tvb, offset);
405 proto_tree_add_uint_format_value(nhrp_tree, hf_nhrp_hdr_version, tvb, offset, 1,
406 hdr->ar_op_version, "%u (%s)", hdr->ar_op_version,
407 (hdr->ar_op_version == 1) ? "NHRP - rfc2332" : "Unknown");
408 offset += 1;
409 proto_tree_add_item(nhrp_tree, hf_nhrp_hdr_op_type, tvb, offset, 1, ENC_BIG_ENDIAN);
410 offset += 1;
412 hdr->ar_shtl = tvb_get_guint8(tvb, offset);
413 shtl_tree_item = proto_tree_add_uint_format_value(nhrp_tree, hf_nhrp_hdr_shtl,
414 tvb, offset, 1, hdr->ar_shtl, "%s/%u",
415 val_to_str_const(NHRP_SHTL_TYPE(hdr->ar_shtl), nhrp_shtl_type_vals, "Unknown Type"),
416 NHRP_SHTL_LEN(hdr->ar_shtl));
417 shtl_tree = proto_item_add_subtree(shtl_tree_item, ett_nhrp_hdr_shtl);
418 proto_tree_add_item(shtl_tree, hf_nhrp_hdr_shtl_type, tvb, offset, 1, ENC_BIG_ENDIAN);
419 proto_tree_add_item(shtl_tree, hf_nhrp_hdr_shtl_len, tvb, offset, 1, ENC_BIG_ENDIAN);
420 offset += 1;
422 hdr->ar_sstl = tvb_get_guint8(tvb, offset);
423 sstl_tree_item = proto_tree_add_uint_format_value(nhrp_tree, hf_nhrp_hdr_sstl,
424 tvb, offset, 1, hdr->ar_sstl, "%s/%u",
425 val_to_str_const(NHRP_SHTL_TYPE(hdr->ar_sstl), nhrp_shtl_type_vals, "Unknown Type"),
426 NHRP_SHTL_LEN(hdr->ar_sstl));
427 sstl_tree = proto_item_add_subtree(sstl_tree_item, ett_nhrp_hdr_sstl);
428 proto_tree_add_item(sstl_tree, hf_nhrp_hdr_sstl_type, tvb, offset, 1, ENC_BIG_ENDIAN);
429 proto_tree_add_item(sstl_tree, hf_nhrp_hdr_sstl_len, tvb, offset, 1, ENC_BIG_ENDIAN);
430 offset += 1;
432 *pOffset = offset;
433 if (hdr->ar_extoff != 0) {
434 if (hdr->ar_extoff >= 20) {
435 *pMandLen = hdr->ar_extoff - 20;
436 *pExtLen = total_len - hdr->ar_extoff;
437 } else {
438 /* Error */
439 *pMandLen = 0;
440 *pExtLen = 0;
443 else {
444 if (total_len >= 20)
445 *pMandLen = total_len - 20;
446 else {
447 /* "Can't happen" - we would have thrown an exception */
448 *pMandLen = 0;
450 *pExtLen = 0;
454 void dissect_cie_list(tvbuff_t *tvb,
455 packet_info *pinfo,
456 proto_tree *tree,
457 gint offset,
458 gint cieEnd,
459 e_nhrp_hdr *hdr,
460 gint isReq,
461 gboolean codeinfo)
463 proto_item *cli_addr_tree_item;
464 proto_tree *cli_addr_tree;
465 proto_item *cli_saddr_tree_item;
466 proto_tree *cli_saddr_tree;
467 guint8 val;
469 while ((offset + 12) <= cieEnd) {
470 guint cli_addr_len = tvb_get_guint8(tvb, offset + 8);
471 guint cli_saddr_len = tvb_get_guint8(tvb, offset + 9);
472 guint cli_prot_len = tvb_get_guint8(tvb, offset + 10);
473 guint cie_len = 12 + cli_addr_len + cli_saddr_len + cli_prot_len;
474 proto_item *cie_tree_item = proto_tree_add_text(tree, tvb, offset, cie_len, "Client Information Entry");
475 proto_tree *cie_tree = proto_item_add_subtree(cie_tree_item, ett_nhrp_cie);
477 if (isReq) {
478 proto_tree_add_item(cie_tree, hf_nhrp_code, tvb, offset, 1, ENC_BIG_ENDIAN);
480 else {
481 guint8 code = tvb_get_guint8(tvb, offset);
482 if ( codeinfo ) {
483 col_append_fstr(pinfo->cinfo, COL_INFO, ", Code=%s",
484 val_to_str(code, nhrp_cie_code_vals, "Unknown (%u)"));
486 proto_tree_add_text(cie_tree, tvb, offset, 1, "Code: %s",
487 val_to_str(code, nhrp_cie_code_vals, "Unknown (%u)"));
489 offset += 1;
491 proto_tree_add_item(cie_tree, hf_nhrp_prefix_len, tvb, offset, 1, ENC_BIG_ENDIAN);
492 offset += 1;
494 proto_tree_add_item(cie_tree, hf_nhrp_unused, tvb, offset, 2, ENC_BIG_ENDIAN);
495 offset += 2;
497 proto_tree_add_item(cie_tree, hf_nhrp_mtu, tvb, offset, 2, ENC_BIG_ENDIAN);
498 offset += 2;
500 proto_tree_add_item(cie_tree, hf_nhrp_holding_time, tvb, offset, 2, ENC_BIG_ENDIAN);
501 offset += 2;
503 val = tvb_get_guint8(tvb, offset);
504 cli_addr_tree_item = proto_tree_add_uint_format_value(cie_tree,
505 hf_nhrp_cli_addr_tl, tvb, offset, 1, val, "%s/%u",
506 val_to_str_const(NHRP_SHTL_TYPE(val), nhrp_shtl_type_vals, "Unknown Type"),
507 NHRP_SHTL_LEN(val));
508 cli_addr_tree = proto_item_add_subtree(cli_addr_tree_item, ett_nhrp_cie_cli_addr_tl);
509 proto_tree_add_item(cli_addr_tree, hf_nhrp_cli_addr_tl_type, tvb, offset, 1, ENC_BIG_ENDIAN);
510 proto_tree_add_item(cli_addr_tree, hf_nhrp_cli_addr_tl_len, tvb, offset, 1, ENC_BIG_ENDIAN);
511 offset += 1;
513 val = tvb_get_guint8(tvb, offset);
514 cli_saddr_tree_item = proto_tree_add_uint_format_value(cie_tree,
515 hf_nhrp_cli_saddr_tl, tvb, offset, 1, val, "%s/%u",
516 val_to_str_const(NHRP_SHTL_TYPE(val), nhrp_shtl_type_vals, "Unknown Type"),
517 NHRP_SHTL_LEN(val));
518 cli_saddr_tree = proto_item_add_subtree(cli_saddr_tree_item, ett_nhrp_cie_cli_saddr_tl);
519 proto_tree_add_item(cli_saddr_tree, hf_nhrp_cli_saddr_tl_type, tvb, offset, 1, ENC_BIG_ENDIAN);
520 proto_tree_add_item(cli_saddr_tree, hf_nhrp_cli_saddr_tl_len, tvb, offset, 1, ENC_BIG_ENDIAN);
521 offset += 1;
523 proto_tree_add_item(cie_tree, hf_nhrp_cli_prot_len, tvb, offset, 1, ENC_BIG_ENDIAN);
524 offset += 1;
526 proto_tree_add_item(cie_tree, hf_nhrp_pref, tvb, offset, 1, ENC_BIG_ENDIAN);
527 offset += 1;
529 if (cli_addr_len) {
530 switch (hdr->ar_afn) {
532 case AFNUM_INET:
533 if (cli_addr_len == 4)
534 proto_tree_add_item(cie_tree, hf_nhrp_client_nbma_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
535 else {
536 proto_tree_add_text(cie_tree, tvb, offset, cli_addr_len,
537 "Client NBMA Address: %s",
538 tvb_bytes_to_str(tvb, offset, cli_addr_len));
540 break;
542 default:
543 proto_tree_add_text(cie_tree, tvb, offset, cli_addr_len,
544 "Client NBMA Address: %s",
545 tvb_bytes_to_str(tvb, offset, cli_addr_len));
546 break;
548 offset += cli_addr_len;
551 if (cli_saddr_len) {
552 proto_tree_add_text(cie_tree, tvb, offset, cli_saddr_len,
553 "Client NBMA Sub Address: %s",
554 tvb_bytes_to_str(tvb, offset, cli_saddr_len));
557 if (cli_prot_len) {
558 if (cli_prot_len == 4)
559 proto_tree_add_item(cie_tree, hf_nhrp_client_prot_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
560 else {
561 proto_tree_add_text(cie_tree, tvb, offset, cli_prot_len,
562 "Client Protocol Address: %s",
563 tvb_bytes_to_str(tvb, offset, cli_prot_len));
565 offset += cli_prot_len;
570 void dissect_nhrp_mand(tvbuff_t *tvb,
571 packet_info *pinfo,
572 proto_tree *tree,
573 gint *pOffset,
574 gint mandLen,
575 oui_info_t *oui_info,
576 e_nhrp_hdr *hdr,
577 guint *srcLen,
578 gboolean codeinfo)
580 gint offset = *pOffset;
581 gint mandEnd = offset + mandLen;
582 guint8 ssl, shl;
583 guint16 flags;
584 guint dstLen;
585 gboolean isReq = FALSE;
586 gboolean isErr = FALSE;
587 gboolean isInd = FALSE;
589 proto_item *nhrp_tree_item;
590 proto_tree *nhrp_tree;
592 tvb_ensure_bytes_exist(tvb, offset, mandLen);
594 switch (hdr->ar_op_type)
596 case NHRP_RESOLUTION_REPLY:
597 case NHRP_REGISTRATION_REPLY:
598 case NHRP_PURGE_REPLY:
599 break;
600 case NHRP_RESOLUTION_REQ:
601 case NHRP_REGISTRATION_REQ:
602 case NHRP_PURGE_REQ:
603 isReq = TRUE;
604 break;
605 case NHRP_ERROR_INDICATION: /* This needs special treatment */
606 isErr = TRUE;
607 isInd = TRUE;
608 break;
609 case NHRP_TRAFFIC_INDICATION:
610 isInd = TRUE;
611 break;
613 nhrp_tree_item = proto_tree_add_text(tree, tvb, offset, mandLen, "NHRP Mandatory Part");
614 nhrp_tree = proto_item_add_subtree(nhrp_tree_item, ett_nhrp_mand);
616 *srcLen = tvb_get_guint8(tvb, offset);
617 proto_tree_add_item(nhrp_tree, hf_nhrp_src_proto_len, tvb, offset, 1, ENC_BIG_ENDIAN);
618 offset += 1;
620 dstLen = tvb_get_guint8(tvb, offset);
621 proto_tree_add_item(nhrp_tree, hf_nhrp_dst_proto_len, tvb, offset, 1, ENC_BIG_ENDIAN);
622 offset += 1;
624 if (!isInd) {
625 proto_item *flag_item;
626 proto_tree *flag_tree;
627 flags = tvb_get_ntohs(tvb, offset);
628 flag_item = proto_tree_add_uint(nhrp_tree, hf_nhrp_flags, tvb, offset, 2, flags);
629 flag_tree = proto_item_add_subtree(flag_item, ett_nhrp_mand_flag);
631 switch (hdr->ar_op_type)
633 case NHRP_RESOLUTION_REQ:
634 case NHRP_RESOLUTION_REPLY:
635 proto_tree_add_boolean(flag_tree, hf_nhrp_flag_Q, tvb, offset, 2, flags);
636 proto_tree_add_boolean(flag_tree, hf_nhrp_flag_A, tvb, offset, 2, flags);
637 proto_tree_add_boolean(flag_tree, hf_nhrp_flag_D, tvb, offset, 2, flags);
638 proto_tree_add_boolean(flag_tree, hf_nhrp_flag_U1, tvb, offset, 2, flags);
639 proto_tree_add_boolean(flag_tree, hf_nhrp_flag_S, tvb, offset, 2, flags);
640 break;
641 case NHRP_REGISTRATION_REQ:
642 case NHRP_REGISTRATION_REPLY:
643 proto_tree_add_boolean(flag_tree, hf_nhrp_flag_U2, tvb, offset, 2, flags);
644 break;
646 case NHRP_PURGE_REQ:
647 case NHRP_PURGE_REPLY:
648 proto_tree_add_boolean(flag_tree, hf_nhrp_flag_N, tvb, offset, 2, flags);
649 break;
651 proto_tree_add_boolean(flag_tree, hf_nhrp_flag_NAT, tvb, offset, 2, flags);
653 offset += 2;
655 col_append_fstr(pinfo->cinfo, COL_INFO, ", ID=%u", tvb_get_ntohl(tvb, offset));
656 proto_tree_add_item(nhrp_tree, hf_nhrp_request_id, tvb, offset, 4, ENC_BIG_ENDIAN);
657 offset += 4;
659 else if (isErr) {
660 offset += 2;
662 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
663 val_to_str(tvb_get_ntohs(tvb, offset), nhrp_error_code_vals, "Unknown Error (%u)"));
664 proto_tree_add_item(nhrp_tree, hf_nhrp_error_code, tvb, offset, 2, ENC_BIG_ENDIAN);
665 offset += 2;
667 proto_tree_add_item(nhrp_tree, hf_nhrp_error_offset, tvb, offset, 2, ENC_BIG_ENDIAN);
668 offset += 2;
670 else {
671 offset += 6;
674 shl = NHRP_SHTL_LEN(hdr->ar_shtl);
675 if (shl) {
676 switch (hdr->ar_afn) {
678 case AFNUM_INET:
679 if (shl == 4)
680 proto_tree_add_item(nhrp_tree, hf_nhrp_src_nbma_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
681 else {
682 proto_tree_add_text(nhrp_tree, tvb, offset, shl,
683 "Source NBMA Address: %s",
684 tvb_bytes_to_str(tvb, offset, shl));
686 break;
688 default:
689 proto_tree_add_text(nhrp_tree, tvb, offset, shl,
690 "Source NBMA Address: %s",
691 tvb_bytes_to_str(tvb, offset, shl));
692 break;
694 offset += shl;
697 ssl = NHRP_SHTL_LEN(hdr->ar_sstl);
698 if (ssl) {
699 proto_tree_add_text(nhrp_tree, tvb, offset, ssl,
700 "Source NBMA Sub Address: %s",
701 tvb_bytes_to_str(tvb, offset, ssl));
702 offset += ssl;
705 if (*srcLen == 4) {
706 proto_tree_add_item(nhrp_tree, hf_nhrp_src_prot_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
707 offset += 4;
709 else if (*srcLen) {
710 proto_tree_add_text(nhrp_tree, tvb, offset, *srcLen,
711 "Source Protocol Address: %s",
712 tvb_bytes_to_str(tvb, offset, *srcLen));
713 offset += *srcLen;
716 if (dstLen == 4) {
717 proto_tree_add_item(nhrp_tree, hf_nhrp_dst_prot_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
718 offset += 4;
720 else if (dstLen) {
721 proto_tree_add_text(nhrp_tree, tvb, offset, dstLen,
722 "Destination Protocol Address: %s",
723 tvb_bytes_to_str(tvb, offset, dstLen));
724 offset += dstLen;
727 if (isInd) {
728 gboolean save_in_error_pkt;
729 gint pkt_len = mandEnd - offset;
730 proto_item *ind_tree_item = proto_tree_add_text(tree, tvb, offset, pkt_len, "Packet Causing Indication");
731 proto_tree *ind_tree = proto_item_add_subtree(ind_tree_item, ett_nhrp_indication);
732 gboolean dissected;
733 tvbuff_t *sub_tvb;
735 save_in_error_pkt = pinfo->flags.in_error_pkt;
736 pinfo->flags.in_error_pkt = TRUE;
737 sub_tvb = tvb_new_subset_remaining(tvb, offset);
738 if (isErr) {
739 _dissect_nhrp(sub_tvb, pinfo, ind_tree, TRUE, FALSE);
741 else {
742 if (hdr->ar_pro_type <= 0xFF) {
743 /* It's an NLPID */
744 if (hdr->ar_pro_type == NLPID_SNAP) {
746 * Dissect based on the SNAP OUI
747 * and PID.
749 if (hdr->ar_pro_type_oui == 0x000000) {
751 * "Should not happen", as
752 * the protocol type should
753 * be the Ethertype, but....
755 dissected = dissector_try_uint(
756 ethertype_subdissector_table,
757 hdr->ar_pro_type_pid,
758 sub_tvb, pinfo, ind_tree);
759 } else {
761 * If we have a dissector
762 * table, use it, otherwise
763 * just dissect as data.
765 if (oui_info != NULL) {
766 dissected = dissector_try_uint(
767 oui_info->table,
768 hdr->ar_pro_type_pid,
769 sub_tvb, pinfo,
770 ind_tree);
771 } else
772 dissected = FALSE;
774 } else {
776 * Dissect based on the NLPID.
778 dissected = dissector_try_uint(
779 osinl_incl_subdissector_table,
780 hdr->ar_pro_type, sub_tvb, pinfo,
781 ind_tree) ||
782 dissector_try_uint(
783 osinl_excl_subdissector_table,
784 hdr->ar_pro_type, sub_tvb, pinfo,
785 ind_tree);
787 } else if (hdr->ar_pro_type <= 0x3FF) {
788 /* Reserved for future use by the IETF */
789 dissected = FALSE;
790 } else if (hdr->ar_pro_type <= 0x04FF) {
791 /* Allocated for use by the ATM Forum */
792 dissected = FALSE;
793 } else if (hdr->ar_pro_type <= 0x05FF) {
794 /* Experimental/Local use */
795 dissected = FALSE;
796 } else {
797 dissected = dissector_try_uint(
798 ethertype_subdissector_table,
799 hdr->ar_pro_type, sub_tvb, pinfo, ind_tree);
801 if (!dissected) {
802 call_dissector(data_handle, sub_tvb, pinfo,
803 ind_tree);
806 pinfo->flags.in_error_pkt = save_in_error_pkt;
807 offset = mandEnd;
810 /* According to RFC 2332, section 5.2.7, there shouldn't be any extensions
811 * in the Error Indication packet. */
812 if (isErr && tvb_reported_length_remaining(tvb, offset)) {
813 expert_add_info(pinfo, tree, &ei_nhrp_ext_not_allowed);
816 dissect_cie_list(tvb, pinfo, nhrp_tree, offset, mandEnd, hdr, isReq, codeinfo);
818 *pOffset = mandEnd;
821 void dissect_nhrp_ext(tvbuff_t *tvb,
822 packet_info *pinfo,
823 proto_tree *tree,
824 gint *pOffset,
825 gint extLen,
826 e_nhrp_hdr *hdr,
827 guint srcLen,
828 gboolean nested)
830 gint offset = *pOffset;
831 gint extEnd = offset + extLen;
833 proto_item *ti;
835 tvb_ensure_bytes_exist(tvb, offset, extLen);
837 while ((offset + 4) <= extEnd)
839 proto_item *nhrp_tree_item;
840 proto_tree *nhrp_tree;
841 gint extTypeC = tvb_get_ntohs(tvb, offset);
842 gint extType = extTypeC & 0x3FFF;
843 guint len = tvb_get_ntohs(tvb, offset+2);
845 if ((extType == NHRP_EXT_NAT_ADDRESS) && (len == 8)) {
846 /* Assume it's not really a Cisco NAT extension, but a device
847 * capabilities extension instead (see RFC 2735). */
848 nhrp_tree_item = proto_tree_add_text(tree, tvb, offset,
849 len + 4, "Device Capabilities Extension");
851 else {
852 nhrp_tree_item = proto_tree_add_text(tree, tvb, offset,
853 len + 4, "%s",
854 val_to_str(extType, ext_type_vals, "Unknown (%u)"));
856 nhrp_tree = proto_item_add_subtree(nhrp_tree_item, ett_nhrp_ext);
857 proto_tree_add_boolean(nhrp_tree, hf_nhrp_ext_C, tvb, offset, 2, extTypeC);
858 proto_tree_add_item(nhrp_tree, hf_nhrp_ext_type, tvb, offset, 2, ENC_BIG_ENDIAN);
859 offset += 2;
861 proto_tree_add_item(nhrp_tree, hf_nhrp_ext_len, tvb, offset, 2, ENC_BIG_ENDIAN);
862 offset += 2;
864 if (len && (extType != NHRP_EXT_NULL)) {
865 tvb_ensure_bytes_exist(tvb, offset, len);
866 if ((extType == NHRP_EXT_NAT_ADDRESS) && (len == 8)) {
867 /* Assume it's not really a Cisco NAT extension, but a device
868 * capabilities extension instead (see RFC 2735). */
869 proto_item *devcap_item;
870 proto_tree *devcap_tree;
871 proto_item *cap_item;
872 proto_tree *cap_tree;
874 devcap_item = proto_tree_add_text(nhrp_tree, tvb, offset, len,
875 "Extension Data: Src is %sVPN-aware; Dst is %sVPN-aware",
876 tvb_get_ntohl(tvb, offset) & 1 ? "" : "non-",
877 tvb_get_ntohl(tvb, offset + 4) & 1 ? "" : "non-");
878 devcap_tree = proto_item_add_subtree(devcap_item, ett_nhrp_devcap_ext);
879 cap_item = proto_tree_add_item(devcap_tree, hf_nhrp_devcap_ext_srccap, tvb, offset, 4, ENC_BIG_ENDIAN);
880 cap_tree = proto_item_add_subtree(cap_item, ett_nhrp_devcap_ext_srccap);
881 proto_tree_add_item(cap_tree, hf_nhrp_devcap_ext_srccap_V, tvb, offset, 4, ENC_BIG_ENDIAN);
883 cap_item = proto_tree_add_item(devcap_tree, hf_nhrp_devcap_ext_dstcap, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
884 cap_tree = proto_item_add_subtree(cap_item, ett_nhrp_devcap_ext_dstcap);
885 proto_tree_add_item(cap_tree, hf_nhrp_devcap_ext_dstcap_V, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
886 goto skip_switch;
889 switch (extType) {
890 case NHRP_EXT_RESP_ADDR:
891 case NHRP_EXT_FWD_RECORD:
892 case NHRP_EXT_REV_RECORD:
893 case NHRP_EXT_NAT_ADDRESS:
894 dissect_cie_list(tvb, pinfo, nhrp_tree,
895 offset, offset + len, hdr, 0, FALSE);
896 break;
898 case NHRP_EXT_AUTH:
899 case NHRP_EXT_MOBILE_AUTH:
900 if (len < (4 + srcLen)) {
901 ti = proto_tree_add_text(nhrp_tree, tvb, offset, len,
902 "Malformed Extension: %s",
903 tvb_bytes_to_str(tvb, offset, len));
904 expert_add_info_format(pinfo, ti, &ei_nhrp_ext_malformed, "Incomplete Authentication Extension");
906 else {
907 proto_item *auth_item;
908 proto_tree *auth_tree;
910 auth_item = proto_tree_add_text(nhrp_tree, tvb, offset, len,
911 "Extension Data: SPI=%u: Data=%s", tvb_get_ntohs(tvb, offset + 2),
912 tvb_bytes_to_str(tvb, offset + 4, len - 4));
913 auth_tree = proto_item_add_subtree(auth_item, ett_nhrp_auth_ext);
914 proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
915 proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_spi, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
916 if (srcLen == 4)
917 proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_src_addr, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
918 else if (srcLen) {
919 proto_tree_add_text(auth_tree, tvb, offset + 4, srcLen,
920 "Source Address: %s",
921 tvb_bytes_to_str(tvb, offset + 4, srcLen));
923 if (len > (4 + srcLen)) {
924 proto_tree_add_text(auth_tree, tvb, offset + 4 + srcLen, len - (4 + srcLen),
925 "Data: %s", tvb_bytes_to_str(tvb, offset + 4 + srcLen, len - (4 + srcLen)));
928 break;
930 case NHRP_EXT_VENDOR_PRIV:
931 if (len < 3) {
932 ti = proto_tree_add_text(nhrp_tree, tvb, offset, len,
933 "Malformed Extension: %s",
934 tvb_bytes_to_str(tvb, offset, len));
935 expert_add_info_format(pinfo, ti, &ei_nhrp_ext_malformed, "Incomplete Vendor-Private Extension");
937 else {
938 proto_item *vendor_item;
939 proto_tree *vendor_tree;
940 gchar manuf[3];
942 tvb_memcpy(tvb, manuf, offset, 3);
943 vendor_item = proto_tree_add_text(nhrp_tree, tvb, offset, len,
944 "Extension Data: Vendor ID=%s, Data=%s", get_manuf_name(manuf),
945 tvb_bytes_to_str(tvb, offset + 3, len - 3));
946 vendor_tree = proto_item_add_subtree(vendor_item, ett_nhrp_vendor_ext);
947 proto_tree_add_bytes_format_value(vendor_tree, hf_nhrp_vendor_ext_id, tvb,
948 offset, 3, manuf, "%s", get_manuf_name(manuf));
949 if (len > 3) {
950 proto_tree_add_text(vendor_tree, tvb, offset + 3, len - 3,
951 "Data: %s", tvb_bytes_to_str(tvb, offset + 3, len - 3));
954 break;
956 default:
957 proto_tree_add_item(nhrp_tree, hf_nhrp_unknown_ext_value, tvb,
958 offset, len, ENC_NA);
959 break;
961 skip_switch:
962 offset += len;
965 if (!nested) {
966 len = tvb_reported_length_remaining(tvb, offset);
967 if ((extType == NHRP_EXT_NULL) && len) {
968 ti = proto_tree_add_text(tree, tvb, offset, len,
969 "Unknown Data (%d bytes)", len);
970 expert_add_info(pinfo, ti, &ei_nhrp_ext_extra);
971 break;
976 *pOffset = extEnd;
979 void dissect_nhrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
981 _dissect_nhrp(tvb, pinfo, tree, FALSE, TRUE);
984 static void _dissect_nhrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
985 gboolean nested, gboolean codeinfo)
987 e_nhrp_hdr hdr;
988 gint mandLen = 0;
989 gint extLen = 0;
990 gint offset = 0;
991 proto_item *ti;
992 proto_tree *nhrp_tree;
993 oui_info_t *oui_info = NULL;
994 guint srcLen = 0;
996 if (!nested) {
997 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NHRP");
998 col_clear(pinfo->cinfo, COL_INFO);
1001 memset(&hdr, 0, sizeof(e_nhrp_hdr));
1002 hdr.ar_op_type = tvb_get_guint8(tvb, 17);
1004 if (!nested) {
1005 col_add_str(pinfo->cinfo, COL_INFO,
1006 val_to_str(hdr.ar_op_type, nhrp_op_type_vals,
1007 "0x%02X - unknown"));
1010 ti = proto_tree_add_protocol_format(tree, proto_nhrp, tvb, 0, -1,
1011 "Next Hop Resolution Protocol (%s)",
1012 val_to_str(hdr.ar_op_type, nhrp_op_type_vals, "0x%02X - unknown"));
1013 nhrp_tree = proto_item_add_subtree(ti, ett_nhrp);
1015 dissect_nhrp_hdr(tvb, pinfo, nhrp_tree, &offset, &mandLen, &extLen,
1016 &oui_info, &hdr);
1017 if (mandLen) {
1018 dissect_nhrp_mand(tvb, pinfo, nhrp_tree, &offset, mandLen,
1019 oui_info, &hdr, &srcLen, codeinfo);
1022 if (extLen) {
1023 dissect_nhrp_ext(tvb, pinfo, nhrp_tree, &offset, extLen, &hdr, srcLen, nested);
1027 void
1028 proto_register_nhrp(void)
1030 static hf_register_info hf[] = {
1032 { &hf_nhrp_hdr_afn,
1033 { "Address Family Number", "nhrp.hdr.afn",
1034 FT_UINT16, BASE_HEX_DEC, VALS(afn_vals), 0x0,
1035 NULL, HFILL }
1037 { &hf_nhrp_hdr_pro_type,
1038 { "Protocol Type (short form)", "nhrp.hdr.pro.type",
1039 FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
1040 NULL, HFILL }
1042 { &hf_nhrp_hdr_pro_snap_oui,
1043 { "Protocol Type (long form) - OUI", "nhrp.hdr.pro.snap.oui",
1044 FT_UINT24, BASE_HEX, VALS(oui_vals), 0x0,
1045 NULL, HFILL }
1047 { &hf_nhrp_hdr_pro_snap_pid,
1048 { "Protocol Type (long form) - PID", "nhrp.hdr.pro.snap.pid",
1049 FT_UINT16, BASE_HEX, NULL, 0x0,
1050 NULL, HFILL }
1052 { &hf_nhrp_hdr_hopcnt,
1053 { "Hop Count", "nhrp.hdr.hopcnt",
1054 FT_UINT8, BASE_DEC, NULL, 0x0,
1055 NULL, HFILL }
1057 { &hf_nhrp_hdr_pktsz,
1058 { "Packet Length", "nhrp.hdr.pktsz",
1059 FT_UINT16, BASE_DEC, NULL, 0x0,
1060 NULL, HFILL }
1062 { &hf_nhrp_hdr_chksum,
1063 { "NHRP Packet Checksum", "nhrp.hdr.chksum",
1064 FT_UINT16, BASE_HEX, NULL, 0x0,
1065 NULL, HFILL }
1067 { &hf_nhrp_hdr_extoff,
1068 { "Extension Offset", "nhrp.hdr.extoff",
1069 FT_UINT16, BASE_DEC, NULL, 0x0,
1070 NULL, HFILL }
1072 { &hf_nhrp_hdr_version,
1073 { "Version", "nhrp.hdr.version",
1074 FT_UINT8, BASE_DEC, NULL, 0x0,
1075 NULL, HFILL }
1077 { &hf_nhrp_hdr_op_type,
1078 { "NHRP Packet Type", "nhrp.hdr.op.type",
1079 FT_UINT8, BASE_DEC, VALS(nhrp_op_type_vals), 0x0,
1080 NULL, HFILL }
1082 { &hf_nhrp_hdr_shtl,
1083 { "Source Address Type/Len", "nhrp.hdr.shtl",
1084 FT_UINT8, BASE_DEC, NULL, 0x0,
1085 NULL, HFILL }
1087 { &hf_nhrp_hdr_shtl_type,
1088 { "Type", "nhrp.hdr.shtl.type",
1089 FT_UINT8, BASE_DEC, VALS(nhrp_shtl_type_vals), NHRP_SHTL_TYPE_MASK,
1090 NULL, HFILL }
1092 { &hf_nhrp_hdr_shtl_len,
1093 { "Length", "nhrp.hdr.shtl.len",
1094 FT_UINT8, BASE_DEC, NULL, NHRP_SHTL_LEN_MASK,
1095 NULL, HFILL }
1097 { &hf_nhrp_hdr_sstl,
1098 { "Source SubAddress Type/Len", "nhrp.hdr.sstl",
1099 FT_UINT8, BASE_DEC, NULL, 0x0,
1100 NULL, HFILL }
1102 { &hf_nhrp_hdr_sstl_type,
1103 { "Type", "nhrp.hdr.sstl.type",
1104 FT_UINT8, BASE_DEC, VALS(nhrp_shtl_type_vals), NHRP_SHTL_TYPE_MASK,
1105 NULL, HFILL }
1107 { &hf_nhrp_hdr_sstl_len,
1108 { "Length", "nhrp.hdr.sstl.len",
1109 FT_UINT8, BASE_DEC, NULL, NHRP_SHTL_LEN_MASK,
1110 NULL, HFILL }
1113 { &hf_nhrp_src_proto_len,
1114 { "Source Protocol Len", "nhrp.src.prot.len",
1115 FT_UINT16, BASE_DEC, NULL, 0x0,
1116 NULL, HFILL }
1118 { &hf_nhrp_dst_proto_len,
1119 { "Destination Protocol Len", "nhrp.dst.prot.len",
1120 FT_UINT16, BASE_DEC, NULL, 0x0,
1121 NULL, HFILL }
1123 { &hf_nhrp_flags,
1124 { "Flags", "nhrp.flags",
1125 FT_UINT16, BASE_HEX, NULL, 0x0,
1126 NULL, HFILL }
1128 { &hf_nhrp_flag_Q,
1129 { "Is Router", "nhrp.flag.q",
1130 FT_BOOLEAN, 16, NULL, 0x8000,
1131 NULL, HFILL }
1133 { &hf_nhrp_flag_N,
1134 { "Expected Purge Reply", "nhrp.flag.n",
1135 FT_BOOLEAN, 16, NULL, 0x8000,
1136 NULL, HFILL }
1138 { &hf_nhrp_flag_A,
1139 { "Authoritative", "nhrp.flag.a",
1140 FT_BOOLEAN, 16, NULL, 0x4000,
1141 "A bit", HFILL }
1143 { &hf_nhrp_flag_D,
1144 { "Stable Association", "nhrp.flag.d",
1145 FT_BOOLEAN, 16, NULL, 0x2000,
1146 "D bit", HFILL }
1148 { &hf_nhrp_flag_U1,
1149 { "Uniqueness Bit", "nhrp.flag.u",
1150 FT_BOOLEAN, 16, NULL, 0x1000,
1151 "U bit", HFILL }
1153 { &hf_nhrp_flag_U2,
1154 { "Uniqueness Bit", "nhrp.flag.u",
1155 FT_BOOLEAN, 16, NULL, 0x8000,
1156 "U bit", HFILL }
1158 { &hf_nhrp_flag_S,
1159 { "Stable Binding", "nhrp.flag.s",
1160 FT_BOOLEAN, 16, NULL, 0x0800,
1161 "S bit", HFILL }
1163 { &hf_nhrp_flag_NAT,
1164 { "Cisco NAT Supported", "nhrp.flag.nat",
1165 FT_BOOLEAN, 16, NULL, 0x0002,
1166 "NAT bit", HFILL }
1168 { &hf_nhrp_request_id,
1169 { "Request ID", "nhrp.reqid",
1170 FT_UINT32, BASE_HEX_DEC, NULL, 0x0,
1171 NULL, HFILL }
1173 { &hf_nhrp_src_nbma_addr,
1174 { "Source NBMA Address", "nhrp.src.nbma.addr",
1175 FT_IPv4, BASE_NONE, NULL, 0x0,
1176 NULL, HFILL }
1178 #if 0
1179 { &hf_nhrp_src_nbma_saddr,
1180 { "Source NBMA Sub Address", "nhrp.src.nbma.saddr",
1181 FT_UINT_BYTES, BASE_NONE, NULL, 0x0,
1182 NULL, HFILL }
1184 #endif
1185 { &hf_nhrp_src_prot_addr,
1186 { "Source Protocol Address", "nhrp.src.prot.addr",
1187 FT_IPv4, BASE_NONE, NULL, 0x0,
1188 NULL, HFILL }
1190 { &hf_nhrp_dst_prot_addr,
1191 { "Destination Protocol Address", "nhrp.dst.prot.addr",
1192 FT_IPv4, BASE_NONE, NULL, 0x0,
1193 NULL, HFILL }
1196 { &hf_nhrp_code,
1197 { "Code", "nhrp.code",
1198 FT_UINT8, BASE_DEC, NULL, 0x0,
1199 NULL, HFILL }
1201 { &hf_nhrp_prefix_len,
1202 { "Prefix Length", "nhrp.prefix",
1203 FT_UINT8, BASE_DEC, NULL, 0x0,
1204 NULL, HFILL }
1206 { &hf_nhrp_unused,
1207 { "Unused", "nhrp.unused",
1208 FT_UINT16, BASE_DEC, NULL, 0x0,
1209 NULL, HFILL }
1211 { &hf_nhrp_mtu,
1212 { "Max Transmission Unit", "nhrp.mtu",
1213 FT_UINT16, BASE_DEC, NULL, 0x0,
1214 NULL, HFILL }
1216 { &hf_nhrp_holding_time,
1217 { "Holding Time (s)", "nhrp.htime",
1218 FT_UINT16, BASE_DEC, NULL, 0x0,
1219 NULL, HFILL }
1221 { &hf_nhrp_cli_addr_tl,
1222 { "Client Address Type/Len", "nhrp.cli.addr_tl",
1223 FT_UINT8, BASE_DEC, NULL, 0x0,
1224 NULL, HFILL }
1226 { &hf_nhrp_cli_addr_tl_type,
1227 { "Type", "nhrp.cli.addr_tl.type",
1228 FT_UINT8, BASE_DEC, VALS(nhrp_shtl_type_vals), NHRP_SHTL_TYPE_MASK,
1229 NULL, HFILL }
1231 { &hf_nhrp_cli_addr_tl_len,
1232 { "Length", "nhrp.cli.addr_tl.len",
1233 FT_UINT8, BASE_DEC, NULL, NHRP_SHTL_LEN_MASK,
1234 NULL, HFILL }
1236 { &hf_nhrp_cli_saddr_tl,
1237 { "Client Sub Address Type/Len", "nhrp.cli.saddr_tl",
1238 FT_UINT8, BASE_DEC, NULL, 0x0,
1239 NULL, HFILL }
1241 { &hf_nhrp_cli_saddr_tl_type,
1242 { "Type", "nhrp.cli.saddr_tl.type",
1243 FT_UINT8, BASE_DEC, VALS(nhrp_shtl_type_vals), NHRP_SHTL_TYPE_MASK,
1244 NULL, HFILL }
1246 { &hf_nhrp_cli_saddr_tl_len,
1247 { "Length", "nhrp.cli.saddr_tl.len",
1248 FT_UINT8, BASE_DEC, NULL, NHRP_SHTL_LEN_MASK,
1249 NULL, HFILL }
1251 { &hf_nhrp_cli_prot_len,
1252 { "Client Protocol Length", "nhrp.prot.len",
1253 FT_UINT8, BASE_DEC, NULL, 0x0,
1254 NULL, HFILL }
1256 { &hf_nhrp_pref,
1257 { "CIE Preference Value", "nhrp.pref",
1258 FT_UINT8, BASE_DEC, NULL, 0x0,
1259 NULL, HFILL }
1261 { &hf_nhrp_client_nbma_addr,
1262 { "Client NBMA Address", "nhrp.client.nbma.addr",
1263 FT_IPv4, BASE_NONE, NULL, 0x0,
1264 NULL, HFILL }
1266 #if 0
1267 { &hf_nhrp_client_nbma_saddr,
1268 { "Client NBMA Sub Address", "nhrp.client.nbma.saddr",
1269 FT_UINT_BYTES, BASE_NONE, NULL, 0x0,
1270 NULL, HFILL }
1272 #endif
1273 { &hf_nhrp_client_prot_addr,
1274 { "Client Protocol Address", "nhrp.client.prot.addr",
1275 FT_IPv4, BASE_NONE, NULL, 0x0,
1276 NULL, HFILL }
1279 { &hf_nhrp_ext_C,
1280 { "Compulsory Flag", "nhrp.ext.c",
1281 FT_BOOLEAN, 16, NULL, 0x8000,
1282 NULL, HFILL }
1284 { &hf_nhrp_ext_type,
1285 { "Extension Type", "nhrp.ext.type",
1286 FT_UINT16, BASE_HEX, NULL, 0x3FFF,
1287 NULL, HFILL }
1289 { &hf_nhrp_ext_len,
1290 { "Extension length", "nhrp.ext.len",
1291 FT_UINT16, BASE_DEC, NULL, 0x0,
1292 NULL, HFILL }
1294 #if 0
1295 { &hf_nhrp_ext_value,
1296 { "Extension Value", "nhrp.ext.val",
1297 FT_UINT_BYTES, BASE_NONE, NULL, 0x0,
1298 NULL, HFILL }
1300 #endif
1302 { &hf_nhrp_error_code,
1303 { "Error Code", "nhrp.err.code",
1304 FT_UINT16, BASE_DEC, VALS(nhrp_error_code_vals), 0x0,
1305 NULL, HFILL }
1307 { &hf_nhrp_error_offset,
1308 { "Error Offset", "nhrp.err.offset",
1309 FT_UINT16, BASE_DEC, NULL, 0x0,
1310 NULL, HFILL }
1312 #if 0
1313 { &hf_nhrp_error_packet,
1314 { "Errored Packet", "nhrp.err.pkt",
1315 FT_UINT_BYTES, BASE_NONE, NULL, 0x0,
1316 NULL, HFILL }
1318 #endif
1319 { &hf_nhrp_auth_ext_reserved,
1320 { "Reserved", "nhrp.auth_ext.reserved",
1321 FT_UINT16, BASE_DEC, NULL, 0x0,
1322 NULL, HFILL }
1324 { &hf_nhrp_auth_ext_spi,
1325 { "SPI", "nhrp.auth_ext.spi",
1326 FT_UINT16, BASE_DEC, NULL, 0x0,
1327 "Security Parameter Index", HFILL }
1329 { &hf_nhrp_auth_ext_src_addr,
1330 { "Source Address", "nhrp.auth_ext.src_addr",
1331 FT_IPv4, BASE_NONE, NULL, 0x0,
1332 NULL, HFILL }
1334 { &hf_nhrp_vendor_ext_id ,
1335 { "Vendor ID", "nhrp.vendor_ext.id",
1336 FT_BYTES, BASE_NONE, NULL, 0x0,
1337 NULL, HFILL }
1339 { &hf_nhrp_devcap_ext_srccap,
1340 { "Source Capabilities", "nhrp.devcap_ext.srccap",
1341 FT_UINT32, BASE_HEX, NULL, 0x0,
1342 NULL, HFILL }
1344 { &hf_nhrp_devcap_ext_srccap_V,
1345 { "VPN-aware", "nhrp.devcap_ext.srccap.V",
1346 FT_BOOLEAN, 32, NULL, 0x00000001,
1347 NULL, HFILL }
1349 { &hf_nhrp_devcap_ext_dstcap,
1350 { "Destination Capabilities", "nhrp.devcap_ext.dstcap",
1351 FT_UINT32, BASE_HEX, NULL, 0x0,
1352 NULL, HFILL }
1354 { &hf_nhrp_devcap_ext_dstcap_V,
1355 { "VPN-aware", "nhrp.devcap_ext.dstcap.V",
1356 FT_BOOLEAN, 32, NULL, 0x00000001,
1357 NULL, HFILL }
1359 { &hf_nhrp_unknown_ext_value,
1360 { "Extension Value", "nhrp.unknown_ext.value",
1361 FT_BYTES, BASE_NONE, NULL, 0x0,
1362 NULL, HFILL }
1366 static gint *ett[] = {
1367 &ett_nhrp,
1368 &ett_nhrp_hdr,
1369 &ett_nhrp_hdr_shtl,
1370 &ett_nhrp_hdr_sstl,
1371 &ett_nhrp_mand,
1372 &ett_nhrp_ext,
1373 &ett_nhrp_mand_flag,
1374 &ett_nhrp_cie,
1375 &ett_nhrp_cie_cli_addr_tl,
1376 &ett_nhrp_cie_cli_saddr_tl,
1377 &ett_nhrp_indication,
1378 &ett_nhrp_auth_ext,
1379 &ett_nhrp_vendor_ext,
1380 &ett_nhrp_devcap_ext,
1381 &ett_nhrp_devcap_ext_srccap,
1382 &ett_nhrp_devcap_ext_dstcap
1385 static ei_register_info ei[] = {
1386 { &ei_nhrp_hdr_extoff, { "nhrp.hdr.extoff.invalid", PI_MALFORMED, PI_ERROR, "Extension offset is less than the fixed header length", EXPFILL }},
1387 { &ei_nhrp_ext_not_allowed, { "nhrp.ext.not_allowed", PI_MALFORMED, PI_ERROR, "Extensions not allowed per RFC2332 section 5.2.7", EXPFILL }},
1388 { &ei_nhrp_ext_malformed, { "nhrp.ext.malformed", PI_MALFORMED, PI_ERROR, "Incomplete Authentication Extension", EXPFILL }},
1389 { &ei_nhrp_ext_extra, { "nhrp.ext.extra", PI_MALFORMED, PI_ERROR, "Superfluous data follows End Extension", EXPFILL }},
1392 expert_module_t* expert_nhrp;
1394 proto_nhrp = proto_register_protocol("NBMA Next Hop Resolution Protocol", "NHRP", "nhrp");
1395 proto_register_field_array(proto_nhrp, hf, array_length(hf));
1396 proto_register_subtree_array(ett, array_length(ett));
1397 expert_nhrp = expert_register_protocol(proto_nhrp);
1398 expert_register_field_array(expert_nhrp, ei, array_length(ei));
1401 void
1402 proto_reg_handoff_nhrp(void)
1404 dissector_handle_t nhrp_handle;
1406 data_handle = find_dissector("data");
1408 osinl_incl_subdissector_table = find_dissector_table("osinl.incl");
1409 osinl_excl_subdissector_table = find_dissector_table("osinl.excl");
1410 ethertype_subdissector_table = find_dissector_table("ethertype");
1412 nhrp_handle = create_dissector_handle(dissect_nhrp, proto_nhrp);
1413 dissector_add_uint("ip.proto", IP_PROTO_NARP, nhrp_handle);
1414 dissector_add_uint("gre.proto", GRE_NHRP, nhrp_handle);
1415 dissector_add_uint("llc.iana_pid", IANA_PID_MARS_NHRP_CONTROL, nhrp_handle);