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.106.2.1 2007/05/24 19:13:16 pavel 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.106.2.1 2007/05/24 19:13:16 pavel Exp $");
   66 
   67 #include "opt_inet.h"
   68 #include "opt_inet6.h"
   69 #include "opt_ipsec.h"
   70 #include "opt_pfil_hooks.h"
   71 
   72 #include <sys/param.h>
   73 #include <sys/malloc.h>
   74 #include <sys/mbuf.h>
   75 #include <sys/errno.h>
   76 #include <sys/protosw.h>
   77 #include <sys/socket.h>
   78 #include <sys/socketvar.h>
   79 #include <sys/systm.h>
   80 #include <sys/proc.h>
   81 #include <sys/kauth.h>
   82 
   83 #include <net/if.h>
   84 #include <net/route.h>
   85 #ifdef PFIL_HOOKS
   86 #include <net/pfil.h>
   87 #endif
   88 
   89 #include <netinet/in.h>
   90 #include <netinet/in_var.h>
   91 #include <netinet/ip6.h>
   92 #include <netinet/icmp6.h>
   93 #include <netinet/in_offload.h>
   94 #include <netinet6/in6_offload.h>
   95 #include <netinet6/ip6_var.h>
   96 #include <netinet6/in6_pcb.h>
   97 #include <netinet6/nd6.h>
   98 #include <netinet6/ip6protosw.h>
   99 #include <netinet6/scope6_var.h>
  100 
  101 #ifdef IPSEC
  102 #include <netinet6/ipsec.h>
  103 #include <netkey/key.h>
  104 #endif /* IPSEC */
  105 
  106 #ifdef FAST_IPSEC
  107 #include <netipsec/ipsec.h>
  108 #include <netipsec/ipsec6.h>
  109 #include <netipsec/key.h>
  110 #include <netipsec/xform.h>
  111 #endif
  112 
  113 
  114 #include <net/net_osdep.h>
  115 
  116 #ifdef PFIL_HOOKS
  117 extern struct pfil_head inet6_pfil_hook;        /* XXX */
  118 #endif
  119 
  120 struct ip6_exthdrs {
  121         struct mbuf *ip6e_ip6;
  122         struct mbuf *ip6e_hbh;
  123         struct mbuf *ip6e_dest1;
  124         struct mbuf *ip6e_rthdr;
  125         struct mbuf *ip6e_dest2;
  126 };
  127 
  128 static int ip6_pcbopt __P((int, u_char *, int, struct ip6_pktopts **,
  129         int, int));
  130 static int ip6_getpcbopt __P((struct ip6_pktopts *, int, struct mbuf **));
  131 static int ip6_setpktopt __P((int, u_char *, int, struct ip6_pktopts *, int,
  132         int, int, int));
  133 static int ip6_setmoptions __P((int, struct ip6_moptions **, struct mbuf *));
  134 static int ip6_getmoptions __P((int, struct ip6_moptions *, struct mbuf **));
  135 static int ip6_copyexthdr __P((struct mbuf **, caddr_t, int));
  136 static int ip6_insertfraghdr __P((struct mbuf *, struct mbuf *, int,
  137         struct ip6_frag **));
  138 static int ip6_insert_jumboopt __P((struct ip6_exthdrs *, u_int32_t));
  139 static int ip6_splithdr __P((struct mbuf *, struct ip6_exthdrs *));
  140 static int ip6_getpmtu __P((struct route_in6 *, struct route_in6 *,
  141         struct ifnet *, struct in6_addr *, u_long *, int *));
  142 static int copypktopts __P((struct ip6_pktopts *, struct ip6_pktopts *, int));
  143 
  144 #ifdef RFC2292
  145 static int ip6_pcbopts __P((struct ip6_pktopts **, struct mbuf *,
  146         struct socket *));
  147 #endif
  148 
  149 #define IN6_NEED_CHECKSUM(ifp, csum_flags) \
  150         (__predict_true(((ifp)->if_flags & IFF_LOOPBACK) == 0 || \
  151         (((csum_flags) & M_CSUM_UDPv6) != 0 && udp_do_loopback_cksum) || \
  152         (((csum_flags) & M_CSUM_TCPv6) != 0 && tcp_do_loopback_cksum)))
  153 
  154 /*
  155  * IP6 output. The packet in mbuf chain m contains a skeletal IP6
  156  * header (with pri, len, nxt, hlim, src, dst).
  157  * This function may modify ver and hlim only.
  158  * The mbuf chain containing the packet will be freed.
  159  * The mbuf opt, if present, will not be freed.
  160  *
  161  * type of "mtu": rt_rmx.rmx_mtu is u_long, ifnet.ifr_mtu is int, and
  162  * nd_ifinfo.linkmtu is u_int32_t.  so we use u_long to hold largest one,
  163  * which is rt_rmx.rmx_mtu.
  164  */
  165 int
  166 ip6_output(
  167     struct mbuf *m0,
  168     struct ip6_pktopts *opt,
  169     struct route_in6 *ro,
  170     int flags,
  171     struct ip6_moptions *im6o,
  172     struct socket *so,
  173     struct ifnet **ifpp         /* XXX: just for statistics */
  174 )
  175 {
  176         struct ip6_hdr *ip6, *mhip6;
  177         struct ifnet *ifp, *origifp;
  178         struct mbuf *m = m0;
  179         int hlen, tlen, len, off;
  180         boolean_t tso;
  181         struct route_in6 ip6route;
  182         struct rtentry *rt = NULL;
  183         struct sockaddr_in6 *dst, src_sa, dst_sa;
  184         int error = 0;
  185         struct in6_ifaddr *ia = NULL;
  186         u_long mtu;
  187         int alwaysfrag, dontfrag;
  188         u_int32_t optlen = 0, plen = 0, unfragpartlen = 0;
  189         struct ip6_exthdrs exthdrs;
  190         struct in6_addr finaldst, src0, dst0;
  191         u_int32_t zone;
  192         struct route_in6 *ro_pmtu = NULL;
  193         int hdrsplit = 0;
  194         int needipsec = 0;
  195 #ifdef IPSEC
  196         int needipsectun = 0;
  197         struct secpolicy *sp = NULL;
  198 
  199         ip6 = mtod(m, struct ip6_hdr *);
  200 #endif /* IPSEC */
  201 #ifdef FAST_IPSEC
  202         struct secpolicy *sp = NULL;
  203         int s;
  204 #endif
  205 
  206 
  207 #ifdef  DIAGNOSTIC
  208         if ((m->m_flags & M_PKTHDR) == 0)
  209                 panic("ip6_output: no HDR");
  210 
  211         if ((m->m_pkthdr.csum_flags &
  212             (M_CSUM_TCPv4|M_CSUM_UDPv4|M_CSUM_TSOv4)) != 0) {
  213                 panic("ip6_output: IPv4 checksum offload flags: %d",
  214                     m->m_pkthdr.csum_flags);
  215         }
  216 
  217         if ((m->m_pkthdr.csum_flags & (M_CSUM_TCPv6|M_CSUM_UDPv6)) ==
  218             (M_CSUM_TCPv6|M_CSUM_UDPv6)) {
  219                 panic("ip6_output: conflicting checksum offload flags: %d",
  220                     m->m_pkthdr.csum_flags);
  221         }
  222 #endif
  223 
  224         M_CSUM_DATA_IPv6_HL_SET(m->m_pkthdr.csum_data, sizeof(struct ip6_hdr));
  225 
  226 #define MAKE_EXTHDR(hp, mp)                                             \
  227     do {                                                                \
  228         if (hp) {                                                       \
  229                 struct ip6_ext *eh = (struct ip6_ext *)(hp);            \
  230                 error = ip6_copyexthdr((mp), (caddr_t)(hp),             \
  231                     ((eh)->ip6e_len + 1) << 3);                         \
  232                 if (error)                                              \
  233                         goto freehdrs;                                  \
  234         }                                                               \
  235     } while (/*CONSTCOND*/ 0)
  236 
  237         bzero(&exthdrs, sizeof(exthdrs));
  238         if (opt) {
  239                 /* Hop-by-Hop options header */
  240                 MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh);
  241                 /* Destination options header(1st part) */
  242                 MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1);
  243                 /* Routing header */
  244                 MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr);
  245                 /* Destination options header(2nd part) */
  246                 MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2);
  247         }
  248 
  249 #ifdef IPSEC
  250         if ((flags & IPV6_FORWARDING) != 0) {
  251                 needipsec = 0;
  252                 goto skippolicycheck;
  253         }
  254 
  255         /* get a security policy for this packet */
  256         if (so == NULL)
  257                 sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error);
  258         else {
  259                 if (IPSEC_PCB_SKIP_IPSEC(sotoinpcb_hdr(so)->inph_sp,
  260                                          IPSEC_DIR_OUTBOUND)) {
  261                         needipsec = 0;
  262                         goto skippolicycheck;
  263                 }
  264                 sp = ipsec6_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error);
  265         }
  266 
  267         if (sp == NULL) {
  268                 ipsec6stat.out_inval++;
  269                 goto freehdrs;
  270         }
  271 
  272         error = 0;
  273 
  274         /* check policy */
  275         switch (sp->policy) {
  276         case IPSEC_POLICY_DISCARD:
  277                 /*
  278                  * This packet is just discarded.
  279                  */
  280                 ipsec6stat.out_polvio++;
  281                 goto freehdrs;
  282 
  283         case IPSEC_POLICY_BYPASS:
  284         case IPSEC_POLICY_NONE:
  285                 /* no need to do IPsec. */
  286                 needipsec = 0;
  287                 break;
  288 
  289         case IPSEC_POLICY_IPSEC:
  290                 if (sp->req == NULL) {
  291                         /* XXX should be panic ? */
  292                         printf("ip6_output: No IPsec request specified.\n");
  293                         error = EINVAL;
  294                         goto freehdrs;
  295                 }
  296                 needipsec = 1;
  297                 break;
  298 
  299         case IPSEC_POLICY_ENTRUST:
  300         default:
  301                 printf("ip6_output: Invalid policy found. %d\n", sp->policy);
  302         }
  303 
  304   skippolicycheck:;
  305 #endif /* IPSEC */
  306 
  307         /*
  308          * Calculate the total length of the extension header chain.
  309          * Keep the length of the unfragmentable part for fragmentation.
  310          */
  311         optlen = 0;
  312         if (exthdrs.ip6e_hbh) optlen += exthdrs.ip6e_hbh->m_len;
  313         if (exthdrs.ip6e_dest1) optlen += exthdrs.ip6e_dest1->m_len;
  314         if (exthdrs.ip6e_rthdr) optlen += exthdrs.ip6e_rthdr->m_len;
  315         unfragpartlen = optlen + sizeof(struct ip6_hdr);
  316         /* NOTE: we don't add AH/ESP length here. do that later. */
  317         if (exthdrs.ip6e_dest2) optlen += exthdrs.ip6e_dest2->m_len;
  318 
  319 #ifdef FAST_IPSEC
  320         /* Check the security policy (SP) for the packet */
  321     
  322         /* XXX For moment, we doesn't support packet with extented action */
  323         if (optlen !=0)
  324                 goto freehdrs;
  325 
  326         sp = ipsec6_check_policy(m,so,flags,&needipsec,&error);
  327         if (error != 0) {
  328                 /*
  329                  * Hack: -EINVAL is used to signal that a packet
  330                  * should be silently discarded.  This is typically
  331                  * because we asked key management for an SA and
  332                  * it was delayed (e.g. kicked up to IKE).
  333                  */
  334         if (error == -EINVAL) 
  335                 error = 0;
  336         goto freehdrs;
  337     }
  338 #endif /* FAST_IPSEC */
  339 
  340 
  341         if (needipsec &&
  342             (m->m_pkthdr.csum_flags & (M_CSUM_UDPv6|M_CSUM_TCPv6)) != 0) {
  343                 in6_delayed_cksum(m);
  344                 m->m_pkthdr.csum_flags &= ~(M_CSUM_UDPv6|M_CSUM_TCPv6);
  345         }
  346 
  347 
  348         /*
  349          * If we need IPsec, or there is at least one extension header,
  350          * separate IP6 header from the payload.
  351          */
  352         if ((needipsec || optlen) && !hdrsplit) {
  353                 if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
  354                         m = NULL;
  355                         goto freehdrs;
  356                 }
  357                 m = exthdrs.ip6e_ip6;
  358                 hdrsplit++;
  359         }
  360 
  361         /* adjust pointer */
  362         ip6 = mtod(m, struct ip6_hdr *);
  363 
  364         /* adjust mbuf packet header length */
  365         m->m_pkthdr.len += optlen;
  366         plen = m->m_pkthdr.len - sizeof(*ip6);
  367 
  368         /* If this is a jumbo payload, insert a jumbo payload option. */
  369         if (plen > IPV6_MAXPACKET) {
  370                 if (!hdrsplit) {
  371                         if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
  372                                 m = NULL;
  373                                 goto freehdrs;
  374                         }
  375                         m = exthdrs.ip6e_ip6;
  376                         hdrsplit++;
  377                 }
  378                 /* adjust pointer */
  379                 ip6 = mtod(m, struct ip6_hdr *);
  380                 if ((error = ip6_insert_jumboopt(&exthdrs, plen)) != 0)
  381                         goto freehdrs;
  382                 optlen += 8; /* XXX JUMBOOPTLEN */
  383                 ip6->ip6_plen = 0;
  384         } else
  385                 ip6->ip6_plen = htons(plen);
  386 
  387         /*
  388          * Concatenate headers and fill in next header fields.
  389          * Here we have, on "m"
  390          *      IPv6 payload
  391          * and we insert headers accordingly.  Finally, we should be getting:
  392          *      IPv6 hbh dest1 rthdr ah* [esp* dest2 payload]
  393          *
  394          * during the header composing process, "m" points to IPv6 header.
  395          * "mprev" points to an extension header prior to esp.
  396          */
  397         {
  398                 u_char *nexthdrp = &ip6->ip6_nxt;
  399                 struct mbuf *mprev = m;
  400 
  401                 /*
  402                  * we treat dest2 specially.  this makes IPsec processing
  403                  * much easier.  the goal here is to make mprev point the
  404                  * mbuf prior to dest2.
  405                  *
  406                  * result: IPv6 dest2 payload
  407                  * m and mprev will point to IPv6 header.
  408                  */
  409                 if (exthdrs.ip6e_dest2) {
  410                         if (!hdrsplit)
  411                                 panic("assumption failed: hdr not split");
  412                         exthdrs.ip6e_dest2->m_next = m->m_next;
  413                         m->m_next = exthdrs.ip6e_dest2;
  414                         *mtod(exthdrs.ip6e_dest2, u_char *) = ip6->ip6_nxt;
  415                         ip6->ip6_nxt = IPPROTO_DSTOPTS;
  416                 }
  417 
  418 #define MAKE_CHAIN(m, mp, p, i)\
  419     do {\
  420         if (m) {\
  421                 if (!hdrsplit) \
  422                         panic("assumption failed: hdr not split"); \
  423                 *mtod((m), u_char *) = *(p);\
  424                 *(p) = (i);\
  425                 p = mtod((m), u_char *);\
  426                 (m)->m_next = (mp)->m_next;\
  427                 (mp)->m_next = (m);\
  428                 (mp) = (m);\
  429         }\
  430     } while (/*CONSTCOND*/ 0)
  431                 /*
  432                  * result: IPv6 hbh dest1 rthdr dest2 payload
  433                  * m will point to IPv6 header.  mprev will point to the
  434                  * extension header prior to dest2 (rthdr in the above case).
  435                  */
  436                 MAKE_CHAIN(exthdrs.ip6e_hbh, mprev, nexthdrp, IPPROTO_HOPOPTS);
  437                 MAKE_CHAIN(exthdrs.ip6e_dest1, mprev, nexthdrp,
  438                     IPPROTO_DSTOPTS);
  439                 MAKE_CHAIN(exthdrs.ip6e_rthdr, mprev, nexthdrp,
  440                     IPPROTO_ROUTING);
  441 
  442                 M_CSUM_DATA_IPv6_HL_SET(m->m_pkthdr.csum_data,
  443                     sizeof(struct ip6_hdr) + optlen);
  444 
  445 #ifdef IPSEC
  446                 if (!needipsec)
  447                         goto skip_ipsec2;
  448 
  449                 /*
  450                  * pointers after IPsec headers are not valid any more.
  451                  * other pointers need a great care too.
  452                  * (IPsec routines should not mangle mbufs prior to AH/ESP)
  453                  */
  454                 exthdrs.ip6e_dest2 = NULL;
  455 
  456             {
  457                 struct ip6_rthdr *rh = NULL;
  458                 int segleft_org = 0;
  459                 struct ipsec_output_state state;
  460 
  461                 if (exthdrs.ip6e_rthdr) {
  462                         rh = mtod(exthdrs.ip6e_rthdr, struct ip6_rthdr *);
  463                         segleft_org = rh->ip6r_segleft;
  464                         rh->ip6r_segleft = 0;
  465                 }
  466 
  467                 bzero(&state, sizeof(state));
  468                 state.m = m;
  469                 error = ipsec6_output_trans(&state, nexthdrp, mprev, sp, flags,
  470                     &needipsectun);
  471                 m = state.m;
  472                 if (error) {
  473                         /* mbuf is already reclaimed in ipsec6_output_trans. */
  474                         m = NULL;
  475                         switch (error) {
  476                         case EHOSTUNREACH:
  477                         case ENETUNREACH:
  478                         case EMSGSIZE:
  479                         case ENOBUFS:
  480                         case ENOMEM:
  481                                 break;
  482                         default:
  483                                 printf("ip6_output (ipsec): error code %d\n", error);
  484                                 /* FALLTHROUGH */
  485                         case ENOENT:
  486                                 /* don't show these error codes to the user */
  487                                 error = 0;
  488                                 break;
  489                         }
  490                         goto bad;
  491                 }
  492                 if (exthdrs.ip6e_rthdr) {
  493                         /* ah6_output doesn't modify mbuf chain */
  494                         rh->ip6r_segleft = segleft_org;
  495                 }
  496             }
  497 skip_ipsec2:;
  498 #endif
  499         }
  500 
  501         /*
  502          * If there is a routing header, replace destination address field
  503          * with the first hop of the routing header.
  504          */
  505         if (exthdrs.ip6e_rthdr) {
  506                 struct ip6_rthdr *rh;
  507                 struct ip6_rthdr0 *rh0;
  508                 struct in6_addr *addr;
  509                 struct sockaddr_in6 sa;
  510 
  511                 rh = (struct ip6_rthdr *)(mtod(exthdrs.ip6e_rthdr,
  512                     struct ip6_rthdr *));
  513                 finaldst = ip6->ip6_dst;
  514                 switch (rh->ip6r_type) {
  515                 case IPV6_RTHDR_TYPE_0:
  516                          rh0 = (struct ip6_rthdr0 *)rh;
  517                          addr = (struct in6_addr *)(rh0 + 1);
  518 
  519                          /*
  520                           * construct a sockaddr_in6 form of
  521                           * the first hop.
  522                           *
  523                           * XXX: we may not have enough
  524                           * information about its scope zone;
  525                           * there is no standard API to pass
  526                           * the information from the
  527                           * application.
  528                           */
  529                          bzero(&sa, sizeof(sa));
  530                          sa.sin6_family = AF_INET6;
  531                          sa.sin6_len = sizeof(sa);
  532                          sa.sin6_addr = addr[0];
  533                          if ((error = sa6_embedscope(&sa,
  534                              ip6_use_defzone)) != 0) {
  535                                  goto bad;
  536                          }
  537                          ip6->ip6_dst = sa.sin6_addr;
  538                          (void)memmove(&addr[0], &addr[1],
  539                              sizeof(struct in6_addr) *
  540                              (rh0->ip6r0_segleft - 1));
  541                          addr[rh0->ip6r0_segleft - 1] = finaldst;
  542                          /* XXX */
  543                          in6_clearscope(addr + rh0->ip6r0_segleft - 1);
  544                          break;
  545                 default:        /* is it possible? */
  546                          error = EINVAL;
  547                          goto bad;
  548                 }
  549         }
  550 
  551         /* Source address validation */
  552         if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) &&
  553             (flags & IPV6_UNSPECSRC) == 0) {
  554                 error = EOPNOTSUPP;
  555                 ip6stat.ip6s_badscope++;
  556                 goto bad;
  557         }
  558         if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) {
  559                 error = EOPNOTSUPP;
  560                 ip6stat.ip6s_badscope++;
  561                 goto bad;
  562         }
  563 
  564         ip6stat.ip6s_localout++;
  565 
  566         /*
  567          * Route packet.
  568          */
  569         /* initialize cached route */
  570         if (ro == 0) {
  571                 ro = &ip6route;
  572                 bzero((caddr_t)ro, sizeof(*ro));
  573         }
  574         ro_pmtu = ro;
  575         if (opt && opt->ip6po_rthdr)
  576                 ro = &opt->ip6po_route;
  577         dst = (struct sockaddr_in6 *)&ro->ro_dst;
  578 
  579         /*
  580          * if specified, try to fill in the traffic class field.
  581          * do not override if a non-zero value is already set.
  582          * we check the diffserv field and the ecn field separately.
  583          */
  584         if (opt && opt->ip6po_tclass >= 0) {
  585                 int mask = 0;
  586 
  587                 if ((ip6->ip6_flow & htonl(0xfc << 20)) == 0)
  588                         mask |= 0xfc;
  589                 if ((ip6->ip6_flow & htonl(0x03 << 20)) == 0)
  590                         mask |= 0x03;
  591                 if (mask != 0)
  592                         ip6->ip6_flow |= htonl((opt->ip6po_tclass & mask) << 20);
  593         }
  594 
  595         /* fill in or override the hop limit field, if necessary. */
  596         if (opt && opt->ip6po_hlim != -1)
  597                 ip6->ip6_hlim = opt->ip6po_hlim & 0xff;
  598         else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
  599                 if (im6o != NULL)
  600                         ip6->ip6_hlim = im6o->im6o_multicast_hlim;
  601                 else
  602                         ip6->ip6_hlim = ip6_defmcasthlim;
  603         }
  604 
  605 #ifdef IPSEC
  606         if (needipsec && needipsectun) {
  607                 struct ipsec_output_state state;
  608 
  609                 /*
  610                  * All the extension headers will become inaccessible
  611                  * (since they can be encrypted).
  612                  * Don't panic, we need no more updates to extension headers
  613                  * on inner IPv6 packet (since they are now encapsulated).
  614                  *
  615                  * IPv6 [ESP|AH] IPv6 [extension headers] payload
  616                  */
  617                 bzero(&exthdrs, sizeof(exthdrs));
  618                 exthdrs.ip6e_ip6 = m;
  619 
  620                 bzero(&state, sizeof(state));
  621                 state.m = m;
  622                 state.ro = (struct route *)ro;
  623                 state.dst = (struct sockaddr *)dst;
  624 
  625                 error = ipsec6_output_tunnel(&state, sp, flags);
  626 
  627                 m = state.m;
  628                 ro_pmtu = ro = (struct route_in6 *)state.ro;
  629                 dst = (struct sockaddr_in6 *)state.dst;
  630                 if (error) {
  631                         /* mbuf is already reclaimed in ipsec6_output_tunnel. */
  632                         m0 = m = NULL;
  633                         m = NULL;
  634                         switch (error) {
  635                         case EHOSTUNREACH:
  636                         case ENETUNREACH:
  637                         case EMSGSIZE:
  638                         case ENOBUFS:
  639                         case ENOMEM:
  640                                 break;
  641                         default:
  642                                 printf("ip6_output (ipsec): error code %d\n", error);
  643                                 /* FALLTHROUGH */
  644                         case ENOENT:
  645                                 /* don't show these error codes to the user */
  646                                 error = 0;
  647                                 break;
  648                         }
  649                         goto bad;
  650                 }
  651 
  652                 exthdrs.ip6e_ip6 = m;
  653         }
  654 #endif /* IPSEC */
  655 #ifdef FAST_IPSEC
  656         if (needipsec) {
  657                 s = splsoftnet();
  658                 error = ipsec6_process_packet(m,sp->req);
  659 
  660                 /*
  661                  * Preserve KAME behaviour: ENOENT can be returned
  662                  * when an SA acquire is in progress.  Don't propagate
  663                  * this to user-level; it confuses applications.
  664                  * XXX this will go away when the SADB is redone.
  665                  */
  666                 if (error == ENOENT)
  667                         error = 0;
  668                 splx(s);
  669                 goto done;
  670     }
  671 #endif /* FAST_IPSEC */    
  672 
  673 
  674 
  675         /* adjust pointer */
  676         ip6 = mtod(m, struct ip6_hdr *);
  677 
  678         bzero(&dst_sa, sizeof(dst_sa));
  679         dst_sa.sin6_family = AF_INET6;
  680         dst_sa.sin6_len = sizeof(dst_sa);
  681         dst_sa.sin6_addr = ip6->ip6_dst;
  682         if ((error = in6_selectroute(&dst_sa, opt, im6o, ro, &ifp, &rt, 0))
  683             != 0) {
  684                 switch (error) {
  685                 case EHOSTUNREACH:
  686                         ip6stat.ip6s_noroute++;
  687                         break;
  688                 case EADDRNOTAVAIL:
  689                 default:
  690                         break; /* XXX statistics? */
  691                 }
  692                 if (ifp != NULL)
  693                         in6_ifstat_inc(ifp, ifs6_out_discard);
  694                 goto bad;
  695         }
  696         if (rt == NULL) {
  697                 /*
  698                  * If in6_selectroute() does not return a route entry,
  699                  * dst may not have been updated.
  700                  */
  701                 *dst = dst_sa;  /* XXX */
  702         }
  703 
  704         /*
  705          * then rt (for unicast) and ifp must be non-NULL valid values.
  706          */
  707         if ((flags & IPV6_FORWARDING) == 0) {
  708                 /* XXX: the FORWARDING flag can be set for mrouting. */
  709                 in6_ifstat_inc(ifp, ifs6_out_request);
  710         }
  711         if (rt != NULL) {
  712                 ia = (struct in6_ifaddr *)(rt->rt_ifa);
  713                 rt->rt_use++;
  714         }
  715 
  716         /*
  717          * The outgoing interface must be in the zone of source and
  718          * destination addresses.  We should use ia_ifp to support the
  719          * case of sending packets to an address of our own.
  720          */
  721         if (ia != NULL && ia->ia_ifp)
  722                 origifp = ia->ia_ifp;
  723         else
  724                 origifp = ifp;
  725 
  726         src0 = ip6->ip6_src;
  727         if (in6_setscope(&src0, origifp, &zone))
  728                 goto badscope;
  729         bzero(&src_sa, sizeof(src_sa));
  730         src_sa.sin6_family = AF_INET6;
  731         src_sa.sin6_len = sizeof(src_sa);
  732         src_sa.sin6_addr = ip6->ip6_src;
  733         if (sa6_recoverscope(&src_sa) || zone != src_sa.sin6_scope_id)
  734                 goto badscope;
  735 
  736         dst0 = ip6->ip6_dst;
  737         if (in6_setscope(&dst0, origifp, &zone))
  738                 goto badscope;
  739         /* re-initialize to be sure */
  740         bzero(&dst_sa, sizeof(dst_sa));
  741         dst_sa.sin6_family = AF_INET6;
  742         dst_sa.sin6_len = sizeof(dst_sa);
  743         dst_sa.sin6_addr = ip6->ip6_dst;
  744         if (sa6_recoverscope(&dst_sa) || zone != dst_sa.sin6_scope_id)
  745                 goto badscope;
  746 
  747         /* scope check is done. */
  748         goto routefound;
  749 
  750   badscope:
  751         ip6stat.ip6s_badscope++;
  752         in6_ifstat_inc(origifp, ifs6_out_discard);
  753         if (error == 0)
  754                 error = EHOSTUNREACH; /* XXX */
  755         goto bad;
  756 
  757   routefound:
  758         if (rt && !IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
  759                 if (opt && opt->ip6po_nextroute.ro_rt) {
  760                         /*
  761                          * The nexthop is explicitly specified by the
  762                          * application.  We assume the next hop is an IPv6
  763                          * address.
  764                          */
  765                         dst = (struct sockaddr_in6 *)opt->ip6po_nexthop;
  766                 } else if ((rt->rt_flags & RTF_GATEWAY))
  767                         dst = (struct sockaddr_in6 *)rt->rt_gateway;
  768         }
  769 
  770         /*
  771          * XXXXXX: original code follows:
  772          */
  773         if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst))
  774                 m->m_flags &= ~(M_BCAST | M_MCAST);     /* just in case */
  775         else {
  776                 struct  in6_multi *in6m;
  777 
  778                 m->m_flags = (m->m_flags & ~M_BCAST) | M_MCAST;
  779 
  780                 in6_ifstat_inc(ifp, ifs6_out_mcast);
  781 
  782                 /*
  783                  * Confirm that the outgoing interface supports multicast.
  784                  */
  785                 if (!(ifp->if_flags & IFF_MULTICAST)) {
  786                         ip6stat.ip6s_noroute++;
  787                         in6_ifstat_inc(ifp, ifs6_out_discard);
  788                         error = ENETUNREACH;
  789                         goto bad;
  790                 }
  791 
  792                 IN6_LOOKUP_MULTI(ip6->ip6_dst, ifp, in6m);
  793                 if (in6m != NULL &&
  794                    (im6o == NULL || im6o->im6o_multicast_loop)) {
  795                         /*
  796                          * If we belong to the destination multicast group
  797                          * on the outgoing interface, and the caller did not
  798                          * forbid loopback, loop back a copy.
  799                          */
  800                         ip6_mloopback(ifp, m, dst);
  801                 } else {
  802                         /*
  803                          * If we are acting as a multicast router, perform
  804                          * multicast forwarding as if the packet had just
  805                          * arrived on the interface to which we are about
  806                          * to send.  The multicast forwarding function
  807                          * recursively calls this function, using the
  808                          * IPV6_FORWARDING flag to prevent infinite recursion.
  809                          *
  810                          * Multicasts that are looped back by ip6_mloopback(),
  811                          * above, will be forwarded by the ip6_input() routine,
  812                          * if necessary.
  813                          */
  814                         if (ip6_mrouter && (flags & IPV6_FORWARDING) == 0) {
  815                                 if (ip6_mforward(ip6, ifp, m) != 0) {
  816                                         m_freem(m);
  817                                         goto done;
  818                                 }
  819                         }
  820                 }
  821                 /*
  822                  * Multicasts with a hoplimit of zero may be looped back,
  823                  * above, but must not be transmitted on a network.
  824                  * Also, multicasts addressed to the loopback interface
  825                  * are not sent -- the above call to ip6_mloopback() will
  826                  * loop back a copy if this host actually belongs to the
  827                  * destination group on the loopback interface.
  828                  */
  829                 if (ip6->ip6_hlim == 0 || (ifp->if_flags & IFF_LOOPBACK) ||
  830                     IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst)) {
  831                         m_freem(m);
  832                         goto done;
  833                 }
  834         }
  835 
  836         /*
  837          * Fill the outgoing inteface to tell the upper layer
  838          * to increment per-interface statistics.
  839          */
  840         if (ifpp)
  841                 *ifpp = ifp;
  842 
  843         /* Determine path MTU. */
  844         if ((error = ip6_getpmtu(ro_pmtu, ro, ifp, &finaldst, &mtu,
  845             &alwaysfrag)) != 0)
  846                 goto bad;
  847 #ifdef IPSEC
  848         if (needipsectun)
  849                 mtu = IPV6_MMTU;
  850 #endif
  851 
  852         /*
  853          * The caller of this function may specify to use the minimum MTU
  854          * in some cases.
  855          * An advanced API option (IPV6_USE_MIN_MTU) can also override MTU
  856          * setting.  The logic is a bit complicated; by default, unicast
  857          * packets will follow path MTU while multicast packets will be sent at
  858          * the minimum MTU.  If IP6PO_MINMTU_ALL is specified, all packets
  859          * including unicast ones will be sent at the minimum MTU.  Multicast
  860          * packets will always be sent at the minimum MTU unless
  861          * IP6PO_MINMTU_DISABLE is explicitly specified.
  862          * See RFC 3542 for more details.
  863          */
  864         if (mtu > IPV6_MMTU) {
  865                 if ((flags & IPV6_MINMTU))
  866                         mtu = IPV6_MMTU;
  867                 else if (opt && opt->ip6po_minmtu == IP6PO_MINMTU_ALL)
  868                         mtu = IPV6_MMTU;
  869                 else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
  870                          (opt == NULL ||
  871                           opt->ip6po_minmtu != IP6PO_MINMTU_DISABLE)) {
  872                         mtu = IPV6_MMTU;
  873                 }
  874         }
  875 
  876         /*
  877          * clear embedded scope identifiers if necessary.
  878          * in6_clearscope will touch the addresses only when necessary.
  879          */
  880         in6_clearscope(&ip6->ip6_src);
  881         in6_clearscope(&ip6->ip6_dst);
  882 
  883         /*
  884          * If the outgoing packet contains a hop-by-hop options header,
  885          * it must be examined and processed even by the source node.
  886          * (RFC 2460, section 4.)
  887          */
  888         if (exthdrs.ip6e_hbh) {
  889                 struct ip6_hbh *hbh = mtod(exthdrs.ip6e_hbh, struct ip6_hbh *);
  890                 u_int32_t dummy1; /* XXX unused */
  891                 u_int32_t dummy2; /* XXX unused */
  892 
  893                 /*
  894                  *  XXX: if we have to send an ICMPv6 error to the sender,
  895                  *       we need the M_LOOP flag since icmp6_error() expects
  896                  *       the IPv6 and the hop-by-hop options header are
  897                  *       continuous unless the flag is set.
  898                  */
  899                 m->m_flags |= M_LOOP;
  900                 m->m_pkthdr.rcvif = ifp;
  901                 if (ip6_process_hopopts(m, (u_int8_t *)(hbh + 1),
  902                     ((hbh->ip6h_len + 1) << 3) - sizeof(struct ip6_hbh),
  903                     &dummy1, &dummy2) < 0) {
  904                         /* m was already freed at this point */
  905                         error = EINVAL;/* better error? */
  906                         goto done;
  907                 }
  908                 m->m_flags &= ~M_LOOP; /* XXX */
  909                 m->m_pkthdr.rcvif = NULL;
  910         }
  911 
  912 #ifdef PFIL_HOOKS
  913         /*
  914          * Run through list of hooks for output packets.
  915          */
  916         if ((error = pfil_run_hooks(&inet6_pfil_hook, &m, ifp, PFIL_OUT)) != 0)
  917                 goto done;
  918         if (m == NULL)
  919                 goto done;
  920         ip6 = mtod(m, struct ip6_hdr *);
  921 #endif /* PFIL_HOOKS */
  922         /*
  923          * Send the packet to the outgoing interface.
  924          * If necessary, do IPv6 fragmentation before sending.
  925          *
  926          * the logic here is rather complex:
  927          * 1: normal case (dontfrag == 0, alwaysfrag == 0)
  928          * 1-a: send as is if tlen <= path mtu
  929          * 1-b: fragment if tlen > path mtu
  930          *
  931          * 2: if user asks us not to fragment (dontfrag == 1)
  932          * 2-a: send as is if tlen <= interface mtu
  933          * 2-b: error if tlen > interface mtu
  934          *
  935          * 3: if we always need to attach fragment header (alwaysfrag == 1)
  936          *      always fragment
  937          *
  938          * 4: if dontfrag == 1 && alwaysfrag == 1
  939          *      error, as we cannot handle this conflicting request
  940          */
  941         tlen = m->m_pkthdr.len;
  942         tso = (m->m_pkthdr.csum_flags & M_CSUM_TSOv6) != 0;
  943         if (opt && (opt->ip6po_flags & IP6PO_DONTFRAG))
  944                 dontfrag = 1;
  945         else
  946                 dontfrag = 0;
  947 
  948         if (dontfrag && alwaysfrag) {   /* case 4 */
  949                 /* conflicting request - can't transmit */
  950                 error = EMSGSIZE;
  951                 goto bad;
  952         }
  953         if (dontfrag && (!tso && tlen > IN6_LINKMTU(ifp))) {    /* case 2-b */
  954                 /*
  955                  * Even if the DONTFRAG option is specified, we cannot send the
  956                  * packet when the data length is larger than the MTU of the
  957                  * outgoing interface.
  958                  * Notify the error by sending IPV6_PATHMTU ancillary data as
  959                  * well as returning an error code (the latter is not described
  960                  * in the API spec.)
  961                  */
  962                 u_int32_t mtu32;
  963                 struct ip6ctlparam ip6cp;
  964 
  965                 mtu32 = (u_int32_t)mtu;
  966                 bzero(&ip6cp, sizeof(ip6cp));
  967                 ip6cp.ip6c_cmdarg = (void *)&mtu32;
  968                 pfctlinput2(PRC_MSGSIZE, (struct sockaddr *)&ro_pmtu->ro_dst,
  969                     (void *)&ip6cp);
  970 
  971                 error = EMSGSIZE;
  972                 goto bad;
  973         }
  974 
  975         /*
  976          * transmit packet without fragmentation
  977          */
  978         if (dontfrag || (!alwaysfrag && (tlen <= mtu || tso))) {
  979                 /* case 1-a and 2-a */
  980                 struct in6_ifaddr *ia6;
  981                 int sw_csum;
  982 
  983                 ip6 = mtod(m, struct ip6_hdr *);
  984                 ia6 = in6_ifawithifp(ifp, &ip6->ip6_src);
  985                 if (ia6) {
  986                         /* Record statistics for this interface address. */
  987                         ia6->ia_ifa.ifa_data.ifad_outbytes += m->m_pkthdr.len;
  988                 }
  989 #ifdef IPSEC
  990                 /* clean ipsec history once it goes out of the node */
  991                 ipsec_delaux(m);
  992 #endif
  993 
  994                 sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_csum_flags_tx;
  995                 if ((sw_csum & (M_CSUM_UDPv6|M_CSUM_TCPv6)) != 0) {
  996                         if (IN6_NEED_CHECKSUM(ifp,
  997                             sw_csum & (M_CSUM_UDPv6|M_CSUM_TCPv6))) {
  998                                 in6_delayed_cksum(m);
  999                         }
 1000                         m->m_pkthdr.csum_flags &= ~(M_CSUM_UDPv6|M_CSUM_TCPv6);
 1001                 }
 1002 
 1003                 if (__predict_true(!tso ||
 1004                     (ifp->if_capenable & IFCAP_TSOv6) != 0)) {
 1005                         error = nd6_output(ifp, origifp, m, dst, rt);
 1006                 } else {
 1007                         error = ip6_tso_output(ifp, origifp, m, dst, rt);
 1008                 }
 1009                 goto done;
 1010         }
 1011 
 1012         if (tso) {
 1013                 error = EINVAL; /* XXX */
 1014                 goto bad;
 1015         }
 1016 
 1017         /*
 1018          * try to fragment the packet.  case 1-b and 3
 1019          */
 1020         if (mtu < IPV6_MMTU) {
 1021                 /* path MTU cannot be less than IPV6_MMTU */
 1022                 error = EMSGSIZE;
 1023                 in6_ifstat_inc(ifp, ifs6_out_fragfail);
 1024                 goto bad;
 1025         } else if (ip6->ip6_plen == 0) {
 1026                 /* jumbo payload cannot be fragmented */
 1027                 error = EMSGSIZE;
 1028                 in6_ifstat_inc(ifp, ifs6_out_fragfail);
 1029                 goto bad;
 1030         } else {
 1031                 struct mbuf **mnext, *m_frgpart;
 1032                 struct ip6_frag *ip6f;
 1033                 u_int32_t id = htonl(ip6_randomid());
 1034                 u_char nextproto;
 1035 #if 0                           /* see below */
 1036                 struct ip6ctlparam ip6cp;
 1037                 u_int32_t mtu32;
 1038 #endif
 1039 
 1040                 /*
 1041                  * Too large for the destination or interface;
 1042                  * fragment if possible.
 1043                  * Must be able to put at least 8 bytes per fragment.
 1044                  */
 1045                 hlen = unfragpartlen;
 1046                 if (mtu > IPV6_MAXPACKET)
 1047                         mtu = IPV6_MAXPACKET;
 1048 
 1049 #if 0
 1050                 /*
 1051                  * It is believed this code is a leftover from the
 1052                  * development of the IPV6_RECVPATHMTU sockopt and
 1053                  * associated work to implement RFC3542.
 1054                  * It's not entirely clear what the intent of the API
 1055                  * is at this point, so disable this code for now.
 1056                  * The IPV6_RECVPATHMTU sockopt and/or IPV6_DONTFRAG
 1057                  * will send notifications if the application requests.
 1058                  */
 1059 
 1060                 /* Notify a proper path MTU to applications. */
 1061                 mtu32 = (u_int32_t)mtu;
 1062                 bzero(&ip6cp, sizeof(ip6cp));
 1063                 ip6cp.ip6c_cmdarg = (void *)&mtu32;
 1064                 pfctlinput2(PRC_MSGSIZE, (struct sockaddr *)&ro_pmtu->ro_dst,
 1065                     (void *)&ip6cp);
 1066 #endif
 1067 
 1068                 len = (mtu - hlen - sizeof(struct ip6_frag)) & ~7;
 1069                 if (len < 8) {
 1070                         error = EMSGSIZE;
 1071                         in6_ifstat_inc(ifp, ifs6_out_fragfail);
 1072                         goto bad;
 1073                 }
 1074 
 1075                 mnext = &m->m_nextpkt;
 1076 
 1077                 /*
 1078                  * Change the next header field of the last header in the
 1079                  * unfragmentable part.
 1080                  */
 1081                 if (exthdrs.ip6e_rthdr) {
 1082                         nextproto = *mtod(exthdrs.ip6e_rthdr, u_char *);
 1083                         *mtod(exthdrs.ip6e_rthdr, u_char *) = IPPROTO_FRAGMENT;
 1084                 } else if (exthdrs.ip6e_dest1) {
 1085                         nextproto = *mtod(exthdrs.ip6e_dest1, u_char *);
 1086                         *mtod(exthdrs.ip6e_dest1, u_char *) = IPPROTO_FRAGMENT;
 1087                 } else if (exthdrs.ip6e_hbh) {
 1088                         nextproto = *mtod(exthdrs.ip6e_hbh, u_char *);
 1089                         *mtod(exthdrs.ip6e_hbh, u_char *) = IPPROTO_FRAGMENT;
 1090                 } else {
 1091                         nextproto = ip6->ip6_nxt;
 1092                         ip6->ip6_nxt = IPPROTO_FRAGMENT;
 1093                 }
 1094 
 1095                 if ((m->m_pkthdr.csum_flags & (M_CSUM_UDPv6|M_CSUM_TCPv6))
 1096                     != 0) {
 1097                         if (IN6_NEED_CHECKSUM(ifp,
 1098                             m->m_pkthdr.csum_flags &
 1099                             (M_CSUM_UDPv6|M_CSUM_TCPv6))) {
 1100                                 in6_delayed_cksum(m);
 1101                         }
 1102                         m->m_pkthdr.csum_flags &= ~(M_CSUM_UDPv6|M_CSUM_TCPv6);
 1103                 }
 1104 
 1105                 /*
 1106                  * Loop through length of segment after first fragment,
 1107                  * make new header and copy data of each part and link onto
 1108                  * chain.
 1109                  */
 1110                 m0 = m;
 1111                 for (off = hlen; off < tlen; off += len) {
 1112                         struct mbuf *mlast;
 1113 
 1114                         MGETHDR(m, M_DONTWAIT, MT_HEADER);
 1115                         if (!m) {
 1116                                 error = ENOBUFS;
 1117                                 ip6stat.ip6s_odropped++;
 1118                                 goto sendorfree;
 1119                         }
 1120                         m->m_pkthdr.rcvif = NULL;
 1121                         m->m_flags = m0->m_flags & M_COPYFLAGS;
 1122                         *mnext = m;
 1123                         mnext = &m->m_nextpkt;
 1124                         m->m_data += max_linkhdr;
 1125                         mhip6 = mtod(m, struct ip6_hdr *);
 1126                         *mhip6 = *ip6;
 1127                         m->m_len = sizeof(*mhip6);
 1128                         error = ip6_insertfraghdr(m0, m, hlen, &ip6f);
 1129                         if (error) {
 1130                                 ip6stat.ip6s_odropped++;
 1131                                 goto sendorfree;
 1132                         }
 1133                         ip6f->ip6f_offlg = htons((u_int16_t)((off - hlen) & ~7));
 1134                         if (off + len >= tlen)
 1135                                 len = tlen - off;
 1136                         else
 1137                                 ip6f->ip6f_offlg |= IP6F_MORE_FRAG;
 1138                         mhip6->ip6_plen = htons((u_int16_t)(len + hlen +
 1139                             sizeof(*ip6f) - sizeof(struct ip6_hdr)));
 1140                         if ((m_frgpart = m_copy(m0, off, len)) == 0) {
 1141                                 error = ENOBUFS;
 1142                                 ip6stat.ip6s_odropped++;
 1143                                 goto sendorfree;
 1144                         }
 1145                         for (mlast = m; mlast->m_next; mlast = mlast->m_next)
 1146                                 ;
 1147                         mlast->m_next = m_frgpart;
 1148                         m->m_pkthdr.len = len + hlen + sizeof(*ip6f);
 1149                         m->m_pkthdr.rcvif = (struct ifnet *)0;
 1150                         ip6f->ip6f_reserved = 0;
 1151                         ip6f->ip6f_ident = id;
 1152                         ip6f->ip6f_nxt = nextproto;
 1153                         ip6stat.ip6s_ofragments++;
 1154                         in6_ifstat_inc(ifp, ifs6_out_fragcreat);
 1155                 }
 1156 
 1157                 in6_ifstat_inc(ifp, ifs6_out_fragok);
 1158         }
 1159 
 1160         /*
 1161          * Remove leading garbages.
 1162          */
 1163 sendorfree:
 1164         m = m0->m_nextpkt;
 1165         m0->m_nextpkt = 0;
 1166         m_freem(m0);
 1167         for (m0 = m; m; m = m0) {
 1168                 m0 = m->m_nextpkt;
 1169                 m->m_nextpkt = 0;
 1170                 if (error == 0) {
 1171                         struct in6_ifaddr *ia6;
 1172                         ip6 = mtod(m, struct ip6_hdr *);
 1173                         ia6 = in6_ifawithifp(ifp, &ip6->ip6_src);
 1174                         if (ia6) {
 1175                                 /*
 1176                                  * Record statistics for this interface
 1177                                  * address.
 1178                                  */
 1179                                 ia6->ia_ifa.ifa_data.ifad_outbytes +=
 1180                                     m->m_pkthdr.len;
 1181                         }
 1182 #ifdef IPSEC
 1183                         /* clean ipsec history once it goes out of the node */
 1184                         ipsec_delaux(m);
 1185 #endif
 1186                         error = nd6_output(ifp, origifp, m, dst, rt);
 1187                 } else
 1188                         m_freem(m);
 1189         }
 1190 
 1191         if (error == 0)
 1192                 ip6stat.ip6s_fragmented++;
 1193 
 1194 done:
 1195         if (ro == &ip6route && ro->ro_rt) { /* brace necessary for RTFREE */
 1196                 RTFREE(ro->ro_rt);
 1197         } else if (ro_pmtu == &ip6route && ro_pmtu->ro_rt) {
 1198                 RTFREE(ro_pmtu->ro_rt);
 1199         }
 1200 
 1201 #ifdef IPSEC
 1202         if (sp != NULL)
 1203                 key_freesp(sp);
 1204 #endif /* IPSEC */
 1205 #ifdef FAST_IPSEC
 1206         if (sp != NULL)
 1207                 KEY_FREESP(&sp);
 1208 #endif /* FAST_IPSEC */
 1209 
 1210 
 1211         return (error);
 1212 
 1213 freehdrs:
 1214         m_freem(exthdrs.ip6e_hbh);      /* m_freem will check if mbuf is 0 */
 1215         m_freem(exthdrs.ip6e_dest1);
 1216         m_freem(exthdrs.ip6e_rthdr);
 1217         m_freem(exthdrs.ip6e_dest2);
 1218         /* FALLTHROUGH */
 1219 bad:
 1220         m_freem(m);
 1221         goto done;
 1222 }
 1223 
 1224 static int
 1225 ip6_copyexthdr(mp, hdr, hlen)
 1226         struct mbuf **mp;
 1227         caddr_t hdr;
 1228         int hlen;
 1229 {
 1230         struct mbuf *m;
 1231 
 1232         if (hlen > MCLBYTES)
 1233                 return (ENOBUFS); /* XXX */
 1234 
 1235         MGET(m, M_DONTWAIT, MT_DATA);
 1236         if (!m)
 1237                 return (ENOBUFS);
 1238 
 1239         if (hlen > MLEN) {
 1240                 MCLGET(m, M_DONTWAIT);
 1241                 if ((m->m_flags & M_EXT) == 0) {
 1242                         m_free(m);
 1243                         return (ENOBUFS);
 1244                 }
 1245         }
 1246         m->m_len = hlen;
 1247         if (hdr)
 1248                 bcopy(hdr, mtod(m, caddr_t), hlen);
 1249 
 1250         *mp = m;
 1251         return (0);
 1252 }
 1253 
 1254 /*
 1255  * Process a delayed payload checksum calculation.
 1256  */
 1257 void
 1258 in6_delayed_cksum(struct mbuf *m)
 1259 {
 1260         uint16_t csum, offset;
 1261 
 1262         KASSERT((m->m_pkthdr.csum_flags & (M_CSUM_UDPv6|M_CSUM_TCPv6)) != 0);
 1263         KASSERT((~m->m_pkthdr.csum_flags & (M_CSUM_UDPv6|M_CSUM_TCPv6)) != 0);
 1264         KASSERT((m->m_pkthdr.csum_flags
 1265             & (M_CSUM_UDPv4|M_CSUM_TCPv4|M_CSUM_TSOv4)) == 0);
 1266 
 1267         offset = M_CSUM_DATA_IPv6_HL(m->m_pkthdr.csum_data);
 1268         csum = in6_cksum(m, 0, offset, m->m_pkthdr.len - offset);
 1269         if (csum == 0 && (m->m_pkthdr.csum_flags & M_CSUM_UDPv6) != 0) {
 1270                 csum = 0xffff;
 1271         }
 1272 
 1273         offset += M_CSUM_DATA_IPv6_OFFSET(m->m_pkthdr.csum_data);
 1274         if ((offset + sizeof(csum)) > m->m_len) {
 1275                 m_copyback(m, offset, sizeof(csum), &csum);
 1276         } else {
 1277                 *(uint16_t *)(mtod(m, caddr_t) + offset) = csum;
 1278         }
 1279 }
 1280 
 1281 /*
 1282  * Insert jumbo payload option.
 1283  */
 1284 static int
 1285 ip6_insert_jumboopt(exthdrs, plen)
 1286         struct ip6_exthdrs *exthdrs;
 1287         u_int32_t plen;
 1288 {
 1289         struct mbuf *mopt;
 1290         u_int8_t *optbuf;
 1291         u_int32_t v;
 1292 
 1293 #define JUMBOOPTLEN     8       /* length of jumbo payload option and padding */
 1294 
 1295         /*
 1296          * If there is no hop-by-hop options header, allocate new one.
 1297          * If there is one but it doesn't have enough space to store the
 1298          * jumbo payload option, allocate a cluster to store the whole options.
 1299          * Otherwise, use it to store the options.
 1300          */
 1301         if (exthdrs->ip6e_hbh == 0) {
 1302                 MGET(mopt, M_DONTWAIT, MT_DATA);
 1303                 if (mopt == 0)
 1304                         return (ENOBUFS);
 1305                 mopt->m_len = JUMBOOPTLEN;
 1306                 optbuf = mtod(mopt, u_int8_t *);
 1307                 optbuf[1] = 0;  /* = ((JUMBOOPTLEN) >> 3) - 1 */
 1308                 exthdrs->ip6e_hbh = mopt;
 1309         } else {
 1310                 struct ip6_hbh *hbh;
 1311 
 1312                 mopt = exthdrs->ip6e_hbh;
 1313                 if (M_TRAILINGSPACE(mopt) < JUMBOOPTLEN) {
 1314                         /*
 1315                          * XXX assumption:
 1316                          * - exthdrs->ip6e_hbh is not referenced from places
 1317                          *   other than exthdrs.
 1318                          * - exthdrs->ip6e_hbh is not an mbuf chain.
 1319                          */
 1320                         int oldoptlen = mopt->m_len;
 1321                         struct mbuf *n;
 1322 
 1323                         /*
 1324                          * XXX: give up if the whole (new) hbh header does
 1325                          * not fit even in an mbuf cluster.
 1326                          */
 1327                         if (oldoptlen + JUMBOOPTLEN > MCLBYTES)
 1328                                 return (ENOBUFS);
 1329 
 1330                         /*
 1331                          * As a consequence, we must always prepare a cluster
 1332                          * at this point.
 1333                          */
 1334                         MGET(n, M_DONTWAIT, MT_DATA);
 1335                         if (n) {
 1336                                 MCLGET(n, M_DONTWAIT);
 1337                                 if ((n->m_flags & M_EXT) == 0) {
 1338                                         m_freem(n);
 1339                                         n = NULL;
 1340                                 }
 1341                         }
 1342                         if (!n)
 1343                                 return (ENOBUFS);
 1344                         n->m_len = oldoptlen + JUMBOOPTLEN;
 1345                         bcopy(mtod(mopt, caddr_t), mtod(n, caddr_t),
 1346                             oldoptlen);
 1347                         optbuf = mtod(n, u_int8_t *) + oldoptlen;
 1348                         m_freem(mopt);
 1349                         mopt = exthdrs->ip6e_hbh = n;
 1350                 } else {
 1351                         optbuf = mtod(mopt, u_int8_t *) + mopt->m_len;
 1352                         mopt->m_len += JUMBOOPTLEN;
 1353                 }
 1354                 optbuf[0] = IP6OPT_PADN;
 1355                 optbuf[1] = 0;
 1356 
 1357                 /*
 1358                  * Adjust the header length according to the pad and
 1359                  * the jumbo payload option.
 1360                  */
 1361                 hbh = mtod(mopt, struct ip6_hbh *);
 1362                 hbh->ip6h_len += (JUMBOOPTLEN >> 3);
 1363         }
 1364 
 1365         /* fill in the option. */
 1366         optbuf[2] = IP6OPT_JUMBO;
 1367         optbuf[3] = 4;
 1368         v = (u_int32_t)htonl(plen + JUMBOOPTLEN);
 1369         bcopy(&v, &optbuf[4], sizeof(u_int32_t));
 1370 
 1371         /* finally, adjust the packet header length */
 1372         exthdrs->ip6e_ip6->m_pkthdr.len += JUMBOOPTLEN;
 1373 
 1374         return (0);
 1375 #undef JUMBOOPTLEN
 1376 }
 1377 
 1378 /*
 1379  * Insert fragment header and copy unfragmentable header portions.
 1380  */
 1381 static int
 1382 ip6_insertfraghdr(m0, m, hlen, frghdrp)
 1383         struct mbuf *m0, *m;
 1384         int hlen;
 1385         struct ip6_frag **frghdrp;
 1386 {
 1387         struct mbuf *n, *mlast;
 1388 
 1389         if (hlen > sizeof(struct ip6_hdr)) {
 1390                 n = m_copym(m0, sizeof(struct ip6_hdr),
 1391                     hlen - sizeof(struct ip6_hdr), M_DONTWAIT);
 1392                 if (n == 0)
 1393                         return (ENOBUFS);
 1394                 m->m_next = n;
 1395         } else
 1396                 n = m;
 1397 
 1398         /* Search for the last mbuf of unfragmentable part. */
 1399         for (mlast = n; mlast->m_next; mlast = mlast->m_next)
 1400                 ;
 1401 
 1402         if ((mlast->m_flags & M_EXT) == 0 &&
 1403             M_TRAILINGSPACE(mlast) >= sizeof(struct ip6_frag)) {
 1404                 /* use the trailing space of the last mbuf for the fragment hdr */
 1405                 *frghdrp = (struct ip6_frag *)(mtod(mlast, caddr_t) +
 1406                     mlast->m_len);
 1407                 mlast->m_len += sizeof(struct ip6_frag);
 1408                 m->m_pkthdr.len += sizeof(struct ip6_frag);
 1409         } else {
 1410                 /* allocate a new mbuf for the fragment header */
 1411                 struct mbuf *mfrg;
 1412 
 1413                 MGET(mfrg, M_DONTWAIT, MT_DATA);
 1414                 if (mfrg == 0)
 1415                         return (ENOBUFS);
 1416                 mfrg->m_len = sizeof(struct ip6_frag);
 1417                 *frghdrp = mtod(mfrg, struct ip6_frag *);
 1418                 mlast->m_next = mfrg;
 1419         }
 1420 
 1421         return (0);
 1422 }
 1423 
 1424 static int
 1425 ip6_getpmtu(ro_pmtu, ro, ifp, dst, mtup, alwaysfragp)
 1426         struct route_in6 *ro_pmtu, *ro;
 1427         struct ifnet *ifp;
 1428         struct in6_addr *dst;
 1429         u_long *mtup;
 1430         int *alwaysfragp;
 1431 {
 1432         u_int32_t mtu = 0;
 1433         int alwaysfrag = 0;
 1434         int error = 0;
 1435 
 1436         if (ro_pmtu != ro) {
 1437                 /* The first hop and the final destination may differ. */
 1438                 struct sockaddr_in6 *sa6_dst =
 1439                     (struct sockaddr_in6 *)&ro_pmtu->ro_dst;
 1440                 if (ro_pmtu->ro_rt &&
 1441                     ((ro_pmtu->ro_rt->rt_flags & RTF_UP) == 0 ||
 1442                       !IN6_ARE_ADDR_EQUAL(&sa6_dst->sin6_addr, dst))) {
 1443                         RTFREE(ro_pmtu->ro_rt);
 1444                         ro_pmtu->ro_rt = (struct rtentry *)NULL;
 1445                 }
 1446                 if (ro_pmtu->ro_rt == NULL) {
 1447                         bzero(sa6_dst, sizeof(*sa6_dst)); /* for safety */
 1448                         sa6_dst->sin6_family = AF_INET6;
 1449                         sa6_dst->sin6_len = sizeof(struct sockaddr_in6);
 1450                         sa6_dst->sin6_addr = *dst;
 1451 
 1452                         rtalloc((struct route *)ro_pmtu);
 1453                 }
 1454         }
 1455         if (ro_pmtu->ro_rt) {
 1456                 u_int32_t ifmtu;
 1457 
 1458                 if (ifp == NULL)
 1459                         ifp = ro_pmtu->ro_rt->rt_ifp;
 1460                 ifmtu = IN6_LINKMTU(ifp);
 1461                 mtu = ro_pmtu->ro_rt->rt_rmx.rmx_mtu;
 1462                 if (mtu == 0)
 1463                         mtu = ifmtu;
 1464                 else if (mtu < IPV6_MMTU) {
 1465                         /*
 1466                          * RFC2460 section 5, last paragraph:
 1467                          * if we record ICMPv6 too big message with
 1468                          * mtu < IPV6_MMTU, transmit packets sized IPV6_MMTU
 1469                          * or smaller, with fragment header attached.
 1470                          * (fragment header is needed regardless from the
 1471                          * packet size, for translators to identify packets)
 1472                          */
 1473                         alwaysfrag = 1;
 1474                         mtu = IPV6_MMTU;
 1475                 } else if (mtu > ifmtu) {
 1476                         /*
 1477                          * The MTU on the route is larger than the MTU on
 1478                          * the interface!  This shouldn't happen, unless the
 1479                          * MTU of the interface has been changed after the
 1480                          * interface was brought up.  Change the MTU in the
 1481                          * route to match the interface MTU (as long as the
 1482                          * field isn't locked).
 1483                          */
 1484                         mtu = ifmtu;
 1485                         if (!(ro_pmtu->ro_rt->rt_rmx.rmx_locks & RTV_MTU))
 1486                                 ro_pmtu->ro_rt->rt_rmx.rmx_mtu = mtu;
 1487                 }
 1488         } else if (ifp) {
 1489                 mtu = IN6_LINKMTU(ifp);
 1490         } else
 1491                 error = EHOSTUNREACH; /* XXX */
 1492 
 1493         *mtup = mtu;
 1494         if (alwaysfragp)
 1495                 *alwaysfragp = alwaysfrag;
 1496         return (error);
 1497 }
 1498 
 1499 /*
 1500  * IP6 socket option processing.
 1501  */
 1502 int
 1503 ip6_ctloutput(op, so, level, optname, mp)
 1504         int op;
 1505         struct socket *so;
 1506         int level, optname;
 1507         struct mbuf **mp;
 1508 {
 1509         int privileged, optdatalen, uproto;
 1510         void *optdata;
 1511         struct in6pcb *in6p = sotoin6pcb(so);
 1512         struct mbuf *m = *mp;
 1513         int error, optval;
 1514         int optlen;
 1515         struct lwp *l = curlwp; /* XXX */
 1516 
 1517         optlen = m ? m->m_len : 0;
 1518         error = optval = 0;
 1519         privileged = (l == 0 || kauth_authorize_generic(l->l_cred,
 1520             KAUTH_GENERIC_ISSUSER, &l->l_acflag)) ? 0 : 1;
 1521         uproto = (int)so->so_proto->pr_protocol;
 1522 
 1523         if (level == IPPROTO_IPV6) {
 1524                 switch (op) {
 1525                 case PRCO_SETOPT:
 1526                         switch (optname) {
 1527 #ifdef RFC2292
 1528                         case IPV6_2292PKTOPTIONS:
 1529                                 /* m is freed in ip6_pcbopts */
 1530                                 error = ip6_pcbopts(&in6p->in6p_outputopts,
 1531                                     m, so);
 1532                                 break;
 1533 #endif
 1534 
 1535                         /*
 1536                          * Use of some Hop-by-Hop options or some
 1537                          * Destination options, might require special
 1538                          * privilege.  That is, normal applications
 1539                          * (without special privilege) might be forbidden
 1540                          * from setting certain options in outgoing packets,
 1541                          * and might never see certain options in received
 1542                          * packets. [RFC 2292 Section 6]
 1543                          * KAME specific note:
 1544                          *  KAME prevents non-privileged users from sending or
 1545                          *  receiving ANY hbh/dst options in order to avoid
 1546                          *  overhead of parsing options in the kernel.
 1547                          */
 1548                         case IPV6_RECVHOPOPTS:
 1549                         case IPV6_RECVDSTOPTS:
 1550                         case IPV6_RECVRTHDRDSTOPTS:
 1551                                 if (!privileged) {
 1552                                         error = EPERM;
 1553                                         break;
 1554                                 }
 1555                                 /* FALLTHROUGH */
 1556                         case IPV6_UNICAST_HOPS:
 1557                         case IPV6_HOPLIMIT:
 1558                         case IPV6_FAITH:
 1559 
 1560                         case IPV6_RECVPKTINFO:
 1561                         case IPV6_RECVHOPLIMIT:
 1562                         case IPV6_RECVRTHDR:
 1563                         case IPV6_RECVPATHMTU:
 1564                         case IPV6_RECVTCLASS:
 1565                         case IPV6_V6ONLY:
 1566                                 if (optlen != sizeof(int)) {
 1567                                         error = EINVAL;
 1568                                         break;
 1569                                 }
 1570                                 optval = *mtod(m, int *);
 1571                                 switch (optname) {
 1572 
 1573                                 case IPV6_UNICAST_HOPS:
 1574                                         if (optval < -1 || optval >= 256)
 1575                                                 error = EINVAL;
 1576                                         else {
 1577                                                 /* -1 = kernel default */
 1578                                                 in6p->in6p_hops = optval;
 1579                                         }
 1580                                         break;
 1581 #define OPTSET(bit) \
 1582 do { \
 1583         if (optval) \
 1584                 in6p->in6p_flags |= (bit); \
 1585         else \
 1586                 in6p->in6p_flags &= ~(bit); \
 1587 } while (/*CONSTCOND*/ 0)
 1588 
 1589 #ifdef RFC2292
 1590 #define OPTSET2292(bit)                         \
 1591 do {                                            \
 1592         in6p->in6p_flags |= IN6P_RFC2292;       \
 1593         if (optval)                             \
 1594                 in6p->in6p_flags |= (bit);      \
 1595         else                                    \
 1596                 in6p->in6p_flags &= ~(bit);     \
 1597 } while (/*CONSTCOND*/ 0)
 1598 #endif
 1599 
 1600 #define OPTBIT(bit) (in6p->in6p_flags & (bit) ? 1 : 0)
 1601 
 1602                                 case IPV6_RECVPKTINFO:
 1603 #ifdef RFC2292
 1604                                         /* cannot mix with RFC2292 */
 1605                                         if (OPTBIT(IN6P_RFC2292)) {
 1606                                                 error = EINVAL;
 1607                                                 break;
 1608                                         }
 1609 #endif
 1610                                         OPTSET(IN6P_PKTINFO);
 1611                                         break;
 1612 
 1613                                 case IPV6_HOPLIMIT:
 1614                                 {
 1615                                         struct ip6_pktopts **optp;
 1616 
 1617 #ifdef RFC2292
 1618                                         /* cannot mix with RFC2292 */
 1619                                         if (OPTBIT(IN6P_RFC2292)) {
 1620                                                 error = EINVAL;
 1621                                                 break;
 1622                                         }
 1623 #endif
 1624                                         optp = &in6p->in6p_outputopts;
 1625                                         error = ip6_pcbopt(IPV6_HOPLIMIT,
 1626                                                            (u_char *)&optval,
 1627                                                            sizeof(optval),
 1628                                                            optp,
 1629                                                            privileged, uproto);
 1630                                         break;
 1631                                 }
 1632 
 1633                                 case IPV6_RECVHOPLIMIT:
 1634 #ifdef RFC2292
 1635                                         /* cannot mix with RFC2292 */
 1636                                         if (OPTBIT(IN6P_RFC2292)) {
 1637                                                 error = EINVAL;
 1638                                                 break;
 1639                                         }
 1640 #endif
 1641                                         OPTSET(IN6P_HOPLIMIT);
 1642                                         break;
 1643 
 1644                                 case IPV6_RECVHOPOPTS:
 1645 #ifdef RFC2292
 1646                                         /* cannot mix with RFC2292 */
 1647                                         if (OPTBIT(IN6P_RFC2292)) {
 1648                                                 error = EINVAL;
 1649                                                 break;
 1650                                         }
 1651 #endif
 1652                                         OPTSET(IN6P_HOPOPTS);
 1653                                         break;
 1654 
 1655                                 case IPV6_RECVDSTOPTS:
 1656 #ifdef RFC2292
 1657                                         /* cannot mix with RFC2292 */
 1658                                         if (OPTBIT(IN6P_RFC2292)) {
 1659                                                 error = EINVAL;
 1660                                                 break;
 1661                                         }
 1662 #endif
 1663                                         OPTSET(IN6P_DSTOPTS);
 1664                                         break;
 1665 
 1666                                 case IPV6_RECVRTHDRDSTOPTS:
 1667 #ifdef RFC2292
 1668                                         /* cannot mix with RFC2292 */
 1669                                         if (OPTBIT(IN6P_RFC2292)) {
 1670                                                 error = EINVAL;
 1671                                                 break;
 1672                                         }
 1673 #endif
 1674                                         OPTSET(IN6P_RTHDRDSTOPTS);
 1675                                         break;
 1676 
 1677                                 case IPV6_RECVRTHDR:
 1678 #ifdef RFC2292
 1679                                         /* cannot mix with RFC2292 */
 1680                                         if (OPTBIT(IN6P_RFC2292)) {
 1681                                                 error = EINVAL;
 1682                                                 break;
 1683                                         }
 1684 #endif
 1685                                         OPTSET(IN6P_RTHDR);
 1686                                         break;
 1687 
 1688                                 case IPV6_FAITH:
 1689                                         OPTSET(IN6P_FAITH);
 1690                                         break;
 1691 
 1692                                 case IPV6_RECVPATHMTU:
 1693                                         /*
 1694                                          * We ignore this option for TCP
 1695                                          * sockets.
 1696                                          * (RFC3542 leaves this case
 1697                                          * unspecified.)
 1698                                          */
 1699                                         if (uproto != IPPROTO_TCP)
 1700                                                 OPTSET(IN6P_MTU);
 1701                                         break;
 1702 
 1703                                 case IPV6_V6ONLY:
 1704                                         /*
 1705                                          * make setsockopt(IPV6_V6ONLY)
 1706                                          * available only prior to bind(2).
 1707                                          * see ipng mailing list, Jun 22 2001.
 1708                                          */
 1709                                         if (in6p->in6p_lport ||
 1710                                             !IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
 1711                                                 error = EINVAL;
 1712                                                 break;
 1713                                         }
 1714 #ifdef INET6_BINDV6ONLY
 1715                                         if (!optval)
 1716                                                 error = EINVAL;
 1717 #else
 1718                                         OPTSET(IN6P_IPV6_V6ONLY);
 1719 #endif
 1720                                         break;
 1721                                 case IPV6_RECVTCLASS:
 1722 #ifdef RFC2292
 1723                                         /* cannot mix with RFC2292 XXX */
 1724                                         if (OPTBIT(IN6P_RFC2292)) {
 1725                                                 error = EINVAL;
 1726                                                 break;
 1727                                         }
 1728 #endif
 1729                                         OPTSET(IN6P_TCLASS);
 1730                                         break;
 1731 
 1732                                 }
 1733                                 break;
 1734 
 1735                         case IPV6_OTCLASS:
 1736                         {
 1737                                 struct ip6_pktopts **optp;
 1738                                 u_int8_t tclass;
 1739 
 1740                                 if (optlen != sizeof(tclass)) {
 1741                                         error = EINVAL;
 1742                                         break;
 1743                                 }
 1744                                 tclass = *mtod(m, u_int8_t *);
 1745                                 optp = &in6p->in6p_outputopts;
 1746                                 error = ip6_pcbopt(optname,
 1747                                                    (u_char *)&tclass,
 1748                                                    sizeof(tclass),
 1749                                                    optp,
 1750                                                    privileged, uproto);
 1751                                 break;
 1752                         }
 1753 
 1754                         case IPV6_TCLASS:
 1755                         case IPV6_DONTFRAG:
 1756                         case IPV6_USE_MIN_MTU:
 1757                                 if (optlen != sizeof(optval)) {
 1758                                         error = EINVAL;
 1759                                         break;
 1760                                 }
 1761                                 optval = *mtod(m, int *);
 1762                                 {
 1763                                         struct ip6_pktopts **optp;
 1764                                         optp = &in6p->in6p_outputopts;
 1765                                         error = ip6_pcbopt(optname,
 1766                                                            (u_char *)&optval,
 1767                                                            sizeof(optval),
 1768                                                            optp,
 1769                                                            privileged, uproto);
 1770                                         break;
 1771                                 }
 1772 
 1773 #ifdef RFC2292
 1774                         case IPV6_2292PKTINFO:
 1775                         case IPV6_2292HOPLIMIT:
 1776                         case IPV6_2292HOPOPTS:
 1777                         case IPV6_2292DSTOPTS:
 1778                         case IPV6_2292RTHDR:
 1779                                 /* RFC 2292 */
 1780                                 if (optlen != sizeof(int)) {
 1781                                         error = EINVAL;
 1782                                         break;
 1783                                 }
 1784                                 optval = *mtod(m, int *);
 1785                                 switch (optname) {
 1786                                 case IPV6_2292PKTINFO:
 1787                                         OPTSET2292(IN6P_PKTINFO);
 1788                                         break;
 1789                                 case IPV6_2292HOPLIMIT:
 1790                                         OPTSET2292(IN6P_HOPLIMIT);
 1791                                         break;
 1792                                 case IPV6_2292HOPOPTS:
 1793                                         /*
 1794                                          * Check super-user privilege.
 1795                                          * See comments for IPV6_RECVHOPOPTS.
 1796                                          */
 1797                                         if (!privileged)
 1798                                                 return (EPERM);
 1799                                         OPTSET2292(IN6P_HOPOPTS);
 1800                                         break;
 1801                                 case IPV6_2292DSTOPTS:
 1802                                         if (!privileged)
 1803                                                 return (EPERM);
 1804                                         OPTSET2292(IN6P_DSTOPTS|IN6P_RTHDRDSTOPTS); /* XXX */
 1805                                         break;
 1806                                 case IPV6_2292RTHDR:
 1807                                         OPTSET2292(IN6P_RTHDR);
 1808                                         break;
 1809                                 }
 1810                                 break;
 1811 #endif
 1812                         case IPV6_PKTINFO:
 1813                         case IPV6_HOPOPTS:
 1814                         case IPV6_RTHDR:
 1815                         case IPV6_DSTOPTS:
 1816                         case IPV6_RTHDRDSTOPTS:
 1817                         case IPV6_NEXTHOP:
 1818                         {
 1819                                 /* new advanced API (RFC3542) */
 1820                                 u_char *optbuf;
 1821                                 int optbuflen;
 1822                                 struct ip6_pktopts **optp;
 1823 
 1824 #ifdef RFC2292
 1825                                 /* cannot mix with RFC2292 */
 1826                                 if (OPTBIT(IN6P_RFC2292)) {
 1827                                         error = EINVAL;
 1828                                         break;
 1829                                 }
 1830 #endif
 1831 
 1832                                 if (m && m->m_next) {
 1833                                         error = EINVAL; /* XXX */
 1834                                         break;
 1835                                 }
 1836                                 if (m) {
 1837                                         optbuf = mtod(m, u_char *);
 1838                                         optbuflen = m->m_len;
 1839                                 } else {
 1840                                         optbuf = NULL;
 1841                                         optbuflen = 0;
 1842                                 }
 1843                                 optp = &in6p->in6p_outputopts;
 1844                                 error = ip6_pcbopt(optname,
 1845                                                    optbuf, optbuflen,
 1846                                                    optp, privileged, uproto);
 1847                                 break;
 1848                         }
 1849 #undef OPTSET
 1850 
 1851                         case IPV6_MULTICAST_IF:
 1852                         case IPV6_MULTICAST_HOPS:
 1853                         case IPV6_MULTICAST_LOOP:
 1854                         case IPV6_JOIN_GROUP:
 1855                         case IPV6_LEAVE_GROUP:
 1856                                 error = ip6_setmoptions(optname,
 1857                                     &in6p->in6p_moptions, m);
 1858                                 break;
 1859 
 1860                         case IPV6_PORTRANGE:
 1861                                 optval = *mtod(m, int *);
 1862 
 1863                                 switch (optval) {
 1864                                 case IPV6_PORTRANGE_DEFAULT:
 1865                                         in6p->in6p_flags &= ~(IN6P_LOWPORT);
 1866                                         in6p->in6p_flags &= ~(IN6P_HIGHPORT);
 1867                                         break;
 1868 
 1869                                 case IPV6_PORTRANGE_HIGH:
 1870                                         in6p->in6p_flags &= ~(IN6P_LOWPORT);
 1871                                         in6p->in6p_flags |= IN6P_HIGHPORT;
 1872                                         break;
 1873 
 1874                                 case IPV6_PORTRANGE_LOW:
 1875                                         in6p->in6p_flags &= ~(IN6P_HIGHPORT);
 1876                                         in6p->in6p_flags |= IN6P_LOWPORT;
 1877                                         break;
 1878 
 1879                                 default:
 1880                                         error = EINVAL;
 1881                                         break;
 1882                                 }
 1883                                 break;
 1884 
 1885 
 1886 #if defined(IPSEC) || defined(FAST_IPSEC)
 1887                         case IPV6_IPSEC_POLICY:
 1888                         {
 1889                                 caddr_t req = NULL;
 1890                                 size_t len = 0;
 1891                                 if (m) {
 1892                                         req = mtod(m, caddr_t);
 1893                                         len = m->m_len;
 1894                                 }
 1895                                 error = ipsec6_set_policy(in6p, optname, req,
 1896                                                           len, privileged);
 1897                         }
 1898                                 break;
 1899 #endif /* IPSEC */
 1900 
 1901                         default:
 1902                                 error = ENOPROTOOPT;
 1903                                 break;
 1904                         }
 1905                         if (m)
 1906                                 (void)m_free(m);
 1907                         break;
 1908 
 1909                 case PRCO_GETOPT:
 1910                         switch (optname) {
 1911 #ifdef RFC2292
 1912                         case IPV6_2292PKTOPTIONS:
 1913                                 /*
 1914                                  * RFC3542 (effectively) deprecated the
 1915                                  * semantics of the 2292-style pktoptions.
 1916                                  * Since it was not reliable in nature (i.e.,
 1917                                  * applications had to expect the lack of some
 1918                                  * information after all), it would make sense
 1919                                  * to simplify this part by always returning
 1920                                  * empty data.
 1921                                  */
 1922                                 *mp = m_get(M_WAIT, MT_SOOPTS);
 1923                                 (*mp)->m_len = 0;
 1924                                 break;
 1925 #endif
 1926 
 1927                         case IPV6_RECVHOPOPTS:
 1928                         case IPV6_RECVDSTOPTS:
 1929                         case IPV6_RECVRTHDRDSTOPTS:
 1930                         case IPV6_UNICAST_HOPS:
 1931                         case IPV6_RECVPKTINFO:
 1932                         case IPV6_RECVHOPLIMIT:
 1933                         case IPV6_RECVRTHDR:
 1934                         case IPV6_RECVPATHMTU:
 1935 
 1936                         case IPV6_FAITH:
 1937                         case IPV6_V6ONLY:
 1938                         case IPV6_PORTRANGE:
 1939                         case IPV6_RECVTCLASS:
 1940                                 switch (optname) {
 1941 
 1942                                 case IPV6_RECVHOPOPTS:
 1943                                         optval = OPTBIT(IN6P_HOPOPTS);
 1944                                         break;
 1945 
 1946                                 case IPV6_RECVDSTOPTS:
 1947                                         optval = OPTBIT(IN6P_DSTOPTS);
 1948                                         break;
 1949 
 1950                                 case IPV6_RECVRTHDRDSTOPTS:
 1951                                         optval = OPTBIT(IN6P_RTHDRDSTOPTS);
 1952                                         break;
 1953 
 1954                                 case IPV6_UNICAST_HOPS:
 1955                                         optval = in6p->in6p_hops;
 1956                                         break;
 1957 
 1958                                 case IPV6_RECVPKTINFO:
 1959                                         optval = OPTBIT(IN6P_PKTINFO);
 1960                                         break;
 1961 
 1962                                 case IPV6_RECVHOPLIMIT:
 1963                                         optval = OPTBIT(IN6P_HOPLIMIT);
 1964                                         break;
 1965 
 1966                                 case IPV6_RECVRTHDR:
 1967                                         optval = OPTBIT(IN6P_RTHDR);
 1968                                         break;
 1969 
 1970                                 case IPV6_RECVPATHMTU:
 1971                                         optval = OPTBIT(IN6P_MTU);
 1972                                         break;
 1973 
 1974                                 case IPV6_FAITH:
 1975                                         optval = OPTBIT(IN6P_FAITH);
 1976                                         break;
 1977 
 1978                                 case IPV6_V6ONLY:
 1979                                         optval = OPTBIT(IN6P_IPV6_V6ONLY);
 1980                                         break;
 1981 
 1982                                 case IPV6_PORTRANGE:
 1983                                     {
 1984                                         int flags;
 1985                                         flags = in6p->in6p_flags;
 1986                                         if (flags & IN6P_HIGHPORT)
 1987                                                 optval = IPV6_PORTRANGE_HIGH;
 1988                                         else if (flags & IN6P_LOWPORT)
 1989                                                 optval = IPV6_PORTRANGE_LOW;
 1990                                         else
 1991                                                 optval = 0;
 1992                                         break;
 1993                                     }
 1994                                 case IPV6_RECVTCLASS:
 1995                                         optval = OPTBIT(IN6P_TCLASS);
 1996                                         break;
 1997 
 1998                                 }
 1999                                 if (error)
 2000                                         break;
 2001                                 *mp = m = m_get(M_WAIT, MT_SOOPTS);
 2002                                 m->m_len = sizeof(int);
 2003                                 *mtod(m, int *) = optval;
 2004                                 break;
 2005 
 2006                         case IPV6_PATHMTU:
 2007                             {
 2008                                 u_long pmtu = 0;
 2009                                 struct ip6_mtuinfo mtuinfo;
 2010                                 struct route_in6 *ro = (struct route_in6 *)&in6p
 2011 ->in6p_route;
 2012 
 2013                                 if (!(so->so_state & SS_ISCONNECTED))
 2014                                         return (ENOTCONN);
 2015                                 /*
 2016                                  * XXX: we dot not consider the case of source
 2017                                  * routing, or optional information to specify
 2018                                  * the outgoing interface.
 2019                                  */
 2020                                 error = ip6_getpmtu(ro, NULL, NULL,
 2021                                     &in6p->in6p_faddr, &pmtu, NULL);
 2022                                 if (error)
 2023                                         break;
 2024                                 if (pmtu > IPV6_MAXPACKET)
 2025                                         pmtu = IPV6_MAXPACKET;
 2026 
 2027                                 memset(&mtuinfo, 0, sizeof(mtuinfo));
 2028                                 mtuinfo.ip6m_mtu = (u_int32_t)pmtu;
 2029                                 optdata = (void *)&mtuinfo;
 2030                                 optdatalen = sizeof(mtuinfo);
 2031                                 if (optdatalen > MCLBYTES)
 2032                                         return (EMSGSIZE); /* XXX */
 2033                                 *mp = m = m_get(M_WAIT, MT_SOOPTS);
 2034                                 if (optdatalen > MLEN)
 2035                                         MCLGET(m, M_WAIT);
 2036                                 m->m_len = optdatalen;
 2037                                 memcpy(mtod(m, void *), optdata, optdatalen);
 2038                                 break;
 2039                             }
 2040 
 2041 #ifdef RFC2292
 2042                         case IPV6_2292PKTINFO:
 2043                         case IPV6_2292HOPLIMIT:
 2044                         case IPV6_2292HOPOPTS:
 2045                         case IPV6_2292RTHDR:
 2046                         case IPV6_2292DSTOPTS:
 2047                                 switch (optname) {
 2048                                 case IPV6_2292PKTINFO:
 2049                                         optval = OPTBIT(IN6P_PKTINFO);
 2050                                         break;
 2051                                 case IPV6_2292HOPLIMIT:
 2052                                         optval = OPTBIT(IN6P_HOPLIMIT);
 2053                                         break;
 2054                                 case IPV6_2292HOPOPTS:
 2055                                         optval = OPTBIT(IN6P_HOPOPTS);
 2056                                         break;
 2057                                 case IPV6_2292RTHDR:
 2058                                         optval = OPTBIT(IN6P_RTHDR);
 2059                                         break;
 2060                                 case IPV6_2292DSTOPTS:
 2061                                         optval = OPTBIT(IN6P_DSTOPTS|IN6P_RTHDRDSTOPTS);
 2062                                         break;
 2063                                 }
 2064                                 *mp = m = m_get(M_WAIT, MT_SOOPTS);
 2065                                 m->m_len = sizeof(int);
 2066                                 *mtod(m, int *) = optval;
 2067                                 break;
 2068 #endif
 2069                         case IPV6_PKTINFO:
 2070                         case IPV6_HOPOPTS:
 2071                         case IPV6_RTHDR:
 2072                         case IPV6_DSTOPTS:
 2073                         case IPV6_RTHDRDSTOPTS:
 2074                         case IPV6_NEXTHOP:
 2075                         case IPV6_OTCLASS:
 2076                         case IPV6_TCLASS:
 2077                         case IPV6_DONTFRAG:
 2078                         case IPV6_USE_MIN_MTU:
 2079                                 error = ip6_getpcbopt(in6p->in6p_outputopts,
 2080                                     optname, mp);
 2081                                 break;
 2082 
 2083                         case IPV6_MULTICAST_IF:
 2084                         case IPV6_MULTICAST_HOPS:
 2085                         case IPV6_MULTICAST_LOOP:
 2086                         case IPV6_JOIN_GROUP:
 2087                         case IPV6_LEAVE_GROUP:
 2088                                 error = ip6_getmoptions(optname,
 2089                                     in6p->in6p_moptions, mp);
 2090                                 break;
 2091 
 2092 #if defined(IPSEC) || defined(FAST_IPSEC)
 2093                         case IPV6_IPSEC_POLICY:
 2094                             {
 2095                                 caddr_t req = NULL;
 2096                                 size_t len = 0;
 2097                                 if (m) {
 2098                                         req = mtod(m, caddr_t);
 2099                                         len = m->m_len;
 2100                                 }
 2101                                 error = ipsec6_get_policy(in6p, req, len, mp);
 2102                                 break;
 2103                             }
 2104 #endif /* IPSEC */
 2105 
 2106 
 2107 
 2108 
 2109                         default:
 2110                                 error = ENOPROTOOPT;
 2111                                 break;
 2112                         }
 2113                         break;
 2114                 }
 2115         } else {
 2116                 error = EINVAL;
 2117                 if (op == PRCO_SETOPT && *mp)
 2118                         (void)m_free(*mp);
 2119         }
 2120         return (error);
 2121 }
 2122 
 2123 int
 2124 ip6_raw_ctloutput(op, so, level, optname, mp)
 2125         int op;
 2126         struct socket *so;
 2127         int level, optname;
 2128         struct mbuf **mp;
 2129 {
 2130         int error = 0, optval, optlen;
 2131         const int icmp6off = offsetof(struct icmp6_hdr, icmp6_cksum);
 2132         struct in6pcb *in6p = sotoin6pcb(so);
 2133         struct mbuf *m = *mp;
 2134 
 2135         optlen = m ? m->m_len : 0;
 2136 
 2137         if (level != IPPROTO_IPV6) {
 2138                 if (op == PRCO_SETOPT && *mp)
 2139                         (void)m_free(*mp);
 2140                 return (EINVAL);
 2141         }
 2142 
 2143         switch (optname) {
 2144         case IPV6_CHECKSUM:
 2145                 /*
 2146                  * For ICMPv6 sockets, no modification allowed for checksum
 2147                  * offset, permit "no change" values to help existing apps.
 2148                  *
 2149                  * XXX RFC3542 says: "An attempt to set IPV6_CHECKSUM
 2150                  * for an ICMPv6 socket will fail."  The current
 2151                  * behavior does not meet RFC3542.
 2152                  */
 2153                 switch (op) {
 2154                 case PRCO_SETOPT:
 2155                         if (optlen != sizeof(int)) {
 2156                                 error = EINVAL;
 2157                                 break;
 2158                         }
 2159                         optval = *mtod(m, int *);
 2160                         if ((optval % 2) != 0) {
 2161                                 /* the API assumes even offset values */
 2162                                 error = EINVAL;
 2163                         } else if (so->so_proto->pr_protocol ==
 2164                             IPPROTO_ICMPV6) {
 2165                                 if (optval != icmp6off)
 2166                                         error = EINVAL;
 2167                         } else
 2168                                 in6p->in6p_cksum = optval;
 2169                         break;
 2170 
 2171                 case PRCO_GETOPT:
 2172                         if (so->so_proto->pr_protocol == IPPROTO_ICMPV6)
 2173                                 optval = icmp6off;
 2174                         else
 2175                                 optval = in6p->in6p_cksum;
 2176 
 2177                         *mp = m = m_get(M_WAIT, MT_SOOPTS);
 2178                         m->m_len = sizeof(int);
 2179                         *mtod(m, int *) = optval;
 2180                         break;
 2181 
 2182                 default:
 2183                         error = EINVAL;
 2184                         break;
 2185                 }
 2186                 break;
 2187 
 2188         default:
 2189                 error = ENOPROTOOPT;
 2190                 break;
 2191         }
 2192 
 2193         if (op == PRCO_SETOPT && m)
 2194                 (void)m_free(m);
 2195 
 2196         return (error);
 2197 }
 2198 
 2199 #ifdef RFC2292
 2200 /*
 2201  * Set up IP6 options in pcb for insertion in output packets or
 2202  * specifying behavior of outgoing packets.
 2203  */
 2204 static int
 2205 ip6_pcbopts(pktopt, m, so)
 2206         struct ip6_pktopts **pktopt;
 2207         struct mbuf *m;
 2208         struct socket *so;
 2209 {
 2210         struct ip6_pktopts *opt = *pktopt;
 2211         int error = 0;
 2212         struct lwp *l = curlwp; /* XXX */
 2213         int priv = 0;
 2214 
 2215         /* turn off any old options. */
 2216         if (opt) {
 2217 #ifdef DIAGNOSTIC
 2218             if (opt->ip6po_pktinfo || opt->ip6po_nexthop ||
 2219                 opt->ip6po_hbh || opt->ip6po_dest1 || opt->ip6po_dest2 ||
 2220                 opt->ip6po_rhinfo.ip6po_rhi_rthdr)
 2221                     printf("ip6_pcbopts: all specified options are cleared.\n");
 2222 #endif
 2223                 ip6_clearpktopts(opt, -1);
 2224         } else
 2225                 opt = malloc(sizeof(*opt), M_IP6OPT, M_WAITOK);
 2226         *pktopt = NULL;
 2227 
 2228         if (!m || m->m_len == 0) {
 2229                 /*
 2230                  * Only turning off any previous options, regardless of
 2231                  * whether the opt is just created or given.
 2232                  */
 2233                 free(opt, M_IP6OPT);
 2234                 return (0);
 2235         }
 2236 
 2237         /*  set options specified by user. */
 2238         if (l && !kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
 2239             &l->l_acflag))
 2240                 priv = 1;
 2241         if ((error = ip6_setpktopts(m, opt, NULL, priv,
 2242             so->so_proto->pr_protocol)) != 0) {
 2243                 ip6_clearpktopts(opt, -1); /* XXX: discard all options */
 2244                 free(opt, M_IP6OPT);
 2245                 return (error);
 2246         }
 2247         *pktopt = opt;
 2248         return (0);
 2249 }
 2250 #endif
 2251 
 2252 /*
 2253  * initialize ip6_pktopts.  beware that there are non-zero default values in
 2254  * the struct.
 2255  */
 2256 void
 2257 ip6_initpktopts(struct ip6_pktopts *opt)
 2258 {
 2259 
 2260         memset(opt, 0, sizeof(*opt));
 2261         opt->ip6po_hlim = -1;   /* -1 means default hop limit */
 2262         opt->ip6po_tclass = -1; /* -1 means default traffic class */
 2263         opt->ip6po_minmtu = IP6PO_MINMTU_MCASTONLY;
 2264 }
 2265 
 2266 #define sin6tosa(sin6)  ((struct sockaddr *)(sin6)) /* XXX */
 2267 static int
 2268 ip6_pcbopt(int optname, u_char *buf, int len, struct ip6_pktopts **pktopt,
 2269     int priv, int uproto)
 2270 {
 2271         struct ip6_pktopts *opt;
 2272 
 2273         if (*pktopt == NULL) {
 2274                 *pktopt = malloc(sizeof(struct ip6_pktopts), M_IP6OPT,
 2275                     M_WAITOK);
 2276                 ip6_initpktopts(*pktopt);
 2277         }
 2278         opt = *pktopt;
 2279 
 2280         return (ip6_setpktopt(optname, buf, len, opt, priv, 1, 0, uproto));
 2281 }
 2282 
 2283 static int
 2284 ip6_getpcbopt(struct ip6_pktopts *pktopt, int optname, struct mbuf **mp)
 2285 {
 2286         void *optdata = NULL;
 2287         int optdatalen = 0;
 2288         struct ip6_ext *ip6e;
 2289         int error = 0;
 2290         struct in6_pktinfo null_pktinfo;
 2291         int deftclass = 0, on;
 2292         int defminmtu = IP6PO_MINMTU_MCASTONLY;
 2293         struct mbuf *m;
 2294 
 2295         switch (optname) {
 2296         case IPV6_PKTINFO:
 2297                 if (pktopt && pktopt->ip6po_pktinfo)
 2298                         optdata = (void *)pktopt->ip6po_pktinfo;
 2299                 else {
 2300                         /* XXX: we don't have to do this every time... */
 2301                         memset(&null_pktinfo, 0, sizeof(null_pktinfo));
 2302                         optdata = (void *)&null_pktinfo;
 2303                 }
 2304                 optdatalen = sizeof(struct in6_pktinfo);
 2305                 break;
 2306         case IPV6_OTCLASS:
 2307                 /* XXX */
 2308                 return (EINVAL);
 2309         case IPV6_TCLASS:
 2310                 if (pktopt && pktopt->ip6po_tclass >= 0)
 2311                         optdata = (void *)&pktopt->ip6po_tclass;
 2312                 else
 2313                         optdata = (void *)&deftclass;
 2314                 optdatalen = sizeof(int);
 2315                 break;
 2316         case IPV6_HOPOPTS:
 2317                 if (pktopt && pktopt->ip6po_hbh) {
 2318                         optdata = (void *)pktopt->ip6po_hbh;
 2319                         ip6e = (struct ip6_ext *)pktopt->ip6po_hbh;
 2320                         optdatalen = (ip6e->ip6e_len + 1) << 3;
 2321                 }
 2322                 break;
 2323         case IPV6_RTHDR:
 2324                 if (pktopt && pktopt->ip6po_rthdr) {
 2325                         optdata = (void *)pktopt->ip6po_rthdr;
 2326                         ip6e = (struct ip6_ext *)pktopt->ip6po_rthdr;
 2327                         optdatalen = (ip6e->ip6e_len + 1) << 3;
 2328                 }
 2329                 break;
 2330         case IPV6_RTHDRDSTOPTS:
 2331                 if (pktopt && pktopt->ip6po_dest1) {
 2332                         optdata = (void *)pktopt->ip6po_dest1;
 2333                         ip6e = (struct ip6_ext *)pktopt->ip6po_dest1;
 2334                         optdatalen = (ip6e->ip6e_len + 1) << 3;
 2335                 }
 2336                 break;
 2337         case IPV6_DSTOPTS:
 2338                 if (pktopt && pktopt->ip6po_dest2) {
 2339                         optdata = (void *)pktopt->ip6po_dest2;
 2340                         ip6e = (struct ip6_ext *)pktopt->ip6po_dest2;
 2341                         optdatalen = (ip6e->ip6e_len + 1) << 3;
 2342                 }
 2343                 break;
 2344         case IPV6_NEXTHOP:
 2345                 if (pktopt && pktopt->ip6po_nexthop) {
 2346                         optdata = (void *)pktopt->ip6po_nexthop;
 2347                         optdatalen = pktopt->ip6po_nexthop->sa_len;
 2348                 }
 2349                 break;
 2350         case IPV6_USE_MIN_MTU:
 2351                 if (pktopt)
 2352                         optdata = (void *)&pktopt->ip6po_minmtu;
 2353                 else
 2354                         optdata = (void *)&defminmtu;
 2355                 optdatalen = sizeof(int);
 2356                 break;
 2357         case IPV6_DONTFRAG:
 2358                 if (pktopt && ((pktopt->ip6po_flags) & IP6PO_DONTFRAG))
 2359                         on = 1;
 2360                 else
 2361                         on = 0;
 2362                 optdata = (void *)&on;
 2363                 optdatalen = sizeof(on);
 2364                 break;
 2365         default:                /* should not happen */
 2366 #ifdef DIAGNOSTIC
 2367                 panic("ip6_getpcbopt: unexpected option\n");
 2368 #endif
 2369                 return (ENOPROTOOPT);
 2370         }
 2371 
 2372         if (optdatalen > MCLBYTES)
 2373                 return (EMSGSIZE); /* XXX */
 2374         *mp = m = m_get(M_WAIT, MT_SOOPTS);
 2375         if (optdatalen > MLEN)
 2376                 MCLGET(m, M_WAIT);
 2377         m->m_len = optdatalen;
 2378         if (optdatalen)
 2379                 memcpy(mtod(m, void *), optdata, optdatalen);
 2380 
 2381         return (error);
 2382 }
 2383 
 2384 void
 2385 ip6_clearpktopts(struct ip6_pktopts *pktopt, int optname)
 2386 {
 2387         if (optname == -1 || optname == IPV6_PKTINFO) {
 2388                 if (pktopt->ip6po_pktinfo)
 2389                         free(pktopt->ip6po_pktinfo, M_IP6OPT);
 2390                 pktopt->ip6po_pktinfo = NULL;
 2391         }
 2392         if (optname == -1 || optname == IPV6_HOPLIMIT)
 2393                 pktopt->ip6po_hlim = -1;
 2394         if (optname == -1 || optname == IPV6_TCLASS)
 2395                 pktopt->ip6po_tclass = -1;
 2396         if (optname == -1 || optname == IPV6_NEXTHOP) {
 2397                 if (pktopt->ip6po_nextroute.ro_rt) {
 2398                         RTFREE(pktopt->ip6po_nextroute.ro_rt);
 2399                         pktopt->ip6po_nextroute.ro_rt = NULL;
 2400                 }
 2401                 if (pktopt->ip6po_nexthop)
 2402                         free(pktopt->ip6po_nexthop, M_IP6OPT);
 2403                 pktopt->ip6po_nexthop = NULL;
 2404         }
 2405         if (optname == -1 || optname == IPV6_HOPOPTS) {
 2406                 if (pktopt->ip6po_hbh)
 2407                         free(pktopt->ip6po_hbh, M_IP6OPT);
 2408                 pktopt->ip6po_hbh = NULL;
 2409         }
 2410         if (optname == -1 || optname == IPV6_RTHDRDSTOPTS) {
 2411                 if (pktopt->ip6po_dest1)
 2412                         free(pktopt->ip6po_dest1, M_IP6OPT);
 2413                 pktopt->ip6po_dest1 = NULL;
 2414         }
 2415         if (optname == -1 || optname == IPV6_RTHDR) {
 2416                 if (pktopt->ip6po_rhinfo.ip6po_rhi_rthdr)
 2417                         free(pktopt->ip6po_rhinfo.ip6po_rhi_rthdr, M_IP6OPT);
 2418                 pktopt->ip6po_rhinfo.ip6po_rhi_rthdr = NULL;
 2419                 if (pktopt->ip6po_route.ro_rt) {
 2420                         RTFREE(pktopt->ip6po_route.ro_rt);
 2421                         pktopt->ip6po_route.ro_rt = NULL;
 2422                 }
 2423         }
 2424         if (optname == -1 || optname == IPV6_DSTOPTS) {
 2425                 if (pktopt->ip6po_dest2)
 2426                         free(pktopt->ip6po_dest2, M_IP6OPT);
 2427                 pktopt->ip6po_dest2 = NULL;
 2428         }
 2429 }
 2430 
 2431 #define PKTOPT_EXTHDRCPY(type)                                  \
 2432 do {                                                            \
 2433         if (src->type) {                                        \
 2434                 int hlen = (((struct ip6_ext *)src->type)->ip6e_len + 1) << 3;\
 2435                 dst->type = malloc(hlen, M_IP6OPT, canwait);    \
 2436                 if (dst->type == NULL && canwait == M_NOWAIT)   \
 2437                         goto bad;                               \
 2438                 memcpy(dst->type, src->type, hlen);             \
 2439         }                                                       \
 2440 } while (/*CONSTCOND*/ 0)
 2441 
 2442 static int
 2443 copypktopts(struct ip6_pktopts *dst, struct ip6_pktopts *src, int canwait)
 2444 {
 2445         dst->ip6po_hlim = src->ip6po_hlim;
 2446         dst->ip6po_tclass = src->ip6po_tclass;
 2447         dst->ip6po_flags = src->ip6po_flags;
 2448         if (src->ip6po_pktinfo) {
 2449                 dst->ip6po_pktinfo = malloc(sizeof(*dst->ip6po_pktinfo),
 2450                     M_IP6OPT, canwait);
 2451                 if (dst->ip6po_pktinfo == NULL && canwait == M_NOWAIT)
 2452                         goto bad;
 2453                 *dst->ip6po_pktinfo = *src->ip6po_pktinfo;
 2454         }
 2455         if (src->ip6po_nexthop) {
 2456                 dst->ip6po_nexthop = malloc(src->ip6po_nexthop->sa_len,
 2457                     M_IP6OPT, canwait);
 2458                 if (dst->ip6po_nexthop == NULL && canwait == M_NOWAIT)
 2459                         goto bad;
 2460                 memcpy(dst->ip6po_nexthop, src->ip6po_nexthop,
 2461                     src->ip6po_nexthop->sa_len);
 2462         }
 2463         PKTOPT_EXTHDRCPY(ip6po_hbh);
 2464         PKTOPT_EXTHDRCPY(ip6po_dest1);
 2465         PKTOPT_EXTHDRCPY(ip6po_dest2);
 2466         PKTOPT_EXTHDRCPY(ip6po_rthdr); /* not copy the cached route */
 2467         return (0);
 2468 
 2469   bad:
 2470         if (dst->ip6po_pktinfo) free(dst->ip6po_pktinfo, M_IP6OPT);
 2471         if (dst->ip6po_nexthop) free(dst->ip6po_nexthop, M_IP6OPT);
 2472         if (dst->ip6po_hbh) free(dst->ip6po_hbh, M_IP6OPT);
 2473         if (dst->ip6po_dest1) free(dst->ip6po_dest1, M_IP6OPT);
 2474         if (dst->ip6po_dest2) free(dst->ip6po_dest2, M_IP6OPT);
 2475         if (dst->ip6po_rthdr) free(dst->ip6po_rthdr, M_IP6OPT);
 2476 
 2477         return (ENOBUFS);
 2478 }
 2479 #undef PKTOPT_EXTHDRCPY
 2480 
 2481 struct ip6_pktopts *
 2482 ip6_copypktopts(struct ip6_pktopts *src, int canwait)
 2483 {
 2484         int error;
 2485         struct ip6_pktopts *dst;
 2486 
 2487         dst = malloc(sizeof(*dst), M_IP6OPT, canwait);
 2488         if (dst == NULL && canwait == M_NOWAIT)
 2489                 return (NULL);
 2490         ip6_initpktopts(dst);
 2491 
 2492         if ((error = copypktopts(dst, src, canwait)) != 0) {
 2493                 free(dst, M_IP6OPT);
 2494                 return (NULL);
 2495         }
 2496 
 2497         return (dst);
 2498 }
 2499 
 2500 void
 2501 ip6_freepcbopts(struct ip6_pktopts *pktopt)
 2502 {
 2503         if (pktopt == NULL)
 2504                 return;
 2505 
 2506         ip6_clearpktopts(pktopt, -1);
 2507 
 2508         free(pktopt, M_IP6OPT);
 2509 }
 2510 
 2511 /*
 2512  * Set the IP6 multicast options in response to user setsockopt().
 2513  */
 2514 static int
 2515 ip6_setmoptions(optname, im6op, m)
 2516         int optname;
 2517         struct ip6_moptions **im6op;
 2518         struct mbuf *m;
 2519 {
 2520         int error = 0;
 2521         u_int loop, ifindex;
 2522         struct ipv6_mreq *mreq;
 2523         struct ifnet *ifp;
 2524         struct ip6_moptions *im6o = *im6op;
 2525         struct route_in6 ro;
 2526         struct in6_multi_mship *imm;
 2527         struct lwp *l = curlwp; /* XXX */
 2528 
 2529         if (im6o == NULL) {
 2530                 /*
 2531                  * No multicast option buffer attached to the pcb;
 2532                  * allocate one and initialize to default values.
 2533                  */
 2534                 im6o = (struct ip6_moptions *)
 2535                         malloc(sizeof(*im6o), M_IPMOPTS, M_WAITOK);
 2536 
 2537                 if (im6o == NULL)
 2538                         return (ENOBUFS);
 2539                 *im6op = im6o;
 2540                 im6o->im6o_multicast_ifp = NULL;
 2541                 im6o->im6o_multicast_hlim = ip6_defmcasthlim;
 2542                 im6o->im6o_multicast_loop = IPV6_DEFAULT_MULTICAST_LOOP;
 2543                 LIST_INIT(&im6o->im6o_memberships);
 2544         }
 2545 
 2546         switch (optname) {
 2547 
 2548         case IPV6_MULTICAST_IF:
 2549                 /*
 2550                  * Select the interface for outgoing multicast packets.
 2551                  */
 2552                 if (m == NULL || m->m_len != sizeof(u_int)) {
 2553                         error = EINVAL;
 2554                         break;
 2555                 }
 2556                 bcopy(mtod(m, u_int *), &ifindex, sizeof(ifindex));
 2557                 if (ifindex != 0) {
 2558                         if (if_indexlim <= ifindex || !ifindex2ifnet[ifindex]) {
 2559                                 error = ENXIO;  /* XXX EINVAL? */
 2560                                 break;
 2561                         }
 2562                         ifp = ifindex2ifnet[ifindex];
 2563                         if ((ifp->if_flags & IFF_MULTICAST) == 0) {
 2564                                 error = EADDRNOTAVAIL;
 2565                                 break;
 2566                         }
 2567                 } else
 2568                         ifp = NULL;
 2569                 im6o->im6o_multicast_ifp = ifp;
 2570                 break;
 2571 
 2572         case IPV6_MULTICAST_HOPS:
 2573             {
 2574                 /*
 2575                  * Set the IP6 hoplimit for outgoing multicast packets.
 2576                  */
 2577                 int optval;
 2578                 if (m == NULL || m->m_len != sizeof(int)) {
 2579                         error = EINVAL;
 2580                         break;
 2581                 }
 2582                 bcopy(mtod(m, u_int *), &optval, sizeof(optval));
 2583                 if (optval < -1 || optval >= 256)
 2584                         error = EINVAL;
 2585                 else if (optval == -1)
 2586                         im6o->im6o_multicast_hlim = ip6_defmcasthlim;
 2587                 else
 2588                         im6o->im6o_multicast_hlim = optval;
 2589                 break;
 2590             }
 2591 
 2592         case IPV6_MULTICAST_LOOP:
 2593                 /*
 2594                  * Set the loopback flag for outgoing multicast packets.
 2595                  * Must be zero or one.
 2596                  */
 2597                 if (m == NULL || m->m_len != sizeof(u_int)) {
 2598                         error = EINVAL;
 2599                         break;
 2600                 }
 2601                 bcopy(mtod(m, u_int *), &loop, sizeof(loop));
 2602                 if (loop > 1) {
 2603                         error = EINVAL;
 2604                         break;
 2605                 }
 2606                 im6o->im6o_multicast_loop = loop;
 2607                 break;
 2608 
 2609         case IPV6_JOIN_GROUP:
 2610                 /*
 2611                  * Add a multicast group membership.
 2612                  * Group must be a valid IP6 multicast address.
 2613                  */
 2614                 if (m == NULL || m->m_len != sizeof(struct ipv6_mreq)) {
 2615                         error = EINVAL;
 2616                         break;
 2617                 }
 2618                 mreq = mtod(m, struct ipv6_mreq *);
 2619                 if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) {
 2620                         /*
 2621                          * We use the unspecified address to specify to accept
 2622                          * all multicast addresses. Only super user is allowed
 2623                          * to do this.
 2624                          */
 2625                         if (kauth_authorize_generic(l->l_cred,
 2626                             KAUTH_GENERIC_ISSUSER, &l->l_acflag))
 2627                         {
 2628                                 error = EACCES;
 2629                                 break;
 2630                         }
 2631                 } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) {
 2632                         error = EINVAL;
 2633                         break;
 2634                 }
 2635 
 2636                 /*
 2637                  * If no interface was explicitly specified, choose an
 2638                  * appropriate one according to the given multicast address.
 2639                  */
 2640                 if (mreq->ipv6mr_interface == 0) {
 2641                         struct sockaddr_in6 *dst;
 2642 
 2643                         /*
 2644                          * Look up the routing table for the
 2645                          * address, and choose the outgoing interface.
 2646                          *   XXX: is it a good approach?
 2647                          */
 2648                         ro.ro_rt = NULL;
 2649                         dst = (struct sockaddr_in6 *)&ro.ro_dst;
 2650                         bzero(dst, sizeof(*dst));
 2651                         dst->sin6_family = AF_INET6;
 2652                         dst->sin6_len = sizeof(*dst);
 2653                         dst->sin6_addr = mreq->ipv6mr_multiaddr;
 2654                         rtalloc((struct route *)&ro);
 2655                         if (ro.ro_rt == NULL) {
 2656                                 error = EADDRNOTAVAIL;
 2657                                 break;
 2658                         }
 2659                         ifp = ro.ro_rt->rt_ifp;
 2660                         rtfree(ro.ro_rt);
 2661                 } else {
 2662                         /*
 2663                          * If the interface is specified, validate it.
 2664                          */
 2665                         if (if_indexlim <= mreq->ipv6mr_interface ||
 2666                             !ifindex2ifnet[mreq->ipv6mr_interface]) {
 2667                                 error = ENXIO;  /* XXX EINVAL? */
 2668                                 break;
 2669                         }
 2670                         ifp = ifindex2ifnet[mreq->ipv6mr_interface];
 2671                 }
 2672 
 2673                 /*
 2674                  * See if we found an interface, and confirm that it
 2675                  * supports multicast
 2676                  */
 2677                 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
 2678                         error = EADDRNOTAVAIL;
 2679                         break;
 2680                 }
 2681 
 2682                 if (in6_setscope(&mreq->ipv6mr_multiaddr, ifp, NULL)) {
 2683                         error = EADDRNOTAVAIL; /* XXX: should not happen */
 2684                         break;
 2685                 }
 2686 
 2687                 /*
 2688                  * See if the membership already exists.
 2689                  */
 2690                 for (imm = im6o->im6o_memberships.lh_first;
 2691                      imm != NULL; imm = imm->i6mm_chain.le_next)
 2692                         if (imm->i6mm_maddr->in6m_ifp == ifp &&
 2693                             IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
 2694                             &mreq->ipv6mr_multiaddr))
 2695                                 break;
 2696                 if (imm != NULL) {
 2697                         error = EADDRINUSE;
 2698                         break;
 2699                 }
 2700                 /*
 2701                  * Everything looks good; add a new record to the multicast
 2702                  * address list for the given interface.
 2703                  */
 2704                 imm = in6_joingroup(ifp, &mreq->ipv6mr_multiaddr, &error, 0);
 2705                 if (imm == NULL)
 2706                         break;
 2707                 LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain);
 2708                 break;
 2709 
 2710         case IPV6_LEAVE_GROUP:
 2711                 /*
 2712                  * Drop a multicast group membership.
 2713                  * Group must be a valid IP6 multicast address.
 2714                  */
 2715                 if (m == NULL || m->m_len != sizeof(struct ipv6_mreq)) {
 2716                         error = EINVAL;
 2717                         break;
 2718                 }
 2719                 mreq = mtod(m, struct ipv6_mreq *);
 2720 
 2721                 /*
 2722                  * If an interface address was specified, get a pointer
 2723                  * to its ifnet structure.
 2724                  */
 2725                 if (mreq->ipv6mr_interface != 0) {
 2726                         if (if_indexlim <= mreq->ipv6mr_interface ||
 2727                             !ifindex2ifnet[mreq->ipv6mr_interface]) {
 2728                                 error = ENXIO;  /* XXX EINVAL? */
 2729                                 break;
 2730                         }
 2731                         ifp = ifindex2ifnet[mreq->ipv6mr_interface];
 2732                 } else
 2733                         ifp = NULL;
 2734 
 2735                 /* Fill in the scope zone ID */
 2736                 if (ifp) {
 2737                         if (in6_setscope(&mreq->ipv6mr_multiaddr, ifp, NULL)) {
 2738                                 /* XXX: should not happen */
 2739                                 error = EADDRNOTAVAIL;
 2740                                 break;
 2741                         }
 2742                 } else if (mreq->ipv6mr_interface != 0) {
 2743                         /*
 2744                          * XXX: This case would happens when the (positive)
 2745                          * index is in the valid range, but the corresponding
 2746                          * interface has been detached dynamically.  The above
 2747                          * check probably avoids such case to happen here, but
 2748                          * we check it explicitly for safety.
 2749                          */
 2750                         error = EADDRNOTAVAIL;
 2751                         break;      
 2752                 } else {        /* ipv6mr_interface == 0 */
 2753                         struct sockaddr_in6 sa6_mc;
 2754 
 2755                         /*
 2756                          * The API spec says as follows:
 2757                          *  If the interface index is specified as 0, the
 2758                          *  system may choose a multicast group membership to
 2759                          *  drop by matching the multicast address only.
 2760                          * On the other hand, we cannot disambiguate the scope
 2761                          * zone unless an interface is provided.  Thus, we
 2762                          * check if there's ambiguity with the default scope
 2763                          * zone as the last resort.
 2764                          */
 2765                         bzero(&sa6_mc, sizeof(sa6_mc));
 2766                         sa6_mc.sin6_family = AF_INET6;
 2767                         sa6_mc.sin6_len = sizeof(sa6_mc);
 2768                         sa6_mc.sin6_addr = mreq->ipv6mr_multiaddr;
 2769                         error = sa6_embedscope(&sa6_mc, ip6_use_defzone);
 2770                         if (error != 0)
 2771                                 break;
 2772                         mreq->ipv6mr_multiaddr = sa6_mc.sin6_addr;
 2773                 }
 2774 
 2775                 /*
 2776                  * Find the membership in the membership list.
 2777                  */
 2778                 for (imm = im6o->im6o_memberships.lh_first;
 2779                      imm != NULL; imm = imm->i6mm_chain.le_next) {
 2780                         if ((ifp == NULL || imm->i6mm_maddr->in6m_ifp == ifp) &&
 2781                             IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
 2782                             &mreq->ipv6mr_multiaddr))
 2783                                 break;
 2784                 }
 2785                 if (imm == NULL) {
 2786                         /* Unable to resolve interface */
 2787                         error = EADDRNOTAVAIL;
 2788                         break;
 2789                 }
 2790                 /*
 2791                  * Give up the multicast address record to which the
 2792                  * membership points.
 2793                  */
 2794                 LIST_REMOVE(imm, i6mm_chain);
 2795                 in6_leavegroup(imm);
 2796                 break;
 2797 
 2798         default:
 2799                 error = EOPNOTSUPP;
 2800                 break;
 2801         }
 2802 
 2803         /*
 2804          * If all options have default values, no need to keep the mbuf.
 2805          */
 2806         if (im6o->im6o_multicast_ifp == NULL &&
 2807             im6o->im6o_multicast_hlim == ip6_defmcasthlim &&
 2808             im6o->im6o_multicast_loop == IPV6_DEFAULT_MULTICAST_LOOP &&
 2809             im6o->im6o_memberships.lh_first == NULL) {
 2810                 free(*im6op, M_IPMOPTS);
 2811                 *im6op = NULL;
 2812         }
 2813 
 2814         return (error);
 2815 }
 2816 
 2817 /*
 2818  * Return the IP6 multicast options in response to user getsockopt().
 2819  */
 2820 static int
 2821 ip6_getmoptions(optname, im6o, mp)
 2822         int optname;
 2823         struct ip6_moptions *im6o;
 2824         struct mbuf **mp;
 2825 {
 2826         u_int *hlim, *loop, *ifindex;
 2827 
 2828         *mp = m_get(M_WAIT, MT_SOOPTS);
 2829 
 2830         switch (optname) {
 2831 
 2832         case IPV6_MULTICAST_IF:
 2833                 ifindex = mtod(*mp, u_int *);
 2834                 (*mp)->m_len = sizeof(u_int);
 2835                 if (im6o == NULL || im6o->im6o_multicast_ifp == NULL)
 2836                         *ifindex = 0;
 2837                 else
 2838                         *ifindex = im6o->im6o_multicast_ifp->if_index;
 2839                 return (0);
 2840 
 2841         case IPV6_MULTICAST_HOPS:
 2842                 hlim = mtod(*mp, u_int *);
 2843                 (*mp)->m_len = sizeof(u_int);
 2844                 if (im6o == NULL)
 2845                         *hlim = ip6_defmcasthlim;
 2846                 else
 2847                         *hlim = im6o->im6o_multicast_hlim;
 2848                 return (0);
 2849 
 2850         case IPV6_MULTICAST_LOOP:
 2851                 loop = mtod(*mp, u_int *);
 2852                 (*mp)->m_len = sizeof(u_int);
 2853                 if (im6o == NULL)
 2854                         *loop = ip6_defmcasthlim;
 2855                 else
 2856                         *loop = im6o->im6o_multicast_loop;
 2857                 return (0);
 2858 
 2859         default:
 2860                 return (EOPNOTSUPP);
 2861         }
 2862 }
 2863 
 2864 /*
 2865  * Discard the IP6 multicast options.
 2866  */
 2867 void
 2868 ip6_freemoptions(im6o)
 2869         struct ip6_moptions *im6o;
 2870 {
 2871         struct in6_multi_mship *imm;
 2872 
 2873         if (im6o == NULL)
 2874                 return;
 2875 
 2876         while ((imm = im6o->im6o_memberships.lh_first) != NULL) {
 2877                 LIST_REMOVE(imm, i6mm_chain);
 2878                 in6_leavegroup(imm);
 2879         }
 2880         free(im6o, M_IPMOPTS);
 2881 }
 2882 
 2883 /*
 2884  * Set IPv6 outgoing packet options based on advanced API.
 2885  */
 2886 int
 2887 ip6_setpktopts(control, opt, stickyopt, priv, uproto)
 2888         struct mbuf *control;
 2889         struct ip6_pktopts *opt, *stickyopt;
 2890         int priv, uproto;
 2891 {
 2892         struct cmsghdr *cm = 0;
 2893 
 2894         if (control == NULL || opt == NULL)
 2895                 return (EINVAL);
 2896 
 2897         ip6_initpktopts(opt);
 2898         if (stickyopt) {
 2899                 int error;
 2900 
 2901                 /*
 2902                  * If stickyopt is provided, make a local copy of the options
 2903                  * for this particular packet, then override them by ancillary
 2904                  * objects.
 2905                  * XXX: copypktopts() does not copy the cached route to a next
 2906                  * hop (if any).  This is not very good in terms of efficiency,
 2907                  * but we can allow this since this option should be rarely
 2908                  * used.
 2909                  */
 2910                 if ((error = copypktopts(opt, stickyopt, M_NOWAIT)) != 0)
 2911                         return (error);
 2912         }
 2913 
 2914         /*
 2915          * XXX: Currently, we assume all the optional information is stored
 2916          * in a single mbuf.
 2917          */
 2918         if (control->m_next)
 2919                 return (EINVAL);
 2920 
 2921         for (; control->m_len; control->m_data += CMSG_ALIGN(cm->cmsg_len),
 2922             control->m_len -= CMSG_ALIGN(cm->cmsg_len)) {
 2923                 int error;
 2924 
 2925                 if (control->m_len < CMSG_LEN(0))
 2926                         return (EINVAL);
 2927 
 2928                 cm = mtod(control, struct cmsghdr *);
 2929                 if (cm->cmsg_len == 0 || cm->cmsg_len > control->m_len)
 2930                         return (EINVAL);
 2931                 if (cm->cmsg_level != IPPROTO_IPV6)
 2932                         continue;
 2933 
 2934                 error = ip6_setpktopt(cm->cmsg_type, CMSG_DATA(cm),
 2935                     cm->cmsg_len - CMSG_LEN(0), opt, priv, 0, 1, uproto);
 2936                 if (error)
 2937                         return (error);
 2938         }
 2939 
 2940         return (0);
 2941 }
 2942 
 2943 /*
 2944  * Set a particular packet option, as a sticky option or an ancillary data
 2945  * item.  "len" can be 0 only when it's a sticky option.
 2946  * We have 4 cases of combination of "sticky" and "cmsg":
 2947  * "sticky=0, cmsg=0": impossible
 2948  * "sticky=0, cmsg=1": RFC2292 or RFC3542 ancillary data
 2949  * "sticky=1, cmsg=0": RFC3542 socket option
 2950  * "sticky=1, cmsg=1": RFC2292 socket option
 2951  */
 2952 static int
 2953 ip6_setpktopt(int optname, u_char *buf, int len, struct ip6_pktopts *opt,
 2954     int priv, int sticky, int cmsg, int uproto)
 2955 {
 2956         int minmtupolicy;
 2957 
 2958         if (!sticky && !cmsg) {
 2959 #ifdef DIAGNOSTIC
 2960                 printf("ip6_setpktopt: impossible case\n");
 2961 #endif
 2962                 return (EINVAL);
 2963         }
 2964 
 2965         /*
 2966          * IPV6_2292xxx is for backward compatibility to RFC2292, and should
 2967          * not be specified in the context of RFC3542.  Conversely,
 2968          * RFC3542 types should not be specified in the context of RFC2292.
 2969          */
 2970         if (!cmsg) {
 2971                 switch (optname) {
 2972                 case IPV6_2292PKTINFO:
 2973                 case IPV6_2292HOPLIMIT:
 2974                 case IPV6_2292NEXTHOP:
 2975                 case IPV6_2292HOPOPTS:
 2976                 case IPV6_2292DSTOPTS:
 2977                 case IPV6_2292RTHDR:
 2978                 case IPV6_2292PKTOPTIONS:
 2979                         return (ENOPROTOOPT);
 2980                 }
 2981         }
 2982         if (sticky && cmsg) {
 2983                 switch (optname) {
 2984                 case IPV6_PKTINFO:
 2985                 case IPV6_HOPLIMIT:
 2986                 case IPV6_NEXTHOP:
 2987                 case IPV6_HOPOPTS:
 2988                 case IPV6_DSTOPTS:
 2989                 case IPV6_RTHDRDSTOPTS:
 2990                 case IPV6_RTHDR:
 2991                 case IPV6_USE_MIN_MTU:
 2992                 case IPV6_DONTFRAG:
 2993                 case IPV6_OTCLASS:
 2994                 case IPV6_TCLASS:
 2995                         return (ENOPROTOOPT);
 2996                 }
 2997         }
 2998 
 2999         switch (optname) {
 3000 #ifdef RFC2292
 3001         case IPV6_2292PKTINFO:
 3002 #endif
 3003         case IPV6_PKTINFO:
 3004         {
 3005                 struct ifnet *ifp = NULL;
 3006                 struct in6_pktinfo *pktinfo;
 3007 
 3008                 if (len != sizeof(struct in6_pktinfo))
 3009                         return (EINVAL);
 3010 
 3011                 pktinfo = (struct in6_pktinfo *)buf;
 3012 
 3013                 /*
 3014                  * An application can clear any sticky IPV6_PKTINFO option by
 3015                  * doing a "regular" setsockopt with ipi6_addr being
 3016                  * in6addr_any and ipi6_ifindex being zero.
 3017                  * [RFC 3542, Section 6]
 3018                  */
 3019                 if (optname == IPV6_PKTINFO && opt->ip6po_pktinfo &&
 3020                     pktinfo->ipi6_ifindex == 0 &&
 3021                     IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) {
 3022                         ip6_clearpktopts(opt, optname);
 3023                         break;
 3024                 }
 3025 
 3026                 if (uproto == IPPROTO_TCP && optname == IPV6_PKTINFO &&
 3027                     sticky && !IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) {
 3028                         return (EINVAL);
 3029                 }
 3030 
 3031                 /* validate the interface index if specified. */
 3032                 if (pktinfo->ipi6_ifindex >= if_indexlim) {
 3033                          return (ENXIO);
 3034                 }
 3035                 if (pktinfo->ipi6_ifindex) {
 3036                         ifp = ifindex2ifnet[pktinfo->ipi6_ifindex];
 3037                         if (ifp == NULL)
 3038                                 return (ENXIO);
 3039                 }
 3040 
 3041                 /*
 3042                  * We store the address anyway, and let in6_selectsrc()
 3043                  * validate the specified address.  This is because ipi6_addr
 3044                  * may not have enough information about its scope zone, and
 3045                  * we may need additional information (such as outgoing
 3046                  * interface or the scope zone of a destination address) to
 3047                  * disambiguate the scope.
 3048                  * XXX: the delay of the validation may confuse the
 3049                  * application when it is used as a sticky option.
 3050                  */
 3051                 if (opt->ip6po_pktinfo == NULL) {
 3052                         opt->ip6po_pktinfo = malloc(sizeof(*pktinfo),
 3053                             M_IP6OPT, M_NOWAIT);
 3054                         if (opt->ip6po_pktinfo == NULL)
 3055                                 return (ENOBUFS);
 3056                 }
 3057                 memcpy(opt->ip6po_pktinfo, pktinfo, sizeof(*pktinfo));
 3058                 break;
 3059         }
 3060 
 3061 #ifdef RFC2292
 3062         case IPV6_2292HOPLIMIT:
 3063 #endif
 3064         case IPV6_HOPLIMIT:
 3065         {
 3066                 int *hlimp;
 3067 
 3068                 /*
 3069                  * RFC 3542 deprecated the usage of sticky IPV6_HOPLIMIT
 3070                  * to simplify the ordering among hoplimit options.
 3071                  */
 3072                 if (optname == IPV6_HOPLIMIT && sticky)
 3073                         return (ENOPROTOOPT);
 3074 
 3075                 if (len != sizeof(int))
 3076                         return (EINVAL);
 3077                 hlimp = (int *)buf;
 3078                 if (*hlimp < -1 || *hlimp > 255)
 3079                         return (EINVAL);
 3080 
 3081                 opt->ip6po_hlim = *hlimp;
 3082                 break;
 3083         }
 3084 
 3085         case IPV6_OTCLASS:
 3086                 if (len != sizeof(u_int8_t))
 3087                         return (EINVAL);
 3088 
 3089                 opt->ip6po_tclass = *(u_int8_t *)buf;
 3090                 break;
 3091 
 3092         case IPV6_TCLASS:
 3093         {
 3094                 int tclass;
 3095 
 3096                 if (len != sizeof(int))
 3097                         return (EINVAL);
 3098                 tclass = *(int *)buf;
 3099                 if (tclass < -1 || tclass > 255)
 3100                         return (EINVAL);
 3101 
 3102                 opt->ip6po_tclass = tclass;
 3103                 break;
 3104         }
 3105 
 3106 #ifdef RFC2292
 3107         case IPV6_2292NEXTHOP:
 3108 #endif
 3109         case IPV6_NEXTHOP:
 3110                 if (!priv)
 3111                         return (EPERM);
 3112 
 3113                 if (len == 0) { /* just remove the option */
 3114                         ip6_clearpktopts(opt, IPV6_NEXTHOP);
 3115                         break;
 3116                 }
 3117 
 3118                 /* check if cmsg_len is large enough for sa_len */
 3119                 if (len < sizeof(struct sockaddr) || len < *buf)
 3120                         return (EINVAL);
 3121 
 3122                 switch (((struct sockaddr *)buf)->sa_family) {
 3123                 case AF_INET6:
 3124                 {
 3125                         struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)buf;
 3126                         int error;
 3127 
 3128                         if (sa6->sin6_len != sizeof(struct sockaddr_in6))
 3129                                 return (EINVAL);
 3130 
 3131                         if (IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr) ||
 3132                             IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) {
 3133                                 return (EINVAL);
 3134                         }
 3135                         if ((error = sa6_embedscope(sa6, ip6_use_defzone))
 3136                             != 0) {
 3137                                 return (error);
 3138                         }
 3139                         break;
 3140                 }
 3141                 case AF_LINK:   /* eventually be supported? */
 3142                 default:
 3143                         return (EAFNOSUPPORT);
 3144                 }
 3145 
 3146                 /* turn off the previous option, then set the new option. */
 3147                 ip6_clearpktopts(opt, IPV6_NEXTHOP);
 3148                 opt->ip6po_nexthop = malloc(*buf, M_IP6OPT, M_NOWAIT);
 3149                 if (opt->ip6po_nexthop == NULL)
 3150                         return (ENOBUFS);
 3151                 memcpy(opt->ip6po_nexthop, buf, *buf);
 3152                 break;
 3153 
 3154 #ifdef RFC2292
 3155         case IPV6_2292HOPOPTS:
 3156 #endif
 3157         case IPV6_HOPOPTS:
 3158         {
 3159                 struct ip6_hbh *hbh;
 3160                 int hbhlen;
 3161 
 3162                 /*
 3163                  * XXX: We don't allow a non-privileged user to set ANY HbH
 3164                  * options, since per-option restriction has too much
 3165                  * overhead.
 3166                  */
 3167                 if (!priv)
 3168                         return (EPERM);
 3169 
 3170                 if (len == 0) {
 3171                         ip6_clearpktopts(opt, IPV6_HOPOPTS);
 3172                         break;  /* just remove the option */
 3173                 }
 3174 
 3175                 /* message length validation */
 3176                 if (len < sizeof(struct ip6_hbh))
 3177                         return (EINVAL);
 3178                 hbh = (struct ip6_hbh *)buf;
 3179                 hbhlen = (hbh->ip6h_len + 1) << 3;
 3180                 if (len != hbhlen)
 3181                         return (EINVAL);
 3182 
 3183                 /* turn off the previous option, then set the new option. */
 3184                 ip6_clearpktopts(opt, IPV6_HOPOPTS);
 3185                 opt->ip6po_hbh = malloc(hbhlen, M_IP6OPT, M_NOWAIT);
 3186                 if (opt->ip6po_hbh == NULL)
 3187                         return (ENOBUFS);
 3188                 memcpy(opt->ip6po_hbh, hbh, hbhlen);
 3189 
 3190                 break;
 3191         }
 3192 
 3193 #ifdef RFC2292
 3194         case IPV6_2292DSTOPTS:
 3195 #endif
 3196         case IPV6_DSTOPTS:
 3197         case IPV6_RTHDRDSTOPTS:
 3198         {
 3199                 struct ip6_dest *dest, **newdest = NULL;
 3200                 int destlen;
 3201 
 3202                 if (!priv)      /* XXX: see the comment for IPV6_HOPOPTS */
 3203                         return (EPERM);
 3204 
 3205                 if (len == 0) {
 3206                         ip6_clearpktopts(opt, optname);
 3207                         break;  /* just remove the option */
 3208                 }
 3209 
 3210                 /* message length validation */
 3211                 if (len < sizeof(struct ip6_dest))
 3212                         return (EINVAL);
 3213                 dest = (struct ip6_dest *)buf;
 3214                 destlen = (dest->ip6d_len + 1) << 3;
 3215                 if (len != destlen)
 3216                         return (EINVAL);
 3217                 /*
 3218                  * Determine the position that the destination options header
 3219                  * should be inserted; before or after the routing header.
 3220                  */
 3221                 switch (optname) {
 3222                 case IPV6_2292DSTOPTS:
 3223                         /*
 3224                          * The old advanced API is ambiguous on this point.
 3225                          * Our approach is to determine the position based
 3226                          * according to the existence of a routing header.
 3227                          * Note, however, that this depends on the order of the
 3228                          * extension headers in the ancillary data; the 1st
 3229                          * part of the destination options header must appear
 3230                          * before the routing header in the ancillary data,
 3231                          * too.
 3232                          * RFC3542 solved the ambiguity by introducing
 3233                          * separate ancillary data or option types.
 3234                          */
 3235                         if (opt->ip6po_rthdr == NULL)
 3236                                 newdest = &opt->ip6po_dest1;
 3237                         else
 3238                                 newdest = &opt->ip6po_dest2;
 3239                         break;
 3240                 case IPV6_RTHDRDSTOPTS:
 3241                         newdest = &opt->ip6po_dest1;
 3242                         break;
 3243                 case IPV6_DSTOPTS:
 3244                         newdest = &opt->ip6po_dest2;
 3245                         break;
 3246                 }
 3247 
 3248                 /* turn off the previous option, then set the new option. */
 3249                 ip6_clearpktopts(opt, optname);
 3250                 *newdest = malloc(destlen, M_IP6OPT, M_NOWAIT);
 3251                 if (*newdest == NULL)
 3252                         return (ENOBUFS);
 3253                 memcpy(*newdest, dest, destlen);
 3254 
 3255                 break;
 3256         }
 3257 
 3258 #ifdef RFC2292
 3259         case IPV6_2292RTHDR:
 3260 #endif
 3261         case IPV6_RTHDR:
 3262         {
 3263                 struct ip6_rthdr *rth;
 3264                 int rthlen;
 3265 
 3266                 if (len == 0) {
 3267                         ip6_clearpktopts(opt, IPV6_RTHDR);
 3268                         break;  /* just remove the option */
 3269                 }
 3270 
 3271                 /* message length validation */
 3272                 if (len < sizeof(struct ip6_rthdr))
 3273                         return (EINVAL);
 3274                 rth = (struct ip6_rthdr *)buf;
 3275                 rthlen = (rth->ip6r_len + 1) << 3;
 3276                 if (len != rthlen)
 3277                         return (EINVAL);
 3278                 switch (rth->ip6r_type) {
 3279                 case IPV6_RTHDR_TYPE_0:
 3280                         if (rth->ip6r_len == 0) /* must contain one addr */
 3281                                 return (EINVAL);
 3282                         if (rth->ip6r_len % 2) /* length must be even */
 3283                                 return (EINVAL);
 3284                         if (rth->ip6r_len / 2 != rth->ip6r_segleft)
 3285                                 return (EINVAL);
 3286                         break;
 3287                 default:
 3288                         return (EINVAL);        /* not supported */
 3289                 }
 3290                 /* turn off the previous option */
 3291                 ip6_clearpktopts(opt, IPV6_RTHDR);
 3292                 opt->ip6po_rthdr = malloc(rthlen, M_IP6OPT, M_NOWAIT);
 3293                 if (opt->ip6po_rthdr == NULL)
 3294                         return (ENOBUFS);
 3295                 memcpy(opt->ip6po_rthdr, rth, rthlen);
 3296                 break;
 3297         }
 3298 
 3299         case IPV6_USE_MIN_MTU:
 3300                 if (len != sizeof(int))
 3301                         return (EINVAL);
 3302                 minmtupolicy = *(int *)buf;
 3303                 if (minmtupolicy != IP6PO_MINMTU_MCASTONLY &&
 3304                     minmtupolicy != IP6PO_MINMTU_DISABLE &&
 3305                     minmtupolicy != IP6PO_MINMTU_ALL) {
 3306                         return (EINVAL);
 3307                 }
 3308                 opt->ip6po_minmtu = minmtupolicy;
 3309                 break;
 3310 
 3311         case IPV6_DONTFRAG:
 3312                 if (len != sizeof(int))
 3313                         return (EINVAL);
 3314 
 3315                 if (uproto == IPPROTO_TCP || *(int *)buf == 0) {
 3316                         /*
 3317                          * we ignore this option for TCP sockets.
 3318                          * (RFC3542 leaves this case unspecified.)
 3319                          */
 3320                         opt->ip6po_flags &= ~IP6PO_DONTFRAG;
 3321                 } else
 3322                         opt->ip6po_flags |= IP6PO_DONTFRAG;
 3323                 break;
 3324 
 3325         default:
 3326                 return (ENOPROTOOPT);
 3327         } /* end of switch */
 3328 
 3329         return (0);
 3330 }
 3331 
 3332 /*
 3333  * Routine called from ip6_output() to loop back a copy of an IP6 multicast
 3334  * packet to the input queue of a specified interface.  Note that this
 3335  * calls the output routine of the loopback "driver", but with an interface
 3336  * pointer that might NOT be lo0ifp -- easier than replicating that code here.
 3337  */
 3338 void
 3339 ip6_mloopback(ifp, m, dst)
 3340         struct ifnet *ifp;
 3341         struct mbuf *m;
 3342         struct sockaddr_in6 *dst;
 3343 {
 3344         struct mbuf *copym;
 3345         struct ip6_hdr *ip6;
 3346 
 3347         copym = m_copy(m, 0, M_COPYALL);
 3348         if (copym == NULL)
 3349                 return;
 3350 
 3351         /*
 3352          * Make sure to deep-copy IPv6 header portion in case the data
 3353          * is in an mbuf cluster, so that we can safely override the IPv6
 3354          * header portion later.
 3355          */
 3356         if ((copym->m_flags & M_EXT) != 0 ||
 3357             copym->m_len < sizeof(struct ip6_hdr)) {
 3358                 copym = m_pullup(copym, sizeof(struct ip6_hdr));
 3359                 if (copym == NULL)
 3360                         return;
 3361         }
 3362 
 3363 #ifdef DIAGNOSTIC
 3364         if (copym->m_len < sizeof(*ip6)) {
 3365                 m_freem(copym);
 3366                 return;
 3367         }
 3368 #endif
 3369 
 3370         ip6 = mtod(copym, struct ip6_hdr *);
 3371         /*
 3372          * clear embedded scope identifiers if necessary.
 3373          * in6_clearscope will touch the addresses only when necessary.
 3374          */
 3375         in6_clearscope(&ip6->ip6_src);
 3376         in6_clearscope(&ip6->ip6_dst);
 3377 
 3378         (void)looutput(ifp, copym, (struct sockaddr *)dst, NULL);
 3379 }
 3380 
 3381 /*
 3382  * Chop IPv6 header off from the payload.
 3383  */
 3384 static int
 3385 ip6_splithdr(m, exthdrs)
 3386         struct mbuf *m;
 3387         struct ip6_exthdrs *exthdrs;
 3388 {
 3389         struct mbuf *mh;
 3390         struct ip6_hdr *ip6;
 3391 
 3392         ip6 = mtod(m, struct ip6_hdr *);
 3393         if (m->m_len > sizeof(*ip6)) {
 3394                 MGETHDR(mh, M_DONTWAIT, MT_HEADER);
 3395                 if (mh == 0) {
 3396                         m_freem(m);
 3397                         return ENOBUFS;
 3398                 }
 3399                 M_MOVE_PKTHDR(mh, m);
 3400                 MH_ALIGN(mh, sizeof(*ip6));
 3401                 m->m_len -= sizeof(*ip6);
 3402                 m->m_data += sizeof(*ip6);
 3403                 mh->m_next = m;
 3404                 m = mh;
 3405                 m->m_len = sizeof(*ip6);
 3406                 bcopy((caddr_t)ip6, mtod(m, caddr_t), sizeof(*ip6));
 3407         }
 3408         exthdrs->ip6e_ip6 = m;
 3409         return 0;
 3410 }
 3411 
 3412 /*
 3413  * Compute IPv6 extension header length.
 3414  */
 3415 int
 3416 ip6_optlen(in6p)
 3417         struct in6pcb *in6p;
 3418 {
 3419         int len;
 3420 
 3421         if (!in6p->in6p_outputopts)
 3422                 return 0;
 3423 
 3424         len = 0;
 3425 #define elen(x) \
 3426     (((struct ip6_ext *)(x)) ? (((struct ip6_ext *)(x))->ip6e_len + 1) << 3 : 0)
 3427 
 3428         len += elen(in6p->in6p_outputopts->ip6po_hbh);
 3429         len += elen(in6p->in6p_outputopts->ip6po_dest1);
 3430         len += elen(in6p->in6p_outputopts->ip6po_rthdr);
 3431         len += elen(in6p->in6p_outputopts->ip6po_dest2);
 3432         return len;
 3433 #undef elen
 3434 }

Cache object: c1b55413fbe33a7fffe6682777399ec3


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