[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

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