1*05b00f60SXin Li /*
2*05b00f60SXin Li * Copyright (c) 2013 The TCPDUMP project
3*05b00f60SXin Li * All rights reserved.
4*05b00f60SXin Li *
5*05b00f60SXin Li * Redistribution and use in source and binary forms, with or without
6*05b00f60SXin Li * modification, are permitted provided that the following conditions
7*05b00f60SXin Li * are met:
8*05b00f60SXin Li * 1. Redistributions of source code must retain the above copyright
9*05b00f60SXin Li * notice, this list of conditions and the following disclaimer.
10*05b00f60SXin Li * 2. Redistributions in binary form must reproduce the above copyright
11*05b00f60SXin Li * notice, this list of conditions and the following disclaimer in the
12*05b00f60SXin Li * documentation and/or other materials provided with the distribution.
13*05b00f60SXin Li *
14*05b00f60SXin Li * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15*05b00f60SXin Li * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16*05b00f60SXin Li * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
17*05b00f60SXin Li * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
18*05b00f60SXin Li * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19*05b00f60SXin Li * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20*05b00f60SXin Li * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21*05b00f60SXin Li * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22*05b00f60SXin Li * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*05b00f60SXin Li * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24*05b00f60SXin Li * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25*05b00f60SXin Li * POSSIBILITY OF SUCH DAMAGE.
26*05b00f60SXin Li */
27*05b00f60SXin Li
28*05b00f60SXin Li /* \summary: Ad Hoc Configuration Protocol (AHCP) printer */
29*05b00f60SXin Li
30*05b00f60SXin Li /* Based on draft-chroboczek-ahcp-00 and source code of ahcpd-0.53 */
31*05b00f60SXin Li
32*05b00f60SXin Li #ifdef HAVE_CONFIG_H
33*05b00f60SXin Li #include <config.h>
34*05b00f60SXin Li #endif
35*05b00f60SXin Li
36*05b00f60SXin Li #include "netdissect-stdinc.h"
37*05b00f60SXin Li
38*05b00f60SXin Li #define ND_LONGJMP_FROM_TCHECK
39*05b00f60SXin Li #include "netdissect.h"
40*05b00f60SXin Li #include "extract.h"
41*05b00f60SXin Li #include "addrtoname.h"
42*05b00f60SXin Li
43*05b00f60SXin Li
44*05b00f60SXin Li #define AHCP_MAGIC_NUMBER 43
45*05b00f60SXin Li #define AHCP_VERSION_1 1
46*05b00f60SXin Li #define AHCP1_HEADER_FIX_LEN 24
47*05b00f60SXin Li #define AHCP1_BODY_MIN_LEN 4
48*05b00f60SXin Li
49*05b00f60SXin Li #define AHCP1_MSG_DISCOVER 0
50*05b00f60SXin Li #define AHCP1_MSG_OFFER 1
51*05b00f60SXin Li #define AHCP1_MSG_REQUEST 2
52*05b00f60SXin Li #define AHCP1_MSG_ACK 3
53*05b00f60SXin Li #define AHCP1_MSG_NACK 4
54*05b00f60SXin Li #define AHCP1_MSG_RELEASE 5
55*05b00f60SXin Li
56*05b00f60SXin Li static const struct tok ahcp1_msg_str[] = {
57*05b00f60SXin Li { AHCP1_MSG_DISCOVER, "Discover" },
58*05b00f60SXin Li { AHCP1_MSG_OFFER, "Offer" },
59*05b00f60SXin Li { AHCP1_MSG_REQUEST, "Request" },
60*05b00f60SXin Li { AHCP1_MSG_ACK, "Ack" },
61*05b00f60SXin Li { AHCP1_MSG_NACK, "Nack" },
62*05b00f60SXin Li { AHCP1_MSG_RELEASE, "Release" },
63*05b00f60SXin Li { 0, NULL }
64*05b00f60SXin Li };
65*05b00f60SXin Li
66*05b00f60SXin Li #define AHCP1_OPT_PAD 0
67*05b00f60SXin Li #define AHCP1_OPT_MANDATORY 1
68*05b00f60SXin Li #define AHCP1_OPT_ORIGIN_TIME 2
69*05b00f60SXin Li #define AHCP1_OPT_EXPIRES 3
70*05b00f60SXin Li #define AHCP1_OPT_MY_IPV6_ADDRESS 4
71*05b00f60SXin Li #define AHCP1_OPT_MY_IPV4_ADDRESS 5
72*05b00f60SXin Li #define AHCP1_OPT_IPV6_PREFIX 6
73*05b00f60SXin Li #define AHCP1_OPT_IPV4_PREFIX 7
74*05b00f60SXin Li #define AHCP1_OPT_IPV6_ADDRESS 8
75*05b00f60SXin Li #define AHCP1_OPT_IPV4_ADDRESS 9
76*05b00f60SXin Li #define AHCP1_OPT_IPV6_PREFIX_DELEGATION 10
77*05b00f60SXin Li #define AHCP1_OPT_IPV4_PREFIX_DELEGATION 11
78*05b00f60SXin Li #define AHCP1_OPT_NAME_SERVER 12
79*05b00f60SXin Li #define AHCP1_OPT_NTP_SERVER 13
80*05b00f60SXin Li #define AHCP1_OPT_MAX 13
81*05b00f60SXin Li
82*05b00f60SXin Li static const struct tok ahcp1_opt_str[] = {
83*05b00f60SXin Li { AHCP1_OPT_PAD, "Pad" },
84*05b00f60SXin Li { AHCP1_OPT_MANDATORY, "Mandatory" },
85*05b00f60SXin Li { AHCP1_OPT_ORIGIN_TIME, "Origin Time" },
86*05b00f60SXin Li { AHCP1_OPT_EXPIRES, "Expires" },
87*05b00f60SXin Li { AHCP1_OPT_MY_IPV6_ADDRESS, "My-IPv6-Address" },
88*05b00f60SXin Li { AHCP1_OPT_MY_IPV4_ADDRESS, "My-IPv4-Address" },
89*05b00f60SXin Li { AHCP1_OPT_IPV6_PREFIX, "IPv6 Prefix" },
90*05b00f60SXin Li { AHCP1_OPT_IPV4_PREFIX, "IPv4 Prefix" },
91*05b00f60SXin Li { AHCP1_OPT_IPV6_ADDRESS, "IPv6 Address" },
92*05b00f60SXin Li { AHCP1_OPT_IPV4_ADDRESS, "IPv4 Address" },
93*05b00f60SXin Li { AHCP1_OPT_IPV6_PREFIX_DELEGATION, "IPv6 Prefix Delegation" },
94*05b00f60SXin Li { AHCP1_OPT_IPV4_PREFIX_DELEGATION, "IPv4 Prefix Delegation" },
95*05b00f60SXin Li { AHCP1_OPT_NAME_SERVER, "Name Server" },
96*05b00f60SXin Li { AHCP1_OPT_NTP_SERVER, "NTP Server" },
97*05b00f60SXin Li { 0, NULL }
98*05b00f60SXin Li };
99*05b00f60SXin Li
100*05b00f60SXin Li static void
ahcp_time_print(netdissect_options * ndo,const u_char * cp,uint8_t len)101*05b00f60SXin Li ahcp_time_print(netdissect_options *ndo,
102*05b00f60SXin Li const u_char *cp, uint8_t len)
103*05b00f60SXin Li {
104*05b00f60SXin Li time_t t;
105*05b00f60SXin Li char buf[sizeof("-yyyyyyyyyy-mm-dd hh:mm:ss UTC")];
106*05b00f60SXin Li
107*05b00f60SXin Li if (len != 4)
108*05b00f60SXin Li goto invalid;
109*05b00f60SXin Li t = GET_BE_U_4(cp);
110*05b00f60SXin Li ND_PRINT(": %s",
111*05b00f60SXin Li nd_format_time(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S UTC",
112*05b00f60SXin Li gmtime(&t)));
113*05b00f60SXin Li return;
114*05b00f60SXin Li
115*05b00f60SXin Li invalid:
116*05b00f60SXin Li nd_print_invalid(ndo);
117*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
118*05b00f60SXin Li }
119*05b00f60SXin Li
120*05b00f60SXin Li static void
ahcp_seconds_print(netdissect_options * ndo,const u_char * cp,uint8_t len)121*05b00f60SXin Li ahcp_seconds_print(netdissect_options *ndo,
122*05b00f60SXin Li const u_char *cp, uint8_t len)
123*05b00f60SXin Li {
124*05b00f60SXin Li if (len != 4)
125*05b00f60SXin Li goto invalid;
126*05b00f60SXin Li ND_PRINT(": %us", GET_BE_U_4(cp));
127*05b00f60SXin Li return;
128*05b00f60SXin Li
129*05b00f60SXin Li invalid:
130*05b00f60SXin Li nd_print_invalid(ndo);
131*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
132*05b00f60SXin Li }
133*05b00f60SXin Li
134*05b00f60SXin Li static void
ahcp_ipv6_addresses_print(netdissect_options * ndo,const u_char * cp,uint8_t len)135*05b00f60SXin Li ahcp_ipv6_addresses_print(netdissect_options *ndo,
136*05b00f60SXin Li const u_char *cp, uint8_t len)
137*05b00f60SXin Li {
138*05b00f60SXin Li const char *sep = ": ";
139*05b00f60SXin Li
140*05b00f60SXin Li while (len) {
141*05b00f60SXin Li if (len < 16)
142*05b00f60SXin Li goto invalid;
143*05b00f60SXin Li ND_PRINT("%s%s", sep, GET_IP6ADDR_STRING(cp));
144*05b00f60SXin Li cp += 16;
145*05b00f60SXin Li len -= 16;
146*05b00f60SXin Li sep = ", ";
147*05b00f60SXin Li }
148*05b00f60SXin Li return;
149*05b00f60SXin Li
150*05b00f60SXin Li invalid:
151*05b00f60SXin Li nd_print_invalid(ndo);
152*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
153*05b00f60SXin Li }
154*05b00f60SXin Li
155*05b00f60SXin Li static void
ahcp_ipv4_addresses_print(netdissect_options * ndo,const u_char * cp,uint8_t len)156*05b00f60SXin Li ahcp_ipv4_addresses_print(netdissect_options *ndo,
157*05b00f60SXin Li const u_char *cp, uint8_t len)
158*05b00f60SXin Li {
159*05b00f60SXin Li const char *sep = ": ";
160*05b00f60SXin Li
161*05b00f60SXin Li while (len) {
162*05b00f60SXin Li if (len < 4)
163*05b00f60SXin Li goto invalid;
164*05b00f60SXin Li ND_PRINT("%s%s", sep, GET_IPADDR_STRING(cp));
165*05b00f60SXin Li cp += 4;
166*05b00f60SXin Li len -= 4;
167*05b00f60SXin Li sep = ", ";
168*05b00f60SXin Li }
169*05b00f60SXin Li return;
170*05b00f60SXin Li
171*05b00f60SXin Li invalid:
172*05b00f60SXin Li nd_print_invalid(ndo);
173*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
174*05b00f60SXin Li }
175*05b00f60SXin Li
176*05b00f60SXin Li static void
ahcp_ipv6_prefixes_print(netdissect_options * ndo,const u_char * cp,uint8_t len)177*05b00f60SXin Li ahcp_ipv6_prefixes_print(netdissect_options *ndo,
178*05b00f60SXin Li const u_char *cp, uint8_t len)
179*05b00f60SXin Li {
180*05b00f60SXin Li const char *sep = ": ";
181*05b00f60SXin Li
182*05b00f60SXin Li while (len) {
183*05b00f60SXin Li if (len < 17)
184*05b00f60SXin Li goto invalid;
185*05b00f60SXin Li ND_PRINT("%s%s/%u", sep, GET_IP6ADDR_STRING(cp), GET_U_1(cp + 16));
186*05b00f60SXin Li cp += 17;
187*05b00f60SXin Li len -= 17;
188*05b00f60SXin Li sep = ", ";
189*05b00f60SXin Li }
190*05b00f60SXin Li return;
191*05b00f60SXin Li
192*05b00f60SXin Li invalid:
193*05b00f60SXin Li nd_print_invalid(ndo);
194*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
195*05b00f60SXin Li }
196*05b00f60SXin Li
197*05b00f60SXin Li static void
ahcp_ipv4_prefixes_print(netdissect_options * ndo,const u_char * cp,uint8_t len)198*05b00f60SXin Li ahcp_ipv4_prefixes_print(netdissect_options *ndo,
199*05b00f60SXin Li const u_char *cp, uint8_t len)
200*05b00f60SXin Li {
201*05b00f60SXin Li const char *sep = ": ";
202*05b00f60SXin Li
203*05b00f60SXin Li while (len) {
204*05b00f60SXin Li if (len < 5)
205*05b00f60SXin Li goto invalid;
206*05b00f60SXin Li ND_PRINT("%s%s/%u", sep, GET_IPADDR_STRING(cp), GET_U_1(cp + 4));
207*05b00f60SXin Li cp += 5;
208*05b00f60SXin Li len -= 5;
209*05b00f60SXin Li sep = ", ";
210*05b00f60SXin Li }
211*05b00f60SXin Li return;
212*05b00f60SXin Li
213*05b00f60SXin Li invalid:
214*05b00f60SXin Li nd_print_invalid(ndo);
215*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
216*05b00f60SXin Li }
217*05b00f60SXin Li
218*05b00f60SXin Li static void
219*05b00f60SXin Li (* const data_decoders[AHCP1_OPT_MAX + 1])(netdissect_options *, const u_char *, uint8_t) = {
220*05b00f60SXin Li /* [AHCP1_OPT_PAD] = */ NULL,
221*05b00f60SXin Li /* [AHCP1_OPT_MANDATORY] = */ NULL,
222*05b00f60SXin Li /* [AHCP1_OPT_ORIGIN_TIME] = */ ahcp_time_print,
223*05b00f60SXin Li /* [AHCP1_OPT_EXPIRES] = */ ahcp_seconds_print,
224*05b00f60SXin Li /* [AHCP1_OPT_MY_IPV6_ADDRESS] = */ ahcp_ipv6_addresses_print,
225*05b00f60SXin Li /* [AHCP1_OPT_MY_IPV4_ADDRESS] = */ ahcp_ipv4_addresses_print,
226*05b00f60SXin Li /* [AHCP1_OPT_IPV6_PREFIX] = */ ahcp_ipv6_prefixes_print,
227*05b00f60SXin Li /* [AHCP1_OPT_IPV4_PREFIX] = */ NULL,
228*05b00f60SXin Li /* [AHCP1_OPT_IPV6_ADDRESS] = */ ahcp_ipv6_addresses_print,
229*05b00f60SXin Li /* [AHCP1_OPT_IPV4_ADDRESS] = */ ahcp_ipv4_addresses_print,
230*05b00f60SXin Li /* [AHCP1_OPT_IPV6_PREFIX_DELEGATION] = */ ahcp_ipv6_prefixes_print,
231*05b00f60SXin Li /* [AHCP1_OPT_IPV4_PREFIX_DELEGATION] = */ ahcp_ipv4_prefixes_print,
232*05b00f60SXin Li /* [AHCP1_OPT_NAME_SERVER] = */ ahcp_ipv6_addresses_print,
233*05b00f60SXin Li /* [AHCP1_OPT_NTP_SERVER] = */ ahcp_ipv6_addresses_print,
234*05b00f60SXin Li };
235*05b00f60SXin Li
236*05b00f60SXin Li static void
ahcp1_options_print(netdissect_options * ndo,const u_char * cp,uint16_t len)237*05b00f60SXin Li ahcp1_options_print(netdissect_options *ndo,
238*05b00f60SXin Li const u_char *cp, uint16_t len)
239*05b00f60SXin Li {
240*05b00f60SXin Li while (len) {
241*05b00f60SXin Li uint8_t option_no, option_len;
242*05b00f60SXin Li
243*05b00f60SXin Li /* Option no */
244*05b00f60SXin Li option_no = GET_U_1(cp);
245*05b00f60SXin Li cp += 1;
246*05b00f60SXin Li len -= 1;
247*05b00f60SXin Li ND_PRINT("\n\t %s", tok2str(ahcp1_opt_str, "Unknown-%u", option_no));
248*05b00f60SXin Li if (option_no == AHCP1_OPT_PAD || option_no == AHCP1_OPT_MANDATORY)
249*05b00f60SXin Li continue;
250*05b00f60SXin Li /* Length */
251*05b00f60SXin Li if (!len)
252*05b00f60SXin Li goto invalid;
253*05b00f60SXin Li option_len = GET_U_1(cp);
254*05b00f60SXin Li cp += 1;
255*05b00f60SXin Li len -= 1;
256*05b00f60SXin Li if (option_len > len)
257*05b00f60SXin Li goto invalid;
258*05b00f60SXin Li /* Value */
259*05b00f60SXin Li if (option_no <= AHCP1_OPT_MAX && data_decoders[option_no] != NULL) {
260*05b00f60SXin Li data_decoders[option_no](ndo, cp, option_len);
261*05b00f60SXin Li } else {
262*05b00f60SXin Li ND_PRINT(" (Length %u)", option_len);
263*05b00f60SXin Li ND_TCHECK_LEN(cp, option_len);
264*05b00f60SXin Li }
265*05b00f60SXin Li cp += option_len;
266*05b00f60SXin Li len -= option_len;
267*05b00f60SXin Li }
268*05b00f60SXin Li return;
269*05b00f60SXin Li
270*05b00f60SXin Li invalid:
271*05b00f60SXin Li nd_print_invalid(ndo);
272*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
273*05b00f60SXin Li }
274*05b00f60SXin Li
275*05b00f60SXin Li static void
ahcp1_body_print(netdissect_options * ndo,const u_char * cp,u_int len)276*05b00f60SXin Li ahcp1_body_print(netdissect_options *ndo,
277*05b00f60SXin Li const u_char *cp, u_int len)
278*05b00f60SXin Li {
279*05b00f60SXin Li uint8_t type, mbz;
280*05b00f60SXin Li uint16_t body_len;
281*05b00f60SXin Li
282*05b00f60SXin Li if (len < AHCP1_BODY_MIN_LEN)
283*05b00f60SXin Li goto invalid;
284*05b00f60SXin Li /* Type */
285*05b00f60SXin Li type = GET_U_1(cp);
286*05b00f60SXin Li cp += 1;
287*05b00f60SXin Li len -= 1;
288*05b00f60SXin Li /* MBZ */
289*05b00f60SXin Li mbz = GET_U_1(cp);
290*05b00f60SXin Li cp += 1;
291*05b00f60SXin Li len -= 1;
292*05b00f60SXin Li /* Length */
293*05b00f60SXin Li body_len = GET_BE_U_2(cp);
294*05b00f60SXin Li cp += 2;
295*05b00f60SXin Li len -= 2;
296*05b00f60SXin Li
297*05b00f60SXin Li if (ndo->ndo_vflag) {
298*05b00f60SXin Li ND_PRINT("\n\t%s", tok2str(ahcp1_msg_str, "Unknown-%u", type));
299*05b00f60SXin Li if (mbz != 0)
300*05b00f60SXin Li ND_PRINT(", MBZ %u", mbz);
301*05b00f60SXin Li ND_PRINT(", Length %u", body_len);
302*05b00f60SXin Li }
303*05b00f60SXin Li if (body_len > len)
304*05b00f60SXin Li goto invalid;
305*05b00f60SXin Li
306*05b00f60SXin Li /* Options */
307*05b00f60SXin Li /* Here use "body_len", not "len" (ignore any extra data). */
308*05b00f60SXin Li if (ndo->ndo_vflag >= 2)
309*05b00f60SXin Li ahcp1_options_print(ndo, cp, body_len);
310*05b00f60SXin Li else
311*05b00f60SXin Li ND_TCHECK_LEN(cp, body_len);
312*05b00f60SXin Li return;
313*05b00f60SXin Li
314*05b00f60SXin Li invalid:
315*05b00f60SXin Li nd_print_invalid(ndo);
316*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
317*05b00f60SXin Li
318*05b00f60SXin Li }
319*05b00f60SXin Li
320*05b00f60SXin Li void
ahcp_print(netdissect_options * ndo,const u_char * cp,u_int len)321*05b00f60SXin Li ahcp_print(netdissect_options *ndo,
322*05b00f60SXin Li const u_char *cp, u_int len)
323*05b00f60SXin Li {
324*05b00f60SXin Li uint8_t version;
325*05b00f60SXin Li
326*05b00f60SXin Li ndo->ndo_protocol = "ahcp";
327*05b00f60SXin Li nd_print_protocol_caps(ndo);
328*05b00f60SXin Li if (len < 2)
329*05b00f60SXin Li goto invalid;
330*05b00f60SXin Li /* Magic */
331*05b00f60SXin Li if (GET_U_1(cp) != AHCP_MAGIC_NUMBER)
332*05b00f60SXin Li goto invalid;
333*05b00f60SXin Li cp += 1;
334*05b00f60SXin Li len -= 1;
335*05b00f60SXin Li /* Version */
336*05b00f60SXin Li version = GET_U_1(cp);
337*05b00f60SXin Li cp += 1;
338*05b00f60SXin Li len -= 1;
339*05b00f60SXin Li switch (version) {
340*05b00f60SXin Li case AHCP_VERSION_1: {
341*05b00f60SXin Li ND_PRINT(" Version 1");
342*05b00f60SXin Li if (len < AHCP1_HEADER_FIX_LEN - 2)
343*05b00f60SXin Li goto invalid;
344*05b00f60SXin Li if (!ndo->ndo_vflag) {
345*05b00f60SXin Li ND_TCHECK_LEN(cp, AHCP1_HEADER_FIX_LEN - 2);
346*05b00f60SXin Li cp += AHCP1_HEADER_FIX_LEN - 2;
347*05b00f60SXin Li len -= AHCP1_HEADER_FIX_LEN - 2;
348*05b00f60SXin Li } else {
349*05b00f60SXin Li /* Hopcount */
350*05b00f60SXin Li ND_PRINT("\n\tHopcount %u", GET_U_1(cp));
351*05b00f60SXin Li cp += 1;
352*05b00f60SXin Li len -= 1;
353*05b00f60SXin Li /* Original Hopcount */
354*05b00f60SXin Li ND_PRINT(", Original Hopcount %u", GET_U_1(cp));
355*05b00f60SXin Li cp += 1;
356*05b00f60SXin Li len -= 1;
357*05b00f60SXin Li /* Nonce */
358*05b00f60SXin Li ND_PRINT(", Nonce 0x%08x", GET_BE_U_4(cp));
359*05b00f60SXin Li cp += 4;
360*05b00f60SXin Li len -= 4;
361*05b00f60SXin Li /* Source Id */
362*05b00f60SXin Li ND_PRINT(", Source Id %s", GET_LINKADDR_STRING(cp, LINKADDR_OTHER, 8));
363*05b00f60SXin Li cp += 8;
364*05b00f60SXin Li len -= 8;
365*05b00f60SXin Li /* Destination Id */
366*05b00f60SXin Li ND_PRINT(", Destination Id %s", GET_LINKADDR_STRING(cp, LINKADDR_OTHER, 8));
367*05b00f60SXin Li cp += 8;
368*05b00f60SXin Li len -= 8;
369*05b00f60SXin Li }
370*05b00f60SXin Li /* Body */
371*05b00f60SXin Li ahcp1_body_print(ndo, cp, len);
372*05b00f60SXin Li break;
373*05b00f60SXin Li }
374*05b00f60SXin Li default:
375*05b00f60SXin Li ND_PRINT(" Version %u (unknown)", version);
376*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
377*05b00f60SXin Li break;
378*05b00f60SXin Li }
379*05b00f60SXin Li return;
380*05b00f60SXin Li
381*05b00f60SXin Li invalid:
382*05b00f60SXin Li nd_print_invalid(ndo);
383*05b00f60SXin Li ND_TCHECK_LEN(cp, len);
384*05b00f60SXin Li }
385