print-mobility.c revision 1.4
1/* 2 * Copyright (C) 2002 WIDE Project. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the project nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> 31#ifndef lint 32__RCSID("$NetBSD: print-mobility.c,v 1.4 2014/11/20 03:05:03 christos Exp $"); 33#endif 34 35#define NETDISSECT_REWORKED 36#ifdef HAVE_CONFIG_H 37#include "config.h" 38#endif 39 40#ifdef INET6 41#include <tcpdump-stdinc.h> 42 43#include "ip6.h" 44#include "interface.h" 45#include "addrtoname.h" 46#include "extract.h" /* must come after interface.h */ 47 48/* Mobility header */ 49struct ip6_mobility { 50 uint8_t ip6m_pproto; /* following payload protocol (for PG) */ 51 uint8_t ip6m_len; /* length in units of 8 octets */ 52 uint8_t ip6m_type; /* message type */ 53 uint8_t reserved; /* reserved */ 54 uint16_t ip6m_cksum; /* sum of IPv6 pseudo-header and MH */ 55 union { 56 uint16_t ip6m_un_data16[1]; /* type-specific field */ 57 uint8_t ip6m_un_data8[2]; /* type-specific field */ 58 } ip6m_dataun; 59}; 60 61#define ip6m_data16 ip6m_dataun.ip6m_un_data16 62#define ip6m_data8 ip6m_dataun.ip6m_un_data8 63 64#define IP6M_MINLEN 8 65 66/* http://www.iana.org/assignments/mobility-parameters/mobility-parameters.xhtml */ 67 68/* message type */ 69#define IP6M_BINDING_REQUEST 0 /* Binding Refresh Request */ 70#define IP6M_HOME_TEST_INIT 1 /* Home Test Init */ 71#define IP6M_CAREOF_TEST_INIT 2 /* Care-of Test Init */ 72#define IP6M_HOME_TEST 3 /* Home Test */ 73#define IP6M_CAREOF_TEST 4 /* Care-of Test */ 74#define IP6M_BINDING_UPDATE 5 /* Binding Update */ 75#define IP6M_BINDING_ACK 6 /* Binding Acknowledgement */ 76#define IP6M_BINDING_ERROR 7 /* Binding Error */ 77 78/* XXX: unused */ 79#define IP6MOPT_BU_MINLEN 10 80#define IP6MOPT_BA_MINLEN 13 81#define IP6MOPT_BR_MINLEN 2 82 83/* Mobility Header Options */ 84#define IP6MOPT_MINLEN 2 85#define IP6MOPT_PAD1 0x0 /* Pad1 */ 86#define IP6MOPT_PADN 0x1 /* PadN */ 87#define IP6MOPT_REFRESH 0x2 /* Binding Refresh Advice */ 88#define IP6MOPT_REFRESH_MINLEN 4 89#define IP6MOPT_ALTCOA 0x3 /* Alternate Care-of Address */ 90#define IP6MOPT_ALTCOA_MINLEN 18 91#define IP6MOPT_NONCEID 0x4 /* Nonce Indices */ 92#define IP6MOPT_NONCEID_MINLEN 6 93#define IP6MOPT_AUTH 0x5 /* Binding Authorization Data */ 94#define IP6MOPT_AUTH_MINLEN 12 95 96static void 97mobility_opt_print(netdissect_options *ndo, 98 const u_char *bp, const unsigned len) 99{ 100 unsigned i, optlen; 101 102 for (i = 0; i < len; i += optlen) { 103 if (bp[i] == IP6MOPT_PAD1) 104 optlen = 1; 105 else { 106 if (i + 1 < len) 107 optlen = bp[i + 1] + 2; 108 else 109 goto trunc; 110 } 111 if (i + optlen > len) 112 goto trunc; 113 114 switch (bp[i]) { 115 case IP6MOPT_PAD1: 116 ND_PRINT((ndo, "(pad1)")); 117 break; 118 case IP6MOPT_PADN: 119 if (len - i < IP6MOPT_MINLEN) { 120 ND_PRINT((ndo, "(padn: trunc)")); 121 goto trunc; 122 } 123 ND_PRINT((ndo, "(padn)")); 124 break; 125 case IP6MOPT_REFRESH: 126 if (len - i < IP6MOPT_REFRESH_MINLEN) { 127 ND_PRINT((ndo, "(refresh: trunc)")); 128 goto trunc; 129 } 130 /* units of 4 secs */ 131 ND_PRINT((ndo, "(refresh: %u)", 132 EXTRACT_16BITS(&bp[i+2]) << 2)); 133 break; 134 case IP6MOPT_ALTCOA: 135 if (len - i < IP6MOPT_ALTCOA_MINLEN) { 136 ND_PRINT((ndo, "(altcoa: trunc)")); 137 goto trunc; 138 } 139 ND_PRINT((ndo, "(alt-CoA: %s)", ip6addr_string(ndo, &bp[i+2]))); 140 break; 141 case IP6MOPT_NONCEID: 142 if (len - i < IP6MOPT_NONCEID_MINLEN) { 143 ND_PRINT((ndo, "(ni: trunc)")); 144 goto trunc; 145 } 146 ND_PRINT((ndo, "(ni: ho=0x%04x co=0x%04x)", 147 EXTRACT_16BITS(&bp[i+2]), 148 EXTRACT_16BITS(&bp[i+4]))); 149 break; 150 case IP6MOPT_AUTH: 151 if (len - i < IP6MOPT_AUTH_MINLEN) { 152 ND_PRINT((ndo, "(auth: trunc)")); 153 goto trunc; 154 } 155 ND_PRINT((ndo, "(auth)")); 156 break; 157 default: 158 if (len - i < IP6MOPT_MINLEN) { 159 ND_PRINT((ndo, "(sopt_type %u: trunc)", bp[i])); 160 goto trunc; 161 } 162 ND_PRINT((ndo, "(type-0x%02x: len=%u)", bp[i], bp[i + 1])); 163 break; 164 } 165 } 166 return; 167 168trunc: 169 ND_PRINT((ndo, "[trunc] ")); 170} 171 172/* 173 * Mobility Header 174 */ 175int 176mobility_print(netdissect_options *ndo, 177 const u_char *bp, const u_char *bp2 _U_) 178{ 179 const struct ip6_mobility *mh; 180 const u_char *ep; 181 unsigned mhlen, hlen; 182 uint8_t type; 183 184 mh = (struct ip6_mobility *)bp; 185 186 /* 'ep' points to the end of available data. */ 187 ep = ndo->ndo_snapend; 188 189 if (!ND_TTEST(mh->ip6m_len)) { 190 /* 191 * There's not enough captured data to include the 192 * mobility header length. 193 * 194 * Our caller expects us to return the length, however, 195 * so return a value that will run to the end of the 196 * captured data. 197 * 198 * XXX - "ip6_print()" doesn't do anything with the 199 * returned length, however, as it breaks out of the 200 * header-processing loop. 201 */ 202 mhlen = ep - bp; 203 goto trunc; 204 } 205 mhlen = (mh->ip6m_len + 1) << 3; 206 207 /* XXX ip6m_cksum */ 208 209 ND_TCHECK(mh->ip6m_type); 210 type = mh->ip6m_type; 211 switch (type) { 212 case IP6M_BINDING_REQUEST: 213 ND_PRINT((ndo, "mobility: BRR")); 214 hlen = IP6M_MINLEN; 215 break; 216 case IP6M_HOME_TEST_INIT: 217 case IP6M_CAREOF_TEST_INIT: 218 ND_PRINT((ndo, "mobility: %soTI", 219 type == IP6M_HOME_TEST_INIT ? "H" : "C")); 220 hlen = IP6M_MINLEN; 221 if (ndo->ndo_vflag) { 222 ND_TCHECK2(*mh, hlen + 8); 223 ND_PRINT((ndo, " %s Init Cookie=%08x:%08x", 224 type == IP6M_HOME_TEST_INIT ? "Home" : "Care-of", 225 EXTRACT_32BITS(&bp[hlen]), 226 EXTRACT_32BITS(&bp[hlen + 4]))); 227 } 228 hlen += 8; 229 break; 230 case IP6M_HOME_TEST: 231 case IP6M_CAREOF_TEST: 232 ND_PRINT((ndo, "mobility: %soT", 233 type == IP6M_HOME_TEST ? "H" : "C")); 234 ND_TCHECK(mh->ip6m_data16[0]); 235 ND_PRINT((ndo, " nonce id=0x%x", EXTRACT_16BITS(&mh->ip6m_data16[0]))); 236 hlen = IP6M_MINLEN; 237 if (ndo->ndo_vflag) { 238 ND_TCHECK2(*mh, hlen + 8); 239 ND_PRINT((ndo, " %s Init Cookie=%08x:%08x", 240 type == IP6M_HOME_TEST ? "Home" : "Care-of", 241 EXTRACT_32BITS(&bp[hlen]), 242 EXTRACT_32BITS(&bp[hlen + 4]))); 243 } 244 hlen += 8; 245 if (ndo->ndo_vflag) { 246 ND_TCHECK2(*mh, hlen + 8); 247 ND_PRINT((ndo, " %s Keygen Token=%08x:%08x", 248 type == IP6M_HOME_TEST ? "Home" : "Care-of", 249 EXTRACT_32BITS(&bp[hlen]), 250 EXTRACT_32BITS(&bp[hlen + 4]))); 251 } 252 hlen += 8; 253 break; 254 case IP6M_BINDING_UPDATE: 255 ND_PRINT((ndo, "mobility: BU")); 256 ND_TCHECK(mh->ip6m_data16[0]); 257 ND_PRINT((ndo, " seq#=%u", EXTRACT_16BITS(&mh->ip6m_data16[0]))); 258 hlen = IP6M_MINLEN; 259 ND_TCHECK2(*mh, hlen + 1); 260 if (bp[hlen] & 0xf0) 261 ND_PRINT((ndo, " ")); 262 if (bp[hlen] & 0x80) 263 ND_PRINT((ndo, "A")); 264 if (bp[hlen] & 0x40) 265 ND_PRINT((ndo, "H")); 266 if (bp[hlen] & 0x20) 267 ND_PRINT((ndo, "L")); 268 if (bp[hlen] & 0x10) 269 ND_PRINT((ndo, "K")); 270 /* Reserved (4bits) */ 271 hlen += 1; 272 /* Reserved (8bits) */ 273 hlen += 1; 274 ND_TCHECK2(*mh, hlen + 2); 275 /* units of 4 secs */ 276 ND_PRINT((ndo, " lifetime=%u", EXTRACT_16BITS(&bp[hlen]) << 2)); 277 hlen += 2; 278 break; 279 case IP6M_BINDING_ACK: 280 ND_PRINT((ndo, "mobility: BA")); 281 ND_TCHECK(mh->ip6m_data8[0]); 282 ND_PRINT((ndo, " status=%u", mh->ip6m_data8[0])); 283 if (mh->ip6m_data8[1] & 0x80) 284 ND_PRINT((ndo, " K")); 285 /* Reserved (7bits) */ 286 hlen = IP6M_MINLEN; 287 ND_TCHECK2(*mh, hlen + 2); 288 ND_PRINT((ndo, " seq#=%u", EXTRACT_16BITS(&bp[hlen]))); 289 hlen += 2; 290 ND_TCHECK2(*mh, hlen + 2); 291 /* units of 4 secs */ 292 ND_PRINT((ndo, " lifetime=%u", EXTRACT_16BITS(&bp[hlen]) << 2)); 293 hlen += 2; 294 break; 295 case IP6M_BINDING_ERROR: 296 ND_PRINT((ndo, "mobility: BE")); 297 ND_TCHECK(mh->ip6m_data8[0]); 298 ND_PRINT((ndo, " status=%u", mh->ip6m_data8[0])); 299 /* Reserved */ 300 hlen = IP6M_MINLEN; 301 ND_TCHECK2(*mh, hlen + 16); 302 ND_PRINT((ndo, " homeaddr %s", ip6addr_string(ndo, &bp[hlen]))); 303 hlen += 16; 304 break; 305 default: 306 ND_PRINT((ndo, "mobility: type-#%u len=%u", type, mh->ip6m_len)); 307 return(mhlen); 308 break; 309 } 310 if (ndo->ndo_vflag) 311 mobility_opt_print(ndo, &bp[hlen], mhlen - hlen); 312 313 return(mhlen); 314 315 trunc: 316 ND_PRINT((ndo, "[|MOBILITY]")); 317 return(mhlen); 318} 319#endif /* INET6 */ 320