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

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

CVSweb <webmaster@jp.NetBSD.org>