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