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

Cache object: 5b516c95d04ad07f651e749ab99f6f9a


[ 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.