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

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

CVSweb <webmaster@jp.NetBSD.org>