The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/bsd/netinet6/ip6_input.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $FreeBSD: src/sys/netinet6/ip6_input.c,v 1.11.2.10 2001/07/24 19:10:18 brooks Exp $     */
    2 /*      $KAME: ip6_input.c,v 1.194 2001/05/27 13:28:35 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 
   69 #include <sys/param.h>
   70 #include <sys/systm.h>
   71 #include <sys/malloc.h>
   72 #include <sys/mbuf.h>
   73 #include <sys/domain.h>
   74 #include <sys/protosw.h>
   75 #include <sys/socket.h>
   76 #include <sys/socketvar.h>
   77 #include <sys/errno.h>
   78 #include <sys/time.h>
   79 #include <sys/kernel.h>
   80 #include <sys/syslog.h>
   81 #include <sys/proc.h>
   82 
   83 #include <net/if.h>
   84 #include <net/if_var.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 #if INET
   93 #include <netinet/ip.h>
   94 #include <netinet/ip_icmp.h>
   95 #endif /*INET*/
   96 #include <netinet/ip6.h>
   97 #include <netinet6/in6_var.h>
   98 #include <netinet6/ip6_var.h>
   99 #include <netinet/in_pcb.h>
  100 #include <netinet/icmp6.h>
  101 #include <netinet6/in6_ifattach.h>
  102 #include <netinet6/nd6.h>
  103 #include <netinet6/in6_prefix.h>
  104 
  105 #if IPSEC
  106 #include <netinet6/ipsec.h>
  107 #if INET6
  108 #include <netinet6/ipsec6.h>
  109 #endif
  110 extern int ipsec_bypass;
  111 #endif
  112 
  113 #include <netinet6/ip6_fw.h>
  114 
  115 #include <netinet6/ip6protosw.h>
  116 
  117 /* we need it for NLOOP. */
  118 #include "loop.h"
  119 #include "faith.h"
  120 
  121 #include <net/net_osdep.h>
  122 
  123 extern struct domain inet6domain;
  124 extern struct ip6protosw inet6sw[];
  125 
  126 struct ip6protosw *  ip6_protox[IPPROTO_MAX];
  127 static int ip6qmaxlen = IFQ_MAXLEN;
  128 struct in6_ifaddr *in6_ifaddr;
  129 
  130 extern void in6_tmpaddrtimer_funneled(void *);
  131 extern void nd6_timer_funneled(void *);
  132 extern void in6_rr_timer_funneled(void *);
  133 
  134 int ip6_forward_srcrt;                  /* XXX */
  135 int ip6_sourcecheck;                    /* XXX */
  136 int ip6_sourcecheck_interval;           /* XXX */
  137 const int int6intrq_present = 1;
  138 
  139 int ip6_ours_check_algorithm;
  140 int in6_init2done = 0;
  141 
  142 
  143 /* firewall hooks */
  144 ip6_fw_chk_t *ip6_fw_chk_ptr;
  145 ip6_fw_ctl_t *ip6_fw_ctl_ptr;
  146 int ip6_fw_enable = 1;
  147 
  148 struct ip6stat ip6stat;
  149 
  150 #ifdef __APPLE__
  151 struct ifqueue ip6intrq;
  152 #endif
  153 
  154 static void ip6_init2 __P((void *));
  155 static struct mbuf *ip6_setdstifaddr __P((struct mbuf *, struct in6_ifaddr *));
  156 
  157 static int ip6_hopopts_input __P((u_int32_t *, u_int32_t *, struct mbuf **, int *));
  158 #if PULLDOWN_TEST
  159 static struct mbuf *ip6_pullexthdr __P((struct mbuf *, size_t, int));
  160 #endif
  161 
  162 #ifdef __APPLE__
  163 void gifattach __P((void));
  164 void faithattach __P((void));
  165 void stfattach __P((void));
  166 #endif
  167 
  168 /*
  169  * IP6 initialization: fill in IP6 protocol switch table.
  170  * All protocols not implemented in kernel go to raw IP6 protocol handler.
  171  */
  172 void
  173 ip6_init()
  174 {
  175         struct ip6protosw *pr;
  176         int i;
  177         struct timeval tv;
  178 
  179 #if DIAGNOSTIC
  180         if (sizeof(struct protosw) != sizeof(struct ip6protosw))
  181                 panic("sizeof(protosw) != sizeof(ip6protosw)");
  182 #endif
  183         pr = (struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW);
  184         if (pr == 0)
  185                 panic("ip6_init");
  186         for (i = 0; i < IPPROTO_MAX; i++)
  187                 ip6_protox[i] = pr;
  188         for (pr = (struct ip6protosw*)inet6domain.dom_protosw; pr; pr = pr->pr_next) {
  189                 if(!((unsigned int)pr->pr_domain)) continue;    /* If uninitialized, skip */
  190                 if (pr->pr_domain->dom_family == PF_INET6 &&
  191                     pr->pr_protocol && pr->pr_protocol != IPPROTO_RAW) {
  192                         ip6_protox[pr->pr_protocol] = pr;
  193                 }
  194         }
  195 
  196         ip6intrq.ifq_maxlen = ip6qmaxlen;
  197 #ifndef __APPLE__
  198         register_netisr(NETISR_IPV6, ip6intr);
  199 #endif
  200         nd6_init();
  201         frag6_init();
  202         icmp6_init();
  203         /*
  204          * in many cases, random() here does NOT return random number
  205          * as initialization during bootstrap time occur in fixed order.
  206          */
  207         microtime(&tv);
  208         ip6_flow_seq = random() ^ tv.tv_usec;
  209         microtime(&tv);
  210         ip6_desync_factor = (random() ^ tv.tv_usec) % MAX_TEMP_DESYNC_FACTOR;
  211         timeout(ip6_init2, (caddr_t)0, 2 * hz);
  212 }
  213 
  214 static void
  215 ip6_init2(dummy)
  216         void *dummy;
  217 {
  218 #ifdef __APPLE__
  219         boolean_t   funnel_state;
  220         funnel_state = thread_funnel_set(network_flock, TRUE);
  221 #endif
  222         /*
  223          * to route local address of p2p link to loopback,
  224          * assign loopback address first.
  225          */
  226         in6_ifattach(&loif[0], NULL, NULL);
  227 
  228 #ifdef __APPLE__
  229         /* nd6_timer_init */
  230         timeout(nd6_timer_funneled, (caddr_t)0, hz);
  231 
  232         /* router renumbering prefix list maintenance */
  233         timeout(in6_rr_timer_funneled, (caddr_t)0, hz);
  234 
  235         /* timer for regeneranation of temporary addresses randomize ID */
  236         timeout(in6_tmpaddrtimer_funneled, (caddr_t)0,
  237                 (ip6_temp_preferred_lifetime - ip6_desync_factor -
  238                        ip6_temp_regen_advance) * hz);
  239 
  240 #if NGIF
  241         gifattach();
  242 #endif
  243 #if NFAITH
  244         faithattach();
  245 #endif
  246 #if NSTF
  247         stfattach();
  248 #endif
  249 #else
  250         /* nd6_timer_init */
  251 
  252         callout_init(&nd6_timer_ch);
  253         callout_reset(&nd6_timer_ch, hz, nd6_timer, NULL);
  254 
  255         /* router renumbering prefix list maintenance */
  256         callout_init(&in6_rr_timer_ch);
  257         callout_reset(&in6_rr_timer_ch, hz, in6_rr_timer, NULL);
  258 
  259         /* timer for regeneranation of temporary addresses randomize ID */
  260         callout_reset(&in6_tmpaddrtimer_ch,
  261                       (ip6_temp_preferred_lifetime - ip6_desync_factor -
  262                        ip6_temp_regen_advance) * hz,
  263                       in6_tmpaddrtimer, NULL);
  264 #endif
  265 
  266         in6_init2done = 1;
  267 #ifdef __APPLE__
  268         (void) thread_funnel_set(network_flock, FALSE);
  269 #endif
  270 }
  271 
  272 #if __FreeBSD__
  273 /* cheat */
  274 /* This must be after route_init(), which is now SI_ORDER_THIRD */
  275 SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);
  276 #endif
  277 
  278 /*
  279  * IP6 input interrupt handling. Just pass the packet to ip6_input.
  280  */
  281 void
  282 ip6intr(void)
  283 {
  284         int s;
  285         struct mbuf *m;
  286 
  287         for (;;) {
  288                 s = splimp();
  289                 IF_DEQUEUE(&ip6intrq, m);
  290                 splx(s);
  291                 if (m == 0)
  292                         return;
  293                 ip6_input(m);
  294         }
  295 }
  296 
  297 extern struct   route_in6 ip6_forward_rt;
  298 
  299 void
  300 ip6_input(m)
  301         struct mbuf *m;
  302 {
  303         struct ip6_hdr *ip6;
  304         int off = sizeof(struct ip6_hdr), nest;
  305         u_int32_t plen;
  306         u_int32_t rtalert = ~0;
  307         int nxt = 0, ours = 0;
  308         struct ifnet *deliverifp = NULL;
  309 
  310 #if IPSEC
  311         /*
  312          * should the inner packet be considered authentic?
  313          * see comment in ah4_input().
  314          */
  315         if (m) {
  316                 m->m_flags &= ~M_AUTHIPHDR;
  317                 m->m_flags &= ~M_AUTHIPDGM;
  318         }
  319 #endif
  320 
  321         /*
  322          * make sure we don't have onion peering information into m_aux.
  323          */
  324         ip6_delaux(m);
  325 
  326         /*
  327          * mbuf statistics
  328          */
  329         if (m->m_flags & M_EXT) {
  330                 if (m->m_next)
  331                         ip6stat.ip6s_mext2m++;
  332                 else
  333                         ip6stat.ip6s_mext1++;
  334         } else {
  335 #define M2MMAX  (sizeof(ip6stat.ip6s_m2m)/sizeof(ip6stat.ip6s_m2m[0]))
  336                 if (m->m_next) {
  337                         if (m->m_flags & M_LOOP) {
  338                                 ip6stat.ip6s_m2m[loif[0].if_index]++;   /* XXX */
  339                         } else if (m->m_pkthdr.rcvif->if_index < M2MMAX)
  340                                 ip6stat.ip6s_m2m[m->m_pkthdr.rcvif->if_index]++;
  341                         else
  342                                 ip6stat.ip6s_m2m[0]++;
  343                 } else
  344                         ip6stat.ip6s_m1++;
  345 #undef M2MMAX
  346         }
  347 
  348         in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_receive);
  349         ip6stat.ip6s_total++;
  350 
  351 #ifndef PULLDOWN_TEST
  352         /*
  353          * L2 bridge code and some other code can return mbuf chain
  354          * that does not conform to KAME requirement.  too bad.
  355          * XXX: fails to join if interface MTU > MCLBYTES.  jumbogram?
  356          */
  357         if (m && m->m_next != NULL && m->m_pkthdr.len < MCLBYTES) {
  358                 struct mbuf *n;
  359 
  360                 MGETHDR(n, M_DONTWAIT, MT_HEADER);
  361                 if (n)
  362                         M_COPY_PKTHDR(n, m);
  363                 if (n && m->m_pkthdr.len > MHLEN) {
  364                         MCLGET(n, M_DONTWAIT);
  365                         if ((n->m_flags & M_EXT) == 0) {
  366                                 m_freem(n);
  367                                 n = NULL;
  368                         }
  369                 }
  370                 if (n == NULL) {
  371                         m_freem(m);
  372                         return; /*ENOBUFS*/
  373                 }
  374 
  375                 m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t));
  376                 n->m_len = m->m_pkthdr.len;
  377                 m_freem(m);
  378                 m = n;
  379         }
  380         IP6_EXTHDR_CHECK(m, 0, sizeof(struct ip6_hdr), /*nothing*/);
  381 #endif
  382 
  383         if (m->m_len < sizeof(struct ip6_hdr)) {
  384                 struct ifnet *inifp;
  385                 inifp = m->m_pkthdr.rcvif;
  386                 if ((m = m_pullup(m, sizeof(struct ip6_hdr))) == 0) {
  387                         ip6stat.ip6s_toosmall++;
  388                         in6_ifstat_inc(inifp, ifs6_in_hdrerr);
  389                         return;
  390                 }
  391         }
  392 
  393         ip6 = mtod(m, struct ip6_hdr *);
  394 
  395         if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
  396                 ip6stat.ip6s_badvers++;
  397                 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
  398                 goto bad;
  399         }
  400 
  401         ip6stat.ip6s_nxthist[ip6->ip6_nxt]++;
  402 
  403         /*
  404          * Check with the firewall...
  405          */
  406         if (ip6_fw_enable && ip6_fw_chk_ptr) {
  407                 u_short port = 0;
  408                 /* If ipfw says divert, we have to just drop packet */
  409                 /* use port as a dummy argument */
  410                 if ((*ip6_fw_chk_ptr)(&ip6, NULL, &port, &m)) {
  411                         m_freem(m);
  412                         m = NULL;
  413                 }
  414                 if (!m)
  415                         return;
  416         }
  417 
  418         /*
  419          * Check against address spoofing/corruption.
  420          */
  421         if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src) ||
  422             IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_dst)) {
  423                 /*
  424                  * XXX: "badscope" is not very suitable for a multicast source.
  425                  */
  426                 ip6stat.ip6s_badscope++;
  427                 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
  428                 goto bad;
  429         }
  430         if ((IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) ||
  431              IN6_IS_ADDR_LOOPBACK(&ip6->ip6_dst)) &&
  432             (m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
  433                 ip6stat.ip6s_badscope++;
  434                 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
  435                 goto bad;
  436         }
  437 
  438         /*
  439          * The following check is not documented in specs.  A malicious
  440          * party may be able to use IPv4 mapped addr to confuse tcp/udp stack
  441          * and bypass security checks (act as if it was from 127.0.0.1 by using
  442          * IPv6 src ::ffff:127.0.0.1).  Be cautious.
  443          *
  444          * This check chokes if we are in an SIIT cloud.  As none of BSDs
  445          * support IPv4-less kernel compilation, we cannot support SIIT
  446          * environment at all.  So, it makes more sense for us to reject any
  447          * malicious packets for non-SIIT environment, than try to do a
  448          * partical support for SIIT environment.
  449          */
  450         if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
  451             IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
  452                 ip6stat.ip6s_badscope++;
  453                 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
  454                 goto bad;
  455         }
  456 #if 0
  457         /*
  458          * Reject packets with IPv4 compatible addresses (auto tunnel).
  459          *
  460          * The code forbids auto tunnel relay case in RFC1933 (the check is
  461          * stronger than RFC1933).  We may want to re-enable it if mech-xx
  462          * is revised to forbid relaying case.
  463          */
  464         if (IN6_IS_ADDR_V4COMPAT(&ip6->ip6_src) ||
  465             IN6_IS_ADDR_V4COMPAT(&ip6->ip6_dst)) {
  466                 ip6stat.ip6s_badscope++;
  467                 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
  468                 goto bad;
  469         }
  470 #endif
  471 
  472         /* drop packets if interface ID portion is already filled */
  473         if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
  474                 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src) &&
  475                     ip6->ip6_src.s6_addr16[1]) {
  476                         ip6stat.ip6s_badscope++;
  477                         goto bad;
  478                 }
  479                 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst) &&
  480                     ip6->ip6_dst.s6_addr16[1]) {
  481                         ip6stat.ip6s_badscope++;
  482                         goto bad;
  483                 }
  484         }
  485 
  486         if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
  487                 ip6->ip6_src.s6_addr16[1]
  488                         = htons(m->m_pkthdr.rcvif->if_index);
  489         if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
  490                 ip6->ip6_dst.s6_addr16[1]
  491                         = htons(m->m_pkthdr.rcvif->if_index);
  492 
  493 #if 0 /* this case seems to be unnecessary. (jinmei, 20010401) */
  494         /*
  495          * We use rt->rt_ifp to determine if the address is ours or not.
  496          * If rt_ifp is lo0, the address is ours.
  497          * The problem here is, rt->rt_ifp for fe80::%lo0/64 is set to lo0,
  498          * so any address under fe80::%lo0/64 will be mistakenly considered
  499          * local.  The special case is supplied to handle the case properly
  500          * by actually looking at interface addresses
  501          * (using in6ifa_ifpwithaddr).
  502          */
  503         if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) != 0 &&
  504             IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst)) {
  505                 if (!in6ifa_ifpwithaddr(m->m_pkthdr.rcvif, &ip6->ip6_dst)) {
  506                         icmp6_error(m, ICMP6_DST_UNREACH,
  507                             ICMP6_DST_UNREACH_ADDR, 0);
  508                         /* m is already freed */
  509                         return;
  510                 }
  511 
  512                 ours = 1;
  513                 deliverifp = m->m_pkthdr.rcvif;
  514                 goto hbhcheck;
  515         }
  516 #endif
  517 
  518         /*
  519          * Multicast check
  520          */
  521         if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
  522                 struct  in6_multi *in6m = 0;
  523 
  524                 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_mcast);
  525                 /*
  526                  * See if we belong to the destination multicast group on the
  527                  * arrival interface.
  528                  */
  529                 IN6_LOOKUP_MULTI(ip6->ip6_dst, m->m_pkthdr.rcvif, in6m);
  530                 if (in6m)
  531                         ours = 1;
  532                 else if (!ip6_mrouter) {
  533                         ip6stat.ip6s_notmember++;
  534                         ip6stat.ip6s_cantforward++;
  535                         in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
  536                         goto bad;
  537                 }
  538                 deliverifp = m->m_pkthdr.rcvif;
  539                 goto hbhcheck;
  540         }
  541 
  542         /*
  543          *  Unicast check
  544          */
  545         switch (ip6_ours_check_algorithm) {
  546         default:
  547                 /*
  548                  * XXX: I intentionally broke our indentation rule here,
  549                  *      since this switch-case is just for measurement and
  550                  *      therefore should soon be removed.
  551                  */
  552         if (ip6_forward_rt.ro_rt != NULL &&
  553             (ip6_forward_rt.ro_rt->rt_flags & RTF_UP) != 0 && 
  554             IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
  555                                &((struct sockaddr_in6 *)(&ip6_forward_rt.ro_dst))->sin6_addr))
  556                 ip6stat.ip6s_forward_cachehit++;
  557         else {
  558                 struct sockaddr_in6 *dst6;
  559 
  560                 if (ip6_forward_rt.ro_rt) {
  561                         /* route is down or destination is different */
  562                         ip6stat.ip6s_forward_cachemiss++;
  563                         rtfree(ip6_forward_rt.ro_rt);
  564                         ip6_forward_rt.ro_rt = 0;
  565                 }
  566 
  567                 bzero(&ip6_forward_rt.ro_dst, sizeof(struct sockaddr_in6));
  568                 dst6 = (struct sockaddr_in6 *)&ip6_forward_rt.ro_dst;
  569                 dst6->sin6_len = sizeof(struct sockaddr_in6);
  570                 dst6->sin6_family = AF_INET6;
  571                 dst6->sin6_addr = ip6->ip6_dst;
  572 #if SCOPEDROUTING
  573                 ip6_forward_rt.ro_dst.sin6_scope_id =
  574                         in6_addr2scopeid(m->m_pkthdr.rcvif, &ip6->ip6_dst);
  575 #endif
  576 
  577                 rtalloc_ign((struct route *)&ip6_forward_rt, RTF_PRCLONING);
  578         }
  579 
  580 #define rt6_key(r) ((struct sockaddr_in6 *)((r)->rt_nodes->rn_key))
  581 
  582         /*
  583          * Accept the packet if the forwarding interface to the destination
  584          * according to the routing table is the loopback interface,
  585          * unless the associated route has a gateway.
  586          * Note that this approach causes to accept a packet if there is a
  587          * route to the loopback interface for the destination of the packet.
  588          * But we think it's even useful in some situations, e.g. when using
  589          * a special daemon which wants to intercept the packet.
  590          *
  591          * XXX: some OSes automatically make a cloned route for the destination
  592          * of an outgoing packet.  If the outgoing interface of the packet
  593          * is a loopback one, the kernel would consider the packet to be
  594          * accepted, even if we have no such address assinged on the interface.
  595          * We check the cloned flag of the route entry to reject such cases,
  596          * assuming that route entries for our own addresses are not made by
  597          * cloning (it should be true because in6_addloop explicitly installs
  598          * the host route).  However, we might have to do an explicit check
  599          * while it would be less efficient.  Or, should we rather install a
  600          * reject route for such a case?
  601          */
  602         if (ip6_forward_rt.ro_rt &&
  603             (ip6_forward_rt.ro_rt->rt_flags &
  604              (RTF_HOST|RTF_GATEWAY)) == RTF_HOST &&
  605 #if RTF_WASCLONED
  606             !(ip6_forward_rt.ro_rt->rt_flags & RTF_WASCLONED) &&
  607 #endif
  608 #if RTF_CLONED
  609             !(ip6_forward_rt.ro_rt->rt_flags & RTF_CLONED) &&
  610 #endif
  611 #if 0
  612             /*
  613              * The check below is redundant since the comparison of
  614              * the destination and the key of the rtentry has
  615              * already done through looking up the routing table.
  616              */
  617             IN6_ARE_ADDR_EQUAL(&ip6->ip6_dst,
  618                                 &rt6_key(ip6_forward_rt.ro_rt)->sin6_addr)
  619 #endif
  620             ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_LOOP) {
  621                 struct in6_ifaddr *ia6 =
  622                         (struct in6_ifaddr *)ip6_forward_rt.ro_rt->rt_ifa;
  623 
  624                 /*
  625                  * record address information into m_aux.
  626                  */
  627                 (void)ip6_setdstifaddr(m, ia6);
  628 
  629                 /*
  630                  * packets to a tentative, duplicated, or somehow invalid
  631                  * address must not be accepted.
  632                  */
  633                 if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
  634                         /* this address is ready */
  635                         ours = 1;
  636                         deliverifp = ia6->ia_ifp;       /* correct? */
  637                         /* Count the packet in the ip address stats */
  638 #ifndef __APPLE__
  639 
  640                         ia6->ia_ifa.if_ipackets++;
  641                         ia6->ia_ifa.if_ibytes += m->m_pkthdr.len;
  642 #endif
  643                         goto hbhcheck;
  644                 } else {
  645                         /* address is not ready, so discard the packet. */
  646                         nd6log((LOG_INFO,
  647                             "ip6_input: packet to an unready address %s->%s\n",
  648                             ip6_sprintf(&ip6->ip6_src),
  649                             ip6_sprintf(&ip6->ip6_dst)));
  650 
  651                         goto bad;
  652                 }
  653         }
  654         } /* XXX indentation (see above) */
  655 
  656         /*
  657          * FAITH(Firewall Aided Internet Translator)
  658          */
  659 #if defined(NFAITH) && 0 < NFAITH
  660         if (ip6_keepfaith) {
  661                 if (ip6_forward_rt.ro_rt && ip6_forward_rt.ro_rt->rt_ifp
  662                  && ip6_forward_rt.ro_rt->rt_ifp->if_type == IFT_FAITH) {
  663                         /* XXX do we need more sanity checks? */
  664                         ours = 1;
  665                         deliverifp = ip6_forward_rt.ro_rt->rt_ifp; /* faith */
  666                         goto hbhcheck;
  667                 }
  668         }
  669 #endif
  670 
  671         /*
  672          * Now there is no reason to process the packet if it's not our own
  673          * and we're not a router.
  674          */
  675         if (!ip6_forwarding) {
  676                 ip6stat.ip6s_cantforward++;
  677                 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
  678                 goto bad;
  679         }
  680 
  681   hbhcheck:
  682         /*
  683          * record address information into m_aux, if we don't have one yet.
  684          * note that we are unable to record it, if the address is not listed
  685          * as our interface address (e.g. multicast addresses, addresses
  686          * within FAITH prefixes and such).
  687          */
  688         if (deliverifp && !ip6_getdstifaddr(m)) {
  689                 struct in6_ifaddr *ia6;
  690 
  691                 ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
  692                 if (ia6) {
  693                         if (!ip6_setdstifaddr(m, ia6)) {
  694                                 /*
  695                                  * XXX maybe we should drop the packet here,
  696                                  * as we could not provide enough information
  697                                  * to the upper layers.
  698                                  */
  699                         }
  700                 }
  701         }
  702 
  703         /*
  704          * Process Hop-by-Hop options header if it's contained.
  705          * m may be modified in ip6_hopopts_input().
  706          * If a JumboPayload option is included, plen will also be modified.
  707          */
  708         plen = (u_int32_t)ntohs(ip6->ip6_plen);
  709         if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
  710                 struct ip6_hbh *hbh;
  711 
  712                 if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) {
  713 #if 0   /*touches NULL pointer*/
  714                         in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
  715 #endif
  716                         return; /* m have already been freed */
  717                 }
  718 
  719                 /* adjust pointer */
  720                 ip6 = mtod(m, struct ip6_hdr *);
  721 
  722                 /*
  723                  * if the payload length field is 0 and the next header field
  724                  * indicates Hop-by-Hop Options header, then a Jumbo Payload
  725                  * option MUST be included.
  726                  */
  727                 if (ip6->ip6_plen == 0 && plen == 0) {
  728                         /*
  729                          * Note that if a valid jumbo payload option is
  730                          * contained, ip6_hoptops_input() must set a valid
  731                          * (non-zero) payload length to the variable plen. 
  732                          */
  733                         ip6stat.ip6s_badoptions++;
  734                         in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_discard);
  735                         in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_hdrerr);
  736                         icmp6_error(m, ICMP6_PARAM_PROB,
  737                                     ICMP6_PARAMPROB_HEADER,
  738                                     (caddr_t)&ip6->ip6_plen - (caddr_t)ip6);
  739                         return;
  740                 }
  741 #ifndef PULLDOWN_TEST
  742                 /* ip6_hopopts_input() ensures that mbuf is contiguous */
  743                 hbh = (struct ip6_hbh *)(ip6 + 1);
  744 #else
  745                 IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
  746                         sizeof(struct ip6_hbh));
  747                 if (hbh == NULL) {
  748                         ip6stat.ip6s_tooshort++;
  749                         return;
  750                 }
  751 #endif
  752                 nxt = hbh->ip6h_nxt;
  753 
  754                 /*
  755                  * accept the packet if a router alert option is included
  756                  * and we act as an IPv6 router.
  757                  */
  758                 if (rtalert != ~0 && ip6_forwarding)
  759                         ours = 1;
  760         } else
  761                 nxt = ip6->ip6_nxt;
  762 
  763         /*
  764          * Check that the amount of data in the buffers
  765          * is as at least much as the IPv6 header would have us expect.
  766          * Trim mbufs if longer than we expect.
  767          * Drop packet if shorter than we expect.
  768          */
  769         if (m->m_pkthdr.len - sizeof(struct ip6_hdr) < plen) {
  770                 ip6stat.ip6s_tooshort++;
  771                 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
  772                 goto bad;
  773         }
  774         if (m->m_pkthdr.len > sizeof(struct ip6_hdr) + plen) {
  775                 if (m->m_len == m->m_pkthdr.len) {
  776                         m->m_len = sizeof(struct ip6_hdr) + plen;
  777                         m->m_pkthdr.len = sizeof(struct ip6_hdr) + plen;
  778                 } else
  779                         m_adj(m, sizeof(struct ip6_hdr) + plen - m->m_pkthdr.len);
  780         }
  781 
  782         /*
  783          * Forward if desirable.
  784          */
  785         if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
  786                 /*
  787                  * If we are acting as a multicast router, all
  788                  * incoming multicast packets are passed to the
  789                  * kernel-level multicast forwarding function.
  790                  * The packet is returned (relatively) intact; if
  791                  * ip6_mforward() returns a non-zero value, the packet
  792                  * must be discarded, else it may be accepted below.
  793                  */
  794                 if (ip6_mrouter && ip6_mforward(ip6, m->m_pkthdr.rcvif, m)) {
  795                         ip6stat.ip6s_cantforward++;
  796                         m_freem(m);
  797                         return;
  798                 }
  799                 if (!ours) {
  800                         m_freem(m);
  801                         return;
  802                 }
  803         } else if (!ours) {
  804                 ip6_forward(m, 0);
  805                 return;
  806         }       
  807 
  808         ip6 = mtod(m, struct ip6_hdr *);
  809 
  810         /*
  811          * Malicious party may be able to use IPv4 mapped addr to confuse
  812          * tcp/udp stack and bypass security checks (act as if it was from
  813          * 127.0.0.1 by using IPv6 src ::ffff:127.0.0.1).  Be cautious.
  814          *
  815          * For SIIT end node behavior, you may want to disable the check.
  816          * However, you will  become vulnerable to attacks using IPv4 mapped
  817          * source.
  818          */
  819         if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
  820             IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
  821                 ip6stat.ip6s_badscope++;
  822                 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_addrerr);
  823                 goto bad;
  824         }
  825 
  826         /*
  827          * Tell launch routine the next header
  828          */
  829         ip6stat.ip6s_delivered++;
  830         in6_ifstat_inc(deliverifp, ifs6_in_deliver);
  831         nest = 0;
  832 
  833         while (nxt != IPPROTO_DONE) {
  834                 if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
  835                         ip6stat.ip6s_toomanyhdr++;
  836                         goto bad;
  837                 }
  838 
  839                 /*
  840                  * protection against faulty packet - there should be
  841                  * more sanity checks in header chain processing.
  842                  */
  843                 if (m->m_pkthdr.len < off) {
  844                         ip6stat.ip6s_tooshort++;
  845                         in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated);
  846                         goto bad;
  847                 }
  848 
  849 #if 0
  850                 /*
  851                  * do we need to do it for every header?  yeah, other
  852                  * functions can play with it (like re-allocate and copy).
  853                  */
  854                 mhist = ip6_addaux(m);
  855                 if (mhist && M_TRAILINGSPACE(mhist) >= sizeof(nxt)) {
  856                         hist = mtod(mhist, caddr_t) + mhist->m_len;
  857                         bcopy(&nxt, hist, sizeof(nxt));
  858                         mhist->m_len += sizeof(nxt);
  859                 } else {
  860                         ip6stat.ip6s_toomanyhdr++;
  861                         goto bad;
  862                 }
  863 #endif
  864 
  865 #if IPSEC
  866                 /*
  867                  * enforce IPsec policy checking if we are seeing last header.
  868                  * note that we do not visit this with protocols with pcb layer
  869                  * code - like udp/tcp/raw ip.
  870                  */
  871                 if ((ipsec_bypass == 0) && (ip6_protox[nxt]->pr_flags & PR_LASTHDR) != 0 &&
  872                     ipsec6_in_reject(m, NULL)) {
  873                         ipsec6stat.in_polvio++;
  874                         goto bad;
  875                 }
  876 #endif
  877 
  878                 nxt = (*ip6_protox[nxt]->pr_input)(&m, &off);
  879         }
  880         return;
  881  bad:
  882         m_freem(m);
  883 }
  884 
  885 /*
  886  * set/grab in6_ifaddr correspond to IPv6 destination address.
  887  * XXX backward compatibility wrapper
  888  */
  889 static struct mbuf *
  890 ip6_setdstifaddr(m, ia6)
  891         struct mbuf *m;
  892         struct in6_ifaddr *ia6;
  893 {
  894         struct mbuf *n;
  895 
  896         n = ip6_addaux(m);
  897         if (n)
  898                 mtod(n, struct ip6aux *)->ip6a_dstia6 = ia6;
  899         return n;       /* NULL if failed to set */
  900 }
  901 
  902 struct in6_ifaddr *
  903 ip6_getdstifaddr(m)
  904         struct mbuf *m;
  905 {
  906         struct mbuf *n;
  907 
  908         n = ip6_findaux(m);
  909         if (n)
  910                 return mtod(n, struct ip6aux *)->ip6a_dstia6;
  911         else
  912                 return NULL;
  913 }
  914 
  915 /*
  916  * Hop-by-Hop options header processing. If a valid jumbo payload option is
  917  * included, the real payload length will be stored in plenp.
  918  */
  919 static int
  920 ip6_hopopts_input(plenp, rtalertp, mp, offp)
  921         u_int32_t *plenp;
  922         u_int32_t *rtalertp;    /* XXX: should be stored more smart way */
  923         struct mbuf **mp;
  924         int *offp;
  925 {
  926         struct mbuf *m = *mp;
  927         int off = *offp, hbhlen;
  928         struct ip6_hbh *hbh;
  929         u_int8_t *opt;
  930 
  931         /* validation of the length of the header */
  932 #ifndef PULLDOWN_TEST
  933         IP6_EXTHDR_CHECK(m, off, sizeof(*hbh), -1);
  934         hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
  935         hbhlen = (hbh->ip6h_len + 1) << 3;
  936 
  937         IP6_EXTHDR_CHECK(m, off, hbhlen, -1);
  938         hbh = (struct ip6_hbh *)(mtod(m, caddr_t) + off);
  939 #else
  940         IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m,
  941                 sizeof(struct ip6_hdr), sizeof(struct ip6_hbh));
  942         if (hbh == NULL) {
  943                 ip6stat.ip6s_tooshort++;
  944                 return -1;
  945         }
  946         hbhlen = (hbh->ip6h_len + 1) << 3;
  947         IP6_EXTHDR_GET(hbh, struct ip6_hbh *, m, sizeof(struct ip6_hdr),
  948                 hbhlen);
  949         if (hbh == NULL) {
  950                 ip6stat.ip6s_tooshort++;
  951                 return -1;
  952         }
  953 #endif
  954         off += hbhlen;
  955         hbhlen -= sizeof(struct ip6_hbh);
  956         opt = (u_int8_t *)hbh + sizeof(struct ip6_hbh);
  957 
  958         if (ip6_process_hopopts(m, (u_int8_t *)hbh + sizeof(struct ip6_hbh),
  959                                 hbhlen, rtalertp, plenp) < 0)
  960                 return(-1);
  961 
  962         *offp = off;
  963         *mp = m;
  964         return(0);
  965 }
  966 
  967 /*
  968  * Search header for all Hop-by-hop options and process each option.
  969  * This function is separate from ip6_hopopts_input() in order to
  970  * handle a case where the sending node itself process its hop-by-hop
  971  * options header. In such a case, the function is called from ip6_output().
  972  *
  973  * The function assumes that hbh header is located right after the IPv6 header
  974  * (RFC2460 p7), opthead is pointer into data content in m, and opthead to
  975  * opthead + hbhlen is located in continuous memory region.
  976  */
  977 int
  978 ip6_process_hopopts(m, opthead, hbhlen, rtalertp, plenp)
  979         struct mbuf *m;
  980         u_int8_t *opthead;
  981         int hbhlen;
  982         u_int32_t *rtalertp;
  983         u_int32_t *plenp;
  984 {
  985         struct ip6_hdr *ip6;
  986         int optlen = 0;
  987         u_int8_t *opt = opthead;
  988         u_int16_t rtalert_val;
  989         u_int32_t jumboplen;
  990         const int erroff = sizeof(struct ip6_hdr) + sizeof(struct ip6_hbh);
  991 
  992         for (; hbhlen > 0; hbhlen -= optlen, opt += optlen) {
  993                 switch (*opt) {
  994                 case IP6OPT_PAD1:
  995                         optlen = 1;
  996                         break;
  997                 case IP6OPT_PADN:
  998                         if (hbhlen < IP6OPT_MINLEN) {
  999                                 ip6stat.ip6s_toosmall++;
 1000                                 goto bad;
 1001                         }
 1002                         optlen = *(opt + 1) + 2;
 1003                         break;
 1004                 case IP6OPT_RTALERT:
 1005                         /* XXX may need check for alignment */
 1006                         if (hbhlen < IP6OPT_RTALERT_LEN) {
 1007                                 ip6stat.ip6s_toosmall++;
 1008                                 goto bad;
 1009                         }
 1010                         if (*(opt + 1) != IP6OPT_RTALERT_LEN - 2) {
 1011                                 /* XXX stat */
 1012                                 icmp6_error(m, ICMP6_PARAM_PROB,
 1013                                             ICMP6_PARAMPROB_HEADER,
 1014                                             erroff + opt + 1 - opthead);
 1015                                 return(-1);
 1016                         }
 1017                         optlen = IP6OPT_RTALERT_LEN;
 1018                         bcopy((caddr_t)(opt + 2), (caddr_t)&rtalert_val, 2);
 1019                         *rtalertp = ntohs(rtalert_val);
 1020                         break;
 1021                 case IP6OPT_JUMBO:
 1022                         /* XXX may need check for alignment */
 1023                         if (hbhlen < IP6OPT_JUMBO_LEN) {
 1024                                 ip6stat.ip6s_toosmall++;
 1025                                 goto bad;
 1026                         }
 1027                         if (*(opt + 1) != IP6OPT_JUMBO_LEN - 2) {
 1028                                 /* XXX stat */
 1029                                 icmp6_error(m, ICMP6_PARAM_PROB,
 1030                                             ICMP6_PARAMPROB_HEADER,
 1031                                             erroff + opt + 1 - opthead);
 1032                                 return(-1);
 1033                         }
 1034                         optlen = IP6OPT_JUMBO_LEN;
 1035 
 1036                         /*
 1037                          * IPv6 packets that have non 0 payload length
 1038                          * must not contain a jumbo payload option.
 1039                          */
 1040                         ip6 = mtod(m, struct ip6_hdr *);
 1041                         if (ip6->ip6_plen) {
 1042                                 ip6stat.ip6s_badoptions++;
 1043                                 icmp6_error(m, ICMP6_PARAM_PROB,
 1044                                             ICMP6_PARAMPROB_HEADER,
 1045                                             erroff + opt - opthead);
 1046                                 return(-1);
 1047                         }
 1048 
 1049                         /*
 1050                          * We may see jumbolen in unaligned location, so
 1051                          * we'd need to perform bcopy().
 1052                          */
 1053                         bcopy(opt + 2, &jumboplen, sizeof(jumboplen));
 1054                         jumboplen = (u_int32_t)htonl(jumboplen);
 1055 
 1056 #if 1
 1057                         /*
 1058                          * if there are multiple jumbo payload options,
 1059                          * *plenp will be non-zero and the packet will be
 1060                          * rejected.
 1061                          * the behavior may need some debate in ipngwg -
 1062                          * multiple options does not make sense, however,
 1063                          * there's no explicit mention in specification.
 1064                          */
 1065                         if (*plenp != 0) {
 1066                                 ip6stat.ip6s_badoptions++;
 1067                                 icmp6_error(m, ICMP6_PARAM_PROB,
 1068                                             ICMP6_PARAMPROB_HEADER,
 1069                                             erroff + opt + 2 - opthead);
 1070                                 return(-1);
 1071                         }
 1072 #endif
 1073 
 1074                         /*
 1075                          * jumbo payload length must be larger than 65535.
 1076                          */
 1077                         if (jumboplen <= IPV6_MAXPACKET) {
 1078                                 ip6stat.ip6s_badoptions++;
 1079                                 icmp6_error(m, ICMP6_PARAM_PROB,
 1080                                             ICMP6_PARAMPROB_HEADER,
 1081                                             erroff + opt + 2 - opthead);
 1082                                 return(-1);
 1083                         }
 1084                         *plenp = jumboplen;
 1085 
 1086                         break;
 1087                 default:                /* unknown option */
 1088                         if (hbhlen < IP6OPT_MINLEN) {
 1089                                 ip6stat.ip6s_toosmall++;
 1090                                 goto bad;
 1091                         }
 1092                         optlen = ip6_unknown_opt(opt, m,
 1093                             erroff + opt - opthead);
 1094                         if (optlen == -1)
 1095                                 return(-1);
 1096                         optlen += 2;
 1097                         break;
 1098                 }
 1099         }
 1100 
 1101         return(0);
 1102 
 1103   bad:
 1104         m_freem(m);
 1105         return(-1);
 1106 }
 1107 
 1108 /*
 1109  * Unknown option processing.
 1110  * The third argument `off' is the offset from the IPv6 header to the option,
 1111  * which is necessary if the IPv6 header the and option header and IPv6 header
 1112  * is not continuous in order to return an ICMPv6 error.
 1113  */
 1114 int
 1115 ip6_unknown_opt(optp, m, off)
 1116         u_int8_t *optp;
 1117         struct mbuf *m;
 1118         int off;
 1119 {
 1120         struct ip6_hdr *ip6;
 1121 
 1122         switch (IP6OPT_TYPE(*optp)) {
 1123         case IP6OPT_TYPE_SKIP: /* ignore the option */
 1124                 return((int)*(optp + 1));
 1125         case IP6OPT_TYPE_DISCARD:       /* silently discard */
 1126                 m_freem(m);
 1127                 return(-1);
 1128         case IP6OPT_TYPE_FORCEICMP: /* send ICMP even if multicasted */
 1129                 ip6stat.ip6s_badoptions++;
 1130                 icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, off);
 1131                 return(-1);
 1132         case IP6OPT_TYPE_ICMP: /* send ICMP if not multicasted */
 1133                 ip6stat.ip6s_badoptions++;
 1134                 ip6 = mtod(m, struct ip6_hdr *);
 1135                 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) ||
 1136                     (m->m_flags & (M_BCAST|M_MCAST)))
 1137                         m_freem(m);
 1138                 else
 1139                         icmp6_error(m, ICMP6_PARAM_PROB,
 1140                                     ICMP6_PARAMPROB_OPTION, off);
 1141                 return(-1);
 1142         }
 1143 
 1144         m_freem(m);             /* XXX: NOTREACHED */
 1145         return(-1);
 1146 }
 1147 
 1148 /*
 1149  * Create the "control" list for this pcb.
 1150  * The function will not modify mbuf chain at all.
 1151  *
 1152  * with KAME mbuf chain restriction:
 1153  * The routine will be called from upper layer handlers like tcp6_input().
 1154  * Thus the routine assumes that the caller (tcp6_input) have already
 1155  * called IP6_EXTHDR_CHECK() and all the extension headers are located in the
 1156  * very first mbuf on the mbuf chain.
 1157  */
 1158 void
 1159 ip6_savecontrol(in6p, mp, ip6, m)
 1160         struct inpcb *in6p;
 1161         struct mbuf **mp;
 1162         struct ip6_hdr *ip6;
 1163         struct mbuf *m;
 1164 {
 1165         struct proc *p = current_proc();        /* XXX */
 1166         int privileged = 0;
 1167         int rthdr_exist = 0;
 1168 
 1169 #ifdef __APPLE__
 1170         if (p && !suser(p->p_ucred, &p->p_acflag))
 1171 #else
 1172         if (p && !suser(p))
 1173 #endif
 1174                 privileged++;
 1175 
 1176 #if SO_TIMESTAMP
 1177         if ((in6p->in6p_socket->so_options & SO_TIMESTAMP) != 0) {
 1178                 struct timeval tv;
 1179 
 1180                 microtime(&tv);
 1181                 *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
 1182                                       SCM_TIMESTAMP, SOL_SOCKET);
 1183                 if (*mp) {
 1184                         mp = &(*mp)->m_next;
 1185                 }
 1186         }
 1187 #endif
 1188 
 1189         /* RFC 2292 sec. 5 */
 1190         if ((in6p->in6p_flags & IN6P_PKTINFO) != 0) {
 1191                 struct in6_pktinfo pi6;
 1192                 bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr));
 1193                 if (IN6_IS_SCOPE_LINKLOCAL(&pi6.ipi6_addr))
 1194                         pi6.ipi6_addr.s6_addr16[1] = 0;
 1195                 pi6.ipi6_ifindex = (m && m->m_pkthdr.rcvif)
 1196                                         ? m->m_pkthdr.rcvif->if_index
 1197                                         : 0;
 1198                 *mp = sbcreatecontrol((caddr_t) &pi6,
 1199                         sizeof(struct in6_pktinfo), IPV6_PKTINFO,
 1200                         IPPROTO_IPV6);
 1201                 if (*mp)
 1202                         mp = &(*mp)->m_next;
 1203         }
 1204 
 1205         if ((in6p->in6p_flags & IN6P_HOPLIMIT) != 0) {
 1206                 int hlim = ip6->ip6_hlim & 0xff;
 1207                 *mp = sbcreatecontrol((caddr_t) &hlim,
 1208                         sizeof(int), IPV6_HOPLIMIT, IPPROTO_IPV6);
 1209                 if (*mp)
 1210                         mp = &(*mp)->m_next;
 1211         }
 1212 
 1213         /*
 1214          * IPV6_HOPOPTS socket option. We require super-user privilege
 1215          * for the option, but it might be too strict, since there might
 1216          * be some hop-by-hop options which can be returned to normal user.
 1217          * See RFC 2292 section 6.
 1218          */
 1219         if ((in6p->in6p_flags & IN6P_HOPOPTS) != 0 && privileged) {
 1220                 /*
 1221                  * Check if a hop-by-hop options header is contatined in the
 1222                  * received packet, and if so, store the options as ancillary
 1223                  * data. Note that a hop-by-hop options header must be
 1224                  * just after the IPv6 header, which fact is assured through
 1225                  * the IPv6 input processing.
 1226                  */
 1227                 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
 1228                 if (ip6->ip6_nxt == IPPROTO_HOPOPTS) {
 1229                         struct ip6_hbh *hbh;
 1230                         int hbhlen = 0;
 1231 #if PULLDOWN_TEST
 1232                         struct mbuf *ext;
 1233 #endif
 1234 
 1235 #ifndef PULLDOWN_TEST
 1236                         hbh = (struct ip6_hbh *)(ip6 + 1);
 1237                         hbhlen = (hbh->ip6h_len + 1) << 3;
 1238 #else
 1239                         ext = ip6_pullexthdr(m, sizeof(struct ip6_hdr),
 1240                             ip6->ip6_nxt);
 1241                         if (ext == NULL) {
 1242                                 ip6stat.ip6s_tooshort++;
 1243                                 return;
 1244                         }
 1245                         hbh = mtod(ext, struct ip6_hbh *);
 1246                         hbhlen = (hbh->ip6h_len + 1) << 3;
 1247                         if (hbhlen != ext->m_len) {
 1248                                 m_freem(ext);
 1249                                 ip6stat.ip6s_tooshort++;
 1250                                 return;
 1251                         }
 1252 #endif
 1253 
 1254                         /*
 1255                          * XXX: We copy whole the header even if a jumbo
 1256                          * payload option is included, which option is to
 1257                          * be removed before returning in the RFC 2292.
 1258                          * Note: this constraint is removed in 2292bis.
 1259                          */
 1260                         *mp = sbcreatecontrol((caddr_t)hbh, hbhlen,
 1261                                               IPV6_HOPOPTS, IPPROTO_IPV6);
 1262                         if (*mp)
 1263                                 mp = &(*mp)->m_next;
 1264 #if PULLDOWN_TEST
 1265                         m_freem(ext);
 1266 #endif
 1267                 }
 1268         }
 1269 
 1270         /* IPV6_DSTOPTS and IPV6_RTHDR socket options */
 1271         if ((in6p->in6p_flags & (IN6P_DSTOPTS | IN6P_RTHDRDSTOPTS)) != 0) {
 1272                 int proto, off, nxt;
 1273 
 1274                 /*
 1275                  * go through the header chain to see if a routing header is
 1276                  * contained in the packet. We need this information to store
 1277                  * destination options headers (if any) properly.
 1278                  * XXX: performance issue. We should record this info when
 1279                  * processing extension headers in incoming routine.
 1280                  * (todo) use m_aux? 
 1281                  */
 1282                 proto = IPPROTO_IPV6;
 1283                 off = 0;
 1284                 nxt = -1;
 1285                 while (1) {
 1286                         int newoff;
 1287 
 1288                         newoff = ip6_nexthdr(m, off, proto, &nxt);
 1289                         if (newoff < 0)
 1290                                 break;
 1291                         if (newoff < off) /* invalid, check for safety */
 1292                                 break;
 1293                         if ((proto = nxt) == IPPROTO_ROUTING) {
 1294                                 rthdr_exist = 1;
 1295                                 break;
 1296                         }
 1297                         off = newoff;
 1298                 }
 1299         }
 1300 
 1301         if ((in6p->in6p_flags &
 1302              (IN6P_RTHDR | IN6P_DSTOPTS | IN6P_RTHDRDSTOPTS)) != 0) {
 1303                 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
 1304                 int nxt = ip6->ip6_nxt, off = sizeof(struct ip6_hdr);
 1305 
 1306                 /*
 1307                  * Search for destination options headers or routing
 1308                  * header(s) through the header chain, and stores each
 1309                  * header as ancillary data.
 1310                  * Note that the order of the headers remains in
 1311                  * the chain of ancillary data.
 1312                  */
 1313                 while (1) {     /* is explicit loop prevention necessary? */
 1314                         struct ip6_ext *ip6e = NULL;
 1315                         int elen;
 1316 #if PULLDOWN_TEST
 1317                         struct mbuf *ext = NULL;
 1318 #endif
 1319 
 1320                         /*
 1321                          * if it is not an extension header, don't try to
 1322                          * pull it from the chain.
 1323                          */
 1324                         switch (nxt) {
 1325                         case IPPROTO_DSTOPTS:
 1326                         case IPPROTO_ROUTING:
 1327                         case IPPROTO_HOPOPTS:
 1328                         case IPPROTO_AH: /* is it possible? */
 1329                                 break;
 1330                         default:
 1331                                 goto loopend;
 1332                         }
 1333 
 1334 #ifndef PULLDOWN_TEST
 1335                         if (off + sizeof(*ip6e) > m->m_len)
 1336                                 goto loopend;
 1337                         ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + off);
 1338                         if (nxt == IPPROTO_AH)
 1339                                 elen = (ip6e->ip6e_len + 2) << 2;
 1340                         else
 1341                                 elen = (ip6e->ip6e_len + 1) << 3;
 1342                         if (off + elen > m->m_len)
 1343                                 goto loopend;
 1344 #else
 1345                         ext = ip6_pullexthdr(m, off, nxt);
 1346                         if (ext == NULL) {
 1347                                 ip6stat.ip6s_tooshort++;
 1348                                 return;
 1349                         }
 1350                         ip6e = mtod(ext, struct ip6_ext *);
 1351                         if (nxt == IPPROTO_AH)
 1352                                 elen = (ip6e->ip6e_len + 2) << 2;
 1353                         else
 1354                                 elen = (ip6e->ip6e_len + 1) << 3;
 1355                         if (elen != ext->m_len) {
 1356                                 m_freem(ext);
 1357                                 ip6stat.ip6s_tooshort++;
 1358                                 return;
 1359                         }
 1360 #endif
 1361 
 1362                         switch (nxt) {
 1363                         case IPPROTO_DSTOPTS:
 1364                                 if ((in6p->in6p_flags & IN6P_DSTOPTS) == 0)
 1365                                         break;
 1366 
 1367                                 /*
 1368                                  * We also require super-user privilege for
 1369                                  * the option.
 1370                                  * See the comments on IN6_HOPOPTS.
 1371                                  */
 1372                                 if (!privileged)
 1373                                         break;
 1374 
 1375                                 *mp = sbcreatecontrol((caddr_t)ip6e, elen,
 1376                                                       IPV6_DSTOPTS,
 1377                                                       IPPROTO_IPV6);
 1378                                 if (*mp)
 1379                                         mp = &(*mp)->m_next;
 1380                                 break;
 1381                         case IPPROTO_ROUTING:
 1382                                 if (!in6p->in6p_flags & IN6P_RTHDR)
 1383                                         break;
 1384 
 1385                                 *mp = sbcreatecontrol((caddr_t)ip6e, elen,
 1386                                                       IPV6_RTHDR,
 1387                                                       IPPROTO_IPV6);
 1388                                 if (*mp)
 1389                                         mp = &(*mp)->m_next;
 1390                                 break;
 1391                         case IPPROTO_HOPOPTS:
 1392                         case IPPROTO_AH: /* is it possible? */
 1393                                 break;
 1394 
 1395                         default:
 1396                                 /*
 1397                                  * other cases have been filtered in the above.
 1398                                  * none will visit this case.  here we supply
 1399                                  * the code just in case (nxt overwritten or
 1400                                  * other cases).
 1401                                  */
 1402 #if PULLDOWN_TEST
 1403                                 m_freem(ext);
 1404 #endif
 1405                                 goto loopend;
 1406 
 1407                         }
 1408 
 1409                         /* proceed with the next header. */
 1410                         off += elen;
 1411                         nxt = ip6e->ip6e_nxt;
 1412                         ip6e = NULL;
 1413 #if PULLDOWN_TEST
 1414                         m_freem(ext);
 1415                         ext = NULL;
 1416 #endif
 1417                 }
 1418           loopend:
 1419                 ;
 1420         }
 1421 
 1422 }
 1423 
 1424 #if PULLDOWN_TEST
 1425 /*
 1426  * pull single extension header from mbuf chain.  returns single mbuf that
 1427  * contains the result, or NULL on error.
 1428  */
 1429 static struct mbuf *
 1430 ip6_pullexthdr(m, off, nxt)
 1431         struct mbuf *m;
 1432         size_t off;
 1433         int nxt;
 1434 {
 1435         struct ip6_ext ip6e;
 1436         size_t elen;
 1437         struct mbuf *n;
 1438 
 1439 #if DIAGNOSTIC
 1440         switch (nxt) {
 1441         case IPPROTO_DSTOPTS:
 1442         case IPPROTO_ROUTING:
 1443         case IPPROTO_HOPOPTS:
 1444         case IPPROTO_AH: /* is it possible? */
 1445                 break;
 1446         default:
 1447                 printf("ip6_pullexthdr: invalid nxt=%d\n", nxt);
 1448         }
 1449 #endif
 1450 
 1451         m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
 1452         if (nxt == IPPROTO_AH)
 1453                 elen = (ip6e.ip6e_len + 2) << 2;
 1454         else
 1455                 elen = (ip6e.ip6e_len + 1) << 3;
 1456 
 1457         MGET(n, M_DONTWAIT, MT_DATA);
 1458         if (n && elen >= MLEN) {
 1459                 MCLGET(n, M_DONTWAIT);
 1460                 if ((n->m_flags & M_EXT) == 0) {
 1461                         m_free(n);
 1462                         n = NULL;
 1463                 }
 1464         }
 1465         if (!n)
 1466                 return NULL;
 1467 
 1468         n->m_len = 0;
 1469         if (elen >= M_TRAILINGSPACE(n)) {
 1470                 m_free(n);
 1471                 return NULL;
 1472         }
 1473 
 1474         m_copydata(m, off, elen, mtod(n, caddr_t));
 1475         n->m_len = elen;
 1476         return n;
 1477 }
 1478 #endif
 1479 
 1480 /*
 1481  * Get pointer to the previous header followed by the header
 1482  * currently processed.
 1483  * XXX: This function supposes that
 1484  *      M includes all headers,
 1485  *      the next header field and the header length field of each header
 1486  *      are valid, and
 1487  *      the sum of each header length equals to OFF.
 1488  * Because of these assumptions, this function must be called very
 1489  * carefully. Moreover, it will not be used in the near future when
 1490  * we develop `neater' mechanism to process extension headers.
 1491  */
 1492 char *
 1493 ip6_get_prevhdr(m, off)
 1494         struct mbuf *m;
 1495         int off;
 1496 {
 1497         struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
 1498 
 1499         if (off == sizeof(struct ip6_hdr))
 1500                 return(&ip6->ip6_nxt);
 1501         else {
 1502                 int len, nxt;
 1503                 struct ip6_ext *ip6e = NULL;
 1504 
 1505                 nxt = ip6->ip6_nxt;
 1506                 len = sizeof(struct ip6_hdr);
 1507                 while (len < off) {
 1508                         ip6e = (struct ip6_ext *)(mtod(m, caddr_t) + len);
 1509 
 1510                         switch (nxt) {
 1511                         case IPPROTO_FRAGMENT:
 1512                                 len += sizeof(struct ip6_frag);
 1513                                 break;
 1514                         case IPPROTO_AH:
 1515                                 len += (ip6e->ip6e_len + 2) << 2;
 1516                                 break;
 1517                         default:
 1518                                 len += (ip6e->ip6e_len + 1) << 3;
 1519                                 break;
 1520                         }
 1521                         nxt = ip6e->ip6e_nxt;
 1522                 }
 1523                 if (ip6e)
 1524                         return(&ip6e->ip6e_nxt);
 1525                 else
 1526                         return NULL;
 1527         }
 1528 }
 1529 
 1530 /*
 1531  * get next header offset.  m will be retained.
 1532  */
 1533 int
 1534 ip6_nexthdr(m, off, proto, nxtp)
 1535         struct mbuf *m;
 1536         int off;
 1537         int proto;
 1538         int *nxtp;
 1539 {
 1540         struct ip6_hdr ip6;
 1541         struct ip6_ext ip6e;
 1542         struct ip6_frag fh;
 1543 
 1544         /* just in case */
 1545         if (m == NULL)
 1546                 panic("ip6_nexthdr: m == NULL");
 1547         if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.len < off)
 1548                 return -1;
 1549 
 1550         switch (proto) {
 1551         case IPPROTO_IPV6:
 1552                 if (m->m_pkthdr.len < off + sizeof(ip6))
 1553                         return -1;
 1554                 m_copydata(m, off, sizeof(ip6), (caddr_t)&ip6);
 1555                 if (nxtp)
 1556                         *nxtp = ip6.ip6_nxt;
 1557                 off += sizeof(ip6);
 1558                 return off;
 1559 
 1560         case IPPROTO_FRAGMENT:
 1561                 /*
 1562                  * terminate parsing if it is not the first fragment,
 1563                  * it does not make sense to parse through it.
 1564                  */
 1565                 if (m->m_pkthdr.len < off + sizeof(fh))
 1566                         return -1;
 1567                 m_copydata(m, off, sizeof(fh), (caddr_t)&fh);
 1568                 if ((ntohs(fh.ip6f_offlg) & IP6F_OFF_MASK) != 0)
 1569                         return -1;
 1570                 if (nxtp)
 1571                         *nxtp = fh.ip6f_nxt;
 1572                 off += sizeof(struct ip6_frag);
 1573                 return off;
 1574 
 1575         case IPPROTO_AH:
 1576                 if (m->m_pkthdr.len < off + sizeof(ip6e))
 1577                         return -1;
 1578                 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
 1579                 if (nxtp)
 1580                         *nxtp = ip6e.ip6e_nxt;
 1581                 off += (ip6e.ip6e_len + 2) << 2;
 1582                 return off;
 1583 
 1584         case IPPROTO_HOPOPTS:
 1585         case IPPROTO_ROUTING:
 1586         case IPPROTO_DSTOPTS:
 1587                 if (m->m_pkthdr.len < off + sizeof(ip6e))
 1588                         return -1;
 1589                 m_copydata(m, off, sizeof(ip6e), (caddr_t)&ip6e);
 1590                 if (nxtp)
 1591                         *nxtp = ip6e.ip6e_nxt;
 1592                 off += (ip6e.ip6e_len + 1) << 3;
 1593                 return off;
 1594 
 1595         case IPPROTO_NONE:
 1596         case IPPROTO_ESP:
 1597         case IPPROTO_IPCOMP:
 1598                 /* give up */
 1599                 return -1;
 1600 
 1601         default:
 1602                 return -1;
 1603         }
 1604 
 1605         return -1;
 1606 }
 1607 
 1608 /*
 1609  * get offset for the last header in the chain.  m will be kept untainted.
 1610  */
 1611 int
 1612 ip6_lasthdr(m, off, proto, nxtp)
 1613         struct mbuf *m;
 1614         int off;
 1615         int proto;
 1616         int *nxtp;
 1617 {
 1618         int newoff;
 1619         int nxt;
 1620 
 1621         if (!nxtp) {
 1622                 nxt = -1;
 1623                 nxtp = &nxt;
 1624         }
 1625         while (1) {
 1626                 newoff = ip6_nexthdr(m, off, proto, nxtp);
 1627                 if (newoff < 0)
 1628                         return off;
 1629                 else if (newoff < off)
 1630                         return -1;      /* invalid */
 1631                 else if (newoff == off)
 1632                         return newoff;
 1633 
 1634                 off = newoff;
 1635                 proto = *nxtp;
 1636         }
 1637 }
 1638 
 1639 struct mbuf *
 1640 ip6_addaux(m)
 1641         struct mbuf *m;
 1642 {
 1643         struct mbuf *n;
 1644 
 1645 #if DIAGNOSTIC
 1646         if (sizeof(struct ip6aux) > MHLEN)
 1647                 panic("assumption failed on sizeof(ip6aux)");
 1648 #endif
 1649         n = m_aux_find(m, AF_INET6, -1);
 1650         if (n) {
 1651                 if (n->m_len < sizeof(struct ip6aux)) {
 1652                         printf("conflicting use of ip6aux");
 1653                         return NULL;
 1654                 }
 1655         } else {
 1656                 n = m_aux_add(m, AF_INET6, -1);
 1657                 if (n) {
 1658                         n->m_len = sizeof(struct ip6aux);
 1659                         bzero(mtod(n, caddr_t), n->m_len);
 1660                 }
 1661         }
 1662         return n;
 1663 }
 1664 
 1665 struct mbuf *
 1666 ip6_findaux(m)
 1667         struct mbuf *m;
 1668 {
 1669         struct mbuf *n;
 1670 
 1671         n = m_aux_find(m, AF_INET6, -1);
 1672         if (n && n->m_len < sizeof(struct ip6aux)) {
 1673                 printf("conflicting use of ip6aux");
 1674                 n = NULL;
 1675         }
 1676         return n;
 1677 }
 1678 
 1679 void
 1680 ip6_delaux(m)
 1681         struct mbuf *m;
 1682 {
 1683         struct mbuf *n;
 1684 
 1685         n = m_aux_find(m, AF_INET6, -1);
 1686         if (n)
 1687                 m_aux_delete(m, n);
 1688 }
 1689 
 1690 /*
 1691  * System control for IP6
 1692  */
 1693 
 1694 u_char  inet6ctlerrmap[PRC_NCMDS] = {
 1695         0,              0,              0,              0,
 1696         0,              EMSGSIZE,       EHOSTDOWN,      EHOSTUNREACH,
 1697         EHOSTUNREACH,   EHOSTUNREACH,   ECONNREFUSED,   ECONNREFUSED,
 1698         EMSGSIZE,       EHOSTUNREACH,   0,              0,
 1699         0,              0,              0,              0,
 1700         ENOPROTOOPT
 1701 };

Cache object: 35943471aa1c1017c0bafe18b824ad6e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.