[BACK]Return to udp_usrreq.c CVS log [TXT][DIR] Up to [local] / sys / netinet

Annotation of sys/netinet/udp_usrreq.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: udp_usrreq.c,v 1.114 2007/06/11 11:29:35 henning Exp $        */
        !             2: /*     $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1982, 1986, 1988, 1990, 1993
        !             6:  *     The Regents of the University of California.  All rights reserved.
        !             7:  *
        !             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 University 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.
        !            19:  *
        !            20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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:  *     @(#)COPYRIGHT   1.1 (NRL) 17 January 1995
        !            33:  *
        !            34:  * NRL grants permission for redistribution and use in source and binary
        !            35:  * forms, with or without modification, of the software and documentation
        !            36:  * created at NRL provided that the following conditions are met:
        !            37:  *
        !            38:  * 1. Redistributions of source code must retain the above copyright
        !            39:  *    notice, this list of conditions and the following disclaimer.
        !            40:  * 2. Redistributions in binary form must reproduce the above copyright
        !            41:  *    notice, this list of conditions and the following disclaimer in the
        !            42:  *    documentation and/or other materials provided with the distribution.
        !            43:  * 3. All advertising materials mentioning features or use of this software
        !            44:  *    must display the following acknowledgements:
        !            45:  *     This product includes software developed by the University of
        !            46:  *     California, Berkeley and its contributors.
        !            47:  *     This product includes software developed at the Information
        !            48:  *     Technology Division, US Naval Research Laboratory.
        !            49:  * 4. Neither the name of the NRL 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:  * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
        !            54:  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            55:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
        !            56:  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL NRL OR
        !            57:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
        !            58:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
        !            59:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
        !            60:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
        !            61:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
        !            62:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
        !            63:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            64:  *
        !            65:  * The views and conclusions contained in the software and documentation
        !            66:  * are those of the authors and should not be interpreted as representing
        !            67:  * official policies, either expressed or implied, of the US Naval
        !            68:  * Research Laboratory (NRL).
        !            69:  */
        !            70:
        !            71: #include <sys/param.h>
        !            72: #include <sys/systm.h>
        !            73: #include <sys/mbuf.h>
        !            74: #include <sys/protosw.h>
        !            75: #include <sys/socket.h>
        !            76: #include <sys/socketvar.h>
        !            77: #include <sys/sysctl.h>
        !            78:
        !            79: #include <net/if.h>
        !            80: #include <net/route.h>
        !            81:
        !            82: #include <netinet/in.h>
        !            83: #include <netinet/in_systm.h>
        !            84: #include <netinet/in_var.h>
        !            85: #include <netinet/ip.h>
        !            86: #include <netinet/in_pcb.h>
        !            87: #include <netinet/ip_var.h>
        !            88: #include <netinet/ip_icmp.h>
        !            89: #include <netinet/udp.h>
        !            90: #include <netinet/udp_var.h>
        !            91:
        !            92: #ifdef IPSEC
        !            93: #include <netinet/ip_ipsp.h>
        !            94: #include <netinet/ip_esp.h>
        !            95: #endif
        !            96:
        !            97: #ifdef INET6
        !            98: #ifndef INET
        !            99: #include <netinet/in.h>
        !           100: #endif
        !           101: #include <netinet6/ip6protosw.h>
        !           102:
        !           103: extern int ip6_defhlim;
        !           104: #endif /* INET6 */
        !           105:
        !           106: /*
        !           107:  * UDP protocol implementation.
        !           108:  * Per RFC 768, August, 1980.
        !           109:  */
        !           110: int    udpcksum = 1;
        !           111:
        !           112: u_int  udp_sendspace = 9216;           /* really max datagram size */
        !           113: u_int  udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
        !           114:                                        /* 40 1K datagrams */
        !           115:
        !           116: int *udpctl_vars[UDPCTL_MAXID] = UDPCTL_VARS;
        !           117:
        !           118: struct inpcbtable udbtable;
        !           119: struct udpstat udpstat;
        !           120:
        !           121: void udp_detach(struct inpcb *);
        !           122: void udp_notify(struct inpcb *, int);
        !           123:
        !           124: #ifndef UDBHASHSIZE
        !           125: #define        UDBHASHSIZE     128
        !           126: #endif
        !           127: int    udbhashsize = UDBHASHSIZE;
        !           128:
        !           129: /* from in_pcb.c */
        !           130: extern struct baddynamicports baddynamicports;
        !           131:
        !           132: void
        !           133: udp_init()
        !           134: {
        !           135:        in_pcbinit(&udbtable, udbhashsize);
        !           136: }
        !           137:
        !           138: #ifdef INET6
        !           139: int
        !           140: udp6_input(mp, offp, proto)
        !           141:        struct mbuf **mp;
        !           142:        int *offp, proto;
        !           143: {
        !           144:        struct mbuf *m = *mp;
        !           145:
        !           146: #if defined(NFAITH) && 0 < NFAITH
        !           147:        if (m->m_pkthdr.rcvif) {
        !           148:                if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
        !           149:                        /* XXX send icmp6 host/port unreach? */
        !           150:                        m_freem(m);
        !           151:                        return IPPROTO_DONE;
        !           152:                }
        !           153:        }
        !           154: #endif
        !           155:
        !           156:        udp_input(m, *offp, proto);
        !           157:        return IPPROTO_DONE;
        !           158: }
        !           159: #endif
        !           160:
        !           161: void
        !           162: udp_input(struct mbuf *m, ...)
        !           163: {
        !           164:        struct ip *ip;
        !           165:        struct udphdr *uh;
        !           166:        struct inpcb *inp;
        !           167:        struct mbuf *opts = NULL;
        !           168:        struct ip save_ip;
        !           169:        int iphlen, len;
        !           170:        va_list ap;
        !           171:        u_int16_t savesum;
        !           172:        union {
        !           173:                struct sockaddr sa;
        !           174:                struct sockaddr_in sin;
        !           175: #ifdef INET6
        !           176:                struct sockaddr_in6 sin6;
        !           177: #endif /* INET6 */
        !           178:        } srcsa, dstsa;
        !           179: #ifdef INET6
        !           180:        struct ip6_hdr *ip6;
        !           181: #endif /* INET6 */
        !           182: #ifdef IPSEC
        !           183:        struct m_tag *mtag;
        !           184:        struct tdb_ident *tdbi;
        !           185:        struct tdb *tdb;
        !           186:        int error, s;
        !           187: #endif /* IPSEC */
        !           188:
        !           189:        va_start(ap, m);
        !           190:        iphlen = va_arg(ap, int);
        !           191:        va_end(ap);
        !           192:
        !           193:        udpstat.udps_ipackets++;
        !           194:
        !           195:        switch (mtod(m, struct ip *)->ip_v) {
        !           196:        case 4:
        !           197:                ip = mtod(m, struct ip *);
        !           198: #ifdef INET6
        !           199:                ip6 = NULL;
        !           200: #endif /* INET6 */
        !           201:                srcsa.sa.sa_family = AF_INET;
        !           202:                break;
        !           203: #ifdef INET6
        !           204:        case 6:
        !           205:                ip = NULL;
        !           206:                ip6 = mtod(m, struct ip6_hdr *);
        !           207:                srcsa.sa.sa_family = AF_INET6;
        !           208:                break;
        !           209: #endif /* INET6 */
        !           210:        default:
        !           211:                goto bad;
        !           212:        }
        !           213:
        !           214:        IP6_EXTHDR_GET(uh, struct udphdr *, m, iphlen, sizeof(struct udphdr));
        !           215:        if (!uh) {
        !           216:                udpstat.udps_hdrops++;
        !           217:                return;
        !           218:        }
        !           219:
        !           220:        /* Check for illegal destination port 0 */
        !           221:        if (uh->uh_dport == 0) {
        !           222:                udpstat.udps_noport++;
        !           223:                goto bad;
        !           224:        }
        !           225:
        !           226:        /*
        !           227:         * Make mbuf data length reflect UDP length.
        !           228:         * If not enough data to reflect UDP length, drop.
        !           229:         */
        !           230:        len = ntohs((u_int16_t)uh->uh_ulen);
        !           231:        if (ip) {
        !           232:                if (m->m_pkthdr.len - iphlen != len) {
        !           233:                        if (len > (m->m_pkthdr.len - iphlen) ||
        !           234:                            len < sizeof(struct udphdr)) {
        !           235:                                udpstat.udps_badlen++;
        !           236:                                goto bad;
        !           237:                        }
        !           238:                        m_adj(m, len - (m->m_pkthdr.len - iphlen));
        !           239:                }
        !           240:        }
        !           241: #ifdef INET6
        !           242:        else if (ip6) {
        !           243:                /* jumbograms */
        !           244:                if (len == 0 && m->m_pkthdr.len - iphlen > 0xffff)
        !           245:                        len = m->m_pkthdr.len - iphlen;
        !           246:                if (len != m->m_pkthdr.len - iphlen) {
        !           247:                        udpstat.udps_badlen++;
        !           248:                        goto bad;
        !           249:                }
        !           250:        }
        !           251: #endif
        !           252:        else /* shouldn't happen */
        !           253:                goto bad;
        !           254:
        !           255:        /*
        !           256:         * Save a copy of the IP header in case we want restore it
        !           257:         * for sending an ICMP error message in response.
        !           258:         */
        !           259:        if (ip)
        !           260:                save_ip = *ip;
        !           261:
        !           262:        /*
        !           263:         * Checksum extended UDP header and data.
        !           264:         * from W.R.Stevens: check incoming udp cksums even if
        !           265:         *      udpcksum is not set.
        !           266:         */
        !           267:        savesum = uh->uh_sum;
        !           268: #ifdef INET6
        !           269:        if (ip6) {
        !           270:                /* Be proactive about malicious use of IPv4 mapped address */
        !           271:                if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
        !           272:                    IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) {
        !           273:                        /* XXX stat */
        !           274:                        goto bad;
        !           275:                }
        !           276:
        !           277:                /*
        !           278:                 * In IPv6, the UDP checksum is ALWAYS used.
        !           279:                 */
        !           280:                if (uh->uh_sum == 0) {
        !           281:                        udpstat.udps_nosum++;
        !           282:                        goto bad;
        !           283:                }
        !           284:                if ((uh->uh_sum = in6_cksum(m, IPPROTO_UDP, iphlen, len))) {
        !           285:                        udpstat.udps_badsum++;
        !           286:                        goto bad;
        !           287:                }
        !           288:        } else
        !           289: #endif /* INET6 */
        !           290:        if (uh->uh_sum) {
        !           291:                if ((m->m_pkthdr.csum_flags & M_UDP_CSUM_IN_OK) == 0) {
        !           292:                        if (m->m_pkthdr.csum_flags & M_UDP_CSUM_IN_BAD) {
        !           293:                                udpstat.udps_badsum++;
        !           294:                                udpstat.udps_inhwcsum++;
        !           295:                                m_freem(m);
        !           296:                                return;
        !           297:                        }
        !           298:
        !           299:                        if ((uh->uh_sum = in4_cksum(m, IPPROTO_UDP,
        !           300:                            iphlen, len))) {
        !           301:                                udpstat.udps_badsum++;
        !           302:                                m_freem(m);
        !           303:                                return;
        !           304:                        }
        !           305:                } else {
        !           306:                        m->m_pkthdr.csum_flags &= ~M_UDP_CSUM_IN_OK;
        !           307:                        udpstat.udps_inhwcsum++;
        !           308:                }
        !           309:        } else
        !           310:                udpstat.udps_nosum++;
        !           311:
        !           312: #ifdef IPSEC
        !           313:        if (udpencap_enable && udpencap_port &&
        !           314:            uh->uh_dport == htons(udpencap_port)) {
        !           315:                u_int32_t spi;
        !           316:                int skip = iphlen + sizeof(struct udphdr);
        !           317:
        !           318:                if (m->m_pkthdr.len - skip < sizeof(u_int32_t)) {
        !           319:                        /* packet too short */
        !           320:                        m_freem(m);
        !           321:                        return;
        !           322:                }
        !           323:                m_copydata(m, skip, sizeof(u_int32_t), (caddr_t) &spi);
        !           324:                /*
        !           325:                 * decapsulate if the SPI is not zero, otherwise pass
        !           326:                 * to userland
        !           327:                 */
        !           328:                if (spi != 0) {
        !           329:                        if ((m = m_pullup2(m, skip)) == NULL) {
        !           330:                                udpstat.udps_hdrops++;
        !           331:                                return;
        !           332:                        }
        !           333:
        !           334:                        /* remove the UDP header */
        !           335:                        bcopy(mtod(m, u_char *),
        !           336:                            mtod(m, u_char *) + sizeof(struct udphdr), iphlen);
        !           337:                        m_adj(m, sizeof(struct udphdr));
        !           338:                        skip -= sizeof(struct udphdr);
        !           339:
        !           340:                        espstat.esps_udpencin++;
        !           341:                        ipsec_common_input(m, skip, offsetof(struct ip, ip_p),
        !           342:                            srcsa.sa.sa_family, IPPROTO_ESP, 1);
        !           343:                        return;
        !           344:                }
        !           345:        }
        !           346: #endif
        !           347:
        !           348:        switch (srcsa.sa.sa_family) {
        !           349:        case AF_INET:
        !           350:                bzero(&srcsa, sizeof(struct sockaddr_in));
        !           351:                srcsa.sin.sin_len = sizeof(struct sockaddr_in);
        !           352:                srcsa.sin.sin_family = AF_INET;
        !           353:                srcsa.sin.sin_port = uh->uh_sport;
        !           354:                srcsa.sin.sin_addr = ip->ip_src;
        !           355:
        !           356:                bzero(&dstsa, sizeof(struct sockaddr_in));
        !           357:                dstsa.sin.sin_len = sizeof(struct sockaddr_in);
        !           358:                dstsa.sin.sin_family = AF_INET;
        !           359:                dstsa.sin.sin_port = uh->uh_dport;
        !           360:                dstsa.sin.sin_addr = ip->ip_dst;
        !           361:                break;
        !           362: #ifdef INET6
        !           363:        case AF_INET6:
        !           364:                bzero(&srcsa, sizeof(struct sockaddr_in6));
        !           365:                srcsa.sin6.sin6_len = sizeof(struct sockaddr_in6);
        !           366:                srcsa.sin6.sin6_family = AF_INET6;
        !           367:                srcsa.sin6.sin6_port = uh->uh_sport;
        !           368: #if 0 /*XXX inbound flowinfo */
        !           369:                srcsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ip6->ip6_flow;
        !           370: #endif
        !           371:                /* KAME hack: recover scopeid */
        !           372:                (void)in6_recoverscope(&srcsa.sin6, &ip6->ip6_src,
        !           373:                    m->m_pkthdr.rcvif);
        !           374:
        !           375:                bzero(&dstsa, sizeof(struct sockaddr_in6));
        !           376:                dstsa.sin6.sin6_len = sizeof(struct sockaddr_in6);
        !           377:                dstsa.sin6.sin6_family = AF_INET6;
        !           378:                dstsa.sin6.sin6_port = uh->uh_dport;
        !           379:                /* KAME hack: recover scopeid */
        !           380:                (void)in6_recoverscope(&dstsa.sin6, &ip6->ip6_dst,
        !           381:                    m->m_pkthdr.rcvif);
        !           382:                break;
        !           383: #endif /* INET6 */
        !           384:        }
        !           385:
        !           386: #ifdef INET6
        !           387:        if ((ip6 && IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) ||
        !           388:            (ip && IN_MULTICAST(ip->ip_dst.s_addr)) ||
        !           389:            (ip && in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif))) {
        !           390: #else /* INET6 */
        !           391:        if (IN_MULTICAST(ip->ip_dst.s_addr) ||
        !           392:            in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
        !           393: #endif /* INET6 */
        !           394:                struct inpcb *last;
        !           395:                /*
        !           396:                 * Deliver a multicast or broadcast datagram to *all* sockets
        !           397:                 * for which the local and remote addresses and ports match
        !           398:                 * those of the incoming datagram.  This allows more than
        !           399:                 * one process to receive multi/broadcasts on the same port.
        !           400:                 * (This really ought to be done for unicast datagrams as
        !           401:                 * well, but that would cause problems with existing
        !           402:                 * applications that open both address-specific sockets and
        !           403:                 * a wildcard socket listening to the same port -- they would
        !           404:                 * end up receiving duplicates of every unicast datagram.
        !           405:                 * Those applications open the multiple sockets to overcome an
        !           406:                 * inadequacy of the UDP socket interface, but for backwards
        !           407:                 * compatibility we avoid the problem here rather than
        !           408:                 * fixing the interface.  Maybe 4.5BSD will remedy this?)
        !           409:                 */
        !           410:
        !           411:                iphlen += sizeof(struct udphdr);
        !           412:
        !           413:                /*
        !           414:                 * Locate pcb(s) for datagram.
        !           415:                 * (Algorithm copied from raw_intr().)
        !           416:                 */
        !           417:                last = NULL;
        !           418:                CIRCLEQ_FOREACH(inp, &udbtable.inpt_queue, inp_queue) {
        !           419: #ifdef INET6
        !           420:                        /* don't accept it if AF does not match */
        !           421:                        if (ip6 && !(inp->inp_flags & INP_IPV6))
        !           422:                                continue;
        !           423:                        if (!ip6 && (inp->inp_flags & INP_IPV6))
        !           424:                                continue;
        !           425: #endif
        !           426:                        if (inp->inp_lport != uh->uh_dport)
        !           427:                                continue;
        !           428: #ifdef INET6
        !           429:                        if (ip6) {
        !           430:                                if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6))
        !           431:                                        if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6,
        !           432:                                            &ip6->ip6_dst))
        !           433:                                                continue;
        !           434:                        } else
        !           435: #endif /* INET6 */
        !           436:                        if (inp->inp_laddr.s_addr != INADDR_ANY) {
        !           437:                                if (inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
        !           438:                                        continue;
        !           439:                        }
        !           440: #ifdef INET6
        !           441:                        if (ip6) {
        !           442:                                if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
        !           443:                                        if (!IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6,
        !           444:                                            &ip6->ip6_src) ||
        !           445:                                            inp->inp_fport != uh->uh_sport)
        !           446:                                                continue;
        !           447:                        } else
        !           448: #endif /* INET6 */
        !           449:                        if (inp->inp_faddr.s_addr != INADDR_ANY) {
        !           450:                                if (inp->inp_faddr.s_addr !=
        !           451:                                    ip->ip_src.s_addr ||
        !           452:                                    inp->inp_fport != uh->uh_sport)
        !           453:                                        continue;
        !           454:                        }
        !           455:
        !           456:                        if (last != NULL) {
        !           457:                                struct mbuf *n;
        !           458:
        !           459:                                if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
        !           460: #ifdef INET6
        !           461:                                        if (ip6 && (last->inp_flags &
        !           462:                                            IN6P_CONTROLOPTS))
        !           463:                                                ip6_savecontrol(last, n, &opts);
        !           464: #endif /* INET6 */
        !           465:                                        if (ip && (last->inp_flags &
        !           466:                                            INP_CONTROLOPTS))
        !           467:                                                ip_savecontrol(last, &opts,
        !           468:                                                    ip, n);
        !           469:
        !           470:                                        m_adj(n, iphlen);
        !           471:                                        if (sbappendaddr(
        !           472:                                            &last->inp_socket->so_rcv,
        !           473:                                            &srcsa.sa, n, opts) == 0) {
        !           474:                                                m_freem(n);
        !           475:                                                if (opts)
        !           476:                                                        m_freem(opts);
        !           477:                                                udpstat.udps_fullsock++;
        !           478:                                        } else
        !           479:                                                sorwakeup(last->inp_socket);
        !           480:                                        opts = NULL;
        !           481:                                }
        !           482:                        }
        !           483:                        last = inp;
        !           484:                        /*
        !           485:                         * Don't look for additional matches if this one does
        !           486:                         * not have either the SO_REUSEPORT or SO_REUSEADDR
        !           487:                         * socket options set.  This heuristic avoids searching
        !           488:                         * through all pcbs in the common case of a non-shared
        !           489:                         * port.  It * assumes that an application will never
        !           490:                         * clear these options after setting them.
        !           491:                         */
        !           492:                        if ((last->inp_socket->so_options & (SO_REUSEPORT |
        !           493:                            SO_REUSEADDR)) == 0)
        !           494:                                break;
        !           495:                }
        !           496:
        !           497:                if (last == NULL) {
        !           498:                        /*
        !           499:                         * No matching pcb found; discard datagram.
        !           500:                         * (No need to send an ICMP Port Unreachable
        !           501:                         * for a broadcast or multicast datgram.)
        !           502:                         */
        !           503:                        udpstat.udps_noportbcast++;
        !           504:                        goto bad;
        !           505:                }
        !           506:
        !           507: #ifdef INET6
        !           508:                if (ip6 && (last->inp_flags & IN6P_CONTROLOPTS))
        !           509:                        ip6_savecontrol(last, m, &opts);
        !           510: #endif /* INET6 */
        !           511:                if (ip && (last->inp_flags & INP_CONTROLOPTS))
        !           512:                        ip_savecontrol(last, &opts, ip, m);
        !           513:
        !           514:                m_adj(m, iphlen);
        !           515:                if (sbappendaddr(&last->inp_socket->so_rcv,
        !           516:                    &srcsa.sa, m, opts) == 0) {
        !           517:                        udpstat.udps_fullsock++;
        !           518:                        goto bad;
        !           519:                }
        !           520:                sorwakeup(last->inp_socket);
        !           521:                return;
        !           522:        }
        !           523:        /*
        !           524:         * Locate pcb for datagram.
        !           525:         */
        !           526: #ifdef INET6
        !           527:        if (ip6)
        !           528:                inp = in6_pcbhashlookup(&udbtable, &ip6->ip6_src, uh->uh_sport,
        !           529:                    &ip6->ip6_dst, uh->uh_dport);
        !           530:        else
        !           531: #endif /* INET6 */
        !           532:        inp = in_pcbhashlookup(&udbtable, ip->ip_src, uh->uh_sport,
        !           533:            ip->ip_dst, uh->uh_dport);
        !           534:        if (inp == 0) {
        !           535:                int     inpl_reverse = 0;
        !           536:                if (m->m_pkthdr.pf.flags & PF_TAG_TRANSLATE_LOCALHOST)
        !           537:                        inpl_reverse = 1;
        !           538:                ++udpstat.udps_pcbhashmiss;
        !           539: #ifdef INET6
        !           540:                if (ip6) {
        !           541:                        inp = in6_pcblookup_listen(&udbtable,
        !           542:                            &ip6->ip6_dst, uh->uh_dport, inpl_reverse);
        !           543:                } else
        !           544: #endif /* INET6 */
        !           545:                inp = in_pcblookup_listen(&udbtable,
        !           546:                    ip->ip_dst, uh->uh_dport, inpl_reverse);
        !           547:                if (inp == 0) {
        !           548:                        udpstat.udps_noport++;
        !           549:                        if (m->m_flags & (M_BCAST | M_MCAST)) {
        !           550:                                udpstat.udps_noportbcast++;
        !           551:                                goto bad;
        !           552:                        }
        !           553: #ifdef INET6
        !           554:                        if (ip6) {
        !           555:                                uh->uh_sum = savesum;
        !           556:                                icmp6_error(m, ICMP6_DST_UNREACH,
        !           557:                                    ICMP6_DST_UNREACH_NOPORT,0);
        !           558:                        } else
        !           559: #endif /* INET6 */
        !           560:                        {
        !           561:                                *ip = save_ip;
        !           562:                                uh->uh_sum = savesum;
        !           563:                                icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT,
        !           564:                                    0, 0);
        !           565:                        }
        !           566:                        return;
        !           567:                }
        !           568:        }
        !           569:
        !           570: #ifdef IPSEC
        !           571:        mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL);
        !           572:        s = splnet();
        !           573:        if (mtag != NULL) {
        !           574:                tdbi = (struct tdb_ident *)(mtag + 1);
        !           575:                tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto);
        !           576:        } else
        !           577:                tdb = NULL;
        !           578:        ipsp_spd_lookup(m, srcsa.sa.sa_family, iphlen, &error,
        !           579:            IPSP_DIRECTION_IN, tdb, inp);
        !           580:        if (error) {
        !           581:                splx(s);
        !           582:                goto bad;
        !           583:        }
        !           584:
        !           585:        /* Latch SA only if the socket is connected */
        !           586:        if (inp->inp_tdb_in != tdb &&
        !           587:            (inp->inp_socket->so_state & SS_ISCONNECTED)) {
        !           588:                if (tdb) {
        !           589:                        tdb_add_inp(tdb, inp, 1);
        !           590:                        if (inp->inp_ipo == NULL) {
        !           591:                                inp->inp_ipo = ipsec_add_policy(inp,
        !           592:                                    srcsa.sa.sa_family, IPSP_DIRECTION_OUT);
        !           593:                                if (inp->inp_ipo == NULL) {
        !           594:                                        splx(s);
        !           595:                                        goto bad;
        !           596:                                }
        !           597:                        }
        !           598:                        if (inp->inp_ipo->ipo_dstid == NULL &&
        !           599:                            tdb->tdb_srcid != NULL) {
        !           600:                                inp->inp_ipo->ipo_dstid = tdb->tdb_srcid;
        !           601:                                tdb->tdb_srcid->ref_count++;
        !           602:                        }
        !           603:                        if (inp->inp_ipsec_remotecred == NULL &&
        !           604:                            tdb->tdb_remote_cred != NULL) {
        !           605:                                inp->inp_ipsec_remotecred =
        !           606:                                    tdb->tdb_remote_cred;
        !           607:                                tdb->tdb_remote_cred->ref_count++;
        !           608:                        }
        !           609:                        if (inp->inp_ipsec_remoteauth == NULL &&
        !           610:                            tdb->tdb_remote_auth != NULL) {
        !           611:                                inp->inp_ipsec_remoteauth =
        !           612:                                    tdb->tdb_remote_auth;
        !           613:                                tdb->tdb_remote_auth->ref_count++;
        !           614:                        }
        !           615:                } else { /* Just reset */
        !           616:                        TAILQ_REMOVE(&inp->inp_tdb_in->tdb_inp_in, inp,
        !           617:                            inp_tdb_in_next);
        !           618:                        inp->inp_tdb_in = NULL;
        !           619:                }
        !           620:        }
        !           621:        splx(s);
        !           622: #endif /*IPSEC */
        !           623:
        !           624:        opts = NULL;
        !           625: #ifdef INET6
        !           626:        if (ip6 && (inp->inp_flags & IN6P_CONTROLOPTS))
        !           627:                ip6_savecontrol(inp, m, &opts);
        !           628: #endif /* INET6 */
        !           629:        if (ip && (inp->inp_flags & INP_CONTROLOPTS))
        !           630:                ip_savecontrol(inp, &opts, ip, m);
        !           631:
        !           632:        iphlen += sizeof(struct udphdr);
        !           633:        m_adj(m, iphlen);
        !           634:        if (sbappendaddr(&inp->inp_socket->so_rcv, &srcsa.sa, m, opts) == 0) {
        !           635:                udpstat.udps_fullsock++;
        !           636:                goto bad;
        !           637:        }
        !           638:        sorwakeup(inp->inp_socket);
        !           639:        return;
        !           640: bad:
        !           641:        m_freem(m);
        !           642:        if (opts)
        !           643:                m_freem(opts);
        !           644: }
        !           645:
        !           646: /*
        !           647:  * Notify a udp user of an asynchronous error;
        !           648:  * just wake up so that he can collect error status.
        !           649:  */
        !           650: void
        !           651: udp_notify(inp, errno)
        !           652:        struct inpcb *inp;
        !           653:        int errno;
        !           654: {
        !           655:        inp->inp_socket->so_error = errno;
        !           656:        sorwakeup(inp->inp_socket);
        !           657:        sowwakeup(inp->inp_socket);
        !           658: }
        !           659:
        !           660: #ifdef INET6
        !           661: void
        !           662: udp6_ctlinput(cmd, sa, d)
        !           663:        int cmd;
        !           664:        struct sockaddr *sa;
        !           665:        void *d;
        !           666: {
        !           667:        struct udphdr uh;
        !           668:        struct sockaddr_in6 sa6;
        !           669:        struct ip6_hdr *ip6;
        !           670:        struct mbuf *m;
        !           671:        int off;
        !           672:        void *cmdarg;
        !           673:        struct ip6ctlparam *ip6cp = NULL;
        !           674:        struct udp_portonly {
        !           675:                u_int16_t uh_sport;
        !           676:                u_int16_t uh_dport;
        !           677:        } *uhp;
        !           678:        void (*notify)(struct inpcb *, int) = udp_notify;
        !           679:
        !           680:        if (sa == NULL)
        !           681:                return;
        !           682:        if (sa->sa_family != AF_INET6 ||
        !           683:            sa->sa_len != sizeof(struct sockaddr_in6))
        !           684:                return;
        !           685:
        !           686:        if ((unsigned)cmd >= PRC_NCMDS)
        !           687:                return;
        !           688:        if (PRC_IS_REDIRECT(cmd))
        !           689:                notify = in_rtchange, d = NULL;
        !           690:        else if (cmd == PRC_HOSTDEAD)
        !           691:                d = NULL;
        !           692:        else if (cmd == PRC_MSGSIZE)
        !           693:                ; /* special code is present, see below */
        !           694:        else if (inet6ctlerrmap[cmd] == 0)
        !           695:                return;
        !           696:
        !           697:        /* if the parameter is from icmp6, decode it. */
        !           698:        if (d != NULL) {
        !           699:                ip6cp = (struct ip6ctlparam *)d;
        !           700:                m = ip6cp->ip6c_m;
        !           701:                ip6 = ip6cp->ip6c_ip6;
        !           702:                off = ip6cp->ip6c_off;
        !           703:                cmdarg = ip6cp->ip6c_cmdarg;
        !           704:        } else {
        !           705:                m = NULL;
        !           706:                ip6 = NULL;
        !           707:                cmdarg = NULL;
        !           708:                /* XXX: translate addresses into internal form */
        !           709:                sa6 = *(struct sockaddr_in6 *)sa;
        !           710: #ifndef SCOPEDROUTING
        !           711:                if (in6_embedscope(&sa6.sin6_addr, &sa6, NULL, NULL)) {
        !           712:                        /* should be impossible */
        !           713:                        return;
        !           714:                }
        !           715: #endif
        !           716:        }
        !           717:
        !           718:        if (ip6cp && ip6cp->ip6c_finaldst) {
        !           719:                bzero(&sa6, sizeof(sa6));
        !           720:                sa6.sin6_family = AF_INET6;
        !           721:                sa6.sin6_len = sizeof(sa6);
        !           722:                sa6.sin6_addr = *ip6cp->ip6c_finaldst;
        !           723:                /* XXX: assuming M is valid in this case */
        !           724:                sa6.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
        !           725:                    ip6cp->ip6c_finaldst);
        !           726: #ifndef SCOPEDROUTING
        !           727:                if (in6_embedscope(ip6cp->ip6c_finaldst, &sa6, NULL, NULL)) {
        !           728:                        /* should be impossible */
        !           729:                        return;
        !           730:                }
        !           731: #endif
        !           732:        } else {
        !           733:                /* XXX: translate addresses into internal form */
        !           734:                sa6 = *(struct sockaddr_in6 *)sa;
        !           735: #ifndef SCOPEDROUTING
        !           736:                if (in6_embedscope(&sa6.sin6_addr, &sa6, NULL, NULL)) {
        !           737:                        /* should be impossible */
        !           738:                        return;
        !           739:                }
        !           740: #endif
        !           741:        }
        !           742:
        !           743:        if (ip6) {
        !           744:                /*
        !           745:                 * XXX: We assume that when IPV6 is non NULL,
        !           746:                 * M and OFF are valid.
        !           747:                 */
        !           748:                struct sockaddr_in6 sa6_src;
        !           749:
        !           750:                /* check if we can safely examine src and dst ports */
        !           751:                if (m->m_pkthdr.len < off + sizeof(*uhp))
        !           752:                        return;
        !           753:
        !           754:                bzero(&uh, sizeof(uh));
        !           755:                m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh);
        !           756:
        !           757:                bzero(&sa6_src, sizeof(sa6_src));
        !           758:                sa6_src.sin6_family = AF_INET6;
        !           759:                sa6_src.sin6_len = sizeof(sa6_src);
        !           760:                sa6_src.sin6_addr = ip6->ip6_src;
        !           761:                sa6_src.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.rcvif,
        !           762:                    &ip6->ip6_src);
        !           763: #ifndef SCOPEDROUTING
        !           764:                if (in6_embedscope(&sa6_src.sin6_addr, &sa6_src, NULL, NULL)) {
        !           765:                        /* should be impossible */
        !           766:                        return;
        !           767:                }
        !           768: #endif
        !           769:
        !           770:                if (cmd == PRC_MSGSIZE) {
        !           771:                        int valid = 0;
        !           772:
        !           773:                        /*
        !           774:                         * Check to see if we have a valid UDP socket
        !           775:                         * corresponding to the address in the ICMPv6 message
        !           776:                         * payload.
        !           777:                         */
        !           778:                        if (in6_pcbhashlookup(&udbtable, &sa6.sin6_addr,
        !           779:                            uh.uh_dport, &sa6_src.sin6_addr, uh.uh_sport))
        !           780:                                valid = 1;
        !           781: #if 0
        !           782:                        /*
        !           783:                         * As the use of sendto(2) is fairly popular,
        !           784:                         * we may want to allow non-connected pcb too.
        !           785:                         * But it could be too weak against attacks...
        !           786:                         * We should at least check if the local address (= s)
        !           787:                         * is really ours.
        !           788:                         */
        !           789:                        else if (in6_pcblookup_listen(&udbtable,
        !           790:                            &sa6_src.sin6_addr, uh.uh_sport, 0);
        !           791:                                valid = 1;
        !           792: #endif
        !           793:
        !           794:                        /*
        !           795:                         * Depending on the value of "valid" and routing table
        !           796:                         * size (mtudisc_{hi,lo}wat), we will:
        !           797:                         * - recalculate the new MTU and create the
        !           798:                         *   corresponding routing entry, or
        !           799:                         * - ignore the MTU change notification.
        !           800:                         */
        !           801:                        icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
        !           802:
        !           803:                        /*
        !           804:                         * regardless of if we called icmp6_mtudisc_update(),
        !           805:                         * we need to call in6_pcbnotify(), to notify path
        !           806:                         * MTU change to the userland (2292bis-02), because
        !           807:                         * some unconnected sockets may share the same
        !           808:                         * destination and want to know the path MTU.
        !           809:                         */
        !           810:                }
        !           811:
        !           812:                (void) in6_pcbnotify(&udbtable, (struct sockaddr *)&sa6,
        !           813:                    uh.uh_dport, (struct sockaddr *)&sa6_src,
        !           814:                    uh.uh_sport, cmd, cmdarg, notify);
        !           815:        } else {
        !           816:                (void) in6_pcbnotify(&udbtable, (struct sockaddr *)&sa6, 0,
        !           817:                    (struct sockaddr *)&sa6_any, 0, cmd, cmdarg, notify);
        !           818:        }
        !           819: }
        !           820: #endif
        !           821:
        !           822: void *
        !           823: udp_ctlinput(cmd, sa, v)
        !           824:        int cmd;
        !           825:        struct sockaddr *sa;
        !           826:        void *v;
        !           827: {
        !           828:        struct ip *ip = v;
        !           829:        struct udphdr *uhp;
        !           830:        struct in_addr faddr;
        !           831:        struct inpcb *inp;
        !           832:        extern int inetctlerrmap[];
        !           833:        void (*notify)(struct inpcb *, int) = udp_notify;
        !           834:        int errno;
        !           835:
        !           836:        if (sa == NULL)
        !           837:                return NULL;
        !           838:        if (sa->sa_family != AF_INET ||
        !           839:            sa->sa_len != sizeof(struct sockaddr_in))
        !           840:                return NULL;
        !           841:        faddr = satosin(sa)->sin_addr;
        !           842:        if (faddr.s_addr == INADDR_ANY)
        !           843:                return NULL;
        !           844:
        !           845:        if ((unsigned)cmd >= PRC_NCMDS)
        !           846:                return NULL;
        !           847:        errno = inetctlerrmap[cmd];
        !           848:        if (PRC_IS_REDIRECT(cmd))
        !           849:                notify = in_rtchange, ip = 0;
        !           850:        else if (cmd == PRC_HOSTDEAD)
        !           851:                ip = 0;
        !           852:        else if (errno == 0)
        !           853:                return NULL;
        !           854:        if (ip) {
        !           855:                uhp = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
        !           856:
        !           857: #ifdef IPSEC
        !           858:                /* PMTU discovery for udpencap */
        !           859:                if (cmd == PRC_MSGSIZE && ip_mtudisc && udpencap_enable &&
        !           860:                    udpencap_port && uhp->uh_sport == htons(udpencap_port)) {
        !           861:                        udpencap_ctlinput(cmd, sa, v);
        !           862:                        return (NULL);
        !           863:                }
        !           864: #endif
        !           865:                inp = in_pcbhashlookup(&udbtable,
        !           866:                    ip->ip_dst, uhp->uh_dport, ip->ip_src, uhp->uh_sport);
        !           867:                if (inp && inp->inp_socket != NULL)
        !           868:                        notify(inp, errno);
        !           869:        } else
        !           870:                in_pcbnotifyall(&udbtable, sa, errno, notify);
        !           871:        return (NULL);
        !           872: }
        !           873:
        !           874: int
        !           875: udp_output(struct mbuf *m, ...)
        !           876: {
        !           877:        struct inpcb *inp;
        !           878:        struct mbuf *addr, *control;
        !           879:        struct udpiphdr *ui;
        !           880:        int len = m->m_pkthdr.len;
        !           881:        struct in_addr laddr;
        !           882:        int s = 0, error = 0;
        !           883:        va_list ap;
        !           884:
        !           885:        va_start(ap, m);
        !           886:        inp = va_arg(ap, struct inpcb *);
        !           887:        addr = va_arg(ap, struct mbuf *);
        !           888:        control = va_arg(ap, struct mbuf *);
        !           889:        va_end(ap);
        !           890:
        !           891: #ifdef DIAGNOSTIC
        !           892:        if ((inp->inp_flags & INP_IPV6) != 0)
        !           893:                panic("IPv6 inpcb to udp_output");
        !           894: #endif
        !           895:
        !           896:        /*
        !           897:         * Compute the packet length of the IP header, and
        !           898:         * punt if the length looks bogus.
        !           899:         */
        !           900:        if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) {
        !           901:                error = EMSGSIZE;
        !           902:                goto release;
        !           903:        }
        !           904:
        !           905:        if (addr) {
        !           906:                laddr = inp->inp_laddr;
        !           907:                if (inp->inp_faddr.s_addr != INADDR_ANY) {
        !           908:                        error = EISCONN;
        !           909:                        goto release;
        !           910:                }
        !           911:                /*
        !           912:                 * Must block input while temporarily connected.
        !           913:                 */
        !           914:                s = splsoftnet();
        !           915:                error = in_pcbconnect(inp, addr);
        !           916:                if (error) {
        !           917:                        splx(s);
        !           918:                        goto release;
        !           919:                }
        !           920:        } else {
        !           921:                if (inp->inp_faddr.s_addr == INADDR_ANY) {
        !           922:                        error = ENOTCONN;
        !           923:                        goto release;
        !           924:                }
        !           925:        }
        !           926:        /*
        !           927:         * Calculate data length and get a mbuf
        !           928:         * for UDP and IP headers.
        !           929:         */
        !           930:        M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
        !           931:        if (m == 0) {
        !           932:                error = ENOBUFS;
        !           933:                goto bail;
        !           934:        }
        !           935:
        !           936:        /*
        !           937:         * Fill in mbuf with extended UDP header
        !           938:         * and addresses and length put into network format.
        !           939:         */
        !           940:        ui = mtod(m, struct udpiphdr *);
        !           941:        bzero(ui->ui_x1, sizeof ui->ui_x1);
        !           942:        ui->ui_pr = IPPROTO_UDP;
        !           943:        ui->ui_len = htons((u_int16_t)len + sizeof (struct udphdr));
        !           944:        ui->ui_src = inp->inp_laddr;
        !           945:        ui->ui_dst = inp->inp_faddr;
        !           946:        ui->ui_sport = inp->inp_lport;
        !           947:        ui->ui_dport = inp->inp_fport;
        !           948:        ui->ui_ulen = ui->ui_len;
        !           949:
        !           950:        /*
        !           951:         * Compute the pseudo-header checksum; defer further checksumming
        !           952:         * until ip_output() or hardware (if it exists).
        !           953:         */
        !           954:        if (udpcksum) {
        !           955:                m->m_pkthdr.csum_flags |= M_UDPV4_CSUM_OUT;
        !           956:                ui->ui_sum = in_cksum_phdr(ui->ui_src.s_addr,
        !           957:                    ui->ui_dst.s_addr, htons((u_int16_t)len +
        !           958:                    sizeof (struct udphdr) + IPPROTO_UDP));
        !           959:        } else
        !           960:                ui->ui_sum = 0;
        !           961:        ((struct ip *)ui)->ip_len = htons(sizeof (struct udpiphdr) + len);
        !           962:        ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl;
        !           963:        ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos;
        !           964:
        !           965:        udpstat.udps_opackets++;
        !           966:        error = ip_output(m, inp->inp_options, &inp->inp_route,
        !           967:            inp->inp_socket->so_options &
        !           968:            (SO_DONTROUTE | SO_BROADCAST | SO_JUMBO),
        !           969:            inp->inp_moptions, inp);
        !           970:
        !           971: bail:
        !           972:        if (addr) {
        !           973:                inp->inp_laddr = laddr;
        !           974:                in_pcbdisconnect(inp);
        !           975:                splx(s);
        !           976:        }
        !           977:        if (control)
        !           978:                m_freem(control);
        !           979:        return (error);
        !           980:
        !           981: release:
        !           982:        m_freem(m);
        !           983:        if (control)
        !           984:                m_freem(control);
        !           985:        return (error);
        !           986: }
        !           987:
        !           988: #ifdef INET6
        !           989: /*ARGSUSED*/
        !           990: int
        !           991: udp6_usrreq(so, req, m, addr, control, p)
        !           992:        struct socket *so;
        !           993:        int req;
        !           994:        struct mbuf *m, *addr, *control;
        !           995:        struct proc *p;
        !           996: {
        !           997:
        !           998:        return udp_usrreq(so, req, m, addr, control);
        !           999: }
        !          1000: #endif
        !          1001:
        !          1002: /*ARGSUSED*/
        !          1003: int
        !          1004: udp_usrreq(so, req, m, addr, control)
        !          1005:        struct socket *so;
        !          1006:        int req;
        !          1007:        struct mbuf *m, *addr, *control;
        !          1008: {
        !          1009:        struct inpcb *inp = sotoinpcb(so);
        !          1010:        int error = 0;
        !          1011:        int s;
        !          1012:
        !          1013:        if (req == PRU_CONTROL) {
        !          1014: #ifdef INET6
        !          1015:                if (inp->inp_flags & INP_IPV6)
        !          1016:                        return (in6_control(so, (u_long)m, (caddr_t)addr,
        !          1017:                            (struct ifnet *)control, 0));
        !          1018:                else
        !          1019: #endif /* INET6 */
        !          1020:                        return (in_control(so, (u_long)m, (caddr_t)addr,
        !          1021:                            (struct ifnet *)control));
        !          1022:        }
        !          1023:        if (inp == NULL && req != PRU_ATTACH) {
        !          1024:                error = EINVAL;
        !          1025:                goto release;
        !          1026:        }
        !          1027:        /*
        !          1028:         * Note: need to block udp_input while changing
        !          1029:         * the udp pcb queue and/or pcb addresses.
        !          1030:         */
        !          1031:        switch (req) {
        !          1032:
        !          1033:        case PRU_ATTACH:
        !          1034:                if (inp != NULL) {
        !          1035:                        error = EINVAL;
        !          1036:                        break;
        !          1037:                }
        !          1038:                s = splsoftnet();
        !          1039:                error = in_pcballoc(so, &udbtable);
        !          1040:                splx(s);
        !          1041:                if (error)
        !          1042:                        break;
        !          1043:                error = soreserve(so, udp_sendspace, udp_recvspace);
        !          1044:                if (error)
        !          1045:                        break;
        !          1046: #ifdef INET6
        !          1047:                if (((struct inpcb *)so->so_pcb)->inp_flags & INP_IPV6)
        !          1048:                        ((struct inpcb *) so->so_pcb)->inp_ipv6.ip6_hlim =
        !          1049:                            ip6_defhlim;
        !          1050:                else
        !          1051: #endif /* INET6 */
        !          1052:                        ((struct inpcb *) so->so_pcb)->inp_ip.ip_ttl = ip_defttl;
        !          1053:                break;
        !          1054:
        !          1055:        case PRU_DETACH:
        !          1056:                udp_detach(inp);
        !          1057:                break;
        !          1058:
        !          1059:        case PRU_BIND:
        !          1060:                s = splsoftnet();
        !          1061: #ifdef INET6
        !          1062:                if (inp->inp_flags & INP_IPV6)
        !          1063:                        error = in6_pcbbind(inp, addr);
        !          1064:                else
        !          1065: #endif
        !          1066:                        error = in_pcbbind(inp, addr);
        !          1067:                splx(s);
        !          1068:                break;
        !          1069:
        !          1070:        case PRU_LISTEN:
        !          1071:                error = EOPNOTSUPP;
        !          1072:                break;
        !          1073:
        !          1074:        case PRU_CONNECT:
        !          1075: #ifdef INET6
        !          1076:                if (inp->inp_flags & INP_IPV6) {
        !          1077:                        if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) {
        !          1078:                                error = EISCONN;
        !          1079:                                break;
        !          1080:                        }
        !          1081:                        s = splsoftnet();
        !          1082:                        error = in6_pcbconnect(inp, addr);
        !          1083:                        splx(s);
        !          1084:                } else
        !          1085: #endif /* INET6 */
        !          1086:                {
        !          1087:                        if (inp->inp_faddr.s_addr != INADDR_ANY) {
        !          1088:                                error = EISCONN;
        !          1089:                                break;
        !          1090:                        }
        !          1091:                        s = splsoftnet();
        !          1092:                        error = in_pcbconnect(inp, addr);
        !          1093:                        splx(s);
        !          1094:                }
        !          1095:
        !          1096:                if (error == 0)
        !          1097:                        soisconnected(so);
        !          1098:                break;
        !          1099:
        !          1100:        case PRU_CONNECT2:
        !          1101:                error = EOPNOTSUPP;
        !          1102:                break;
        !          1103:
        !          1104:        case PRU_ACCEPT:
        !          1105:                error = EOPNOTSUPP;
        !          1106:                break;
        !          1107:
        !          1108:        case PRU_DISCONNECT:
        !          1109: #ifdef INET6
        !          1110:                if (inp->inp_flags & INP_IPV6) {
        !          1111:                        if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) {
        !          1112:                                error = ENOTCONN;
        !          1113:                                break;
        !          1114:                        }
        !          1115:                } else
        !          1116: #endif /* INET6 */
        !          1117:                {
        !          1118:                        if (inp->inp_faddr.s_addr == INADDR_ANY) {
        !          1119:                                error = ENOTCONN;
        !          1120:                                break;
        !          1121:                        }
        !          1122:                }
        !          1123:
        !          1124:                s = splsoftnet();
        !          1125: #ifdef INET6
        !          1126:                if (inp->inp_flags & INP_IPV6)
        !          1127:                        inp->inp_laddr6 = in6addr_any;
        !          1128:                else
        !          1129: #endif /* INET6 */
        !          1130:                        inp->inp_laddr.s_addr = INADDR_ANY;
        !          1131:                in_pcbdisconnect(inp);
        !          1132:
        !          1133:                splx(s);
        !          1134:                so->so_state &= ~SS_ISCONNECTED;                /* XXX */
        !          1135:                break;
        !          1136:
        !          1137:        case PRU_SHUTDOWN:
        !          1138:                socantsendmore(so);
        !          1139:                break;
        !          1140:
        !          1141:        case PRU_SEND:
        !          1142: #ifdef INET6
        !          1143:                if (inp->inp_flags & INP_IPV6)
        !          1144:                        return (udp6_output(inp, m, addr, control));
        !          1145:                else
        !          1146:                        return (udp_output(m, inp, addr, control));
        !          1147: #else
        !          1148:                return (udp_output(m, inp, addr, control));
        !          1149: #endif
        !          1150:
        !          1151:        case PRU_ABORT:
        !          1152:                soisdisconnected(so);
        !          1153:                udp_detach(inp);
        !          1154:                break;
        !          1155:
        !          1156:        case PRU_SOCKADDR:
        !          1157: #ifdef INET6
        !          1158:                if (inp->inp_flags & INP_IPV6)
        !          1159:                        in6_setsockaddr(inp, addr);
        !          1160:                else
        !          1161: #endif /* INET6 */
        !          1162:                        in_setsockaddr(inp, addr);
        !          1163:                break;
        !          1164:
        !          1165:        case PRU_PEERADDR:
        !          1166: #ifdef INET6
        !          1167:                if (inp->inp_flags & INP_IPV6)
        !          1168:                        in6_setpeeraddr(inp, addr);
        !          1169:                else
        !          1170: #endif /* INET6 */
        !          1171:                        in_setpeeraddr(inp, addr);
        !          1172:                break;
        !          1173:
        !          1174:        case PRU_SENSE:
        !          1175:                /*
        !          1176:                 * stat: don't bother with a blocksize.
        !          1177:                 */
        !          1178:                /*
        !          1179:                 * Perhaps Path MTU might be returned for a connected
        !          1180:                 * UDP socket in this case.
        !          1181:                 */
        !          1182:                return (0);
        !          1183:
        !          1184:        case PRU_SENDOOB:
        !          1185:        case PRU_FASTTIMO:
        !          1186:        case PRU_SLOWTIMO:
        !          1187:        case PRU_PROTORCV:
        !          1188:        case PRU_PROTOSEND:
        !          1189:                error =  EOPNOTSUPP;
        !          1190:                break;
        !          1191:
        !          1192:        case PRU_RCVD:
        !          1193:        case PRU_RCVOOB:
        !          1194:                return (EOPNOTSUPP);    /* do not free mbuf's */
        !          1195:
        !          1196:        default:
        !          1197:                panic("udp_usrreq");
        !          1198:        }
        !          1199:
        !          1200: release:
        !          1201:        if (control) {
        !          1202:                m_freem(control);
        !          1203:        }
        !          1204:        if (m)
        !          1205:                m_freem(m);
        !          1206:        return (error);
        !          1207: }
        !          1208:
        !          1209: void
        !          1210: udp_detach(inp)
        !          1211:        struct inpcb *inp;
        !          1212: {
        !          1213:        int s = splsoftnet();
        !          1214:
        !          1215:        in_pcbdetach(inp);
        !          1216:        splx(s);
        !          1217: }
        !          1218:
        !          1219: /*
        !          1220:  * Sysctl for udp variables.
        !          1221:  */
        !          1222: int
        !          1223: udp_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
        !          1224:        int *name;
        !          1225:        u_int namelen;
        !          1226:        void *oldp;
        !          1227:        size_t *oldlenp;
        !          1228:        void *newp;
        !          1229:        size_t newlen;
        !          1230: {
        !          1231:        /* All sysctl names at this level are terminal. */
        !          1232:        if (namelen != 1)
        !          1233:                return (ENOTDIR);
        !          1234:
        !          1235:        switch (name[0]) {
        !          1236:        case UDPCTL_BADDYNAMIC:
        !          1237:                return (sysctl_struct(oldp, oldlenp, newp, newlen,
        !          1238:                    baddynamicports.udp, sizeof(baddynamicports.udp)));
        !          1239:        default:
        !          1240:                if (name[0] < UDPCTL_MAXID)
        !          1241:                        return (sysctl_int_arr(udpctl_vars, name, namelen,
        !          1242:                            oldp, oldlenp, newp, newlen));
        !          1243:                return (ENOPROTOOPT);
        !          1244:        }
        !          1245:        /* NOTREACHED */
        !          1246: }

CVSweb