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