The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netiso/tp_pcb.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 0dd2d0dc16db0fae0219314e8528bce2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.