Home | History | Annotate | Download | only in tcpdump
      1 /*
      2  * Copyright (C) 1998 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-ip6opts.c,v 1.17.2.1 2005/04/20 22:19:06 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"
     49 
     50 /* items outside of rfc2292bis */
     51 #ifndef IP6OPT_MINLEN
     52 #define IP6OPT_MINLEN	2
     53 #endif
     54 #ifndef IP6OPT_RTALERT_LEN
     55 #define IP6OPT_RTALERT_LEN	4
     56 #endif
     57 #ifndef IP6OPT_JUMBO_LEN
     58 #define IP6OPT_JUMBO_LEN	6
     59 #endif
     60 #define IP6OPT_HOMEADDR_MINLEN 18
     61 #define IP6OPT_BU_MINLEN       10
     62 #define IP6OPT_BA_MINLEN       13
     63 #define IP6OPT_BR_MINLEN        2
     64 #define IP6SOPT_UI            0x2
     65 #define IP6SOPT_UI_MINLEN       4
     66 #define IP6SOPT_ALTCOA        0x3
     67 #define IP6SOPT_ALTCOA_MINLEN  18
     68 #define IP6SOPT_AUTH          0x4
     69 #define IP6SOPT_AUTH_MINLEN     6
     70 
     71 static void ip6_sopt_print(const u_char *, int);
     72 
     73 static void
     74 ip6_sopt_print(const u_char *bp, int len)
     75 {
     76     int i;
     77     int optlen;
     78 
     79     for (i = 0; i < len; i += optlen) {
     80 	if (bp[i] == IP6OPT_PAD1)
     81 	    optlen = 1;
     82 	else {
     83 	    if (i + 1 < len)
     84 		optlen = bp[i + 1] + 2;
     85 	    else
     86 		goto trunc;
     87 	}
     88 	if (i + optlen > len)
     89 	    goto trunc;
     90 
     91 	switch (bp[i]) {
     92 	case IP6OPT_PAD1:
     93             printf(", pad1");
     94 	    break;
     95 	case IP6OPT_PADN:
     96 	    if (len - i < IP6OPT_MINLEN) {
     97 		printf(", padn: trunc");
     98 		goto trunc;
     99 	    }
    100             printf(", padn");
    101 	    break;
    102         case IP6SOPT_UI:
    103              if (len - i < IP6SOPT_UI_MINLEN) {
    104 		printf(", ui: trunc");
    105 		goto trunc;
    106 	    }
    107             printf(", ui: 0x%04x ", EXTRACT_16BITS(&bp[i + 2]));
    108 	    break;
    109         case IP6SOPT_ALTCOA:
    110              if (len - i < IP6SOPT_ALTCOA_MINLEN) {
    111 		printf(", altcoa: trunc");
    112 		goto trunc;
    113 	    }
    114             printf(", alt-CoA: %s", ip6addr_string(&bp[i+2]));
    115 	    break;
    116         case IP6SOPT_AUTH:
    117              if (len - i < IP6SOPT_AUTH_MINLEN) {
    118 		printf(", auth: trunc");
    119 		goto trunc;
    120 	    }
    121             printf(", auth spi: 0x%08x", EXTRACT_32BITS(&bp[i + 2]));
    122 	    break;
    123 	default:
    124 	    if (len - i < IP6OPT_MINLEN) {
    125 		printf(", sopt_type %d: trunc)", bp[i]);
    126 		goto trunc;
    127 	    }
    128 	    printf(", sopt_type 0x%02x: len=%d", bp[i], bp[i + 1]);
    129 	    break;
    130 	}
    131     }
    132     return;
    133 
    134 trunc:
    135     printf("[trunc] ");
    136 }
    137 
    138 void
    139 ip6_opt_print(const u_char *bp, int len)
    140 {
    141     int i;
    142     int optlen = 0;
    143 
    144     for (i = 0; i < len; i += optlen) {
    145 	if (bp[i] == IP6OPT_PAD1)
    146 	    optlen = 1;
    147 	else {
    148 	    if (i + 1 < len)
    149 		optlen = bp[i + 1] + 2;
    150 	    else
    151 		goto trunc;
    152 	}
    153 	if (i + optlen > len)
    154 	    goto trunc;
    155 
    156 	switch (bp[i]) {
    157 	case IP6OPT_PAD1:
    158             printf("(pad1)");
    159 	    break;
    160 	case IP6OPT_PADN:
    161 	    if (len - i < IP6OPT_MINLEN) {
    162 		printf("(padn: trunc)");
    163 		goto trunc;
    164 	    }
    165             printf("(padn)");
    166 	    break;
    167 	case IP6OPT_ROUTER_ALERT:
    168 	    if (len - i < IP6OPT_RTALERT_LEN) {
    169 		printf("(rtalert: trunc)");
    170 		goto trunc;
    171 	    }
    172 	    if (bp[i + 1] != IP6OPT_RTALERT_LEN - 2) {
    173 		printf("(rtalert: invalid len %d)", bp[i + 1]);
    174 		goto trunc;
    175 	    }
    176 	    printf("(rtalert: 0x%04x) ", EXTRACT_16BITS(&bp[i + 2]));
    177 	    break;
    178 	case IP6OPT_JUMBO:
    179 	    if (len - i < IP6OPT_JUMBO_LEN) {
    180 		printf("(jumbo: trunc)");
    181 		goto trunc;
    182 	    }
    183 	    if (bp[i + 1] != IP6OPT_JUMBO_LEN - 2) {
    184 		printf("(jumbo: invalid len %d)", bp[i + 1]);
    185 		goto trunc;
    186 	    }
    187 	    printf("(jumbo: %u) ", EXTRACT_32BITS(&bp[i + 2]));
    188 	    break;
    189         case IP6OPT_HOME_ADDRESS:
    190 	    if (len - i < IP6OPT_HOMEADDR_MINLEN) {
    191 		printf("(homeaddr: trunc)");
    192 		goto trunc;
    193 	    }
    194 	    if (bp[i + 1] < IP6OPT_HOMEADDR_MINLEN - 2) {
    195 		printf("(homeaddr: invalid len %d)", bp[i + 1]);
    196 		goto trunc;
    197 	    }
    198 	    printf("(homeaddr: %s", ip6addr_string(&bp[i + 2]));
    199             if (bp[i + 1] > IP6OPT_HOMEADDR_MINLEN - 2) {
    200 		ip6_sopt_print(&bp[i + IP6OPT_HOMEADDR_MINLEN],
    201 		    (optlen - IP6OPT_HOMEADDR_MINLEN));
    202 	    }
    203             printf(")");
    204 	    break;
    205         case IP6OPT_BINDING_UPDATE:
    206 	    if (len - i < IP6OPT_BU_MINLEN) {
    207 		printf("(bu: trunc)");
    208 		goto trunc;
    209 	    }
    210 	    if (bp[i + 1] < IP6OPT_BU_MINLEN - 2) {
    211 		printf("(bu: invalid len %d)", bp[i + 1]);
    212 		goto trunc;
    213 	    }
    214 	    printf("(bu: ");
    215 	    if (bp[i + 2] & 0x80)
    216 		    printf("A");
    217 	    if (bp[i + 2] & 0x40)
    218 		    printf("H");
    219 	    if (bp[i + 2] & 0x20)
    220 		    printf("S");
    221 	    if (bp[i + 2] & 0x10)
    222 		    printf("D");
    223 	    if ((bp[i + 2] & 0x0f) || bp[i + 3] || bp[i + 4])
    224 		    printf("res");
    225 	    printf(", sequence: %u", bp[i + 5]);
    226 	    printf(", lifetime: %u", EXTRACT_32BITS(&bp[i + 6]));
    227 
    228 	    if (bp[i + 1] > IP6OPT_BU_MINLEN - 2) {
    229 		ip6_sopt_print(&bp[i + IP6OPT_BU_MINLEN],
    230 		    (optlen - IP6OPT_BU_MINLEN));
    231 	    }
    232 	    printf(")");
    233 	    break;
    234 	case IP6OPT_BINDING_ACK:
    235 	    if (len - i < IP6OPT_BA_MINLEN) {
    236 		printf("(ba: trunc)");
    237 		goto trunc;
    238 	    }
    239 	    if (bp[i + 1] < IP6OPT_BA_MINLEN - 2) {
    240 		printf("(ba: invalid len %d)", bp[i + 1]);
    241 		goto trunc;
    242 	    }
    243 	    printf("(ba: ");
    244 	    printf("status: %u", bp[i + 2]);
    245 	    if (bp[i + 3])
    246 		    printf("res");
    247 	    printf(", sequence: %u", bp[i + 4]);
    248 	    printf(", lifetime: %u", EXTRACT_32BITS(&bp[i + 5]));
    249 	    printf(", refresh: %u", EXTRACT_32BITS(&bp[i + 9]));
    250 
    251 	    if (bp[i + 1] > IP6OPT_BA_MINLEN - 2) {
    252 		ip6_sopt_print(&bp[i + IP6OPT_BA_MINLEN],
    253 		    (optlen - IP6OPT_BA_MINLEN));
    254 	    }
    255             printf(")");
    256 	    break;
    257         case IP6OPT_BINDING_REQ:
    258 	    if (len - i < IP6OPT_BR_MINLEN) {
    259 		printf("(br: trunc)");
    260 		goto trunc;
    261 	    }
    262             printf("(br");
    263             if (bp[i + 1] > IP6OPT_BR_MINLEN - 2) {
    264 		ip6_sopt_print(&bp[i + IP6OPT_BR_MINLEN],
    265 		    (optlen - IP6OPT_BR_MINLEN));
    266 	    }
    267             printf(")");
    268 	    break;
    269 	default:
    270 	    if (len - i < IP6OPT_MINLEN) {
    271 		printf("(type %d: trunc)", bp[i]);
    272 		goto trunc;
    273 	    }
    274 	    printf("(opt_type 0x%02x: len=%d) ", bp[i], bp[i + 1]);
    275 	    break;
    276 	}
    277     }
    278 
    279 #if 0
    280 end:
    281 #endif
    282     return;
    283 
    284 trunc:
    285     printf("[trunc] ");
    286 }
    287 
    288 int
    289 hbhopt_print(register const u_char *bp)
    290 {
    291     const struct ip6_hbh *dp = (struct ip6_hbh *)bp;
    292     int hbhlen = 0;
    293 
    294     TCHECK(dp->ip6h_len);
    295     hbhlen = (int)((dp->ip6h_len + 1) << 3);
    296     TCHECK2(*dp, hbhlen);
    297     printf("HBH ");
    298     if (vflag)
    299 	ip6_opt_print((const u_char *)dp + sizeof(*dp), hbhlen - sizeof(*dp));
    300 
    301     return(hbhlen);
    302 
    303   trunc:
    304     fputs("[|HBH]", stdout);
    305     return(-1);
    306 }
    307 
    308 int
    309 dstopt_print(register const u_char *bp)
    310 {
    311     const struct ip6_dest *dp = (struct ip6_dest *)bp;
    312     int dstoptlen = 0;
    313 
    314     TCHECK(dp->ip6d_len);
    315     dstoptlen = (int)((dp->ip6d_len + 1) << 3);
    316     TCHECK2(*dp, dstoptlen);
    317     printf("DSTOPT ");
    318     if (vflag) {
    319 	ip6_opt_print((const u_char *)dp + sizeof(*dp),
    320 	    dstoptlen - sizeof(*dp));
    321     }
    322 
    323     return(dstoptlen);
    324 
    325   trunc:
    326     fputs("[|DSTOPT]", stdout);
    327     return(-1);
    328 }
    329 #endif /* INET6 */
    330