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/netinet6/ip6_output.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 /*      $NetBSD: ip6_output.c,v 1.82.2.1 2004/06/14 18:01:09 tron Exp $ */
    2 /*      $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 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, 1990, 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. Neither the name of the University nor the names of its contributors
   46  *    may be used to endorse or promote products derived from this software
   47  *    without specific prior written permission.
   48  *
   49  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   52  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   53  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   58  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   59  * SUCH DAMAGE.
   60  *
   61  *      @(#)ip_output.c 8.3 (Berkeley) 1/21/94
   62  */
   63 
   64 #include <sys/cdefs.h>
   65 __KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.82.2.1 2004/06/14 18:01:09 tron Exp $");
   66 
   67 #include "opt_inet.h"
   68 #include "opt_ipsec.h"
   69 #include "opt_pfil_hooks.h"
   70 
   71 #include <sys/param.h>
   72 #include <sys/malloc.h>
   73 #include <sys/mbuf.h>
   74 #include <sys/errno.h>
   75 #include <sys/protosw.h>
   76 #include <sys/socket.h>
   77 #include <sys/socketvar.h>
   78 #include <sys/systm.h>
   79 #include <sys/proc.h>
   80 
   81 #include <net/if.h>
   82 #include <net/route.h>
   83 #ifdef PFIL_HOOKS
   84 #include <net/pfil.h>
   85 #endif
   86 
   87 #include <netinet/in.h>
   88 #include <netinet/in_var.h>
   89 #include <netinet/ip6.h>
   90 #include <netinet/icmp6.h>
   91 #include <netinet6/ip6_var.h>
   92 #include <netinet6/in6_pcb.h>
   93 #include <netinet6/nd6.h>
   94 #include <netinet6/ip6protosw.h>
   95 
   96 #ifdef IPSEC
   97 #include <netinet6/ipsec.h>
   98 #include <netkey/key.h>
   99 #endif /* IPSEC */
  100 
  101 #include "loop.h"
  102 
  103 #include <net/net_osdep.h>
  104 
  105 #ifdef PFIL_HOOKS
  106 extern struct pfil_head inet6_pfil_hook;        /* XXX */
  107 #endif
  108 
  109 struct ip6_exthdrs {
  110         struct mbuf *ip6e_ip6;
  111         struct mbuf *ip6e_hbh;
  112         struct mbuf *ip6e_dest1;
  113         struct mbuf *ip6e_rthdr;
  114         struct mbuf *ip6e_dest2;
  115 };
  116 
  117 static int ip6_pcbopts __P((struct ip6_pktopts **, struct mbuf *,
  118         struct socket *));
  119 static int ip6_setmoptions __P((int, struct ip6_moptions **, struct mbuf *));
  120 static int ip6_getmoptions __P((int, struct ip6_moptions *, struct mbuf **));
  121 static int ip6_copyexthdr __P((struct mbuf **, caddr_t, int));
  122 static int ip6_insertfraghdr __P((struct mbuf *, struct mbuf *, int,
  123         struct ip6_frag **));
  124 static int ip6_insert_jumboopt __P((struct ip6_exthdrs *, u_int32_t));
  125 static int ip6_splithdr __P((struct mbuf *, struct ip6_exthdrs *));
  126 
  127 extern struct ifnet loif[NLOOP];
  128 
  129 /*
  130  * IP6 output. The packet in mbuf chain m contains a skeletal IP6
  131  * header (with pri, len, nxt, hlim, src, dst).
  132  * This function may modify ver and hlim only.
  133  * The mbuf chain containing the packet will be freed.
  134  * The mbuf opt, if present, will not be freed.
  135  *
  136  * type of "mtu": rt_rmx.rmx_mtu is u_long, ifnet.ifr_mtu is int, and
  137  * nd_ifinfo.linkmtu is u_int32_t.  so we use u_long to hold largest one,
  138  * which is rt_rmx.rmx_mtu.
  139  */
  140 int
  141 ip6_output(m0, opt, ro, flags, im6o, so, ifpp)
  142         struct mbuf *m0;
  143         struct ip6_pktopts *opt;
  144         struct route_in6 *ro;
  145         int flags;
  146         struct ip6_moptions *im6o;
  147         struct socket *so;
  148         struct ifnet **ifpp;            /* XXX: just for statistics */
  149 {
  150         struct ip6_hdr *ip6, *mhip6;
  151         struct ifnet *ifp, *origifp;
  152         struct mbuf *m = m0;
  153         int hlen, tlen, len, off;
  154         struct route_in6 ip6route;
  155         struct sockaddr_in6 *dst;
  156         int error = 0;
  157         u_long mtu;
  158         int alwaysfrag, dontfrag;
  159         u_int32_t optlen = 0, plen = 0, unfragpartlen = 0;
  160         struct ip6_exthdrs exthdrs;
  161         struct in6_addr finaldst;
  162         struct route_in6 *ro_pmtu = NULL;
  163         int hdrsplit = 0;
  164         int needipsec = 0;
  165 #ifdef IPSEC
  166         int needipsectun = 0;
  167         struct secpolicy *sp = NULL;
  168 
  169         ip6 = mtod(m, struct ip6_hdr *);
  170 #endif /* IPSEC */
  171 
  172 #define MAKE_EXTHDR(hp, mp)                                             \
  173     do {                                                                \
  174         if (hp) {                                                       \
  175                 struct ip6_ext *eh = (struct ip6_ext *)(hp);            \
  176                 error = ip6_copyexthdr((mp), (caddr_t)(hp),             \
  177                     ((eh)->ip6e_len + 1) << 3);                         \
  178                 if (error)                                              \
  179                         goto freehdrs;                                  \
  180         }                                                               \
  181     } while (/*CONSTCOND*/ 0)
  182 
  183         bzero(&exthdrs, sizeof(exthdrs));
  184         if (opt) {
  185                 /* Hop-by-Hop options header */
  186                 MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh);
  187                 /* Destination options header(1st part) */
  188                 MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1);
  189                 /* Routing header */
  190                 MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr);
  191                 /* Destination options header(2nd part) */
  192                 MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2);
  193         }
  194 
  195 #ifdef IPSEC
  196         if ((flags & IPV6_FORWARDING) != 0) {
  197                 needipsec = 0;
  198                 goto skippolicycheck;
  199         }
  200 
  201         /* get a security policy for this packet */
  202         if (so == NULL)
  203                 sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error);
  204         else {
  205                 if (IPSEC_PCB_SKIP_IPSEC(sotoinpcb_hdr(so)->inph_sp,
  206                                          IPSEC_DIR_OUTBOUND)) {
  207                         needipsec = 0;
  208                         goto skippolicycheck;
  209                 }
  210                 sp = ipsec6_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error);
  211         }
  212 
  213         if (sp == NULL) {
  214                 ipsec6stat.out_inval++;
  215                 goto freehdrs;
  216         }
  217 
  218         error = 0;
  219 
  220         /* check policy */
  221         switch (sp->policy) {
  222         case IPSEC_POLICY_DISCARD:
  223                 /*
  224                  * This packet is just discarded.
  225                  */
  226                 ipsec6stat.out_polvio++;
  227                 goto freehdrs;
  228 
  229         case IPSEC_POLICY_BYPASS:
  230         case IPSEC_POLICY_NONE:
  231                 /* no need to do IPsec. */
  232                 needipsec = 0;
  233                 break;
  234 
  235         case IPSEC_POLICY_IPSEC:
  236                 if (sp->req == NULL) {
  237                         /* XXX should be panic ? */
  238                         printf("ip6_output: No IPsec request specified.\n");
  239                         error = EINVAL;
  240                         goto freehdrs;
  241                 }
  242                 needipsec = 1;
  243                 break;
  244 
  245         case IPSEC_POLICY_ENTRUST:
  246         default:
  247                 printf("ip6_output: Invalid policy found. %d\n", sp->policy);
  248         }
  249 
  250   skippolicycheck:;
  251 #endif /* IPSEC */
  252 
  253         /*
  254          * Calculate the total length of the extension header chain.
  255          * Keep the length of the unfragmentable part for fragmentation.
  256          */
  257         optlen = 0;
  258         if (exthdrs.ip6e_hbh) optlen += exthdrs.ip6e_hbh->m_len;
  259         if (exthdrs.ip6e_dest1) optlen += exthdrs.ip6e_dest1->m_len;
  260         if (exthdrs.ip6e_rthdr) optlen += exthdrs.ip6e_rthdr->m_len;
  261         unfragpartlen = optlen + sizeof(struct ip6_hdr);
  262         /* NOTE: we don't add AH/ESP length here. do that later. */
  263         if (exthdrs.ip6e_dest2) optlen += exthdrs.ip6e_dest2->m_len;
  264 
  265         /*
  266          * If we need IPsec, or there is at least one extension header,
  267          * separate IP6 header from the payload.
  268          */
  269         if ((needipsec || optlen) && !hdrsplit) {
  270                 if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
  271                         m = NULL;
  272                         goto freehdrs;
  273                 }
  274                 m = exthdrs.ip6e_ip6;
  275                 hdrsplit++;
  276         }
  277 
  278         /* adjust pointer */
  279         ip6 = mtod(m, struct ip6_hdr *);
  280 
  281         /* adjust mbuf packet header length */
  282         m->m_pkthdr.len += optlen;
  283         plen = m->m_pkthdr.len - sizeof(*ip6);
  284 
  285         /* If this is a jumbo payload, insert a jumbo payload option. */
  286         if (plen > IPV6_MAXPACKET) {
  287                 if (!hdrsplit) {
  288                         if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
  289                                 m = NULL;
  290                                 goto freehdrs;
  291                         }
  292                         m = exthdrs.ip6e_ip6;
  293                         hdrsplit++;
  294                 }
  295                 /* adjust pointer */
  296                 ip6 = mtod(m, struct ip6_hdr *);
  297                 if ((error = ip6_insert_jumboopt(&exthdrs, plen)) != 0)
  298                         goto freehdrs;
  299                 ip6->ip6_plen = 0;
  300         } else
  301                 ip6->ip6_plen = htons(plen);
  302 
  303         /*
  304          * Concatenate headers and fill in next header fields.
  305          * Here we have, on "m"
  306          *      IPv6 payload
  307          * and we insert headers accordingly.  Finally, we should be getting:
  308          *      IPv6 hbh dest1 rthdr ah* [esp* dest2 payload]
  309          *
  310          * during the header composing process, "m" points to IPv6 header.
  311          * "mprev" points to an extension header prior to esp.
  312          */
  313         {
  314                 u_char *nexthdrp = &ip6->ip6_nxt;
  315                 struct mbuf *mprev = m;
  316 
  317                 /*
  318                  * we treat dest2 specially.  this makes IPsec processing
  319                  * much easier.  the goal here is to make mprev point the
  320                  * mbuf prior to dest2.
  321                  *
  322                  * result: IPv6 dest2 payload
  323                  * m and mprev will point to IPv6 header.
  324                  */
  325                 if (exthdrs.ip6e_dest2) {
  326                         if (!hdrsplit)
  327                                 panic("assumption failed: hdr not split");
  328                         exthdrs.ip6e_dest2->m_next = m->m_next;
  329                         m->m_next = exthdrs.ip6e_dest2;
  330                         *mtod(exthdrs.ip6e_dest2, u_char *) = ip6->ip6_nxt;
  331                         ip6->ip6_nxt = IPPROTO_DSTOPTS;
  332                 }
  333 
  334 #define MAKE_CHAIN(m, mp, p, i)\
  335     do {\
  336         if (m) {\
  337                 if (!hdrsplit) \
  338                         panic("assumption failed: hdr not split"); \
  339                 *mtod((m), u_char *) = *(p);\
  340                 *(p) = (i);\
  341                 p = mtod((m), u_char *);\
  342                 (m)->m_next = (mp)->m_next;\
  343                 (mp)->m_next = (m);\
  344                 (mp) = (m);\
  345         }\
  346     } while (/*CONSTCOND*/ 0)
  347                 /*
  348                  * result: IPv6 hbh dest1 rthdr dest2 payload
  349                  * m will point to IPv6 header.  mprev will point to the
  350                  * extension header prior to dest2 (rthdr in the above case).
  351                  */
  352                 MAKE_CHAIN(exthdrs.ip6e_hbh, mprev, nexthdrp, IPPROTO_HOPOPTS);
  353                 MAKE_CHAIN(exthdrs.ip6e_dest1, mprev, nexthdrp,
  354                     IPPROTO_DSTOPTS);
  355                 MAKE_CHAIN(exthdrs.ip6e_rthdr, mprev, nexthdrp,
  356                     IPPROTO_ROUTING);
  357 
  358 #ifdef IPSEC
  359                 if (!needipsec)
  360                         goto skip_ipsec2;
  361 
  362                 /*
  363                  * pointers after IPsec headers are not valid any more.
  364                  * other pointers need a great care too.
  365                  * (IPsec routines should not mangle mbufs prior to AH/ESP)
  366                  */
  367                 exthdrs.ip6e_dest2 = NULL;
  368 
  369             {
  370                 struct ip6_rthdr *rh = NULL;
  371                 int segleft_org = 0;
  372                 struct ipsec_output_state state;
  373 
  374                 if (exthdrs.ip6e_rthdr) {
  375                         rh = mtod(exthdrs.ip6e_rthdr, struct ip6_rthdr *);
  376                         segleft_org = rh->ip6r_segleft;
  377                         rh->ip6r_segleft = 0;
  378                 }
  379 
  380                 bzero(&state, sizeof(state));
  381                 state.m = m;
  382                 error = ipsec6_output_trans(&state, nexthdrp, mprev, sp, flags,
  383                     &needipsectun);
  384                 m = state.m;
  385                 if (error) {
  386                         /* mbuf is already reclaimed in ipsec6_output_trans. */
  387                         m = NULL;
  388                         switch (error) {
  389                         case EHOSTUNREACH:
  390                         case ENETUNREACH:
  391                         case EMSGSIZE:
  392                         case ENOBUFS:
  393                         case ENOMEM:
  394                                 break;
  395                         default:
  396                                 printf("ip6_output (ipsec): error code %d\n", error);
  397                                 /* FALLTHROUGH */
  398                         case ENOENT:
  399                                 /* don't show these error codes to the user */
  400                                 error = 0;
  401                                 break;
  402                         }
  403                         goto bad;
  404                 }
  405                 if (exthdrs.ip6e_rthdr) {
  406                         /* ah6_output doesn't modify mbuf chain */
  407                         rh->ip6r_segleft = segleft_org;
  408                 }
  409             }
  410 skip_ipsec2:;
  411 #endif
  412         }
  413 
  414         /*
  415          * If there is a routing header, replace destination address field
  416          * with the first hop of the routing header.
  417          */
  418         if (exthdrs.ip6e_rthdr) {
  419                 struct ip6_rthdr *rh;
  420                 struct ip6_rthdr0 *rh0;
  421                 struct in6_addr *addr;
  422 
  423                 rh = (struct ip6_rthdr *)(mtod(exthdrs.ip6e_rthdr,
  424                     struct ip6_rthdr *));
  425                 finaldst = ip6->ip6_dst;
  426                 switch (rh->ip6r_type) {
  427                 case IPV6_RTHDR_TYPE_0:
  428                          rh0 = (struct ip6_rthdr0 *)rh;
  429                          addr = (struct in6_addr *)(rh0 + 1);
  430                          ip6->ip6_dst = addr[0];
  431                          bcopy(&addr[1], &addr[0],
  432                              sizeof(struct in6_addr) * (rh0->ip6r0_segleft - 1));
  433                          addr[rh0->ip6r0_segleft - 1] = finaldst;
  434                          break;
  435                 default:        /* is it possible? */
  436                          error = EINVAL;
  437                          goto bad;
  438                 }
  439         }
  440 
  441         /* Source address validation */
  442         if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) &&
  443             (flags & IPV6_UNSPECSRC) == 0) {
  444                 error = EOPNOTSUPP;
  445                 ip6stat.ip6s_badscope++;
  446                 goto bad;
  447         }
  448         if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) {
  449                 error = EOPNOTSUPP;
  450                 ip6stat.ip6s_badscope++;
  451                 goto bad;
  452         }
  453 
  454         ip6stat.ip6s_localout++;
  455 
  456         /*
  457          * Route packet.
  458          */
  459         /* initialize cached route */
  460         if (ro == 0) {
  461                 ro = &ip6route;
  462                 bzero((caddr_t)ro, sizeof(*ro));
  463         }
  464         ro_pmtu = ro;
  465         if (opt && opt->ip6po_rthdr)
  466                 ro = &opt->ip6po_route;
  467         dst = (struct sockaddr_in6 *)&ro->ro_dst;
  468         /*
  469          * If there is a cached route,
  470          * check that it is to the same destination
  471          * and is still up. If not, free it and try again.
  472          */
  473         if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
  474             dst->sin6_family != AF_INET6 ||
  475             !IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &ip6->ip6_dst))) {
  476                 RTFREE(ro->ro_rt);
  477                 ro->ro_rt = (struct rtentry *)0;
  478         }
  479         if (ro->ro_rt == 0) {
  480                 bzero(dst, sizeof(*dst));
  481                 dst->sin6_family = AF_INET6;
  482                 dst->sin6_len = sizeof(struct sockaddr_in6);
  483                 dst->sin6_addr = ip6->ip6_dst;
  484         }
  485 #ifdef IPSEC
  486         if (needipsec && needipsectun) {
  487                 struct ipsec_output_state state;
  488 
  489                 /*
  490                  * All the extension headers will become inaccessible
  491                  * (since they can be encrypted).
  492                  * Don't panic, we need no more updates to extension headers
  493                  * on inner IPv6 packet (since they are now encapsulated).
  494                  *
  495                  * IPv6 [ESP|AH] IPv6 [extension headers] payload
  496                  */
  497                 bzero(&exthdrs, sizeof(exthdrs));
  498                 exthdrs.ip6e_ip6 = m;
  499 
  500                 bzero(&state, sizeof(state));
  501                 state.m = m;
  502                 state.ro = (struct route *)ro;
  503                 state.dst = (struct sockaddr *)dst;
  504 
  505                 error = ipsec6_output_tunnel(&state, sp, flags);
  506 
  507                 m = state.m;
  508                 ro = (struct route_in6 *)state.ro;
  509                 dst = (struct sockaddr_in6 *)state.dst;
  510                 if (error) {
  511                         /* mbuf is already reclaimed in ipsec6_output_tunnel. */
  512                         m0 = m = NULL;
  513                         m = NULL;
  514                         switch (error) {
  515                         case EHOSTUNREACH:
  516                         case ENETUNREACH:
  517                         case EMSGSIZE:
  518                         case ENOBUFS:
  519                         case ENOMEM:
  520                                 break;
  521                         default:
  522                                 printf("ip6_output (ipsec): error code %d\n", error);
  523                                 /* FALLTHROUGH */
  524                         case ENOENT:
  525                                 /* don't show these error codes to the user */
  526                                 error = 0;
  527                                 break;
  528                         }
  529                         goto bad;
  530                 }
  531 
  532                 exthdrs.ip6e_ip6 = m;
  533         }
  534 #endif /* IPSEC */
  535 
  536         if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
  537                 /* Unicast */
  538 
  539 #define ifatoia6(ifa)   ((struct in6_ifaddr *)(ifa))
  540 #define sin6tosa(sin6)  ((struct sockaddr *)(sin6))
  541                 /* xxx
  542                  * interface selection comes here
  543                  * if an interface is specified from an upper layer,
  544                  * ifp must point it.
  545                  */
  546                 if (ro->ro_rt == 0) {
  547                         /*
  548                          * non-bsdi always clone routes, if parent is
  549                          * PRF_CLONING.
  550                          */
  551                         rtalloc((struct route *)ro);
  552                 }
  553                 if (ro->ro_rt == 0) {
  554                         ip6stat.ip6s_noroute++;
  555                         error = EHOSTUNREACH;
  556                         /* XXX in6_ifstat_inc(ifp, ifs6_out_discard); */
  557                         goto bad;
  558                 }
  559                 ifp = ro->ro_rt->rt_ifp;
  560                 ro->ro_rt->rt_use++;
  561                 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
  562                         dst = (struct sockaddr_in6 *)ro->ro_rt->rt_gateway;
  563                 m->m_flags &= ~(M_BCAST | M_MCAST);     /* just in case */
  564 
  565                 in6_ifstat_inc(ifp, ifs6_out_request);
  566 
  567                 /*
  568                  * Check if the outgoing interface conflicts with
  569                  * the interface specified by ifi6_ifindex (if specified).
  570                  * Note that loopback interface is always okay.
  571                  * (this may happen when we are sending a packet to one of
  572                  *  our own addresses.)
  573                  */
  574                 if (opt && opt->ip6po_pktinfo &&
  575                     opt->ip6po_pktinfo->ipi6_ifindex) {
  576                         if (!(ifp->if_flags & IFF_LOOPBACK) &&
  577                             ifp->if_index != opt->ip6po_pktinfo->ipi6_ifindex) {
  578                                 ip6stat.ip6s_noroute++;
  579                                 in6_ifstat_inc(ifp, ifs6_out_discard);
  580                                 error = EHOSTUNREACH;
  581                                 goto bad;
  582                         }
  583                 }
  584 
  585                 if (opt && opt->ip6po_hlim != -1)
  586                         ip6->ip6_hlim = opt->ip6po_hlim & 0xff;
  587         } else {
  588                 /* Multicast */
  589                 struct  in6_multi *in6m;
  590 
  591                 m->m_flags = (m->m_flags & ~M_BCAST) | M_MCAST;
  592 
  593                 /*
  594                  * See if the caller provided any multicast options
  595                  */
  596                 ifp = NULL;
  597                 if (im6o != NULL) {
  598                         ip6->ip6_hlim = im6o->im6o_multicast_hlim;
  599                         if (im6o->im6o_multicast_ifp != NULL)
  600                                 ifp = im6o->im6o_multicast_ifp;
  601                 } else
  602                         ip6->ip6_hlim = ip6_defmcasthlim;
  603 
  604                 /*
  605                  * See if the caller provided the outgoing interface
  606                  * as an ancillary data.
  607                  * Boundary check for ifindex is assumed to be already done.
  608                  */
  609                 if (opt && opt->ip6po_pktinfo && opt->ip6po_pktinfo->ipi6_ifindex)
  610                         ifp = ifindex2ifnet[opt->ip6po_pktinfo->ipi6_ifindex];
  611 
  612                 /*
  613                  * If the destination is a node-local scope multicast,
  614                  * the packet should be loop-backed only.
  615                  */
  616                 if (IN6_IS_ADDR_MC_NODELOCAL(&ip6->ip6_dst)) {
  617                         /*
  618                          * If the outgoing interface is already specified,
  619                          * it should be a loopback interface.
  620                          */
  621                         if (ifp && (ifp->if_flags & IFF_LOOPBACK) == 0) {
  622                                 ip6stat.ip6s_badscope++;
  623                                 error = ENETUNREACH; /* XXX: better error? */
  624                                 /* XXX correct ifp? */
  625                                 in6_ifstat_inc(ifp, ifs6_out_discard);
  626                                 goto bad;
  627                         } else {
  628                                 ifp = &loif[0];
  629                         }
  630                 }
  631 
  632                 if (opt && opt->ip6po_hlim != -1)
  633                         ip6->ip6_hlim = opt->ip6po_hlim & 0xff;
  634 
  635                 /*
  636                  * If caller did not provide an interface lookup a
  637                  * default in the routing table.  This is either a
  638                  * default for the speicfied group (i.e. a host
  639                  * route), or a multicast default (a route for the
  640                  * ``net'' ff00::/8).
  641                  */
  642                 if (ifp == NULL) {
  643                         if (ro->ro_rt == 0) {
  644                                 ro->ro_rt = rtalloc1((struct sockaddr *)
  645                                     &ro->ro_dst, 0);
  646                         }
  647                         if (ro->ro_rt == 0) {
  648                                 ip6stat.ip6s_noroute++;
  649                                 error = EHOSTUNREACH;
  650                                 /* XXX in6_ifstat_inc(ifp, ifs6_out_discard) */
  651                                 goto bad;
  652                         }
  653                         ifp = ro->ro_rt->rt_ifp;
  654                         ro->ro_rt->rt_use++;
  655                 }
  656 
  657                 if ((flags & IPV6_FORWARDING) == 0)
  658                         in6_ifstat_inc(ifp, ifs6_out_request);
  659                 in6_ifstat_inc(ifp, ifs6_out_mcast);
  660 
  661                 /*
  662                  * Confirm that the outgoing interface supports multicast.
  663                  */
  664                 if ((ifp->if_flags & IFF_MULTICAST) == 0) {
  665                         ip6stat.ip6s_noroute++;
  666                         in6_ifstat_inc(ifp, ifs6_out_discard);
  667                         error = ENETUNREACH;
  668                         goto bad;
  669                 }
  670                 IN6_LOOKUP_MULTI(ip6->ip6_dst, ifp, in6m);
  671                 if (in6m != NULL &&
  672                    (im6o == NULL || im6o->im6o_multicast_loop)) {
  673                         /*
  674                          * If we belong to the destination multicast group
  675                          * on the outgoing interface, and the caller did not
  676                          * forbid loopback, loop back a copy.
  677                          */
  678                         ip6_mloopback(ifp, m, dst);
  679                 } else {
  680                         /*
  681                          * If we are acting as a multicast router, perform
  682                          * multicast forwarding as if the packet had just
  683                          * arrived on the interface to which we are about
  684                          * to send.  The multicast forwarding function
  685                          * recursively calls this function, using the
  686                          * IPV6_FORWARDING flag to prevent infinite recursion.
  687                          *
  688                          * Multicasts that are looped back by ip6_mloopback(),
  689                          * above, will be forwarded by the ip6_input() routine,
  690                          * if necessary.
  691                          */
  692                         if (ip6_mrouter && (flags & IPV6_FORWARDING) == 0) {
  693                                 if (ip6_mforward(ip6, ifp, m) != 0) {
  694                                         m_freem(m);
  695                                         goto done;
  696                                 }
  697                         }
  698                 }
  699                 /*
  700                  * Multicasts with a hoplimit of zero may be looped back,
  701                  * above, but must not be transmitted on a network.
  702                  * Also, multicasts addressed to the loopback interface
  703                  * are not sent -- the above call to ip6_mloopback() will
  704                  * loop back a copy if this host actually belongs to the
  705                  * destination group on the loopback interface.
  706                  */
  707                 if (ip6->ip6_hlim == 0 || (ifp->if_flags & IFF_LOOPBACK)) {
  708                         m_freem(m);
  709                         goto done;
  710                 }
  711         }
  712 
  713         /*
  714          * Fill the outgoing inteface to tell the upper layer
  715          * to increment per-interface statistics.
  716          */
  717         if (ifpp)
  718                 *ifpp = ifp;
  719 
  720         /* Determine path MTU. */
  721         if ((error = ip6_getpmtu(ro_pmtu, ro, ifp, &finaldst, &mtu,
  722             &alwaysfrag)) != 0)
  723                 goto bad;
  724 
  725         /*
  726          * The caller of this function may specify to use the minimum MTU
  727          * in some cases.
  728          */
  729         if (mtu > IPV6_MMTU) {
  730                 if ((flags & IPV6_MINMTU))
  731                         mtu = IPV6_MMTU;
  732         }
  733 
  734         /* Fake scoped addresses */
  735         if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
  736                 /*
  737                  * If source or destination address is a scoped address, and
  738                  * the packet is going to be sent to a loopback interface,
  739                  * we should keep the original interface.
  740                  */
  741 
  742                 /*
  743                  * XXX: this is a very experimental and temporary solution.
  744                  * We eventually have sockaddr_in6 and use the sin6_scope_id
  745                  * field of the structure here.
  746                  * We rely on the consistency between two scope zone ids
  747                  * of source add destination, which should already be assured
  748                  * Larger scopes than link will be supported in the near
  749                  * future.
  750                  */
  751                 origifp = NULL;
  752                 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
  753                         origifp = ifindex2ifnet[ntohs(ip6->ip6_src.s6_addr16[1])];
  754                 else if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
  755                         origifp = ifindex2ifnet[ntohs(ip6->ip6_dst.s6_addr16[1])];
  756                 /*
  757                  * XXX: origifp can be NULL even in those two cases above.
  758                  * For example, if we remove the (only) link-local address
  759                  * from the loopback interface, and try to send a link-local
  760                  * address without link-id information.  Then the source
  761                  * address is ::1, and the destination address is the
  762                  * link-local address with its s6_addr16[1] being zero.
  763                  * What is worse, if the packet goes to the loopback interface
  764                  * by a default rejected route, the null pointer would be
  765                  * passed to looutput, and the kernel would hang.
  766                  * The following last resort would prevent such disaster.
  767                  */
  768                 if (origifp == NULL)
  769                         origifp = ifp;
  770         } else
  771                 origifp = ifp;
  772         if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
  773                 ip6->ip6_src.s6_addr16[1] = 0;
  774         if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
  775                 ip6->ip6_dst.s6_addr16[1] = 0;
  776 
  777         /*
  778          * If the outgoing packet contains a hop-by-hop options header,
  779          * it must be examined and processed even by the source node.
  780          * (RFC 2460, section 4.)
  781          */
  782         if (exthdrs.ip6e_hbh) {
  783                 struct ip6_hbh *hbh = mtod(exthdrs.ip6e_hbh, struct ip6_hbh *);
  784                 u_int32_t dummy1; /* XXX unused */
  785                 u_int32_t dummy2; /* XXX unused */
  786 
  787                 /*
  788                  *  XXX: if we have to send an ICMPv6 error to the sender,
  789                  *       we need the M_LOOP flag since icmp6_error() expects
  790                  *       the IPv6 and the hop-by-hop options header are
  791                  *       continuous unless the flag is set.
  792                  */
  793                 m->m_flags |= M_LOOP;
  794                 m->m_pkthdr.rcvif = ifp;
  795                 if (ip6_process_hopopts(m, (u_int8_t *)(hbh + 1),
  796                     ((hbh->ip6h_len + 1) << 3) - sizeof(struct ip6_hbh),
  797                     &dummy1, &dummy2) < 0) {
  798                         /* m was already freed at this point */
  799                         error = EINVAL;/* better error? */
  800                         goto done;
  801                 }
  802                 m->m_flags &= ~M_LOOP; /* XXX */
  803                 m->m_pkthdr.rcvif = NULL;
  804         }
  805 
  806 #ifdef PFIL_HOOKS
  807         /*
  808          * Run through list of hooks for output packets.
  809          */
  810         if ((error = pfil_run_hooks(&inet6_pfil_hook, &m, ifp, PFIL_OUT)) != 0)
  811                 goto done;
  812         if (m == NULL)
  813                 goto done;
  814         ip6 = mtod(m, struct ip6_hdr *);
  815 #endif /* PFIL_HOOKS */
  816         /*
  817          * Send the packet to the outgoing interface.
  818          * If necessary, do IPv6 fragmentation before sending.
  819          *
  820          * the logic here is rather complex:
  821          * 1: normal case (dontfrag == 0, alwaysfrag == 0)
  822          * 1-a: send as is if tlen <= path mtu
  823          * 1-b: fragment if tlen > path mtu
  824          *
  825          * 2: if user asks us not to fragment (dontfrag == 1)
  826          * 2-a: send as is if tlen <= interface mtu
  827          * 2-b: error if tlen > interface mtu
  828          *
  829          * 3: if we always need to attach fragment header (alwaysfrag == 1)
  830          *      always fragment
  831          *
  832          * 4: if dontfrag == 1 && alwaysfrag == 1
  833          *      error, as we cannot handle this conflicting request
  834          */
  835         tlen = m->m_pkthdr.len;
  836 
  837         dontfrag = 0;
  838         if (dontfrag && alwaysfrag) {   /* case 4 */
  839                 /* conflicting request - can't transmit */
  840                 error = EMSGSIZE;
  841                 goto bad;
  842         }
  843         if (dontfrag && tlen > IN6_LINKMTU(ifp)) {      /* case 2-b */
  844                 /*
  845                  * Even if the DONTFRAG option is specified, we cannot send the
  846                  * packet when the data length is larger than the MTU of the
  847                  * outgoing interface.
  848                  * Notify the error by sending IPV6_PATHMTU ancillary data as
  849                  * well as returning an error code (the latter is not described
  850                  * in the API spec.)
  851                  */
  852                 u_int32_t mtu32;
  853                 struct ip6ctlparam ip6cp;
  854 
  855                 mtu32 = (u_int32_t)mtu;
  856                 bzero(&ip6cp, sizeof(ip6cp));
  857                 ip6cp.ip6c_cmdarg = (void *)&mtu32;
  858                 pfctlinput2(PRC_MSGSIZE, (struct sockaddr *)&ro_pmtu->ro_dst,
  859                     (void *)&ip6cp);
  860 
  861                 error = EMSGSIZE;
  862                 goto bad;
  863         }
  864 
  865         /*
  866          * transmit packet without fragmentation
  867          */
  868         if (dontfrag || (!alwaysfrag && tlen <= mtu)) { /* case 1-a and 2-a */
  869                 struct in6_ifaddr *ia6;
  870 
  871                 ip6 = mtod(m, struct ip6_hdr *);
  872                 ia6 = in6_ifawithifp(ifp, &ip6->ip6_src);
  873                 if (ia6) {
  874                         /* Record statistics for this interface address. */
  875                         ia6->ia_ifa.ifa_data.ifad_outbytes += m->m_pkthdr.len;
  876                 }
  877 #ifdef IPSEC
  878                 /* clean ipsec history once it goes out of the node */
  879                 ipsec_delaux(m);
  880 #endif
  881                 error = nd6_output(ifp, origifp, m, dst, ro->ro_rt);
  882                 goto done;
  883         }
  884 
  885         /*
  886          * try to fragment the packet.  case 1-b and 3
  887          */
  888         if (mtu < IPV6_MMTU) {
  889                 /* path MTU cannot be less than IPV6_MMTU */
  890                 error = EMSGSIZE;
  891                 in6_ifstat_inc(ifp, ifs6_out_fragfail);
  892                 goto bad;
  893         } else if (ip6->ip6_plen == 0) {
  894                 /* jumbo payload cannot be fragmented */
  895                 error = EMSGSIZE;
  896                 in6_ifstat_inc(ifp, ifs6_out_fragfail);
  897                 goto bad;
  898         } else {
  899                 struct mbuf **mnext, *m_frgpart;
  900                 struct ip6_frag *ip6f;
  901                 u_int32_t id = htonl(ip6_randomid());
  902                 u_char nextproto;
  903                 struct ip6ctlparam ip6cp;
  904                 u_int32_t mtu32;
  905 
  906                 /*
  907                  * Too large for the destination or interface;
  908                  * fragment if possible.
  909                  * Must be able to put at least 8 bytes per fragment.
  910                  */
  911                 hlen = unfragpartlen;
  912                 if (mtu > IPV6_MAXPACKET)
  913                         mtu = IPV6_MAXPACKET;
  914 
  915                 /* Notify a proper path MTU to applications. */
  916                 mtu32 = (u_int32_t)mtu;
  917                 bzero(&ip6cp, sizeof(ip6cp));
  918                 ip6cp.ip6c_cmdarg = (void *)&mtu32;
  919                 pfctlinput2(PRC_MSGSIZE, (struct sockaddr *)&ro_pmtu->ro_dst,
  920                     (void *)&ip6cp);
  921 
  922                 len = (mtu - hlen - sizeof(struct ip6_frag)) & ~7;
  923                 if (len < 8) {
  924                         error = EMSGSIZE;
  925                         in6_ifstat_inc(ifp, ifs6_out_fragfail);
  926                         goto bad;
  927                 }
  928 
  929                 mnext = &m->m_nextpkt;
  930 
  931                 /*
  932                  * Change the next header field of the last header in the
  933                  * unfragmentable part.
  934                  */
  935                 if (exthdrs.ip6e_rthdr) {
  936                         nextproto = *mtod(exthdrs.ip6e_rthdr, u_char *);
  937                         *mtod(exthdrs.ip6e_rthdr, u_char *) = IPPROTO_FRAGMENT;
  938                 } else if (exthdrs.ip6e_dest1) {
  939                         nextproto = *mtod(exthdrs.ip6e_dest1, u_char *);
  940                         *mtod(exthdrs.ip6e_dest1, u_char *) = IPPROTO_FRAGMENT;
  941                 } else if (exthdrs.ip6e_hbh) {
  942                         nextproto = *mtod(exthdrs.ip6e_hbh, u_char *);
  943                         *mtod(exthdrs.ip6e_hbh, u_char *) = IPPROTO_FRAGMENT;
  944                 } else {
  945                         nextproto = ip6->ip6_nxt;
  946                         ip6->ip6_nxt = IPPROTO_FRAGMENT;
  947                 }
  948 
  949                 /*
  950                  * Loop through length of segment after first fragment,
  951                  * make new header and copy data of each part and link onto
  952                  * chain.
  953                  */
  954                 m0 = m;
  955                 for (off = hlen; off < tlen; off += len) {
  956                         struct mbuf *mlast;
  957 
  958                         MGETHDR(m, M_DONTWAIT, MT_HEADER);
  959                         if (!m) {
  960                                 error = ENOBUFS;
  961                                 ip6stat.ip6s_odropped++;
  962                                 goto sendorfree;
  963                         }
  964                         m->m_pkthdr.rcvif = NULL;
  965                         m->m_flags = m0->m_flags & M_COPYFLAGS;
  966                         *mnext = m;
  967                         mnext = &m->m_nextpkt;
  968                         m->m_data += max_linkhdr;
  969                         mhip6 = mtod(m, struct ip6_hdr *);
  970                         *mhip6 = *ip6;
  971                         m->m_len = sizeof(*mhip6);
  972                         error = ip6_insertfraghdr(m0, m, hlen, &ip6f);
  973                         if (error) {
  974                                 ip6stat.ip6s_odropped++;
  975                                 goto sendorfree;
  976                         }
  977                         ip6f->ip6f_offlg = htons((u_int16_t)((off - hlen) & ~7));
  978                         if (off + len >= tlen)
  979                                 len = tlen - off;
  980                         else
  981                                 ip6f->ip6f_offlg |= IP6F_MORE_FRAG;
  982                         mhip6->ip6_plen = htons((u_int16_t)(len + hlen +
  983                             sizeof(*ip6f) - sizeof(struct ip6_hdr)));
  984                         if ((m_frgpart = m_copy(m0, off, len)) == 0) {
  985                                 error = ENOBUFS;
  986                                 ip6stat.ip6s_odropped++;
  987                                 goto sendorfree;
  988                         }
  989                         for (mlast = m; mlast->m_next; mlast = mlast->m_next)
  990                                 ;
  991                         mlast->m_next = m_frgpart;
  992                         m->m_pkthdr.len = len + hlen + sizeof(*ip6f);
  993                         m->m_pkthdr.rcvif = (struct ifnet *)0;
  994                         ip6f->ip6f_reserved = 0;
  995                         ip6f->ip6f_ident = id;
  996                         ip6f->ip6f_nxt = nextproto;
  997                         ip6stat.ip6s_ofragments++;
  998                         in6_ifstat_inc(ifp, ifs6_out_fragcreat);
  999                 }
 1000 
 1001                 in6_ifstat_inc(ifp, ifs6_out_fragok);
 1002         }
 1003 
 1004         /*
 1005          * Remove leading garbages.
 1006          */
 1007 sendorfree:
 1008         m = m0->m_nextpkt;
 1009         m0->m_nextpkt = 0;
 1010         m_freem(m0);
 1011         for (m0 = m; m; m = m0) {
 1012                 m0 = m->m_nextpkt;
 1013                 m->m_nextpkt = 0;
 1014                 if (error == 0) {
 1015                         struct in6_ifaddr *ia6;
 1016                         ip6 = mtod(m, struct ip6_hdr *);
 1017                         ia6 = in6_ifawithifp(ifp, &ip6->ip6_src);
 1018                         if (ia6) {
 1019                                 /*
 1020                                  * Record statistics for this interface
 1021                                  * address.
 1022                                  */
 1023                                 ia6->ia_ifa.ifa_data.ifad_outbytes +=
 1024                                     m->m_pkthdr.len;
 1025                         }
 1026 #ifdef IPSEC
 1027                         /* clean ipsec history once it goes out of the node */
 1028                         ipsec_delaux(m);
 1029 #endif
 1030                         error = nd6_output(ifp, origifp, m, dst, ro->ro_rt);
 1031                 } else
 1032                         m_freem(m);
 1033         }
 1034 
 1035         if (error == 0)
 1036                 ip6stat.ip6s_fragmented++;
 1037 
 1038 done:
 1039         if (ro == &ip6route && ro->ro_rt) { /* brace necessary for RTFREE */
 1040                 RTFREE(ro->ro_rt);
 1041         } else if (ro_pmtu == &ip6route && ro_pmtu->ro_rt) {
 1042                 RTFREE(ro_pmtu->ro_rt);
 1043         }
 1044 
 1045 #ifdef IPSEC
 1046         if (sp != NULL)
 1047                 key_freesp(sp);
 1048 #endif /* IPSEC */
 1049 
 1050         return (error);
 1051 
 1052 freehdrs:
 1053         m_freem(exthdrs.ip6e_hbh);      /* m_freem will check if mbuf is 0 */
 1054         m_freem(exthdrs.ip6e_dest1);
 1055         m_freem(exthdrs.ip6e_rthdr);
 1056         m_freem(exthdrs.ip6e_dest2);
 1057         /* FALLTHROUGH */
 1058 bad:
 1059         m_freem(m);
 1060         goto done;
 1061 }
 1062 
 1063 static int
 1064 ip6_copyexthdr(mp, hdr, hlen)
 1065         struct mbuf **mp;
 1066         caddr_t hdr;
 1067         int hlen;
 1068 {
 1069         struct mbuf *m;
 1070 
 1071         if (hlen > MCLBYTES)
 1072                 return (ENOBUFS); /* XXX */
 1073 
 1074         MGET(m, M_DONTWAIT, MT_DATA);
 1075         if (!m)
 1076                 return (ENOBUFS);
 1077 
 1078         if (hlen > MLEN) {
 1079                 MCLGET(m, M_DONTWAIT);
 1080                 if ((m->m_flags & M_EXT) == 0) {
 1081                         m_free(m);
 1082                         return (ENOBUFS);
 1083                 }
 1084         }
 1085         m->m_len = hlen;
 1086         if (hdr)
 1087                 bcopy(hdr, mtod(m, caddr_t), hlen);
 1088 
 1089         *mp = m;
 1090         return (0);
 1091 }
 1092 
 1093 /*
 1094  * Insert jumbo payload option.
 1095  */
 1096 static int
 1097 ip6_insert_jumboopt(exthdrs, plen)
 1098         struct ip6_exthdrs *exthdrs;
 1099         u_int32_t plen;
 1100 {
 1101         struct mbuf *mopt;
 1102         u_int8_t *optbuf;
 1103         u_int32_t v;
 1104 
 1105 #define JUMBOOPTLEN     8       /* length of jumbo payload option and padding */
 1106 
 1107         /*
 1108          * If there is no hop-by-hop options header, allocate new one.
 1109          * If there is one but it doesn't have enough space to store the
 1110          * jumbo payload option, allocate a cluster to store the whole options.
 1111          * Otherwise, use it to store the options.
 1112          */
 1113         if (exthdrs->ip6e_hbh == 0) {
 1114                 MGET(mopt, M_DONTWAIT, MT_DATA);
 1115                 if (mopt == 0)
 1116                         return (ENOBUFS);
 1117                 mopt->m_len = JUMBOOPTLEN;
 1118                 optbuf = mtod(mopt, u_int8_t *);
 1119                 optbuf[1] = 0;  /* = ((JUMBOOPTLEN) >> 3) - 1 */
 1120                 exthdrs->ip6e_hbh = mopt;
 1121         } else {
 1122                 struct ip6_hbh *hbh;
 1123 
 1124                 mopt = exthdrs->ip6e_hbh;
 1125                 if (M_TRAILINGSPACE(mopt) < JUMBOOPTLEN) {
 1126                         /*
 1127                          * XXX assumption:
 1128                          * - exthdrs->ip6e_hbh is not referenced from places
 1129                          *   other than exthdrs.
 1130                          * - exthdrs->ip6e_hbh is not an mbuf chain.
 1131                          */
 1132                         int oldoptlen = mopt->m_len;
 1133                         struct mbuf *n;
 1134 
 1135                         /*
 1136                          * XXX: give up if the whole (new) hbh header does
 1137                          * not fit even in an mbuf cluster.
 1138                          */
 1139                         if (oldoptlen + JUMBOOPTLEN > MCLBYTES)
 1140                                 return (ENOBUFS);
 1141 
 1142                         /*
 1143                          * As a consequence, we must always prepare a cluster
 1144                          * at this point.
 1145                          */
 1146                         MGET(n, M_DONTWAIT, MT_DATA);
 1147                         if (n) {
 1148                                 MCLGET(n, M_DONTWAIT);
 1149                                 if ((n->m_flags & M_EXT) == 0) {
 1150                                         m_freem(n);
 1151                                         n = NULL;
 1152                                 }
 1153                         }
 1154                         if (!n)
 1155                                 return (ENOBUFS);
 1156                         n->m_len = oldoptlen + JUMBOOPTLEN;
 1157                         bcopy(mtod(mopt, caddr_t), mtod(n, caddr_t),
 1158                             oldoptlen);
 1159                         optbuf = mtod(n, u_int8_t *) + oldoptlen;
 1160                         m_freem(mopt);
 1161                         mopt = exthdrs->ip6e_hbh = n;
 1162                 } else {
 1163                         optbuf = mtod(mopt, u_int8_t *) + mopt->m_len;
 1164                         mopt->m_len += JUMBOOPTLEN;
 1165                 }
 1166                 optbuf[0] = IP6OPT_PADN;
 1167                 optbuf[1] = 0;
 1168 
 1169                 /*
 1170                  * Adjust the header length according to the pad and
 1171                  * the jumbo payload option.
 1172                  */
 1173                 hbh = mtod(mopt, struct ip6_hbh *);
 1174                 hbh->ip6h_len += (JUMBOOPTLEN >> 3);
 1175         }
 1176 
 1177         /* fill in the option. */
 1178         optbuf[2] = IP6OPT_JUMBO;
 1179         optbuf[3] = 4;
 1180         v = (u_int32_t)htonl(plen + JUMBOOPTLEN);
 1181         bcopy(&v, &optbuf[4], sizeof(u_int32_t));
 1182 
 1183         /* finally, adjust the packet header length */
 1184         exthdrs->ip6e_ip6->m_pkthdr.len += JUMBOOPTLEN;
 1185 
 1186         return (0);
 1187 #undef JUMBOOPTLEN
 1188 }
 1189 
 1190 /*
 1191  * Insert fragment header and copy unfragmentable header portions.
 1192  */
 1193 static int
 1194 ip6_insertfraghdr(m0, m, hlen, frghdrp)
 1195         struct mbuf *m0, *m;
 1196         int hlen;
 1197         struct ip6_frag **frghdrp;
 1198 {
 1199         struct mbuf *n, *mlast;
 1200 
 1201         if (hlen > sizeof(struct ip6_hdr)) {
 1202                 n = m_copym(m0, sizeof(struct ip6_hdr),
 1203                     hlen - sizeof(struct ip6_hdr), M_DONTWAIT);
 1204                 if (n == 0)
 1205                         return (ENOBUFS);
 1206                 m->m_next = n;
 1207         } else
 1208                 n = m;
 1209 
 1210         /* Search for the last mbuf of unfragmentable part. */
 1211         for (mlast = n; mlast->m_next; mlast = mlast->m_next)
 1212                 ;
 1213 
 1214         if ((mlast->m_flags & M_EXT) == 0 &&
 1215             M_TRAILINGSPACE(mlast) >= sizeof(struct ip6_frag)) {
 1216                 /* use the trailing space of the last mbuf for the fragment hdr */
 1217                 *frghdrp = (struct ip6_frag *)(mtod(mlast, caddr_t) +
 1218                     mlast->m_len);
 1219                 mlast->m_len += sizeof(struct ip6_frag);
 1220                 m->m_pkthdr.len += sizeof(struct ip6_frag);
 1221         } else {
 1222                 /* allocate a new mbuf for the fragment header */
 1223                 struct mbuf *mfrg;
 1224 
 1225                 MGET(mfrg, M_DONTWAIT, MT_DATA);
 1226                 if (mfrg == 0)
 1227                         return (ENOBUFS);
 1228                 mfrg->m_len = sizeof(struct ip6_frag);
 1229                 *frghdrp = mtod(mfrg, struct ip6_frag *);
 1230                 mlast->m_next = mfrg;
 1231         }
 1232 
 1233         return (0);
 1234 }
 1235 
 1236 int
 1237 ip6_getpmtu(ro_pmtu, ro, ifp, dst, mtup, alwaysfragp)
 1238         struct route_in6 *ro_pmtu, *ro;
 1239         struct ifnet *ifp;
 1240         struct in6_addr *dst;
 1241         u_long *mtup;
 1242         int *alwaysfragp;
 1243 {
 1244         u_int32_t mtu = 0;
 1245         int alwaysfrag = 0;
 1246         int error = 0;
 1247 
 1248         if (ro_pmtu != ro) {
 1249                 /* The first hop and the final destination may differ. */
 1250                 struct sockaddr_in6 *sa6_dst =
 1251                     (struct sockaddr_in6 *)&ro_pmtu->ro_dst;
 1252                 if (ro_pmtu->ro_rt &&
 1253                     ((ro_pmtu->ro_rt->rt_flags & RTF_UP) == 0 ||
 1254                       !IN6_ARE_ADDR_EQUAL(&sa6_dst->sin6_addr, dst))) {
 1255                         RTFREE(ro_pmtu->ro_rt);
 1256                         ro_pmtu->ro_rt = (struct rtentry *)NULL;
 1257                 }
 1258                 if (ro_pmtu->ro_rt == NULL) {
 1259                         bzero(sa6_dst, sizeof(*sa6_dst)); /* for safety */
 1260                         sa6_dst->sin6_family = AF_INET6;
 1261                         sa6_dst->sin6_len = sizeof(struct sockaddr_in6);
 1262                         sa6_dst->sin6_addr = *dst;
 1263 
 1264                         rtalloc((struct route *)ro_pmtu);
 1265                 }
 1266         }
 1267         if (ro_pmtu->ro_rt) {
 1268                 u_int32_t ifmtu;
 1269 
 1270                 if (ifp == NULL)
 1271                         ifp = ro_pmtu->ro_rt->rt_ifp;
 1272                 ifmtu = IN6_LINKMTU(ifp);
 1273                 mtu = ro_pmtu->ro_rt->rt_rmx.rmx_mtu;
 1274                 if (mtu == 0)
 1275                         mtu = ifmtu;
 1276                 else if (mtu < IPV6_MMTU) {
 1277                         /*
 1278                          * RFC2460 section 5, last paragraph:
 1279                          * if we record ICMPv6 too big message with
 1280                          * mtu < IPV6_MMTU, transmit packets sized IPV6_MMTU
 1281                          * or smaller, with fragment header attached.
 1282                          * (fragment header is needed regardless from the
 1283                          * packet size, for translators to identify packets)
 1284                          */
 1285                         alwaysfrag = 1;
 1286                         mtu = IPV6_MMTU;
 1287                 } else if (mtu > ifmtu) {
 1288                         /*
 1289                          * The MTU on the route is larger than the MTU on
 1290                          * the interface!  This shouldn't happen, unless the
 1291                          * MTU of the interface has been changed after the
 1292                          * interface was brought up.  Change the MTU in the
 1293                          * route to match the interface MTU (as long as the
 1294                          * field isn't locked).
 1295                          */
 1296                         mtu = ifmtu;
 1297                         if (!(ro_pmtu->ro_rt->rt_rmx.rmx_locks & RTV_MTU))
 1298                                 ro_pmtu->ro_rt->rt_rmx.rmx_mtu = mtu;
 1299                 }
 1300         } else if (ifp) {
 1301                 mtu = IN6_LINKMTU(ifp);
 1302         } else
 1303                 error = EHOSTUNREACH; /* XXX */
 1304 
 1305         *mtup = mtu;
 1306         if (alwaysfragp)
 1307                 *alwaysfragp = alwaysfrag;
 1308         return (error);
 1309 }
 1310 
 1311 /*
 1312  * IP6 socket option processing.
 1313  */
 1314 int
 1315 ip6_ctloutput(op, so, level, optname, mp)
 1316         int op;
 1317         struct socket *so;
 1318         int level, optname;
 1319         struct mbuf **mp;
 1320 {
 1321         struct in6pcb *in6p = sotoin6pcb(so);
 1322         struct mbuf *m = *mp;
 1323         int optval = 0;
 1324         int error = 0;
 1325         struct proc *p = curproc;       /* XXX */
 1326 
 1327         if (level == IPPROTO_IPV6) {
 1328                 switch (op) {
 1329                 case PRCO_SETOPT:
 1330                         switch (optname) {
 1331                         case IPV6_PKTOPTIONS:
 1332                                 /* m is freed in ip6_pcbopts */
 1333                                 return (ip6_pcbopts(&in6p->in6p_outputopts,
 1334                                     m, so));
 1335                         case IPV6_HOPOPTS:
 1336                         case IPV6_DSTOPTS:
 1337                                 if (p == 0 || suser(p->p_ucred, &p->p_acflag)) {
 1338                                         error = EPERM;
 1339                                         break;
 1340                                 }
 1341                                 /* FALLTHROUGH */
 1342                         case IPV6_UNICAST_HOPS:
 1343                         case IPV6_RECVOPTS:
 1344                         case IPV6_RECVRETOPTS:
 1345                         case IPV6_RECVDSTADDR:
 1346                         case IPV6_PKTINFO:
 1347                         case IPV6_HOPLIMIT:
 1348                         case IPV6_RTHDR:
 1349                         case IPV6_FAITH:
 1350                         case IPV6_V6ONLY:
 1351                         case IPV6_USE_MIN_MTU:
 1352                                 if (!m || m->m_len != sizeof(int)) {
 1353                                         error = EINVAL;
 1354                                         break;
 1355                                 }
 1356                                 optval = *mtod(m, int *);
 1357                                 switch (optname) {
 1358 
 1359                                 case IPV6_UNICAST_HOPS:
 1360                                         if (optval < -1 || optval >= 256)
 1361                                                 error = EINVAL;
 1362                                         else {
 1363                                                 /* -1 = kernel default */
 1364                                                 in6p->in6p_hops = optval;
 1365                                         }
 1366                                         break;
 1367 #define OPTSET(bit) \
 1368 do { \
 1369         if (optval) \
 1370                 in6p->in6p_flags |= (bit); \
 1371         else \
 1372                 in6p->in6p_flags &= ~(bit); \
 1373 } while (/*CONSTCOND*/ 0)
 1374 
 1375                                 case IPV6_RECVOPTS:
 1376                                         OPTSET(IN6P_RECVOPTS);
 1377                                         break;
 1378 
 1379                                 case IPV6_RECVRETOPTS:
 1380                                         OPTSET(IN6P_RECVRETOPTS);
 1381                                         break;
 1382 
 1383                                 case IPV6_RECVDSTADDR:
 1384                                         OPTSET(IN6P_RECVDSTADDR);
 1385                                         break;
 1386 
 1387                                 case IPV6_PKTINFO:
 1388                                         OPTSET(IN6P_PKTINFO);
 1389                                         break;
 1390 
 1391                                 case IPV6_HOPLIMIT:
 1392                                         OPTSET(IN6P_HOPLIMIT);
 1393                                         break;
 1394 
 1395                                 case IPV6_HOPOPTS:
 1396                                         OPTSET(IN6P_HOPOPTS);
 1397                                         break;
 1398 
 1399                                 case IPV6_DSTOPTS:
 1400                                         OPTSET(IN6P_DSTOPTS);
 1401                                         break;
 1402 
 1403                                 case IPV6_RTHDR:
 1404                                         OPTSET(IN6P_RTHDR);
 1405                                         break;
 1406 
 1407                                 case IPV6_FAITH:
 1408                                         OPTSET(IN6P_FAITH);
 1409                                         break;
 1410 
 1411                                 case IPV6_USE_MIN_MTU:
 1412                                         OPTSET(IN6P_MINMTU);
 1413                                         break;
 1414 
 1415                                 case IPV6_V6ONLY:
 1416                                         /*
 1417                                          * make setsockopt(IPV6_V6ONLY)
 1418                                          * available only prior to bind(2).
 1419                                          * see ipng mailing list, Jun 22 2001.
 1420                                          */
 1421                                         if (in6p->in6p_lport ||
 1422                                             !IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
 1423                                                 error = EINVAL;
 1424                                                 break;
 1425                                         }
 1426 #ifdef INET6_BINDV6ONLY
 1427                                         if (!optval)
 1428                                                 error = EINVAL;
 1429 #else
 1430                                         OPTSET(IN6P_IPV6_V6ONLY);
 1431 #endif
 1432                                         break;
 1433                                 }
 1434                                 break;
 1435 #undef OPTSET
 1436 
 1437                         case IPV6_MULTICAST_IF:
 1438                         case IPV6_MULTICAST_HOPS:
 1439                         case IPV6_MULTICAST_LOOP:
 1440                         case IPV6_JOIN_GROUP:
 1441                         case IPV6_LEAVE_GROUP:
 1442                                 error = ip6_setmoptions(optname,
 1443                                     &in6p->in6p_moptions, m);
 1444                                 break;
 1445 
 1446                         case IPV6_PORTRANGE:
 1447                                 optval = *mtod(m, int *);
 1448 
 1449                                 switch (optval) {
 1450                                 case IPV6_PORTRANGE_DEFAULT:
 1451                                         in6p->in6p_flags &= ~(IN6P_LOWPORT);
 1452                                         in6p->in6p_flags &= ~(IN6P_HIGHPORT);
 1453                                         break;
 1454 
 1455                                 case IPV6_PORTRANGE_HIGH:
 1456                                         in6p->in6p_flags &= ~(IN6P_LOWPORT);
 1457                                         in6p->in6p_flags |= IN6P_HIGHPORT;
 1458                                         break;
 1459 
 1460                                 case IPV6_PORTRANGE_LOW:
 1461                                         in6p->in6p_flags &= ~(IN6P_HIGHPORT);
 1462                                         in6p->in6p_flags |= IN6P_LOWPORT;
 1463                                         break;
 1464 
 1465                                 default:
 1466                                         error = EINVAL;
 1467                                         break;
 1468                                 }
 1469                                 break;
 1470 
 1471 #ifdef IPSEC
 1472                         case IPV6_IPSEC_POLICY:
 1473                             {
 1474                                 caddr_t req = NULL;
 1475                                 size_t len = 0;
 1476 
 1477                                 int priv = 0;
 1478                                 if (p == 0 || suser(p->p_ucred, &p->p_acflag))
 1479                                         priv = 0;
 1480                                 else
 1481                                         priv = 1;
 1482                                 if (m) {
 1483                                         req = mtod(m, caddr_t);
 1484                                         len = m->m_len;
 1485                                 }
 1486                                 error = ipsec6_set_policy(in6p,
 1487                                                    optname, req, len, priv);
 1488                             }
 1489                                 break;
 1490 #endif /* IPSEC */
 1491 
 1492                         default:
 1493                                 error = ENOPROTOOPT;
 1494                                 break;
 1495                         }
 1496                         if (m)
 1497                                 (void)m_free(m);
 1498                         break;
 1499 
 1500                 case PRCO_GETOPT:
 1501                         switch (optname) {
 1502 
 1503                         case IPV6_OPTIONS:
 1504                         case IPV6_RETOPTS:
 1505                                 error = ENOPROTOOPT;
 1506                                 break;
 1507 
 1508                         case IPV6_PKTOPTIONS:
 1509                                 if (in6p->in6p_options) {
 1510                                         *mp = m_copym(in6p->in6p_options, 0,
 1511                                             M_COPYALL, M_WAIT);
 1512                                 } else {
 1513                                         *mp = m_get(M_WAIT, MT_SOOPTS);
 1514                                         (*mp)->m_len = 0;
 1515                                 }
 1516                                 break;
 1517 
 1518                         case IPV6_HOPOPTS:
 1519                         case IPV6_DSTOPTS:
 1520                                 if (p == 0 || suser(p->p_ucred, &p->p_acflag)) {
 1521                                         error = EPERM;
 1522                                         break;
 1523                                 }
 1524                                 /* FALLTHROUGH */
 1525                         case IPV6_UNICAST_HOPS:
 1526                         case IPV6_RECVOPTS:
 1527                         case IPV6_RECVRETOPTS:
 1528                         case IPV6_RECVDSTADDR:
 1529                         case IPV6_PORTRANGE:
 1530                         case IPV6_PKTINFO:
 1531                         case IPV6_HOPLIMIT:
 1532                         case IPV6_RTHDR:
 1533                         case IPV6_FAITH:
 1534                         case IPV6_V6ONLY:
 1535                         case IPV6_USE_MIN_MTU:
 1536                                 *mp = m = m_get(M_WAIT, MT_SOOPTS);
 1537                                 m->m_len = sizeof(int);
 1538                                 switch (optname) {
 1539 
 1540                                 case IPV6_UNICAST_HOPS:
 1541                                         optval = in6p->in6p_hops;
 1542                                         break;
 1543 
 1544 #define OPTBIT(bit) (in6p->in6p_flags & bit ? 1 : 0)
 1545 
 1546                                 case IPV6_RECVOPTS:
 1547                                         optval = OPTBIT(IN6P_RECVOPTS);
 1548                                         break;
 1549 
 1550                                 case IPV6_RECVRETOPTS:
 1551                                         optval = OPTBIT(IN6P_RECVRETOPTS);
 1552                                         break;
 1553 
 1554                                 case IPV6_RECVDSTADDR:
 1555                                         optval = OPTBIT(IN6P_RECVDSTADDR);
 1556                                         break;
 1557 
 1558                                 case IPV6_PORTRANGE:
 1559                                     {
 1560                                         int flags;
 1561                                         flags = in6p->in6p_flags;
 1562                                         if (flags & IN6P_HIGHPORT)
 1563                                                 optval = IPV6_PORTRANGE_HIGH;
 1564                                         else if (flags & IN6P_LOWPORT)
 1565                                                 optval = IPV6_PORTRANGE_LOW;
 1566                                         else
 1567                                                 optval = 0;
 1568                                         break;
 1569                                     }
 1570 
 1571                                 case IPV6_PKTINFO:
 1572                                         optval = OPTBIT(IN6P_PKTINFO);
 1573                                         break;
 1574 
 1575                                 case IPV6_HOPLIMIT:
 1576                                         optval = OPTBIT(IN6P_HOPLIMIT);
 1577                                         break;
 1578 
 1579                                 case IPV6_HOPOPTS:
 1580                                         optval = OPTBIT(IN6P_HOPOPTS);
 1581                                         break;
 1582 
 1583                                 case IPV6_DSTOPTS:
 1584                                         optval = OPTBIT(IN6P_DSTOPTS);
 1585                                         break;
 1586 
 1587                                 case IPV6_RTHDR:
 1588                                         optval = OPTBIT(IN6P_RTHDR);
 1589                                         break;
 1590 
 1591                                 case IPV6_FAITH:
 1592                                         optval = OPTBIT(IN6P_FAITH);
 1593                                         break;
 1594 
 1595                                 case IPV6_V6ONLY:
 1596                                         optval = OPTBIT(IN6P_IPV6_V6ONLY);
 1597                                         break;
 1598 
 1599                                 case IPV6_USE_MIN_MTU:
 1600                                         optval = OPTBIT(IN6P_MINMTU);
 1601                                         break;
 1602                                 }
 1603                                 *mtod(m, int *) = optval;
 1604                                 break;
 1605 
 1606                         case IPV6_MULTICAST_IF:
 1607                         case IPV6_MULTICAST_HOPS:
 1608                         case IPV6_MULTICAST_LOOP:
 1609                         case IPV6_JOIN_GROUP:
 1610                         case IPV6_LEAVE_GROUP:
 1611                                 error = ip6_getmoptions(optname, in6p->in6p_moptions, mp);
 1612                                 break;
 1613 
 1614 #ifdef IPSEC
 1615                         case IPV6_IPSEC_POLICY:
 1616                         {
 1617                                 caddr_t req = NULL;
 1618                                 size_t len = 0;
 1619 
 1620                                 if (m) {
 1621                                         req = mtod(m, caddr_t);
 1622                                         len = m->m_len;
 1623                                 }
 1624                                 error = ipsec6_get_policy(in6p, req, len, mp);
 1625                                 break;
 1626                         }
 1627 #endif /* IPSEC */
 1628 
 1629                         default:
 1630                                 error = ENOPROTOOPT;
 1631                                 break;
 1632                         }
 1633                         break;
 1634                 }
 1635         } else {
 1636                 error = EINVAL;
 1637                 if (op == PRCO_SETOPT && *mp)
 1638                         (void)m_free(*mp);
 1639         }
 1640         return (error);
 1641 }
 1642 
 1643 int
 1644 ip6_raw_ctloutput(op, so, level, optname, mp)
 1645         int op;
 1646         struct socket *so;
 1647         int level, optname;
 1648         struct mbuf **mp;
 1649 {
 1650         int error = 0, optval, optlen;
 1651         const int icmp6off = offsetof(struct icmp6_hdr, icmp6_cksum);
 1652         struct in6pcb *in6p = sotoin6pcb(so);
 1653         struct mbuf *m = *mp;
 1654 
 1655         optlen = m ? m->m_len : 0;
 1656 
 1657         if (level != IPPROTO_IPV6) {
 1658                 if (op == PRCO_SETOPT && *mp)
 1659                         (void)m_free(*mp);
 1660                 return (EINVAL);
 1661         }
 1662 
 1663         switch (optname) {
 1664         case IPV6_CHECKSUM:
 1665                 /*
 1666                  * For ICMPv6 sockets, no modification allowed for checksum
 1667                  * offset, permit "no change" values to help existing apps.
 1668                  *
 1669                  * XXX 2292bis says: "An attempt to set IPV6_CHECKSUM
 1670                  * for an ICMPv6 socket will fail."
 1671                  * The current behavior does not meet 2292bis.
 1672                  */
 1673                 switch (op) {
 1674                 case PRCO_SETOPT:
 1675                         if (optlen != sizeof(int)) {
 1676                                 error = EINVAL;
 1677                                 break;
 1678                         }
 1679                         optval = *mtod(m, int *);
 1680                         if ((optval % 2) != 0) {
 1681                                 /* the API assumes even offset values */
 1682                                 error = EINVAL;
 1683                         } else if (so->so_proto->pr_protocol ==
 1684                             IPPROTO_ICMPV6) {
 1685                                 if (optval != icmp6off)
 1686                                         error = EINVAL;
 1687                         } else
 1688                                 in6p->in6p_cksum = optval;
 1689                         break;
 1690 
 1691                 case PRCO_GETOPT:
 1692                         if (so->so_proto->pr_protocol == IPPROTO_ICMPV6)
 1693                                 optval = icmp6off;
 1694                         else
 1695                                 optval = in6p->in6p_cksum;
 1696 
 1697                         *mp = m = m_get(M_WAIT, MT_SOOPTS);
 1698                         m->m_len = sizeof(int);
 1699                         *mtod(m, int *) = optval;
 1700                         break;
 1701 
 1702                 default:
 1703                         error = EINVAL;
 1704                         break;
 1705                 }
 1706                 break;
 1707 
 1708         default:
 1709                 error = ENOPROTOOPT;
 1710                 break;
 1711         }
 1712 
 1713         if (op == PRCO_SETOPT && m)
 1714                 (void)m_free(m);
 1715 
 1716         return (error);
 1717 }
 1718 
 1719 /*
 1720  * Set up IP6 options in pcb for insertion in output packets.
 1721  * Store in mbuf with pointer in pcbopt, adding pseudo-option
 1722  * with destination address if source routed.
 1723  */
 1724 static int
 1725 ip6_pcbopts(pktopt, m, so)
 1726         struct ip6_pktopts **pktopt;
 1727         struct mbuf *m;
 1728         struct socket *so;
 1729 {
 1730         struct ip6_pktopts *opt = *pktopt;
 1731         int error = 0;
 1732         struct proc *p = curproc;       /* XXX */
 1733         int priv = 0;
 1734 
 1735         /* turn off any old options. */
 1736         if (opt) {
 1737                 if (opt->ip6po_m)
 1738                         (void)m_free(opt->ip6po_m);
 1739         } else
 1740                 opt = malloc(sizeof(*opt), M_IP6OPT, M_WAITOK);
 1741         *pktopt = 0;
 1742 
 1743         if (!m || m->m_len == 0) {
 1744                 /*
 1745                  * Only turning off any previous options.
 1746                  */
 1747                 free(opt, M_IP6OPT);
 1748                 if (m)
 1749                         (void)m_free(m);
 1750                 return (0);
 1751         }
 1752 
 1753         /*  set options specified by user. */
 1754         if (p && !suser(p->p_ucred, &p->p_acflag))
 1755                 priv = 1;
 1756         if ((error = ip6_setpktoptions(m, opt, priv)) != 0) {
 1757                 (void)m_free(m);
 1758                 free(opt, M_IP6OPT);
 1759                 return (error);
 1760         }
 1761         *pktopt = opt;
 1762         return (0);
 1763 }
 1764 
 1765 /*
 1766  * Set the IP6 multicast options in response to user setsockopt().
 1767  */
 1768 static int
 1769 ip6_setmoptions(optname, im6op, m)
 1770         int optname;
 1771         struct ip6_moptions **im6op;
 1772         struct mbuf *m;
 1773 {
 1774         int error = 0;
 1775         u_int loop, ifindex;
 1776         struct ipv6_mreq *mreq;
 1777         struct ifnet *ifp;
 1778         struct ip6_moptions *im6o = *im6op;
 1779         struct route_in6 ro;
 1780         struct sockaddr_in6 *dst;
 1781         struct in6_multi_mship *imm;
 1782         struct proc *p = curproc;       /* XXX */
 1783 
 1784         if (im6o == NULL) {
 1785                 /*
 1786                  * No multicast option buffer attached to the pcb;
 1787                  * allocate one and initialize to default values.
 1788                  */
 1789                 im6o = (struct ip6_moptions *)
 1790                         malloc(sizeof(*im6o), M_IPMOPTS, M_WAITOK);
 1791 
 1792                 if (im6o == NULL)
 1793                         return (ENOBUFS);
 1794                 *im6op = im6o;
 1795                 im6o->im6o_multicast_ifp = NULL;
 1796                 im6o->im6o_multicast_hlim = ip6_defmcasthlim;
 1797                 im6o->im6o_multicast_loop = IPV6_DEFAULT_MULTICAST_LOOP;
 1798                 LIST_INIT(&im6o->im6o_memberships);
 1799         }
 1800 
 1801         switch (optname) {
 1802 
 1803         case IPV6_MULTICAST_IF:
 1804                 /*
 1805                  * Select the interface for outgoing multicast packets.
 1806                  */
 1807                 if (m == NULL || m->m_len != sizeof(u_int)) {
 1808                         error = EINVAL;
 1809                         break;
 1810                 }
 1811                 bcopy(mtod(m, u_int *), &ifindex, sizeof(ifindex));
 1812                 if (ifindex < 0 || if_indexlim <= ifindex ||
 1813                     !ifindex2ifnet[ifindex]) {
 1814                         error = ENXIO;  /* XXX EINVAL? */
 1815                         break;
 1816                 }
 1817                 ifp = ifindex2ifnet[ifindex];
 1818                 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
 1819                         error = EADDRNOTAVAIL;
 1820                         break;
 1821                 }
 1822                 im6o->im6o_multicast_ifp = ifp;
 1823                 break;
 1824 
 1825         case IPV6_MULTICAST_HOPS:
 1826             {
 1827                 /*
 1828                  * Set the IP6 hoplimit for outgoing multicast packets.
 1829                  */
 1830                 int optval;
 1831                 if (m == NULL || m->m_len != sizeof(int)) {
 1832                         error = EINVAL;
 1833                         break;
 1834                 }
 1835                 bcopy(mtod(m, u_int *), &optval, sizeof(optval));
 1836                 if (optval < -1 || optval >= 256)
 1837                         error = EINVAL;
 1838                 else if (optval == -1)
 1839                         im6o->im6o_multicast_hlim = ip6_defmcasthlim;
 1840                 else
 1841                         im6o->im6o_multicast_hlim = optval;
 1842                 break;
 1843             }
 1844 
 1845         case IPV6_MULTICAST_LOOP:
 1846                 /*
 1847                  * Set the loopback flag for outgoing multicast packets.
 1848                  * Must be zero or one.
 1849                  */
 1850                 if (m == NULL || m->m_len != sizeof(u_int)) {
 1851                         error = EINVAL;
 1852                         break;
 1853                 }
 1854                 bcopy(mtod(m, u_int *), &loop, sizeof(loop));
 1855                 if (loop > 1) {
 1856                         error = EINVAL;
 1857                         break;
 1858                 }
 1859                 im6o->im6o_multicast_loop = loop;
 1860                 break;
 1861 
 1862         case IPV6_JOIN_GROUP:
 1863                 /*
 1864                  * Add a multicast group membership.
 1865                  * Group must be a valid IP6 multicast address.
 1866                  */
 1867                 if (m == NULL || m->m_len != sizeof(struct ipv6_mreq)) {
 1868                         error = EINVAL;
 1869                         break;
 1870                 }
 1871                 mreq = mtod(m, struct ipv6_mreq *);
 1872                 if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) {
 1873                         /*
 1874                          * We use the unspecified address to specify to accept
 1875                          * all multicast addresses. Only super user is allowed
 1876                          * to do this.
 1877                          */
 1878                         if (suser(p->p_ucred, &p->p_acflag))
 1879                         {
 1880                                 error = EACCES;
 1881                                 break;
 1882                         }
 1883                 } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) {
 1884                         error = EINVAL;
 1885                         break;
 1886                 }
 1887 
 1888                 /*
 1889                  * If the interface is specified, validate it.
 1890                  */
 1891                 if (mreq->ipv6mr_interface < 0 ||
 1892                     if_indexlim <= mreq->ipv6mr_interface ||
 1893                     !ifindex2ifnet[mreq->ipv6mr_interface]) {
 1894                         error = ENXIO;  /* XXX EINVAL? */
 1895                         break;
 1896                 }
 1897                 /*
 1898                  * If no interface was explicitly specified, choose an
 1899                  * appropriate one according to the given multicast address.
 1900                  */
 1901                 if (mreq->ipv6mr_interface == 0) {
 1902                         /*
 1903                          * If the multicast address is in node-local scope,
 1904                          * the interface should be a loopback interface.
 1905                          * Otherwise, look up the routing table for the
 1906                          * address, and choose the outgoing interface.
 1907                          *   XXX: is it a good approach?
 1908                          */
 1909                         if (IN6_IS_ADDR_MC_NODELOCAL(&mreq->ipv6mr_multiaddr)) {
 1910                                 ifp = &loif[0];
 1911                         } else {
 1912                                 ro.ro_rt = NULL;
 1913                                 dst = (struct sockaddr_in6 *)&ro.ro_dst;
 1914                                 bzero(dst, sizeof(*dst));
 1915                                 dst->sin6_len = sizeof(struct sockaddr_in6);
 1916                                 dst->sin6_family = AF_INET6;
 1917                                 dst->sin6_addr = mreq->ipv6mr_multiaddr;
 1918                                 rtalloc((struct route *)&ro);
 1919                                 if (ro.ro_rt == NULL) {
 1920                                         error = EADDRNOTAVAIL;
 1921                                         break;
 1922                                 }
 1923                                 ifp = ro.ro_rt->rt_ifp;
 1924                                 rtfree(ro.ro_rt);
 1925                         }
 1926                 } else
 1927                         ifp = ifindex2ifnet[mreq->ipv6mr_interface];
 1928 
 1929                 /*
 1930                  * See if we found an interface, and confirm that it
 1931                  * supports multicast
 1932                  */
 1933                 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
 1934                         error = EADDRNOTAVAIL;
 1935                         break;
 1936                 }
 1937                 /*
 1938                  * Put interface index into the multicast address,
 1939                  * if the address has link-local scope.
 1940                  */
 1941                 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)) {
 1942                         mreq->ipv6mr_multiaddr.s6_addr16[1] =
 1943                             htons(ifp->if_index);
 1944                 }
 1945                 /*
 1946                  * See if the membership already exists.
 1947                  */
 1948                 for (imm = im6o->im6o_memberships.lh_first;
 1949                      imm != NULL; imm = imm->i6mm_chain.le_next)
 1950                         if (imm->i6mm_maddr->in6m_ifp == ifp &&
 1951                             IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
 1952                             &mreq->ipv6mr_multiaddr))
 1953                                 break;
 1954                 if (imm != NULL) {
 1955                         error = EADDRINUSE;
 1956                         break;
 1957                 }
 1958                 /*
 1959                  * Everything looks good; add a new record to the multicast
 1960                  * address list for the given interface.
 1961                  */
 1962                 imm = in6_joingroup(ifp, &mreq->ipv6mr_multiaddr, &error);
 1963                 if (!imm)
 1964                         break;
 1965                 LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain);
 1966                 break;
 1967 
 1968         case IPV6_LEAVE_GROUP:
 1969                 /*
 1970                  * Drop a multicast group membership.
 1971                  * Group must be a valid IP6 multicast address.
 1972                  */
 1973                 if (m == NULL || m->m_len != sizeof(struct ipv6_mreq)) {
 1974                         error = EINVAL;
 1975                         break;
 1976                 }
 1977                 mreq = mtod(m, struct ipv6_mreq *);
 1978                 if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) {
 1979                         if (suser(p->p_ucred, &p->p_acflag))
 1980                         {
 1981                                 error = EACCES;
 1982                                 break;
 1983                         }
 1984                 } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) {
 1985                         error = EINVAL;
 1986                         break;
 1987                 }
 1988                 /*
 1989                  * If an interface address was specified, get a pointer
 1990                  * to its ifnet structure.
 1991                  */
 1992                 if (mreq->ipv6mr_interface < 0 ||
 1993                     if_indexlim <= mreq->ipv6mr_interface ||
 1994                     !ifindex2ifnet[mreq->ipv6mr_interface]) {
 1995                         error = ENXIO;  /* XXX EINVAL? */
 1996                         break;
 1997                 }
 1998                 ifp = ifindex2ifnet[mreq->ipv6mr_interface];
 1999                 /*
 2000                  * Put interface index into the multicast address,
 2001                  * if the address has link-local scope.
 2002                  */
 2003                 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)) {
 2004                         mreq->ipv6mr_multiaddr.s6_addr16[1] =
 2005                             htons(mreq->ipv6mr_interface);
 2006                 }
 2007                 /*
 2008                  * Find the membership in the membership list.
 2009                  */
 2010                 for (imm = im6o->im6o_memberships.lh_first;
 2011                      imm != NULL; imm = imm->i6mm_chain.le_next) {
 2012                         if ((ifp == NULL || imm->i6mm_maddr->in6m_ifp == ifp) &&
 2013                             IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
 2014                             &mreq->ipv6mr_multiaddr))
 2015                                 break;
 2016                 }
 2017                 if (imm == NULL) {
 2018                         /* Unable to resolve interface */
 2019                         error = EADDRNOTAVAIL;
 2020                         break;
 2021                 }
 2022                 /*
 2023                  * Give up the multicast address record to which the
 2024                  * membership points.
 2025                  */
 2026                 LIST_REMOVE(imm, i6mm_chain);
 2027                 in6_leavegroup(imm);
 2028                 break;
 2029 
 2030         default:
 2031                 error = EOPNOTSUPP;
 2032                 break;
 2033         }
 2034 
 2035         /*
 2036          * If all options have default values, no need to keep the mbuf.
 2037          */
 2038         if (im6o->im6o_multicast_ifp == NULL &&
 2039             im6o->im6o_multicast_hlim == ip6_defmcasthlim &&
 2040             im6o->im6o_multicast_loop == IPV6_DEFAULT_MULTICAST_LOOP &&
 2041             im6o->im6o_memberships.lh_first == NULL) {
 2042                 free(*im6op, M_IPMOPTS);
 2043                 *im6op = NULL;
 2044         }
 2045 
 2046         return (error);
 2047 }
 2048 
 2049 /*
 2050  * Return the IP6 multicast options in response to user getsockopt().
 2051  */
 2052 static int
 2053 ip6_getmoptions(optname, im6o, mp)
 2054         int optname;
 2055         struct ip6_moptions *im6o;
 2056         struct mbuf **mp;
 2057 {
 2058         u_int *hlim, *loop, *ifindex;
 2059 
 2060         *mp = m_get(M_WAIT, MT_SOOPTS);
 2061 
 2062         switch (optname) {
 2063 
 2064         case IPV6_MULTICAST_IF:
 2065                 ifindex = mtod(*mp, u_int *);
 2066                 (*mp)->m_len = sizeof(u_int);
 2067                 if (im6o == NULL || im6o->im6o_multicast_ifp == NULL)
 2068                         *ifindex = 0;
 2069                 else
 2070                         *ifindex = im6o->im6o_multicast_ifp->if_index;
 2071                 return (0);
 2072 
 2073         case IPV6_MULTICAST_HOPS:
 2074                 hlim = mtod(*mp, u_int *);
 2075                 (*mp)->m_len = sizeof(u_int);
 2076                 if (im6o == NULL)
 2077                         *hlim = ip6_defmcasthlim;
 2078                 else
 2079                         *hlim = im6o->im6o_multicast_hlim;
 2080                 return (0);
 2081 
 2082         case IPV6_MULTICAST_LOOP:
 2083                 loop = mtod(*mp, u_int *);
 2084                 (*mp)->m_len = sizeof(u_int);
 2085                 if (im6o == NULL)
 2086                         *loop = ip6_defmcasthlim;
 2087                 else
 2088                         *loop = im6o->im6o_multicast_loop;
 2089                 return (0);
 2090 
 2091         default:
 2092                 return (EOPNOTSUPP);
 2093         }
 2094 }
 2095 
 2096 /*
 2097  * Discard the IP6 multicast options.
 2098  */
 2099 void
 2100 ip6_freemoptions(im6o)
 2101         struct ip6_moptions *im6o;
 2102 {
 2103         struct in6_multi_mship *imm;
 2104 
 2105         if (im6o == NULL)
 2106                 return;
 2107 
 2108         while ((imm = im6o->im6o_memberships.lh_first) != NULL) {
 2109                 LIST_REMOVE(imm, i6mm_chain);
 2110                 in6_leavegroup(imm);
 2111         }
 2112         free(im6o, M_IPMOPTS);
 2113 }
 2114 
 2115 /*
 2116  * Set IPv6 outgoing packet options based on advanced API.
 2117  */
 2118 int
 2119 ip6_setpktoptions(control, opt, priv)
 2120         struct mbuf *control;
 2121         struct ip6_pktopts *opt;
 2122         int priv;
 2123 {
 2124         struct cmsghdr *cm = 0;
 2125 
 2126         if (control == 0 || opt == 0)
 2127                 return (EINVAL);
 2128 
 2129         bzero(opt, sizeof(*opt));
 2130         opt->ip6po_hlim = -1; /* -1 means to use default hop limit */
 2131 
 2132         /*
 2133          * XXX: Currently, we assume all the optional information is stored
 2134          * in a single mbuf.
 2135          */
 2136         if (control->m_next)
 2137                 return (EINVAL);
 2138 
 2139         opt->ip6po_m = control;
 2140 
 2141         for (; control->m_len; control->m_data += CMSG_ALIGN(cm->cmsg_len),
 2142             control->m_len -= CMSG_ALIGN(cm->cmsg_len)) {
 2143                 cm = mtod(control, struct cmsghdr *);
 2144                 if (cm->cmsg_len == 0 || cm->cmsg_len > control->m_len)
 2145                         return (EINVAL);
 2146                 if (cm->cmsg_level != IPPROTO_IPV6)
 2147                         continue;
 2148 
 2149                 switch (cm->cmsg_type) {
 2150                 case IPV6_PKTINFO:
 2151                         if (cm->cmsg_len != CMSG_LEN(sizeof(struct in6_pktinfo)))
 2152                                 return (EINVAL);
 2153                         opt->ip6po_pktinfo = (struct in6_pktinfo *)CMSG_DATA(cm);
 2154                         if (opt->ip6po_pktinfo->ipi6_ifindex &&
 2155                             IN6_IS_ADDR_LINKLOCAL(&opt->ip6po_pktinfo->ipi6_addr))
 2156                                 opt->ip6po_pktinfo->ipi6_addr.s6_addr16[1] =
 2157                                         htons(opt->ip6po_pktinfo->ipi6_ifindex);
 2158 
 2159                         if (opt->ip6po_pktinfo->ipi6_ifindex >= if_indexlim ||
 2160                             opt->ip6po_pktinfo->ipi6_ifindex < 0)
 2161                                 return (ENXIO);
 2162                         if (opt->ip6po_pktinfo->ipi6_ifindex > 0 &&
 2163                             !ifindex2ifnet[opt->ip6po_pktinfo->ipi6_ifindex])
 2164                                 return (ENXIO);
 2165 
 2166                         /*
 2167                          * Check if the requested source address is indeed a
 2168                          * unicast address assigned to the node, and can be
 2169                          * used as the packet's source address.
 2170                          */
 2171                         if (!IN6_IS_ADDR_UNSPECIFIED(&opt->ip6po_pktinfo->ipi6_addr)) {
 2172                                 struct ifaddr *ia;
 2173                                 struct in6_ifaddr *ia6;
 2174                                 struct sockaddr_in6 sin6;
 2175 
 2176                                 bzero(&sin6, sizeof(sin6));
 2177                                 sin6.sin6_len = sizeof(sin6);
 2178                                 sin6.sin6_family = AF_INET6;
 2179                                 sin6.sin6_addr =
 2180                                         opt->ip6po_pktinfo->ipi6_addr;
 2181                                 ia = ifa_ifwithaddr(sin6tosa(&sin6));
 2182                                 if (ia == NULL ||
 2183                                     (opt->ip6po_pktinfo->ipi6_ifindex &&
 2184                                      (ia->ifa_ifp->if_index !=
 2185                                       opt->ip6po_pktinfo->ipi6_ifindex))) {
 2186                                         return (EADDRNOTAVAIL);
 2187                                 }
 2188                                 ia6 = (struct in6_ifaddr *)ia;
 2189                                 if ((ia6->ia6_flags & (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)) != 0) {
 2190                                         return (EADDRNOTAVAIL);
 2191                                 }
 2192 
 2193                                 /*
 2194                                  * Check if the requested source address is
 2195                                  * indeed a unicast address assigned to the
 2196                                  * node.
 2197                                  */
 2198                                 if (IN6_IS_ADDR_MULTICAST(&opt->ip6po_pktinfo->ipi6_addr))
 2199                                         return (EADDRNOTAVAIL);
 2200                         }
 2201                         break;
 2202 
 2203                 case IPV6_HOPLIMIT:
 2204                         if (cm->cmsg_len != CMSG_LEN(sizeof(int)))
 2205                                 return (EINVAL);
 2206                         else {
 2207                                 int t;
 2208 
 2209                                 bcopy(CMSG_DATA(cm), &t, sizeof(t));
 2210                                 if (t < -1 || t > 255)
 2211                                         return (EINVAL);
 2212                                 opt->ip6po_hlim = t;
 2213                         }
 2214                         break;
 2215 
 2216                 case IPV6_NEXTHOP:
 2217                         if (!priv)
 2218                                 return (EPERM);
 2219 
 2220                         /* check if cmsg_len is large enough for sa_len */
 2221                         if (cm->cmsg_len < sizeof(u_char) ||
 2222                             cm->cmsg_len < CMSG_LEN(*CMSG_DATA(cm)))
 2223                                 return (EINVAL);
 2224 
 2225                         opt->ip6po_nexthop = (struct sockaddr *)CMSG_DATA(cm);
 2226 
 2227                         break;
 2228 
 2229                 case IPV6_HOPOPTS:
 2230                         if (cm->cmsg_len < CMSG_LEN(sizeof(struct ip6_hbh)))
 2231                                 return (EINVAL);
 2232                         else {
 2233                                 struct  ip6_hbh *t;
 2234 
 2235                                 t = (struct ip6_hbh *)CMSG_DATA(cm);
 2236                                 if (cm->cmsg_len !=
 2237                                     CMSG_LEN((t->ip6h_len + 1) << 3))
 2238                                         return (EINVAL);
 2239                                 opt->ip6po_hbh = t;
 2240                         }
 2241                         break;
 2242 
 2243                 case IPV6_DSTOPTS:
 2244                         if (cm->cmsg_len < CMSG_LEN(sizeof(struct ip6_dest)))
 2245                                 return (EINVAL);
 2246 
 2247                         /*
 2248                          * If there is no routing header yet, the destination
 2249                          * options header should be put on the 1st part.
 2250                          * Otherwise, the header should be on the 2nd part.
 2251                          * (See RFC 2460, section 4.1)
 2252                          */
 2253                         if (opt->ip6po_rthdr == NULL) {
 2254                                 struct ip6_dest *t;
 2255 
 2256                                 t = (struct ip6_dest *)CMSG_DATA(cm);
 2257                                 if (cm->cmsg_len !=
 2258                                     CMSG_LEN((t->ip6d_len + 1) << 3));
 2259                                         return (EINVAL);
 2260                                 opt->ip6po_dest1 = t;
 2261                         }
 2262                         else {
 2263                                 struct ip6_dest *t;
 2264 
 2265                                 t = (struct ip6_dest *)CMSG_DATA(cm);
 2266                                 if (cm->cmsg_len !=
 2267                                     CMSG_LEN((opt->ip6po_dest2->ip6d_len + 1) << 3))
 2268                                         return (EINVAL);
 2269                                 opt->ip6po_dest2 = t;
 2270                         }
 2271                         break;
 2272 
 2273                 case IPV6_RTHDR:
 2274                         if (cm->cmsg_len < CMSG_LEN(sizeof(struct ip6_rthdr)))
 2275                                 return (EINVAL);
 2276                         else {
 2277                                 struct ip6_rthdr *t;
 2278 
 2279                                 t = (struct ip6_rthdr *)CMSG_DATA(cm);
 2280                                 if (cm->cmsg_len !=
 2281                                     CMSG_LEN((t->ip6r_len + 1) << 3))
 2282                                         return (EINVAL);
 2283                                 switch (t->ip6r_type) {
 2284                                 case IPV6_RTHDR_TYPE_0:
 2285                                         if (t->ip6r_segleft == 0)
 2286                                                 return (EINVAL);
 2287                                         break;
 2288                                 default:
 2289                                         return (EINVAL);
 2290                                 }
 2291                                 opt->ip6po_rthdr = t;
 2292                         }
 2293                         break;
 2294 
 2295                 default:
 2296                         return (ENOPROTOOPT);
 2297                 }
 2298         }
 2299 
 2300         return (0);
 2301 }
 2302 
 2303 /*
 2304  * Routine called from ip6_output() to loop back a copy of an IP6 multicast
 2305  * packet to the input queue of a specified interface.  Note that this
 2306  * calls the output routine of the loopback "driver", but with an interface
 2307  * pointer that might NOT be &loif -- easier than replicating that code here.
 2308  */
 2309 void
 2310 ip6_mloopback(ifp, m, dst)
 2311         struct ifnet *ifp;
 2312         struct mbuf *m;
 2313         struct sockaddr_in6 *dst;
 2314 {
 2315         struct mbuf *copym;
 2316         struct ip6_hdr *ip6;
 2317 
 2318         copym = m_copy(m, 0, M_COPYALL);
 2319         if (copym == NULL)
 2320                 return;
 2321 
 2322         /*
 2323          * Make sure to deep-copy IPv6 header portion in case the data
 2324          * is in an mbuf cluster, so that we can safely override the IPv6
 2325          * header portion later.
 2326          */
 2327         if ((copym->m_flags & M_EXT) != 0 ||
 2328             copym->m_len < sizeof(struct ip6_hdr)) {
 2329                 copym = m_pullup(copym, sizeof(struct ip6_hdr));
 2330                 if (copym == NULL)
 2331                         return;
 2332         }
 2333 
 2334 #ifdef DIAGNOSTIC
 2335         if (copym->m_len < sizeof(*ip6)) {
 2336                 m_freem(copym);
 2337                 return;
 2338         }
 2339 #endif
 2340 
 2341         ip6 = mtod(copym, struct ip6_hdr *);
 2342         if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
 2343                 ip6->ip6_src.s6_addr16[1] = 0;
 2344         if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
 2345                 ip6->ip6_dst.s6_addr16[1] = 0;
 2346 
 2347         (void)looutput(ifp, copym, (struct sockaddr *)dst, NULL);
 2348 }
 2349 
 2350 /*
 2351  * Chop IPv6 header off from the payload.
 2352  */
 2353 static int
 2354 ip6_splithdr(m, exthdrs)
 2355         struct mbuf *m;
 2356         struct ip6_exthdrs *exthdrs;
 2357 {
 2358         struct mbuf *mh;
 2359         struct ip6_hdr *ip6;
 2360 
 2361         ip6 = mtod(m, struct ip6_hdr *);
 2362         if (m->m_len > sizeof(*ip6)) {
 2363                 MGETHDR(mh, M_DONTWAIT, MT_HEADER);
 2364                 if (mh == 0) {
 2365                         m_freem(m);
 2366                         return ENOBUFS;
 2367                 }
 2368                 M_COPY_PKTHDR(mh, m);
 2369                 MH_ALIGN(mh, sizeof(*ip6));
 2370                 m_tag_delete_chain(m, NULL);
 2371                 m->m_flags &= ~M_PKTHDR;
 2372                 m->m_len -= sizeof(*ip6);
 2373                 m->m_data += sizeof(*ip6);
 2374                 mh->m_next = m;
 2375                 m = mh;
 2376                 m->m_len = sizeof(*ip6);
 2377                 bcopy((caddr_t)ip6, mtod(m, caddr_t), sizeof(*ip6));
 2378         }
 2379         exthdrs->ip6e_ip6 = m;
 2380         return 0;
 2381 }
 2382 
 2383 /*
 2384  * Compute IPv6 extension header length.
 2385  */
 2386 int
 2387 ip6_optlen(in6p)
 2388         struct in6pcb *in6p;
 2389 {
 2390         int len;
 2391 
 2392         if (!in6p->in6p_outputopts)
 2393                 return 0;
 2394 
 2395         len = 0;
 2396 #define elen(x) \
 2397     (((struct ip6_ext *)(x)) ? (((struct ip6_ext *)(x))->ip6e_len + 1) << 3 : 0)
 2398 
 2399         len += elen(in6p->in6p_outputopts->ip6po_hbh);
 2400         len += elen(in6p->in6p_outputopts->ip6po_dest1);
 2401         len += elen(in6p->in6p_outputopts->ip6po_rthdr);
 2402         len += elen(in6p->in6p_outputopts->ip6po_dest2);
 2403         return len;
 2404 #undef elen
 2405 }

Cache object: eda5dee5849590a48f87b3b4e4821ab4


[ 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.