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

Cache object: a2cb9cb4ceda1d1e44f8f1e08eeae3ef


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