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

Annotation of src/sys/netinet6/raw_ip6.c, Revision 1.168

1.168   ! maxv        1: /*     $NetBSD: raw_ip6.c,v 1.167 2018/04/12 06:49:39 maxv Exp $       */
1.34      itojun      2: /*     $KAME: raw_ip6.c,v 1.82 2001/07/23 18:57:56 jinmei Exp $        */
1.3       thorpej     3:
1.2       itojun      4: /*
                      5:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
                      6:  * All rights reserved.
1.24      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.24      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, 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.55      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:  *     @(#)raw_ip.c    8.2 (Berkeley) 1/4/94
                     62:  */
1.39      lukem      63:
                     64: #include <sys/cdefs.h>
1.168   ! maxv       65: __KERNEL_RCSID(0, "$NetBSD: raw_ip6.c,v 1.167 2018/04/12 06:49:39 maxv Exp $");
1.6       thorpej    66:
1.141     pooka      67: #ifdef _KERNEL_OPT
1.6       thorpej    68: #include "opt_ipsec.h"
1.153     knakahar   69: #include "opt_net_mpsafe.h"
1.141     pooka      70: #endif
1.2       itojun     71:
                     72: #include <sys/param.h>
1.69      atatat     73: #include <sys/sysctl.h>
1.2       itojun     74: #include <sys/mbuf.h>
                     75: #include <sys/socket.h>
                     76: #include <sys/protosw.h>
                     77: #include <sys/socketvar.h>
                     78: #include <sys/systm.h>
                     79: #include <sys/proc.h>
1.77      elad       80: #include <sys/kauth.h>
1.116     rmind      81: #include <sys/kmem.h>
1.2       itojun     82:
                     83: #include <net/if.h>
                     84: #include <net/if_types.h>
1.97      thorpej    85: #include <net/net_stats.h>
1.2       itojun     86:
                     87: #include <netinet/in.h>
                     88: #include <netinet/in_var.h>
1.19      itojun     89: #include <netinet/ip6.h>
1.2       itojun     90: #include <netinet6/ip6_var.h>
1.94      thorpej    91: #include <netinet6/ip6_private.h>
1.2       itojun     92: #include <netinet6/ip6_mroute.h>
1.19      itojun     93: #include <netinet/icmp6.h>
1.94      thorpej    94: #include <netinet6/icmp6_private.h>
1.2       itojun     95: #include <netinet6/in6_pcb.h>
1.20      itojun     96: #include <netinet6/ip6protosw.h>
1.24      itojun     97: #include <netinet6/scope6_var.h>
1.37      itojun     98: #include <netinet6/raw_ip6.h>
1.2       itojun     99:
1.111     christos  100: #ifdef IPSEC
1.81      degroote  101: #include <netipsec/ipsec.h>
1.97      thorpej   102: #include <netipsec/ipsec_var.h>
1.81      degroote  103: #include <netipsec/ipsec6.h>
                    104: #endif
                    105:
1.2       itojun    106: #include "faith.h"
1.32      itojun    107: #if defined(NFAITH) && 0 < NFAITH
                    108: #include <net/if_faith.h>
                    109: #endif
1.2       itojun    110:
1.59      itojun    111: extern struct inpcbtable rawcbtable;
                    112: struct inpcbtable raw6cbtable;
1.2       itojun    113: #define ifatoia6(ifa)  ((struct in6_ifaddr *)(ifa))
                    114:
                    115: /*
                    116:  * Raw interface to IP6 protocol.
                    117:  */
                    118:
1.95      thorpej   119: static percpu_t *rip6stat_percpu;
                    120:
1.97      thorpej   121: #define        RIP6_STATINC(x)         _NET_STATINC(rip6stat_percpu, x)
1.37      itojun    122:
1.105     pooka     123: static void sysctl_net_inet6_raw6_setup(struct sysctllog **);
                    124:
1.2       itojun    125: /*
                    126:  * Initialize raw connection block queue.
                    127:  */
                    128: void
1.103     cegger    129: rip6_init(void)
1.2       itojun    130: {
1.47      itojun    131:
1.105     pooka     132:        sysctl_net_inet6_raw6_setup(NULL);
1.59      itojun    133:        in6_pcbinit(&raw6cbtable, 1, 1);
1.95      thorpej   134:
                    135:        rip6stat_percpu = percpu_alloc(sizeof(uint64_t) * RIP6_NSTATS);
1.2       itojun    136: }
                    137:
                    138: /*
                    139:  * Setup generic address and protocol structures
                    140:  * for raw_input routine, then pass them along with
                    141:  * mbuf chain.
                    142:  */
                    143: int
1.85      christos  144: rip6_input(struct mbuf **mp, int *offp, int proto)
1.2       itojun    145: {
                    146:        struct mbuf *m = *mp;
1.27      itojun    147:        struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
1.59      itojun    148:        struct inpcb_hdr *inph;
1.27      itojun    149:        struct in6pcb *in6p;
1.2       itojun    150:        struct in6pcb *last = NULL;
                    151:        struct sockaddr_in6 rip6src;
1.168   ! maxv      152:        struct mbuf *n, *opts = NULL;
1.2       itojun    153:
1.95      thorpej   154:        RIP6_STATINC(RIP6_STAT_IPACKETS);
1.37      itojun    155:
1.2       itojun    156: #if defined(NFAITH) && 0 < NFAITH
1.32      itojun    157:        if (faithprefix(&ip6->ip6_dst)) {
                    158:                /* send icmp6 host unreach? */
                    159:                m_freem(m);
                    160:                return IPPROTO_DONE;
1.2       itojun    161:        }
                    162: #endif
1.14      itojun    163:
1.89      dyoung    164:        sockaddr_in6_init(&rip6src, &ip6->ip6_src, 0, 0, 0);
1.75      rpaulo    165:        if (sa6_recoverscope(&rip6src) != 0) {
                    166:                /* XXX: should be impossible. */
                    167:                m_freem(m);
                    168:                return IPPROTO_DONE;
                    169:        }
1.2       itojun    170:
1.112     christos  171:        TAILQ_FOREACH(inph, &raw6cbtable.inpt_queue, inph_queue) {
1.59      itojun    172:                in6p = (struct in6pcb *)inph;
                    173:                if (in6p->in6p_af != AF_INET6)
                    174:                        continue;
1.2       itojun    175:                if (in6p->in6p_ip6.ip6_nxt &&
                    176:                    in6p->in6p_ip6.ip6_nxt != proto)
                    177:                        continue;
1.12      itojun    178:                if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
1.37      itojun    179:                    !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
1.2       itojun    180:                        continue;
1.12      itojun    181:                if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
1.37      itojun    182:                    !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
1.2       itojun    183:                        continue;
1.37      itojun    184:                if (in6p->in6p_cksum != -1) {
1.95      thorpej   185:                        RIP6_STATINC(RIP6_STAT_ISUM);
1.64      itojun    186:                        if (in6_cksum(m, proto, *offp,
1.37      itojun    187:                            m->m_pkthdr.len - *offp)) {
1.95      thorpej   188:                                RIP6_STATINC(RIP6_STAT_BADSUM);
1.37      itojun    189:                                continue;
                    190:                        }
1.2       itojun    191:                }
1.30      itojun    192:
1.168   ! maxv      193:                if (last == NULL) {
        !           194:                        ;
        !           195:                }
1.111     christos  196: #ifdef IPSEC
1.168   ! maxv      197:                else if (ipsec_used && ipsec_in_reject(m, last)) {
        !           198:                        /* do not inject data into pcb */
        !           199:                }
1.159     maxv      200: #endif
1.168   ! maxv      201:                else if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
        !           202:                        if (last->in6p_flags & IN6P_CONTROLOPTS)
        !           203:                                ip6_savecontrol(last, &opts, ip6, n);
        !           204:                        /* strip intermediate headers */
        !           205:                        m_adj(n, *offp);
        !           206:                        if (sbappendaddr(&last->in6p_socket->so_rcv,
        !           207:                            sin6tosa(&rip6src), n, opts) == 0) {
        !           208:                                soroverflow(last->in6p_socket);
        !           209:                                m_freem(n);
        !           210:                                if (opts)
        !           211:                                        m_freem(opts);
        !           212:                                RIP6_STATINC(RIP6_STAT_FULLSOCK);
        !           213:                        } else {
        !           214:                                sorwakeup(last->in6p_socket);
1.2       itojun    215:                        }
1.168   ! maxv      216:                        opts = NULL;
1.2       itojun    217:                }
1.168   ! maxv      218:
1.2       itojun    219:                last = in6p;
                    220:        }
1.159     maxv      221:
1.111     christos  222: #ifdef IPSEC
1.163     maxv      223:        if (ipsec_used && last && ipsec_in_reject(m, last)) {
1.81      degroote  224:                m_freem(m);
1.159     maxv      225:                IP6_STATDEC(IP6_STAT_DELIVERED);
                    226:                /* do not inject data into pcb */
                    227:        } else
                    228: #endif
1.2       itojun    229:        if (last) {
                    230:                if (last->in6p_flags & IN6P_CONTROLOPTS)
                    231:                        ip6_savecontrol(last, &opts, ip6, m);
                    232:                /* strip intermediate headers */
                    233:                m_adj(m, *offp);
                    234:                if (sbappendaddr(&last->in6p_socket->so_rcv,
1.148     ozaki-r   235:                    sin6tosa(&rip6src), m, opts) == 0) {
1.166     roy       236:                        soroverflow(last->in6p_socket);
1.2       itojun    237:                        m_freem(m);
                    238:                        if (opts)
                    239:                                m_freem(opts);
1.95      thorpej   240:                        RIP6_STATINC(RIP6_STAT_FULLSOCK);
1.2       itojun    241:                } else
                    242:                        sorwakeup(last->in6p_socket);
                    243:        } else {
1.95      thorpej   244:                RIP6_STATINC(RIP6_STAT_NOSOCK);
1.37      itojun    245:                if (m->m_flags & M_MCAST)
1.95      thorpej   246:                        RIP6_STATINC(RIP6_STAT_NOSOCKMCAST);
1.2       itojun    247:                if (proto == IPPROTO_NONE)
                    248:                        m_freem(m);
                    249:                else {
1.144     ozaki-r   250:                        int s;
                    251:                        struct ifnet *rcvif = m_get_rcvif(m, &s);
1.160     maxv      252:                        const int prvnxt = ip6_get_prevhdr(m, *offp);
1.144     ozaki-r   253:                        in6_ifstat_inc(rcvif, ifs6_in_protounknown);
                    254:                        m_put_rcvif(rcvif, &s);
1.2       itojun    255:                        icmp6_error(m, ICMP6_PARAM_PROB,
1.43      itojun    256:                            ICMP6_PARAMPROB_NEXTHEADER,
1.160     maxv      257:                            prvnxt);
1.2       itojun    258:                }
1.94      thorpej   259:                IP6_STATDEC(IP6_STAT_DELIVERED);
1.2       itojun    260:        }
                    261:        return IPPROTO_DONE;
                    262: }
                    263:
1.98      ad        264: void *
1.82      dyoung    265: rip6_ctlinput(int cmd, const struct sockaddr *sa, void *d)
1.20      itojun    266: {
1.27      itojun    267:        struct ip6_hdr *ip6;
1.29      itojun    268:        struct ip6ctlparam *ip6cp = NULL;
                    269:        const struct sockaddr_in6 *sa6_src = NULL;
                    270:        void *cmdarg;
1.88      dyoung    271:        void (*notify)(struct in6pcb *, int) = in6_rtchange;
1.29      itojun    272:        int nxt;
1.20      itojun    273:
                    274:        if (sa->sa_family != AF_INET6 ||
                    275:            sa->sa_len != sizeof(struct sockaddr_in6))
1.102     yamt      276:                return NULL;
1.20      itojun    277:
1.21      itojun    278:        if ((unsigned)cmd >= PRC_NCMDS)
1.102     yamt      279:                return NULL;
1.21      itojun    280:        if (PRC_IS_REDIRECT(cmd))
                    281:                notify = in6_rtchange, d = NULL;
                    282:        else if (cmd == PRC_HOSTDEAD)
                    283:                d = NULL;
1.29      itojun    284:        else if (cmd == PRC_MSGSIZE)
                    285:                ; /* special code is present, see below */
1.21      itojun    286:        else if (inet6ctlerrmap[cmd] == 0)
1.102     yamt      287:                return NULL;
1.20      itojun    288:
                    289:        /* if the parameter is from icmp6, decode it. */
                    290:        if (d != NULL) {
1.29      itojun    291:                ip6cp = (struct ip6ctlparam *)d;
1.20      itojun    292:                ip6 = ip6cp->ip6c_ip6;
1.29      itojun    293:                cmdarg = ip6cp->ip6c_cmdarg;
                    294:                sa6_src = ip6cp->ip6c_src;
                    295:                nxt = ip6cp->ip6c_nxt;
1.20      itojun    296:        } else {
                    297:                ip6 = NULL;
1.29      itojun    298:                cmdarg = NULL;
                    299:                sa6_src = &sa6_any;
                    300:                nxt = -1;
1.20      itojun    301:        }
                    302:
1.29      itojun    303:        if (ip6 && cmd == PRC_MSGSIZE) {
1.82      dyoung    304:                const struct sockaddr_in6 *sa6 = (const struct sockaddr_in6 *)sa;
1.29      itojun    305:                int valid = 0;
                    306:                struct in6pcb *in6p;
1.20      itojun    307:
                    308:                /*
1.29      itojun    309:                 * Check to see if we have a valid raw IPv6 socket
                    310:                 * corresponding to the address in the ICMPv6 message
                    311:                 * payload, and the protocol (ip6_nxt) meets the socket.
                    312:                 * XXX chase extension headers, or pass final nxt value
                    313:                 * from icmp6_notify_error()
1.20      itojun    314:                 */
1.29      itojun    315:                in6p = NULL;
1.59      itojun    316:                in6p = in6_pcblookup_connect(&raw6cbtable, &sa6->sin6_addr, 0,
1.108     dyoung    317:                                             (const struct in6_addr *)&sa6_src->sin6_addr, 0, 0, 0);
1.29      itojun    318: #if 0
                    319:                if (!in6p) {
                    320:                        /*
                    321:                         * As the use of sendto(2) is fairly popular,
                    322:                         * we may want to allow non-connected pcb too.
                    323:                         * But it could be too weak against attacks...
                    324:                         * We should at least check if the local
                    325:                         * address (= s) is really ours.
                    326:                         */
1.59      itojun    327:                        in6p = in6_pcblookup_bind(&raw6cbtable,
1.75      rpaulo    328:                            &sa6->sin6_addr, 0, 0);
1.29      itojun    329:                }
                    330: #endif
                    331:
                    332:                if (in6p && in6p->in6p_ip6.ip6_nxt &&
                    333:                    in6p->in6p_ip6.ip6_nxt == nxt)
                    334:                        valid++;
1.20      itojun    335:
1.29      itojun    336:                /*
                    337:                 * Depending on the value of "valid" and routing table
                    338:                 * size (mtudisc_{hi,lo}wat), we will:
1.44      itojun    339:                 * - recalculate the new MTU and create the
1.29      itojun    340:                 *   corresponding routing entry, or
                    341:                 * - ignore the MTU change notification.
                    342:                 */
                    343:                icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
1.20      itojun    344:
1.29      itojun    345:                /*
                    346:                 * regardless of if we called icmp6_mtudisc_update(),
1.76      rpaulo    347:                 * we need to call in6_pcbnotify(), to notify path MTU
                    348:                 * change to the userland (RFC3542), because some
                    349:                 * unconnected sockets may share the same destination
                    350:                 * and want to know the path MTU.
1.29      itojun    351:                 */
1.20      itojun    352:        }
1.29      itojun    353:
1.59      itojun    354:        (void) in6_pcbnotify(&raw6cbtable, sa, 0,
1.148     ozaki-r   355:            sin6tocsa(sa6_src), 0, cmd, cmdarg, notify);
1.98      ad        356:        return NULL;
1.20      itojun    357: }
                    358:
1.2       itojun    359: /*
                    360:  * Generate IPv6 header and pass packet to ip6_output.
                    361:  * Tack on options user may have setup with control call.
                    362:  */
                    363: int
1.106     dyoung    364: rip6_output(struct mbuf *m, struct socket * const so,
                    365:     struct sockaddr_in6 * const dstsock, struct mbuf * const control)
1.2       itojun    366: {
                    367:        struct in6_addr *dst;
                    368:        struct ip6_hdr *ip6;
                    369:        struct in6pcb *in6p;
                    370:        u_int   plen = m->m_pkthdr.len;
                    371:        int error = 0;
1.75      rpaulo    372:        struct ip6_pktopts opt, *optp = NULL;
1.2       itojun    373:        struct ifnet *oifp = NULL;
1.12      itojun    374:        int type, code;         /* for ICMPv6 output statistics only */
1.75      rpaulo    375:        int scope_ambiguous = 0;
1.145     ozaki-r   376:        int bound = curlwp_bind();
1.146     ozaki-r   377:        struct psref psref;
1.2       itojun    378:
                    379:        in6p = sotoin6pcb(so);
                    380:
                    381:        dst = &dstsock->sin6_addr;
                    382:        if (control) {
1.76      rpaulo    383:                if ((error = ip6_setpktopts(control, &opt,
                    384:                    in6p->in6p_outputopts,
1.104     elad      385:                    kauth_cred_get(), so->so_proto->pr_protocol)) != 0) {
1.2       itojun    386:                        goto bad;
1.76      rpaulo    387:                }
1.2       itojun    388:                optp = &opt;
                    389:        } else
                    390:                optp = in6p->in6p_outputopts;
                    391:
1.12      itojun    392:        /*
1.75      rpaulo    393:         * Check and convert scope zone ID into internal form.
                    394:         * XXX: we may still need to determine the zone later.
                    395:         */
                    396:        if (!(so->so_state & SS_ISCONNECTED)) {
                    397:                if (dstsock->sin6_scope_id == 0 && !ip6_use_defzone)
                    398:                        scope_ambiguous = 1;
                    399:                if ((error = sa6_embedscope(dstsock, ip6_use_defzone)) != 0)
                    400:                        goto bad;
                    401:        }
                    402:
                    403:        /*
1.12      itojun    404:         * For an ICMPv6 packet, we should know its type and code
                    405:         * to update statistics.
                    406:         */
                    407:        if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
                    408:                struct icmp6_hdr *icmp6;
                    409:                if (m->m_len < sizeof(struct icmp6_hdr) &&
                    410:                    (m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) {
                    411:                        error = ENOBUFS;
                    412:                        goto bad;
                    413:                }
                    414:                icmp6 = mtod(m, struct icmp6_hdr *);
                    415:                type = icmp6->icmp6_type;
                    416:                code = icmp6->icmp6_code;
1.62      christos  417:        } else {
                    418:                type = 0;
                    419:                code = 0;
1.12      itojun    420:        }
                    421:
1.52      itojun    422:        M_PREPEND(m, sizeof(*ip6), M_DONTWAIT);
                    423:        if (!m) {
                    424:                error = ENOBUFS;
                    425:                goto bad;
                    426:        }
1.2       itojun    427:        ip6 = mtod(m, struct ip6_hdr *);
                    428:
                    429:        /*
                    430:         * Next header might not be ICMP6 but use its pseudo header anyway.
                    431:         */
                    432:        ip6->ip6_dst = *dst;
                    433:
1.12      itojun    434:        /*
                    435:         * Source address selection.
                    436:         */
1.152     ozaki-r   437:        error = in6_selectsrc(dstsock, optp, in6p->in6p_moptions,
                    438:            &in6p->in6p_route, &in6p->in6p_laddr, &oifp, &psref, &ip6->ip6_src);
                    439:        if (error != 0)
1.75      rpaulo    440:                goto bad;
1.2       itojun    441:
1.75      rpaulo    442:        if (oifp && scope_ambiguous) {
                    443:                /*
                    444:                 * Application should provide a proper zone ID or the use of
                    445:                 * default zone IDs should be enabled.  Unfortunately, some
                    446:                 * applications do not behave as it should, so we need a
                    447:                 * workaround.  Even if an appropriate ID is not determined
                    448:                 * (when it's required), if we can determine the outgoing
                    449:                 * interface. determine the zone ID based on the interface.
                    450:                 */
                    451:                error = in6_setscope(&dstsock->sin6_addr, oifp, NULL);
                    452:                if (error != 0)
1.2       itojun    453:                        goto bad;
1.12      itojun    454:        }
1.75      rpaulo    455:        ip6->ip6_dst = dstsock->sin6_addr;
1.2       itojun    456:
1.75      rpaulo    457:        /* fill in the rest of the IPv6 header fields */
1.2       itojun    458:        ip6->ip6_flow = in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK;
1.20      itojun    459:        ip6->ip6_vfc  &= ~IPV6_VERSION_MASK;
                    460:        ip6->ip6_vfc  |= IPV6_VERSION;
1.75      rpaulo    461:        /* ip6_plen will be filled in ip6_output, so not fill it here. */
1.2       itojun    462:        ip6->ip6_nxt   = in6p->in6p_ip6.ip6_nxt;
1.12      itojun    463:        ip6->ip6_hlim = in6_selecthlim(in6p, oifp);
1.2       itojun    464:
1.146     ozaki-r   465:        if_put(oifp, &psref);
                    466:        oifp = NULL;
                    467:
1.2       itojun    468:        if (so->so_proto->pr_protocol == IPPROTO_ICMPV6 ||
                    469:            in6p->in6p_cksum != -1) {
1.161     maxv      470:                const uint8_t nxt = ip6->ip6_nxt;
1.2       itojun    471:                int off;
1.67      yamt      472:                u_int16_t sum;
1.2       itojun    473:
                    474:                /* compute checksum */
                    475:                if (so->so_proto->pr_protocol == IPPROTO_ICMPV6)
                    476:                        off = offsetof(struct icmp6_hdr, icmp6_cksum);
                    477:                else
                    478:                        off = in6p->in6p_cksum;
                    479:                if (plen < off + 1) {
                    480:                        error = EINVAL;
                    481:                        goto bad;
                    482:                }
                    483:                off += sizeof(struct ip6_hdr);
                    484:
1.68      yamt      485:                sum = 0;
1.84      christos  486:                m = m_copyback_cow(m, off, sizeof(sum), (void *)&sum,
1.68      yamt      487:                    M_DONTWAIT);
                    488:                if (m == NULL) {
1.66      yamt      489:                        error = ENOBUFS;
                    490:                        goto bad;
                    491:                }
1.161     maxv      492:                sum = in6_cksum(m, nxt, sizeof(*ip6), plen);
1.84      christos  493:                m = m_copyback_cow(m, off, sizeof(sum), (void *)&sum,
1.68      yamt      494:                    M_DONTWAIT);
                    495:                if (m == NULL) {
                    496:                        error = ENOBUFS;
                    497:                        goto bad;
                    498:                }
1.2       itojun    499:        }
1.27      itojun    500:
1.144     ozaki-r   501:        {
                    502:                struct ifnet *ret_oifp = NULL;
                    503:
                    504:                error = ip6_output(m, optp, &in6p->in6p_route, 0,
1.156     ozaki-r   505:                    in6p->in6p_moptions, in6p, &ret_oifp);
1.144     ozaki-r   506:                if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
                    507:                        if (ret_oifp)
                    508:                                icmp6_ifoutstat_inc(ret_oifp, type, code);
                    509:                        ICMP6_STATINC(ICMP6_STAT_OUTHIST + type);
                    510:                } else
                    511:                        RIP6_STATINC(RIP6_STAT_OPACKETS);
                    512:        }
1.2       itojun    513:
                    514:        goto freectl;
                    515:
                    516:  bad:
                    517:        if (m)
                    518:                m_freem(m);
                    519:
                    520:  freectl:
1.76      rpaulo    521:        if (control) {
                    522:                ip6_clearpktopts(&opt, -1);
1.2       itojun    523:                m_freem(control);
1.76      rpaulo    524:        }
1.146     ozaki-r   525:        if_put(oifp, &psref);
1.145     ozaki-r   526:        curlwp_bindx(bound);
1.83      dyoung    527:        return error;
1.2       itojun    528: }
                    529:
1.40      itojun    530: /*
1.2       itojun    531:  * Raw IPv6 socket option processing.
1.40      itojun    532:  */
1.2       itojun    533: int
1.100     plunky    534: rip6_ctloutput(int op, struct socket *so, struct sockopt *sopt)
1.2       itojun    535: {
                    536:        int error = 0;
                    537:
1.100     plunky    538:        if (sopt->sopt_level == SOL_SOCKET && sopt->sopt_name == SO_NOHEADER) {
                    539:                int optval;
                    540:
1.87      dyoung    541:                /* need to fiddle w/ opt(IPPROTO_IPV6, IPV6_CHECKSUM)? */
1.90      dyoung    542:                if (op == PRCO_GETOPT) {
1.100     plunky    543:                        optval = 1;
                    544:                        error = sockopt_set(sopt, &optval, sizeof(optval));
                    545:                } else if (op == PRCO_SETOPT) {
                    546:                        error = sockopt_getint(sopt, &optval);
                    547:                        if (error)
                    548:                                goto out;
                    549:                        if (optval == 0)
                    550:                                error = EINVAL;
                    551:                }
                    552:
                    553:                goto out;
                    554:        } else if (sopt->sopt_level != IPPROTO_IPV6)
                    555:                return ip6_ctloutput(op, so, sopt);
1.87      dyoung    556:
1.100     plunky    557:        switch (sopt->sopt_name) {
1.87      dyoung    558:        case MRT6_INIT:
                    559:        case MRT6_DONE:
                    560:        case MRT6_ADD_MIF:
                    561:        case MRT6_DEL_MIF:
                    562:        case MRT6_ADD_MFC:
                    563:        case MRT6_DEL_MFC:
                    564:        case MRT6_PIM:
                    565:                if (op == PRCO_SETOPT)
1.100     plunky    566:                        error = ip6_mrouter_set(so, sopt);
1.87      dyoung    567:                else if (op == PRCO_GETOPT)
1.100     plunky    568:                        error = ip6_mrouter_get(so, sopt);
1.87      dyoung    569:                else
                    570:                        error = EINVAL;
                    571:                break;
                    572:        case IPV6_CHECKSUM:
1.100     plunky    573:                return ip6_raw_ctloutput(op, so, sopt);
1.27      itojun    574:        default:
1.100     plunky    575:                return ip6_ctloutput(op, so, sopt);
1.2       itojun    576:        }
1.100     plunky    577:  out:
1.87      dyoung    578:        return error;
1.2       itojun    579: }
                    580:
                    581: extern u_long rip6_sendspace;
                    582: extern u_long rip6_recvspace;
                    583:
                    584: int
1.116     rmind     585: rip6_attach(struct socket *so, int proto)
                    586: {
                    587:        struct in6pcb *in6p;
                    588:        int s, error;
                    589:
                    590:        KASSERT(sotoin6pcb(so) == NULL);
                    591:        sosetlock(so);
                    592:
                    593:        error = kauth_authorize_network(curlwp->l_cred,
                    594:            KAUTH_NETWORK_SOCKET, KAUTH_REQ_NETWORK_SOCKET_RAWSOCK,
                    595:            KAUTH_ARG(AF_INET6),
                    596:            KAUTH_ARG(SOCK_RAW),
                    597:            KAUTH_ARG(so->so_proto->pr_protocol));
                    598:        if (error) {
                    599:                return error;
                    600:        }
                    601:        s = splsoftnet();
                    602:        error = soreserve(so, rip6_sendspace, rip6_recvspace);
                    603:        if (error) {
                    604:                splx(s);
                    605:                return error;
                    606:        }
                    607:        if ((error = in6_pcballoc(so, &raw6cbtable)) != 0) {
                    608:                splx(s);
                    609:                return error;
                    610:        }
                    611:        splx(s);
                    612:        in6p = sotoin6pcb(so);
                    613:        in6p->in6p_ip6.ip6_nxt = proto;
                    614:        in6p->in6p_cksum = -1;
                    615:
                    616:        in6p->in6p_icmp6filt = kmem_alloc(sizeof(struct icmp6_filter), KM_SLEEP);
                    617:        ICMP6_FILTER_SETPASSALL(in6p->in6p_icmp6filt);
                    618:        KASSERT(solocked(so));
                    619:        return error;
                    620: }
                    621:
                    622: static void
                    623: rip6_detach(struct socket *so)
                    624: {
                    625:        struct in6pcb *in6p = sotoin6pcb(so);
                    626:
                    627:        KASSERT(solocked(so));
                    628:        KASSERT(in6p != NULL);
                    629:
                    630:        if (so == ip6_mrouter) {
                    631:                ip6_mrouter_done();
                    632:        }
                    633:        /* xxx: RSVP */
                    634:        if (in6p->in6p_icmp6filt != NULL) {
                    635:                kmem_free(in6p->in6p_icmp6filt, sizeof(struct icmp6_filter));
                    636:                in6p->in6p_icmp6filt = NULL;
                    637:        }
                    638:        in6_pcbdetach(in6p);
                    639: }
                    640:
1.119     rtr       641: static int
1.138     rtr       642: rip6_accept(struct socket *so, struct sockaddr *nam)
1.127     rtr       643: {
                    644:        KASSERT(solocked(so));
                    645:
                    646:        return EOPNOTSUPP;
                    647: }
                    648:
                    649: static int
1.137     rtr       650: rip6_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
1.129     rtr       651: {
                    652:        struct in6pcb *in6p = sotoin6pcb(so);
1.137     rtr       653:        struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
1.149     ozaki-r   654:        struct ifaddr *ifa = NULL;
1.129     rtr       655:        int error = 0;
1.149     ozaki-r   656:        int s;
1.129     rtr       657:
                    658:        KASSERT(solocked(so));
                    659:        KASSERT(in6p != NULL);
                    660:        KASSERT(nam != NULL);
                    661:
1.137     rtr       662:        if (addr->sin6_len != sizeof(*addr))
1.129     rtr       663:                return EINVAL;
1.143     ozaki-r   664:        if (IFNET_READER_EMPTY() || addr->sin6_family != AF_INET6)
1.129     rtr       665:                return EADDRNOTAVAIL;
                    666:
                    667:        if ((error = sa6_embedscope(addr, ip6_use_defzone)) != 0)
                    668:                return error;
                    669:
                    670:        /*
                    671:         * we don't support mapped address here, it would confuse
                    672:         * users so reject it
                    673:         */
                    674:        if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr))
                    675:                return EADDRNOTAVAIL;
1.149     ozaki-r   676:        s = pserialize_read_enter();
1.129     rtr       677:        if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) &&
1.149     ozaki-r   678:            (ifa = ifa_ifwithaddr(sin6tosa(addr))) == NULL) {
                    679:                error = EADDRNOTAVAIL;
                    680:                goto out;
                    681:        }
                    682:        if (ifa && (ifatoia6(ifa))->ia6_flags &
1.151     roy       683:            (IN6_IFF_ANYCAST | IN6_IFF_DUPLICATED)) {
1.149     ozaki-r   684:                error = EADDRNOTAVAIL;
                    685:                goto out;
                    686:        }
                    687:
1.129     rtr       688:        in6p->in6p_laddr = addr->sin6_addr;
1.149     ozaki-r   689:        error = 0;
                    690: out:
                    691:        pserialize_read_exit(s);
                    692:        return error;
1.129     rtr       693: }
                    694:
                    695: static int
1.133     rtr       696: rip6_listen(struct socket *so, struct lwp *l)
1.129     rtr       697: {
                    698:        KASSERT(solocked(so));
                    699:
                    700:        return EOPNOTSUPP;
                    701: }
                    702:
                    703: static int
1.140     rtr       704: rip6_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
1.130     rtr       705: {
                    706:        struct in6pcb *in6p = sotoin6pcb(so);
1.140     rtr       707:        struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
1.152     ozaki-r   708:        struct in6_addr in6a;
1.130     rtr       709:        struct ifnet *ifp = NULL;
                    710:        int scope_ambiguous = 0;
                    711:        int error = 0;
1.146     ozaki-r   712:        struct psref psref;
                    713:        int bound;
1.130     rtr       714:
                    715:        KASSERT(solocked(so));
                    716:        KASSERT(in6p != NULL);
                    717:        KASSERT(nam != NULL);
                    718:
1.143     ozaki-r   719:        if (IFNET_READER_EMPTY())
1.130     rtr       720:                return EADDRNOTAVAIL;
                    721:        if (addr->sin6_family != AF_INET6)
                    722:                return EAFNOSUPPORT;
                    723:
                    724:        /*
                    725:         * Application should provide a proper zone ID or the use of
                    726:         * default zone IDs should be enabled.  Unfortunately, some
                    727:         * applications do not behave as it should, so we need a
                    728:         * workaround.  Even if an appropriate ID is not determined,
                    729:         * we'll see if we can determine the outgoing interface.  If we
                    730:         * can, determine the zone ID based on the interface below.
                    731:         */
                    732:        if (addr->sin6_scope_id == 0 && !ip6_use_defzone)
                    733:                scope_ambiguous = 1;
                    734:        if ((error = sa6_embedscope(addr, ip6_use_defzone)) != 0)
                    735:                return error;
                    736:
1.146     ozaki-r   737:        bound = curlwp_bind();
1.130     rtr       738:        /* Source address selection. XXX: need pcblookup? */
1.152     ozaki-r   739:        error = in6_selectsrc(addr, in6p->in6p_outputopts,
1.130     rtr       740:            in6p->in6p_moptions, &in6p->in6p_route,
1.152     ozaki-r   741:            &in6p->in6p_laddr, &ifp, &psref, &in6a);
                    742:        if (error != 0)
1.144     ozaki-r   743:                goto out;
1.130     rtr       744:        /* XXX: see above */
                    745:        if (ifp && scope_ambiguous &&
                    746:            (error = in6_setscope(&addr->sin6_addr, ifp, NULL)) != 0) {
1.144     ozaki-r   747:                goto out;
1.130     rtr       748:        }
1.152     ozaki-r   749:        in6p->in6p_laddr = in6a;
1.130     rtr       750:        in6p->in6p_faddr = addr->sin6_addr;
                    751:        soisconnected(so);
1.144     ozaki-r   752: out:
1.146     ozaki-r   753:        if_put(ifp, &psref);
                    754:        curlwp_bindx(bound);
1.130     rtr       755:        return error;
                    756: }
                    757:
                    758: static int
1.136     rtr       759: rip6_connect2(struct socket *so, struct socket *so2)
                    760: {
                    761:        KASSERT(solocked(so));
                    762:
                    763:        return EOPNOTSUPP;
                    764: }
                    765:
                    766: static int
1.132     rtr       767: rip6_disconnect(struct socket *so)
                    768: {
                    769:        struct in6pcb *in6p = sotoin6pcb(so);
                    770:
                    771:        KASSERT(solocked(so));
                    772:        KASSERT(in6p != NULL);
                    773:
                    774:        if ((so->so_state & SS_ISCONNECTED) == 0)
                    775:                return ENOTCONN;
                    776:
                    777:        in6p->in6p_faddr = in6addr_any;
                    778:        so->so_state &= ~SS_ISCONNECTED;        /* XXX */
                    779:        return 0;
                    780: }
                    781:
                    782: static int
                    783: rip6_shutdown(struct socket *so)
                    784: {
                    785:        KASSERT(solocked(so));
                    786:
                    787:        /*
                    788:         * Mark the connection as being incapable of futther input.
                    789:         */
                    790:        socantsendmore(so);
                    791:        return 0;
                    792: }
                    793:
                    794: static int
                    795: rip6_abort(struct socket *so)
                    796: {
                    797:        KASSERT(solocked(so));
                    798:
                    799:        soisdisconnected(so);
                    800:        rip6_detach(so);
                    801:        return 0;
                    802: }
                    803:
                    804: static int
1.121     rtr       805: rip6_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
1.119     rtr       806: {
1.121     rtr       807:        return in6_control(so, cmd, nam, ifp);
1.119     rtr       808: }
                    809:
1.122     rtr       810: static int
                    811: rip6_stat(struct socket *so, struct stat *ub)
                    812: {
1.125     rtr       813:        KASSERT(solocked(so));
                    814:
1.124     rtr       815:        /* stat: don't bother with a blocksize */
                    816:        return 0;
1.122     rtr       817: }
                    818:
1.126     rtr       819: static int
1.138     rtr       820: rip6_peeraddr(struct socket *so, struct sockaddr *nam)
1.126     rtr       821: {
                    822:        KASSERT(solocked(so));
                    823:        KASSERT(sotoin6pcb(so) != NULL);
                    824:        KASSERT(nam != NULL);
                    825:
1.138     rtr       826:        in6_setpeeraddr(sotoin6pcb(so), (struct sockaddr_in6 *)nam);
1.126     rtr       827:        return 0;
                    828: }
                    829:
                    830: static int
1.138     rtr       831: rip6_sockaddr(struct socket *so, struct sockaddr *nam)
1.126     rtr       832: {
                    833:        KASSERT(solocked(so));
                    834:        KASSERT(sotoin6pcb(so) != NULL);
                    835:        KASSERT(nam != NULL);
                    836:
1.138     rtr       837:        in6_setsockaddr(sotoin6pcb(so), (struct sockaddr_in6 *)nam);
1.126     rtr       838:        return 0;
                    839: }
                    840:
1.128     rtr       841: static int
1.135     rtr       842: rip6_rcvd(struct socket *so, int flags, struct lwp *l)
                    843: {
                    844:        KASSERT(solocked(so));
                    845:
                    846:        return EOPNOTSUPP;
                    847: }
                    848:
                    849: static int
1.128     rtr       850: rip6_recvoob(struct socket *so, struct mbuf *m, int flags)
                    851: {
                    852:        KASSERT(solocked(so));
                    853:
                    854:        return EOPNOTSUPP;
                    855: }
                    856:
                    857: static int
1.140     rtr       858: rip6_send(struct socket *so, struct mbuf *m, struct sockaddr *nam,
1.134     rtr       859:     struct mbuf *control, struct lwp *l)
                    860: {
                    861:        struct in6pcb *in6p = sotoin6pcb(so);
                    862:        struct sockaddr_in6 tmp;
                    863:        struct sockaddr_in6 *dst;
                    864:        int error = 0;
                    865:
                    866:        KASSERT(solocked(so));
                    867:        KASSERT(in6p != NULL);
                    868:        KASSERT(m != NULL);
                    869:
                    870:        /*
                    871:         * Ship a packet out. The appropriate raw output
                    872:         * routine handles any messaging necessary.
                    873:         */
                    874:
                    875:        /* always copy sockaddr to avoid overwrites */
                    876:        if (so->so_state & SS_ISCONNECTED) {
                    877:                if (nam) {
                    878:                        error = EISCONN;
                    879:                        goto release;
                    880:                }
                    881:                /* XXX */
                    882:                sockaddr_in6_init(&tmp, &in6p->in6p_faddr, 0, 0, 0);
                    883:                dst = &tmp;
                    884:        } else {
                    885:                if (nam == NULL) {
                    886:                        error = ENOTCONN;
                    887:                        goto release;
                    888:                }
1.140     rtr       889:                tmp = *(struct sockaddr_in6 *)nam;
1.134     rtr       890:                dst = &tmp;
                    891:
                    892:                if (dst->sin6_family != AF_INET6) {
                    893:                        error = EAFNOSUPPORT;
                    894:                        goto release;
                    895:                }
                    896:        }
                    897:        error = rip6_output(m, so, dst, control);
                    898:        m = NULL;
                    899:
                    900: release:
                    901:        if (m)
                    902:                m_freem(m);
                    903:
                    904:        return error;
                    905: }
                    906:
                    907: static int
1.128     rtr       908: rip6_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
                    909: {
                    910:        KASSERT(solocked(so));
                    911:
                    912:        if (m)
                    913:                m_freem(m);
                    914:
                    915:        return EOPNOTSUPP;
                    916: }
                    917:
1.136     rtr       918: static int
                    919: rip6_purgeif(struct socket *so, struct ifnet *ifp)
                    920: {
                    921:
                    922:        mutex_enter(softnet_lock);
1.155     ozaki-r   923:        in6_pcbpurgeif0(&raw6cbtable, ifp);
                    924: #ifdef NET_MPSAFE
                    925:        mutex_exit(softnet_lock);
1.153     knakahar  926: #endif
1.136     rtr       927:        in6_purgeif(ifp);
1.155     ozaki-r   928: #ifdef NET_MPSAFE
                    929:        mutex_enter(softnet_lock);
                    930: #endif
1.136     rtr       931:        in6_pcbpurgeif(&raw6cbtable, ifp);
                    932:        mutex_exit(softnet_lock);
                    933:
                    934:        return 0;
                    935: }
                    936:
1.95      thorpej   937: static int
                    938: sysctl_net_inet6_raw6_stats(SYSCTLFN_ARGS)
                    939: {
                    940:
1.99      thorpej   941:        return (NETSTAT_SYSCTL(rip6stat_percpu, RIP6_NSTATS));
1.95      thorpej   942: }
                    943:
1.105     pooka     944: static void
                    945: sysctl_net_inet6_raw6_setup(struct sysctllog **clog)
1.69      atatat    946: {
                    947:
                    948:        sysctl_createv(clog, 0, NULL, NULL,
                    949:                       CTLFLAG_PERMANENT,
                    950:                       CTLTYPE_NODE, "inet6", NULL,
                    951:                       NULL, 0, NULL, 0,
                    952:                       CTL_NET, PF_INET6, CTL_EOL);
                    953:        sysctl_createv(clog, 0, NULL, NULL,
                    954:                       CTLFLAG_PERMANENT,
                    955:                       CTLTYPE_NODE, "raw6",
                    956:                       SYSCTL_DESCR("Raw IPv6 settings"),
                    957:                       NULL, 0, NULL, 0,
                    958:                       CTL_NET, PF_INET6, IPPROTO_RAW, CTL_EOL);
                    959:
                    960:        sysctl_createv(clog, 0, NULL, NULL,
                    961:                       CTLFLAG_PERMANENT,
1.71      atatat    962:                       CTLTYPE_STRUCT, "pcblist",
1.69      atatat    963:                       SYSCTL_DESCR("Raw IPv6 control block list"),
                    964:                       sysctl_inpcblist, 0, &raw6cbtable, 0,
                    965:                       CTL_NET, PF_INET6, IPPROTO_RAW,
                    966:                       CTL_CREATE, CTL_EOL);
1.73      rpaulo    967:        sysctl_createv(clog, 0, NULL, NULL,
                    968:                       CTLFLAG_PERMANENT,
                    969:                       CTLTYPE_STRUCT, "stats",
                    970:                       SYSCTL_DESCR("Raw IPv6 statistics"),
1.95      thorpej   971:                       sysctl_net_inet6_raw6_stats, 0, NULL, 0,
1.73      rpaulo    972:                       CTL_NET, PF_INET6, IPPROTO_RAW, RAW6CTL_STATS,
                    973:                       CTL_EOL);
1.69      atatat    974: }
1.115     rmind     975:
1.117     rmind     976: PR_WRAP_USRREQS(rip6)
                    977: #define        rip6_attach             rip6_attach_wrapper
                    978: #define        rip6_detach             rip6_detach_wrapper
1.127     rtr       979: #define        rip6_accept             rip6_accept_wrapper
1.129     rtr       980: #define        rip6_bind               rip6_bind_wrapper
                    981: #define        rip6_listen             rip6_listen_wrapper
1.130     rtr       982: #define        rip6_connect            rip6_connect_wrapper
1.136     rtr       983: #define        rip6_connect2           rip6_connect2_wrapper
1.132     rtr       984: #define        rip6_disconnect         rip6_disconnect_wrapper
                    985: #define        rip6_shutdown           rip6_shutdown_wrapper
                    986: #define        rip6_abort              rip6_abort_wrapper
1.119     rtr       987: #define        rip6_ioctl              rip6_ioctl_wrapper
1.122     rtr       988: #define        rip6_stat               rip6_stat_wrapper
1.126     rtr       989: #define        rip6_peeraddr           rip6_peeraddr_wrapper
                    990: #define        rip6_sockaddr           rip6_sockaddr_wrapper
1.135     rtr       991: #define        rip6_rcvd               rip6_rcvd_wrapper
1.128     rtr       992: #define        rip6_recvoob            rip6_recvoob_wrapper
1.134     rtr       993: #define        rip6_send               rip6_send_wrapper
1.128     rtr       994: #define        rip6_sendoob            rip6_sendoob_wrapper
1.136     rtr       995: #define        rip6_purgeif            rip6_purgeif_wrapper
1.115     rmind     996:
                    997: const struct pr_usrreqs rip6_usrreqs = {
1.116     rmind     998:        .pr_attach      = rip6_attach,
                    999:        .pr_detach      = rip6_detach,
1.127     rtr      1000:        .pr_accept      = rip6_accept,
1.129     rtr      1001:        .pr_bind        = rip6_bind,
                   1002:        .pr_listen      = rip6_listen,
1.130     rtr      1003:        .pr_connect     = rip6_connect,
1.136     rtr      1004:        .pr_connect2    = rip6_connect2,
1.132     rtr      1005:        .pr_disconnect  = rip6_disconnect,
                   1006:        .pr_shutdown    = rip6_shutdown,
                   1007:        .pr_abort       = rip6_abort,
1.119     rtr      1008:        .pr_ioctl       = rip6_ioctl,
1.122     rtr      1009:        .pr_stat        = rip6_stat,
1.126     rtr      1010:        .pr_peeraddr    = rip6_peeraddr,
                   1011:        .pr_sockaddr    = rip6_sockaddr,
1.135     rtr      1012:        .pr_rcvd        = rip6_rcvd,
1.128     rtr      1013:        .pr_recvoob     = rip6_recvoob,
1.134     rtr      1014:        .pr_send        = rip6_send,
1.128     rtr      1015:        .pr_sendoob     = rip6_sendoob,
1.136     rtr      1016:        .pr_purgeif     = rip6_purgeif,
1.115     rmind    1017: };

CVSweb <webmaster@jp.NetBSD.org>