Annotation of kernel/bsd/netinet/in_pcb.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
                     26: /*
                     27:  * Copyright (c) 1982, 1986, 1991, 1993, 1995
                     28:  *     The Regents of the University of California.  All rights reserved.
                     29:  *
                     30:  * Redistribution and use in source and binary forms, with or without
                     31:  * modification, are permitted provided that the following conditions
                     32:  * are met:
                     33:  * 1. Redistributions of source code must retain the above copyright
                     34:  *    notice, this list of conditions and the following disclaimer.
                     35:  * 2. Redistributions in binary form must reproduce the above copyright
                     36:  *    notice, this list of conditions and the following disclaimer in the
                     37:  *    documentation and/or other materials provided with the distribution.
                     38:  * 3. All advertising materials mentioning features or use of this software
                     39:  *    must display the following acknowledgement:
                     40:  *     This product includes software developed by the University of
                     41:  *     California, Berkeley and its contributors.
                     42:  * 4. Neither the name of the University nor the names of its contributors
                     43:  *    may be used to endorse or promote products derived from this software
                     44:  *    without specific prior written permission.
                     45:  *
                     46:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     47:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     48:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     49:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     50:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     51:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     52:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     53:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     54:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     55:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     56:  * SUCH DAMAGE.
                     57:  *
                     58:  *     @(#)in_pcb.c    8.4 (Berkeley) 5/24/95
                     59:  */
                     60: 
                     61: #include <sys/param.h>
                     62: #include <sys/systm.h>
                     63: #include <sys/malloc.h>
                     64: #include <sys/mbuf.h>
                     65: #include <sys/protosw.h>
                     66: #include <sys/socket.h>
                     67: #include <sys/socketvar.h>
                     68: #include <sys/ioctl.h>
                     69: #include <sys/errno.h>
                     70: #include <sys/time.h>
                     71: #include <sys/proc.h>
                     72: 
                     73: #include <net/if.h>
                     74: #include <net/route.h>
                     75: 
                     76: #include <netinet/in.h>
                     77: #include <netinet/in_systm.h>
                     78: #include <netinet/ip.h>
                     79: #include <netinet/in_pcb.h>
                     80: #include <netinet/in_var.h>
                     81: #include <netinet/ip_var.h>
                     82: 
                     83: #include <kern/kdebug.h>
                     84: 
                     85: 
                     86: #if KDEBUG
                     87: 
                     88: #define DBG_FNC_PCB_LOOKUP     NETDBG_CODE(DBG_NETTCP, (6 << 8))
                     89: #define DBG_FNC_PCB_HLOOKUP    NETDBG_CODE(DBG_NETTCP, ((6 << 8) | 1))
                     90: 
                     91: #endif
                     92: 
                     93: 
                     94: struct zone   *inpcb_zone;
                     95: struct in_addr zeroin_addr;
                     96: 
                     97: 
                     98: 
                     99: 
                    100: void
                    101: lport_hash_remove(inp)
                    102:         register struct inpcb *inp;
                    103: {
                    104:        if ((*inp->lport_hash_str->hash_array)[inp->lport_hash_element] == inp)
                    105:                (*inp->lport_hash_str->hash_array)[inp->lport_hash_element] = inp->lport_hash_next;
                    106: 
                    107:        if (inp->lport_hash_prev) 
                    108:                inp->lport_hash_prev->lport_hash_next = inp->lport_hash_next;
                    109: 
                    110:        if (inp->lport_hash_next) 
                    111:                inp->lport_hash_next->lport_hash_prev = inp->lport_hash_prev;
                    112: 
                    113:        inp->lport_hash_next = 0;
                    114:        inp->lport_hash_prev = 0;
                    115:        inp->lport_hash_element = -1;
                    116: }
                    117: 
                    118: 
                    119: 
                    120: 
                    121: void
                    122: lport_hash_insert(inp)
                    123:        register struct inpcb *inp;
                    124: 
                    125: {
                    126:         register u_long        h_idx;
                    127: 
                    128:        if (inp->lport_hash_element != -1)
                    129:                return;
                    130:                    
                    131:        h_idx = inp->inp_lport & inp->lport_hash_str->hash_mask;
                    132: 
                    133:        if ((*inp->lport_hash_str->hash_array)[h_idx]) {
                    134:                (*inp->lport_hash_str->hash_array)[h_idx]->lport_hash_prev = inp;
                    135:                inp->lport_hash_next = (*inp->lport_hash_str->hash_array)[h_idx];
                    136:                inp->lport_hash_prev = 0;
                    137:                (*inp->lport_hash_str->hash_array)[h_idx] = inp;
                    138:        } else {
                    139:                (*inp->lport_hash_str->hash_array)[h_idx] = inp;
                    140:                inp->lport_hash_next = 0;
                    141:                inp->lport_hash_prev = 0;
                    142:        }
                    143: 
                    144:        inp->lport_hash_element = h_idx;
                    145: }
                    146: 
                    147: 
                    148: 
                    149: 
                    150: void
                    151: hash_remove(inp)
                    152:         register struct inpcb *inp;
                    153: {
                    154:        if ((*inp->hash_str->hash_array)[inp->hash_element] == inp)
                    155:                (*inp->hash_str->hash_array)[inp->hash_element] = inp->hash_next;
                    156: 
                    157:        if (inp->hash_prev) 
                    158:                inp->hash_prev->hash_next = inp->hash_next;
                    159: 
                    160:        if (inp->hash_next) 
                    161:                inp->hash_next->hash_prev = inp->hash_prev;
                    162: 
                    163:        inp->hash_next = 0;
                    164:        inp->hash_prev = 0;
                    165:        inp->hash_element = -1;
                    166: }
                    167: 
                    168: 
                    169: 
                    170: void
                    171: hash_insert(inp)
                    172:         register struct inpcb *inp;
                    173: {
                    174:         register u_long        h_idx;
                    175: 
                    176:        if (inp->hash_element != -1)
                    177:                return;
                    178: 
                    179:        h_idx = (inp->inp_lport + inp->inp_fport + inp->inp_faddr.s_addr) & inp->hash_str->hash_mask;
                    180: 
                    181:        if ((*inp->hash_str->hash_array)[h_idx]) {
                    182:                (*inp->hash_str->hash_array)[h_idx]->hash_prev = inp;
                    183:                inp->hash_next = (*inp->hash_str->hash_array)[h_idx];
                    184:                inp->hash_prev = 0;
                    185:                (*inp->hash_str->hash_array)[h_idx] = inp;
                    186:        } else {
                    187:                (*inp->hash_str->hash_array)[h_idx] = inp;
                    188:                inp->hash_next = 0;
                    189:                inp->hash_prev = 0;
                    190:        }
                    191:        inp->hash_element = h_idx;
                    192: }
                    193: 
                    194: 
                    195: struct inpcb *inet_hash1(hash_str, l_addr, l_port, f_addr, f_port)
                    196:        struct inpcb_hash_str *hash_str;
                    197:         u_long l_addr;
                    198:        u_short l_port;
                    199:        u_long  f_addr;
                    200:        u_short f_port;
                    201: {
                    202:        return ((*hash_str->hash_array)[(l_port + f_port + f_addr) & hash_str->hash_mask]);
                    203: }
                    204: 
                    205: 
                    206: struct inpcb *inet_lport_hash1(lport_hash_str, l_port)
                    207:        struct inpcb_hash_str *lport_hash_str;
                    208:        u_short  l_port;
                    209: 
                    210: {
                    211:        return ((*lport_hash_str->hash_array)[l_port & lport_hash_str->hash_mask]);
                    212: }
                    213: 
                    214: 
                    215: 
                    216: int
                    217: in_pcballoc(so, head, hash_str, lport_hash_str)
                    218:        struct socket *so;
                    219:        struct inpcb *head;
                    220:        struct inpcb_hash_str *hash_str;
                    221:        struct inpcb_hash_str *lport_hash_str;
                    222: {
                    223:        register struct inpcb *inp;
                    224:        caddr_t               temp;
                    225: 
                    226:        if (so->cached_in_sock_layer == 0) {
                    227: #if TEMPDEBUG
                    228:            printf("PCBALLOC calling zalloc for socket %x\n", so);
                    229: #endif
                    230:            inp = zalloc(inpcb_zone);
                    231:            if (inp == NULL)
                    232:                return (ENOBUFS);
                    233:            bzero((caddr_t)inp, sizeof(*inp));
                    234:        }
                    235:        else {
                    236: #if TEMPDEBUG
                    237:            printf("PCBALLOC reusing PCB for socket %x\n", so);
                    238: #endif
                    239:            inp = so->so_saved_pcb;
                    240:            temp = inp->inp_saved_ppcb;
                    241:            bzero((caddr_t) inp, sizeof(*inp));
                    242:            inp->inp_saved_ppcb = temp;
                    243:        }
                    244: 
                    245:        inp->hash_element = -1;
                    246:        inp->lport_hash_element = -1;
                    247:        inp->inp_head = head;
                    248:        inp->hash_str = hash_str;
                    249:        inp->lport_hash_str = lport_hash_str;
                    250:        inp->inp_socket = so;
                    251:        if (head)
                    252:            insque(inp, head);
                    253:        so->so_pcb = (caddr_t)inp;
                    254:        return (0);
                    255: }
                    256: 
                    257: int
                    258: in_pcbbind(inp, nam)
                    259:        register struct inpcb *inp;
                    260:        struct mbuf *nam;
                    261: {
                    262:        register struct socket *so = inp->inp_socket;
                    263:        register struct inpcb *head = inp->inp_head;
                    264:        register struct sockaddr_in *sin;
                    265:        struct proc *p = current_proc();                /* XXX */
                    266:        u_short lport = 0;
                    267:        int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
                    268:        int error;
                    269:        register int    loop_count = 0;
                    270:        struct inpcb    *hash_head;
                    271: 
                    272: 
                    273:        if (in_ifaddr == 0)
                    274:                return (EADDRNOTAVAIL);
                    275:        if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY)
                    276:                return (EINVAL);
                    277:        if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 &&
                    278:            ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
                    279:             (so->so_options & SO_ACCEPTCONN) == 0))
                    280:                wild = INPLOOKUP_WILDCARD;
                    281:        if (nam) {
                    282:                sin = mtod(nam, struct sockaddr_in *);
                    283:                if (nam->m_len != sizeof (*sin))
                    284:                        return (EINVAL);
                    285: #ifdef notdef
                    286:                /*
                    287:                 * We should check the family, but old programs
                    288:                 * incorrectly fail to initialize it.
                    289:                 */
                    290:                if (sin->sin_family != AF_INET)
                    291:                        return (EAFNOSUPPORT);
                    292: #endif
                    293:                lport = sin->sin_port;
                    294:                if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
                    295:                        /*
                    296:                         * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
                    297:                         * allow complete duplication of binding if
                    298:                         * SO_REUSEPORT is set, or if SO_REUSEADDR is set
                    299:                         * and a multicast address is bound on both
                    300:                         * new and duplicated sockets.
                    301:                         */
                    302:                        if (so->so_options & SO_REUSEADDR)
                    303:                                reuseport = SO_REUSEADDR|SO_REUSEPORT;
                    304:                } else if (sin->sin_addr.s_addr != INADDR_ANY) {
                    305:                        sin->sin_port = 0;              /* yech... */
                    306:                        if (ifa_ifwithaddr((struct sockaddr *)sin) == 0)
                    307:                                return (EADDRNOTAVAIL);
                    308:                }
                    309:                if (lport) {
                    310:                        struct inpcb *t;
                    311: 
                    312:                        /* GROSS */
                    313:                        if (ntohs(lport) < IPPORT_RESERVED &&
                    314:                            (error = suser(p->p_ucred, &p->p_acflag)))
                    315:                                return (EACCES);
                    316: 
                    317:                        hash_head = inet_lport_hash1(inp->lport_hash_str, lport);
                    318:                        t = lport_hash_in_pcbwild(hash_head,
                    319:                                                  zeroin_addr, 0, sin->sin_addr,
                    320:                                                  lport, wild);
                    321: 
                    322:                        if (t && (reuseport & t->inp_socket->so_options) == 0)
                    323:                                return (EADDRINUSE);
                    324:                }
                    325:                inp->inp_laddr = sin->sin_addr;
                    326:        }
                    327:        if (lport == 0) {
                    328:            for (;;) {
                    329:                if (++loop_count >= (IPPORT_USERRESERVED - IPPORT_RESERVED))
                    330:                    return EADDRINUSE;
                    331: 
                    332:                if (head->inp_lport++ < IPPORT_RESERVED ||
                    333:                    head->inp_lport > IPPORT_USERRESERVED) 
                    334:                    head->inp_lport = IPPORT_RESERVED;
                    335: 
                    336:                lport = htons(head->inp_lport);
                    337: 
                    338:                hash_head = inet_lport_hash1(inp->lport_hash_str, lport);
                    339:                if (lport_hash_in_pcbwild(hash_head,
                    340:                                          zeroin_addr, 0, inp->inp_laddr, lport, wild))
                    341:                        continue;
                    342: 
                    343:                break;
                    344:            }
                    345:        }
                    346: 
                    347:        inp->inp_lport = lport;
                    348:        lport_hash_insert(inp);
                    349: 
                    350:        return (0);
                    351: }
                    352: 
                    353: /*
                    354:  * Connect from a socket to a specified address.
                    355:  * Both address and port must be specified in argument sin.
                    356:  * If don't have a local address for this socket yet,
                    357:  * then pick one.
                    358:  */
                    359: int
                    360: in_pcbconnect(inp, nam)
                    361:        register struct inpcb *inp;
                    362:        struct mbuf *nam;
                    363: {
                    364:     struct inpcb       *hash_head;
                    365:        struct in_ifaddr *ia;
                    366:        struct sockaddr_in *ifaddr;
                    367:        register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
                    368: 
                    369:        if (nam->m_len != sizeof (*sin))
                    370:                return (EINVAL);
                    371:        if (sin->sin_family != AF_INET)
                    372:                return (EAFNOSUPPORT);
                    373:        if (sin->sin_port == 0)
                    374:                return (EADDRNOTAVAIL);
                    375:        if (in_ifaddr) {
                    376:                /*
                    377:                 * If the destination address is INADDR_ANY,
                    378:                 * use the primary local address.
                    379:                 * If the supplied address is INADDR_BROADCAST,
                    380:                 * and the primary interface supports broadcast,
                    381:                 * choose the broadcast address for that interface.
                    382:                 */
                    383: #define        satosin(sa)     ((struct sockaddr_in *)(sa))
                    384: #define sintosa(sin)   ((struct sockaddr *)(sin))
                    385: #define ifatoia(ifa)   ((struct in_ifaddr *)(ifa))
                    386:                if (sin->sin_addr.s_addr == INADDR_ANY)
                    387:                    sin->sin_addr = IA_SIN(in_ifaddr)->sin_addr;
                    388:                else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST &&
                    389:                  (in_ifaddr->ia_ifp->if_flags & IFF_BROADCAST))
                    390:                    sin->sin_addr = satosin(&in_ifaddr->ia_broadaddr)->sin_addr;
                    391:        }
                    392:        if (inp->inp_laddr.s_addr == INADDR_ANY) {
                    393:                register struct route *ro;
                    394: 
                    395:                ia = (struct in_ifaddr *)0;
                    396:                /* 
                    397:                 * If route is known or can be allocated now,
                    398:                 * our src addr is taken from the i/f, else punt.
                    399:                 */
                    400:                ro = &inp->inp_route;
                    401:                if (ro->ro_rt &&
                    402:                    (satosin(&ro->ro_dst)->sin_addr.s_addr !=
                    403:                        sin->sin_addr.s_addr || 
                    404:                    inp->inp_socket->so_options & SO_DONTROUTE)) {
                    405:                        RTFREE(ro->ro_rt);
                    406:                        ro->ro_rt = (struct rtentry *)0;
                    407:                }
                    408:                if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
                    409:                    (ro->ro_rt == (struct rtentry *)0 ||
                    410:                    ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
                    411:                        /* No route yet, so try to acquire one */
                    412:                        ro->ro_dst.sa_family = AF_INET;
                    413:                        ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
                    414:                        ((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
                    415:                                sin->sin_addr;
                    416:                        rtalloc(ro);
                    417:                }
                    418:                /*
                    419:                 * If we found a route, use the address
                    420:                 * corresponding to the outgoing interface
                    421:                 * unless it is the loopback (in case a route
                    422:                 * to our address on another net goes to loopback).
                    423:                 */
                    424:                if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK))
                    425:                        ia = ifatoia(ro->ro_rt->rt_ifa);
                    426:                if (ia == 0) {
                    427:                        u_short fport = sin->sin_port;
                    428: 
                    429:                        sin->sin_port = 0;
                    430:                        ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin)));
                    431:                        if (ia == 0)
                    432:                                ia = ifatoia(ifa_ifwithnet(sintosa(sin)));
                    433:                        sin->sin_port = fport;
                    434:                        if (ia == 0)
                    435:                                ia = in_ifaddr;
                    436:                        if (ia == 0)
                    437:                                return (EADDRNOTAVAIL);
                    438:                }
                    439:                /*
                    440:                 * If the destination address is multicast and an outgoing
                    441:                 * interface has been set as a multicast option, use the
                    442:                 * address of that interface as our source address.
                    443:                 */
                    444:                if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) &&
                    445:                    inp->inp_moptions != NULL) {
                    446:                        struct ip_moptions *imo;
                    447:                        struct ifnet *ifp;
                    448: 
                    449:                        imo = inp->inp_moptions;
                    450:                        if (imo->imo_multicast_ifp != NULL) {
                    451:                                ifp = imo->imo_multicast_ifp;
                    452:                                for (ia = in_ifaddr; ia; ia = ia->ia_next)
                    453:                                        if (ia->ia_ifp == ifp)
                    454:                                                break;
                    455:                                if (ia == 0)
                    456:                                        return (EADDRNOTAVAIL);
                    457:                        }
                    458:                }
                    459:                ifaddr = (struct sockaddr_in *)&ia->ia_addr;
                    460:        }
                    461: 
                    462:        if ( !(inp->inp_flags & INP_NOLOOKUP)) {
                    463:                hash_head = inet_hash1(inp->hash_str,
                    464:                                       inp->inp_laddr.s_addr ? inp->inp_laddr.s_addr : ifaddr->sin_addr.s_addr,
                    465:                                       inp->inp_lport,
                    466:                                       sin->sin_addr.s_addr,
                    467:                                       sin->sin_port);
                    468: 
                    469:                if (hash_in_pcblookup(hash_head,
                    470:                                      sin->sin_addr,
                    471:                                      sin->sin_port,
                    472:                                      inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
                    473:                                      inp->inp_lport))
                    474:                        return (EADDRINUSE);
                    475:        }
                    476: 
                    477: 
                    478:        if (inp->inp_laddr.s_addr == INADDR_ANY) {
                    479:                if (inp->inp_lport == 0)
                    480:                        (void)in_pcbbind(inp, (struct mbuf *)0);
                    481:                inp->inp_laddr = ifaddr->sin_addr;
                    482:        }
                    483:        inp->inp_faddr = sin->sin_addr;
                    484:        inp->inp_fport = sin->sin_port;
                    485:        hash_insert(inp);
                    486:        return (0);
                    487: }
                    488: 
                    489: int
                    490: in_pcbdisconnect(inp)
                    491:        struct inpcb *inp;
                    492: {
                    493: 
                    494:        inp->inp_faddr.s_addr = INADDR_ANY;
                    495:        inp->inp_fport = 0;
                    496: 
                    497:        if (inp->inp_socket->so_state & SS_NOFDREF)
                    498:                in_pcbdetach(inp);
                    499:        else {
                    500:                if (inp->hash_element >= 0)
                    501:                        hash_remove(inp);
                    502:        }
                    503: }
                    504: 
                    505: int
                    506: in_pcbdetach(inp)
                    507:        struct inpcb *inp;
                    508: {
                    509:        struct socket *so = inp->inp_socket;
                    510: 
                    511:        if (inp->hash_element >= 0)
                    512:                hash_remove(inp);
                    513: 
                    514:        if (inp->lport_hash_element >= 0)
                    515:                lport_hash_remove(inp);
                    516: #if TEMPDEBUG
                    517:        if (so->cached_in_sock_layer)
                    518:            printf("PCB_DETACH for cached socket %x\n", so);
                    519:        else
                    520:            printf("PCB_DETACH for allocated socket %x\n", so);
                    521: #endif
                    522:        so->so_pcb = 0;
                    523: 
                    524:        if (inp->inp_options)
                    525:                (void)m_free(inp->inp_options);
                    526:        if (inp->inp_route.ro_rt)
                    527:                rtfree(inp->inp_route.ro_rt);
                    528:        ip_freemoptions(inp->inp_moptions);
                    529:        if ((inp->inp_next) && (inp->inp_prev))
                    530:            remque(inp);
                    531: 
                    532:        if (so->cached_in_sock_layer)
                    533:                so->so_saved_pcb = inp;
                    534:        else
                    535:                zfree(inpcb_zone, (vm_offset_t) inp);
                    536:        sofree(so);
                    537: }
                    538: 
                    539: int
                    540: in_setsockaddr(inp, nam)
                    541:        register struct inpcb *inp;
                    542:        struct mbuf *nam;
                    543: {
                    544:        register struct sockaddr_in *sin;
                    545:        
                    546:        nam->m_len = sizeof (*sin);
                    547:        sin = mtod(nam, struct sockaddr_in *);
                    548:        bzero((caddr_t)sin, sizeof (*sin));
                    549:        sin->sin_family = AF_INET;
                    550:        sin->sin_len = sizeof(*sin);
                    551:        sin->sin_port = inp->inp_lport;
                    552:        sin->sin_addr = inp->inp_laddr;
                    553: }
                    554: 
                    555: int
                    556: in_setpeeraddr(inp, nam)
                    557:        struct inpcb *inp;
                    558:        struct mbuf *nam;
                    559: {
                    560:        register struct sockaddr_in *sin;
                    561:        
                    562:        nam->m_len = sizeof (*sin);
                    563:        sin = mtod(nam, struct sockaddr_in *);
                    564:        bzero((caddr_t)sin, sizeof (*sin));
                    565:        sin->sin_family = AF_INET;
                    566:        sin->sin_len = sizeof(*sin);
                    567:        sin->sin_port = inp->inp_fport;
                    568:        sin->sin_addr = inp->inp_faddr;
                    569: }
                    570: 
                    571: /*
                    572:  * Pass some notification to all connections of a protocol
                    573:  * associated with address dst.  The local address and/or port numbers
                    574:  * may be specified to limit the search.  The "usual action" will be
                    575:  * taken, depending on the ctlinput cmd.  The caller must filter any
                    576:  * cmds that are uninteresting (e.g., no error in the map).
                    577:  * Call the protocol specific routine (if any) to report
                    578:  * any errors for each matching socket.
                    579:  *
                    580:  * Must be called at splnet.
                    581:  */
                    582: int
                    583: in_pcbnotify(head, dst, fport_arg, laddr, lport_arg, cmd, notify)
                    584:        struct inpcb *head;
                    585:        struct sockaddr *dst;
                    586:        u_int fport_arg, lport_arg;
                    587:        struct in_addr laddr;
                    588:        int cmd;
                    589:        void (*notify) __P((struct inpcb *, int));
                    590: {
                    591:        extern u_char inetctlerrmap[];
                    592:        register struct inpcb *inp, *oinp;
                    593:        struct in_addr faddr;
                    594:        u_short fport = fport_arg, lport = lport_arg;
                    595:        int errno;
                    596: 
                    597:        if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET)
                    598:                return;
                    599:        faddr = ((struct sockaddr_in *)dst)->sin_addr;
                    600:        if (faddr.s_addr == INADDR_ANY)
                    601:                return;
                    602: 
                    603:        /*
                    604:         * Redirects go to all references to the destination,
                    605:         * and use in_rtchange to invalidate the route cache.
                    606:         * Dead host indications: notify all references to the destination.
                    607:         * Otherwise, if we have knowledge of the local port and address,
                    608:         * deliver only to that socket.
                    609:         */
                    610:        if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
                    611:                fport = 0;
                    612:                lport = 0;
                    613:                laddr.s_addr = 0;
                    614:                if (cmd != PRC_HOSTDEAD)
                    615:                        notify = in_rtchange;
                    616:        }
                    617:        errno = inetctlerrmap[cmd];
                    618:        for (inp = head->inp_next; inp != head;) {
                    619:                if (inp->inp_faddr.s_addr != faddr.s_addr ||
                    620:                    inp->inp_socket == 0 ||
                    621:                    (lport && inp->inp_lport != lport) ||
                    622:                    (laddr.s_addr && inp->inp_laddr.s_addr != laddr.s_addr) ||
                    623:                    (fport && inp->inp_fport != fport)) {
                    624:                        inp = inp->inp_next;
                    625:                        continue;
                    626:                }
                    627:                oinp = inp;
                    628:                inp = inp->inp_next;
                    629:                if (notify)
                    630:                        (*notify)(oinp, errno);
                    631:        }
                    632: }
                    633: 
                    634: /*
                    635:  * Check for alternatives when higher level complains
                    636:  * about service problems.  For now, invalidate cached
                    637:  * routing information.  If the route was created dynamically
                    638:  * (by a redirect), time to try a default gateway again.
                    639:  */
                    640: int
                    641: in_losing(inp)
                    642:        struct inpcb *inp;
                    643: {
                    644:        register struct rtentry *rt;
                    645:        struct rt_addrinfo info;
                    646: 
                    647:        if ((rt = inp->inp_route.ro_rt)) {
                    648:                inp->inp_route.ro_rt = 0;
                    649:                bzero((caddr_t)&info, sizeof(info));
                    650:                info.rti_info[RTAX_DST] =
                    651:                        (struct sockaddr *)&inp->inp_route.ro_dst;
                    652:                info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
                    653:                info.rti_info[RTAX_NETMASK] = rt_mask(rt);
                    654:                rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
                    655:                if (rt->rt_flags & RTF_DYNAMIC)
                    656:                        (void) rtrequest(RTM_DELETE, rt_key(rt),
                    657:                                rt->rt_gateway, rt_mask(rt), rt->rt_flags, 
                    658:                                (struct rtentry **)0);
                    659:                else 
                    660:                /*
                    661:                 * A new route can be allocated
                    662:                 * the next time output is attempted.
                    663:                 */
                    664:                        rtfree(rt);
                    665:        }
                    666: }
                    667: 
                    668: /*
                    669:  * After a routing change, flush old routing
                    670:  * and allocate a (hopefully) better one.
                    671:  */
                    672: void
                    673: in_rtchange(inp, errno)
                    674:        register struct inpcb *inp;
                    675:        int errno;
                    676: {
                    677:        if (inp->inp_route.ro_rt) {
                    678:                rtfree(inp->inp_route.ro_rt);
                    679:                inp->inp_route.ro_rt = 0;
                    680:                /*
                    681:                 * A new route can be allocated the next time
                    682:                 * output is attempted.
                    683:                 */
                    684:        }
                    685: }
                    686: 
                    687: struct inpcb *
                    688: in_pcblookup(head, faddr, fport_arg, laddr, lport_arg, flags)
                    689:        struct inpcb *head;
                    690:        struct in_addr faddr, laddr;
                    691:        u_int fport_arg, lport_arg;
                    692:        int flags;
                    693: {
                    694:        register struct inpcb *inp, *match = 0;
                    695:        int matchwild = 3, wildcard;
                    696:        u_short fport = fport_arg, lport = lport_arg;
                    697: #if KDEBUG
                    698:        register int checked = 0;
                    699: #endif
                    700:        KERNEL_DEBUG(DBG_FNC_PCB_LOOKUP | DBG_FUNC_START, 0,0,0,0,0);
                    701: 
                    702:        for (inp = head->inp_next; inp != head; inp = inp->inp_next) {
                    703: #if KDEBUG
                    704:                checked++;
                    705: #endif
                    706:                if (inp->inp_lport != lport)
                    707:                        continue;
                    708:                wildcard = 0;
                    709:                if (inp->inp_laddr.s_addr != INADDR_ANY) {
                    710:                        if (laddr.s_addr == INADDR_ANY)
                    711:                                wildcard++;
                    712:                        else if (inp->inp_laddr.s_addr != laddr.s_addr)
                    713:                                continue;
                    714:                } else {
                    715:                        if (laddr.s_addr != INADDR_ANY)
                    716:                                wildcard++;
                    717:                }
                    718:                if (inp->inp_faddr.s_addr != INADDR_ANY) {
                    719:                        if (faddr.s_addr == INADDR_ANY)
                    720:                                wildcard++;
                    721:                        else if (inp->inp_faddr.s_addr != faddr.s_addr ||
                    722:                            inp->inp_fport != fport)
                    723:                                continue;
                    724:                } else {
                    725:                        if (faddr.s_addr != INADDR_ANY)
                    726:                                wildcard++;
                    727:                }
                    728:                if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)
                    729:                        continue;
                    730:                if (wildcard < matchwild) {
                    731:                        match = inp;
                    732:                        matchwild = wildcard;
                    733:                        if (matchwild == 0)
                    734:                                break;
                    735:                }
                    736:        }
                    737: #if KDEBUG
                    738:        KERNEL_DEBUG(DBG_FNC_PCB_LOOKUP | DBG_FUNC_END, checked,match,0,0,0);
                    739: #endif
                    740:        return (match);
                    741: }
                    742: 
                    743: 
                    744: 
                    745: struct inpcb *
                    746: hash_in_pcbwild(head, faddr, fport_arg, laddr, lport_arg, flags)
                    747:        struct inpcb *head;
                    748:        struct in_addr faddr, laddr;
                    749:        u_int fport_arg, lport_arg;
                    750:        int flags;
                    751: {
                    752:        register struct inpcb *inp, *match = 0;
                    753:        int matchwild = 3, wildcard;
                    754:        u_short fport = fport_arg, lport = lport_arg;
                    755: #if KDEBUG
                    756:        register int checked = 0;
                    757: #endif
                    758: 
                    759:        KERNEL_DEBUG(DBG_FNC_PCB_LOOKUP | DBG_FUNC_START, 0,0,0,0,-1);
                    760: 
                    761:        for (inp = head; inp != 0; inp = inp->hash_next) {
                    762: #if KDEBUG
                    763:                checked++;
                    764: #endif
                    765:                if (inp->inp_lport != lport)
                    766:                        continue;
                    767:                wildcard = 0;
                    768:                if (inp->inp_laddr.s_addr != INADDR_ANY) {
                    769:                        if (laddr.s_addr == INADDR_ANY)
                    770:                                wildcard++;
                    771:                        else if (inp->inp_laddr.s_addr != laddr.s_addr)
                    772:                                continue;
                    773:                } else {
                    774:                        if (laddr.s_addr != INADDR_ANY)
                    775:                                wildcard++;
                    776:                }
                    777:                if (inp->inp_faddr.s_addr != INADDR_ANY) {
                    778:                        if (faddr.s_addr == INADDR_ANY)
                    779:                                wildcard++;
                    780:                        else if (inp->inp_faddr.s_addr != faddr.s_addr ||
                    781:                            inp->inp_fport != fport)
                    782:                                continue;
                    783:                } else {
                    784:                        if (faddr.s_addr != INADDR_ANY)
                    785:                                wildcard++;
                    786:                }
                    787:                if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)
                    788:                        continue;
                    789:                if (wildcard < matchwild) {
                    790:                        match = inp;
                    791:                        matchwild = wildcard;
                    792:                        if (matchwild == 0)
                    793:                                break;
                    794:                }
                    795:        }
                    796: #if KDEBUG
                    797:        KERNEL_DEBUG(DBG_FNC_PCB_LOOKUP | DBG_FUNC_END, checked,match,0,0,-1);
                    798: #endif
                    799:        return (match);
                    800: }
                    801: 
                    802: 
                    803: 
                    804: struct inpcb *
                    805: lport_hash_in_pcbwild(head, faddr, fport_arg, laddr, lport_arg, flags)
                    806:        struct inpcb *head;
                    807:        struct in_addr faddr, laddr;
                    808:        u_int fport_arg, lport_arg;
                    809:        int flags;
                    810: {
                    811:        register struct inpcb *inp, *match = 0;
                    812:        int matchwild = 3, wildcard;
                    813:        u_short fport = fport_arg, lport = lport_arg;
                    814: #if KDEBUG
                    815:        register int checked = 0;
                    816: #endif
                    817: 
                    818:        KERNEL_DEBUG(DBG_FNC_PCB_LOOKUP | DBG_FUNC_START, 0,0,0,0,-1);
                    819: 
                    820:        for (inp = head; inp != 0; inp = inp->lport_hash_next) {
                    821: #if KDEBUG
                    822:                checked++;
                    823: #endif
                    824:                if (inp->inp_lport != lport)
                    825:                        continue;
                    826:                wildcard = 0;
                    827:                if (inp->inp_laddr.s_addr != INADDR_ANY) {
                    828:                        if (laddr.s_addr == INADDR_ANY)
                    829:                                wildcard++;
                    830:                        else if (inp->inp_laddr.s_addr != laddr.s_addr)
                    831:                                continue;
                    832:                } else {
                    833:                        if (laddr.s_addr != INADDR_ANY)
                    834:                                wildcard++;
                    835:                }
                    836:                if (inp->inp_faddr.s_addr != INADDR_ANY) {
                    837:                        if (faddr.s_addr == INADDR_ANY)
                    838:                                wildcard++;
                    839:                        else if (inp->inp_faddr.s_addr != faddr.s_addr ||
                    840:                            inp->inp_fport != fport)
                    841:                                continue;
                    842:                } else {
                    843:                        if (faddr.s_addr != INADDR_ANY)
                    844:                                wildcard++;
                    845:                }
                    846:                if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)
                    847:                        continue;
                    848:                if (wildcard < matchwild) {
                    849:                        match = inp;
                    850:                        matchwild = wildcard;
                    851:                        if (matchwild == 0)
                    852:                                break;
                    853:                }
                    854:        }
                    855: #if KDEBUG
                    856:        KERNEL_DEBUG(DBG_FNC_PCB_LOOKUP | DBG_FUNC_END, checked,match,0,0,-1);
                    857: #endif
                    858:        return (match);
                    859: }
                    860: 
                    861: 
                    862: 
                    863: 
                    864: 
                    865: struct inpcb *
                    866: hash_in_pcblookup(head, faddr, fport_arg, laddr, lport_arg)
                    867:        struct inpcb *head;
                    868:        struct in_addr faddr, laddr;
                    869:        u_int fport_arg, lport_arg;
                    870: {
                    871:        register struct inpcb *inp;
                    872:        u_short fport = fport_arg, lport = lport_arg;
                    873: #if KDEBUG
                    874:        register int checked = 0;
                    875: #endif
                    876:        KERNEL_DEBUG(DBG_FNC_PCB_HLOOKUP | DBG_FUNC_START, 0,0,0,0,0);
                    877: 
                    878:        for (inp = head; inp != 0; inp = inp->hash_next) {
                    879: #if KDEBUG
                    880:                checked++;
                    881: #endif
                    882:                if (inp->inp_lport == lport && inp->inp_laddr.s_addr == laddr.s_addr &&
                    883:                    inp->inp_faddr.s_addr == faddr.s_addr && inp->inp_fport == fport)
                    884:                        break;
                    885:        }
                    886: #if KDEBUG
                    887:        KERNEL_DEBUG(DBG_FNC_PCB_HLOOKUP | DBG_FUNC_END, checked,inp,0,0,0);
                    888: #endif
                    889:         return (inp);
                    890: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.