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