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_emit.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_emit.c,v 1.18 2003/08/11 15:17:29 itojun 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_emit.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 file contains tp_emit() and tp_error_emit(), which form TPDUs and
   62  * hand them to ip. They take data in the form of mbuf chain, allocate mbufs
   63  * as necessary for headers, and set the fields as appropriate from
   64  * information found in the tpcb and net-level pcb.
   65  *
   66  * The worst thing about this code is adding the variable-length options on a
   67  * machine that requires alignment for any memory access that isn't of size
   68  * 1.  See the macro ADDOPTION() below.
   69  *
   70  * We don't do any concatenation. (There's a kludge to test the basic mechanism
   71  * of separation under the 'w' tpdebug option, that's all.)
   72  */
   73 
   74 #include <sys/cdefs.h>
   75 __KERNEL_RCSID(0, "$NetBSD: tp_emit.c,v 1.18 2003/08/11 15:17:29 itojun Exp $");
   76 
   77 #include <sys/param.h>
   78 #include <sys/systm.h>
   79 #include <sys/mbuf.h>
   80 #include <sys/socket.h>
   81 #include <sys/socketvar.h>
   82 #include <sys/protosw.h>
   83 #include <sys/errno.h>
   84 #include <sys/time.h>
   85 
   86 #include <net/if.h>
   87 
   88 #include <netiso/iso.h>
   89 #include <netiso/iso_pcb.h>
   90 #include <netiso/argo_debug.h>
   91 #include <netiso/tp_timer.h>
   92 #include <netiso/tp_param.h>
   93 #include <netiso/tp_stat.h>
   94 #include <netiso/tp_pcb.h>
   95 #include <netiso/tp_tpdu.h>
   96 #include <netiso/tp_trace.h>
   97 #include <netiso/tp_meas.h>
   98 #include <netiso/tp_seq.h>
   99 #include <netiso/tp_var.h>
  100 #include <netiso/iso_errno.h>
  101 #include <netiso/iso_var.h>
  102 
  103 #ifdef TRUE
  104 #undef FALSE
  105 #undef TRUE
  106 #endif
  107 #include <netccitt/x25.h>
  108 #include <netccitt/pk.h>
  109 #include <netccitt/pk_var.h>
  110 
  111 /*
  112  * Here is a mighty kludge.  The token ring misorders packets if you fire
  113  * them at it too fast, and TP sans checksum is "too fast", so we have
  114  * introduced a delay when checksumming isn't used.
  115  */
  116 char            tp_delay = 0x00;/* delay to keep token ring from blowing it */
  117 
  118 /*
  119  * NAME:        tp_emit()
  120  *
  121  * CALLED FROM: tp.trans and from tp_sbsend()
  122  *
  123  * FUNCTION and ARGUMENTS:
  124  *      Emits one tpdu of the type (dutype), of the format appropriate
  125  *      to the connection described by the pcb (tpcb), with sequence
  126  *      number (seq) (where appropriate), end-of-tsdu bit (eot) where
  127  *      appropriate, and with the data in the mbuf chain (data).
  128  *      For DR and ER tpdus, the argument (eot) is
  129  *      the reason for issuing the tpdu rather than an end-of-tsdu indicator.
  130  *
  131  * RETURNS:
  132  *      0  OK
  133  *      ENOBUFS
  134  *      E* returned from net layer output rtn
  135  *
  136  * SIDE EFFECTS:
  137  *
  138  * NOTES:
  139  *
  140  *      WE ASSUME that the tp header + all options will fit in ONE mbuf.
  141  *      If mbufs are 256 this will most likely be true, but if they are 128 it's
  142  *      possible that they won't.
  143  *      If you used every option on the CR + max. user data you'd overrun
  144  *      112 but unless you used > 115 bytes for the security
  145  *      parameter, it would fit in a 256-byte mbuf (240 bytes for the header)
  146  *      We don't support the security parameter, so this isn't a problem.
  147  *      If security is added, we ought to remove this assumption.
  148  *
  149  *  We do not implement the flow control confirmation "element of procedure".
  150  *  A) it should not affect interoperability,
  151  *  B) it should not be necessary - the protocol will eventually
  152  *      straighten things out w/o FCC, as long as we don't have severely
  153  *              mismatched keepalive and inactivity timers, and
  154  *      C) it appears not to be REQUIRED, and
  155  *  D) it's incredibly grotesque, and no doubt will lengthen a few
  156  *      critical paths.
  157  *  HOWEVER, we're thinking about putting it in anyway, for
  158  *  completeness, just like we did with ack subsequencing.
  159  */
  160 
  161 int
  162 tp_emit(dutype, tpcb, seq, eot, data)
  163         int             dutype;
  164         struct tp_pcb  *tpcb;
  165         SeqNum          seq;
  166         u_int           eot;
  167         struct mbuf    *data;
  168 {
  169         struct tpdu *hdr;
  170         struct mbuf *m;
  171         int             csum_offset = 0;
  172         int             datalen = 0;
  173         int             error = 0;
  174         SeqNum          olduwe;
  175         int             acking_ooo;
  176 
  177         /*
  178          * NOTE: here we treat tpdu_li as if it DID include the li field, up
  179          * until the end, at which time we subtract 1 THis is because if we
  180          * subtract 1 right away, we end up adding one every time we add an
  181          * option.
  182          */
  183 #ifdef ARGO_DEBUG
  184         if (argo_debug[D_EMIT]) {
  185                 printf(
  186                        "tp_emit dutype 0x%x, tpcb %p, eot 0x%x, seq 0x%x, data %p",
  187                        dutype, tpcb, eot, seq, data);
  188         }
  189 #endif
  190 
  191         if (dutype == CR_TPDU || dutype == CC_TPDU) {
  192                 m = (struct mbuf *) malloc((u_long) 256, M_MBUF, M_DONTWAIT);
  193                 if (m) {
  194                         m->m_type = TPMT_TPHDR;
  195                         mbstat.m_mtypes[TPMT_TPHDR]++;
  196                         m->m_next = NULL;
  197                         m->m_nextpkt = NULL;
  198                         m->m_data = m->m_pktdat;
  199                         m->m_flags = M_PKTHDR;
  200                         bzero(&m->m_pkthdr, sizeof(m->m_pkthdr));
  201                 }
  202         } else {
  203                 MGETHDR(m, M_DONTWAIT, TPMT_TPHDR);
  204         }
  205         m->m_data += max_hdr;
  206         if (m == NULL) {
  207                 if (data != (struct mbuf *) 0)
  208                         m_freem(data);
  209                 error = ENOBUFS;
  210                 goto done;
  211         }
  212         m->m_len = sizeof(struct tpdu);
  213         m->m_nextpkt = NULL;
  214 
  215         hdr = mtod(m, struct tpdu *);
  216         bzero((caddr_t) hdr, sizeof(struct tpdu));
  217 
  218         {
  219                 hdr->tpdu_type = dutype;
  220                 hdr->tpdu_li = tp_headersize(dutype, tpcb);
  221                 /*
  222                  * class 0 doesn't use this for DT
  223                  * it'll just get overwritten below
  224                  */
  225                 hdr->tpdu_dref = htons(tpcb->tp_fref);
  226                 if (tpcb->tp_use_checksum ||
  227                 (dutype == CR_TPDU_type && (tpcb->tp_class & TP_CLASS_4))) {
  228                         csum_offset = hdr->tpdu_li + 2; /* DOESN'T include csum */
  229                         ADDOPTION(TPP_checksum, hdr, 2, eot /* dummy arg */ );
  230 #ifdef ARGO_DEBUG
  231                         if (argo_debug[D_CHKSUM]) {
  232                                 printf(
  233                                        "tp_emit: csum_offset 0x%x, hdr->tpdu_li 0x%x\n",
  234                                        csum_offset, hdr->tpdu_li);
  235                         }
  236 #endif
  237                 }
  238                 /*
  239                  * VARIABLE PARTS...
  240                  */
  241                 switch (dutype) {
  242 
  243                 case CR_TPDU_type:
  244                         hdr->tpdu_CRdref_0 = 0; /* must be zero */
  245                 case CC_TPDU_type:
  246                         if (!tpcb->tp_cebit_off) {
  247                                 tpcb->tp_win_recv = tp_start_win << 8;
  248                                 LOCAL_CREDIT(tpcb);
  249                                 CONG_INIT_SAMPLE(tpcb);
  250                         } else
  251                                 LOCAL_CREDIT(tpcb);
  252 
  253                         /* Case CC_TPDU_type used to be here */
  254                         {
  255                                 u_char          x;
  256 
  257                                 hdr->tpdu_CCsref = htons(tpcb->tp_lref);        /* same as CRsref */
  258 
  259                                 if (tpcb->tp_class > TP_CLASS_1) {
  260                                         tpcb->tp_sent_uwe = tpcb->tp_lcredit - 1;
  261                                         tpcb->tp_sent_rcvnxt = 1;
  262                                         tpcb->tp_sent_lcdt = tpcb->tp_lcredit;
  263                                         hdr->tpdu_cdt = tpcb->tp_lcredit;
  264                                 } else {
  265 #ifdef TPCONS
  266                                         if (tpcb->tp_netservice == ISO_CONS) {
  267                                                 struct isopcb  *isop = (struct isopcb *) tpcb->tp_npcb;
  268                                                 struct pklcd   *lcp = (struct pklcd *) (isop->isop_chan);
  269                                                 lcp->lcd_flags &= ~X25_DG_CIRCUIT;
  270                                         }
  271 #endif
  272                                         hdr->tpdu_cdt = 0;
  273                                 }
  274                                 hdr->tpdu_CCclass = tp_mask_to_num(tpcb->tp_class);
  275                                 hdr->tpdu_CCoptions =
  276                                         (tpcb->tp_xtd_format ? TPO_XTD_FMT : 0) |
  277                                         (tpcb->tp_use_efc ? TPO_USE_EFC : 0);
  278 
  279 #ifdef TP_PERF_MEAS
  280                                 if (DOPERF(tpcb)) {
  281                                         u_char  perf_meas = tpcb->tp_perf_on;
  282                                         ADDOPTION(TPP_perf_meas, hdr,
  283                                                   sizeof(perf_meas), perf_meas);
  284                                 }
  285 #endif
  286 
  287                                         if (dutype == CR_TPDU_type) {
  288                                         IncStat(ts_CR_sent);
  289 
  290                                         ASSERT(tpcb->tp_lsuffixlen > 0);
  291                                         ASSERT(tpcb->tp_fsuffixlen > 0);
  292 
  293                                         ADDOPTION(TPP_calling_sufx, hdr,
  294                                                   tpcb->tp_lsuffixlen, tpcb->tp_lsuffix[0]);
  295                                         ADDOPTION(TPP_called_sufx, hdr,
  296                                                   tpcb->tp_fsuffixlen, tpcb->tp_fsuffix[0]);
  297                                 } else {
  298                                         IncStat(ts_CC_sent);
  299                                 }
  300 
  301                                 ADDOPTION(TPP_tpdu_size, hdr,
  302                                           sizeof(tpcb->tp_tpdusize), tpcb->tp_tpdusize);
  303 
  304                                 if (tpcb->tp_class != TP_CLASS_0) {
  305                                         short           millisec = 500 * (tpcb->tp_sendack_ticks);
  306 
  307                                         millisec = htons(millisec);
  308                                         ADDOPTION(TPP_acktime, hdr, sizeof(short), millisec);
  309 
  310                                         x = (tpcb->tp_use_nxpd ? TPAO_USE_NXPD : 0)
  311                                                 | (tpcb->tp_use_rcc ? TPAO_USE_RCC : 0)
  312                                                 | (tpcb->tp_use_checksum ? 0 : TPAO_NO_CSUM)
  313                                                 | (tpcb->tp_xpd_service ? TPAO_USE_TXPD : 0);
  314                                         ADDOPTION(TPP_addl_opt, hdr, 1, x);
  315 
  316                                         if ((tpcb->tp_l_tpdusize ^ (1 << tpcb->tp_tpdusize)) != 0) {
  317                                                 u_short         size_s = tpcb->tp_l_tpdusize >> 7;
  318                                                 u_char          size_c = size_s;
  319                                                 ASSERT(tpcb->tp_l_tpdusize < 65536 * 128);
  320                                                 if (dutype == CR_TPDU_type)
  321                                                         tpcb->tp_ptpdusize = size_s;
  322                                                 if (size_s < 256) {
  323                                                         ADDOPTION(TPP_ptpdu_size, hdr, 1, size_c);
  324                                                 } else {
  325                                                         size_s = htons(size_s);
  326                                                         ADDOPTION(TPP_ptpdu_size, hdr, 2, size_s);
  327                                                 }
  328                                         }
  329                                 }
  330                                 if ((dutype == CR_TPDU_type) && (tpcb->tp_class != TP_CLASS_0)) {
  331 
  332                                         ASSERT(1 == sizeof(tpcb->tp_vers));
  333                                         ADDOPTION(TPP_vers, hdr, 1, tpcb->tp_vers);
  334 
  335                                         /*
  336                                          * for each alt protocol class x, x =
  337                                          * x<<4; option = concat(option, x);
  338                                          * Well, for now we only have TP0 for
  339                                          * an alternative so... this is easy.
  340                                          *
  341                                          * HOWEVER... There should be NO alt
  342                                          * protocol class over CLNS.  Need to
  343                                          * see if the route suggests CONS,
  344                                          * and iff so add alt class.
  345                                          */
  346                                         x = 0;
  347                                         ADDOPTION(TPP_alt_class, hdr, 1, x);
  348                                 }
  349 #if 0
  350                                 if (hdr->tpdu_li > MLEN)
  351                                         panic("tp_emit CR/CC");
  352 #endif
  353                         }
  354                         break;
  355 
  356                 case DR_TPDU_type:
  357                         if (hdr->tpdu_DRdref == 0) {
  358                                 /* don't issue the DR */
  359                                 goto done;
  360                         }
  361                         hdr->tpdu_cdt = 0;
  362                         hdr->tpdu_DRsref = htons(tpcb->tp_lref);
  363                         hdr->tpdu_DRreason = (u_char) eot;      /* WHICH BYTE OF THIS??? */
  364 
  365                         /* forget the add'l information variable part */
  366                         IncStat(ts_DR_sent);
  367                         break;
  368 
  369                 case DC_TPDU_type:      /* not used in class 0 */
  370                         ASSERT(tpcb->tp_class != TP_CLASS_0);
  371                         hdr->tpdu_DCsref = htons(tpcb->tp_lref);
  372                         hdr->tpdu_cdt = 0;
  373                         data = (struct mbuf *) 0;
  374                         IncStat(ts_DC_sent);
  375                         break;
  376 
  377                 case XAK_TPDU_type:     /* xak not used in class 0 */
  378                         ASSERT(tpcb->tp_class != TP_CLASS_0);   /* fall through */
  379                         hdr->tpdu_cdt = 0;
  380 
  381 #ifdef TPPT
  382                         if (tp_traceflags[D_XPD]) {
  383                                 tptraceTPCB(TPPTXack, seq, 0, 0, 0, 0);
  384                         }
  385 #endif
  386                         data = (struct mbuf *) 0;
  387                         if (tpcb->tp_xtd_format) {
  388 #ifdef BYTE_ORDER
  389                                 union seq_type  seqeotX;
  390 
  391                                 seqeotX.s_seq = seq;
  392                                 seqeotX.s_eot = 1;
  393                                 hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot);
  394 #else
  395                                 hdr->tpdu_XAKseqX = seq;
  396 #endif                          /* BYTE_ORDER */
  397                         } else {
  398                                 hdr->tpdu_XAKseq = seq;
  399                         }
  400                         IncStat(ts_XAK_sent);
  401                         IncPStat(tpcb, tps_XAK_sent);
  402                         break;
  403 
  404                 case XPD_TPDU_type:     /* xpd not used in class 0 */
  405                         ASSERT(tpcb->tp_class != TP_CLASS_0);   /* fall through */
  406                         hdr->tpdu_cdt = 0;
  407                         if (tpcb->tp_xtd_format) {
  408 #ifdef BYTE_ORDER
  409                                 union seq_type  seqeotX;
  410 
  411                                 seqeotX.s_seq = seq;
  412                                 seqeotX.s_eot = 1;
  413                                 hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot);
  414 #else
  415                                 hdr->tpdu_XPDseqX = seq;
  416                                 hdr->tpdu_XPDeotX = 1;  /* always 1 for XPD tpdu */
  417 #endif                          /* BYTE_ORDER */
  418                         } else {
  419                                 hdr->tpdu_XPDseq = seq;
  420                                 hdr->tpdu_XPDeot = 1;   /* always 1 for XPD tpdu */
  421                         }
  422                         IncStat(ts_XPD_sent);
  423                         IncPStat(tpcb, tps_XPD_sent);
  424 
  425                         /* kludge to test the input size checking */
  426 #ifdef ARGO_DEBUG
  427                         if (argo_debug[D_SIZE_CHECK]) {
  428 #if 0
  429                                  if (data->m_len <= 16 && 
  430                                      data->m_off < (MLEN-18)) {
  431                                         printf("Sending too much data on XPD: 18 bytes\n");
  432                                         data->m_len = 18; 
  433                                 }
  434 #endif
  435                         }
  436 #endif
  437                         break;
  438 
  439                 case DT_TPDU_type:
  440                         hdr->tpdu_cdt = 0;
  441 #ifdef TPPT
  442                         if (tp_traceflags[D_DATA]) {
  443                                 tptraceTPCB(TPPTmisc,
  444                                             "emit DT: eot seq tpdu_li", eot,
  445                                             seq, hdr->tpdu_li, 0);
  446                         }
  447 #endif
  448                         if (tpcb->tp_xtd_format) {
  449 #ifdef BYTE_ORDER
  450                                 union seq_type  seqeotX;
  451 
  452                                 seqeotX.s_seq = seq;
  453                                 seqeotX.s_eot = eot;
  454                                 hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot);
  455 #else
  456                                 hdr->tpdu_DTseqX = seq;
  457                                 hdr->tpdu_DTeotX = eot;
  458 #endif                          /* BYTE_ORDER */
  459                         } else if (tpcb->tp_class == TP_CLASS_0) {
  460 #ifdef ARGO_DEBUG
  461                                 if (argo_debug[D_EMIT]) {
  462                                         printf("DT tpdu: class 0 m %p hdr %p\n", m, hdr);
  463                                         dump_buf(hdr, hdr->tpdu_li + 1);
  464                                 }
  465 #endif
  466                                 ((struct tp0du *) hdr)->tp0du_eot = eot;
  467                                 ((struct tp0du *) hdr)->tp0du_mbz = 0;
  468 #ifdef ARGO_DEBUG
  469                                 if (argo_debug[D_EMIT]) {
  470                                         printf("DT 2 tpdu: class 0 m %p hdr %p\n", m, hdr);
  471                                         dump_buf(hdr, hdr->tpdu_li + 1);
  472                                 }
  473 #endif
  474                         } else {
  475                                 hdr->tpdu_DTseq = seq;
  476                                 hdr->tpdu_DTeot = eot;
  477                         }
  478                         if (eot) {
  479                                 IncStat(ts_EOT_sent);
  480                         }
  481                         IncStat(ts_DT_sent);
  482                         IncPStat(tpcb, tps_DT_sent);
  483                         break;
  484 
  485                 case AK_TPDU_type:      /* ak not used in class 0 */
  486                         ASSERT(tpcb->tp_class != TP_CLASS_0);
  487                         data = (struct mbuf *) 0;
  488                         olduwe = tpcb->tp_sent_uwe;
  489 
  490                         if (seq != tpcb->tp_sent_rcvnxt || tpcb->tp_rsycnt == 0) {
  491                                 LOCAL_CREDIT(tpcb);
  492                                 tpcb->tp_sent_uwe =
  493                                         SEQ(tpcb, tpcb->tp_rcvnxt + tpcb->tp_lcredit - 1);
  494                                 tpcb->tp_sent_lcdt = tpcb->tp_lcredit;
  495                                 acking_ooo = 0;
  496                         } else
  497                                 acking_ooo = 1;
  498 
  499 #ifdef ARGO_DEBUG
  500                         if (argo_debug[D_RENEG]) {
  501                                 /*
  502                                  * occasionally fake a reneging so you can test
  503                                  * subsequencing
  504                                  */
  505                                 if (olduwe & 0x1) {
  506                                         tpcb->tp_reneged = 1;
  507                                         IncStat(ts_ldebug);
  508                                 }
  509                         }
  510 #endif
  511                         /*
  512                          * Are we about to reneg on credit? When might we do
  513                          * so? a) when using optimistic credit (which we no
  514                          * longer do). b) when drain() gets implemented (not
  515                          * in the plans). c) when D_RENEG is on. d) when DEC
  516                          * BIT response is implemented. (not- when we do
  517                          * this, we'll need to implement flow control
  518                          * confirmation)
  519                          */
  520                         if (SEQ_LT(tpcb, tpcb->tp_sent_uwe, olduwe)) {
  521                                 tpcb->tp_reneged = 1;
  522                                 IncStat(ts_lcdt_reduced);
  523 #ifdef TPPT
  524                                 if (tp_traceflags[D_CREDIT]) {
  525                                         tptraceTPCB(TPPTmisc,
  526                                       "RENEG: olduwe newuwe lcredit rcvnxt",
  527                                                     olduwe,
  528                                         tpcb->tp_sent_uwe, tpcb->tp_lcredit,
  529                                                     tpcb->tp_rcvnxt);
  530                                 }
  531 #endif
  532                         }
  533 #ifdef TP_PERF_MEAS
  534                         if (DOPERF(tpcb)) {
  535                                 /*
  536                                  * new lwe is less than old uwe means we're
  537                                  * acking before we received a whole window full
  538                                  */
  539                                 if (SEQ_LT(tpcb, tpcb->tp_rcvnxt, olduwe)) {
  540                                         /*
  541                                          * tmp1 = number of pkts fewer than
  542                                          * the full window
  543                                          */
  544                                         int    tmp1 =
  545                                         (int) SEQ_SUB(tpcb, olduwe,
  546                                                       tpcb->tp_rcvnxt);
  547 
  548                                         if (tmp1 > TP_PM_MAX)
  549                                                 tmp1 = TP_PM_MAX;
  550                                         IncPStat(tpcb, tps_ack_early[tmp1]);
  551 
  552                                         /*
  553                                          * tmp1 = amt of new cdt we're
  554                                          * advertising 
  555                                          */
  556                                         tmp1 = SEQ_SUB(tpcb, seq,
  557                                                        tpcb->tp_sent_rcvnxt);
  558                                         if (tmp1 > TP_PM_MAX)
  559                                                 tmp1 = TP_PM_MAX;
  560 
  561                                         IncPStat(tpcb,
  562                                                  tps_cdt_acked[tmp1]
  563                                                  [((tpcb->tp_lcredit >
  564                                                     TP_PM_MAX) ?
  565                                                    TP_PM_MAX : 
  566                                                    tpcb->tp_lcredit)]);
  567 
  568                                 }
  569                         }
  570 #endif
  571 
  572 #ifdef TPPT
  573                         if (tp_traceflags[D_ACKSEND]) {
  574                                 tptraceTPCB(TPPTack, seq, tpcb->tp_lcredit,
  575                                             tpcb->tp_sent_uwe,
  576                                             tpcb->tp_r_subseq, 0);
  577                         }
  578 #endif
  579                         if (tpcb->tp_xtd_format) {
  580 #ifdef BYTE_ORDER
  581                                 union seq_type  seqeotX;
  582 
  583                                 seqeotX.s_seq = seq;
  584                                 seqeotX.s_eot = 0;
  585                                 hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot);
  586                                 hdr->tpdu_AKcdtX = htons(tpcb->tp_lcredit);
  587 #else
  588                                 hdr->tpdu_cdt = 0;
  589                                 hdr->tpdu_AKseqX = seq;
  590                                 hdr->tpdu_AKcdtX = tpcb->tp_lcredit;
  591 #endif                          /* BYTE_ORDER */
  592                         } else {
  593                                 hdr->tpdu_AKseq = seq;
  594                                 hdr->tpdu_AKcdt = tpcb->tp_lcredit;
  595                         }
  596                         if ((tpcb->tp_class == TP_CLASS_4) &&
  597                             (tpcb->tp_reneged || acking_ooo)) {
  598                                 /*
  599                                  * Ack subsequence parameter req'd if WE
  600                                  * reneged on credit offered.  (ISO 8073,
  601                                  * 12.2.3.8.2, p. 74)
  602                                  */
  603 #ifdef ARGO_DEBUG
  604                                 if (argo_debug[D_RENEG]) {
  605                                         printf("Adding subseq 0x%x\n", tpcb->tp_s_subseq);
  606                                 }
  607 #endif
  608                                 tpcb->tp_s_subseq++;
  609                                 /*
  610                                  * add tmp subseq and do a htons on it.
  611                                  */
  612                                 ADDOPTION(TPP_subseq, hdr,
  613                                           sizeof(tpcb->tp_s_subseq), tpcb->tp_s_subseq);
  614                         } else
  615                                 tpcb->tp_s_subseq = 0;
  616 
  617                         if (tpcb->tp_sendfcc || eot) {  /* overloaded to mean
  618                                                          * SEND FCC */
  619                                 /*
  620                                  * Rules for sending FCC ("should" send when)
  621                                  * : %a) received an ack from peer with NO
  622                                  * NEWS whatsoever, and it did not contain an
  623                                  * FCC b) received an ack from peer that
  624                                  * opens its closed window. c) received an
  625                                  * ack from peer after it reneged on its
  626                                  * offered credit, AND this ack raises UWE
  627                                  * but LWE is same and below UWE at time of
  628                                  * reneging (reduction) Now, ISO 8073
  629                                  * 12.2.3.8.3 says that a retransmitted AK
  630                                  * shall not contain the FCC parameter.  Now,
  631                                  * how the hell you tell the difference
  632                                  * between a retransmitted ack and an ack
  633                                  * that's sent in response to a received ack,
  634                                  * I don't know, because without any local
  635                                  * activity, and w/o any received DTs, they
  636                                  * will contain exactly the same credit/seq#
  637                                  * information. Anyway, given that the
  638                                  * "retransmission of acks" procedure (ISO
  639                                  * 8073 12.2.3.8.3) is optional, and we don't
  640                                  * do it (although the peer can't tell that),
  641                                  * we ignore this last rule.
  642                                  *
  643                                  * We send FCC for reasons a) and b) only. To
  644                                  * add reason c) would require a ridiculous
  645                                  * amount of state.
  646                                  *
  647                                  */
  648                                 u_short         bogus[4];       /* lwe(32), subseq(16),
  649                                                                  * cdt(16) */
  650                                 SeqNum          lwe;
  651                                 u_short         subseq, fcredit;
  652 
  653                                 tpcb->tp_sendfcc = 0;
  654 
  655                                 lwe = (SeqNum) htonl(tpcb->tp_snduna);
  656                                 subseq = htons(tpcb->tp_r_subseq);
  657                                 fcredit = htons(tpcb->tp_fcredit);
  658 
  659                                 bcopy((caddr_t) & lwe, (caddr_t) & bogus[0], sizeof(SeqNum));
  660                                 bcopy((caddr_t) & subseq, (caddr_t) & bogus[2], sizeof(u_short));
  661                                 bcopy((caddr_t) & fcredit, (caddr_t) & bogus[3], sizeof(u_short));
  662 
  663 #ifdef TPPT
  664                                 if (tp_traceflags[D_ACKSEND]) {
  665                                         tptraceTPCB(TPPTmisc,
  666                                       "emit w/FCC: snduna r_subseq fcredit",
  667                                          tpcb->tp_snduna, tpcb->tp_r_subseq,
  668                                                     tpcb->tp_fcredit, 0);
  669                                 }
  670 #endif
  671 
  672 #ifdef ARGO_DEBUG
  673                                 if (argo_debug[D_ACKSEND]) {
  674                                         printf("Calling ADDOPTION 0x%x, %p, 0x%lx,0x%x\n",
  675                                                TPP_flow_cntl_conf,
  676                                                hdr, (unsigned long)sizeof(bogus), bogus[0]);
  677                                 }
  678 #endif
  679                                 ADDOPTION(TPP_flow_cntl_conf, hdr, sizeof(bogus), bogus[0]);
  680 #ifdef ARGO_DEBUG
  681                                 if (argo_debug[D_ACKSEND]) {
  682                                         printf("after ADDOPTION hdr %p hdr->tpdu_li 0x%x\n",
  683                                                hdr, hdr->tpdu_li);
  684                                         printf(
  685                                                "after ADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n",
  686                                                csum_offset, hdr->tpdu_li);
  687                                 }
  688 #endif
  689 
  690                         }
  691                         tpcb->tp_reneged = 0;
  692                         tpcb->tp_sent_rcvnxt = seq;
  693                         if (tpcb->tp_fcredit == 0) {
  694                                 int             timo = tpcb->tp_keepalive_ticks;
  695                                 if (tpcb->tp_rxtshift < TP_MAXRXTSHIFT)
  696                                         tpcb->tp_rxtshift++;
  697                                 timo = min(timo, ((int) tpcb->tp_dt_ticks) << tpcb->tp_rxtshift);
  698                                 tp_ctimeout(tpcb, TM_sendack, timo);
  699                         } else
  700                                 tp_ctimeout(tpcb, TM_sendack, tpcb->tp_keepalive_ticks);
  701                         IncStat(ts_AK_sent);
  702                         IncPStat(tpcb, tps_AK_sent);
  703 #ifdef ARGO_DEBUG
  704                         if (argo_debug[D_ACKSEND]) {
  705                                 printf(
  706                                        "2 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n",
  707                                        csum_offset, hdr->tpdu_li);
  708                         }
  709 #endif
  710                         break;
  711 
  712                 case ER_TPDU_type:
  713                         hdr->tpdu_ERreason = eot;
  714                         hdr->tpdu_cdt = 0;
  715                         /* no user data */
  716                         data = (struct mbuf *) 0;
  717                         IncStat(ts_ER_sent);
  718                         break;
  719                 }
  720 
  721         }
  722         ASSERT((int) hdr->tpdu_li != 0);
  723 #if 0
  724         ASSERT((int) hdr->tpdu_li < MLEN);
  725 #endif
  726 
  727         m->m_next = data;
  728 
  729 #if 0
  730         ASSERT(hdr->tpdu_li < MLEN);    /* leave this in */
  731 #endif
  732         ASSERT(hdr->tpdu_li != 0);      /* leave this in */
  733 
  734         m->m_len = hdr->tpdu_li;
  735         hdr->tpdu_li--;         /* doesn't include the li field */
  736 
  737         datalen = m_datalen(m); /* total len */
  738 
  739         ASSERT(datalen <= tpcb->tp_l_tpdusize); /* may become a problem when
  740                                                  * CLNP is used; leave in
  741                                                  * here for the time being */
  742 #ifdef ARGO_DEBUG
  743         if (argo_debug[D_ACKSEND]) {
  744                 printf(
  745                  "4 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n",
  746                        csum_offset, hdr->tpdu_li);
  747         }
  748 #endif
  749         if (datalen > tpcb->tp_l_tpdusize) {
  750                 printf("data len 0x%x tpcb->tp_l_tpdusize 0x%x\n",
  751                        datalen, tpcb->tp_l_tpdusize);
  752         }
  753 #ifdef ARGO_DEBUG
  754         if (argo_debug[D_EMIT]) {
  755                 printf(
  756                        "tp_emit before gen_csum m_len 0x%x, csum_offset 0x%x, datalen 0x%x\n",
  757                        m->m_len, csum_offset, datalen);
  758         }
  759 #endif
  760         if (tpcb->tp_use_checksum ||
  761             (dutype == CR_TPDU_type && (tpcb->tp_class & TP_CLASS_4))) {
  762                 iso_gen_csum(m, csum_offset, datalen);
  763         }
  764 #ifdef ARGO_DEBUG
  765         if (argo_debug[D_EMIT]) {
  766                 printf("tp_emit before tpxxx_output tpcb %p, dutype 0x%x, datalen 0x%x\n",
  767                        tpcb, dutype, datalen);
  768                 dump_buf(mtod(m, caddr_t), datalen);
  769         }
  770 #endif
  771 
  772 #ifdef TP_PERF_MEAS
  773         if (DOPERF(tpcb)) {
  774                 if (dutype == DT_TPDU_type) {
  775                         PStat(tpcb, Nb_to_ll) += (datalen - m->m_len);
  776                         tpmeas(tpcb->tp_lref, TPtime_to_ll, NULL,
  777                                seq, PStat(tpcb, Nb_to_ll),
  778                                (datalen - m->m_len));
  779                 }
  780         }
  781 #endif
  782 
  783 #ifdef TPPT
  784         if (tp_traceflags[D_EMIT]) {
  785                 tptraceTPCB(TPPTtpduout, dutype, hdr, hdr->tpdu_li + 1, datalen, 0);
  786         }
  787 #endif
  788 #ifdef ARGO_DEBUG
  789             if (argo_debug[D_EMIT]) {
  790                 printf("OUTPUT: tpcb %p, isop %p, so %p\n",
  791                        tpcb, tpcb->tp_npcb, tpcb->tp_sock);
  792         }
  793 #endif
  794 
  795         {
  796                 extern char     tp_delay;
  797 
  798                 if (tp_delay)
  799                         if (tpcb->tp_use_checksum == 0) {
  800                                 u_int  i = tp_delay;
  801                                 for (; i != 0; i--)
  802                                         (void) iso_check_csum(m, datalen);
  803                         }
  804         }
  805         ASSERT(m->m_len > 0);
  806         error = (tpcb->tp_nlproto->nlp_output) (m, datalen, tpcb->tp_npcb,
  807                                                 !tpcb->tp_use_checksum);
  808 #ifdef ARGO_DEBUG
  809         if (argo_debug[D_EMIT]) {
  810                 printf("OUTPUT: returned 0x%x\n", error);
  811         }
  812 #endif
  813 #ifdef TPPT
  814         if (tp_traceflags[D_EMIT]) {
  815                 tptraceTPCB(TPPTmisc,
  816                        "tp_emit nlproto->output netservice returns datalen",
  817          tpcb->tp_nlproto->nlp_output, tpcb->tp_netservice, error, datalen);
  818         }
  819 #endif
  820 done:
  821         if (error) {
  822                 if (dutype == AK_TPDU_type)
  823                         tp_ctimeout(tpcb, TM_sendack, 1);
  824                 if (error == E_CO_QFULL) {
  825                         tp_quench((struct inpcb *) tpcb, PRC_QUENCH);
  826                         return 0;
  827                 }
  828         }
  829         return error;
  830 }
  831 /*
  832  * NAME:                tp_error_emit()
  833  * CALLED FROM: tp_input() when a DR or ER is to be issued in
  834  *      response to an input error.
  835  * FUNCTION and ARGUMENTS:
  836  *      The error type is the first argument.
  837  *      The argument (sref) is the source reference on the bad incoming tpdu,
  838  *      and is used for a destination reference on the outgoing packet.
  839  *      (faddr) and (laddr) are the foreign and local addresses for this
  840  *      connection.
  841  *      (erdata) is a ptr to the errant incoming tpdu, and is copied into the
  842  *      outgoing ER, if an ER is to be issued.
  843  *      (erlen)  is the number of octets of the errant tpdu that we should
  844  *      try to copy.
  845  *      (tpcb) is the pcb that describes the connection for which the bad tpdu
  846  *      arrived.
  847  * RETURN VALUES:
  848  *              0 OK
  849  *      ENOBUFS
  850  *      E* from net layer datagram output routine
  851  * SIDE EFFECTS:
  852  *
  853  * NOTES:
  854  */
  855 
  856 int
  857 tp_error_emit(error, sref, faddr, laddr, erdata, erlen, tpcb, cons_channel,
  858               dgout_routine)
  859         int             error;
  860         u_long          sref;
  861         struct sockaddr_iso *faddr, *laddr;
  862         struct mbuf    *erdata;
  863         int             erlen;
  864         struct tp_pcb  *tpcb;
  865         caddr_t         cons_channel;
  866         int           (*dgout_routine) __P((struct mbuf *, ...));
  867 {
  868         int             dutype;
  869         int             datalen = 0;
  870         struct tpdu *hdr;
  871         struct mbuf *m;
  872         int             csum_offset;
  873 
  874 #ifdef TPPT
  875         if (tp_traceflags[D_ERROR_EMIT]) {
  876                 tptrace(TPPTmisc, "tp_error_emit error sref tpcb erlen",
  877                         error, sref, tpcb, erlen);
  878         }
  879 #endif
  880 #ifdef ARGO_DEBUG
  881         if (argo_debug[D_ERROR_EMIT]) {
  882                 printf(
  883                        "tp_error_emit error 0x%x sref %lx tpcb %p erlen 0x%x chan %p\n",
  884                        error, sref, tpcb, erlen, cons_channel);
  885         }
  886 #endif
  887 
  888         MGET(m, M_DONTWAIT, TPMT_TPHDR);
  889         if (m == NULL) {
  890                 return ENOBUFS;
  891         }
  892         m->m_len = sizeof(struct tpdu);
  893         m->m_nextpkt = NULL;
  894 
  895         hdr = mtod(m, struct tpdu *);
  896 
  897 #ifdef ARGO_DEBUG
  898         if (argo_debug[D_ERROR_EMIT]) {
  899                 printf("[error 0x%x] [error&0xff  0x%x] [(char)error 0x%x]\n",
  900                        error, error & 0xff, (char) error);
  901         }
  902 #endif
  903 
  904 
  905         if (error & TP_ERROR_SNDC)
  906                 dutype = DC_TPDU_type;
  907         else if (error & 0x40) {
  908                 error &= ~0x40;
  909                 dutype = ER_TPDU_type;
  910         } else
  911                 dutype = DR_TPDU_type;
  912         error &= 0xff;
  913 
  914         hdr->tpdu_type = dutype;
  915         hdr->tpdu_cdt = 0;
  916 
  917         switch (dutype) {
  918 
  919         case DC_TPDU_type:
  920                 IncStat(ts_DC_sent);
  921                 hdr->tpdu_li = 6;
  922                 hdr->tpdu_DCdref = htons(sref);
  923                 hdr->tpdu_DCsref = tpcb ? htons(tpcb->tp_lref) : 0;
  924 #ifdef ARGO_DEBUG
  925                 if (argo_debug[D_ERROR_EMIT]) {
  926                         printf("DC case:\n");
  927                         dump_buf(hdr, 6);
  928                 }
  929 #endif
  930                 /* forget the add'l information variable part */
  931                 break;
  932 
  933         case DR_TPDU_type:
  934                 IncStat(ts_DR_sent);
  935                 hdr->tpdu_li = 7;
  936                 hdr->tpdu_DRdref = htons(sref);
  937                 hdr->tpdu_DRsref = 0;
  938                 hdr->tpdu_DRreason = (char) error;
  939 #ifdef ARGO_DEBUG
  940                 if (argo_debug[D_ERROR_EMIT]) {
  941                         printf("DR case:\n");
  942                         dump_buf(hdr, 7);
  943                 }
  944 #endif
  945                 /* forget the add'l information variable part */
  946                 break;
  947 
  948         case ER_TPDU_type:
  949                 IncStat(ts_ER_sent);
  950                 hdr->tpdu_li = 5;
  951                 hdr->tpdu_ERreason = (char) error;
  952                 hdr->tpdu_ERdref = htons(sref);
  953                 break;
  954 
  955         default:
  956                 ASSERT(0);
  957                 printf("TP PANIC: bad dutype 0x%x\n", dutype);
  958         }
  959 
  960         if (tpcb)
  961                 if (tpcb->tp_use_checksum) {
  962                         ADDOPTION(TPP_checksum, hdr, 2, csum_offset /* dummy argument */ );
  963                         csum_offset = hdr->tpdu_li - 2;
  964                 }
  965 #if 0
  966         ASSERT(hdr->tpdu_li < MLEN);
  967 #endif
  968 
  969         if (dutype == ER_TPDU_type) {
  970                 /* copy the errant tpdu into another 'variable part' */
  971                 caddr_t P;
  972 
  973 #ifdef TPPT
  974                 if (tp_traceflags[D_ERROR_EMIT]) {
  975                         tptrace(TPPTmisc, "error_emit ER len tpduli", erlen, hdr->tpdu_li,
  976                                 0, 0);
  977                 }
  978 #endif
  979 #ifdef ARGO_DEBUG
  980                 if (argo_debug[D_ERROR_EMIT]) {
  981                         printf("error_emit ER len 0x%x tpduli 0x%x\n", erlen, hdr->tpdu_li);
  982                 }
  983 #endif
  984 
  985                 /* copy at most as many octets for which you have room */
  986                 if (erlen + hdr->tpdu_li + 2 > TP_MAX_HEADER_LEN)
  987                         erlen = TP_MAX_HEADER_LEN - hdr->tpdu_li - 2;
  988 
  989                 /* add the "invalid tpdu" parameter : required in class 0 */
  990                 P = (caddr_t) hdr + (int) (hdr->tpdu_li);
  991                 vbptr(P)->tpv_code = TPP_invalid_tpdu;  /* parameter code */
  992                 vbptr(P)->tpv_len = erlen;      /* parameter length */
  993                 m->m_len = hdr->tpdu_li + 2;    /* 1 for code, 1 for length */
  994 
  995                 /*
  996                  * tp_input very likely handed us an mbuf chain w/ nothing in
  997                  * the first mbuf and the data following the empty mbuf
  998                  */
  999                 if (erdata->m_len == 0) {
 1000                         erdata = m_free(erdata);        /* returns the next mbuf
 1001                                                          * on the chain */
 1002                 }
 1003                 /*
 1004                  * copy only up to the bad octet
 1005                  * (or max that will fit in a header
 1006                  */
 1007                 m->m_next = m_copy(erdata, 0, erlen);
 1008                 hdr->tpdu_li += erlen + 2;
 1009                 m_freem(erdata);
 1010         } else {
 1011 #ifdef ARGO_DEBUG
 1012                 if (argo_debug[D_ERROR_EMIT]) {
 1013                         printf("error_emit DR error %d tpduli %x\n", error, hdr->tpdu_li);
 1014                         dump_buf((char *) hdr, hdr->tpdu_li);
 1015                 }
 1016 #endif
 1017                 m->m_len = hdr->tpdu_li;
 1018                 m_freem(erdata);
 1019         }
 1020 
 1021         hdr->tpdu_li--;
 1022 #ifdef TPPT
 1023         if (tp_traceflags[D_ERROR_EMIT]) {
 1024                 tptrace(TPPTtpduout, 2, hdr, hdr->tpdu_li + 1, 0, 0);
 1025         }
 1026 #endif
 1027 
 1028         datalen = m_datalen(m);
 1029         if (tpcb) {
 1030                 if (tpcb->tp_use_checksum) {
 1031 #ifdef TPPT
 1032                         if (tp_traceflags[D_ERROR_EMIT]) {
 1033                                 tptrace(TPPTmisc, "before gen csum datalen", datalen, 0, 0, 0);
 1034                         }
 1035 #endif
 1036 #ifdef ARGO_DEBUG
 1037                         if (argo_debug[D_ERROR_EMIT]) {
 1038                                 printf("before gen csum datalen 0x%x, csum_offset 0x%x\n",
 1039                                        datalen, csum_offset);
 1040                         }
 1041 #endif
 1042 
 1043                         iso_gen_csum(m, csum_offset, datalen);
 1044                 }
 1045 #ifdef ARGO_DEBUG
 1046                 if (argo_debug[D_ERROR_EMIT]) {
 1047                         printf("OUTPUT: tpcb %p, isop %p, so %p\n",
 1048                                tpcb, tpcb->tp_npcb, tpcb->tp_sock);
 1049                 }
 1050 #endif
 1051         }
 1052         if (cons_channel) {
 1053 #ifdef TPCONS
 1054                 struct pklcd   *lcp = (struct pklcd *) cons_channel;
 1055 #ifdef notdef
 1056                 struct isopcb  *isop = (struct isopcb *) lcp->lcd_upnext;
 1057 #endif
 1058                 tpcons_output_dg(m, datalen, cons_channel);
 1059 #ifdef notdef
 1060                 if (tpcb == 0) iso_pcbdetach(isop);
 1061 #endif
 1062                 /*
 1063                  * but other side may want to try again over same VC, so,
 1064                  * we'll depend on him closing it, but in case it gets
 1065                  * forgotten we'll mark it for garbage collection
 1066                  */
 1067                 lcp->lcd_flags |= X25_DG_CIRCUIT;
 1068 #ifdef ARGO_DEBUG
 1069                 if (argo_debug[D_ERROR_EMIT]) {
 1070                         printf("OUTPUT: dutype 0x%x channel 0x%x\n",
 1071                                dutype, cons_channel);
 1072                 }
 1073 #endif
 1074 #else
 1075                 printf("TP panic! cons channel %p but not cons configured\n",
 1076                        cons_channel);
 1077 #endif
 1078                 return 0;
 1079         } else if (tpcb) {
 1080 
 1081 #ifdef ARGO_DEBUG
 1082                 if (argo_debug[D_ERROR_EMIT]) {
 1083                         printf("tp_error_emit 1 sending DG: Laddr\n");
 1084                         dump_addr(sisotosa(laddr));
 1085                         printf("Faddr\n");
 1086                         dump_addr(sisotosa(faddr));
 1087                 }
 1088 #endif
 1089                 return (*tpcb->tp_nlproto->nlp_dgoutput) (m, datalen,
 1090                                                          &laddr->siso_addr,
 1091                                                          &faddr->siso_addr,
 1092                         /* no route */ (caddr_t) 0, !tpcb->tp_use_checksum);
 1093         } else if (dgout_routine) {
 1094 #ifdef ARGO_DEBUG
 1095                 if (argo_debug[D_ERROR_EMIT]) {
 1096                         printf("tp_error_emit sending DG: Laddr\n");
 1097                         dump_addr(sisotosa(laddr));
 1098                         printf("Faddr\n");
 1099                         dump_addr(sisotosa(faddr));
 1100                 }
 1101 #endif
 1102                 return (*dgout_routine) (m, datalen, &laddr->siso_addr, &faddr->siso_addr,
 1103                                         (caddr_t) 0, /* nochecksum==false */ 0);
 1104         } else {
 1105 #ifdef ARGO_DEBUG
 1106                 if (argo_debug[D_ERROR_EMIT]) {
 1107                         printf("tp_error_emit DROPPING %p\n", m);
 1108                 }
 1109 #endif
 1110                 IncStat(ts_send_drop);
 1111                 m_freem(m);
 1112                 return 0;
 1113         }
 1114 }

Cache object: fe80a77c3ad998d9609ece2b9f933bf5


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