Annotation of XNU/bsd/netiso/tp_pcb.c, revision 1.1.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.