149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*53686Ssklower * @(#)tp_emit.c 7.14 (Berkeley) 05/27/92 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; 15151204Ssklower SeqNum olduwe; 15251204Ssklower 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 */ 219*53686Ssklower case CC_TPDU_type: 22039924Ssklower if (!tpcb->tp_cebit_off) { 22139924Ssklower tpcb->tp_win_recv = tp_start_win << 8; 22239924Ssklower LOCAL_CREDIT(tpcb); 22339924Ssklower CONG_INIT_SAMPLE(tpcb); 22451204Ssklower } else 22539924Ssklower LOCAL_CREDIT(tpcb); 22636399Ssklower 227*53686Ssklower /* Case CC_TPDU_type used to be here */ 228*53686Ssklower { 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 ) { 23436399Ssklower tpcb->tp_sent_uwe = tpcb->tp_lcredit -1; 23536399Ssklower tpcb->tp_sent_rcvnxt = 1; 23636399Ssklower tpcb->tp_sent_lcdt = tpcb->tp_lcredit; 23736399Ssklower hdr->tpdu_cdt = tpcb->tp_lcredit; 23836399Ssklower } else { 23945900Ssklower #ifdef TPCONS 24045900Ssklower if (tpcb->tp_netservice == ISO_CONS) { 24145900Ssklower struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; 24245900Ssklower struct pklcd *lcp = (struct pklcd *)(isop->isop_chan); 24345900Ssklower lcp->lcd_flags &= ~X25_DG_CIRCUIT; 24445900Ssklower } 24545900Ssklower #endif 24636399Ssklower hdr->tpdu_cdt = 0; 24736399Ssklower } 24836399Ssklower hdr->tpdu_CCclass = tp_mask_to_num(tpcb->tp_class); 24936399Ssklower hdr->tpdu_CCoptions = 25036399Ssklower (tpcb->tp_xtd_format? TPO_XTD_FMT:0) | 25136399Ssklower (tpcb->tp_use_efc? TPO_USE_EFC:0); 25236399Ssklower 25336399Ssklower IFPERF(tpcb) 25436399Ssklower u_char perf_meas = tpcb->tp_perf_on; 25536399Ssklower ADDOPTION(TPP_perf_meas, hdr, sizeof(perf_meas), perf_meas); 25636399Ssklower ENDPERF 25736399Ssklower 25836399Ssklower if( dutype == CR_TPDU_type ) { 25936399Ssklower IncStat(ts_CR_sent); 26036399Ssklower 26136399Ssklower ASSERT( tpcb->tp_lsuffixlen > 0 ); 26236399Ssklower ASSERT( tpcb->tp_fsuffixlen > 0 ); 26336399Ssklower 26436399Ssklower ADDOPTION(TPP_calling_sufx, hdr, 26537469Ssklower tpcb->tp_lsuffixlen, tpcb->tp_lsuffix[0]); 26636399Ssklower ADDOPTION(TPP_called_sufx, hdr, 26737469Ssklower tpcb->tp_fsuffixlen, tpcb->tp_fsuffix[0]); 26836399Ssklower } else { 26936399Ssklower IncStat(ts_CC_sent); 27036399Ssklower } 27136399Ssklower 27236399Ssklower ADDOPTION(TPP_tpdu_size, hdr, 27336399Ssklower sizeof(tpcb->tp_tpdusize), tpcb->tp_tpdusize); 27436399Ssklower 27536399Ssklower if (tpcb->tp_class != TP_CLASS_0) { 27636399Ssklower short millisec = 500*(tpcb->tp_sendack_ticks); 27736399Ssklower 27836399Ssklower millisec = htons(millisec); 27936399Ssklower ADDOPTION(TPP_acktime, hdr, sizeof(short), millisec); 28036399Ssklower 28136399Ssklower x = (tpcb->tp_use_nxpd? TPAO_USE_NXPD: 0) 28236399Ssklower | (tpcb->tp_use_rcc? TPAO_USE_RCC : 0) 28336399Ssklower | (tpcb->tp_use_checksum?0: TPAO_NO_CSUM) 28436399Ssklower | (tpcb->tp_xpd_service? TPAO_USE_TXPD: 0); 28536399Ssklower ADDOPTION(TPP_addl_opt, hdr, 1, x); 28636399Ssklower 28751996Ssklower if ((tpcb->tp_l_tpdusize ^ (1 << tpcb->tp_tpdusize)) != 0) { 28851996Ssklower u_short size_s = tpcb->tp_l_tpdusize >> 7; 28951996Ssklower u_char size_c = size_s; 29051996Ssklower ASSERT(tpcb->tp_l_tpdusize < 65536 * 128); 29151996Ssklower if (dutype == CR_TPDU_type) 29251996Ssklower tpcb->tp_ptpdusize = size_s; 29351996Ssklower if (size_s < 256) { 29451996Ssklower ADDOPTION(TPP_ptpdu_size, hdr, 1, size_c); 29551996Ssklower } else { 29651996Ssklower size_s = htons(size_s); 29751996Ssklower ADDOPTION(TPP_ptpdu_size, hdr, 2, size_s); 29851996Ssklower } 29951996Ssklower } 30036399Ssklower } 30136399Ssklower 30236399Ssklower if( (dutype == CR_TPDU_type) && (tpcb->tp_class != TP_CLASS_0)){ 30336399Ssklower 30436399Ssklower ASSERT( 1 == sizeof(tpcb->tp_vers) ); 30536399Ssklower ADDOPTION(TPP_vers, hdr, 1, tpcb->tp_vers); 30636399Ssklower 30736399Ssklower /* for each alt protocol class x, 30836399Ssklower * x = x<<4; 30936399Ssklower * option = concat(option, x); 31036399Ssklower * Well, for now we only have TP0 for an 31136399Ssklower * alternative so... this is easy. 31236399Ssklower * 31336399Ssklower * HOWEVER... There should be NO alt protocol 31436399Ssklower * class over CLNS. Need to see if the route suggests 31536399Ssklower * CONS, and iff so add alt class. 31636399Ssklower */ 31736399Ssklower x = 0; 31836399Ssklower ADDOPTION(TPP_alt_class, hdr, 1, x); 31936399Ssklower } 32036399Ssklower 32136399Ssklower if( hdr->tpdu_li > MLEN) 32236399Ssklower panic("tp_emit CR/CC"); 32336399Ssklower } 32436399Ssklower break; 32536399Ssklower 32636399Ssklower case DR_TPDU_type: 32736399Ssklower if( hdr->tpdu_DRdref == 0 ) { 32836399Ssklower /* don't issue the DR */ 32936399Ssklower goto done; 33036399Ssklower } 33136399Ssklower hdr->tpdu_cdt = 0; 33236399Ssklower hdr->tpdu_DRsref = htons(tpcb->tp_lref); 33336399Ssklower hdr->tpdu_DRreason = (u_char)eot; /* WHICH BYTE OF THIS??? */ 33436399Ssklower 33536399Ssklower /* forget the add'l information variable part */ 33636399Ssklower IncStat(ts_DR_sent); 33736399Ssklower break; 33836399Ssklower 33936399Ssklower case DC_TPDU_type: /* not used in class 0 */ 34036399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); 34136399Ssklower hdr->tpdu_DCsref = htons(tpcb->tp_lref); 34236399Ssklower hdr->tpdu_cdt = 0; 34336399Ssklower data = (struct mbuf *)0; 34436399Ssklower IncStat(ts_DC_sent); 34536399Ssklower break; 34636399Ssklower 34736399Ssklower case XAK_TPDU_type: /* xak not used in class 0 */ 34836399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); /* fall through */ 34936399Ssklower hdr->tpdu_cdt = 0; 35036399Ssklower 35136399Ssklower IFTRACE(D_XPD) 35236399Ssklower tptraceTPCB(TPPTXack, seq, 0, 0, 0, 0); 35336399Ssklower ENDTRACE 35436399Ssklower data = (struct mbuf *)0; 35536399Ssklower if (tpcb->tp_xtd_format) { 35636399Ssklower #ifdef BYTE_ORDER 35748747Ssklower union seq_type seqeotX; 35848747Ssklower 35948747Ssklower seqeotX.s_seq = seq; 36048747Ssklower seqeotX.s_eot = 1; 36148747Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 36236399Ssklower #else 36336399Ssklower hdr->tpdu_XAKseqX = seq; 36436399Ssklower #endif BYTE_ORDER 36536399Ssklower } else { 36636399Ssklower hdr->tpdu_XAKseq = seq; 36736399Ssklower } 36836399Ssklower IncStat(ts_XAK_sent); 36936399Ssklower IncPStat(tpcb, tps_XAK_sent); 37036399Ssklower break; 37136399Ssklower 37236399Ssklower case XPD_TPDU_type: /* xpd not used in class 0 */ 37336399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); /* fall through */ 37436399Ssklower hdr->tpdu_cdt = 0; 37536399Ssklower if (tpcb->tp_xtd_format) { 37636399Ssklower #ifdef BYTE_ORDER 37736399Ssklower union seq_type seqeotX; 37836399Ssklower 37936399Ssklower seqeotX.s_seq = seq; 38036399Ssklower seqeotX.s_eot = 1; 38136399Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 38236399Ssklower #else 38336399Ssklower hdr->tpdu_XPDseqX = seq; 38436399Ssklower hdr->tpdu_XPDeotX = 1; /* always 1 for XPD tpdu */ 38536399Ssklower #endif BYTE_ORDER 38636399Ssklower } else { 38736399Ssklower hdr->tpdu_XPDseq = seq; 38836399Ssklower hdr->tpdu_XPDeot = 1; /* always 1 for XPD tpdu */ 38936399Ssklower } 39036399Ssklower IncStat(ts_XPD_sent); 39136399Ssklower IncPStat(tpcb, tps_XPD_sent); 39236399Ssklower 39336399Ssklower /* kludge to test the input size checking */ 39436399Ssklower IFDEBUG(D_SIZE_CHECK) 39537469Ssklower /*if(data->m_len <= 16 && data->m_off < (MLEN-18) ) { 39636399Ssklower printf("Sending too much data on XPD: 18 bytes\n"); 39736399Ssklower data->m_len = 18; 39837469Ssklower }*/ 39936399Ssklower ENDDEBUG 40036399Ssklower break; 40136399Ssklower 40236399Ssklower case DT_TPDU_type: 40336399Ssklower hdr->tpdu_cdt = 0; 40436399Ssklower IFTRACE(D_DATA) 40536399Ssklower tptraceTPCB(TPPTmisc, "emit DT: eot seq tpdu_li", eot, seq, 40636399Ssklower hdr->tpdu_li, 0); 40736399Ssklower ENDTRACE 40836399Ssklower if (tpcb->tp_xtd_format) { 40936399Ssklower #ifdef BYTE_ORDER 41036399Ssklower union seq_type seqeotX; 41136399Ssklower 41236399Ssklower seqeotX.s_seq = seq; 41336399Ssklower seqeotX.s_eot = eot; 41436399Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 41536399Ssklower #else 41636399Ssklower hdr->tpdu_DTseqX = seq; 41736399Ssklower hdr->tpdu_DTeotX = eot; 41836399Ssklower #endif BYTE_ORDER 41936399Ssklower } else if (tpcb->tp_class == TP_CLASS_0) { 42036399Ssklower IFDEBUG(D_EMIT) 42136399Ssklower printf("DT tpdu: class 0 m 0x%x hdr 0x%x\n", m, hdr); 42236399Ssklower dump_buf( hdr, hdr->tpdu_li + 1 ); 42336399Ssklower ENDDEBUG 42436399Ssklower ((struct tp0du *)hdr)->tp0du_eot = eot; 42536399Ssklower ((struct tp0du *)hdr)->tp0du_mbz = 0; 42636399Ssklower IFDEBUG(D_EMIT) 42736399Ssklower printf("DT 2 tpdu: class 0 m 0x%x hdr 0x%x\n", m, hdr); 42836399Ssklower dump_buf( hdr, hdr->tpdu_li + 1 ); 42936399Ssklower ENDDEBUG 43036399Ssklower } else { 43136399Ssklower hdr->tpdu_DTseq = seq; 43236399Ssklower hdr->tpdu_DTeot = eot; 43336399Ssklower } 43436399Ssklower if(eot) { 43536399Ssklower IncStat(ts_EOT_sent); 43636399Ssklower } 43736399Ssklower IncStat(ts_DT_sent); 43836399Ssklower IncPStat(tpcb, tps_DT_sent); 43936399Ssklower break; 44036399Ssklower 44136399Ssklower case AK_TPDU_type:/* ak not used in class 0 */ 44236399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); 44336399Ssklower data = (struct mbuf *)0; 44451204Ssklower olduwe = tpcb->tp_sent_uwe; 44536399Ssklower 44651204Ssklower if (seq != tpcb->tp_sent_rcvnxt || tpcb->tp_rsycnt == 0) { 44751204Ssklower LOCAL_CREDIT( tpcb ); 44836399Ssklower tpcb->tp_sent_uwe = 44936399Ssklower SEQ(tpcb,tpcb->tp_rcvnxt + tpcb->tp_lcredit -1); 45036399Ssklower tpcb->tp_sent_lcdt = tpcb->tp_lcredit; 45151204Ssklower acking_ooo = 0; 45251204Ssklower } else 45351204Ssklower acking_ooo = 1; 45436399Ssklower 45551204Ssklower IFDEBUG(D_RENEG) 45651204Ssklower /* occasionally fake a reneging so 45751204Ssklower you can test subsequencing */ 45851204Ssklower if( olduwe & 0x1 ) { 45936399Ssklower tpcb->tp_reneged = 1; 46051204Ssklower IncStat(ts_ldebug); 46136399Ssklower } 46251204Ssklower ENDDEBUG 46351204Ssklower /* Are we about to reneg on credit? 46451204Ssklower * When might we do so? 46551204Ssklower * a) when using optimistic credit (which we no longer do). 46651204Ssklower * b) when drain() gets implemented (not in the plans). 46751204Ssklower * c) when D_RENEG is on. 46851204Ssklower * d) when DEC BIT response is implemented. 46951204Ssklower * (not- when we do this, we'll need to implement flow control 47051204Ssklower * confirmation) 47151204Ssklower */ 47251204Ssklower if( SEQ_LT(tpcb, tpcb->tp_sent_uwe, olduwe) ) { 47351204Ssklower tpcb->tp_reneged = 1; 47451204Ssklower IncStat(ts_lcdt_reduced); 47551204Ssklower IFTRACE(D_CREDIT) 47651204Ssklower tptraceTPCB(TPPTmisc, 47751204Ssklower "RENEG: olduwe newuwe lcredit rcvnxt", 47851204Ssklower olduwe, 47951204Ssklower tpcb->tp_sent_uwe, tpcb->tp_lcredit, 48051204Ssklower tpcb->tp_rcvnxt); 48151204Ssklower ENDTRACE 48251204Ssklower } 48351204Ssklower IFPERF(tpcb) 48451204Ssklower /* new lwe is less than old uwe means we're 48551204Ssklower * acking before we received a whole window full 48651204Ssklower */ 48751204Ssklower if( SEQ_LT( tpcb, tpcb->tp_rcvnxt, olduwe) ) { 48851204Ssklower /* tmp1 = number of pkts fewer than the full window */ 48951204Ssklower register int tmp1 = 49051204Ssklower (int) SEQ_SUB( tpcb, olduwe, tpcb->tp_rcvnxt); 49136399Ssklower 49251204Ssklower if(tmp1 > TP_PM_MAX) 49351204Ssklower tmp1 = TP_PM_MAX; 49451204Ssklower IncPStat( tpcb, tps_ack_early[tmp1] ); 49536399Ssklower 49651204Ssklower /* tmp1 = amt of new cdt we're advertising */ 49751204Ssklower tmp1 = SEQ_SUB( tpcb, seq, tpcb->tp_sent_rcvnxt); 49851204Ssklower if(tmp1 > TP_PM_MAX ) 49951204Ssklower tmp1 = TP_PM_MAX; 50036399Ssklower 50151204Ssklower IncPStat( tpcb, 50251204Ssklower tps_cdt_acked [ tmp1 ] 50351204Ssklower [ ((tpcb->tp_lcredit > TP_PM_MAX)? 50451204Ssklower TP_PM_MAX:tpcb->tp_lcredit) ] ); 50536399Ssklower 50651204Ssklower } 50751204Ssklower ENDPERF 50836399Ssklower 50936399Ssklower IFTRACE(D_ACKSEND) 51036399Ssklower tptraceTPCB(TPPTack, seq, tpcb->tp_lcredit, tpcb->tp_sent_uwe, 51136399Ssklower tpcb->tp_r_subseq, 0); 51236399Ssklower ENDTRACE 51336399Ssklower if (tpcb->tp_xtd_format) { 51436399Ssklower #ifdef BYTE_ORDER 51548747Ssklower union seq_type seqeotX; 51648747Ssklower 51748747Ssklower seqeotX.s_seq = seq; 51848747Ssklower seqeotX.s_eot = 0; 51948747Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 52036399Ssklower hdr->tpdu_AKcdtX = htons(tpcb->tp_lcredit); 52136399Ssklower #else 52236399Ssklower hdr->tpdu_cdt = 0; 52336399Ssklower hdr->tpdu_AKseqX = seq; 52436399Ssklower hdr->tpdu_AKcdtX = tpcb->tp_lcredit; 52536399Ssklower #endif BYTE_ORDER 52636399Ssklower } else { 52736399Ssklower hdr->tpdu_AKseq = seq; 52836399Ssklower hdr->tpdu_AKcdt = tpcb->tp_lcredit; 52936399Ssklower } 53051204Ssklower if ((tpcb->tp_class == TP_CLASS_4) && 53151204Ssklower (tpcb->tp_reneged || acking_ooo)) { 53236399Ssklower /* 53336399Ssklower * Ack subsequence parameter req'd if WE reneged on 53436399Ssklower * credit offered. (ISO 8073, 12.2.3.8.2, p. 74) 53536399Ssklower */ 53636399Ssklower IFDEBUG(D_RENEG) 53736399Ssklower printf("Adding subseq 0x%x\n", tpcb->tp_s_subseq); 53836399Ssklower ENDDEBUG 53936399Ssklower tpcb->tp_s_subseq++; 54036399Ssklower /* 54136399Ssklower * add tmp subseq and do a htons on it. 54236399Ssklower */ 54336399Ssklower ADDOPTION(TPP_subseq, hdr, 54436399Ssklower sizeof(tpcb->tp_s_subseq), tpcb->tp_s_subseq); 54536399Ssklower } else 54636399Ssklower tpcb->tp_s_subseq = 0; 54736399Ssklower 54836399Ssklower if ( tpcb->tp_sendfcc || eot ) /* overloaded to mean SEND FCC */ { 54936399Ssklower /* 55036399Ssklower * Rules for sending FCC ("should" send when) : 55136399Ssklower * %a) received an ack from peer with NO NEWS whatsoever, 55236399Ssklower * and it did not contain an FCC 55336399Ssklower * b) received an ack from peer that opens its closed window. 55436399Ssklower * c) received an ack from peer after it reneged on its 55536399Ssklower * offered credit, AND this ack raises UWE but LWE is same 55636399Ssklower * and below UWE at time of reneging (reduction) 55736399Ssklower * Now, ISO 8073 12.2.3.8.3 says 55836399Ssklower * that a retransmitted AK shall not contain the FCC 55936399Ssklower * parameter. Now, how the hell you tell the difference 56036399Ssklower * between a retransmitted ack and an ack that's sent in 56136399Ssklower * response to a received ack, I don't know, because without 56236399Ssklower * any local activity, and w/o any received DTs, they 56336399Ssklower * will contain exactly the same credit/seq# information. 56436399Ssklower * Anyway, given that the "retransmission of acks" 56536399Ssklower * procedure (ISO 8073 12.2.3.8.3) is optional, and we 56636399Ssklower * don't do it (although the peer can't tell that), we 56736399Ssklower * ignore this last rule. 56836399Ssklower * 56936399Ssklower * We send FCC for reasons a) and b) only. 57036399Ssklower * To add reason c) would require a ridiculous amount of state. 57136399Ssklower * 57236399Ssklower */ 57336399Ssklower u_short bogus[4]; /* lwe(32), subseq(16), cdt(16) */ 57436399Ssklower SeqNum lwe; 57536399Ssklower u_short subseq, fcredit; 57636399Ssklower 57736399Ssklower tpcb->tp_sendfcc = 0; 57836399Ssklower 57936399Ssklower lwe = (SeqNum) htonl(tpcb->tp_snduna); 58036399Ssklower subseq = htons(tpcb->tp_r_subseq); 58136399Ssklower fcredit = htons(tpcb->tp_fcredit); 58236399Ssklower 58337469Ssklower bcopy((caddr_t) &lwe, (caddr_t)&bogus[0], sizeof(SeqNum)); 58437469Ssklower bcopy((caddr_t) &subseq, (caddr_t)&bogus[2], sizeof(u_short)); 58537469Ssklower bcopy((caddr_t) &fcredit, (caddr_t)&bogus[3], sizeof(u_short)); 58636399Ssklower 58736399Ssklower IFTRACE(D_ACKSEND) 58836399Ssklower tptraceTPCB(TPPTmisc, 58936399Ssklower "emit w/FCC: snduna r_subseq fcredit", 59036399Ssklower tpcb->tp_snduna, tpcb->tp_r_subseq, 59136399Ssklower tpcb->tp_fcredit, 0); 59236399Ssklower ENDTRACE 59336399Ssklower 59436399Ssklower IFDEBUG(D_ACKSEND) 59536399Ssklower printf("Calling ADDOPTION 0x%x, 0x%x, 0x%x,0x%x\n", 59636399Ssklower TPP_flow_cntl_conf, 59736399Ssklower hdr, sizeof(bogus), bogus[0]); 59836399Ssklower ENDDEBUG 59936399Ssklower ADDOPTION(TPP_flow_cntl_conf, hdr, sizeof(bogus), bogus[0]); 60036399Ssklower IFDEBUG(D_ACKSEND) 60136399Ssklower printf("after ADDOPTION hdr 0x%x hdr->tpdu_li 0x%x\n", 60236399Ssklower hdr, hdr->tpdu_li); 60336399Ssklower printf( 60436399Ssklower "after ADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 60536399Ssklower csum_offset, hdr->tpdu_li); 60636399Ssklower ENDDEBUG 60736399Ssklower 60836399Ssklower } 60936399Ssklower tpcb->tp_reneged = 0; 61036399Ssklower tpcb->tp_sent_rcvnxt = seq; 61151204Ssklower if (tpcb->tp_fcredit == 0) { 61251204Ssklower int timo = tpcb->tp_keepalive_ticks; 61351204Ssklower if (tpcb->tp_rxtshift < TP_MAXRXTSHIFT) 61451204Ssklower tpcb->tp_rxtshift++; 61551204Ssklower timo = min(timo, ((int)tpcb->tp_dt_ticks) << tpcb->tp_rxtshift); 61651204Ssklower tp_ctimeout(tpcb, TM_sendack, timo); 61751204Ssklower } else 61851204Ssklower tp_ctimeout(tpcb, TM_sendack, tpcb->tp_keepalive_ticks); 61936399Ssklower IncStat(ts_AK_sent); 62036399Ssklower IncPStat(tpcb, tps_AK_sent); 62136399Ssklower IFDEBUG(D_ACKSEND) 62236399Ssklower printf( 62336399Ssklower "2 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 62436399Ssklower csum_offset, hdr->tpdu_li); 62536399Ssklower ENDDEBUG 62636399Ssklower break; 62736399Ssklower 62836399Ssklower case ER_TPDU_type: 62936399Ssklower hdr->tpdu_ERreason = eot; 63036399Ssklower hdr->tpdu_cdt = 0; 63136399Ssklower /* no user data */ 63236399Ssklower data = (struct mbuf *)0; 63336399Ssklower IncStat(ts_ER_sent); 63436399Ssklower break; 63536399Ssklower } 63636399Ssklower 63736399Ssklower } 63836399Ssklower ASSERT( ((int)hdr->tpdu_li > 0) && ((int)hdr->tpdu_li < MLEN) ); 63936399Ssklower 64036399Ssklower m->m_next = data; 64136399Ssklower 64237469Ssklower ASSERT( hdr->tpdu_li < MLEN ); /* leave this in */ 64336399Ssklower ASSERT( hdr->tpdu_li != 0 ); /* leave this in */ 64436399Ssklower 64536399Ssklower m->m_len = hdr->tpdu_li ; 64636399Ssklower hdr->tpdu_li --; /* doesn't include the li field */ 64736399Ssklower 64836399Ssklower datalen = m_datalen( m ); /* total len */ 64936399Ssklower 65036399Ssklower ASSERT( datalen <= tpcb->tp_l_tpdusize ); /* may become a problem 65136399Ssklower when CLNP is used; leave in here for the time being */ 65236399Ssklower IFDEBUG(D_ACKSEND) 65336399Ssklower printf( 65436399Ssklower "4 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 65536399Ssklower csum_offset, hdr->tpdu_li); 65636399Ssklower ENDDEBUG 65736399Ssklower if( datalen > tpcb->tp_l_tpdusize ) { 65836399Ssklower printf("data len 0x%x tpcb->tp_l_tpdusize 0x%x\n", 65936399Ssklower datalen, tpcb->tp_l_tpdusize); 66036399Ssklower } 66136399Ssklower IFDEBUG(D_EMIT) 66236399Ssklower printf( 66336399Ssklower "tp_emit before gen_csum m_len 0x%x, csum_offset 0x%x, datalen 0x%x\n", 66436399Ssklower m->m_len, csum_offset, datalen); 66536399Ssklower ENDDEBUG 66636399Ssklower if( tpcb->tp_use_checksum || 66736399Ssklower (dutype == CR_TPDU_type && (tpcb->tp_class & TP_CLASS_4)) ) { 66836399Ssklower iso_gen_csum(m, csum_offset, datalen); 66936399Ssklower } 67036399Ssklower 67136399Ssklower IFDEBUG(D_EMIT) 67236399Ssklower printf("tp_emit before tpxxx_output tpcb 0x%x, dutype 0x%x, datalen 0x%x\n", 67336399Ssklower tpcb, dutype, datalen); 67437469Ssklower dump_buf(mtod(m, caddr_t), datalen); 67536399Ssklower ENDDEBUG 67636399Ssklower 67736399Ssklower IFPERF(tpcb) 67836399Ssklower if( dutype == DT_TPDU_type ) { 67936399Ssklower PStat(tpcb, Nb_to_ll) += (datalen - m->m_len); 68037469Ssklower tpmeas( tpcb->tp_lref, TPtime_to_ll, (struct timeval *)0, 68136399Ssklower seq, PStat(tpcb, Nb_to_ll), (datalen - m->m_len)); 68236399Ssklower } 68336399Ssklower ENDPERF 68436399Ssklower 68536399Ssklower IFTRACE(D_EMIT) 68636399Ssklower tptraceTPCB(TPPTtpduout, dutype, hdr, hdr->tpdu_li+1, datalen, 0); 68736399Ssklower ENDTRACE 68836399Ssklower IFDEBUG(D_EMIT) 68936399Ssklower printf("OUTPUT: tpcb 0x%x, isop 0x%x, so 0x%x\n", 69036399Ssklower tpcb, tpcb->tp_npcb, tpcb->tp_sock); 69136399Ssklower ENDDEBUG 69236399Ssklower 69336399Ssklower { extern char tp_delay; 69436399Ssklower 69536399Ssklower if( tp_delay ) 69636399Ssklower if( tpcb->tp_use_checksum == 0 ) { 69736399Ssklower register u_int i = tp_delay; 69836399Ssklower for (; i!= 0; i--) 69936399Ssklower (void) iso_check_csum(m, datalen); 70036399Ssklower } 70136399Ssklower } 70236399Ssklower ASSERT( m->m_len > 0 ); 70336399Ssklower error = (tpcb->tp_nlproto->nlp_output)(tpcb->tp_npcb, m, datalen, 70436399Ssklower !tpcb->tp_use_checksum); 70536399Ssklower IFDEBUG(D_EMIT) 70636399Ssklower printf("OUTPUT: returned 0x%x\n", error); 70736399Ssklower ENDDEBUG 70836399Ssklower IFTRACE(D_EMIT) 70936399Ssklower tptraceTPCB(TPPTmisc, 71036399Ssklower "tp_emit nlproto->output netservice returns datalen", 71136399Ssklower tpcb->tp_nlproto->nlp_output, tpcb->tp_netservice, error, datalen); 71236399Ssklower ENDTRACE 71336399Ssklower done: 71451204Ssklower if (error) { 71551204Ssklower if (dutype == AK_TPDU_type) 71651204Ssklower tp_ctimeout(tpcb, TM_sendack, 1); 71751204Ssklower if (error == E_CO_QFULL) { 71851204Ssklower tp_quench(tpcb, PRC_QUENCH); 71951204Ssklower return 0; 72051204Ssklower } 72136399Ssklower } 72236399Ssklower return error; 72336399Ssklower } 72436399Ssklower /* 72536399Ssklower * NAME: tp_error_emit() 72636399Ssklower * CALLED FROM: tp_input() when a DR or ER is to be issued in 72736399Ssklower * response to an input error. 72836399Ssklower * FUNCTION and ARGUMENTS: 72936399Ssklower * The error type is the first argument. 73036399Ssklower * The argument (sref) is the source reference on the bad incoming tpdu, 73136399Ssklower * and is used for a destination reference on the outgoing packet. 73236399Ssklower * (faddr) and (laddr) are the foreign and local addresses for this 73336399Ssklower * connection. 73436399Ssklower * (erdata) is a ptr to the errant incoming tpdu, and is copied into the 73536399Ssklower * outgoing ER, if an ER is to be issued. 73636399Ssklower * (erlen) is the number of octets of the errant tpdu that we should 73736399Ssklower * try to copy. 73836399Ssklower * (tpcb) is the pcb that describes the connection for which the bad tpdu 73936399Ssklower * arrived. 74036399Ssklower * RETURN VALUES: 74136399Ssklower * 0 OK 74236399Ssklower * ENOBUFS 74336399Ssklower * E* from net layer datagram output routine 74436399Ssklower * SIDE EFFECTS: 74536399Ssklower * 74636399Ssklower * NOTES: 74736399Ssklower */ 74836399Ssklower 74936399Ssklower int 75036399Ssklower tp_error_emit(error, sref, faddr, laddr, erdata, erlen, tpcb, cons_channel, 75136399Ssklower dgout_routine) 75236399Ssklower int error; 75336399Ssklower u_long sref; 75436399Ssklower struct sockaddr_iso *faddr, *laddr; 75536399Ssklower struct mbuf *erdata; 75636399Ssklower int erlen; 75736399Ssklower struct tp_pcb *tpcb; 75850535Ssklower caddr_t cons_channel; 75936399Ssklower int (*dgout_routine)(); 76036399Ssklower { 76136399Ssklower int dutype; 76236399Ssklower int datalen = 0; 76336399Ssklower register struct tpdu *hdr; 76436399Ssklower register struct mbuf *m; 76536399Ssklower int csum_offset; 76636399Ssklower 76736399Ssklower IFTRACE(D_ERROR_EMIT) 76836399Ssklower tptrace(TPPTmisc, "tp_error_emit error sref tpcb erlen", 76936399Ssklower error, sref, tpcb, erlen); 77036399Ssklower ENDTRACE 77136399Ssklower IFDEBUG(D_ERROR_EMIT) 77236399Ssklower printf( 77336399Ssklower "tp_error_emit error 0x%x sref 0x%x tpcb 0x%x erlen 0x%x chan 0x%x\n", 77436399Ssklower error, sref, tpcb, erlen, cons_channel); 77536399Ssklower ENDDEBUG 77636399Ssklower 77736399Ssklower MGET(m, M_DONTWAIT, TPMT_TPHDR); 77836399Ssklower if (m == NULL) { 77936399Ssklower return ENOBUFS; 78036399Ssklower } 78136399Ssklower m->m_len = sizeof(struct tpdu); 78236399Ssklower m->m_act = MNULL; 78336399Ssklower 78436399Ssklower hdr = mtod(m, struct tpdu *); 78536399Ssklower 78636399Ssklower IFDEBUG(D_ERROR_EMIT) 78736399Ssklower printf("[error 0x%x] [error&0xff 0x%x] [(char)error 0x%x]\n", 78836399Ssklower error, error&0xff, (char)error); 78936399Ssklower ENDDEBUG 79036399Ssklower 79136399Ssklower 79242494Ssklower if (error & TP_ERROR_SNDC) 79342494Ssklower dutype = DC_TPDU_type; 79442494Ssklower else if (error & 0x40) { 79536399Ssklower error &= ~0x40; 79636399Ssklower dutype = ER_TPDU_type; 79736399Ssklower } else 79836399Ssklower dutype = DR_TPDU_type; 79942494Ssklower error &= 0xff; 80036399Ssklower 80136399Ssklower hdr->tpdu_type = dutype; 80236399Ssklower hdr->tpdu_cdt = 0; 80336399Ssklower 80436399Ssklower switch( dutype ) { 80536399Ssklower 80642494Ssklower case DC_TPDU_type: 80742494Ssklower IncStat(ts_DC_sent); 80842494Ssklower hdr->tpdu_li = 6; 80942494Ssklower hdr->tpdu_DCdref = htons(sref); 81042494Ssklower hdr->tpdu_DCsref = tpcb ? htons(tpcb->tp_lref) : 0; 81142494Ssklower IFDEBUG(D_ERROR_EMIT) 81242494Ssklower printf("DC case:\n"); 81342494Ssklower dump_buf( hdr, 6); 81442494Ssklower ENDDEBUG 81542494Ssklower /* forget the add'l information variable part */ 81642494Ssklower break; 81742494Ssklower 81836399Ssklower case DR_TPDU_type: 81936399Ssklower IncStat(ts_DR_sent); 82036399Ssklower hdr->tpdu_li = 7; 82136399Ssklower hdr->tpdu_DRdref = htons(sref); 82242494Ssklower hdr->tpdu_DRsref = 0; 82336399Ssklower hdr->tpdu_DRreason = (char)error; 82436399Ssklower IFDEBUG(D_ERROR_EMIT) 82536399Ssklower printf("DR case:\n"); 82636399Ssklower dump_buf( hdr, 7); 82736399Ssklower ENDDEBUG 82836399Ssklower /* forget the add'l information variable part */ 82936399Ssklower break; 83036399Ssklower 83136399Ssklower case ER_TPDU_type: 83236399Ssklower IncStat(ts_ER_sent); 83336399Ssklower hdr->tpdu_li = 5; 83436399Ssklower hdr->tpdu_ERreason = (char)error; 83550535Ssklower hdr->tpdu_ERdref = htons(sref); 83636399Ssklower break; 83736399Ssklower 83836399Ssklower default: 83936399Ssklower ASSERT(0); 84036399Ssklower printf("TP PANIC: bad dutype 0x%x\n", dutype); 84136399Ssklower } 84236399Ssklower 84336399Ssklower if(tpcb) 84436399Ssklower if( tpcb->tp_use_checksum ) { 84536399Ssklower ADDOPTION(TPP_checksum, hdr, 2, csum_offset /* dummy argument */); 84636399Ssklower csum_offset = hdr->tpdu_li - 2; 84736399Ssklower } 84836399Ssklower 84937469Ssklower ASSERT( hdr->tpdu_li < MLEN ); 85036399Ssklower 85136399Ssklower if (dutype == ER_TPDU_type) { 85236399Ssklower /* copy the errant tpdu into another 'variable part' */ 85336399Ssklower register caddr_t P; 85436399Ssklower 85536399Ssklower IFTRACE(D_ERROR_EMIT) 85636399Ssklower tptrace(TPPTmisc, "error_emit ER len tpduli", erlen, hdr->tpdu_li, 85736399Ssklower 0,0); 85836399Ssklower ENDTRACE 85936399Ssklower IFDEBUG(D_ERROR_EMIT) 86036399Ssklower printf("error_emit ER len 0x%x tpduli 0x%x\n", erlen, hdr->tpdu_li); 86136399Ssklower ENDDEBUG 86236399Ssklower 86336399Ssklower /* copy at most as many octets for which you have room */ 86436399Ssklower if (erlen + hdr->tpdu_li + 2 > TP_MAX_HEADER_LEN) 86536399Ssklower erlen = TP_MAX_HEADER_LEN - hdr->tpdu_li - 2; 86636399Ssklower 86736399Ssklower /* add the "invalid tpdu" parameter : required in class 0 */ 86836399Ssklower P = (caddr_t)hdr + (int)(hdr->tpdu_li); 86936399Ssklower vbptr(P)->tpv_code = TPP_invalid_tpdu; /* parameter code */ 87036399Ssklower vbptr(P)->tpv_len = erlen; /* parameter length */ 87136399Ssklower m->m_len = hdr->tpdu_li + 2; /* 1 for code, 1 for length */ 87236399Ssklower 87336399Ssklower /* tp_input very likely handed us an mbuf chain w/ nothing in 87436399Ssklower * the first mbuf and the data following the empty mbuf 87536399Ssklower */ 87636399Ssklower if(erdata->m_len == 0) { 87736399Ssklower erdata = m_free(erdata); /* returns the next mbuf on the chain */ 87836399Ssklower } 87937469Ssklower /* 88037469Ssklower * copy only up to the bad octet 88137469Ssklower * (or max that will fit in a header 88237469Ssklower */ 88337469Ssklower m->m_next = m_copy(erdata, 0, erlen); 88436399Ssklower hdr->tpdu_li += erlen + 2; 88536399Ssklower m_freem(erdata); 88636399Ssklower } else { 88736399Ssklower IFDEBUG(D_ERROR_EMIT) 88836399Ssklower printf("error_emit DR error tpduli 0x%x\n", error, hdr->tpdu_li); 88936399Ssklower dump_buf( (char *)hdr, hdr->tpdu_li ); 89036399Ssklower ENDDEBUG 89136399Ssklower m->m_len = hdr->tpdu_li ; 89236399Ssklower m_freem(erdata); 89336399Ssklower } 89436399Ssklower 89536399Ssklower hdr->tpdu_li --; 89636399Ssklower IFTRACE(D_ERROR_EMIT) 89736399Ssklower tptrace(TPPTtpduout, 2, hdr, hdr->tpdu_li+1, 0, 0); 89836399Ssklower ENDTRACE 89936399Ssklower 90036399Ssklower datalen = m_datalen( m); 90150648Ssklower if (tpcb) { 90236399Ssklower if( tpcb->tp_use_checksum ) { 90336399Ssklower IFTRACE(D_ERROR_EMIT) 90436399Ssklower tptrace(TPPTmisc, "before gen csum datalen", datalen,0,0,0); 90536399Ssklower ENDTRACE 90636399Ssklower IFDEBUG(D_ERROR_EMIT) 90736399Ssklower printf("before gen csum datalen 0x%x, csum_offset 0x%x\n", 90836399Ssklower datalen, csum_offset); 90936399Ssklower ENDDEBUG 91036399Ssklower 91136399Ssklower iso_gen_csum(m, csum_offset, datalen); 91236399Ssklower } 91336399Ssklower 91436399Ssklower IFDEBUG(D_ERROR_EMIT) 91536399Ssklower printf("OUTPUT: tpcb 0x%x, isop 0x%x, so 0x%x\n", 91636399Ssklower tpcb, tpcb->tp_npcb, tpcb->tp_sock); 91736399Ssklower ENDDEBUG 91850648Ssklower } 91950648Ssklower if (cons_channel) { 92050648Ssklower #ifdef TPCONS 92150648Ssklower struct pklcd *lcp = (struct pklcd *)cons_channel; 92250648Ssklower struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext; 92336399Ssklower 92450648Ssklower tpcons_dg_output(cons_channel, m, datalen); 92550648Ssklower /* was if (tpcb == 0) iso_pcbdetach(isop); */ 92650648Ssklower /* but other side may want to try again over same VC, 92750648Ssklower so, we'll depend on him closing it, but in case it gets forgotten 92850648Ssklower we'll mark it for garbage collection */ 92950648Ssklower lcp->lcd_flags |= X25_DG_CIRCUIT; 93036399Ssklower IFDEBUG(D_ERROR_EMIT) 93150648Ssklower printf("OUTPUT: dutype 0x%x channel 0x%x\n", 93250648Ssklower dutype, cons_channel); 93350648Ssklower ENDDEBUG 93450648Ssklower #else 93550648Ssklower printf("TP panic! cons channel 0x%x but not cons configured\n", 93650648Ssklower cons_channel); 93750648Ssklower #endif 93850648Ssklower } else if (tpcb) { 93950648Ssklower 94050648Ssklower IFDEBUG(D_ERROR_EMIT) 94136399Ssklower printf("tp_error_emit 1 sending DG: Laddr\n"); 94237469Ssklower dump_addr((struct sockaddr *)laddr); 94336399Ssklower printf("Faddr\n"); 94437469Ssklower dump_addr((struct sockaddr *)faddr); 94536399Ssklower ENDDEBUG 94636399Ssklower return (tpcb->tp_nlproto->nlp_dgoutput)( 94736399Ssklower &laddr->siso_addr, 94836399Ssklower &faddr->siso_addr, 94936399Ssklower m, datalen, 95036399Ssklower /* no route */ (caddr_t)0, !tpcb->tp_use_checksum); 95150648Ssklower } else if (dgout_routine) { 95236399Ssklower IFDEBUG(D_ERROR_EMIT) 95336399Ssklower printf("tp_error_emit sending DG: Laddr\n"); 95437469Ssklower dump_addr((struct sockaddr *)laddr); 95536399Ssklower printf("Faddr\n"); 95637469Ssklower dump_addr((struct sockaddr *)faddr); 95736399Ssklower ENDDEBUG 95850648Ssklower return (*dgout_routine)( &laddr->siso_addr, &faddr->siso_addr, 95950648Ssklower m, datalen, /* no route */ 96050648Ssklower (caddr_t)0, /* nochecksum==false */0); 96150648Ssklower } else { 96236399Ssklower IFDEBUG(D_ERROR_EMIT) 96336399Ssklower printf("tp_error_emit DROPPING \n", m); 96436399Ssklower ENDDEBUG 96536399Ssklower IncStat(ts_send_drop); 96636399Ssklower m_freem(m); 96736399Ssklower return 0; 96836399Ssklower } 96936399Ssklower } 970