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