ip6_input.c revision 71794
1/* $FreeBSD: head/sys/netinet6/ip6_input.c 71794 2001-01-29 11:28:20Z peter $ */ 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 /* XXX is the line really necessary? */ 274 IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /*nothing*/); 275#endif 276 277 if (m->m_len < sizeof(struct ip6_hdr)) { 278 struct ifnet *inifp; 279 inifp = m->m_pkthdr.rcvif; 280 if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) { 281 ip6stat.ip6s_toosmall++; 282 in6_ifstat_inc(inifp, ifs6_in_hdrerr); 283 return; 284 } 285 } 286 287 ip6 = mtod(m, struct ip6_hdr *); 288 289 if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { 290 ip6stat.ip6s_badvers++; 291 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); 292 goto bad; 293 } 294 295#ifdef PFIL_HOOKS 296 /* 297 * Run through list of hooks for input packets. If there are any 298 * filters which require that additional packets in the flow are 299 * not fast-forwarded, they must clear the M_CANFASTFWD flag. 300 * Note that filters must _never_ set this flag, as another filter 301 * in the list may have previously cleared it. 302 */ 303 m0 = m; 304 pfh = pfil_hook_get(PFIL_IN, &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh); 305 for (; pfh; pfh = pfh->pfil_link.tqe_next) 306 if (pfh->pfil_func) { 307 rv = pfh->pfil_func(ip6, sizeof(*ip6), 308 m->m_pkthdr.rcvif, 0, &m0); 309 if (rv) 310 return; 311 m = m0; 312 if (m == NULL) 313 return; 314 ip6 = mtod(m, struct ip6_hdr *); 315 } 316#endif /* PFIL_HOOKS */ 317 318 ip6stat.ip6s_nxthist[ip6->ip6_nxt]++; 319 320 /* 321 * Check with the firewall... 322 */ 323 if (ip6_fw_enable && ip6_fw_chk_ptr) { 324 u_short port = 0; 325 /* If ipfw says divert, we have to just drop packet */ 326 /* use port as a dummy argument */ 327 if ((*ip6_fw_chk_ptr)(&ip6, NULL, &port, &m)) { 328 m_freem(m); 329 m = NULL; 330 } 331 if (!m) 332 return; 333 } 334 335 /* 336 * Scope check 337 */ 338 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) || 339 IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) { 340 ip6stat.ip6s_badscope++; 341 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); 342 goto bad; 343 } 344 345 /* 346 * Don't check IPv4 mapped address here. SIIT assumes that 347 * routers would forward IPv6 native packets with IPv4 mapped 348 * address normally. 349 */ 350#if 0 351 /* 352 * Reject packets with IPv4 compatible addresses (auto tunnel). 353 * 354 * The code forbids auto tunnel relay case in RFC1933 (the check is 355 * stronger than RFC1933). We may want to re-enable it if mech-xx 356 * is revised to forbid relaying case. 357 */ 358 if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) || 359 IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) { 360 ip6stat.ip6s_badscope++; 361 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); 362 goto bad; 363 } 364#endif 365 if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) || 366 IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) { 367 if (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) { 368 ours = 1; 369 deliverifp = m->m_pkthdr.rcvif; 370 goto hbhcheck; 371 } else { 372 ip6stat.ip6s_badscope++; 373 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); 374 goto bad; 375 } 376 } 377 378#ifndef FAKE_LOOPBACK_IF 379 if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) 380#else 381 if (1) 382#endif 383 { 384 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) 385 ip6->ip6_src.s6_addr16[1] 386 = htons(m->m_pkthdr.rcvif->if_index); 387 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) 388 ip6->ip6_dst.s6_addr16[1] 389 = htons(m->m_pkthdr.rcvif->if_index); 390 } 391 392 /* 393 * XXX we need this since we do not have "goto ours" hack route 394 * for some of our ifaddrs on loopback interface. 395 * we should correct it by changing in6_ifattach to install 396 * "goto ours" hack route. 397 */ 398 if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) != 0) { 399 if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) { 400 ours = 1; 401 deliverifp = m->m_pkthdr.rcvif; 402 goto hbhcheck; 403 } 404 } 405 406 /* 407 * Multicast check 408 */ 409 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { 410 struct in6_multi *in6m = 0; 411 412 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast); 413 /* 414 * See if we belong to the destination multicast group on the 415 * arrival interface. 416 */ 417 IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m); 418 if (in6m) 419 ours = 1; 420 else if (!ip6_mrouter) { 421 ip6stat.ip6s_notmember++; 422 ip6stat.ip6s_cantforward++; 423 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); 424 goto bad; 425 } 426 deliverifp = m->m_pkthdr.rcvif; 427 goto hbhcheck; 428 } 429 430 /* 431 * Unicast check 432 */ 433 if (ip6_forward_rt.ro_rt != NULL && 434 (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) != 0 && 435 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, 436 &ip6_forward_rt.ro_dst.sin6_addr)) 437 ip6stat.ip6s_forward_cachehit++; 438 else { 439 if (ip6_forward_rt.ro_rt) { 440 /* route is down or destination is different */ 441 ip6stat.ip6s_forward_cachemiss++; 442 RTFREE(ip6_forward_rt.ro_rt); 443 ip6_forward_rt.ro_rt = 0; 444 } 445 446 bzero(&ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6)); 447 ip6_forward_rt.ro_dst.sin6_len = sizeof(struct sockaddr_in6); 448 ip6_forward_rt.ro_dst.sin6_family = AF_INET6; 449 ip6_forward_rt.ro_dst.sin6_addr = ip6->ip6_dst; 450#ifdef SCOPEDROUTING 451 ip6_forward_rt.ro_dst.sin6_scope_id = 452 in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_dst); 453#endif 454 455 rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING); 456 } 457 458#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key)) 459 460 /* 461 * Accept the packet if the forwarding interface to the destination 462 * according to the routing table is the loopback interface, 463 * unless the associated route has a gateway. 464 * Note that this approach causes to accept a packet if there is a 465 * route to the loopback interface for the destination of the packet. 466 * But we think it's even useful in some situations, e.g. when using 467 * a special daemon which wants to intercept the packet. 468 */ 469 if (ip6_forward_rt.ro_rt && 470 (ip6_forward_rt.ro_rt->rt_flags & 471 (RTF_HOST|RTF_GATEWAY)) == RTF_HOST && 472#if 0 473 /* 474 * The check below is redundant since the comparison of 475 * the destination and the key of the rtentry has 476 * already done through looking up the routing table. 477 */ 478 IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, 479 &rt6_key(ip6_forward_rt.ro_rt)->sin6_addr) && 480#endif 481 ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) { 482 struct in6_ifaddr *ia6 = 483 (struct in6_ifaddr *)ip6_forward_rt.ro_rt->rt_ifa; 484 if (ia6->ia6_flags & IN6_IFF_ANYCAST) 485 m->m_flags |= M_ANYCAST6; 486 /* 487 * packets to a tentative, duplicated, or somehow invalid 488 * address must not be accepted. 489 */ 490 if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) { 491 /* this address is ready */ 492 ours = 1; 493 deliverifp = ia6->ia_ifp; /* correct? */ 494 495 /* Count the packet in the ip address stats */ 496 ia6->ia_ifa.if_ipackets++; 497 ia6->ia_ifa.if_ibytes += m->m_pkthdr.len; 498 499 goto hbhcheck; 500 } else { 501 /* address is not ready, so discard the packet. */ 502 log(LOG_INFO, 503 "ip6_input: packet to an unready address %s->%s", 504 ip6_sprintf(&ip6->ip6_src), 505 ip6_sprintf(&ip6->ip6_dst)); 506 507 goto bad; 508 } 509 } 510 511 /* 512 * FAITH(Firewall Aided Internet Translator) 513 */ 514#if defined(NFAITH) && 0 < NFAITH 515 if (ip6_keepfaith) { 516 if (ip6_forward_rt.ro_rt && ip6_forward_rt.ro_rt->rt_ifp 517 && ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) { 518 /* XXX do we need more sanity checks? */ 519 ours = 1; 520 deliverifp = ip6_forward_rt.ro_rt->rt_ifp; /*faith*/ 521 goto hbhcheck; 522 } 523 } 524#endif 525 526 /* 527 * Now there is no reason to process the packet if it's not our own 528 * and we're not a router. 529 */ 530 if (!ip6_forwarding) { 531 ip6stat.ip6s_cantforward++; 532 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); 533 goto bad; 534 } 535 536 hbhcheck: 537 /* 538 * Process Hop-by-Hop options header if it's contained. 539 * m may be modified in ip6_hopopts_input(). 540 * If a JumboPayload option is included, plen will also be modified. 541 */ 542 plen = (u_int32_t)ntohs(ip6->ip6_plen); 543 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) { 544 struct ip6_hbh *hbh; 545 546 if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) { 547#if 0 /*touches NULL pointer*/ 548 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); 549#endif 550 return; /* m have already been freed */ 551 } 552 553 /* adjust pointer */ 554 ip6 = mtod(m, struct ip6_hdr *); 555 556 /* 557 * if the payload length field is 0 and the next header field 558 * indicates Hop-by-Hop Options header, then a Jumbo Payload 559 * option MUST be included. 560 */ 561 if (ip6->ip6_plen == 0 && plen == 0) { 562 /* 563 * Note that if a valid jumbo payload option is 564 * contained, ip6_hoptops_input() must set a valid 565 * (non-zero) payload length to the variable plen. 566 */ 567 ip6stat.ip6s_badoptions++; 568 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); 569 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); 570 icmp6_error(m, ICMP6_PARAM_PROB, 571 ICMP6_PARAMPROB_HEADER, 572 (caddr_t)&ip6->ip6_plen - (caddr_t)ip6); 573 return; 574 } 575#ifndef PULLDOWN_TEST 576 /* ip6_hopopts_input() ensures that mbuf is contiguous */ 577 hbh = (struct ip6_hbh *)(ip6 + 1); 578#else 579 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), 580 sizeof(struct ip6_hbh)); 581 if (hbh == NULL) { 582 ip6stat.ip6s_tooshort++; 583 return; 584 } 585#endif 586 nxt = hbh->ip6h_nxt; 587 588 /* 589 * accept the packet if a router alert option is included 590 * and we act as an IPv6 router. 591 */ 592 if (rtalert != ~0 && ip6_forwarding) 593 ours = 1; 594 } else 595 nxt = ip6->ip6_nxt; 596 597 /* 598 * Check that the amount of data in the buffers 599 * is as at least much as the IPv6 header would have us expect. 600 * Trim mbufs if longer than we expect. 601 * Drop packet if shorter than we expect. 602 */ 603 if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) { 604 ip6stat.ip6s_tooshort++; 605 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); 606 goto bad; 607 } 608 if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) { 609 if (m->m_len == m->m_pkthdr.len) { 610 m->m_len = sizeof(struct ip6_hdr) + plen; 611 m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen; 612 } else 613 m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len); 614 } 615 616 /* 617 * Forward if desirable. 618 */ 619 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { 620 /* 621 * If we are acting as a multicast router, all 622 * incoming multicast packets are passed to the 623 * kernel-level multicast forwarding function. 624 * The packet is returned (relatively) intact; if 625 * ip6_mforward() returns a non-zero value, the packet 626 * must be discarded, else it may be accepted below. 627 */ 628 if (ip6_mrouter && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) { 629 ip6stat.ip6s_cantforward++; 630 m_freem(m); 631 return; 632 } 633 if (!ours) { 634 m_freem(m); 635 return; 636 } 637 } else if (!ours) { 638 ip6_forward(m, 0); 639 return; 640 } 641 642 ip6 = mtod(m, struct ip6_hdr *); 643 644 /* 645 * Malicious party may be able to use IPv4 mapped addr to confuse 646 * tcp/udp stack and bypass security checks (act as if it was from 647 * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1). Be cautious. 648 * 649 * For SIIT end node behavior, you may want to disable the check. 650 * However, you will become vulnerable to attacks using IPv4 mapped 651 * source. 652 */ 653 if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || 654 IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { 655 ip6stat.ip6s_badscope++; 656 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); 657 goto bad; 658 } 659 660 /* 661 * Tell launch routine the next header 662 */ 663 ip6stat.ip6s_delivered++; 664 in6_ifstat_inc(deliverifp, ifs6_in_deliver); 665 nest = 0; 666 while (nxt != IPPROTO_DONE) { 667 if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) { 668 ip6stat.ip6s_toomanyhdr++; 669 goto bad; 670 } 671 672 /* 673 * protection against faulty packet - there should be 674 * more sanity checks in header chain processing. 675 */ 676 if (m->m_pkthdr.len < off) { 677 ip6stat.ip6s_tooshort++; 678 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); 679 goto bad; 680 } 681 682 nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt); 683 } 684 return; 685 bad: 686 m_freem(m); 687} 688 689/* 690 * Hop-by-Hop options header processing. If a valid jumbo payload option is 691 * included, the real payload length will be stored in plenp. 692 */ 693static int 694ip6_hopopts_input(plenp, rtalertp, mp, offp) 695 u_int32_t *plenp; 696 u_int32_t *rtalertp; /* XXX: should be stored more smart way */ 697 struct mbuf **mp; 698 int *offp; 699{ 700 register struct mbuf *m = *mp; 701 int off = *offp, hbhlen; 702 struct ip6_hbh *hbh; 703 u_int8_t *opt; 704 705 /* validation of the length of the header */ 706#ifndef PULLDOWN_TEST 707 IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1); 708 hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off); 709 hbhlen = (hbh->ip6h_len + 1) << 3; 710 711 IP6_EXTHDR_CHECK(m, off, hbhlen, -1); 712 hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off); 713#else 714 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, 715 sizeof(struct ip6_hdr), sizeof(struct ip6_hbh)); 716 if (hbh == NULL) { 717 ip6stat.ip6s_tooshort++; 718 return -1; 719 } 720 hbhlen = (hbh->ip6h_len + 1) << 3; 721 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), 722 hbhlen); 723 if (hbh == NULL) { 724 ip6stat.ip6s_tooshort++; 725 return -1; 726 } 727#endif 728 off += hbhlen; 729 hbhlen -= sizeof(struct ip6_hbh); 730 opt = (u_int8_t *)hbh + sizeof(struct ip6_hbh); 731 732 if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh), 733 hbhlen, rtalertp, plenp) < 0) 734 return(-1); 735 736 *offp = off; 737 *mp = m; 738 return(0); 739} 740 741/* 742 * Search header for all Hop-by-hop options and process each option. 743 * This function is separate from ip6_hopopts_input() in order to 744 * handle a case where the sending node itself process its hop-by-hop 745 * options header. In such a case, the function is called from ip6_output(). 746 */ 747int 748ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp) 749 struct mbuf *m; 750 u_int8_t *opthead; 751 int hbhlen; 752 u_int32_t *rtalertp; 753 u_int32_t *plenp; 754{ 755 struct ip6_hdr *ip6; 756 int optlen = 0; 757 u_int8_t *opt = opthead; 758 u_int16_t rtalert_val; 759 u_int32_t jumboplen; 760 761 for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) { 762 switch(*opt) { 763 case IP6OPT_PAD1: 764 optlen = 1; 765 break; 766 case IP6OPT_PADN: 767 if (hbhlen < IP6OPT_MINLEN) { 768 ip6stat.ip6s_toosmall++; 769 goto bad; 770 } 771 optlen = *(opt + 1) + 2; 772 break; 773 case IP6OPT_RTALERT: 774 /* XXX may need check for alignment */ 775 if (hbhlen < IP6OPT_RTALERT_LEN) { 776 ip6stat.ip6s_toosmall++; 777 goto bad; 778 } 779 if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) 780 /* XXX: should we discard the packet? */ 781 log(LOG_ERR, "length of router alert opt is inconsitent(%d)", 782 *(opt + 1)); 783 optlen = IP6OPT_RTALERT_LEN; 784 bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2); 785 *rtalertp = ntohs(rtalert_val); 786 break; 787 case IP6OPT_JUMBO: 788 /* XXX may need check for alignment */ 789 if (hbhlen < IP6OPT_JUMBO_LEN) { 790 ip6stat.ip6s_toosmall++; 791 goto bad; 792 } 793 if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) 794 /* XXX: should we discard the packet? */ 795 log(LOG_ERR, "length of jumbopayload opt " 796 "is inconsistent(%d)", 797 *(opt + 1)); 798 optlen = IP6OPT_JUMBO_LEN; 799 800 /* 801 * IPv6 packets that have non 0 payload length 802 * must not contain a jumbo paylod option. 803 */ 804 ip6 = mtod(m, struct ip6_hdr *); 805 if (ip6->ip6_plen) { 806 ip6stat.ip6s_badoptions++; 807 icmp6_error(m, ICMP6_PARAM_PROB, 808 ICMP6_PARAMPROB_HEADER, 809 sizeof(struct ip6_hdr) + 810 sizeof(struct ip6_hbh) + 811 opt - opthead); 812 return(-1); 813 } 814 815 /* 816 * We may see jumbolen in unaligned location, so 817 * we'd need to perform bcopy(). 818 */ 819 bcopy(opt + 2, &jumboplen, sizeof(jumboplen)); 820 jumboplen = (u_int32_t)htonl(jumboplen); 821 822#if 1 823 /* 824 * if there are multiple jumbo payload options, 825 * *plenp will be non-zero and the packet will be 826 * rejected. 827 * the behavior may need some debate in ipngwg - 828 * multiple options does not make sense, however, 829 * there's no explicit mention in specification. 830 */ 831 if (*plenp != 0) { 832 ip6stat.ip6s_badoptions++; 833 icmp6_error(m, ICMP6_PARAM_PROB, 834 ICMP6_PARAMPROB_HEADER, 835 sizeof(struct ip6_hdr) + 836 sizeof(struct ip6_hbh) + 837 opt + 2 - opthead); 838 return(-1); 839 } 840#endif 841 842 /* 843 * jumbo payload length must be larger than 65535. 844 */ 845 if (jumboplen <= IPV6_MAXPACKET) { 846 ip6stat.ip6s_badoptions++; 847 icmp6_error(m, ICMP6_PARAM_PROB, 848 ICMP6_PARAMPROB_HEADER, 849 sizeof(struct ip6_hdr) + 850 sizeof(struct ip6_hbh) + 851 opt + 2 - opthead); 852 return(-1); 853 } 854 *plenp = jumboplen; 855 856 break; 857 default: /* unknown option */ 858 if (hbhlen < IP6OPT_MINLEN) { 859 ip6stat.ip6s_toosmall++; 860 goto bad; 861 } 862 if ((optlen = ip6_unknown_opt(opt, m, 863 sizeof(struct ip6_hdr) + 864 sizeof(struct ip6_hbh) + 865 opt - opthead)) == -1) 866 return(-1); 867 optlen += 2; 868 break; 869 } 870 } 871 872 return(0); 873 874 bad: 875 m_freem(m); 876 return(-1); 877} 878 879/* 880 * Unknown option processing. 881 * The third argument `off' is the offset from the IPv6 header to the option, 882 * which is necessary if the IPv6 header the and option header and IPv6 header 883 * is not continuous in order to return an ICMPv6 error. 884 */ 885int 886ip6_unknown_opt(optp, m, off) 887 u_int8_t *optp; 888 struct mbuf *m; 889 int off; 890{ 891 struct ip6_hdr *ip6; 892 893 switch(IP6OPT_TYPE(*optp)) { 894 case IP6OPT_TYPE_SKIP: /* ignore the option */ 895 return((int)*(optp + 1)); 896 case IP6OPT_TYPE_DISCARD: /* silently discard */ 897 m_freem(m); 898 return(-1); 899 case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */ 900 ip6stat.ip6s_badoptions++; 901 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off); 902 return(-1); 903 case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */ 904 ip6stat.ip6s_badoptions++; 905 ip6 = mtod(m, struct ip6_hdr *); 906 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || 907 (m->m_flags & (M_BCAST|M_MCAST))) 908 m_freem(m); 909 else 910 icmp6_error(m, ICMP6_PARAM_PROB, 911 ICMP6_PARAMPROB_OPTION, off); 912 return(-1); 913 } 914 915 m_freem(m); /* XXX: NOTREACHED */ 916 return(-1); 917} 918 919/* 920 * Create the "control" list for this pcb. 921 * 922 * The routine will be called from upper layer handlers like tcp6_input(). 923 * Thus the routine assumes that the caller (tcp6_input) have already 924 * called IP6_EXTHDR_CHECK() and all the extension headers are located in the 925 * very first mbuf on the mbuf chain. 926 * We may want to add some infinite loop prevention or sanity checks for safety. 927 * (This applies only when you are using KAME mbuf chain restriction, i.e. 928 * you are using IP6_EXTHDR_CHECK() not m_pulldown()) 929 */ 930void 931ip6_savecontrol(in6p, mp, ip6, m) 932 register struct in6pcb *in6p; 933 register struct mbuf **mp; 934 register struct ip6_hdr *ip6; 935 register struct mbuf *m; 936{ 937 struct proc *p = curproc; /* XXX */ 938 int privileged; 939 940 privileged = 0; 941 if (p && !suser(p)) 942 privileged++; 943 944 if (in6p->in6p_socket->so_options & SO_TIMESTAMP) { 945 struct timeval tv; 946 947 microtime(&tv); 948 *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv), 949 SCM_TIMESTAMP, SOL_SOCKET); 950 if (*mp) 951 mp = &(*mp)->m_next; 952 } 953 954#ifdef noyet 955 /* options were tossed above */ 956 if (in6p->in6p_flags & IN6P_RECVOPTS) 957 /* broken */ 958 /* ip6_srcroute doesn't do what we want here, need to fix */ 959 if (in6p->in6p_flags & IPV6P_RECVRETOPTS) 960 /* broken */ 961#endif 962 963 /* RFC 2292 sec. 5 */ 964 if (in6p->in6p_flags & IN6P_PKTINFO) { 965 struct in6_pktinfo pi6; 966 bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr)); 967 if (IN6_IS_SCOPE_LINKLOCAL(&pi6.ipi6_addr)) 968 pi6.ipi6_addr.s6_addr16[1] = 0; 969 pi6.ipi6_ifindex = (m && m->m_pkthdr.rcvif) 970 ? m->m_pkthdr.rcvif->if_index 971 : 0; 972 *mp = sbcreatecontrol((caddr_t) &pi6, 973 sizeof(struct in6_pktinfo), IPV6_PKTINFO, 974 IPPROTO_IPV6); 975 if (*mp) 976 mp = &(*mp)->m_next; 977 } 978 if (in6p->in6p_flags & IN6P_HOPLIMIT) { 979 int hlim = ip6->ip6_hlim & 0xff; 980 *mp = sbcreatecontrol((caddr_t) &hlim, 981 sizeof(int), IPV6_HOPLIMIT, IPPROTO_IPV6); 982 if (*mp) 983 mp = &(*mp)->m_next; 984 } 985 /* IN6P_NEXTHOP - for outgoing packet only */ 986 987 /* 988 * IPV6_HOPOPTS socket option. We require super-user privilege 989 * for the option, but it might be too strict, since there might 990 * be some hop-by-hop options which can be returned to normal user. 991 * See RFC 2292 section 6. 992 */ 993 if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) { 994 /* 995 * Check if a hop-by-hop options header is contatined in the 996 * received packet, and if so, store the options as ancillary 997 * data. Note that a hop-by-hop options header must be 998 * just after the IPv6 header, which fact is assured through 999 * the IPv6 input processing. 1000 */ 1001 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 1002 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) { 1003 struct ip6_hbh *hbh; 1004 int hbhlen; 1005 1006#ifndef PULLDOWN_TEST 1007 hbh = (struct ip6_hbh *)(ip6 + 1); 1008 hbhlen = (hbh->ip6h_len + 1) << 3; 1009#else 1010 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, 1011 sizeof(struct ip6_hdr), sizeof(struct ip6_hbh)); 1012 if (hbh == NULL) { 1013 ip6stat.ip6s_tooshort++; 1014 return; 1015 } 1016 hbhlen = (hbh->ip6h_len + 1) << 3; 1017 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, 1018 sizeof(struct ip6_hdr), hbhlen); 1019 if (hbh == NULL) { 1020 ip6stat.ip6s_tooshort++; 1021 return; 1022 } 1023#endif 1024 1025 /* 1026 * XXX: We copy whole the header even if a jumbo 1027 * payload option is included, which option is to 1028 * be removed before returning in the RFC 2292. 1029 * But it's too painful operation... 1030 */ 1031 *mp = sbcreatecontrol((caddr_t)hbh, hbhlen, 1032 IPV6_HOPOPTS, IPPROTO_IPV6); 1033 if (*mp) 1034 mp = &(*mp)->m_next; 1035 } 1036 } 1037 1038 /* IPV6_DSTOPTS and IPV6_RTHDR socket options */ 1039 if (in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDR)) { 1040 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 1041 int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);; 1042 1043 /* 1044 * Search for destination options headers or routing 1045 * header(s) through the header chain, and stores each 1046 * header as ancillary data. 1047 * Note that the order of the headers remains in 1048 * the chain of ancillary data. 1049 */ 1050 while(1) { /* is explicit loop prevention necessary? */ 1051 struct ip6_ext *ip6e; 1052 int elen; 1053 1054#ifndef PULLDOWN_TEST 1055 ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off); 1056 if (nxt == IPPROTO_AH) 1057 elen = (ip6e->ip6e_len + 2) << 2; 1058 else 1059 elen = (ip6e->ip6e_len + 1) << 3; 1060#else 1061 IP6_EXTHDR_GET(ip6e, struct ip6_ext *, m, off, 1062 sizeof(struct ip6_ext)); 1063 if (ip6e == NULL) { 1064 ip6stat.ip6s_tooshort++; 1065 return; 1066 } 1067 if (nxt == IPPROTO_AH) 1068 elen = (ip6e->ip6e_len + 2) << 2; 1069 else 1070 elen = (ip6e->ip6e_len + 1) << 3; 1071 IP6_EXTHDR_GET(ip6e, struct ip6_ext *, m, off, elen); 1072 if (ip6e == NULL) { 1073 ip6stat.ip6s_tooshort++; 1074 return; 1075 } 1076#endif 1077 1078 switch(nxt) { 1079 case IPPROTO_DSTOPTS: 1080 if (!in6p->in6p_flags & IN6P_DSTOPTS) 1081 break; 1082 1083 /* 1084 * We also require super-user privilege for 1085 * the option. 1086 * See the comments on IN6_HOPOPTS. 1087 */ 1088 if (!privileged) 1089 break; 1090 1091 *mp = sbcreatecontrol((caddr_t)ip6e, elen, 1092 IPV6_DSTOPTS, 1093 IPPROTO_IPV6); 1094 if (*mp) 1095 mp = &(*mp)->m_next; 1096 break; 1097 1098 case IPPROTO_ROUTING: 1099 if (!in6p->in6p_flags & IN6P_RTHDR) 1100 break; 1101 1102 *mp = sbcreatecontrol((caddr_t)ip6e, elen, 1103 IPV6_RTHDR, 1104 IPPROTO_IPV6); 1105 if (*mp) 1106 mp = &(*mp)->m_next; 1107 break; 1108 1109 case IPPROTO_UDP: 1110 case IPPROTO_TCP: 1111 case IPPROTO_ICMPV6: 1112 default: 1113 /* 1114 * stop search if we encounter an upper 1115 * layer protocol headers. 1116 */ 1117 goto loopend; 1118 1119 case IPPROTO_HOPOPTS: 1120 case IPPROTO_AH: /* is it possible? */ 1121 break; 1122 } 1123 1124 /* proceed with the next header. */ 1125 off += elen; 1126 nxt = ip6e->ip6e_nxt; 1127 } 1128 loopend: 1129 } 1130 if ((in6p->in6p_flags & IN6P_HOPOPTS) && privileged) { 1131 /* to be done */ 1132 } 1133 if ((in6p->in6p_flags & IN6P_DSTOPTS) && privileged) { 1134 /* to be done */ 1135 } 1136 /* IN6P_RTHDR - to be done */ 1137 1138} 1139 1140/* 1141 * Get pointer to the previous header followed by the header 1142 * currently processed. 1143 * XXX: This function supposes that 1144 * M includes all headers, 1145 * the next header field and the header length field of each header 1146 * are valid, and 1147 * the sum of each header length equals to OFF. 1148 * Because of these assumptions, this function must be called very 1149 * carefully. Moreover, it will not be used in the near future when 1150 * we develop `neater' mechanism to process extension headers. 1151 */ 1152char * 1153ip6_get_prevhdr(m, off) 1154 struct mbuf *m; 1155 int off; 1156{ 1157 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 1158 1159 if (off == sizeof(struct ip6_hdr)) 1160 return(&ip6->ip6_nxt); 1161 else { 1162 int len, nxt; 1163 struct ip6_ext *ip6e = NULL; 1164 1165 nxt = ip6->ip6_nxt; 1166 len = sizeof(struct ip6_hdr); 1167 while (len < off) { 1168 ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len); 1169 1170 switch(nxt) { 1171 case IPPROTO_FRAGMENT: 1172 len += sizeof(struct ip6_frag); 1173 break; 1174 case IPPROTO_AH: 1175 len += (ip6e->ip6e_len + 2) << 2; 1176 break; 1177 default: 1178 len += (ip6e->ip6e_len + 1) << 3; 1179 break; 1180 } 1181 nxt = ip6e->ip6e_nxt; 1182 } 1183 if (ip6e) 1184 return(&ip6e->ip6e_nxt); 1185 else 1186 return NULL; 1187 } 1188} 1189 1190/* 1191 * get next header offset. m will be retained. 1192 */ 1193int 1194ip6_nexthdr(m, off, proto, nxtp) 1195 struct mbuf *m; 1196 int off; 1197 int proto; 1198 int *nxtp; 1199{ 1200 struct ip6_hdr ip6; 1201 struct ip6_ext ip6e; 1202 struct ip6_frag fh; 1203 1204 /* just in case */ 1205 if (m == NULL) 1206 panic("ip6_nexthdr: m == NULL"); 1207 if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len < off) 1208 return -1; 1209 1210 switch (proto) { 1211 case IPPROTO_IPV6: 1212 if (m->m_pkthdr.len < off + sizeof(ip6)) 1213 return -1; 1214 m_copydata(m, off, sizeof(ip6), (caddr_t)&ip6); 1215 if (nxtp) 1216 *nxtp = ip6.ip6_nxt; 1217 off += sizeof(ip6); 1218 return off; 1219 1220 case IPPROTO_FRAGMENT: 1221 /* 1222 * terminate parsing if it is not the first fragment, 1223 * it does not make sense to parse through it. 1224 */ 1225 if (m->m_pkthdr.len < off + sizeof(fh)) 1226 return -1; 1227 m_copydata(m, off, sizeof(fh), (caddr_t)&fh); 1228 if ((ntohs(fh.ip6f_offlg) & IP6F_OFF_MASK) != 0) 1229 return -1; 1230 if (nxtp) 1231 *nxtp = fh.ip6f_nxt; 1232 off += sizeof(struct ip6_frag); 1233 return off; 1234 1235 case IPPROTO_AH: 1236 if (m->m_pkthdr.len < off + sizeof(ip6e)) 1237 return -1; 1238 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e); 1239 if (nxtp) 1240 *nxtp = ip6e.ip6e_nxt; 1241 off += (ip6e.ip6e_len + 2) << 2; 1242 return off; 1243 1244 case IPPROTO_HOPOPTS: 1245 case IPPROTO_ROUTING: 1246 case IPPROTO_DSTOPTS: 1247 if (m->m_pkthdr.len < off + sizeof(ip6e)) 1248 return -1; 1249 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e); 1250 if (nxtp) 1251 *nxtp = ip6e.ip6e_nxt; 1252 off += (ip6e.ip6e_len + 1) << 3; 1253 return off; 1254 1255 case IPPROTO_NONE: 1256 case IPPROTO_ESP: 1257 case IPPROTO_IPCOMP: 1258 /* give up */ 1259 return -1; 1260 1261 default: 1262 return -1; 1263 } 1264 1265 return -1; 1266} 1267 1268/* 1269 * get offset for the last header in the chain. m will be kept untainted. 1270 */ 1271int 1272ip6_lasthdr(m, off, proto, nxtp) 1273 struct mbuf *m; 1274 int off; 1275 int proto; 1276 int *nxtp; 1277{ 1278 int newoff; 1279 int nxt; 1280 1281 if (!nxtp) { 1282 nxt = -1; 1283 nxtp = &nxt; 1284 } 1285 while (1) { 1286 newoff = ip6_nexthdr(m, off, proto, nxtp); 1287 if (newoff < 0) 1288 return off; 1289 else if (newoff < off) 1290 return -1; /* invalid */ 1291 else if (newoff == off) 1292 return newoff; 1293 1294 off = newoff; 1295 proto = *nxtp; 1296 } 1297} 1298 1299/* 1300 * System control for IP6 1301 */ 1302 1303u_char inet6ctlerrmap[PRC_NCMDS] = { 1304 0, 0, 0, 0, 1305 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, 1306 EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, 1307 EMSGSIZE, EHOSTUNREACH, 0, 0, 1308 0, 0, 0, 0, 1309 ENOPROTOOPT 1310}; 1311