LCOV - code coverage report
Current view: top level - netinet6 - ip6_output.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 1230 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 28 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ip6_output.c,v 1.239 2018/08/28 15:15:02 mpi 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 "pf.h"
      65             : 
      66             : #include <sys/param.h>
      67             : #include <sys/malloc.h>
      68             : #include <sys/mbuf.h>
      69             : #include <sys/errno.h>
      70             : #include <sys/protosw.h>
      71             : #include <sys/socket.h>
      72             : #include <sys/socketvar.h>
      73             : #include <sys/proc.h>
      74             : #include <sys/systm.h>
      75             : 
      76             : #include <net/if.h>
      77             : #include <net/if_var.h>
      78             : #include <net/if_enc.h>
      79             : #include <net/route.h>
      80             : 
      81             : #include <netinet/in.h>
      82             : #include <netinet/ip.h>
      83             : #include <netinet/in_pcb.h>
      84             : #include <netinet/udp.h>
      85             : #include <netinet/tcp.h>
      86             : 
      87             : #include <netinet/ip_var.h>
      88             : #include <netinet/tcp_timer.h>
      89             : #include <netinet/tcp_var.h>
      90             : #include <netinet/udp_var.h>
      91             : 
      92             : #include <netinet6/in6_var.h>
      93             : #include <netinet/ip6.h>
      94             : #include <netinet/icmp6.h>
      95             : #include <netinet6/ip6_var.h>
      96             : #include <netinet6/nd6.h>
      97             : #include <netinet6/ip6protosw.h>
      98             : 
      99             : #include <crypto/idgen.h>
     100             : 
     101             : #if NPF > 0
     102             : #include <net/pfvar.h>
     103             : #endif
     104             : 
     105             : #ifdef IPSEC
     106             : #include <netinet/ip_ipsp.h>
     107             : #include <netinet/ip_ah.h>
     108             : #include <netinet/ip_esp.h>
     109             : #endif /* IPSEC */
     110             : 
     111             : struct ip6_exthdrs {
     112             :         struct mbuf *ip6e_ip6;
     113             :         struct mbuf *ip6e_hbh;
     114             :         struct mbuf *ip6e_dest1;
     115             :         struct mbuf *ip6e_rthdr;
     116             :         struct mbuf *ip6e_dest2;
     117             : };
     118             : 
     119             : int ip6_pcbopt(int, u_char *, int, struct ip6_pktopts **, int, int);
     120             : int ip6_getpcbopt(struct ip6_pktopts *, int, struct mbuf *);
     121             : int ip6_setpktopt(int, u_char *, int, struct ip6_pktopts *, int, int, int);
     122             : int ip6_setmoptions(int, struct ip6_moptions **, struct mbuf *, unsigned int);
     123             : int ip6_getmoptions(int, struct ip6_moptions *, struct mbuf *);
     124             : int ip6_copyexthdr(struct mbuf **, caddr_t, int);
     125             : int ip6_insertfraghdr(struct mbuf *, struct mbuf *, int,
     126             :         struct ip6_frag **);
     127             : int ip6_insert_jumboopt(struct ip6_exthdrs *, u_int32_t);
     128             : int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *);
     129             : int ip6_getpmtu(struct rtentry *, struct ifnet *, u_long *);
     130             : int copypktopts(struct ip6_pktopts *, struct ip6_pktopts *);
     131             : static __inline u_int16_t __attribute__((__unused__))
     132             :     in6_cksum_phdr(const struct in6_addr *, const struct in6_addr *,
     133             :     u_int32_t, u_int32_t);
     134             : void in6_delayed_cksum(struct mbuf *, u_int8_t);
     135             : 
     136             : /* Context for non-repeating IDs */
     137             : struct idgen32_ctx ip6_id_ctx;
     138             : 
     139             : /*
     140             :  * IP6 output. The packet in mbuf chain m contains a skeletal IP6
     141             :  * header (with pri, len, nxt, hlim, src, dst).
     142             :  * This function may modify ver and hlim only.
     143             :  * The mbuf chain containing the packet will be freed.
     144             :  * The mbuf opt, if present, will not be freed.
     145             :  *
     146             :  * type of "mtu": rt_mtu is u_long, ifnet.ifr_mtu is int, and
     147             :  * nd_ifinfo.linkmtu is u_int32_t.  so we use u_long to hold largest one,
     148             :  * which is rt_mtu.
     149             :  */
     150             : int
     151           0 : ip6_output(struct mbuf *m0, struct ip6_pktopts *opt, struct route_in6 *ro,
     152             :     int flags, struct ip6_moptions *im6o, struct inpcb *inp)
     153             : {
     154             :         struct ip6_hdr *ip6;
     155             :         struct ifnet *ifp = NULL;
     156           0 :         struct mbuf *m = m0;
     157             :         int hlen, tlen;
     158           0 :         struct route_in6 ip6route;
     159             :         struct rtentry *rt = NULL;
     160           0 :         struct sockaddr_in6 *dst, dstsock;
     161           0 :         int error = 0;
     162           0 :         u_long mtu;
     163             :         int dontfrag;
     164             :         u_int16_t src_scope, dst_scope;
     165             :         u_int32_t optlen = 0, plen = 0, unfragpartlen = 0;
     166           0 :         struct ip6_exthdrs exthdrs;
     167           0 :         struct in6_addr finaldst;
     168             :         struct route_in6 *ro_pmtu = NULL;
     169             :         int hdrsplit = 0;
     170             :         u_int8_t sproto = 0;
     171             : #ifdef IPSEC
     172             :         struct tdb *tdb = NULL;
     173             : #endif /* IPSEC */
     174             : 
     175             : #ifdef IPSEC
     176           0 :         if (inp && (inp->inp_flags & INP_IPV6) == 0)
     177           0 :                 panic("ip6_output: IPv4 pcb is passed");
     178             : #endif /* IPSEC */
     179             : 
     180           0 :         ip6 = mtod(m, struct ip6_hdr *);
     181           0 :         finaldst = ip6->ip6_dst;
     182             : 
     183             : #define MAKE_EXTHDR(hp, mp)                                             \
     184             :     do {                                                                \
     185             :         if (hp) {                                                       \
     186             :                 struct ip6_ext *eh = (struct ip6_ext *)(hp);            \
     187             :                 error = ip6_copyexthdr((mp), (caddr_t)(hp),             \
     188             :                     ((eh)->ip6e_len + 1) << 3);                                \
     189             :                 if (error)                                              \
     190             :                         goto freehdrs;                                  \
     191             :         }                                                               \
     192             :     } while (0)
     193             : 
     194           0 :         bzero(&exthdrs, sizeof(exthdrs));
     195             : 
     196           0 :         if (opt) {
     197             :                 /* Hop-by-Hop options header */
     198           0 :                 MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh);
     199             :                 /* Destination options header(1st part) */
     200           0 :                 MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1);
     201             :                 /* Routing header */
     202           0 :                 MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr);
     203             :                 /* Destination options header(2nd part) */
     204           0 :                 MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2);
     205             :         }
     206             : 
     207             : #ifdef IPSEC
     208           0 :         if (ipsec_in_use || inp) {
     209           0 :                 tdb = ip6_output_ipsec_lookup(m, &error, inp);
     210           0 :                 if (error != 0) {
     211             :                         /*
     212             :                          * -EINVAL is used to indicate that the packet should
     213             :                          * be silently dropped, typically because we've asked
     214             :                          * key management for an SA.
     215             :                          */
     216           0 :                         if (error == -EINVAL) /* Should silently drop packet */
     217           0 :                                 error = 0;
     218             : 
     219             :                         goto freehdrs;
     220             :                 }
     221             :         }
     222             : #endif /* IPSEC */
     223             : 
     224             :         /*
     225             :          * Calculate the total length of the extension header chain.
     226             :          * Keep the length of the unfragmentable part for fragmentation.
     227             :          */
     228             :         optlen = 0;
     229           0 :         if (exthdrs.ip6e_hbh) optlen += exthdrs.ip6e_hbh->m_len;
     230           0 :         if (exthdrs.ip6e_dest1) optlen += exthdrs.ip6e_dest1->m_len;
     231           0 :         if (exthdrs.ip6e_rthdr) optlen += exthdrs.ip6e_rthdr->m_len;
     232           0 :         unfragpartlen = optlen + sizeof(struct ip6_hdr);
     233             :         /* NOTE: we don't add AH/ESP length here. do that later. */
     234           0 :         if (exthdrs.ip6e_dest2) optlen += exthdrs.ip6e_dest2->m_len;
     235             : 
     236             :         /*
     237             :          * If we need IPsec, or there is at least one extension header,
     238             :          * separate IP6 header from the payload.
     239             :          */
     240           0 :         if ((sproto || optlen) && !hdrsplit) {
     241           0 :                 if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
     242           0 :                         m = NULL;
     243           0 :                         goto freehdrs;
     244             :                 }
     245           0 :                 m = exthdrs.ip6e_ip6;
     246             :                 hdrsplit++;
     247           0 :         }
     248             : 
     249             :         /* adjust pointer */
     250           0 :         ip6 = mtod(m, struct ip6_hdr *);
     251             : 
     252             :         /* adjust mbuf packet header length */
     253           0 :         m->m_pkthdr.len += optlen;
     254           0 :         plen = m->m_pkthdr.len - sizeof(*ip6);
     255             : 
     256             :         /* If this is a jumbo payload, insert a jumbo payload option. */
     257           0 :         if (plen > IPV6_MAXPACKET) {
     258           0 :                 if (!hdrsplit) {
     259           0 :                         if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
     260           0 :                                 m = NULL;
     261           0 :                                 goto freehdrs;
     262             :                         }
     263           0 :                         m = exthdrs.ip6e_ip6;
     264           0 :                         hdrsplit++;
     265           0 :                 }
     266             :                 /* adjust pointer */
     267           0 :                 ip6 = mtod(m, struct ip6_hdr *);
     268           0 :                 if ((error = ip6_insert_jumboopt(&exthdrs, plen)) != 0)
     269             :                         goto freehdrs;
     270           0 :                 ip6->ip6_plen = 0;
     271           0 :         } else
     272           0 :                 ip6->ip6_plen = htons(plen);
     273             : 
     274             :         /*
     275             :          * Concatenate headers and fill in next header fields.
     276             :          * Here we have, on "m"
     277             :          *      IPv6 payload
     278             :          * and we insert headers accordingly.  Finally, we should be getting:
     279             :          *      IPv6 hbh dest1 rthdr ah* [esp* dest2 payload]
     280             :          *
     281             :          * during the header composing process, "m" points to IPv6 header.
     282             :          * "mprev" points to an extension header prior to esp.
     283             :          */
     284             :         {
     285           0 :                 u_char *nexthdrp = &ip6->ip6_nxt;
     286           0 :                 struct mbuf *mprev = m;
     287             : 
     288             :                 /*
     289             :                  * we treat dest2 specially.  this makes IPsec processing
     290             :                  * much easier.  the goal here is to make mprev point the
     291             :                  * mbuf prior to dest2.
     292             :                  *
     293             :                  * result: IPv6 dest2 payload
     294             :                  * m and mprev will point to IPv6 header.
     295             :                  */
     296           0 :                 if (exthdrs.ip6e_dest2) {
     297           0 :                         if (!hdrsplit)
     298           0 :                                 panic("assumption failed: hdr not split");
     299           0 :                         exthdrs.ip6e_dest2->m_next = m->m_next;
     300           0 :                         m->m_next = exthdrs.ip6e_dest2;
     301           0 :                         *mtod(exthdrs.ip6e_dest2, u_char *) = ip6->ip6_nxt;
     302           0 :                         ip6->ip6_nxt = IPPROTO_DSTOPTS;
     303           0 :                 }
     304             : 
     305             : #define MAKE_CHAIN(m, mp, p, i)\
     306             :     do {\
     307             :         if (m) {\
     308             :                 if (!hdrsplit) \
     309             :                         panic("assumption failed: hdr not split"); \
     310             :                 *mtod((m), u_char *) = *(p);\
     311             :                 *(p) = (i);\
     312             :                 p = mtod((m), u_char *);\
     313             :                 (m)->m_next = (mp)->m_next;\
     314             :                 (mp)->m_next = (m);\
     315             :                 (mp) = (m);\
     316             :         }\
     317             :     } while (0)
     318             :                 /*
     319             :                  * result: IPv6 hbh dest1 rthdr dest2 payload
     320             :                  * m will point to IPv6 header.  mprev will point to the
     321             :                  * extension header prior to dest2 (rthdr in the above case).
     322             :                  */
     323           0 :                 MAKE_CHAIN(exthdrs.ip6e_hbh, mprev, nexthdrp, IPPROTO_HOPOPTS);
     324           0 :                 MAKE_CHAIN(exthdrs.ip6e_dest1, mprev, nexthdrp,
     325             :                     IPPROTO_DSTOPTS);
     326           0 :                 MAKE_CHAIN(exthdrs.ip6e_rthdr, mprev, nexthdrp,
     327             :                     IPPROTO_ROUTING);
     328             :         }
     329             : 
     330             :         /*
     331             :          * If there is a routing header, replace the destination address field
     332             :          * with the first hop of the routing header.
     333             :          */
     334           0 :         if (exthdrs.ip6e_rthdr) {
     335             :                 struct ip6_rthdr *rh;
     336             :                 struct ip6_rthdr0 *rh0;
     337             :                 struct in6_addr *addr;
     338             : 
     339           0 :                 rh = (struct ip6_rthdr *)(mtod(exthdrs.ip6e_rthdr,
     340             :                     struct ip6_rthdr *));
     341           0 :                 switch (rh->ip6r_type) {
     342             :                 case IPV6_RTHDR_TYPE_0:
     343           0 :                          rh0 = (struct ip6_rthdr0 *)rh;
     344           0 :                          addr = (struct in6_addr *)(rh0 + 1);
     345           0 :                          ip6->ip6_dst = addr[0];
     346           0 :                          bcopy(&addr[1], &addr[0],
     347           0 :                              sizeof(struct in6_addr) * (rh0->ip6r0_segleft - 1));
     348           0 :                          addr[rh0->ip6r0_segleft - 1] = finaldst;
     349             :                          break;
     350             :                 default:        /* is it possible? */
     351           0 :                          error = EINVAL;
     352           0 :                          goto bad;
     353             :                 }
     354           0 :         }
     355             : 
     356             :         /* Source address validation */
     357           0 :         if (!(flags & IPV6_UNSPECSRC) &&
     358           0 :             IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
     359             :                 /*
     360             :                  * XXX: we can probably assume validation in the caller, but
     361             :                  * we explicitly check the address here for safety.
     362             :                  */
     363           0 :                 error = EOPNOTSUPP;
     364           0 :                 ip6stat_inc(ip6s_badscope);
     365           0 :                 goto bad;
     366             :         }
     367           0 :         if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) {
     368           0 :                 error = EOPNOTSUPP;
     369           0 :                 ip6stat_inc(ip6s_badscope);
     370           0 :                 goto bad;
     371             :         }
     372             : 
     373           0 :         ip6stat_inc(ip6s_localout);
     374             : 
     375             :         /*
     376             :          * Route packet.
     377             :          */
     378             : #if NPF > 0
     379             : reroute:
     380             : #endif
     381             : 
     382             :         /* initialize cached route */
     383           0 :         if (ro == NULL) {
     384             :                 ro = &ip6route;
     385           0 :                 bzero((caddr_t)ro, sizeof(*ro));
     386           0 :         }
     387             :         ro_pmtu = ro;
     388           0 :         if (opt && opt->ip6po_rthdr)
     389           0 :                 ro = &opt->ip6po_route;
     390           0 :         dst = &ro->ro_dst;
     391             : 
     392             :         /*
     393             :          * if specified, try to fill in the traffic class field.
     394             :          * do not override if a non-zero value is already set.
     395             :          * we check the diffserv field and the ecn field separately.
     396             :          */
     397           0 :         if (opt && opt->ip6po_tclass >= 0) {
     398             :                 int mask = 0;
     399             : 
     400           0 :                 if ((ip6->ip6_flow & htonl(0xfc << 20)) == 0)
     401           0 :                         mask |= 0xfc;
     402           0 :                 if ((ip6->ip6_flow & htonl(0x03 << 20)) == 0)
     403           0 :                         mask |= 0x03;
     404           0 :                 if (mask != 0)
     405           0 :                         ip6->ip6_flow |= htonl((opt->ip6po_tclass & mask) << 20);
     406           0 :         }
     407             : 
     408             :         /* fill in or override the hop limit field, if necessary. */
     409           0 :         if (opt && opt->ip6po_hlim != -1)
     410           0 :                 ip6->ip6_hlim = opt->ip6po_hlim & 0xff;
     411           0 :         else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
     412           0 :                 if (im6o != NULL)
     413           0 :                         ip6->ip6_hlim = im6o->im6o_hlim;
     414             :                 else
     415           0 :                         ip6->ip6_hlim = ip6_defmcasthlim;
     416             :         }
     417             : 
     418             : #ifdef IPSEC
     419           0 :         if (tdb) {
     420             :                 /*
     421             :                  * XXX what should we do if ip6_hlim == 0 and the
     422             :                  * packet gets tunneled?
     423             :                  */
     424             :                 /*
     425             :                  * if we are source-routing, do not attempt to tunnel the
     426             :                  * packet just because ip6_dst is different from what tdb has.
     427             :                  * XXX
     428             :                  */
     429           0 :                 error = ip6_output_ipsec_send(tdb, m,
     430           0 :                     exthdrs.ip6e_rthdr ? 1 : 0, 0);
     431           0 :                 goto done;
     432             :         }
     433             : #endif /* IPSEC */
     434             : 
     435           0 :         bzero(&dstsock, sizeof(dstsock));
     436           0 :         dstsock.sin6_family = AF_INET6;
     437           0 :         dstsock.sin6_addr = ip6->ip6_dst;
     438           0 :         dstsock.sin6_len = sizeof(dstsock);
     439           0 :         ro->ro_tableid = m->m_pkthdr.ph_rtableid;
     440             : 
     441           0 :         if (IN6_IS_ADDR_MULTICAST(&dstsock.sin6_addr)) {
     442             :                 struct in6_pktinfo *pi = NULL;
     443             : 
     444             :                 /*
     445             :                  * If the caller specify the outgoing interface
     446             :                  * explicitly, use it.
     447             :                  */
     448           0 :                 if (opt != NULL && (pi = opt->ip6po_pktinfo) != NULL)
     449           0 :                         ifp = if_get(pi->ipi6_ifindex);
     450             : 
     451           0 :                 if (ifp == NULL && im6o != NULL)
     452           0 :                         ifp = if_get(im6o->im6o_ifidx);
     453           0 :         }
     454             : 
     455           0 :         if (ifp == NULL) {
     456           0 :                 rt = in6_selectroute(&dstsock, opt, ro, ro->ro_tableid);
     457           0 :                 if (rt == NULL) {
     458           0 :                         ip6stat_inc(ip6s_noroute);
     459           0 :                         error = EHOSTUNREACH;
     460           0 :                         goto bad;
     461             :                 }
     462           0 :                 if (ISSET(rt->rt_flags, RTF_LOCAL))
     463           0 :                         ifp = if_get(rtable_loindex(m->m_pkthdr.ph_rtableid));
     464             :                 else
     465           0 :                         ifp = if_get(rt->rt_ifidx);
     466             :                 /*
     467             :                  * We aren't using rtisvalid() here because the UP/DOWN state
     468             :                  * machine is broken with some Ethernet drivers like em(4).
     469             :                  * As a result we might try to use an invalid cached route
     470             :                  * entry while an interface is being detached.
     471             :                  */
     472           0 :                 if (ifp == NULL) {
     473           0 :                         ip6stat_inc(ip6s_noroute);
     474           0 :                         error = EHOSTUNREACH;
     475           0 :                         goto bad;
     476             :                 }
     477             :         } else {
     478           0 :                 *dst = dstsock;
     479             :         }
     480             : 
     481           0 :         if (rt && (rt->rt_flags & RTF_GATEWAY) &&
     482           0 :             !IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst))
     483           0 :                 dst = satosin6(rt->rt_gateway);
     484             : 
     485           0 :         if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
     486             :                 /* Unicast */
     487             : 
     488           0 :                 m->m_flags &= ~(M_BCAST | M_MCAST);      /* just in case */
     489           0 :         } else {
     490             :                 /* Multicast */
     491             : 
     492           0 :                 m->m_flags = (m->m_flags & ~M_BCAST) | M_MCAST;
     493             : 
     494             :                 /*
     495             :                  * Confirm that the outgoing interface supports multicast.
     496             :                  */
     497           0 :                 if ((ifp->if_flags & IFF_MULTICAST) == 0) {
     498           0 :                         ip6stat_inc(ip6s_noroute);
     499           0 :                         error = ENETUNREACH;
     500           0 :                         goto bad;
     501             :                 }
     502             : 
     503           0 :                 if ((im6o == NULL || im6o->im6o_loop) &&
     504           0 :                     in6_hasmulti(&ip6->ip6_dst, ifp)) {
     505             :                         /*
     506             :                          * If we belong to the destination multicast group
     507             :                          * on the outgoing interface, and the caller did not
     508             :                          * forbid loopback, loop back a copy.
     509             :                          * Can't defer TCP/UDP checksumming, do the
     510             :                          * computation now.
     511             :                          */
     512           0 :                         in6_proto_cksum_out(m, NULL);
     513           0 :                         ip6_mloopback(ifp, m, dst);
     514           0 :                 }
     515             : #ifdef MROUTING
     516             :                 else {
     517             :                         /*
     518             :                          * If we are acting as a multicast router, perform
     519             :                          * multicast forwarding as if the packet had just
     520             :                          * arrived on the interface to which we are about
     521             :                          * to send.  The multicast forwarding function
     522             :                          * recursively calls this function, using the
     523             :                          * IPV6_FORWARDING flag to prevent infinite recursion.
     524             :                          *
     525             :                          * Multicasts that are looped back by ip6_mloopback(),
     526             :                          * above, will be forwarded by the ip6_input() routine,
     527             :                          * if necessary.
     528             :                          */
     529           0 :                         if (ip6_mforwarding && ip6_mrouter[ifp->if_rdomain] &&
     530           0 :                             (flags & IPV6_FORWARDING) == 0) {
     531           0 :                                 if (ip6_mforward(ip6, ifp, m) != 0) {
     532           0 :                                         m_freem(m);
     533           0 :                                         goto done;
     534             :                                 }
     535             :                         }
     536             :                 }
     537             : #endif
     538             :                 /*
     539             :                  * Multicasts with a hoplimit of zero may be looped back,
     540             :                  * above, but must not be transmitted on a network.
     541             :                  * Also, multicasts addressed to the loopback interface
     542             :                  * are not sent -- the above call to ip6_mloopback() will
     543             :                  * loop back a copy if this host actually belongs to the
     544             :                  * destination group on the loopback interface.
     545             :                  */
     546           0 :                 if (ip6->ip6_hlim == 0 || (ifp->if_flags & IFF_LOOPBACK) ||
     547           0 :                     IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst)) {
     548           0 :                         m_freem(m);
     549           0 :                         goto done;
     550             :                 }
     551             :         }
     552             : 
     553             :         /*
     554             :          * If this packet is going trough a loopback interface we wont
     555             :          * be able to restore its scope ID using the interface index.
     556             :          */
     557           0 :         if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src)) {
     558           0 :                 if (ifp->if_flags & IFF_LOOPBACK)
     559           0 :                         src_scope = ip6->ip6_src.s6_addr16[1];
     560           0 :                 ip6->ip6_src.s6_addr16[1] = 0;
     561           0 :         }
     562           0 :         if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst)) {
     563           0 :                 if (ifp->if_flags & IFF_LOOPBACK)
     564           0 :                         dst_scope = ip6->ip6_dst.s6_addr16[1];
     565           0 :                 ip6->ip6_dst.s6_addr16[1] = 0;
     566           0 :         }
     567             : 
     568             :         /* Determine path MTU. */
     569           0 :         if ((error = ip6_getpmtu(ro_pmtu->ro_rt, ifp, &mtu)) != 0)
     570             :                 goto bad;
     571             : 
     572             :         /*
     573             :          * The caller of this function may specify to use the minimum MTU
     574             :          * in some cases.
     575             :          * An advanced API option (IPV6_USE_MIN_MTU) can also override MTU
     576             :          * setting.  The logic is a bit complicated; by default, unicast
     577             :          * packets will follow path MTU while multicast packets will be sent at
     578             :          * the minimum MTU.  If IP6PO_MINMTU_ALL is specified, all packets
     579             :          * including unicast ones will be sent at the minimum MTU.  Multicast
     580             :          * packets will always be sent at the minimum MTU unless
     581             :          * IP6PO_MINMTU_DISABLE is explicitly specified.
     582             :          * See RFC 3542 for more details.
     583             :          */
     584           0 :         if (mtu > IPV6_MMTU) {
     585           0 :                 if ((flags & IPV6_MINMTU))
     586           0 :                         mtu = IPV6_MMTU;
     587           0 :                 else if (opt && opt->ip6po_minmtu == IP6PO_MINMTU_ALL)
     588           0 :                         mtu = IPV6_MMTU;
     589           0 :                 else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
     590           0 :                          (opt == NULL ||
     591           0 :                           opt->ip6po_minmtu != IP6PO_MINMTU_DISABLE)) {
     592           0 :                         mtu = IPV6_MMTU;
     593           0 :                 }
     594             :         }
     595             : 
     596             :         /*
     597             :          * If the outgoing packet contains a hop-by-hop options header,
     598             :          * it must be examined and processed even by the source node.
     599             :          * (RFC 2460, section 4.)
     600             :          */
     601           0 :         if (exthdrs.ip6e_hbh) {
     602           0 :                 struct ip6_hbh *hbh = mtod(exthdrs.ip6e_hbh, struct ip6_hbh *);
     603           0 :                 u_int32_t dummy1; /* XXX unused */
     604           0 :                 u_int32_t dummy2; /* XXX unused */
     605             : 
     606           0 :                 m->m_pkthdr.ph_ifidx = ifp->if_index;
     607           0 :                 if (ip6_process_hopopts(m, (u_int8_t *)(hbh + 1),
     608           0 :                     ((hbh->ip6h_len + 1) << 3) - sizeof(struct ip6_hbh),
     609           0 :                     &dummy1, &dummy2) < 0) {
     610             :                         /* m was already freed at this point */
     611           0 :                         error = EINVAL;/* better error? */
     612           0 :                         goto done;
     613             :                 }
     614           0 :                 m->m_pkthdr.ph_ifidx = 0;
     615           0 :         }
     616             : 
     617             : #if NPF > 0
     618           0 :         if (pf_test(AF_INET6, PF_OUT, ifp, &m) != PF_PASS) {
     619           0 :                 error = EHOSTUNREACH;
     620           0 :                 m_freem(m);
     621           0 :                 goto done;
     622             :         }
     623           0 :         if (m == NULL)
     624             :                 goto done;
     625           0 :         ip6 = mtod(m, struct ip6_hdr *);
     626           0 :         if ((m->m_pkthdr.pf.flags & (PF_TAG_REROUTE | PF_TAG_GENERATED)) ==
     627             :             (PF_TAG_REROUTE | PF_TAG_GENERATED)) {
     628             :                 /* already rerun the route lookup, go on */
     629           0 :                 m->m_pkthdr.pf.flags &= ~(PF_TAG_GENERATED | PF_TAG_REROUTE);
     630           0 :         } else if (m->m_pkthdr.pf.flags & PF_TAG_REROUTE) {
     631             :                 /* tag as generated to skip over pf_test on rerun */
     632           0 :                 m->m_pkthdr.pf.flags |= PF_TAG_GENERATED;
     633           0 :                 finaldst = ip6->ip6_dst;
     634             :                 ro = NULL;
     635           0 :                 if_put(ifp); /* drop reference since destination changed */
     636             :                 ifp = NULL;
     637           0 :                 goto reroute;
     638             :         }
     639             : #endif
     640             : 
     641             :         /*
     642             :          * If the packet is not going on the wire it can be destinated
     643             :          * to any local address.  In this case do not clear its scopes
     644             :          * to let ip6_input() find a matching local route.
     645             :          */
     646           0 :         if (ifp->if_flags & IFF_LOOPBACK) {
     647           0 :                 if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src))
     648           0 :                         ip6->ip6_src.s6_addr16[1] = src_scope;
     649           0 :                 if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst))
     650           0 :                         ip6->ip6_dst.s6_addr16[1] = dst_scope;
     651             :         }
     652             : 
     653           0 :         in6_proto_cksum_out(m, ifp);
     654             : 
     655             :         /*
     656             :          * Send the packet to the outgoing interface.
     657             :          * If necessary, do IPv6 fragmentation before sending.
     658             :          *
     659             :          * the logic here is rather complex:
     660             :          * 1: normal case (dontfrag == 0)
     661             :          * 1-a: send as is if tlen <= path mtu
     662             :          * 1-b: fragment if tlen > path mtu
     663             :          *
     664             :          * 2: if user asks us not to fragment (dontfrag == 1)
     665             :          * 2-a: send as is if tlen <= interface mtu
     666             :          * 2-b: error if tlen > interface mtu
     667             :          */
     668           0 :         tlen = m->m_pkthdr.len;
     669             : 
     670           0 :         if (ISSET(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT)) {
     671           0 :                 CLR(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT);
     672             :                 dontfrag = 1;
     673           0 :         } else if (opt && ISSET(opt->ip6po_flags, IP6PO_DONTFRAG))
     674           0 :                 dontfrag = 1;
     675             :         else
     676             :                 dontfrag = 0;
     677           0 :         if (dontfrag && tlen > ifp->if_mtu) {     /* case 2-b */
     678           0 :                 error = EMSGSIZE;
     679           0 :                 goto bad;
     680             :         }
     681             : 
     682             :         /*
     683             :          * transmit packet without fragmentation
     684             :          */
     685           0 :         if (dontfrag || (tlen <= mtu)) {     /* case 1-a and 2-a */
     686           0 :                 error = ifp->if_output(ifp, m, sin6tosa(dst), ro->ro_rt);
     687           0 :                 goto done;
     688             :         }
     689             : 
     690             :         /*
     691             :          * try to fragment the packet.  case 1-b
     692             :          */
     693           0 :         if (mtu < IPV6_MMTU) {
     694             :                 /* path MTU cannot be less than IPV6_MMTU */
     695           0 :                 error = EMSGSIZE;
     696           0 :                 goto bad;
     697           0 :         } else if (ip6->ip6_plen == 0) {
     698             :                 /* jumbo payload cannot be fragmented */
     699           0 :                 error = EMSGSIZE;
     700           0 :                 goto bad;
     701             :         } else {
     702             :                 u_char nextproto;
     703             : #if 0
     704             :                 struct ip6ctlparam ip6cp;
     705             :                 u_int32_t mtu32;
     706             : #endif
     707             : 
     708             :                 /*
     709             :                  * Too large for the destination or interface;
     710             :                  * fragment if possible.
     711             :                  * Must be able to put at least 8 bytes per fragment.
     712             :                  */
     713             :                 hlen = unfragpartlen;
     714           0 :                 if (mtu > IPV6_MAXPACKET)
     715           0 :                         mtu = IPV6_MAXPACKET;
     716             : 
     717             :                 /*
     718             :                  * Change the next header field of the last header in the
     719             :                  * unfragmentable part.
     720             :                  */
     721           0 :                 if (exthdrs.ip6e_rthdr) {
     722           0 :                         nextproto = *mtod(exthdrs.ip6e_rthdr, u_char *);
     723           0 :                         *mtod(exthdrs.ip6e_rthdr, u_char *) = IPPROTO_FRAGMENT;
     724           0 :                 } else if (exthdrs.ip6e_dest1) {
     725           0 :                         nextproto = *mtod(exthdrs.ip6e_dest1, u_char *);
     726           0 :                         *mtod(exthdrs.ip6e_dest1, u_char *) = IPPROTO_FRAGMENT;
     727           0 :                 } else if (exthdrs.ip6e_hbh) {
     728           0 :                         nextproto = *mtod(exthdrs.ip6e_hbh, u_char *);
     729           0 :                         *mtod(exthdrs.ip6e_hbh, u_char *) = IPPROTO_FRAGMENT;
     730           0 :                 } else {
     731           0 :                         nextproto = ip6->ip6_nxt;
     732           0 :                         ip6->ip6_nxt = IPPROTO_FRAGMENT;
     733             :                 }
     734             : 
     735           0 :                 m0 = m;
     736           0 :                 error = ip6_fragment(m0, hlen, nextproto, mtu);
     737           0 :                 if (error)
     738           0 :                         ip6stat_inc(ip6s_odropped);
     739             :         }
     740             : 
     741             :         /*
     742             :          * Remove leading garbages.
     743             :          */
     744           0 :         m = m0->m_nextpkt;
     745           0 :         m0->m_nextpkt = 0;
     746           0 :         m_freem(m0);
     747           0 :         for (m0 = m; m; m = m0) {
     748           0 :                 m0 = m->m_nextpkt;
     749           0 :                 m->m_nextpkt = 0;
     750           0 :                 if (error == 0) {
     751           0 :                         ip6stat_inc(ip6s_ofragments);
     752           0 :                         error = ifp->if_output(ifp, m, sin6tosa(dst),
     753           0 :                             ro->ro_rt);
     754           0 :                 } else
     755           0 :                         m_freem(m);
     756             :         }
     757             : 
     758           0 :         if (error == 0)
     759           0 :                 ip6stat_inc(ip6s_fragmented);
     760             : 
     761             : done:
     762           0 :         if_put(ifp);
     763           0 :         if (ro == &ip6route && ro->ro_rt) {
     764           0 :                 rtfree(ro->ro_rt);
     765           0 :         } else if (ro_pmtu == &ip6route && ro_pmtu->ro_rt) {
     766           0 :                 rtfree(ro_pmtu->ro_rt);
     767           0 :         }
     768             : 
     769           0 :         return (error);
     770             : 
     771             : freehdrs:
     772           0 :         m_freem(exthdrs.ip6e_hbh);      /* m_freem will check if mbuf is 0 */
     773           0 :         m_freem(exthdrs.ip6e_dest1);
     774           0 :         m_freem(exthdrs.ip6e_rthdr);
     775           0 :         m_freem(exthdrs.ip6e_dest2);
     776             :         /* FALLTHROUGH */
     777             : bad:
     778           0 :         m_freem(m);
     779           0 :         goto done;
     780           0 : }
     781             : 
     782             : int
     783           0 : ip6_fragment(struct mbuf *m0, int hlen, u_char nextproto, u_long mtu)
     784             : {
     785             :         struct mbuf     *m, **mnext, *m_frgpart;
     786             :         struct ip6_hdr  *mhip6;
     787           0 :         struct ip6_frag *ip6f;
     788             :         u_int32_t        id;
     789             :         int              tlen, len, off;
     790             :         int              error;
     791             : 
     792           0 :         id = htonl(ip6_randomid());
     793             : 
     794           0 :         mnext = &m0->m_nextpkt;
     795           0 :         *mnext = NULL;
     796             : 
     797           0 :         tlen = m0->m_pkthdr.len;
     798           0 :         len = (mtu - hlen - sizeof(struct ip6_frag)) & ~7;
     799           0 :         if (len < 8)
     800           0 :                 return (EMSGSIZE);
     801             : 
     802             :         /*
     803             :          * Loop through length of segment after first fragment,
     804             :          * make new header and copy data of each part and link onto
     805             :          * chain.
     806             :          */
     807           0 :         for (off = hlen; off < tlen; off += len) {
     808             :                 struct mbuf *mlast;
     809             : 
     810           0 :                 if ((m = m_gethdr(M_DONTWAIT, MT_HEADER)) == NULL)
     811           0 :                         return (ENOBUFS);
     812           0 :                 *mnext = m;
     813           0 :                 mnext = &m->m_nextpkt;
     814           0 :                 if ((error = m_dup_pkthdr(m, m0, M_DONTWAIT)) != 0)
     815           0 :                         return (error);
     816           0 :                 m->m_data += max_linkhdr;
     817           0 :                 mhip6 = mtod(m, struct ip6_hdr *);
     818           0 :                 *mhip6 = *mtod(m0, struct ip6_hdr *);
     819           0 :                 m->m_len = sizeof(*mhip6);
     820           0 :                 if ((error = ip6_insertfraghdr(m0, m, hlen, &ip6f)) != 0)
     821           0 :                         return (error);
     822           0 :                 ip6f->ip6f_offlg = htons((u_int16_t)((off - hlen) & ~7));
     823           0 :                 if (off + len >= tlen)
     824           0 :                         len = tlen - off;
     825             :                 else
     826           0 :                         ip6f->ip6f_offlg |= IP6F_MORE_FRAG;
     827           0 :                 mhip6->ip6_plen = htons((u_int16_t)(len + hlen +
     828             :                     sizeof(*ip6f) - sizeof(struct ip6_hdr)));
     829           0 :                 if ((m_frgpart = m_copym(m0, off, len, M_DONTWAIT)) == NULL)
     830           0 :                         return (ENOBUFS);
     831           0 :                 for (mlast = m; mlast->m_next; mlast = mlast->m_next)
     832             :                         ;
     833           0 :                 mlast->m_next = m_frgpart;
     834           0 :                 m->m_pkthdr.len = len + hlen + sizeof(*ip6f);
     835           0 :                 ip6f->ip6f_reserved = 0;
     836           0 :                 ip6f->ip6f_ident = id;
     837           0 :                 ip6f->ip6f_nxt = nextproto;
     838           0 :         }
     839             : 
     840           0 :         return (0);
     841           0 : }
     842             : 
     843             : int
     844           0 : ip6_copyexthdr(struct mbuf **mp, caddr_t hdr, int hlen)
     845             : {
     846             :         struct mbuf *m;
     847             : 
     848           0 :         if (hlen > MCLBYTES)
     849           0 :                 return (ENOBUFS); /* XXX */
     850             : 
     851           0 :         MGET(m, M_DONTWAIT, MT_DATA);
     852           0 :         if (!m)
     853           0 :                 return (ENOBUFS);
     854             : 
     855           0 :         if (hlen > MLEN) {
     856           0 :                 MCLGET(m, M_DONTWAIT);
     857           0 :                 if ((m->m_flags & M_EXT) == 0) {
     858           0 :                         m_free(m);
     859           0 :                         return (ENOBUFS);
     860             :                 }
     861             :         }
     862           0 :         m->m_len = hlen;
     863           0 :         if (hdr)
     864           0 :                 memcpy(mtod(m, caddr_t), hdr, hlen);
     865             : 
     866           0 :         *mp = m;
     867           0 :         return (0);
     868           0 : }
     869             : 
     870             : /*
     871             :  * Insert jumbo payload option.
     872             :  */
     873             : int
     874           0 : ip6_insert_jumboopt(struct ip6_exthdrs *exthdrs, u_int32_t plen)
     875             : {
     876             :         struct mbuf *mopt;
     877             :         u_int8_t *optbuf;
     878             :         u_int32_t v;
     879             : 
     880             : #define JUMBOOPTLEN     8       /* length of jumbo payload option and padding */
     881             : 
     882             :         /*
     883             :          * If there is no hop-by-hop options header, allocate new one.
     884             :          * If there is one but it doesn't have enough space to store the
     885             :          * jumbo payload option, allocate a cluster to store the whole options.
     886             :          * Otherwise, use it to store the options.
     887             :          */
     888           0 :         if (exthdrs->ip6e_hbh == 0) {
     889           0 :                 MGET(mopt, M_DONTWAIT, MT_DATA);
     890           0 :                 if (mopt == NULL)
     891           0 :                         return (ENOBUFS);
     892           0 :                 mopt->m_len = JUMBOOPTLEN;
     893           0 :                 optbuf = mtod(mopt, u_int8_t *);
     894           0 :                 optbuf[1] = 0;  /* = ((JUMBOOPTLEN) >> 3) - 1 */
     895           0 :                 exthdrs->ip6e_hbh = mopt;
     896           0 :         } else {
     897             :                 struct ip6_hbh *hbh;
     898             : 
     899             :                 mopt = exthdrs->ip6e_hbh;
     900           0 :                 if (M_TRAILINGSPACE(mopt) < JUMBOOPTLEN) {
     901             :                         /*
     902             :                          * XXX assumption:
     903             :                          * - exthdrs->ip6e_hbh is not referenced from places
     904             :                          *   other than exthdrs.
     905             :                          * - exthdrs->ip6e_hbh is not an mbuf chain.
     906             :                          */
     907           0 :                         int oldoptlen = mopt->m_len;
     908             :                         struct mbuf *n;
     909             : 
     910             :                         /*
     911             :                          * XXX: give up if the whole (new) hbh header does
     912             :                          * not fit even in an mbuf cluster.
     913             :                          */
     914           0 :                         if (oldoptlen + JUMBOOPTLEN > MCLBYTES)
     915           0 :                                 return (ENOBUFS);
     916             : 
     917             :                         /*
     918             :                          * As a consequence, we must always prepare a cluster
     919             :                          * at this point.
     920             :                          */
     921           0 :                         MGET(n, M_DONTWAIT, MT_DATA);
     922           0 :                         if (n) {
     923           0 :                                 MCLGET(n, M_DONTWAIT);
     924           0 :                                 if ((n->m_flags & M_EXT) == 0) {
     925           0 :                                         m_freem(n);
     926             :                                         n = NULL;
     927           0 :                                 }
     928             :                         }
     929           0 :                         if (!n)
     930           0 :                                 return (ENOBUFS);
     931           0 :                         n->m_len = oldoptlen + JUMBOOPTLEN;
     932           0 :                         memcpy(mtod(n, caddr_t), mtod(mopt, caddr_t),
     933             :                               oldoptlen);
     934           0 :                         optbuf = mtod(n, u_int8_t *) + oldoptlen;
     935           0 :                         m_freem(mopt);
     936           0 :                         mopt = exthdrs->ip6e_hbh = n;
     937           0 :                 } else {
     938           0 :                         optbuf = mtod(mopt, u_int8_t *) + mopt->m_len;
     939           0 :                         mopt->m_len += JUMBOOPTLEN;
     940             :                 }
     941           0 :                 optbuf[0] = IP6OPT_PADN;
     942           0 :                 optbuf[1] = 0;
     943             : 
     944             :                 /*
     945             :                  * Adjust the header length according to the pad and
     946             :                  * the jumbo payload option.
     947             :                  */
     948           0 :                 hbh = mtod(mopt, struct ip6_hbh *);
     949           0 :                 hbh->ip6h_len += (JUMBOOPTLEN >> 3);
     950           0 :         }
     951             : 
     952             :         /* fill in the option. */
     953           0 :         optbuf[2] = IP6OPT_JUMBO;
     954           0 :         optbuf[3] = 4;
     955           0 :         v = (u_int32_t)htonl(plen + JUMBOOPTLEN);
     956           0 :         memcpy(&optbuf[4], &v, sizeof(u_int32_t));
     957             : 
     958             :         /* finally, adjust the packet header length */
     959           0 :         exthdrs->ip6e_ip6->m_pkthdr.len += JUMBOOPTLEN;
     960             : 
     961           0 :         return (0);
     962             : #undef JUMBOOPTLEN
     963           0 : }
     964             : 
     965             : /*
     966             :  * Insert fragment header and copy unfragmentable header portions.
     967             :  */
     968             : int
     969           0 : ip6_insertfraghdr(struct mbuf *m0, struct mbuf *m, int hlen,
     970             :     struct ip6_frag **frghdrp)
     971             : {
     972             :         struct mbuf *n, *mlast;
     973             : 
     974           0 :         if (hlen > sizeof(struct ip6_hdr)) {
     975           0 :                 n = m_copym(m0, sizeof(struct ip6_hdr),
     976           0 :                     hlen - sizeof(struct ip6_hdr), M_DONTWAIT);
     977           0 :                 if (n == NULL)
     978           0 :                         return (ENOBUFS);
     979           0 :                 m->m_next = n;
     980           0 :         } else
     981             :                 n = m;
     982             : 
     983             :         /* Search for the last mbuf of unfragmentable part. */
     984           0 :         for (mlast = n; mlast->m_next; mlast = mlast->m_next)
     985             :                 ;
     986             : 
     987           0 :         if ((mlast->m_flags & M_EXT) == 0 &&
     988           0 :             M_TRAILINGSPACE(mlast) >= sizeof(struct ip6_frag)) {
     989             :                 /* use the trailing space of the last mbuf for the fragment hdr */
     990           0 :                 *frghdrp = (struct ip6_frag *)(mtod(mlast, caddr_t) +
     991           0 :                     mlast->m_len);
     992           0 :                 mlast->m_len += sizeof(struct ip6_frag);
     993           0 :                 m->m_pkthdr.len += sizeof(struct ip6_frag);
     994           0 :         } else {
     995             :                 /* allocate a new mbuf for the fragment header */
     996             :                 struct mbuf *mfrg;
     997             : 
     998           0 :                 MGET(mfrg, M_DONTWAIT, MT_DATA);
     999           0 :                 if (mfrg == NULL)
    1000           0 :                         return (ENOBUFS);
    1001           0 :                 mfrg->m_len = sizeof(struct ip6_frag);
    1002           0 :                 *frghdrp = mtod(mfrg, struct ip6_frag *);
    1003           0 :                 mlast->m_next = mfrg;
    1004           0 :         }
    1005             : 
    1006           0 :         return (0);
    1007           0 : }
    1008             : 
    1009             : int
    1010           0 : ip6_getpmtu(struct rtentry *rt, struct ifnet *ifp, u_long *mtup)
    1011             : {
    1012             :         u_int32_t mtu = 0;
    1013             :         int error = 0;
    1014             : 
    1015           0 :         if (rt != NULL) {
    1016           0 :                 mtu = rt->rt_mtu;
    1017           0 :                 if (mtu == 0)
    1018           0 :                         mtu = ifp->if_mtu;
    1019           0 :                 else if (mtu < IPV6_MMTU) {
    1020             :                         /* RFC8021 IPv6 Atomic Fragments Considered Harmful */
    1021             :                         mtu = IPV6_MMTU;
    1022           0 :                 } else if (mtu > ifp->if_mtu) {
    1023             :                         /*
    1024             :                          * The MTU on the route is larger than the MTU on
    1025             :                          * the interface!  This shouldn't happen, unless the
    1026             :                          * MTU of the interface has been changed after the
    1027             :                          * interface was brought up.  Change the MTU in the
    1028             :                          * route to match the interface MTU (as long as the
    1029             :                          * field isn't locked).
    1030             :                          */
    1031             :                         mtu = ifp->if_mtu;
    1032           0 :                         if (!(rt->rt_locks & RTV_MTU))
    1033           0 :                                 rt->rt_mtu = mtu;
    1034             :                 }
    1035             :         } else {
    1036           0 :                 mtu = ifp->if_mtu;
    1037             :         }
    1038             : 
    1039           0 :         *mtup = mtu;
    1040           0 :         return (error);
    1041             : }
    1042             : 
    1043             : /*
    1044             :  * IP6 socket option processing.
    1045             :  */
    1046             : int
    1047           0 : ip6_ctloutput(int op, struct socket *so, int level, int optname,
    1048             :     struct mbuf *m)
    1049             : {
    1050             :         int privileged, optdatalen, uproto;
    1051             :         void *optdata;
    1052           0 :         struct inpcb *inp = sotoinpcb(so);
    1053           0 :         int error, optval;
    1054           0 :         struct proc *p = curproc; /* For IPsec and rdomain */
    1055             :         u_int rtid = 0;
    1056             : 
    1057           0 :         error = optval = 0;
    1058             : 
    1059           0 :         privileged = (inp->inp_socket->so_state & SS_PRIV);
    1060           0 :         uproto = (int)so->so_proto->pr_protocol;
    1061             : 
    1062           0 :         if (level != IPPROTO_IPV6)
    1063           0 :                 return (EINVAL);
    1064             : 
    1065           0 :         switch (op) {
    1066             :         case PRCO_SETOPT:
    1067           0 :                 switch (optname) {
    1068             :                 /*
    1069             :                  * Use of some Hop-by-Hop options or some
    1070             :                  * Destination options, might require special
    1071             :                  * privilege.  That is, normal applications
    1072             :                  * (without special privilege) might be forbidden
    1073             :                  * from setting certain options in outgoing packets,
    1074             :                  * and might never see certain options in received
    1075             :                  * packets. [RFC 2292 Section 6]
    1076             :                  * KAME specific note:
    1077             :                  *  KAME prevents non-privileged users from sending or
    1078             :                  *  receiving ANY hbh/dst options in order to avoid
    1079             :                  *  overhead of parsing options in the kernel.
    1080             :                  */
    1081             :                 case IPV6_RECVHOPOPTS:
    1082             :                 case IPV6_RECVDSTOPTS:
    1083           0 :                         if (!privileged) {
    1084             :                                 error = EPERM;
    1085           0 :                                 break;
    1086             :                         }
    1087             :                         /* FALLTHROUGH */
    1088             :                 case IPV6_UNICAST_HOPS:
    1089             :                 case IPV6_MINHOPCOUNT:
    1090             :                 case IPV6_HOPLIMIT:
    1091             : 
    1092             :                 case IPV6_RECVPKTINFO:
    1093             :                 case IPV6_RECVHOPLIMIT:
    1094             :                 case IPV6_RECVRTHDR:
    1095             :                 case IPV6_RECVPATHMTU:
    1096             :                 case IPV6_RECVTCLASS:
    1097             :                 case IPV6_V6ONLY:
    1098             :                 case IPV6_AUTOFLOWLABEL:
    1099             :                 case IPV6_RECVDSTPORT:
    1100           0 :                         if (m == NULL || m->m_len != sizeof(int)) {
    1101             :                                 error = EINVAL;
    1102           0 :                                 break;
    1103             :                         }
    1104           0 :                         optval = *mtod(m, int *);
    1105           0 :                         switch (optname) {
    1106             : 
    1107             :                         case IPV6_UNICAST_HOPS:
    1108           0 :                                 if (optval < -1 || optval >= 256)
    1109           0 :                                         error = EINVAL;
    1110             :                                 else {
    1111             :                                         /* -1 = kernel default */
    1112           0 :                                         inp->inp_hops = optval;
    1113             :                                 }
    1114             :                                 break;
    1115             : 
    1116             :                         case IPV6_MINHOPCOUNT:
    1117           0 :                                 if (optval < 0 || optval > 255)
    1118           0 :                                         error = EINVAL;
    1119             :                                 else
    1120           0 :                                         inp->inp_ip6_minhlim = optval;
    1121             :                                 break;
    1122             : 
    1123             : #define OPTSET(bit) \
    1124             : do { \
    1125             :         if (optval) \
    1126             :                 inp->inp_flags |= (bit); \
    1127             :         else \
    1128             :                 inp->inp_flags &= ~(bit); \
    1129             : } while (/*CONSTCOND*/ 0)
    1130             : #define OPTBIT(bit) (inp->inp_flags & (bit) ? 1 : 0)
    1131             : 
    1132             :                         case IPV6_RECVPKTINFO:
    1133           0 :                                 OPTSET(IN6P_PKTINFO);
    1134             :                                 break;
    1135             : 
    1136             :                         case IPV6_HOPLIMIT:
    1137             :                         {
    1138             :                                 struct ip6_pktopts **optp;
    1139             : 
    1140           0 :                                 optp = &inp->inp_outputopts6;
    1141           0 :                                 error = ip6_pcbopt(IPV6_HOPLIMIT,
    1142             :                                                    (u_char *)&optval,
    1143             :                                                    sizeof(optval),
    1144             :                                                    optp,
    1145             :                                                    privileged, uproto);
    1146             :                                 break;
    1147             :                         }
    1148             : 
    1149             :                         case IPV6_RECVHOPLIMIT:
    1150           0 :                                 OPTSET(IN6P_HOPLIMIT);
    1151             :                                 break;
    1152             : 
    1153             :                         case IPV6_RECVHOPOPTS:
    1154           0 :                                 OPTSET(IN6P_HOPOPTS);
    1155             :                                 break;
    1156             : 
    1157             :                         case IPV6_RECVDSTOPTS:
    1158           0 :                                 OPTSET(IN6P_DSTOPTS);
    1159             :                                 break;
    1160             : 
    1161             :                         case IPV6_RECVRTHDR:
    1162           0 :                                 OPTSET(IN6P_RTHDR);
    1163             :                                 break;
    1164             : 
    1165             :                         case IPV6_RECVPATHMTU:
    1166             :                                 /*
    1167             :                                  * We ignore this option for TCP
    1168             :                                  * sockets.
    1169             :                                  * (RFC3542 leaves this case
    1170             :                                  * unspecified.)
    1171             :                                  */
    1172           0 :                                 if (uproto != IPPROTO_TCP)
    1173           0 :                                         OPTSET(IN6P_MTU);
    1174             :                                 break;
    1175             : 
    1176             :                         case IPV6_V6ONLY:
    1177             :                                 /*
    1178             :                                  * make setsockopt(IPV6_V6ONLY)
    1179             :                                  * available only prior to bind(2).
    1180             :                                  * see ipng mailing list, Jun 22 2001.
    1181             :                                  */
    1182           0 :                                 if (inp->inp_lport ||
    1183           0 :                                     !IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) {
    1184             :                                         error = EINVAL;
    1185           0 :                                         break;
    1186             :                                 }
    1187             :                                 /* No support for IPv4-mapped addresses. */
    1188           0 :                                 if (!optval)
    1189           0 :                                         error = EINVAL;
    1190             :                                 else
    1191             :                                         error = 0;
    1192             :                                 break;
    1193             :                         case IPV6_RECVTCLASS:
    1194           0 :                                 OPTSET(IN6P_TCLASS);
    1195             :                                 break;
    1196             :                         case IPV6_AUTOFLOWLABEL:
    1197           0 :                                 OPTSET(IN6P_AUTOFLOWLABEL);
    1198             :                                 break;
    1199             : 
    1200             :                         case IPV6_RECVDSTPORT:
    1201           0 :                                 OPTSET(IN6P_RECVDSTPORT);
    1202             :                                 break;
    1203             :                         }
    1204             :                         break;
    1205             : 
    1206             :                 case IPV6_TCLASS:
    1207             :                 case IPV6_DONTFRAG:
    1208             :                 case IPV6_USE_MIN_MTU:
    1209           0 :                         if (m == NULL || m->m_len != sizeof(optval)) {
    1210             :                                 error = EINVAL;
    1211           0 :                                 break;
    1212             :                         }
    1213           0 :                         optval = *mtod(m, int *);
    1214             :                         {
    1215             :                                 struct ip6_pktopts **optp;
    1216           0 :                                 optp = &inp->inp_outputopts6;
    1217           0 :                                 error = ip6_pcbopt(optname,
    1218             :                                                    (u_char *)&optval,
    1219             :                                                    sizeof(optval),
    1220             :                                                    optp,
    1221             :                                                    privileged, uproto);
    1222             :                                 break;
    1223             :                         }
    1224             : 
    1225             :                 case IPV6_PKTINFO:
    1226             :                 case IPV6_HOPOPTS:
    1227             :                 case IPV6_RTHDR:
    1228             :                 case IPV6_DSTOPTS:
    1229             :                 case IPV6_RTHDRDSTOPTS:
    1230             :                 {
    1231             :                         /* new advanced API (RFC3542) */
    1232             :                         u_char *optbuf;
    1233             :                         int optbuflen;
    1234             :                         struct ip6_pktopts **optp;
    1235             : 
    1236           0 :                         if (m && m->m_next) {
    1237             :                                 error = EINVAL; /* XXX */
    1238           0 :                                 break;
    1239             :                         }
    1240           0 :                         if (m) {
    1241           0 :                                 optbuf = mtod(m, u_char *);
    1242           0 :                                 optbuflen = m->m_len;
    1243           0 :                         } else {
    1244             :                                 optbuf = NULL;
    1245             :                                 optbuflen = 0;
    1246             :                         }
    1247           0 :                         optp = &inp->inp_outputopts6;
    1248           0 :                         error = ip6_pcbopt(optname,
    1249             :                                            optbuf, optbuflen,
    1250             :                                            optp, privileged, uproto);
    1251           0 :                         break;
    1252             :                 }
    1253             : #undef OPTSET
    1254             : 
    1255             :                 case IPV6_MULTICAST_IF:
    1256             :                 case IPV6_MULTICAST_HOPS:
    1257             :                 case IPV6_MULTICAST_LOOP:
    1258             :                 case IPV6_JOIN_GROUP:
    1259             :                 case IPV6_LEAVE_GROUP:
    1260           0 :                         error = ip6_setmoptions(optname,
    1261           0 :                                                 &inp->inp_moptions6,
    1262           0 :                                                 m, inp->inp_rtableid);
    1263           0 :                         break;
    1264             : 
    1265             :                 case IPV6_PORTRANGE:
    1266           0 :                         if (m == NULL || m->m_len != sizeof(int)) {
    1267             :                                 error = EINVAL;
    1268           0 :                                 break;
    1269             :                         }
    1270           0 :                         optval = *mtod(m, int *);
    1271             : 
    1272           0 :                         switch (optval) {
    1273             :                         case IPV6_PORTRANGE_DEFAULT:
    1274           0 :                                 inp->inp_flags &= ~(IN6P_LOWPORT);
    1275           0 :                                 inp->inp_flags &= ~(IN6P_HIGHPORT);
    1276           0 :                                 break;
    1277             : 
    1278             :                         case IPV6_PORTRANGE_HIGH:
    1279           0 :                                 inp->inp_flags &= ~(IN6P_LOWPORT);
    1280           0 :                                 inp->inp_flags |= IN6P_HIGHPORT;
    1281           0 :                                 break;
    1282             : 
    1283             :                         case IPV6_PORTRANGE_LOW:
    1284           0 :                                 inp->inp_flags &= ~(IN6P_HIGHPORT);
    1285           0 :                                 inp->inp_flags |= IN6P_LOWPORT;
    1286           0 :                                 break;
    1287             : 
    1288             :                         default:
    1289             :                                 error = EINVAL;
    1290           0 :                                 break;
    1291             :                         }
    1292             :                         break;
    1293             : 
    1294             :                 case IPSEC6_OUTSA:
    1295             :                         error = EINVAL;
    1296           0 :                         break;
    1297             : 
    1298             :                 case IPV6_AUTH_LEVEL:
    1299             :                 case IPV6_ESP_TRANS_LEVEL:
    1300             :                 case IPV6_ESP_NETWORK_LEVEL:
    1301             :                 case IPV6_IPCOMP_LEVEL:
    1302             : #ifndef IPSEC
    1303             :                         error = EINVAL;
    1304             : #else
    1305           0 :                         if (m == NULL || m->m_len != sizeof(int)) {
    1306             :                                 error = EINVAL;
    1307           0 :                                 break;
    1308             :                         }
    1309           0 :                         optval = *mtod(m, int *);
    1310             : 
    1311           0 :                         if (optval < IPSEC_LEVEL_BYPASS ||
    1312           0 :                             optval > IPSEC_LEVEL_UNIQUE) {
    1313             :                                 error = EINVAL;
    1314           0 :                                 break;
    1315             :                         }
    1316             : 
    1317           0 :                         switch (optname) {
    1318             :                         case IPV6_AUTH_LEVEL:
    1319           0 :                                 if (optval < IPSEC_AUTH_LEVEL_DEFAULT &&
    1320           0 :                                     suser(p)) {
    1321             :                                         error = EACCES;
    1322           0 :                                         break;
    1323             :                                 }
    1324           0 :                                 inp->inp_seclevel[SL_AUTH] = optval;
    1325           0 :                                 break;
    1326             : 
    1327             :                         case IPV6_ESP_TRANS_LEVEL:
    1328           0 :                                 if (optval < IPSEC_ESP_TRANS_LEVEL_DEFAULT &&
    1329           0 :                                     suser(p)) {
    1330             :                                         error = EACCES;
    1331           0 :                                         break;
    1332             :                                 }
    1333           0 :                                 inp->inp_seclevel[SL_ESP_TRANS] = optval;
    1334           0 :                                 break;
    1335             : 
    1336             :                         case IPV6_ESP_NETWORK_LEVEL:
    1337           0 :                                 if (optval < IPSEC_ESP_NETWORK_LEVEL_DEFAULT &&
    1338           0 :                                     suser(p)) {
    1339             :                                         error = EACCES;
    1340           0 :                                         break;
    1341             :                                 }
    1342           0 :                                 inp->inp_seclevel[SL_ESP_NETWORK] = optval;
    1343           0 :                                 break;
    1344             : 
    1345             :                         case IPV6_IPCOMP_LEVEL:
    1346           0 :                                 if (optval < IPSEC_IPCOMP_LEVEL_DEFAULT &&
    1347           0 :                                     suser(p)) {
    1348             :                                         error = EACCES;
    1349           0 :                                         break;
    1350             :                                 }
    1351           0 :                                 inp->inp_seclevel[SL_IPCOMP] = optval;
    1352           0 :                                 break;
    1353             :                         }
    1354             : #endif
    1355             :                         break;
    1356             :                 case SO_RTABLE:
    1357           0 :                         if (m == NULL || m->m_len < sizeof(u_int)) {
    1358             :                                 error = EINVAL;
    1359           0 :                                 break;
    1360             :                         }
    1361           0 :                         rtid = *mtod(m, u_int *);
    1362           0 :                         if (inp->inp_rtableid == rtid)
    1363             :                                 break;
    1364             :                         /* needs privileges to switch when already set */
    1365           0 :                         if (p->p_p->ps_rtableid != rtid &&
    1366           0 :                             p->p_p->ps_rtableid != 0 &&
    1367           0 :                             (error = suser(p)) != 0)
    1368             :                                 break;
    1369             :                         /* table must exist */
    1370           0 :                         if (!rtable_exists(rtid)) {
    1371             :                                 error = EINVAL;
    1372           0 :                                 break;
    1373             :                         }
    1374           0 :                         if (inp->inp_lport) {
    1375             :                                 error = EBUSY;
    1376           0 :                                 break;
    1377             :                         }
    1378           0 :                         inp->inp_rtableid = rtid;
    1379           0 :                         in_pcbrehash(inp);
    1380           0 :                         break;
    1381             :                 case IPV6_PIPEX:
    1382           0 :                         if (m != NULL && m->m_len == sizeof(int))
    1383           0 :                                 inp->inp_pipex = *mtod(m, int *);
    1384             :                         else
    1385             :                                 error = EINVAL;
    1386             :                         break;
    1387             : 
    1388             :                 default:
    1389             :                         error = ENOPROTOOPT;
    1390           0 :                         break;
    1391             :                 }
    1392             :                 break;
    1393             : 
    1394             :         case PRCO_GETOPT:
    1395           0 :                 switch (optname) {
    1396             : 
    1397             :                 case IPV6_RECVHOPOPTS:
    1398             :                 case IPV6_RECVDSTOPTS:
    1399             :                 case IPV6_UNICAST_HOPS:
    1400             :                 case IPV6_MINHOPCOUNT:
    1401             :                 case IPV6_RECVPKTINFO:
    1402             :                 case IPV6_RECVHOPLIMIT:
    1403             :                 case IPV6_RECVRTHDR:
    1404             :                 case IPV6_RECVPATHMTU:
    1405             : 
    1406             :                 case IPV6_V6ONLY:
    1407             :                 case IPV6_PORTRANGE:
    1408             :                 case IPV6_RECVTCLASS:
    1409             :                 case IPV6_AUTOFLOWLABEL:
    1410             :                 case IPV6_RECVDSTPORT:
    1411           0 :                         switch (optname) {
    1412             : 
    1413             :                         case IPV6_RECVHOPOPTS:
    1414           0 :                                 optval = OPTBIT(IN6P_HOPOPTS);
    1415           0 :                                 break;
    1416             : 
    1417             :                         case IPV6_RECVDSTOPTS:
    1418           0 :                                 optval = OPTBIT(IN6P_DSTOPTS);
    1419           0 :                                 break;
    1420             : 
    1421             :                         case IPV6_UNICAST_HOPS:
    1422           0 :                                 optval = inp->inp_hops;
    1423           0 :                                 break;
    1424             : 
    1425             :                         case IPV6_MINHOPCOUNT:
    1426           0 :                                 optval = inp->inp_ip6_minhlim;
    1427           0 :                                 break;
    1428             : 
    1429             :                         case IPV6_RECVPKTINFO:
    1430           0 :                                 optval = OPTBIT(IN6P_PKTINFO);
    1431           0 :                                 break;
    1432             : 
    1433             :                         case IPV6_RECVHOPLIMIT:
    1434           0 :                                 optval = OPTBIT(IN6P_HOPLIMIT);
    1435           0 :                                 break;
    1436             : 
    1437             :                         case IPV6_RECVRTHDR:
    1438           0 :                                 optval = OPTBIT(IN6P_RTHDR);
    1439           0 :                                 break;
    1440             : 
    1441             :                         case IPV6_RECVPATHMTU:
    1442           0 :                                 optval = OPTBIT(IN6P_MTU);
    1443           0 :                                 break;
    1444             : 
    1445             :                         case IPV6_V6ONLY:
    1446           0 :                                 optval = 1;
    1447           0 :                                 break;
    1448             : 
    1449             :                         case IPV6_PORTRANGE:
    1450             :                             {
    1451             :                                 int flags;
    1452           0 :                                 flags = inp->inp_flags;
    1453           0 :                                 if (flags & IN6P_HIGHPORT)
    1454           0 :                                         optval = IPV6_PORTRANGE_HIGH;
    1455           0 :                                 else if (flags & IN6P_LOWPORT)
    1456           0 :                                         optval = IPV6_PORTRANGE_LOW;
    1457             :                                 else
    1458           0 :                                         optval = 0;
    1459             :                                 break;
    1460             :                             }
    1461             :                         case IPV6_RECVTCLASS:
    1462           0 :                                 optval = OPTBIT(IN6P_TCLASS);
    1463           0 :                                 break;
    1464             : 
    1465             :                         case IPV6_AUTOFLOWLABEL:
    1466           0 :                                 optval = OPTBIT(IN6P_AUTOFLOWLABEL);
    1467           0 :                                 break;
    1468             : 
    1469             :                         case IPV6_RECVDSTPORT:
    1470           0 :                                 optval = OPTBIT(IN6P_RECVDSTPORT);
    1471           0 :                                 break;
    1472             :                         }
    1473           0 :                         if (error)
    1474             :                                 break;
    1475           0 :                         m->m_len = sizeof(int);
    1476           0 :                         *mtod(m, int *) = optval;
    1477           0 :                         break;
    1478             : 
    1479             :                 case IPV6_PATHMTU:
    1480             :                 {
    1481           0 :                         u_long pmtu = 0;
    1482           0 :                         struct ip6_mtuinfo mtuinfo;
    1483             :                         struct ifnet *ifp;
    1484             :                         struct rtentry *rt;
    1485             : 
    1486           0 :                         if (!(so->so_state & SS_ISCONNECTED))
    1487           0 :                                 return (ENOTCONN);
    1488             : 
    1489           0 :                         rt = in_pcbrtentry(inp);
    1490           0 :                         if (!rtisvalid(rt))
    1491           0 :                                 return (EHOSTUNREACH);
    1492             : 
    1493           0 :                         ifp = if_get(rt->rt_ifidx);
    1494           0 :                         if (ifp == NULL)
    1495           0 :                                 return (EHOSTUNREACH);
    1496             :                         /*
    1497             :                          * XXX: we dot not consider the case of source
    1498             :                          * routing, or optional information to specify
    1499             :                          * the outgoing interface.
    1500             :                          */
    1501           0 :                         error = ip6_getpmtu(rt, ifp, &pmtu);
    1502           0 :                         if_put(ifp);
    1503           0 :                         if (error)
    1504           0 :                                 break;
    1505           0 :                         if (pmtu > IPV6_MAXPACKET)
    1506           0 :                                 pmtu = IPV6_MAXPACKET;
    1507             : 
    1508           0 :                         bzero(&mtuinfo, sizeof(mtuinfo));
    1509           0 :                         mtuinfo.ip6m_mtu = (u_int32_t)pmtu;
    1510             :                         optdata = (void *)&mtuinfo;
    1511             :                         optdatalen = sizeof(mtuinfo);
    1512           0 :                         if (optdatalen > MCLBYTES)
    1513           0 :                                 return (EMSGSIZE); /* XXX */
    1514           0 :                         if (optdatalen > MLEN)
    1515           0 :                                 MCLGET(m, M_WAIT);
    1516           0 :                         m->m_len = optdatalen;
    1517           0 :                         bcopy(optdata, mtod(m, void *), optdatalen);
    1518           0 :                         break;
    1519           0 :                 }
    1520             : 
    1521             :                 case IPV6_PKTINFO:
    1522             :                 case IPV6_HOPOPTS:
    1523             :                 case IPV6_RTHDR:
    1524             :                 case IPV6_DSTOPTS:
    1525             :                 case IPV6_RTHDRDSTOPTS:
    1526             :                 case IPV6_TCLASS:
    1527             :                 case IPV6_DONTFRAG:
    1528             :                 case IPV6_USE_MIN_MTU:
    1529           0 :                         error = ip6_getpcbopt(inp->inp_outputopts6,
    1530             :                             optname, m);
    1531           0 :                         break;
    1532             : 
    1533             :                 case IPV6_MULTICAST_IF:
    1534             :                 case IPV6_MULTICAST_HOPS:
    1535             :                 case IPV6_MULTICAST_LOOP:
    1536             :                 case IPV6_JOIN_GROUP:
    1537             :                 case IPV6_LEAVE_GROUP:
    1538           0 :                         error = ip6_getmoptions(optname,
    1539           0 :                             inp->inp_moptions6, m);
    1540           0 :                         break;
    1541             : 
    1542             :                 case IPSEC6_OUTSA:
    1543             :                         error = EINVAL;
    1544           0 :                         break;
    1545             : 
    1546             :                 case IPV6_AUTH_LEVEL:
    1547             :                 case IPV6_ESP_TRANS_LEVEL:
    1548             :                 case IPV6_ESP_NETWORK_LEVEL:
    1549             :                 case IPV6_IPCOMP_LEVEL:
    1550             : #ifndef IPSEC
    1551             :                         m->m_len = sizeof(int);
    1552             :                         *mtod(m, int *) = IPSEC_LEVEL_NONE;
    1553             : #else
    1554           0 :                         m->m_len = sizeof(int);
    1555           0 :                         switch (optname) {
    1556             :                         case IPV6_AUTH_LEVEL:
    1557           0 :                                 optval = inp->inp_seclevel[SL_AUTH];
    1558           0 :                                 break;
    1559             : 
    1560             :                         case IPV6_ESP_TRANS_LEVEL:
    1561           0 :                                 optval =
    1562           0 :                                     inp->inp_seclevel[SL_ESP_TRANS];
    1563           0 :                                 break;
    1564             : 
    1565             :                         case IPV6_ESP_NETWORK_LEVEL:
    1566           0 :                                 optval =
    1567           0 :                                     inp->inp_seclevel[SL_ESP_NETWORK];
    1568           0 :                                 break;
    1569             : 
    1570             :                         case IPV6_IPCOMP_LEVEL:
    1571           0 :                                 optval = inp->inp_seclevel[SL_IPCOMP];
    1572           0 :                                 break;
    1573             :                         }
    1574           0 :                         *mtod(m, int *) = optval;
    1575             : #endif
    1576           0 :                         break;
    1577             :                 case SO_RTABLE:
    1578           0 :                         m->m_len = sizeof(u_int);
    1579           0 :                         *mtod(m, u_int *) = optval;
    1580           0 :                         break;
    1581             :                 case IPV6_PIPEX:
    1582           0 :                         m->m_len = sizeof(int);
    1583           0 :                         *mtod(m, int *) = optval;
    1584           0 :                         break;
    1585             : 
    1586             :                 default:
    1587             :                         error = ENOPROTOOPT;
    1588           0 :                         break;
    1589             :                 }
    1590             :                 break;
    1591             :         }
    1592           0 :         return (error);
    1593           0 : }
    1594             : 
    1595             : int
    1596           0 : ip6_raw_ctloutput(int op, struct socket *so, int level, int optname,
    1597             :     struct mbuf *m)
    1598             : {
    1599             :         int error = 0, optval;
    1600             :         const int icmp6off = offsetof(struct icmp6_hdr, icmp6_cksum);
    1601           0 :         struct inpcb *inp = sotoinpcb(so);
    1602             : 
    1603           0 :         if (level != IPPROTO_IPV6)
    1604           0 :                 return (EINVAL);
    1605             : 
    1606           0 :         switch (optname) {
    1607             :         case IPV6_CHECKSUM:
    1608             :                 /*
    1609             :                  * For ICMPv6 sockets, no modification allowed for checksum
    1610             :                  * offset, permit "no change" values to help existing apps.
    1611             :                  *
    1612             :                  * RFC3542 says: "An attempt to set IPV6_CHECKSUM
    1613             :                  * for an ICMPv6 socket will fail."
    1614             :                  * The current behavior does not meet RFC3542.
    1615             :                  */
    1616           0 :                 switch (op) {
    1617             :                 case PRCO_SETOPT:
    1618           0 :                         if (m == NULL || m->m_len != sizeof(int)) {
    1619             :                                 error = EINVAL;
    1620           0 :                                 break;
    1621             :                         }
    1622           0 :                         optval = *mtod(m, int *);
    1623           0 :                         if ((optval % 2) != 0) {
    1624             :                                 /* the API assumes even offset values */
    1625             :                                 error = EINVAL;
    1626           0 :                         } else if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
    1627           0 :                                 if (optval != icmp6off)
    1628           0 :                                         error = EINVAL;
    1629             :                         } else
    1630           0 :                                 inp->inp_cksum6 = optval;
    1631             :                         break;
    1632             : 
    1633             :                 case PRCO_GETOPT:
    1634           0 :                         if (so->so_proto->pr_protocol == IPPROTO_ICMPV6)
    1635           0 :                                 optval = icmp6off;
    1636             :                         else
    1637           0 :                                 optval = inp->inp_cksum6;
    1638             : 
    1639           0 :                         m->m_len = sizeof(int);
    1640           0 :                         *mtod(m, int *) = optval;
    1641           0 :                         break;
    1642             : 
    1643             :                 default:
    1644             :                         error = EINVAL;
    1645           0 :                         break;
    1646             :                 }
    1647             :                 break;
    1648             : 
    1649             :         default:
    1650             :                 error = ENOPROTOOPT;
    1651           0 :                 break;
    1652             :         }
    1653             : 
    1654           0 :         return (error);
    1655           0 : }
    1656             : 
    1657             : /*
    1658             :  * initialize ip6_pktopts.  beware that there are non-zero default values in
    1659             :  * the struct.
    1660             :  */
    1661             : void
    1662           0 : ip6_initpktopts(struct ip6_pktopts *opt)
    1663             : {
    1664           0 :         bzero(opt, sizeof(*opt));
    1665           0 :         opt->ip6po_hlim = -1;        /* -1 means default hop limit */
    1666           0 :         opt->ip6po_tclass = -1;      /* -1 means default traffic class */
    1667           0 :         opt->ip6po_minmtu = IP6PO_MINMTU_MCASTONLY;
    1668           0 : }
    1669             : 
    1670             : int
    1671           0 : ip6_pcbopt(int optname, u_char *buf, int len, struct ip6_pktopts **pktopt,
    1672             :     int priv, int uproto)
    1673             : {
    1674             :         struct ip6_pktopts *opt;
    1675             : 
    1676           0 :         if (*pktopt == NULL) {
    1677           0 :                 *pktopt = malloc(sizeof(struct ip6_pktopts), M_IP6OPT,
    1678             :                     M_WAITOK);
    1679           0 :                 ip6_initpktopts(*pktopt);
    1680           0 :         }
    1681           0 :         opt = *pktopt;
    1682             : 
    1683           0 :         return (ip6_setpktopt(optname, buf, len, opt, priv, 1, uproto));
    1684             : }
    1685             : 
    1686             : int
    1687           0 : ip6_getpcbopt(struct ip6_pktopts *pktopt, int optname, struct mbuf *m)
    1688             : {
    1689             :         void *optdata = NULL;
    1690             :         int optdatalen = 0;
    1691             :         struct ip6_ext *ip6e;
    1692             :         int error = 0;
    1693           0 :         struct in6_pktinfo null_pktinfo;
    1694           0 :         int deftclass = 0, on;
    1695           0 :         int defminmtu = IP6PO_MINMTU_MCASTONLY;
    1696             : 
    1697           0 :         switch (optname) {
    1698             :         case IPV6_PKTINFO:
    1699           0 :                 if (pktopt && pktopt->ip6po_pktinfo)
    1700           0 :                         optdata = (void *)pktopt->ip6po_pktinfo;
    1701             :                 else {
    1702             :                         /* XXX: we don't have to do this every time... */
    1703           0 :                         bzero(&null_pktinfo, sizeof(null_pktinfo));
    1704             :                         optdata = (void *)&null_pktinfo;
    1705             :                 }
    1706             :                 optdatalen = sizeof(struct in6_pktinfo);
    1707           0 :                 break;
    1708             :         case IPV6_TCLASS:
    1709           0 :                 if (pktopt && pktopt->ip6po_tclass >= 0)
    1710           0 :                         optdata = (void *)&pktopt->ip6po_tclass;
    1711             :                 else
    1712             :                         optdata = (void *)&deftclass;
    1713             :                 optdatalen = sizeof(int);
    1714           0 :                 break;
    1715             :         case IPV6_HOPOPTS:
    1716           0 :                 if (pktopt && pktopt->ip6po_hbh) {
    1717           0 :                         optdata = (void *)pktopt->ip6po_hbh;
    1718           0 :                         ip6e = (struct ip6_ext *)pktopt->ip6po_hbh;
    1719           0 :                         optdatalen = (ip6e->ip6e_len + 1) << 3;
    1720           0 :                 }
    1721             :                 break;
    1722             :         case IPV6_RTHDR:
    1723           0 :                 if (pktopt && pktopt->ip6po_rthdr) {
    1724           0 :                         optdata = (void *)pktopt->ip6po_rthdr;
    1725           0 :                         ip6e = (struct ip6_ext *)pktopt->ip6po_rthdr;
    1726           0 :                         optdatalen = (ip6e->ip6e_len + 1) << 3;
    1727           0 :                 }
    1728             :                 break;
    1729             :         case IPV6_RTHDRDSTOPTS:
    1730           0 :                 if (pktopt && pktopt->ip6po_dest1) {
    1731           0 :                         optdata = (void *)pktopt->ip6po_dest1;
    1732           0 :                         ip6e = (struct ip6_ext *)pktopt->ip6po_dest1;
    1733           0 :                         optdatalen = (ip6e->ip6e_len + 1) << 3;
    1734           0 :                 }
    1735             :                 break;
    1736             :         case IPV6_DSTOPTS:
    1737           0 :                 if (pktopt && pktopt->ip6po_dest2) {
    1738           0 :                         optdata = (void *)pktopt->ip6po_dest2;
    1739           0 :                         ip6e = (struct ip6_ext *)pktopt->ip6po_dest2;
    1740           0 :                         optdatalen = (ip6e->ip6e_len + 1) << 3;
    1741           0 :                 }
    1742             :                 break;
    1743             :         case IPV6_USE_MIN_MTU:
    1744           0 :                 if (pktopt)
    1745           0 :                         optdata = (void *)&pktopt->ip6po_minmtu;
    1746             :                 else
    1747             :                         optdata = (void *)&defminmtu;
    1748             :                 optdatalen = sizeof(int);
    1749           0 :                 break;
    1750             :         case IPV6_DONTFRAG:
    1751           0 :                 if (pktopt && ((pktopt->ip6po_flags) & IP6PO_DONTFRAG))
    1752           0 :                         on = 1;
    1753             :                 else
    1754           0 :                         on = 0;
    1755             :                 optdata = (void *)&on;
    1756             :                 optdatalen = sizeof(on);
    1757           0 :                 break;
    1758             :         default:                /* should not happen */
    1759             : #ifdef DIAGNOSTIC
    1760           0 :                 panic("ip6_getpcbopt: unexpected option");
    1761             : #endif
    1762             :                 return (ENOPROTOOPT);
    1763             :         }
    1764             : 
    1765           0 :         if (optdatalen > MCLBYTES)
    1766           0 :                 return (EMSGSIZE); /* XXX */
    1767           0 :         if (optdatalen > MLEN)
    1768           0 :                 MCLGET(m, M_WAIT);
    1769           0 :         m->m_len = optdatalen;
    1770           0 :         if (optdatalen)
    1771           0 :                 bcopy(optdata, mtod(m, void *), optdatalen);
    1772             : 
    1773           0 :         return (error);
    1774           0 : }
    1775             : 
    1776             : void
    1777           0 : ip6_clearpktopts(struct ip6_pktopts *pktopt, int optname)
    1778             : {
    1779           0 :         if (optname == -1 || optname == IPV6_PKTINFO) {
    1780           0 :                 if (pktopt->ip6po_pktinfo)
    1781           0 :                         free(pktopt->ip6po_pktinfo, M_IP6OPT, 0);
    1782           0 :                 pktopt->ip6po_pktinfo = NULL;
    1783           0 :         }
    1784           0 :         if (optname == -1 || optname == IPV6_HOPLIMIT)
    1785           0 :                 pktopt->ip6po_hlim = -1;
    1786           0 :         if (optname == -1 || optname == IPV6_TCLASS)
    1787           0 :                 pktopt->ip6po_tclass = -1;
    1788           0 :         if (optname == -1 || optname == IPV6_HOPOPTS) {
    1789           0 :                 if (pktopt->ip6po_hbh)
    1790           0 :                         free(pktopt->ip6po_hbh, M_IP6OPT, 0);
    1791           0 :                 pktopt->ip6po_hbh = NULL;
    1792           0 :         }
    1793           0 :         if (optname == -1 || optname == IPV6_RTHDRDSTOPTS) {
    1794           0 :                 if (pktopt->ip6po_dest1)
    1795           0 :                         free(pktopt->ip6po_dest1, M_IP6OPT, 0);
    1796           0 :                 pktopt->ip6po_dest1 = NULL;
    1797           0 :         }
    1798           0 :         if (optname == -1 || optname == IPV6_RTHDR) {
    1799           0 :                 if (pktopt->ip6po_rhinfo.ip6po_rhi_rthdr)
    1800           0 :                         free(pktopt->ip6po_rhinfo.ip6po_rhi_rthdr, M_IP6OPT, 0);
    1801           0 :                 pktopt->ip6po_rhinfo.ip6po_rhi_rthdr = NULL;
    1802           0 :                 if (pktopt->ip6po_route.ro_rt) {
    1803           0 :                         rtfree(pktopt->ip6po_route.ro_rt);
    1804           0 :                         pktopt->ip6po_route.ro_rt = NULL;
    1805           0 :                 }
    1806             :         }
    1807           0 :         if (optname == -1 || optname == IPV6_DSTOPTS) {
    1808           0 :                 if (pktopt->ip6po_dest2)
    1809           0 :                         free(pktopt->ip6po_dest2, M_IP6OPT, 0);
    1810           0 :                 pktopt->ip6po_dest2 = NULL;
    1811           0 :         }
    1812           0 : }
    1813             : 
    1814             : #define PKTOPT_EXTHDRCPY(type) \
    1815             : do {\
    1816             :         if (src->type) {\
    1817             :                 size_t hlen = (((struct ip6_ext *)src->type)->ip6e_len + 1) << 3;\
    1818             :                 dst->type = malloc(hlen, M_IP6OPT, M_NOWAIT);\
    1819             :                 if (dst->type == NULL)\
    1820             :                         goto bad;\
    1821             :                 memcpy(dst->type, src->type, hlen);\
    1822             :         }\
    1823             : } while (/*CONSTCOND*/ 0)
    1824             : 
    1825             : int
    1826           0 : copypktopts(struct ip6_pktopts *dst, struct ip6_pktopts *src)
    1827             : {
    1828           0 :         dst->ip6po_hlim = src->ip6po_hlim;
    1829           0 :         dst->ip6po_tclass = src->ip6po_tclass;
    1830           0 :         dst->ip6po_flags = src->ip6po_flags;
    1831           0 :         if (src->ip6po_pktinfo) {
    1832           0 :                 dst->ip6po_pktinfo = malloc(sizeof(*dst->ip6po_pktinfo),
    1833             :                     M_IP6OPT, M_NOWAIT);
    1834           0 :                 if (dst->ip6po_pktinfo == NULL)
    1835             :                         goto bad;
    1836           0 :                 *dst->ip6po_pktinfo = *src->ip6po_pktinfo;
    1837           0 :         }
    1838           0 :         PKTOPT_EXTHDRCPY(ip6po_hbh);
    1839           0 :         PKTOPT_EXTHDRCPY(ip6po_dest1);
    1840           0 :         PKTOPT_EXTHDRCPY(ip6po_dest2);
    1841           0 :         PKTOPT_EXTHDRCPY(ip6po_rthdr); /* not copy the cached route */
    1842           0 :         return (0);
    1843             : 
    1844             :   bad:
    1845           0 :         ip6_clearpktopts(dst, -1);
    1846           0 :         return (ENOBUFS);
    1847           0 : }
    1848             : #undef PKTOPT_EXTHDRCPY
    1849             : 
    1850             : void
    1851           0 : ip6_freepcbopts(struct ip6_pktopts *pktopt)
    1852             : {
    1853           0 :         if (pktopt == NULL)
    1854             :                 return;
    1855             : 
    1856           0 :         ip6_clearpktopts(pktopt, -1);
    1857             : 
    1858           0 :         free(pktopt, M_IP6OPT, 0);
    1859           0 : }
    1860             : 
    1861             : /*
    1862             :  * Set the IP6 multicast options in response to user setsockopt().
    1863             :  */
    1864             : int
    1865           0 : ip6_setmoptions(int optname, struct ip6_moptions **im6op, struct mbuf *m,
    1866             :     unsigned int rtableid)
    1867             : {
    1868           0 :         int error = 0;
    1869             :         u_int loop, ifindex;
    1870             :         struct ipv6_mreq *mreq;
    1871             :         struct ifnet *ifp;
    1872           0 :         struct ip6_moptions *im6o = *im6op;
    1873             :         struct in6_multi_mship *imm;
    1874           0 :         struct proc *p = curproc;       /* XXX */
    1875             : 
    1876           0 :         if (im6o == NULL) {
    1877             :                 /*
    1878             :                  * No multicast option buffer attached to the pcb;
    1879             :                  * allocate one and initialize to default values.
    1880             :                  */
    1881           0 :                 im6o = (struct ip6_moptions *)
    1882           0 :                         malloc(sizeof(*im6o), M_IPMOPTS, M_WAITOK);
    1883             : 
    1884           0 :                 if (im6o == NULL)
    1885           0 :                         return (ENOBUFS);
    1886           0 :                 *im6op = im6o;
    1887           0 :                 im6o->im6o_ifidx = 0;
    1888           0 :                 im6o->im6o_hlim = ip6_defmcasthlim;
    1889           0 :                 im6o->im6o_loop = IPV6_DEFAULT_MULTICAST_LOOP;
    1890           0 :                 LIST_INIT(&im6o->im6o_memberships);
    1891           0 :         }
    1892             : 
    1893           0 :         switch (optname) {
    1894             : 
    1895             :         case IPV6_MULTICAST_IF:
    1896             :                 /*
    1897             :                  * Select the interface for outgoing multicast packets.
    1898             :                  */
    1899           0 :                 if (m == NULL || m->m_len != sizeof(u_int)) {
    1900           0 :                         error = EINVAL;
    1901           0 :                         break;
    1902             :                 }
    1903           0 :                 memcpy(&ifindex, mtod(m, u_int *), sizeof(ifindex));
    1904           0 :                 if (ifindex != 0) {
    1905           0 :                         ifp = if_get(ifindex);
    1906           0 :                         if (ifp == NULL) {
    1907           0 :                                 error = ENXIO;  /* XXX EINVAL? */
    1908           0 :                                 break;
    1909             :                         }
    1910           0 :                         if ((ifp->if_flags & IFF_MULTICAST) == 0) {
    1911           0 :                                 error = EADDRNOTAVAIL;
    1912           0 :                                 if_put(ifp);
    1913           0 :                                 break;
    1914             :                         }
    1915           0 :                         if_put(ifp);
    1916           0 :                 }
    1917           0 :                 im6o->im6o_ifidx = ifindex;
    1918           0 :                 break;
    1919             : 
    1920             :         case IPV6_MULTICAST_HOPS:
    1921             :             {
    1922             :                 /*
    1923             :                  * Set the IP6 hoplimit for outgoing multicast packets.
    1924             :                  */
    1925             :                 int optval;
    1926           0 :                 if (m == NULL || m->m_len != sizeof(int)) {
    1927           0 :                         error = EINVAL;
    1928           0 :                         break;
    1929             :                 }
    1930           0 :                 memcpy(&optval, mtod(m, u_int *), sizeof(optval));
    1931           0 :                 if (optval < -1 || optval >= 256)
    1932           0 :                         error = EINVAL;
    1933           0 :                 else if (optval == -1)
    1934           0 :                         im6o->im6o_hlim = ip6_defmcasthlim;
    1935             :                 else
    1936           0 :                         im6o->im6o_hlim = optval;
    1937           0 :                 break;
    1938             :             }
    1939             : 
    1940             :         case IPV6_MULTICAST_LOOP:
    1941             :                 /*
    1942             :                  * Set the loopback flag for outgoing multicast packets.
    1943             :                  * Must be zero or one.
    1944             :                  */
    1945           0 :                 if (m == NULL || m->m_len != sizeof(u_int)) {
    1946           0 :                         error = EINVAL;
    1947           0 :                         break;
    1948             :                 }
    1949           0 :                 memcpy(&loop, mtod(m, u_int *), sizeof(loop));
    1950           0 :                 if (loop > 1) {
    1951           0 :                         error = EINVAL;
    1952           0 :                         break;
    1953             :                 }
    1954           0 :                 im6o->im6o_loop = loop;
    1955           0 :                 break;
    1956             : 
    1957             :         case IPV6_JOIN_GROUP:
    1958             :                 /*
    1959             :                  * Add a multicast group membership.
    1960             :                  * Group must be a valid IP6 multicast address.
    1961             :                  */
    1962           0 :                 if (m == NULL || m->m_len != sizeof(struct ipv6_mreq)) {
    1963           0 :                         error = EINVAL;
    1964           0 :                         break;
    1965             :                 }
    1966           0 :                 mreq = mtod(m, struct ipv6_mreq *);
    1967           0 :                 if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) {
    1968             :                         /*
    1969             :                          * We use the unspecified address to specify to accept
    1970             :                          * all multicast addresses. Only super user is allowed
    1971             :                          * to do this.
    1972             :                          */
    1973           0 :                         if (suser(p))
    1974             :                         {
    1975           0 :                                 error = EACCES;
    1976           0 :                                 break;
    1977             :                         }
    1978           0 :                 } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) {
    1979           0 :                         error = EINVAL;
    1980           0 :                         break;
    1981             :                 }
    1982             : 
    1983             :                 /*
    1984             :                  * If no interface was explicitly specified, choose an
    1985             :                  * appropriate one according to the given multicast address.
    1986             :                  */
    1987           0 :                 if (mreq->ipv6mr_interface == 0) {
    1988             :                         struct rtentry *rt;
    1989           0 :                         struct sockaddr_in6 dst;
    1990             : 
    1991           0 :                         memset(&dst, 0, sizeof(dst));
    1992           0 :                         dst.sin6_len = sizeof(dst);
    1993           0 :                         dst.sin6_family = AF_INET6;
    1994           0 :                         dst.sin6_addr = mreq->ipv6mr_multiaddr;
    1995           0 :                         rt = rtalloc(sin6tosa(&dst), RT_RESOLVE, rtableid);
    1996           0 :                         if (rt == NULL) {
    1997           0 :                                 error = EADDRNOTAVAIL;
    1998           0 :                                 break;
    1999             :                         }
    2000           0 :                         ifp = if_get(rt->rt_ifidx);
    2001           0 :                         rtfree(rt);
    2002           0 :                 } else {
    2003             :                         /*
    2004             :                          * If the interface is specified, validate it.
    2005             :                          */
    2006           0 :                         ifp = if_get(mreq->ipv6mr_interface);
    2007           0 :                         if (ifp == NULL) {
    2008           0 :                                 error = ENXIO;  /* XXX EINVAL? */
    2009           0 :                                 break;
    2010             :                         }
    2011             :                 }
    2012             : 
    2013             :                 /*
    2014             :                  * See if we found an interface, and confirm that it
    2015             :                  * supports multicast
    2016             :                  */
    2017           0 :                 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
    2018           0 :                         if_put(ifp);
    2019           0 :                         error = EADDRNOTAVAIL;
    2020           0 :                         break;
    2021             :                 }
    2022             :                 /*
    2023             :                  * Put interface index into the multicast address,
    2024             :                  * if the address has link/interface-local scope.
    2025             :                  */
    2026           0 :                 if (IN6_IS_SCOPE_EMBED(&mreq->ipv6mr_multiaddr)) {
    2027           0 :                         mreq->ipv6mr_multiaddr.s6_addr16[1] =
    2028           0 :                             htons(ifp->if_index);
    2029           0 :                 }
    2030             :                 /*
    2031             :                  * See if the membership already exists.
    2032             :                  */
    2033           0 :                 LIST_FOREACH(imm, &im6o->im6o_memberships, i6mm_chain)
    2034           0 :                         if (imm->i6mm_maddr->in6m_ifidx == ifp->if_index &&
    2035           0 :                             IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
    2036             :                             &mreq->ipv6mr_multiaddr))
    2037             :                                 break;
    2038           0 :                 if (imm != NULL) {
    2039           0 :                         if_put(ifp);
    2040           0 :                         error = EADDRINUSE;
    2041           0 :                         break;
    2042             :                 }
    2043             :                 /*
    2044             :                  * Everything looks good; add a new record to the multicast
    2045             :                  * address list for the given interface.
    2046             :                  */
    2047           0 :                 imm = in6_joingroup(ifp, &mreq->ipv6mr_multiaddr, &error);
    2048           0 :                 if_put(ifp);
    2049           0 :                 if (!imm)
    2050             :                         break;
    2051           0 :                 LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain);
    2052           0 :                 break;
    2053             : 
    2054             :         case IPV6_LEAVE_GROUP:
    2055             :                 /*
    2056             :                  * Drop a multicast group membership.
    2057             :                  * Group must be a valid IP6 multicast address.
    2058             :                  */
    2059           0 :                 if (m == NULL || m->m_len != sizeof(struct ipv6_mreq)) {
    2060           0 :                         error = EINVAL;
    2061           0 :                         break;
    2062             :                 }
    2063           0 :                 mreq = mtod(m, struct ipv6_mreq *);
    2064           0 :                 if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) {
    2065           0 :                         if (suser(p))
    2066             :                         {
    2067           0 :                                 error = EACCES;
    2068           0 :                                 break;
    2069             :                         }
    2070           0 :                 } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) {
    2071           0 :                         error = EINVAL;
    2072           0 :                         break;
    2073             :                 }
    2074             : 
    2075             :                 /*
    2076             :                  * Put interface index into the multicast address,
    2077             :                  * if the address has link-local scope.
    2078             :                  */
    2079           0 :                 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)) {
    2080           0 :                         mreq->ipv6mr_multiaddr.s6_addr16[1] =
    2081           0 :                             htons(mreq->ipv6mr_interface);
    2082           0 :                 }
    2083             : 
    2084             :                 /*
    2085             :                  * If an interface address was specified, get a pointer
    2086             :                  * to its ifnet structure.
    2087             :                  */
    2088           0 :                 if (mreq->ipv6mr_interface == 0)
    2089           0 :                         ifp = NULL;
    2090             :                 else {
    2091           0 :                         ifp = if_get(mreq->ipv6mr_interface);
    2092           0 :                         if (ifp == NULL) {
    2093           0 :                                 error = ENXIO;  /* XXX EINVAL? */
    2094           0 :                                 break;
    2095             :                         }
    2096             :                 }
    2097             : 
    2098             :                 /*
    2099             :                  * Find the membership in the membership list.
    2100             :                  */
    2101           0 :                 LIST_FOREACH(imm, &im6o->im6o_memberships, i6mm_chain) {
    2102           0 :                         if ((ifp == NULL ||
    2103           0 :                             imm->i6mm_maddr->in6m_ifidx == ifp->if_index) &&
    2104           0 :                             IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
    2105             :                             &mreq->ipv6mr_multiaddr))
    2106             :                                 break;
    2107             :                 }
    2108             : 
    2109           0 :                 if_put(ifp);
    2110             : 
    2111           0 :                 if (imm == NULL) {
    2112             :                         /* Unable to resolve interface */
    2113           0 :                         error = EADDRNOTAVAIL;
    2114           0 :                         break;
    2115             :                 }
    2116             :                 /*
    2117             :                  * Give up the multicast address record to which the
    2118             :                  * membership points.
    2119             :                  */
    2120           0 :                 LIST_REMOVE(imm, i6mm_chain);
    2121           0 :                 in6_leavegroup(imm);
    2122           0 :                 break;
    2123             : 
    2124             :         default:
    2125           0 :                 error = EOPNOTSUPP;
    2126           0 :                 break;
    2127             :         }
    2128             : 
    2129             :         /*
    2130             :          * If all options have default values, no need to keep the option
    2131             :          * structure.
    2132             :          */
    2133           0 :         if (im6o->im6o_ifidx == 0 &&
    2134           0 :             im6o->im6o_hlim == ip6_defmcasthlim &&
    2135           0 :             im6o->im6o_loop == IPV6_DEFAULT_MULTICAST_LOOP &&
    2136           0 :             LIST_EMPTY(&im6o->im6o_memberships)) {
    2137           0 :                 free(*im6op, M_IPMOPTS, 0);
    2138           0 :                 *im6op = NULL;
    2139           0 :         }
    2140             : 
    2141           0 :         return (error);
    2142           0 : }
    2143             : 
    2144             : /*
    2145             :  * Return the IP6 multicast options in response to user getsockopt().
    2146             :  */
    2147             : int
    2148           0 : ip6_getmoptions(int optname, struct ip6_moptions *im6o, struct mbuf *m)
    2149             : {
    2150             :         u_int *hlim, *loop, *ifindex;
    2151             : 
    2152           0 :         switch (optname) {
    2153             :         case IPV6_MULTICAST_IF:
    2154           0 :                 ifindex = mtod(m, u_int *);
    2155           0 :                 m->m_len = sizeof(u_int);
    2156           0 :                 if (im6o == NULL || im6o->im6o_ifidx == 0)
    2157           0 :                         *ifindex = 0;
    2158             :                 else
    2159           0 :                         *ifindex = im6o->im6o_ifidx;
    2160           0 :                 return (0);
    2161             : 
    2162             :         case IPV6_MULTICAST_HOPS:
    2163           0 :                 hlim = mtod(m, u_int *);
    2164           0 :                 m->m_len = sizeof(u_int);
    2165           0 :                 if (im6o == NULL)
    2166           0 :                         *hlim = ip6_defmcasthlim;
    2167             :                 else
    2168           0 :                         *hlim = im6o->im6o_hlim;
    2169           0 :                 return (0);
    2170             : 
    2171             :         case IPV6_MULTICAST_LOOP:
    2172           0 :                 loop = mtod(m, u_int *);
    2173           0 :                 m->m_len = sizeof(u_int);
    2174           0 :                 if (im6o == NULL)
    2175           0 :                         *loop = ip6_defmcasthlim;
    2176             :                 else
    2177           0 :                         *loop = im6o->im6o_loop;
    2178           0 :                 return (0);
    2179             : 
    2180             :         default:
    2181           0 :                 return (EOPNOTSUPP);
    2182             :         }
    2183           0 : }
    2184             : 
    2185             : /*
    2186             :  * Discard the IP6 multicast options.
    2187             :  */
    2188             : void
    2189           0 : ip6_freemoptions(struct ip6_moptions *im6o)
    2190             : {
    2191             :         struct in6_multi_mship *imm;
    2192             : 
    2193           0 :         if (im6o == NULL)
    2194           0 :                 return;
    2195             : 
    2196           0 :         while (!LIST_EMPTY(&im6o->im6o_memberships)) {
    2197             :                 imm = LIST_FIRST(&im6o->im6o_memberships);
    2198           0 :                 LIST_REMOVE(imm, i6mm_chain);
    2199           0 :                 in6_leavegroup(imm);
    2200             :         }
    2201           0 :         free(im6o, M_IPMOPTS, 0);
    2202           0 : }
    2203             : 
    2204             : /*
    2205             :  * Set IPv6 outgoing packet options based on advanced API.
    2206             :  */
    2207             : int
    2208           0 : ip6_setpktopts(struct mbuf *control, struct ip6_pktopts *opt,
    2209             :     struct ip6_pktopts *stickyopt, int priv, int uproto)
    2210             : {
    2211             :         u_int clen;
    2212             :         struct cmsghdr *cm = 0;
    2213             :         caddr_t cmsgs;
    2214             :         int error;
    2215             : 
    2216           0 :         if (control == NULL || opt == NULL)
    2217           0 :                 return (EINVAL);
    2218             : 
    2219           0 :         ip6_initpktopts(opt);
    2220           0 :         if (stickyopt) {
    2221             :                 int error;
    2222             : 
    2223             :                 /*
    2224             :                  * If stickyopt is provided, make a local copy of the options
    2225             :                  * for this particular packet, then override them by ancillary
    2226             :                  * objects.
    2227             :                  * XXX: copypktopts() does not copy the cached route to a next
    2228             :                  * hop (if any).  This is not very good in terms of efficiency,
    2229             :                  * but we can allow this since this option should be rarely
    2230             :                  * used.
    2231             :                  */
    2232           0 :                 if ((error = copypktopts(opt, stickyopt)) != 0)
    2233           0 :                         return (error);
    2234           0 :         }
    2235             : 
    2236             :         /*
    2237             :          * XXX: Currently, we assume all the optional information is stored
    2238             :          * in a single mbuf.
    2239             :          */
    2240           0 :         if (control->m_next)
    2241           0 :                 return (EINVAL);
    2242             : 
    2243           0 :         clen = control->m_len;
    2244           0 :         cmsgs = mtod(control, caddr_t);
    2245           0 :         do {
    2246           0 :                 if (clen < CMSG_LEN(0))
    2247           0 :                         return (EINVAL);
    2248           0 :                 cm = (struct cmsghdr *)cmsgs;
    2249           0 :                 if (cm->cmsg_len < CMSG_LEN(0) || cm->cmsg_len > clen ||
    2250           0 :                     CMSG_ALIGN(cm->cmsg_len) > clen)
    2251           0 :                         return (EINVAL);
    2252           0 :                 if (cm->cmsg_level == IPPROTO_IPV6) {
    2253           0 :                         error = ip6_setpktopt(cm->cmsg_type, CMSG_DATA(cm),
    2254           0 :                             cm->cmsg_len - CMSG_LEN(0), opt, priv, 0, uproto);
    2255           0 :                         if (error)
    2256           0 :                                 return (error);
    2257             :                 }
    2258             : 
    2259           0 :                 clen -= CMSG_ALIGN(cm->cmsg_len);
    2260           0 :                 cmsgs += CMSG_ALIGN(cm->cmsg_len);
    2261           0 :         } while (clen);
    2262             : 
    2263           0 :         return (0);
    2264           0 : }
    2265             : 
    2266             : /*
    2267             :  * Set a particular packet option, as a sticky option or an ancillary data
    2268             :  * item.  "len" can be 0 only when it's a sticky option.
    2269             :  */
    2270             : int
    2271           0 : ip6_setpktopt(int optname, u_char *buf, int len, struct ip6_pktopts *opt,
    2272             :     int priv, int sticky, int uproto)
    2273             : {
    2274             :         int minmtupolicy;
    2275             : 
    2276           0 :         switch (optname) {
    2277             :         case IPV6_PKTINFO:
    2278             :         {
    2279             :                 struct ifnet *ifp = NULL;
    2280             :                 struct in6_pktinfo *pktinfo;
    2281             : 
    2282           0 :                 if (len != sizeof(struct in6_pktinfo))
    2283           0 :                         return (EINVAL);
    2284             : 
    2285           0 :                 pktinfo = (struct in6_pktinfo *)buf;
    2286             : 
    2287             :                 /*
    2288             :                  * An application can clear any sticky IPV6_PKTINFO option by
    2289             :                  * doing a "regular" setsockopt with ipi6_addr being
    2290             :                  * in6addr_any and ipi6_ifindex being zero.
    2291             :                  * [RFC 3542, Section 6]
    2292             :                  */
    2293           0 :                 if (opt->ip6po_pktinfo &&
    2294           0 :                     pktinfo->ipi6_ifindex == 0 &&
    2295           0 :                     IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) {
    2296           0 :                         ip6_clearpktopts(opt, optname);
    2297           0 :                         break;
    2298             :                 }
    2299             : 
    2300           0 :                 if (uproto == IPPROTO_TCP &&
    2301           0 :                     sticky && !IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) {
    2302           0 :                         return (EINVAL);
    2303             :                 }
    2304             : 
    2305           0 :                 if (pktinfo->ipi6_ifindex) {
    2306           0 :                         ifp = if_get(pktinfo->ipi6_ifindex);
    2307           0 :                         if (ifp == NULL)
    2308           0 :                                 return (ENXIO);
    2309           0 :                         if_put(ifp);
    2310           0 :                 }
    2311             : 
    2312             :                 /*
    2313             :                  * We store the address anyway, and let in6_selectsrc()
    2314             :                  * validate the specified address.  This is because ipi6_addr
    2315             :                  * may not have enough information about its scope zone, and
    2316             :                  * we may need additional information (such as outgoing
    2317             :                  * interface or the scope zone of a destination address) to
    2318             :                  * disambiguate the scope.
    2319             :                  * XXX: the delay of the validation may confuse the
    2320             :                  * application when it is used as a sticky option.
    2321             :                  */
    2322           0 :                 if (opt->ip6po_pktinfo == NULL) {
    2323           0 :                         opt->ip6po_pktinfo = malloc(sizeof(*pktinfo),
    2324             :                             M_IP6OPT, M_NOWAIT);
    2325           0 :                         if (opt->ip6po_pktinfo == NULL)
    2326           0 :                                 return (ENOBUFS);
    2327             :                 }
    2328           0 :                 bcopy(pktinfo, opt->ip6po_pktinfo, sizeof(*pktinfo));
    2329           0 :                 break;
    2330             :         }
    2331             : 
    2332             :         case IPV6_HOPLIMIT:
    2333             :         {
    2334             :                 int *hlimp;
    2335             : 
    2336             :                 /*
    2337             :                  * RFC 3542 deprecated the usage of sticky IPV6_HOPLIMIT
    2338             :                  * to simplify the ordering among hoplimit options.
    2339             :                  */
    2340           0 :                 if (sticky)
    2341           0 :                         return (ENOPROTOOPT);
    2342             : 
    2343           0 :                 if (len != sizeof(int))
    2344           0 :                         return (EINVAL);
    2345           0 :                 hlimp = (int *)buf;
    2346           0 :                 if (*hlimp < -1 || *hlimp > 255)
    2347           0 :                         return (EINVAL);
    2348             : 
    2349           0 :                 opt->ip6po_hlim = *hlimp;
    2350           0 :                 break;
    2351             :         }
    2352             : 
    2353             :         case IPV6_TCLASS:
    2354             :         {
    2355             :                 int tclass;
    2356             : 
    2357           0 :                 if (len != sizeof(int))
    2358           0 :                         return (EINVAL);
    2359           0 :                 tclass = *(int *)buf;
    2360           0 :                 if (tclass < -1 || tclass > 255)
    2361           0 :                         return (EINVAL);
    2362             : 
    2363           0 :                 opt->ip6po_tclass = tclass;
    2364           0 :                 break;
    2365             :         }
    2366             :         case IPV6_HOPOPTS:
    2367             :         {
    2368             :                 struct ip6_hbh *hbh;
    2369             :                 int hbhlen;
    2370             : 
    2371             :                 /*
    2372             :                  * XXX: We don't allow a non-privileged user to set ANY HbH
    2373             :                  * options, since per-option restriction has too much
    2374             :                  * overhead.
    2375             :                  */
    2376           0 :                 if (!priv)
    2377           0 :                         return (EPERM);
    2378             : 
    2379           0 :                 if (len == 0) {
    2380           0 :                         ip6_clearpktopts(opt, IPV6_HOPOPTS);
    2381           0 :                         break;  /* just remove the option */
    2382             :                 }
    2383             : 
    2384             :                 /* message length validation */
    2385           0 :                 if (len < sizeof(struct ip6_hbh))
    2386           0 :                         return (EINVAL);
    2387           0 :                 hbh = (struct ip6_hbh *)buf;
    2388           0 :                 hbhlen = (hbh->ip6h_len + 1) << 3;
    2389           0 :                 if (len != hbhlen)
    2390           0 :                         return (EINVAL);
    2391             : 
    2392             :                 /* turn off the previous option, then set the new option. */
    2393           0 :                 ip6_clearpktopts(opt, IPV6_HOPOPTS);
    2394           0 :                 opt->ip6po_hbh = malloc(hbhlen, M_IP6OPT, M_NOWAIT);
    2395           0 :                 if (opt->ip6po_hbh == NULL)
    2396           0 :                         return (ENOBUFS);
    2397           0 :                 memcpy(opt->ip6po_hbh, hbh, hbhlen);
    2398             : 
    2399           0 :                 break;
    2400             :         }
    2401             : 
    2402             :         case IPV6_DSTOPTS:
    2403             :         case IPV6_RTHDRDSTOPTS:
    2404             :         {
    2405             :                 struct ip6_dest *dest, **newdest = NULL;
    2406             :                 int destlen;
    2407             : 
    2408           0 :                 if (!priv)      /* XXX: see the comment for IPV6_HOPOPTS */
    2409           0 :                         return (EPERM);
    2410             : 
    2411           0 :                 if (len == 0) {
    2412           0 :                         ip6_clearpktopts(opt, optname);
    2413           0 :                         break;  /* just remove the option */
    2414             :                 }
    2415             : 
    2416             :                 /* message length validation */
    2417           0 :                 if (len < sizeof(struct ip6_dest))
    2418           0 :                         return (EINVAL);
    2419           0 :                 dest = (struct ip6_dest *)buf;
    2420           0 :                 destlen = (dest->ip6d_len + 1) << 3;
    2421           0 :                 if (len != destlen)
    2422           0 :                         return (EINVAL);
    2423             :                 /*
    2424             :                  * Determine the position that the destination options header
    2425             :                  * should be inserted; before or after the routing header.
    2426             :                  */
    2427           0 :                 switch (optname) {
    2428             :                 case IPV6_RTHDRDSTOPTS:
    2429           0 :                         newdest = &opt->ip6po_dest1;
    2430           0 :                         break;
    2431             :                 case IPV6_DSTOPTS:
    2432           0 :                         newdest = &opt->ip6po_dest2;
    2433           0 :                         break;
    2434             :                 }
    2435             : 
    2436             :                 /* turn off the previous option, then set the new option. */
    2437           0 :                 ip6_clearpktopts(opt, optname);
    2438           0 :                 *newdest = malloc(destlen, M_IP6OPT, M_NOWAIT);
    2439           0 :                 if (*newdest == NULL)
    2440           0 :                         return (ENOBUFS);
    2441           0 :                 memcpy(*newdest, dest, destlen);
    2442             : 
    2443           0 :                 break;
    2444             :         }
    2445             : 
    2446             :         case IPV6_RTHDR:
    2447             :         {
    2448             :                 struct ip6_rthdr *rth;
    2449             :                 int rthlen;
    2450             : 
    2451           0 :                 if (len == 0) {
    2452           0 :                         ip6_clearpktopts(opt, IPV6_RTHDR);
    2453           0 :                         break;  /* just remove the option */
    2454             :                 }
    2455             : 
    2456             :                 /* message length validation */
    2457           0 :                 if (len < sizeof(struct ip6_rthdr))
    2458           0 :                         return (EINVAL);
    2459           0 :                 rth = (struct ip6_rthdr *)buf;
    2460           0 :                 rthlen = (rth->ip6r_len + 1) << 3;
    2461           0 :                 if (len != rthlen)
    2462           0 :                         return (EINVAL);
    2463             : 
    2464           0 :                 switch (rth->ip6r_type) {
    2465             :                 case IPV6_RTHDR_TYPE_0:
    2466           0 :                         if (rth->ip6r_len == 0)      /* must contain one addr */
    2467           0 :                                 return (EINVAL);
    2468           0 :                         if (rth->ip6r_len % 2) /* length must be even */
    2469           0 :                                 return (EINVAL);
    2470           0 :                         if (rth->ip6r_len / 2 != rth->ip6r_segleft)
    2471           0 :                                 return (EINVAL);
    2472             :                         break;
    2473             :                 default:
    2474           0 :                         return (EINVAL);        /* not supported */
    2475             :                 }
    2476             :                 /* turn off the previous option */
    2477           0 :                 ip6_clearpktopts(opt, IPV6_RTHDR);
    2478           0 :                 opt->ip6po_rthdr = malloc(rthlen, M_IP6OPT, M_NOWAIT);
    2479           0 :                 if (opt->ip6po_rthdr == NULL)
    2480           0 :                         return (ENOBUFS);
    2481           0 :                 memcpy(opt->ip6po_rthdr, rth, rthlen);
    2482           0 :                 break;
    2483             :         }
    2484             : 
    2485             :         case IPV6_USE_MIN_MTU:
    2486           0 :                 if (len != sizeof(int))
    2487           0 :                         return (EINVAL);
    2488           0 :                 minmtupolicy = *(int *)buf;
    2489           0 :                 if (minmtupolicy != IP6PO_MINMTU_MCASTONLY &&
    2490           0 :                     minmtupolicy != IP6PO_MINMTU_DISABLE &&
    2491           0 :                     minmtupolicy != IP6PO_MINMTU_ALL) {
    2492           0 :                         return (EINVAL);
    2493             :                 }
    2494           0 :                 opt->ip6po_minmtu = minmtupolicy;
    2495           0 :                 break;
    2496             : 
    2497             :         case IPV6_DONTFRAG:
    2498           0 :                 if (len != sizeof(int))
    2499           0 :                         return (EINVAL);
    2500             : 
    2501           0 :                 if (uproto == IPPROTO_TCP || *(int *)buf == 0) {
    2502             :                         /*
    2503             :                          * we ignore this option for TCP sockets.
    2504             :                          * (RFC3542 leaves this case unspecified.)
    2505             :                          */
    2506           0 :                         opt->ip6po_flags &= ~IP6PO_DONTFRAG;
    2507           0 :                 } else
    2508           0 :                         opt->ip6po_flags |= IP6PO_DONTFRAG;
    2509             :                 break;
    2510             : 
    2511             :         default:
    2512           0 :                 return (ENOPROTOOPT);
    2513             :         } /* end of switch */
    2514             : 
    2515           0 :         return (0);
    2516           0 : }
    2517             : 
    2518             : /*
    2519             :  * Routine called from ip6_output() to loop back a copy of an IP6 multicast
    2520             :  * packet to the input queue of a specified interface.
    2521             :  */
    2522             : void
    2523           0 : ip6_mloopback(struct ifnet *ifp, struct mbuf *m, struct sockaddr_in6 *dst)
    2524             : {
    2525             :         struct mbuf *copym;
    2526             :         struct ip6_hdr *ip6;
    2527             : 
    2528             :         /*
    2529             :          * Duplicate the packet.
    2530             :          */
    2531           0 :         copym = m_copym(m, 0, M_COPYALL, M_NOWAIT);
    2532           0 :         if (copym == NULL)
    2533           0 :                 return;
    2534             : 
    2535             :         /*
    2536             :          * Make sure to deep-copy IPv6 header portion in case the data
    2537             :          * is in an mbuf cluster, so that we can safely override the IPv6
    2538             :          * header portion later.
    2539             :          */
    2540           0 :         if ((copym->m_flags & M_EXT) != 0 ||
    2541           0 :             copym->m_len < sizeof(struct ip6_hdr)) {
    2542           0 :                 copym = m_pullup(copym, sizeof(struct ip6_hdr));
    2543           0 :                 if (copym == NULL)
    2544           0 :                         return;
    2545             :         }
    2546             : 
    2547             : #ifdef DIAGNOSTIC
    2548           0 :         if (copym->m_len < sizeof(*ip6)) {
    2549           0 :                 m_freem(copym);
    2550           0 :                 return;
    2551             :         }
    2552             : #endif
    2553             : 
    2554           0 :         ip6 = mtod(copym, struct ip6_hdr *);
    2555           0 :         if (IN6_IS_SCOPE_EMBED(&ip6->ip6_src))
    2556           0 :                 ip6->ip6_src.s6_addr16[1] = 0;
    2557           0 :         if (IN6_IS_SCOPE_EMBED(&ip6->ip6_dst))
    2558           0 :                 ip6->ip6_dst.s6_addr16[1] = 0;
    2559             : 
    2560           0 :         if_input_local(ifp, copym, dst->sin6_family);
    2561           0 : }
    2562             : 
    2563             : /*
    2564             :  * Chop IPv6 header off from the payload.
    2565             :  */
    2566             : int
    2567           0 : ip6_splithdr(struct mbuf *m, struct ip6_exthdrs *exthdrs)
    2568             : {
    2569             :         struct mbuf *mh;
    2570             :         struct ip6_hdr *ip6;
    2571             : 
    2572           0 :         ip6 = mtod(m, struct ip6_hdr *);
    2573           0 :         if (m->m_len > sizeof(*ip6)) {
    2574           0 :                 MGETHDR(mh, M_DONTWAIT, MT_HEADER);
    2575           0 :                 if (mh == NULL) {
    2576           0 :                         m_freem(m);
    2577           0 :                         return ENOBUFS;
    2578             :                 }
    2579           0 :                 M_MOVE_PKTHDR(mh, m);
    2580           0 :                 MH_ALIGN(mh, sizeof(*ip6));
    2581           0 :                 m->m_len -= sizeof(*ip6);
    2582           0 :                 m->m_data += sizeof(*ip6);
    2583           0 :                 mh->m_next = m;
    2584             :                 m = mh;
    2585           0 :                 m->m_len = sizeof(*ip6);
    2586           0 :                 bcopy((caddr_t)ip6, mtod(m, caddr_t), sizeof(*ip6));
    2587           0 :         }
    2588           0 :         exthdrs->ip6e_ip6 = m;
    2589           0 :         return 0;
    2590           0 : }
    2591             : 
    2592             : u_int32_t
    2593           0 : ip6_randomid(void)
    2594             : {
    2595           0 :         return idgen32(&ip6_id_ctx);
    2596             : }
    2597             : 
    2598             : void
    2599           0 : ip6_randomid_init(void)
    2600             : {
    2601           0 :         idgen32_init(&ip6_id_ctx);
    2602           0 : }
    2603             : 
    2604             : /*
    2605             :  *      Compute significant parts of the IPv6 checksum pseudo-header
    2606             :  *      for use in a delayed TCP/UDP checksum calculation.
    2607             :  */
    2608             : static __inline u_int16_t __attribute__((__unused__))
    2609           0 : in6_cksum_phdr(const struct in6_addr *src, const struct in6_addr *dst,
    2610             :     u_int32_t len, u_int32_t nxt)
    2611             : {
    2612             :         u_int32_t sum = 0;
    2613             :         const u_int16_t *w;
    2614             : 
    2615           0 :         w = (const u_int16_t *) src;
    2616           0 :         sum += w[0];
    2617           0 :         if (!IN6_IS_SCOPE_EMBED(src))
    2618           0 :                 sum += w[1];
    2619           0 :         sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5];
    2620           0 :         sum += w[6]; sum += w[7];
    2621             : 
    2622           0 :         w = (const u_int16_t *) dst;
    2623           0 :         sum += w[0];
    2624           0 :         if (!IN6_IS_SCOPE_EMBED(dst))
    2625           0 :                 sum += w[1];
    2626           0 :         sum += w[2]; sum += w[3]; sum += w[4]; sum += w[5];
    2627           0 :         sum += w[6]; sum += w[7];
    2628             : 
    2629           0 :         sum += (u_int16_t)(len >> 16) + (u_int16_t)(len /*& 0xffff*/);
    2630             : 
    2631           0 :         sum += (u_int16_t)(nxt >> 16) + (u_int16_t)(nxt /*& 0xffff*/);
    2632             : 
    2633           0 :         sum = (u_int16_t)(sum >> 16) + (u_int16_t)(sum /*& 0xffff*/);
    2634             : 
    2635           0 :         if (sum > 0xffff)
    2636           0 :                 sum -= 0xffff;
    2637             : 
    2638           0 :         return (sum);
    2639             : }
    2640             : 
    2641             : /*
    2642             :  * Process a delayed payload checksum calculation.
    2643             :  */
    2644             : void
    2645           0 : in6_delayed_cksum(struct mbuf *m, u_int8_t nxt)
    2646             : {
    2647           0 :         int nxtp, offset;
    2648           0 :         u_int16_t csum;
    2649             : 
    2650           0 :         offset = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxtp);
    2651           0 :         if (offset <= 0 || nxtp != nxt)
    2652             :                 /* If the desired next protocol isn't found, punt. */
    2653           0 :                 return;
    2654           0 :         csum = (u_int16_t)(in6_cksum(m, 0, offset, m->m_pkthdr.len - offset));
    2655             : 
    2656           0 :         switch (nxt) {
    2657             :         case IPPROTO_TCP:
    2658           0 :                 offset += offsetof(struct tcphdr, th_sum);
    2659           0 :                 break;
    2660             : 
    2661             :         case IPPROTO_UDP:
    2662           0 :                 offset += offsetof(struct udphdr, uh_sum);
    2663           0 :                 if (csum == 0)
    2664           0 :                         csum = 0xffff;
    2665             :                 break;
    2666             : 
    2667             :         case IPPROTO_ICMPV6:
    2668           0 :                 offset += offsetof(struct icmp6_hdr, icmp6_cksum);
    2669           0 :                 break;
    2670             :         }
    2671             : 
    2672           0 :         if ((offset + sizeof(u_int16_t)) > m->m_len)
    2673           0 :                 m_copyback(m, offset, sizeof(csum), &csum, M_NOWAIT);
    2674             :         else
    2675           0 :                 *(u_int16_t *)(mtod(m, caddr_t) + offset) = csum;
    2676           0 : }
    2677             : 
    2678             : void
    2679           0 : in6_proto_cksum_out(struct mbuf *m, struct ifnet *ifp)
    2680             : {
    2681           0 :         struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
    2682             : 
    2683             :         /* some hw and in6_delayed_cksum need the pseudo header cksum */
    2684           0 :         if (m->m_pkthdr.csum_flags &
    2685             :             (M_TCP_CSUM_OUT|M_UDP_CSUM_OUT|M_ICMP_CSUM_OUT)) {
    2686           0 :                 int nxt, offset;
    2687           0 :                 u_int16_t csum;
    2688             : 
    2689           0 :                 offset = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
    2690           0 :                 csum = in6_cksum_phdr(&ip6->ip6_src, &ip6->ip6_dst,
    2691           0 :                     htonl(m->m_pkthdr.len - offset), htonl(nxt));
    2692           0 :                 if (nxt == IPPROTO_TCP)
    2693           0 :                         offset += offsetof(struct tcphdr, th_sum);
    2694           0 :                 else if (nxt == IPPROTO_UDP)
    2695           0 :                         offset += offsetof(struct udphdr, uh_sum);
    2696           0 :                 else if (nxt == IPPROTO_ICMPV6)
    2697           0 :                         offset += offsetof(struct icmp6_hdr, icmp6_cksum);
    2698           0 :                 if ((offset + sizeof(u_int16_t)) > m->m_len)
    2699           0 :                         m_copyback(m, offset, sizeof(csum), &csum, M_NOWAIT);
    2700             :                 else
    2701           0 :                         *(u_int16_t *)(mtod(m, caddr_t) + offset) = csum;
    2702           0 :         }
    2703             : 
    2704           0 :         if (m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT) {
    2705           0 :                 if (!ifp || !(ifp->if_capabilities & IFCAP_CSUM_TCPv6) ||
    2706           0 :                     ip6->ip6_nxt != IPPROTO_TCP ||
    2707           0 :                     ifp->if_bridgeport != NULL) {
    2708           0 :                         tcpstat_inc(tcps_outswcsum);
    2709           0 :                         in6_delayed_cksum(m, IPPROTO_TCP);
    2710           0 :                         m->m_pkthdr.csum_flags &= ~M_TCP_CSUM_OUT; /* Clear */
    2711           0 :                 }
    2712           0 :         } else if (m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT) {
    2713           0 :                 if (!ifp || !(ifp->if_capabilities & IFCAP_CSUM_UDPv6) ||
    2714           0 :                     ip6->ip6_nxt != IPPROTO_UDP ||
    2715           0 :                     ifp->if_bridgeport != NULL) {
    2716           0 :                         udpstat_inc(udps_outswcsum);
    2717           0 :                         in6_delayed_cksum(m, IPPROTO_UDP);
    2718           0 :                         m->m_pkthdr.csum_flags &= ~M_UDP_CSUM_OUT; /* Clear */
    2719           0 :                 }
    2720           0 :         } else if (m->m_pkthdr.csum_flags & M_ICMP_CSUM_OUT) {
    2721           0 :                 in6_delayed_cksum(m, IPPROTO_ICMPV6);
    2722           0 :                 m->m_pkthdr.csum_flags &= ~M_ICMP_CSUM_OUT; /* Clear */
    2723           0 :         }
    2724           0 : }
    2725             : 
    2726             : #ifdef IPSEC
    2727             : struct tdb *
    2728           0 : ip6_output_ipsec_lookup(struct mbuf *m, int *error, struct inpcb *inp)
    2729             : {
    2730             :         struct tdb *tdb;
    2731             :         struct m_tag *mtag;
    2732             :         struct tdb_ident *tdbi;
    2733             : 
    2734             :         /*
    2735             :          * Check if there was an outgoing SA bound to the flow
    2736             :          * from a transport protocol.
    2737             :          */
    2738             : 
    2739             :         /* Do we have any pending SAs to apply ? */
    2740           0 :         tdb = ipsp_spd_lookup(m, AF_INET6, sizeof(struct ip6_hdr),
    2741             :             error, IPSP_DIRECTION_OUT, NULL, inp, 0);
    2742             : 
    2743           0 :         if (tdb == NULL)
    2744           0 :                 return NULL;
    2745             :         /* Loop detection */
    2746           0 :         for (mtag = m_tag_first(m); mtag != NULL; mtag = m_tag_next(m, mtag)) {
    2747           0 :                 if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE)
    2748             :                         continue;
    2749           0 :                 tdbi = (struct tdb_ident *)(mtag + 1);
    2750           0 :                 if (tdbi->spi == tdb->tdb_spi &&
    2751           0 :                     tdbi->proto == tdb->tdb_sproto &&
    2752           0 :                     tdbi->rdomain == tdb->tdb_rdomain &&
    2753           0 :                     !memcmp(&tdbi->dst, &tdb->tdb_dst,
    2754             :                     sizeof(union sockaddr_union))) {
    2755             :                         /* no IPsec needed */
    2756           0 :                         return NULL;
    2757             :                 }
    2758             :         }
    2759           0 :         return tdb;
    2760           0 : }
    2761             : 
    2762             : int
    2763           0 : ip6_output_ipsec_send(struct tdb *tdb, struct mbuf *m, int tunalready, int fwd)
    2764             : {
    2765             : #if NPF > 0
    2766             :         struct ifnet *encif;
    2767             : #endif
    2768             :         int error;
    2769             : 
    2770             : #if NPF > 0
    2771           0 :         if ((encif = enc_getif(tdb->tdb_rdomain, tdb->tdb_tap)) == NULL ||
    2772           0 :             pf_test(AF_INET6, fwd ? PF_FWD : PF_OUT, encif, &m) != PF_PASS) {
    2773           0 :                 m_freem(m);
    2774           0 :                 return EHOSTUNREACH;
    2775             :         }
    2776           0 :         if (m == NULL)
    2777           0 :                 return 0;
    2778             :         /*
    2779             :          * PF_TAG_REROUTE handling or not...
    2780             :          * Packet is entering IPsec so the routing is
    2781             :          * already overruled by the IPsec policy.
    2782             :          * Until now the change was not reconsidered.
    2783             :          * What's the behaviour?
    2784             :          */
    2785           0 :         in6_proto_cksum_out(m, encif);
    2786             : #endif
    2787           0 :         m->m_flags &= ~(M_BCAST | M_MCAST);      /* just in case */
    2788             : 
    2789             :         /* Callee frees mbuf */
    2790           0 :         error = ipsp_process_packet(m, tdb, AF_INET6, tunalready);
    2791           0 :         if (error) {
    2792           0 :                 ipsecstat_inc(ipsec_odrops);
    2793           0 :                 tdb->tdb_odrops++;
    2794           0 :         }
    2795           0 :         return error;
    2796           0 : }
    2797             : #endif /* IPSEC */

Generated by: LCOV version 1.13