| @@ -1,1964 +1,1964 @@ | | | @@ -1,1964 +1,1964 @@ |
1 | /* $NetBSD: ip6_input.c,v 1.122 2008/08/21 15:34:10 matt Exp $ */ | | 1 | /* $NetBSD: ip6_input.c,v 1.122.4.1 2009/05/03 13:22:22 bouyer Exp $ */ |
2 | /* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */ | | 2 | /* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */ |
3 | | | 3 | |
4 | /* | | 4 | /* |
5 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | | 5 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | | 9 | * modification, are permitted provided that the following conditions |
10 | * are met: | | 10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright | | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | | 14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. | | 15 | * documentation and/or other materials provided with the distribution. |
16 | * 3. Neither the name of the project nor the names of its contributors | | 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 | | 17 | * may be used to endorse or promote products derived from this software |
18 | * without specific prior written permission. | | 18 | * without specific prior written permission. |
19 | * | | 19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND | | 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 | | 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE | | 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 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 | | 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 | | 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 | | 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
30 | * SUCH DAMAGE. | | 30 | * SUCH DAMAGE. |
31 | */ | | 31 | */ |
32 | | | 32 | |
33 | /* | | 33 | /* |
34 | * Copyright (c) 1982, 1986, 1988, 1993 | | 34 | * Copyright (c) 1982, 1986, 1988, 1993 |
35 | * The Regents of the University of California. All rights reserved. | | 35 | * The Regents of the University of California. All rights reserved. |
36 | * | | 36 | * |
37 | * Redistribution and use in source and binary forms, with or without | | 37 | * Redistribution and use in source and binary forms, with or without |
38 | * modification, are permitted provided that the following conditions | | 38 | * modification, are permitted provided that the following conditions |
39 | * are met: | | 39 | * are met: |
40 | * 1. Redistributions of source code must retain the above copyright | | 40 | * 1. Redistributions of source code must retain the above copyright |
41 | * notice, this list of conditions and the following disclaimer. | | 41 | * notice, this list of conditions and the following disclaimer. |
42 | * 2. Redistributions in binary form must reproduce the above copyright | | 42 | * 2. Redistributions in binary form must reproduce the above copyright |
43 | * notice, this list of conditions and the following disclaimer in the | | 43 | * notice, this list of conditions and the following disclaimer in the |
44 | * documentation and/or other materials provided with the distribution. | | 44 | * documentation and/or other materials provided with the distribution. |
45 | * 3. Neither the name of the University nor the names of its contributors | | 45 | * 3. Neither the name of the University nor the names of its contributors |
46 | * may be used to endorse or promote products derived from this software | | 46 | * may be used to endorse or promote products derived from this software |
47 | * without specific prior written permission. | | 47 | * without specific prior written permission. |
48 | * | | 48 | * |
49 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 49 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
50 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 50 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
51 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 51 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
52 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 52 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
53 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 53 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
54 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 54 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
55 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 55 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
56 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 56 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
57 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 57 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
58 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 58 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
59 | * SUCH DAMAGE. | | 59 | * SUCH DAMAGE. |
60 | * | | 60 | * |
61 | * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 | | 61 | * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 |
62 | */ | | 62 | */ |
63 | | | 63 | |
64 | #include <sys/cdefs.h> | | 64 | #include <sys/cdefs.h> |
65 | __KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.122 2008/08/21 15:34:10 matt Exp $"); | | 65 | __KERNEL_RCSID(0, "$NetBSD: ip6_input.c,v 1.122.4.1 2009/05/03 13:22:22 bouyer Exp $"); |
66 | | | 66 | |
67 | #include "opt_inet.h" | | 67 | #include "opt_inet.h" |
68 | #include "opt_inet6.h" | | 68 | #include "opt_inet6.h" |
69 | #include "opt_ipsec.h" | | 69 | #include "opt_ipsec.h" |
70 | #include "opt_pfil_hooks.h" | | 70 | #include "opt_pfil_hooks.h" |
71 | | | 71 | |
72 | #include <sys/param.h> | | 72 | #include <sys/param.h> |
73 | #include <sys/systm.h> | | 73 | #include <sys/systm.h> |
74 | #include <sys/malloc.h> | | 74 | #include <sys/malloc.h> |
75 | #include <sys/mbuf.h> | | 75 | #include <sys/mbuf.h> |
76 | #include <sys/domain.h> | | 76 | #include <sys/domain.h> |
77 | #include <sys/protosw.h> | | 77 | #include <sys/protosw.h> |
78 | #include <sys/socket.h> | | 78 | #include <sys/socket.h> |
79 | #include <sys/socketvar.h> | | 79 | #include <sys/socketvar.h> |
80 | #include <sys/errno.h> | | 80 | #include <sys/errno.h> |
81 | #include <sys/time.h> | | 81 | #include <sys/time.h> |
82 | #include <sys/kernel.h> | | 82 | #include <sys/kernel.h> |
83 | #include <sys/syslog.h> | | 83 | #include <sys/syslog.h> |
84 | #include <sys/proc.h> | | 84 | #include <sys/proc.h> |
85 | #include <sys/sysctl.h> | | 85 | #include <sys/sysctl.h> |
86 | | | 86 | |
87 | #include <net/if.h> | | 87 | #include <net/if.h> |
88 | #include <net/if_types.h> | | 88 | #include <net/if_types.h> |
89 | #include <net/if_dl.h> | | 89 | #include <net/if_dl.h> |
90 | #include <net/route.h> | | 90 | #include <net/route.h> |
91 | #include <net/netisr.h> | | 91 | #include <net/netisr.h> |
92 | #ifdef PFIL_HOOKS | | 92 | #ifdef PFIL_HOOKS |
93 | #include <net/pfil.h> | | 93 | #include <net/pfil.h> |
94 | #endif | | 94 | #endif |
95 | | | 95 | |
96 | #include <netinet/in.h> | | 96 | #include <netinet/in.h> |
97 | #include <netinet/in_systm.h> | | 97 | #include <netinet/in_systm.h> |
98 | #ifdef INET | | 98 | #ifdef INET |
99 | #include <netinet/ip.h> | | 99 | #include <netinet/ip.h> |
100 | #include <netinet/ip_icmp.h> | | 100 | #include <netinet/ip_icmp.h> |
101 | #endif /* INET */ | | 101 | #endif /* INET */ |
102 | #include <netinet/ip6.h> | | 102 | #include <netinet/ip6.h> |
103 | #include <netinet6/in6_var.h> | | 103 | #include <netinet6/in6_var.h> |
104 | #include <netinet6/ip6_var.h> | | 104 | #include <netinet6/ip6_var.h> |
105 | #include <netinet6/ip6_private.h> | | 105 | #include <netinet6/ip6_private.h> |
106 | #include <netinet6/in6_pcb.h> | | 106 | #include <netinet6/in6_pcb.h> |
107 | #include <netinet/icmp6.h> | | 107 | #include <netinet/icmp6.h> |
108 | #include <netinet6/scope6_var.h> | | 108 | #include <netinet6/scope6_var.h> |
109 | #include <netinet6/in6_ifattach.h> | | 109 | #include <netinet6/in6_ifattach.h> |
110 | #include <netinet6/nd6.h> | | 110 | #include <netinet6/nd6.h> |
111 | | | 111 | |
112 | #ifdef IPSEC | | 112 | #ifdef IPSEC |
113 | #include <netinet6/ipsec.h> | | 113 | #include <netinet6/ipsec.h> |
114 | #include <netinet6/ipsec_private.h> | | 114 | #include <netinet6/ipsec_private.h> |
115 | #endif | | 115 | #endif |
116 | | | 116 | |
117 | #ifdef FAST_IPSEC | | 117 | #ifdef FAST_IPSEC |
118 | #include <netipsec/ipsec.h> | | 118 | #include <netipsec/ipsec.h> |
119 | #include <netipsec/ipsec6.h> | | 119 | #include <netipsec/ipsec6.h> |
120 | #include <netipsec/key.h> | | 120 | #include <netipsec/key.h> |
121 | #endif /* FAST_IPSEC */ | | 121 | #endif /* FAST_IPSEC */ |
122 | | | 122 | |
123 | #include <netinet6/ip6protosw.h> | | 123 | #include <netinet6/ip6protosw.h> |
124 | | | 124 | |
125 | #include "faith.h" | | 125 | #include "faith.h" |
126 | #include "gif.h" | | 126 | #include "gif.h" |
127 | | | 127 | |
128 | #if NGIF > 0 | | 128 | #if NGIF > 0 |
129 | #include <netinet6/in6_gif.h> | | 129 | #include <netinet6/in6_gif.h> |
130 | #endif | | 130 | #endif |
131 | | | 131 | |
132 | #include <net/net_osdep.h> | | 132 | #include <net/net_osdep.h> |
133 | | | 133 | |
134 | extern struct domain inet6domain; | | 134 | extern struct domain inet6domain; |
135 | | | 135 | |
136 | u_char ip6_protox[IPPROTO_MAX]; | | 136 | u_char ip6_protox[IPPROTO_MAX]; |
137 | static int ip6qmaxlen = IFQ_MAXLEN; | | 137 | static int ip6qmaxlen = IFQ_MAXLEN; |
138 | struct in6_ifaddr *in6_ifaddr; | | 138 | struct in6_ifaddr *in6_ifaddr; |
139 | struct ifqueue ip6intrq; | | 139 | struct ifqueue ip6intrq; |
140 | | | 140 | |
141 | extern callout_t in6_tmpaddrtimer_ch; | | 141 | extern callout_t in6_tmpaddrtimer_ch; |
142 | | | 142 | |
143 | int ip6_forward_srcrt; /* XXX */ | | 143 | int ip6_forward_srcrt; /* XXX */ |
144 | int ip6_sourcecheck; /* XXX */ | | 144 | int ip6_sourcecheck; /* XXX */ |
145 | int ip6_sourcecheck_interval; /* XXX */ | | 145 | int ip6_sourcecheck_interval; /* XXX */ |
146 | | | 146 | |
147 | #ifdef PFIL_HOOKS | | 147 | #ifdef PFIL_HOOKS |
148 | struct pfil_head inet6_pfil_hook; | | 148 | struct pfil_head inet6_pfil_hook; |
149 | #endif | | 149 | #endif |
150 | | | 150 | |
151 | percpu_t *ip6stat_percpu; | | 151 | percpu_t *ip6stat_percpu; |
152 | | | 152 | |
153 | static void ip6_init2(void *); | | 153 | static void ip6_init2(void *); |
154 | static struct m_tag *ip6_setdstifaddr(struct mbuf *, const struct in6_ifaddr *); | | 154 | static struct m_tag *ip6_setdstifaddr(struct mbuf *, const struct in6_ifaddr *); |
155 | | | 155 | |
156 | static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *); | | 156 | static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *); |
157 | static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int); | | 157 | static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int); |
158 | | | 158 | |
159 | /* | | 159 | /* |
160 | * IP6 initialization: fill in IP6 protocol switch table. | | 160 | * IP6 initialization: fill in IP6 protocol switch table. |
161 | * All protocols not implemented in kernel go to raw IP6 protocol handler. | | 161 | * All protocols not implemented in kernel go to raw IP6 protocol handler. |
162 | */ | | 162 | */ |
163 | void | | 163 | void |
164 | ip6_init(void) | | 164 | ip6_init(void) |
165 | { | | 165 | { |
166 | const struct ip6protosw *pr; | | 166 | const struct ip6protosw *pr; |
167 | int i; | | 167 | int i; |
168 | | | 168 | |
169 | pr = (const struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW); | | 169 | pr = (const struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW); |
170 | if (pr == 0) | | 170 | if (pr == 0) |
171 | panic("ip6_init"); | | 171 | panic("ip6_init"); |
172 | for (i = 0; i < IPPROTO_MAX; i++) | | 172 | for (i = 0; i < IPPROTO_MAX; i++) |
173 | ip6_protox[i] = pr - inet6sw; | | 173 | ip6_protox[i] = pr - inet6sw; |
174 | for (pr = (const struct ip6protosw *)inet6domain.dom_protosw; | | 174 | for (pr = (const struct ip6protosw *)inet6domain.dom_protosw; |
175 | pr < (const struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++) | | 175 | pr < (const struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++) |
176 | if (pr->pr_domain->dom_family == PF_INET6 && | | 176 | if (pr->pr_domain->dom_family == PF_INET6 && |
177 | pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) | | 177 | pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) |
178 | ip6_protox[pr->pr_protocol] = pr - inet6sw; | | 178 | ip6_protox[pr->pr_protocol] = pr - inet6sw; |
179 | ip6intrq.ifq_maxlen = ip6qmaxlen; | | 179 | ip6intrq.ifq_maxlen = ip6qmaxlen; |
180 | scope6_init(); | | 180 | scope6_init(); |
181 | addrsel_policy_init(); | | 181 | addrsel_policy_init(); |
182 | nd6_init(); | | 182 | nd6_init(); |
183 | frag6_init(); | | 183 | frag6_init(); |
184 | ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR; | | 184 | ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR; |
185 | | | 185 | |
186 | ip6_init2((void *)0); | | 186 | ip6_init2((void *)0); |
187 | #ifdef GATEWAY | | 187 | #ifdef GATEWAY |
188 | ip6flow_init(ip6_hashsize); | | 188 | ip6flow_init(ip6_hashsize); |
189 | #endif | | 189 | #endif |
190 | | | 190 | |
191 | #ifdef PFIL_HOOKS | | 191 | #ifdef PFIL_HOOKS |
192 | /* Register our Packet Filter hook. */ | | 192 | /* Register our Packet Filter hook. */ |
193 | inet6_pfil_hook.ph_type = PFIL_TYPE_AF; | | 193 | inet6_pfil_hook.ph_type = PFIL_TYPE_AF; |
194 | inet6_pfil_hook.ph_af = AF_INET6; | | 194 | inet6_pfil_hook.ph_af = AF_INET6; |
195 | i = pfil_head_register(&inet6_pfil_hook); | | 195 | i = pfil_head_register(&inet6_pfil_hook); |
196 | if (i != 0) | | 196 | if (i != 0) |
197 | printf("ip6_init: WARNING: unable to register pfil hook, " | | 197 | printf("ip6_init: WARNING: unable to register pfil hook, " |
198 | "error %d\n", i); | | 198 | "error %d\n", i); |
199 | #endif /* PFIL_HOOKS */ | | 199 | #endif /* PFIL_HOOKS */ |
200 | | | 200 | |
201 | ip6stat_percpu = percpu_alloc(sizeof(uint64_t) * IP6_NSTATS); | | 201 | ip6stat_percpu = percpu_alloc(sizeof(uint64_t) * IP6_NSTATS); |
202 | } | | 202 | } |
203 | | | 203 | |
204 | static void | | 204 | static void |
205 | ip6_init2(void *dummy) | | 205 | ip6_init2(void *dummy) |
206 | { | | 206 | { |
207 | | | 207 | |
208 | /* nd6_timer_init */ | | 208 | /* nd6_timer_init */ |
209 | callout_init(&nd6_timer_ch, CALLOUT_MPSAFE); | | 209 | callout_init(&nd6_timer_ch, CALLOUT_MPSAFE); |
210 | callout_reset(&nd6_timer_ch, hz, nd6_timer, NULL); | | 210 | callout_reset(&nd6_timer_ch, hz, nd6_timer, NULL); |
211 | | | 211 | |
212 | /* timer for regeneranation of temporary addresses randomize ID */ | | 212 | /* timer for regeneranation of temporary addresses randomize ID */ |
213 | callout_init(&in6_tmpaddrtimer_ch, CALLOUT_MPSAFE); | | 213 | callout_init(&in6_tmpaddrtimer_ch, CALLOUT_MPSAFE); |
214 | callout_reset(&in6_tmpaddrtimer_ch, | | 214 | callout_reset(&in6_tmpaddrtimer_ch, |
215 | (ip6_temp_preferred_lifetime - ip6_desync_factor - | | 215 | (ip6_temp_preferred_lifetime - ip6_desync_factor - |
216 | ip6_temp_regen_advance) * hz, | | 216 | ip6_temp_regen_advance) * hz, |
217 | in6_tmpaddrtimer, NULL); | | 217 | in6_tmpaddrtimer, NULL); |
218 | } | | 218 | } |
219 | | | 219 | |
220 | /* | | 220 | /* |
221 | * IP6 input interrupt handling. Just pass the packet to ip6_input. | | 221 | * IP6 input interrupt handling. Just pass the packet to ip6_input. |
222 | */ | | 222 | */ |
223 | void | | 223 | void |
224 | ip6intr(void) | | 224 | ip6intr(void) |
225 | { | | 225 | { |
226 | int s; | | 226 | int s; |
227 | struct mbuf *m; | | 227 | struct mbuf *m; |
228 | | | 228 | |
229 | mutex_enter(softnet_lock); | | 229 | mutex_enter(softnet_lock); |
230 | KERNEL_LOCK(1, NULL); | | 230 | KERNEL_LOCK(1, NULL); |
231 | for (;;) { | | 231 | for (;;) { |
232 | s = splnet(); | | 232 | s = splnet(); |
233 | IF_DEQUEUE(&ip6intrq, m); | | 233 | IF_DEQUEUE(&ip6intrq, m); |
234 | splx(s); | | 234 | splx(s); |
235 | if (m == 0) | | 235 | if (m == 0) |
236 | break; | | 236 | break; |
237 | /* drop the packet if IPv6 operation is disabled on the IF */ | | 237 | /* drop the packet if IPv6 operation is disabled on the IF */ |
238 | if ((ND_IFINFO(m->m_pkthdr.rcvif)->flags & ND6_IFF_IFDISABLED)) { | | 238 | if ((ND_IFINFO(m->m_pkthdr.rcvif)->flags & ND6_IFF_IFDISABLED)) { |
239 | m_freem(m); | | 239 | m_freem(m); |
240 | break; | | 240 | break; |
241 | } | | 241 | } |
242 | ip6_input(m); | | 242 | ip6_input(m); |
243 | } | | 243 | } |
244 | KERNEL_UNLOCK_ONE(NULL); | | 244 | KERNEL_UNLOCK_ONE(NULL); |
245 | mutex_exit(softnet_lock); | | 245 | mutex_exit(softnet_lock); |
246 | } | | 246 | } |
247 | | | 247 | |
248 | extern struct route ip6_forward_rt; | | 248 | extern struct route ip6_forward_rt; |
249 | | | 249 | |
250 | void | | 250 | void |
251 | ip6_input(struct mbuf *m) | | 251 | ip6_input(struct mbuf *m) |
252 | { | | 252 | { |
253 | struct ip6_hdr *ip6; | | 253 | struct ip6_hdr *ip6; |
254 | int hit, off = sizeof(struct ip6_hdr), nest; | | 254 | int hit, off = sizeof(struct ip6_hdr), nest; |
255 | u_int32_t plen; | | 255 | u_int32_t plen; |
256 | u_int32_t rtalert = ~0; | | 256 | u_int32_t rtalert = ~0; |
257 | int nxt, ours = 0, rh_present = 0; | | 257 | int nxt, ours = 0, rh_present = 0; |
258 | struct ifnet *deliverifp = NULL; | | 258 | struct ifnet *deliverifp = NULL; |
259 | int srcrt = 0; | | 259 | int srcrt = 0; |
260 | const struct rtentry *rt; | | 260 | const struct rtentry *rt; |
261 | union { | | 261 | union { |
262 | struct sockaddr dst; | | 262 | struct sockaddr dst; |
263 | struct sockaddr_in6 dst6; | | 263 | struct sockaddr_in6 dst6; |
264 | } u; | | 264 | } u; |
265 | #ifdef FAST_IPSEC | | 265 | #ifdef FAST_IPSEC |
266 | struct m_tag *mtag; | | 266 | struct m_tag *mtag; |
267 | struct tdb_ident *tdbi; | | 267 | struct tdb_ident *tdbi; |
268 | struct secpolicy *sp; | | 268 | struct secpolicy *sp; |
269 | int s, error; | | 269 | int s, error; |
270 | #endif | | 270 | #endif |
271 | | | 271 | |
272 | #ifdef IPSEC | | 272 | #ifdef IPSEC |
273 | /* | | 273 | /* |
274 | * should the inner packet be considered authentic? | | 274 | * should the inner packet be considered authentic? |
275 | * see comment in ah4_input(). | | 275 | * see comment in ah4_input(). |
276 | */ | | 276 | */ |
277 | m->m_flags &= ~M_AUTHIPHDR; | | 277 | m->m_flags &= ~M_AUTHIPHDR; |
278 | m->m_flags &= ~M_AUTHIPDGM; | | 278 | m->m_flags &= ~M_AUTHIPDGM; |
279 | #endif | | 279 | #endif |
280 | | | 280 | |
281 | /* | | 281 | /* |
282 | * make sure we don't have onion peering information into m_tag. | | 282 | * make sure we don't have onion peering information into m_tag. |
283 | */ | | 283 | */ |
284 | ip6_delaux(m); | | 284 | ip6_delaux(m); |
285 | | | 285 | |
286 | /* | | 286 | /* |
287 | * mbuf statistics | | 287 | * mbuf statistics |
288 | */ | | 288 | */ |
289 | if (m->m_flags & M_EXT) { | | 289 | if (m->m_flags & M_EXT) { |
290 | if (m->m_next) | | 290 | if (m->m_next) |
291 | IP6_STATINC(IP6_STAT_MEXT2M); | | 291 | IP6_STATINC(IP6_STAT_MEXT2M); |
292 | else | | 292 | else |
293 | IP6_STATINC(IP6_STAT_MEXT1); | | 293 | IP6_STATINC(IP6_STAT_MEXT1); |
294 | } else { | | 294 | } else { |
295 | #define M2MMAX 32 | | 295 | #define M2MMAX 32 |
296 | if (m->m_next) { | | 296 | if (m->m_next) { |
297 | if (m->m_flags & M_LOOP) { | | 297 | if (m->m_flags & M_LOOP) { |
298 | /*XXX*/ IP6_STATINC(IP6_STAT_M2M + lo0ifp->if_index); | | 298 | /*XXX*/ IP6_STATINC(IP6_STAT_M2M + lo0ifp->if_index); |
299 | } else if (m->m_pkthdr.rcvif->if_index < M2MMAX) { | | 299 | } else if (m->m_pkthdr.rcvif->if_index < M2MMAX) { |
300 | IP6_STATINC(IP6_STAT_M2M + | | 300 | IP6_STATINC(IP6_STAT_M2M + |
301 | m->m_pkthdr.rcvif->if_index); | | 301 | m->m_pkthdr.rcvif->if_index); |
302 | } else | | 302 | } else |
303 | IP6_STATINC(IP6_STAT_M2M); | | 303 | IP6_STATINC(IP6_STAT_M2M); |
304 | } else | | 304 | } else |
305 | IP6_STATINC(IP6_STAT_M1); | | 305 | IP6_STATINC(IP6_STAT_M1); |
306 | #undef M2MMAX | | 306 | #undef M2MMAX |
307 | } | | 307 | } |
308 | | | 308 | |
309 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive); | | 309 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive); |
310 | IP6_STATINC(IP6_STAT_TOTAL); | | 310 | IP6_STATINC(IP6_STAT_TOTAL); |
311 | | | 311 | |
312 | /* | | 312 | /* |
313 | * If the IPv6 header is not aligned, slurp it up into a new | | 313 | * If the IPv6 header is not aligned, slurp it up into a new |
314 | * mbuf with space for link headers, in the event we forward | | 314 | * mbuf with space for link headers, in the event we forward |
315 | * it. Otherwise, if it is aligned, make sure the entire base | | 315 | * it. Otherwise, if it is aligned, make sure the entire base |
316 | * IPv6 header is in the first mbuf of the chain. | | 316 | * IPv6 header is in the first mbuf of the chain. |
317 | */ | | 317 | */ |
318 | if (IP6_HDR_ALIGNED_P(mtod(m, void *)) == 0) { | | 318 | if (IP6_HDR_ALIGNED_P(mtod(m, void *)) == 0) { |
319 | struct ifnet *inifp = m->m_pkthdr.rcvif; | | 319 | struct ifnet *inifp = m->m_pkthdr.rcvif; |
320 | if ((m = m_copyup(m, sizeof(struct ip6_hdr), | | 320 | if ((m = m_copyup(m, sizeof(struct ip6_hdr), |
321 | (max_linkhdr + 3) & ~3)) == NULL) { | | 321 | (max_linkhdr + 3) & ~3)) == NULL) { |
322 | /* XXXJRT new stat, please */ | | 322 | /* XXXJRT new stat, please */ |
323 | IP6_STATINC(IP6_STAT_TOOSMALL); | | 323 | IP6_STATINC(IP6_STAT_TOOSMALL); |
324 | in6_ifstat_inc(inifp, ifs6_in_hdrerr); | | 324 | in6_ifstat_inc(inifp, ifs6_in_hdrerr); |
325 | return; | | 325 | return; |
326 | } | | 326 | } |
327 | } else if (__predict_false(m->m_len < sizeof(struct ip6_hdr))) { | | 327 | } else if (__predict_false(m->m_len < sizeof(struct ip6_hdr))) { |
328 | struct ifnet *inifp = m->m_pkthdr.rcvif; | | 328 | struct ifnet *inifp = m->m_pkthdr.rcvif; |
329 | if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { | | 329 | if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { |
330 | IP6_STATINC(IP6_STAT_TOOSMALL); | | 330 | IP6_STATINC(IP6_STAT_TOOSMALL); |
331 | in6_ifstat_inc(inifp, ifs6_in_hdrerr); | | 331 | in6_ifstat_inc(inifp, ifs6_in_hdrerr); |
332 | return; | | 332 | return; |
333 | } | | 333 | } |
334 | } | | 334 | } |
335 | | | 335 | |
336 | ip6 = mtod(m, struct ip6_hdr *); | | 336 | ip6 = mtod(m, struct ip6_hdr *); |
337 | | | 337 | |
338 | if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { | | 338 | if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { |
339 | IP6_STATINC(IP6_STAT_BADVERS); | | 339 | IP6_STATINC(IP6_STAT_BADVERS); |
340 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); | | 340 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); |
341 | goto bad; | | 341 | goto bad; |
342 | } | | 342 | } |
343 | | | 343 | |
344 | #if defined(IPSEC) | | 344 | #if defined(IPSEC) |
345 | /* IPv6 fast forwarding is not compatible with IPsec. */ | | 345 | /* IPv6 fast forwarding is not compatible with IPsec. */ |
346 | m->m_flags &= ~M_CANFASTFWD; | | 346 | m->m_flags &= ~M_CANFASTFWD; |
347 | #else | | 347 | #else |
348 | /* | | 348 | /* |
349 | * Assume that we can create a fast-forward IP flow entry | | 349 | * Assume that we can create a fast-forward IP flow entry |
350 | * based on this packet. | | 350 | * based on this packet. |
351 | */ | | 351 | */ |
352 | m->m_flags |= M_CANFASTFWD; | | 352 | m->m_flags |= M_CANFASTFWD; |
353 | #endif | | 353 | #endif |
354 | | | 354 | |
355 | #ifdef PFIL_HOOKS | | 355 | #ifdef PFIL_HOOKS |
356 | /* | | 356 | /* |
357 | * Run through list of hooks for input packets. If there are any | | 357 | * Run through list of hooks for input packets. If there are any |
358 | * filters which require that additional packets in the flow are | | 358 | * filters which require that additional packets in the flow are |
359 | * not fast-forwarded, they must clear the M_CANFASTFWD flag. | | 359 | * not fast-forwarded, they must clear the M_CANFASTFWD flag. |
360 | * Note that filters must _never_ set this flag, as another filter | | 360 | * Note that filters must _never_ set this flag, as another filter |
361 | * in the list may have previously cleared it. | | 361 | * in the list may have previously cleared it. |
362 | */ | | 362 | */ |
363 | /* | | 363 | /* |
364 | * let ipfilter look at packet on the wire, | | 364 | * let ipfilter look at packet on the wire, |
365 | * not the decapsulated packet. | | 365 | * not the decapsulated packet. |
366 | */ | | 366 | */ |
367 | #ifdef IPSEC | | 367 | #ifdef IPSEC |
368 | if (!ipsec_getnhist(m)) | | 368 | if (!ipsec_getnhist(m)) |
369 | #elif defined(FAST_IPSEC) | | 369 | #elif defined(FAST_IPSEC) |
370 | if (!ipsec_indone(m)) | | 370 | if (!ipsec_indone(m)) |
371 | #else | | 371 | #else |
372 | if (1) | | 372 | if (1) |
373 | #endif | | 373 | #endif |
374 | { | | 374 | { |
375 | struct in6_addr odst; | | 375 | struct in6_addr odst; |
376 | | | 376 | |
377 | odst = ip6->ip6_dst; | | 377 | odst = ip6->ip6_dst; |
378 | if (pfil_run_hooks(&inet6_pfil_hook, &m, m->m_pkthdr.rcvif, | | 378 | if (pfil_run_hooks(&inet6_pfil_hook, &m, m->m_pkthdr.rcvif, |
379 | PFIL_IN) != 0) | | 379 | PFIL_IN) != 0) |
380 | return; | | 380 | return; |
381 | if (m == NULL) | | 381 | if (m == NULL) |
382 | return; | | 382 | return; |
383 | ip6 = mtod(m, struct ip6_hdr *); | | 383 | ip6 = mtod(m, struct ip6_hdr *); |
384 | srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst); | | 384 | srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst); |
385 | } | | 385 | } |
386 | #endif /* PFIL_HOOKS */ | | 386 | #endif /* PFIL_HOOKS */ |
387 | | | 387 | |
388 | IP6_STATINC(IP6_STAT_NXTHIST + ip6->ip6_nxt); | | 388 | IP6_STATINC(IP6_STAT_NXTHIST + ip6->ip6_nxt); |
389 | | | 389 | |
390 | #ifdef ALTQ | | 390 | #ifdef ALTQ |
391 | if (altq_input != NULL && (*altq_input)(m, AF_INET6) == 0) { | | 391 | if (altq_input != NULL && (*altq_input)(m, AF_INET6) == 0) { |
392 | /* packet is dropped by traffic conditioner */ | | 392 | /* packet is dropped by traffic conditioner */ |
393 | return; | | 393 | return; |
394 | } | | 394 | } |
395 | #endif | | 395 | #endif |
396 | | | 396 | |
397 | /* | | 397 | /* |
398 | * Check against address spoofing/corruption. | | 398 | * Check against address spoofing/corruption. |
399 | */ | | 399 | */ |
400 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) || | | 400 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) || |
401 | IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) { | | 401 | IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) { |
402 | /* | | 402 | /* |
403 | * XXX: "badscope" is not very suitable for a multicast source. | | 403 | * XXX: "badscope" is not very suitable for a multicast source. |
404 | */ | | 404 | */ |
405 | IP6_STATINC(IP6_STAT_BADSCOPE); | | 405 | IP6_STATINC(IP6_STAT_BADSCOPE); |
406 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); | | 406 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); |
407 | goto bad; | | 407 | goto bad; |
408 | } | | 408 | } |
409 | /* | | 409 | /* |
410 | * The following check is not documented in specs. A malicious | | 410 | * The following check is not documented in specs. A malicious |
411 | * party may be able to use IPv4 mapped addr to confuse tcp/udp stack | | 411 | * party may be able to use IPv4 mapped addr to confuse tcp/udp stack |
412 | * and bypass security checks (act as if it was from 127.0.0.1 by using | | 412 | * and bypass security checks (act as if it was from 127.0.0.1 by using |
413 | * IPv6 src ::ffff:127.0.0.1). Be cautious. | | 413 | * IPv6 src ::ffff:127.0.0.1). Be cautious. |
414 | * | | 414 | * |
415 | * This check chokes if we are in an SIIT cloud. As none of BSDs | | 415 | * This check chokes if we are in an SIIT cloud. As none of BSDs |
416 | * support IPv4-less kernel compilation, we cannot support SIIT | | 416 | * support IPv4-less kernel compilation, we cannot support SIIT |
417 | * environment at all. So, it makes more sense for us to reject any | | 417 | * environment at all. So, it makes more sense for us to reject any |
418 | * malicious packets for non-SIIT environment, than try to do a | | 418 | * malicious packets for non-SIIT environment, than try to do a |
419 | * partial support for SIIT environment. | | 419 | * partial support for SIIT environment. |
420 | */ | | 420 | */ |
421 | if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || | | 421 | if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || |
422 | IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { | | 422 | IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { |
423 | IP6_STATINC(IP6_STAT_BADSCOPE); | | 423 | IP6_STATINC(IP6_STAT_BADSCOPE); |
424 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); | | 424 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); |
425 | goto bad; | | 425 | goto bad; |
426 | } | | 426 | } |
427 | #if 0 | | 427 | #if 0 |
428 | /* | | 428 | /* |
429 | * Reject packets with IPv4 compatible addresses (auto tunnel). | | 429 | * Reject packets with IPv4 compatible addresses (auto tunnel). |
430 | * | | 430 | * |
431 | * The code forbids auto tunnel relay case in RFC1933 (the check is | | 431 | * The code forbids auto tunnel relay case in RFC1933 (the check is |
432 | * stronger than RFC1933). We may want to re-enable it if mech-xx | | 432 | * stronger than RFC1933). We may want to re-enable it if mech-xx |
433 | * is revised to forbid relaying case. | | 433 | * is revised to forbid relaying case. |
434 | */ | | 434 | */ |
435 | if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) || | | 435 | if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) || |
436 | IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) { | | 436 | IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) { |
437 | IP6_STATINC(IP6_STAT_BADSCOPE); | | 437 | IP6_STATINC(IP6_STAT_BADSCOPE); |
438 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); | | 438 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); |
439 | goto bad; | | 439 | goto bad; |
440 | } | | 440 | } |
441 | #endif | | 441 | #endif |
442 | | | 442 | |
443 | /* | | 443 | /* |
444 | * Disambiguate address scope zones (if there is ambiguity). | | 444 | * Disambiguate address scope zones (if there is ambiguity). |
445 | * We first make sure that the original source or destination address | | 445 | * We first make sure that the original source or destination address |
446 | * is not in our internal form for scoped addresses. Such addresses | | 446 | * is not in our internal form for scoped addresses. Such addresses |
447 | * are not necessarily invalid spec-wise, but we cannot accept them due | | 447 | * are not necessarily invalid spec-wise, but we cannot accept them due |
448 | * to the usage conflict. | | 448 | * to the usage conflict. |
449 | * in6_setscope() then also checks and rejects the cases where src or | | 449 | * in6_setscope() then also checks and rejects the cases where src or |
450 | * dst are the loopback address and the receiving interface | | 450 | * dst are the loopback address and the receiving interface |
451 | * is not loopback. | | 451 | * is not loopback. |
452 | */ | | 452 | */ |
453 | if (__predict_false( | | 453 | if (__predict_false( |
454 | m_makewritable(&m, 0, sizeof(struct ip6_hdr), M_DONTWAIT))) | | 454 | m_makewritable(&m, 0, sizeof(struct ip6_hdr), M_DONTWAIT))) |
455 | goto bad; | | 455 | goto bad; |
456 | ip6 = mtod(m, struct ip6_hdr *); | | 456 | ip6 = mtod(m, struct ip6_hdr *); |
457 | if (in6_clearscope(&ip6->ip6_src) || in6_clearscope(&ip6->ip6_dst)) { | | 457 | if (in6_clearscope(&ip6->ip6_src) || in6_clearscope(&ip6->ip6_dst)) { |
458 | IP6_STATINC(IP6_STAT_BADSCOPE); /* XXX */ | | 458 | IP6_STATINC(IP6_STAT_BADSCOPE); /* XXX */ |
459 | goto bad; | | 459 | goto bad; |
460 | } | | 460 | } |
461 | if (in6_setscope(&ip6->ip6_src, m->m_pkthdr.rcvif, NULL) || | | 461 | if (in6_setscope(&ip6->ip6_src, m->m_pkthdr.rcvif, NULL) || |
462 | in6_setscope(&ip6->ip6_dst, m->m_pkthdr.rcvif, NULL)) { | | 462 | in6_setscope(&ip6->ip6_dst, m->m_pkthdr.rcvif, NULL)) { |
463 | IP6_STATINC(IP6_STAT_BADSCOPE); | | 463 | IP6_STATINC(IP6_STAT_BADSCOPE); |
464 | goto bad; | | 464 | goto bad; |
465 | } | | 465 | } |
466 | | | 466 | |
467 | /* | | 467 | /* |
468 | * Multicast check | | 468 | * Multicast check |
469 | */ | | 469 | */ |
470 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { | | 470 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { |
471 | struct in6_multi *in6m = 0; | | 471 | struct in6_multi *in6m = 0; |
472 | | | 472 | |
473 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast); | | 473 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast); |
474 | /* | | 474 | /* |
475 | * See if we belong to the destination multicast group on the | | 475 | * See if we belong to the destination multicast group on the |
476 | * arrival interface. | | 476 | * arrival interface. |
477 | */ | | 477 | */ |
478 | IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m); | | 478 | IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m); |
479 | if (in6m) | | 479 | if (in6m) |
480 | ours = 1; | | 480 | ours = 1; |
481 | else if (!ip6_mrouter) { | | 481 | else if (!ip6_mrouter) { |
482 | uint64_t *ip6s = IP6_STAT_GETREF(); | | 482 | uint64_t *ip6s = IP6_STAT_GETREF(); |
483 | ip6s[IP6_STAT_NOTMEMBER]++; | | 483 | ip6s[IP6_STAT_NOTMEMBER]++; |
484 | ip6s[IP6_STAT_CANTFORWARD]++; | | 484 | ip6s[IP6_STAT_CANTFORWARD]++; |
485 | IP6_STAT_PUTREF(); | | 485 | IP6_STAT_PUTREF(); |
486 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); | | 486 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); |
487 | goto bad; | | 487 | goto bad; |
488 | } | | 488 | } |
489 | deliverifp = m->m_pkthdr.rcvif; | | 489 | deliverifp = m->m_pkthdr.rcvif; |
490 | goto hbhcheck; | | 490 | goto hbhcheck; |
491 | } | | 491 | } |
492 | | | 492 | |
493 | sockaddr_in6_init(&u.dst6, &ip6->ip6_dst, 0, 0, 0); | | 493 | sockaddr_in6_init(&u.dst6, &ip6->ip6_dst, 0, 0, 0); |
494 | | | 494 | |
495 | /* | | 495 | /* |
496 | * Unicast check | | 496 | * Unicast check |
497 | */ | | 497 | */ |
498 | rt = rtcache_lookup2(&ip6_forward_rt, &u.dst, 1, &hit); | | 498 | rt = rtcache_lookup2(&ip6_forward_rt, &u.dst, 1, &hit); |
499 | if (hit) | | 499 | if (hit) |
500 | IP6_STATINC(IP6_STAT_FORWARD_CACHEHIT); | | 500 | IP6_STATINC(IP6_STAT_FORWARD_CACHEHIT); |
501 | else | | 501 | else |
502 | IP6_STATINC(IP6_STAT_FORWARD_CACHEMISS); | | 502 | IP6_STATINC(IP6_STAT_FORWARD_CACHEMISS); |
503 | | | 503 | |
504 | #define rt6_getkey(__rt) satocsin6(rt_getkey(__rt)) | | 504 | #define rt6_getkey(__rt) satocsin6(rt_getkey(__rt)) |
505 | | | 505 | |
506 | /* | | 506 | /* |
507 | * Accept the packet if the forwarding interface to the destination | | 507 | * Accept the packet if the forwarding interface to the destination |
508 | * according to the routing table is the loopback interface, | | 508 | * according to the routing table is the loopback interface, |
509 | * unless the associated route has a gateway. | | 509 | * unless the associated route has a gateway. |
510 | * Note that this approach causes to accept a packet if there is a | | 510 | * Note that this approach causes to accept a packet if there is a |
511 | * route to the loopback interface for the destination of the packet. | | 511 | * route to the loopback interface for the destination of the packet. |
512 | * But we think it's even useful in some situations, e.g. when using | | 512 | * But we think it's even useful in some situations, e.g. when using |
513 | * a special daemon which wants to intercept the packet. | | 513 | * a special daemon which wants to intercept the packet. |
514 | */ | | 514 | */ |
515 | if (rt != NULL && | | 515 | if (rt != NULL && |
516 | (rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST && | | 516 | (rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST && |
517 | !(rt->rt_flags & RTF_CLONED) && | | 517 | !(rt->rt_flags & RTF_CLONED) && |
518 | #if 0 | | 518 | #if 0 |
519 | /* | | 519 | /* |
520 | * The check below is redundant since the comparison of | | 520 | * The check below is redundant since the comparison of |
521 | * the destination and the key of the rtentry has | | 521 | * the destination and the key of the rtentry has |
522 | * already done through looking up the routing table. | | 522 | * already done through looking up the routing table. |
523 | */ | | 523 | */ |
524 | IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &rt6_getkey(rt)->sin6_addr) && | | 524 | IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, &rt6_getkey(rt)->sin6_addr) && |
525 | #endif | | 525 | #endif |
526 | rt->rt_ifp->if_type == IFT_LOOP) { | | 526 | rt->rt_ifp->if_type == IFT_LOOP) { |
527 | struct in6_ifaddr *ia6 = (struct in6_ifaddr *)rt->rt_ifa; | | 527 | struct in6_ifaddr *ia6 = (struct in6_ifaddr *)rt->rt_ifa; |
528 | if (ia6->ia6_flags & IN6_IFF_ANYCAST) | | 528 | if (ia6->ia6_flags & IN6_IFF_ANYCAST) |
529 | m->m_flags |= M_ANYCAST6; | | 529 | m->m_flags |= M_ANYCAST6; |
530 | /* | | 530 | /* |
531 | * packets to a tentative, duplicated, or somehow invalid | | 531 | * packets to a tentative, duplicated, or somehow invalid |
532 | * address must not be accepted. | | 532 | * address must not be accepted. |
533 | */ | | 533 | */ |
534 | if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) { | | 534 | if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) { |
535 | /* this address is ready */ | | 535 | /* this address is ready */ |
536 | ours = 1; | | 536 | ours = 1; |
537 | deliverifp = ia6->ia_ifp; /* correct? */ | | 537 | deliverifp = ia6->ia_ifp; /* correct? */ |
538 | goto hbhcheck; | | 538 | goto hbhcheck; |
539 | } else { | | 539 | } else { |
540 | /* address is not ready, so discard the packet. */ | | 540 | /* address is not ready, so discard the packet. */ |
541 | nd6log((LOG_INFO, | | 541 | nd6log((LOG_INFO, |
542 | "ip6_input: packet to an unready address %s->%s\n", | | 542 | "ip6_input: packet to an unready address %s->%s\n", |
543 | ip6_sprintf(&ip6->ip6_src), | | 543 | ip6_sprintf(&ip6->ip6_src), |
544 | ip6_sprintf(&ip6->ip6_dst))); | | 544 | ip6_sprintf(&ip6->ip6_dst))); |
545 | | | 545 | |
546 | goto bad; | | 546 | goto bad; |
547 | } | | 547 | } |
548 | } | | 548 | } |
549 | | | 549 | |
550 | /* | | 550 | /* |
551 | * FAITH (Firewall Aided Internet Translator) | | 551 | * FAITH (Firewall Aided Internet Translator) |
552 | */ | | 552 | */ |
553 | #if defined(NFAITH) && 0 < NFAITH | | 553 | #if defined(NFAITH) && 0 < NFAITH |
554 | if (ip6_keepfaith) { | | 554 | if (ip6_keepfaith) { |
555 | if (rt != NULL && rt->rt_ifp != NULL && | | 555 | if (rt != NULL && rt->rt_ifp != NULL && |
556 | rt->rt_ifp->if_type == IFT_FAITH) { | | 556 | rt->rt_ifp->if_type == IFT_FAITH) { |
557 | /* XXX do we need more sanity checks? */ | | 557 | /* XXX do we need more sanity checks? */ |
558 | ours = 1; | | 558 | ours = 1; |
559 | deliverifp = rt->rt_ifp; /* faith */ | | 559 | deliverifp = rt->rt_ifp; /* faith */ |
560 | goto hbhcheck; | | 560 | goto hbhcheck; |
561 | } | | 561 | } |
562 | } | | 562 | } |
563 | #endif | | 563 | #endif |
564 | | | 564 | |
565 | #if 0 | | 565 | #if 0 |
566 | { | | 566 | { |
567 | /* | | 567 | /* |
568 | * Last resort: check in6_ifaddr for incoming interface. | | 568 | * Last resort: check in6_ifaddr for incoming interface. |
569 | * The code is here until I update the "goto ours hack" code above | | 569 | * The code is here until I update the "goto ours hack" code above |
570 | * working right. | | 570 | * working right. |
571 | */ | | 571 | */ |
572 | struct ifaddr *ifa; | | 572 | struct ifaddr *ifa; |
573 | IFADDR_FOREACH(ifa, m->m_pkthdr.rcvif) { | | 573 | IFADDR_FOREACH(ifa, m->m_pkthdr.rcvif) { |
574 | if (ifa->ifa_addr == NULL) | | 574 | if (ifa->ifa_addr == NULL) |
575 | continue; /* just for safety */ | | 575 | continue; /* just for safety */ |
576 | if (ifa->ifa_addr->sa_family != AF_INET6) | | 576 | if (ifa->ifa_addr->sa_family != AF_INET6) |
577 | continue; | | 577 | continue; |
578 | if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ip6->ip6_dst)) { | | 578 | if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ip6->ip6_dst)) { |
579 | ours = 1; | | 579 | ours = 1; |
580 | deliverifp = ifa->ifa_ifp; | | 580 | deliverifp = ifa->ifa_ifp; |
581 | goto hbhcheck; | | 581 | goto hbhcheck; |
582 | } | | 582 | } |
583 | } | | 583 | } |
584 | } | | 584 | } |
585 | #endif | | 585 | #endif |
586 | | | 586 | |
587 | /* | | 587 | /* |
588 | * Now there is no reason to process the packet if it's not our own | | 588 | * Now there is no reason to process the packet if it's not our own |
589 | * and we're not a router. | | 589 | * and we're not a router. |
590 | */ | | 590 | */ |
591 | if (!ip6_forwarding) { | | 591 | if (!ip6_forwarding) { |
592 | IP6_STATINC(IP6_STAT_CANTFORWARD); | | 592 | IP6_STATINC(IP6_STAT_CANTFORWARD); |
593 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); | | 593 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); |
594 | goto bad; | | 594 | goto bad; |
595 | } | | 595 | } |
596 | | | 596 | |
597 | hbhcheck: | | 597 | hbhcheck: |
598 | /* | | 598 | /* |
599 | * record address information into m_tag, if we don't have one yet. | | 599 | * record address information into m_tag, if we don't have one yet. |
600 | * note that we are unable to record it, if the address is not listed | | 600 | * note that we are unable to record it, if the address is not listed |
601 | * as our interface address (e.g. multicast addresses, addresses | | 601 | * as our interface address (e.g. multicast addresses, addresses |
602 | * within FAITH prefixes and such). | | 602 | * within FAITH prefixes and such). |
603 | */ | | 603 | */ |
604 | if (deliverifp && ip6_getdstifaddr(m) == NULL) { | | 604 | if (deliverifp && ip6_getdstifaddr(m) == NULL) { |
605 | struct in6_ifaddr *ia6; | | 605 | struct in6_ifaddr *ia6; |
606 | | | 606 | |
607 | ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst); | | 607 | ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst); |
608 | if (ia6 != NULL && ip6_setdstifaddr(m, ia6) == NULL) { | | 608 | if (ia6 != NULL && ip6_setdstifaddr(m, ia6) == NULL) { |
609 | /* | | 609 | /* |
610 | * XXX maybe we should drop the packet here, | | 610 | * XXX maybe we should drop the packet here, |
611 | * as we could not provide enough information | | 611 | * as we could not provide enough information |
612 | * to the upper layers. | | 612 | * to the upper layers. |
613 | */ | | 613 | */ |
614 | } | | 614 | } |
615 | } | | 615 | } |
616 | | | 616 | |
617 | /* | | 617 | /* |
618 | * Process Hop-by-Hop options header if it's contained. | | 618 | * Process Hop-by-Hop options header if it's contained. |
619 | * m may be modified in ip6_hopopts_input(). | | 619 | * m may be modified in ip6_hopopts_input(). |
620 | * If a JumboPayload option is included, plen will also be modified. | | 620 | * If a JumboPayload option is included, plen will also be modified. |
621 | */ | | 621 | */ |
622 | plen = (u_int32_t)ntohs(ip6->ip6_plen); | | 622 | plen = (u_int32_t)ntohs(ip6->ip6_plen); |
623 | if (ip6->ip6_nxt == IPPROTO_HOPOPTS) { | | 623 | if (ip6->ip6_nxt == IPPROTO_HOPOPTS) { |
624 | struct ip6_hbh *hbh; | | 624 | struct ip6_hbh *hbh; |
625 | | | 625 | |
626 | if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) { | | 626 | if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) { |
627 | #if 0 /*touches NULL pointer*/ | | 627 | #if 0 /*touches NULL pointer*/ |
628 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); | | 628 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); |
629 | #endif | | 629 | #endif |
630 | return; /* m have already been freed */ | | 630 | return; /* m have already been freed */ |
631 | } | | 631 | } |
632 | | | 632 | |
633 | /* adjust pointer */ | | 633 | /* adjust pointer */ |
634 | ip6 = mtod(m, struct ip6_hdr *); | | 634 | ip6 = mtod(m, struct ip6_hdr *); |
635 | | | 635 | |
636 | /* | | 636 | /* |
637 | * if the payload length field is 0 and the next header field | | 637 | * if the payload length field is 0 and the next header field |
638 | * indicates Hop-by-Hop Options header, then a Jumbo Payload | | 638 | * indicates Hop-by-Hop Options header, then a Jumbo Payload |
639 | * option MUST be included. | | 639 | * option MUST be included. |
640 | */ | | 640 | */ |
641 | if (ip6->ip6_plen == 0 && plen == 0) { | | 641 | if (ip6->ip6_plen == 0 && plen == 0) { |
642 | /* | | 642 | /* |
643 | * Note that if a valid jumbo payload option is | | 643 | * Note that if a valid jumbo payload option is |
644 | * contained, ip6_hopopts_input() must set a valid | | 644 | * contained, ip6_hopopts_input() must set a valid |
645 | * (non-zero) payload length to the variable plen. | | 645 | * (non-zero) payload length to the variable plen. |
646 | */ | | 646 | */ |
647 | IP6_STATINC(IP6_STAT_BADOPTIONS); | | 647 | IP6_STATINC(IP6_STAT_BADOPTIONS); |
648 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); | | 648 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); |
649 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); | | 649 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); |
650 | icmp6_error(m, ICMP6_PARAM_PROB, | | 650 | icmp6_error(m, ICMP6_PARAM_PROB, |
651 | ICMP6_PARAMPROB_HEADER, | | 651 | ICMP6_PARAMPROB_HEADER, |
652 | (char *)&ip6->ip6_plen - (char *)ip6); | | 652 | (char *)&ip6->ip6_plen - (char *)ip6); |
653 | return; | | 653 | return; |
654 | } | | 654 | } |
655 | IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), | | 655 | IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), |
656 | sizeof(struct ip6_hbh)); | | 656 | sizeof(struct ip6_hbh)); |
657 | if (hbh == NULL) { | | 657 | if (hbh == NULL) { |
658 | IP6_STATINC(IP6_STAT_TOOSHORT); | | 658 | IP6_STATINC(IP6_STAT_TOOSHORT); |
659 | return; | | 659 | return; |
660 | } | | 660 | } |
661 | KASSERT(IP6_HDR_ALIGNED_P(hbh)); | | 661 | KASSERT(IP6_HDR_ALIGNED_P(hbh)); |
662 | nxt = hbh->ip6h_nxt; | | 662 | nxt = hbh->ip6h_nxt; |
663 | | | 663 | |
664 | /* | | 664 | /* |
665 | * accept the packet if a router alert option is included | | 665 | * accept the packet if a router alert option is included |
666 | * and we act as an IPv6 router. | | 666 | * and we act as an IPv6 router. |
667 | */ | | 667 | */ |
668 | if (rtalert != ~0 && ip6_forwarding) | | 668 | if (rtalert != ~0 && ip6_forwarding) |
669 | ours = 1; | | 669 | ours = 1; |
670 | } else | | 670 | } else |
671 | nxt = ip6->ip6_nxt; | | 671 | nxt = ip6->ip6_nxt; |
672 | | | 672 | |
673 | /* | | 673 | /* |
674 | * Check that the amount of data in the buffers | | 674 | * Check that the amount of data in the buffers |
675 | * is as at least much as the IPv6 header would have us expect. | | 675 | * is as at least much as the IPv6 header would have us expect. |
676 | * Trim mbufs if longer than we expect. | | 676 | * Trim mbufs if longer than we expect. |
677 | * Drop packet if shorter than we expect. | | 677 | * Drop packet if shorter than we expect. |
678 | */ | | 678 | */ |
679 | if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) { | | 679 | if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) { |
680 | IP6_STATINC(IP6_STAT_TOOSHORT); | | 680 | IP6_STATINC(IP6_STAT_TOOSHORT); |
681 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); | | 681 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); |
682 | goto bad; | | 682 | goto bad; |
683 | } | | 683 | } |
684 | if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) { | | 684 | if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) { |
685 | if (m->m_len == m->m_pkthdr.len) { | | 685 | if (m->m_len == m->m_pkthdr.len) { |
686 | m->m_len = sizeof(struct ip6_hdr) + plen; | | 686 | m->m_len = sizeof(struct ip6_hdr) + plen; |
687 | m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen; | | 687 | m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen; |
688 | } else | | 688 | } else |
689 | m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len); | | 689 | m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len); |
690 | } | | 690 | } |
691 | | | 691 | |
692 | /* | | 692 | /* |
693 | * Forward if desirable. | | 693 | * Forward if desirable. |
694 | */ | | 694 | */ |
695 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { | | 695 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { |
696 | /* | | 696 | /* |
697 | * If we are acting as a multicast router, all | | 697 | * If we are acting as a multicast router, all |
698 | * incoming multicast packets are passed to the | | 698 | * incoming multicast packets are passed to the |
699 | * kernel-level multicast forwarding function. | | 699 | * kernel-level multicast forwarding function. |
700 | * The packet is returned (relatively) intact; if | | 700 | * The packet is returned (relatively) intact; if |
701 | * ip6_mforward() returns a non-zero value, the packet | | 701 | * ip6_mforward() returns a non-zero value, the packet |
702 | * must be discarded, else it may be accepted below. | | 702 | * must be discarded, else it may be accepted below. |
703 | */ | | 703 | */ |
704 | if (ip6_mrouter && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) { | | 704 | if (ip6_mrouter && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) { |
705 | IP6_STATINC(IP6_STAT_CANTFORWARD); | | 705 | IP6_STATINC(IP6_STAT_CANTFORWARD); |
706 | m_freem(m); | | 706 | m_freem(m); |
707 | return; | | 707 | return; |
708 | } | | 708 | } |
709 | if (!ours) { | | 709 | if (!ours) { |
710 | m_freem(m); | | 710 | m_freem(m); |
711 | return; | | 711 | return; |
712 | } | | 712 | } |
713 | } else if (!ours) { | | 713 | } else if (!ours) { |
714 | ip6_forward(m, srcrt); | | 714 | ip6_forward(m, srcrt); |
715 | return; | | 715 | return; |
716 | } | | 716 | } |
717 | | | 717 | |
718 | ip6 = mtod(m, struct ip6_hdr *); | | 718 | ip6 = mtod(m, struct ip6_hdr *); |
719 | | | 719 | |
720 | /* | | 720 | /* |
721 | * Malicious party may be able to use IPv4 mapped addr to confuse | | 721 | * Malicious party may be able to use IPv4 mapped addr to confuse |
722 | * tcp/udp stack and bypass security checks (act as if it was from | | 722 | * tcp/udp stack and bypass security checks (act as if it was from |
723 | * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1). Be cautious. | | 723 | * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1). Be cautious. |
724 | * | | 724 | * |
725 | * For SIIT end node behavior, you may want to disable the check. | | 725 | * For SIIT end node behavior, you may want to disable the check. |
726 | * However, you will become vulnerable to attacks using IPv4 mapped | | 726 | * However, you will become vulnerable to attacks using IPv4 mapped |
727 | * source. | | 727 | * source. |
728 | */ | | 728 | */ |
729 | if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || | | 729 | if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || |
730 | IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { | | 730 | IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { |
731 | IP6_STATINC(IP6_STAT_BADSCOPE); | | 731 | IP6_STATINC(IP6_STAT_BADSCOPE); |
732 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); | | 732 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); |
733 | goto bad; | | 733 | goto bad; |
734 | } | | 734 | } |
735 | | | 735 | |
736 | /* | | 736 | /* |
737 | * Tell launch routine the next header | | 737 | * Tell launch routine the next header |
738 | */ | | 738 | */ |
739 | #ifdef IFA_STATS | | 739 | #ifdef IFA_STATS |
740 | if (deliverifp != NULL) { | | 740 | if (deliverifp != NULL) { |
741 | struct in6_ifaddr *ia6; | | 741 | struct in6_ifaddr *ia6; |
742 | ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst); | | 742 | ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst); |
743 | if (ia6) | | 743 | if (ia6) |
744 | ia6->ia_ifa.ifa_data.ifad_inbytes += m->m_pkthdr.len; | | 744 | ia6->ia_ifa.ifa_data.ifad_inbytes += m->m_pkthdr.len; |
745 | } | | 745 | } |
746 | #endif | | 746 | #endif |
747 | IP6_STATINC(IP6_STAT_DELIVERED); | | 747 | IP6_STATINC(IP6_STAT_DELIVERED); |
748 | in6_ifstat_inc(deliverifp, ifs6_in_deliver); | | 748 | in6_ifstat_inc(deliverifp, ifs6_in_deliver); |
749 | nest = 0; | | 749 | nest = 0; |
750 | | | 750 | |
751 | rh_present = 0; | | 751 | rh_present = 0; |
752 | while (nxt != IPPROTO_DONE) { | | 752 | while (nxt != IPPROTO_DONE) { |
753 | if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) { | | 753 | if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) { |
754 | IP6_STATINC(IP6_STAT_TOOMANYHDR); | | 754 | IP6_STATINC(IP6_STAT_TOOMANYHDR); |
755 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); | | 755 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); |
756 | goto bad; | | 756 | goto bad; |
757 | } | | 757 | } |
758 | | | 758 | |
759 | /* | | 759 | /* |
760 | * protection against faulty packet - there should be | | 760 | * protection against faulty packet - there should be |
761 | * more sanity checks in header chain processing. | | 761 | * more sanity checks in header chain processing. |
762 | */ | | 762 | */ |
763 | if (m->m_pkthdr.len < off) { | | 763 | if (m->m_pkthdr.len < off) { |
764 | IP6_STATINC(IP6_STAT_TOOSHORT); | | 764 | IP6_STATINC(IP6_STAT_TOOSHORT); |
765 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); | | 765 | in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); |
766 | goto bad; | | 766 | goto bad; |
767 | } | | 767 | } |
768 | | | 768 | |
769 | if (nxt == IPPROTO_ROUTING) { | | 769 | if (nxt == IPPROTO_ROUTING) { |
770 | if (rh_present++) { | | 770 | if (rh_present++) { |
771 | in6_ifstat_inc(m->m_pkthdr.rcvif, | | 771 | in6_ifstat_inc(m->m_pkthdr.rcvif, |
772 | ifs6_in_hdrerr); | | 772 | ifs6_in_hdrerr); |
773 | IP6_STATINC(IP6_STAT_BADOPTIONS); | | 773 | IP6_STATINC(IP6_STAT_BADOPTIONS); |
774 | goto bad; | | 774 | goto bad; |
775 | } | | 775 | } |
776 | } | | 776 | } |
777 | | | 777 | |
778 | #ifdef IPSEC | | 778 | #ifdef IPSEC |
779 | /* | | 779 | /* |
780 | * enforce IPsec policy checking if we are seeing last header. | | 780 | * enforce IPsec policy checking if we are seeing last header. |
781 | * note that we do not visit this with protocols with pcb layer | | 781 | * note that we do not visit this with protocols with pcb layer |
782 | * code - like udp/tcp/raw ip. | | 782 | * code - like udp/tcp/raw ip. |
783 | */ | | 783 | */ |
784 | if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 && | | 784 | if ((inet6sw[ip6_protox[nxt]].pr_flags & PR_LASTHDR) != 0 && |
785 | ipsec6_in_reject(m, NULL)) { | | 785 | ipsec6_in_reject(m, NULL)) { |
786 | IPSEC6_STATINC(IPSEC_STAT_IN_POLVIO); | | 786 | IPSEC6_STATINC(IPSEC_STAT_IN_POLVIO); |
787 | goto bad; | | 787 | goto bad; |
788 | } | | 788 | } |
789 | #endif | | 789 | #endif |
790 | #ifdef FAST_IPSEC | | 790 | #ifdef FAST_IPSEC |
791 | /* | | 791 | /* |
792 | * enforce IPsec policy checking if we are seeing last header. | | 792 | * enforce IPsec policy checking if we are seeing last header. |
793 | * note that we do not visit this with protocols with pcb layer | | 793 | * note that we do not visit this with protocols with pcb layer |
794 | * code - like udp/tcp/raw ip. | | 794 | * code - like udp/tcp/raw ip. |
795 | */ | | 795 | */ |
796 | if ((inet6sw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0) { | | 796 | if ((inet6sw[ip_protox[nxt]].pr_flags & PR_LASTHDR) != 0) { |
797 | /* | | 797 | /* |
798 | * Check if the packet has already had IPsec processing | | 798 | * Check if the packet has already had IPsec processing |
799 | * done. If so, then just pass it along. This tag gets | | 799 | * done. If so, then just pass it along. This tag gets |
800 | * set during AH, ESP, etc. input handling, before the | | 800 | * set during AH, ESP, etc. input handling, before the |
801 | * packet is returned to the ip input queue for delivery. | | 801 | * packet is returned to the ip input queue for delivery. |
802 | */ | | 802 | */ |
803 | mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); | | 803 | mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); |
804 | s = splsoftnet(); | | 804 | s = splsoftnet(); |
805 | if (mtag != NULL) { | | 805 | if (mtag != NULL) { |
806 | tdbi = (struct tdb_ident *)(mtag + 1); | | 806 | tdbi = (struct tdb_ident *)(mtag + 1); |
807 | sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND); | | 807 | sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND); |
808 | } else { | | 808 | } else { |
809 | sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, | | 809 | sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, |
810 | IP_FORWARDING, &error); | | 810 | IP_FORWARDING, &error); |
811 | } | | 811 | } |
812 | if (sp != NULL) { | | 812 | if (sp != NULL) { |
813 | /* | | 813 | /* |
814 | * Check security policy against packet attributes. | | 814 | * Check security policy against packet attributes. |
815 | */ | | 815 | */ |
816 | error = ipsec_in_reject(sp, m); | | 816 | error = ipsec_in_reject(sp, m); |
817 | KEY_FREESP(&sp); | | 817 | KEY_FREESP(&sp); |
818 | } else { | | 818 | } else { |
819 | /* XXX error stat??? */ | | 819 | /* XXX error stat??? */ |
820 | error = EINVAL; | | 820 | error = EINVAL; |
821 | DPRINTF(("ip6_input: no SP, packet discarded\n"));/*XXX*/ | | 821 | DPRINTF(("ip6_input: no SP, packet discarded\n"));/*XXX*/ |
822 | } | | 822 | } |
823 | splx(s); | | 823 | splx(s); |
824 | if (error) | | 824 | if (error) |
825 | goto bad; | | 825 | goto bad; |
826 | } | | 826 | } |
827 | #endif /* FAST_IPSEC */ | | 827 | #endif /* FAST_IPSEC */ |
828 | | | 828 | |
829 | | | 829 | |
830 | nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt); | | 830 | nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt); |
831 | } | | 831 | } |
832 | return; | | 832 | return; |
833 | bad: | | 833 | bad: |
834 | m_freem(m); | | 834 | m_freem(m); |
835 | } | | 835 | } |
836 | | | 836 | |
837 | /* | | 837 | /* |
838 | * set/grab in6_ifaddr correspond to IPv6 destination address. | | 838 | * set/grab in6_ifaddr correspond to IPv6 destination address. |
839 | */ | | 839 | */ |
840 | static struct m_tag * | | 840 | static struct m_tag * |
841 | ip6_setdstifaddr(struct mbuf *m, const struct in6_ifaddr *ia) | | 841 | ip6_setdstifaddr(struct mbuf *m, const struct in6_ifaddr *ia) |
842 | { | | 842 | { |
843 | struct m_tag *mtag; | | 843 | struct m_tag *mtag; |
844 | | | 844 | |
845 | mtag = ip6_addaux(m); | | 845 | mtag = ip6_addaux(m); |
846 | if (mtag != NULL) { | | 846 | if (mtag != NULL) { |
847 | struct ip6aux *ip6a; | | 847 | struct ip6aux *ip6a; |
848 | | | 848 | |
849 | ip6a = (struct ip6aux *)(mtag + 1); | | 849 | ip6a = (struct ip6aux *)(mtag + 1); |
850 | in6_setscope(&ip6a->ip6a_src, ia->ia_ifp, &ip6a->ip6a_scope_id); | | 850 | in6_setscope(&ip6a->ip6a_src, ia->ia_ifp, &ip6a->ip6a_scope_id); |
851 | ip6a->ip6a_src = ia->ia_addr.sin6_addr; | | 851 | ip6a->ip6a_src = ia->ia_addr.sin6_addr; |
852 | ip6a->ip6a_flags = ia->ia6_flags; | | 852 | ip6a->ip6a_flags = ia->ia6_flags; |
853 | } | | 853 | } |
854 | return mtag; /* NULL if failed to set */ | | 854 | return mtag; /* NULL if failed to set */ |
855 | } | | 855 | } |
856 | | | 856 | |
857 | const struct ip6aux * | | 857 | const struct ip6aux * |
858 | ip6_getdstifaddr(struct mbuf *m) | | 858 | ip6_getdstifaddr(struct mbuf *m) |
859 | { | | 859 | { |
860 | struct m_tag *mtag; | | 860 | struct m_tag *mtag; |
861 | | | 861 | |
862 | mtag = ip6_findaux(m); | | 862 | mtag = ip6_findaux(m); |
863 | if (mtag != NULL) | | 863 | if (mtag != NULL) |
864 | return (struct ip6aux *)(mtag + 1); | | 864 | return (struct ip6aux *)(mtag + 1); |
865 | else | | 865 | else |
866 | return NULL; | | 866 | return NULL; |
867 | } | | 867 | } |
868 | | | 868 | |
869 | /* | | 869 | /* |
870 | * Hop-by-Hop options header processing. If a valid jumbo payload option is | | 870 | * Hop-by-Hop options header processing. If a valid jumbo payload option is |
871 | * included, the real payload length will be stored in plenp. | | 871 | * included, the real payload length will be stored in plenp. |
872 | * | | 872 | * |
873 | * rtalertp - XXX: should be stored more smart way | | 873 | * rtalertp - XXX: should be stored more smart way |
874 | */ | | 874 | */ |
875 | static int | | 875 | static int |
876 | ip6_hopopts_input(u_int32_t *plenp, u_int32_t *rtalertp, | | 876 | ip6_hopopts_input(u_int32_t *plenp, u_int32_t *rtalertp, |
877 | struct mbuf **mp, int *offp) | | 877 | struct mbuf **mp, int *offp) |
878 | { | | 878 | { |
879 | struct mbuf *m = *mp; | | 879 | struct mbuf *m = *mp; |
880 | int off = *offp, hbhlen; | | 880 | int off = *offp, hbhlen; |
881 | struct ip6_hbh *hbh; | | 881 | struct ip6_hbh *hbh; |
882 | | | 882 | |
883 | /* validation of the length of the header */ | | 883 | /* validation of the length of the header */ |
884 | IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, | | 884 | IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, |
885 | sizeof(struct ip6_hdr), sizeof(struct ip6_hbh)); | | 885 | sizeof(struct ip6_hdr), sizeof(struct ip6_hbh)); |
886 | if (hbh == NULL) { | | 886 | if (hbh == NULL) { |
887 | IP6_STATINC(IP6_STAT_TOOSHORT); | | 887 | IP6_STATINC(IP6_STAT_TOOSHORT); |
888 | return -1; | | 888 | return -1; |
889 | } | | 889 | } |
890 | hbhlen = (hbh->ip6h_len + 1) << 3; | | 890 | hbhlen = (hbh->ip6h_len + 1) << 3; |
891 | IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), | | 891 | IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), |
892 | hbhlen); | | 892 | hbhlen); |
893 | if (hbh == NULL) { | | 893 | if (hbh == NULL) { |
894 | IP6_STATINC(IP6_STAT_TOOSHORT); | | 894 | IP6_STATINC(IP6_STAT_TOOSHORT); |
895 | return -1; | | 895 | return -1; |
896 | } | | 896 | } |
897 | KASSERT(IP6_HDR_ALIGNED_P(hbh)); | | 897 | KASSERT(IP6_HDR_ALIGNED_P(hbh)); |
898 | off += hbhlen; | | 898 | off += hbhlen; |
899 | hbhlen -= sizeof(struct ip6_hbh); | | 899 | hbhlen -= sizeof(struct ip6_hbh); |
900 | | | 900 | |
901 | if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh), | | 901 | if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh), |
902 | hbhlen, rtalertp, plenp) < 0) | | 902 | hbhlen, rtalertp, plenp) < 0) |
903 | return (-1); | | 903 | return (-1); |
904 | | | 904 | |
905 | *offp = off; | | 905 | *offp = off; |
906 | *mp = m; | | 906 | *mp = m; |
907 | return (0); | | 907 | return (0); |
908 | } | | 908 | } |
909 | | | 909 | |
910 | /* | | 910 | /* |
911 | * Search header for all Hop-by-hop options and process each option. | | 911 | * Search header for all Hop-by-hop options and process each option. |
912 | * This function is separate from ip6_hopopts_input() in order to | | 912 | * This function is separate from ip6_hopopts_input() in order to |
913 | * handle a case where the sending node itself process its hop-by-hop | | 913 | * handle a case where the sending node itself process its hop-by-hop |
914 | * options header. In such a case, the function is called from ip6_output(). | | 914 | * options header. In such a case, the function is called from ip6_output(). |
915 | * | | 915 | * |
916 | * The function assumes that hbh header is located right after the IPv6 header | | 916 | * The function assumes that hbh header is located right after the IPv6 header |
917 | * (RFC2460 p7), opthead is pointer into data content in m, and opthead to | | 917 | * (RFC2460 p7), opthead is pointer into data content in m, and opthead to |
918 | * opthead + hbhlen is located in continuous memory region. | | 918 | * opthead + hbhlen is located in continuous memory region. |
919 | */ | | 919 | */ |
920 | int | | 920 | int |
921 | ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen, | | 921 | ip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen, |
922 | u_int32_t *rtalertp, u_int32_t *plenp) | | 922 | u_int32_t *rtalertp, u_int32_t *plenp) |
923 | { | | 923 | { |
924 | struct ip6_hdr *ip6; | | 924 | struct ip6_hdr *ip6; |
925 | int optlen = 0; | | 925 | int optlen = 0; |
926 | u_int8_t *opt = opthead; | | 926 | u_int8_t *opt = opthead; |
927 | u_int16_t rtalert_val; | | 927 | u_int16_t rtalert_val; |
928 | u_int32_t jumboplen; | | 928 | u_int32_t jumboplen; |
929 | const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh); | | 929 | const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh); |
930 | | | 930 | |
931 | for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) { | | 931 | for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) { |
932 | switch (*opt) { | | 932 | switch (*opt) { |
933 | case IP6OPT_PAD1: | | 933 | case IP6OPT_PAD1: |
934 | optlen = 1; | | 934 | optlen = 1; |
935 | break; | | 935 | break; |
936 | case IP6OPT_PADN: | | 936 | case IP6OPT_PADN: |
937 | if (hbhlen < IP6OPT_MINLEN) { | | 937 | if (hbhlen < IP6OPT_MINLEN) { |
938 | IP6_STATINC(IP6_STAT_TOOSMALL); | | 938 | IP6_STATINC(IP6_STAT_TOOSMALL); |
939 | goto bad; | | 939 | goto bad; |
940 | } | | 940 | } |
941 | optlen = *(opt + 1) + 2; | | 941 | optlen = *(opt + 1) + 2; |
942 | break; | | 942 | break; |
943 | case IP6OPT_RTALERT: | | 943 | case IP6OPT_RTALERT: |
944 | /* XXX may need check for alignment */ | | 944 | /* XXX may need check for alignment */ |
945 | if (hbhlen < IP6OPT_RTALERT_LEN) { | | 945 | if (hbhlen < IP6OPT_RTALERT_LEN) { |
946 | IP6_STATINC(IP6_STAT_TOOSMALL); | | 946 | IP6_STATINC(IP6_STAT_TOOSMALL); |
947 | goto bad; | | 947 | goto bad; |
948 | } | | 948 | } |
949 | if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) { | | 949 | if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) { |
950 | /* XXX stat */ | | 950 | /* XXX stat */ |
951 | icmp6_error(m, ICMP6_PARAM_PROB, | | 951 | icmp6_error(m, ICMP6_PARAM_PROB, |
952 | ICMP6_PARAMPROB_HEADER, | | 952 | ICMP6_PARAMPROB_HEADER, |
953 | erroff + opt + 1 - opthead); | | 953 | erroff + opt + 1 - opthead); |
954 | return (-1); | | 954 | return (-1); |
955 | } | | 955 | } |
956 | optlen = IP6OPT_RTALERT_LEN; | | 956 | optlen = IP6OPT_RTALERT_LEN; |
957 | bcopy((void *)(opt + 2), (void *)&rtalert_val, 2); | | 957 | bcopy((void *)(opt + 2), (void *)&rtalert_val, 2); |
958 | *rtalertp = ntohs(rtalert_val); | | 958 | *rtalertp = ntohs(rtalert_val); |
959 | break; | | 959 | break; |
960 | case IP6OPT_JUMBO: | | 960 | case IP6OPT_JUMBO: |
961 | /* XXX may need check for alignment */ | | 961 | /* XXX may need check for alignment */ |
962 | if (hbhlen < IP6OPT_JUMBO_LEN) { | | 962 | if (hbhlen < IP6OPT_JUMBO_LEN) { |
963 | IP6_STATINC(IP6_STAT_TOOSMALL); | | 963 | IP6_STATINC(IP6_STAT_TOOSMALL); |
964 | goto bad; | | 964 | goto bad; |
965 | } | | 965 | } |
966 | if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) { | | 966 | if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) { |
967 | /* XXX stat */ | | 967 | /* XXX stat */ |
968 | icmp6_error(m, ICMP6_PARAM_PROB, | | 968 | icmp6_error(m, ICMP6_PARAM_PROB, |
969 | ICMP6_PARAMPROB_HEADER, | | 969 | ICMP6_PARAMPROB_HEADER, |
970 | erroff + opt + 1 - opthead); | | 970 | erroff + opt + 1 - opthead); |
971 | return (-1); | | 971 | return (-1); |
972 | } | | 972 | } |
973 | optlen = IP6OPT_JUMBO_LEN; | | 973 | optlen = IP6OPT_JUMBO_LEN; |
974 | | | 974 | |
975 | /* | | 975 | /* |
976 | * IPv6 packets that have non 0 payload length | | 976 | * IPv6 packets that have non 0 payload length |
977 | * must not contain a jumbo payload option. | | 977 | * must not contain a jumbo payload option. |
978 | */ | | 978 | */ |
979 | ip6 = mtod(m, struct ip6_hdr *); | | 979 | ip6 = mtod(m, struct ip6_hdr *); |
980 | if (ip6->ip6_plen) { | | 980 | if (ip6->ip6_plen) { |
981 | IP6_STATINC(IP6_STAT_BADOPTIONS); | | 981 | IP6_STATINC(IP6_STAT_BADOPTIONS); |
982 | icmp6_error(m, ICMP6_PARAM_PROB, | | 982 | icmp6_error(m, ICMP6_PARAM_PROB, |
983 | ICMP6_PARAMPROB_HEADER, | | 983 | ICMP6_PARAMPROB_HEADER, |
984 | erroff + opt - opthead); | | 984 | erroff + opt - opthead); |
985 | return (-1); | | 985 | return (-1); |
986 | } | | 986 | } |
987 | | | 987 | |
988 | /* | | 988 | /* |
989 | * We may see jumbolen in unaligned location, so | | 989 | * We may see jumbolen in unaligned location, so |
990 | * we'd need to perform bcopy(). | | 990 | * we'd need to perform bcopy(). |
991 | */ | | 991 | */ |
992 | bcopy(opt + 2, &jumboplen, sizeof(jumboplen)); | | 992 | bcopy(opt + 2, &jumboplen, sizeof(jumboplen)); |
993 | jumboplen = (u_int32_t)htonl(jumboplen); | | 993 | jumboplen = (u_int32_t)htonl(jumboplen); |
994 | | | 994 | |
995 | #if 1 | | 995 | #if 1 |
996 | /* | | 996 | /* |
997 | * if there are multiple jumbo payload options, | | 997 | * if there are multiple jumbo payload options, |
998 | * *plenp will be non-zero and the packet will be | | 998 | * *plenp will be non-zero and the packet will be |
999 | * rejected. | | 999 | * rejected. |
1000 | * the behavior may need some debate in ipngwg - | | 1000 | * the behavior may need some debate in ipngwg - |
1001 | * multiple options does not make sense, however, | | 1001 | * multiple options does not make sense, however, |
1002 | * there's no explicit mention in specification. | | 1002 | * there's no explicit mention in specification. |
1003 | */ | | 1003 | */ |
1004 | if (*plenp != 0) { | | 1004 | if (*plenp != 0) { |
1005 | IP6_STATINC(IP6_STAT_BADOPTIONS); | | 1005 | IP6_STATINC(IP6_STAT_BADOPTIONS); |
1006 | icmp6_error(m, ICMP6_PARAM_PROB, | | 1006 | icmp6_error(m, ICMP6_PARAM_PROB, |
1007 | ICMP6_PARAMPROB_HEADER, | | 1007 | ICMP6_PARAMPROB_HEADER, |
1008 | erroff + opt + 2 - opthead); | | 1008 | erroff + opt + 2 - opthead); |
1009 | return (-1); | | 1009 | return (-1); |
1010 | } | | 1010 | } |
1011 | #endif | | 1011 | #endif |
1012 | | | 1012 | |
1013 | /* | | 1013 | /* |
1014 | * jumbo payload length must be larger than 65535. | | 1014 | * jumbo payload length must be larger than 65535. |
1015 | */ | | 1015 | */ |
1016 | if (jumboplen <= IPV6_MAXPACKET) { | | 1016 | if (jumboplen <= IPV6_MAXPACKET) { |
1017 | IP6_STATINC(IP6_STAT_BADOPTIONS); | | 1017 | IP6_STATINC(IP6_STAT_BADOPTIONS); |
1018 | icmp6_error(m, ICMP6_PARAM_PROB, | | 1018 | icmp6_error(m, ICMP6_PARAM_PROB, |
1019 | ICMP6_PARAMPROB_HEADER, | | 1019 | ICMP6_PARAMPROB_HEADER, |
1020 | erroff + opt + 2 - opthead); | | 1020 | erroff + opt + 2 - opthead); |
1021 | return (-1); | | 1021 | return (-1); |
1022 | } | | 1022 | } |
1023 | *plenp = jumboplen; | | 1023 | *plenp = jumboplen; |
1024 | | | 1024 | |
1025 | break; | | 1025 | break; |
1026 | default: /* unknown option */ | | 1026 | default: /* unknown option */ |
1027 | if (hbhlen < IP6OPT_MINLEN) { | | 1027 | if (hbhlen < IP6OPT_MINLEN) { |
1028 | IP6_STATINC(IP6_STAT_TOOSMALL); | | 1028 | IP6_STATINC(IP6_STAT_TOOSMALL); |
1029 | goto bad; | | 1029 | goto bad; |
1030 | } | | 1030 | } |
1031 | optlen = ip6_unknown_opt(opt, m, | | 1031 | optlen = ip6_unknown_opt(opt, m, |
1032 | erroff + opt - opthead); | | 1032 | erroff + opt - opthead); |
1033 | if (optlen == -1) | | 1033 | if (optlen == -1) |
1034 | return (-1); | | 1034 | return (-1); |
1035 | optlen += 2; | | 1035 | optlen += 2; |
1036 | break; | | 1036 | break; |
1037 | } | | 1037 | } |
1038 | } | | 1038 | } |
1039 | | | 1039 | |
1040 | return (0); | | 1040 | return (0); |
1041 | | | 1041 | |
1042 | bad: | | 1042 | bad: |
1043 | m_freem(m); | | 1043 | m_freem(m); |
1044 | return (-1); | | 1044 | return (-1); |
1045 | } | | 1045 | } |
1046 | | | 1046 | |
1047 | /* | | 1047 | /* |
1048 | * Unknown option processing. | | 1048 | * Unknown option processing. |
1049 | * The third argument `off' is the offset from the IPv6 header to the option, | | 1049 | * The third argument `off' is the offset from the IPv6 header to the option, |
1050 | * which is necessary if the IPv6 header the and option header and IPv6 header | | 1050 | * which is necessary if the IPv6 header the and option header and IPv6 header |
1051 | * is not continuous in order to return an ICMPv6 error. | | 1051 | * is not continuous in order to return an ICMPv6 error. |
1052 | */ | | 1052 | */ |
1053 | int | | 1053 | int |
1054 | ip6_unknown_opt(u_int8_t *optp, struct mbuf *m, int off) | | 1054 | ip6_unknown_opt(u_int8_t *optp, struct mbuf *m, int off) |
1055 | { | | 1055 | { |
1056 | struct ip6_hdr *ip6; | | 1056 | struct ip6_hdr *ip6; |
1057 | | | 1057 | |
1058 | switch (IP6OPT_TYPE(*optp)) { | | 1058 | switch (IP6OPT_TYPE(*optp)) { |
1059 | case IP6OPT_TYPE_SKIP: /* ignore the option */ | | 1059 | case IP6OPT_TYPE_SKIP: /* ignore the option */ |
1060 | return ((int)*(optp + 1)); | | 1060 | return ((int)*(optp + 1)); |
1061 | case IP6OPT_TYPE_DISCARD: /* silently discard */ | | 1061 | case IP6OPT_TYPE_DISCARD: /* silently discard */ |
1062 | m_freem(m); | | 1062 | m_freem(m); |
1063 | return (-1); | | 1063 | return (-1); |
1064 | case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */ | | 1064 | case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */ |
1065 | IP6_STATINC(IP6_STAT_BADOPTIONS); | | 1065 | IP6_STATINC(IP6_STAT_BADOPTIONS); |
1066 | icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off); | | 1066 | icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off); |
1067 | return (-1); | | 1067 | return (-1); |
1068 | case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */ | | 1068 | case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */ |
1069 | IP6_STATINC(IP6_STAT_BADOPTIONS); | | 1069 | IP6_STATINC(IP6_STAT_BADOPTIONS); |
1070 | ip6 = mtod(m, struct ip6_hdr *); | | 1070 | ip6 = mtod(m, struct ip6_hdr *); |
1071 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || | | 1071 | if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || |
1072 | (m->m_flags & (M_BCAST|M_MCAST))) | | 1072 | (m->m_flags & (M_BCAST|M_MCAST))) |
1073 | m_freem(m); | | 1073 | m_freem(m); |
1074 | else | | 1074 | else |
1075 | icmp6_error(m, ICMP6_PARAM_PROB, | | 1075 | icmp6_error(m, ICMP6_PARAM_PROB, |
1076 | ICMP6_PARAMPROB_OPTION, off); | | 1076 | ICMP6_PARAMPROB_OPTION, off); |
1077 | return (-1); | | 1077 | return (-1); |
1078 | } | | 1078 | } |
1079 | | | 1079 | |
1080 | m_freem(m); /* XXX: NOTREACHED */ | | 1080 | m_freem(m); /* XXX: NOTREACHED */ |
1081 | return (-1); | | 1081 | return (-1); |
1082 | } | | 1082 | } |
1083 | | | 1083 | |
1084 | /* | | 1084 | /* |
1085 | * Create the "control" list for this pcb. | | 1085 | * Create the "control" list for this pcb. |
1086 | * | | 1086 | * |
1087 | * The routine will be called from upper layer handlers like tcp6_input(). | | 1087 | * The routine will be called from upper layer handlers like tcp6_input(). |
1088 | * Thus the routine assumes that the caller (tcp6_input) have already | | 1088 | * Thus the routine assumes that the caller (tcp6_input) have already |
1089 | * called IP6_EXTHDR_CHECK() and all the extension headers are located in the | | 1089 | * called IP6_EXTHDR_CHECK() and all the extension headers are located in the |
1090 | * very first mbuf on the mbuf chain. | | 1090 | * very first mbuf on the mbuf chain. |
1091 | * We may want to add some infinite loop prevention or sanity checks for safety. | | 1091 | * We may want to add some infinite loop prevention or sanity checks for safety. |
1092 | * (This applies only when you are using KAME mbuf chain restriction, i.e. | | 1092 | * (This applies only when you are using KAME mbuf chain restriction, i.e. |
1093 | * you are using IP6_EXTHDR_CHECK() not m_pulldown()) | | 1093 | * you are using IP6_EXTHDR_CHECK() not m_pulldown()) |
1094 | */ | | 1094 | */ |
1095 | void | | 1095 | void |
1096 | ip6_savecontrol(struct in6pcb *in6p, struct mbuf **mp, | | 1096 | ip6_savecontrol(struct in6pcb *in6p, struct mbuf **mp, |
1097 | struct ip6_hdr *ip6, struct mbuf *m) | | 1097 | struct ip6_hdr *ip6, struct mbuf *m) |
1098 | { | | 1098 | { |
1099 | #ifdef RFC2292 | | 1099 | #ifdef RFC2292 |
1100 | #define IS2292(x, y) ((in6p->in6p_flags & IN6P_RFC2292) ? (x) : (y)) | | 1100 | #define IS2292(x, y) ((in6p->in6p_flags & IN6P_RFC2292) ? (x) : (y)) |
1101 | #else | | 1101 | #else |
1102 | #define IS2292(x, y) (y) | | 1102 | #define IS2292(x, y) (y) |
1103 | #endif | | 1103 | #endif |
1104 | | | 1104 | |
1105 | #ifdef SO_TIMESTAMP | | 1105 | #ifdef SO_TIMESTAMP |
1106 | if (in6p->in6p_socket->so_options & SO_TIMESTAMP) { | | 1106 | if (in6p->in6p_socket->so_options & SO_TIMESTAMP) { |
1107 | struct timeval tv; | | 1107 | struct timeval tv; |
1108 | | | 1108 | |
1109 | microtime(&tv); | | 1109 | microtime(&tv); |
1110 | *mp = sbcreatecontrol((void *) &tv, sizeof(tv), | | 1110 | *mp = sbcreatecontrol((void *) &tv, sizeof(tv), |
1111 | SCM_TIMESTAMP, SOL_SOCKET); | | 1111 | SCM_TIMESTAMP, SOL_SOCKET); |
1112 | if (*mp) | | 1112 | if (*mp) |
1113 | mp = &(*mp)->m_next; | | 1113 | mp = &(*mp)->m_next; |
1114 | } | | 1114 | } |
1115 | #endif | | 1115 | #endif |
1116 | | | 1116 | |
1117 | /* some OSes call this logic with IPv4 packet, for SO_TIMESTAMP */ | | 1117 | /* some OSes call this logic with IPv4 packet, for SO_TIMESTAMP */ |
1118 | if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) | | 1118 | if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) |
1119 | return; | | 1119 | return; |
1120 | | | 1120 | |
1121 | /* RFC 2292 sec. 5 */ | | 1121 | /* RFC 2292 sec. 5 */ |
1122 | if ((in6p->in6p_flags & IN6P_PKTINFO) != 0) { | | 1122 | if ((in6p->in6p_flags & IN6P_PKTINFO) != 0) { |
1123 | struct in6_pktinfo pi6; | | 1123 | struct in6_pktinfo pi6; |
1124 | | | 1124 | |
1125 | bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr)); | | 1125 | bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr)); |
1126 | in6_clearscope(&pi6.ipi6_addr); /* XXX */ | | 1126 | in6_clearscope(&pi6.ipi6_addr); /* XXX */ |
1127 | pi6.ipi6_ifindex = m->m_pkthdr.rcvif ? | | 1127 | pi6.ipi6_ifindex = m->m_pkthdr.rcvif ? |
1128 | m->m_pkthdr.rcvif->if_index : 0; | | 1128 | m->m_pkthdr.rcvif->if_index : 0; |
1129 | *mp = sbcreatecontrol((void *) &pi6, | | 1129 | *mp = sbcreatecontrol((void *) &pi6, |
1130 | sizeof(struct in6_pktinfo), | | 1130 | sizeof(struct in6_pktinfo), |
1131 | IS2292(IPV6_2292PKTINFO, IPV6_PKTINFO), IPPROTO_IPV6); | | 1131 | IS2292(IPV6_2292PKTINFO, IPV6_PKTINFO), IPPROTO_IPV6); |
1132 | if (*mp) | | 1132 | if (*mp) |
1133 | mp = &(*mp)->m_next; | | 1133 | mp = &(*mp)->m_next; |
1134 | } | | 1134 | } |
1135 | | | 1135 | |
1136 | if (in6p->in6p_flags & IN6P_HOPLIMIT) { | | 1136 | if (in6p->in6p_flags & IN6P_HOPLIMIT) { |
1137 | int hlim = ip6->ip6_hlim & 0xff; | | 1137 | int hlim = ip6->ip6_hlim & 0xff; |
1138 | | | 1138 | |
1139 | *mp = sbcreatecontrol((void *) &hlim, sizeof(int), | | 1139 | *mp = sbcreatecontrol((void *) &hlim, sizeof(int), |
1140 | IS2292(IPV6_2292HOPLIMIT, IPV6_HOPLIMIT), IPPROTO_IPV6); | | 1140 | IS2292(IPV6_2292HOPLIMIT, IPV6_HOPLIMIT), IPPROTO_IPV6); |
1141 | if (*mp) | | 1141 | if (*mp) |
1142 | mp = &(*mp)->m_next; | | 1142 | mp = &(*mp)->m_next; |
1143 | } | | 1143 | } |
1144 | | | 1144 | |
1145 | if ((in6p->in6p_flags & IN6P_TCLASS) != 0) { | | 1145 | if ((in6p->in6p_flags & IN6P_TCLASS) != 0) { |
1146 | u_int32_t flowinfo; | | 1146 | u_int32_t flowinfo; |
1147 | int tclass; | | 1147 | int tclass; |
1148 | | | 1148 | |
1149 | flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK); | | 1149 | flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK); |
1150 | flowinfo >>= 20; | | 1150 | flowinfo >>= 20; |
1151 | | | 1151 | |
1152 | tclass = flowinfo & 0xff; | | 1152 | tclass = flowinfo & 0xff; |
1153 | *mp = sbcreatecontrol((void *)&tclass, sizeof(tclass), | | 1153 | *mp = sbcreatecontrol((void *)&tclass, sizeof(tclass), |
1154 | IPV6_TCLASS, IPPROTO_IPV6); | | 1154 | IPV6_TCLASS, IPPROTO_IPV6); |
1155 | | | 1155 | |
1156 | if (*mp) | | 1156 | if (*mp) |
1157 | mp = &(*mp)->m_next; | | 1157 | mp = &(*mp)->m_next; |
1158 | } | | 1158 | } |
1159 | | | 1159 | |
1160 | /* | | 1160 | /* |
1161 | * IPV6_HOPOPTS socket option. Recall that we required super-user | | 1161 | * IPV6_HOPOPTS socket option. Recall that we required super-user |
1162 | * privilege for the option (see ip6_ctloutput), but it might be too | | 1162 | * privilege for the option (see ip6_ctloutput), but it might be too |
1163 | * strict, since there might be some hop-by-hop options which can be | | 1163 | * strict, since there might be some hop-by-hop options which can be |
1164 | * returned to normal user. | | 1164 | * returned to normal user. |
1165 | * See also RFC3542 section 8 (or RFC2292 section 6). | | 1165 | * See also RFC3542 section 8 (or RFC2292 section 6). |
1166 | */ | | 1166 | */ |
1167 | if ((in6p->in6p_flags & IN6P_HOPOPTS) != 0) { | | 1167 | if ((in6p->in6p_flags & IN6P_HOPOPTS) != 0) { |
1168 | /* | | 1168 | /* |
1169 | * Check if a hop-by-hop options header is contatined in the | | 1169 | * Check if a hop-by-hop options header is contatined in the |
1170 | * received packet, and if so, store the options as ancillary | | 1170 | * received packet, and if so, store the options as ancillary |
1171 | * data. Note that a hop-by-hop options header must be | | 1171 | * data. Note that a hop-by-hop options header must be |
1172 | * just after the IPv6 header, which fact is assured through | | 1172 | * just after the IPv6 header, which fact is assured through |
1173 | * the IPv6 input processing. | | 1173 | * the IPv6 input processing. |
1174 | */ | | 1174 | */ |
1175 | struct ip6_hdr *xip6 = mtod(m, struct ip6_hdr *); | | 1175 | struct ip6_hdr *xip6 = mtod(m, struct ip6_hdr *); |
1176 | if (xip6->ip6_nxt == IPPROTO_HOPOPTS) { | | 1176 | if (xip6->ip6_nxt == IPPROTO_HOPOPTS) { |
1177 | struct ip6_hbh *hbh; | | 1177 | struct ip6_hbh *hbh; |
1178 | int hbhlen; | | 1178 | int hbhlen; |
1179 | struct mbuf *ext; | | 1179 | struct mbuf *ext; |
1180 | | | 1180 | |
1181 | ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr), | | 1181 | ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr), |
1182 | xip6->ip6_nxt); | | 1182 | xip6->ip6_nxt); |
1183 | if (ext == NULL) { | | 1183 | if (ext == NULL) { |
1184 | IP6_STATINC(IP6_STAT_TOOSHORT); | | 1184 | IP6_STATINC(IP6_STAT_TOOSHORT); |
1185 | return; | | 1185 | return; |
1186 | } | | 1186 | } |
1187 | hbh = mtod(ext, struct ip6_hbh *); | | 1187 | hbh = mtod(ext, struct ip6_hbh *); |
1188 | hbhlen = (hbh->ip6h_len + 1) << 3; | | 1188 | hbhlen = (hbh->ip6h_len + 1) << 3; |
1189 | if (hbhlen != ext->m_len) { | | 1189 | if (hbhlen != ext->m_len) { |
1190 | m_freem(ext); | | 1190 | m_freem(ext); |
1191 | IP6_STATINC(IP6_STAT_TOOSHORT); | | 1191 | IP6_STATINC(IP6_STAT_TOOSHORT); |
1192 | return; | | 1192 | return; |
1193 | } | | 1193 | } |
1194 | | | 1194 | |
1195 | /* | | 1195 | /* |
1196 | * XXX: We copy whole the header even if a jumbo | | 1196 | * XXX: We copy whole the header even if a jumbo |
1197 | * payload option is included, which option is to | | 1197 | * payload option is included, which option is to |
1198 | * be removed before returning in the RFC 2292. | | 1198 | * be removed before returning in the RFC 2292. |
1199 | * Note: this constraint is removed in RFC3542. | | 1199 | * Note: this constraint is removed in RFC3542. |
1200 | */ | | 1200 | */ |
1201 | *mp = sbcreatecontrol((void *)hbh, hbhlen, | | 1201 | *mp = sbcreatecontrol((void *)hbh, hbhlen, |
1202 | IS2292(IPV6_2292HOPOPTS, IPV6_HOPOPTS), | | 1202 | IS2292(IPV6_2292HOPOPTS, IPV6_HOPOPTS), |
1203 | IPPROTO_IPV6); | | 1203 | IPPROTO_IPV6); |
1204 | if (*mp) | | 1204 | if (*mp) |
1205 | mp = &(*mp)->m_next; | | 1205 | mp = &(*mp)->m_next; |
1206 | m_freem(ext); | | 1206 | m_freem(ext); |
1207 | } | | 1207 | } |
1208 | } | | 1208 | } |
1209 | | | 1209 | |
1210 | /* IPV6_DSTOPTS and IPV6_RTHDR socket options */ | | 1210 | /* IPV6_DSTOPTS and IPV6_RTHDR socket options */ |
1211 | if (in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDR)) { | | 1211 | if (in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDR)) { |
1212 | struct ip6_hdr *xip6 = mtod(m, struct ip6_hdr *); | | 1212 | struct ip6_hdr *xip6 = mtod(m, struct ip6_hdr *); |
1213 | int nxt = xip6->ip6_nxt, off = sizeof(struct ip6_hdr); | | 1213 | int nxt = xip6->ip6_nxt, off = sizeof(struct ip6_hdr); |
1214 | | | 1214 | |
1215 | /* | | 1215 | /* |
1216 | * Search for destination options headers or routing | | 1216 | * Search for destination options headers or routing |
1217 | * header(s) through the header chain, and stores each | | 1217 | * header(s) through the header chain, and stores each |
1218 | * header as ancillary data. | | 1218 | * header as ancillary data. |
1219 | * Note that the order of the headers remains in | | 1219 | * Note that the order of the headers remains in |
1220 | * the chain of ancillary data. | | 1220 | * the chain of ancillary data. |
1221 | */ | | 1221 | */ |
1222 | for (;;) { /* is explicit loop prevention necessary? */ | | 1222 | for (;;) { /* is explicit loop prevention necessary? */ |
1223 | struct ip6_ext *ip6e = NULL; | | 1223 | struct ip6_ext *ip6e = NULL; |
1224 | int elen; | | 1224 | int elen; |
1225 | struct mbuf *ext = NULL; | | 1225 | struct mbuf *ext = NULL; |
1226 | | | 1226 | |
1227 | /* | | 1227 | /* |
1228 | * if it is not an extension header, don't try to | | 1228 | * if it is not an extension header, don't try to |
1229 | * pull it from the chain. | | 1229 | * pull it from the chain. |
1230 | */ | | 1230 | */ |
1231 | switch (nxt) { | | 1231 | switch (nxt) { |
1232 | case IPPROTO_DSTOPTS: | | 1232 | case IPPROTO_DSTOPTS: |
1233 | case IPPROTO_ROUTING: | | 1233 | case IPPROTO_ROUTING: |
1234 | case IPPROTO_HOPOPTS: | | 1234 | case IPPROTO_HOPOPTS: |
1235 | case IPPROTO_AH: /* is it possible? */ | | 1235 | case IPPROTO_AH: /* is it possible? */ |
1236 | break; | | 1236 | break; |
1237 | default: | | 1237 | default: |
1238 | goto loopend; | | 1238 | goto loopend; |
1239 | } | | 1239 | } |
1240 | | | 1240 | |
1241 | ext = ip6_pullexthdr(m, off, nxt); | | 1241 | ext = ip6_pullexthdr(m, off, nxt); |
1242 | if (ext == NULL) { | | 1242 | if (ext == NULL) { |
1243 | IP6_STATINC(IP6_STAT_TOOSHORT); | | 1243 | IP6_STATINC(IP6_STAT_TOOSHORT); |
1244 | return; | | 1244 | return; |
1245 | } | | 1245 | } |
1246 | ip6e = mtod(ext, struct ip6_ext *); | | 1246 | ip6e = mtod(ext, struct ip6_ext *); |
1247 | if (nxt == IPPROTO_AH) | | 1247 | if (nxt == IPPROTO_AH) |
1248 | elen = (ip6e->ip6e_len + 2) << 2; | | 1248 | elen = (ip6e->ip6e_len + 2) << 2; |
1249 | else | | 1249 | else |
1250 | elen = (ip6e->ip6e_len + 1) << 3; | | 1250 | elen = (ip6e->ip6e_len + 1) << 3; |
1251 | if (elen != ext->m_len) { | | 1251 | if (elen != ext->m_len) { |
1252 | m_freem(ext); | | 1252 | m_freem(ext); |
1253 | IP6_STATINC(IP6_STAT_TOOSHORT); | | 1253 | IP6_STATINC(IP6_STAT_TOOSHORT); |
1254 | return; | | 1254 | return; |
1255 | } | | 1255 | } |
1256 | KASSERT(IP6_HDR_ALIGNED_P(ip6e)); | | 1256 | KASSERT(IP6_HDR_ALIGNED_P(ip6e)); |
1257 | | | 1257 | |
1258 | switch (nxt) { | | 1258 | switch (nxt) { |
1259 | case IPPROTO_DSTOPTS: | | 1259 | case IPPROTO_DSTOPTS: |
1260 | if (!in6p->in6p_flags & IN6P_DSTOPTS) | | 1260 | if (!(in6p->in6p_flags & IN6P_DSTOPTS)) |
1261 | break; | | 1261 | break; |
1262 | | | 1262 | |
1263 | *mp = sbcreatecontrol((void *)ip6e, elen, | | 1263 | *mp = sbcreatecontrol((void *)ip6e, elen, |
1264 | IS2292(IPV6_2292DSTOPTS, IPV6_DSTOPTS), | | 1264 | IS2292(IPV6_2292DSTOPTS, IPV6_DSTOPTS), |
1265 | IPPROTO_IPV6); | | 1265 | IPPROTO_IPV6); |
1266 | if (*mp) | | 1266 | if (*mp) |
1267 | mp = &(*mp)->m_next; | | 1267 | mp = &(*mp)->m_next; |
1268 | break; | | 1268 | break; |
1269 | | | 1269 | |
1270 | case IPPROTO_ROUTING: | | 1270 | case IPPROTO_ROUTING: |
1271 | if (!in6p->in6p_flags & IN6P_RTHDR) | | 1271 | if (!(in6p->in6p_flags & IN6P_RTHDR)) |
1272 | break; | | 1272 | break; |
1273 | | | 1273 | |
1274 | *mp = sbcreatecontrol((void *)ip6e, elen, | | 1274 | *mp = sbcreatecontrol((void *)ip6e, elen, |
1275 | IS2292(IPV6_2292RTHDR, IPV6_RTHDR), | | 1275 | IS2292(IPV6_2292RTHDR, IPV6_RTHDR), |
1276 | IPPROTO_IPV6); | | 1276 | IPPROTO_IPV6); |
1277 | if (*mp) | | 1277 | if (*mp) |
1278 | mp = &(*mp)->m_next; | | 1278 | mp = &(*mp)->m_next; |
1279 | break; | | 1279 | break; |
1280 | | | 1280 | |
1281 | case IPPROTO_HOPOPTS: | | 1281 | case IPPROTO_HOPOPTS: |
1282 | case IPPROTO_AH: /* is it possible? */ | | 1282 | case IPPROTO_AH: /* is it possible? */ |
1283 | break; | | 1283 | break; |
1284 | | | 1284 | |
1285 | default: | | 1285 | default: |
1286 | /* | | 1286 | /* |
1287 | * other cases have been filtered in the above. | | 1287 | * other cases have been filtered in the above. |
1288 | * none will visit this case. here we supply | | 1288 | * none will visit this case. here we supply |
1289 | * the code just in case (nxt overwritten or | | 1289 | * the code just in case (nxt overwritten or |
1290 | * other cases). | | 1290 | * other cases). |
1291 | */ | | 1291 | */ |
1292 | m_freem(ext); | | 1292 | m_freem(ext); |
1293 | goto loopend; | | 1293 | goto loopend; |
1294 | | | 1294 | |
1295 | } | | 1295 | } |
1296 | | | 1296 | |
1297 | /* proceed with the next header. */ | | 1297 | /* proceed with the next header. */ |
1298 | off += elen; | | 1298 | off += elen; |
1299 | nxt = ip6e->ip6e_nxt; | | 1299 | nxt = ip6e->ip6e_nxt; |
1300 | ip6e = NULL; | | 1300 | ip6e = NULL; |
1301 | m_freem(ext); | | 1301 | m_freem(ext); |
1302 | ext = NULL; | | 1302 | ext = NULL; |
1303 | } | | 1303 | } |
1304 | loopend: | | 1304 | loopend: |
1305 | ; | | 1305 | ; |
1306 | } | | 1306 | } |
1307 | } | | 1307 | } |
1308 | #undef IS2292 | | 1308 | #undef IS2292 |
1309 | | | 1309 | |
1310 | | | 1310 | |
1311 | void | | 1311 | void |
1312 | ip6_notify_pmtu(struct in6pcb *in6p, const struct sockaddr_in6 *dst, | | 1312 | ip6_notify_pmtu(struct in6pcb *in6p, const struct sockaddr_in6 *dst, |
1313 | uint32_t *mtu) | | 1313 | uint32_t *mtu) |
1314 | { | | 1314 | { |
1315 | struct socket *so; | | 1315 | struct socket *so; |
1316 | struct mbuf *m_mtu; | | 1316 | struct mbuf *m_mtu; |
1317 | struct ip6_mtuinfo mtuctl; | | 1317 | struct ip6_mtuinfo mtuctl; |
1318 | | | 1318 | |
1319 | so = in6p->in6p_socket; | | 1319 | so = in6p->in6p_socket; |
1320 | | | 1320 | |
1321 | if (mtu == NULL) | | 1321 | if (mtu == NULL) |
1322 | return; | | 1322 | return; |
1323 | | | 1323 | |
1324 | #ifdef DIAGNOSTIC | | 1324 | #ifdef DIAGNOSTIC |
1325 | if (so == NULL) /* I believe this is impossible */ | | 1325 | if (so == NULL) /* I believe this is impossible */ |
1326 | panic("ip6_notify_pmtu: socket is NULL"); | | 1326 | panic("ip6_notify_pmtu: socket is NULL"); |
1327 | #endif | | 1327 | #endif |
1328 | | | 1328 | |
1329 | memset(&mtuctl, 0, sizeof(mtuctl)); /* zero-clear for safety */ | | 1329 | memset(&mtuctl, 0, sizeof(mtuctl)); /* zero-clear for safety */ |
1330 | mtuctl.ip6m_mtu = *mtu; | | 1330 | mtuctl.ip6m_mtu = *mtu; |
1331 | mtuctl.ip6m_addr = *dst; | | 1331 | mtuctl.ip6m_addr = *dst; |
1332 | if (sa6_recoverscope(&mtuctl.ip6m_addr)) | | 1332 | if (sa6_recoverscope(&mtuctl.ip6m_addr)) |
1333 | return; | | 1333 | return; |
1334 | | | 1334 | |
1335 | if ((m_mtu = sbcreatecontrol((void *)&mtuctl, sizeof(mtuctl), | | 1335 | if ((m_mtu = sbcreatecontrol((void *)&mtuctl, sizeof(mtuctl), |
1336 | IPV6_PATHMTU, IPPROTO_IPV6)) == NULL) | | 1336 | IPV6_PATHMTU, IPPROTO_IPV6)) == NULL) |
1337 | return; | | 1337 | return; |
1338 | | | 1338 | |
1339 | if (sbappendaddr(&so->so_rcv, (const struct sockaddr *)dst, NULL, m_mtu) | | 1339 | if (sbappendaddr(&so->so_rcv, (const struct sockaddr *)dst, NULL, m_mtu) |
1340 | == 0) { | | 1340 | == 0) { |
1341 | m_freem(m_mtu); | | 1341 | m_freem(m_mtu); |
1342 | /* XXX: should count statistics */ | | 1342 | /* XXX: should count statistics */ |
1343 | } else | | 1343 | } else |
1344 | sorwakeup(so); | | 1344 | sorwakeup(so); |
1345 | | | 1345 | |
1346 | return; | | 1346 | return; |
1347 | } | | 1347 | } |
1348 | | | 1348 | |
1349 | /* | | 1349 | /* |
1350 | * pull single extension header from mbuf chain. returns single mbuf that | | 1350 | * pull single extension header from mbuf chain. returns single mbuf that |
1351 | * contains the result, or NULL on error. | | 1351 | * contains the result, or NULL on error. |
1352 | */ | | 1352 | */ |
1353 | static struct mbuf * | | 1353 | static struct mbuf * |
1354 | ip6_pullexthdr(struct mbuf *m, size_t off, int nxt) | | 1354 | ip6_pullexthdr(struct mbuf *m, size_t off, int nxt) |
1355 | { | | 1355 | { |
1356 | struct ip6_ext ip6e; | | 1356 | struct ip6_ext ip6e; |
1357 | size_t elen; | | 1357 | size_t elen; |
1358 | struct mbuf *n; | | 1358 | struct mbuf *n; |
1359 | | | 1359 | |
1360 | #ifdef DIAGNOSTIC | | 1360 | #ifdef DIAGNOSTIC |
1361 | switch (nxt) { | | 1361 | switch (nxt) { |
1362 | case IPPROTO_DSTOPTS: | | 1362 | case IPPROTO_DSTOPTS: |
1363 | case IPPROTO_ROUTING: | | 1363 | case IPPROTO_ROUTING: |
1364 | case IPPROTO_HOPOPTS: | | 1364 | case IPPROTO_HOPOPTS: |
1365 | case IPPROTO_AH: /* is it possible? */ | | 1365 | case IPPROTO_AH: /* is it possible? */ |
1366 | break; | | 1366 | break; |
1367 | default: | | 1367 | default: |
1368 | printf("ip6_pullexthdr: invalid nxt=%d\n", nxt); | | 1368 | printf("ip6_pullexthdr: invalid nxt=%d\n", nxt); |
1369 | } | | 1369 | } |
1370 | #endif | | 1370 | #endif |
1371 | | | 1371 | |
1372 | m_copydata(m, off, sizeof(ip6e), (void *)&ip6e); | | 1372 | m_copydata(m, off, sizeof(ip6e), (void *)&ip6e); |
1373 | if (nxt == IPPROTO_AH) | | 1373 | if (nxt == IPPROTO_AH) |
1374 | elen = (ip6e.ip6e_len + 2) << 2; | | 1374 | elen = (ip6e.ip6e_len + 2) << 2; |
1375 | else | | 1375 | else |
1376 | elen = (ip6e.ip6e_len + 1) << 3; | | 1376 | elen = (ip6e.ip6e_len + 1) << 3; |
1377 | | | 1377 | |
1378 | MGET(n, M_DONTWAIT, MT_DATA); | | 1378 | MGET(n, M_DONTWAIT, MT_DATA); |
1379 | if (n && elen >= MLEN) { | | 1379 | if (n && elen >= MLEN) { |
1380 | MCLGET(n, M_DONTWAIT); | | 1380 | MCLGET(n, M_DONTWAIT); |
1381 | if ((n->m_flags & M_EXT) == 0) { | | 1381 | if ((n->m_flags & M_EXT) == 0) { |
1382 | m_free(n); | | 1382 | m_free(n); |
1383 | n = NULL; | | 1383 | n = NULL; |
1384 | } | | 1384 | } |
1385 | } | | 1385 | } |
1386 | if (!n) | | 1386 | if (!n) |
1387 | return NULL; | | 1387 | return NULL; |
1388 | | | 1388 | |
1389 | n->m_len = 0; | | 1389 | n->m_len = 0; |
1390 | if (elen >= M_TRAILINGSPACE(n)) { | | 1390 | if (elen >= M_TRAILINGSPACE(n)) { |
1391 | m_free(n); | | 1391 | m_free(n); |
1392 | return NULL; | | 1392 | return NULL; |
1393 | } | | 1393 | } |
1394 | | | 1394 | |
1395 | m_copydata(m, off, elen, mtod(n, void *)); | | 1395 | m_copydata(m, off, elen, mtod(n, void *)); |
1396 | n->m_len = elen; | | 1396 | n->m_len = elen; |
1397 | return n; | | 1397 | return n; |
1398 | } | | 1398 | } |
1399 | | | 1399 | |
1400 | /* | | 1400 | /* |
1401 | * Get pointer to the previous header followed by the header | | 1401 | * Get pointer to the previous header followed by the header |
1402 | * currently processed. | | 1402 | * currently processed. |
1403 | * XXX: This function supposes that | | 1403 | * XXX: This function supposes that |
1404 | * M includes all headers, | | 1404 | * M includes all headers, |
1405 | * the next header field and the header length field of each header | | 1405 | * the next header field and the header length field of each header |
1406 | * are valid, and | | 1406 | * are valid, and |
1407 | * the sum of each header length equals to OFF. | | 1407 | * the sum of each header length equals to OFF. |
1408 | * Because of these assumptions, this function must be called very | | 1408 | * Because of these assumptions, this function must be called very |
1409 | * carefully. Moreover, it will not be used in the near future when | | 1409 | * carefully. Moreover, it will not be used in the near future when |
1410 | * we develop `neater' mechanism to process extension headers. | | 1410 | * we develop `neater' mechanism to process extension headers. |
1411 | */ | | 1411 | */ |
1412 | u_int8_t * | | 1412 | u_int8_t * |
1413 | ip6_get_prevhdr(struct mbuf *m, int off) | | 1413 | ip6_get_prevhdr(struct mbuf *m, int off) |
1414 | { | | 1414 | { |
1415 | struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); | | 1415 | struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); |
1416 | | | 1416 | |
1417 | if (off == sizeof(struct ip6_hdr)) | | 1417 | if (off == sizeof(struct ip6_hdr)) |
1418 | return (&ip6->ip6_nxt); | | 1418 | return (&ip6->ip6_nxt); |
1419 | else { | | 1419 | else { |
1420 | int len, nxt; | | 1420 | int len, nxt; |
1421 | struct ip6_ext *ip6e = NULL; | | 1421 | struct ip6_ext *ip6e = NULL; |
1422 | | | 1422 | |
1423 | nxt = ip6->ip6_nxt; | | 1423 | nxt = ip6->ip6_nxt; |
1424 | len = sizeof(struct ip6_hdr); | | 1424 | len = sizeof(struct ip6_hdr); |
1425 | while (len < off) { | | 1425 | while (len < off) { |
1426 | ip6e = (struct ip6_ext *)(mtod(m, char *) + len); | | 1426 | ip6e = (struct ip6_ext *)(mtod(m, char *) + len); |
1427 | | | 1427 | |
1428 | switch (nxt) { | | 1428 | switch (nxt) { |
1429 | case IPPROTO_FRAGMENT: | | 1429 | case IPPROTO_FRAGMENT: |
1430 | len += sizeof(struct ip6_frag); | | 1430 | len += sizeof(struct ip6_frag); |
1431 | break; | | 1431 | break; |
1432 | case IPPROTO_AH: | | 1432 | case IPPROTO_AH: |
1433 | len += (ip6e->ip6e_len + 2) << 2; | | 1433 | len += (ip6e->ip6e_len + 2) << 2; |
1434 | break; | | 1434 | break; |
1435 | default: | | 1435 | default: |
1436 | len += (ip6e->ip6e_len + 1) << 3; | | 1436 | len += (ip6e->ip6e_len + 1) << 3; |
1437 | break; | | 1437 | break; |
1438 | } | | 1438 | } |
1439 | nxt = ip6e->ip6e_nxt; | | 1439 | nxt = ip6e->ip6e_nxt; |
1440 | } | | 1440 | } |
1441 | if (ip6e) | | 1441 | if (ip6e) |
1442 | return (&ip6e->ip6e_nxt); | | 1442 | return (&ip6e->ip6e_nxt); |
1443 | else | | 1443 | else |
1444 | return NULL; | | 1444 | return NULL; |
1445 | } | | 1445 | } |
1446 | } | | 1446 | } |
1447 | | | 1447 | |
1448 | /* | | 1448 | /* |
1449 | * get next header offset. m will be retained. | | 1449 | * get next header offset. m will be retained. |
1450 | */ | | 1450 | */ |
1451 | int | | 1451 | int |
1452 | ip6_nexthdr(struct mbuf *m, int off, int proto, int *nxtp) | | 1452 | ip6_nexthdr(struct mbuf *m, int off, int proto, int *nxtp) |
1453 | { | | 1453 | { |
1454 | struct ip6_hdr ip6; | | 1454 | struct ip6_hdr ip6; |
1455 | struct ip6_ext ip6e; | | 1455 | struct ip6_ext ip6e; |
1456 | struct ip6_frag fh; | | 1456 | struct ip6_frag fh; |
1457 | | | 1457 | |
1458 | /* just in case */ | | 1458 | /* just in case */ |
1459 | if (m == NULL) | | 1459 | if (m == NULL) |
1460 | panic("ip6_nexthdr: m == NULL"); | | 1460 | panic("ip6_nexthdr: m == NULL"); |
1461 | if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len < off) | | 1461 | if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len < off) |
1462 | return -1; | | 1462 | return -1; |
1463 | | | 1463 | |
1464 | switch (proto) { | | 1464 | switch (proto) { |
1465 | case IPPROTO_IPV6: | | 1465 | case IPPROTO_IPV6: |
1466 | /* do not chase beyond intermediate IPv6 headers */ | | 1466 | /* do not chase beyond intermediate IPv6 headers */ |
1467 | if (off != 0) | | 1467 | if (off != 0) |
1468 | return -1; | | 1468 | return -1; |
1469 | if (m->m_pkthdr.len < off + sizeof(ip6)) | | 1469 | if (m->m_pkthdr.len < off + sizeof(ip6)) |
1470 | return -1; | | 1470 | return -1; |
1471 | m_copydata(m, off, sizeof(ip6), (void *)&ip6); | | 1471 | m_copydata(m, off, sizeof(ip6), (void *)&ip6); |
1472 | if (nxtp) | | 1472 | if (nxtp) |
1473 | *nxtp = ip6.ip6_nxt; | | 1473 | *nxtp = ip6.ip6_nxt; |
1474 | off += sizeof(ip6); | | 1474 | off += sizeof(ip6); |
1475 | return off; | | 1475 | return off; |
1476 | | | 1476 | |
1477 | case IPPROTO_FRAGMENT: | | 1477 | case IPPROTO_FRAGMENT: |
1478 | /* | | 1478 | /* |
1479 | * terminate parsing if it is not the first fragment, | | 1479 | * terminate parsing if it is not the first fragment, |
1480 | * it does not make sense to parse through it. | | 1480 | * it does not make sense to parse through it. |
1481 | */ | | 1481 | */ |
1482 | if (m->m_pkthdr.len < off + sizeof(fh)) | | 1482 | if (m->m_pkthdr.len < off + sizeof(fh)) |
1483 | return -1; | | 1483 | return -1; |
1484 | m_copydata(m, off, sizeof(fh), (void *)&fh); | | 1484 | m_copydata(m, off, sizeof(fh), (void *)&fh); |
1485 | if ((fh.ip6f_offlg & IP6F_OFF_MASK) != 0) | | 1485 | if ((fh.ip6f_offlg & IP6F_OFF_MASK) != 0) |
1486 | return -1; | | 1486 | return -1; |
1487 | if (nxtp) | | 1487 | if (nxtp) |
1488 | *nxtp = fh.ip6f_nxt; | | 1488 | *nxtp = fh.ip6f_nxt; |
1489 | off += sizeof(struct ip6_frag); | | 1489 | off += sizeof(struct ip6_frag); |
1490 | return off; | | 1490 | return off; |
1491 | | | 1491 | |
1492 | case IPPROTO_AH: | | 1492 | case IPPROTO_AH: |
1493 | if (m->m_pkthdr.len < off + sizeof(ip6e)) | | 1493 | if (m->m_pkthdr.len < off + sizeof(ip6e)) |
1494 | return -1; | | 1494 | return -1; |
1495 | m_copydata(m, off, sizeof(ip6e), (void *)&ip6e); | | 1495 | m_copydata(m, off, sizeof(ip6e), (void *)&ip6e); |
1496 | if (nxtp) | | 1496 | if (nxtp) |
1497 | *nxtp = ip6e.ip6e_nxt; | | 1497 | *nxtp = ip6e.ip6e_nxt; |
1498 | off += (ip6e.ip6e_len + 2) << 2; | | 1498 | off += (ip6e.ip6e_len + 2) << 2; |
1499 | if (m->m_pkthdr.len < off) | | 1499 | if (m->m_pkthdr.len < off) |
1500 | return -1; | | 1500 | return -1; |
1501 | return off; | | 1501 | return off; |
1502 | | | 1502 | |
1503 | case IPPROTO_HOPOPTS: | | 1503 | case IPPROTO_HOPOPTS: |
1504 | case IPPROTO_ROUTING: | | 1504 | case IPPROTO_ROUTING: |
1505 | case IPPROTO_DSTOPTS: | | 1505 | case IPPROTO_DSTOPTS: |
1506 | if (m->m_pkthdr.len < off + sizeof(ip6e)) | | 1506 | if (m->m_pkthdr.len < off + sizeof(ip6e)) |
1507 | return -1; | | 1507 | return -1; |
1508 | m_copydata(m, off, sizeof(ip6e), (void *)&ip6e); | | 1508 | m_copydata(m, off, sizeof(ip6e), (void *)&ip6e); |
1509 | if (nxtp) | | 1509 | if (nxtp) |
1510 | *nxtp = ip6e.ip6e_nxt; | | 1510 | *nxtp = ip6e.ip6e_nxt; |
1511 | off += (ip6e.ip6e_len + 1) << 3; | | 1511 | off += (ip6e.ip6e_len + 1) << 3; |
1512 | if (m->m_pkthdr.len < off) | | 1512 | if (m->m_pkthdr.len < off) |
1513 | return -1; | | 1513 | return -1; |
1514 | return off; | | 1514 | return off; |
1515 | | | 1515 | |
1516 | case IPPROTO_NONE: | | 1516 | case IPPROTO_NONE: |
1517 | case IPPROTO_ESP: | | 1517 | case IPPROTO_ESP: |
1518 | case IPPROTO_IPCOMP: | | 1518 | case IPPROTO_IPCOMP: |
1519 | /* give up */ | | 1519 | /* give up */ |
1520 | return -1; | | 1520 | return -1; |
1521 | | | 1521 | |
1522 | default: | | 1522 | default: |
1523 | return -1; | | 1523 | return -1; |
1524 | } | | 1524 | } |
1525 | } | | 1525 | } |
1526 | | | 1526 | |
1527 | /* | | 1527 | /* |
1528 | * get offset for the last header in the chain. m will be kept untainted. | | 1528 | * get offset for the last header in the chain. m will be kept untainted. |
1529 | */ | | 1529 | */ |
1530 | int | | 1530 | int |
1531 | ip6_lasthdr(struct mbuf *m, int off, int proto, int *nxtp) | | 1531 | ip6_lasthdr(struct mbuf *m, int off, int proto, int *nxtp) |
1532 | { | | 1532 | { |
1533 | int newoff; | | 1533 | int newoff; |
1534 | int nxt; | | 1534 | int nxt; |
1535 | | | 1535 | |
1536 | if (!nxtp) { | | 1536 | if (!nxtp) { |
1537 | nxt = -1; | | 1537 | nxt = -1; |
1538 | nxtp = &nxt; | | 1538 | nxtp = &nxt; |
1539 | } | | 1539 | } |
1540 | for (;;) { | | 1540 | for (;;) { |
1541 | newoff = ip6_nexthdr(m, off, proto, nxtp); | | 1541 | newoff = ip6_nexthdr(m, off, proto, nxtp); |
1542 | if (newoff < 0) | | 1542 | if (newoff < 0) |
1543 | return off; | | 1543 | return off; |
1544 | else if (newoff < off) | | 1544 | else if (newoff < off) |
1545 | return -1; /* invalid */ | | 1545 | return -1; /* invalid */ |
1546 | else if (newoff == off) | | 1546 | else if (newoff == off) |
1547 | return newoff; | | 1547 | return newoff; |
1548 | | | 1548 | |
1549 | off = newoff; | | 1549 | off = newoff; |
1550 | proto = *nxtp; | | 1550 | proto = *nxtp; |
1551 | } | | 1551 | } |
1552 | } | | 1552 | } |
1553 | | | 1553 | |
1554 | struct m_tag * | | 1554 | struct m_tag * |
1555 | ip6_addaux(struct mbuf *m) | | 1555 | ip6_addaux(struct mbuf *m) |
1556 | { | | 1556 | { |
1557 | struct m_tag *mtag; | | 1557 | struct m_tag *mtag; |
1558 | | | 1558 | |
1559 | mtag = m_tag_find(m, PACKET_TAG_INET6, NULL); | | 1559 | mtag = m_tag_find(m, PACKET_TAG_INET6, NULL); |
1560 | if (!mtag) { | | 1560 | if (!mtag) { |
1561 | mtag = m_tag_get(PACKET_TAG_INET6, sizeof(struct ip6aux), | | 1561 | mtag = m_tag_get(PACKET_TAG_INET6, sizeof(struct ip6aux), |
1562 | M_NOWAIT); | | 1562 | M_NOWAIT); |
1563 | if (mtag) { | | 1563 | if (mtag) { |
1564 | m_tag_prepend(m, mtag); | | 1564 | m_tag_prepend(m, mtag); |
1565 | bzero(mtag + 1, sizeof(struct ip6aux)); | | 1565 | bzero(mtag + 1, sizeof(struct ip6aux)); |
1566 | } | | 1566 | } |
1567 | } | | 1567 | } |
1568 | return mtag; | | 1568 | return mtag; |
1569 | } | | 1569 | } |
1570 | | | 1570 | |
1571 | struct m_tag * | | 1571 | struct m_tag * |
1572 | ip6_findaux(struct mbuf *m) | | 1572 | ip6_findaux(struct mbuf *m) |
1573 | { | | 1573 | { |
1574 | struct m_tag *mtag; | | 1574 | struct m_tag *mtag; |
1575 | | | 1575 | |
1576 | mtag = m_tag_find(m, PACKET_TAG_INET6, NULL); | | 1576 | mtag = m_tag_find(m, PACKET_TAG_INET6, NULL); |
1577 | return mtag; | | 1577 | return mtag; |
1578 | } | | 1578 | } |
1579 | | | 1579 | |
1580 | void | | 1580 | void |
1581 | ip6_delaux(struct mbuf *m) | | 1581 | ip6_delaux(struct mbuf *m) |
1582 | { | | 1582 | { |
1583 | struct m_tag *mtag; | | 1583 | struct m_tag *mtag; |
1584 | | | 1584 | |
1585 | mtag = m_tag_find(m, PACKET_TAG_INET6, NULL); | | 1585 | mtag = m_tag_find(m, PACKET_TAG_INET6, NULL); |
1586 | if (mtag) | | 1586 | if (mtag) |
1587 | m_tag_delete(m, mtag); | | 1587 | m_tag_delete(m, mtag); |
1588 | } | | 1588 | } |
1589 | | | 1589 | |
1590 | #ifdef GATEWAY | | 1590 | #ifdef GATEWAY |
1591 | /* | | 1591 | /* |
1592 | * sysctl helper routine for net.inet.ip6.maxflows. Since | | 1592 | * sysctl helper routine for net.inet.ip6.maxflows. Since |
1593 | * we could reduce this value, call ip6flow_reap(); | | 1593 | * we could reduce this value, call ip6flow_reap(); |
1594 | */ | | 1594 | */ |
1595 | static int | | 1595 | static int |
1596 | sysctl_net_inet6_ip6_maxflows(SYSCTLFN_ARGS) | | 1596 | sysctl_net_inet6_ip6_maxflows(SYSCTLFN_ARGS) |
1597 | { | | 1597 | { |
1598 | int error; | | 1598 | int error; |
1599 | | | 1599 | |
1600 | error = sysctl_lookup(SYSCTLFN_CALL(rnode)); | | 1600 | error = sysctl_lookup(SYSCTLFN_CALL(rnode)); |
1601 | if (error || newp == NULL) | | 1601 | if (error || newp == NULL) |
1602 | return (error); | | 1602 | return (error); |
1603 | | | 1603 | |
1604 | mutex_enter(softnet_lock); | | 1604 | mutex_enter(softnet_lock); |
1605 | KERNEL_LOCK(1, NULL); | | 1605 | KERNEL_LOCK(1, NULL); |
1606 | | | 1606 | |
1607 | ip6flow_reap(0); | | 1607 | ip6flow_reap(0); |
1608 | | | 1608 | |
1609 | KERNEL_UNLOCK_ONE(NULL); | | 1609 | KERNEL_UNLOCK_ONE(NULL); |
1610 | mutex_exit(softnet_lock); | | 1610 | mutex_exit(softnet_lock); |
1611 | | | 1611 | |
1612 | return (0); | | 1612 | return (0); |
1613 | } | | 1613 | } |
1614 | | | 1614 | |
1615 | static int | | 1615 | static int |
1616 | sysctl_net_inet6_ip6_hashsize(SYSCTLFN_ARGS) | | 1616 | sysctl_net_inet6_ip6_hashsize(SYSCTLFN_ARGS) |
1617 | { | | 1617 | { |
1618 | int error, tmp; | | 1618 | int error, tmp; |
1619 | struct sysctlnode node; | | 1619 | struct sysctlnode node; |
1620 | | | 1620 | |
1621 | node = *rnode; | | 1621 | node = *rnode; |
1622 | tmp = ip6_hashsize; | | 1622 | tmp = ip6_hashsize; |
1623 | node.sysctl_data = &tmp; | | 1623 | node.sysctl_data = &tmp; |
1624 | error = sysctl_lookup(SYSCTLFN_CALL(&node)); | | 1624 | error = sysctl_lookup(SYSCTLFN_CALL(&node)); |
1625 | if (error || newp == NULL) | | 1625 | if (error || newp == NULL) |
1626 | return (error); | | 1626 | return (error); |
1627 | | | 1627 | |
1628 | if ((tmp & (tmp - 1)) == 0 && tmp != 0) { | | 1628 | if ((tmp & (tmp - 1)) == 0 && tmp != 0) { |
1629 | /* | | 1629 | /* |
1630 | * Can only fail due to malloc() | | 1630 | * Can only fail due to malloc() |
1631 | */ | | 1631 | */ |
1632 | mutex_enter(softnet_lock); | | 1632 | mutex_enter(softnet_lock); |
1633 | KERNEL_LOCK(1, NULL); | | 1633 | KERNEL_LOCK(1, NULL); |
1634 | | | 1634 | |
1635 | error = ip6flow_invalidate_all(tmp); | | 1635 | error = ip6flow_invalidate_all(tmp); |
1636 | | | 1636 | |
1637 | KERNEL_UNLOCK_ONE(NULL); | | 1637 | KERNEL_UNLOCK_ONE(NULL); |
1638 | mutex_exit(softnet_lock); | | 1638 | mutex_exit(softnet_lock); |
1639 | } else { | | 1639 | } else { |
1640 | /* | | 1640 | /* |
1641 | * EINVAL if not a power of 2 | | 1641 | * EINVAL if not a power of 2 |
1642 | */ | | 1642 | */ |
1643 | error = EINVAL; | | 1643 | error = EINVAL; |
1644 | } | | 1644 | } |
1645 | | | 1645 | |
1646 | return error; | | 1646 | return error; |
1647 | } | | 1647 | } |
1648 | #endif /* GATEWAY */ | | 1648 | #endif /* GATEWAY */ |
1649 | | | 1649 | |
1650 | /* | | 1650 | /* |
1651 | * System control for IP6 | | 1651 | * System control for IP6 |
1652 | */ | | 1652 | */ |
1653 | | | 1653 | |
1654 | const u_char inet6ctlerrmap[PRC_NCMDS] = { | | 1654 | const u_char inet6ctlerrmap[PRC_NCMDS] = { |
1655 | 0, 0, 0, 0, | | 1655 | 0, 0, 0, 0, |
1656 | 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, | | 1656 | 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, |
1657 | EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, | | 1657 | EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, |
1658 | EMSGSIZE, EHOSTUNREACH, 0, 0, | | 1658 | EMSGSIZE, EHOSTUNREACH, 0, 0, |
1659 | 0, 0, 0, 0, | | 1659 | 0, 0, 0, 0, |
1660 | ENOPROTOOPT | | 1660 | ENOPROTOOPT |
1661 | }; | | 1661 | }; |
1662 | | | 1662 | |
1663 | static int | | 1663 | static int |
1664 | sysctl_net_inet6_ip6_stats(SYSCTLFN_ARGS) | | 1664 | sysctl_net_inet6_ip6_stats(SYSCTLFN_ARGS) |
1665 | { | | 1665 | { |
1666 | | | 1666 | |
1667 | return (NETSTAT_SYSCTL(ip6stat_percpu, IP6_NSTATS)); | | 1667 | return (NETSTAT_SYSCTL(ip6stat_percpu, IP6_NSTATS)); |
1668 | } | | 1668 | } |
1669 | | | 1669 | |
1670 | SYSCTL_SETUP(sysctl_net_inet6_ip6_setup, "sysctl net.inet6.ip6 subtree setup") | | 1670 | SYSCTL_SETUP(sysctl_net_inet6_ip6_setup, "sysctl net.inet6.ip6 subtree setup") |
1671 | { | | 1671 | { |
1672 | #ifdef RFC2292 | | 1672 | #ifdef RFC2292 |
1673 | #define IS2292(x, y) ((in6p->in6p_flags & IN6P_RFC2292) ? (x) : (y)) | | 1673 | #define IS2292(x, y) ((in6p->in6p_flags & IN6P_RFC2292) ? (x) : (y)) |
1674 | #else | | 1674 | #else |
1675 | #define IS2292(x, y) (y) | | 1675 | #define IS2292(x, y) (y) |
1676 | #endif | | 1676 | #endif |
1677 | | | 1677 | |
1678 | sysctl_createv(clog, 0, NULL, NULL, | | 1678 | sysctl_createv(clog, 0, NULL, NULL, |
1679 | CTLFLAG_PERMANENT, | | 1679 | CTLFLAG_PERMANENT, |
1680 | CTLTYPE_NODE, "net", NULL, | | 1680 | CTLTYPE_NODE, "net", NULL, |
1681 | NULL, 0, NULL, 0, | | 1681 | NULL, 0, NULL, 0, |
1682 | CTL_NET, CTL_EOL); | | 1682 | CTL_NET, CTL_EOL); |
1683 | sysctl_createv(clog, 0, NULL, NULL, | | 1683 | sysctl_createv(clog, 0, NULL, NULL, |
1684 | CTLFLAG_PERMANENT, | | 1684 | CTLFLAG_PERMANENT, |
1685 | CTLTYPE_NODE, "inet6", | | 1685 | CTLTYPE_NODE, "inet6", |
1686 | SYSCTL_DESCR("PF_INET6 related settings"), | | 1686 | SYSCTL_DESCR("PF_INET6 related settings"), |
1687 | NULL, 0, NULL, 0, | | 1687 | NULL, 0, NULL, 0, |
1688 | CTL_NET, PF_INET6, CTL_EOL); | | 1688 | CTL_NET, PF_INET6, CTL_EOL); |
1689 | sysctl_createv(clog, 0, NULL, NULL, | | 1689 | sysctl_createv(clog, 0, NULL, NULL, |
1690 | CTLFLAG_PERMANENT, | | 1690 | CTLFLAG_PERMANENT, |
1691 | CTLTYPE_NODE, "ip6", | | 1691 | CTLTYPE_NODE, "ip6", |
1692 | SYSCTL_DESCR("IPv6 related settings"), | | 1692 | SYSCTL_DESCR("IPv6 related settings"), |
1693 | NULL, 0, NULL, 0, | | 1693 | NULL, 0, NULL, 0, |
1694 | CTL_NET, PF_INET6, IPPROTO_IPV6, CTL_EOL); | | 1694 | CTL_NET, PF_INET6, IPPROTO_IPV6, CTL_EOL); |
1695 | | | 1695 | |
1696 | sysctl_createv(clog, 0, NULL, NULL, | | 1696 | sysctl_createv(clog, 0, NULL, NULL, |
1697 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1697 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1698 | CTLTYPE_INT, "forwarding", | | 1698 | CTLTYPE_INT, "forwarding", |
1699 | SYSCTL_DESCR("Enable forwarding of INET6 datagrams"), | | 1699 | SYSCTL_DESCR("Enable forwarding of INET6 datagrams"), |
1700 | NULL, 0, &ip6_forwarding, 0, | | 1700 | NULL, 0, &ip6_forwarding, 0, |
1701 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1701 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1702 | IPV6CTL_FORWARDING, CTL_EOL); | | 1702 | IPV6CTL_FORWARDING, CTL_EOL); |
1703 | sysctl_createv(clog, 0, NULL, NULL, | | 1703 | sysctl_createv(clog, 0, NULL, NULL, |
1704 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1704 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1705 | CTLTYPE_INT, "redirect", | | 1705 | CTLTYPE_INT, "redirect", |
1706 | SYSCTL_DESCR("Enable sending of ICMPv6 redirect messages"), | | 1706 | SYSCTL_DESCR("Enable sending of ICMPv6 redirect messages"), |
1707 | NULL, 0, &ip6_sendredirects, 0, | | 1707 | NULL, 0, &ip6_sendredirects, 0, |
1708 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1708 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1709 | IPV6CTL_SENDREDIRECTS, CTL_EOL); | | 1709 | IPV6CTL_SENDREDIRECTS, CTL_EOL); |
1710 | sysctl_createv(clog, 0, NULL, NULL, | | 1710 | sysctl_createv(clog, 0, NULL, NULL, |
1711 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1711 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1712 | CTLTYPE_INT, "hlim", | | 1712 | CTLTYPE_INT, "hlim", |
1713 | SYSCTL_DESCR("Hop limit for an INET6 datagram"), | | 1713 | SYSCTL_DESCR("Hop limit for an INET6 datagram"), |
1714 | NULL, 0, &ip6_defhlim, 0, | | 1714 | NULL, 0, &ip6_defhlim, 0, |
1715 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1715 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1716 | IPV6CTL_DEFHLIM, CTL_EOL); | | 1716 | IPV6CTL_DEFHLIM, CTL_EOL); |
1717 | #ifdef notyet | | 1717 | #ifdef notyet |
1718 | sysctl_createv(clog, 0, NULL, NULL, | | 1718 | sysctl_createv(clog, 0, NULL, NULL, |
1719 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1719 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1720 | CTLTYPE_INT, "mtu", NULL, | | 1720 | CTLTYPE_INT, "mtu", NULL, |
1721 | NULL, 0, &, 0, | | 1721 | NULL, 0, &, 0, |
1722 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1722 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1723 | IPV6CTL_DEFMTU, CTL_EOL); | | 1723 | IPV6CTL_DEFMTU, CTL_EOL); |
1724 | #endif | | 1724 | #endif |
1725 | #ifdef __no_idea__ | | 1725 | #ifdef __no_idea__ |
1726 | sysctl_createv(clog, 0, NULL, NULL, | | 1726 | sysctl_createv(clog, 0, NULL, NULL, |
1727 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1727 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1728 | CTLTYPE_INT, "forwsrcrt", NULL, | | 1728 | CTLTYPE_INT, "forwsrcrt", NULL, |
1729 | NULL, 0, &?, 0, | | 1729 | NULL, 0, &?, 0, |
1730 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1730 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1731 | IPV6CTL_FORWSRCRT, CTL_EOL); | | 1731 | IPV6CTL_FORWSRCRT, CTL_EOL); |
1732 | sysctl_createv(clog, 0, NULL, NULL, | | 1732 | sysctl_createv(clog, 0, NULL, NULL, |
1733 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1733 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1734 | CTLTYPE_STRUCT, "mrtstats", NULL, | | 1734 | CTLTYPE_STRUCT, "mrtstats", NULL, |
1735 | NULL, 0, &?, sizeof(?), | | 1735 | NULL, 0, &?, sizeof(?), |
1736 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1736 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1737 | IPV6CTL_MRTSTATS, CTL_EOL); | | 1737 | IPV6CTL_MRTSTATS, CTL_EOL); |
1738 | sysctl_createv(clog, 0, NULL, NULL, | | 1738 | sysctl_createv(clog, 0, NULL, NULL, |
1739 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1739 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1740 | CTLTYPE_?, "mrtproto", NULL, | | 1740 | CTLTYPE_?, "mrtproto", NULL, |
1741 | NULL, 0, &?, sizeof(?), | | 1741 | NULL, 0, &?, sizeof(?), |
1742 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1742 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1743 | IPV6CTL_MRTPROTO, CTL_EOL); | | 1743 | IPV6CTL_MRTPROTO, CTL_EOL); |
1744 | #endif | | 1744 | #endif |
1745 | sysctl_createv(clog, 0, NULL, NULL, | | 1745 | sysctl_createv(clog, 0, NULL, NULL, |
1746 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1746 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1747 | CTLTYPE_INT, "maxfragpackets", | | 1747 | CTLTYPE_INT, "maxfragpackets", |
1748 | SYSCTL_DESCR("Maximum number of fragments to buffer " | | 1748 | SYSCTL_DESCR("Maximum number of fragments to buffer " |
1749 | "for reassembly"), | | 1749 | "for reassembly"), |
1750 | NULL, 0, &ip6_maxfragpackets, 0, | | 1750 | NULL, 0, &ip6_maxfragpackets, 0, |
1751 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1751 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1752 | IPV6CTL_MAXFRAGPACKETS, CTL_EOL); | | 1752 | IPV6CTL_MAXFRAGPACKETS, CTL_EOL); |
1753 | #ifdef __no_idea__ | | 1753 | #ifdef __no_idea__ |
1754 | sysctl_createv(clog, 0, NULL, NULL, | | 1754 | sysctl_createv(clog, 0, NULL, NULL, |
1755 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1755 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1756 | CTLTYPE_INT, "sourcecheck", NULL, | | 1756 | CTLTYPE_INT, "sourcecheck", NULL, |
1757 | NULL, 0, &?, 0, | | 1757 | NULL, 0, &?, 0, |
1758 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1758 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1759 | IPV6CTL_SOURCECHECK, CTL_EOL); | | 1759 | IPV6CTL_SOURCECHECK, CTL_EOL); |
1760 | sysctl_createv(clog, 0, NULL, NULL, | | 1760 | sysctl_createv(clog, 0, NULL, NULL, |
1761 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1761 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1762 | CTLTYPE_INT, "sourcecheck_logint", NULL, | | 1762 | CTLTYPE_INT, "sourcecheck_logint", NULL, |
1763 | NULL, 0, &?, 0, | | 1763 | NULL, 0, &?, 0, |
1764 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1764 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1765 | IPV6CTL_SOURCECHECK_LOGINT, CTL_EOL); | | 1765 | IPV6CTL_SOURCECHECK_LOGINT, CTL_EOL); |
1766 | #endif | | 1766 | #endif |
1767 | sysctl_createv(clog, 0, NULL, NULL, | | 1767 | sysctl_createv(clog, 0, NULL, NULL, |
1768 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1768 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1769 | CTLTYPE_INT, "accept_rtadv", | | 1769 | CTLTYPE_INT, "accept_rtadv", |
1770 | SYSCTL_DESCR("Accept router advertisements"), | | 1770 | SYSCTL_DESCR("Accept router advertisements"), |
1771 | NULL, 0, &ip6_accept_rtadv, 0, | | 1771 | NULL, 0, &ip6_accept_rtadv, 0, |
1772 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1772 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1773 | IPV6CTL_ACCEPT_RTADV, CTL_EOL); | | 1773 | IPV6CTL_ACCEPT_RTADV, CTL_EOL); |
1774 | sysctl_createv(clog, 0, NULL, NULL, | | 1774 | sysctl_createv(clog, 0, NULL, NULL, |
1775 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1775 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1776 | CTLTYPE_INT, "keepfaith", | | 1776 | CTLTYPE_INT, "keepfaith", |
1777 | SYSCTL_DESCR("Activate faith interface"), | | 1777 | SYSCTL_DESCR("Activate faith interface"), |
1778 | NULL, 0, &ip6_keepfaith, 0, | | 1778 | NULL, 0, &ip6_keepfaith, 0, |
1779 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1779 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1780 | IPV6CTL_KEEPFAITH, CTL_EOL); | | 1780 | IPV6CTL_KEEPFAITH, CTL_EOL); |
1781 | sysctl_createv(clog, 0, NULL, NULL, | | 1781 | sysctl_createv(clog, 0, NULL, NULL, |
1782 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1782 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1783 | CTLTYPE_INT, "log_interval", | | 1783 | CTLTYPE_INT, "log_interval", |
1784 | SYSCTL_DESCR("Minumum interval between logging " | | 1784 | SYSCTL_DESCR("Minumum interval between logging " |
1785 | "unroutable packets"), | | 1785 | "unroutable packets"), |
1786 | NULL, 0, &ip6_log_interval, 0, | | 1786 | NULL, 0, &ip6_log_interval, 0, |
1787 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1787 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1788 | IPV6CTL_LOG_INTERVAL, CTL_EOL); | | 1788 | IPV6CTL_LOG_INTERVAL, CTL_EOL); |
1789 | sysctl_createv(clog, 0, NULL, NULL, | | 1789 | sysctl_createv(clog, 0, NULL, NULL, |
1790 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1790 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1791 | CTLTYPE_INT, "hdrnestlimit", | | 1791 | CTLTYPE_INT, "hdrnestlimit", |
1792 | SYSCTL_DESCR("Maximum number of nested IPv6 headers"), | | 1792 | SYSCTL_DESCR("Maximum number of nested IPv6 headers"), |
1793 | NULL, 0, &ip6_hdrnestlimit, 0, | | 1793 | NULL, 0, &ip6_hdrnestlimit, 0, |
1794 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1794 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1795 | IPV6CTL_HDRNESTLIMIT, CTL_EOL); | | 1795 | IPV6CTL_HDRNESTLIMIT, CTL_EOL); |
1796 | sysctl_createv(clog, 0, NULL, NULL, | | 1796 | sysctl_createv(clog, 0, NULL, NULL, |
1797 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1797 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1798 | CTLTYPE_INT, "dad_count", | | 1798 | CTLTYPE_INT, "dad_count", |
1799 | SYSCTL_DESCR("Number of Duplicate Address Detection " | | 1799 | SYSCTL_DESCR("Number of Duplicate Address Detection " |
1800 | "probes to send"), | | 1800 | "probes to send"), |
1801 | NULL, 0, &ip6_dad_count, 0, | | 1801 | NULL, 0, &ip6_dad_count, 0, |
1802 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1802 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1803 | IPV6CTL_DAD_COUNT, CTL_EOL); | | 1803 | IPV6CTL_DAD_COUNT, CTL_EOL); |
1804 | sysctl_createv(clog, 0, NULL, NULL, | | 1804 | sysctl_createv(clog, 0, NULL, NULL, |
1805 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1805 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1806 | CTLTYPE_INT, "auto_flowlabel", | | 1806 | CTLTYPE_INT, "auto_flowlabel", |
1807 | SYSCTL_DESCR("Assign random IPv6 flow labels"), | | 1807 | SYSCTL_DESCR("Assign random IPv6 flow labels"), |
1808 | NULL, 0, &ip6_auto_flowlabel, 0, | | 1808 | NULL, 0, &ip6_auto_flowlabel, 0, |
1809 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1809 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1810 | IPV6CTL_AUTO_FLOWLABEL, CTL_EOL); | | 1810 | IPV6CTL_AUTO_FLOWLABEL, CTL_EOL); |
1811 | sysctl_createv(clog, 0, NULL, NULL, | | 1811 | sysctl_createv(clog, 0, NULL, NULL, |
1812 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1812 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1813 | CTLTYPE_INT, "defmcasthlim", | | 1813 | CTLTYPE_INT, "defmcasthlim", |
1814 | SYSCTL_DESCR("Default multicast hop limit"), | | 1814 | SYSCTL_DESCR("Default multicast hop limit"), |
1815 | NULL, 0, &ip6_defmcasthlim, 0, | | 1815 | NULL, 0, &ip6_defmcasthlim, 0, |
1816 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1816 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1817 | IPV6CTL_DEFMCASTHLIM, CTL_EOL); | | 1817 | IPV6CTL_DEFMCASTHLIM, CTL_EOL); |
1818 | #if NGIF > 0 | | 1818 | #if NGIF > 0 |
1819 | sysctl_createv(clog, 0, NULL, NULL, | | 1819 | sysctl_createv(clog, 0, NULL, NULL, |
1820 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1820 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1821 | CTLTYPE_INT, "gifhlim", | | 1821 | CTLTYPE_INT, "gifhlim", |
1822 | SYSCTL_DESCR("Default hop limit for a gif tunnel datagram"), | | 1822 | SYSCTL_DESCR("Default hop limit for a gif tunnel datagram"), |
1823 | NULL, 0, &ip6_gif_hlim, 0, | | 1823 | NULL, 0, &ip6_gif_hlim, 0, |
1824 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1824 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1825 | IPV6CTL_GIF_HLIM, CTL_EOL); | | 1825 | IPV6CTL_GIF_HLIM, CTL_EOL); |
1826 | #endif /* NGIF */ | | 1826 | #endif /* NGIF */ |
1827 | sysctl_createv(clog, 0, NULL, NULL, | | 1827 | sysctl_createv(clog, 0, NULL, NULL, |
1828 | CTLFLAG_PERMANENT, | | 1828 | CTLFLAG_PERMANENT, |
1829 | CTLTYPE_STRING, "kame_version", | | 1829 | CTLTYPE_STRING, "kame_version", |
1830 | SYSCTL_DESCR("KAME Version"), | | 1830 | SYSCTL_DESCR("KAME Version"), |
1831 | NULL, 0, __UNCONST(__KAME_VERSION), 0, | | 1831 | NULL, 0, __UNCONST(__KAME_VERSION), 0, |
1832 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1832 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1833 | IPV6CTL_KAME_VERSION, CTL_EOL); | | 1833 | IPV6CTL_KAME_VERSION, CTL_EOL); |
1834 | sysctl_createv(clog, 0, NULL, NULL, | | 1834 | sysctl_createv(clog, 0, NULL, NULL, |
1835 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1835 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1836 | CTLTYPE_INT, "use_deprecated", | | 1836 | CTLTYPE_INT, "use_deprecated", |
1837 | SYSCTL_DESCR("Allow use of deprecated addresses as " | | 1837 | SYSCTL_DESCR("Allow use of deprecated addresses as " |
1838 | "source addresses"), | | 1838 | "source addresses"), |
1839 | NULL, 0, &ip6_use_deprecated, 0, | | 1839 | NULL, 0, &ip6_use_deprecated, 0, |
1840 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1840 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1841 | IPV6CTL_USE_DEPRECATED, CTL_EOL); | | 1841 | IPV6CTL_USE_DEPRECATED, CTL_EOL); |
1842 | sysctl_createv(clog, 0, NULL, NULL, | | 1842 | sysctl_createv(clog, 0, NULL, NULL, |
1843 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1843 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1844 | CTLTYPE_INT, "rr_prune", NULL, | | 1844 | CTLTYPE_INT, "rr_prune", NULL, |
1845 | NULL, 0, &ip6_rr_prune, 0, | | 1845 | NULL, 0, &ip6_rr_prune, 0, |
1846 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1846 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1847 | IPV6CTL_RR_PRUNE, CTL_EOL); | | 1847 | IPV6CTL_RR_PRUNE, CTL_EOL); |
1848 | sysctl_createv(clog, 0, NULL, NULL, | | 1848 | sysctl_createv(clog, 0, NULL, NULL, |
1849 | CTLFLAG_PERMANENT | | 1849 | CTLFLAG_PERMANENT |
1850 | #ifndef INET6_BINDV6ONLY | | 1850 | #ifndef INET6_BINDV6ONLY |
1851 | |CTLFLAG_READWRITE, | | 1851 | |CTLFLAG_READWRITE, |
1852 | #endif | | 1852 | #endif |
1853 | CTLTYPE_INT, "v6only", | | 1853 | CTLTYPE_INT, "v6only", |
1854 | SYSCTL_DESCR("Disallow PF_INET6 sockets from connecting " | | 1854 | SYSCTL_DESCR("Disallow PF_INET6 sockets from connecting " |
1855 | "to PF_INET sockets"), | | 1855 | "to PF_INET sockets"), |
1856 | NULL, 0, &ip6_v6only, 0, | | 1856 | NULL, 0, &ip6_v6only, 0, |
1857 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1857 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1858 | IPV6CTL_V6ONLY, CTL_EOL); | | 1858 | IPV6CTL_V6ONLY, CTL_EOL); |
1859 | sysctl_createv(clog, 0, NULL, NULL, | | 1859 | sysctl_createv(clog, 0, NULL, NULL, |
1860 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1860 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1861 | CTLTYPE_INT, "anonportmin", | | 1861 | CTLTYPE_INT, "anonportmin", |
1862 | SYSCTL_DESCR("Lowest ephemeral port number to assign"), | | 1862 | SYSCTL_DESCR("Lowest ephemeral port number to assign"), |
1863 | sysctl_net_inet_ip_ports, 0, &ip6_anonportmin, 0, | | 1863 | sysctl_net_inet_ip_ports, 0, &ip6_anonportmin, 0, |
1864 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1864 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1865 | IPV6CTL_ANONPORTMIN, CTL_EOL); | | 1865 | IPV6CTL_ANONPORTMIN, CTL_EOL); |
1866 | sysctl_createv(clog, 0, NULL, NULL, | | 1866 | sysctl_createv(clog, 0, NULL, NULL, |
1867 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1867 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1868 | CTLTYPE_INT, "anonportmax", | | 1868 | CTLTYPE_INT, "anonportmax", |
1869 | SYSCTL_DESCR("Highest ephemeral port number to assign"), | | 1869 | SYSCTL_DESCR("Highest ephemeral port number to assign"), |
1870 | sysctl_net_inet_ip_ports, 0, &ip6_anonportmax, 0, | | 1870 | sysctl_net_inet_ip_ports, 0, &ip6_anonportmax, 0, |
1871 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1871 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1872 | IPV6CTL_ANONPORTMAX, CTL_EOL); | | 1872 | IPV6CTL_ANONPORTMAX, CTL_EOL); |
1873 | #ifndef IPNOPRIVPORTS | | 1873 | #ifndef IPNOPRIVPORTS |
1874 | sysctl_createv(clog, 0, NULL, NULL, | | 1874 | sysctl_createv(clog, 0, NULL, NULL, |
1875 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1875 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1876 | CTLTYPE_INT, "lowportmin", | | 1876 | CTLTYPE_INT, "lowportmin", |
1877 | SYSCTL_DESCR("Lowest privileged ephemeral port number " | | 1877 | SYSCTL_DESCR("Lowest privileged ephemeral port number " |
1878 | "to assign"), | | 1878 | "to assign"), |
1879 | sysctl_net_inet_ip_ports, 0, &ip6_lowportmin, 0, | | 1879 | sysctl_net_inet_ip_ports, 0, &ip6_lowportmin, 0, |
1880 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1880 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1881 | IPV6CTL_LOWPORTMIN, CTL_EOL); | | 1881 | IPV6CTL_LOWPORTMIN, CTL_EOL); |
1882 | sysctl_createv(clog, 0, NULL, NULL, | | 1882 | sysctl_createv(clog, 0, NULL, NULL, |
1883 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1883 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1884 | CTLTYPE_INT, "lowportmax", | | 1884 | CTLTYPE_INT, "lowportmax", |
1885 | SYSCTL_DESCR("Highest privileged ephemeral port number " | | 1885 | SYSCTL_DESCR("Highest privileged ephemeral port number " |
1886 | "to assign"), | | 1886 | "to assign"), |
1887 | sysctl_net_inet_ip_ports, 0, &ip6_lowportmax, 0, | | 1887 | sysctl_net_inet_ip_ports, 0, &ip6_lowportmax, 0, |
1888 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1888 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1889 | IPV6CTL_LOWPORTMAX, CTL_EOL); | | 1889 | IPV6CTL_LOWPORTMAX, CTL_EOL); |
1890 | #endif /* IPNOPRIVPORTS */ | | 1890 | #endif /* IPNOPRIVPORTS */ |
1891 | sysctl_createv(clog, 0, NULL, NULL, | | 1891 | sysctl_createv(clog, 0, NULL, NULL, |
1892 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1892 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1893 | CTLTYPE_INT, "use_tempaddr", | | 1893 | CTLTYPE_INT, "use_tempaddr", |
1894 | SYSCTL_DESCR("Use temporary address"), | | 1894 | SYSCTL_DESCR("Use temporary address"), |
1895 | NULL, 0, &ip6_use_tempaddr, 0, | | 1895 | NULL, 0, &ip6_use_tempaddr, 0, |
1896 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1896 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1897 | CTL_CREATE, CTL_EOL); | | 1897 | CTL_CREATE, CTL_EOL); |
1898 | sysctl_createv(clog, 0, NULL, NULL, | | 1898 | sysctl_createv(clog, 0, NULL, NULL, |
1899 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1899 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1900 | CTLTYPE_INT, "temppltime", | | 1900 | CTLTYPE_INT, "temppltime", |
1901 | SYSCTL_DESCR("preferred lifetime of a temporary address"), | | 1901 | SYSCTL_DESCR("preferred lifetime of a temporary address"), |
1902 | NULL, 0, &ip6_temp_preferred_lifetime, 0, | | 1902 | NULL, 0, &ip6_temp_preferred_lifetime, 0, |
1903 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1903 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1904 | CTL_CREATE, CTL_EOL); | | 1904 | CTL_CREATE, CTL_EOL); |
1905 | sysctl_createv(clog, 0, NULL, NULL, | | 1905 | sysctl_createv(clog, 0, NULL, NULL, |
1906 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1906 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1907 | CTLTYPE_INT, "tempvltime", | | 1907 | CTLTYPE_INT, "tempvltime", |
1908 | SYSCTL_DESCR("valid lifetime of a temporary address"), | | 1908 | SYSCTL_DESCR("valid lifetime of a temporary address"), |
1909 | NULL, 0, &ip6_temp_valid_lifetime, 0, | | 1909 | NULL, 0, &ip6_temp_valid_lifetime, 0, |
1910 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1910 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1911 | CTL_CREATE, CTL_EOL); | | 1911 | CTL_CREATE, CTL_EOL); |
1912 | sysctl_createv(clog, 0, NULL, NULL, | | 1912 | sysctl_createv(clog, 0, NULL, NULL, |
1913 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1913 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1914 | CTLTYPE_INT, "maxfrags", | | 1914 | CTLTYPE_INT, "maxfrags", |
1915 | SYSCTL_DESCR("Maximum fragments in reassembly queue"), | | 1915 | SYSCTL_DESCR("Maximum fragments in reassembly queue"), |
1916 | NULL, 0, &ip6_maxfrags, 0, | | 1916 | NULL, 0, &ip6_maxfrags, 0, |
1917 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1917 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1918 | IPV6CTL_MAXFRAGS, CTL_EOL); | | 1918 | IPV6CTL_MAXFRAGS, CTL_EOL); |
1919 | sysctl_createv(clog, 0, NULL, NULL, | | 1919 | sysctl_createv(clog, 0, NULL, NULL, |
1920 | CTLFLAG_PERMANENT, | | 1920 | CTLFLAG_PERMANENT, |
1921 | CTLTYPE_STRUCT, "stats", | | 1921 | CTLTYPE_STRUCT, "stats", |
1922 | SYSCTL_DESCR("IPv6 statistics"), | | 1922 | SYSCTL_DESCR("IPv6 statistics"), |
1923 | sysctl_net_inet6_ip6_stats, 0, NULL, 0, | | 1923 | sysctl_net_inet6_ip6_stats, 0, NULL, 0, |
1924 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1924 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1925 | IPV6CTL_STATS, CTL_EOL); | | 1925 | IPV6CTL_STATS, CTL_EOL); |
1926 | sysctl_createv(clog, 0, NULL, NULL, | | 1926 | sysctl_createv(clog, 0, NULL, NULL, |
1927 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1927 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1928 | CTLTYPE_INT, "use_defaultzone", | | 1928 | CTLTYPE_INT, "use_defaultzone", |
1929 | SYSCTL_DESCR("Whether to use the default scope zones"), | | 1929 | SYSCTL_DESCR("Whether to use the default scope zones"), |
1930 | NULL, 0, &ip6_use_defzone, 0, | | 1930 | NULL, 0, &ip6_use_defzone, 0, |
1931 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1931 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1932 | IPV6CTL_USE_DEFAULTZONE, CTL_EOL); | | 1932 | IPV6CTL_USE_DEFAULTZONE, CTL_EOL); |
1933 | sysctl_createv(clog, 0, NULL, NULL, | | 1933 | sysctl_createv(clog, 0, NULL, NULL, |
1934 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1934 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1935 | CTLTYPE_INT, "mcast_pmtu", | | 1935 | CTLTYPE_INT, "mcast_pmtu", |
1936 | SYSCTL_DESCR("Enable pMTU discovery for multicast packet"), | | 1936 | SYSCTL_DESCR("Enable pMTU discovery for multicast packet"), |
1937 | NULL, 0, &ip6_mcast_pmtu, 0, | | 1937 | NULL, 0, &ip6_mcast_pmtu, 0, |
1938 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1938 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1939 | CTL_CREATE, CTL_EOL); | | 1939 | CTL_CREATE, CTL_EOL); |
1940 | #ifdef GATEWAY | | 1940 | #ifdef GATEWAY |
1941 | sysctl_createv(clog, 0, NULL, NULL, | | 1941 | sysctl_createv(clog, 0, NULL, NULL, |
1942 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1942 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1943 | CTLTYPE_INT, "maxflows", | | 1943 | CTLTYPE_INT, "maxflows", |
1944 | SYSCTL_DESCR("Number of flows for fast forwarding (IPv6)"), | | 1944 | SYSCTL_DESCR("Number of flows for fast forwarding (IPv6)"), |
1945 | sysctl_net_inet6_ip6_maxflows, 0, &ip6_maxflows, 0, | | 1945 | sysctl_net_inet6_ip6_maxflows, 0, &ip6_maxflows, 0, |
1946 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1946 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1947 | CTL_CREATE, CTL_EOL); | | 1947 | CTL_CREATE, CTL_EOL); |
1948 | sysctl_createv(clog, 0, NULL, NULL, | | 1948 | sysctl_createv(clog, 0, NULL, NULL, |
1949 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, | | 1949 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
1950 | CTLTYPE_INT, "hashsize", | | 1950 | CTLTYPE_INT, "hashsize", |
1951 | SYSCTL_DESCR("Size of hash table for fast forwarding (IPv6)"), | | 1951 | SYSCTL_DESCR("Size of hash table for fast forwarding (IPv6)"), |
1952 | sysctl_net_inet6_ip6_hashsize, 0, &ip6_hashsize, 0, | | 1952 | sysctl_net_inet6_ip6_hashsize, 0, &ip6_hashsize, 0, |
1953 | CTL_NET, PF_INET6, IPPROTO_IPV6, | | 1953 | CTL_NET, PF_INET6, IPPROTO_IPV6, |
1954 | CTL_CREATE, CTL_EOL); | | 1954 | CTL_CREATE, CTL_EOL); |
1955 | #endif | | 1955 | #endif |
1956 | } | | 1956 | } |
1957 | | | 1957 | |
1958 | void | | 1958 | void |
1959 | ip6_statinc(u_int stat) | | 1959 | ip6_statinc(u_int stat) |
1960 | { | | 1960 | { |
1961 | | | 1961 | |
1962 | KASSERT(stat < IP6_NSTATS); | | 1962 | KASSERT(stat < IP6_NSTATS); |
1963 | IP6_STATINC(stat); | | 1963 | IP6_STATINC(stat); |
1964 | } | | 1964 | } |