print-mobility.c revision 127668
1127668Sbms/* 2127668Sbms * Copyright (C) 2002 WIDE Project. 3127668Sbms * All rights reserved. 4127668Sbms * 5127668Sbms * Redistribution and use in source and binary forms, with or without 6127668Sbms * modification, are permitted provided that the following conditions 7127668Sbms * are met: 8127668Sbms * 1. Redistributions of source code must retain the above copyright 9127668Sbms * notice, this list of conditions and the following disclaimer. 10127668Sbms * 2. Redistributions in binary form must reproduce the above copyright 11127668Sbms * notice, this list of conditions and the following disclaimer in the 12127668Sbms * documentation and/or other materials provided with the distribution. 13127668Sbms * 3. Neither the name of the project nor the names of its contributors 14127668Sbms * may be used to endorse or promote products derived from this software 15127668Sbms * without specific prior written permission. 16127668Sbms * 17127668Sbms * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18127668Sbms * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19127668Sbms * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20127668Sbms * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21127668Sbms * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22127668Sbms * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23127668Sbms * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24127668Sbms * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25127668Sbms * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26127668Sbms * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27127668Sbms * SUCH DAMAGE. 28127668Sbms */ 29127668Sbms 30127668Sbms#ifdef HAVE_CONFIG_H 31127668Sbms#include "config.h" 32127668Sbms#endif 33127668Sbms 34127668Sbms#ifndef lint 35127668Sbmsstatic const char rcsid[] _U_ = 36127668Sbms "@(#) $Header: /tcpdump/master/tcpdump/print-mobility.c,v 1.9.2.2 2003/11/16 08:51:33 guy Exp $"; 37127668Sbms#endif 38127668Sbms 39127668Sbms#ifdef INET6 40127668Sbms#include <tcpdump-stdinc.h> 41127668Sbms 42127668Sbms#include <stdio.h> 43127668Sbms 44127668Sbms#include "ip6.h" 45127668Sbms 46127668Sbms#include "interface.h" 47127668Sbms#include "addrtoname.h" 48127668Sbms#include "extract.h" /* must come after interface.h */ 49127668Sbms 50127668Sbms/* Mobility header */ 51127668Sbmsstruct ip6_mobility { 52127668Sbms u_int8_t ip6m_pproto; /* following payload protocol (for PG) */ 53127668Sbms u_int8_t ip6m_len; /* length in units of 8 octets */ 54127668Sbms u_int8_t ip6m_type; /* message type */ 55127668Sbms u_int8_t reserved; /* reserved */ 56127668Sbms u_int16_t ip6m_cksum; /* sum of IPv6 pseudo-header and MH */ 57127668Sbms union { 58127668Sbms u_int16_t ip6m_un_data16[1]; /* type-specific field */ 59127668Sbms u_int8_t ip6m_un_data8[2]; /* type-specific fiedl */ 60127668Sbms } ip6m_dataun; 61127668Sbms}; 62127668Sbms 63127668Sbms#define ip6m_data16 ip6m_dataun.ip6m_un_data16 64127668Sbms#define ip6m_data8 ip6m_dataun.ip6m_un_data8 65127668Sbms 66127668Sbms#define IP6M_MINLEN 8 67127668Sbms 68127668Sbms/* message type */ 69127668Sbms#define IP6M_BINDING_REQUEST 0 /* Binding Refresh Request */ 70127668Sbms#define IP6M_HOME_TEST_INIT 1 /* Home Test Init */ 71127668Sbms#define IP6M_CAREOF_TEST_INIT 2 /* Care-of Test Init */ 72127668Sbms#define IP6M_HOME_TEST 3 /* Home Test */ 73127668Sbms#define IP6M_CAREOF_TEST 4 /* Care-of Test */ 74127668Sbms#define IP6M_BINDING_UPDATE 5 /* Binding Update */ 75127668Sbms#define IP6M_BINDING_ACK 6 /* Binding Acknowledgement */ 76127668Sbms#define IP6M_BINDING_ERROR 7 /* Binding Error */ 77127668Sbms 78127668Sbms/* Mobility Header Options */ 79127668Sbms#define IP6MOPT_MINLEN 2 80127668Sbms#define IP6MOPT_PAD1 0x0 /* Pad1 */ 81127668Sbms#define IP6MOPT_PADN 0x1 /* PadN */ 82127668Sbms#define IP6MOPT_REFRESH 0x2 /* Binding Refresh Advice */ 83127668Sbms#define IP6MOPT_REFRESH_MINLEN 4 84127668Sbms#define IP6MOPT_ALTCOA 0x3 /* Alternate Care-of Address */ 85127668Sbms#define IP6MOPT_ALTCOA_MINLEN 18 86127668Sbms#define IP6MOPT_NONCEID 0x4 /* Nonce Indices */ 87127668Sbms#define IP6MOPT_NONCEID_MINLEN 6 88127668Sbms#define IP6MOPT_AUTH 0x5 /* Binding Authorization Data */ 89127668Sbms#define IP6MOPT_AUTH_MINLEN 12 90127668Sbms 91127668Sbmsstatic void 92127668Sbmsmobility_opt_print(const u_char *bp, int len) 93127668Sbms{ 94127668Sbms int i; 95127668Sbms int optlen; 96127668Sbms 97127668Sbms for (i = 0; i < len; i += optlen) { 98127668Sbms if (bp[i] == IP6MOPT_PAD1) 99127668Sbms optlen = 1; 100127668Sbms else { 101127668Sbms if (i + 1 < len) 102127668Sbms optlen = bp[i + 1] + 2; 103127668Sbms else 104127668Sbms goto trunc; 105127668Sbms } 106127668Sbms if (i + optlen > len) 107127668Sbms goto trunc; 108127668Sbms 109127668Sbms switch (bp[i]) { 110127668Sbms case IP6MOPT_PAD1: 111127668Sbms printf("(pad1)"); 112127668Sbms break; 113127668Sbms case IP6MOPT_PADN: 114127668Sbms if (len - i < IP6MOPT_MINLEN) { 115127668Sbms printf("(padn: trunc)"); 116127668Sbms goto trunc; 117127668Sbms } 118127668Sbms printf("(padn)"); 119127668Sbms break; 120127668Sbms case IP6MOPT_REFRESH: 121127668Sbms if (len - i < IP6MOPT_REFRESH_MINLEN) { 122127668Sbms printf("(refresh: trunc)"); 123127668Sbms goto trunc; 124127668Sbms } 125127668Sbms /* units of 4 secs */ 126127668Sbms printf("(refresh: %d)", 127127668Sbms EXTRACT_16BITS(&bp[i+2]) << 2); 128127668Sbms break; 129127668Sbms case IP6MOPT_ALTCOA: 130127668Sbms if (len - i < IP6MOPT_ALTCOA_MINLEN) { 131127668Sbms printf("(altcoa: trunc)"); 132127668Sbms goto trunc; 133127668Sbms } 134127668Sbms printf("(alt-CoA: %s)", ip6addr_string(&bp[i+2])); 135127668Sbms break; 136127668Sbms case IP6MOPT_NONCEID: 137127668Sbms if (len - i < IP6MOPT_NONCEID_MINLEN) { 138127668Sbms printf("(ni: trunc)"); 139127668Sbms goto trunc; 140127668Sbms } 141127668Sbms printf("(ni: ho=0x%04x co=0x%04x)", 142127668Sbms EXTRACT_16BITS(&bp[i+2]), 143127668Sbms EXTRACT_16BITS(&bp[i+4])); 144127668Sbms break; 145127668Sbms case IP6MOPT_AUTH: 146127668Sbms if (len - i < IP6MOPT_AUTH_MINLEN) { 147127668Sbms printf("(auth: trunc)"); 148127668Sbms goto trunc; 149127668Sbms } 150127668Sbms printf("(auth)"); 151127668Sbms break; 152127668Sbms default: 153127668Sbms if (len - i < IP6MOPT_MINLEN) { 154127668Sbms printf("(sopt_type %d: trunc)", bp[i]); 155127668Sbms goto trunc; 156127668Sbms } 157127668Sbms printf("(type-0x%02x: len=%d)", bp[i], bp[i + 1]); 158127668Sbms break; 159127668Sbms } 160127668Sbms } 161127668Sbms return; 162127668Sbms 163127668Sbmstrunc: 164127668Sbms printf("[trunc] "); 165127668Sbms} 166127668Sbms 167127668Sbms/* 168127668Sbms * Mobility Header 169127668Sbms */ 170127668Sbmsint 171127668Sbmsmobility_print(const u_char *bp, const u_char *bp2) 172127668Sbms{ 173127668Sbms const struct ip6_mobility *mh; 174127668Sbms const struct ip6_hdr *ip6; 175127668Sbms const u_char *ep; 176127668Sbms int mhlen, hlen, type; 177127668Sbms 178127668Sbms mh = (struct ip6_mobility *)bp; 179127668Sbms ip6 = (struct ip6_hdr *)bp2; 180127668Sbms 181127668Sbms /* 'ep' points to the end of available data. */ 182127668Sbms ep = snapend; 183127668Sbms 184127668Sbms if (!TTEST(mh->ip6m_len)) { 185127668Sbms /* 186127668Sbms * There's not enough captured data to include the 187127668Sbms * mobility header length. 188127668Sbms * 189127668Sbms * Our caller expects us to return the length, however, 190127668Sbms * so return a value that will run to the end of the 191127668Sbms * captured data. 192127668Sbms * 193127668Sbms * XXX - "ip6_print()" doesn't do anything with the 194127668Sbms * returned length, however, as it breaks out of the 195127668Sbms * header-processing loop. 196127668Sbms */ 197127668Sbms mhlen = ep - bp; 198127668Sbms goto trunc; 199127668Sbms } 200127668Sbms mhlen = (int)((mh->ip6m_len + 1) << 3); 201127668Sbms 202127668Sbms /* XXX ip6m_cksum */ 203127668Sbms 204127668Sbms TCHECK(mh->ip6m_type); 205127668Sbms type = mh->ip6m_type; 206127668Sbms switch (type) { 207127668Sbms case IP6M_BINDING_REQUEST: 208127668Sbms printf("mobility: BRR"); 209127668Sbms hlen = IP6M_MINLEN; 210127668Sbms break; 211127668Sbms case IP6M_HOME_TEST_INIT: 212127668Sbms case IP6M_CAREOF_TEST_INIT: 213127668Sbms printf("mobility: %soTI", 214127668Sbms type == IP6M_HOME_TEST_INIT ? "H" : "C"); 215127668Sbms hlen = IP6M_MINLEN; 216127668Sbms if (vflag) { 217127668Sbms TCHECK2(*mh, hlen + 8); 218127668Sbms printf(" %s Init Cookie=%08x:%08x", 219127668Sbms type == IP6M_HOME_TEST_INIT ? "Home" : "Care-of", 220127668Sbms EXTRACT_32BITS(&bp[hlen]), 221127668Sbms EXTRACT_32BITS(&bp[hlen + 4])); 222127668Sbms } 223127668Sbms hlen += 8; 224127668Sbms break; 225127668Sbms case IP6M_HOME_TEST: 226127668Sbms case IP6M_CAREOF_TEST: 227127668Sbms printf("mobility: %soT", 228127668Sbms type == IP6M_HOME_TEST ? "H" : "C"); 229127668Sbms TCHECK(mh->ip6m_data16[0]); 230127668Sbms printf(" nonce id=0x%x", EXTRACT_16BITS(&mh->ip6m_data16[0])); 231127668Sbms hlen = IP6M_MINLEN; 232127668Sbms if (vflag) { 233127668Sbms TCHECK2(*mh, hlen + 8); 234127668Sbms printf(" %s Init Cookie=%08x:%08x", 235127668Sbms type == IP6M_HOME_TEST ? "Home" : "Care-of", 236127668Sbms EXTRACT_32BITS(&bp[hlen]), 237127668Sbms EXTRACT_32BITS(&bp[hlen + 4])); 238127668Sbms } 239127668Sbms hlen += 8; 240127668Sbms if (vflag) { 241127668Sbms TCHECK2(*mh, hlen + 8); 242127668Sbms printf(" %s Keygen Token=%08x:%08x", 243127668Sbms type == IP6M_HOME_TEST ? "Home" : "Care-of", 244127668Sbms EXTRACT_32BITS(&bp[hlen]), 245127668Sbms EXTRACT_32BITS(&bp[hlen + 4])); 246127668Sbms } 247127668Sbms hlen += 8; 248127668Sbms break; 249127668Sbms case IP6M_BINDING_UPDATE: 250127668Sbms printf("mobility: BU"); 251127668Sbms TCHECK(mh->ip6m_data16[0]); 252127668Sbms printf(" seq#=%d", EXTRACT_16BITS(&mh->ip6m_data16[0])); 253127668Sbms hlen = IP6M_MINLEN; 254127668Sbms TCHECK2(*mh, hlen + 1); 255127668Sbms if (bp[hlen] & 0xf0) 256127668Sbms printf(" "); 257127668Sbms if (bp[hlen] & 0x80) 258127668Sbms printf("A"); 259127668Sbms if (bp[hlen] & 0x40) 260127668Sbms printf("H"); 261127668Sbms if (bp[hlen] & 0x20) 262127668Sbms printf("L"); 263127668Sbms if (bp[hlen] & 0x10) 264127668Sbms printf("K"); 265127668Sbms /* Reserved (4bits) */ 266127668Sbms hlen += 1; 267127668Sbms /* Reserved (8bits) */ 268127668Sbms hlen += 1; 269127668Sbms TCHECK2(*mh, hlen + 2); 270127668Sbms /* units of 4 secs */ 271127668Sbms printf(" lifetime=%d", EXTRACT_16BITS(&bp[hlen]) << 2); 272127668Sbms hlen += 2; 273127668Sbms break; 274127668Sbms case IP6M_BINDING_ACK: 275127668Sbms printf("mobility: BA"); 276127668Sbms TCHECK(mh->ip6m_data8[0]); 277127668Sbms printf(" status=%d", mh->ip6m_data8[0]); 278127668Sbms if (mh->ip6m_data8[1] & 0x80) 279127668Sbms printf(" K"); 280127668Sbms /* Reserved (7bits) */ 281127668Sbms hlen = IP6M_MINLEN; 282127668Sbms TCHECK2(*mh, hlen + 2); 283127668Sbms printf(" seq#=%d", EXTRACT_16BITS(&bp[hlen])); 284127668Sbms hlen += 2; 285127668Sbms TCHECK2(*mh, hlen + 2); 286127668Sbms /* units of 4 secs */ 287127668Sbms printf(" lifetime=%d", EXTRACT_16BITS(&bp[hlen]) << 2); 288127668Sbms hlen += 2; 289127668Sbms break; 290127668Sbms case IP6M_BINDING_ERROR: 291127668Sbms printf("mobility: BE"); 292127668Sbms TCHECK(mh->ip6m_data8[0]); 293127668Sbms printf(" status=%d", mh->ip6m_data8[0]); 294127668Sbms /* Reserved */ 295127668Sbms hlen = IP6M_MINLEN; 296127668Sbms TCHECK2(*mh, hlen + 16); 297127668Sbms printf(" homeaddr %s", ip6addr_string(&bp[hlen])); 298127668Sbms hlen += 16; 299127668Sbms break; 300127668Sbms default: 301127668Sbms printf("mobility: type-#%d len=%d", type, mh->ip6m_len); 302127668Sbms return(mhlen); 303127668Sbms break; 304127668Sbms } 305127668Sbms if (vflag) 306127668Sbms mobility_opt_print(&bp[hlen], mhlen - hlen); 307127668Sbms 308127668Sbms return(mhlen); 309127668Sbms 310127668Sbms trunc: 311127668Sbms fputs("[|MOBILITY]", stdout); 312127668Sbms return(mhlen); 313127668Sbms} 314127668Sbms#endif /* INET6 */ 315