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.18 2005-04-20 22:18:50 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     if (len == 0)
    145         return;
    146     for (i = 0; i < len; i += optlen) {
    147 	if (bp[i] == IP6OPT_PAD1)
    148 	    optlen = 1;
    149 	else {
    150 	    if (i + 1 < len)
    151 		optlen = bp[i + 1] + 2;
    152 	    else
    153 		goto trunc;
    154 	}
    155 	if (i + optlen > len)
    156 	    goto trunc;
    157 
    158 	switch (bp[i]) {
    159 	case IP6OPT_PAD1:
    160             printf("(pad1)");
    161 	    break;
    162 	case IP6OPT_PADN:
    163 	    if (len - i < IP6OPT_MINLEN) {
    164 		printf("(padn: trunc)");
    165 		goto trunc;
    166 	    }
    167             printf("(padn)");
    168 	    break;
    169 	case IP6OPT_ROUTER_ALERT:
    170 	    if (len - i < IP6OPT_RTALERT_LEN) {
    171 		printf("(rtalert: trunc)");
    172 		goto trunc;
    173 	    }
    174 	    if (bp[i + 1] != IP6OPT_RTALERT_LEN - 2) {
    175 		printf("(rtalert: invalid len %d)", bp[i + 1]);
    176 		goto trunc;
    177 	    }
    178 	    printf("(rtalert: 0x%04x) ", EXTRACT_16BITS(&bp[i + 2]));
    179 	    break;
    180 	case IP6OPT_JUMBO:
    181 	    if (len - i < IP6OPT_JUMBO_LEN) {
    182 		printf("(jumbo: trunc)");
    183 		goto trunc;
    184 	    }
    185 	    if (bp[i + 1] != IP6OPT_JUMBO_LEN - 2) {
    186 		printf("(jumbo: invalid len %d)", bp[i + 1]);
    187 		goto trunc;
    188 	    }
    189 	    printf("(jumbo: %u) ", EXTRACT_32BITS(&bp[i + 2]));
    190 	    break;
    191         case IP6OPT_HOME_ADDRESS:
    192 	    if (len - i < IP6OPT_HOMEADDR_MINLEN) {
    193 		printf("(homeaddr: trunc)");
    194 		goto trunc;
    195 	    }
    196 	    if (bp[i + 1] < IP6OPT_HOMEADDR_MINLEN - 2) {
    197 		printf("(homeaddr: invalid len %d)", bp[i + 1]);
    198 		goto trunc;
    199 	    }
    200 	    printf("(homeaddr: %s", ip6addr_string(&bp[i + 2]));
    201             if (bp[i + 1] > IP6OPT_HOMEADDR_MINLEN - 2) {
    202 		ip6_sopt_print(&bp[i + IP6OPT_HOMEADDR_MINLEN],
    203 		    (optlen - IP6OPT_HOMEADDR_MINLEN));
    204 	    }
    205             printf(")");
    206 	    break;
    207         case IP6OPT_BINDING_UPDATE:
    208 	    if (len - i < IP6OPT_BU_MINLEN) {
    209 		printf("(bu: trunc)");
    210 		goto trunc;
    211 	    }
    212 	    if (bp[i + 1] < IP6OPT_BU_MINLEN - 2) {
    213 		printf("(bu: invalid len %d)", bp[i + 1]);
    214 		goto trunc;
    215 	    }
    216 	    printf("(bu: ");
    217 	    if (bp[i + 2] & 0x80)
    218 		    printf("A");
    219 	    if (bp[i + 2] & 0x40)
    220 		    printf("H");
    221 	    if (bp[i + 2] & 0x20)
    222 		    printf("S");
    223 	    if (bp[i + 2] & 0x10)
    224 		    printf("D");
    225 	    if ((bp[i + 2] & 0x0f) || bp[i + 3] || bp[i + 4])
    226 		    printf("res");
    227 	    printf(", sequence: %u", bp[i + 5]);
    228 	    printf(", lifetime: %u", EXTRACT_32BITS(&bp[i + 6]));
    229 
    230 	    if (bp[i + 1] > IP6OPT_BU_MINLEN - 2) {
    231 		ip6_sopt_print(&bp[i + IP6OPT_BU_MINLEN],
    232 		    (optlen - IP6OPT_BU_MINLEN));
    233 	    }
    234 	    printf(")");
    235 	    break;
    236 	case IP6OPT_BINDING_ACK:
    237 	    if (len - i < IP6OPT_BA_MINLEN) {
    238 		printf("(ba: trunc)");
    239 		goto trunc;
    240 	    }
    241 	    if (bp[i + 1] < IP6OPT_BA_MINLEN - 2) {
    242 		printf("(ba: invalid len %d)", bp[i + 1]);
    243 		goto trunc;
    244 	    }
    245 	    printf("(ba: ");
    246 	    printf("status: %u", bp[i + 2]);
    247 	    if (bp[i + 3])
    248 		    printf("res");
    249 	    printf(", sequence: %u", bp[i + 4]);
    250 	    printf(", lifetime: %u", EXTRACT_32BITS(&bp[i + 5]));
    251 	    printf(", refresh: %u", EXTRACT_32BITS(&bp[i + 9]));
    252 
    253 	    if (bp[i + 1] > IP6OPT_BA_MINLEN - 2) {
    254 		ip6_sopt_print(&bp[i + IP6OPT_BA_MINLEN],
    255 		    (optlen - IP6OPT_BA_MINLEN));
    256 	    }
    257             printf(")");
    258 	    break;
    259         case IP6OPT_BINDING_REQ:
    260 	    if (len - i < IP6OPT_BR_MINLEN) {
    261 		printf("(br: trunc)");
    262 		goto trunc;
    263 	    }
    264             printf("(br");
    265             if (bp[i + 1] > IP6OPT_BR_MINLEN - 2) {
    266 		ip6_sopt_print(&bp[i + IP6OPT_BR_MINLEN],
    267 		    (optlen - IP6OPT_BR_MINLEN));
    268 	    }
    269             printf(")");
    270 	    break;
    271 	default:
    272 	    if (len - i < IP6OPT_MINLEN) {
    273 		printf("(type %d: trunc)", bp[i]);
    274 		goto trunc;
    275 	    }
    276 	    printf("(opt_type 0x%02x: len=%d)", bp[i], bp[i + 1]);
    277 	    break;
    278 	}
    279     }
    280     printf(" ");
    281 
    282 #if 0
    283 end:
    284 #endif
    285     return;
    286 
    287 trunc:
    288     printf("[trunc] ");
    289 }
    290 
    291 int
    292 hbhopt_print(register const u_char *bp)
    293 {
    294     const struct ip6_hbh *dp = (struct ip6_hbh *)bp;
    295     int hbhlen = 0;
    296 
    297     TCHECK(dp->ip6h_len);
    298     hbhlen = (int)((dp->ip6h_len + 1) << 3);
    299     TCHECK2(*dp, hbhlen);
    300     printf("HBH ");
    301     if (vflag)
    302 	ip6_opt_print((const u_char *)dp + sizeof(*dp), hbhlen - sizeof(*dp));
    303 
    304     return(hbhlen);
    305 
    306   trunc:
    307     fputs("[|HBH]", stdout);
    308     return(-1);
    309 }
    310 
    311 int
    312 dstopt_print(register const u_char *bp)
    313 {
    314     const struct ip6_dest *dp = (struct ip6_dest *)bp;
    315     int dstoptlen = 0;
    316 
    317     TCHECK(dp->ip6d_len);
    318     dstoptlen = (int)((dp->ip6d_len + 1) << 3);
    319     TCHECK2(*dp, dstoptlen);
    320     printf("DSTOPT ");
    321     if (vflag) {
    322 	ip6_opt_print((const u_char *)dp + sizeof(*dp),
    323 	    dstoptlen - sizeof(*dp));
    324     }
    325 
    326     return(dstoptlen);
    327 
    328   trunc:
    329     fputs("[|DSTOPT]", stdout);
    330     return(-1);
    331 }
    332 #endif /* INET6 */
    333