Annotation of sys/netinet6/route6.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: route6.c,v 1.16 2007/05/31 23:17:38 mcbride Exp $ */
2: /* $KAME: route6.c,v 1.22 2000/12/03 00:54:00 itojun Exp $ */
3:
4: /*
5: * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. Neither the name of the project nor the names of its contributors
17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #include <sys/param.h>
34: #include <sys/mbuf.h>
35: #include <sys/socket.h>
36: #include <sys/systm.h>
37:
38: #include <net/if.h>
39:
40: #include <netinet/in.h>
41: #include <netinet6/in6_var.h>
42: #include <netinet/ip6.h>
43: #include <netinet6/ip6_var.h>
44:
45: #include <netinet/icmp6.h>
46:
47: #if 0
48: static int ip6_rthdr0(struct mbuf *, struct ip6_hdr *, struct ip6_rthdr0 *);
49: #endif
50:
51: int
52: route6_input(mp, offp, proto)
53: struct mbuf **mp;
54: int *offp, proto; /* proto is unused */
55: {
56: struct ip6_hdr *ip6;
57: struct mbuf *m = *mp;
58: struct ip6_rthdr *rh;
59: int off = *offp, rhlen;
60:
61: ip6 = mtod(m, struct ip6_hdr *);
62: IP6_EXTHDR_GET(rh, struct ip6_rthdr *, m, off, sizeof(*rh));
63: if (rh == NULL) {
64: ip6stat.ip6s_tooshort++;
65: return IPPROTO_DONE;
66: }
67:
68: switch (rh->ip6r_type) {
69: #if 0
70: /*
71: * See http://www.secdev.org/conf/IPv6_RH_security-csw07.pdf
72: * for why IPV6_RTHDR_TYPE_0 is banned here.
73: *
74: * We return ICMPv6 parameter problem so that innocent people
75: * (not an attacker) would notice about the use of IPV6_RTHDR_TYPE_0.
76: * Since there's no amplification, and ICMPv6 error will be rate-
77: * controlled, it shouldn't cause any problem.
78: * If you are concerned about this, you may want to use the following
79: * code fragment:
80: *
81: * case IPV6_RTHDR_TYPE_0:
82: * m_freem(m);
83: * return (IPPROTO_DONE);
84: */
85: case IPV6_RTHDR_TYPE_0:
86: rhlen = (rh->ip6r_len + 1) << 3;
87: if (rh->ip6r_segleft == 0)
88: break; /* Final dst. Just ignore the header. */
89: /*
90: * note on option length:
91: * maximum rhlen: 2048
92: * max mbuf m_pulldown can handle: MCLBYTES == usually 2048
93: * so, here we are assuming that m_pulldown can handle
94: * rhlen == 2048 case. this may not be a good thing to
95: * assume - we may want to avoid pulling it up altogether.
96: */
97: IP6_EXTHDR_GET(rh, struct ip6_rthdr *, m, off, rhlen);
98: if (rh == NULL) {
99: ip6stat.ip6s_tooshort++;
100: return IPPROTO_DONE;
101: }
102: if (ip6_rthdr0(m, ip6, (struct ip6_rthdr0 *)rh))
103: return (IPPROTO_DONE);
104: break;
105: #endif
106: default:
107: /* unknown routing type */
108: if (rh->ip6r_segleft == 0) {
109: rhlen = (rh->ip6r_len + 1) << 3;
110: break; /* Final dst. Just ignore the header. */
111: }
112: ip6stat.ip6s_badoptions++;
113: icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
114: (caddr_t)&rh->ip6r_type - (caddr_t)ip6);
115: return (IPPROTO_DONE);
116: }
117:
118: *offp += rhlen;
119: return (rh->ip6r_nxt);
120: }
121:
122: #if 0
123: /*
124: * Type0 routing header processing
125: *
126: * RFC2292 backward compatibility warning: no support for strict/loose bitmap,
127: * as it was dropped between RFC1883 and RFC2460.
128: */
129: static int
130: ip6_rthdr0(m, ip6, rh0)
131: struct mbuf *m;
132: struct ip6_hdr *ip6;
133: struct ip6_rthdr0 *rh0;
134: {
135: int addrs, index;
136: struct in6_addr *nextaddr, tmpaddr;
137:
138: if (rh0->ip6r0_segleft == 0)
139: return (0);
140:
141: if (rh0->ip6r0_len % 2) {
142: /*
143: * Type 0 routing header can't contain more than 23 addresses.
144: * RFC 2460: this limitation was removed since strict/loose
145: * bitmap field was deleted.
146: */
147: ip6stat.ip6s_badoptions++;
148: icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
149: (caddr_t)&rh0->ip6r0_len - (caddr_t)ip6);
150: return (-1);
151: }
152:
153: if ((addrs = rh0->ip6r0_len / 2) < rh0->ip6r0_segleft) {
154: ip6stat.ip6s_badoptions++;
155: icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER,
156: (caddr_t)&rh0->ip6r0_segleft - (caddr_t)ip6);
157: return (-1);
158: }
159:
160: index = addrs - rh0->ip6r0_segleft;
161: rh0->ip6r0_segleft--;
162: nextaddr = ((struct in6_addr *)(rh0 + 1)) + index;
163:
164: /*
165: * reject invalid addresses. be proactive about malicious use of
166: * IPv4 mapped/compat address.
167: * XXX need more checks?
168: */
169: if (IN6_IS_ADDR_MULTICAST(nextaddr) ||
170: IN6_IS_ADDR_UNSPECIFIED(nextaddr) ||
171: IN6_IS_ADDR_V4MAPPED(nextaddr) ||
172: IN6_IS_ADDR_V4COMPAT(nextaddr)) {
173: ip6stat.ip6s_badoptions++;
174: goto bad;
175: }
176: if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
177: IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst) ||
178: IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst) ||
179: IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {
180: ip6stat.ip6s_badoptions++;
181: goto bad;
182: }
183:
184: /*
185: * Swap the IPv6 destination address and nextaddr. Forward the packet.
186: */
187: tmpaddr = *nextaddr;
188: *nextaddr = ip6->ip6_dst;
189: if (IN6_IS_ADDR_LINKLOCAL(nextaddr))
190: nextaddr->s6_addr16[1] = 0;
191: ip6->ip6_dst = tmpaddr;
192: if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst))
193: ip6->ip6_dst.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
194:
195: ip6_forward(m, 1);
196:
197: return (-1); /* m would be freed in ip6_forward() */
198:
199: bad:
200: m_freem(m);
201: return (-1);
202: }
203: #endif
CVSweb