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