xref: /openbsd-src/usr.sbin/tcpdump/print-ip6opts.c (revision 898184e3e61f9129feb5978fad5a8c6865f00b92)
1 /*	$OpenBSD: print-ip6opts.c,v 1.3 2006/12/09 01:12:28 itojun Exp $	*/
2 
3 /*
4  * Copyright (C) 1998 WIDE Project.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the project nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #ifdef INET6
33 #include <sys/param.h>
34 #include <sys/time.h>
35 #include <sys/types.h>
36 #include <sys/socket.h>
37 
38 #include <netinet/in.h>
39 #include <netinet/ip6.h>
40 
41 #include <stdio.h>
42 
43 #include "interface.h"
44 #include "addrtoname.h"
45 
46 void
47 ip6_opt_print(const u_char *bp, int len)
48 {
49     int i;
50     int optlen;
51 
52     for (i = 0; i < len; i += optlen) {
53 	switch (bp[i]) {
54 	case IP6OPT_PAD1:
55 	    optlen = 1;
56 	    break;
57 	case IP6OPT_PADN:
58 	    if (len - i < IP6OPT_MINLEN) {
59 		printf("(padn: trunc)");
60 		goto trunc;
61 	    }
62 	    optlen = bp[i + 1] + 2;
63 	    break;
64 	case IP6OPT_ROUTER_ALERT:
65 	    if (len - i < IP6OPT_RTALERT_LEN) {
66 		printf("(rtalert: trunc)");
67 		goto trunc;
68 	    }
69 	    if (bp[i + 1] != IP6OPT_RTALERT_LEN - 2) {
70 		printf("(rtalert: invalid len %d)", bp[i + 1]);
71 		goto trunc;
72 	    }
73 	    printf("(rtalert: 0x%04x) ", ntohs(*(u_short *)&bp[i + 2]));
74 	    optlen = IP6OPT_RTALERT_LEN;
75 	    break;
76 	case IP6OPT_JUMBO:
77 	    if (len - i < IP6OPT_JUMBO_LEN) {
78 		printf("(jumbo: trunc)");
79 		goto trunc;
80 	    }
81 	    if (bp[i + 1] != IP6OPT_JUMBO_LEN - 2) {
82 		printf("(jumbo: invalid len %d)", bp[i + 1]);
83 		goto trunc;
84 	    }
85 	    printf("(jumbo: %u) ", (u_int32_t)ntohl(*(u_int *)&bp[i + 2]));
86 	    optlen = IP6OPT_JUMBO_LEN;
87 	    break;
88 	default:
89 	    if (len - i < IP6OPT_MINLEN) {
90 		printf("(type %d: trunc)", bp[i]);
91 		goto trunc;
92 	    }
93 	    printf("(type 0x%02x: len=%d) ", bp[i], bp[i + 1]);
94 	    optlen = bp[i + 1] + 2;
95 	    break;
96 	}
97     }
98 
99 #if 0
100 end:
101 #endif
102     return;
103 
104 trunc:
105     printf("[trunc] ");
106 }
107 
108 int
109 hbhopt_print(register const u_char *bp)
110 {
111     const struct ip6_hbh *dp = (struct ip6_hbh *)bp;
112     register const u_char *ep;
113     int hbhlen = 0;
114 
115     /* 'ep' points to the end of avaible data. */
116     ep = snapend;
117     TCHECK(dp->ip6h_len);
118     hbhlen = (int)((dp->ip6h_len + 1) << 3);
119     TCHECK2(*dp, hbhlen);
120     printf("HBH ");
121     if (vflag)
122 	ip6_opt_print((const u_char *)dp + sizeof(*dp), hbhlen - sizeof(*dp));
123 
124     return(hbhlen);
125 
126   trunc:
127     fputs("[|HBH]", stdout);
128     return(hbhlen);
129 }
130 
131 int
132 dstopt_print(register const u_char *bp)
133 {
134     const struct ip6_dest *dp = (struct ip6_dest *)bp;
135     register const u_char *ep;
136     int dstoptlen = 0;
137 
138     /* 'ep' points to the end of avaible data. */
139     ep = snapend;
140     TCHECK(dp->ip6d_len);
141     dstoptlen = (int)((dp->ip6d_len + 1) << 3);
142     TCHECK2(*dp, dstoptlen);
143     printf("DSTOPT ");
144     if (vflag) {
145 	ip6_opt_print((const u_char *)dp + sizeof(*dp),
146 	    dstoptlen - sizeof(*dp));
147     }
148 
149     return(dstoptlen);
150 
151   trunc:
152     fputs("[|DSTOPT]", stdout);
153     return(dstoptlen);
154 }
155 #endif /* INET6 */
156