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

unix.superglobalmegacorp.com

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