[BACK]Return to ip6_output.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / netinet6

Annotation of src/sys/netinet6/ip6_output.c, Revision 1.216

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

CVSweb <webmaster@jp.NetBSD.org>