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

Annotation of src/sys/netinet6/udp6_usrreq.c, Revision 1.30.2.4

1.30.2.4! he          1: /*     $NetBSD: udp6_usrreq.c,v 1.30.2.3 2001/04/06 00:29:38 he Exp $  */
1.30.2.2  tv          2: /*     $KAME: udp6_usrreq.c,v 1.62 2000/10/19 01:11:05 itojun Exp $    */
1.3       thorpej     3:
1.2       itojun      4: /*
                      5:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
                      6:  * All rights reserved.
1.27      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.27      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, 1989, 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.
                     45:  * 3. All advertising materials mentioning features or use of this software
                     46:  *    must display the following acknowledgement:
                     47:  *     This product includes software developed by the University of
                     48:  *     California, Berkeley and its contributors.
                     49:  * 4. Neither the name of the University nor the names of its contributors
                     50:  *    may be used to endorse or promote products derived from this software
                     51:  *    without specific prior written permission.
                     52:  *
                     53:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     54:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     55:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     56:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     57:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     58:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     59:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     60:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     61:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     62:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     63:  * SUCH DAMAGE.
                     64:  *
                     65:  *     @(#)udp_var.h   8.1 (Berkeley) 6/10/93
                     66:  */
1.5       thorpej    67:
                     68: #include "opt_ipsec.h"
1.2       itojun     69:
                     70: #include <sys/param.h>
                     71: #include <sys/malloc.h>
                     72: #include <sys/mbuf.h>
                     73: #include <sys/protosw.h>
                     74: #include <sys/socket.h>
                     75: #include <sys/socketvar.h>
                     76: #include <sys/errno.h>
                     77: #include <sys/stat.h>
                     78: #include <sys/systm.h>
                     79: #include <sys/proc.h>
1.8       itojun     80: #include <sys/syslog.h>
1.2       itojun     81:
                     82: #include <net/if.h>
                     83: #include <net/route.h>
                     84: #include <net/if_types.h>
                     85:
                     86: #include <netinet/in.h>
                     87: #include <netinet/in_var.h>
1.14      itojun     88: #include <netinet/in_systm.h>
                     89: #include <netinet/ip.h>
                     90: #include <netinet/ip_var.h>
                     91: #include <netinet/in_pcb.h>
                     92: #include <netinet/udp.h>
                     93: #include <netinet/udp_var.h>
1.23      itojun     94: #include <netinet/ip6.h>
1.27      itojun     95: #include <netinet6/ip6_var.h>
1.2       itojun     96: #include <netinet6/in6_pcb.h>
1.23      itojun     97: #include <netinet/icmp6.h>
1.2       itojun     98: #include <netinet6/udp6_var.h>
1.14      itojun     99: #include <netinet6/ip6protosw.h>
1.2       itojun    100:
                    101: #ifdef IPSEC
                    102: #include <netinet6/ipsec.h>
                    103: #endif /*IPSEC*/
                    104:
                    105: #include "faith.h"
1.30.2.4! he        106: #if defined(NFAITH) && NFAITH > 0
        !           107: #include <net/if_faith.h>
        !           108: #endif
1.2       itojun    109:
                    110: /*
                    111:  * UDP protocol inplementation.
                    112:  * Per RFC 768, August, 1980.
                    113:  */
                    114:
                    115: struct in6pcb *udp6_last_in6pcb = &udb6;
                    116:
1.17      itojun    117: #ifdef UDP6
1.2       itojun    118: static int in6_mcmatch __P((struct in6pcb *, struct in6_addr *, struct ifnet *));
1.14      itojun    119: #endif
1.2       itojun    120: static void udp6_detach __P((struct in6pcb *));
                    121: static void udp6_notify __P((struct in6pcb *, int));
                    122:
                    123: void
                    124: udp6_init()
                    125: {
                    126:        udb6.in6p_next = udb6.in6p_prev = &udb6;
                    127: }
                    128:
1.17      itojun    129: #ifdef UDP6
1.2       itojun    130: static int
                    131: in6_mcmatch(in6p, ia6, ifp)
                    132:        struct in6pcb *in6p;
                    133:        register struct in6_addr *ia6;
                    134:        struct ifnet *ifp;
                    135: {
                    136:        struct ip6_moptions *im6o = in6p->in6p_moptions;
                    137:        struct in6_multi_mship *imm;
                    138:
                    139:        if (im6o == NULL)
                    140:                return 0;
                    141:
                    142:        for (imm = im6o->im6o_memberships.lh_first; imm != NULL;
                    143:             imm = imm->i6mm_chain.le_next) {
                    144:                if ((ifp == NULL ||
                    145:                     imm->i6mm_maddr->in6m_ifp == ifp) &&
                    146:                    IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
                    147:                                       ia6))
                    148:                        return 1;
                    149:        }
                    150:        return 0;
                    151: }
                    152:
                    153: int
                    154: udp6_input(mp, offp, proto)
                    155:        struct mbuf **mp;
                    156:        int *offp, proto;
                    157: {
                    158:        struct mbuf *m = *mp;
                    159:        register struct ip6_hdr *ip6;
                    160:        register struct udphdr *uh;
                    161:        register struct in6pcb *in6p;
                    162:        struct  mbuf *opts = 0;
                    163:        int off = *offp;
1.14      itojun    164:        u_int32_t plen, ulen;
1.2       itojun    165:        struct sockaddr_in6 udp_in6;
                    166:
1.30.2.4! he        167:        ip6 = mtod(m, struct ip6_hdr *);
        !           168:
1.2       itojun    169: #if defined(NFAITH) && 0 < NFAITH
1.30.2.4! he        170:        if (faithprefix(&ip6->ip6_dst)) {
        !           171:                /* send icmp6 host unreach? */
        !           172:                m_freem(m);
        !           173:                return IPPROTO_DONE;
1.2       itojun    174:        }
                    175: #endif
1.30.2.4! he        176:
1.2       itojun    177:        udp6stat.udp6s_ipackets++;
                    178:
1.14      itojun    179:        /* check for jumbogram is done in ip6_input.  we can trust pkthdr.len */
                    180:        plen = m->m_pkthdr.len - off;
                    181: #ifndef PULLDOWN_TEST
1.2       itojun    182:        IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE);
                    183:        uh = (struct udphdr *)((caddr_t)ip6 + off);
1.14      itojun    184: #else
1.24      itojun    185:        IP6_EXTHDR_GET(uh, struct udphdr *, m, off, sizeof(struct udphdr));
1.14      itojun    186:        if (uh == NULL) {
                    187:                udp6stat.udp6s_hdrops++;
                    188:                return IPPROTO_DONE;
                    189:        }
                    190: #endif
1.2       itojun    191:        ulen = ntohs((u_short)uh->uh_ulen);
1.27      itojun    192:        /*
                    193:         * RFC2675 section 4: jumbograms will have 0 in the UDP header field,
                    194:         * iff payload length > 0xffff.
                    195:         */
                    196:        if (ulen == 0 && plen > 0xffff)
1.14      itojun    197:                ulen = plen;
1.2       itojun    198:
                    199:        if (plen != ulen) {
                    200:                udp6stat.udp6s_badlen++;
1.16      itojun    201:                goto bad;
                    202:        }
1.18      itojun    203:
                    204:        /* destination port of 0 is illegal, based on RFC768. */
                    205:        if (uh->uh_dport == 0)
                    206:                goto bad;
1.16      itojun    207:
                    208:        /* Be proactive about malicious use of IPv4 mapped address */
                    209:        if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
                    210:            IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
                    211:                /* XXX stat */
1.2       itojun    212:                goto bad;
                    213:        }
                    214:
                    215:        /*
                    216:         * Checksum extended UDP header and data.
                    217:         */
                    218:        if (uh->uh_sum == 0)
                    219:                udp6stat.udp6s_nosum++;
                    220:        else if (in6_cksum(m, IPPROTO_UDP, off, ulen) != 0) {
                    221:                udp6stat.udp6s_badsum++;
                    222:                goto bad;
                    223:        }
                    224:
                    225:        if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
                    226:                struct  in6pcb *last;
                    227:
                    228:                /*
                    229:                 * Deliver a multicast datagram to all sockets
                    230:                 * for which the local and remote addresses and ports match
                    231:                 * those of the incoming datagram.  This allows more than
                    232:                 * one process to receive multicasts on the same port.
                    233:                 * (This really ought to be done for unicast datagrams as
                    234:                 * well, but that would cause problems with existing
                    235:                 * applications that open both address-specific sockets and
                    236:                 * a wildcard socket listening to the same port -- they would
                    237:                 * end up receiving duplicates of every unicast datagram.
                    238:                 * Those applications open the multiple sockets to overcome an
                    239:                 * inadequacy of the UDP socket interface, but for backwards
                    240:                 * compatibility we avoid the problem here rather than
                    241:                 * fixing the interface.  Maybe 4.5BSD will remedy this?)
                    242:                 */
                    243:
                    244:                /*
                    245:                 * In a case that laddr should be set to the link-local
                    246:                 * address (this happens in RIPng), the multicast address
                    247:                 * specified in the received packet does not match with
                    248:                 * laddr. To cure this situation, the matching is relaxed
                    249:                 * if the receiving interface is the same as one specified
                    250:                 * in the socket and if the destination multicast address
                    251:                 * matches one of the multicast groups specified in the socket.
                    252:                 */
                    253:
1.27      itojun    254:                /*
1.2       itojun    255:                 * Construct sockaddr format source address.
                    256:                 */
                    257:                bzero(&udp_in6, sizeof(udp_in6));
                    258:                udp_in6.sin6_len = sizeof(struct sockaddr_in6);
                    259:                udp_in6.sin6_family = AF_INET6;
                    260:                udp_in6.sin6_port = uh->uh_sport;
                    261:                udp_in6.sin6_addr = ip6->ip6_src;
                    262:                if (IN6_IS_SCOPE_LINKLOCAL(&udp_in6.sin6_addr))
                    263:                        udp_in6.sin6_addr.s6_addr16[1] = 0;
                    264:                if (m->m_pkthdr.rcvif) {
                    265:                        if (IN6_IS_SCOPE_LINKLOCAL(&udp_in6.sin6_addr)) {
                    266:                                udp_in6.sin6_scope_id =
                    267:                                        m->m_pkthdr.rcvif->if_index;
                    268:                        } else
                    269:                                udp_in6.sin6_scope_id = 0;
                    270:                } else
                    271:                        udp_in6.sin6_scope_id = 0;
                    272:                /*
                    273:                 * KAME note: usually we drop udphdr from mbuf here.
                    274:                 * We need udphdr for IPsec processing so we do that later.
                    275:                 */
                    276:
                    277:                /*
                    278:                 * Locate pcb(s) for datagram.
                    279:                 * (Algorithm copied from raw_intr().)
                    280:                 */
                    281:                last = NULL;
                    282:                for (in6p = udb6.in6p_next;
                    283:                     in6p != &udb6;
                    284:                     in6p = in6p->in6p_next) {
                    285:                        if (in6p->in6p_lport != uh->uh_dport)
                    286:                                continue;
1.14      itojun    287:                        if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
1.2       itojun    288:                                if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr,
                    289:                                                        &ip6->ip6_dst) &&
                    290:                                    !in6_mcmatch(in6p, &ip6->ip6_dst,
                    291:                                                 m->m_pkthdr.rcvif))
                    292:                                        continue;
                    293:                        }
1.14      itojun    294:                        if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
1.2       itojun    295:                                if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr,
                    296:                                                        &ip6->ip6_src) ||
                    297:                                   in6p->in6p_fport != uh->uh_sport)
                    298:                                        continue;
                    299:                        }
                    300:
                    301:                        if (last != NULL) {
                    302:                                struct  mbuf *n;
                    303:
                    304: #ifdef IPSEC
                    305:                                /*
                    306:                                 * Check AH/ESP integrity.
                    307:                                 */
1.24      itojun    308:                                if (ipsec6_in_reject(m, last)) {
1.2       itojun    309:                                        ipsec6stat.in_polvio++;
                    310:                                        /* do not inject data into pcb */
                    311:                                } else
                    312: #endif /*IPSEC*/
                    313:                                if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
                    314:                                        /*
                    315:                                         * KAME NOTE: do not
                    316:                                         * m_copy(m, offset, ...) above.
                    317:                                         * sbappendaddr() expects M_PKTHDR,
                    318:                                         * and m_copy() will copy M_PKTHDR
                    319:                                         * only if offset is 0.
                    320:                                         */
1.8       itojun    321:                                        if (last->in6p_flags & IN6P_CONTROLOPTS
                    322:                                         || last->in6p_socket->so_options & SO_TIMESTAMP) {
1.2       itojun    323:                                                ip6_savecontrol(last, &opts,
                    324:                                                                ip6, n);
                    325:                                        }
                    326:
1.11      itojun    327:                                        m_adj(n, off + sizeof(struct udphdr));
1.2       itojun    328:                                        if (sbappendaddr(&last->in6p_socket->so_rcv,
                    329:                                                        (struct sockaddr *)&udp_in6,
                    330:                                                        n, opts) == 0) {
                    331:                                                m_freem(n);
                    332:                                                if (opts)
                    333:                                                        m_freem(opts);
                    334:                                                udp6stat.udp6s_fullsock++;
                    335:                                        } else
                    336:                                                sorwakeup(last->in6p_socket);
                    337:                                        opts = 0;
                    338:                                }
                    339:                        }
                    340:                        last = in6p;
                    341:                        /*
                    342:                         * Don't look for additional matches if this one does
                    343:                         * not have either the SO_REUSEPORT or SO_REUSEADDR
                    344:                         * socket options set.  This heuristic avoids searching
                    345:                         * through all pcbs in the common case of a non-shared
                    346:                         * port.  It assumes that an application will never
                    347:                         * clear these options after setting them.
                    348:                         */
                    349:                        if ((last->in6p_socket->so_options &
                    350:                             (SO_REUSEPORT|SO_REUSEADDR)) == 0)
                    351:                                break;
                    352:                }
                    353:
                    354:                if (last == NULL) {
                    355:                        /*
                    356:                         * No matching pcb found; discard datagram.
                    357:                         * (No need to send an ICMP Port Unreachable
                    358:                         * for a broadcast or multicast datgram.)
                    359:                         */
                    360:                        udp6stat.udp6s_noport++;
                    361:                        udp6stat.udp6s_noportmcast++;
                    362:                        goto bad;
                    363:                }
                    364: #ifdef IPSEC
                    365:                /*
                    366:                 * Check AH/ESP integrity.
                    367:                 */
                    368:                if (last != NULL && ipsec6_in_reject(m, last)) {
                    369:                        ipsec6stat.in_polvio++;
                    370:                        goto bad;
                    371:                }
                    372: #endif /*IPSEC*/
1.8       itojun    373:                if (last->in6p_flags & IN6P_CONTROLOPTS
                    374:                 || last->in6p_socket->so_options & SO_TIMESTAMP) {
1.2       itojun    375:                        ip6_savecontrol(last, &opts, ip6, m);
1.8       itojun    376:                }
1.2       itojun    377:
                    378:                m_adj(m, off + sizeof(struct udphdr));
                    379:                if (sbappendaddr(&last->in6p_socket->so_rcv,
                    380:                                (struct sockaddr *)&udp_in6,
                    381:                                m, opts) == 0) {
                    382:                        udp6stat.udp6s_fullsock++;
                    383:                        goto bad;
                    384:                }
                    385:                sorwakeup(last->in6p_socket);
                    386:                return IPPROTO_DONE;
                    387:        }
                    388:        /*
                    389:         * Locate pcb for datagram.
                    390:         */
                    391:        in6p = udp6_last_in6pcb;
                    392:        if (in6p->in6p_lport != uh->uh_dport ||
                    393:           in6p->in6p_fport != uh->uh_sport ||
                    394:           !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src) ||
                    395:           !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst)) {
                    396:                in6p = in6_pcblookup(&udb6,
                    397:                                     &ip6->ip6_src, uh->uh_sport,
                    398:                                     &ip6->ip6_dst, uh->uh_dport,
                    399:                                     IN6PLOOKUP_WILDCARD);
                    400:                if (in6p)
                    401:                        udp6_last_in6pcb = in6p;
                    402:                udp6stat.udp6ps_pcbcachemiss++;
                    403:        }
                    404:        if (in6p == 0) {
                    405:                udp6stat.udp6s_noport++;
                    406:                if (m->m_flags & M_MCAST) {
                    407:                        printf("UDP6: M_MCAST is set in a unicast packet.\n");
                    408:                        udp6stat.udp6s_noportmcast++;
                    409:                        goto bad;
                    410:                }
                    411:                icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
                    412:                return IPPROTO_DONE;
                    413:        }
                    414: #ifdef IPSEC
                    415:        /*
                    416:         * Check AH/ESP integrity.
                    417:         */
                    418:        if (in6p != NULL && ipsec6_in_reject(m, in6p)) {
                    419:                ipsec6stat.in_polvio++;
                    420:                goto bad;
                    421:        }
                    422: #endif /*IPSEC*/
                    423:
                    424:        /*
                    425:         * Construct sockaddr format source address.
                    426:         * Stuff source address and datagram in user buffer.
                    427:         */
                    428:        bzero(&udp_in6, sizeof(udp_in6));
                    429:        udp_in6.sin6_len = sizeof(struct sockaddr_in6);
                    430:        udp_in6.sin6_family = AF_INET6;
                    431:        udp_in6.sin6_port = uh->uh_sport;
                    432:        udp_in6.sin6_addr = ip6->ip6_src;
                    433:        if (IN6_IS_SCOPE_LINKLOCAL(&udp_in6.sin6_addr))
                    434:                udp_in6.sin6_addr.s6_addr16[1] = 0;
                    435:        if (m->m_pkthdr.rcvif) {
                    436:                if (IN6_IS_SCOPE_LINKLOCAL(&udp_in6.sin6_addr))
                    437:                        udp_in6.sin6_scope_id = m->m_pkthdr.rcvif->if_index;
                    438:                else
                    439:                        udp_in6.sin6_scope_id = 0;
                    440:        } else
                    441:                udp_in6.sin6_scope_id = 0;
1.8       itojun    442:        if (in6p->in6p_flags & IN6P_CONTROLOPTS
                    443:         || in6p->in6p_socket->so_options & SO_TIMESTAMP) {
1.2       itojun    444:                ip6_savecontrol(in6p, &opts, ip6, m);
1.8       itojun    445:        }
1.2       itojun    446:
                    447:        m_adj(m, off + sizeof(struct udphdr));
                    448:        if (sbappendaddr(&in6p->in6p_socket->so_rcv,
                    449:                        (struct sockaddr *)&udp_in6,
                    450:                        m, opts) == 0) {
                    451:                udp6stat.udp6s_fullsock++;
                    452:                goto bad;
                    453:        }
                    454:        sorwakeup(in6p->in6p_socket);
                    455:        return IPPROTO_DONE;
                    456: bad:
                    457:        if (m)
                    458:                m_freem(m);
                    459:        if (opts)
                    460:                m_freem(opts);
                    461:        return IPPROTO_DONE;
                    462: }
1.14      itojun    463: #endif
1.2       itojun    464:
                    465: /*
                    466:  * Notify a udp user of an asynchronous error;
1.27      itojun    467:  * just wake up so that he can collect error status.
1.2       itojun    468:  */
                    469: static void
                    470: udp6_notify(in6p, errno)
                    471:        register struct in6pcb *in6p;
                    472:        int errno;
                    473: {
                    474:        in6p->in6p_socket->so_error = errno;
                    475:        sorwakeup(in6p->in6p_socket);
                    476:        sowwakeup(in6p->in6p_socket);
                    477: }
                    478:
                    479: void
1.14      itojun    480: udp6_ctlinput(cmd, sa, d)
1.2       itojun    481:        int cmd;
                    482:        struct sockaddr *sa;
1.14      itojun    483:        void *d;
1.2       itojun    484: {
                    485:        register struct udphdr *uhp;
                    486:        struct udphdr uh;
1.7       itojun    487:        struct sockaddr_in6 sa6;
1.14      itojun    488:        register struct ip6_hdr *ip6;
                    489:        struct mbuf *m;
                    490:        int off;
1.25      itojun    491:        void (*notify) __P((struct in6pcb *, int)) = udp6_notify;
1.2       itojun    492:
1.10      itojun    493:        if (sa->sa_family != AF_INET6 ||
                    494:            sa->sa_len != sizeof(struct sockaddr_in6))
                    495:                return;
1.14      itojun    496:
1.25      itojun    497:        if ((unsigned)cmd >= PRC_NCMDS)
                    498:                return;
                    499:        if (PRC_IS_REDIRECT(cmd))
                    500:                notify = in6_rtchange, d = NULL;
                    501:        else if (cmd == PRC_HOSTDEAD)
                    502:                d = NULL;
                    503:        else if (inet6ctlerrmap[cmd] == 0)
1.2       itojun    504:                return;
1.7       itojun    505:
1.14      itojun    506:        /* if the parameter is from icmp6, decode it. */
                    507:        if (d != NULL) {
                    508:                struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
                    509:                m = ip6cp->ip6c_m;
                    510:                ip6 = ip6cp->ip6c_ip6;
                    511:                off = ip6cp->ip6c_off;
                    512:        } else {
                    513:                m = NULL;
                    514:                ip6 = NULL;
                    515:        }
                    516:
1.7       itojun    517:        /* translate addresses into internal form */
                    518:        sa6 = *(struct sockaddr_in6 *)sa;
1.22      itojun    519:        if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr) && m && m->m_pkthdr.rcvif)
1.7       itojun    520:                sa6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
                    521:
1.2       itojun    522:        if (ip6) {
                    523:                /*
                    524:                 * XXX: We assume that when IPV6 is non NULL,
                    525:                 * M and OFF are valid.
                    526:                 */
1.7       itojun    527:                struct in6_addr s;
                    528:
                    529:                /* translate addresses into internal form */
1.12      itojun    530:                memcpy(&s, &ip6->ip6_src, sizeof(s));
1.7       itojun    531:                if (IN6_IS_ADDR_LINKLOCAL(&s))
                    532:                        s.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
1.30.2.1  tv        533:
                    534:                /* check if we can safely examine src and dst ports */
                    535:                if (m->m_pkthdr.len < off + sizeof(uh))
                    536:                        return;
1.7       itojun    537:
1.2       itojun    538:                if (m->m_len < off + sizeof(uh)) {
                    539:                        /*
                    540:                         * this should be rare case,
                    541:                         * so we compromise on this copy...
                    542:                         */
                    543:                        m_copydata(m, off, sizeof(uh), (caddr_t)&uh);
                    544:                        uhp = &uh;
                    545:                } else
                    546:                        uhp = (struct udphdr *)(mtod(m, caddr_t) + off);
1.7       itojun    547:                (void) in6_pcbnotify(&udb6, (struct sockaddr *)&sa6,
                    548:                                        uhp->uh_dport, &s,
1.25      itojun    549:                                        uhp->uh_sport, cmd, notify);
1.2       itojun    550:        } else {
1.7       itojun    551:                (void) in6_pcbnotify(&udb6, (struct sockaddr *)&sa6, 0,
1.25      itojun    552:                                        &zeroin6_addr, 0, cmd, notify);
1.2       itojun    553:        }
                    554: }
                    555:
                    556: int
1.29      itojun    557: udp6_output(in6p, m, addr6, control, p)
1.2       itojun    558:        register struct in6pcb *in6p;
                    559:        register struct mbuf *m;
                    560:        struct mbuf *addr6, *control;
1.29      itojun    561:        struct proc *p;
1.2       itojun    562: {
1.14      itojun    563:        register u_int32_t ulen = m->m_pkthdr.len;
                    564:        u_int32_t plen = sizeof(struct udphdr) + ulen;
1.2       itojun    565:        struct ip6_hdr *ip6;
                    566:        struct udphdr *udp6;
1.14      itojun    567:        struct  in6_addr *laddr, *faddr;
                    568:        u_short fport;
                    569:        int error = 0;
1.2       itojun    570:        struct ip6_pktopts opt, *stickyopt = in6p->in6p_outputopts;
1.14      itojun    571:        int priv;
                    572:        int af, hlen;
                    573: #ifdef INET
                    574:        struct ip *ip;
                    575: #endif
1.30      itojun    576:        struct sockaddr_in6 tmp;
1.2       itojun    577:
1.14      itojun    578:        priv = 0;
1.2       itojun    579:        if (p && !suser(p->p_ucred, &p->p_acflag))
                    580:                priv = 1;
                    581:        if (control) {
                    582:                if ((error = ip6_setpktoptions(control, &opt, priv)) != 0)
                    583:                        goto release;
                    584:                in6p->in6p_outputopts = &opt;
                    585:        }
                    586:
                    587:        if (addr6) {
1.14      itojun    588:                /*
                    589:                 * IPv4 version of udp_output calls in_pcbconnect in this case,
                    590:                 * which needs splnet and affects performance.
                    591:                 * Since we saw no essential reason for calling in_pcbconnect,
                    592:                 * we get rid of such kind of logic, and call in6_selectsrc
                    593:                 * and In6_pcbsetport in order to fill in the local address
                    594:                 * and the local port.
                    595:                 */
                    596:                struct sockaddr_in6 *sin6 = mtod(addr6, struct sockaddr_in6 *);
                    597:
                    598:                if (addr6->m_len != sizeof(*sin6)) {
                    599:                        error = EINVAL;
                    600:                        goto release;
                    601:                }
                    602:                if (sin6->sin6_family != AF_INET6) {
                    603:                        error = EAFNOSUPPORT;
                    604:                        goto release;
                    605:                }
                    606:                if (sin6->sin6_port == 0) {
                    607:                        error = EADDRNOTAVAIL;
                    608:                        goto release;
                    609:                }
                    610:
                    611:                if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
1.2       itojun    612:                        error = EISCONN;
                    613:                        goto release;
                    614:                }
1.30      itojun    615:
                    616:                /* protect *sin6 from overwrites */
                    617:                tmp = *sin6;
                    618:                sin6 = &tmp;
1.14      itojun    619:
                    620:                faddr = &sin6->sin6_addr;
                    621:                fport = sin6->sin6_port; /* allow 0 port */
1.2       itojun    622:                /*
1.14      itojun    623:                 * If the scope of the destination is link-local,
1.27      itojun    624:                 * embed the interface index in the address.
1.14      itojun    625:                 *
1.27      itojun    626:                 * XXX advanced-api value overrides sin6_scope_id
1.2       itojun    627:                 */
1.14      itojun    628:                if (IN6_IS_ADDR_LINKLOCAL(faddr) ||
                    629:                    IN6_IS_ADDR_MC_LINKLOCAL(faddr)) {
                    630:                        struct ip6_pktopts *optp = in6p->in6p_outputopts;
                    631:                        struct in6_pktinfo *pi = NULL;
                    632:                        struct ifnet *oifp = NULL;
                    633:                        struct ip6_moptions *mopt = NULL;
                    634:
                    635:                        /*
                    636:                         * XXX Boundary check is assumed to be already done in
                    637:                         * ip6_setpktoptions().
                    638:                         */
                    639:                        if (optp && (pi = optp->ip6po_pktinfo) &&
                    640:                            pi->ipi6_ifindex) {
                    641:                                faddr->s6_addr16[1] = htons(pi->ipi6_ifindex);
                    642:                                oifp = ifindex2ifnet[pi->ipi6_ifindex];
1.27      itojun    643:                        } else if (IN6_IS_ADDR_MULTICAST(faddr) &&
1.14      itojun    644:                                 (mopt = in6p->in6p_moptions) &&
                    645:                                 mopt->im6o_multicast_ifp) {
                    646:                                oifp = mopt->im6o_multicast_ifp;
1.27      itojun    647:                                faddr->s6_addr16[1] = htons(oifp->if_index);
1.14      itojun    648:                        } else if (sin6->sin6_scope_id) {
                    649:                                /* boundary check */
1.27      itojun    650:                                if (sin6->sin6_scope_id < 0
1.14      itojun    651:                                    || if_index < sin6->sin6_scope_id) {
                    652:                                        error = ENXIO;  /* XXX EINVAL? */
                    653:                                        goto release;
                    654:                                }
                    655:                                /* XXX */
                    656:                                faddr->s6_addr16[1] =
                    657:                                        htons(sin6->sin6_scope_id & 0xffff);
                    658:                        }
                    659:                }
                    660:
                    661:                if (!IN6_IS_ADDR_V4MAPPED(faddr)) {
                    662:                        laddr = in6_selectsrc(sin6, in6p->in6p_outputopts,
                    663:                                              in6p->in6p_moptions,
                    664:                                              &in6p->in6p_route,
                    665:                                              &in6p->in6p_laddr, &error);
                    666:                } else
                    667:                        laddr = &in6p->in6p_laddr;      /*XXX*/
                    668:                if (laddr == NULL) {
                    669:                        if (error == 0)
                    670:                                error = EADDRNOTAVAIL;
1.2       itojun    671:                        goto release;
                    672:                }
1.14      itojun    673:                if (in6p->in6p_lport == 0 &&
                    674:                    (error = in6_pcbsetport(laddr, in6p)) != 0)
                    675:                        goto release;
1.2       itojun    676:        } else {
1.14      itojun    677:                if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
1.2       itojun    678:                        error = ENOTCONN;
                    679:                        goto release;
                    680:                }
1.14      itojun    681:                laddr = &in6p->in6p_laddr;
                    682:                faddr = &in6p->in6p_faddr;
                    683:                fport = in6p->in6p_fport;
1.2       itojun    684:        }
1.14      itojun    685:
                    686:        if (!IN6_IS_ADDR_V4MAPPED(faddr)) {
                    687:                af = AF_INET6;
                    688:                hlen = sizeof(struct ip6_hdr);
                    689:        } else {
                    690:                af = AF_INET;
                    691:                hlen = sizeof(struct ip);
                    692:        }
                    693:
1.2       itojun    694:        /*
                    695:         * Calculate data length and get a mbuf
                    696:         * for UDP and IP6 headers.
                    697:         */
1.14      itojun    698:        M_PREPEND(m, hlen + sizeof(struct udphdr), M_DONTWAIT);
1.2       itojun    699:        if (m == 0) {
                    700:                error = ENOBUFS;
                    701:                goto release;
                    702:        }
                    703:
                    704:        /*
                    705:         * Stuff checksum and output datagram.
                    706:         */
1.14      itojun    707:        udp6 = (struct udphdr *)(mtod(m, caddr_t) + hlen);
                    708:        udp6->uh_sport = in6p->in6p_lport; /* lport is always set in the PCB */
                    709:        udp6->uh_dport = fport;
                    710:        if (plen <= 0xffff)
                    711:                udp6->uh_ulen = htons((u_short)plen);
                    712:        else
                    713:                udp6->uh_ulen = 0;
                    714:        udp6->uh_sum = 0;
                    715:
                    716:        switch (af) {
                    717:        case AF_INET6:
                    718:                ip6 = mtod(m, struct ip6_hdr *);
                    719:                ip6->ip6_flow   = in6p->in6p_flowinfo & IPV6_FLOWINFO_MASK;
1.15      itojun    720:                ip6->ip6_vfc    &= ~IPV6_VERSION_MASK;
                    721:                ip6->ip6_vfc    |= IPV6_VERSION;
1.2       itojun    722: #if 0                          /* ip6_plen will be filled in ip6_output. */
1.14      itojun    723:                ip6->ip6_plen   = htons((u_short)plen);
1.2       itojun    724: #endif
1.14      itojun    725:                ip6->ip6_nxt    = IPPROTO_UDP;
                    726:                ip6->ip6_hlim   = in6_selecthlim(in6p,
                    727:                                                 in6p->in6p_route.ro_rt ?
                    728:                                                 in6p->in6p_route.ro_rt->rt_ifp : NULL);
                    729:                ip6->ip6_src    = *laddr;
                    730:                ip6->ip6_dst    = *faddr;
                    731:
                    732:                if ((udp6->uh_sum = in6_cksum(m, IPPROTO_UDP,
                    733:                                sizeof(struct ip6_hdr), plen)) == 0) {
                    734:                        udp6->uh_sum = 0xffff;
                    735:                }
                    736:
                    737:                udp6stat.udp6s_opackets++;
                    738: #ifdef IPSEC
1.30.2.3  he        739:                if (ipsec_setsocket(m, in6p->in6p_socket) != 0) {
                    740:                        error = ENOBUFS;
                    741:                        goto release;
                    742:                }
1.14      itojun    743: #endif /*IPSEC*/
                    744:                error = ip6_output(m, in6p->in6p_outputopts, &in6p->in6p_route,
                    745:                            0, in6p->in6p_moptions, NULL);
                    746:                break;
                    747:        case AF_INET:
                    748: #ifdef INET
                    749:                /* can't transmit jumbogram over IPv4 */
                    750:                if (plen > 0xffff) {
                    751:                        error = EMSGSIZE;
                    752:                        goto release;
                    753:                }
                    754:
                    755:                ip = mtod(m, struct ip *);
1.2       itojun    756:
1.14      itojun    757:                ip->ip_len = plen;
                    758:                ip->ip_p = IPPROTO_UDP;
1.30.2.2  tv        759:                ip->ip_ttl = in6_selecthlim(in6p, NULL);        /*XXX*/
1.14      itojun    760:                ip->ip_tos = 0;                 /*XXX*/
                    761:                bcopy(&laddr->s6_addr[12], &ip->ip_src, sizeof(ip->ip_src));
                    762:                bcopy(&faddr->s6_addr[12], &ip->ip_dst, sizeof(ip->ip_dst));
                    763:
                    764:                udp6->uh_sum = 0;
                    765:                if ((udp6->uh_sum = in_cksum(m, ulen)) == 0)
                    766:                        udp6->uh_sum = 0xffff;
1.2       itojun    767:
1.14      itojun    768:                udpstat.udps_opackets++;
1.2       itojun    769: #ifdef IPSEC
1.30.2.3  he        770:                (void)ipsec_setsocket(m, NULL); /*XXX*/
1.2       itojun    771: #endif /*IPSEC*/
1.14      itojun    772:                error = ip_output(m, NULL, &in6p->in6p_route, 0 /*XXX*/);
                    773:                break;
                    774: #else
                    775:                error = EAFNOSUPPORT;
                    776:                goto release;
                    777: #endif
1.2       itojun    778:        }
                    779:        goto releaseopt;
                    780:
                    781: release:
                    782:        m_freem(m);
                    783:
                    784: releaseopt:
                    785:        if (control) {
                    786:                in6p->in6p_outputopts = stickyopt;
                    787:                m_freem(control);
                    788:        }
                    789:        return(error);
                    790: }
                    791:
                    792: extern int udp6_sendspace;
                    793: extern int udp6_recvspace;
                    794:
                    795: int
                    796: udp6_usrreq(so, req, m, addr6, control, p)
                    797:        struct socket *so;
                    798:        int req;
                    799:        struct mbuf *m, *addr6, *control;
                    800:        struct proc *p;
                    801: {
                    802:        struct  in6pcb *in6p = sotoin6pcb(so);
                    803:        int     error = 0;
                    804:        int     s;
                    805:
1.27      itojun    806:        /*
1.2       itojun    807:         * MAPPED_ADDR implementation info:
                    808:         *  Mapped addr support for PRU_CONTROL is not necessary.
                    809:         *  Because typical user of PRU_CONTROL is such as ifconfig,
                    810:         *  and they don't associate any addr to their socket.  Then
                    811:         *  socket family is only hint about the PRU_CONTROL'ed address
                    812:         *  family, especially when getting addrs from kernel.
                    813:         *  So AF_INET socket need to be used to control AF_INET addrs,
                    814:         *  and AF_INET6 socket for AF_INET6 addrs.
                    815:         */
                    816:        if (req == PRU_CONTROL)
                    817:                return(in6_control(so, (u_long)m, (caddr_t)addr6,
                    818:                                   (struct ifnet *)control, p));
1.20      thorpej   819:
1.21      thorpej   820:        if (req == PRU_PURGEIF) {
                    821:                in6_purgeif((struct ifnet *)control);
                    822:                in6_pcbpurgeif(&udb6, (struct ifnet *)control);
1.20      thorpej   823:                return (0);
                    824:        }
1.2       itojun    825:
                    826:        if (in6p == NULL && req != PRU_ATTACH) {
                    827:                error = EINVAL;
                    828:                goto release;
                    829:        }
                    830:
                    831:        switch (req) {
                    832:        case PRU_ATTACH:
                    833:                /*
                    834:                 * MAPPED_ADDR implementation spec:
1.27      itojun    835:                 *  Always attach for IPv6,
1.2       itojun    836:                 *  and only when necessary for IPv4.
                    837:                 */
                    838:                if (in6p != NULL) {
                    839:                        error = EINVAL;
                    840:                        break;
                    841:                }
1.4       itojun    842:                s = splsoftnet();
1.2       itojun    843:                error = in6_pcballoc(so, &udb6);
                    844:                splx(s);
                    845:                if (error)
                    846:                        break;
                    847:                error = soreserve(so, udp6_sendspace, udp6_recvspace);
                    848:                if (error)
                    849:                        break;
                    850:                in6p = sotoin6pcb(so);
                    851:                in6p->in6p_cksum = -1;  /* just to be sure */
                    852: #ifdef IPSEC
1.19      itojun    853:                error = ipsec_init_policy(so, &in6p->in6p_sp);
1.14      itojun    854:                if (error != 0) {
1.13      itojun    855:                        in6_pcbdetach(in6p);
1.14      itojun    856:                        break;
                    857:                }
1.2       itojun    858: #endif /*IPSEC*/
                    859:                break;
                    860:
                    861:        case PRU_DETACH:
                    862:                udp6_detach(in6p);
                    863:                break;
                    864:
                    865:        case PRU_BIND:
1.4       itojun    866:                s = splsoftnet();
1.29      itojun    867:                error = in6_pcbbind(in6p, addr6, p);
1.2       itojun    868:                splx(s);
                    869:                break;
                    870:
                    871:        case PRU_LISTEN:
                    872:                error = EOPNOTSUPP;
                    873:                break;
                    874:
                    875:        case PRU_CONNECT:
1.14      itojun    876:                if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
1.2       itojun    877:                        error = EISCONN;
                    878:                        break;
                    879:                }
1.4       itojun    880:                s = splsoftnet();
1.2       itojun    881:                error = in6_pcbconnect(in6p, addr6);
                    882:                if (ip6_auto_flowlabel) {
                    883:                        in6p->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
1.27      itojun    884:                        in6p->in6p_flowinfo |=
1.2       itojun    885:                                (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK);
                    886:                }
                    887:                splx(s);
                    888:                if (error == 0)
                    889:                        soisconnected(so);
                    890:                break;
                    891:
                    892:        case PRU_CONNECT2:
                    893:                error = EOPNOTSUPP;
                    894:                break;
                    895:
                    896:        case PRU_ACCEPT:
                    897:                error = EOPNOTSUPP;
                    898:                break;
                    899:
                    900:        case PRU_DISCONNECT:
                    901:                if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
                    902:                        error = ENOTCONN;
                    903:                        break;
                    904:                }
1.4       itojun    905:                s = splsoftnet();
1.2       itojun    906:                in6_pcbdisconnect(in6p);
                    907:                bzero((caddr_t)&in6p->in6p_laddr, sizeof(in6p->in6p_laddr));
                    908:                splx(s);
                    909:                so->so_state &= ~SS_ISCONNECTED;                /* XXX */
                    910:                break;
                    911:
                    912:        case PRU_SHUTDOWN:
                    913:                socantsendmore(so);
                    914:                break;
                    915:
                    916:        case PRU_SEND:
1.29      itojun    917:                return(udp6_output(in6p, m, addr6, control, p));
1.2       itojun    918:
                    919:        case PRU_ABORT:
                    920:                soisdisconnected(so);
                    921:                udp6_detach(in6p);
                    922:                break;
                    923:
                    924:        case PRU_SOCKADDR:
                    925:                in6_setsockaddr(in6p, addr6);
                    926:                break;
                    927:
                    928:        case PRU_PEERADDR:
                    929:                in6_setpeeraddr(in6p, addr6);
                    930:                break;
                    931:
                    932:        case PRU_SENSE:
                    933:                /*
                    934:                 * stat: don't bother with a blocksize
                    935:                 */
                    936:                return(0);
                    937:
                    938:        case PRU_SENDOOB:
                    939:        case PRU_FASTTIMO:
                    940:        case PRU_SLOWTIMO:
                    941:        case PRU_PROTORCV:
                    942:        case PRU_PROTOSEND:
                    943:                error = EOPNOTSUPP;
                    944:                break;
                    945:
                    946:        case PRU_RCVD:
                    947:        case PRU_RCVOOB:
                    948:                return(EOPNOTSUPP);     /* do not free mbuf's */
                    949:
                    950:        default:
                    951:                panic("udp6_usrreq");
                    952:        }
                    953:
                    954: release:
                    955:        if (control) {
                    956:                printf("udp control data unexpectedly retained\n");
                    957:                m_freem(control);
                    958:        }
                    959:        if (m)
                    960:                m_freem(m);
                    961:        return(error);
                    962: }
                    963:
                    964: static void
                    965: udp6_detach(in6p)
                    966:        struct in6pcb *in6p;
                    967: {
1.27      itojun    968:        int s = splsoftnet();
1.2       itojun    969:
                    970:        if (in6p == udp6_last_in6pcb)
                    971:                udp6_last_in6pcb = &udb6;
                    972:        in6_pcbdetach(in6p);
                    973:        splx(s);
                    974: }
                    975:
                    976: #include <vm/vm.h>
                    977: #include <sys/sysctl.h>
                    978:
                    979: int
                    980: udp6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
                    981:        int *name;
                    982:        u_int namelen;
                    983:        void *oldp;
                    984:        size_t *oldlenp;
                    985:        void *newp;
                    986:        size_t newlen;
                    987: {
                    988:        /* All sysctl names at this level are terminal. */
                    989:        if (namelen != 1)
                    990:                return ENOTDIR;
                    991:
                    992:        switch (name[0]) {
                    993:
1.28      itojun    994:        case UDP6CTL_SENDSPACE:
1.2       itojun    995:                return sysctl_int(oldp, oldlenp, newp, newlen,
                    996:                    &udp6_sendspace);
                    997:        case UDP6CTL_RECVSPACE:
1.27      itojun    998:                return sysctl_int(oldp, oldlenp, newp, newlen,
1.2       itojun    999:                    &udp6_recvspace);
                   1000:        default:
                   1001:                return ENOPROTOOPT;
                   1002:        }
                   1003:        /* NOTREACHED */
                   1004: }

CVSweb <webmaster@jp.NetBSD.org>