1139826Simp/*- 253541Sshin * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 353541Sshin * All rights reserved. 453541Sshin * 553541Sshin * Redistribution and use in source and binary forms, with or without 653541Sshin * modification, are permitted provided that the following conditions 753541Sshin * are met: 853541Sshin * 1. Redistributions of source code must retain the above copyright 953541Sshin * notice, this list of conditions and the following disclaimer. 1053541Sshin * 2. Redistributions in binary form must reproduce the above copyright 1153541Sshin * notice, this list of conditions and the following disclaimer in the 1253541Sshin * documentation and/or other materials provided with the distribution. 1353541Sshin * 3. Neither the name of the project nor the names of its contributors 1453541Sshin * may be used to endorse or promote products derived from this software 1553541Sshin * without specific prior written permission. 1653541Sshin * 1753541Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 1853541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1953541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2053541Sshin * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2153541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2253541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2353541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2453541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2553541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2653541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2753541Sshin * SUCH DAMAGE. 28174510Sobrien * 29174510Sobrien * $KAME: ip6_input.c,v 1.259 2002/01/21 04:58:09 jinmei Exp $ 3053541Sshin */ 3153541Sshin 32139826Simp/*- 3353541Sshin * Copyright (c) 1982, 1986, 1988, 1993 3453541Sshin * The Regents of the University of California. All rights reserved. 3553541Sshin * 3653541Sshin * Redistribution and use in source and binary forms, with or without 3753541Sshin * modification, are permitted provided that the following conditions 3853541Sshin * are met: 3953541Sshin * 1. Redistributions of source code must retain the above copyright 4053541Sshin * notice, this list of conditions and the following disclaimer. 4153541Sshin * 2. Redistributions in binary form must reproduce the above copyright 4253541Sshin * notice, this list of conditions and the following disclaimer in the 4353541Sshin * documentation and/or other materials provided with the distribution. 4453541Sshin * 4. Neither the name of the University nor the names of its contributors 4553541Sshin * may be used to endorse or promote products derived from this software 4653541Sshin * without specific prior written permission. 4753541Sshin * 4853541Sshin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 4953541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5053541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5153541Sshin * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 5253541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 5353541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 5453541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5553541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 5653541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5753541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5853541Sshin * SUCH DAMAGE. 5953541Sshin * 6053541Sshin * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 6153541Sshin */ 6253541Sshin 63174510Sobrien#include <sys/cdefs.h> 64174510Sobrien__FBSDID("$FreeBSD: stable/10/sys/netinet6/ip6_input.c 329158 2018-02-12 13:52:58Z ae $"); 65174510Sobrien 6662587Sitojun#include "opt_inet.h" 6762587Sitojun#include "opt_inet6.h" 68225044Sbz#include "opt_ipfw.h" 6955009Sshin#include "opt_ipsec.h" 70254889Smarkj#include "opt_kdtrace.h" 71207828Skmacy#include "opt_route.h" 7255009Sshin 7353541Sshin#include <sys/param.h> 7453541Sshin#include <sys/systm.h> 7578064Sume#include <sys/malloc.h> 7653541Sshin#include <sys/mbuf.h> 7783366Sjulian#include <sys/proc.h> 7853541Sshin#include <sys/domain.h> 7953541Sshin#include <sys/protosw.h> 80254889Smarkj#include <sys/sdt.h> 8153541Sshin#include <sys/socket.h> 8253541Sshin#include <sys/socketvar.h> 8353541Sshin#include <sys/errno.h> 8453541Sshin#include <sys/time.h> 8553541Sshin#include <sys/kernel.h> 8653541Sshin#include <sys/syslog.h> 8753541Sshin 8853541Sshin#include <net/if.h> 8953541Sshin#include <net/if_types.h> 9053541Sshin#include <net/if_dl.h> 9153541Sshin#include <net/route.h> 9253541Sshin#include <net/netisr.h> 9364060Sdarrenr#include <net/pfil.h> 94185571Sbz#include <net/vnet.h> 9553541Sshin 9653541Sshin#include <netinet/in.h> 97254889Smarkj#include <netinet/in_kdtrace.h> 98225044Sbz#include <netinet/ip_var.h> 9953541Sshin#include <netinet/in_systm.h> 100186119Sqingli#include <net/if_llatbl.h> 10162587Sitojun#ifdef INET 10253541Sshin#include <netinet/ip.h> 10353541Sshin#include <netinet/ip_icmp.h> 10495023Ssuz#endif /* INET */ 10562587Sitojun#include <netinet/ip6.h> 10653541Sshin#include <netinet6/in6_var.h> 10753541Sshin#include <netinet6/ip6_var.h> 10862587Sitojun#include <netinet/in_pcb.h> 10962587Sitojun#include <netinet/icmp6.h> 110121161Sume#include <netinet6/scope6_var.h> 11153541Sshin#include <netinet6/in6_ifattach.h> 11253541Sshin#include <netinet6/nd6.h> 11353541Sshin 114171167Sgnn#ifdef IPSEC 115105199Ssam#include <netipsec/ipsec.h> 116171133Sgnn#include <netinet6/ip6_ipsec.h> 117105199Ssam#include <netipsec/ipsec6.h> 118171167Sgnn#endif /* IPSEC */ 119105199Ssam 12053541Sshin#include <netinet6/ip6protosw.h> 12153541Sshin 12262587Sitojunextern struct domain inet6domain; 12353541Sshin 12462587Sitojunu_char ip6_protox[IPPROTO_MAX]; 125207369SbzVNET_DEFINE(struct in6_ifaddrhead, in6_ifaddrhead); 126244272SaeVNET_DEFINE(struct in6_ifaddrlisthead *, in6_ifaddrhashtbl); 127244272SaeVNET_DEFINE(u_long, in6_ifaddrhmask); 128185088Szec 129193219Srwatsonstatic struct netisr_handler ip6_nh = { 130193219Srwatson .nh_name = "ip6", 131193219Srwatson .nh_handler = ip6_input, 132193219Srwatson .nh_proto = NETISR_IPV6, 133193219Srwatson .nh_policy = NETISR_POLICY_FLOW, 134193219Srwatson}; 135193219Srwatson 136195699SrwatsonVNET_DECLARE(struct callout, in6_tmpaddrtimer_ch); 137195727Srwatson#define V_in6_tmpaddrtimer_ch VNET(in6_tmpaddrtimer_ch) 13878064Sume 139207369SbzVNET_DEFINE(struct pfil_head, inet6_pfil_hook); 140207369Sbz 141253085SaeVNET_PCPUSTAT_DEFINE(struct ip6stat, ip6stat); 142253085SaeVNET_PCPUSTAT_SYSINIT(ip6stat); 143253085Sae#ifdef VIMAGE 144253085SaeVNET_PCPUSTAT_SYSUNINIT(ip6stat); 145253085Sae#endif /* VIMAGE */ 146207369Sbz 147194971Srwatsonstruct rwlock in6_ifaddr_lock; 148194971SrwatsonRW_SYSINIT(in6_ifaddr_lock, &in6_ifaddr_lock, "in6_ifaddr_lock"); 149194971Srwatson 150175162Sobrienstatic void ip6_init2(void *); 151175162Sobrienstatic struct ip6aux *ip6_setdstifaddr(struct mbuf *, struct in6_ifaddr *); 152235956Sbzstatic struct ip6aux *ip6_addaux(struct mbuf *); 153235956Sbzstatic struct ip6aux *ip6_findaux(struct mbuf *m); 154235956Sbzstatic void ip6_delaux (struct mbuf *); 155175162Sobrienstatic int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *); 15662587Sitojun#ifdef PULLDOWN_TEST 157175162Sobrienstatic struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int); 15853541Sshin#endif 15953541Sshin 16053541Sshin/* 16153541Sshin * IP6 initialization: fill in IP6 protocol switch table. 16253541Sshin * All protocols not implemented in kernel go to raw IP6 protocol handler. 16353541Sshin */ 16453541Sshinvoid 165171259Sdelphijip6_init(void) 16653541Sshin{ 16778064Sume struct ip6protosw *pr; 16878064Sume int i; 16953541Sshin 170185895Szec TUNABLE_INT_FETCH("net.inet6.ip6.auto_linklocal", 171185895Szec &V_ip6_auto_linklocal); 172232379Shrs TUNABLE_INT_FETCH("net.inet6.ip6.accept_rtadv", &V_ip6_accept_rtadv); 173232379Shrs TUNABLE_INT_FETCH("net.inet6.ip6.no_radr", &V_ip6_no_radr); 174185088Szec 175207369Sbz TAILQ_INIT(&V_in6_ifaddrhead); 176244272Sae V_in6_ifaddrhashtbl = hashinit(IN6ADDR_NHASH, M_IFADDR, 177244272Sae &V_in6_ifaddrhmask); 178185088Szec 179207369Sbz /* Initialize packet filter hooks. */ 180207369Sbz V_inet6_pfil_hook.ph_type = PFIL_TYPE_AF; 181207369Sbz V_inet6_pfil_hook.ph_af = AF_INET6; 182207369Sbz if ((i = pfil_head_register(&V_inet6_pfil_hook)) != 0) 183207369Sbz printf("%s: WARNING: unable to register pfil hook, " 184207369Sbz "error %d\n", __func__, i); 185185088Szec 186190787Szec scope6_init(); 187190787Szec addrsel_policy_init(); 188190787Szec nd6_init(); 189190787Szec frag6_init(); 190190787Szec 191190787Szec V_ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR; 192190787Szec 193190787Szec /* Skip global initialization stuff for non-default instances. */ 194190787Szec if (!IS_DEFAULT_VNET(curvnet)) 195190787Szec return; 196190787Szec 19778064Sume#ifdef DIAGNOSTIC 19878064Sume if (sizeof(struct protosw) != sizeof(struct ip6protosw)) 19978064Sume panic("sizeof(protosw) != sizeof(ip6protosw)"); 20078064Sume#endif 20153541Sshin pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW); 202191433Sbz if (pr == NULL) 20353541Sshin panic("ip6_init"); 204136689Sandre 205186393Sbz /* Initialize the entire ip6_protox[] array to IPPROTO_RAW. */ 20653541Sshin for (i = 0; i < IPPROTO_MAX; i++) 20753541Sshin ip6_protox[i] = pr - inet6sw; 208136689Sandre /* 209136689Sandre * Cycle through IP protocols and put them into the appropriate place 210136689Sandre * in ip6_protox[]. 211136689Sandre */ 21253541Sshin for (pr = (struct ip6protosw *)inet6domain.dom_protosw; 21353541Sshin pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++) 21453541Sshin if (pr->pr_domain->dom_family == PF_INET6 && 215136689Sandre pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) { 216136689Sandre /* Be careful to only index valid IP protocols. */ 217143675Ssam if (pr->pr_protocol < IPPROTO_MAX) 218136689Sandre ip6_protox[pr->pr_protocol] = pr - inet6sw; 219136689Sandre } 220134383Sandre 221193219Srwatson netisr_register(&ip6_nh); 22253541Sshin} 22353541Sshin 224212155Sbz/* 225212155Sbz * The protocol to be inserted into ip6_protox[] must be already registered 226212155Sbz * in inet6sw[], either statically or through pf_proto_register(). 227212155Sbz */ 228212155Sbzint 229212155Sbzip6proto_register(short ip6proto) 230212155Sbz{ 231212155Sbz struct ip6protosw *pr; 232212155Sbz 233212155Sbz /* Sanity checks. */ 234212155Sbz if (ip6proto <= 0 || ip6proto >= IPPROTO_MAX) 235212155Sbz return (EPROTONOSUPPORT); 236212155Sbz 237212155Sbz /* 238212155Sbz * The protocol slot must not be occupied by another protocol 239212155Sbz * already. An index pointing to IPPROTO_RAW is unused. 240212155Sbz */ 241212155Sbz pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW); 242212155Sbz if (pr == NULL) 243212155Sbz return (EPFNOSUPPORT); 244212155Sbz if (ip6_protox[ip6proto] != pr - inet6sw) /* IPPROTO_RAW */ 245212155Sbz return (EEXIST); 246212155Sbz 247212155Sbz /* 248212155Sbz * Find the protocol position in inet6sw[] and set the index. 249212155Sbz */ 250212155Sbz for (pr = (struct ip6protosw *)inet6domain.dom_protosw; 251212155Sbz pr < (struct ip6protosw *)inet6domain.dom_protoswNPROTOSW; pr++) { 252212155Sbz if (pr->pr_domain->dom_family == PF_INET6 && 253212155Sbz pr->pr_protocol && pr->pr_protocol == ip6proto) { 254212155Sbz ip6_protox[pr->pr_protocol] = pr - inet6sw; 255212155Sbz return (0); 256212155Sbz } 257212155Sbz } 258212155Sbz return (EPROTONOSUPPORT); 259212155Sbz} 260212155Sbz 261212155Sbzint 262212155Sbzip6proto_unregister(short ip6proto) 263212155Sbz{ 264212155Sbz struct ip6protosw *pr; 265212155Sbz 266212155Sbz /* Sanity checks. */ 267212155Sbz if (ip6proto <= 0 || ip6proto >= IPPROTO_MAX) 268212155Sbz return (EPROTONOSUPPORT); 269212155Sbz 270212155Sbz /* Check if the protocol was indeed registered. */ 271212155Sbz pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW); 272212155Sbz if (pr == NULL) 273212155Sbz return (EPFNOSUPPORT); 274212155Sbz if (ip6_protox[ip6proto] == pr - inet6sw) /* IPPROTO_RAW */ 275212155Sbz return (ENOENT); 276212155Sbz 277212155Sbz /* Reset the protocol slot to IPPROTO_RAW. */ 278212155Sbz ip6_protox[ip6proto] = pr - inet6sw; 279212155Sbz return (0); 280212155Sbz} 281212155Sbz 282193731Szec#ifdef VIMAGE 283193731Szecvoid 284193731Szecip6_destroy() 285193731Szec{ 286255523Strociny int i; 287193731Szec 288255523Strociny if ((i = pfil_head_unregister(&V_inet6_pfil_hook)) != 0) 289255523Strociny printf("%s: WARNING: unable to unregister pfil hook, " 290255523Strociny "error %d\n", __func__, i); 291244272Sae hashdestroy(V_in6_ifaddrhashtbl, M_IFADDR, V_in6_ifaddrhmask); 292193731Szec nd6_destroy(); 293193731Szec callout_drain(&V_in6_tmpaddrtimer_ch); 294193731Szec} 295193731Szec#endif 296193731Szec 297190787Szecstatic int 298190787Szecip6_init2_vnet(const void *unused __unused) 29953541Sshin{ 30053541Sshin 30153541Sshin /* nd6_timer_init */ 302181803Sbz callout_init(&V_nd6_timer_ch, 0); 303191688Szec callout_reset(&V_nd6_timer_ch, hz, nd6_timer, curvnet); 30478064Sume 30578064Sume /* timer for regeneranation of temporary addresses randomize ID */ 306181803Sbz callout_init(&V_in6_tmpaddrtimer_ch, 0); 307181803Sbz callout_reset(&V_in6_tmpaddrtimer_ch, 308181803Sbz (V_ip6_temp_preferred_lifetime - V_ip6_desync_factor - 309181803Sbz V_ip6_temp_regen_advance) * hz, 310191688Szec in6_tmpaddrtimer, curvnet); 311190787Szec 312190787Szec return (0); 31353541Sshin} 31453541Sshin 315190787Szecstatic void 316190787Szecip6_init2(void *dummy) 317190787Szec{ 318190787Szec 319190787Szec ip6_init2_vnet(NULL); 320190787Szec} 321190787Szec 32253541Sshin/* cheat */ 32355009Sshin/* This must be after route_init(), which is now SI_ORDER_THIRD */ 32455009SshinSYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL); 32553541Sshin 326235962Sbzstatic int 327235962Sbzip6_input_hbh(struct mbuf *m, uint32_t *plen, uint32_t *rtalert, int *off, 328235962Sbz int *nxt, int *ours) 329235962Sbz{ 330235962Sbz struct ip6_hdr *ip6; 331235962Sbz struct ip6_hbh *hbh; 332235962Sbz 333235962Sbz if (ip6_hopopts_input(plen, rtalert, &m, off)) { 334235962Sbz#if 0 /*touches NULL pointer*/ 335235962Sbz in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); 336235962Sbz#endif 337235962Sbz goto out; /* m have already been freed */ 338235962Sbz } 339235962Sbz 340235962Sbz /* adjust pointer */ 341235962Sbz ip6 = mtod(m, struct ip6_hdr *); 342235962Sbz 343235962Sbz /* 344235962Sbz * if the payload length field is 0 and the next header field 345235962Sbz * indicates Hop-by-Hop Options header, then a Jumbo Payload 346235962Sbz * option MUST be included. 347235962Sbz */ 348235962Sbz if (ip6->ip6_plen == 0 && *plen == 0) { 349235962Sbz /* 350235962Sbz * Note that if a valid jumbo payload option is 351235962Sbz * contained, ip6_hopopts_input() must set a valid 352235962Sbz * (non-zero) payload length to the variable plen. 353235962Sbz */ 354249294Sae IP6STAT_INC(ip6s_badoptions); 355235962Sbz in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); 356235962Sbz in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); 357235962Sbz icmp6_error(m, ICMP6_PARAM_PROB, 358235962Sbz ICMP6_PARAMPROB_HEADER, 359235962Sbz (caddr_t)&ip6->ip6_plen - (caddr_t)ip6); 360235962Sbz goto out; 361235962Sbz } 362235962Sbz#ifndef PULLDOWN_TEST 363235962Sbz /* ip6_hopopts_input() ensures that mbuf is contiguous */ 364235962Sbz hbh = (struct ip6_hbh *)(ip6 + 1); 365235962Sbz#else 366235962Sbz IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), 367235962Sbz sizeof(struct ip6_hbh)); 368235962Sbz if (hbh == NULL) { 369249294Sae IP6STAT_INC(ip6s_tooshort); 370235962Sbz goto out; 371235962Sbz } 372235962Sbz#endif 373235962Sbz *nxt = hbh->ip6h_nxt; 374235962Sbz 375235962Sbz /* 376235962Sbz * If we are acting as a router and the packet contains a 377235962Sbz * router alert option, see if we know the option value. 378235962Sbz * Currently, we only support the option value for MLD, in which 379235962Sbz * case we should pass the packet to the multicast routing 380235962Sbz * daemon. 381235962Sbz */ 382235962Sbz if (*rtalert != ~0) { 383235962Sbz switch (*rtalert) { 384235962Sbz case IP6OPT_RTALERT_MLD: 385235962Sbz if (V_ip6_forwarding) 386235962Sbz *ours = 1; 387235962Sbz break; 388235962Sbz default: 389235962Sbz /* 390235962Sbz * RFC2711 requires unrecognized values must be 391235962Sbz * silently ignored. 392235962Sbz */ 393235962Sbz break; 394235962Sbz } 395235962Sbz } 396235962Sbz 397235962Sbz return (0); 398235962Sbz 399235962Sbzout: 400235962Sbz return (1); 401235962Sbz} 402235962Sbz 40353541Sshinvoid 404171259Sdelphijip6_input(struct mbuf *m) 40553541Sshin{ 40653541Sshin struct ip6_hdr *ip6; 40753541Sshin int off = sizeof(struct ip6_hdr), nest; 40853541Sshin u_int32_t plen; 40953541Sshin u_int32_t rtalert = ~0; 41053541Sshin int nxt, ours = 0; 411186119Sqingli struct ifnet *deliverifp = NULL, *ifp = NULL; 412121143Ssam struct in6_addr odst; 413187989Sbz struct route_in6 rin6; 414121143Ssam int srcrt = 0; 415186119Sqingli struct llentry *lle = NULL; 416187989Sbz struct sockaddr_in6 dst6, *dst; 417121144Ssam 418187989Sbz bzero(&rin6, sizeof(struct route_in6)); 419171167Sgnn#ifdef IPSEC 42053541Sshin /* 42153541Sshin * should the inner packet be considered authentic? 42253541Sshin * see comment in ah4_input(). 423171133Sgnn * NB: m cannot be NULL when passed to the input routine 42453541Sshin */ 42553541Sshin 426171133Sgnn m->m_flags &= ~M_AUTHIPHDR; 427171133Sgnn m->m_flags &= ~M_AUTHIPDGM; 428171133Sgnn 429171167Sgnn#endif /* IPSEC */ 430171133Sgnn 43153541Sshin /* 432121630Sume * make sure we don't have onion peering information into m_tag. 43378064Sume */ 43478064Sume ip6_delaux(m); 43578064Sume 436225044Sbz if (m->m_flags & M_FASTFWD_OURS) { 437225044Sbz /* 438225044Sbz * Firewall changed destination to local. 439225044Sbz */ 440225044Sbz m->m_flags &= ~M_FASTFWD_OURS; 441225044Sbz ours = 1; 442225044Sbz deliverifp = m->m_pkthdr.rcvif; 443225044Sbz ip6 = mtod(m, struct ip6_hdr *); 444225044Sbz goto hbhcheck; 445225044Sbz } 446225044Sbz 44778064Sume /* 44895023Ssuz * mbuf statistics 44953541Sshin */ 45053541Sshin if (m->m_flags & M_EXT) { 45153541Sshin if (m->m_next) 452249294Sae IP6STAT_INC(ip6s_mext2m); 45353541Sshin else 454249294Sae IP6STAT_INC(ip6s_mext1); 45553541Sshin } else { 45653541Sshin if (m->m_next) { 45753541Sshin if (m->m_flags & M_LOOP) { 458249294Sae IP6STAT_INC(ip6s_m2m[V_loif->if_index]); 459249544Sae } else if (m->m_pkthdr.rcvif->if_index < IP6S_M2MMAX) 460249294Sae IP6STAT_INC( 461249294Sae ip6s_m2m[m->m_pkthdr.rcvif->if_index]); 46253541Sshin else 463249294Sae IP6STAT_INC(ip6s_m2m[0]); 46453541Sshin } else 465249294Sae IP6STAT_INC(ip6s_m1); 46653541Sshin } 46753541Sshin 468151474Ssuz /* drop the packet if IPv6 operation is disabled on the IF */ 469151474Ssuz if ((ND_IFINFO(m->m_pkthdr.rcvif)->flags & ND6_IFF_IFDISABLED)) { 470151474Ssuz m_freem(m); 471151474Ssuz return; 472151474Ssuz } 473151474Ssuz 47453541Sshin in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive); 475249294Sae IP6STAT_INC(ip6s_total); 47653541Sshin 47762587Sitojun#ifndef PULLDOWN_TEST 47874336Skuriyama /* 47974336Skuriyama * L2 bridge code and some other code can return mbuf chain 48074336Skuriyama * that does not conform to KAME requirement. too bad. 48174336Skuriyama * XXX: fails to join if interface MTU > MCLBYTES. jumbogram? 48274336Skuriyama */ 48374336Skuriyama if (m && m->m_next != NULL && m->m_pkthdr.len < MCLBYTES) { 48474336Skuriyama struct mbuf *n; 48574336Skuriyama 486248320Sglebius if (m->m_pkthdr.len > MHLEN) 487248320Sglebius n = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 488248320Sglebius else 489248320Sglebius n = m_gethdr(M_NOWAIT, MT_DATA); 49095023Ssuz if (n == NULL) { 49177003Sume m_freem(m); 492120913Sume return; /* ENOBUFS */ 49377003Sume } 49474336Skuriyama 495248328Sglebius m_move_pkthdr(n, m); 496108825Ssam m_copydata(m, 0, n->m_pkthdr.len, mtod(n, caddr_t)); 497108825Ssam n->m_len = n->m_pkthdr.len; 49874336Skuriyama m_freem(m); 49974336Skuriyama m = n; 50074336Skuriyama } 501120913Sume IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /* nothing */); 50262587Sitojun#endif 50353541Sshin 50453541Sshin if (m->m_len < sizeof(struct ip6_hdr)) { 50553541Sshin struct ifnet *inifp; 50653541Sshin inifp = m->m_pkthdr.rcvif; 507120913Sume if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { 508249294Sae IP6STAT_INC(ip6s_toosmall); 50953541Sshin in6_ifstat_inc(inifp, ifs6_in_hdrerr); 51053541Sshin return; 51153541Sshin } 51253541Sshin } 51353541Sshin 51453541Sshin ip6 = mtod(m, struct ip6_hdr *); 51553541Sshin 51653541Sshin if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { 517249294Sae IP6STAT_INC(ip6s_badvers); 51853541Sshin in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr); 51953541Sshin goto bad; 52053541Sshin } 52153541Sshin 522249294Sae IP6STAT_INC(ip6s_nxthist[ip6->ip6_nxt]); 52353541Sshin 524254889Smarkj IP_PROBE(receive, NULL, NULL, ip6, m->m_pkthdr.rcvif, NULL, ip6); 525254889Smarkj 52653541Sshin /* 52778064Sume * Check against address spoofing/corruption. 52853541Sshin */ 52953541Sshin if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) || 53053541Sshin IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) { 53178064Sume /* 53278064Sume * XXX: "badscope" is not very suitable for a multicast source. 53378064Sume */ 534249294Sae IP6STAT_INC(ip6s_badscope); 53553541Sshin in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); 53653541Sshin goto bad; 53753541Sshin } 538126444Sume if (IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst) && 539126444Sume !(m->m_flags & M_LOOP)) { 540126444Sume /* 541126444Sume * In this case, the packet should come from the loopback 542126444Sume * interface. However, we cannot just check the if_flags, 543126444Sume * because ip6_mloopback() passes the "actual" interface 544126444Sume * as the outgoing/incoming interface. 545126444Sume */ 546249294Sae IP6STAT_INC(ip6s_badscope); 54778064Sume in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); 54878064Sume goto bad; 54978064Sume } 550262256Sae if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) && 551262256Sae IPV6_ADDR_MC_SCOPE(&ip6->ip6_dst) == 0) { 552262256Sae /* 553262256Sae * RFC4291 2.7: 554262256Sae * Nodes must not originate a packet to a multicast address 555262256Sae * whose scop field contains the reserved value 0; if such 556262256Sae * a packet is received, it must be silently dropped. 557262256Sae */ 558262256Sae IP6STAT_INC(ip6s_badscope); 559262256Sae in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); 560262256Sae goto bad; 561262256Sae } 562130416Smlaier#ifdef ALTQ 563130416Smlaier if (altq_input != NULL && (*altq_input)(m, AF_INET6) == 0) { 564130416Smlaier /* packet is dropped by traffic conditioner */ 565130416Smlaier return; 566130416Smlaier } 567130416Smlaier#endif 56862587Sitojun /* 56978064Sume * The following check is not documented in specs. A malicious 57078064Sume * party may be able to use IPv4 mapped addr to confuse tcp/udp stack 57178064Sume * and bypass security checks (act as if it was from 127.0.0.1 by using 572120913Sume * IPv6 src ::ffff:127.0.0.1). Be cautious. 57378064Sume * 57478064Sume * This check chokes if we are in an SIIT cloud. As none of BSDs 57578064Sume * support IPv4-less kernel compilation, we cannot support SIIT 57678064Sume * environment at all. So, it makes more sense for us to reject any 57778064Sume * malicious packets for non-SIIT environment, than try to do a 578120913Sume * partial support for SIIT environment. 57962587Sitojun */ 58078064Sume if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || 58178064Sume IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { 582249294Sae IP6STAT_INC(ip6s_badscope); 58378064Sume in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); 58478064Sume goto bad; 58578064Sume } 58662587Sitojun#if 0 58762587Sitojun /* 58862587Sitojun * Reject packets with IPv4 compatible addresses (auto tunnel). 58962587Sitojun * 59062587Sitojun * The code forbids auto tunnel relay case in RFC1933 (the check is 59162587Sitojun * stronger than RFC1933). We may want to re-enable it if mech-xx 59262587Sitojun * is revised to forbid relaying case. 59362587Sitojun */ 59462587Sitojun if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) || 59562587Sitojun IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) { 596249294Sae IP6STAT_INC(ip6s_badscope); 59762587Sitojun in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); 59862587Sitojun goto bad; 59962587Sitojun } 60062587Sitojun#endif 601222856Sbz#ifdef IPSEC 602222856Sbz /* 603222856Sbz * Bypass packet filtering for packets previously handled by IPsec. 604222856Sbz */ 605222856Sbz if (ip6_ipsec_filtertunnel(m)) 606222856Sbz goto passin; 607222856Sbz#endif /* IPSEC */ 60875246Sume 609126444Sume /* 610126508Smlaier * Run through list of hooks for input packets. 611126508Smlaier * 612126508Smlaier * NB: Beware of the destination address changing 613126508Smlaier * (e.g. by NAT rewriting). When this happens, 614126508Smlaier * tell ip6_forward to do the right thing. 615126508Smlaier */ 616126508Smlaier odst = ip6->ip6_dst; 617134383Sandre 618134383Sandre /* Jump over all PFIL processing if hooks are not active. */ 619197952Sjulian if (!PFIL_HOOKED(&V_inet6_pfil_hook)) 620134383Sandre goto passin; 621134383Sandre 622197952Sjulian if (pfil_run_hooks(&V_inet6_pfil_hook, &m, 623197952Sjulian m->m_pkthdr.rcvif, PFIL_IN, NULL)) 624126508Smlaier return; 625126508Smlaier if (m == NULL) /* consumed by filter */ 626126508Smlaier return; 627126508Smlaier ip6 = mtod(m, struct ip6_hdr *); 628126508Smlaier srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst); 629126508Smlaier 630225044Sbz if (m->m_flags & M_FASTFWD_OURS) { 631225044Sbz m->m_flags &= ~M_FASTFWD_OURS; 632225044Sbz ours = 1; 633225044Sbz deliverifp = m->m_pkthdr.rcvif; 634225044Sbz goto hbhcheck; 635225044Sbz } 636242463Sae if ((m->m_flags & M_IP6_NEXTHOP) && 637242463Sae m_tag_find(m, PACKET_TAG_IPFORWARD, NULL) != NULL) { 638225044Sbz /* 639225044Sbz * Directly ship the packet on. This allows forwarding 640225044Sbz * packets originally destined to us to some other directly 641225044Sbz * connected host. 642225044Sbz */ 643225044Sbz ip6_forward(m, 1); 644225044Sbz goto out; 645225044Sbz } 646225044Sbz 647134383Sandrepassin: 648126508Smlaier /* 649154804Sume * Disambiguate address scope zones (if there is ambiguity). 650154804Sume * We first make sure that the original source or destination address 651154804Sume * is not in our internal form for scoped addresses. Such addresses 652154804Sume * are not necessarily invalid spec-wise, but we cannot accept them due 653154804Sume * to the usage conflict. 654154804Sume * in6_setscope() then also checks and rejects the cases where src or 655154804Sume * dst are the loopback address and the receiving interface 656154804Sume * is not loopback. 657154804Sume */ 658154804Sume if (in6_clearscope(&ip6->ip6_src) || in6_clearscope(&ip6->ip6_dst)) { 659249294Sae IP6STAT_INC(ip6s_badscope); /* XXX */ 660154804Sume goto bad; 661154804Sume } 662154804Sume if (in6_setscope(&ip6->ip6_src, m->m_pkthdr.rcvif, NULL) || 663154804Sume in6_setscope(&ip6->ip6_dst, m->m_pkthdr.rcvif, NULL)) { 664249294Sae IP6STAT_INC(ip6s_badscope); 665154804Sume goto bad; 666154804Sume } 667154804Sume 668154804Sume /* 669191672Sbms * Multicast check. Assume packet is for us to avoid 670191672Sbms * prematurely taking locks. 67153541Sshin */ 67253541Sshin if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { 673191672Sbms ours = 1; 67453541Sshin in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast); 67553541Sshin deliverifp = m->m_pkthdr.rcvif; 67653541Sshin goto hbhcheck; 67753541Sshin } 67853541Sshin 67953541Sshin /* 68053541Sshin * Unicast check 68153541Sshin */ 682186119Sqingli 683186119Sqingli bzero(&dst6, sizeof(dst6)); 684186119Sqingli dst6.sin6_family = AF_INET6; 685186119Sqingli dst6.sin6_len = sizeof(struct sockaddr_in6); 686186119Sqingli dst6.sin6_addr = ip6->ip6_dst; 687186119Sqingli ifp = m->m_pkthdr.rcvif; 688243148Sae IF_AFDATA_RLOCK(ifp); 689186119Sqingli lle = lla_lookup(LLTABLE6(ifp), 0, 690186119Sqingli (struct sockaddr *)&dst6); 691243148Sae IF_AFDATA_RUNLOCK(ifp); 692186119Sqingli if ((lle != NULL) && (lle->la_flags & LLE_IFADDR)) { 693210350Sbz struct ifaddr *ifa; 694210350Sbz struct in6_ifaddr *ia6; 695210350Sbz int bad; 696210350Sbz 697210350Sbz bad = 1; 698210350Sbz#define sa_equal(a1, a2) \ 699210350Sbz (bcmp((a1), (a2), ((a1))->sin6_len) == 0) 700229621Sjhb IF_ADDR_RLOCK(ifp); 701210350Sbz TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { 702210350Sbz if (ifa->ifa_addr->sa_family != dst6.sin6_family) 703210350Sbz continue; 704210350Sbz if (sa_equal(&dst6, ifa->ifa_addr)) 705210350Sbz break; 706210350Sbz } 707210350Sbz KASSERT(ifa != NULL, ("%s: ifa not found for lle %p", 708210350Sbz __func__, lle)); 709210350Sbz#undef sa_equal 710210350Sbz 711210350Sbz ia6 = (struct in6_ifaddr *)ifa; 712210350Sbz if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) { 713210350Sbz /* Count the packet in the ip address stats */ 714210350Sbz ia6->ia_ifa.if_ipackets++; 715210350Sbz ia6->ia_ifa.if_ibytes += m->m_pkthdr.len; 716210350Sbz 717210350Sbz /* 718210350Sbz * record address information into m_tag. 719210350Sbz */ 720210350Sbz (void)ip6_setdstifaddr(m, ia6); 721210350Sbz 722210350Sbz bad = 0; 723210350Sbz } else { 724210350Sbz char ip6bufs[INET6_ADDRSTRLEN]; 725210350Sbz char ip6bufd[INET6_ADDRSTRLEN]; 726210350Sbz /* address is not ready, so discard the packet. */ 727210350Sbz nd6log((LOG_INFO, 728210350Sbz "ip6_input: packet to an unready address %s->%s\n", 729210350Sbz ip6_sprintf(ip6bufs, &ip6->ip6_src), 730210350Sbz ip6_sprintf(ip6bufd, &ip6->ip6_dst))); 731210350Sbz } 732229621Sjhb IF_ADDR_RUNLOCK(ifp); 733186119Sqingli LLE_RUNLOCK(lle); 734210350Sbz if (bad) 735210350Sbz goto bad; 736210350Sbz else { 737210350Sbz ours = 1; 738210350Sbz deliverifp = ifp; 739210350Sbz goto hbhcheck; 740210350Sbz } 741186119Sqingli } 742186293Sbz if (lle != NULL) 743186293Sbz LLE_RUNLOCK(lle); 744186119Sqingli 745187989Sbz dst = &rin6.ro_dst; 746187989Sbz dst->sin6_len = sizeof(struct sockaddr_in6); 747187989Sbz dst->sin6_family = AF_INET6; 748187989Sbz dst->sin6_addr = ip6->ip6_dst; 749231852Sbz rin6.ro_rt = in6_rtalloc1((struct sockaddr *)dst, 0, 0, M_GETFIB(m)); 750187989Sbz if (rin6.ro_rt) 751187989Sbz RT_UNLOCK(rin6.ro_rt); 75278064Sume 75353541Sshin#define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key)) 75453541Sshin 75553541Sshin /* 75653541Sshin * Accept the packet if the forwarding interface to the destination 75753541Sshin * according to the routing table is the loopback interface, 75853541Sshin * unless the associated route has a gateway. 75953541Sshin * Note that this approach causes to accept a packet if there is a 76053541Sshin * route to the loopback interface for the destination of the packet. 76153541Sshin * But we think it's even useful in some situations, e.g. when using 76253541Sshin * a special daemon which wants to intercept the packet. 76378064Sume * 76478064Sume * XXX: some OSes automatically make a cloned route for the destination 76578064Sume * of an outgoing packet. If the outgoing interface of the packet 76678064Sume * is a loopback one, the kernel would consider the packet to be 76778064Sume * accepted, even if we have no such address assinged on the interface. 76878064Sume * We check the cloned flag of the route entry to reject such cases, 76978064Sume * assuming that route entries for our own addresses are not made by 77078064Sume * cloning (it should be true because in6_addloop explicitly installs 77178064Sume * the host route). However, we might have to do an explicit check 77278064Sume * while it would be less efficient. Or, should we rather install a 77378064Sume * reject route for such a case? 77453541Sshin */ 775187989Sbz if (rin6.ro_rt && 776187989Sbz (rin6.ro_rt->rt_flags & 77753541Sshin (RTF_HOST|RTF_GATEWAY)) == RTF_HOST && 77878064Sume#ifdef RTF_WASCLONED 779187989Sbz !(rin6.ro_rt->rt_flags & RTF_WASCLONED) && 78078064Sume#endif 78178064Sume#ifdef RTF_CLONED 782187989Sbz !(rin6.ro_rt->rt_flags & RTF_CLONED) && 78378064Sume#endif 78462587Sitojun#if 0 78553541Sshin /* 78662587Sitojun * The check below is redundant since the comparison of 78762587Sitojun * the destination and the key of the rtentry has 78862587Sitojun * already done through looking up the routing table. 78953541Sshin */ 79062587Sitojun IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst, 791187989Sbz &rt6_key(rin6.ro_rt)->sin6_addr) 79262587Sitojun#endif 793187989Sbz rin6.ro_rt->rt_ifp->if_type == IFT_LOOP) { 794196569Sqingli int free_ia6 = 0; 795196569Sqingli struct in6_ifaddr *ia6; 79678064Sume 79762587Sitojun /* 798196569Sqingli * found the loopback route to the interface address 799196569Sqingli */ 800196569Sqingli if (rin6.ro_rt->rt_gateway->sa_family == AF_LINK) { 801196569Sqingli struct sockaddr_in6 dest6; 802196569Sqingli 803196569Sqingli bzero(&dest6, sizeof(dest6)); 804196569Sqingli dest6.sin6_family = AF_INET6; 805196569Sqingli dest6.sin6_len = sizeof(dest6); 806196569Sqingli dest6.sin6_addr = ip6->ip6_dst; 807196569Sqingli ia6 = (struct in6_ifaddr *) 808196569Sqingli ifa_ifwithaddr((struct sockaddr *)&dest6); 809196569Sqingli if (ia6 == NULL) 810196569Sqingli goto bad; 811196569Sqingli free_ia6 = 1; 812196569Sqingli } 813196569Sqingli else 814196569Sqingli ia6 = (struct in6_ifaddr *)rin6.ro_rt->rt_ifa; 815196569Sqingli 816196569Sqingli /* 817121630Sume * record address information into m_tag. 81878064Sume */ 81978064Sume (void)ip6_setdstifaddr(m, ia6); 82078064Sume 82178064Sume /* 82262587Sitojun * packets to a tentative, duplicated, or somehow invalid 82362587Sitojun * address must not be accepted. 82462587Sitojun */ 82553541Sshin if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) { 82662587Sitojun /* this address is ready */ 82753541Sshin ours = 1; 82853541Sshin deliverifp = ia6->ia_ifp; /* correct? */ 82967334Sjoe /* Count the packet in the ip address stats */ 83067334Sjoe ia6->ia_ifa.if_ipackets++; 83167334Sjoe ia6->ia_ifa.if_ibytes += m->m_pkthdr.len; 832196569Sqingli if (ia6 != NULL && free_ia6 != 0) 833196569Sqingli ifa_free(&ia6->ia_ifa); 83453541Sshin goto hbhcheck; 83553541Sshin } else { 836165118Sbz char ip6bufs[INET6_ADDRSTRLEN]; 837165118Sbz char ip6bufd[INET6_ADDRSTRLEN]; 83862587Sitojun /* address is not ready, so discard the packet. */ 83978064Sume nd6log((LOG_INFO, 84078064Sume "ip6_input: packet to an unready address %s->%s\n", 841165118Sbz ip6_sprintf(ip6bufs, &ip6->ip6_src), 842165118Sbz ip6_sprintf(ip6bufd, &ip6->ip6_dst))); 84362587Sitojun 844196569Sqingli if (ia6 != NULL && free_ia6 != 0) 845196569Sqingli ifa_free(&ia6->ia_ifa); 84662587Sitojun goto bad; 84753541Sshin } 84853541Sshin } 84953541Sshin 85053541Sshin /* 851120913Sume * FAITH (Firewall Aided Internet Translator) 85253541Sshin */ 853181803Sbz if (V_ip6_keepfaith) { 854187989Sbz if (rin6.ro_rt && rin6.ro_rt->rt_ifp && 855187989Sbz rin6.ro_rt->rt_ifp->if_type == IFT_FAITH) { 85653541Sshin /* XXX do we need more sanity checks? */ 85753541Sshin ours = 1; 858187989Sbz deliverifp = rin6.ro_rt->rt_ifp; /* faith */ 85953541Sshin goto hbhcheck; 86053541Sshin } 86153541Sshin } 86253541Sshin 86353541Sshin /* 86453541Sshin * Now there is no reason to process the packet if it's not our own 86553541Sshin * and we're not a router. 86653541Sshin */ 867181803Sbz if (!V_ip6_forwarding) { 868249294Sae IP6STAT_INC(ip6s_cantforward); 86953541Sshin in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); 87053541Sshin goto bad; 87153541Sshin } 87253541Sshin 87353541Sshin hbhcheck: 87453541Sshin /* 875121630Sume * record address information into m_tag, if we don't have one yet. 87678064Sume * note that we are unable to record it, if the address is not listed 87778064Sume * as our interface address (e.g. multicast addresses, addresses 87878064Sume * within FAITH prefixes and such). 87978064Sume */ 880236501Semax if (deliverifp) { 88178064Sume struct in6_ifaddr *ia6; 88278064Sume 883236501Semax if ((ia6 = ip6_getdstifaddr(m)) != NULL) { 884236501Semax ifa_free(&ia6->ia_ifa); 885236501Semax } else { 886236501Semax ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst); 887236501Semax if (ia6) { 888236501Semax if (!ip6_setdstifaddr(m, ia6)) { 889236501Semax /* 890236501Semax * XXX maybe we should drop the packet here, 891236501Semax * as we could not provide enough information 892236501Semax * to the upper layers. 893236501Semax */ 894236501Semax } 895236501Semax ifa_free(&ia6->ia_ifa); 89678064Sume } 89778064Sume } 89878064Sume } 89978064Sume 90078064Sume /* 90153541Sshin * Process Hop-by-Hop options header if it's contained. 90253541Sshin * m may be modified in ip6_hopopts_input(). 90353541Sshin * If a JumboPayload option is included, plen will also be modified. 90453541Sshin */ 90553541Sshin plen = (u_int32_t)ntohs(ip6->ip6_plen); 90653541Sshin if (ip6->ip6_nxt == IPPROTO_HOPOPTS) { 907235962Sbz int error; 90862587Sitojun 909235962Sbz error = ip6_input_hbh(m, &plen, &rtalert, &off, &nxt, &ours); 910235962Sbz if (error != 0) 911187989Sbz goto out; 91253541Sshin } else 91353541Sshin nxt = ip6->ip6_nxt; 91453541Sshin 91553541Sshin /* 91653541Sshin * Check that the amount of data in the buffers 91753541Sshin * is as at least much as the IPv6 header would have us expect. 91853541Sshin * Trim mbufs if longer than we expect. 91953541Sshin * Drop packet if shorter than we expect. 92053541Sshin */ 92153541Sshin if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) { 922249294Sae IP6STAT_INC(ip6s_tooshort); 92353541Sshin in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); 92453541Sshin goto bad; 92553541Sshin } 92653541Sshin if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) { 92753541Sshin if (m->m_len == m->m_pkthdr.len) { 92853541Sshin m->m_len = sizeof(struct ip6_hdr) + plen; 92953541Sshin m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen; 93053541Sshin } else 93153541Sshin m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len); 93253541Sshin } 93353541Sshin 93453541Sshin /* 93553541Sshin * Forward if desirable. 93653541Sshin */ 937191672Sbms if (V_ip6_mrouter && 938191672Sbms IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) { 93956723Sshin /* 94056723Sshin * If we are acting as a multicast router, all 94156723Sshin * incoming multicast packets are passed to the 94256723Sshin * kernel-level multicast forwarding function. 94356723Sshin * The packet is returned (relatively) intact; if 94456723Sshin * ip6_mforward() returns a non-zero value, the packet 94556723Sshin * must be discarded, else it may be accepted below. 946192923Sbms * 947192923Sbms * XXX TODO: Check hlim and multicast scope here to avoid 948192923Sbms * unnecessarily calling into ip6_mforward(). 94956723Sshin */ 950191672Sbms if (ip6_mforward && 951166938Sbms ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) { 952191672Sbms IP6STAT_INC(ip6s_cantforward); 953191672Sbms in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard); 954187989Sbz goto bad; 95556723Sshin } 95653541Sshin } else if (!ours) { 957121143Ssam ip6_forward(m, srcrt); 958187989Sbz goto out; 959121673Sume } 96053541Sshin 96162587Sitojun ip6 = mtod(m, struct ip6_hdr *); 96262587Sitojun 96353541Sshin /* 96462587Sitojun * Malicious party may be able to use IPv4 mapped addr to confuse 96562587Sitojun * tcp/udp stack and bypass security checks (act as if it was from 96662587Sitojun * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1). Be cautious. 96762587Sitojun * 96862587Sitojun * For SIIT end node behavior, you may want to disable the check. 96962587Sitojun * However, you will become vulnerable to attacks using IPv4 mapped 97062587Sitojun * source. 97162587Sitojun */ 97262587Sitojun if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || 97362587Sitojun IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { 974249294Sae IP6STAT_INC(ip6s_badscope); 97562587Sitojun in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr); 97662587Sitojun goto bad; 97762587Sitojun } 97862587Sitojun 97962587Sitojun /* 98053541Sshin * Tell launch routine the next header 98153541Sshin */ 982249294Sae IP6STAT_INC(ip6s_delivered); 98353541Sshin in6_ifstat_inc(deliverifp, ifs6_in_deliver); 98453541Sshin nest = 0; 98578064Sume 98653541Sshin while (nxt != IPPROTO_DONE) { 987181803Sbz if (V_ip6_hdrnestlimit && (++nest > V_ip6_hdrnestlimit)) { 988249294Sae IP6STAT_INC(ip6s_toomanyhdr); 98953541Sshin goto bad; 99053541Sshin } 99153541Sshin 99253541Sshin /* 99353541Sshin * protection against faulty packet - there should be 99453541Sshin * more sanity checks in header chain processing. 99553541Sshin */ 99653541Sshin if (m->m_pkthdr.len < off) { 997249294Sae IP6STAT_INC(ip6s_tooshort); 99853541Sshin in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); 99953541Sshin goto bad; 100053541Sshin } 100153541Sshin 1002171167Sgnn#ifdef IPSEC 100378064Sume /* 100478064Sume * enforce IPsec policy checking if we are seeing last header. 100578064Sume * note that we do not visit this with protocols with pcb layer 100678064Sume * code - like udp/tcp/raw ip. 100778064Sume */ 1008171133Sgnn if (ip6_ipsec_input(m, nxt)) 100978064Sume goto bad; 1010171167Sgnn#endif /* IPSEC */ 1011192923Sbms 1012192923Sbms /* 1013192923Sbms * Use mbuf flags to propagate Router Alert option to 1014192923Sbms * ICMPv6 layer, as hop-by-hop options have been stripped. 1015192923Sbms */ 1016192923Sbms if (nxt == IPPROTO_ICMPV6 && rtalert != ~0) 1017192923Sbms m->m_flags |= M_RTALERT_MLD; 1018192923Sbms 101953541Sshin nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt); 102053541Sshin } 1021187989Sbz goto out; 1022187989Sbzbad: 102353541Sshin m_freem(m); 1024187989Sbzout: 1025187989Sbz if (rin6.ro_rt) 1026187989Sbz RTFREE(rin6.ro_rt); 102753541Sshin} 102853541Sshin 102953541Sshin/* 103078064Sume * set/grab in6_ifaddr correspond to IPv6 destination address. 103178064Sume * XXX backward compatibility wrapper 1032194760Srwatson * 1033194760Srwatson * XXXRW: We should bump the refcount on ia6 before sticking it in the m_tag, 1034194760Srwatson * and then bump it when the tag is copied, and release it when the tag is 1035194760Srwatson * freed. Unfortunately, m_tags don't support deep copies (yet), so instead 1036194760Srwatson * we just bump the ia refcount when we receive it. This should be fixed. 103778064Sume */ 1038121673Sumestatic struct ip6aux * 1039171259Sdelphijip6_setdstifaddr(struct mbuf *m, struct in6_ifaddr *ia6) 104078064Sume{ 1041121673Sume struct ip6aux *ip6a; 104278064Sume 1043121673Sume ip6a = ip6_addaux(m); 1044121673Sume if (ip6a) 1045121673Sume ip6a->ip6a_dstia6 = ia6; 1046121673Sume return ip6a; /* NULL if failed to set */ 104778064Sume} 104878064Sume 104978064Sumestruct in6_ifaddr * 1050171259Sdelphijip6_getdstifaddr(struct mbuf *m) 105178064Sume{ 1052121673Sume struct ip6aux *ip6a; 1053194760Srwatson struct in6_ifaddr *ia; 105478064Sume 1055121673Sume ip6a = ip6_findaux(m); 1056194760Srwatson if (ip6a) { 1057194760Srwatson ia = ip6a->ip6a_dstia6; 1058194760Srwatson ifa_ref(&ia->ia_ifa); 1059194760Srwatson return ia; 1060194760Srwatson } else 106178064Sume return NULL; 106278064Sume} 106378064Sume 106478064Sume/* 106553541Sshin * Hop-by-Hop options header processing. If a valid jumbo payload option is 106653541Sshin * included, the real payload length will be stored in plenp. 1067171259Sdelphij * 1068171259Sdelphij * rtalertp - XXX: should be stored more smart way 106953541Sshin */ 107053541Sshinstatic int 1071171259Sdelphijip6_hopopts_input(u_int32_t *plenp, u_int32_t *rtalertp, 1072171259Sdelphij struct mbuf **mp, int *offp) 107353541Sshin{ 107478064Sume struct mbuf *m = *mp; 107553541Sshin int off = *offp, hbhlen; 107653541Sshin struct ip6_hbh *hbh; 107753541Sshin 107853541Sshin /* validation of the length of the header */ 107962587Sitojun#ifndef PULLDOWN_TEST 108053541Sshin IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1); 108153541Sshin hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off); 108253541Sshin hbhlen = (hbh->ip6h_len + 1) << 3; 108353541Sshin 108453541Sshin IP6_EXTHDR_CHECK(m, off, hbhlen, -1); 108553541Sshin hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off); 108662587Sitojun#else 108762587Sitojun IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, 108862587Sitojun sizeof(struct ip6_hdr), sizeof(struct ip6_hbh)); 108962587Sitojun if (hbh == NULL) { 1090249294Sae IP6STAT_INC(ip6s_tooshort); 109162587Sitojun return -1; 109262587Sitojun } 109362587Sitojun hbhlen = (hbh->ip6h_len + 1) << 3; 109462587Sitojun IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr), 109562587Sitojun hbhlen); 109662587Sitojun if (hbh == NULL) { 1097249294Sae IP6STAT_INC(ip6s_tooshort); 109862587Sitojun return -1; 109962587Sitojun } 110062587Sitojun#endif 110153541Sshin off += hbhlen; 110253541Sshin hbhlen -= sizeof(struct ip6_hbh); 110353541Sshin if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh), 110453541Sshin hbhlen, rtalertp, plenp) < 0) 1105120856Sume return (-1); 110653541Sshin 110753541Sshin *offp = off; 110853541Sshin *mp = m; 1109120856Sume return (0); 111053541Sshin} 111153541Sshin 111253541Sshin/* 111353541Sshin * Search header for all Hop-by-hop options and process each option. 111453541Sshin * This function is separate from ip6_hopopts_input() in order to 111553541Sshin * handle a case where the sending node itself process its hop-by-hop 111653541Sshin * options header. In such a case, the function is called from ip6_output(). 111778064Sume * 111878064Sume * The function assumes that hbh header is located right after the IPv6 header 111978064Sume * (RFC2460 p7), opthead is pointer into data content in m, and opthead to 1120215956Sbrucec * opthead + hbhlen is located in contiguous memory region. 112153541Sshin */ 112253541Sshinint 1123171259Sdelphijip6_process_hopopts(struct mbuf *m, u_int8_t *opthead, int hbhlen, 1124171259Sdelphij u_int32_t *rtalertp, u_int32_t *plenp) 112553541Sshin{ 112653541Sshin struct ip6_hdr *ip6; 112753541Sshin int optlen = 0; 112853541Sshin u_int8_t *opt = opthead; 112953541Sshin u_int16_t rtalert_val; 113062587Sitojun u_int32_t jumboplen; 113178064Sume const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh); 113253541Sshin 113353541Sshin for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) { 113478064Sume switch (*opt) { 113578064Sume case IP6OPT_PAD1: 113678064Sume optlen = 1; 113778064Sume break; 113878064Sume case IP6OPT_PADN: 113978064Sume if (hbhlen < IP6OPT_MINLEN) { 1140249294Sae IP6STAT_INC(ip6s_toosmall); 114178064Sume goto bad; 114278064Sume } 114378064Sume optlen = *(opt + 1) + 2; 114478064Sume break; 1145121472Sume case IP6OPT_ROUTER_ALERT: 114662587Sitojun /* XXX may need check for alignment */ 114778064Sume if (hbhlen < IP6OPT_RTALERT_LEN) { 1148249294Sae IP6STAT_INC(ip6s_toosmall); 114978064Sume goto bad; 115078064Sume } 115178064Sume if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) { 115278064Sume /* XXX stat */ 115378064Sume icmp6_error(m, ICMP6_PARAM_PROB, 1154120913Sume ICMP6_PARAMPROB_HEADER, 1155120913Sume erroff + opt + 1 - opthead); 1156120856Sume return (-1); 115778064Sume } 115878064Sume optlen = IP6OPT_RTALERT_LEN; 115978064Sume bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2); 116078064Sume *rtalertp = ntohs(rtalert_val); 116178064Sume break; 116278064Sume case IP6OPT_JUMBO: 116378064Sume /* XXX may need check for alignment */ 116462587Sitojun if (hbhlen < IP6OPT_JUMBO_LEN) { 1165249294Sae IP6STAT_INC(ip6s_toosmall); 116662587Sitojun goto bad; 116762587Sitojun } 116878064Sume if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) { 116978064Sume /* XXX stat */ 117078064Sume icmp6_error(m, ICMP6_PARAM_PROB, 1171120913Sume ICMP6_PARAMPROB_HEADER, 1172120913Sume erroff + opt + 1 - opthead); 1173120856Sume return (-1); 117478064Sume } 117562587Sitojun optlen = IP6OPT_JUMBO_LEN; 117653541Sshin 117762587Sitojun /* 117862587Sitojun * IPv6 packets that have non 0 payload length 117978064Sume * must not contain a jumbo payload option. 118062587Sitojun */ 118162587Sitojun ip6 = mtod(m, struct ip6_hdr *); 118262587Sitojun if (ip6->ip6_plen) { 1183249294Sae IP6STAT_INC(ip6s_badoptions); 118462587Sitojun icmp6_error(m, ICMP6_PARAM_PROB, 1185120913Sume ICMP6_PARAMPROB_HEADER, 1186120913Sume erroff + opt - opthead); 1187120856Sume return (-1); 118862587Sitojun } 118953541Sshin 119062587Sitojun /* 119162587Sitojun * We may see jumbolen in unaligned location, so 119262587Sitojun * we'd need to perform bcopy(). 119362587Sitojun */ 119462587Sitojun bcopy(opt + 2, &jumboplen, sizeof(jumboplen)); 119562587Sitojun jumboplen = (u_int32_t)htonl(jumboplen); 119662587Sitojun 119762587Sitojun#if 1 119862587Sitojun /* 119962587Sitojun * if there are multiple jumbo payload options, 120062587Sitojun * *plenp will be non-zero and the packet will be 120162587Sitojun * rejected. 120262587Sitojun * the behavior may need some debate in ipngwg - 120362587Sitojun * multiple options does not make sense, however, 120462587Sitojun * there's no explicit mention in specification. 120562587Sitojun */ 120662587Sitojun if (*plenp != 0) { 1207249294Sae IP6STAT_INC(ip6s_badoptions); 120862587Sitojun icmp6_error(m, ICMP6_PARAM_PROB, 1209120913Sume ICMP6_PARAMPROB_HEADER, 1210120913Sume erroff + opt + 2 - opthead); 1211120856Sume return (-1); 121262587Sitojun } 121362587Sitojun#endif 121462587Sitojun 121562587Sitojun /* 121662587Sitojun * jumbo payload length must be larger than 65535. 121762587Sitojun */ 121862587Sitojun if (jumboplen <= IPV6_MAXPACKET) { 1219249294Sae IP6STAT_INC(ip6s_badoptions); 122062587Sitojun icmp6_error(m, ICMP6_PARAM_PROB, 1221120913Sume ICMP6_PARAMPROB_HEADER, 1222120913Sume erroff + opt + 2 - opthead); 1223120856Sume return (-1); 122462587Sitojun } 122562587Sitojun *plenp = jumboplen; 122662587Sitojun 122762587Sitojun break; 122878064Sume default: /* unknown option */ 122978064Sume if (hbhlen < IP6OPT_MINLEN) { 1230249294Sae IP6STAT_INC(ip6s_toosmall); 123178064Sume goto bad; 123278064Sume } 123378064Sume optlen = ip6_unknown_opt(opt, m, 123478064Sume erroff + opt - opthead); 123578064Sume if (optlen == -1) 1236120856Sume return (-1); 123778064Sume optlen += 2; 123878064Sume break; 123953541Sshin } 124053541Sshin } 124153541Sshin 1242120856Sume return (0); 124353541Sshin 124453541Sshin bad: 124553541Sshin m_freem(m); 1246120856Sume return (-1); 124753541Sshin} 124853541Sshin 124953541Sshin/* 125053541Sshin * Unknown option processing. 125153541Sshin * The third argument `off' is the offset from the IPv6 header to the option, 125253541Sshin * which is necessary if the IPv6 header the and option header and IPv6 header 1253215956Sbrucec * is not contiguous in order to return an ICMPv6 error. 125453541Sshin */ 125553541Sshinint 1256171259Sdelphijip6_unknown_opt(u_int8_t *optp, struct mbuf *m, int off) 125753541Sshin{ 125853541Sshin struct ip6_hdr *ip6; 125953541Sshin 126078064Sume switch (IP6OPT_TYPE(*optp)) { 126178064Sume case IP6OPT_TYPE_SKIP: /* ignore the option */ 1262120856Sume return ((int)*(optp + 1)); 126378064Sume case IP6OPT_TYPE_DISCARD: /* silently discard */ 126478064Sume m_freem(m); 1265120856Sume return (-1); 126678064Sume case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */ 1267249294Sae IP6STAT_INC(ip6s_badoptions); 126878064Sume icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off); 1269120856Sume return (-1); 127078064Sume case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */ 1271249294Sae IP6STAT_INC(ip6s_badoptions); 127278064Sume ip6 = mtod(m, struct ip6_hdr *); 127378064Sume if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || 127478064Sume (m->m_flags & (M_BCAST|M_MCAST))) 127578064Sume m_freem(m); 127678064Sume else 127778064Sume icmp6_error(m, ICMP6_PARAM_PROB, 127878064Sume ICMP6_PARAMPROB_OPTION, off); 1279120856Sume return (-1); 128053541Sshin } 128153541Sshin 128253541Sshin m_freem(m); /* XXX: NOTREACHED */ 1283120856Sume return (-1); 128453541Sshin} 128553541Sshin 128653541Sshin/* 128762587Sitojun * Create the "control" list for this pcb. 1288179289Sbz * These functions will not modify mbuf chain at all. 128962587Sitojun * 1290179289Sbz * With KAME mbuf chain restriction: 129162587Sitojun * The routine will be called from upper layer handlers like tcp6_input(). 129262587Sitojun * Thus the routine assumes that the caller (tcp6_input) have already 129362587Sitojun * called IP6_EXTHDR_CHECK() and all the extension headers are located in the 129462587Sitojun * very first mbuf on the mbuf chain. 1295179289Sbz * 1296179289Sbz * ip6_savecontrol_v4 will handle those options that are possible to be 1297179289Sbz * set on a v4-mapped socket. 1298179289Sbz * ip6_savecontrol will directly call ip6_savecontrol_v4 to handle those 1299179289Sbz * options and handle the v6-only ones itself. 130053541Sshin */ 1301181782Sbzstruct mbuf ** 1302181782Sbzip6_savecontrol_v4(struct inpcb *inp, struct mbuf *m, struct mbuf **mp, 1303181782Sbz int *v4only) 130453541Sshin{ 1305121674Sume struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 130653541Sshin 130778064Sume#ifdef SO_TIMESTAMP 1308179289Sbz if ((inp->inp_socket->so_options & SO_TIMESTAMP) != 0) { 130953541Sshin struct timeval tv; 131053541Sshin 131153541Sshin microtime(&tv); 131253541Sshin *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv), 1313120913Sume SCM_TIMESTAMP, SOL_SOCKET); 1314121472Sume if (*mp) 131553541Sshin mp = &(*mp)->m_next; 131697658Stanimura } 131762587Sitojun#endif 131862587Sitojun 1319179289Sbz#define IS2292(inp, x, y) (((inp)->inp_flags & IN6P_RFC2292) ? (x) : (y)) 132053541Sshin /* RFC 2292 sec. 5 */ 1321179289Sbz if ((inp->inp_flags & IN6P_PKTINFO) != 0) { 132253541Sshin struct in6_pktinfo pi6; 1323120913Sume 1324236958Stuexen if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { 1325236958Stuexen#ifdef INET 1326236958Stuexen struct ip *ip; 1327236958Stuexen 1328236958Stuexen ip = mtod(m, struct ip *); 1329236958Stuexen pi6.ipi6_addr.s6_addr32[0] = 0; 1330236958Stuexen pi6.ipi6_addr.s6_addr32[1] = 0; 1331236958Stuexen pi6.ipi6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP; 1332236958Stuexen pi6.ipi6_addr.s6_addr32[3] = ip->ip_dst.s_addr; 1333236958Stuexen#else 1334236958Stuexen /* We won't hit this code */ 1335236958Stuexen bzero(&pi6.ipi6_addr, sizeof(struct in6_addr)); 1336236958Stuexen#endif 1337236958Stuexen } else { 1338236958Stuexen bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr)); 1339236958Stuexen in6_clearscope(&pi6.ipi6_addr); /* XXX */ 1340236958Stuexen } 1341120913Sume pi6.ipi6_ifindex = 1342120913Sume (m && m->m_pkthdr.rcvif) ? m->m_pkthdr.rcvif->if_index : 0; 1343120913Sume 134453541Sshin *mp = sbcreatecontrol((caddr_t) &pi6, 1345120913Sume sizeof(struct in6_pktinfo), 1346179289Sbz IS2292(inp, IPV6_2292PKTINFO, IPV6_PKTINFO), IPPROTO_IPV6); 1347121472Sume if (*mp) 134853541Sshin mp = &(*mp)->m_next; 134953541Sshin } 135078064Sume 1351179289Sbz if ((inp->inp_flags & IN6P_HOPLIMIT) != 0) { 1352236958Stuexen int hlim; 1353120913Sume 1354236958Stuexen if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { 1355236958Stuexen#ifdef INET 1356236958Stuexen struct ip *ip; 1357236958Stuexen 1358236958Stuexen ip = mtod(m, struct ip *); 1359236958Stuexen hlim = ip->ip_ttl; 1360236958Stuexen#else 1361236958Stuexen /* We won't hit this code */ 1362236958Stuexen hlim = 0; 1363236958Stuexen#endif 1364236958Stuexen } else { 1365236958Stuexen hlim = ip6->ip6_hlim & 0xff; 1366236958Stuexen } 1367120913Sume *mp = sbcreatecontrol((caddr_t) &hlim, sizeof(int), 1368179289Sbz IS2292(inp, IPV6_2292HOPLIMIT, IPV6_HOPLIMIT), 1369179289Sbz IPPROTO_IPV6); 1370121472Sume if (*mp) 137153541Sshin mp = &(*mp)->m_next; 137253541Sshin } 137353541Sshin 1374236958Stuexen if ((inp->inp_flags & IN6P_TCLASS) != 0) { 1375236958Stuexen int tclass; 1376236958Stuexen 1377236958Stuexen if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { 1378236958Stuexen#ifdef INET 1379236958Stuexen struct ip *ip; 1380236958Stuexen 1381236958Stuexen ip = mtod(m, struct ip *); 1382236958Stuexen tclass = ip->ip_tos; 1383236958Stuexen#else 1384236958Stuexen /* We won't hit this code */ 1385236958Stuexen tclass = 0; 1386236958Stuexen#endif 1387236958Stuexen } else { 1388236958Stuexen u_int32_t flowinfo; 1389236958Stuexen 1390236958Stuexen flowinfo = (u_int32_t)ntohl(ip6->ip6_flow & IPV6_FLOWINFO_MASK); 1391236958Stuexen flowinfo >>= 20; 1392236958Stuexen tclass = flowinfo & 0xff; 1393236958Stuexen } 1394236958Stuexen *mp = sbcreatecontrol((caddr_t) &tclass, sizeof(int), 1395236958Stuexen IPV6_TCLASS, IPPROTO_IPV6); 1396236958Stuexen if (*mp) 1397236958Stuexen mp = &(*mp)->m_next; 1398236958Stuexen } 1399236958Stuexen 1400236958Stuexen if (v4only != NULL) { 1401236958Stuexen if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { 1402236958Stuexen *v4only = 1; 1403236958Stuexen } else { 1404236958Stuexen *v4only = 0; 1405236958Stuexen } 1406236958Stuexen } 1407236958Stuexen 1408181782Sbz return (mp); 1409179289Sbz} 1410179289Sbz 1411179289Sbzvoid 1412179289Sbzip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp) 1413179289Sbz{ 1414179289Sbz struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); 1415181782Sbz int v4only = 0; 1416179289Sbz 1417181782Sbz mp = ip6_savecontrol_v4(in6p, m, mp, &v4only); 1418181782Sbz if (v4only) 1419179289Sbz return; 1420179289Sbz 142153541Sshin /* 1422130002Sume * IPV6_HOPOPTS socket option. Recall that we required super-user 1423130002Sume * privilege for the option (see ip6_ctloutput), but it might be too 1424130002Sume * strict, since there might be some hop-by-hop options which can be 1425130002Sume * returned to normal user. 1426130002Sume * See also RFC 2292 section 6 (or RFC 3542 section 8). 142753541Sshin */ 1428186141Sbz if ((in6p->inp_flags & IN6P_HOPOPTS) != 0) { 142953541Sshin /* 143053541Sshin * Check if a hop-by-hop options header is contatined in the 143153541Sshin * received packet, and if so, store the options as ancillary 143253541Sshin * data. Note that a hop-by-hop options header must be 1433120913Sume * just after the IPv6 header, which is assured through the 1434120913Sume * IPv6 input processing. 143553541Sshin */ 143653541Sshin if (ip6->ip6_nxt == IPPROTO_HOPOPTS) { 143762587Sitojun struct ip6_hbh *hbh; 143878064Sume int hbhlen = 0; 143978064Sume#ifdef PULLDOWN_TEST 144078064Sume struct mbuf *ext; 144178064Sume#endif 144253541Sshin 144362587Sitojun#ifndef PULLDOWN_TEST 144462587Sitojun hbh = (struct ip6_hbh *)(ip6 + 1); 144562587Sitojun hbhlen = (hbh->ip6h_len + 1) << 3; 144662587Sitojun#else 144778064Sume ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr), 144878064Sume ip6->ip6_nxt); 144978064Sume if (ext == NULL) { 1450249294Sae IP6STAT_INC(ip6s_tooshort); 145162587Sitojun return; 145262587Sitojun } 145378064Sume hbh = mtod(ext, struct ip6_hbh *); 145462587Sitojun hbhlen = (hbh->ip6h_len + 1) << 3; 145578064Sume if (hbhlen != ext->m_len) { 145678064Sume m_freem(ext); 1457249294Sae IP6STAT_INC(ip6s_tooshort); 145862587Sitojun return; 145962587Sitojun } 146062587Sitojun#endif 146162587Sitojun 146253541Sshin /* 1463120913Sume * XXX: We copy the whole header even if a 1464120913Sume * jumbo payload option is included, the option which 1465120913Sume * is to be removed before returning according to 1466120913Sume * RFC2292. 1467148169Sume * Note: this constraint is removed in RFC3542 146853541Sshin */ 146962587Sitojun *mp = sbcreatecontrol((caddr_t)hbh, hbhlen, 1470179289Sbz IS2292(in6p, IPV6_2292HOPOPTS, IPV6_HOPOPTS), 1471121472Sume IPPROTO_IPV6); 1472121472Sume if (*mp) 147353541Sshin mp = &(*mp)->m_next; 147478064Sume#ifdef PULLDOWN_TEST 147578064Sume m_freem(ext); 147678064Sume#endif 147753541Sshin } 147853541Sshin } 147953541Sshin 1480186141Sbz if ((in6p->inp_flags & (IN6P_RTHDR | IN6P_DSTOPTS)) != 0) { 148178064Sume int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr); 148253541Sshin 148353541Sshin /* 148453541Sshin * Search for destination options headers or routing 148553541Sshin * header(s) through the header chain, and stores each 148653541Sshin * header as ancillary data. 148753541Sshin * Note that the order of the headers remains in 148853541Sshin * the chain of ancillary data. 148953541Sshin */ 149078064Sume while (1) { /* is explicit loop prevention necessary? */ 149178064Sume struct ip6_ext *ip6e = NULL; 149262587Sitojun int elen; 149378064Sume#ifdef PULLDOWN_TEST 149478064Sume struct mbuf *ext = NULL; 149578064Sume#endif 149653541Sshin 149778064Sume /* 149878064Sume * if it is not an extension header, don't try to 149978064Sume * pull it from the chain. 150078064Sume */ 150178064Sume switch (nxt) { 150278064Sume case IPPROTO_DSTOPTS: 150378064Sume case IPPROTO_ROUTING: 150478064Sume case IPPROTO_HOPOPTS: 150578064Sume case IPPROTO_AH: /* is it possible? */ 150678064Sume break; 150778064Sume default: 150878064Sume goto loopend; 150978064Sume } 151078064Sume 151162587Sitojun#ifndef PULLDOWN_TEST 151278064Sume if (off + sizeof(*ip6e) > m->m_len) 151378064Sume goto loopend; 151462587Sitojun ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off); 151562587Sitojun if (nxt == IPPROTO_AH) 151662587Sitojun elen = (ip6e->ip6e_len + 2) << 2; 151762587Sitojun else 151862587Sitojun elen = (ip6e->ip6e_len + 1) << 3; 151978064Sume if (off + elen > m->m_len) 152078064Sume goto loopend; 152162587Sitojun#else 152278064Sume ext = ip6_pullexthdr(m, off, nxt); 152378064Sume if (ext == NULL) { 1524249294Sae IP6STAT_INC(ip6s_tooshort); 152562587Sitojun return; 152662587Sitojun } 152778064Sume ip6e = mtod(ext, struct ip6_ext *); 152862587Sitojun if (nxt == IPPROTO_AH) 152962587Sitojun elen = (ip6e->ip6e_len + 2) << 2; 153062587Sitojun else 153162587Sitojun elen = (ip6e->ip6e_len + 1) << 3; 153278064Sume if (elen != ext->m_len) { 153378064Sume m_freem(ext); 1534249294Sae IP6STAT_INC(ip6s_tooshort); 153562587Sitojun return; 153662587Sitojun } 153762587Sitojun#endif 153862587Sitojun 153978064Sume switch (nxt) { 154078064Sume case IPPROTO_DSTOPTS: 1541186141Sbz if (!(in6p->inp_flags & IN6P_DSTOPTS)) 154278064Sume break; 154353541Sshin 154478064Sume *mp = sbcreatecontrol((caddr_t)ip6e, elen, 1545179289Sbz IS2292(in6p, 1546179289Sbz IPV6_2292DSTOPTS, IPV6_DSTOPTS), 1547120913Sume IPPROTO_IPV6); 154878064Sume if (*mp) 154978064Sume mp = &(*mp)->m_next; 155078064Sume break; 155178064Sume case IPPROTO_ROUTING: 1552201794Strasz if (!(in6p->inp_flags & IN6P_RTHDR)) 155378064Sume break; 155453541Sshin 155578064Sume *mp = sbcreatecontrol((caddr_t)ip6e, elen, 1556179289Sbz IS2292(in6p, IPV6_2292RTHDR, IPV6_RTHDR), 1557120913Sume IPPROTO_IPV6); 155878064Sume if (*mp) 155978064Sume mp = &(*mp)->m_next; 156078064Sume break; 156178064Sume case IPPROTO_HOPOPTS: 156278064Sume case IPPROTO_AH: /* is it possible? */ 156378064Sume break; 156453541Sshin 156578064Sume default: 156678064Sume /* 1567171260Sdelphij * other cases have been filtered in the above. 156878064Sume * none will visit this case. here we supply 156978064Sume * the code just in case (nxt overwritten or 157078064Sume * other cases). 157178064Sume */ 157278064Sume#ifdef PULLDOWN_TEST 157378064Sume m_freem(ext); 157478064Sume#endif 157578064Sume goto loopend; 157653541Sshin 157753541Sshin } 157853541Sshin 157953541Sshin /* proceed with the next header. */ 158062587Sitojun off += elen; 158153541Sshin nxt = ip6e->ip6e_nxt; 158278064Sume ip6e = NULL; 158378064Sume#ifdef PULLDOWN_TEST 158478064Sume m_freem(ext); 158578064Sume ext = NULL; 158678064Sume#endif 158753541Sshin } 158853541Sshin loopend: 158978064Sume ; 159053541Sshin } 1591179289Sbz} 1592121472Sume#undef IS2292 159378064Sume 1594125776Sumevoid 1595279911Saeip6_notify_pmtu(struct inpcb *inp, struct sockaddr_in6 *dst, u_int32_t mtu) 1596125776Sume{ 1597125776Sume struct socket *so; 1598125776Sume struct mbuf *m_mtu; 1599125776Sume struct ip6_mtuinfo mtuctl; 1600125776Sume 1601279911Sae KASSERT(inp != NULL, ("%s: inp == NULL", __func__)); 1602279911Sae /* 1603279911Sae * Notify the error by sending IPV6_PATHMTU ancillary data if 1604279911Sae * application wanted to know the MTU value. 1605279911Sae * NOTE: we notify disconnected sockets, because some udp 1606279911Sae * applications keep sending sockets disconnected. 1607279911Sae * NOTE: our implementation doesn't notify connected sockets that has 1608279911Sae * foreign address that is different than given destination addresses 1609279911Sae * (this is permitted by RFC 3542). 1610279911Sae */ 1611279911Sae if ((inp->inp_flags & IN6P_MTU) == 0 || ( 1612279911Sae !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) && 1613279911Sae !IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &dst->sin6_addr))) 1614125776Sume return; 1615125776Sume 1616279911Sae mtuctl.ip6m_mtu = mtu; 1617125776Sume mtuctl.ip6m_addr = *dst; 1618148385Sume if (sa6_recoverscope(&mtuctl.ip6m_addr)) 1619148385Sume return; 1620125776Sume 1621125776Sume if ((m_mtu = sbcreatecontrol((caddr_t)&mtuctl, sizeof(mtuctl), 1622125776Sume IPV6_PATHMTU, IPPROTO_IPV6)) == NULL) 1623125776Sume return; 1624125776Sume 1625279911Sae so = inp->inp_socket; 1626125776Sume if (sbappendaddr(&so->so_rcv, (struct sockaddr *)dst, NULL, m_mtu) 1627125776Sume == 0) { 1628125776Sume m_freem(m_mtu); 1629125776Sume /* XXX: should count statistics */ 1630125776Sume } else 1631125776Sume sorwakeup(so); 1632125776Sume} 1633125776Sume 163478064Sume#ifdef PULLDOWN_TEST 163578064Sume/* 163678064Sume * pull single extension header from mbuf chain. returns single mbuf that 163778064Sume * contains the result, or NULL on error. 163878064Sume */ 163978064Sumestatic struct mbuf * 1640171259Sdelphijip6_pullexthdr(struct mbuf *m, size_t off, int nxt) 164178064Sume{ 164278064Sume struct ip6_ext ip6e; 164378064Sume size_t elen; 164478064Sume struct mbuf *n; 164578064Sume 164678064Sume#ifdef DIAGNOSTIC 164778064Sume switch (nxt) { 164878064Sume case IPPROTO_DSTOPTS: 164978064Sume case IPPROTO_ROUTING: 165078064Sume case IPPROTO_HOPOPTS: 165178064Sume case IPPROTO_AH: /* is it possible? */ 165278064Sume break; 165378064Sume default: 165478064Sume printf("ip6_pullexthdr: invalid nxt=%d\n", nxt); 165553541Sshin } 165678064Sume#endif 165778064Sume 165878064Sume m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e); 165978064Sume if (nxt == IPPROTO_AH) 166078064Sume elen = (ip6e.ip6e_len + 2) << 2; 166178064Sume else 166278064Sume elen = (ip6e.ip6e_len + 1) << 3; 166378064Sume 1664248328Sglebius if (elen > MLEN) 1665248328Sglebius n = m_getcl(M_NOWAIT, MT_DATA, 0); 1666248328Sglebius else 1667248328Sglebius n = m_get(M_NOWAIT, MT_DATA); 1668248328Sglebius if (n == NULL) 166978064Sume return NULL; 167062587Sitojun 167178064Sume m_copydata(m, off, elen, mtod(n, caddr_t)); 167278064Sume n->m_len = elen; 167378064Sume return n; 167453541Sshin} 167578064Sume#endif 167653541Sshin 167753541Sshin/* 167853541Sshin * Get pointer to the previous header followed by the header 167953541Sshin * currently processed. 168053541Sshin */ 1681329158Saeint 1682171259Sdelphijip6_get_prevhdr(struct mbuf *m, int off) 168353541Sshin{ 1684329158Sae struct ip6_ext ip6e; 1685329158Sae struct ip6_hdr *ip6; 1686329158Sae int len, nlen, nxt; 168753541Sshin 168853541Sshin if (off == sizeof(struct ip6_hdr)) 1689329158Sae return (offsetof(struct ip6_hdr, ip6_nxt)); 1690329158Sae if (off < sizeof(struct ip6_hdr)) 1691329158Sae panic("%s: off < sizeof(struct ip6_hdr)", __func__); 169253541Sshin 1693329158Sae ip6 = mtod(m, struct ip6_hdr *); 1694329158Sae nxt = ip6->ip6_nxt; 1695329158Sae len = sizeof(struct ip6_hdr); 1696329158Sae nlen = 0; 1697329158Sae while (len < off) { 1698329158Sae m_copydata(m, len, sizeof(ip6e), (caddr_t)&ip6e); 1699329158Sae switch (nxt) { 1700329158Sae case IPPROTO_FRAGMENT: 1701329158Sae nlen = sizeof(struct ip6_frag); 1702329158Sae break; 1703329158Sae case IPPROTO_AH: 1704329158Sae nlen = (ip6e.ip6e_len + 2) << 2; 1705329158Sae break; 1706329158Sae default: 1707329158Sae nlen = (ip6e.ip6e_len + 1) << 3; 170853541Sshin } 1709329158Sae len += nlen; 1710329158Sae nxt = ip6e.ip6e_nxt; 171153541Sshin } 1712329158Sae return (len - nlen); 171353541Sshin} 171453541Sshin 171553541Sshin/* 171662587Sitojun * get next header offset. m will be retained. 171762587Sitojun */ 171862587Sitojunint 1719171259Sdelphijip6_nexthdr(struct mbuf *m, int off, int proto, int *nxtp) 172062587Sitojun{ 172162587Sitojun struct ip6_hdr ip6; 172262587Sitojun struct ip6_ext ip6e; 172362587Sitojun struct ip6_frag fh; 172462587Sitojun 172562587Sitojun /* just in case */ 172662587Sitojun if (m == NULL) 172762587Sitojun panic("ip6_nexthdr: m == NULL"); 172862587Sitojun if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len < off) 172962587Sitojun return -1; 173062587Sitojun 173162587Sitojun switch (proto) { 173262587Sitojun case IPPROTO_IPV6: 173362587Sitojun if (m->m_pkthdr.len < off + sizeof(ip6)) 173462587Sitojun return -1; 173562587Sitojun m_copydata(m, off, sizeof(ip6), (caddr_t)&ip6); 173662587Sitojun if (nxtp) 173762587Sitojun *nxtp = ip6.ip6_nxt; 173862587Sitojun off += sizeof(ip6); 173962587Sitojun return off; 174062587Sitojun 174162587Sitojun case IPPROTO_FRAGMENT: 174262587Sitojun /* 174362587Sitojun * terminate parsing if it is not the first fragment, 174462587Sitojun * it does not make sense to parse through it. 174562587Sitojun */ 174662587Sitojun if (m->m_pkthdr.len < off + sizeof(fh)) 174762587Sitojun return -1; 174862587Sitojun m_copydata(m, off, sizeof(fh), (caddr_t)&fh); 1749120978Sume /* IP6F_OFF_MASK = 0xfff8(BigEndian), 0xf8ff(LittleEndian) */ 1750120978Sume if (fh.ip6f_offlg & IP6F_OFF_MASK) 175162587Sitojun return -1; 175262587Sitojun if (nxtp) 175362587Sitojun *nxtp = fh.ip6f_nxt; 175462587Sitojun off += sizeof(struct ip6_frag); 175562587Sitojun return off; 175662587Sitojun 175762587Sitojun case IPPROTO_AH: 175862587Sitojun if (m->m_pkthdr.len < off + sizeof(ip6e)) 175962587Sitojun return -1; 176062587Sitojun m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e); 176162587Sitojun if (nxtp) 176262587Sitojun *nxtp = ip6e.ip6e_nxt; 176362587Sitojun off += (ip6e.ip6e_len + 2) << 2; 176462587Sitojun return off; 176562587Sitojun 176662587Sitojun case IPPROTO_HOPOPTS: 176762587Sitojun case IPPROTO_ROUTING: 176862587Sitojun case IPPROTO_DSTOPTS: 176962587Sitojun if (m->m_pkthdr.len < off + sizeof(ip6e)) 177062587Sitojun return -1; 177162587Sitojun m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e); 177262587Sitojun if (nxtp) 177362587Sitojun *nxtp = ip6e.ip6e_nxt; 177462587Sitojun off += (ip6e.ip6e_len + 1) << 3; 177562587Sitojun return off; 177662587Sitojun 177762587Sitojun case IPPROTO_NONE: 177862587Sitojun case IPPROTO_ESP: 177962587Sitojun case IPPROTO_IPCOMP: 178062587Sitojun /* give up */ 178162587Sitojun return -1; 178262587Sitojun 178362587Sitojun default: 178462587Sitojun return -1; 178562587Sitojun } 178662587Sitojun 178762587Sitojun return -1; 178862587Sitojun} 178962587Sitojun 179062587Sitojun/* 179162587Sitojun * get offset for the last header in the chain. m will be kept untainted. 179262587Sitojun */ 179362587Sitojunint 1794171259Sdelphijip6_lasthdr(struct mbuf *m, int off, int proto, int *nxtp) 179562587Sitojun{ 179662587Sitojun int newoff; 179762587Sitojun int nxt; 179862587Sitojun 179962587Sitojun if (!nxtp) { 180062587Sitojun nxt = -1; 180162587Sitojun nxtp = &nxt; 180262587Sitojun } 180362587Sitojun while (1) { 180462587Sitojun newoff = ip6_nexthdr(m, off, proto, nxtp); 180562587Sitojun if (newoff < 0) 180662587Sitojun return off; 180762587Sitojun else if (newoff < off) 180862587Sitojun return -1; /* invalid */ 180962587Sitojun else if (newoff == off) 181062587Sitojun return newoff; 181162587Sitojun 181262587Sitojun off = newoff; 181362587Sitojun proto = *nxtp; 181462587Sitojun } 181562587Sitojun} 181662587Sitojun 1817235956Sbzstatic struct ip6aux * 1818171259Sdelphijip6_addaux(struct mbuf *m) 181978064Sume{ 1820120913Sume struct m_tag *mtag; 1821120913Sume 1822120913Sume mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL); 1823120913Sume if (!mtag) { 1824120913Sume mtag = m_tag_get(PACKET_TAG_IPV6_INPUT, sizeof(struct ip6aux), 1825120913Sume M_NOWAIT); 1826121630Sume if (mtag) { 1827120913Sume m_tag_prepend(m, mtag); 1828121630Sume bzero(mtag + 1, sizeof(struct ip6aux)); 1829121630Sume } 183078064Sume } 1831121673Sume return mtag ? (struct ip6aux *)(mtag + 1) : NULL; 183278064Sume} 183378064Sume 1834235956Sbzstatic struct ip6aux * 1835171259Sdelphijip6_findaux(struct mbuf *m) 183678064Sume{ 1837120913Sume struct m_tag *mtag; 1838120913Sume 1839120913Sume mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL); 1840121673Sume return mtag ? (struct ip6aux *)(mtag + 1) : NULL; 184178064Sume} 184278064Sume 1843235956Sbzstatic void 1844171259Sdelphijip6_delaux(struct mbuf *m) 184578064Sume{ 1846120913Sume struct m_tag *mtag; 1847120913Sume 1848120913Sume mtag = m_tag_find(m, PACKET_TAG_IPV6_INPUT, NULL); 1849120913Sume if (mtag) 1850120913Sume m_tag_delete(m, mtag); 185178064Sume} 185278064Sume 185362587Sitojun/* 185453541Sshin * System control for IP6 185553541Sshin */ 185653541Sshin 185753541Sshinu_char inet6ctlerrmap[PRC_NCMDS] = { 185853541Sshin 0, 0, 0, 0, 185953541Sshin 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, 186053541Sshin EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, 186153541Sshin EMSGSIZE, EHOSTUNREACH, 0, 0, 186253541Sshin 0, 0, 0, 0, 186353541Sshin ENOPROTOOPT 186453541Sshin}; 1865