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.26 2004/04/19 05:16:46 matt 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.26 2004/04/19 05:16:46 matt 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         },
  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(void)
  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(struct socket *so)
  368 {
  369         soisdisconnecting(so);
  370         so->so_state &= ~SS_CANTSENDMORE;
  371 #ifdef TP_PERF_MEAS
  372         if (DOPERF(sototpcb(so))) {
  373                 struct tp_pcb *tpcb = sototpcb(so);
  374                 u_int           fsufx, lsufx;
  375 
  376                 bcopy((caddr_t) tpcb->tp_fsuffix, (caddr_t) &fsufx,
  377                       sizeof(u_int));
  378                 bcopy((caddr_t) tpcb->tp_lsuffix, (caddr_t) &lsufx,
  379                       sizeof(u_int));
  380 
  381                 tpmeas(tpcb->tp_lref, TPtime_close, &time, fsufx, lsufx,
  382                        tpcb->tp_fref);
  383                 tpcb->tp_perf_on = 0;   /* turn perf off */
  384         }
  385 #endif
  386 }
  387 
  388 
  389 /*
  390  * NAME: tp_soisdisconnected()
  391  *
  392  * CALLED FROM:
  393  *      tp.trans
  394  *
  395  * FUNCTION and ARGUMENTS:
  396  *  Set state of the socket (so) to reflect that fact that we're disconnectED
  397  *  Set the state of the reference structure to closed, and
  398  *  recycle the suffix.
  399  *  Start a reference timer.
  400  *
  401  * RETURNS:     Nada
  402  *
  403  * SIDE EFFECTS:
  404  *
  405  * NOTES:
  406  *  This differs from the regular soisdisconnected() in that the latter
  407  *  also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags.
  408  *  We don't want to set those flags because those flags will cause
  409  *  a SIGPIPE to be delivered in sosend() and we don't like that.
  410  *  If anyone else is sleeping on this socket, wake 'em up.
  411  */
  412 void
  413 tp_soisdisconnected(struct tp_pcb *tpcb)
  414 {
  415         struct socket *so = tpcb->tp_sock;
  416 
  417         soisdisconnecting(so);
  418         so->so_state &= ~SS_CANTSENDMORE;
  419 #ifdef TP_PERF_MEAS
  420         if (DOPERF(tpcb)) {
  421                 struct tp_pcb *ttpcb = sototpcb(so);
  422                 u_int           fsufx, lsufx;
  423 
  424                 /* CHOKE */
  425                 bcopy((caddr_t) ttpcb->tp_fsuffix, (caddr_t) &fsufx,
  426                       sizeof(u_int));
  427                 bcopy((caddr_t) ttpcb->tp_lsuffix, (caddr_t) &lsufx,
  428                       sizeof(u_int));
  429 
  430                 tpmeas(ttpcb->tp_lref, TPtime_close,
  431                        &time, &lsufx, &fsufx, ttpcb->tp_fref);
  432                 tpcb->tp_perf_on = 0;   /* turn perf off */
  433         }
  434 #endif
  435 
  436         tpcb->tp_refstate = REF_FROZEN;
  437         tp_recycle_tsuffix(tpcb);
  438         tp_etimeout(tpcb, TM_reference, (int) tpcb->tp_refer_ticks);
  439 }
  440 
  441 /*
  442  * NAME:        tp_freeref()
  443  *
  444  * CALLED FROM:
  445  *  tp.trans when the reference timer goes off, and
  446  *  from tp_attach() and tp_detach() when a tpcb is partially set up but not
  447  *  set up enough to have a ref timer set for it, and it's discarded
  448  *  due to some sort of error or an early close()
  449  *
  450  * FUNCTION and ARGUMENTS:
  451  *  Frees the reference represented by (r) for re-use.
  452  *
  453  * RETURNS: Nothing
  454  *
  455  * SIDE EFFECTS:
  456  *
  457  * NOTES:       better be called at clock priority !!!!!
  458  */
  459 void
  460 tp_freeref(RefNum n)
  461 {
  462         struct tp_ref *r = tp_ref + n;
  463         struct tp_pcb *tpcb;
  464 
  465         tpcb = r->tpr_pcb;
  466 #ifdef ARGO_DEBUG
  467         if (argo_debug[D_TIMER]) {
  468                 printf("tp_freeref called for ref %d pcb %p maxrefopen %d\n",
  469                        n, tpcb, tp_refinfo.tpr_maxopen);
  470         }
  471 #endif
  472 #ifdef TPPT
  473         if (tp_traceflags[D_TIMER]) {
  474                 tptrace(TPPTmisc, "tp_freeref ref maxrefopen pcb",
  475                         n, tp_refinfo.tpr_maxopen, tpcb, 0);
  476         }
  477 #endif
  478         if (tpcb == 0)
  479                 return;
  480 #ifdef ARGO_DEBUG
  481         if (argo_debug[D_CONN]) {
  482                 printf("tp_freeref: CLEARING tpr_pcb %p\n", tpcb);
  483         }
  484 #endif
  485         r->tpr_pcb = (struct tp_pcb *) 0;
  486         tpcb->tp_refstate = REF_FREE;
  487 
  488         for (r = tp_ref + tp_refinfo.tpr_maxopen; r > tp_ref; r--)
  489                 if (r->tpr_pcb)
  490                         break;
  491         tp_refinfo.tpr_maxopen = r - tp_ref;
  492         tp_refinfo.tpr_numopen--;
  493 
  494 #ifdef ARGO_DEBUG
  495         if (argo_debug[D_TIMER]) {
  496                 printf("tp_freeref ends w/ maxrefopen %d\n", tp_refinfo.tpr_maxopen);
  497         }
  498 #endif
  499 }
  500 
  501 /*
  502  * NAME:  tp_getref()
  503  *
  504  * CALLED FROM:
  505  *  tp_attach()
  506  *
  507  * FUNCTION and ARGUMENTS:
  508  *  obtains the next free reference and allocates the appropriate
  509  *  ref structure, links that structure to (tpcb)
  510  *
  511  * RETURN VALUE:
  512  *      a reference number
  513  *  or TP_ENOREF
  514  *
  515  * SIDE EFFECTS:
  516  *
  517  * NOTES:
  518  */
  519 u_long
  520 tp_getref(struct tp_pcb *tpcb)
  521 {
  522         struct tp_ref *r, *rlim;
  523         int    i;
  524         caddr_t         obase;
  525         unsigned        size;
  526 
  527         if (++tp_refinfo.tpr_numopen < tp_refinfo.tpr_size)
  528                 for (r = tp_refinfo.tpr_base, rlim = r + tp_refinfo.tpr_size;
  529                      ++r < rlim;)       /* tp_ref[0] is never used */
  530                         if (r->tpr_pcb == 0)
  531                                 goto got_one;
  532         /* else have to allocate more space */
  533 
  534         obase = (caddr_t) tp_refinfo.tpr_base;
  535         size = tp_refinfo.tpr_size * sizeof(struct tp_ref);
  536         r = (struct tp_ref *) malloc(size + size, M_PCB, M_NOWAIT);
  537         if (r == 0)
  538                 return (--tp_refinfo.tpr_numopen, TP_ENOREF);
  539         tp_refinfo.tpr_base = tp_ref = r;
  540         tp_refinfo.tpr_size *= 2;
  541         bcopy(obase, (caddr_t) r, size);
  542         free(obase, M_PCB);
  543         r = (struct tp_ref *) (size + (caddr_t) r);
  544         bzero((caddr_t) r, size);
  545 
  546 got_one:
  547         r->tpr_pcb = tpcb;
  548         tpcb->tp_refstate = REF_OPENING;
  549         i = r - tp_refinfo.tpr_base;
  550         if (tp_refinfo.tpr_maxopen < i)
  551                 tp_refinfo.tpr_maxopen = i;
  552         return (u_long) i;
  553 }
  554 
  555 /*
  556  * NAME: tp_set_npcb()
  557  *
  558  * CALLED FROM:
  559  *      tp_attach(), tp_route_to()
  560  *
  561  * FUNCTION and ARGUMENTS:
  562  *  given a tpcb, allocate an appropriate lower-lever npcb, freeing
  563  *  any old ones that might need re-assigning.
  564  */
  565 int
  566 tp_set_npcb(struct tp_pcb *tpcb)
  567 {
  568         struct socket *so = tpcb->tp_sock;
  569         int             error;
  570 
  571         if (tpcb->tp_nlproto && tpcb->tp_npcb) {
  572                 short           so_state = so->so_state;
  573                 so->so_state &= ~SS_NOFDREF;
  574                 (*tpcb->tp_nlproto->nlp_pcbdetach)(tpcb->tp_npcb);
  575                 so->so_state = so_state;
  576         }
  577         tpcb->tp_nlproto = &nl_protosw[tpcb->tp_netservice];
  578         /* xx_pcballoc sets so_pcb */
  579         error = (*tpcb->tp_nlproto->nlp_pcballoc)(so,
  580                                     tpcb->tp_nlproto->nlp_pcblist);
  581         tpcb->tp_npcb = so->so_pcb;
  582         so->so_pcb = tpcb;
  583         return (error);
  584 }
  585 /*
  586  * NAME: tp_attach()
  587  *
  588  * CALLED FROM:
  589  *      tp_usrreq, PRU_ATTACH
  590  *
  591  * FUNCTION and ARGUMENTS:
  592  *  given a socket (so) and a protocol family (dom), allocate a tpcb
  593  *  and ref structure, initialize everything in the structures that
  594  *  needs to be initialized.
  595  *
  596  * RETURN VALUE:
  597  *  0 ok
  598  *  EINVAL if DEBUG(X) in is on and a disaster has occurred
  599  *  ENOPROTOOPT if TP hasn't been configured or if the
  600  *   socket wasn't created with tp as its protocol
  601  *  EISCONN if this socket is already part of a connection
  602  *  ETOOMANYREFS if ran out of tp reference numbers.
  603  *  E* whatever error is returned from soreserve()
  604  *    for from the network-layer pcb allocation routine
  605  *
  606  * SIDE EFFECTS:
  607  *
  608  * NOTES:
  609  */
  610 int
  611 tp_attach(struct socket *so, int protocol)
  612 {
  613         struct tp_pcb *tpcb;
  614         int             error = 0;
  615         int             dom = so->so_proto->pr_domain->dom_family;
  616         u_long          lref;
  617 
  618 #ifdef ARGO_DEBUG
  619         if (argo_debug[D_CONN]) {
  620                 printf("tp_attach:dom 0x%x so %p ", dom, so);
  621         }
  622 #endif
  623 #ifdef TPPT
  624         if (tp_traceflags[D_CONN]) {
  625                 tptrace(TPPTmisc, "tp_attach:dom so", dom, so, 0, 0);
  626         }
  627 #endif
  628 
  629         if (so->so_pcb != NULL) {
  630                 return EISCONN; /* socket already part of a connection */
  631         }
  632         if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0)
  633                 error = soreserve(so, tp_sendspace, tp_recvspace);
  634         /* later an ioctl will allow reallocation IF still in closed state */
  635 
  636         if (error)
  637                 goto bad2;
  638 
  639         MALLOC(tpcb, struct tp_pcb *, sizeof(*tpcb), M_PCB, M_NOWAIT|M_ZERO);
  640         if (tpcb == NULL) {
  641                 error = ENOBUFS;
  642                 goto bad2;
  643         }
  644 
  645         if (((lref = tp_getref(tpcb)) & TP_ENOREF) != 0) {
  646                 error = ETOOMANYREFS;
  647                 goto bad3;
  648         }
  649         tpcb->tp_lref = lref;
  650         tpcb->tp_sock = so;
  651         tpcb->tp_domain = dom;
  652         tpcb->tp_rhiwat = so->so_rcv.sb_hiwat;
  653         /* tpcb->tp_proto = protocol; someday maybe? */
  654         if (protocol && protocol < ISOPROTO_TP4) {
  655                 tpcb->tp_netservice = ISO_CONS;
  656                 tpcb->tp_snduna = (SeqNum) - 1; /* kludge so the pseudo-ack
  657                                                  * from the CR/CC will
  658                                                  * generate correct fake-ack
  659                                                  * values */
  660         } else {
  661                 tpcb->tp_netservice = (dom == AF_INET) ? IN_CLNS : ISO_CLNS;
  662                 /* the default */
  663         }
  664         tpcb->_tp_param = tp_conn_param[tpcb->tp_netservice];
  665 
  666         tpcb->tp_state = TP_CLOSED;
  667         tpcb->tp_vers = TP_VERSION;
  668         tpcb->tp_notdetached = 1;
  669 
  670         /*
  671          * Spec says default is 128 octets, that is, if the tpdusize argument
  672          * never appears, use 128. As the initiator, we will always "propose"
  673          * the 2048 size, that is, we will put this argument in the CR
  674          * always, but accept what the other side sends on the CC. If the
  675          * initiator sends us something larger on a CR, we'll respond w/
  676          * this. Our maximum is 4096.  See tp_chksum.c comments.
  677          */
  678         tpcb->tp_cong_win =
  679                 tpcb->tp_l_tpdusize = 1 << tpcb->tp_tpdusize;
  680 
  681         tpcb->tp_seqmask = TP_NML_FMT_MASK;
  682         tpcb->tp_seqbit = TP_NML_FMT_BIT;
  683         tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1;
  684 
  685         /* attach to a network-layer protoswitch */
  686         if ((error = tp_set_npcb(tpcb)) != 0)
  687                 goto bad4;
  688         ASSERT(tpcb->tp_nlproto->nlp_afamily == tpcb->tp_domain);
  689 
  690         /* nothing to do for iso case */
  691         if (dom == AF_INET)
  692                 sotoinpcb(so)->inp_ppcb = (caddr_t) tpcb;
  693 
  694         return 0;
  695 
  696 bad4:
  697 #ifdef ARGO_DEBUG
  698         if (argo_debug[D_CONN]) {
  699                 printf("BAD4 in tp_attach, so %p\n", so);
  700         }
  701 #endif
  702         tp_freeref(tpcb->tp_lref);
  703 
  704 bad3:
  705 #ifdef ARGO_DEBUG
  706         if (argo_debug[D_CONN]) {
  707                 printf("BAD3 in tp_attach, so %p\n", so);
  708         }
  709 #endif
  710 
  711         free((caddr_t) tpcb, M_PCB);    /* never a cluster  */
  712 
  713 bad2:
  714 #ifdef ARGO_DEBUG
  715         if (argo_debug[D_CONN]) {
  716                 printf("BAD2 in tp_attach, so %p\n", so);
  717         }
  718 #endif
  719         so->so_pcb = 0;
  720 
  721         /* bad: */
  722 #ifdef ARGO_DEBUG
  723         if (argo_debug[D_CONN]) {
  724                 printf("BAD in tp_attach, so %p\n", so);
  725         }
  726 #endif
  727         return error;
  728 }
  729 
  730 /*
  731  * NAME:  tp_detach()
  732  *
  733  * CALLED FROM:
  734  *      tp.trans, on behalf of a user close request
  735  *  and when the reference timer goes off
  736  * (if the disconnect  was initiated by the protocol entity
  737  * rather than by the user)
  738  *
  739  * FUNCTION and ARGUMENTS:
  740  *  remove the tpcb structure from the list of active or
  741  *  partially active connections, recycle all the mbufs
  742  *  associated with the pcb, ref structure, sockbufs, etc.
  743  *  Only free the ref structure if you know that a ref timer
  744  *  wasn't set for this tpcb.
  745  *
  746  * RETURNS:  Nada
  747  *
  748  * SIDE EFFECTS:
  749  *
  750  * NOTES:
  751  *  tp_soisdisconnected() was already when this is called
  752  */
  753 void
  754 tp_detach(struct tp_pcb *tpcb)
  755 {
  756         struct socket *so = tpcb->tp_sock;
  757 
  758 #ifdef ARGO_DEBUG
  759         if (argo_debug[D_CONN]) {
  760                 printf("tp_detach(tpcb %p, so %p)\n",
  761                        tpcb, so);
  762         }
  763 #endif
  764 #ifdef TPPT
  765         if (tp_traceflags[D_CONN]) {
  766                 tptraceTPCB(TPPTmisc, "tp_detach tpcb so lsufx",
  767                             tpcb, so, *(u_short *) (tpcb->tp_lsuffix), 0);
  768         }
  769 #endif
  770 
  771 #ifdef ARGO_DEBUG
  772                 if (argo_debug[D_CONN]) {
  773                 printf("so_snd at %p so_rcv at %p\n", &so->so_snd, &so->so_rcv);
  774                 dump_mbuf(so->so_snd.sb_mb, "so_snd at detach ");
  775                 printf("about to call LL detach, nlproto %p, nl_detach %p\n",
  776                        tpcb->tp_nlproto, tpcb->tp_nlproto->nlp_pcbdetach);
  777         }
  778 #endif
  779 
  780         if (tpcb->tp_Xsnd.sb_mb) {
  781                 printf("Unsent Xdata on detach; would panic");
  782                 sbflush(&tpcb->tp_Xsnd);
  783         }
  784         if (tpcb->tp_ucddata)
  785                 m_freem(tpcb->tp_ucddata);
  786 
  787 #ifdef ARGO_DEBUG
  788         if (argo_debug[D_CONN]) {
  789                 printf("reassembly info cnt %d rsyq %p\n",
  790                        tpcb->tp_rsycnt, tpcb->tp_rsyq);
  791         }
  792 #endif
  793         if (tpcb->tp_rsyq)
  794                 tp_rsyflush(tpcb);
  795 
  796         if (tpcb->tp_next) {
  797                 remque(tpcb);
  798                 tpcb->tp_next = tpcb->tp_prev = 0;
  799         }
  800         tpcb->tp_notdetached = 0;
  801 
  802 #ifdef ARGO_DEBUG
  803         if (argo_debug[D_CONN]) {
  804                 printf("calling (...nlproto->...)(%p, so %p)\n",
  805                        tpcb->tp_npcb, so);
  806                 printf("so %p so_head %p,  qlen %d q0len %d qlimit %d\n",
  807                        so, so->so_head,
  808                        so->so_q0len, so->so_qlen, so->so_qlimit);
  809         }
  810 #endif
  811 
  812         (*tpcb->tp_nlproto->nlp_pcbdetach)(tpcb->tp_npcb);
  813         /* does an so->so_pcb = 0; sofree(so) */
  814 
  815 #ifdef ARGO_DEBUG
  816         if (argo_debug[D_CONN]) {
  817                 printf("after xxx_pcbdetach\n");
  818         }
  819 #endif
  820 
  821         if (tpcb->tp_state == TP_LISTENING) {
  822                 struct tp_pcb **tt;
  823                 for (tt = &tp_listeners; *tt; tt = &((*tt)->tp_nextlisten))
  824                         if (*tt == tpcb)
  825                                 break;
  826                 if (*tt)
  827                         *tt = tpcb->tp_nextlisten;
  828                 else
  829                         printf("tp_detach from listen: should panic\n");
  830         }
  831         if (tpcb->tp_refstate == REF_OPENING) {
  832                 /*
  833                  * no connection existed here so no reference timer will be
  834                  * called
  835                  */
  836 #ifdef ARGO_DEBUG
  837                 if (argo_debug[D_CONN]) {
  838                         printf("SETTING ref %d to REF_FREE\n", tpcb->tp_lref);
  839                 }
  840 #endif
  841 
  842                 tp_freeref(tpcb->tp_lref);
  843         }
  844 #ifdef TP_PERF_MEAS
  845         /*
  846          * Get rid of the cluster mbuf allocated for performance
  847          * measurements, if there is one.  Note that tpcb->tp_perf_on says
  848          * nothing about whether or not a cluster mbuf was allocated, so you
  849          * have to check for a pointer to one (that is, we need the
  850          * TP_PERF_MEASs around the following section of code, not the
  851          * IFPERFs)
  852          */
  853         if (tpcb->tp_p_meas) {
  854                 struct mbuf *m = tpcb->tp_p_mbuf;
  855                 struct mbuf    *n;
  856 #ifdef ARGO_DEBUG
  857                 if (argo_debug[D_PERF_MEAS]) {
  858                         printf("freeing tp_p_meas 0x%x  ", tpcb->tp_p_meas);
  859                 }
  860 #endif
  861                 free(tpcb->tp_p_meas, M_PCB);
  862                 tpcb->tp_p_meas = 0;
  863         }
  864 #endif                          /* TP_PERF_MEAS */
  865 
  866 #ifdef ARGO_DEBUG
  867         if (argo_debug[D_CONN]) {
  868                 printf("end of detach, NOT single, tpcb %p\n", tpcb);
  869         }
  870 #endif
  871         /* free((caddr_t)tpcb, M_PCB); WHere to put this ? */
  872 }
  873 
  874 struct que {
  875         struct tp_pcb  *next;
  876         struct tp_pcb  *prev;
  877 }               tp_bound_pcbs =
  878 {
  879         (struct tp_pcb *) & tp_bound_pcbs, (struct tp_pcb *) & tp_bound_pcbs
  880 };
  881 
  882 u_short         tp_unique;
  883 
  884 int
  885 tp_tselinuse(int tlen, caddr_t tsel, struct sockaddr_iso *siso, int reuseaddr)
  886 {
  887         struct tp_pcb  *b = tp_bound_pcbs.next, *l = tp_listeners;
  888         struct tp_pcb *t;
  889 
  890         for (;;) {
  891                 if (b != (struct tp_pcb *) & tp_bound_pcbs) {
  892                         t = b;
  893                         b = t->tp_next;
  894                 } else if (l) {
  895                         t = l;
  896                         l = t->tp_nextlisten;
  897                 } else
  898                         break;
  899                 if (tlen == t->tp_lsuffixlen && bcmp(tsel, t->tp_lsuffix, tlen) == 0) {
  900                         if (t->tp_flags & TPF_GENERAL_ADDR) {
  901                                 if (siso == 0 || reuseaddr == 0)
  902                                         return 1;
  903                         } else if (siso) {
  904                                 if (siso->siso_family == t->tp_domain &&
  905                                     (*t->tp_nlproto->nlp_cmpnetaddr)(t->tp_npcb,
  906                                         (struct sockaddr *) siso, TP_LOCAL))
  907                                         return 1;
  908                         } else if (reuseaddr == 0)
  909                                 return 1;
  910                 }
  911         }
  912         return 0;
  913 
  914 }
  915 
  916 
  917 int
  918 tp_pcbbind(void *v, struct mbuf *nam, struct proc *p)
  919 {
  920         struct tp_pcb *tpcb = v;
  921         struct sockaddr_iso *siso = 0;
  922         int             tlen = 0, wrapped = 0;
  923         caddr_t         tsel = NULL;
  924         u_short         tutil;
  925 
  926         if (tpcb->tp_state != TP_CLOSED)
  927                 return (EINVAL);
  928         if (nam) {
  929                 siso = mtod(nam, struct sockaddr_iso *);
  930                 switch (siso->siso_family) {
  931                 default:
  932                         return (EAFNOSUPPORT);
  933 #ifdef ISO
  934                 case AF_ISO:
  935                         tlen = siso->siso_tlen;
  936                         tsel = TSEL(siso);
  937                         if (siso->siso_nlen == 0)
  938                                 siso = 0;
  939                         break;
  940 #endif
  941 #ifdef INET
  942                 case AF_INET:
  943                         tsel = (caddr_t) & tutil;
  944                         if ((tutil = satosin(siso)->sin_port) != 0)
  945                                 tlen = 2;
  946                         if (satosin(siso)->sin_addr.s_addr == 0)
  947                                 siso = 0;
  948 #endif
  949                 }
  950         }
  951         if (tpcb->tp_lsuffixlen == 0) {
  952                 if (tlen) {
  953                         if (tp_tselinuse(tlen, tsel, siso,
  954                                   tpcb->tp_sock->so_options & SO_REUSEADDR))
  955                                 return (EINVAL);
  956                 } else {
  957                         for (tsel = (caddr_t) & tutil, tlen = 2;;) {
  958                                 if (tp_unique++ < ISO_PORT_RESERVED ||
  959                                     tp_unique > ISO_PORT_USERRESERVED) {
  960                                         if (wrapped++)
  961                                                 return ESRCH;
  962                                         tp_unique = ISO_PORT_RESERVED;
  963                                 }
  964                                 tutil = htons(tp_unique);
  965                                 if (tp_tselinuse(tlen, tsel, siso, 0) == 0)
  966                                         break;
  967                         }
  968                         if (siso)
  969                                 switch (siso->siso_family) {
  970 #ifdef ISO
  971                                 case AF_ISO:
  972                                         bcopy(tsel, TSEL(siso), tlen);
  973                                         siso->siso_tlen = tlen;
  974                                         break;
  975 #endif
  976 #ifdef INET
  977                                 case AF_INET:
  978                                         satosin(siso)->sin_port = tutil;
  979 #endif
  980                                 }
  981                 }
  982                 bcopy(tsel, tpcb->tp_lsuffix, (tpcb->tp_lsuffixlen = tlen));
  983                 insque(tpcb, &tp_bound_pcbs);
  984         } else {
  985                 if (tlen || siso == 0)
  986                         return (EINVAL);
  987         }
  988         if (siso == 0) {
  989                 tpcb->tp_flags |= TPF_GENERAL_ADDR;
  990                 return (0);
  991         }
  992         return (*tpcb->tp_nlproto->nlp_pcbbind)(tpcb->tp_npcb, nam, p);
  993 }

Cache object: 32f4c649b8823087cc90c56ca7f262b4


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