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

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

CVSweb <webmaster@jp.NetBSD.org>