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

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

CVSweb <webmaster@jp.NetBSD.org>