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