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