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