xref: /freebsd/contrib/tcpdump/print-ahcp.c (revision 0a7e5f1f02aad2ff5fff1c60f44c6975fd07e1d9)
13c602fabSXin LI /*
23c602fabSXin LI  * Copyright (c) 2013 The TCPDUMP project
33c602fabSXin LI  * All rights reserved.
43c602fabSXin LI  *
53c602fabSXin LI  * Redistribution and use in source and binary forms, with or without
63c602fabSXin LI  * modification, are permitted provided that the following conditions
73c602fabSXin LI  * are met:
83c602fabSXin LI  * 1. Redistributions of source code must retain the above copyright
93c602fabSXin LI  *    notice, this list of conditions and the following disclaimer.
103c602fabSXin LI  * 2. Redistributions in binary form must reproduce the above copyright
113c602fabSXin LI  *    notice, this list of conditions and the following disclaimer in the
123c602fabSXin LI  *    documentation and/or other materials provided with the distribution.
133c602fabSXin LI  *
143c602fabSXin LI  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
153c602fabSXin LI  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
163c602fabSXin LI  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
173c602fabSXin LI  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
183c602fabSXin LI  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
193c602fabSXin LI  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
203c602fabSXin LI  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
213c602fabSXin LI  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
223c602fabSXin LI  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
233c602fabSXin LI  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
243c602fabSXin LI  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
253c602fabSXin LI  * POSSIBILITY OF SUCH DAMAGE.
263c602fabSXin LI  */
273c602fabSXin LI 
283340d773SGleb Smirnoff /* \summary: Ad Hoc Configuration Protocol (AHCP) printer */
293340d773SGleb Smirnoff 
303340d773SGleb Smirnoff /* Based on draft-chroboczek-ahcp-00 and source code of ahcpd-0.53 */
313340d773SGleb Smirnoff 
32*ee67461eSJoseph Mingrone #include <config.h>
333c602fabSXin LI 
34*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
353c602fabSXin LI 
36*ee67461eSJoseph Mingrone #define ND_LONGJMP_FROM_TCHECK
373340d773SGleb Smirnoff #include "netdissect.h"
383c602fabSXin LI #include "extract.h"
393c602fabSXin LI #include "addrtoname.h"
403c602fabSXin LI 
413c602fabSXin LI 
423c602fabSXin LI #define AHCP_MAGIC_NUMBER 43
433c602fabSXin LI #define AHCP_VERSION_1 1
443c602fabSXin LI #define AHCP1_HEADER_FIX_LEN 24
453c602fabSXin LI #define AHCP1_BODY_MIN_LEN 4
463c602fabSXin LI 
473c602fabSXin LI #define AHCP1_MSG_DISCOVER 0
483c602fabSXin LI #define AHCP1_MSG_OFFER    1
493c602fabSXin LI #define AHCP1_MSG_REQUEST  2
503c602fabSXin LI #define AHCP1_MSG_ACK      3
513c602fabSXin LI #define AHCP1_MSG_NACK     4
523c602fabSXin LI #define AHCP1_MSG_RELEASE  5
533c602fabSXin LI 
543c602fabSXin LI static const struct tok ahcp1_msg_str[] = {
553c602fabSXin LI 	{ AHCP1_MSG_DISCOVER, "Discover" },
563c602fabSXin LI 	{ AHCP1_MSG_OFFER,    "Offer"    },
573c602fabSXin LI 	{ AHCP1_MSG_REQUEST,  "Request"  },
583c602fabSXin LI 	{ AHCP1_MSG_ACK,      "Ack"      },
593c602fabSXin LI 	{ AHCP1_MSG_NACK,     "Nack"     },
603c602fabSXin LI 	{ AHCP1_MSG_RELEASE,  "Release"  },
613c602fabSXin LI 	{ 0, NULL }
623c602fabSXin LI };
633c602fabSXin LI 
643c602fabSXin LI #define AHCP1_OPT_PAD                     0
653c602fabSXin LI #define AHCP1_OPT_MANDATORY               1
663c602fabSXin LI #define AHCP1_OPT_ORIGIN_TIME             2
673c602fabSXin LI #define AHCP1_OPT_EXPIRES                 3
683c602fabSXin LI #define AHCP1_OPT_MY_IPV6_ADDRESS         4
693c602fabSXin LI #define AHCP1_OPT_MY_IPV4_ADDRESS         5
703c602fabSXin LI #define AHCP1_OPT_IPV6_PREFIX             6
713c602fabSXin LI #define AHCP1_OPT_IPV4_PREFIX             7
723c602fabSXin LI #define AHCP1_OPT_IPV6_ADDRESS            8
733c602fabSXin LI #define AHCP1_OPT_IPV4_ADDRESS            9
743c602fabSXin LI #define AHCP1_OPT_IPV6_PREFIX_DELEGATION 10
753c602fabSXin LI #define AHCP1_OPT_IPV4_PREFIX_DELEGATION 11
763c602fabSXin LI #define AHCP1_OPT_NAME_SERVER            12
773c602fabSXin LI #define AHCP1_OPT_NTP_SERVER             13
783c602fabSXin LI #define AHCP1_OPT_MAX                    13
793c602fabSXin LI 
803c602fabSXin LI static const struct tok ahcp1_opt_str[] = {
813c602fabSXin LI 	{ AHCP1_OPT_PAD,                    "Pad"                    },
823c602fabSXin LI 	{ AHCP1_OPT_MANDATORY,              "Mandatory"              },
833c602fabSXin LI 	{ AHCP1_OPT_ORIGIN_TIME,            "Origin Time"            },
843c602fabSXin LI 	{ AHCP1_OPT_EXPIRES,                "Expires"                },
853c602fabSXin LI 	{ AHCP1_OPT_MY_IPV6_ADDRESS,        "My-IPv6-Address"        },
863c602fabSXin LI 	{ AHCP1_OPT_MY_IPV4_ADDRESS,        "My-IPv4-Address"        },
873c602fabSXin LI 	{ AHCP1_OPT_IPV6_PREFIX,            "IPv6 Prefix"            },
883c602fabSXin LI 	{ AHCP1_OPT_IPV4_PREFIX,            "IPv4 Prefix"            },
893c602fabSXin LI 	{ AHCP1_OPT_IPV6_ADDRESS,           "IPv6 Address"           },
903c602fabSXin LI 	{ AHCP1_OPT_IPV4_ADDRESS,           "IPv4 Address"           },
913c602fabSXin LI 	{ AHCP1_OPT_IPV6_PREFIX_DELEGATION, "IPv6 Prefix Delegation" },
923c602fabSXin LI 	{ AHCP1_OPT_IPV4_PREFIX_DELEGATION, "IPv4 Prefix Delegation" },
933c602fabSXin LI 	{ AHCP1_OPT_NAME_SERVER,            "Name Server"            },
943c602fabSXin LI 	{ AHCP1_OPT_NTP_SERVER,             "NTP Server"             },
953c602fabSXin LI 	{ 0, NULL }
963c602fabSXin LI };
973c602fabSXin LI 
98*ee67461eSJoseph Mingrone static void
ahcp_time_print(netdissect_options * ndo,const u_char * cp,uint8_t len)99*ee67461eSJoseph Mingrone ahcp_time_print(netdissect_options *ndo,
100*ee67461eSJoseph Mingrone                 const u_char *cp, uint8_t len)
1018bdc5a62SPatrick Kelsey {
1023c602fabSXin LI 	time_t t;
103*ee67461eSJoseph Mingrone 	char buf[sizeof("-yyyyyyyyyy-mm-dd hh:mm:ss UTC")];
1043c602fabSXin LI 
105*ee67461eSJoseph Mingrone 	if (len != 4)
1063340d773SGleb Smirnoff 		goto invalid;
107*ee67461eSJoseph Mingrone 	t = GET_BE_U_4(cp);
108*ee67461eSJoseph Mingrone 	ND_PRINT(": %s",
109*ee67461eSJoseph Mingrone 	    nd_format_time(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S UTC",
110*ee67461eSJoseph Mingrone 	      gmtime(&t)));
111*ee67461eSJoseph Mingrone 	return;
1123c602fabSXin LI 
1133340d773SGleb Smirnoff invalid:
114*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
115*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
1163c602fabSXin LI }
1173c602fabSXin LI 
118*ee67461eSJoseph Mingrone static void
ahcp_seconds_print(netdissect_options * ndo,const u_char * cp,uint8_t len)119*ee67461eSJoseph Mingrone ahcp_seconds_print(netdissect_options *ndo,
120*ee67461eSJoseph Mingrone                    const u_char *cp, uint8_t len)
1218bdc5a62SPatrick Kelsey {
122*ee67461eSJoseph Mingrone 	if (len != 4)
1233340d773SGleb Smirnoff 		goto invalid;
124*ee67461eSJoseph Mingrone 	ND_PRINT(": %us", GET_BE_U_4(cp));
125*ee67461eSJoseph Mingrone 	return;
1263c602fabSXin LI 
1273340d773SGleb Smirnoff invalid:
128*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
129*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
1303c602fabSXin LI }
1313c602fabSXin LI 
132*ee67461eSJoseph Mingrone static void
ahcp_ipv6_addresses_print(netdissect_options * ndo,const u_char * cp,uint8_t len)133*ee67461eSJoseph Mingrone ahcp_ipv6_addresses_print(netdissect_options *ndo,
134*ee67461eSJoseph Mingrone                           const u_char *cp, uint8_t len)
1358bdc5a62SPatrick Kelsey {
1363c602fabSXin LI 	const char *sep = ": ";
1373c602fabSXin LI 
138*ee67461eSJoseph Mingrone 	while (len) {
139*ee67461eSJoseph Mingrone 		if (len < 16)
1403340d773SGleb Smirnoff 			goto invalid;
141*ee67461eSJoseph Mingrone 		ND_PRINT("%s%s", sep, GET_IP6ADDR_STRING(cp));
1423c602fabSXin LI 		cp += 16;
143*ee67461eSJoseph Mingrone 		len -= 16;
1443c602fabSXin LI 		sep = ", ";
1453c602fabSXin LI 	}
146*ee67461eSJoseph Mingrone 	return;
1473c602fabSXin LI 
1483340d773SGleb Smirnoff invalid:
149*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
150*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
1513c602fabSXin LI }
1523c602fabSXin LI 
153*ee67461eSJoseph Mingrone static void
ahcp_ipv4_addresses_print(netdissect_options * ndo,const u_char * cp,uint8_t len)154*ee67461eSJoseph Mingrone ahcp_ipv4_addresses_print(netdissect_options *ndo,
155*ee67461eSJoseph Mingrone                           const u_char *cp, uint8_t len)
1568bdc5a62SPatrick Kelsey {
1573c602fabSXin LI 	const char *sep = ": ";
1583c602fabSXin LI 
159*ee67461eSJoseph Mingrone 	while (len) {
160*ee67461eSJoseph Mingrone 		if (len < 4)
1613340d773SGleb Smirnoff 			goto invalid;
162*ee67461eSJoseph Mingrone 		ND_PRINT("%s%s", sep, GET_IPADDR_STRING(cp));
1633c602fabSXin LI 		cp += 4;
164*ee67461eSJoseph Mingrone 		len -= 4;
1653c602fabSXin LI 		sep = ", ";
1663c602fabSXin LI 	}
167*ee67461eSJoseph Mingrone 	return;
1683c602fabSXin LI 
1693340d773SGleb Smirnoff invalid:
170*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
171*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
1723c602fabSXin LI }
1733c602fabSXin LI 
174*ee67461eSJoseph Mingrone static void
ahcp_ipv6_prefixes_print(netdissect_options * ndo,const u_char * cp,uint8_t len)175*ee67461eSJoseph Mingrone ahcp_ipv6_prefixes_print(netdissect_options *ndo,
176*ee67461eSJoseph Mingrone                          const u_char *cp, uint8_t len)
1778bdc5a62SPatrick Kelsey {
1783c602fabSXin LI 	const char *sep = ": ";
1793c602fabSXin LI 
180*ee67461eSJoseph Mingrone 	while (len) {
181*ee67461eSJoseph Mingrone 		if (len < 17)
1823340d773SGleb Smirnoff 			goto invalid;
183*ee67461eSJoseph Mingrone 		ND_PRINT("%s%s/%u", sep, GET_IP6ADDR_STRING(cp), GET_U_1(cp + 16));
1843c602fabSXin LI 		cp += 17;
185*ee67461eSJoseph Mingrone 		len -= 17;
1863c602fabSXin LI 		sep = ", ";
1873c602fabSXin LI 	}
188*ee67461eSJoseph Mingrone 	return;
1893c602fabSXin LI 
1903340d773SGleb Smirnoff invalid:
191*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
192*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
1933c602fabSXin LI }
1943c602fabSXin LI 
195*ee67461eSJoseph Mingrone static void
ahcp_ipv4_prefixes_print(netdissect_options * ndo,const u_char * cp,uint8_t len)196*ee67461eSJoseph Mingrone ahcp_ipv4_prefixes_print(netdissect_options *ndo,
197*ee67461eSJoseph Mingrone                          const u_char *cp, uint8_t len)
1988bdc5a62SPatrick Kelsey {
1993c602fabSXin LI 	const char *sep = ": ";
2003c602fabSXin LI 
201*ee67461eSJoseph Mingrone 	while (len) {
202*ee67461eSJoseph Mingrone 		if (len < 5)
2033340d773SGleb Smirnoff 			goto invalid;
204*ee67461eSJoseph Mingrone 		ND_PRINT("%s%s/%u", sep, GET_IPADDR_STRING(cp), GET_U_1(cp + 4));
2053c602fabSXin LI 		cp += 5;
206*ee67461eSJoseph Mingrone 		len -= 5;
2073c602fabSXin LI 		sep = ", ";
2083c602fabSXin LI 	}
209*ee67461eSJoseph Mingrone 	return;
2103c602fabSXin LI 
2113340d773SGleb Smirnoff invalid:
212*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
213*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
2143c602fabSXin LI }
2153c602fabSXin LI 
216*ee67461eSJoseph Mingrone static void
217*ee67461eSJoseph Mingrone (* const data_decoders[AHCP1_OPT_MAX + 1])(netdissect_options *, const u_char *, uint8_t) = {
2183c602fabSXin LI 	/* [AHCP1_OPT_PAD]                    = */  NULL,
2193c602fabSXin LI 	/* [AHCP1_OPT_MANDATORY]              = */  NULL,
2203c602fabSXin LI 	/* [AHCP1_OPT_ORIGIN_TIME]            = */  ahcp_time_print,
2213c602fabSXin LI 	/* [AHCP1_OPT_EXPIRES]                = */  ahcp_seconds_print,
2223c602fabSXin LI 	/* [AHCP1_OPT_MY_IPV6_ADDRESS]        = */  ahcp_ipv6_addresses_print,
2233c602fabSXin LI 	/* [AHCP1_OPT_MY_IPV4_ADDRESS]        = */  ahcp_ipv4_addresses_print,
2243c602fabSXin LI 	/* [AHCP1_OPT_IPV6_PREFIX]            = */  ahcp_ipv6_prefixes_print,
2253c602fabSXin LI 	/* [AHCP1_OPT_IPV4_PREFIX]            = */  NULL,
2263c602fabSXin LI 	/* [AHCP1_OPT_IPV6_ADDRESS]           = */  ahcp_ipv6_addresses_print,
2273c602fabSXin LI 	/* [AHCP1_OPT_IPV4_ADDRESS]           = */  ahcp_ipv4_addresses_print,
2283c602fabSXin LI 	/* [AHCP1_OPT_IPV6_PREFIX_DELEGATION] = */  ahcp_ipv6_prefixes_print,
2293c602fabSXin LI 	/* [AHCP1_OPT_IPV4_PREFIX_DELEGATION] = */  ahcp_ipv4_prefixes_print,
2303c602fabSXin LI 	/* [AHCP1_OPT_NAME_SERVER]            = */  ahcp_ipv6_addresses_print,
2313c602fabSXin LI 	/* [AHCP1_OPT_NTP_SERVER]             = */  ahcp_ipv6_addresses_print,
2323c602fabSXin LI };
2333c602fabSXin LI 
2343c602fabSXin LI static void
ahcp1_options_print(netdissect_options * ndo,const u_char * cp,uint16_t len)235*ee67461eSJoseph Mingrone ahcp1_options_print(netdissect_options *ndo,
236*ee67461eSJoseph Mingrone                     const u_char *cp, uint16_t len)
2378bdc5a62SPatrick Kelsey {
238*ee67461eSJoseph Mingrone 	while (len) {
2393c602fabSXin LI 		uint8_t option_no, option_len;
2403c602fabSXin LI 
2413c602fabSXin LI 		/* Option no */
242*ee67461eSJoseph Mingrone 		option_no = GET_U_1(cp);
2433c602fabSXin LI 		cp += 1;
244*ee67461eSJoseph Mingrone 		len -= 1;
245*ee67461eSJoseph Mingrone 		ND_PRINT("\n\t %s", tok2str(ahcp1_opt_str, "Unknown-%u", option_no));
2463c602fabSXin LI 		if (option_no == AHCP1_OPT_PAD || option_no == AHCP1_OPT_MANDATORY)
2473c602fabSXin LI 			continue;
2483c602fabSXin LI 		/* Length */
249*ee67461eSJoseph Mingrone 		if (!len)
2503340d773SGleb Smirnoff 			goto invalid;
251*ee67461eSJoseph Mingrone 		option_len = GET_U_1(cp);
2523c602fabSXin LI 		cp += 1;
253*ee67461eSJoseph Mingrone 		len -= 1;
254*ee67461eSJoseph Mingrone 		if (option_len > len)
2553340d773SGleb Smirnoff 			goto invalid;
2563c602fabSXin LI 		/* Value */
2573c602fabSXin LI 		if (option_no <= AHCP1_OPT_MAX && data_decoders[option_no] != NULL) {
258*ee67461eSJoseph Mingrone 			data_decoders[option_no](ndo, cp, option_len);
2593c602fabSXin LI 		} else {
260*ee67461eSJoseph Mingrone 			ND_PRINT(" (Length %u)", option_len);
261*ee67461eSJoseph Mingrone 			ND_TCHECK_LEN(cp, option_len);
2623c602fabSXin LI 		}
2633c602fabSXin LI 		cp += option_len;
264*ee67461eSJoseph Mingrone 		len -= option_len;
2653c602fabSXin LI 	}
2663c602fabSXin LI 	return;
2673c602fabSXin LI 
2683340d773SGleb Smirnoff invalid:
269*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
270*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
2713c602fabSXin LI }
2723c602fabSXin LI 
2733c602fabSXin LI static void
ahcp1_body_print(netdissect_options * ndo,const u_char * cp,u_int len)274*ee67461eSJoseph Mingrone ahcp1_body_print(netdissect_options *ndo,
275*ee67461eSJoseph Mingrone                  const u_char *cp, u_int len)
2768bdc5a62SPatrick Kelsey {
2773c602fabSXin LI 	uint8_t type, mbz;
2783c602fabSXin LI 	uint16_t body_len;
2793c602fabSXin LI 
280*ee67461eSJoseph Mingrone 	if (len < AHCP1_BODY_MIN_LEN)
2813340d773SGleb Smirnoff 		goto invalid;
2823c602fabSXin LI 	/* Type */
283*ee67461eSJoseph Mingrone 	type = GET_U_1(cp);
2843c602fabSXin LI 	cp += 1;
285*ee67461eSJoseph Mingrone 	len -= 1;
2863c602fabSXin LI 	/* MBZ */
287*ee67461eSJoseph Mingrone 	mbz = GET_U_1(cp);
2883c602fabSXin LI 	cp += 1;
289*ee67461eSJoseph Mingrone 	len -= 1;
2903c602fabSXin LI 	/* Length */
291*ee67461eSJoseph Mingrone 	body_len = GET_BE_U_2(cp);
2923c602fabSXin LI 	cp += 2;
293*ee67461eSJoseph Mingrone 	len -= 2;
2943c602fabSXin LI 
2953c602fabSXin LI 	if (ndo->ndo_vflag) {
296*ee67461eSJoseph Mingrone 		ND_PRINT("\n\t%s", tok2str(ahcp1_msg_str, "Unknown-%u", type));
2973c602fabSXin LI 		if (mbz != 0)
298*ee67461eSJoseph Mingrone 			ND_PRINT(", MBZ %u", mbz);
299*ee67461eSJoseph Mingrone 		ND_PRINT(", Length %u", body_len);
3003c602fabSXin LI 	}
301*ee67461eSJoseph Mingrone 	if (body_len > len)
3023340d773SGleb Smirnoff 		goto invalid;
3033c602fabSXin LI 
3043c602fabSXin LI 	/* Options */
305*ee67461eSJoseph Mingrone 	/* Here use "body_len", not "len" (ignore any extra data). */
3063c602fabSXin LI 	if (ndo->ndo_vflag >= 2)
307*ee67461eSJoseph Mingrone 		ahcp1_options_print(ndo, cp, body_len);
3083c602fabSXin LI 	else
309*ee67461eSJoseph Mingrone 		ND_TCHECK_LEN(cp, body_len);
3103c602fabSXin LI 	return;
3113c602fabSXin LI 
3123340d773SGleb Smirnoff invalid:
313*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
314*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
315*ee67461eSJoseph Mingrone 
3163c602fabSXin LI }
3173c602fabSXin LI 
3183c602fabSXin LI void
ahcp_print(netdissect_options * ndo,const u_char * cp,u_int len)319*ee67461eSJoseph Mingrone ahcp_print(netdissect_options *ndo,
320*ee67461eSJoseph Mingrone            const u_char *cp, u_int len)
3218bdc5a62SPatrick Kelsey {
3223c602fabSXin LI 	uint8_t version;
3233c602fabSXin LI 
324*ee67461eSJoseph Mingrone 	ndo->ndo_protocol = "ahcp";
325*ee67461eSJoseph Mingrone 	nd_print_protocol_caps(ndo);
3263c602fabSXin LI 	if (len < 2)
3273340d773SGleb Smirnoff 		goto invalid;
3283c602fabSXin LI 	/* Magic */
329*ee67461eSJoseph Mingrone 	if (GET_U_1(cp) != AHCP_MAGIC_NUMBER)
3303340d773SGleb Smirnoff 		goto invalid;
3313c602fabSXin LI 	cp += 1;
332*ee67461eSJoseph Mingrone 	len -= 1;
3333c602fabSXin LI 	/* Version */
334*ee67461eSJoseph Mingrone 	version = GET_U_1(cp);
3353c602fabSXin LI 	cp += 1;
336*ee67461eSJoseph Mingrone 	len -= 1;
3373c602fabSXin LI 	switch (version) {
3383c602fabSXin LI 		case AHCP_VERSION_1: {
339*ee67461eSJoseph Mingrone 			ND_PRINT(" Version 1");
340*ee67461eSJoseph Mingrone 			if (len < AHCP1_HEADER_FIX_LEN - 2)
3413340d773SGleb Smirnoff 				goto invalid;
3423c602fabSXin LI 			if (!ndo->ndo_vflag) {
343*ee67461eSJoseph Mingrone 				ND_TCHECK_LEN(cp, AHCP1_HEADER_FIX_LEN - 2);
3443c602fabSXin LI 				cp += AHCP1_HEADER_FIX_LEN - 2;
345*ee67461eSJoseph Mingrone 				len -= AHCP1_HEADER_FIX_LEN - 2;
3463c602fabSXin LI 			} else {
3473c602fabSXin LI 				/* Hopcount */
348*ee67461eSJoseph Mingrone 				ND_PRINT("\n\tHopcount %u", GET_U_1(cp));
3493c602fabSXin LI 				cp += 1;
350*ee67461eSJoseph Mingrone 				len -= 1;
3513c602fabSXin LI 				/* Original Hopcount */
352*ee67461eSJoseph Mingrone 				ND_PRINT(", Original Hopcount %u", GET_U_1(cp));
3533c602fabSXin LI 				cp += 1;
354*ee67461eSJoseph Mingrone 				len -= 1;
3553c602fabSXin LI 				/* Nonce */
356*ee67461eSJoseph Mingrone 				ND_PRINT(", Nonce 0x%08x", GET_BE_U_4(cp));
3573c602fabSXin LI 				cp += 4;
358*ee67461eSJoseph Mingrone 				len -= 4;
3593c602fabSXin LI 				/* Source Id */
360*ee67461eSJoseph Mingrone 				ND_PRINT(", Source Id %s", GET_LINKADDR_STRING(cp, LINKADDR_OTHER, 8));
3613c602fabSXin LI 				cp += 8;
362*ee67461eSJoseph Mingrone 				len -= 8;
3633c602fabSXin LI 				/* Destination Id */
364*ee67461eSJoseph Mingrone 				ND_PRINT(", Destination Id %s", GET_LINKADDR_STRING(cp, LINKADDR_OTHER, 8));
3653c602fabSXin LI 				cp += 8;
366*ee67461eSJoseph Mingrone 				len -= 8;
3673c602fabSXin LI 			}
3683c602fabSXin LI 			/* Body */
369*ee67461eSJoseph Mingrone 			ahcp1_body_print(ndo, cp, len);
3703c602fabSXin LI 			break;
3713c602fabSXin LI 		}
3723c602fabSXin LI 		default:
373*ee67461eSJoseph Mingrone 			ND_PRINT(" Version %u (unknown)", version);
374*ee67461eSJoseph Mingrone 			ND_TCHECK_LEN(cp, len);
3753c602fabSXin LI 			break;
3763c602fabSXin LI 	}
3773c602fabSXin LI 	return;
3783c602fabSXin LI 
3793340d773SGleb Smirnoff invalid:
380*ee67461eSJoseph Mingrone 	nd_print_invalid(ndo);
381*ee67461eSJoseph Mingrone 	ND_TCHECK_LEN(cp, len);
3823c602fabSXin LI }
383