ip6_input.c revision 1.10 1 1.10 itojun /* $NetBSD: ip6_input.c,v 1.10 2000/01/06 02:52:29 itojun Exp $ */
2 1.3 thorpej
3 1.2 itojun /*
4 1.2 itojun * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 1.2 itojun * All rights reserved.
6 1.2 itojun *
7 1.2 itojun * Redistribution and use in source and binary forms, with or without
8 1.2 itojun * modification, are permitted provided that the following conditions
9 1.2 itojun * are met:
10 1.2 itojun * 1. Redistributions of source code must retain the above copyright
11 1.2 itojun * notice, this list of conditions and the following disclaimer.
12 1.2 itojun * 2. Redistributions in binary form must reproduce the above copyright
13 1.2 itojun * notice, this list of conditions and the following disclaimer in the
14 1.2 itojun * documentation and/or other materials provided with the distribution.
15 1.2 itojun * 3. Neither the name of the project nor the names of its contributors
16 1.2 itojun * may be used to endorse or promote products derived from this software
17 1.2 itojun * without specific prior written permission.
18 1.2 itojun *
19 1.2 itojun * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 1.2 itojun * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 1.2 itojun * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 1.2 itojun * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 1.2 itojun * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 1.2 itojun * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 1.2 itojun * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 1.2 itojun * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 1.2 itojun * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 1.2 itojun * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 1.2 itojun * SUCH DAMAGE.
30 1.2 itojun */
31 1.2 itojun
32 1.2 itojun /*
33 1.2 itojun * Copyright (c) 1982, 1986, 1988, 1993
34 1.2 itojun * The Regents of the University of California. All rights reserved.
35 1.2 itojun *
36 1.2 itojun * Redistribution and use in source and binary forms, with or without
37 1.2 itojun * modification, are permitted provided that the following conditions
38 1.2 itojun * are met:
39 1.2 itojun * 1. Redistributions of source code must retain the above copyright
40 1.2 itojun * notice, this list of conditions and the following disclaimer.
41 1.2 itojun * 2. Redistributions in binary form must reproduce the above copyright
42 1.2 itojun * notice, this list of conditions and the following disclaimer in the
43 1.2 itojun * documentation and/or other materials provided with the distribution.
44 1.2 itojun * 3. All advertising materials mentioning features or use of this software
45 1.2 itojun * must display the following acknowledgement:
46 1.2 itojun * This product includes software developed by the University of
47 1.2 itojun * California, Berkeley and its contributors.
48 1.2 itojun * 4. Neither the name of the University nor the names of its contributors
49 1.2 itojun * may be used to endorse or promote products derived from this software
50 1.2 itojun * without specific prior written permission.
51 1.2 itojun *
52 1.2 itojun * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 1.2 itojun * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 1.2 itojun * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 1.2 itojun * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 1.2 itojun * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 1.2 itojun * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 1.2 itojun * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 1.2 itojun * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 1.2 itojun * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 1.2 itojun * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 1.2 itojun * SUCH DAMAGE.
63 1.2 itojun *
64 1.2 itojun * @(#)ip_input.c 8.2 (Berkeley) 1/4/94
65 1.2 itojun */
66 1.2 itojun
67 1.2 itojun #ifdef __FreeBSD__
68 1.2 itojun #include "opt_ip6fw.h"
69 1.2 itojun #endif
70 1.2 itojun #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
71 1.2 itojun #include "opt_inet.h"
72 1.6 itojun #ifdef __NetBSD__ /*XXX*/
73 1.4 thorpej #include "opt_ipsec.h"
74 1.6 itojun #endif
75 1.2 itojun #endif
76 1.2 itojun
77 1.2 itojun #include <sys/param.h>
78 1.2 itojun #include <sys/systm.h>
79 1.2 itojun #include <sys/malloc.h>
80 1.2 itojun #include <sys/mbuf.h>
81 1.2 itojun #include <sys/domain.h>
82 1.2 itojun #include <sys/protosw.h>
83 1.2 itojun #include <sys/socket.h>
84 1.2 itojun #include <sys/socketvar.h>
85 1.2 itojun #include <sys/errno.h>
86 1.2 itojun #include <sys/time.h>
87 1.2 itojun #include <sys/kernel.h>
88 1.2 itojun #include <sys/syslog.h>
89 1.9 itojun #if !defined(__bsdi__) && !(defined(__FreeBSD__) && __FreeBSD__ < 3)
90 1.2 itojun #include <sys/proc.h>
91 1.2 itojun #endif
92 1.2 itojun
93 1.2 itojun #include <net/if.h>
94 1.2 itojun #include <net/if_types.h>
95 1.2 itojun #include <net/if_dl.h>
96 1.2 itojun #include <net/route.h>
97 1.2 itojun #include <net/netisr.h>
98 1.2 itojun
99 1.2 itojun #include <netinet/in.h>
100 1.9 itojun #include <netinet/in_systm.h>
101 1.9 itojun #ifdef INET
102 1.9 itojun #include <netinet/ip.h>
103 1.9 itojun #include <netinet/ip_icmp.h>
104 1.9 itojun #endif /*INET*/
105 1.9 itojun #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802)
106 1.9 itojun #include <netinet/in_pcb.h>
107 1.9 itojun #endif
108 1.2 itojun #include <netinet6/in6_var.h>
109 1.2 itojun #include <netinet6/ip6.h>
110 1.9 itojun #if !((defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802))
111 1.2 itojun #include <netinet6/in6_pcb.h>
112 1.2 itojun #endif
113 1.2 itojun #include <netinet6/ip6_var.h>
114 1.2 itojun #include <netinet6/icmp6.h>
115 1.2 itojun #include <netinet6/in6_ifattach.h>
116 1.2 itojun #include <netinet6/nd6.h>
117 1.9 itojun #include <netinet6/in6_prefix.h>
118 1.2 itojun
119 1.9 itojun #ifdef IPV6FIREWALL
120 1.9 itojun #include <netinet6/ip6_fw.h>
121 1.9 itojun #endif
122 1.2 itojun
123 1.2 itojun #include <netinet6/ip6protosw.h>
124 1.2 itojun
125 1.2 itojun /* we need it for NLOOP. */
126 1.9 itojun #ifndef __bsdi__
127 1.2 itojun #include "loop.h"
128 1.9 itojun #endif
129 1.2 itojun #include "faith.h"
130 1.2 itojun
131 1.2 itojun #include "gif.h"
132 1.2 itojun #include "bpfilter.h"
133 1.2 itojun
134 1.9 itojun #include <net/net_osdep.h>
135 1.9 itojun
136 1.9 itojun #ifdef __OpenBSD__ /*KAME IPSEC*/
137 1.9 itojun #undef IPSEC
138 1.9 itojun #endif
139 1.9 itojun
140 1.2 itojun extern struct domain inet6domain;
141 1.2 itojun extern struct ip6protosw inet6sw[];
142 1.2 itojun #ifdef __bsdi__
143 1.9 itojun #if _BSDI_VERSION < 199802
144 1.2 itojun extern struct ifnet loif;
145 1.9 itojun #else
146 1.9 itojun extern struct ifnet *loifp;
147 1.9 itojun #endif
148 1.2 itojun #endif
149 1.2 itojun
150 1.2 itojun u_char ip6_protox[IPPROTO_MAX];
151 1.2 itojun static int ip6qmaxlen = IFQ_MAXLEN;
152 1.2 itojun struct in6_ifaddr *in6_ifaddr;
153 1.2 itojun struct ifqueue ip6intrq;
154 1.2 itojun
155 1.9 itojun #if defined(__NetBSD__) || defined(__OpenBSD__)
156 1.2 itojun extern struct ifnet loif[NLOOP];
157 1.9 itojun #endif
158 1.2 itojun int ip6_forward_srcrt; /* XXX */
159 1.2 itojun int ip6_sourcecheck; /* XXX */
160 1.2 itojun int ip6_sourcecheck_interval; /* XXX */
161 1.9 itojun
162 1.9 itojun #ifdef IPV6FIREWALL
163 1.9 itojun /* firewall hooks */
164 1.9 itojun ip6_fw_chk_t *ip6_fw_chk_ptr;
165 1.9 itojun ip6_fw_ctl_t *ip6_fw_ctl_ptr;
166 1.2 itojun #endif
167 1.2 itojun
168 1.2 itojun struct ip6stat ip6stat;
169 1.2 itojun
170 1.2 itojun static void ip6_init2 __P((void *));
171 1.2 itojun
172 1.5 itojun static int ip6_hopopts_input __P((u_int32_t *, u_int32_t *, struct mbuf **, int *));
173 1.2 itojun
174 1.9 itojun #if defined(PTR)
175 1.9 itojun extern int ip6_protocol_tr;
176 1.9 itojun
177 1.9 itojun int ptr_in6 __P((struct mbuf *, struct mbuf **));
178 1.9 itojun extern void ip_forward __P((struct mbuf *, int));
179 1.9 itojun #endif
180 1.9 itojun
181 1.2 itojun /*
182 1.2 itojun * IP6 initialization: fill in IP6 protocol switch table.
183 1.2 itojun * All protocols not implemented in kernel go to raw IP6 protocol handler.
184 1.2 itojun */
185 1.2 itojun void
186 1.2 itojun ip6_init()
187 1.2 itojun {
188 1.2 itojun register struct ip6protosw *pr;
189 1.2 itojun register int i;
190 1.2 itojun struct timeval tv;
191 1.2 itojun
192 1.2 itojun pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
193 1.2 itojun if (pr == 0)
194 1.2 itojun panic("ip6_init");
195 1.2 itojun for (i = 0; i < IPPROTO_MAX; i++)
196 1.2 itojun ip6_protox[i] = pr - inet6sw;
197 1.2 itojun for (pr = (struct ip6protosw *)inet6domain.dom_protosw;
198 1.2 itojun pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++)
199 1.2 itojun if (pr->pr_domain->dom_family == PF_INET6 &&
200 1.2 itojun pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW)
201 1.2 itojun ip6_protox[pr->pr_protocol] = pr - inet6sw;
202 1.2 itojun ip6intrq.ifq_maxlen = ip6qmaxlen;
203 1.2 itojun nd6_init();
204 1.2 itojun frag6_init();
205 1.9 itojun #ifdef IPV6FIREWALL
206 1.9 itojun ip6_fw_init();
207 1.9 itojun #endif
208 1.2 itojun /*
209 1.2 itojun * in many cases, random() here does NOT return random number
210 1.2 itojun * as initialization during bootstrap time occur in fixed order.
211 1.2 itojun */
212 1.2 itojun microtime(&tv);
213 1.2 itojun ip6_flow_seq = random() ^ tv.tv_usec;
214 1.2 itojun
215 1.9 itojun #ifndef __FreeBSD__
216 1.2 itojun ip6_init2((void *)0);
217 1.9 itojun #endif
218 1.2 itojun }
219 1.2 itojun
220 1.2 itojun static void
221 1.2 itojun ip6_init2(dummy)
222 1.2 itojun void *dummy;
223 1.2 itojun {
224 1.9 itojun int ret;
225 1.9 itojun #if defined(__bsdi__) && _BSDI_VERSION < 199802
226 1.9 itojun struct ifnet *loifp = &loif;
227 1.9 itojun #endif
228 1.9 itojun
229 1.9 itojun /* get EUI64 from somewhere */
230 1.9 itojun ret = in6_ifattach_getifid(NULL);
231 1.2 itojun
232 1.2 itojun /*
233 1.2 itojun * to route local address of p2p link to loopback,
234 1.2 itojun * assign loopback address first.
235 1.2 itojun */
236 1.9 itojun #ifdef __bsdi__
237 1.9 itojun in6_ifattach(loifp, IN6_IFT_LOOP, NULL, 0);
238 1.9 itojun #else
239 1.9 itojun in6_ifattach(&loif[0], IN6_IFT_LOOP, NULL, 0);
240 1.9 itojun #endif
241 1.2 itojun
242 1.2 itojun /* nd6_timer_init */
243 1.2 itojun timeout(nd6_timer, (caddr_t)0, hz);
244 1.9 itojun /* router renumbering prefix list maintenance */
245 1.9 itojun timeout(in6_rr_timer, (caddr_t)0, hz);
246 1.2 itojun }
247 1.2 itojun
248 1.2 itojun #ifdef __FreeBSD__
249 1.2 itojun /* cheat */
250 1.2 itojun SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, ip6_init2, NULL);
251 1.2 itojun #endif
252 1.2 itojun
253 1.2 itojun /*
254 1.2 itojun * IP6 input interrupt handling. Just pass the packet to ip6_input.
255 1.2 itojun */
256 1.2 itojun void
257 1.2 itojun ip6intr()
258 1.2 itojun {
259 1.2 itojun int s;
260 1.2 itojun struct mbuf *m;
261 1.2 itojun
262 1.2 itojun for (;;) {
263 1.2 itojun s = splimp();
264 1.2 itojun IF_DEQUEUE(&ip6intrq, m);
265 1.2 itojun splx(s);
266 1.2 itojun if (m == 0)
267 1.2 itojun return;
268 1.2 itojun ip6_input(m);
269 1.2 itojun }
270 1.2 itojun }
271 1.2 itojun
272 1.2 itojun #ifdef __FreeBSD__
273 1.2 itojun NETISR_SET(NETISR_IPV6, ip6intr);
274 1.2 itojun #endif
275 1.2 itojun
276 1.2 itojun extern struct route_in6 ip6_forward_rt;
277 1.2 itojun
278 1.2 itojun void
279 1.2 itojun ip6_input(m)
280 1.2 itojun struct mbuf *m;
281 1.2 itojun {
282 1.9 itojun struct ip6_hdr *ip6;
283 1.2 itojun int off = sizeof(struct ip6_hdr), nest;
284 1.2 itojun u_int32_t plen;
285 1.5 itojun u_int32_t rtalert = ~0;
286 1.2 itojun int nxt, ours = 0;
287 1.9 itojun struct ifnet *deliverifp = NULL;
288 1.9 itojun #if defined(__bsdi__) && _BSDI_VERSION < 199802
289 1.9 itojun struct ifnet *loifp = &loif;
290 1.9 itojun #endif
291 1.2 itojun
292 1.2 itojun #ifdef IPSEC
293 1.2 itojun /*
294 1.2 itojun * should the inner packet be considered authentic?
295 1.2 itojun * see comment in ah4_input().
296 1.2 itojun */
297 1.2 itojun if (m) {
298 1.2 itojun m->m_flags &= ~M_AUTHIPHDR;
299 1.2 itojun m->m_flags &= ~M_AUTHIPDGM;
300 1.2 itojun }
301 1.2 itojun #endif
302 1.9 itojun
303 1.2 itojun /*
304 1.2 itojun * mbuf statistics by kazu
305 1.2 itojun */
306 1.2 itojun if (m->m_flags & M_EXT) {
307 1.2 itojun if (m->m_next)
308 1.2 itojun ip6stat.ip6s_mext2m++;
309 1.2 itojun else
310 1.2 itojun ip6stat.ip6s_mext1++;
311 1.2 itojun } else {
312 1.2 itojun if (m->m_next) {
313 1.9 itojun if (m->m_flags & M_LOOP) {
314 1.9 itojun #ifdef __bsdi__
315 1.9 itojun ip6stat.ip6s_m2m[loifp->if_index]++; /*XXX*/
316 1.9 itojun #else
317 1.2 itojun ip6stat.ip6s_m2m[loif[0].if_index]++; /*XXX*/
318 1.9 itojun #endif
319 1.9 itojun }
320 1.2 itojun else if (m->m_pkthdr.rcvif->if_index <= 31)
321 1.2 itojun ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++;
322 1.2 itojun else
323 1.2 itojun ip6stat.ip6s_m2m[0]++;
324 1.2 itojun } else
325 1.2 itojun ip6stat.ip6s_m1++;
326 1.2 itojun }
327 1.2 itojun
328 1.9 itojun in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);
329 1.9 itojun ip6stat.ip6s_total++;
330 1.9 itojun
331 1.9 itojun #ifndef PULLDOWN_TEST
332 1.9 itojun /* XXX is the line really necessary? */
333 1.2 itojun IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /*nothing*/);
334 1.9 itojun #endif
335 1.2 itojun
336 1.9 itojun if (m->m_len < sizeof(struct ip6_hdr)) {
337 1.9 itojun struct ifnet *inifp;
338 1.9 itojun inifp = m->m_pkthdr.rcvif;
339 1.9 itojun if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) {
340 1.9 itojun ip6stat.ip6s_toosmall++;
341 1.9 itojun in6_ifstat_inc(inifp, ifs6_in_hdrerr);
342 1.9 itojun return;
343 1.9 itojun }
344 1.2 itojun }
345 1.2 itojun
346 1.2 itojun ip6 = mtod(m, struct ip6_hdr *);
347 1.2 itojun
348 1.2 itojun if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
349 1.2 itojun ip6stat.ip6s_badvers++;
350 1.9 itojun in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
351 1.2 itojun goto bad;
352 1.2 itojun }
353 1.2 itojun
354 1.2 itojun ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
355 1.2 itojun
356 1.9 itojun #ifdef IPV6FIREWALL
357 1.9 itojun /*
358 1.9 itojun * Check with the firewall...
359 1.9 itojun */
360 1.9 itojun if (ip6_fw_chk_ptr) {
361 1.9 itojun u_short port = 0;
362 1.9 itojun /* If ipfw says divert, we have to just drop packet */
363 1.9 itojun /* use port as a dummy argument */
364 1.9 itojun if ((*ip6_fw_chk_ptr)(&ip6, NULL, &port, &m)) {
365 1.9 itojun m_freem(m);
366 1.9 itojun m = NULL;
367 1.9 itojun }
368 1.9 itojun if (!m)
369 1.9 itojun return;
370 1.9 itojun }
371 1.9 itojun #endif
372 1.9 itojun
373 1.2 itojun /*
374 1.2 itojun * Scope check
375 1.2 itojun */
376 1.2 itojun if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
377 1.2 itojun IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
378 1.2 itojun ip6stat.ip6s_badscope++;
379 1.9 itojun in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
380 1.2 itojun goto bad;
381 1.2 itojun }
382 1.2 itojun if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
383 1.2 itojun IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) {
384 1.2 itojun if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) {
385 1.2 itojun ours = 1;
386 1.9 itojun deliverifp = m->m_pkthdr.rcvif;
387 1.2 itojun goto hbhcheck;
388 1.2 itojun } else {
389 1.2 itojun ip6stat.ip6s_badscope++;
390 1.9 itojun in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
391 1.2 itojun goto bad;
392 1.2 itojun }
393 1.2 itojun }
394 1.2 itojun
395 1.2 itojun if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) {
396 1.2 itojun if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
397 1.2 itojun ours = 1;
398 1.9 itojun deliverifp = m->m_pkthdr.rcvif;
399 1.2 itojun goto hbhcheck;
400 1.2 itojun }
401 1.2 itojun } else {
402 1.2 itojun if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
403 1.2 itojun ip6->ip6_src.s6_addr16[1]
404 1.2 itojun = htons(m->m_pkthdr.rcvif->if_index);
405 1.2 itojun if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
406 1.2 itojun ip6->ip6_dst.s6_addr16[1]
407 1.2 itojun = htons(m->m_pkthdr.rcvif->if_index);
408 1.2 itojun }
409 1.2 itojun
410 1.9 itojun #if defined(PTR)
411 1.9 itojun /*
412 1.9 itojun *
413 1.9 itojun */
414 1.9 itojun if (ip6_protocol_tr)
415 1.9 itojun {
416 1.9 itojun struct mbuf *m1 = NULL;
417 1.9 itojun
418 1.9 itojun switch (ptr_in6(m, &m1))
419 1.9 itojun {
420 1.9 itojun case IPPROTO_IP: goto mcastcheck;
421 1.9 itojun case IPPROTO_IPV4: ip_forward(m1, 0); break;
422 1.9 itojun case IPPROTO_IPV6: ip6_forward(m1, 0); break;
423 1.9 itojun case IPPROTO_MAX: /* discard this packet */
424 1.9 itojun default:
425 1.9 itojun }
426 1.9 itojun
427 1.9 itojun if (m != m1)
428 1.9 itojun m_freem(m);
429 1.9 itojun
430 1.9 itojun return;
431 1.9 itojun }
432 1.9 itojun
433 1.9 itojun mcastcheck:
434 1.9 itojun #endif
435 1.9 itojun
436 1.2 itojun /*
437 1.2 itojun * Multicast check
438 1.2 itojun */
439 1.2 itojun if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
440 1.2 itojun struct in6_multi *in6m = 0;
441 1.9 itojun
442 1.9 itojun in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);
443 1.2 itojun /*
444 1.2 itojun * See if we belong to the destination multicast group on the
445 1.2 itojun * arrival interface.
446 1.2 itojun */
447 1.2 itojun IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m);
448 1.2 itojun if (in6m)
449 1.2 itojun ours = 1;
450 1.2 itojun else if (!ip6_mrouter) {
451 1.2 itojun ip6stat.ip6s_notmember++;
452 1.2 itojun ip6stat.ip6s_cantforward++;
453 1.9 itojun in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
454 1.2 itojun goto bad;
455 1.2 itojun }
456 1.9 itojun deliverifp = m->m_pkthdr.rcvif;
457 1.2 itojun goto hbhcheck;
458 1.2 itojun }
459 1.2 itojun
460 1.2 itojun /*
461 1.2 itojun * Unicast check
462 1.2 itojun */
463 1.2 itojun if (ip6_forward_rt.ro_rt == 0 ||
464 1.2 itojun !IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
465 1.2 itojun &ip6_forward_rt.ro_dst.sin6_addr)) {
466 1.2 itojun if (ip6_forward_rt.ro_rt) {
467 1.2 itojun RTFREE(ip6_forward_rt.ro_rt);
468 1.2 itojun ip6_forward_rt.ro_rt = 0;
469 1.2 itojun }
470 1.2 itojun bzero(&ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6));
471 1.2 itojun ip6_forward_rt.ro_dst.sin6_len = sizeof(struct sockaddr_in6);
472 1.2 itojun ip6_forward_rt.ro_dst.sin6_family = AF_INET6;
473 1.2 itojun ip6_forward_rt.ro_dst.sin6_addr = ip6->ip6_dst;
474 1.2 itojun
475 1.2 itojun #ifdef __FreeBSD__
476 1.2 itojun rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING);
477 1.9 itojun #else
478 1.9 itojun rtalloc((struct route *)&ip6_forward_rt);
479 1.2 itojun #endif
480 1.2 itojun }
481 1.2 itojun
482 1.2 itojun #define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
483 1.2 itojun
484 1.2 itojun /*
485 1.2 itojun * Accept the packet if the forwarding interface to the destination
486 1.2 itojun * according to the routing table is the loopback interface,
487 1.2 itojun * unless the associated route has a gateway.
488 1.2 itojun * Note that this approach causes to accept a packet if there is a
489 1.2 itojun * route to the loopback interface for the destination of the packet.
490 1.2 itojun * But we think it's even useful in some situations, e.g. when using
491 1.2 itojun * a special daemon which wants to intercept the packet.
492 1.2 itojun */
493 1.2 itojun if (ip6_forward_rt.ro_rt &&
494 1.2 itojun (ip6_forward_rt.ro_rt->rt_flags &
495 1.2 itojun (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
496 1.2 itojun #if 0
497 1.2 itojun /*
498 1.2 itojun * The check below is redundant since the comparison of
499 1.2 itojun * the destination and the key of the rtentry has
500 1.2 itojun * already done through looking up the routing table.
501 1.2 itojun */
502 1.2 itojun IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
503 1.2 itojun &rt6_key(ip6_forward_rt.ro_rt)->sin6_addr) &&
504 1.2 itojun #endif
505 1.9 itojun ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) {
506 1.2 itojun struct in6_ifaddr *ia6 =
507 1.2 itojun (struct in6_ifaddr *)ip6_forward_rt.ro_rt->rt_ifa;
508 1.2 itojun /* packet to tentative address must not be received */
509 1.2 itojun if (ia6->ia6_flags & IN6_IFF_ANYCAST)
510 1.2 itojun m->m_flags |= M_ANYCAST6;
511 1.2 itojun if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
512 1.2 itojun /* this interface is ready */
513 1.2 itojun ours = 1;
514 1.9 itojun deliverifp = ia6->ia_ifp; /* correct? */
515 1.2 itojun goto hbhcheck;
516 1.2 itojun } else {
517 1.2 itojun /* this interface is not ready, fall through */
518 1.2 itojun }
519 1.2 itojun }
520 1.2 itojun
521 1.2 itojun /*
522 1.2 itojun * FAITH(Firewall Aided Internet Translator)
523 1.2 itojun */
524 1.2 itojun #if defined(NFAITH) && 0 < NFAITH
525 1.2 itojun if (ip6_keepfaith) {
526 1.2 itojun if (ip6_forward_rt.ro_rt && ip6_forward_rt.ro_rt->rt_ifp
527 1.2 itojun && ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) {
528 1.2 itojun /* XXX do we need more sanity checks? */
529 1.2 itojun ours = 1;
530 1.9 itojun deliverifp = ip6_forward_rt.ro_rt->rt_ifp; /*faith*/
531 1.9 itojun goto hbhcheck;
532 1.9 itojun }
533 1.9 itojun }
534 1.9 itojun #endif
535 1.9 itojun
536 1.9 itojun #if 0
537 1.9 itojun {
538 1.9 itojun /*
539 1.9 itojun * Last resort: check in6_ifaddr for incoming interface.
540 1.9 itojun * The code is here until I update the "goto ours hack" code above
541 1.9 itojun * working right.
542 1.9 itojun */
543 1.9 itojun struct ifaddr *ifa;
544 1.9 itojun for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first;
545 1.9 itojun ifa;
546 1.9 itojun ifa = ifa->ifa_list.tqe_next) {
547 1.9 itojun if (ifa->ifa_addr == NULL)
548 1.9 itojun continue; /* just for safety */
549 1.9 itojun if (ifa->ifa_addr->sa_family != AF_INET6)
550 1.9 itojun continue;
551 1.9 itojun if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ip6->ip6_dst)) {
552 1.9 itojun ours = 1;
553 1.9 itojun deliverifp = ifa->ifa_ifp;
554 1.2 itojun goto hbhcheck;
555 1.2 itojun }
556 1.2 itojun }
557 1.9 itojun }
558 1.2 itojun #endif
559 1.2 itojun
560 1.2 itojun /*
561 1.2 itojun * Now there is no reason to process the packet if it's not our own
562 1.2 itojun * and we're not a router.
563 1.2 itojun */
564 1.2 itojun if (!ip6_forwarding) {
565 1.2 itojun ip6stat.ip6s_cantforward++;
566 1.9 itojun in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
567 1.2 itojun goto bad;
568 1.2 itojun }
569 1.2 itojun
570 1.2 itojun hbhcheck:
571 1.2 itojun /*
572 1.2 itojun * Process Hop-by-Hop options header if it's contained.
573 1.2 itojun * m may be modified in ip6_hopopts_input().
574 1.2 itojun * If a JumboPayload option is included, plen will also be modified.
575 1.2 itojun */
576 1.2 itojun plen = (u_int32_t)ntohs(ip6->ip6_plen);
577 1.2 itojun if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
578 1.9 itojun struct ip6_hbh *hbh;
579 1.9 itojun
580 1.9 itojun if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) {
581 1.9 itojun #if 0 /*touches NULL pointer*/
582 1.9 itojun in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
583 1.9 itojun #endif
584 1.2 itojun return; /* m have already been freed */
585 1.9 itojun }
586 1.2 itojun /* adjust pointer */
587 1.2 itojun ip6 = mtod(m, struct ip6_hdr *);
588 1.9 itojun #ifndef PULLDOWN_TEST
589 1.9 itojun /* ip6_hopopts_input() ensures that mbuf is contiguous */
590 1.9 itojun hbh = (struct ip6_hbh *)(ip6 + 1);
591 1.9 itojun #else
592 1.9 itojun IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
593 1.9 itojun sizeof(struct ip6_hbh));
594 1.9 itojun if (hbh == NULL) {
595 1.9 itojun ip6stat.ip6s_tooshort++;
596 1.9 itojun return;
597 1.9 itojun }
598 1.9 itojun #endif
599 1.9 itojun nxt = hbh->ip6h_nxt;
600 1.2 itojun
601 1.2 itojun /*
602 1.2 itojun * accept the packet if a router alert option is included
603 1.2 itojun * and we act as an IPv6 router.
604 1.2 itojun */
605 1.5 itojun if (rtalert != ~0 && ip6_forwarding)
606 1.2 itojun ours = 1;
607 1.2 itojun } else
608 1.2 itojun nxt = ip6->ip6_nxt;
609 1.2 itojun
610 1.2 itojun /*
611 1.2 itojun * Check that the amount of data in the buffers
612 1.2 itojun * is as at least much as the IPv6 header would have us expect.
613 1.2 itojun * Trim mbufs if longer than we expect.
614 1.2 itojun * Drop packet if shorter than we expect.
615 1.2 itojun */
616 1.2 itojun if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
617 1.2 itojun ip6stat.ip6s_tooshort++;
618 1.9 itojun in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
619 1.2 itojun goto bad;
620 1.2 itojun }
621 1.2 itojun if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
622 1.2 itojun if (m->m_len == m->m_pkthdr.len) {
623 1.2 itojun m->m_len = sizeof(struct ip6_hdr) + plen;
624 1.2 itojun m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen;
625 1.2 itojun } else
626 1.2 itojun m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len);
627 1.2 itojun }
628 1.2 itojun
629 1.2 itojun /*
630 1.2 itojun * Forward if desirable.
631 1.2 itojun */
632 1.2 itojun if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
633 1.2 itojun /*
634 1.2 itojun * If we are acting as a multicast router, all
635 1.2 itojun * incoming multicast packets are passed to the
636 1.2 itojun * kernel-level multicast forwarding function.
637 1.2 itojun * The packet is returned (relatively) intact; if
638 1.2 itojun * ip6_mforward() returns a non-zero value, the packet
639 1.2 itojun * must be discarded, else it may be accepted below.
640 1.2 itojun */
641 1.2 itojun if (ip6_mrouter && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) {
642 1.2 itojun ip6stat.ip6s_cantforward++;
643 1.2 itojun m_freem(m);
644 1.2 itojun return;
645 1.2 itojun }
646 1.2 itojun if (!ours) {
647 1.2 itojun m_freem(m);
648 1.2 itojun return;
649 1.2 itojun }
650 1.2 itojun }
651 1.2 itojun else if (!ours) {
652 1.2 itojun ip6_forward(m, 0);
653 1.2 itojun return;
654 1.2 itojun }
655 1.2 itojun
656 1.2 itojun /*
657 1.2 itojun * Tell launch routine the next header
658 1.2 itojun */
659 1.9 itojun #if defined(__NetBSD__) && defined(IFA_STATS)
660 1.9 itojun if (IFA_STATS && deliverifp != NULL) {
661 1.9 itojun struct in6_ifaddr *ia6;
662 1.9 itojun ip6 = mtod(m, struct ip6_hdr *);
663 1.9 itojun ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
664 1.9 itojun if (ia6)
665 1.9 itojun ia6->ia_ifa.ifa_data.ifad_inbytes += m->m_pkthdr.len;
666 1.9 itojun }
667 1.9 itojun #endif
668 1.2 itojun ip6stat.ip6s_delivered++;
669 1.9 itojun in6_ifstat_inc(deliverifp, ifs6_in_deliver);
670 1.2 itojun nest = 0;
671 1.2 itojun while (nxt != IPPROTO_DONE) {
672 1.2 itojun if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
673 1.2 itojun ip6stat.ip6s_toomanyhdr++;
674 1.2 itojun goto bad;
675 1.2 itojun }
676 1.8 itojun
677 1.8 itojun /*
678 1.8 itojun * protection against faulty packet - there should be
679 1.8 itojun * more sanity checks in header chain processing.
680 1.8 itojun */
681 1.8 itojun if (m->m_pkthdr.len < off) {
682 1.8 itojun ip6stat.ip6s_tooshort++;
683 1.9 itojun in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
684 1.8 itojun goto bad;
685 1.8 itojun }
686 1.8 itojun
687 1.2 itojun nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
688 1.2 itojun }
689 1.2 itojun return;
690 1.2 itojun bad:
691 1.2 itojun m_freem(m);
692 1.2 itojun }
693 1.2 itojun
694 1.2 itojun /*
695 1.2 itojun * Hop-by-Hop options header processing. If a valid jumbo payload option is
696 1.2 itojun * included, the real payload length will be stored in plenp.
697 1.2 itojun */
698 1.2 itojun static int
699 1.2 itojun ip6_hopopts_input(plenp, rtalertp, mp, offp)
700 1.2 itojun u_int32_t *plenp;
701 1.5 itojun u_int32_t *rtalertp; /* XXX: should be stored more smart way */
702 1.2 itojun struct mbuf **mp;
703 1.2 itojun int *offp;
704 1.2 itojun {
705 1.2 itojun register struct mbuf *m = *mp;
706 1.2 itojun int off = *offp, hbhlen;
707 1.2 itojun struct ip6_hbh *hbh;
708 1.2 itojun u_int8_t *opt;
709 1.2 itojun
710 1.2 itojun /* validation of the length of the header */
711 1.9 itojun #ifndef PULLDOWN_TEST
712 1.2 itojun IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1);
713 1.2 itojun hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
714 1.2 itojun hbhlen = (hbh->ip6h_len + 1) << 3;
715 1.2 itojun
716 1.2 itojun IP6_EXTHDR_CHECK(m, off, hbhlen, -1);
717 1.2 itojun hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
718 1.9 itojun #else
719 1.9 itojun IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
720 1.9 itojun sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
721 1.9 itojun if (hbh == NULL) {
722 1.9 itojun ip6stat.ip6s_tooshort++;
723 1.9 itojun return -1;
724 1.9 itojun }
725 1.9 itojun hbhlen = (hbh->ip6h_len + 1) << 3;
726 1.9 itojun IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
727 1.9 itojun hbhlen);
728 1.9 itojun if (hbh == NULL) {
729 1.9 itojun ip6stat.ip6s_tooshort++;
730 1.9 itojun return -1;
731 1.9 itojun }
732 1.9 itojun #endif
733 1.2 itojun off += hbhlen;
734 1.2 itojun hbhlen -= sizeof(struct ip6_hbh);
735 1.2 itojun opt = (u_int8_t *)hbh + sizeof(struct ip6_hbh);
736 1.2 itojun
737 1.2 itojun if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
738 1.2 itojun hbhlen, rtalertp, plenp) < 0)
739 1.2 itojun return(-1);
740 1.2 itojun
741 1.2 itojun *offp = off;
742 1.2 itojun *mp = m;
743 1.2 itojun return(0);
744 1.2 itojun }
745 1.2 itojun
746 1.2 itojun /*
747 1.2 itojun * Search header for all Hop-by-hop options and process each option.
748 1.2 itojun * This function is separate from ip6_hopopts_input() in order to
749 1.2 itojun * handle a case where the sending node itself process its hop-by-hop
750 1.2 itojun * options header. In such a case, the function is called from ip6_output().
751 1.2 itojun */
752 1.2 itojun int
753 1.2 itojun ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
754 1.2 itojun struct mbuf *m;
755 1.2 itojun u_int8_t *opthead;
756 1.2 itojun int hbhlen;
757 1.5 itojun u_int32_t *rtalertp;
758 1.2 itojun u_int32_t *plenp;
759 1.2 itojun {
760 1.2 itojun struct ip6_hdr *ip6;
761 1.2 itojun int optlen = 0;
762 1.2 itojun u_int8_t *opt = opthead;
763 1.2 itojun u_int16_t rtalert_val;
764 1.2 itojun
765 1.2 itojun for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
766 1.2 itojun switch(*opt) {
767 1.2 itojun case IP6OPT_PAD1:
768 1.2 itojun optlen = 1;
769 1.2 itojun break;
770 1.2 itojun case IP6OPT_PADN:
771 1.2 itojun if (hbhlen < IP6OPT_MINLEN) {
772 1.2 itojun ip6stat.ip6s_toosmall++;
773 1.2 itojun goto bad;
774 1.2 itojun }
775 1.2 itojun optlen = *(opt + 1) + 2;
776 1.2 itojun break;
777 1.2 itojun case IP6OPT_RTALERT:
778 1.8 itojun /* XXX may need check for alignment */
779 1.2 itojun if (hbhlen < IP6OPT_RTALERT_LEN) {
780 1.2 itojun ip6stat.ip6s_toosmall++;
781 1.2 itojun goto bad;
782 1.2 itojun }
783 1.2 itojun if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2)
784 1.2 itojun /* XXX: should we discard the packet? */
785 1.2 itojun log(LOG_ERR, "length of router alert opt is inconsitent(%d)",
786 1.2 itojun *(opt + 1));
787 1.2 itojun optlen = IP6OPT_RTALERT_LEN;
788 1.2 itojun bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
789 1.2 itojun *rtalertp = ntohs(rtalert_val);
790 1.2 itojun break;
791 1.2 itojun case IP6OPT_JUMBO:
792 1.8 itojun /* XXX may need check for alignment */
793 1.2 itojun if (hbhlen < IP6OPT_JUMBO_LEN) {
794 1.2 itojun ip6stat.ip6s_toosmall++;
795 1.2 itojun goto bad;
796 1.2 itojun }
797 1.2 itojun if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2)
798 1.2 itojun /* XXX: should we discard the packet? */
799 1.2 itojun log(LOG_ERR, "length of jumbopayload opt "
800 1.2 itojun "is inconsistent(%d)",
801 1.2 itojun *(opt + 1));
802 1.2 itojun optlen = IP6OPT_JUMBO_LEN;
803 1.2 itojun
804 1.2 itojun /*
805 1.2 itojun * We can simply cast because of the alignment
806 1.2 itojun * requirement of the jumbo payload option.
807 1.2 itojun */
808 1.8 itojun #if 0
809 1.2 itojun *plenp = ntohl(*(u_int32_t *)(opt + 2));
810 1.8 itojun #else
811 1.8 itojun bcopy(opt + 2, plenp, sizeof(*plenp));
812 1.8 itojun *plenp = htonl(*plenp);
813 1.8 itojun #endif
814 1.2 itojun if (*plenp <= IPV6_MAXPACKET) {
815 1.2 itojun /*
816 1.2 itojun * jumbo payload length must be larger
817 1.2 itojun * than 65535
818 1.2 itojun */
819 1.2 itojun ip6stat.ip6s_badoptions++;
820 1.2 itojun icmp6_error(m, ICMP6_PARAM_PROB,
821 1.2 itojun ICMP6_PARAMPROB_HEADER,
822 1.2 itojun sizeof(struct ip6_hdr) +
823 1.2 itojun sizeof(struct ip6_hbh) +
824 1.2 itojun opt + 2 - opthead);
825 1.2 itojun return(-1);
826 1.2 itojun }
827 1.2 itojun
828 1.2 itojun ip6 = mtod(m, struct ip6_hdr *);
829 1.2 itojun if (ip6->ip6_plen) {
830 1.2 itojun /*
831 1.2 itojun * IPv6 packets that have non 0 payload length
832 1.2 itojun * must not contain a jumbo paylod option.
833 1.2 itojun */
834 1.2 itojun ip6stat.ip6s_badoptions++;
835 1.2 itojun icmp6_error(m, ICMP6_PARAM_PROB,
836 1.2 itojun ICMP6_PARAMPROB_HEADER,
837 1.2 itojun sizeof(struct ip6_hdr) +
838 1.2 itojun sizeof(struct ip6_hbh) +
839 1.2 itojun opt - opthead);
840 1.2 itojun return(-1);
841 1.2 itojun }
842 1.2 itojun break;
843 1.2 itojun default: /* unknown option */
844 1.2 itojun if (hbhlen < IP6OPT_MINLEN) {
845 1.2 itojun ip6stat.ip6s_toosmall++;
846 1.2 itojun goto bad;
847 1.2 itojun }
848 1.2 itojun if ((optlen = ip6_unknown_opt(opt, m,
849 1.2 itojun sizeof(struct ip6_hdr) +
850 1.2 itojun sizeof(struct ip6_hbh) +
851 1.2 itojun opt - opthead)) == -1)
852 1.2 itojun return(-1);
853 1.2 itojun optlen += 2;
854 1.2 itojun break;
855 1.2 itojun }
856 1.2 itojun }
857 1.2 itojun
858 1.2 itojun return(0);
859 1.2 itojun
860 1.2 itojun bad:
861 1.2 itojun m_freem(m);
862 1.2 itojun return(-1);
863 1.2 itojun }
864 1.2 itojun
865 1.2 itojun /*
866 1.2 itojun * Unknown option processing.
867 1.2 itojun * The third argument `off' is the offset from the IPv6 header to the option,
868 1.2 itojun * which is necessary if the IPv6 header the and option header and IPv6 header
869 1.2 itojun * is not continuous in order to return an ICMPv6 error.
870 1.2 itojun */
871 1.2 itojun int
872 1.2 itojun ip6_unknown_opt(optp, m, off)
873 1.2 itojun u_int8_t *optp;
874 1.2 itojun struct mbuf *m;
875 1.2 itojun int off;
876 1.2 itojun {
877 1.2 itojun struct ip6_hdr *ip6;
878 1.2 itojun
879 1.2 itojun switch(IP6OPT_TYPE(*optp)) {
880 1.2 itojun case IP6OPT_TYPE_SKIP: /* ignore the option */
881 1.2 itojun return((int)*(optp + 1));
882 1.2 itojun case IP6OPT_TYPE_DISCARD: /* silently discard */
883 1.2 itojun m_freem(m);
884 1.2 itojun return(-1);
885 1.2 itojun case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
886 1.2 itojun ip6stat.ip6s_badoptions++;
887 1.2 itojun icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
888 1.2 itojun return(-1);
889 1.2 itojun case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
890 1.2 itojun ip6stat.ip6s_badoptions++;
891 1.2 itojun ip6 = mtod(m, struct ip6_hdr *);
892 1.2 itojun if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
893 1.2 itojun (m->m_flags & (M_BCAST|M_MCAST)))
894 1.2 itojun m_freem(m);
895 1.2 itojun else
896 1.2 itojun icmp6_error(m, ICMP6_PARAM_PROB,
897 1.2 itojun ICMP6_PARAMPROB_OPTION, off);
898 1.2 itojun return(-1);
899 1.2 itojun }
900 1.2 itojun
901 1.2 itojun m_freem(m); /* XXX: NOTREACHED */
902 1.2 itojun return(-1);
903 1.2 itojun }
904 1.2 itojun
905 1.2 itojun /*
906 1.9 itojun * Create the "control" list for this pcb.
907 1.9 itojun *
908 1.9 itojun * The routine will be called from upper layer handlers like tcp6_input().
909 1.9 itojun * Thus the routine assumes that the caller (tcp6_input) have already
910 1.9 itojun * called IP6_EXTHDR_CHECK() and all the extension headers are located in the
911 1.9 itojun * very first mbuf on the mbuf chain.
912 1.9 itojun * We may want to add some infinite loop prevention or sanity checks for safety.
913 1.9 itojun * (This applies only when you are using KAME mbuf chain restriction, i.e.
914 1.9 itojun * you are using IP6_EXTHDR_CHECK() not m_pulldown())
915 1.2 itojun */
916 1.2 itojun void
917 1.2 itojun ip6_savecontrol(in6p, mp, ip6, m)
918 1.9 itojun #if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(HAVE_NRL_INPCB)
919 1.9 itojun register struct inpcb *in6p;
920 1.9 itojun #else
921 1.2 itojun register struct in6pcb *in6p;
922 1.9 itojun #endif
923 1.2 itojun register struct mbuf **mp;
924 1.2 itojun register struct ip6_hdr *ip6;
925 1.2 itojun register struct mbuf *m;
926 1.2 itojun {
927 1.9 itojun #ifdef HAVE_NRL_INPCB
928 1.9 itojun # define in6p_flags inp_flags
929 1.9 itojun #endif
930 1.9 itojun #if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
931 1.2 itojun struct proc *p = curproc; /* XXX */
932 1.2 itojun #endif
933 1.2 itojun #ifdef __bsdi__
934 1.2 itojun # define sbcreatecontrol so_cmsg
935 1.2 itojun #endif
936 1.9 itojun int privileged;
937 1.2 itojun
938 1.9 itojun privileged = 0;
939 1.9 itojun #if defined(__NetBSD__) || (defined(__FreeBSD__) && __FreeBSD__ >= 3)
940 1.9 itojun if (p && !suser(p->p_ucred, &p->p_acflag))
941 1.9 itojun privileged++;
942 1.9 itojun #else
943 1.9 itojun #ifdef HAVE_NRL_INPCB
944 1.9 itojun if ((in6p->inp_socket->so_state & SS_PRIV) != 0)
945 1.9 itojun privileged++;
946 1.9 itojun #else
947 1.9 itojun if ((in6p->in6p_socket->so_state & SS_PRIV) != 0)
948 1.9 itojun privileged++;
949 1.9 itojun #endif
950 1.9 itojun #endif
951 1.9 itojun
952 1.9 itojun #ifdef SO_TIMESTAMP
953 1.2 itojun if (in6p->in6p_socket->so_options & SO_TIMESTAMP) {
954 1.2 itojun struct timeval tv;
955 1.2 itojun
956 1.2 itojun microtime(&tv);
957 1.2 itojun *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
958 1.2 itojun SCM_TIMESTAMP, SOL_SOCKET);
959 1.2 itojun if (*mp)
960 1.2 itojun mp = &(*mp)->m_next;
961 1.2 itojun }
962 1.9 itojun #endif
963 1.2 itojun if (in6p->in6p_flags & IN6P_RECVDSTADDR) {
964 1.2 itojun *mp = sbcreatecontrol((caddr_t) &ip6->ip6_dst,
965 1.2 itojun sizeof(struct in6_addr), IPV6_RECVDSTADDR,
966 1.2 itojun IPPROTO_IPV6);
967 1.2 itojun if (*mp)
968 1.2 itojun mp = &(*mp)->m_next;
969 1.2 itojun }
970 1.2 itojun
971 1.2 itojun #ifdef noyet
972 1.2 itojun /* options were tossed above */
973 1.2 itojun if (in6p->in6p_flags & IN6P_RECVOPTS)
974 1.2 itojun /* broken */
975 1.2 itojun /* ip6_srcroute doesn't do what we want here, need to fix */
976 1.2 itojun if (in6p->in6p_flags & IPV6P_RECVRETOPTS)
977 1.2 itojun /* broken */
978 1.2 itojun #endif
979 1.2 itojun
980 1.2 itojun /* RFC 2292 sec. 5 */
981 1.2 itojun if (in6p->in6p_flags & IN6P_PKTINFO) {
982 1.2 itojun struct in6_pktinfo pi6;
983 1.2 itojun bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
984 1.2 itojun if (IN6_IS_SCOPE_LINKLOCAL(&pi6.ipi6_addr))
985 1.2 itojun pi6.ipi6_addr.s6_addr16[1] = 0;
986 1.2 itojun pi6.ipi6_ifindex = (m && m->m_pkthdr.rcvif)
987 1.2 itojun ? m->m_pkthdr.rcvif->if_index
988 1.2 itojun : 0;
989 1.2 itojun *mp = sbcreatecontrol((caddr_t) &pi6,
990 1.2 itojun sizeof(struct in6_pktinfo), IPV6_PKTINFO,
991 1.2 itojun IPPROTO_IPV6);
992 1.2 itojun if (*mp)
993 1.2 itojun mp = &(*mp)->m_next;
994 1.2 itojun }
995 1.2 itojun if (in6p->in6p_flags & IN6P_HOPLIMIT) {
996 1.2 itojun int hlim = ip6->ip6_hlim & 0xff;
997 1.2 itojun *mp = sbcreatecontrol((caddr_t) &hlim,
998 1.2 itojun sizeof(int), IPV6_HOPLIMIT, IPPROTO_IPV6);
999 1.2 itojun if (*mp)
1000 1.2 itojun mp = &(*mp)->m_next;
1001 1.2 itojun }
1002 1.2 itojun /* IN6P_NEXTHOP - for outgoing packet only */
1003 1.2 itojun
1004 1.2 itojun /*
1005 1.2 itojun * IPV6_HOPOPTS socket option. We require super-user privilege
1006 1.2 itojun * for the option, but it might be too strict, since there might
1007 1.2 itojun * be some hop-by-hop options which can be returned to normal user.
1008 1.2 itojun * See RFC 2292 section 6.
1009 1.2 itojun */
1010 1.9 itojun if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) {
1011 1.2 itojun /*
1012 1.2 itojun * Check if a hop-by-hop options header is contatined in the
1013 1.2 itojun * received packet, and if so, store the options as ancillary
1014 1.2 itojun * data. Note that a hop-by-hop options header must be
1015 1.2 itojun * just after the IPv6 header, which fact is assured through
1016 1.2 itojun * the IPv6 input processing.
1017 1.2 itojun */
1018 1.2 itojun struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1019 1.2 itojun if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
1020 1.9 itojun struct ip6_hbh *hbh;
1021 1.9 itojun int hbhlen;
1022 1.9 itojun
1023 1.9 itojun #ifndef PULLDOWN_TEST
1024 1.9 itojun hbh = (struct ip6_hbh *)(ip6 + 1);
1025 1.9 itojun hbhlen = (hbh->ip6h_len + 1) << 3;
1026 1.9 itojun #else
1027 1.9 itojun IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
1028 1.9 itojun sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
1029 1.9 itojun if (hbh == NULL) {
1030 1.9 itojun ip6stat.ip6s_tooshort++;
1031 1.9 itojun return;
1032 1.9 itojun }
1033 1.9 itojun hbhlen = (hbh->ip6h_len + 1) << 3;
1034 1.9 itojun IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
1035 1.9 itojun sizeof(struct ip6_hdr), hbhlen);
1036 1.9 itojun if (hbh == NULL) {
1037 1.9 itojun ip6stat.ip6s_tooshort++;
1038 1.9 itojun return;
1039 1.9 itojun }
1040 1.9 itojun #endif
1041 1.2 itojun
1042 1.2 itojun /*
1043 1.2 itojun * XXX: We copy whole the header even if a jumbo
1044 1.2 itojun * payload option is included, which option is to
1045 1.2 itojun * be removed before returning in the RFC 2292.
1046 1.2 itojun * But it's too painful operation...
1047 1.2 itojun */
1048 1.9 itojun *mp = sbcreatecontrol((caddr_t)hbh, hbhlen,
1049 1.2 itojun IPV6_HOPOPTS, IPPROTO_IPV6);
1050 1.2 itojun if (*mp)
1051 1.2 itojun mp = &(*mp)->m_next;
1052 1.2 itojun }
1053 1.2 itojun }
1054 1.2 itojun
1055 1.2 itojun /* IPV6_DSTOPTS and IPV6_RTHDR socket options */
1056 1.2 itojun if (in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDR)) {
1057 1.2 itojun struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1058 1.2 itojun int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);;
1059 1.2 itojun
1060 1.2 itojun /*
1061 1.2 itojun * Search for destination options headers or routing
1062 1.2 itojun * header(s) through the header chain, and stores each
1063 1.2 itojun * header as ancillary data.
1064 1.2 itojun * Note that the order of the headers remains in
1065 1.2 itojun * the chain of ancillary data.
1066 1.2 itojun */
1067 1.2 itojun while(1) { /* is explicit loop prevention necessary? */
1068 1.9 itojun struct ip6_ext *ip6e;
1069 1.9 itojun int elen;
1070 1.9 itojun
1071 1.9 itojun #ifndef PULLDOWN_TEST
1072 1.9 itojun ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off);
1073 1.9 itojun if (nxt == IPPROTO_AH)
1074 1.9 itojun elen = (ip6e->ip6e_len + 2) << 2;
1075 1.9 itojun else
1076 1.9 itojun elen = (ip6e->ip6e_len + 1) << 3;
1077 1.9 itojun #else
1078 1.9 itojun IP6_EXTHDR_GET(ip6e, struct ip6_ext *, m, off,
1079 1.9 itojun sizeof(struct ip6_ext));
1080 1.9 itojun if (ip6e == NULL) {
1081 1.9 itojun ip6stat.ip6s_tooshort++;
1082 1.9 itojun return;
1083 1.9 itojun }
1084 1.9 itojun if (nxt == IPPROTO_AH)
1085 1.9 itojun elen = (ip6e->ip6e_len + 2) << 2;
1086 1.9 itojun else
1087 1.9 itojun elen = (ip6e->ip6e_len + 1) << 3;
1088 1.9 itojun IP6_EXTHDR_GET(ip6e, struct ip6_ext *, m, off, elen);
1089 1.9 itojun if (ip6e == NULL) {
1090 1.9 itojun ip6stat.ip6s_tooshort++;
1091 1.9 itojun return;
1092 1.9 itojun }
1093 1.9 itojun #endif
1094 1.2 itojun
1095 1.2 itojun switch(nxt) {
1096 1.2 itojun case IPPROTO_DSTOPTS:
1097 1.2 itojun if (!in6p->in6p_flags & IN6P_DSTOPTS)
1098 1.2 itojun break;
1099 1.2 itojun
1100 1.2 itojun /*
1101 1.2 itojun * We also require super-user privilege for
1102 1.2 itojun * the option.
1103 1.2 itojun * See the comments on IN6_HOPOPTS.
1104 1.2 itojun */
1105 1.9 itojun if (!privileged)
1106 1.2 itojun break;
1107 1.2 itojun
1108 1.9 itojun *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1109 1.2 itojun IPV6_DSTOPTS,
1110 1.2 itojun IPPROTO_IPV6);
1111 1.2 itojun if (*mp)
1112 1.2 itojun mp = &(*mp)->m_next;
1113 1.2 itojun break;
1114 1.2 itojun
1115 1.2 itojun case IPPROTO_ROUTING:
1116 1.2 itojun if (!in6p->in6p_flags & IN6P_RTHDR)
1117 1.2 itojun break;
1118 1.2 itojun
1119 1.9 itojun *mp = sbcreatecontrol((caddr_t)ip6e, elen,
1120 1.2 itojun IPV6_RTHDR,
1121 1.2 itojun IPPROTO_IPV6);
1122 1.2 itojun if (*mp)
1123 1.2 itojun mp = &(*mp)->m_next;
1124 1.2 itojun break;
1125 1.2 itojun
1126 1.2 itojun case IPPROTO_UDP:
1127 1.2 itojun case IPPROTO_TCP:
1128 1.2 itojun case IPPROTO_ICMPV6:
1129 1.2 itojun default:
1130 1.2 itojun /*
1131 1.2 itojun * stop search if we encounter an upper
1132 1.2 itojun * layer protocol headers.
1133 1.2 itojun */
1134 1.2 itojun goto loopend;
1135 1.2 itojun
1136 1.2 itojun case IPPROTO_HOPOPTS:
1137 1.2 itojun case IPPROTO_AH: /* is it possible? */
1138 1.2 itojun break;
1139 1.2 itojun }
1140 1.2 itojun
1141 1.2 itojun /* proceed with the next header. */
1142 1.9 itojun off += elen;
1143 1.2 itojun nxt = ip6e->ip6e_nxt;
1144 1.2 itojun }
1145 1.2 itojun loopend:
1146 1.2 itojun }
1147 1.9 itojun if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) {
1148 1.2 itojun /* to be done */
1149 1.2 itojun }
1150 1.9 itojun if ((in6p->in6p_flags & IN6P_DSTOPTS) && privileged) {
1151 1.2 itojun /* to be done */
1152 1.2 itojun }
1153 1.2 itojun /* IN6P_RTHDR - to be done */
1154 1.2 itojun
1155 1.2 itojun #ifdef __bsdi__
1156 1.2 itojun # undef sbcreatecontrol
1157 1.2 itojun #endif
1158 1.9 itojun #ifdef __OpenBSD__
1159 1.9 itojun # undef in6p_flags
1160 1.9 itojun #endif
1161 1.2 itojun }
1162 1.2 itojun
1163 1.2 itojun /*
1164 1.2 itojun * Get pointer to the previous header followed by the header
1165 1.2 itojun * currently processed.
1166 1.2 itojun * XXX: This function supposes that
1167 1.2 itojun * M includes all headers,
1168 1.2 itojun * the next header field and the header length field of each header
1169 1.2 itojun * are valid, and
1170 1.2 itojun * the sum of each header length equals to OFF.
1171 1.2 itojun * Because of these assumptions, this function must be called very
1172 1.2 itojun * carefully. Moreover, it will not be used in the near future when
1173 1.2 itojun * we develop `neater' mechanism to process extension headers.
1174 1.2 itojun */
1175 1.2 itojun char *
1176 1.2 itojun ip6_get_prevhdr(m, off)
1177 1.2 itojun struct mbuf *m;
1178 1.2 itojun int off;
1179 1.2 itojun {
1180 1.2 itojun struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1181 1.2 itojun
1182 1.2 itojun if (off == sizeof(struct ip6_hdr))
1183 1.2 itojun return(&ip6->ip6_nxt);
1184 1.2 itojun else {
1185 1.2 itojun int len, nxt;
1186 1.2 itojun struct ip6_ext *ip6e = NULL;
1187 1.2 itojun
1188 1.2 itojun nxt = ip6->ip6_nxt;
1189 1.2 itojun len = sizeof(struct ip6_hdr);
1190 1.2 itojun while (len < off) {
1191 1.2 itojun ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
1192 1.2 itojun
1193 1.2 itojun switch(nxt) {
1194 1.2 itojun case IPPROTO_FRAGMENT:
1195 1.2 itojun len += sizeof(struct ip6_frag);
1196 1.2 itojun break;
1197 1.2 itojun case IPPROTO_AH:
1198 1.2 itojun len += (ip6e->ip6e_len + 2) << 2;
1199 1.2 itojun break;
1200 1.2 itojun default:
1201 1.2 itojun len += (ip6e->ip6e_len + 1) << 3;
1202 1.2 itojun break;
1203 1.2 itojun }
1204 1.2 itojun nxt = ip6e->ip6e_nxt;
1205 1.2 itojun }
1206 1.2 itojun if (ip6e)
1207 1.2 itojun return(&ip6e->ip6e_nxt);
1208 1.2 itojun else
1209 1.2 itojun return NULL;
1210 1.2 itojun }
1211 1.2 itojun }
1212 1.2 itojun
1213 1.2 itojun /*
1214 1.2 itojun * System control for IP6
1215 1.2 itojun */
1216 1.2 itojun
1217 1.2 itojun u_char inet6ctlerrmap[PRC_NCMDS] = {
1218 1.2 itojun 0, 0, 0, 0,
1219 1.2 itojun 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH,
1220 1.2 itojun EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
1221 1.2 itojun EMSGSIZE, EHOSTUNREACH, 0, 0,
1222 1.2 itojun 0, 0, 0, 0,
1223 1.2 itojun ENOPROTOOPT
1224 1.2 itojun };
1225 1.2 itojun
1226 1.9 itojun #if defined(__NetBSD__) || defined(__OpenBSD__)
1227 1.2 itojun #include <vm/vm.h>
1228 1.2 itojun #include <sys/sysctl.h>
1229 1.2 itojun
1230 1.2 itojun int
1231 1.2 itojun ip6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
1232 1.2 itojun int *name;
1233 1.2 itojun u_int namelen;
1234 1.2 itojun void *oldp;
1235 1.2 itojun size_t *oldlenp;
1236 1.2 itojun void *newp;
1237 1.2 itojun size_t newlen;
1238 1.2 itojun {
1239 1.2 itojun /* All sysctl names at this level are terminal. */
1240 1.2 itojun if (namelen != 1)
1241 1.2 itojun return ENOTDIR;
1242 1.2 itojun
1243 1.2 itojun switch (name[0]) {
1244 1.2 itojun
1245 1.2 itojun case IPV6CTL_FORWARDING:
1246 1.2 itojun return sysctl_int(oldp, oldlenp, newp, newlen,
1247 1.2 itojun &ip6_forwarding);
1248 1.2 itojun case IPV6CTL_SENDREDIRECTS:
1249 1.2 itojun return sysctl_int(oldp, oldlenp, newp, newlen,
1250 1.2 itojun &ip6_sendredirects);
1251 1.2 itojun case IPV6CTL_DEFHLIM:
1252 1.2 itojun return sysctl_int(oldp, oldlenp, newp, newlen, &ip6_defhlim);
1253 1.2 itojun case IPV6CTL_MAXFRAGPACKETS:
1254 1.2 itojun return sysctl_int(oldp, oldlenp, newp, newlen,
1255 1.2 itojun &ip6_maxfragpackets);
1256 1.2 itojun case IPV6CTL_ACCEPT_RTADV:
1257 1.2 itojun return sysctl_int(oldp, oldlenp, newp, newlen,
1258 1.2 itojun &ip6_accept_rtadv);
1259 1.2 itojun case IPV6CTL_KEEPFAITH:
1260 1.2 itojun return sysctl_int(oldp, oldlenp, newp, newlen, &ip6_keepfaith);
1261 1.2 itojun case IPV6CTL_LOG_INTERVAL:
1262 1.2 itojun return sysctl_int(oldp, oldlenp, newp, newlen,
1263 1.2 itojun &ip6_log_interval);
1264 1.2 itojun case IPV6CTL_HDRNESTLIMIT:
1265 1.2 itojun return sysctl_int(oldp, oldlenp, newp, newlen,
1266 1.2 itojun &ip6_hdrnestlimit);
1267 1.2 itojun case IPV6CTL_DAD_COUNT:
1268 1.2 itojun return sysctl_int(oldp, oldlenp, newp, newlen, &ip6_dad_count);
1269 1.2 itojun case IPV6CTL_AUTO_FLOWLABEL:
1270 1.2 itojun return sysctl_int(oldp, oldlenp, newp, newlen,
1271 1.2 itojun &ip6_auto_flowlabel);
1272 1.2 itojun case IPV6CTL_DEFMCASTHLIM:
1273 1.2 itojun return sysctl_int(oldp, oldlenp, newp, newlen,
1274 1.2 itojun &ip6_defmcasthlim);
1275 1.2 itojun case IPV6CTL_GIF_HLIM:
1276 1.2 itojun return sysctl_int(oldp, oldlenp, newp, newlen,
1277 1.2 itojun &ip6_gif_hlim);
1278 1.2 itojun case IPV6CTL_KAME_VERSION:
1279 1.2 itojun return sysctl_rdstring(oldp, oldlenp, newp, __KAME_VERSION);
1280 1.9 itojun case IPV6CTL_USE_DEPRECATED:
1281 1.9 itojun return sysctl_int(oldp, oldlenp, newp, newlen,
1282 1.9 itojun &ip6_use_deprecated);
1283 1.10 itojun case IPV6CTL_RR_PRUNE:
1284 1.10 itojun return sysctl_int(oldp, oldlenp, newp, newlen, &ip6_rr_prune);
1285 1.2 itojun default:
1286 1.2 itojun return EOPNOTSUPP;
1287 1.2 itojun }
1288 1.2 itojun /* NOTREACHED */
1289 1.2 itojun }
1290 1.9 itojun #endif /* __NetBSD__ || __OpenBSD__ */
1291 1.9 itojun
1292 1.9 itojun #ifdef __bsdi__
1293 1.9 itojun int *ip6_sysvars[] = IPV6CTL_VARS;
1294 1.9 itojun
1295 1.9 itojun int
1296 1.9 itojun ip6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
1297 1.9 itojun int *name;
1298 1.9 itojun u_int namelen;
1299 1.9 itojun void *oldp;
1300 1.9 itojun size_t *oldlenp;
1301 1.9 itojun void *newp;
1302 1.9 itojun size_t newlen;
1303 1.9 itojun {
1304 1.9 itojun if (name[0] >= IPV6CTL_MAXID)
1305 1.9 itojun return (EOPNOTSUPP);
1306 1.9 itojun
1307 1.9 itojun switch (name[0]) {
1308 1.9 itojun case IPV6CTL_STATS:
1309 1.9 itojun return sysctl_rdtrunc(oldp, oldlenp, newp, &ip6stat,
1310 1.9 itojun sizeof(ip6stat));
1311 1.9 itojun case IPV6CTL_KAME_VERSION:
1312 1.9 itojun return sysctl_rdstring(oldp, oldlenp, newp, __KAME_VERSION);
1313 1.9 itojun default:
1314 1.9 itojun return (sysctl_int_arr(ip6_sysvars, name, namelen,
1315 1.9 itojun oldp, oldlenp, newp, newlen));
1316 1.9 itojun }
1317 1.9 itojun }
1318 1.9 itojun #endif /* __bsdi__ */
1319