home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / netiso / tp_pcb.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-06  |  23.1 KB  |  873 lines

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