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

Annotation of sys/netinet/in_pcb.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: in_pcb.c,v 1.89 2007/04/10 17:47:55 miod Exp $        */
                      2: /*     $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $     */
                      3:
                      4: /*
                      5:  * Copyright (c) 1982, 1986, 1991, 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/proc.h>
                     78: #include <sys/domain.h>
                     79:
                     80: #include <net/if.h>
                     81: #include <net/route.h>
                     82:
                     83: #include <netinet/in.h>
                     84: #include <netinet/in_systm.h>
                     85: #include <netinet/ip.h>
                     86: #include <netinet/in_pcb.h>
                     87: #include <netinet/in_var.h>
                     88: #include <netinet/ip_var.h>
                     89: #include <dev/rndvar.h>
                     90:
                     91: #include <sys/mount.h>
                     92: #include <nfs/nfsproto.h>
                     93:
                     94: #ifdef INET6
                     95: #include <netinet6/ip6_var.h>
                     96: #endif /* INET6 */
                     97: #ifdef IPSEC
                     98: #include <netinet/ip_esp.h>
                     99: #endif /* IPSEC */
                    100:
                    101: struct in_addr zeroin_addr;
                    102:
                    103: extern int ipsec_auth_default_level;
                    104: extern int ipsec_esp_trans_default_level;
                    105: extern int ipsec_esp_network_default_level;
                    106: extern int ipsec_ipcomp_default_level;
                    107:
                    108: /*
                    109:  * These configure the range of local port addresses assigned to
                    110:  * "unspecified" outgoing connections/packets/whatever.
                    111:  */
                    112: int ipport_firstauto = IPPORT_RESERVED;
                    113: int ipport_lastauto = IPPORT_USERRESERVED;
                    114: int ipport_hifirstauto = IPPORT_HIFIRSTAUTO;
                    115: int ipport_hilastauto = IPPORT_HILASTAUTO;
                    116:
                    117: struct pool inpcb_pool;
                    118: int inpcb_pool_initalized = 0;
                    119:
                    120: #define        INPCBHASH(table, faddr, fport, laddr, lport) \
                    121:        &(table)->inpt_hashtbl[(ntohl((faddr)->s_addr) + \
                    122:        ntohs((fport)) + ntohs((lport))) & (table->inpt_hash)]
                    123:
                    124: #define        IN6PCBHASH(table, faddr, fport, laddr, lport) \
                    125:        &(table)->inpt_hashtbl[(ntohl((faddr)->s6_addr32[0] ^ \
                    126:        (faddr)->s6_addr32[3]) + ntohs((fport)) + ntohs((lport))) & \
                    127:        (table->inpt_hash)]
                    128:
                    129: #define        INPCBLHASH(table, lport) \
                    130:        &(table)->inpt_lhashtbl[lport & table->inpt_lhash]
                    131:
                    132: void
                    133: in_pcbinit(table, hashsize)
                    134:        struct inpcbtable *table;
                    135:        int hashsize;
                    136: {
                    137:
                    138:        CIRCLEQ_INIT(&table->inpt_queue);
                    139:        table->inpt_hashtbl = hashinit(hashsize, M_PCB, M_NOWAIT,
                    140:            &table->inpt_hash);
                    141:        if (table->inpt_hashtbl == NULL)
                    142:                panic("in_pcbinit: hashinit failed");
                    143:        table->inpt_lhashtbl = hashinit(hashsize, M_PCB, M_NOWAIT,
                    144:            &table->inpt_lhash);
                    145:        if (table->inpt_lhashtbl == NULL)
                    146:                panic("in_pcbinit: hashinit failed for lport");
                    147:        table->inpt_lastport = 0;
                    148: }
                    149:
                    150: struct baddynamicports baddynamicports;
                    151:
                    152: /*
                    153:  * Check if the specified port is invalid for dynamic allocation.
                    154:  */
                    155: int
                    156: in_baddynamic(port, proto)
                    157:        u_int16_t port;
                    158:        u_int16_t proto;
                    159: {
                    160:
                    161:
                    162:        switch (proto) {
                    163:        case IPPROTO_TCP:
                    164:                if (port == NFS_PORT)
                    165:                        return (1);
                    166:                if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
                    167:                        return (0);
                    168:                return (DP_ISSET(baddynamicports.tcp, port));
                    169:        case IPPROTO_UDP:
                    170: #ifdef IPSEC
                    171:                if (port == udpencap_port)
                    172:                        return (1);
                    173: #endif
                    174:                if (port == NFS_PORT)
                    175:                        return (1);
                    176:                if (port < IPPORT_RESERVED/2 || port >= IPPORT_RESERVED)
                    177:                        return (0);
                    178:                return (DP_ISSET(baddynamicports.udp, port));
                    179:        default:
                    180:                return (0);
                    181:        }
                    182: }
                    183:
                    184: int
                    185: in_pcballoc(so, v)
                    186:        struct socket *so;
                    187:        void *v;
                    188: {
                    189:        struct inpcbtable *table = v;
                    190:        struct inpcb *inp;
                    191:        int s;
                    192:
                    193:        if (inpcb_pool_initalized == 0) {
                    194:                pool_init(&inpcb_pool, sizeof(struct inpcb), 0, 0, 0,
                    195:                    "inpcbpl", NULL);
                    196:                inpcb_pool_initalized = 1;
                    197:        }
                    198:        inp = pool_get(&inpcb_pool, PR_NOWAIT);
                    199:        if (inp == NULL)
                    200:                return (ENOBUFS);
                    201:        bzero((caddr_t)inp, sizeof(*inp));
                    202:        inp->inp_table = table;
                    203:        inp->inp_socket = so;
                    204:        inp->inp_seclevel[SL_AUTH] = ipsec_auth_default_level;
                    205:        inp->inp_seclevel[SL_ESP_TRANS] = ipsec_esp_trans_default_level;
                    206:        inp->inp_seclevel[SL_ESP_NETWORK] = ipsec_esp_network_default_level;
                    207:        inp->inp_seclevel[SL_IPCOMP] = ipsec_ipcomp_default_level;
                    208:        s = splnet();
                    209:        CIRCLEQ_INSERT_HEAD(&table->inpt_queue, inp, inp_queue);
                    210:        LIST_INSERT_HEAD(INPCBLHASH(table, inp->inp_lport), inp, inp_lhash);
                    211:        LIST_INSERT_HEAD(INPCBHASH(table, &inp->inp_faddr, inp->inp_fport,
                    212:            &inp->inp_laddr, inp->inp_lport), inp, inp_hash);
                    213:        splx(s);
                    214:        so->so_pcb = inp;
                    215:        inp->inp_hops = -1;
                    216:
                    217: #ifdef INET6
                    218:        /*
                    219:         * Small change in this function to set the INP_IPV6 flag so routines
                    220:         * outside pcb-specific routines don't need to use sotopf(), and all
                    221:         * of its pointer chasing, later.
                    222:         */
                    223:        if (sotopf(so) == PF_INET6)
                    224:                inp->inp_flags = INP_IPV6;
                    225:        inp->in6p_cksum = -1;
                    226: #endif /* INET6 */
                    227:        return (0);
                    228: }
                    229:
                    230: int
                    231: in_pcbbind(v, nam)
                    232:        void *v;
                    233:        struct mbuf *nam;
                    234: {
                    235:        struct inpcb *inp = v;
                    236:        struct socket *so = inp->inp_socket;
                    237:        struct inpcbtable *table = inp->inp_table;
                    238:        u_int16_t *lastport = &inp->inp_table->inpt_lastport;
                    239:        struct sockaddr_in *sin;
                    240:        struct proc *p = curproc;               /* XXX */
                    241:        u_int16_t lport = 0;
                    242:        int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
                    243:        int error;
                    244:
                    245: #ifdef INET6
                    246:        if (sotopf(so) == PF_INET6)
                    247:                return in6_pcbbind(inp, nam);
                    248: #endif /* INET6 */
                    249:
                    250:        if (TAILQ_EMPTY(&in_ifaddr))
                    251:                return (EADDRNOTAVAIL);
                    252:        if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY)
                    253:                return (EINVAL);
                    254:        if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 &&
                    255:            ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
                    256:             (so->so_options & SO_ACCEPTCONN) == 0))
                    257:                wild = INPLOOKUP_WILDCARD;
                    258:        if (nam) {
                    259:                sin = mtod(nam, struct sockaddr_in *);
                    260:                if (nam->m_len != sizeof (*sin))
                    261:                        return (EINVAL);
                    262: #ifdef notdef
                    263:                /*
                    264:                 * We should check the family, but old programs
                    265:                 * incorrectly fail to initialize it.
                    266:                 */
                    267:                if (sin->sin_family != AF_INET)
                    268:                        return (EAFNOSUPPORT);
                    269: #endif
                    270:                lport = sin->sin_port;
                    271:                if (IN_MULTICAST(sin->sin_addr.s_addr)) {
                    272:                        /*
                    273:                         * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
                    274:                         * allow complete duplication of binding if
                    275:                         * SO_REUSEPORT is set, or if SO_REUSEADDR is set
                    276:                         * and a multicast address is bound on both
                    277:                         * new and duplicated sockets.
                    278:                         */
                    279:                        if (so->so_options & SO_REUSEADDR)
                    280:                                reuseport = SO_REUSEADDR|SO_REUSEPORT;
                    281:                } else if (sin->sin_addr.s_addr != INADDR_ANY) {
                    282:                        sin->sin_port = 0;              /* yech... */
                    283:                        if (in_iawithaddr(sin->sin_addr, NULL) == 0)
                    284:                                return (EADDRNOTAVAIL);
                    285:                }
                    286:                if (lport) {
                    287:                        struct inpcb *t;
                    288:
                    289:                        /* GROSS */
                    290:                        if (ntohs(lport) < IPPORT_RESERVED &&
                    291:                            (error = suser(p, 0)))
                    292:                                return (EACCES);
                    293:                        if (so->so_euid) {
                    294:                                t = in_pcblookup(table, &zeroin_addr, 0,
                    295:                                    &sin->sin_addr, lport, INPLOOKUP_WILDCARD);
                    296:                                if (t && (so->so_euid != t->inp_socket->so_euid))
                    297:                                        return (EADDRINUSE);
                    298:                        }
                    299:                        t = in_pcblookup(table, &zeroin_addr, 0,
                    300:                            &sin->sin_addr, lport, wild);
                    301:                        if (t && (reuseport & t->inp_socket->so_options) == 0)
                    302:                                return (EADDRINUSE);
                    303:                }
                    304:                inp->inp_laddr = sin->sin_addr;
                    305:        }
                    306:        if (lport == 0) {
                    307:                u_int16_t first, last;
                    308:                int count;
                    309:
                    310:                if (inp->inp_flags & INP_HIGHPORT) {
                    311:                        first = ipport_hifirstauto;     /* sysctl */
                    312:                        last = ipport_hilastauto;
                    313:                } else if (inp->inp_flags & INP_LOWPORT) {
                    314:                        if ((error = suser(p, 0)))
                    315:                                return (EACCES);
                    316:                        first = IPPORT_RESERVED-1; /* 1023 */
                    317:                        last = 600;                /* not IPPORT_RESERVED/2 */
                    318:                } else {
                    319:                        first = ipport_firstauto;       /* sysctl */
                    320:                        last  = ipport_lastauto;
                    321:                }
                    322:
                    323:                /*
                    324:                 * Simple check to ensure all ports are not used up causing
                    325:                 * a deadlock here.
                    326:                 *
                    327:                 * We split the two cases (up and down) so that the direction
                    328:                 * is not being tested on each round of the loop.
                    329:                 */
                    330:
                    331:                if (first > last) {
                    332:                        /*
                    333:                         * counting down
                    334:                         */
                    335:                        count = first - last;
                    336:                        if (count)
                    337:                                *lastport = first - (arc4random() % count);
                    338:
                    339:                        do {
                    340:                                if (count-- < 0)        /* completely used? */
                    341:                                        return (EADDRNOTAVAIL);
                    342:                                --*lastport;
                    343:                                if (*lastport > first || *lastport < last)
                    344:                                        *lastport = first;
                    345:                                lport = htons(*lastport);
                    346:                        } while (in_baddynamic(*lastport, so->so_proto->pr_protocol) ||
                    347:                            in_pcblookup(table, &zeroin_addr, 0,
                    348:                            &inp->inp_laddr, lport, wild));
                    349:                } else {
                    350:                        /*
                    351:                         * counting up
                    352:                         */
                    353:                        count = last - first;
                    354:                        if (count)
                    355:                                *lastport = first + (arc4random() % count);
                    356:
                    357:                        do {
                    358:                                if (count-- < 0)        /* completely used? */
                    359:                                        return (EADDRNOTAVAIL);
                    360:                                ++*lastport;
                    361:                                if (*lastport < first || *lastport > last)
                    362:                                        *lastport = first;
                    363:                                lport = htons(*lastport);
                    364:                        } while (in_baddynamic(*lastport, so->so_proto->pr_protocol) ||
                    365:                            in_pcblookup(table, &zeroin_addr, 0,
                    366:                            &inp->inp_laddr, lport, wild));
                    367:                }
                    368:        }
                    369:        inp->inp_lport = lport;
                    370:        in_pcbrehash(inp);
                    371:        return (0);
                    372: }
                    373:
                    374: /*
                    375:  * Connect from a socket to a specified address.
                    376:  * Both address and port must be specified in argument sin.
                    377:  * If don't have a local address for this socket yet,
                    378:  * then pick one.
                    379:  */
                    380: int
                    381: in_pcbconnect(v, nam)
                    382:        void *v;
                    383:        struct mbuf *nam;
                    384: {
                    385:        struct inpcb *inp = v;
                    386:        struct sockaddr_in *ifaddr = NULL;
                    387:        struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
                    388:
                    389: #ifdef INET6
                    390:        if (sotopf(inp->inp_socket) == PF_INET6)
                    391:                return (in6_pcbconnect(inp, nam));
                    392:        if ((inp->inp_flags & INP_IPV6) != 0)
                    393:                panic("IPv6 pcb passed into in_pcbconnect");
                    394: #endif /* INET6 */
                    395:
                    396:        if (nam->m_len != sizeof (*sin))
                    397:                return (EINVAL);
                    398:        if (sin->sin_family != AF_INET)
                    399:                return (EAFNOSUPPORT);
                    400:        if (sin->sin_port == 0)
                    401:                return (EADDRNOTAVAIL);
                    402:        if (!TAILQ_EMPTY(&in_ifaddr)) {
                    403:                /*
                    404:                 * If the destination address is INADDR_ANY,
                    405:                 * use the primary local address.
                    406:                 * If the supplied address is INADDR_BROADCAST,
                    407:                 * and the primary interface supports broadcast,
                    408:                 * choose the broadcast address for that interface.
                    409:                 */
                    410:                if (sin->sin_addr.s_addr == INADDR_ANY)
                    411:                        sin->sin_addr = TAILQ_FIRST(&in_ifaddr)->ia_addr.sin_addr;
                    412:                else if (sin->sin_addr.s_addr == INADDR_BROADCAST &&
                    413:                  (TAILQ_FIRST(&in_ifaddr)->ia_ifp->if_flags & IFF_BROADCAST))
                    414:                        sin->sin_addr = TAILQ_FIRST(&in_ifaddr)->ia_broadaddr.sin_addr;
                    415:        }
                    416:        if (inp->inp_laddr.s_addr == INADDR_ANY) {
                    417:                int error;
                    418:                ifaddr = in_selectsrc(sin, &inp->inp_route,
                    419:                        inp->inp_socket->so_options, inp->inp_moptions, &error);
                    420:                if (ifaddr == NULL) {
                    421:                        if (error == 0)
                    422:                                error = EADDRNOTAVAIL;
                    423:                        return error;
                    424:                }
                    425:        }
                    426:        if (in_pcbhashlookup(inp->inp_table, sin->sin_addr, sin->sin_port,
                    427:            inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
                    428:            inp->inp_lport) != 0)
                    429:                return (EADDRINUSE);
                    430:        if (inp->inp_laddr.s_addr == INADDR_ANY) {
                    431:                if (inp->inp_lport == 0 &&
                    432:                    in_pcbbind(inp, (struct mbuf *)0) == EADDRNOTAVAIL)
                    433:                        return (EADDRNOTAVAIL);
                    434:                inp->inp_laddr = ifaddr->sin_addr;
                    435:        }
                    436:        inp->inp_faddr = sin->sin_addr;
                    437:        inp->inp_fport = sin->sin_port;
                    438:        in_pcbrehash(inp);
                    439: #ifdef IPSEC
                    440:        {
                    441:                int error; /* This is just ignored */
                    442:
                    443:                /* Cause an IPsec SA to be established. */
                    444:                ipsp_spd_inp(NULL, AF_INET, 0, &error, IPSP_DIRECTION_OUT,
                    445:                    NULL, inp, NULL);
                    446:        }
                    447: #endif
                    448:        return (0);
                    449: }
                    450:
                    451: void
                    452: in_pcbdisconnect(v)
                    453:        void *v;
                    454: {
                    455:        struct inpcb *inp = v;
                    456:
                    457:        switch (sotopf(inp->inp_socket)) {
                    458: #ifdef INET6
                    459:        case PF_INET6:
                    460:                inp->inp_faddr6 = in6addr_any;
                    461:                break;
                    462: #endif
                    463:        case PF_INET:
                    464:                inp->inp_faddr.s_addr = INADDR_ANY;
                    465:                break;
                    466:        }
                    467:
                    468:        inp->inp_fport = 0;
                    469:        in_pcbrehash(inp);
                    470:        if (inp->inp_socket->so_state & SS_NOFDREF)
                    471:                in_pcbdetach(inp);
                    472: }
                    473:
                    474: void
                    475: in_pcbdetach(v)
                    476:        void *v;
                    477: {
                    478:        struct inpcb *inp = v;
                    479:        struct socket *so = inp->inp_socket;
                    480:        int s;
                    481:
                    482:        so->so_pcb = 0;
                    483:        sofree(so);
                    484:        if (inp->inp_options)
                    485:                (void)m_freem(inp->inp_options);
                    486:        if (inp->inp_route.ro_rt)
                    487:                rtfree(inp->inp_route.ro_rt);
                    488: #ifdef INET6
                    489:        if (inp->inp_flags & INP_IPV6)
                    490:                ip6_freemoptions(inp->inp_moptions6);
                    491:        else
                    492: #endif
                    493:                ip_freemoptions(inp->inp_moptions);
                    494: #ifdef IPSEC
                    495:        /* IPsec cleanup here */
                    496:        s = spltdb();
                    497:        if (inp->inp_tdb_in)
                    498:                TAILQ_REMOVE(&inp->inp_tdb_in->tdb_inp_in,
                    499:                             inp, inp_tdb_in_next);
                    500:        if (inp->inp_tdb_out)
                    501:                TAILQ_REMOVE(&inp->inp_tdb_out->tdb_inp_out, inp,
                    502:                             inp_tdb_out_next);
                    503:        if (inp->inp_ipsec_remotecred)
                    504:                ipsp_reffree(inp->inp_ipsec_remotecred);
                    505:        if (inp->inp_ipsec_remoteauth)
                    506:                ipsp_reffree(inp->inp_ipsec_remoteauth);
                    507:        if (inp->inp_ipo)
                    508:                ipsec_delete_policy(inp->inp_ipo);
                    509:        splx(s);
                    510: #endif
                    511:        s = splnet();
                    512:        LIST_REMOVE(inp, inp_lhash);
                    513:        LIST_REMOVE(inp, inp_hash);
                    514:        CIRCLEQ_REMOVE(&inp->inp_table->inpt_queue, inp, inp_queue);
                    515:        splx(s);
                    516:        pool_put(&inpcb_pool, inp);
                    517: }
                    518:
                    519: void
                    520: in_setsockaddr(inp, nam)
                    521:        struct inpcb *inp;
                    522:        struct mbuf *nam;
                    523: {
                    524:        struct sockaddr_in *sin;
                    525:
                    526:        nam->m_len = sizeof (*sin);
                    527:        sin = mtod(nam, struct sockaddr_in *);
                    528:        bzero((caddr_t)sin, sizeof (*sin));
                    529:        sin->sin_family = AF_INET;
                    530:        sin->sin_len = sizeof(*sin);
                    531:        sin->sin_port = inp->inp_lport;
                    532:        sin->sin_addr = inp->inp_laddr;
                    533: }
                    534:
                    535: void
                    536: in_setpeeraddr(inp, nam)
                    537:        struct inpcb *inp;
                    538:        struct mbuf *nam;
                    539: {
                    540:        struct sockaddr_in *sin;
                    541:
                    542: #ifdef INET6
                    543:        if (sotopf(inp->inp_socket) == PF_INET6) {
                    544:                in6_setpeeraddr(inp, nam);
                    545:                return;
                    546:        }
                    547: #endif /* INET6 */
                    548:
                    549:        nam->m_len = sizeof (*sin);
                    550:        sin = mtod(nam, struct sockaddr_in *);
                    551:        bzero((caddr_t)sin, sizeof (*sin));
                    552:        sin->sin_family = AF_INET;
                    553:        sin->sin_len = sizeof(*sin);
                    554:        sin->sin_port = inp->inp_fport;
                    555:        sin->sin_addr = inp->inp_faddr;
                    556: }
                    557:
                    558: /*
                    559:  * Pass some notification to all connections of a protocol
                    560:  * associated with address dst.  The "usual action" will be
                    561:  * taken, depending on the ctlinput cmd.  The caller must filter any
                    562:  * cmds that are uninteresting (e.g., no error in the map).
                    563:  * Call the protocol specific routine (if any) to report
                    564:  * any errors for each matching socket.
                    565:  *
                    566:  * Must be called at splsoftnet.
                    567:  */
                    568: void
                    569: in_pcbnotifyall(table, dst, errno, notify)
                    570:        struct inpcbtable *table;
                    571:        struct sockaddr *dst;
                    572:        int errno;
                    573:        void (*notify)(struct inpcb *, int);
                    574: {
                    575:        struct inpcb *inp, *oinp;
                    576:        struct in_addr faddr;
                    577:
                    578:        splassert(IPL_SOFTNET);
                    579:
                    580: #ifdef INET6
                    581:        /*
                    582:         * See in6_pcbnotify() for IPv6 codepath.  By the time this
                    583:         * gets called, the addresses passed are either definitely IPv4 or
                    584:         * IPv6; *_pcbnotify() never gets called with v4-mapped v6 addresses.
                    585:         */
                    586: #endif /* INET6 */
                    587:
                    588:        if (dst->sa_family != AF_INET)
                    589:                return;
                    590:        faddr = satosin(dst)->sin_addr;
                    591:        if (faddr.s_addr == INADDR_ANY)
                    592:                return;
                    593:
                    594:        for (inp = CIRCLEQ_FIRST(&table->inpt_queue);
                    595:            inp != CIRCLEQ_END(&table->inpt_queue);) {
                    596: #ifdef INET6
                    597:                if (inp->inp_flags & INP_IPV6) {
                    598:                        inp = CIRCLEQ_NEXT(inp, inp_queue);
                    599:                        continue;
                    600:                }
                    601: #endif
                    602:                if (inp->inp_faddr.s_addr != faddr.s_addr ||
                    603:                    inp->inp_socket == 0) {
                    604:                        inp = CIRCLEQ_NEXT(inp, inp_queue);
                    605:                        continue;
                    606:                }
                    607:                oinp = inp;
                    608:                inp = CIRCLEQ_NEXT(inp, inp_queue);
                    609:                if (notify)
                    610:                        (*notify)(oinp, errno);
                    611:        }
                    612: }
                    613:
                    614: /*
                    615:  * Check for alternatives when higher level complains
                    616:  * about service problems.  For now, invalidate cached
                    617:  * routing information.  If the route was created dynamically
                    618:  * (by a redirect), time to try a default gateway again.
                    619:  */
                    620: void
                    621: in_losing(inp)
                    622:        struct inpcb *inp;
                    623: {
                    624:        struct rtentry *rt;
                    625:        struct rt_addrinfo info;
                    626:
                    627:        if ((rt = inp->inp_route.ro_rt)) {
                    628:                inp->inp_route.ro_rt = 0;
                    629:                bzero((caddr_t)&info, sizeof(info));
                    630:                info.rti_info[RTAX_DST] = &inp->inp_route.ro_dst;
                    631:                info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
                    632:                info.rti_info[RTAX_NETMASK] = rt_mask(rt);
                    633:                rt_missmsg(RTM_LOSING, &info, rt->rt_flags, rt->rt_ifp, 0, 0);
                    634:                if (rt->rt_flags & RTF_DYNAMIC)
                    635:                        (void) rtrequest(RTM_DELETE, rt_key(rt),
                    636:                                rt->rt_gateway, rt_mask(rt), rt->rt_flags,
                    637:                                (struct rtentry **)0, 0);
                    638:                /*
                    639:                 * A new route can be allocated
                    640:                 * the next time output is attempted.
                    641:                 * rtfree() needs to be called in anycase because the inp
                    642:                 * is still holding a reference to rt.
                    643:                 */
                    644:                rtfree(rt);
                    645:        }
                    646: }
                    647:
                    648: /*
                    649:  * After a routing change, flush old routing
                    650:  * and allocate a (hopefully) better one.
                    651:  */
                    652: void
                    653: in_rtchange(inp, errno)
                    654:        struct inpcb *inp;
                    655:        int errno;
                    656: {
                    657:        if (inp->inp_route.ro_rt) {
                    658:                rtfree(inp->inp_route.ro_rt);
                    659:                inp->inp_route.ro_rt = 0;
                    660:                /*
                    661:                 * A new route can be allocated the next time
                    662:                 * output is attempted.
                    663:                 */
                    664:        }
                    665: }
                    666:
                    667: struct inpcb *
                    668: in_pcblookup(table, faddrp, fport_arg, laddrp, lport_arg, flags)
                    669:        struct inpcbtable *table;
                    670:        void *faddrp, *laddrp;
                    671:        u_int fport_arg, lport_arg;
                    672:        int flags;
                    673: {
                    674:        struct inpcb *inp, *match = 0;
                    675:        int matchwild = 3, wildcard;
                    676:        u_int16_t fport = fport_arg, lport = lport_arg;
                    677:        struct in_addr faddr = *(struct in_addr *)faddrp;
                    678:        struct in_addr laddr = *(struct in_addr *)laddrp;
                    679:
                    680:        for (inp = LIST_FIRST(INPCBLHASH(table, lport)); inp;
                    681:            inp = LIST_NEXT(inp, inp_lhash)) {
                    682:                if (inp->inp_lport != lport)
                    683:                        continue;
                    684:                wildcard = 0;
                    685: #ifdef INET6
                    686:                if (flags & INPLOOKUP_IPV6) {
                    687:                        struct in6_addr *laddr6 = (struct in6_addr *)laddrp;
                    688:                        struct in6_addr *faddr6 = (struct in6_addr *)faddrp;
                    689:
                    690:                        if (!(inp->inp_flags & INP_IPV6))
                    691:                                continue;
                    692:
                    693:                        if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) {
                    694:                                if (IN6_IS_ADDR_UNSPECIFIED(laddr6))
                    695:                                        wildcard++;
                    696:                                else if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, laddr6))
                    697:                                        continue;
                    698:                        } else {
                    699:                                if (!IN6_IS_ADDR_UNSPECIFIED(laddr6))
                    700:                                        wildcard++;
                    701:                        }
                    702:
                    703:                        if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) {
                    704:                                if (IN6_IS_ADDR_UNSPECIFIED(faddr6))
                    705:                                        wildcard++;
                    706:                                else if (!IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6,
                    707:                                    faddr6) || inp->inp_fport != fport)
                    708:                                        continue;
                    709:                        } else {
                    710:                                if (!IN6_IS_ADDR_UNSPECIFIED(faddr6))
                    711:                                        wildcard++;
                    712:                        }
                    713:                } else
                    714: #endif /* INET6 */
                    715:                {
                    716: #ifdef INET6
                    717:                        if (inp->inp_flags & INP_IPV6)
                    718:                                continue;
                    719: #endif /* INET6 */
                    720:
                    721:                        if (inp->inp_faddr.s_addr != INADDR_ANY) {
                    722:                                if (faddr.s_addr == INADDR_ANY)
                    723:                                        wildcard++;
                    724:                                else if (inp->inp_faddr.s_addr != faddr.s_addr ||
                    725:                                    inp->inp_fport != fport)
                    726:                                        continue;
                    727:                        } else {
                    728:                                if (faddr.s_addr != INADDR_ANY)
                    729:                                        wildcard++;
                    730:                        }
                    731:                        if (inp->inp_laddr.s_addr != INADDR_ANY) {
                    732:                                if (laddr.s_addr == INADDR_ANY)
                    733:                                        wildcard++;
                    734:                                else if (inp->inp_laddr.s_addr != laddr.s_addr)
                    735:                                        continue;
                    736:                        } else {
                    737:                                if (laddr.s_addr != INADDR_ANY)
                    738:                                        wildcard++;
                    739:                        }
                    740:                }
                    741:                if ((!wildcard || (flags & INPLOOKUP_WILDCARD)) &&
                    742:                    wildcard < matchwild) {
                    743:                        match = inp;
                    744:                        if ((matchwild = wildcard) == 0)
                    745:                                break;
                    746:                }
                    747:        }
                    748:        return (match);
                    749: }
                    750:
                    751: struct rtentry *
                    752: in_pcbrtentry(inp)
                    753:        struct inpcb *inp;
                    754: {
                    755:        struct route *ro;
                    756:
                    757:        ro = &inp->inp_route;
                    758:
                    759:        /*
                    760:         * No route yet, so try to acquire one.
                    761:         */
                    762:        if (ro->ro_rt == NULL) {
                    763: #ifdef INET6
                    764:                bzero(ro, sizeof(struct route_in6));
                    765: #else
                    766:                bzero(ro, sizeof(struct route));
                    767: #endif
                    768:
                    769:                switch(sotopf(inp->inp_socket)) {
                    770: #ifdef INET6
                    771:                case PF_INET6:
                    772:                        if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
                    773:                                break;
                    774:                        ro->ro_dst.sa_family = AF_INET6;
                    775:                        ro->ro_dst.sa_len = sizeof(struct sockaddr_in6);
                    776:                        ((struct sockaddr_in6 *) &ro->ro_dst)->sin6_addr =
                    777:                            inp->inp_faddr6;
                    778:                        rtalloc_mpath(ro, &inp->inp_laddr6.s6_addr32[0], 0);
                    779:                        break;
                    780: #endif /* INET6 */
                    781:                case PF_INET:
                    782:                        if (inp->inp_faddr.s_addr == INADDR_ANY)
                    783:                                break;
                    784:                        ro->ro_dst.sa_family = AF_INET;
                    785:                        ro->ro_dst.sa_len = sizeof(ro->ro_dst);
                    786:                        satosin(&ro->ro_dst)->sin_addr = inp->inp_faddr;
                    787:                        rtalloc_mpath(ro, &inp->inp_laddr.s_addr, 0);
                    788:                        break;
                    789:                }
                    790:        }
                    791:        return (ro->ro_rt);
                    792: }
                    793:
                    794: struct sockaddr_in *
                    795: in_selectsrc(sin, ro, soopts, mopts, errorp)
                    796:        struct sockaddr_in *sin;
                    797:        struct route *ro;
                    798:        int soopts;
                    799:        struct ip_moptions *mopts;
                    800:        int *errorp;
                    801: {
                    802:        struct sockaddr_in *sin2;
                    803:        struct in_ifaddr *ia;
                    804:
                    805:        ia = (struct in_ifaddr *)0;
                    806:        /*
                    807:         * If route is known or can be allocated now,
                    808:         * our src addr is taken from the i/f, else punt.
                    809:         */
                    810:        if (ro->ro_rt &&
                    811:            (satosin(&ro->ro_dst)->sin_addr.s_addr !=
                    812:                sin->sin_addr.s_addr ||
                    813:            soopts & SO_DONTROUTE)) {
                    814:                RTFREE(ro->ro_rt);
                    815:                ro->ro_rt = (struct rtentry *)0;
                    816:        }
                    817:        if ((soopts & SO_DONTROUTE) == 0 && /*XXX*/
                    818:            (ro->ro_rt == (struct rtentry *)0 ||
                    819:            ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
                    820:                /* No route yet, so try to acquire one */
                    821:                ro->ro_dst.sa_family = AF_INET;
                    822:                ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
                    823:                satosin(&ro->ro_dst)->sin_addr = sin->sin_addr;
                    824:                rtalloc_mpath(ro, NULL, 0);
                    825:
                    826:                /*
                    827:                 * It is important to bzero out the rest of the
                    828:                 * struct sockaddr_in when mixing v6 & v4!
                    829:                 */
                    830:                sin2 = (struct sockaddr_in *)&ro->ro_dst;
                    831:                bzero(sin2->sin_zero, sizeof(sin2->sin_zero));
                    832:        }
                    833:        /*
                    834:         * If we found a route, use the address
                    835:         * corresponding to the outgoing interface
                    836:         * unless it is the loopback (in case a route
                    837:         * to our address on another net goes to loopback).
                    838:         */
                    839:        if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK))
                    840:                ia = ifatoia(ro->ro_rt->rt_ifa);
                    841:        if (ia == 0) {
                    842:                u_int16_t fport = sin->sin_port;
                    843:
                    844:                sin->sin_port = 0;
                    845:                ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin)));
                    846:                if (ia == 0)
                    847:                        ia = ifatoia(ifa_ifwithnet(sintosa(sin)));
                    848:                sin->sin_port = fport;
                    849:                if (ia == 0)
                    850:                        ia = TAILQ_FIRST(&in_ifaddr);
                    851:                if (ia == 0) {
                    852:                        *errorp = EADDRNOTAVAIL;
                    853:                        return NULL;
                    854:                }
                    855:        }
                    856:        /*
                    857:         * If the destination address is multicast and an outgoing
                    858:         * interface has been set as a multicast option, use the
                    859:         * address of that interface as our source address.
                    860:         */
                    861:        if (IN_MULTICAST(sin->sin_addr.s_addr) && mopts != NULL) {
                    862:                struct ip_moptions *imo;
                    863:                struct ifnet *ifp;
                    864:
                    865:                imo = mopts;
                    866:                if (imo->imo_multicast_ifp != NULL) {
                    867:                        ifp = imo->imo_multicast_ifp;
                    868:                        TAILQ_FOREACH(ia, &in_ifaddr, ia_list)
                    869:                                if (ia->ia_ifp == ifp)
                    870:                                        break;
                    871:                        if (ia == 0) {
                    872:                                *errorp = EADDRNOTAVAIL;
                    873:                                return NULL;
                    874:                        }
                    875:                }
                    876:        }
                    877:        return satosin(&ia->ia_addr);
                    878: }
                    879:
                    880: void
                    881: in_pcbrehash(inp)
                    882:        struct inpcb *inp;
                    883: {
                    884:        struct inpcbtable *table = inp->inp_table;
                    885:        int s;
                    886:
                    887:        s = splnet();
                    888:        LIST_REMOVE(inp, inp_lhash);
                    889:        LIST_INSERT_HEAD(INPCBLHASH(table, inp->inp_lport), inp, inp_lhash);
                    890:        LIST_REMOVE(inp, inp_hash);
                    891: #ifdef INET6
                    892:        if (inp->inp_flags & INP_IPV6) {
                    893:                LIST_INSERT_HEAD(IN6PCBHASH(table, &inp->inp_faddr6,
                    894:                    inp->inp_fport, &inp->inp_laddr6, inp->inp_lport),
                    895:                    inp, inp_hash);
                    896:        } else {
                    897: #endif /* INET6 */
                    898:                LIST_INSERT_HEAD(INPCBHASH(table, &inp->inp_faddr,
                    899:                    inp->inp_fport, &inp->inp_laddr, inp->inp_lport),
                    900:                    inp, inp_hash);
                    901: #ifdef INET6
                    902:        }
                    903: #endif /* INET6 */
                    904:        splx(s);
                    905: }
                    906:
                    907: #ifdef DIAGNOSTIC
                    908: int    in_pcbnotifymiss = 0;
                    909: #endif
                    910:
                    911: /*
                    912:  * The in(6)_pcbhashlookup functions are used to locate connected sockets
                    913:  * quickly:
                    914:  *             faddr.fport <-> laddr.lport
                    915:  * No wildcard matching is done so that listening sockets are not found.
                    916:  * If the functions return NULL in(6)_pcblookup_listen can be used to
                    917:  * find a listening/bound socket that may accept the connection.
                    918:  * After those two lookups no other are necessary.
                    919:  */
                    920: struct inpcb *
                    921: in_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg)
                    922:        struct inpcbtable *table;
                    923:        struct in_addr faddr, laddr;
                    924:        u_int fport_arg, lport_arg;
                    925: {
                    926:        struct inpcbhead *head;
                    927:        struct inpcb *inp;
                    928:        u_int16_t fport = fport_arg, lport = lport_arg;
                    929:
                    930:        head = INPCBHASH(table, &faddr, fport, &laddr, lport);
                    931:        LIST_FOREACH(inp, head, inp_hash) {
                    932: #ifdef INET6
                    933:                if (inp->inp_flags & INP_IPV6)
                    934:                        continue;       /*XXX*/
                    935: #endif
                    936:                if (inp->inp_faddr.s_addr == faddr.s_addr &&
                    937:                    inp->inp_fport == fport &&
                    938:                    inp->inp_lport == lport &&
                    939:                    inp->inp_laddr.s_addr == laddr.s_addr) {
                    940:                        /*
                    941:                         * Move this PCB to the head of hash chain so that
                    942:                         * repeated accesses are quicker.  This is analogous to
                    943:                         * the historic single-entry PCB cache.
                    944:                         */
                    945:                        if (inp != LIST_FIRST(head)) {
                    946:                                LIST_REMOVE(inp, inp_hash);
                    947:                                LIST_INSERT_HEAD(head, inp, inp_hash);
                    948:                        }
                    949:                        break;
                    950:                }
                    951:        }
                    952: #ifdef DIAGNOSTIC
                    953:        if (inp == NULL && in_pcbnotifymiss) {
                    954:                printf("in_pcbhashlookup: faddr=%08x fport=%d laddr=%08x lport=%d\n",
                    955:                    ntohl(faddr.s_addr), ntohs(fport),
                    956:                    ntohl(laddr.s_addr), ntohs(lport));
                    957:        }
                    958: #endif
                    959:        return (inp);
                    960: }
                    961:
                    962: #ifdef INET6
                    963: struct inpcb *
                    964: in6_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg)
                    965:        struct inpcbtable *table;
                    966:        struct in6_addr *faddr, *laddr;
                    967:        u_int fport_arg, lport_arg;
                    968: {
                    969:        struct inpcbhead *head;
                    970:        struct inpcb *inp;
                    971:        u_int16_t fport = fport_arg, lport = lport_arg;
                    972:
                    973:        head = IN6PCBHASH(table, faddr, fport, laddr, lport);
                    974:        LIST_FOREACH(inp, head, inp_hash) {
                    975:                if (!(inp->inp_flags & INP_IPV6))
                    976:                        continue;
                    977:                if (IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, faddr) &&
                    978:                    inp->inp_fport == fport && inp->inp_lport == lport &&
                    979:                    IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, laddr)) {
                    980:                        /*
                    981:                         * Move this PCB to the head of hash chain so that
                    982:                         * repeated accesses are quicker.  This is analogous to
                    983:                         * the historic single-entry PCB cache.
                    984:                         */
                    985:                        if (inp != LIST_FIRST(head)) {
                    986:                                LIST_REMOVE(inp, inp_hash);
                    987:                                LIST_INSERT_HEAD(head, inp, inp_hash);
                    988:                        }
                    989:                        break;
                    990:                }
                    991:        }
                    992: #ifdef DIAGNOSTIC
                    993:        if (inp == NULL && in_pcbnotifymiss) {
                    994:                printf("in6_pcbhashlookup: faddr=");
                    995:                printf(" fport=%d laddr=", ntohs(fport));
                    996:                printf(" lport=%d\n", ntohs(lport));
                    997:        }
                    998: #endif
                    999:        return (inp);
                   1000: }
                   1001: #endif /* INET6 */
                   1002:
                   1003: /*
                   1004:  * The in(6)_pcblookup_listen functions are used to locate listening
                   1005:  * sockets quickly.  This are sockets with unspecified foreign address
                   1006:  * and port:
                   1007:  *             *.*     <-> laddr.lport
                   1008:  *             *.*     <->     *.lport
                   1009:  */
                   1010: struct inpcb *
                   1011: in_pcblookup_listen(table, laddr, lport_arg, reverse)
                   1012:        struct inpcbtable *table;
                   1013:        struct in_addr laddr;
                   1014:        u_int lport_arg;
                   1015:        int reverse;
                   1016: {
                   1017:        struct inpcbhead *head;
                   1018:        struct in_addr *key1, *key2;
                   1019:        struct inpcb *inp;
                   1020:        u_int16_t lport = lport_arg;
                   1021:
                   1022:        if (reverse) {
                   1023:                key1 = &zeroin_addr;
                   1024:                key2 = &laddr;
                   1025:        } else {
                   1026:                key1 = &laddr;
                   1027:                key2 = &zeroin_addr;
                   1028:        }
                   1029:
                   1030:        head = INPCBHASH(table, &zeroin_addr, 0, key1, lport);
                   1031:        LIST_FOREACH(inp, head, inp_hash) {
                   1032: #ifdef INET6
                   1033:                if (inp->inp_flags & INP_IPV6)
                   1034:                        continue;       /*XXX*/
                   1035: #endif
                   1036:                if (inp->inp_lport == lport && inp->inp_fport == 0 &&
                   1037:                    inp->inp_laddr.s_addr == key1->s_addr &&
                   1038:                    inp->inp_faddr.s_addr == INADDR_ANY)
                   1039:                        break;
                   1040:        }
                   1041:        if (inp == NULL && key1->s_addr != key2->s_addr) {
                   1042:                head = INPCBHASH(table, &zeroin_addr, 0, key2, lport);
                   1043:                LIST_FOREACH(inp, head, inp_hash) {
                   1044: #ifdef INET6
                   1045:                        if (inp->inp_flags & INP_IPV6)
                   1046:                                continue;       /*XXX*/
                   1047: #endif
                   1048:                        if (inp->inp_lport == lport && inp->inp_fport == 0 &&
                   1049:                            inp->inp_laddr.s_addr == key2->s_addr &&
                   1050:                            inp->inp_faddr.s_addr == INADDR_ANY)
                   1051:                                break;
                   1052:                }
                   1053:        }
                   1054: #ifdef DIAGNOSTIC
                   1055:        if (inp == NULL && in_pcbnotifymiss) {
                   1056:                printf("in_pcblookup_listen: laddr=%08x lport=%d\n",
                   1057:                    ntohl(laddr.s_addr), ntohs(lport));
                   1058:        }
                   1059: #endif
                   1060:        /*
                   1061:         * Move this PCB to the head of hash chain so that
                   1062:         * repeated accesses are quicker.  This is analogous to
                   1063:         * the historic single-entry PCB cache.
                   1064:         */
                   1065:        if (inp != NULL && inp != LIST_FIRST(head)) {
                   1066:                LIST_REMOVE(inp, inp_hash);
                   1067:                LIST_INSERT_HEAD(head, inp, inp_hash);
                   1068:        }
                   1069:        return (inp);
                   1070: }
                   1071:
                   1072: #ifdef INET6
                   1073: struct inpcb *
                   1074: in6_pcblookup_listen(table, laddr, lport_arg, reverse)
                   1075:        struct inpcbtable *table;
                   1076:        struct in6_addr *laddr;
                   1077:        u_int lport_arg;
                   1078:        int reverse;
                   1079: {
                   1080:        struct inpcbhead *head;
                   1081:        struct in6_addr *key1, *key2;
                   1082:        struct inpcb *inp;
                   1083:        u_int16_t lport = lport_arg;
                   1084:
                   1085:        if (reverse) {
                   1086:                key1 = &zeroin6_addr;
                   1087:                key2 = laddr;
                   1088:        } else {
                   1089:                key1 = laddr;
                   1090:                key2 = &zeroin6_addr;
                   1091:        }
                   1092:
                   1093:        head = IN6PCBHASH(table, &zeroin6_addr, 0, key1, lport);
                   1094:        LIST_FOREACH(inp, head, inp_hash) {
                   1095:                if (!(inp->inp_flags & INP_IPV6))
                   1096:                        continue;
                   1097:                if (inp->inp_lport == lport && inp->inp_fport == 0 &&
                   1098:                    IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, key1) &&
                   1099:                    IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
                   1100:                        break;
                   1101:        }
                   1102:        if (inp == NULL && ! IN6_ARE_ADDR_EQUAL(key1, key2)) {
                   1103:                head = IN6PCBHASH(table, &zeroin6_addr, 0, key2, lport);
                   1104:                LIST_FOREACH(inp, head, inp_hash) {
                   1105:                        if (!(inp->inp_flags & INP_IPV6))
                   1106:                                continue;
                   1107:                        if (inp->inp_lport == lport && inp->inp_fport == 0 &&
                   1108:                            IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, key2) &&
                   1109:                            IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
                   1110:                                break;
                   1111:                }
                   1112:        }
                   1113: #ifdef DIAGNOSTIC
                   1114:        if (inp == NULL && in_pcbnotifymiss) {
                   1115:                printf("in6_pcblookup_listen: laddr= lport=%d\n",
                   1116:                    ntohs(lport));
                   1117:        }
                   1118: #endif
                   1119:        /*
                   1120:         * Move this PCB to the head of hash chain so that
                   1121:         * repeated accesses are quicker.  This is analogous to
                   1122:         * the historic single-entry PCB cache.
                   1123:         */
                   1124:        if (inp != NULL && inp != LIST_FIRST(head)) {
                   1125:                LIST_REMOVE(inp, inp_hash);
                   1126:                LIST_INSERT_HEAD(head, inp, inp_hash);
                   1127:        }
                   1128:        return (inp);
                   1129: }
                   1130: #endif /* INET6 */

CVSweb