Annotation of XNU/bsd/netiso/tp_pcb.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*-
        !            23:  * Copyright (c) 1991, 1993
        !            24:  *     The Regents of the University of California.  All rights reserved.
        !            25:  *
        !            26:  * Redistribution and use in source and binary forms, with or without
        !            27:  * modification, are permitted provided that the following conditions
        !            28:  * are met:
        !            29:  * 1. Redistributions of source code must retain the above copyright
        !            30:  *    notice, this list of conditions and the following disclaimer.
        !            31:  * 2. Redistributions in binary form must reproduce the above copyright
        !            32:  *    notice, this list of conditions and the following disclaimer in the
        !            33:  *    documentation and/or other materials provided with the distribution.
        !            34:  * 3. All advertising materials mentioning features or use of this software
        !            35:  *    must display the following acknowledgement:
        !            36:  *     This product includes software developed by the University of
        !            37:  *     California, Berkeley and its contributors.
        !            38:  * 4. Neither the name of the University nor the names of its contributors
        !            39:  *    may be used to endorse or promote products derived from this software
        !            40:  *    without specific prior written permission.
        !            41:  *
        !            42:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            43:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            44:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            45:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            46:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            47:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            48:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            49:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            50:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            51:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            52:  * SUCH DAMAGE.
        !            53:  *
        !            54:  *     @(#)tp_pcb.c    8.1 (Berkeley) 6/10/93
        !            55:  */
        !            56: 
        !            57: /***********************************************************
        !            58:                                Copyright IBM Corporation 1987
        !            59: 
        !            60:                       All Rights Reserved
        !            61: 
        !            62: Permission to use, copy, modify, and distribute this software and its 
        !            63: documentation for any purpose and without fee is hereby granted, 
        !            64: provided that the above copyright notice appear in all copies and that
        !            65: both that copyright notice and this permission notice appear in 
        !            66: supporting documentation, and that the name of IBM not be
        !            67: used in advertising or publicity pertaining to distribution of the
        !            68: software without specific, written prior permission.  
        !            69: 
        !            70: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
        !            71: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
        !            72: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
        !            73: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
        !            74: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
        !            75: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
        !            76: SOFTWARE.
        !            77: 
        !            78: ******************************************************************/
        !            79: 
        !            80: /*
        !            81:  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
        !            82:  */
        !            83: /* 
        !            84:  * ARGO TP
        !            85:  *
        !            86:  *
        !            87:  * This is the initialization and cleanup stuff - 
        !            88:  * for the tp machine in general as well as  for the individual pcbs.
        !            89:  * tp_init() is called at system startup.  tp_attach() and tp_getref() are
        !            90:  * called when a socket is created.  tp_detach() and tp_freeref()
        !            91:  * are called during the closing stage and/or when the reference timer 
        !            92:  * goes off. 
        !            93:  * tp_soisdisconnecting() and tp_soisdisconnected() are tp-specific 
        !            94:  * versions of soisconnect*
        !            95:  * and are called (obviously) during the closing phase.
        !            96:  *
        !            97:  */
        !            98: 
        !            99: #include <sys/param.h>
        !           100: #include <sys/systm.h>
        !           101: #include <sys/mbuf.h>
        !           102: #include <sys/socket.h>
        !           103: #include <sys/socketvar.h>
        !           104: #include <sys/domain.h>
        !           105: #include <sys/protosw.h>
        !           106: #include <sys/errno.h>
        !           107: #include <sys/time.h>
        !           108: 
        !           109: #include <netiso/argo_debug.h>
        !           110: #include <netiso/tp_param.h>
        !           111: #include <netiso/tp_timer.h>
        !           112: #include <netiso/tp_ip.h>
        !           113: #include <netiso/tp_stat.h>
        !           114: #include <netiso/tp_pcb.h>
        !           115: #include <netiso/tp_tpdu.h>
        !           116: #include <netiso/tp_trace.h>
        !           117: #include <netiso/tp_meas.h>
        !           118: #include <netiso/tp_seq.h>
        !           119: #include <netiso/tp_clnp.h>
        !           120: 
        !           121: /* ticks are in units of: 
        !           122:  * 500 nano-fortnights ;-) or
        !           123:  * 500 ms or 
        !           124:  * 1/2 second 
        !           125:  */
        !           126: 
        !           127: struct tp_conn_param tp_conn_param[] = {
        !           128:        /* ISO_CLNS: TP4 CONNECTION LESS */
        !           129:        {
        !           130:                TP_NRETRANS,    /* short p_Nretrans;  */
        !           131:                20,             /* 10 sec */    /* short p_dr_ticks;  */
        !           132: 
        !           133:                20,             /* 10 sec */    /* short p_cc_ticks; */
        !           134:                20,             /* 10 sec */    /* short p_dt_ticks; */
        !           135: 
        !           136:                40,             /* 20 sec */    /* short p_x_ticks;      */
        !           137:                80,             /* 40 sec */    /* short p_cr_ticks;*/
        !           138: 
        !           139:                240,    /* 2 min */     /* short p_keepalive_ticks;*/
        !           140:                10,             /* 5 sec */     /* short p_sendack_ticks;  */
        !           141: 
        !           142:                600,    /* 5 min */     /* short p_ref_ticks;   */
        !           143:                360,    /* 3 min */     /* short p_inact_ticks; */
        !           144: 
        !           145:                (short) 100,                    /* short p_lcdtfract */
        !           146:                (short) TP_SOCKBUFSIZE, /* short p_winsize */
        !           147:                TP_TPDUSIZE,                    /* u_char p_tpdusize */
        !           148: 
        !           149:                TPACK_WINDOW,                   /* 4 bits p_ack_strat */
        !           150:                TPRX_USE_CW | TPRX_FASTSTART, 
        !           151:                                                                /* 4 bits p_rx_strat*/
        !           152:                TP_CLASS_4 | TP_CLASS_0,/* 5 bits p_class */
        !           153:                1,                                              /* 1 bit xtd format */
        !           154:                1,                                              /* 1 bit xpd service */
        !           155:                1,                                              /* 1 bit use_checksum */
        !           156:                0,                                              /* 1 bit use net xpd */
        !           157:                0,                                              /* 1 bit use rcc */
        !           158:                0,                                              /* 1 bit use efc */
        !           159:                1,                                              /* no disc indications */
        !           160:                0,                                              /* don't change params */
        !           161:                ISO_CLNS,                               /* p_netservice */
        !           162:        },
        !           163:        /* IN_CLNS: TP4 CONNECTION LESS */
        !           164:        {
        !           165:                TP_NRETRANS,    /* short p_Nretrans;  */
        !           166:                20,             /* 10 sec */    /* short p_dr_ticks;  */
        !           167: 
        !           168:                20,             /* 10 sec */    /* short p_cc_ticks; */
        !           169:                20,             /* 10 sec */    /* short p_dt_ticks; */
        !           170: 
        !           171:                40,             /* 20 sec */    /* short p_x_ticks;      */
        !           172:                80,             /* 40 sec */    /* short p_cr_ticks;*/
        !           173: 
        !           174:                240,    /* 2 min */     /* short p_keepalive_ticks;*/
        !           175:                10,             /* 5 sec */     /* short p_sendack_ticks;  */
        !           176: 
        !           177:                600,    /* 5 min */     /* short p_ref_ticks;   */
        !           178:                360,    /* 3 min */     /* short p_inact_ticks; */
        !           179: 
        !           180:                (short) 100,                    /* short p_lcdtfract */
        !           181:                (short) TP_SOCKBUFSIZE, /* short p_winsize */
        !           182:                TP_TPDUSIZE,                    /* u_char p_tpdusize */
        !           183: 
        !           184:                TPACK_WINDOW,                   /* 4 bits p_ack_strat */
        !           185:                TPRX_USE_CW | TPRX_FASTSTART, 
        !           186:                                                                /* 4 bits p_rx_strat*/
        !           187:                TP_CLASS_4,                             /* 5 bits p_class */
        !           188:                1,                                              /* 1 bit xtd format */
        !           189:                1,                                              /* 1 bit xpd service */
        !           190:                1,                                              /* 1 bit use_checksum */
        !           191:                0,                                              /* 1 bit use net xpd */
        !           192:                0,                                              /* 1 bit use rcc */
        !           193:                0,                                              /* 1 bit use efc */
        !           194:                1,                                              /* no disc indications */
        !           195:                0,                                              /* don't change params */
        !           196:                IN_CLNS,                                /* p_netservice */
        !           197:        },
        !           198:        /* ISO_CONS: TP0 CONNECTION MODE */
        !           199:        {
        !           200:                TP_NRETRANS,                    /* short p_Nretrans;  */
        !           201:                0,              /* n/a */               /* short p_dr_ticks; */
        !           202: 
        !           203:                40,             /* 20 sec */    /* short p_cc_ticks; */
        !           204:                0,              /* n/a */               /* short p_dt_ticks; */
        !           205: 
        !           206:                0,              /* n/a */               /* short p_x_ticks;     */
        !           207:                360,    /* 3  min */    /* short p_cr_ticks;*/
        !           208: 
        !           209:                0,              /* n/a */               /* short p_keepalive_ticks;*/
        !           210:                0,              /* n/a */               /* short p_sendack_ticks; */
        !           211: 
        !           212:                600,    /* for cr/cc to clear *//* short p_ref_ticks;   */
        !           213:                0,              /* n/a */               /* short p_inact_ticks; */
        !           214: 
        !           215:                /* Use tp4 defaults just in case the user changes ONLY
        !           216:                 * the class 
        !           217:                 */
        !           218:                (short) 100,                    /* short p_lcdtfract */
        !           219:                (short) TP0_SOCKBUFSIZE,        /* short p_winsize */
        !           220:                TP0_TPDUSIZE,                   /* 8 bits p_tpdusize */
        !           221: 
        !           222:                0,                                              /* 4 bits p_ack_strat */
        !           223:                0,                                              /* 4 bits p_rx_strat*/
        !           224:                TP_CLASS_0,                             /* 5 bits p_class */
        !           225:                0,                                              /* 1 bit xtd format */
        !           226:                0,                                              /* 1 bit xpd service */
        !           227:                0,                                              /* 1 bit use_checksum */
        !           228:                0,                                              /* 1 bit use net xpd */
        !           229:                0,                                              /* 1 bit use rcc */
        !           230:                0,                                              /* 1 bit use efc */
        !           231:                0,                                              /* no disc indications */
        !           232:                0,                                              /* don't change params */
        !           233:                ISO_CONS,                               /* p_netservice */
        !           234:        },
        !           235:        /* ISO_COSNS: TP4 CONNECTION LESS SERVICE over CONSNS */
        !           236:        {
        !           237:                TP_NRETRANS,    /* short p_Nretrans;  */
        !           238:                40,             /* 20 sec */    /* short p_dr_ticks;  */
        !           239: 
        !           240:                40,             /* 20 sec */    /* short p_cc_ticks; */
        !           241:                80,             /* 40 sec */    /* short p_dt_ticks; */
        !           242: 
        !           243:                120,            /* 1 min */     /* short p_x_ticks;      */
        !           244:                360,            /* 3 min */     /* short p_cr_ticks;*/
        !           245: 
        !           246:                360,    /* 3 min */     /* short p_keepalive_ticks;*/
        !           247:                20,             /* 10 sec */    /* short p_sendack_ticks;  */
        !           248: 
        !           249:                600,    /* 5 min */     /* short p_ref_ticks;   */
        !           250:                480,    /* 4 min */     /* short p_inact_ticks; */
        !           251: 
        !           252:                (short) 100,                    /* short p_lcdtfract */
        !           253:                (short) TP0_SOCKBUFSIZE,        /* short p_winsize */
        !           254:                TP0_TPDUSIZE,                   /* u_char p_tpdusize */
        !           255: 
        !           256:                TPACK_WINDOW,                   /* 4 bits p_ack_strat */
        !           257:                TPRX_USE_CW ,                   /* No fast start */ 
        !           258:                                                                /* 4 bits p_rx_strat*/
        !           259:                TP_CLASS_4 | TP_CLASS_0,/* 5 bits p_class */
        !           260:                0,                                              /* 1 bit xtd format */
        !           261:                1,                                              /* 1 bit xpd service */
        !           262:                1,                                              /* 1 bit use_checksum */
        !           263:                0,                                              /* 1 bit use net xpd */
        !           264:                0,                                              /* 1 bit use rcc */
        !           265:                0,                                              /* 1 bit use efc */
        !           266:                0,                                              /* no disc indications */
        !           267:                0,                                              /* don't change params */
        !           268:                ISO_COSNS,                              /* p_netservice */
        !           269:        },
        !           270: };
        !           271: 
        !           272: #if INET
        !           273: int            in_putnetaddr();
        !           274: int            in_getnetaddr();
        !           275: int            in_cmpnetaddr();
        !           276: int    in_putsufx(); 
        !           277: int    in_getsufx(); 
        !           278: int    in_recycle_tsuffix(); 
        !           279: int    tpip_mtu(); 
        !           280: int    in_pcbbind(); 
        !           281: int    in_pcbconnect(); 
        !           282: int    in_pcbdisconnect(); 
        !           283: int    in_pcbdetach(); 
        !           284: int    in_pcballoc(); 
        !           285: int    tpip_output(); 
        !           286: int    tpip_output_dg(); 
        !           287: struct inpcb   tp_inpcb;
        !           288: #endif /* INET */
        !           289: #if ISO
        !           290: int            iso_putnetaddr();
        !           291: int            iso_getnetaddr();
        !           292: int            iso_cmpnetaddr();
        !           293: int    iso_putsufx(); 
        !           294: int    iso_getsufx(); 
        !           295: int    iso_recycle_tsuffix(); 
        !           296: int            tpclnp_mtu(); 
        !           297: int            iso_pcbbind(); 
        !           298: int            iso_pcbconnect(); 
        !           299: int            iso_pcbdisconnect(); 
        !           300: int    iso_pcbdetach(); 
        !           301: int    iso_pcballoc(); 
        !           302: int    tpclnp_output(); 
        !           303: int    tpclnp_output_dg(); 
        !           304: int            iso_nlctloutput();
        !           305: struct isopcb  tp_isopcb;
        !           306: #endif /* ISO */
        !           307: #if TPCONS
        !           308: int            iso_putnetaddr();
        !           309: int            iso_getnetaddr();
        !           310: int            iso_cmpnetaddr();
        !           311: int    iso_putsufx(); 
        !           312: int    iso_getsufx(); 
        !           313: int    iso_recycle_tsuffix(); 
        !           314: int            iso_pcbbind(); 
        !           315: int            tpcons_pcbconnect(); 
        !           316: int            tpclnp_mtu();
        !           317: int            iso_pcbdisconnect(); 
        !           318: int    iso_pcbdetach(); 
        !           319: int    iso_pcballoc(); 
        !           320: int    tpcons_output(); 
        !           321: struct isopcb  tp_isopcb;
        !           322: #endif /* TPCONS */
        !           323: 
        !           324: 
        !           325: struct nl_protosw nl_protosw[] = {
        !           326:        /* ISO_CLNS */
        !           327: #if ISO
        !           328:        { AF_ISO, iso_putnetaddr, iso_getnetaddr, iso_cmpnetaddr,
        !           329:                iso_putsufx, iso_getsufx,
        !           330:                iso_recycle_tsuffix,
        !           331:                tpclnp_mtu, iso_pcbbind, iso_pcbconnect,
        !           332:                iso_pcbdisconnect,      iso_pcbdetach,
        !           333:                iso_pcballoc,
        !           334:                tpclnp_output, tpclnp_output_dg, iso_nlctloutput,
        !           335:                (caddr_t) &tp_isopcb,
        !           336:                },
        !           337: #else
        !           338:        { 0 },
        !           339: #endif /* ISO */
        !           340:        /* IN_CLNS */
        !           341: #if INET
        !           342:        { AF_INET, in_putnetaddr, in_getnetaddr, in_cmpnetaddr,
        !           343:                in_putsufx, in_getsufx,
        !           344:                in_recycle_tsuffix,
        !           345:                tpip_mtu, in_pcbbind, in_pcbconnect,
        !           346:                in_pcbdisconnect,       in_pcbdetach,
        !           347:                in_pcballoc,
        !           348:                tpip_output, tpip_output_dg, /* nl_ctloutput */ NULL,
        !           349:                (caddr_t) &tp_inpcb,
        !           350:                },
        !           351: #else
        !           352:        { 0 },
        !           353: #endif /* INET */
        !           354:        /* ISO_CONS */
        !           355: #if defined(ISO) && defined(TPCONS)
        !           356:        { AF_ISO, iso_putnetaddr, iso_getnetaddr, iso_cmpnetaddr,
        !           357:                iso_putsufx, iso_getsufx,
        !           358:                iso_recycle_tsuffix,
        !           359:                tpclnp_mtu, iso_pcbbind, tpcons_pcbconnect,
        !           360:                iso_pcbdisconnect,      iso_pcbdetach,
        !           361:                iso_pcballoc,
        !           362:                tpcons_output, tpcons_output, iso_nlctloutput,
        !           363:                (caddr_t) &tp_isopcb,
        !           364:                },
        !           365: #else
        !           366:        { 0 },
        !           367: #endif /* ISO_CONS */
        !           368:        /* End of protosw marker */
        !           369:        { 0 }
        !           370: };
        !           371: 
        !           372: u_long tp_sendspace = 1024 * 4;
        !           373: u_long tp_recvspace = 1024 * 4;
        !           374: 
        !           375: /*
        !           376:  * NAME:  tp_init()
        !           377:  *
        !           378:  * CALLED FROM:
        !           379:  *  autoconf through the protosw structure
        !           380:  *
        !           381:  * FUNCTION:
        !           382:  *  initialize tp machine
        !           383:  *
        !           384:  * RETURNS:  Nada
        !           385:  *
        !           386:  * SIDE EFFECTS:
        !           387:  * 
        !           388:  * NOTES:
        !           389:  */
        !           390: int
        !           391: tp_init()
        !           392: {
        !           393:        static int      init_done=0;
        !           394:        void            tp_timerinit();
        !           395: 
        !           396:        if (init_done++)
        !           397:                return 0;
        !           398: 
        !           399: 
        !           400:        /* FOR INET */
        !           401:        tp_inpcb.inp_next = tp_inpcb.inp_prev = &tp_inpcb;
        !           402:        /* FOR ISO */
        !           403:        tp_isopcb.isop_next = tp_isopcb.isop_prev = &tp_isopcb;
        !           404: 
        !           405:     tp_start_win = 2;
        !           406: 
        !           407:        tp_timerinit();
        !           408:        bzero((caddr_t)&tp_stat, sizeof(struct tp_stat));
        !           409:        return 0;
        !           410: }
        !           411: 
        !           412: /*
        !           413:  * NAME:       tp_soisdisconnecting()
        !           414:  *
        !           415:  * CALLED FROM:
        !           416:  *  tp.trans
        !           417:  *
        !           418:  * FUNCTION and ARGUMENTS:
        !           419:  *  Set state of the socket (so) to reflect that fact that we're disconnectING
        !           420:  *
        !           421:  * RETURNS:    Nada
        !           422:  *
        !           423:  * SIDE EFFECTS:
        !           424:  *
        !           425:  * NOTES:
        !           426:  *  This differs from the regular soisdisconnecting() in that the latter
        !           427:  *  also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags.
        !           428:  *  We don't want to set those flags because those flags will cause
        !           429:  *  a SIGPIPE to be delivered in sosend() and we don't like that.
        !           430:  *  If anyone else is sleeping on this socket, wake 'em up.
        !           431:  */
        !           432: void
        !           433: tp_soisdisconnecting(so)
        !           434:        register struct socket *so;
        !           435: {
        !           436:        soisdisconnecting(so);
        !           437:        so->so_state &= ~SS_CANTSENDMORE;
        !           438:        IFPERF(sototpcb(so))
        !           439:                register struct tp_pcb *tpcb = sototpcb(so);
        !           440:                u_int   fsufx, lsufx;
        !           441: 
        !           442:                bcopy ((caddr_t)tpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) );
        !           443:                bcopy ((caddr_t)tpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) );
        !           444: 
        !           445:                tpmeas(tpcb->tp_lref, TPtime_close, &time, fsufx, lsufx, tpcb->tp_fref);
        !           446:                tpcb->tp_perf_on = 0; /* turn perf off */
        !           447:        ENDPERF
        !           448: }
        !           449: 
        !           450: 
        !           451: /*
        !           452:  * NAME: tp_soisdisconnected()
        !           453:  *
        !           454:  * CALLED FROM:
        !           455:  *     tp.trans        
        !           456:  *
        !           457:  * FUNCTION and ARGUMENTS:
        !           458:  *  Set state of the socket (so) to reflect that fact that we're disconnectED
        !           459:  *  Set the state of the reference structure to closed, and
        !           460:  *  recycle the suffix.
        !           461:  *  Start a reference timer.
        !           462:  *
        !           463:  * RETURNS:    Nada
        !           464:  *
        !           465:  * SIDE EFFECTS:
        !           466:  *
        !           467:  * NOTES:
        !           468:  *  This differs from the regular soisdisconnected() in that the latter
        !           469:  *  also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags.
        !           470:  *  We don't want to set those flags because those flags will cause
        !           471:  *  a SIGPIPE to be delivered in sosend() and we don't like that.
        !           472:  *  If anyone else is sleeping on this socket, wake 'em up.
        !           473:  */
        !           474: void
        !           475: tp_soisdisconnected(tpcb)
        !           476:        register struct tp_pcb  *tpcb;
        !           477: {
        !           478:        register struct socket  *so = tpcb->tp_sock;
        !           479: 
        !           480:        soisdisconnecting(so);
        !           481:        so->so_state &= ~SS_CANTSENDMORE;
        !           482:        IFPERF(tpcb)
        !           483:                register struct tp_pcb *ttpcb = sototpcb(so);
        !           484:                u_int   fsufx, lsufx;
        !           485: 
        !           486:                /* CHOKE */
        !           487:                bcopy ((caddr_t)ttpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) );
        !           488:                bcopy ((caddr_t)ttpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) );
        !           489: 
        !           490:                tpmeas(ttpcb->tp_lref, TPtime_close, 
        !           491:                   &time, &lsufx, &fsufx, ttpcb->tp_fref);
        !           492:                tpcb->tp_perf_on = 0; /* turn perf off */
        !           493:        ENDPERF
        !           494: 
        !           495:        tpcb->tp_refstate = REF_FROZEN;
        !           496:        tp_recycle_tsuffix(tpcb);
        !           497:        tp_etimeout(tpcb, TM_reference, (int)tpcb->tp_refer_ticks);
        !           498: }
        !           499: 
        !           500: /*
        !           501:  * NAME:       tp_freeref()
        !           502:  *
        !           503:  * CALLED FROM:
        !           504:  *  tp.trans when the reference timer goes off, and
        !           505:  *  from tp_attach() and tp_detach() when a tpcb is partially set up but not
        !           506:  *  set up enough to have a ref timer set for it, and it's discarded
        !           507:  *  due to some sort of error or an early close()
        !           508:  *
        !           509:  * FUNCTION and ARGUMENTS:
        !           510:  *  Frees the reference represented by (r) for re-use.
        !           511:  *
        !           512:  * RETURNS: Nothing
        !           513:  * 
        !           514:  * SIDE EFFECTS:
        !           515:  *
        !           516:  * NOTES:      better be called at clock priority !!!!!
        !           517:  */
        !           518: void
        !           519: tp_freeref(n)
        !           520: RefNum n;
        !           521: {
        !           522:        register struct tp_ref *r = tp_ref + n;
        !           523:        register struct tp_pcb *tpcb;
        !           524: 
        !           525:        tpcb = r->tpr_pcb;
        !           526:        IFDEBUG(D_TIMER)
        !           527:                printf("tp_freeref called for ref %d pcb %x maxrefopen %d\n", 
        !           528:                n, tpcb, tp_refinfo.tpr_maxopen);
        !           529:        ENDDEBUG
        !           530:        IFTRACE(D_TIMER)
        !           531:                tptrace(TPPTmisc, "tp_freeref ref maxrefopen pcb",
        !           532:                n, tp_refinfo.tpr_maxopen, tpcb, 0);
        !           533:        ENDTRACE
        !           534:        if (tpcb == 0)
        !           535:                return;
        !           536:        IFDEBUG(D_CONN)
        !           537:                printf("tp_freeref: CLEARING tpr_pcb 0x%x\n", tpcb);
        !           538:        ENDDEBUG
        !           539:        r->tpr_pcb = (struct tp_pcb *)0;
        !           540:        tpcb->tp_refstate = REF_FREE;
        !           541: 
        !           542:        for (r = tp_ref + tp_refinfo.tpr_maxopen; r > tp_ref; r--)
        !           543:                if (r->tpr_pcb)
        !           544:                        break;
        !           545:        tp_refinfo.tpr_maxopen = r - tp_ref;
        !           546:        tp_refinfo.tpr_numopen--;
        !           547: 
        !           548:        IFDEBUG(D_TIMER)
        !           549:                printf("tp_freeref ends w/ maxrefopen %d\n", tp_refinfo.tpr_maxopen);
        !           550:        ENDDEBUG
        !           551: }
        !           552: 
        !           553: /*
        !           554:  * NAME:  tp_getref()
        !           555:  *
        !           556:  * CALLED FROM:
        !           557:  *  tp_attach()
        !           558:  *
        !           559:  * FUNCTION and ARGUMENTS:
        !           560:  *  obtains the next free reference and allocates the appropriate
        !           561:  *  ref structure, links that structure to (tpcb) 
        !           562:  *
        !           563:  * RETURN VALUE:
        !           564:  *     a reference number
        !           565:  *  or TP_ENOREF
        !           566:  *
        !           567:  * SIDE EFFECTS:
        !           568:  *
        !           569:  * NOTES:
        !           570:  */
        !           571: u_long
        !           572: tp_getref(tpcb) 
        !           573:        register struct tp_pcb *tpcb;
        !           574: {
        !           575:        register struct tp_ref  *r, *rlim;
        !           576:        register int                    i;
        !           577:        caddr_t obase;
        !           578:        unsigned size;
        !           579: 
        !           580:        if (++tp_refinfo.tpr_numopen < tp_refinfo.tpr_size)
        !           581:                for (r = tp_refinfo.tpr_base, rlim = r + tp_refinfo.tpr_size;
        !           582:                                                                ++r < rlim; )   /* tp_ref[0] is never used */
        !           583:                        if (r->tpr_pcb == 0)
        !           584:                                goto got_one;
        !           585:        /* else have to allocate more space */
        !           586: 
        !           587:        obase = (caddr_t)tp_refinfo.tpr_base;
        !           588:        size = tp_refinfo.tpr_size * sizeof(struct tp_ref);
        !           589: //     r = (struct tp_ref *) malloc(size + size, M_PCB, M_NOWAIT);
        !           590:        MALLOC(r, struct tp_ref *, size + size, M_PCB, M_NOWAIT);
        !           591:        if (r == 0)
        !           592:                return (--tp_refinfo.tpr_numopen, TP_ENOREF);
        !           593:        tp_refinfo.tpr_base = tp_ref = r;
        !           594:        tp_refinfo.tpr_size *= 2;
        !           595:        bcopy(obase, (caddr_t)r, size);
        !           596:        FREE(obase, M_PCB);
        !           597:        r = (struct tp_ref *)(size + (caddr_t)r);
        !           598:        bzero((caddr_t)r, size);
        !           599: 
        !           600: got_one:
        !           601:        r->tpr_pcb = tpcb;
        !           602:        tpcb->tp_refstate = REF_OPENING;
        !           603:        i = r - tp_refinfo.tpr_base;
        !           604:        if (tp_refinfo.tpr_maxopen < i) 
        !           605:                tp_refinfo.tpr_maxopen = i;
        !           606:        return (u_long)i;
        !           607: }
        !           608: 
        !           609: /*
        !           610:  * NAME: tp_set_npcb()
        !           611:  *
        !           612:  * CALLED FROM:
        !           613:  *     tp_attach(), tp_route_to()
        !           614:  *
        !           615:  * FUNCTION and ARGUMENTS:
        !           616:  *  given a tpcb, allocate an appropriate lower-lever npcb, freeing
        !           617:  *  any old ones that might need re-assigning.
        !           618:  */
        !           619: tp_set_npcb(tpcb)
        !           620: register struct tp_pcb *tpcb;
        !           621: {
        !           622:        register struct socket *so = tpcb->tp_sock;
        !           623:        int error;
        !           624: 
        !           625:        if (tpcb->tp_nlproto && tpcb->tp_npcb) {
        !           626:                short so_state = so->so_state;
        !           627:                so->so_state &= ~SS_NOFDREF;
        !           628:                tpcb->tp_nlproto->nlp_pcbdetach(tpcb->tp_npcb);
        !           629:                so->so_state = so_state;
        !           630:        }
        !           631:        tpcb->tp_nlproto = &nl_protosw[tpcb->tp_netservice];
        !           632:        /* xx_pcballoc sets so_pcb */
        !           633:        error = tpcb->tp_nlproto->nlp_pcballoc(so, tpcb->tp_nlproto->nlp_pcblist);
        !           634:        tpcb->tp_npcb = so->so_pcb;
        !           635:        so->so_pcb = (caddr_t)tpcb;
        !           636:        return (error);
        !           637: }
        !           638: /*
        !           639:  * NAME: tp_attach()
        !           640:  *
        !           641:  * CALLED FROM:
        !           642:  *     tp_usrreq, PRU_ATTACH
        !           643:  *
        !           644:  * FUNCTION and ARGUMENTS:
        !           645:  *  given a socket (so) and a protocol family (dom), allocate a tpcb
        !           646:  *  and ref structure, initialize everything in the structures that
        !           647:  *  needs to be initialized.
        !           648:  *
        !           649:  * RETURN VALUE:
        !           650:  *  0 ok
        !           651:  *  EINVAL if DEBUG(X) in is on and a disaster has occurred
        !           652:  *  ENOPROTOOPT if TP hasn't been configured or if the
        !           653:  *   socket wasn't created with tp as its protocol
        !           654:  *  EISCONN if this socket is already part of a connection
        !           655:  *  ETOOMANYREFS if ran out of tp reference numbers.
        !           656:  *  E* whatever error is returned from soreserve()
        !           657:  *    for from the network-layer pcb allocation routine
        !           658:  *
        !           659:  * SIDE EFFECTS:
        !           660:  *
        !           661:  * NOTES:
        !           662:  */
        !           663: tp_attach(so, protocol)
        !           664:        struct socket                   *so;
        !           665:        int                                     protocol;
        !           666: {
        !           667:        register struct tp_pcb  *tpcb;
        !           668:        int                                     error = 0;
        !           669:        int                                     dom = so->so_proto->pr_domain->dom_family;
        !           670:        u_long                                  lref;
        !           671:        extern struct tp_conn_param tp_conn_param[];
        !           672: 
        !           673:        IFDEBUG(D_CONN)
        !           674:                printf("tp_attach:dom 0x%x so 0x%x ", dom, so);
        !           675:        ENDDEBUG
        !           676:        IFTRACE(D_CONN)
        !           677:                tptrace(TPPTmisc, "tp_attach:dom so", dom, so, 0, 0);
        !           678:        ENDTRACE
        !           679: 
        !           680:        if (so->so_pcb != NULL) { 
        !           681:                return EISCONN; /* socket already part of a connection*/
        !           682:        }
        !           683: 
        !           684:        if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0)
        !           685:                error = soreserve(so, tp_sendspace, tp_recvspace);
        !           686:                /* later an ioctl will allow reallocation IF still in closed state */
        !           687: 
        !           688:        if (error)
        !           689:                goto bad2;
        !           690: 
        !           691:        MALLOC(tpcb, struct tp_pcb *, sizeof(*tpcb), M_PCB, M_NOWAIT);
        !           692:        if (tpcb == NULL) {
        !           693:                error = ENOBUFS;
        !           694:                goto bad2;
        !           695:        }
        !           696:        bzero( (caddr_t)tpcb, sizeof (struct tp_pcb) );
        !           697: 
        !           698:        if ( ((lref = tp_getref(tpcb)) &  TP_ENOREF) != 0 ) { 
        !           699:                error = ETOOMANYREFS; 
        !           700:                goto bad3;
        !           701:        }
        !           702:        tpcb->tp_lref = lref;
        !           703:        tpcb->tp_sock =  so;
        !           704:        tpcb->tp_domain = dom;
        !           705:        tpcb->tp_rhiwat = so->so_rcv.sb_hiwat;
        !           706:        /* tpcb->tp_proto = protocol; someday maybe? */
        !           707:        if (protocol && protocol<ISOPROTO_TP4) {
        !           708:                tpcb->tp_netservice = ISO_CONS;
        !           709:                tpcb->tp_snduna = (SeqNum) -1;/* kludge so the pseudo-ack from the CR/CC
        !           710:                                                                 * will generate correct fake-ack values
        !           711:                                                                 */
        !           712:        } else {
        !           713:                tpcb->tp_netservice = (dom== AF_INET)?IN_CLNS:ISO_CLNS;
        !           714:                /* the default */
        !           715:        }
        !           716:        tpcb->_tp_param = tp_conn_param[tpcb->tp_netservice];
        !           717: 
        !           718:        tpcb->tp_state = TP_CLOSED;
        !           719:        tpcb->tp_vers  = TP_VERSION;
        !           720:        tpcb->tp_notdetached = 1;
        !           721: 
        !           722:                   /* Spec says default is 128 octets,
        !           723:                        * that is, if the tpdusize argument never appears, use 128.
        !           724:                        * As the initiator, we will always "propose" the 2048
        !           725:                        * size, that is, we will put this argument in the CR 
        !           726:                        * always, but accept what the other side sends on the CC.
        !           727:                        * If the initiator sends us something larger on a CR,
        !           728:                        * we'll respond w/ this.
        !           729:                        * Our maximum is 4096.  See tp_chksum.c comments.
        !           730:                        */
        !           731:        tpcb->tp_cong_win = 
        !           732:                tpcb->tp_l_tpdusize = 1 << tpcb->tp_tpdusize;
        !           733: 
        !           734:        tpcb->tp_seqmask  = TP_NML_FMT_MASK;
        !           735:        tpcb->tp_seqbit  =  TP_NML_FMT_BIT;
        !           736:        tpcb->tp_seqhalf  =  tpcb->tp_seqbit >> 1;
        !           737: 
        !           738:        /* attach to a network-layer protoswitch */
        !           739:        if ( error =  tp_set_npcb(tpcb))
        !           740:                goto bad4;
        !           741:        ASSERT( tpcb->tp_nlproto->nlp_afamily == tpcb->tp_domain);
        !           742: 
        !           743:        /* nothing to do for iso case */
        !           744:        if( dom == AF_INET )
        !           745:                sotoinpcb(so)->inp_ppcb = (caddr_t) tpcb;
        !           746: 
        !           747:        return 0;
        !           748: 
        !           749: bad4:
        !           750:        IFDEBUG(D_CONN)
        !           751:                printf("BAD4 in tp_attach, so 0x%x\n", so);
        !           752:        ENDDEBUG
        !           753:        tp_freeref(tpcb->tp_lref);
        !           754: 
        !           755: bad3:
        !           756:        IFDEBUG(D_CONN)
        !           757:                printf("BAD3 in tp_attach, so 0x%x\n", so);
        !           758:        ENDDEBUG
        !           759: 
        !           760:        FREE((caddr_t)tpcb, M_PCB); /* never a cluster  */
        !           761: 
        !           762: bad2:
        !           763:        IFDEBUG(D_CONN)
        !           764:                printf("BAD2 in tp_attach, so 0x%x\n", so);
        !           765:        ENDDEBUG
        !           766:        so->so_pcb = 0;
        !           767: 
        !           768: /*bad:*/
        !           769:        IFDEBUG(D_CONN)
        !           770:                printf("BAD in tp_attach, so 0x%x\n", so);
        !           771:        ENDDEBUG
        !           772:        return error;
        !           773: }
        !           774: 
        !           775: /*
        !           776:  * NAME:  tp_detach()
        !           777:  *
        !           778:  * CALLED FROM:
        !           779:  *     tp.trans, on behalf of a user close request
        !           780:  *  and when the reference timer goes off
        !           781:  * (if the disconnect  was initiated by the protocol entity 
        !           782:  * rather than by the user)
        !           783:  *
        !           784:  * FUNCTION and ARGUMENTS:
        !           785:  *  remove the tpcb structure from the list of active or
        !           786:  *  partially active connections, recycle all the mbufs
        !           787:  *  associated with the pcb, ref structure, sockbufs, etc.
        !           788:  *  Only free the ref structure if you know that a ref timer
        !           789:  *  wasn't set for this tpcb.
        !           790:  *
        !           791:  * RETURNS:  Nada
        !           792:  *
        !           793:  * SIDE EFFECTS:
        !           794:  *
        !           795:  * NOTES:
        !           796:  *  tp_soisdisconnected() was already when this is called
        !           797:  */
        !           798: void
        !           799: tp_detach(tpcb)
        !           800:        register struct tp_pcb  *tpcb;
        !           801: {
        !           802:        void                                    tp_freeref(), tp_rsyflush();
        !           803:        register struct socket   *so = tpcb->tp_sock;
        !           804: 
        !           805:        IFDEBUG(D_CONN)
        !           806:                printf("tp_detach(tpcb 0x%x, so 0x%x)\n",
        !           807:                        tpcb,so);
        !           808:        ENDDEBUG
        !           809:        IFTRACE(D_CONN)
        !           810:                tptraceTPCB(TPPTmisc, "tp_detach tpcb so lsufx", 
        !           811:                        tpcb, so, *(u_short *)(tpcb->tp_lsuffix), 0);
        !           812:        ENDTRACE
        !           813: 
        !           814:        IFDEBUG(D_CONN)
        !           815:                printf("so_snd at 0x%x so_rcv at 0x%x\n", &so->so_snd, &so->so_rcv);
        !           816:                dump_mbuf(so->so_snd.sb_mb, "so_snd at detach ");
        !           817:                printf("about to call LL detach, nlproto 0x%x, nl_detach 0x%x\n",
        !           818:                                tpcb->tp_nlproto, tpcb->tp_nlproto->nlp_pcbdetach);
        !           819:        ENDDEBUG
        !           820: 
        !           821:        if (tpcb->tp_Xsnd.sb_mb) {
        !           822:                printf("Unsent Xdata on detach; would panic");
        !           823:                sbflush(&tpcb->tp_Xsnd);
        !           824:        }
        !           825:        if (tpcb->tp_ucddata)
        !           826:                m_freem(tpcb->tp_ucddata);
        !           827: 
        !           828:        IFDEBUG(D_CONN)
        !           829:                printf("reassembly info cnt %d rsyq 0x%x\n",
        !           830:                    tpcb->tp_rsycnt, tpcb->tp_rsyq);
        !           831:        ENDDEBUG
        !           832:        if (tpcb->tp_rsyq)
        !           833:                tp_rsyflush(tpcb);
        !           834: 
        !           835:        if (tpcb->tp_next) {
        !           836:                remque(tpcb);
        !           837:                tpcb->tp_next = tpcb->tp_prev = 0;
        !           838:        }
        !           839:        tpcb->tp_notdetached = 0;
        !           840: 
        !           841:        IFDEBUG(D_CONN)
        !           842:                printf("calling (...nlproto->...)(0x%x, so 0x%x)\n", 
        !           843:                        tpcb->tp_npcb, so);
        !           844:                printf("so 0x%x so_head 0x%x,  qlen %d q0len %d qlimit %d\n", 
        !           845:                so,  so->so_head,
        !           846:                so->so_q0len, so->so_qlen, so->so_qlimit);
        !           847:        ENDDEBUG
        !           848: 
        !           849:        (tpcb->tp_nlproto->nlp_pcbdetach)(tpcb->tp_npcb);
        !           850:                                /* does an so->so_pcb = 0; sofree(so) */
        !           851: 
        !           852:        IFDEBUG(D_CONN)
        !           853:                printf("after xxx_pcbdetach\n");
        !           854:        ENDDEBUG
        !           855: 
        !           856:        if (tpcb->tp_state == TP_LISTENING) {
        !           857:                register struct tp_pcb **tt;
        !           858:                for (tt = &tp_listeners; *tt; tt = &((*tt)->tp_nextlisten))
        !           859:                        if (*tt == tpcb)
        !           860:                                break;
        !           861:                if (*tt)
        !           862:                        *tt = tpcb->tp_nextlisten;
        !           863:                else
        !           864:                        printf("tp_detach from listen: should panic\n");
        !           865:        }
        !           866:        if (tpcb->tp_refstate == REF_OPENING ) {
        !           867:                /* no connection existed here so no reference timer will be called */
        !           868:                IFDEBUG(D_CONN)
        !           869:                        printf("SETTING ref %d to REF_FREE\n", tpcb->tp_lref);
        !           870:                ENDDEBUG
        !           871: 
        !           872:                tp_freeref(tpcb->tp_lref);
        !           873:        }
        !           874: #ifdef TP_PERF_MEAS
        !           875:        /* 
        !           876:         * Get rid of the cluster mbuf allocated for performance measurements, if
        !           877:         * there is one.  Note that tpcb->tp_perf_on says nothing about whether or 
        !           878:         * not a cluster mbuf was allocated, so you have to check for a pointer 
        !           879:         * to one (that is, we need the TP_PERF_MEASs around the following section 
        !           880:         * of code, not the IFPERFs)
        !           881:         */
        !           882:        if (tpcb->tp_p_mbuf) {
        !           883:                register struct mbuf *m = tpcb->tp_p_mbuf;
        !           884:                struct mbuf *n;
        !           885:                IFDEBUG(D_PERF_MEAS)
        !           886:                        printf("freeing tp_p_meas 0x%x  ", tpcb->tp_p_meas);
        !           887:                ENDDEBUG
        !           888:                do {
        !           889:                    MFREE(m, n);
        !           890:                    m = n;
        !           891:                } while (n);
        !           892:                tpcb->tp_p_meas = 0;
        !           893:                tpcb->tp_p_mbuf = 0;
        !           894:        }
        !           895: #endif /* TP_PERF_MEAS */
        !           896: 
        !           897:        IFDEBUG(D_CONN)
        !           898:                printf( "end of detach, NOT single, tpcb 0x%x\n", tpcb);
        !           899:        ENDDEBUG
        !           900:        /* FREE((caddr_t)tpcb, M_PCB); WHere to put this ? */
        !           901: }
        !           902: 
        !           903: struct que {
        !           904:        struct tp_pcb *next;
        !           905:        struct tp_pcb *prev;
        !           906: } tp_bound_pcbs =
        !           907: {(struct tp_pcb *)&tp_bound_pcbs, (struct tp_pcb *)&tp_bound_pcbs};
        !           908: 
        !           909: u_short tp_unique;
        !           910: 
        !           911: tp_tselinuse(tlen, tsel, siso, reuseaddr)
        !           912: caddr_t tsel;
        !           913: register struct sockaddr_iso *siso;
        !           914: {
        !           915:        struct tp_pcb *b = tp_bound_pcbs.next, *l = tp_listeners;
        !           916:        register struct tp_pcb *t;
        !           917: 
        !           918:        for (;;) {
        !           919:                if (b != (struct tp_pcb *)&tp_bound_pcbs) {
        !           920:                        t = b; b = t->tp_next;
        !           921:                } else if (l) {
        !           922:                        t = l; l = t->tp_nextlisten;
        !           923:                } else
        !           924:                        break;
        !           925:                if (tlen == t->tp_lsuffixlen && bcmp(tsel, t->tp_lsuffix, tlen) == 0) {
        !           926:                        if (t->tp_flags & TPF_GENERAL_ADDR) {
        !           927:                                if (siso == 0 || reuseaddr == 0)
        !           928:                                        return 1;
        !           929:                        } else if (siso) {
        !           930:                                if (siso->siso_family == t->tp_domain &&
        !           931:                                        t->tp_nlproto->nlp_cmpnetaddr(t->tp_npcb, siso, TP_LOCAL))
        !           932:                                                return 1;
        !           933:                        } else if (reuseaddr == 0)
        !           934:                                                return 1;
        !           935:                }
        !           936:        }
        !           937:        return 0;
        !           938: 
        !           939: }
        !           940: 
        !           941: 
        !           942: tp_pcbbind(tpcb, nam)
        !           943: register struct tp_pcb *tpcb;
        !           944: register struct mbuf *nam;
        !           945: {
        !           946:        register struct sockaddr_iso *siso = 0;
        !           947:        int tlen = 0, wrapped = 0;
        !           948:        caddr_t tsel;
        !           949:        u_short tutil;
        !           950: 
        !           951:        if (tpcb->tp_state != TP_CLOSED)
        !           952:                return (EINVAL);
        !           953:        if (nam) {
        !           954:                siso = mtod(nam, struct sockaddr_iso *);
        !           955:                switch (siso->siso_family) {
        !           956:                default:
        !           957:                        return (EAFNOSUPPORT);
        !           958: #if ISO
        !           959:                case AF_ISO:
        !           960:                        tlen = siso->siso_tlen;
        !           961:                        tsel = TSEL(siso);
        !           962:                        if (siso->siso_nlen == 0)
        !           963:                                siso = 0;
        !           964:                        break;
        !           965: #endif
        !           966: #if INET
        !           967:                case AF_INET:
        !           968:                        tsel = (caddr_t)&tutil;
        !           969:                        if (tutil =  ((struct sockaddr_in *)siso)->sin_port) {
        !           970:                                tlen = 2;
        !           971:                        }
        !           972:                        if (((struct sockaddr_in *)siso)->sin_addr.s_addr == 0)
        !           973:                                siso = 0;
        !           974:                }
        !           975: #endif
        !           976:        }
        !           977:        if (tpcb->tp_lsuffixlen == 0) {
        !           978:                if (tlen) {
        !           979:                        if (tp_tselinuse(tlen, tsel, siso,
        !           980:                                                                tpcb->tp_sock->so_options & SO_REUSEADDR))
        !           981:                                return (EINVAL);
        !           982:                } else {
        !           983:                        for (tsel = (caddr_t)&tutil, tlen = 2;;){
        !           984:                                if (tp_unique++ < ISO_PORT_RESERVED ||
        !           985:                                        tp_unique > ISO_PORT_USERRESERVED) {
        !           986:                                                if (wrapped++)
        !           987:                                                        return ESRCH;
        !           988:                                                tp_unique = ISO_PORT_RESERVED;
        !           989:                                }
        !           990:                                tutil = htons(tp_unique);
        !           991:                                if (tp_tselinuse(tlen, tsel, siso, 0) == 0)
        !           992:                                        break;
        !           993:                        }
        !           994:                        if (siso) switch (siso->siso_family) {
        !           995: #if ISO
        !           996:                                case AF_ISO:
        !           997:                                        bcopy(tsel, TSEL(siso), tlen);
        !           998:                                        siso->siso_tlen = tlen;
        !           999:                                        break;
        !          1000: #endif
        !          1001: #if INET
        !          1002:                                case AF_INET:
        !          1003:                                        ((struct sockaddr_in *)siso)->sin_port = tutil;
        !          1004: #endif
        !          1005:                                }
        !          1006:                }
        !          1007:                bcopy(tsel, tpcb->tp_lsuffix, (tpcb->tp_lsuffixlen = tlen));
        !          1008:                insque(tpcb, &tp_bound_pcbs);
        !          1009:        } else {
        !          1010:                if (tlen || siso == 0)
        !          1011:                        return (EINVAL);
        !          1012:        }
        !          1013:        if (siso == 0) {
        !          1014:                tpcb->tp_flags |= TPF_GENERAL_ADDR;
        !          1015:                return (0);
        !          1016:        }
        !          1017:        return tpcb->tp_nlproto->nlp_pcbbind(tpcb->tp_npcb, nam);
        !          1018: }

unix.superglobalmegacorp.com

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