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 #ifdef HAVE_CONFIG_H 31 #include "config.h" 32 #endif 33 34 #include <sys/cdefs.h> 35 #ifndef lint 36 #if 0 37 static const char rcsid[] _U_ = 38 "@(#) Header: /tcpdump/master/tcpdump/print-mobility.c,v 1.12 2005-04-20 22:21:00 guy Exp"; 39 #else 40 __RCSID("$NetBSD: print-mobility.c,v 1.2 2010/12/05 05:11:30 christos Exp $"); 41 #endif 42 #endif 43 44 #ifdef INET6 45 #include <tcpdump-stdinc.h> 46 47 #include <stdio.h> 48 49 #include "ip6.h" 50 51 #include "interface.h" 52 #include "addrtoname.h" 53 #include "extract.h" /* must come after interface.h */ 54 55 /* Mobility header */ 56 struct ip6_mobility { 57 u_int8_t ip6m_pproto; /* following payload protocol (for PG) */ 58 u_int8_t ip6m_len; /* length in units of 8 octets */ 59 u_int8_t ip6m_type; /* message type */ 60 u_int8_t reserved; /* reserved */ 61 u_int16_t ip6m_cksum; /* sum of IPv6 pseudo-header and MH */ 62 union { 63 u_int16_t ip6m_un_data16[1]; /* type-specific field */ 64 u_int8_t ip6m_un_data8[2]; /* type-specific fiedl */ 65 } ip6m_dataun; 66 }; 67 68 #define ip6m_data16 ip6m_dataun.ip6m_un_data16 69 #define ip6m_data8 ip6m_dataun.ip6m_un_data8 70 71 #define IP6M_MINLEN 8 72 73 /* message type */ 74 #define IP6M_BINDING_REQUEST 0 /* Binding Refresh Request */ 75 #define IP6M_HOME_TEST_INIT 1 /* Home Test Init */ 76 #define IP6M_CAREOF_TEST_INIT 2 /* Care-of Test Init */ 77 #define IP6M_HOME_TEST 3 /* Home Test */ 78 #define IP6M_CAREOF_TEST 4 /* Care-of Test */ 79 #define IP6M_BINDING_UPDATE 5 /* Binding Update */ 80 #define IP6M_BINDING_ACK 6 /* Binding Acknowledgement */ 81 #define IP6M_BINDING_ERROR 7 /* Binding Error */ 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 96 static void 97 mobility_opt_print(const u_char *bp, int len) 98 { 99 int i; 100 int 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 printf("(pad1)"); 117 break; 118 case IP6MOPT_PADN: 119 if (len - i < IP6MOPT_MINLEN) { 120 printf("(padn: trunc)"); 121 goto trunc; 122 } 123 printf("(padn)"); 124 break; 125 case IP6MOPT_REFRESH: 126 if (len - i < IP6MOPT_REFRESH_MINLEN) { 127 printf("(refresh: trunc)"); 128 goto trunc; 129 } 130 /* units of 4 secs */ 131 printf("(refresh: %d)", 132 EXTRACT_16BITS(&bp[i+2]) << 2); 133 break; 134 case IP6MOPT_ALTCOA: 135 if (len - i < IP6MOPT_ALTCOA_MINLEN) { 136 printf("(altcoa: trunc)"); 137 goto trunc; 138 } 139 printf("(alt-CoA: %s)", ip6addr_string(&bp[i+2])); 140 break; 141 case IP6MOPT_NONCEID: 142 if (len - i < IP6MOPT_NONCEID_MINLEN) { 143 printf("(ni: trunc)"); 144 goto trunc; 145 } 146 printf("(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 printf("(auth: trunc)"); 153 goto trunc; 154 } 155 printf("(auth)"); 156 break; 157 default: 158 if (len - i < IP6MOPT_MINLEN) { 159 printf("(sopt_type %d: trunc)", bp[i]); 160 goto trunc; 161 } 162 printf("(type-0x%02x: len=%d)", bp[i], bp[i + 1]); 163 break; 164 } 165 } 166 return; 167 168 trunc: 169 printf("[trunc] "); 170 } 171 172 /* 173 * Mobility Header 174 */ 175 int 176 mobility_print(const u_char *bp, const u_char *bp2 _U_) 177 { 178 const struct ip6_mobility *mh; 179 const u_char *ep; 180 int mhlen, hlen, type; 181 182 mh = (struct ip6_mobility *)bp; 183 184 /* 'ep' points to the end of available data. */ 185 ep = snapend; 186 187 if (!TTEST(mh->ip6m_len)) { 188 /* 189 * There's not enough captured data to include the 190 * mobility header length. 191 * 192 * Our caller expects us to return the length, however, 193 * so return a value that will run to the end of the 194 * captured data. 195 * 196 * XXX - "ip6_print()" doesn't do anything with the 197 * returned length, however, as it breaks out of the 198 * header-processing loop. 199 */ 200 mhlen = ep - bp; 201 goto trunc; 202 } 203 mhlen = (int)((mh->ip6m_len + 1) << 3); 204 205 /* XXX ip6m_cksum */ 206 207 TCHECK(mh->ip6m_type); 208 type = mh->ip6m_type; 209 switch (type) { 210 case IP6M_BINDING_REQUEST: 211 printf("mobility: BRR"); 212 hlen = IP6M_MINLEN; 213 break; 214 case IP6M_HOME_TEST_INIT: 215 case IP6M_CAREOF_TEST_INIT: 216 printf("mobility: %soTI", 217 type == IP6M_HOME_TEST_INIT ? "H" : "C"); 218 hlen = IP6M_MINLEN; 219 if (vflag) { 220 TCHECK2(*mh, hlen + 8); 221 printf(" %s Init Cookie=%08x:%08x", 222 type == IP6M_HOME_TEST_INIT ? "Home" : "Care-of", 223 EXTRACT_32BITS(&bp[hlen]), 224 EXTRACT_32BITS(&bp[hlen + 4])); 225 } 226 hlen += 8; 227 break; 228 case IP6M_HOME_TEST: 229 case IP6M_CAREOF_TEST: 230 printf("mobility: %soT", 231 type == IP6M_HOME_TEST ? "H" : "C"); 232 TCHECK(mh->ip6m_data16[0]); 233 printf(" nonce id=0x%x", EXTRACT_16BITS(&mh->ip6m_data16[0])); 234 hlen = IP6M_MINLEN; 235 if (vflag) { 236 TCHECK2(*mh, hlen + 8); 237 printf(" %s Init Cookie=%08x:%08x", 238 type == IP6M_HOME_TEST ? "Home" : "Care-of", 239 EXTRACT_32BITS(&bp[hlen]), 240 EXTRACT_32BITS(&bp[hlen + 4])); 241 } 242 hlen += 8; 243 if (vflag) { 244 TCHECK2(*mh, hlen + 8); 245 printf(" %s Keygen Token=%08x:%08x", 246 type == IP6M_HOME_TEST ? "Home" : "Care-of", 247 EXTRACT_32BITS(&bp[hlen]), 248 EXTRACT_32BITS(&bp[hlen + 4])); 249 } 250 hlen += 8; 251 break; 252 case IP6M_BINDING_UPDATE: 253 printf("mobility: BU"); 254 TCHECK(mh->ip6m_data16[0]); 255 printf(" seq#=%d", EXTRACT_16BITS(&mh->ip6m_data16[0])); 256 hlen = IP6M_MINLEN; 257 TCHECK2(*mh, hlen + 1); 258 if (bp[hlen] & 0xf0) 259 printf(" "); 260 if (bp[hlen] & 0x80) 261 printf("A"); 262 if (bp[hlen] & 0x40) 263 printf("H"); 264 if (bp[hlen] & 0x20) 265 printf("L"); 266 if (bp[hlen] & 0x10) 267 printf("K"); 268 /* Reserved (4bits) */ 269 hlen += 1; 270 /* Reserved (8bits) */ 271 hlen += 1; 272 TCHECK2(*mh, hlen + 2); 273 /* units of 4 secs */ 274 printf(" lifetime=%d", EXTRACT_16BITS(&bp[hlen]) << 2); 275 hlen += 2; 276 break; 277 case IP6M_BINDING_ACK: 278 printf("mobility: BA"); 279 TCHECK(mh->ip6m_data8[0]); 280 printf(" status=%d", mh->ip6m_data8[0]); 281 if (mh->ip6m_data8[1] & 0x80) 282 printf(" K"); 283 /* Reserved (7bits) */ 284 hlen = IP6M_MINLEN; 285 TCHECK2(*mh, hlen + 2); 286 printf(" seq#=%d", EXTRACT_16BITS(&bp[hlen])); 287 hlen += 2; 288 TCHECK2(*mh, hlen + 2); 289 /* units of 4 secs */ 290 printf(" lifetime=%d", EXTRACT_16BITS(&bp[hlen]) << 2); 291 hlen += 2; 292 break; 293 case IP6M_BINDING_ERROR: 294 printf("mobility: BE"); 295 TCHECK(mh->ip6m_data8[0]); 296 printf(" status=%d", mh->ip6m_data8[0]); 297 /* Reserved */ 298 hlen = IP6M_MINLEN; 299 TCHECK2(*mh, hlen + 16); 300 printf(" homeaddr %s", ip6addr_string(&bp[hlen])); 301 hlen += 16; 302 break; 303 default: 304 printf("mobility: type-#%d len=%d", type, mh->ip6m_len); 305 return(mhlen); 306 break; 307 } 308 if (vflag) 309 mobility_opt_print(&bp[hlen], mhlen - hlen); 310 311 return(mhlen); 312 313 trunc: 314 fputs("[|MOBILITY]", stdout); 315 return(mhlen); 316 } 317 #endif /* INET6 */ 318