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_input.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_input.c,v 1.26 2006/09/07 02:40:33 dogcow 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_input.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  * tp_input() gets an mbuf chain from ip.  Actually, not directly from ip,
   62  * because ip calls a net-level routine that strips off the net header and
   63  * then calls tp_input(), passing the proper type of addresses for the
   64  * address family in use (how it figures out which AF is not yet determined.)
   65  *
   66  * Decomposing the tpdu is some of the most laughable code.  The variable-length
   67  * parameters and the problem of non-aligned memory references necessitates
   68  * such abominations as the macros WHILE_OPTIONS (q.v. below) to loop through
   69  * the header and decompose it.
   70  *
   71  * The routine tp_newsocket() is called when a CR comes in for a listening
   72  * socket.  tp_input calls sonewconn() and tp_newsocket() to set up the
   73  * "child" socket.  Most tpcb values are copied from the parent tpcb into the
   74  * child.
   75  *
   76  * Also in here is tp_headersize() (grot) which tells the expected size of a tp
   77  * header, to be used by other layers.  It's in here because it uses the
   78  * static structure tpdu_info.
   79  */
   80 
   81 #include <sys/cdefs.h>
   82 __KERNEL_RCSID(0, "$NetBSD: tp_input.c,v 1.26 2006/09/07 02:40:33 dogcow Exp $");
   83 
   84 #include "opt_iso.h"
   85 
   86 #include <sys/param.h>
   87 #include <sys/systm.h>
   88 #include <sys/mbuf.h>
   89 #include <sys/socket.h>
   90 #include <sys/socketvar.h>
   91 #include <sys/domain.h>
   92 #include <sys/protosw.h>
   93 #include <sys/errno.h>
   94 #include <sys/time.h>
   95 #include <sys/kernel.h>
   96 
   97 #include <net/if.h>
   98 
   99 #include <netiso/iso.h>
  100 #include <netiso/iso_errno.h>
  101 #include <netiso/iso_pcb.h>
  102 #include <netiso/tp_param.h>
  103 #include <netiso/tp_var.h>
  104 #include <netiso/tp_timer.h>
  105 #include <netiso/tp_stat.h>
  106 #include <netiso/tp_pcb.h>
  107 #include <netiso/argo_debug.h>
  108 #include <netiso/tp_trace.h>
  109 #include <netiso/tp_tpdu.h>
  110 #include <netiso/iso_var.h>
  111 
  112 #include <machine/stdarg.h>
  113 
  114 static struct socket *
  115         tp_newsocket(struct socket *, struct sockaddr *, caddr_t, u_int, u_int);
  116 
  117 struct mbuf *
  118 tp_inputprep(struct mbuf *m)
  119 {
  120         int             hdrlen;
  121 
  122 #ifdef ARGO_DEBUG
  123         if (argo_debug[D_TPINPUT]) {
  124                 printf("tp_inputprep: m %p\n", m);
  125         }
  126 #endif
  127 
  128         while (m->m_len < 1) {
  129                 /*
  130                  * The "m_free" logic if( (m = m_free(m)) == NULL ) return
  131                  * (struct mbuf *)0; would cause a system crash if ever
  132                  * executed. This logic will be executed if the first mbuf in
  133                  * the chain only contains a CLNP header. The m_free routine
  134                  * will release the mbuf containing the CLNP header from the
  135                  * chain and the new head of the chain will not have the
  136                  * M_PKTHDR bit set. This routine, tp_inputprep, will
  137                  * eventually call the "sbappendaddr" routine. "sbappendaddr"
  138                  * calls "panic" if M_PKTHDR is not set. m_pullup is a cheap
  139                  * way of keeping the head of the chain from being freed.
  140                  */
  141                 if ((m = m_pullup(m, 1)) == NULL)
  142                         return (NULL);
  143         }
  144         if (((long) m->m_data) & 0x3) {
  145                 /*
  146                  * If we are not 4-byte aligned, we have to be above the
  147                  * beginning of the mbuf, and it is ok just to slide it back.
  148                  */
  149                 caddr_t         ocp = m->m_data;
  150 
  151                 m->m_data = (caddr_t) (((long) m->m_data) & ~0x3);
  152                 bcopy(ocp, m->m_data, (unsigned) m->m_len);
  153         }
  154         CHANGE_MTYPE(m, TPMT_DATA);
  155 
  156         /*
  157          * we KNOW that there is at least 1 byte in this mbuf and that it is
  158          * hdr->tpdu_li XXXXXXX!
  159          */
  160 
  161         hdrlen = 1 + *mtod(m, u_char *);
  162 
  163         /*
  164          * now pull up the whole tp header
  165          */
  166         if (m->m_len < hdrlen) {
  167                 if ((m = m_pullup(m, hdrlen)) == NULL) {
  168                         IncStat(ts_recv_drop);
  169                         return (struct mbuf *) 0;
  170                 }
  171         }
  172 #ifdef ARGO_DEBUG
  173         if (argo_debug[D_INPUT]) {
  174                 printf(
  175                        " at end: m %p hdr->tpdu_li 0x%x m_len 0x%x\n", m,
  176                        hdrlen, m->m_len);
  177         }
  178 #endif
  179         return m;
  180 }
  181 
  182 /*
  183  * begin groan -- this array and the following macros allow you to step
  184  * through the parameters of the variable part of a header note that if for
  185  * any reason the values of the **_TPDU macros (in tp_events.h) should
  186  * change, this array has to be rearranged
  187  */
  188 
  189 #define TP_LEN_CLASS_0_INDEX    2
  190 #define TP_MAX_DATA_INDEX 3
  191 
  192 static const u_char tpdu_info[][4] =
  193 {
  194         /* length                                                max data len */
  195         /* reg fmt      xtd fmt  class 0                          */
  196         /* UNUSED               0x0 */ { 0x0, 0x0, 0x0, 0x0             },
  197         /* XPD_TPDU_type        0x1 */ { 0x5, 0x8, 0x0, TP_MAX_XPD_DATA },
  198         /* XAK_TPDU_type        0x2 */ { 0x5, 0x8, 0x0, 0x0             },
  199         /* GR_TPDU_type         0x3 */ { 0x0, 0x0, 0x0, 0x0             },
  200         /* UNUSED               0x4 */ { 0x0, 0x0, 0x0, 0x0             },
  201         /* UNUSED               0x5 */ { 0x0, 0x0, 0x0, 0x0             },
  202         /* AK_TPDU_type         0x6 */ { 0x5, 0xa, 0x0, 0x0             },
  203         /* ER_TPDU_type         0x7 */ { 0x5, 0x5, 0x0, 0x0             },
  204         /* DR_TPDU_type         0x8 */ { 0x7, 0x7, 0x7, TP_MAX_DR_DATA  },
  205         /* UNUSED               0x9 */ { 0x0, 0x0, 0x0, 0x0             },
  206         /* UNUSED               0xa */ { 0x0, 0x0, 0x0, 0x0             },
  207         /* UNUSED               0xb */ { 0x0, 0x0, 0x0, 0x0             },
  208         /* DC_TPDU_type         0xc */ { 0x6, 0x6, 0x0, 0x0             },
  209         /* CC_TPDU_type         0xd */ { 0x7, 0x7, 0x7, TP_MAX_CC_DATA  },
  210         /* CR_TPDU_type         0xe */ { 0x7, 0x7, 0x7, TP_MAX_CR_DATA  },
  211         /* DT_TPDU_type         0xf */ { 0x5, 0x8, 0x3, 0x0             },
  212 };
  213 
  214 #define CHECK(Phrase, Erval, Stat, Whattodo, Loc)\
  215         if (Phrase) {error = (Erval); errlen = (int)(Loc); IncStat(Stat);\
  216         goto Whattodo; }
  217 
  218 /*
  219  * WHENEVER YOU USE THE FOLLOWING MACRO, BE SURE THE TPDUTYPE IS A LEGIT
  220  * VALUE FIRST!
  221  */
  222 
  223 #define WHILE_OPTIONS(P, hdr, format)\
  224 {       caddr_t P = tpdu_info[(hdr)->tpdu_type][(format)] + (caddr_t)hdr;\
  225         caddr_t PLIM = 1 + hdr->tpdu_li + (caddr_t)hdr;\
  226         for (;; P += 2 + ((struct tp_vbp *)P)->tpv_len) {\
  227                 CHECK((P > PLIM), E_TP_LENGTH_INVAL, ts_inv_length,\
  228                                 respond, P - (caddr_t)hdr);\
  229                 if (P == PLIM) break;
  230 
  231 #define END_WHILE_OPTIONS(P) } }
  232 
  233 /* end groan */
  234 
  235 /*
  236  * NAME:  tp_newsocket()
  237  *
  238  * CALLED FROM:
  239  *  tp_input() on incoming CR, when a socket w/ the called suffix
  240  * is awaiting a  connection request
  241  *
  242  * FUNCTION and ARGUMENTS:
  243  *  Create a new socket structure, attach to it a new transport pcb,
  244  *  using a copy of the net level pcb for the parent socket.
  245  *  (so) is the parent socket.
  246  *  (fname) is the foreign address (all that's used is the nsap portion)
  247  *
  248  * RETURN VALUE:
  249  *  a new socket structure, being this end of the newly formed connection.
  250  *
  251  * SIDE EFFECTS:
  252  *  Sets a few things in the tpcb and net level pcb
  253  *
  254  * NOTES:
  255  */
  256 static struct socket *
  257 tp_newsocket(
  258         struct socket  *so,
  259         struct sockaddr *fname,
  260         caddr_t         cons_channel,
  261         u_int          class_to_use,
  262         u_int           netservice)
  263 {
  264         struct tp_pcb *tpcb = sototpcb(so);     /* old tpcb, needed
  265                                                          * below */
  266         struct tp_pcb *newtpcb;
  267 
  268         /*
  269          * sonewconn() gets a new socket structure, a new lower layer pcb and
  270          * a new tpcb, but the pcbs are unnamed (not bound)
  271          */
  272 #ifdef TPPT
  273         if (tp_traceflags[D_NEWSOCK]) {
  274                 tptraceTPCB(TPPTmisc, "newsock: listg_so, _tpcb, so_head",
  275                             so, tpcb, so->so_head, 0);
  276         }
  277 #endif
  278 
  279         if ((so = sonewconn(so, SS_ISCONFIRMING)) == (struct socket *) 0)
  280                 return so;
  281 #ifdef TPPT
  282         if (tp_traceflags[D_NEWSOCK]) {
  283                 tptraceTPCB(TPPTmisc, "newsock: after newconn so, so_head",
  284                             so, so->so_head, 0, 0);
  285         }
  286 #endif
  287 
  288 #ifdef ARGO_DEBUG
  289         if (argo_debug[D_NEWSOCK]) {
  290                 printf("tp_newsocket(channel %p)  after sonewconn so %p \n",
  291                        cons_channel, so);
  292                 dump_addr(fname);
  293                 {
  294                         struct socket  *t, *head;
  295 
  296                         head = so->so_head;
  297                         t = so;
  298                         printf("so %p so_head %p so_q0 %p, q0len %d\n",
  299                                t, t->so_head, t->so_q0.tqh_first, t->so_q0len);
  300                         while ((t = t->so_q0.tqh_first) && t != so && t != head)
  301                                 printf("so %p so_head %p so_q0 %p, q0len %d\n",
  302                                        t, t->so_head, t->so_q0.tqh_first,
  303                                        t->so_q0len);
  304                 }
  305         }
  306 #endif
  307 
  308         /*
  309          * before we clobber the old tpcb ptr, get these items from the
  310          * parent pcb
  311          */
  312         newtpcb = sototpcb(so);
  313         newtpcb->_tp_param = tpcb->_tp_param;
  314         newtpcb->tp_flags = tpcb->tp_flags;
  315         newtpcb->tp_lcredit = tpcb->tp_lcredit;
  316         newtpcb->tp_l_tpdusize = tpcb->tp_l_tpdusize;
  317         newtpcb->tp_lsuffixlen = tpcb->tp_lsuffixlen;
  318         bcopy(tpcb->tp_lsuffix, newtpcb->tp_lsuffix, newtpcb->tp_lsuffixlen);
  319 
  320         if ( /* old */ tpcb->tp_ucddata) {
  321                 /*
  322                  * These data are the connect- , confirm- or disconnect-
  323                  * data.
  324                  */
  325                 struct mbuf    *conndata;
  326 
  327                 conndata = m_copy(tpcb->tp_ucddata, 0, (int) M_COPYALL);
  328 #ifdef ARGO_DEBUG
  329                 if (argo_debug[D_CONN]) {
  330                         dump_mbuf(conndata, "conndata after mcopy");
  331                 }
  332 #endif
  333                 newtpcb->tp_ucddata = conndata;
  334         }
  335         tpcb = newtpcb;
  336         tpcb->tp_state = TP_LISTENING;
  337         tpcb->tp_class = class_to_use;
  338         tpcb->tp_netservice = netservice;
  339 
  340 
  341         ASSERT(fname != 0);     /* just checking */
  342         if (fname) {
  343                 /*
  344                  *      tp_route_to takes its address argument in the form of an mbuf.
  345                  */
  346                 struct mbuf    *m;
  347                 int             err;
  348 
  349                 MGET(m, M_DONTWAIT, MT_SONAME); /* mbuf type used is
  350                                                  * confusing */
  351                 if (m) {
  352                         /*
  353                          * this seems a bit grotesque, but tp_route_to expects
  354                          * an mbuf * instead of simply a sockaddr; it calls the ll
  355                          * pcb_connect, which expects the name/addr in an mbuf as well.
  356                          * sigh.
  357                          */
  358                         bcopy((caddr_t) fname, mtod(m, caddr_t), fname->sa_len);
  359                         m->m_len = fname->sa_len;
  360 
  361                         /*
  362                          * grot  : have to say the kernel can override params
  363                          * in the passive open case
  364                          */
  365                         tpcb->tp_dont_change_params = 0;
  366                         err = tp_route_to(m, tpcb, cons_channel);
  367                         m_free(m);
  368 
  369                         if (!err)
  370                                 goto ok;
  371                 }
  372 #ifdef ARGO_DEBUG
  373                 if (argo_debug[D_CONN]) {
  374                         printf("tp_route_to FAILED! detaching tpcb %p, so %p\n",
  375                                tpcb, so);
  376                 }
  377 #endif
  378                 (void) tp_detach(tpcb);
  379                 return 0;
  380         }
  381 ok:
  382 #ifdef ARGO_DEBUG
  383         if (argo_debug[D_TPINPUT]) {
  384                 printf("tp_newsocket returning so %p, sototpcb(so) %p\n",
  385                        so, sototpcb(so));
  386         }
  387 #endif
  388         return so;
  389 }
  390 
  391 /*
  392  * NAME:        tp_input()
  393  *
  394  * CALLED FROM: net layer input routine
  395  *
  396  * FUNCTION and ARGUMENTS: Process an incoming TPDU (m), finding the associated
  397  * tpcb if there is one. Create the appropriate type of event and call the
  398  * driver. (faddr) and (laddr) are the foreign and local addresses.
  399  *
  400  * When tp_input() is called we KNOW that the ENTIRE TP HEADER has been
  401  * m_pullup-ed.
  402  *
  403  * RETURN VALUE: Nada
  404  *
  405  * SIDE EFFECTS: When using COSNS it may affect the state of the net-level pcb
  406  *
  407  * NOTE: The initial value of acktime is 2 so that we will never have a 0 value
  408  * for tp_peer_acktime.  It gets used in the computation of the
  409  * retransmission timer value, and so it mustn't be zero. 2 seems like a
  410  * reasonable minimum.
  411  */
  412 void
  413 tp_input(struct mbuf *m, ...)
  414 {
  415         struct sockaddr *faddr, *laddr; /* NSAP addresses */
  416         caddr_t         cons_channel;
  417         int             (*dgout_routine) (struct mbuf *, ...);
  418         int             ce_bit;
  419         struct tp_pcb *tpcb;
  420         struct tpdu *hdr;
  421         struct socket  *so;
  422         struct tp_event e;
  423         int             error;
  424         unsigned        dutype;
  425         u_short         dref, sref, acktime, subseq;
  426         u_char          preferred_class, class_to_use, pdusize;
  427         u_char          opt, dusize, addlopt, myversion = 0;
  428 #ifdef TP_PERF_MEAS
  429         u_char          perf_meas;
  430 #endif                          /* TP_PERF_MEAS */
  431         u_char          fsufxlen, lsufxlen;
  432         caddr_t         fsufxloc, lsufxloc;
  433         int             tpdu_len;
  434         u_int           takes_data;
  435         u_int           fcc_present;
  436         int             errlen;
  437         struct tp_conn_param tpp;
  438         va_list         ap;
  439 
  440         va_start(ap, m);
  441         faddr = va_arg(ap, struct sockaddr *);
  442         laddr = va_arg(ap, struct sockaddr *);
  443         cons_channel = va_arg(ap, caddr_t);
  444         /* XXX: Does va_arg does not work for function ptrs */
  445         dgout_routine = (int (*)(struct mbuf *, ...)) va_arg(ap, void *);
  446         ce_bit = va_arg(ap, int);
  447         va_end(ap);
  448 
  449 again:
  450         hdr = mtod(m, struct tpdu *);
  451         tpcb = 0;
  452         error = errlen = tpdu_len = 0;
  453         takes_data = fcc_present = FALSE;
  454         acktime = 2;
  455         sref = subseq = 0;
  456         fsufxloc = lsufxloc = NULL;
  457         fsufxlen = lsufxlen =
  458                 preferred_class = class_to_use = pdusize = addlopt = 0;
  459         dusize = TP_DFL_TPDUSIZE;
  460 #ifdef TP_PERF_MEAS
  461         GET_CUR_TIME(&e.e_time);
  462         perf_meas = 0;
  463 #endif                          /* TP_PERF_MEAS */
  464 
  465 #ifdef ARGO_DEBUG
  466         if (argo_debug[D_TPINPUT]) {
  467                 printf("tp_input(%p, ... %p)\n", m, cons_channel);
  468         }
  469 #endif
  470 
  471 
  472         /*
  473          * get the actual tpdu length - necessary for monitoring and for
  474          * checksumming
  475          *
  476          * Also, maybe measure the mbuf chain lengths and sizes.
  477          */
  478 
  479         {
  480                 struct mbuf *n = m;
  481 #ifdef ARGO_DEBUG
  482                 int             chain_length = 0;
  483 #endif                          /* ARGO_DEBUG */
  484 
  485                 for (;;) {
  486                         tpdu_len += n->m_len;
  487 #ifdef ARGO_DEBUG
  488                         if (argo_debug[D_MBUF_MEAS]) {
  489                                 if (n->m_flags & M_EXT) {
  490                                         IncStat(ts_mb_cluster);
  491                                 } else {
  492                                         IncStat(ts_mb_small);
  493                                 }
  494                                 chain_length++;
  495                         }
  496 #endif
  497                         if (n->m_next == NULL) {
  498                                 break;
  499                         }
  500                         n = n->m_next;
  501                 }
  502 #ifdef ARGO_DEBUG
  503                 if (argo_debug[D_MBUF_MEAS]) {
  504                         if (chain_length > 16)
  505                                 chain_length = 0;       /* zero used for
  506                                                          * anything > 16 */
  507                         tp_stat.ts_mb_len_distr[chain_length]++;
  508                 }
  509 #endif
  510         }
  511 #ifdef TPPT
  512         if (tp_traceflags[D_TPINPUT]) {
  513                 tptraceTPCB(TPPTtpduin, hdr->tpdu_type, hdr, hdr->tpdu_li + 1,
  514                             tpdu_len, 0);
  515         }
  516 #endif
  517 
  518                 dref = ntohs((short) hdr->tpdu_dref);
  519         sref = ntohs((short) hdr->tpdu_sref);
  520         dutype = (int) hdr->tpdu_type;
  521 
  522 #ifdef ARGO_DEBUG
  523         if (argo_debug[D_TPINPUT]) {
  524                 printf("input: dutype 0x%x cons_channel %p dref 0x%x\n",
  525                     dutype, cons_channel, dref);
  526                 printf("input: dref 0x%x sref 0x%x\n", dref, sref);
  527         }
  528 #endif
  529 #ifdef TPPT
  530         if (tp_traceflags[D_TPINPUT]) {
  531                 tptrace(TPPTmisc, "channel dutype dref ",
  532                         cons_channel, dutype, dref, 0);
  533         }
  534 #endif
  535 
  536 
  537 #ifdef ARGO_DEBUG
  538         if ((dutype < TP_MIN_TPDUTYPE) || (dutype > TP_MAX_TPDUTYPE)) {
  539                 printf("BAD dutype! 0x%x, channel %p dref 0x%x\n",
  540                        dutype, cons_channel, dref);
  541                 dump_buf(m, sizeof(struct mbuf));
  542 
  543                 IncStat(ts_inv_dutype);
  544                 goto discard;
  545         }
  546 #endif                          /* ARGO_DEBUG */
  547 
  548         CHECK((dutype < TP_MIN_TPDUTYPE || dutype > TP_MAX_TPDUTYPE),
  549               E_TP_INV_TPDU, ts_inv_dutype, respond,
  550               2);
  551         /*
  552          * unfortunately we can't take the address of the tpdu_type field,
  553          * since it's a bit field - so we just use the constant offset 2
  554          */
  555 
  556         /*
  557          * Now this isn't very neat but since you locate a pcb one way at the
  558          * beginning of connection establishment, and by the dref for each
  559          * tpdu after that, we have to treat CRs differently
  560          */
  561         if (dutype == CR_TPDU_type) {
  562                 u_char          alt_classes = 0;
  563 
  564                 preferred_class = 1 << hdr->tpdu_CRclass;
  565                 opt = hdr->tpdu_CRoptions;
  566 
  567                 WHILE_OPTIONS(P, hdr, 1)        /* { */
  568                         switch (vbptr(P)->tpv_code) {
  569 
  570                 case TPP_tpdu_size:
  571                         vb_getval(P, u_char, dusize);
  572 #ifdef ARGO_DEBUG
  573                         if (argo_debug[D_TPINPUT]) {
  574                                 printf("CR dusize 0x%x\n", dusize);
  575                         }
  576 #endif
  577                         /* COS tests: NBS IA (Dec. 1987) Sec. 4.5.2.1 */
  578                         if (dusize < TP_MIN_TPDUSIZE || dusize > TP_MAX_TPDUSIZE)
  579                                 dusize = TP_DFL_TPDUSIZE;
  580                         break;
  581                 case TPP_ptpdu_size:
  582                         switch (vbptr(P)->tpv_len) {
  583                         case 1:
  584                                 pdusize = vbval(P, u_char);
  585                                 break;
  586                         case 2:
  587                                 pdusize = ntohs(vbval(P, u_short));
  588                                 break;
  589                         default:;
  590 #ifdef ARGO_DEBUG
  591                                 if (argo_debug[D_TPINPUT]) {
  592                                         printf("malformed prefered TPDU option\n");
  593                                 }
  594 #endif
  595                         }
  596                         break;
  597                 case TPP_addl_opt:
  598                         vb_getval(P, u_char, addlopt);
  599                         break;
  600                 case TPP_calling_sufx:
  601                         /*
  602                          * could use vb_getval, but we want to save the loc &
  603                          * len for later use
  604                          */
  605                         fsufxloc = (caddr_t) & vbptr(P)->tpv_val;
  606                         fsufxlen = vbptr(P)->tpv_len;
  607 #ifdef ARGO_DEBUG
  608                         if (argo_debug[D_TPINPUT]) {
  609                                 printf("CR fsufx:");
  610                                 {
  611                                         int    j;
  612                                         for (j = 0; j < fsufxlen; j++) {
  613                                                 printf(" 0x%x. ", *((caddr_t) (fsufxloc + j)));
  614                                         }
  615                                         printf("\n");
  616                                 }
  617                         }
  618 #endif
  619                         break;
  620                 case TPP_called_sufx:
  621                         /*
  622                          * could use vb_getval, but we want to save the loc &
  623                          * len for later use
  624                          */
  625                         lsufxloc = (caddr_t) & vbptr(P)->tpv_val;
  626                         lsufxlen = vbptr(P)->tpv_len;
  627 #ifdef ARGO_DEBUG
  628                         if (argo_debug[D_TPINPUT]) {
  629                                 printf("CR lsufx:");
  630                                 {
  631                                         int    j;
  632                                         for (j = 0; j < lsufxlen; j++) {
  633                                                 printf(" 0x%x. ", *((u_char *) (lsufxloc + j)));
  634                                         }
  635                                         printf("\n");
  636                                 }
  637                         }
  638 #endif
  639                         break;
  640 
  641 #ifdef TP_PERF_MEAS
  642                 case TPP_perf_meas:
  643                         vb_getval(P, u_char, perf_meas);
  644                         break;
  645 #endif                          /* TP_PERF_MEAS */
  646 
  647                 case TPP_vers:
  648                         /* not in class 0; 1 octet; in CR_TPDU only */
  649                         /*
  650                          * COS tests says if version wrong, use default
  651                          * version!?XXX
  652                          */
  653                         CHECK((vbval(P, u_char) != TP_VERSION),
  654                               E_TP_INV_PVAL, ts_inv_pval, setversion,
  655                         (1 + (caddr_t) & vbptr(P)->tpv_val - (caddr_t) hdr));
  656         setversion:
  657                         myversion = vbval(P, u_char);
  658                         break;
  659                 case TPP_acktime:
  660                         vb_getval(P, u_short, acktime);
  661                         acktime = ntohs(acktime);
  662                         acktime = acktime / 500;        /* convert to slowtimo
  663                                                          * ticks */
  664                         if ((short) acktime <= 0)
  665                                 acktime = 2;    /* don't allow a bad peer to
  666                                                  * screw us up */
  667 #ifdef ARGO_DEBUG
  668                         if (argo_debug[D_TPINPUT]) {
  669                                 printf("CR acktime 0x%x\n", acktime);
  670                         }
  671 #endif
  672                         break;
  673 
  674                 case TPP_alt_class:
  675                         {
  676                                 u_char         *aclass = 0;
  677                                 int    i;
  678                                 static u_char   bad_alt_classes[5] =
  679                                 {~0, ~3, ~5, ~0xf, ~0x1f};
  680 
  681                                 aclass =
  682                                         (u_char *) & (((struct tp_vbp *) P)->tpv_val);
  683                                 for (i = ((struct tp_vbp *) P)->tpv_len; i > 0; i--) {
  684                                         alt_classes |= (1 << ((*aclass++) >> 4));
  685                                 }
  686                                 CHECK((bad_alt_classes[hdr->tpdu_CRclass] & alt_classes),
  687                                       E_TP_INV_PVAL, ts_inv_aclass, respond,
  688                                       ((caddr_t) aclass) - (caddr_t) hdr);
  689 #ifdef ARGO_DEBUG
  690                                 if (argo_debug[D_TPINPUT]) {
  691                                         printf("alt_classes 0x%x\n", alt_classes);
  692                                 }
  693 #endif
  694                         }
  695                         break;
  696 
  697                 case TPP_security:
  698                 case TPP_residER:
  699                 case TPP_priority:
  700                 case TPP_transdelay:
  701                 case TPP_throughput:
  702                 case TPP_addl_info:
  703                 case TPP_subseq:
  704                 default:
  705 #ifdef ARGO_DEBUG
  706                         if (argo_debug[D_TPINPUT]) {
  707                                 printf("param ignored CR_TPDU code= 0x%x\n",
  708                                        vbptr(P)->tpv_code);
  709                         }
  710 #endif
  711                         IncStat(ts_param_ignored);
  712                         break;
  713 
  714                 case TPP_checksum:
  715 #ifdef ARGO_DEBUG
  716                         if (argo_debug[D_TPINPUT]) {
  717                                 printf("CR before cksum\n");
  718                         }
  719 #endif
  720 
  721                         CHECK(iso_check_csum(m, tpdu_len),
  722                               E_TP_INV_PVAL, ts_bad_csum, discard, 0)
  723 #ifdef ARGO_DEBUG
  724                                 if (argo_debug[D_TPINPUT]) {
  725                                 printf("CR before cksum\n");
  726                         }
  727 #endif
  728                         break;
  729                 }
  730 
  731                  /* } */ END_WHILE_OPTIONS(P)
  732                         if (lsufxlen == 0) {
  733                         /* can't look for a tpcb w/o any called sufx */
  734                         error = E_TP_LENGTH_INVAL;
  735                         IncStat(ts_inv_sufx);
  736                         goto respond;
  737                 } else {
  738                         struct tp_pcb *t;
  739                         /*
  740                          * The intention here is to trap all CR requests
  741                          * to a given nsap, for constructing transport
  742                          * service bridges at user level; so these
  743                          * intercepts should precede the normal listens.
  744                          * Phrasing the logic in this way also allows for
  745                          * mop-up listeners, which we don't currently implement.
  746                          * We also wish to have a single socket be able to
  747                          * listen over any network service provider,
  748                          * (cons or clns or ip).
  749                          */
  750                         for (t = tp_listeners; t; t = t->tp_nextlisten)
  751                                 if ((t->tp_lsuffixlen == 0 ||
  752                                      (lsufxlen == t->tp_lsuffixlen &&
  753                                       bcmp(lsufxloc, t->tp_lsuffix, lsufxlen) == 0)) &&
  754                                     ((t->tp_flags & TPF_GENERAL_ADDR) ||
  755                                      (laddr->sa_family == t->tp_domain &&
  756                                       (*t->tp_nlproto->nlp_cmpnetaddr)
  757                                       (t->tp_npcb, laddr, TP_LOCAL))))
  758                                         break;
  759 
  760                         CHECK(t == 0, E_TP_NO_SESSION, ts_inv_sufx, respond,
  761                           (1 + 2 + (caddr_t) & hdr->_tpduf - (caddr_t) hdr))
  762                         /*
  763                          * _tpduf is the fixed part; add 2 to get the dref
  764                          * bits of the fixed part (can't take the address of
  765                          * a bit field)
  766                          */
  767 #ifdef ARGO_DEBUG
  768                                 if (argo_debug[D_TPINPUT]) {
  769                                 printf("checking if dup CR\n");
  770                         }
  771 #endif
  772                         tpcb = t;
  773                         for (t = tpcb->tp_next; t != tpcb; t = t->tp_next) {
  774                                 if (sref != t->tp_fref)
  775                                         continue;
  776                                 if ((*tpcb->tp_nlproto->nlp_cmpnetaddr) (
  777                                            t->tp_npcb, faddr, TP_FOREIGN)) {
  778 #ifdef ARGO_DEBUG
  779                                         if (argo_debug[D_TPINPUT]) {
  780                                                 printf("duplicate CR discarded\n");
  781                                         }
  782 #endif
  783                                         goto discard;
  784                                 }
  785                         }
  786 #ifdef TPPT
  787                 if (tp_traceflags[D_TPINPUT]) {
  788                                 tptrace(TPPTmisc, "tp_input: tpcb *lsufxloc tpstate",
  789                                         tpcb, *lsufxloc, tpcb->tp_state, 0);
  790                         }
  791 #endif
  792                 }
  793 
  794                 /*
  795                  * WE HAVE A TPCB already know that the classes in the CR
  796                  * match at least one class implemented, but we don't know
  797                  * yet if they include any classes permitted by this server.
  798                  */
  799 
  800 #ifdef ARGO_DEBUG
  801                 if (argo_debug[D_TPINPUT]) {
  802                         printf("HAVE A TPCB 1: %p\n", tpcb);
  803                 }
  804 #endif
  805 #ifdef ARGO_DEBUG
  806                 if (argo_debug[D_CONN]) {
  807                         printf(
  808                                "CR: bef CHKS: flags 0x%x class_to_use 0x%x alt 0x%x opt 0x%x tp_class 0x%x\n",
  809                                tpcb->tp_flags, class_to_use, alt_classes, opt, tpcb->tp_class);
  810                 }
  811 #endif
  812                 /* tpcb->tp_class doesn't include any classes not implemented  */
  813                 class_to_use = (preferred_class & tpcb->tp_class);
  814                 if ((class_to_use = preferred_class & tpcb->tp_class) == 0)
  815                         class_to_use = alt_classes & tpcb->tp_class;
  816 
  817                 class_to_use = 1 << tp_mask_to_num(class_to_use);
  818 
  819                 {
  820                         tpp = tpcb->_tp_param;
  821                         tpp.p_class = class_to_use;
  822                         tpp.p_tpdusize = dusize;
  823                         tpp.p_ptpdusize = pdusize;
  824                         tpp.p_xtd_format = (opt & TPO_XTD_FMT) == TPO_XTD_FMT;
  825                         tpp.p_xpd_service = (addlopt & TPAO_USE_TXPD) == TPAO_USE_TXPD;
  826                         tpp.p_use_checksum = (tpp.p_class == TP_CLASS_0) ? 0 :
  827                                 (addlopt & TPAO_NO_CSUM) == 0;
  828                         tpp.p_version = myversion;
  829 #ifdef notdef
  830                         tpp.p_use_efc = (opt & TPO_USE_EFC) == TPO_USE_EFC;
  831                         tpp.p_use_nxpd = (addlopt & TPAO_USE_NXPD) == TPAO_USE_NXPD;
  832                         tpp.p_use_rcc = (addlopt & TPAO_USE_RCC) == TPAO_USE_RCC;
  833 #endif                          /* notdef */
  834 
  835                         CHECK(
  836                               tp_consistency(tpcb, 0 /* not force or strict */ , &tpp) != 0,
  837                         E_TP_NEGOT_FAILED, ts_negotfailed, clear_parent_tcb,
  838                               (1 + 2 + (caddr_t) & hdr->_tpdufr.CRCC - (caddr_t) hdr)
  839                         /* ^ more or less the location of class */
  840                                 )
  841                 }
  842 #ifdef TPPT
  843                 if (tp_traceflags[D_CONN]) {
  844                         tptrace(TPPTmisc,
  845                        "after 1 consist class_to_use class, out, tpconsout",
  846                                 class_to_use,
  847                                 tpcb->tp_class, dgout_routine, tpcons_output
  848                         );
  849                 }
  850 #endif
  851                 CHECK(((class_to_use == TP_CLASS_0) &&
  852                       (dgout_routine != tpcons_output)),
  853                         E_TP_NEGOT_FAILED, ts_negotfailed, clear_parent_tcb,
  854                      (1 + 2 + (caddr_t) & hdr->_tpdufr.CRCC - (caddr_t) hdr)
  855                 /* ^ more or less the location of class */
  856                         )
  857 #ifdef ARGO_DEBUG
  858                         if (argo_debug[D_CONN]) {
  859                         printf("CR: after CRCCCHECKS: tpcb %p, flags 0x%x\n",
  860                                tpcb, tpcb->tp_flags);
  861                 }
  862 #endif
  863                 takes_data = TRUE;
  864                 e.TPDU_ATTR(CR).e_cdt = hdr->tpdu_CRcdt;
  865                 e.ev_number = CR_TPDU;
  866 
  867                 so = tpcb->tp_sock;
  868                 if (so->so_options & SO_ACCEPTCONN) {
  869                         struct tp_pcb  *parent_tpcb = tpcb;
  870                         /*
  871                          * Create a socket, tpcb, ll pcb, etc. for this
  872                          * newborn connection, and fill in all the values.
  873                          */
  874 #ifdef ARGO_DEBUG
  875                         if (argo_debug[D_CONN]) {
  876                                 printf("abt to call tp_newsocket(%p, %p, %p, %p)\n",
  877                                        so, laddr, faddr, cons_channel);
  878                         }
  879 #endif
  880                         if ((so =
  881                              tp_newsocket(so, faddr, cons_channel,
  882                                           class_to_use,
  883                                ((tpcb->tp_netservice == IN_CLNS) ? IN_CLNS :
  884                                 (dgout_routine == tpcons_output) ? ISO_CONS : ISO_CLNS))
  885                              ) == (struct socket *) 0) {
  886                                 /*
  887                                  * note - even if netservice is IN_CLNS, as
  888                                  * far as the tp entity is concerned, the
  889                                  * only differences are CO vs CL
  890                                  */
  891 #ifdef ARGO_DEBUG
  892                                 if (argo_debug[D_CONN]) {
  893                                         printf("tp_newsocket returns 0\n");
  894                                 }
  895 #endif
  896                                 goto discard;
  897                 clear_parent_tcb:
  898                                 tpcb = 0;
  899                                 goto respond;
  900                         }
  901                         tpcb = sototpcb(so);
  902                         insque(tpcb, parent_tpcb);
  903 
  904                         /*
  905                          * Stash the addresses in the net level pcb
  906                          * kind of like a pcbconnect() but don't need
  907                          * or want all those checks.
  908                          */
  909                         (tpcb->tp_nlproto->nlp_putnetaddr) (tpcb->tp_npcb, faddr, TP_FOREIGN);
  910                         (tpcb->tp_nlproto->nlp_putnetaddr) (tpcb->tp_npcb, laddr, TP_LOCAL);
  911 
  912                         /* stash the f suffix in the new tpcb */
  913                         if ((tpcb->tp_fsuffixlen = fsufxlen) != 0) {
  914                                 bcopy(fsufxloc, tpcb->tp_fsuffix, fsufxlen);
  915                                 (tpcb->tp_nlproto->nlp_putsufx)
  916                                         (tpcb->tp_npcb, fsufxloc, fsufxlen, TP_FOREIGN);
  917                         }
  918                         /* stash the l suffix in the new tpcb */
  919                         tpcb->tp_lsuffixlen = lsufxlen;
  920                         bcopy(lsufxloc, tpcb->tp_lsuffix, lsufxlen);
  921                         (tpcb->tp_nlproto->nlp_putsufx)
  922                                 (tpcb->tp_npcb, lsufxloc, lsufxlen, TP_LOCAL);
  923 #ifdef TP_PERF_MEAS
  924                         if (tpcb->tp_perf_on = perf_meas) {     /* assignment */
  925                                 /*
  926                                  * ok, let's create an mbuf for stashing the
  927                                  * statistics if one doesn't already exist
  928                                  */
  929                                 (void) tp_setup_perf(tpcb);
  930                         }
  931 #endif                          /* TP_PERF_MEAS */
  932                         tpcb->tp_fref = sref;
  933 
  934                         /*
  935                          * We've already checked for consistency with the
  936                          * options set in tpp,  but we couldn't set them
  937                          * earlier because we didn't want to change options
  938                          * in the LISTENING tpcb. Now we set the options in
  939                          * the new socket's tpcb.
  940                          */
  941                         (void) tp_consistency(tpcb, TP_FORCE, &tpp);
  942 
  943                         if (!tpcb->tp_use_checksum)
  944                                 IncStat(ts_csum_off);
  945                         if (tpcb->tp_xpd_service)
  946                                 IncStat(ts_use_txpd);
  947                         if (tpcb->tp_xtd_format)
  948                                 IncStat(ts_xtd_fmt);
  949 
  950                         tpcb->tp_peer_acktime = acktime;
  951 
  952                         /*
  953                          * The following kludge is used to test
  954                          * retransmissions and timeout during connection
  955                          * establishment.
  956                          */
  957 #ifdef ARGO_DEBUG
  958                         if (argo_debug[D_ZDREF]) {
  959                                 IncStat(ts_zdebug);
  960                                 /* tpcb->tp_fref = 0; */
  961                         }
  962 #endif
  963                 }
  964                 LOCAL_CREDIT(tpcb);
  965                 IncStat(ts_CR_rcvd);
  966                 if (!tpcb->tp_cebit_off) {
  967                         tpcb->tp_win_recv = tp_start_win << 8;
  968                         tpcb->tp_cong_sample.cs_size = 0;
  969                         CONG_INIT_SAMPLE(tpcb);
  970                         CONG_UPDATE_SAMPLE(tpcb, ce_bit);
  971                 }
  972         } else if (dutype == ER_TPDU_type) {
  973                 /*
  974                  * ER TPDUs have to be recognized separately because they
  975                  * don't necessarily have a tpcb with them and we don't want
  976                  * err out looking for such a beast. We could put a bunch of
  977                  * little kludges in the next section of code so it would
  978                  * avoid references to tpcb if dutype == ER_TPDU_type but we
  979                  * don't want code for ERs to mess up code for data transfer.
  980                  */
  981                 IncStat(ts_ER_rcvd);
  982                 e.ev_number = ER_TPDU;
  983                 e.TPDU_ATTR(ER).e_reason = (u_char) hdr->tpdu_ERreason;
  984                 CHECK(((int) dref <= 0 || dref >= tp_refinfo.tpr_size ||
  985                      (tpcb = tp_ref[dref].tpr_pcb) == (struct tp_pcb *) 0 ||
  986                        tpcb->tp_refstate == REF_FREE ||
  987                        tpcb->tp_refstate == REF_FROZEN),
  988                       E_TP_MISM_REFS, ts_inv_dref, discard, 0)
  989         } else {
  990                 /* tpdu type is CC, XPD, XAK, GR, AK, DR, DC, or DT */
  991 
  992                 /*
  993                  * In the next 4 checks, _tpduf is the fixed part; add 2 to
  994                  * get the dref bits of the fixed part (can't take the
  995                  * address of a bit field)
  996                  */
  997 #ifdef TPCONS
  998                 if (cons_channel && dutype == DT_TPDU_type) {
  999                         struct isopcb  *isop = ((struct isopcb *)
 1000                                ((struct pklcd *) cons_channel)->lcd_upnext);
 1001                         if (isop && isop->isop_refcnt == 1 && isop->isop_socket &&
 1002                             (tpcb = sototpcb(isop->isop_socket)) &&
 1003                             (tpcb->tp_class == TP_CLASS_0 /* || == CLASS_1 */ )) {
 1004 #ifdef ARGO_DEBUG
 1005                                 if (argo_debug[D_TPINPUT]) {
 1006                                         printf("tpinput_dt: class 0 short circuit\n");
 1007                                 }
 1008 #endif
 1009                                 dref = tpcb->tp_lref;
 1010                                 sref = tpcb->tp_fref;
 1011                                 CHECK((tpcb->tp_refstate == REF_FREE),
 1012                                       E_TP_MISM_REFS, ts_inv_dref, nonx_dref,
 1013                                       (1 + 2 + (caddr_t) & hdr->_tpduf - (caddr_t) hdr))
 1014                                         goto tp0_data;
 1015                         }
 1016                 }
 1017 #endif
 1018                 {
 1019 
 1020                         CHECK(((int) dref <= 0 || dref >= tp_refinfo.tpr_size),
 1021                               E_TP_MISM_REFS, ts_inv_dref, nonx_dref,
 1022                           (1 + 2 + (caddr_t) & hdr->_tpduf - (caddr_t) hdr))
 1023                                 CHECK(((tpcb = tp_ref[dref].tpr_pcb) == (struct tp_pcb *) 0),
 1024                                       E_TP_MISM_REFS, ts_inv_dref, nonx_dref,
 1025                           (1 + 2 + (caddr_t) & hdr->_tpduf - (caddr_t) hdr))
 1026                                 CHECK((tpcb->tp_refstate == REF_FREE),
 1027                                       E_TP_MISM_REFS, ts_inv_dref, nonx_dref,
 1028                           (1 + 2 + (caddr_t) & hdr->_tpduf - (caddr_t) hdr))
 1029                 }
 1030 
 1031 #ifdef ARGO_DEBUG
 1032                 if (argo_debug[D_TPINPUT]) {
 1033                         printf("HAVE A TPCB 2: %p\n", tpcb);
 1034                 }
 1035 #endif
 1036 
 1037                 /* causes a DR to be sent for CC; ER for all else */
 1038                 CHECK((tpcb->tp_refstate == REF_FROZEN),
 1039                 (dutype == CC_TPDU_type ? E_TP_NO_SESSION : E_TP_MISM_REFS),
 1040                       ts_inv_dref, respond,
 1041                       (1 + 2 + (caddr_t) & hdr->_tpduf - (caddr_t) hdr))
 1042 #ifdef ARGO_DEBUG
 1043                 if (argo_debug[D_TPINPUT]) {
 1044                         printf("state of dref %d ok, tpcb %p\n", dref, tpcb);
 1045                 }
 1046 #endif
 1047                 /*
 1048                  * At this point the state of the dref could be FROZEN:
 1049                  * tpr_pcb == NULL,  has ( reference only) timers for
 1050                  * example, DC may arrive after the close() has detached the
 1051                  * tpcb (e.g., if user turned off SO_LISTEN option) OPENING :
 1052                  * a tpcb exists but no timers yet OPEN  : tpcb exists &
 1053                  * timers are outstanding
 1054                  */
 1055 
 1056                 if (!tpcb->tp_cebit_off)
 1057                         CONG_UPDATE_SAMPLE(tpcb, ce_bit);
 1058 
 1059                 dusize = tpcb->tp_tpdusize;
 1060                 pdusize = tpcb->tp_ptpdusize;
 1061 
 1062                 dutype = hdr->tpdu_type << 8;   /* for the switch below */
 1063 
 1064                 WHILE_OPTIONS(P, hdr, tpcb->tp_xtd_format)      /* { */
 1065 #define caseof(x,y) case (((x)<<8)+(y))
 1066                         switch (dutype | vbptr(P)->tpv_code) {
 1067 
 1068         caseof(CC_TPDU_type, TPP_addl_opt):
 1069                         /* not in class 0; 1 octet */
 1070                         vb_getval(P, u_char, addlopt);
 1071                         break;
 1072         caseof(CC_TPDU_type, TPP_tpdu_size):
 1073                         {
 1074                                 u_char          odusize = dusize;
 1075                                 vb_getval(P, u_char, dusize);
 1076                                 CHECK((dusize < TP_MIN_TPDUSIZE ||
 1077                                        dusize > TP_MAX_TPDUSIZE || dusize > odusize),
 1078                                       E_TP_INV_PVAL, ts_inv_pval, respond,
 1079                                       (1 + (caddr_t) & vbptr(P)->tpv_val - (caddr_t) hdr))
 1080 #ifdef ARGO_DEBUG
 1081                                         if (argo_debug[D_TPINPUT]) {
 1082                                         printf("CC dusize 0x%x\n", dusize);
 1083                                 }
 1084 #endif
 1085                         }
 1086                         break;
 1087         caseof(CC_TPDU_type, TPP_ptpdu_size):
 1088                         {
 1089                                 u_short         opdusize = pdusize;
 1090                                 switch (vbptr(P)->tpv_len) {
 1091                                 case 1:
 1092                                         pdusize = vbval(P, u_char);
 1093                                         break;
 1094                                 case 2:
 1095                                         pdusize = ntohs(vbval(P, u_short));
 1096                                         break;
 1097                                 default:;
 1098 #ifdef ARGO_DEBUG
 1099                                         if (argo_debug[D_TPINPUT]) {
 1100                                                 printf("malformed prefered TPDU option\n");
 1101                                         }
 1102 #endif
 1103                                 }
 1104                                 CHECK((pdusize == 0 ||
 1105                                        (opdusize && (pdusize > opdusize))),
 1106                                       E_TP_INV_PVAL, ts_inv_pval, respond,
 1107                                       (1 + (caddr_t) & vbptr(P)->tpv_val - (caddr_t) hdr))
 1108                         }
 1109                         break;
 1110         caseof(CC_TPDU_type, TPP_calling_sufx):
 1111 #ifdef ARGO_DEBUG
 1112                         if (argo_debug[D_TPINPUT]) {
 1113                                 printf("CC calling (local) sufxlen 0x%x\n", lsufxlen);
 1114                         }
 1115 #endif
 1116                         lsufxloc = (caddr_t) & vbptr(P)->tpv_val;
 1117                         lsufxlen = vbptr(P)->tpv_len;
 1118                         break;
 1119         caseof(CC_TPDU_type, TPP_acktime):
 1120                         /* class 4 only, 2 octets */
 1121                         vb_getval(P, u_short, acktime);
 1122                         acktime = ntohs(acktime);
 1123                         acktime = acktime / 500;        /* convert to slowtimo
 1124                                                          * ticks */
 1125                         if ((short) acktime <= 0)
 1126                                 acktime = 2;
 1127                         break;
 1128         caseof(CC_TPDU_type, TPP_called_sufx):
 1129                         fsufxloc = (caddr_t) & vbptr(P)->tpv_val;
 1130                         fsufxlen = vbptr(P)->tpv_len;
 1131 #ifdef ARGO_DEBUG
 1132                         if (argo_debug[D_TPINPUT]) {
 1133                                 printf("CC called (foreign) sufx len %d\n", fsufxlen);
 1134                         }
 1135 #endif
 1136                         break;
 1137 
 1138         caseof(CC_TPDU_type, TPP_checksum):
 1139         caseof(DR_TPDU_type, TPP_checksum):
 1140         caseof(DT_TPDU_type, TPP_checksum):
 1141         caseof(XPD_TPDU_type, TPP_checksum):
 1142                         if (tpcb->tp_use_checksum) {
 1143                                 CHECK(iso_check_csum(m, tpdu_len),
 1144                                       E_TP_INV_PVAL, ts_bad_csum, discard, 0)
 1145                         }
 1146                         break;
 1147 
 1148                         /*
 1149                          * this is different from the above because in the
 1150                          * context of concat/ sep tpdu_len might not be the
 1151                          * same as hdr len
 1152                          */
 1153         caseof(AK_TPDU_type, TPP_checksum):
 1154         caseof(XAK_TPDU_type, TPP_checksum):
 1155         caseof(DC_TPDU_type, TPP_checksum):
 1156                         if (tpcb->tp_use_checksum) {
 1157                                 CHECK(iso_check_csum(m, (int) hdr->tpdu_li + 1),
 1158                                       E_TP_INV_PVAL, ts_bad_csum, discard, 0)
 1159                         }
 1160                         break;
 1161 #ifdef notdef
 1162         caseof(DR_TPDU_type, TPP_addl_info):
 1163                         /*
 1164                          * ignore - its length and meaning are user defined
 1165                          * and there's no way to pass this info to the user
 1166                          * anyway
 1167                          */
 1168                         break;
 1169 #endif                          /* notdef */
 1170 
 1171         caseof(AK_TPDU_type, TPP_subseq):
 1172                         /* used after reduction of window */
 1173                         vb_getval(P, u_short, subseq);
 1174                         subseq = ntohs(subseq);
 1175 #ifdef ARGO_DEBUG
 1176                         if (argo_debug[D_ACKRECV]) {
 1177                                 printf("AK dref 0x%x Subseq 0x%x\n", dref, subseq);
 1178                         }
 1179 #endif
 1180                         break;
 1181 
 1182         caseof(AK_TPDU_type, TPP_flow_cntl_conf):
 1183                         {
 1184                                 u_int           ylwe;
 1185                                 u_short         ysubseq, ycredit;
 1186 
 1187                                 fcc_present = TRUE;
 1188                                 vb_getval(P, u_int, ylwe);
 1189                                 vb_getval(P, u_short, ysubseq);
 1190                                 vb_getval(P, u_short, ycredit);
 1191                                 ylwe = ntohl(ylwe);
 1192                                 ysubseq = ntohs(ysubseq);
 1193                                 ycredit = ntohs(ycredit);
 1194 #ifdef ARGO_DEBUG
 1195                                 if (argo_debug[D_ACKRECV]) {
 1196                                         printf("%s%x, subseq 0x%x, cdt 0x%x dref 0x%x\n",
 1197                                                "AK FCC lwe 0x", ylwe, ysubseq, ycredit, dref);
 1198                                 }
 1199 #endif
 1200                         }
 1201                         break;
 1202 
 1203                 default:
 1204 #ifdef ARGO_DEBUG
 1205                         if (argo_debug[D_TPINPUT]) {
 1206                                 printf("param ignored dutype 0x%x, code  0x%x\n",
 1207                                        dutype, vbptr(P)->tpv_code);
 1208                         }
 1209 #endif
 1210 #ifdef TPPT
 1211                         if (tp_traceflags[D_TPINPUT]) {
 1212                                 tptrace(TPPTmisc, "param ignored dutype code ",
 1213                                         dutype, vbptr(P)->tpv_code, 0, 0);
 1214                         }
 1215 #endif
 1216                         IncStat(ts_param_ignored);
 1217                         break;
 1218 #undef caseof
 1219                 }
 1220                  /* } */ END_WHILE_OPTIONS(P)
 1221                 /* NOTE: the variable dutype has been shifted left! */
 1222 
 1223                         switch (hdr->tpdu_type) {
 1224                 case CC_TPDU_type:
 1225                         /*
 1226                          * If CC comes back with an unacceptable class
 1227                          * respond with a DR or ER
 1228                          */
 1229 
 1230                         opt = hdr->tpdu_CCoptions;      /* 1 byte */
 1231 
 1232                         {
 1233                                 tpp = tpcb->_tp_param;
 1234                                 tpp.p_class = (1 << hdr->tpdu_CCclass);
 1235                                 tpp.p_tpdusize = dusize;
 1236                                 tpp.p_ptpdusize = pdusize;
 1237                                 tpp.p_dont_change_params = 0;
 1238                                 tpp.p_xtd_format = (opt & TPO_XTD_FMT) == TPO_XTD_FMT;
 1239                                 tpp.p_xpd_service = (addlopt & TPAO_USE_TXPD) == TPAO_USE_TXPD;
 1240                                 tpp.p_use_checksum = (addlopt & TPAO_NO_CSUM) == 0;
 1241 #ifdef notdef
 1242                                 tpp.p_use_efc = (opt & TPO_USE_EFC) == TPO_USE_EFC;
 1243                                 tpp.p_use_nxpd = (addlopt & TPAO_USE_NXPD) == TPAO_USE_NXPD;
 1244                                 tpp.p_use_rcc = (addlopt & TPAO_USE_RCC) == TPAO_USE_RCC;
 1245 #endif                          /* notdef */
 1246 
 1247                                 CHECK(
 1248                                   tp_consistency(tpcb, TP_FORCE, &tpp) != 0,
 1249                                  E_TP_NEGOT_FAILED, ts_negotfailed, respond,
 1250                                       (1 + 2 + (caddr_t) & hdr->_tpdufr.CRCC - (caddr_t) hdr)
 1251                                 /* ^ more or less the location of class */
 1252                                         )
 1253 #ifdef TPPT
 1254                                         if (tp_traceflags[D_CONN]) {
 1255                                         tptrace(TPPTmisc,
 1256                                     "after 1 consist class, out, tpconsout",
 1257                                                 tpcb->tp_class, dgout_routine, tpcons_output, 0
 1258                                         );
 1259                                 }
 1260 #endif
 1261                                         CHECK(
 1262                                             ((class_to_use == TP_CLASS_0) &&
 1263                                           (dgout_routine != tpcons_output)),
 1264                                  E_TP_NEGOT_FAILED, ts_negotfailed, respond,
 1265                                               (1 + 2 + (caddr_t) & hdr->_tpdufr.CRCC - (caddr_t) hdr)
 1266                                 /* ^ more or less the location of class */
 1267                                         )
 1268 #ifdef TPCONS
 1269                                         if (tpcb->tp_netservice == ISO_CONS &&
 1270                                             class_to_use == TP_CLASS_0) {
 1271                                         struct isopcb  *isop = (struct isopcb *) tpcb->tp_npcb;
 1272                                         struct pklcd   *lcp = (struct pklcd *) isop->isop_chan;
 1273                                         lcp->lcd_flags &= ~X25_DG_CIRCUIT;
 1274                                 }
 1275 #endif
 1276                         }
 1277                         if (!tpcb->tp_use_checksum)
 1278                                 IncStat(ts_csum_off);
 1279                         if (tpcb->tp_xpd_service)
 1280                                 IncStat(ts_use_txpd);
 1281                         if (tpcb->tp_xtd_format)
 1282                                 IncStat(ts_xtd_fmt);
 1283 
 1284 #ifdef TPPT
 1285                         if (tp_traceflags[D_CONN]) {
 1286                                 tptrace(TPPTmisc, "after CC class flags dusize CCclass",
 1287                           tpcb->tp_class, tpcb->tp_flags, tpcb->tp_tpdusize,
 1288                                         hdr->tpdu_CCclass);
 1289                         }
 1290 #endif
 1291 
 1292                         /*
 1293                          * if called or calling suffixes appeared on the CC,
 1294                          * they'd better jive with what's in the pcb
 1295                          */
 1296                                 if (fsufxlen) {
 1297                                 CHECK(((tpcb->tp_fsuffixlen != fsufxlen) ||
 1298                                 bcmp(fsufxloc, tpcb->tp_fsuffix, fsufxlen)),
 1299                                       E_TP_INV_PVAL, ts_inv_sufx, respond,
 1300                                       (1 + fsufxloc - (caddr_t) hdr))
 1301                         }
 1302                         if (lsufxlen) {
 1303                                 CHECK(((tpcb->tp_lsuffixlen != lsufxlen) ||
 1304                                 bcmp(lsufxloc, tpcb->tp_lsuffix, lsufxlen)),
 1305                                       E_TP_INV_PVAL, ts_inv_sufx, respond,
 1306                                       (1 + lsufxloc - (caddr_t) hdr))
 1307                         }
 1308                         e.TPDU_ATTR(CC).e_sref = sref;
 1309                         e.TPDU_ATTR(CC).e_cdt = hdr->tpdu_CCcdt;
 1310                         takes_data = TRUE;
 1311                         e.ev_number = CC_TPDU;
 1312                         IncStat(ts_CC_rcvd);
 1313                         break;
 1314 
 1315                 case DC_TPDU_type:
 1316                         if (sref != tpcb->tp_fref)
 1317                                 printf("INPUT: inv sufx DCsref 0x%x, tp_fref 0x%x\n",
 1318                                        sref, tpcb->tp_fref);
 1319 
 1320                         CHECK((sref != tpcb->tp_fref),
 1321                               E_TP_MISM_REFS, ts_inv_sufx, discard,
 1322                          (1 + (caddr_t) & hdr->tpdu_DCsref - (caddr_t) hdr))
 1323                                 e.ev_number = DC_TPDU;
 1324                         IncStat(ts_DC_rcvd);
 1325                         break;
 1326 
 1327                 case DR_TPDU_type:
 1328 #ifdef TPPT
 1329                         if (tp_traceflags[D_TPINPUT]) {
 1330                                 tptrace(TPPTmisc, "DR recvd", hdr->tpdu_DRreason, 0, 0, 0);
 1331                         }
 1332 #endif
 1333                                 if (sref != tpcb->tp_fref) {
 1334                                 printf("INPUT: inv sufx DRsref 0x%x tp_fref 0x%x\n",
 1335                                        sref, tpcb->tp_fref);
 1336                         }
 1337                         CHECK((sref != 0 && sref != tpcb->tp_fref &&
 1338                                tpcb->tp_state != TP_CRSENT),
 1339                               (TP_ERROR_SNDC | E_TP_MISM_REFS), ts_inv_sufx, respond,
 1340                          (1 + (caddr_t) & hdr->tpdu_DRsref - (caddr_t) hdr))
 1341                                 e.TPDU_ATTR(DR).e_reason = hdr->tpdu_DRreason;
 1342                         e.TPDU_ATTR(DR).e_sref = (u_short) sref;
 1343                         takes_data = TRUE;
 1344                         e.ev_number = DR_TPDU;
 1345                         IncStat(ts_DR_rcvd);
 1346                         break;
 1347 
 1348                 case ER_TPDU_type:
 1349 #ifdef TPPT
 1350                         if (tp_traceflags[D_TPINPUT]) {
 1351                                 tptrace(TPPTmisc, "ER recvd", hdr->tpdu_ERreason, 0, 0, 0);
 1352                         }
 1353 #endif
 1354                                 e.ev_number = ER_TPDU;
 1355                         e.TPDU_ATTR(ER).e_reason = hdr->tpdu_ERreason;
 1356                         IncStat(ts_ER_rcvd);
 1357                         break;
 1358 
 1359                 case AK_TPDU_type:
 1360 
 1361                         e.TPDU_ATTR(AK).e_subseq = subseq;
 1362                         e.TPDU_ATTR(AK).e_fcc_present = fcc_present;
 1363 
 1364                         if (tpcb->tp_xtd_format) {
 1365 #ifdef BYTE_ORDER
 1366                                 union seq_type  seqeotX;
 1367 
 1368                                 seqeotX.s_seqeot = ntohl(hdr->tpdu_seqeotX);
 1369                                 e.TPDU_ATTR(AK).e_seq = seqeotX.s_seq;
 1370                                 e.TPDU_ATTR(AK).e_cdt = ntohs(hdr->tpdu_AKcdtX);
 1371 #else
 1372                                 e.TPDU_ATTR(AK).e_cdt = hdr->tpdu_AKcdtX;
 1373                                 e.TPDU_ATTR(AK).e_seq = hdr->tpdu_AKseqX;
 1374 #endif                          /* BYTE_ORDER */
 1375                         } else {
 1376                                 e.TPDU_ATTR(AK).e_cdt = hdr->tpdu_AKcdt;
 1377                                 e.TPDU_ATTR(AK).e_seq = hdr->tpdu_AKseq;
 1378                         }
 1379 #ifdef TPPT
 1380                         if (tp_traceflags[D_TPINPUT]) {
 1381                                 tptrace(TPPTmisc, "AK recvd seq cdt subseq fcc_pres",
 1382                                e.TPDU_ATTR(AK).e_seq, e.TPDU_ATTR(AK).e_cdt,
 1383                                         subseq, fcc_present);
 1384                         }
 1385 #endif
 1386 
 1387                                 e.ev_number = AK_TPDU;
 1388                         IncStat(ts_AK_rcvd);
 1389                         IncPStat(tpcb, tps_AK_rcvd);
 1390                         break;
 1391 
 1392                 case XAK_TPDU_type:
 1393                         if (tpcb->tp_xtd_format) {
 1394 #ifdef BYTE_ORDER
 1395                                 union seq_type  seqeotX;
 1396 
 1397                                 seqeotX.s_seqeot = ntohl(hdr->tpdu_seqeotX);
 1398                                 e.TPDU_ATTR(XAK).e_seq = seqeotX.s_seq;
 1399 #else
 1400                                 e.TPDU_ATTR(XAK).e_seq = hdr->tpdu_XAKseqX;
 1401 #endif                          /* BYTE_ORDER */
 1402                         } else {
 1403                                 e.TPDU_ATTR(XAK).e_seq = hdr->tpdu_XAKseq;
 1404                         }
 1405                         e.ev_number = XAK_TPDU;
 1406                         IncStat(ts_XAK_rcvd);
 1407                         IncPStat(tpcb, tps_XAK_rcvd);
 1408                         break;
 1409 
 1410                 case XPD_TPDU_type:
 1411                         if (tpcb->tp_xtd_format) {
 1412 #ifdef BYTE_ORDER
 1413                                 union seq_type  seqeotX;
 1414 
 1415                                 seqeotX.s_seqeot = ntohl(hdr->tpdu_seqeotX);
 1416                                 e.TPDU_ATTR(XPD).e_seq = seqeotX.s_seq;
 1417 #else
 1418                                 e.TPDU_ATTR(XPD).e_seq = hdr->tpdu_XPDseqX;
 1419 #endif                          /* BYTE_ORDER */
 1420                         } else {
 1421                                 e.TPDU_ATTR(XPD).e_seq = hdr->tpdu_XPDseq;
 1422                         }
 1423                         takes_data = TRUE;
 1424                         e.ev_number = XPD_TPDU;
 1425                         IncStat(ts_XPD_rcvd);
 1426                         IncPStat(tpcb, tps_XPD_rcvd);
 1427                         break;
 1428 
 1429                 case DT_TPDU_type:
 1430                         /*
 1431                          * the y option will cause occasional packets
 1432                          * to be dropped. A little crude but it
 1433                          * works.
 1434                          */
 1435 
 1436 #ifdef ARGO_DEBUG
 1437                         if (argo_debug[D_DROP]) {
 1438                                 if (time_second & 0x4 &&
 1439                                     hdr->tpdu_DTseq & 0x1) {
 1440                                         IncStat(ts_ydebug);
 1441                                         goto discard;
 1442                                 }
 1443                         }
 1444 #endif
 1445                         if (tpcb->tp_class == TP_CLASS_0) {
 1446 #ifdef TPCONS
 1447                 tp0_data:
 1448 #endif
 1449                                 e.TPDU_ATTR(DT).e_seq = 0;      /* actually don't care */
 1450                                 e.TPDU_ATTR(DT).e_eot = (((struct tp0du *) hdr)->tp0du_eot);
 1451                         } else if (tpcb->tp_xtd_format) {
 1452 #ifdef BYTE_ORDER
 1453                                 union seq_type  seqeotX;
 1454 
 1455                                 seqeotX.s_seqeot = ntohl(hdr->tpdu_seqeotX);
 1456                                 e.TPDU_ATTR(DT).e_seq = seqeotX.s_seq;
 1457                                 e.TPDU_ATTR(DT).e_eot = seqeotX.s_eot;
 1458 #else
 1459                                 e.TPDU_ATTR(DT).e_seq = hdr->tpdu_DTseqX;
 1460                                 e.TPDU_ATTR(DT).e_eot = hdr->tpdu_DTeotX;
 1461 #endif                          /* BYTE_ORDER */
 1462                         } else {
 1463                                 e.TPDU_ATTR(DT).e_seq = hdr->tpdu_DTseq;
 1464                                 e.TPDU_ATTR(DT).e_eot = hdr->tpdu_DTeot;
 1465                         }
 1466                         if (e.TPDU_ATTR(DT).e_eot)
 1467                                 IncStat(ts_eot_input);
 1468                         takes_data = TRUE;
 1469                         e.ev_number = DT_TPDU;
 1470                         IncStat(ts_DT_rcvd);
 1471                         IncPStat(tpcb, tps_DT_rcvd);
 1472                         break;
 1473 
 1474                 case GR_TPDU_type:
 1475                         tp_indicate(T_DISCONNECT, tpcb, ECONNABORTED);
 1476                         /* drop through */
 1477                 default:
 1478                         /*
 1479                          * this should NEVER happen because there is a check
 1480                          * for dutype well above here
 1481                          */
 1482                         error = E_TP_INV_TPDU;  /* causes an ER  */
 1483 #ifdef ARGO_DEBUG
 1484                         if (argo_debug[D_TPINPUT]) {
 1485                                 printf("INVALID dutype 0x%x\n", hdr->tpdu_type);
 1486                         }
 1487 #endif
 1488                         IncStat(ts_inv_dutype);
 1489                         goto respond;
 1490                 }
 1491         }
 1492         /*
 1493          * peel off the tp header; remember that the du_li doesn't count
 1494          * itself. This may leave us w/ an empty mbuf at the front of a
 1495          * chain. We can't just throw away the empty mbuf because hdr still
 1496          * points into the mbuf's data area and we're still using hdr (the
 1497          * tpdu header)
 1498          */
 1499         m->m_len -= ((int) hdr->tpdu_li + 1);
 1500         m->m_data += ((int) hdr->tpdu_li + 1);
 1501 
 1502         if (takes_data) {
 1503                 int             xmax = tpdu_info[hdr->tpdu_type][TP_MAX_DATA_INDEX];
 1504                 int             datalen = tpdu_len - hdr->tpdu_li - 1, mbtype = MT_DATA;
 1505                 struct {
 1506                         struct tp_disc_reason dr;
 1507                         struct cmsghdr  x_hdr;
 1508                 }               x;
 1509 #define c_hdr x.x_hdr
 1510                 struct mbuf *n;
 1511 
 1512                 CHECK((xmax && datalen > xmax), E_TP_LENGTH_INVAL,
 1513                       ts_inv_length, respond, (xmax + hdr->tpdu_li + 1));
 1514                 switch (hdr->tpdu_type) {
 1515 
 1516                 case CR_TPDU_type:
 1517                         c_hdr.cmsg_type = TPOPT_CONN_DATA;
 1518                         goto make_control_msg;
 1519 
 1520                 case CC_TPDU_type:
 1521                         c_hdr.cmsg_type = TPOPT_CFRM_DATA;
 1522                         goto make_control_msg;
 1523 
 1524                 case DR_TPDU_type:
 1525                         x.dr.dr_hdr.cmsg_len = sizeof(x) - sizeof(c_hdr);
 1526                         x.dr.dr_hdr.cmsg_type = TPOPT_DISC_REASON;
 1527                         x.dr.dr_hdr.cmsg_level = SOL_TRANSPORT;
 1528                         x.dr.dr_reason = hdr->tpdu_DRreason;
 1529                         c_hdr.cmsg_type = TPOPT_DISC_DATA;
 1530         make_control_msg:
 1531                         datalen += sizeof(c_hdr);
 1532                         c_hdr.cmsg_len = datalen;
 1533                         c_hdr.cmsg_level = SOL_TRANSPORT;
 1534                         mbtype = MT_CONTROL;
 1535                         MGET(n, M_DONTWAIT, MT_DATA);
 1536                         if (n == 0) {
 1537                                 m_freem(m);
 1538                                 m = 0;
 1539                                 datalen = 0;
 1540                                 goto invoke;
 1541                         }
 1542                         if (hdr->tpdu_type == DR_TPDU_type) {
 1543                                 datalen += sizeof(x) - sizeof(c_hdr);
 1544                                 bcopy((caddr_t) & x, mtod(n, caddr_t), n->m_len = sizeof(x));
 1545                         } else
 1546                                 bcopy((caddr_t) & c_hdr, mtod(n, caddr_t),
 1547                                       n->m_len = sizeof(c_hdr));
 1548                         n->m_next = m;
 1549                         m = n;
 1550                         /* FALLTHROUGH */
 1551 
 1552                 case XPD_TPDU_type:
 1553                         if (mbtype != MT_CONTROL)
 1554                                 mbtype = MT_OOBDATA;
 1555                         m->m_flags |= M_EOR;
 1556                         /* FALLTHROUGH */
 1557 
 1558                 case DT_TPDU_type:
 1559                         for (n = m; n; n = n->m_next) {
 1560                                 MCHTYPE(n, mbtype);
 1561                         }
 1562         invoke:
 1563                         e.TPDU_ATTR(DT).e_datalen = datalen;
 1564                         e.TPDU_ATTR(DT).e_data = m;
 1565                         break;
 1566 
 1567                 default:
 1568                         printf(
 1569                                "ERROR in tp_input! hdr->tpdu_type 0x%x takes_data 0x%x m %p\n",
 1570                                hdr->tpdu_type, takes_data, m);
 1571                         break;
 1572                 }
 1573                 /*
 1574                  * prevent m_freem() after tp_driver() from throwing it all
 1575                  * away
 1576                  */
 1577                 m = NULL;
 1578         }
 1579         IncStat(ts_tpdu_rcvd);
 1580 
 1581 #ifdef ARGO_DEBUG
 1582         if (argo_debug[D_TPINPUT]) {
 1583                 printf("tp_input: before driver, state 0x%x event 0x%x m %p",
 1584                        tpcb->tp_state, e.ev_number, m);
 1585                 printf(" e.e_data %p\n", e.TPDU_ATTR(DT).e_data);
 1586                 printf("takes_data 0x%x m_len 0x%x, tpdu_len 0x%x\n",
 1587                        takes_data, (m == NULL) ? 0 : m->m_len, tpdu_len);
 1588         }
 1589 #endif
 1590 
 1591         error = tp_driver(tpcb, &e);
 1592 
 1593         ASSERT(tpcb != (struct tp_pcb *) 0);
 1594         ASSERT(tpcb->tp_sock != (struct socket *) 0);
 1595         if (tpcb->tp_sock->so_error == 0)
 1596                 tpcb->tp_sock->so_error = error;
 1597 
 1598         /*
 1599          * Kludge to keep the state tables under control (adding data on
 1600          * connect & disconnect & freeing the mbuf containing the data would
 1601          * have exploded the tables and made a big mess ).
 1602          */
 1603         switch (e.ev_number) {
 1604         case CC_TPDU:
 1605         case DR_TPDU:
 1606         case CR_TPDU:
 1607                 m = e.TPDU_ATTR(CC).e_data;     /* same field for all three
 1608                                                  * dutypes */
 1609 #ifdef ARGO_DEBUG
 1610                 if (argo_debug[D_TPINPUT]) {
 1611                         printf("after driver, restoring m to %p, takes_data 0x%x\n",
 1612                                m, takes_data);
 1613                 }
 1614 #endif
 1615                 break;
 1616         default:
 1617                 break;
 1618         }
 1619         /*
 1620          * Concatenated sequences are terminated by any tpdu that carries
 1621          * data: CR, CC, DT, XPD, DR. All other tpdu types may be
 1622          * concatenated: AK, XAK, DC, ER.
 1623          */
 1624 
 1625         if (takes_data == 0) {
 1626                 ASSERT(m != NULL);
 1627                 /*
 1628                  * we already peeled off the prev. tp header so we can just
 1629                  * pull up some more and repeat
 1630                  */
 1631 
 1632                 if ((m = tp_inputprep(m)) != NULL) {
 1633 #ifdef ARGO_DEBUG
 1634                         if (argo_debug[D_TPINPUT]) {
 1635                                 hdr = mtod(m, struct tpdu *);
 1636                                 printf("tp_input @ separate: hdr %p size %d m %p\n",
 1637                                        hdr, (int) hdr->tpdu_li + 1, m);
 1638                                 dump_mbuf(m, "tp_input after driver, at separate");
 1639                         }
 1640 #endif
 1641 
 1642                         IncStat(ts_concat_rcvd);
 1643                         goto again;
 1644                 }
 1645         }
 1646         if (m != NULL) {
 1647 #ifdef ARGO_DEBUG
 1648                 if (argo_debug[D_TPINPUT]) {
 1649                         printf("tp_input : m_freem(%p)\n", m);
 1650                 }
 1651 #endif
 1652                 m_freem(m);
 1653 #ifdef ARGO_DEBUG
 1654                 if (argo_debug[D_TPINPUT]) {
 1655                         printf("tp_input : after m_freem %p\n", m);
 1656                 }
 1657 #endif
 1658         }
 1659         return;
 1660 
 1661 discard:
 1662         /* class 4: drop the tpdu */
 1663         /*
 1664          * class 2,0: Should drop the net connection, if you can figure out
 1665          * to which connection it applies
 1666          */
 1667 #ifdef ARGO_DEBUG
 1668         if (argo_debug[D_TPINPUT]) {
 1669                 printf("tp_input DISCARD\n");
 1670         }
 1671 #endif
 1672 #ifdef TPPT
 1673         if (tp_traceflags[D_TPINPUT]) {
 1674                 tptrace(TPPTmisc, "tp_input DISCARD m", m, 0, 0, 0);
 1675         }
 1676 #endif
 1677                 m_freem(m);
 1678         IncStat(ts_recv_drop);
 1679         return;
 1680 
 1681 nonx_dref:
 1682         switch (dutype) {
 1683         default:
 1684                 goto discard;
 1685         case CC_TPDU_type:
 1686                 /* error = E_TP_MISM_REFS; */
 1687                 break;
 1688         case DR_TPDU_type:
 1689                 error |= TP_ERROR_SNDC;
 1690         }
 1691 respond:
 1692 #ifdef ARGO_DEBUG
 1693         if (argo_debug[D_TPINPUT]) {
 1694                 printf("RESPOND: error 0x%x, errlen 0x%x\n", error, errlen);
 1695         }
 1696 #endif
 1697 #ifdef TPPT
 1698         if (tp_traceflags[D_TPINPUT]) {
 1699                 tptrace(TPPTmisc, "tp_input RESPOND m error sref", m, error, sref, 0);
 1700         }
 1701 #endif
 1702                 if (sref == 0)
 1703                 goto discard;
 1704         (void) tp_error_emit(error, (u_long) sref, satosiso(faddr),
 1705                              satosiso(laddr), m, errlen, tpcb,
 1706                              cons_channel, dgout_routine);
 1707 #ifdef ARGO_DEBUG
 1708         if (argo_debug[D_ERROR_EMIT]) {
 1709                 printf("tp_input after error_emit\n");
 1710         }
 1711 #endif
 1712 
 1713 #ifdef lint
 1714         printf("", sref, opt);
 1715 #endif                          /* lint */
 1716         IncStat(ts_recv_drop);
 1717 }
 1718 
 1719 
 1720 /*
 1721  * NAME: tp_headersize()
 1722  *
 1723  * CALLED FROM:
 1724  *  tp_emit() and tp_sbsend()
 1725  *  TP needs to know the header size so it can figure out how
 1726  *  much data to put in each tpdu.
 1727  *
 1728  * FUNCTION, ARGUMENTS, and RETURN VALUE:
 1729  *  For a given connection, represented by (tpcb), and
 1730  *  tpdu type (dutype), return the size of a tp header.
 1731  *
 1732  * RETURNS:       the expected size of the heade in bytesr
 1733  *
 1734  * SIDE EFFECTS:
 1735  *
 1736  * NOTES:        It would be nice if it got the network header size as well.
 1737  */
 1738 int
 1739 tp_headersize(int dutype, struct tp_pcb *tpcb)
 1740 {
 1741         int    size = 0;
 1742 
 1743 #ifdef TPPT
 1744         if (tp_traceflags[D_CONN]) {
 1745                 tptrace(TPPTmisc, "tp_headersize dutype class xtd_format",
 1746                         dutype, tpcb->tp_class, tpcb->tp_xtd_format, 0);
 1747         }
 1748 #endif
 1749         if (!((tpcb->tp_class == TP_CLASS_0) ||
 1750                       (tpcb->tp_class == TP_CLASS_4) ||
 1751                       (dutype == DR_TPDU_type) ||
 1752                       (dutype == CR_TPDU_type))) {
 1753                 printf("tp_headersize:dutype 0x%x, class 0x%x",
 1754                        dutype, tpcb->tp_class);
 1755                 /* TODO: identify this and GET RID OF IT */
 1756         }
 1757         ASSERT((tpcb->tp_class == TP_CLASS_0) ||
 1758                (tpcb->tp_class == TP_CLASS_4) ||
 1759                (dutype == DR_TPDU_type) ||
 1760                (dutype == CR_TPDU_type));
 1761 
 1762         if (tpcb->tp_class == TP_CLASS_0) {
 1763                 size = tpdu_info[dutype][TP_LEN_CLASS_0_INDEX];
 1764         } else {
 1765                 size = tpdu_info[dutype][tpcb->tp_xtd_format];
 1766         }
 1767         return size;
 1768         /* caller must get network level header size separately */
 1769 }

Cache object: 8509780a6f90701f59678696e5968f41


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