149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*51204Ssklower * @(#)tp_emit.c 7.12 (Berkeley) 09/26/91 849268Sbostic */ 949268Sbostic 1036399Ssklower /*********************************************************** 1136399Ssklower Copyright IBM Corporation 1987 1236399Ssklower 1336399Ssklower All Rights Reserved 1436399Ssklower 1536399Ssklower Permission to use, copy, modify, and distribute this software and its 1636399Ssklower documentation for any purpose and without fee is hereby granted, 1736399Ssklower provided that the above copyright notice appear in all copies and that 1836399Ssklower both that copyright notice and this permission notice appear in 1936399Ssklower supporting documentation, and that the name of IBM not be 2036399Ssklower used in advertising or publicity pertaining to distribution of the 2136399Ssklower software without specific, written prior permission. 2236399Ssklower 2336399Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 2436399Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 2536399Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 2636399Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 2736399Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 2836399Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2936399Ssklower SOFTWARE. 3036399Ssklower 3136399Ssklower ******************************************************************/ 3236399Ssklower 3336399Ssklower /* 3436399Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 3536399Ssklower */ 3636399Ssklower /* 3736399Ssklower * ARGO TP 3836399Ssklower * 3936399Ssklower * $Header: tp_emit.c,v 5.5 88/11/18 17:27:20 nhall Exp $ 4036399Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_emit.c,v $ 4136399Ssklower * 4236399Ssklower * This file contains tp_emit() and tp_error_emit(), which 4336399Ssklower * form TPDUs and hand them to ip. 4436399Ssklower * They take data in the form of mbuf chain, allocate mbufs as 4536399Ssklower * necessary for headers, and set the fields as appropriate from 4636399Ssklower * information found in the tpcb and net-level pcb. 4736399Ssklower * 4836399Ssklower * The worst thing about this code is adding the variable-length 4936399Ssklower * options on a machine that requires alignment for any memory access 5036399Ssklower * that isn't of size 1. See the macro ADDOPTION() below. 5136399Ssklower * 5236399Ssklower * We don't do any concatenation. (There's a kludge to test the 5336399Ssklower * basic mechanism of separation under the 'w' tpdebug option, that's all.) 5436399Ssklower */ 5536399Ssklower 5636399Ssklower #include "param.h" 5736399Ssklower #include "mbuf.h" 5836399Ssklower #include "socket.h" 5936399Ssklower #include "socketvar.h" 6036399Ssklower #include "protosw.h" 6136399Ssklower #include "errno.h" 6236399Ssklower #include "types.h" 6336399Ssklower #include "time.h" 6437469Ssklower #include "iso.h" 6545900Ssklower #include "iso_pcb.h" 6637469Ssklower #include "argo_debug.h" 6737469Ssklower #include "tp_timer.h" 6837469Ssklower #include "tp_param.h" 6937469Ssklower #include "tp_stat.h" 7037469Ssklower #include "tp_pcb.h" 7137469Ssklower #include "tp_tpdu.h" 7237469Ssklower #include "tp_trace.h" 7337469Ssklower #include "tp_meas.h" 7437469Ssklower #include "tp_seq.h" 7537469Ssklower #include "iso_errno.h" 7636399Ssklower 7745900Ssklower #include "../net/if.h" 7845900Ssklower #ifdef TRUE 7945900Ssklower #undef FALSE 8045900Ssklower #undef TRUE 8145900Ssklower #endif 8245900Ssklower #include "../netccitt/x25.h" 8345900Ssklower #include "../netccitt/pk.h" 8445900Ssklower #include "../netccitt/pk_var.h" 8545900Ssklower 8636399Ssklower void iso_gen_csum(); 8736399Ssklower 8836399Ssklower 8936399Ssklower /* Here is a mighty kludge. The token ring misorders packets if you 9036399Ssklower * fire them at it too fast, and TP sans checksum is "too fast", so 9136399Ssklower * we have introduced a delay when checksumming isn't used. 9236399Ssklower */ 9336399Ssklower char tp_delay = 0x00; /* delay to keep token ring from blowing it */ 9436399Ssklower 9536399Ssklower /* 9636399Ssklower * NAME: tp_emit() 9736399Ssklower * 9836399Ssklower * CALLED FROM: tp.trans and from tp_sbsend() 9936399Ssklower * 10036399Ssklower * FUNCTION and ARGUMENTS: 10136399Ssklower * Emits one tpdu of the type (dutype), of the format appropriate 10236399Ssklower * to the connection described by the pcb (tpcb), with sequence 10336399Ssklower * number (seq) (where appropriate), end-of-tsdu bit (eot) where 10436399Ssklower * appropriate, and with the data in the mbuf chain (data). 10536399Ssklower * For DR and ER tpdus, the argument (eot) is 10636399Ssklower * the reason for issuing the tpdu rather than an end-of-tsdu indicator. 10736399Ssklower * 10836399Ssklower * RETURNS: 10936399Ssklower * 0 OK 11036399Ssklower * ENOBUFS 11136399Ssklower * E* returned from net layer output rtn 11236399Ssklower * 11336399Ssklower * SIDE EFFECTS: 11436399Ssklower * 11536399Ssklower * NOTES: 11636399Ssklower * 11736399Ssklower * WE ASSUME that the tp header + all options will fit in ONE mbuf. 11836399Ssklower * If mbufs are 256 this will most likely be true, but if they are 128 it's 11936399Ssklower * possible that they won't. 12036399Ssklower * If you used every option on the CR + max. user data you'd overrun 12136399Ssklower * 112 but unless you used > 115 bytes for the security 12236399Ssklower * parameter, it would fit in a 256-byte mbuf (240 bytes for the header) 12336399Ssklower * We don't support the security parameter, so this isn't a problem. 12436399Ssklower * If security is added, we ought to remove this assumption. 12536399Ssklower * 12636399Ssklower * We do not implement the flow control confirmation "element of procedure". 12736399Ssklower * A) it should not affect interoperability, 12836399Ssklower * B) it should not be necessary - the protocol will eventually 12936399Ssklower * straighten things out w/o FCC, as long as we don't have severely 13036399Ssklower * mismatched keepalive and inactivity timers, and 13136399Ssklower * C) it appears not to be REQUIRED, and 13236399Ssklower * D) it's incredibly grotesque, and no doubt will lengthen a few 13336399Ssklower * critical paths. 13436399Ssklower * HOWEVER, we're thinking about putting it in anyway, for 13536399Ssklower * completeness, just like we did with ack subsequencing. 13636399Ssklower */ 13736399Ssklower 13836399Ssklower int 13936399Ssklower tp_emit(dutype, tpcb, seq, eot, data) 14036399Ssklower int dutype; 14136399Ssklower struct tp_pcb *tpcb; 14236399Ssklower SeqNum seq; 14336399Ssklower u_int eot; 14436399Ssklower struct mbuf *data; 14536399Ssklower { 14636399Ssklower register struct tpdu *hdr; 14736399Ssklower register struct mbuf *m; 14836399Ssklower int csum_offset=0; 14936399Ssklower int datalen = 0; 15036399Ssklower int error = 0; 151*51204Ssklower SeqNum olduwe; 152*51204Ssklower int acking_ooo; 15336399Ssklower 15436399Ssklower /* NOTE: 15536399Ssklower * here we treat tpdu_li as if it DID include the li field, up until 15636399Ssklower * the end, at which time we subtract 1 15736399Ssklower * THis is because if we subtract 1 right away, we end up adding 15836399Ssklower * one every time we add an option. 15936399Ssklower */ 16036399Ssklower IFDEBUG(D_EMIT) 16136399Ssklower printf( 16237469Ssklower "tp_emit dutype 0x%x, tpcb 0x%x, eot 0x%x, seq 0x%x, data 0x%x", 16337469Ssklower dutype, tpcb, eot, seq, data); 16436399Ssklower ENDDEBUG 16536399Ssklower 16637469Ssklower if (dutype == CR_TPDU || dutype == CC_TPDU) { 16737469Ssklower m = (struct mbuf *) malloc((u_long)256, M_MBUF, M_DONTWAIT); 16837469Ssklower if (m) { 16937469Ssklower m->m_type = TPMT_TPHDR; 17037469Ssklower mbstat.m_mtypes[TPMT_TPHDR]++; 17137469Ssklower m->m_next = MNULL; 17249583Ssklower m->m_nextpkt = MNULL; 17349583Ssklower m->m_data = m->m_pktdat; 17449583Ssklower m->m_flags = M_PKTHDR; 17537469Ssklower } 17637469Ssklower } else { 17749583Ssklower MGETHDR(m, M_DONTWAIT, TPMT_TPHDR); 17837469Ssklower } 17949583Ssklower m->m_data += max_hdr; 18036399Ssklower if (m == NULL) { 18136399Ssklower if(data != (struct mbuf *)0) 18236399Ssklower m_freem(data); 18336399Ssklower error = ENOBUFS; 18436399Ssklower goto done; 18536399Ssklower } 18636399Ssklower m->m_len = sizeof(struct tpdu); 18736399Ssklower m->m_act = MNULL; 18836399Ssklower 18936399Ssklower hdr = mtod(m, struct tpdu *); 19037469Ssklower bzero((caddr_t)hdr, sizeof(struct tpdu)); 19136399Ssklower 19236399Ssklower { 19336399Ssklower int tp_headersize(); 19436399Ssklower 19536399Ssklower hdr->tpdu_type = dutype; 19636399Ssklower hdr->tpdu_li = tp_headersize(dutype, tpcb); 19736399Ssklower /* 19836399Ssklower * class 0 doesn't use this for DT 19936399Ssklower * it'll just get overwritten below 20036399Ssklower */ 20136399Ssklower hdr->tpdu_dref = htons(tpcb->tp_fref); 20236399Ssklower if( tpcb->tp_use_checksum || 20336399Ssklower (dutype == CR_TPDU_type && (tpcb->tp_class & TP_CLASS_4) )) { 20436399Ssklower csum_offset = hdr->tpdu_li + 2; /* DOESN'T include csum */ 20536399Ssklower ADDOPTION(TPP_checksum, hdr, 2, eot /* dummy arg */); 20636399Ssklower IFDEBUG(D_CHKSUM) 20736399Ssklower printf( 20836399Ssklower "tp_emit: csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 20936399Ssklower csum_offset, hdr->tpdu_li); 21036399Ssklower ENDDEBUG 21136399Ssklower } 21236399Ssklower /* 21336399Ssklower * VARIABLE PARTS... 21436399Ssklower */ 21536399Ssklower switch( dutype ) { 21636399Ssklower 21736399Ssklower case CR_TPDU_type: 21842494Ssklower hdr->tpdu_CRdref_0 = 0; /* must be zero */ 21939924Ssklower if (!tpcb->tp_cebit_off) { 22039924Ssklower tpcb->tp_win_recv = tp_start_win << 8; 22139924Ssklower LOCAL_CREDIT(tpcb); 22239924Ssklower CONG_INIT_SAMPLE(tpcb); 223*51204Ssklower } else 22439924Ssklower LOCAL_CREDIT(tpcb); 22536399Ssklower 22639924Ssklower 22736399Ssklower case CC_TPDU_type: 22836399Ssklower { 22936399Ssklower u_char x; 23036399Ssklower 23136399Ssklower hdr->tpdu_CCsref = htons(tpcb->tp_lref); /* same as CRsref */ 23236399Ssklower 23336399Ssklower if( tpcb->tp_class > TP_CLASS_1 ) { 23439924Ssklower /* ifdef CE_BIT, we did this in tp_input when the CR came in */ 23539924Ssklower if (tpcb->tp_cebit_off) 23639924Ssklower LOCAL_CREDIT( tpcb ); 23736399Ssklower tpcb->tp_sent_uwe = tpcb->tp_lcredit -1; 23836399Ssklower tpcb->tp_sent_rcvnxt = 1; 23936399Ssklower tpcb->tp_sent_lcdt = tpcb->tp_lcredit; 24036399Ssklower hdr->tpdu_cdt = tpcb->tp_lcredit; 24136399Ssklower } else { 24245900Ssklower #ifdef TPCONS 24345900Ssklower if (tpcb->tp_netservice == ISO_CONS) { 24445900Ssklower struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; 24545900Ssklower struct pklcd *lcp = (struct pklcd *)(isop->isop_chan); 24645900Ssklower lcp->lcd_flags &= ~X25_DG_CIRCUIT; 24745900Ssklower } 24845900Ssklower #endif 24936399Ssklower hdr->tpdu_cdt = 0; 25036399Ssklower } 25136399Ssklower hdr->tpdu_CCclass = tp_mask_to_num(tpcb->tp_class); 25236399Ssklower hdr->tpdu_CCoptions = 25336399Ssklower (tpcb->tp_xtd_format? TPO_XTD_FMT:0) | 25436399Ssklower (tpcb->tp_use_efc? TPO_USE_EFC:0); 25536399Ssklower 25636399Ssklower IFPERF(tpcb) 25736399Ssklower u_char perf_meas = tpcb->tp_perf_on; 25836399Ssklower ADDOPTION(TPP_perf_meas, hdr, sizeof(perf_meas), perf_meas); 25936399Ssklower ENDPERF 26036399Ssklower 26136399Ssklower if( dutype == CR_TPDU_type ) { 26236399Ssklower IncStat(ts_CR_sent); 26336399Ssklower 26436399Ssklower ASSERT( tpcb->tp_lsuffixlen > 0 ); 26536399Ssklower ASSERT( tpcb->tp_fsuffixlen > 0 ); 26636399Ssklower 26736399Ssklower ADDOPTION(TPP_calling_sufx, hdr, 26837469Ssklower tpcb->tp_lsuffixlen, tpcb->tp_lsuffix[0]); 26936399Ssklower ADDOPTION(TPP_called_sufx, hdr, 27037469Ssklower tpcb->tp_fsuffixlen, tpcb->tp_fsuffix[0]); 27136399Ssklower } else { 27236399Ssklower IncStat(ts_CC_sent); 27336399Ssklower } 27436399Ssklower 27536399Ssklower ADDOPTION(TPP_tpdu_size, hdr, 27636399Ssklower sizeof(tpcb->tp_tpdusize), tpcb->tp_tpdusize); 27736399Ssklower 27836399Ssklower if (tpcb->tp_class != TP_CLASS_0) { 27936399Ssklower short millisec = 500*(tpcb->tp_sendack_ticks); 28036399Ssklower 28136399Ssklower millisec = htons(millisec); 28236399Ssklower ADDOPTION(TPP_acktime, hdr, sizeof(short), millisec); 28336399Ssklower 28436399Ssklower x = (tpcb->tp_use_nxpd? TPAO_USE_NXPD: 0) 28536399Ssklower | (tpcb->tp_use_rcc? TPAO_USE_RCC : 0) 28636399Ssklower | (tpcb->tp_use_checksum?0: TPAO_NO_CSUM) 28736399Ssklower | (tpcb->tp_xpd_service? TPAO_USE_TXPD: 0); 28836399Ssklower ADDOPTION(TPP_addl_opt, hdr, 1, x); 28936399Ssklower 29036399Ssklower } 29136399Ssklower 29236399Ssklower if( (dutype == CR_TPDU_type) && (tpcb->tp_class != TP_CLASS_0)){ 29336399Ssklower 29436399Ssklower ASSERT( 1 == sizeof(tpcb->tp_vers) ); 29536399Ssklower ADDOPTION(TPP_vers, hdr, 1, tpcb->tp_vers); 29636399Ssklower 29736399Ssklower /* for each alt protocol class x, 29836399Ssklower * x = x<<4; 29936399Ssklower * option = concat(option, x); 30036399Ssklower * Well, for now we only have TP0 for an 30136399Ssklower * alternative so... this is easy. 30236399Ssklower * 30336399Ssklower * HOWEVER... There should be NO alt protocol 30436399Ssklower * class over CLNS. Need to see if the route suggests 30536399Ssklower * CONS, and iff so add alt class. 30636399Ssklower */ 30736399Ssklower x = 0; 30836399Ssklower ADDOPTION(TPP_alt_class, hdr, 1, x); 30936399Ssklower } 31036399Ssklower 31136399Ssklower if( hdr->tpdu_li > MLEN) 31236399Ssklower panic("tp_emit CR/CC"); 31336399Ssklower } 31436399Ssklower break; 31536399Ssklower 31636399Ssklower case DR_TPDU_type: 31736399Ssklower if( hdr->tpdu_DRdref == 0 ) { 31836399Ssklower /* don't issue the DR */ 31936399Ssklower goto done; 32036399Ssklower } 32136399Ssklower hdr->tpdu_cdt = 0; 32236399Ssklower hdr->tpdu_DRsref = htons(tpcb->tp_lref); 32336399Ssklower hdr->tpdu_DRreason = (u_char)eot; /* WHICH BYTE OF THIS??? */ 32436399Ssklower 32536399Ssklower /* forget the add'l information variable part */ 32636399Ssklower IncStat(ts_DR_sent); 32736399Ssklower break; 32836399Ssklower 32936399Ssklower case DC_TPDU_type: /* not used in class 0 */ 33036399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); 33136399Ssklower hdr->tpdu_DCsref = htons(tpcb->tp_lref); 33236399Ssklower hdr->tpdu_cdt = 0; 33336399Ssklower data = (struct mbuf *)0; 33436399Ssklower IncStat(ts_DC_sent); 33536399Ssklower break; 33636399Ssklower 33736399Ssklower case XAK_TPDU_type: /* xak not used in class 0 */ 33836399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); /* fall through */ 33936399Ssklower hdr->tpdu_cdt = 0; 34036399Ssklower 34136399Ssklower IFTRACE(D_XPD) 34236399Ssklower tptraceTPCB(TPPTXack, seq, 0, 0, 0, 0); 34336399Ssklower ENDTRACE 34436399Ssklower data = (struct mbuf *)0; 34536399Ssklower if (tpcb->tp_xtd_format) { 34636399Ssklower #ifdef BYTE_ORDER 34748747Ssklower union seq_type seqeotX; 34848747Ssklower 34948747Ssklower seqeotX.s_seq = seq; 35048747Ssklower seqeotX.s_eot = 1; 35148747Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 35236399Ssklower #else 35336399Ssklower hdr->tpdu_XAKseqX = seq; 35436399Ssklower #endif BYTE_ORDER 35536399Ssklower } else { 35636399Ssklower hdr->tpdu_XAKseq = seq; 35736399Ssklower } 35836399Ssklower IncStat(ts_XAK_sent); 35936399Ssklower IncPStat(tpcb, tps_XAK_sent); 36036399Ssklower break; 36136399Ssklower 36236399Ssklower case XPD_TPDU_type: /* xpd not used in class 0 */ 36336399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); /* fall through */ 36436399Ssklower hdr->tpdu_cdt = 0; 36536399Ssklower if (tpcb->tp_xtd_format) { 36636399Ssklower #ifdef BYTE_ORDER 36736399Ssklower union seq_type seqeotX; 36836399Ssklower 36936399Ssklower seqeotX.s_seq = seq; 37036399Ssklower seqeotX.s_eot = 1; 37136399Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 37236399Ssklower #else 37336399Ssklower hdr->tpdu_XPDseqX = seq; 37436399Ssklower hdr->tpdu_XPDeotX = 1; /* always 1 for XPD tpdu */ 37536399Ssklower #endif BYTE_ORDER 37636399Ssklower } else { 37736399Ssklower hdr->tpdu_XPDseq = seq; 37836399Ssklower hdr->tpdu_XPDeot = 1; /* always 1 for XPD tpdu */ 37936399Ssklower } 38036399Ssklower IncStat(ts_XPD_sent); 38136399Ssklower IncPStat(tpcb, tps_XPD_sent); 38236399Ssklower 38336399Ssklower /* kludge to test the input size checking */ 38436399Ssklower IFDEBUG(D_SIZE_CHECK) 38537469Ssklower /*if(data->m_len <= 16 && data->m_off < (MLEN-18) ) { 38636399Ssklower printf("Sending too much data on XPD: 18 bytes\n"); 38736399Ssklower data->m_len = 18; 38837469Ssklower }*/ 38936399Ssklower ENDDEBUG 39036399Ssklower break; 39136399Ssklower 39236399Ssklower case DT_TPDU_type: 39336399Ssklower hdr->tpdu_cdt = 0; 39436399Ssklower IFTRACE(D_DATA) 39536399Ssklower tptraceTPCB(TPPTmisc, "emit DT: eot seq tpdu_li", eot, seq, 39636399Ssklower hdr->tpdu_li, 0); 39736399Ssklower ENDTRACE 39836399Ssklower if (tpcb->tp_xtd_format) { 39936399Ssklower #ifdef BYTE_ORDER 40036399Ssklower union seq_type seqeotX; 40136399Ssklower 40236399Ssklower seqeotX.s_seq = seq; 40336399Ssklower seqeotX.s_eot = eot; 40436399Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 40536399Ssklower #else 40636399Ssklower hdr->tpdu_DTseqX = seq; 40736399Ssklower hdr->tpdu_DTeotX = eot; 40836399Ssklower #endif BYTE_ORDER 40936399Ssklower } else if (tpcb->tp_class == TP_CLASS_0) { 41036399Ssklower IFDEBUG(D_EMIT) 41136399Ssklower printf("DT tpdu: class 0 m 0x%x hdr 0x%x\n", m, hdr); 41236399Ssklower dump_buf( hdr, hdr->tpdu_li + 1 ); 41336399Ssklower ENDDEBUG 41436399Ssklower ((struct tp0du *)hdr)->tp0du_eot = eot; 41536399Ssklower ((struct tp0du *)hdr)->tp0du_mbz = 0; 41636399Ssklower IFDEBUG(D_EMIT) 41736399Ssklower printf("DT 2 tpdu: class 0 m 0x%x hdr 0x%x\n", m, hdr); 41836399Ssklower dump_buf( hdr, hdr->tpdu_li + 1 ); 41936399Ssklower ENDDEBUG 42036399Ssklower } else { 42136399Ssklower hdr->tpdu_DTseq = seq; 42236399Ssklower hdr->tpdu_DTeot = eot; 42336399Ssklower } 42436399Ssklower if(eot) { 42536399Ssklower IncStat(ts_EOT_sent); 42636399Ssklower } 42736399Ssklower IncStat(ts_DT_sent); 42836399Ssklower IncPStat(tpcb, tps_DT_sent); 42936399Ssklower break; 43036399Ssklower 43136399Ssklower case AK_TPDU_type:/* ak not used in class 0 */ 43236399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); 43336399Ssklower data = (struct mbuf *)0; 434*51204Ssklower olduwe = tpcb->tp_sent_uwe; 43536399Ssklower 436*51204Ssklower if (seq != tpcb->tp_sent_rcvnxt || tpcb->tp_rsycnt == 0) { 437*51204Ssklower LOCAL_CREDIT( tpcb ); 43836399Ssklower tpcb->tp_sent_uwe = 43936399Ssklower SEQ(tpcb,tpcb->tp_rcvnxt + tpcb->tp_lcredit -1); 44036399Ssklower tpcb->tp_sent_lcdt = tpcb->tp_lcredit; 441*51204Ssklower acking_ooo = 0; 442*51204Ssklower } else 443*51204Ssklower acking_ooo = 1; 44436399Ssklower 445*51204Ssklower IFDEBUG(D_RENEG) 446*51204Ssklower /* occasionally fake a reneging so 447*51204Ssklower you can test subsequencing */ 448*51204Ssklower if( olduwe & 0x1 ) { 44936399Ssklower tpcb->tp_reneged = 1; 450*51204Ssklower IncStat(ts_ldebug); 45136399Ssklower } 452*51204Ssklower ENDDEBUG 453*51204Ssklower /* Are we about to reneg on credit? 454*51204Ssklower * When might we do so? 455*51204Ssklower * a) when using optimistic credit (which we no longer do). 456*51204Ssklower * b) when drain() gets implemented (not in the plans). 457*51204Ssklower * c) when D_RENEG is on. 458*51204Ssklower * d) when DEC BIT response is implemented. 459*51204Ssklower * (not- when we do this, we'll need to implement flow control 460*51204Ssklower * confirmation) 461*51204Ssklower */ 462*51204Ssklower if( SEQ_LT(tpcb, tpcb->tp_sent_uwe, olduwe) ) { 463*51204Ssklower tpcb->tp_reneged = 1; 464*51204Ssklower IncStat(ts_lcdt_reduced); 465*51204Ssklower IFTRACE(D_CREDIT) 466*51204Ssklower tptraceTPCB(TPPTmisc, 467*51204Ssklower "RENEG: olduwe newuwe lcredit rcvnxt", 468*51204Ssklower olduwe, 469*51204Ssklower tpcb->tp_sent_uwe, tpcb->tp_lcredit, 470*51204Ssklower tpcb->tp_rcvnxt); 471*51204Ssklower ENDTRACE 472*51204Ssklower } 473*51204Ssklower IFPERF(tpcb) 474*51204Ssklower /* new lwe is less than old uwe means we're 475*51204Ssklower * acking before we received a whole window full 476*51204Ssklower */ 477*51204Ssklower if( SEQ_LT( tpcb, tpcb->tp_rcvnxt, olduwe) ) { 478*51204Ssklower /* tmp1 = number of pkts fewer than the full window */ 479*51204Ssklower register int tmp1 = 480*51204Ssklower (int) SEQ_SUB( tpcb, olduwe, tpcb->tp_rcvnxt); 48136399Ssklower 482*51204Ssklower if(tmp1 > TP_PM_MAX) 483*51204Ssklower tmp1 = TP_PM_MAX; 484*51204Ssklower IncPStat( tpcb, tps_ack_early[tmp1] ); 48536399Ssklower 486*51204Ssklower /* tmp1 = amt of new cdt we're advertising */ 487*51204Ssklower tmp1 = SEQ_SUB( tpcb, seq, tpcb->tp_sent_rcvnxt); 488*51204Ssklower if(tmp1 > TP_PM_MAX ) 489*51204Ssklower tmp1 = TP_PM_MAX; 49036399Ssklower 491*51204Ssklower IncPStat( tpcb, 492*51204Ssklower tps_cdt_acked [ tmp1 ] 493*51204Ssklower [ ((tpcb->tp_lcredit > TP_PM_MAX)? 494*51204Ssklower TP_PM_MAX:tpcb->tp_lcredit) ] ); 49536399Ssklower 496*51204Ssklower } 497*51204Ssklower ENDPERF 49836399Ssklower 49936399Ssklower IFTRACE(D_ACKSEND) 50036399Ssklower tptraceTPCB(TPPTack, seq, tpcb->tp_lcredit, tpcb->tp_sent_uwe, 50136399Ssklower tpcb->tp_r_subseq, 0); 50236399Ssklower ENDTRACE 50336399Ssklower if (tpcb->tp_xtd_format) { 50436399Ssklower #ifdef BYTE_ORDER 50548747Ssklower union seq_type seqeotX; 50648747Ssklower 50748747Ssklower seqeotX.s_seq = seq; 50848747Ssklower seqeotX.s_eot = 0; 50948747Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 51036399Ssklower hdr->tpdu_AKcdtX = htons(tpcb->tp_lcredit); 51136399Ssklower #else 51236399Ssklower hdr->tpdu_cdt = 0; 51336399Ssklower hdr->tpdu_AKseqX = seq; 51436399Ssklower hdr->tpdu_AKcdtX = tpcb->tp_lcredit; 51536399Ssklower #endif BYTE_ORDER 51636399Ssklower } else { 51736399Ssklower hdr->tpdu_AKseq = seq; 51836399Ssklower hdr->tpdu_AKcdt = tpcb->tp_lcredit; 51936399Ssklower } 520*51204Ssklower if ((tpcb->tp_class == TP_CLASS_4) && 521*51204Ssklower (tpcb->tp_reneged || acking_ooo)) { 52236399Ssklower /* 52336399Ssklower * Ack subsequence parameter req'd if WE reneged on 52436399Ssklower * credit offered. (ISO 8073, 12.2.3.8.2, p. 74) 52536399Ssklower */ 52636399Ssklower IFDEBUG(D_RENEG) 52736399Ssklower printf("Adding subseq 0x%x\n", tpcb->tp_s_subseq); 52836399Ssklower ENDDEBUG 52936399Ssklower tpcb->tp_s_subseq++; 53036399Ssklower /* 53136399Ssklower * add tmp subseq and do a htons on it. 53236399Ssklower */ 53336399Ssklower ADDOPTION(TPP_subseq, hdr, 53436399Ssklower sizeof(tpcb->tp_s_subseq), tpcb->tp_s_subseq); 53536399Ssklower } else 53636399Ssklower tpcb->tp_s_subseq = 0; 53736399Ssklower 53836399Ssklower if ( tpcb->tp_sendfcc || eot ) /* overloaded to mean SEND FCC */ { 53936399Ssklower /* 54036399Ssklower * Rules for sending FCC ("should" send when) : 54136399Ssklower * %a) received an ack from peer with NO NEWS whatsoever, 54236399Ssklower * and it did not contain an FCC 54336399Ssklower * b) received an ack from peer that opens its closed window. 54436399Ssklower * c) received an ack from peer after it reneged on its 54536399Ssklower * offered credit, AND this ack raises UWE but LWE is same 54636399Ssklower * and below UWE at time of reneging (reduction) 54736399Ssklower * Now, ISO 8073 12.2.3.8.3 says 54836399Ssklower * that a retransmitted AK shall not contain the FCC 54936399Ssklower * parameter. Now, how the hell you tell the difference 55036399Ssklower * between a retransmitted ack and an ack that's sent in 55136399Ssklower * response to a received ack, I don't know, because without 55236399Ssklower * any local activity, and w/o any received DTs, they 55336399Ssklower * will contain exactly the same credit/seq# information. 55436399Ssklower * Anyway, given that the "retransmission of acks" 55536399Ssklower * procedure (ISO 8073 12.2.3.8.3) is optional, and we 55636399Ssklower * don't do it (although the peer can't tell that), we 55736399Ssklower * ignore this last rule. 55836399Ssklower * 55936399Ssklower * We send FCC for reasons a) and b) only. 56036399Ssklower * To add reason c) would require a ridiculous amount of state. 56136399Ssklower * 56236399Ssklower */ 56336399Ssklower u_short bogus[4]; /* lwe(32), subseq(16), cdt(16) */ 56436399Ssklower SeqNum lwe; 56536399Ssklower u_short subseq, fcredit; 56636399Ssklower 56736399Ssklower tpcb->tp_sendfcc = 0; 56836399Ssklower 56936399Ssklower lwe = (SeqNum) htonl(tpcb->tp_snduna); 57036399Ssklower subseq = htons(tpcb->tp_r_subseq); 57136399Ssklower fcredit = htons(tpcb->tp_fcredit); 57236399Ssklower 57337469Ssklower bcopy((caddr_t) &lwe, (caddr_t)&bogus[0], sizeof(SeqNum)); 57437469Ssklower bcopy((caddr_t) &subseq, (caddr_t)&bogus[2], sizeof(u_short)); 57537469Ssklower bcopy((caddr_t) &fcredit, (caddr_t)&bogus[3], sizeof(u_short)); 57636399Ssklower 57736399Ssklower IFTRACE(D_ACKSEND) 57836399Ssklower tptraceTPCB(TPPTmisc, 57936399Ssklower "emit w/FCC: snduna r_subseq fcredit", 58036399Ssklower tpcb->tp_snduna, tpcb->tp_r_subseq, 58136399Ssklower tpcb->tp_fcredit, 0); 58236399Ssklower ENDTRACE 58336399Ssklower 58436399Ssklower IFDEBUG(D_ACKSEND) 58536399Ssklower printf("Calling ADDOPTION 0x%x, 0x%x, 0x%x,0x%x\n", 58636399Ssklower TPP_flow_cntl_conf, 58736399Ssklower hdr, sizeof(bogus), bogus[0]); 58836399Ssklower ENDDEBUG 58936399Ssklower ADDOPTION(TPP_flow_cntl_conf, hdr, sizeof(bogus), bogus[0]); 59036399Ssklower IFDEBUG(D_ACKSEND) 59136399Ssklower printf("after ADDOPTION hdr 0x%x hdr->tpdu_li 0x%x\n", 59236399Ssklower hdr, hdr->tpdu_li); 59336399Ssklower printf( 59436399Ssklower "after ADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 59536399Ssklower csum_offset, hdr->tpdu_li); 59636399Ssklower ENDDEBUG 59736399Ssklower 59836399Ssklower } 59936399Ssklower tpcb->tp_reneged = 0; 60036399Ssklower tpcb->tp_sent_rcvnxt = seq; 601*51204Ssklower if (tpcb->tp_fcredit == 0) { 602*51204Ssklower int timo = tpcb->tp_keepalive_ticks; 603*51204Ssklower if (tpcb->tp_rxtshift < TP_MAXRXTSHIFT) 604*51204Ssklower tpcb->tp_rxtshift++; 605*51204Ssklower timo = min(timo, ((int)tpcb->tp_dt_ticks) << tpcb->tp_rxtshift); 606*51204Ssklower tp_ctimeout(tpcb, TM_sendack, timo); 607*51204Ssklower } else 608*51204Ssklower tp_ctimeout(tpcb, TM_sendack, tpcb->tp_keepalive_ticks); 60936399Ssklower IncStat(ts_AK_sent); 61036399Ssklower IncPStat(tpcb, tps_AK_sent); 61136399Ssklower IFDEBUG(D_ACKSEND) 61236399Ssklower printf( 61336399Ssklower "2 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 61436399Ssklower csum_offset, hdr->tpdu_li); 61536399Ssklower ENDDEBUG 61636399Ssklower break; 61736399Ssklower 61836399Ssklower case ER_TPDU_type: 61936399Ssklower hdr->tpdu_ERreason = eot; 62036399Ssklower hdr->tpdu_cdt = 0; 62136399Ssklower /* no user data */ 62236399Ssklower data = (struct mbuf *)0; 62336399Ssklower IncStat(ts_ER_sent); 62436399Ssklower break; 62536399Ssklower } 62636399Ssklower 62736399Ssklower } 62836399Ssklower ASSERT( ((int)hdr->tpdu_li > 0) && ((int)hdr->tpdu_li < MLEN) ); 62936399Ssklower 63036399Ssklower m->m_next = data; 63136399Ssklower 63237469Ssklower ASSERT( hdr->tpdu_li < MLEN ); /* leave this in */ 63336399Ssklower ASSERT( hdr->tpdu_li != 0 ); /* leave this in */ 63436399Ssklower 63536399Ssklower m->m_len = hdr->tpdu_li ; 63636399Ssklower hdr->tpdu_li --; /* doesn't include the li field */ 63736399Ssklower 63836399Ssklower datalen = m_datalen( m ); /* total len */ 63936399Ssklower 64036399Ssklower ASSERT( datalen <= tpcb->tp_l_tpdusize ); /* may become a problem 64136399Ssklower when CLNP is used; leave in here for the time being */ 64236399Ssklower IFDEBUG(D_ACKSEND) 64336399Ssklower printf( 64436399Ssklower "4 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 64536399Ssklower csum_offset, hdr->tpdu_li); 64636399Ssklower ENDDEBUG 64736399Ssklower if( datalen > tpcb->tp_l_tpdusize ) { 64836399Ssklower printf("data len 0x%x tpcb->tp_l_tpdusize 0x%x\n", 64936399Ssklower datalen, tpcb->tp_l_tpdusize); 65036399Ssklower } 65136399Ssklower IFDEBUG(D_EMIT) 65236399Ssklower printf( 65336399Ssklower "tp_emit before gen_csum m_len 0x%x, csum_offset 0x%x, datalen 0x%x\n", 65436399Ssklower m->m_len, csum_offset, datalen); 65536399Ssklower ENDDEBUG 65636399Ssklower if( tpcb->tp_use_checksum || 65736399Ssklower (dutype == CR_TPDU_type && (tpcb->tp_class & TP_CLASS_4)) ) { 65836399Ssklower iso_gen_csum(m, csum_offset, datalen); 65936399Ssklower } 66036399Ssklower 66136399Ssklower IFDEBUG(D_EMIT) 66236399Ssklower printf("tp_emit before tpxxx_output tpcb 0x%x, dutype 0x%x, datalen 0x%x\n", 66336399Ssklower tpcb, dutype, datalen); 66437469Ssklower dump_buf(mtod(m, caddr_t), datalen); 66536399Ssklower ENDDEBUG 66636399Ssklower 66736399Ssklower IFPERF(tpcb) 66836399Ssklower if( dutype == DT_TPDU_type ) { 66936399Ssklower PStat(tpcb, Nb_to_ll) += (datalen - m->m_len); 67037469Ssklower tpmeas( tpcb->tp_lref, TPtime_to_ll, (struct timeval *)0, 67136399Ssklower seq, PStat(tpcb, Nb_to_ll), (datalen - m->m_len)); 67236399Ssklower } 67336399Ssklower ENDPERF 67436399Ssklower 67536399Ssklower IFTRACE(D_EMIT) 67636399Ssklower tptraceTPCB(TPPTtpduout, dutype, hdr, hdr->tpdu_li+1, datalen, 0); 67736399Ssklower ENDTRACE 67836399Ssklower IFDEBUG(D_EMIT) 67936399Ssklower printf("OUTPUT: tpcb 0x%x, isop 0x%x, so 0x%x\n", 68036399Ssklower tpcb, tpcb->tp_npcb, tpcb->tp_sock); 68136399Ssklower ENDDEBUG 68236399Ssklower 68336399Ssklower { extern char tp_delay; 68436399Ssklower 68536399Ssklower if( tp_delay ) 68636399Ssklower if( tpcb->tp_use_checksum == 0 ) { 68736399Ssklower register u_int i = tp_delay; 68836399Ssklower for (; i!= 0; i--) 68936399Ssklower (void) iso_check_csum(m, datalen); 69036399Ssklower } 69136399Ssklower } 69236399Ssklower ASSERT( m->m_len > 0 ); 69336399Ssklower error = (tpcb->tp_nlproto->nlp_output)(tpcb->tp_npcb, m, datalen, 69436399Ssklower !tpcb->tp_use_checksum); 69536399Ssklower IFDEBUG(D_EMIT) 69636399Ssklower printf("OUTPUT: returned 0x%x\n", error); 69736399Ssklower ENDDEBUG 69836399Ssklower IFTRACE(D_EMIT) 69936399Ssklower tptraceTPCB(TPPTmisc, 70036399Ssklower "tp_emit nlproto->output netservice returns datalen", 70136399Ssklower tpcb->tp_nlproto->nlp_output, tpcb->tp_netservice, error, datalen); 70236399Ssklower ENDTRACE 70336399Ssklower done: 704*51204Ssklower if (error) { 705*51204Ssklower if (dutype == AK_TPDU_type) 706*51204Ssklower tp_ctimeout(tpcb, TM_sendack, 1); 707*51204Ssklower if (error == E_CO_QFULL) { 708*51204Ssklower tp_quench(tpcb, PRC_QUENCH); 709*51204Ssklower return 0; 710*51204Ssklower } 71136399Ssklower } 71236399Ssklower return error; 71336399Ssklower } 71436399Ssklower /* 71536399Ssklower * NAME: tp_error_emit() 71636399Ssklower * CALLED FROM: tp_input() when a DR or ER is to be issued in 71736399Ssklower * response to an input error. 71836399Ssklower * FUNCTION and ARGUMENTS: 71936399Ssklower * The error type is the first argument. 72036399Ssklower * The argument (sref) is the source reference on the bad incoming tpdu, 72136399Ssklower * and is used for a destination reference on the outgoing packet. 72236399Ssklower * (faddr) and (laddr) are the foreign and local addresses for this 72336399Ssklower * connection. 72436399Ssklower * (erdata) is a ptr to the errant incoming tpdu, and is copied into the 72536399Ssklower * outgoing ER, if an ER is to be issued. 72636399Ssklower * (erlen) is the number of octets of the errant tpdu that we should 72736399Ssklower * try to copy. 72836399Ssklower * (tpcb) is the pcb that describes the connection for which the bad tpdu 72936399Ssklower * arrived. 73036399Ssklower * RETURN VALUES: 73136399Ssklower * 0 OK 73236399Ssklower * ENOBUFS 73336399Ssklower * E* from net layer datagram output routine 73436399Ssklower * SIDE EFFECTS: 73536399Ssklower * 73636399Ssklower * NOTES: 73736399Ssklower */ 73836399Ssklower 73936399Ssklower int 74036399Ssklower tp_error_emit(error, sref, faddr, laddr, erdata, erlen, tpcb, cons_channel, 74136399Ssklower dgout_routine) 74236399Ssklower int error; 74336399Ssklower u_long sref; 74436399Ssklower struct sockaddr_iso *faddr, *laddr; 74536399Ssklower struct mbuf *erdata; 74636399Ssklower int erlen; 74736399Ssklower struct tp_pcb *tpcb; 74850535Ssklower caddr_t cons_channel; 74936399Ssklower int (*dgout_routine)(); 75036399Ssklower { 75136399Ssklower int dutype; 75236399Ssklower int datalen = 0; 75336399Ssklower register struct tpdu *hdr; 75436399Ssklower register struct mbuf *m; 75536399Ssklower int csum_offset; 75636399Ssklower 75736399Ssklower IFTRACE(D_ERROR_EMIT) 75836399Ssklower tptrace(TPPTmisc, "tp_error_emit error sref tpcb erlen", 75936399Ssklower error, sref, tpcb, erlen); 76036399Ssklower ENDTRACE 76136399Ssklower IFDEBUG(D_ERROR_EMIT) 76236399Ssklower printf( 76336399Ssklower "tp_error_emit error 0x%x sref 0x%x tpcb 0x%x erlen 0x%x chan 0x%x\n", 76436399Ssklower error, sref, tpcb, erlen, cons_channel); 76536399Ssklower ENDDEBUG 76636399Ssklower 76736399Ssklower MGET(m, M_DONTWAIT, TPMT_TPHDR); 76836399Ssklower if (m == NULL) { 76936399Ssklower return ENOBUFS; 77036399Ssklower } 77136399Ssklower m->m_len = sizeof(struct tpdu); 77236399Ssklower m->m_act = MNULL; 77336399Ssklower 77436399Ssklower hdr = mtod(m, struct tpdu *); 77536399Ssklower 77636399Ssklower IFDEBUG(D_ERROR_EMIT) 77736399Ssklower printf("[error 0x%x] [error&0xff 0x%x] [(char)error 0x%x]\n", 77836399Ssklower error, error&0xff, (char)error); 77936399Ssklower ENDDEBUG 78036399Ssklower 78136399Ssklower 78242494Ssklower if (error & TP_ERROR_SNDC) 78342494Ssklower dutype = DC_TPDU_type; 78442494Ssklower else if (error & 0x40) { 78536399Ssklower error &= ~0x40; 78636399Ssklower dutype = ER_TPDU_type; 78736399Ssklower } else 78836399Ssklower dutype = DR_TPDU_type; 78942494Ssklower error &= 0xff; 79036399Ssklower 79136399Ssklower hdr->tpdu_type = dutype; 79236399Ssklower hdr->tpdu_cdt = 0; 79336399Ssklower 79436399Ssklower switch( dutype ) { 79536399Ssklower 79642494Ssklower case DC_TPDU_type: 79742494Ssklower IncStat(ts_DC_sent); 79842494Ssklower hdr->tpdu_li = 6; 79942494Ssklower hdr->tpdu_DCdref = htons(sref); 80042494Ssklower hdr->tpdu_DCsref = tpcb ? htons(tpcb->tp_lref) : 0; 80142494Ssklower IFDEBUG(D_ERROR_EMIT) 80242494Ssklower printf("DC case:\n"); 80342494Ssklower dump_buf( hdr, 6); 80442494Ssklower ENDDEBUG 80542494Ssklower /* forget the add'l information variable part */ 80642494Ssklower break; 80742494Ssklower 80836399Ssklower case DR_TPDU_type: 80936399Ssklower IncStat(ts_DR_sent); 81036399Ssklower hdr->tpdu_li = 7; 81136399Ssklower hdr->tpdu_DRdref = htons(sref); 81242494Ssklower hdr->tpdu_DRsref = 0; 81336399Ssklower hdr->tpdu_DRreason = (char)error; 81436399Ssklower IFDEBUG(D_ERROR_EMIT) 81536399Ssklower printf("DR case:\n"); 81636399Ssklower dump_buf( hdr, 7); 81736399Ssklower ENDDEBUG 81836399Ssklower /* forget the add'l information variable part */ 81936399Ssklower break; 82036399Ssklower 82136399Ssklower case ER_TPDU_type: 82236399Ssklower IncStat(ts_ER_sent); 82336399Ssklower hdr->tpdu_li = 5; 82436399Ssklower hdr->tpdu_ERreason = (char)error; 82550535Ssklower hdr->tpdu_ERdref = htons(sref); 82636399Ssklower break; 82736399Ssklower 82836399Ssklower default: 82936399Ssklower ASSERT(0); 83036399Ssklower printf("TP PANIC: bad dutype 0x%x\n", dutype); 83136399Ssklower } 83236399Ssklower 83336399Ssklower if(tpcb) 83436399Ssklower if( tpcb->tp_use_checksum ) { 83536399Ssklower ADDOPTION(TPP_checksum, hdr, 2, csum_offset /* dummy argument */); 83636399Ssklower csum_offset = hdr->tpdu_li - 2; 83736399Ssklower } 83836399Ssklower 83937469Ssklower ASSERT( hdr->tpdu_li < MLEN ); 84036399Ssklower 84136399Ssklower if (dutype == ER_TPDU_type) { 84236399Ssklower /* copy the errant tpdu into another 'variable part' */ 84336399Ssklower register caddr_t P; 84436399Ssklower 84536399Ssklower IFTRACE(D_ERROR_EMIT) 84636399Ssklower tptrace(TPPTmisc, "error_emit ER len tpduli", erlen, hdr->tpdu_li, 84736399Ssklower 0,0); 84836399Ssklower ENDTRACE 84936399Ssklower IFDEBUG(D_ERROR_EMIT) 85036399Ssklower printf("error_emit ER len 0x%x tpduli 0x%x\n", erlen, hdr->tpdu_li); 85136399Ssklower ENDDEBUG 85236399Ssklower 85336399Ssklower /* copy at most as many octets for which you have room */ 85436399Ssklower if (erlen + hdr->tpdu_li + 2 > TP_MAX_HEADER_LEN) 85536399Ssklower erlen = TP_MAX_HEADER_LEN - hdr->tpdu_li - 2; 85636399Ssklower 85736399Ssklower /* add the "invalid tpdu" parameter : required in class 0 */ 85836399Ssklower P = (caddr_t)hdr + (int)(hdr->tpdu_li); 85936399Ssklower vbptr(P)->tpv_code = TPP_invalid_tpdu; /* parameter code */ 86036399Ssklower vbptr(P)->tpv_len = erlen; /* parameter length */ 86136399Ssklower m->m_len = hdr->tpdu_li + 2; /* 1 for code, 1 for length */ 86236399Ssklower 86336399Ssklower /* tp_input very likely handed us an mbuf chain w/ nothing in 86436399Ssklower * the first mbuf and the data following the empty mbuf 86536399Ssklower */ 86636399Ssklower if(erdata->m_len == 0) { 86736399Ssklower erdata = m_free(erdata); /* returns the next mbuf on the chain */ 86836399Ssklower } 86937469Ssklower /* 87037469Ssklower * copy only up to the bad octet 87137469Ssklower * (or max that will fit in a header 87237469Ssklower */ 87337469Ssklower m->m_next = m_copy(erdata, 0, erlen); 87436399Ssklower hdr->tpdu_li += erlen + 2; 87536399Ssklower m_freem(erdata); 87636399Ssklower } else { 87736399Ssklower IFDEBUG(D_ERROR_EMIT) 87836399Ssklower printf("error_emit DR error tpduli 0x%x\n", error, hdr->tpdu_li); 87936399Ssklower dump_buf( (char *)hdr, hdr->tpdu_li ); 88036399Ssklower ENDDEBUG 88136399Ssklower m->m_len = hdr->tpdu_li ; 88236399Ssklower m_freem(erdata); 88336399Ssklower } 88436399Ssklower 88536399Ssklower hdr->tpdu_li --; 88636399Ssklower IFTRACE(D_ERROR_EMIT) 88736399Ssklower tptrace(TPPTtpduout, 2, hdr, hdr->tpdu_li+1, 0, 0); 88836399Ssklower ENDTRACE 88936399Ssklower 89036399Ssklower datalen = m_datalen( m); 89150648Ssklower if (tpcb) { 89236399Ssklower if( tpcb->tp_use_checksum ) { 89336399Ssklower IFTRACE(D_ERROR_EMIT) 89436399Ssklower tptrace(TPPTmisc, "before gen csum datalen", datalen,0,0,0); 89536399Ssklower ENDTRACE 89636399Ssklower IFDEBUG(D_ERROR_EMIT) 89736399Ssklower printf("before gen csum datalen 0x%x, csum_offset 0x%x\n", 89836399Ssklower datalen, csum_offset); 89936399Ssklower ENDDEBUG 90036399Ssklower 90136399Ssklower iso_gen_csum(m, csum_offset, datalen); 90236399Ssklower } 90336399Ssklower 90436399Ssklower IFDEBUG(D_ERROR_EMIT) 90536399Ssklower printf("OUTPUT: tpcb 0x%x, isop 0x%x, so 0x%x\n", 90636399Ssklower tpcb, tpcb->tp_npcb, tpcb->tp_sock); 90736399Ssklower ENDDEBUG 90850648Ssklower } 90950648Ssklower if (cons_channel) { 91050648Ssklower #ifdef TPCONS 91150648Ssklower struct pklcd *lcp = (struct pklcd *)cons_channel; 91250648Ssklower struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext; 91336399Ssklower 91450648Ssklower tpcons_dg_output(cons_channel, m, datalen); 91550648Ssklower /* was if (tpcb == 0) iso_pcbdetach(isop); */ 91650648Ssklower /* but other side may want to try again over same VC, 91750648Ssklower so, we'll depend on him closing it, but in case it gets forgotten 91850648Ssklower we'll mark it for garbage collection */ 91950648Ssklower lcp->lcd_flags |= X25_DG_CIRCUIT; 92036399Ssklower IFDEBUG(D_ERROR_EMIT) 92150648Ssklower printf("OUTPUT: dutype 0x%x channel 0x%x\n", 92250648Ssklower dutype, cons_channel); 92350648Ssklower ENDDEBUG 92450648Ssklower #else 92550648Ssklower printf("TP panic! cons channel 0x%x but not cons configured\n", 92650648Ssklower cons_channel); 92750648Ssklower #endif 92850648Ssklower } else if (tpcb) { 92950648Ssklower 93050648Ssklower IFDEBUG(D_ERROR_EMIT) 93136399Ssklower printf("tp_error_emit 1 sending DG: Laddr\n"); 93237469Ssklower dump_addr((struct sockaddr *)laddr); 93336399Ssklower printf("Faddr\n"); 93437469Ssklower dump_addr((struct sockaddr *)faddr); 93536399Ssklower ENDDEBUG 93636399Ssklower return (tpcb->tp_nlproto->nlp_dgoutput)( 93736399Ssklower &laddr->siso_addr, 93836399Ssklower &faddr->siso_addr, 93936399Ssklower m, datalen, 94036399Ssklower /* no route */ (caddr_t)0, !tpcb->tp_use_checksum); 94150648Ssklower } else if (dgout_routine) { 94236399Ssklower IFDEBUG(D_ERROR_EMIT) 94336399Ssklower printf("tp_error_emit sending DG: Laddr\n"); 94437469Ssklower dump_addr((struct sockaddr *)laddr); 94536399Ssklower printf("Faddr\n"); 94637469Ssklower dump_addr((struct sockaddr *)faddr); 94736399Ssklower ENDDEBUG 94850648Ssklower return (*dgout_routine)( &laddr->siso_addr, &faddr->siso_addr, 94950648Ssklower m, datalen, /* no route */ 95050648Ssklower (caddr_t)0, /* nochecksum==false */0); 95150648Ssklower } else { 95236399Ssklower IFDEBUG(D_ERROR_EMIT) 95336399Ssklower printf("tp_error_emit DROPPING \n", m); 95436399Ssklower ENDDEBUG 95536399Ssklower IncStat(ts_send_drop); 95636399Ssklower m_freem(m); 95736399Ssklower return 0; 95836399Ssklower } 95936399Ssklower } 960