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_ = 36190207Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-mobility.c,v 1.12 2005-04-20 22:21:00 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 171147899Ssammobility_print(const u_char *bp, const u_char *bp2 _U_) 172127668Sbms{ 173127668Sbms const struct ip6_mobility *mh; 174127668Sbms const u_char *ep; 175127668Sbms int mhlen, hlen, type; 176127668Sbms 177127668Sbms mh = (struct ip6_mobility *)bp; 178127668Sbms 179127668Sbms /* 'ep' points to the end of available data. */ 180127668Sbms ep = snapend; 181127668Sbms 182127668Sbms if (!TTEST(mh->ip6m_len)) { 183127668Sbms /* 184127668Sbms * There's not enough captured data to include the 185127668Sbms * mobility header length. 186127668Sbms * 187127668Sbms * Our caller expects us to return the length, however, 188127668Sbms * so return a value that will run to the end of the 189127668Sbms * captured data. 190127668Sbms * 191127668Sbms * XXX - "ip6_print()" doesn't do anything with the 192127668Sbms * returned length, however, as it breaks out of the 193127668Sbms * header-processing loop. 194127668Sbms */ 195127668Sbms mhlen = ep - bp; 196127668Sbms goto trunc; 197127668Sbms } 198127668Sbms mhlen = (int)((mh->ip6m_len + 1) << 3); 199127668Sbms 200127668Sbms /* XXX ip6m_cksum */ 201127668Sbms 202127668Sbms TCHECK(mh->ip6m_type); 203127668Sbms type = mh->ip6m_type; 204127668Sbms switch (type) { 205127668Sbms case IP6M_BINDING_REQUEST: 206127668Sbms printf("mobility: BRR"); 207127668Sbms hlen = IP6M_MINLEN; 208127668Sbms break; 209127668Sbms case IP6M_HOME_TEST_INIT: 210127668Sbms case IP6M_CAREOF_TEST_INIT: 211127668Sbms printf("mobility: %soTI", 212127668Sbms type == IP6M_HOME_TEST_INIT ? "H" : "C"); 213127668Sbms hlen = IP6M_MINLEN; 214127668Sbms if (vflag) { 215127668Sbms TCHECK2(*mh, hlen + 8); 216127668Sbms printf(" %s Init Cookie=%08x:%08x", 217127668Sbms type == IP6M_HOME_TEST_INIT ? "Home" : "Care-of", 218127668Sbms EXTRACT_32BITS(&bp[hlen]), 219127668Sbms EXTRACT_32BITS(&bp[hlen + 4])); 220127668Sbms } 221127668Sbms hlen += 8; 222127668Sbms break; 223127668Sbms case IP6M_HOME_TEST: 224127668Sbms case IP6M_CAREOF_TEST: 225127668Sbms printf("mobility: %soT", 226127668Sbms type == IP6M_HOME_TEST ? "H" : "C"); 227127668Sbms TCHECK(mh->ip6m_data16[0]); 228127668Sbms printf(" nonce id=0x%x", EXTRACT_16BITS(&mh->ip6m_data16[0])); 229127668Sbms hlen = IP6M_MINLEN; 230127668Sbms if (vflag) { 231127668Sbms TCHECK2(*mh, hlen + 8); 232127668Sbms printf(" %s Init Cookie=%08x:%08x", 233127668Sbms type == IP6M_HOME_TEST ? "Home" : "Care-of", 234127668Sbms EXTRACT_32BITS(&bp[hlen]), 235127668Sbms EXTRACT_32BITS(&bp[hlen + 4])); 236127668Sbms } 237127668Sbms hlen += 8; 238127668Sbms if (vflag) { 239127668Sbms TCHECK2(*mh, hlen + 8); 240127668Sbms printf(" %s Keygen Token=%08x:%08x", 241127668Sbms type == IP6M_HOME_TEST ? "Home" : "Care-of", 242127668Sbms EXTRACT_32BITS(&bp[hlen]), 243127668Sbms EXTRACT_32BITS(&bp[hlen + 4])); 244127668Sbms } 245127668Sbms hlen += 8; 246127668Sbms break; 247127668Sbms case IP6M_BINDING_UPDATE: 248127668Sbms printf("mobility: BU"); 249127668Sbms TCHECK(mh->ip6m_data16[0]); 250127668Sbms printf(" seq#=%d", EXTRACT_16BITS(&mh->ip6m_data16[0])); 251127668Sbms hlen = IP6M_MINLEN; 252127668Sbms TCHECK2(*mh, hlen + 1); 253127668Sbms if (bp[hlen] & 0xf0) 254127668Sbms printf(" "); 255127668Sbms if (bp[hlen] & 0x80) 256127668Sbms printf("A"); 257127668Sbms if (bp[hlen] & 0x40) 258127668Sbms printf("H"); 259127668Sbms if (bp[hlen] & 0x20) 260127668Sbms printf("L"); 261127668Sbms if (bp[hlen] & 0x10) 262127668Sbms printf("K"); 263127668Sbms /* Reserved (4bits) */ 264127668Sbms hlen += 1; 265127668Sbms /* Reserved (8bits) */ 266127668Sbms hlen += 1; 267127668Sbms TCHECK2(*mh, hlen + 2); 268127668Sbms /* units of 4 secs */ 269127668Sbms printf(" lifetime=%d", EXTRACT_16BITS(&bp[hlen]) << 2); 270127668Sbms hlen += 2; 271127668Sbms break; 272127668Sbms case IP6M_BINDING_ACK: 273127668Sbms printf("mobility: BA"); 274127668Sbms TCHECK(mh->ip6m_data8[0]); 275127668Sbms printf(" status=%d", mh->ip6m_data8[0]); 276127668Sbms if (mh->ip6m_data8[1] & 0x80) 277127668Sbms printf(" K"); 278127668Sbms /* Reserved (7bits) */ 279127668Sbms hlen = IP6M_MINLEN; 280127668Sbms TCHECK2(*mh, hlen + 2); 281127668Sbms printf(" seq#=%d", EXTRACT_16BITS(&bp[hlen])); 282127668Sbms hlen += 2; 283127668Sbms TCHECK2(*mh, hlen + 2); 284127668Sbms /* units of 4 secs */ 285127668Sbms printf(" lifetime=%d", EXTRACT_16BITS(&bp[hlen]) << 2); 286127668Sbms hlen += 2; 287127668Sbms break; 288127668Sbms case IP6M_BINDING_ERROR: 289127668Sbms printf("mobility: BE"); 290127668Sbms TCHECK(mh->ip6m_data8[0]); 291127668Sbms printf(" status=%d", mh->ip6m_data8[0]); 292127668Sbms /* Reserved */ 293127668Sbms hlen = IP6M_MINLEN; 294127668Sbms TCHECK2(*mh, hlen + 16); 295127668Sbms printf(" homeaddr %s", ip6addr_string(&bp[hlen])); 296127668Sbms hlen += 16; 297127668Sbms break; 298127668Sbms default: 299127668Sbms printf("mobility: type-#%d len=%d", type, mh->ip6m_len); 300127668Sbms return(mhlen); 301127668Sbms break; 302127668Sbms } 303127668Sbms if (vflag) 304127668Sbms mobility_opt_print(&bp[hlen], mhlen - hlen); 305127668Sbms 306127668Sbms return(mhlen); 307127668Sbms 308127668Sbms trunc: 309127668Sbms fputs("[|MOBILITY]", stdout); 310127668Sbms return(mhlen); 311127668Sbms} 312127668Sbms#endif /* INET6 */ 313