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

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

CVSweb <webmaster@jp.NetBSD.org>