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.9.2.2 2003/11/16 08:51:33 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) 172 { 173 const struct ip6_mobility *mh; 174 const struct ip6_hdr *ip6; 175 const u_char *ep; 176 int mhlen, hlen, type; 177 178 mh = (struct ip6_mobility *)bp; 179 ip6 = (struct ip6_hdr *)bp2; 180 181 /* 'ep' points to the end of available data. */ 182 ep = snapend; 183 184 if (!TTEST(mh->ip6m_len)) { 185 /* 186 * There's not enough captured data to include the 187 * mobility header length. 188 * 189 * Our caller expects us to return the length, however, 190 * so return a value that will run to the end of the 191 * captured data. 192 * 193 * XXX - "ip6_print()" doesn't do anything with the 194 * returned length, however, as it breaks out of the 195 * header-processing loop. 196 */ 197 mhlen = ep - bp; 198 goto trunc; 199 } 200 mhlen = (int)((mh->ip6m_len + 1) << 3); 201 202 /* XXX ip6m_cksum */ 203 204 TCHECK(mh->ip6m_type); 205 type = mh->ip6m_type; 206 switch (type) { 207 case IP6M_BINDING_REQUEST: 208 printf("mobility: BRR"); 209 hlen = IP6M_MINLEN; 210 break; 211 case IP6M_HOME_TEST_INIT: 212 case IP6M_CAREOF_TEST_INIT: 213 printf("mobility: %soTI", 214 type == IP6M_HOME_TEST_INIT ? "H" : "C"); 215 hlen = IP6M_MINLEN; 216 if (vflag) { 217 TCHECK2(*mh, hlen + 8); 218 printf(" %s Init Cookie=%08x:%08x", 219 type == IP6M_HOME_TEST_INIT ? "Home" : "Care-of", 220 EXTRACT_32BITS(&bp[hlen]), 221 EXTRACT_32BITS(&bp[hlen + 4])); 222 } 223 hlen += 8; 224 break; 225 case IP6M_HOME_TEST: 226 case IP6M_CAREOF_TEST: 227 printf("mobility: %soT", 228 type == IP6M_HOME_TEST ? "H" : "C"); 229 TCHECK(mh->ip6m_data16[0]); 230 printf(" nonce id=0x%x", EXTRACT_16BITS(&mh->ip6m_data16[0])); 231 hlen = IP6M_MINLEN; 232 if (vflag) { 233 TCHECK2(*mh, hlen + 8); 234 printf(" %s Init Cookie=%08x:%08x", 235 type == IP6M_HOME_TEST ? "Home" : "Care-of", 236 EXTRACT_32BITS(&bp[hlen]), 237 EXTRACT_32BITS(&bp[hlen + 4])); 238 } 239 hlen += 8; 240 if (vflag) { 241 TCHECK2(*mh, hlen + 8); 242 printf(" %s Keygen Token=%08x:%08x", 243 type == IP6M_HOME_TEST ? "Home" : "Care-of", 244 EXTRACT_32BITS(&bp[hlen]), 245 EXTRACT_32BITS(&bp[hlen + 4])); 246 } 247 hlen += 8; 248 break; 249 case IP6M_BINDING_UPDATE: 250 printf("mobility: BU"); 251 TCHECK(mh->ip6m_data16[0]); 252 printf(" seq#=%d", EXTRACT_16BITS(&mh->ip6m_data16[0])); 253 hlen = IP6M_MINLEN; 254 TCHECK2(*mh, hlen + 1); 255 if (bp[hlen] & 0xf0) 256 printf(" "); 257 if (bp[hlen] & 0x80) 258 printf("A"); 259 if (bp[hlen] & 0x40) 260 printf("H"); 261 if (bp[hlen] & 0x20) 262 printf("L"); 263 if (bp[hlen] & 0x10) 264 printf("K"); 265 /* Reserved (4bits) */ 266 hlen += 1; 267 /* Reserved (8bits) */ 268 hlen += 1; 269 TCHECK2(*mh, hlen + 2); 270 /* units of 4 secs */ 271 printf(" lifetime=%d", EXTRACT_16BITS(&bp[hlen]) << 2); 272 hlen += 2; 273 break; 274 case IP6M_BINDING_ACK: 275 printf("mobility: BA"); 276 TCHECK(mh->ip6m_data8[0]); 277 printf(" status=%d", mh->ip6m_data8[0]); 278 if (mh->ip6m_data8[1] & 0x80) 279 printf(" K"); 280 /* Reserved (7bits) */ 281 hlen = IP6M_MINLEN; 282 TCHECK2(*mh, hlen + 2); 283 printf(" seq#=%d", EXTRACT_16BITS(&bp[hlen])); 284 hlen += 2; 285 TCHECK2(*mh, hlen + 2); 286 /* units of 4 secs */ 287 printf(" lifetime=%d", EXTRACT_16BITS(&bp[hlen]) << 2); 288 hlen += 2; 289 break; 290 case IP6M_BINDING_ERROR: 291 printf("mobility: BE"); 292 TCHECK(mh->ip6m_data8[0]); 293 printf(" status=%d", mh->ip6m_data8[0]); 294 /* Reserved */ 295 hlen = IP6M_MINLEN; 296 TCHECK2(*mh, hlen + 16); 297 printf(" homeaddr %s", ip6addr_string(&bp[hlen])); 298 hlen += 16; 299 break; 300 default: 301 printf("mobility: type-#%d len=%d", type, mh->ip6m_len); 302 return(mhlen); 303 break; 304 } 305 if (vflag) 306 mobility_opt_print(&bp[hlen], mhlen - hlen); 307 308 return(mhlen); 309 310 trunc: 311 fputs("[|MOBILITY]", stdout); 312 return(mhlen); 313 } 314 #endif /* INET6 */ 315