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.36 2008/04/23 09:57:59 plunky 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.36 2008/04/23 09:57:59 plunky 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 
  260 struct tp_stat tp_stat;
  261 u_int tp_start_win;
  262 
  263 struct nl_protosw nl_protosw[] = {
  264         /* ISO_CLNS */
  265 #ifdef ISO
  266         {AF_ISO, iso_putnetaddr, iso_getnetaddr, iso_cmpnetaddr,
  267                 iso_putsufx, iso_getsufx,
  268                 iso_recycle_tsuffix,
  269                 tpclnp_mtu, iso_pcbbind, iso_pcbconnect,
  270                 iso_pcbdisconnect, iso_pcbdetach,
  271                 iso_pcballoc,
  272                 tpclnp_output, tpclnp_output_dg, iso_nlctloutput,
  273                 (void *) & tp_isopcb,
  274         },
  275 #else
  276         { .nlp_afamily = 0, },
  277 #endif                          /* ISO */
  278         /* IN_CLNS */
  279 #ifdef INET
  280         {AF_INET, in_putnetaddr, in_getnetaddr, in_cmpnetaddr,
  281                 in_putsufx, in_getsufx,
  282                 in_recycle_tsuffix,
  283                 tpip_mtu, in_pcbbind, in_pcbconnect,
  284                 in_pcbdisconnect, in_pcbdetach,
  285                 in_pcballoc,
  286                 tpip_output, tpip_output_dg, /* nl_ctloutput */ NULL,
  287                 (void *) & tp_inpcb,
  288         },
  289 #else
  290         { .nlp_afamily = 0, },
  291 #endif                          /* INET */
  292         /* ISO_CONS */
  293         { .nlp_afamily = 0, },
  294         /* End of protosw marker */
  295         { .nlp_afamily = 0, },
  296 };
  297 
  298 u_long          tp_sendspace = 1024 * 4;
  299 u_long          tp_recvspace = 1024 * 4;
  300 
  301 /*
  302  * NAME:  tp_init()
  303  *
  304  * CALLED FROM:
  305  *  autoconf through the protosw structure
  306  *
  307  * FUNCTION:
  308  *  initialize tp machine
  309  *
  310  * RETURNS:  Nada
  311  *
  312  * SIDE EFFECTS:
  313  *
  314  * NOTES:
  315  */
  316 void
  317 tp_init(void)
  318 {
  319         static int      init_done = 0;
  320 
  321         if (init_done++)
  322                 return;
  323 
  324 #ifdef INET
  325         /* FOR INET */
  326         in_pcbinit(&tp_inpcb, 1, 1);
  327 #endif
  328 #ifdef ISO
  329         /* FOR ISO */
  330         tp_isopcb.isop_next = tp_isopcb.isop_prev = &tp_isopcb;
  331 #endif
  332 
  333         tp_start_win = 2;
  334 
  335         tp_timerinit();
  336         bzero((void *) & tp_stat, sizeof(struct tp_stat));
  337 }
  338 
  339 /*
  340  * NAME:        tp_soisdisconnecting()
  341  *
  342  * CALLED FROM:
  343  *  tp.trans
  344  *
  345  * FUNCTION and ARGUMENTS:
  346  *  Set state of the socket (so) to reflect that fact that we're disconnectING
  347  *
  348  * RETURNS:     Nada
  349  *
  350  * SIDE EFFECTS:
  351  *
  352  * NOTES:
  353  *  This differs from the regular soisdisconnecting() in that the latter
  354  *  also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags.
  355  *  We don't want to set those flags because those flags will cause
  356  *  a SIGPIPE to be delivered in sosend() and we don't like that.
  357  *  If anyone else is sleeping on this socket, wake 'em up.
  358  */
  359 void
  360 tp_soisdisconnecting(struct socket *so)
  361 {
  362         soisdisconnecting(so);
  363         so->so_state &= ~SS_CANTSENDMORE;
  364 #ifdef TP_PERF_MEAS
  365         if (DOPERF(sototpcb(so))) {
  366                 struct tp_pcb *tpcb = sototpcb(so);
  367                 u_int           fsufx, lsufx;
  368                 struct timeval  now;
  369 
  370                 bcopy((void *) tpcb->tp_fsuffix, (void *) &fsufx,
  371                       sizeof(u_int));
  372                 bcopy((void *) tpcb->tp_lsuffix, (void *) &lsufx,
  373                       sizeof(u_int));
  374 
  375                 getmicrotime(&now);
  376                 tpmeas(tpcb->tp_lref, TPtime_close, &now, fsufx, lsufx,
  377                        tpcb->tp_fref);
  378                 tpcb->tp_perf_on = 0;   /* turn perf off */
  379         }
  380 #endif
  381 }
  382 
  383 
  384 /*
  385  * NAME: tp_soisdisconnected()
  386  *
  387  * CALLED FROM:
  388  *      tp.trans
  389  *
  390  * FUNCTION and ARGUMENTS:
  391  *  Set state of the socket (so) to reflect that fact that we're disconnectED
  392  *  Set the state of the reference structure to closed, and
  393  *  recycle the suffix.
  394  *  Start a reference timer.
  395  *
  396  * RETURNS:     Nada
  397  *
  398  * SIDE EFFECTS:
  399  *
  400  * NOTES:
  401  *  This differs from the regular soisdisconnected() in that the latter
  402  *  also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags.
  403  *  We don't want to set those flags because those flags will cause
  404  *  a SIGPIPE to be delivered in sosend() and we don't like that.
  405  *  If anyone else is sleeping on this socket, wake 'em up.
  406  */
  407 void
  408 tp_soisdisconnected(struct tp_pcb *tpcb)
  409 {
  410         struct socket *so = tpcb->tp_sock;
  411 
  412         soisdisconnecting(so);
  413         so->so_state &= ~SS_CANTSENDMORE;
  414 #ifdef TP_PERF_MEAS
  415         if (DOPERF(tpcb)) {
  416                 struct tp_pcb *ttpcb = sototpcb(so);
  417                 u_int           fsufx, lsufx;
  418                 struct timeval  now;
  419 
  420                 /* CHOKE */
  421                 bcopy((void *) ttpcb->tp_fsuffix, (void *) &fsufx,
  422                       sizeof(u_int));
  423                 bcopy((void *) ttpcb->tp_lsuffix, (void *) &lsufx,
  424                       sizeof(u_int));
  425 
  426                 getmicrotime(&now);
  427                 tpmeas(ttpcb->tp_lref, TPtime_close,
  428                        &now, &lsufx, &fsufx, ttpcb->tp_fref);
  429                 tpcb->tp_perf_on = 0;   /* turn perf off */
  430         }
  431 #endif
  432 
  433         tpcb->tp_refstate = REF_FROZEN;
  434         tp_recycle_tsuffix(tpcb);
  435         tp_etimeout(tpcb, TM_reference, (int) tpcb->tp_refer_ticks);
  436 }
  437 
  438 /*
  439  * NAME:        tp_freeref()
  440  *
  441  * CALLED FROM:
  442  *  tp.trans when the reference timer goes off, and
  443  *  from tp_attach() and tp_detach() when a tpcb is partially set up but not
  444  *  set up enough to have a ref timer set for it, and it's discarded
  445  *  due to some sort of error or an early close()
  446  *
  447  * FUNCTION and ARGUMENTS:
  448  *  Frees the reference represented by (r) for re-use.
  449  *
  450  * RETURNS: Nothing
  451  *
  452  * SIDE EFFECTS:
  453  *
  454  * NOTES:       better be called at clock priority !!!!!
  455  */
  456 void
  457 tp_freeref(RefNum n)
  458 {
  459         struct tp_ref *r = tp_ref + n;
  460         struct tp_pcb *tpcb;
  461 
  462         tpcb = r->tpr_pcb;
  463 #ifdef ARGO_DEBUG
  464         if (argo_debug[D_TIMER]) {
  465                 printf("tp_freeref called for ref %d pcb %p maxrefopen %d\n",
  466                        n, tpcb, tp_refinfo.tpr_maxopen);
  467         }
  468 #endif
  469 #ifdef TPPT
  470         if (tp_traceflags[D_TIMER]) {
  471                 tptrace(TPPTmisc, "tp_freeref ref maxrefopen pcb",
  472                         n, tp_refinfo.tpr_maxopen, tpcb, 0);
  473         }
  474 #endif
  475         if (tpcb == 0)
  476                 return;
  477 #ifdef ARGO_DEBUG
  478         if (argo_debug[D_CONN]) {
  479                 printf("tp_freeref: CLEARING tpr_pcb %p\n", tpcb);
  480         }
  481 #endif
  482         r->tpr_pcb = (struct tp_pcb *) 0;
  483         tpcb->tp_refstate = REF_FREE;
  484 
  485         for (r = tp_ref + tp_refinfo.tpr_maxopen; r > tp_ref; r--)
  486                 if (r->tpr_pcb)
  487                         break;
  488         tp_refinfo.tpr_maxopen = r - tp_ref;
  489         tp_refinfo.tpr_numopen--;
  490 
  491 #ifdef ARGO_DEBUG
  492         if (argo_debug[D_TIMER]) {
  493                 printf("tp_freeref ends w/ maxrefopen %d\n", tp_refinfo.tpr_maxopen);
  494         }
  495 #endif
  496 }
  497 
  498 /*
  499  * NAME:  tp_getref()
  500  *
  501  * CALLED FROM:
  502  *  tp_attach()
  503  *
  504  * FUNCTION and ARGUMENTS:
  505  *  obtains the next free reference and allocates the appropriate
  506  *  ref structure, links that structure to (tpcb)
  507  *
  508  * RETURN VALUE:
  509  *      a reference number
  510  *  or TP_ENOREF
  511  *
  512  * SIDE EFFECTS:
  513  *
  514  * NOTES:
  515  */
  516 u_long
  517 tp_getref(struct tp_pcb *tpcb)
  518 {
  519         struct tp_ref *r, *rlim;
  520         int    i;
  521         void *        obase;
  522         unsigned        size;
  523 
  524         if (++tp_refinfo.tpr_numopen < tp_refinfo.tpr_size)
  525                 for (r = tp_refinfo.tpr_base, rlim = r + tp_refinfo.tpr_size;
  526                      ++r < rlim;)       /* tp_ref[0] is never used */
  527                         if (r->tpr_pcb == 0)
  528                                 goto got_one;
  529         /* else have to allocate more space */
  530 
  531         obase = (void *) tp_refinfo.tpr_base;
  532         size = tp_refinfo.tpr_size * sizeof(struct tp_ref);
  533         r = (struct tp_ref *) malloc(size + size, M_PCB, M_NOWAIT);
  534         if (r == 0)
  535                 return (--tp_refinfo.tpr_numopen, TP_ENOREF);
  536         tp_refinfo.tpr_base = tp_ref = r;
  537         tp_refinfo.tpr_size *= 2;
  538         memcpy(r, obase, size);
  539         free(obase, M_PCB);
  540         r = (struct tp_ref *)(size + (char *)r);
  541         bzero((void *) r, size);
  542 
  543 got_one:
  544         r->tpr_pcb = tpcb;
  545         tpcb->tp_refstate = REF_OPENING;
  546         i = r - tp_refinfo.tpr_base;
  547         if (tp_refinfo.tpr_maxopen < i)
  548                 tp_refinfo.tpr_maxopen = i;
  549         return (u_long) i;
  550 }
  551 
  552 /*
  553  * NAME: tp_set_npcb()
  554  *
  555  * CALLED FROM:
  556  *      tp_attach(), tp_route_to()
  557  *
  558  * FUNCTION and ARGUMENTS:
  559  *  given a tpcb, allocate an appropriate lower-lever npcb, freeing
  560  *  any old ones that might need re-assigning.
  561  */
  562 int
  563 tp_set_npcb(struct tp_pcb *tpcb)
  564 {
  565         struct socket *so = tpcb->tp_sock;
  566         int             error;
  567 
  568         if (tpcb->tp_nlproto && tpcb->tp_npcb) {
  569                 short           so_state = so->so_state;
  570                 so->so_state &= ~SS_NOFDREF;
  571                 (*tpcb->tp_nlproto->nlp_pcbdetach)(tpcb->tp_npcb);
  572                 so->so_state = so_state;
  573         }
  574         tpcb->tp_nlproto = &nl_protosw[tpcb->tp_netservice];
  575         /* xx_pcballoc sets so_pcb */
  576         error = (*tpcb->tp_nlproto->nlp_pcballoc)(so,
  577                                     tpcb->tp_nlproto->nlp_pcblist);
  578         tpcb->tp_npcb = so->so_pcb;
  579         so->so_pcb = tpcb;
  580         return (error);
  581 }
  582 /*
  583  * NAME: tp_attach()
  584  *
  585  * CALLED FROM:
  586  *      tp_usrreq, PRU_ATTACH
  587  *
  588  * FUNCTION and ARGUMENTS:
  589  *  given a socket (so) and a protocol family (dom), allocate a tpcb
  590  *  and ref structure, initialize everything in the structures that
  591  *  needs to be initialized.
  592  *
  593  * RETURN VALUE:
  594  *  0 ok
  595  *  EINVAL if DEBUG(X) in is on and a disaster has occurred
  596  *  ENOPROTOOPT if TP hasn't been configured or if the
  597  *   socket wasn't created with tp as its protocol
  598  *  EISCONN if this socket is already part of a connection
  599  *  ETOOMANYREFS if ran out of tp reference numbers.
  600  *  E* whatever error is returned from soreserve()
  601  *    for from the network-layer pcb allocation routine
  602  *
  603  * SIDE EFFECTS:
  604  *
  605  * NOTES:
  606  */
  607 int
  608 tp_attach(struct socket *so, int protocol)
  609 {
  610         struct tp_pcb *tpcb;
  611         int             error = 0;
  612         int             dom = so->so_proto->pr_domain->dom_family;
  613         u_long          lref;
  614 
  615 #ifdef ARGO_DEBUG
  616         if (argo_debug[D_CONN]) {
  617                 printf("tp_attach:dom 0x%x so %p ", dom, so);
  618         }
  619 #endif
  620 #ifdef TPPT
  621         if (tp_traceflags[D_CONN]) {
  622                 tptrace(TPPTmisc, "tp_attach:dom so", dom, so, 0, 0);
  623         }
  624 #endif
  625 
  626         if (so->so_pcb != NULL) {
  627                 return EISCONN; /* socket already part of a connection */
  628         }
  629         if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0)
  630                 error = soreserve(so, tp_sendspace, tp_recvspace);
  631         /* later an ioctl will allow reallocation IF still in closed state */
  632 
  633         if (error)
  634                 goto bad2;
  635 
  636         MALLOC(tpcb, struct tp_pcb *, sizeof(*tpcb), M_PCB, M_NOWAIT|M_ZERO);
  637         if (tpcb == NULL) {
  638                 error = ENOBUFS;
  639                 goto bad2;
  640         }
  641 
  642         if (((lref = tp_getref(tpcb)) & TP_ENOREF) != 0) {
  643                 error = ETOOMANYREFS;
  644                 goto bad3;
  645         }
  646         tpcb->tp_lref = lref;
  647         tpcb->tp_sock = so;
  648         tpcb->tp_domain = dom;
  649         tpcb->tp_rhiwat = so->so_rcv.sb_hiwat;
  650         /* tpcb->tp_proto = protocol; someday maybe? */
  651         if (protocol && protocol < ISOPROTO_TP4) {
  652                 tpcb->tp_netservice = ISO_CONS;
  653                 tpcb->tp_snduna = (SeqNum) - 1; /* kludge so the pseudo-ack
  654                                                  * from the CR/CC will
  655                                                  * generate correct fake-ack
  656                                                  * values */
  657         } else {
  658                 tpcb->tp_netservice = (dom == AF_INET) ? IN_CLNS : ISO_CLNS;
  659                 /* the default */
  660         }
  661         tpcb->_tp_param = tp_conn_param[tpcb->tp_netservice];
  662 
  663         tpcb->tp_state = TP_CLOSED;
  664         tpcb->tp_vers = TP_VERSION;
  665         tpcb->tp_notdetached = 1;
  666 
  667         /*
  668          * Spec says default is 128 octets, that is, if the tpdusize argument
  669          * never appears, use 128. As the initiator, we will always "propose"
  670          * the 2048 size, that is, we will put this argument in the CR
  671          * always, but accept what the other side sends on the CC. If the
  672          * initiator sends us something larger on a CR, we'll respond w/
  673          * this. Our maximum is 4096.  See tp_chksum.c comments.
  674          */
  675         tpcb->tp_cong_win =
  676                 tpcb->tp_l_tpdusize = 1 << tpcb->tp_tpdusize;
  677 
  678         tpcb->tp_seqmask = TP_NML_FMT_MASK;
  679         tpcb->tp_seqbit = TP_NML_FMT_BIT;
  680         tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1;
  681 
  682         /* attach to a network-layer protoswitch */
  683         if ((error = tp_set_npcb(tpcb)) != 0)
  684                 goto bad4;
  685         ASSERT(tpcb->tp_nlproto->nlp_afamily == tpcb->tp_domain);
  686 
  687         /* nothing to do for iso case */
  688         if (dom == AF_INET) {
  689                 /* tp_set_npcb sets it */
  690                 KASSERT(so->so_pcb != NULL);
  691                 sotoinpcb(so)->inp_ppcb = (void *) tpcb;
  692         }
  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((void *) 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                 iso_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((void *)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, const char *tsel, struct sockaddr_iso *siso,
  886     int reuseaddr)
  887 {
  888         struct tp_pcb  *b = tp_bound_pcbs.next, *l = tp_listeners;
  889         struct tp_pcb *t;
  890 
  891         for (;;) {
  892                 if (b != (struct tp_pcb *) & tp_bound_pcbs) {
  893                         t = b;
  894                         b = t->tp_next;
  895                 } else if (l) {
  896                         t = l;
  897                         l = t->tp_nextlisten;
  898                 } else
  899                         break;
  900                 if (tlen == t->tp_lsuffixlen && bcmp(tsel, t->tp_lsuffix, tlen) == 0) {
  901                         if (t->tp_flags & TPF_GENERAL_ADDR) {
  902                                 if (siso == 0 || reuseaddr == 0)
  903                                         return 1;
  904                         } else if (siso) {
  905                                 if (siso->siso_family == t->tp_domain &&
  906                                     (*t->tp_nlproto->nlp_cmpnetaddr)(t->tp_npcb,
  907                                         (struct sockaddr *) siso, TP_LOCAL))
  908                                         return 1;
  909                         } else if (reuseaddr == 0)
  910                                 return 1;
  911                 }
  912         }
  913         return 0;
  914 
  915 }
  916 
  917 
  918 int
  919 tp_pcbbind(void *v, struct mbuf *nam, struct lwp *l)
  920 {
  921         struct tp_pcb *tpcb = v;
  922         struct sockaddr_iso *siso = 0;
  923         int             tlen = 0, wrapped = 0;
  924         const char *tsel = NULL;
  925         u_short         tutil;
  926 
  927         if (tpcb->tp_state != TP_CLOSED)
  928                 return (EINVAL);
  929         if (nam) {
  930                 siso = mtod(nam, struct sockaddr_iso *);
  931                 switch (siso->siso_family) {
  932                 default:
  933                         return (EAFNOSUPPORT);
  934 #ifdef ISO
  935                 case AF_ISO:
  936                         tlen = siso->siso_tlen;
  937                         tsel = TSEL(siso);
  938                         if (siso->siso_nlen == 0)
  939                                 siso = 0;
  940                         break;
  941 #endif
  942 #ifdef INET
  943                 case AF_INET:
  944                         tsel = (void *) & tutil;
  945                         if ((tutil = satosin(siso)->sin_port) != 0)
  946                                 tlen = 2;
  947                         if (satosin(siso)->sin_addr.s_addr == 0)
  948                                 siso = 0;
  949 #endif
  950                 }
  951         }
  952         if (tpcb->tp_lsuffixlen == 0) {
  953                 if (tlen) {
  954                         if (tp_tselinuse(tlen, tsel, siso,
  955                                   tpcb->tp_sock->so_options & SO_REUSEADDR))
  956                                 return (EINVAL);
  957                 } else {
  958                         for (tsel = (void *) & tutil, tlen = 2;;) {
  959                                 if (tp_unique++ < ISO_PORT_RESERVED ||
  960                                     tp_unique > ISO_PORT_USERRESERVED) {
  961                                         if (wrapped++)
  962                                                 return ESRCH;
  963                                         tp_unique = ISO_PORT_RESERVED;
  964                                 }
  965                                 tutil = htons(tp_unique);
  966                                 if (tp_tselinuse(tlen, tsel, siso, 0) == 0)
  967                                         break;
  968                         }
  969                         if (siso)
  970                                 switch (siso->siso_family) {
  971 #ifdef ISO
  972                                 case AF_ISO:
  973                                         memcpy(WRITABLE_TSEL(siso), tsel, tlen);
  974                                         siso->siso_tlen = tlen;
  975                                         break;
  976 #endif
  977 #ifdef INET
  978                                 case AF_INET:
  979                                         satosin(siso)->sin_port = tutil;
  980 #endif
  981                                 }
  982                 }
  983                 bcopy(tsel, tpcb->tp_lsuffix, (tpcb->tp_lsuffixlen = tlen));
  984                 iso_insque(tpcb, &tp_bound_pcbs);
  985         } else {
  986                 if (tlen || siso == 0)
  987                         return (EINVAL);
  988         }
  989         if (siso == 0) {
  990                 tpcb->tp_flags |= TPF_GENERAL_ADDR;
  991                 return (0);
  992         }
  993         return (*tpcb->tp_nlproto->nlp_pcbbind)(tpcb->tp_npcb, nam, l);
  994 }

Cache object: 1a54e0e007bbc2813f04717d4cc71696


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