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