149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*51996Ssklower * @(#)tp_emit.c 7.13 (Berkeley) 12/17/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; 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 */ 21939924Ssklower if (!tpcb->tp_cebit_off) { 22039924Ssklower tpcb->tp_win_recv = tp_start_win << 8; 22139924Ssklower LOCAL_CREDIT(tpcb); 22239924Ssklower CONG_INIT_SAMPLE(tpcb); 22351204Ssklower } 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 290*51996Ssklower if ((tpcb->tp_l_tpdusize ^ (1 << tpcb->tp_tpdusize)) != 0) { 291*51996Ssklower u_short size_s = tpcb->tp_l_tpdusize >> 7; 292*51996Ssklower u_char size_c = size_s; 293*51996Ssklower ASSERT(tpcb->tp_l_tpdusize < 65536 * 128); 294*51996Ssklower if (dutype == CR_TPDU_type) 295*51996Ssklower tpcb->tp_ptpdusize = size_s; 296*51996Ssklower if (size_s < 256) { 297*51996Ssklower ADDOPTION(TPP_ptpdu_size, hdr, 1, size_c); 298*51996Ssklower } else { 299*51996Ssklower size_s = htons(size_s); 300*51996Ssklower ADDOPTION(TPP_ptpdu_size, hdr, 2, size_s); 301*51996Ssklower } 302*51996Ssklower } 30336399Ssklower } 30436399Ssklower 30536399Ssklower if( (dutype == CR_TPDU_type) && (tpcb->tp_class != TP_CLASS_0)){ 30636399Ssklower 30736399Ssklower ASSERT( 1 == sizeof(tpcb->tp_vers) ); 30836399Ssklower ADDOPTION(TPP_vers, hdr, 1, tpcb->tp_vers); 30936399Ssklower 31036399Ssklower /* for each alt protocol class x, 31136399Ssklower * x = x<<4; 31236399Ssklower * option = concat(option, x); 31336399Ssklower * Well, for now we only have TP0 for an 31436399Ssklower * alternative so... this is easy. 31536399Ssklower * 31636399Ssklower * HOWEVER... There should be NO alt protocol 31736399Ssklower * class over CLNS. Need to see if the route suggests 31836399Ssklower * CONS, and iff so add alt class. 31936399Ssklower */ 32036399Ssklower x = 0; 32136399Ssklower ADDOPTION(TPP_alt_class, hdr, 1, x); 32236399Ssklower } 32336399Ssklower 32436399Ssklower if( hdr->tpdu_li > MLEN) 32536399Ssklower panic("tp_emit CR/CC"); 32636399Ssklower } 32736399Ssklower break; 32836399Ssklower 32936399Ssklower case DR_TPDU_type: 33036399Ssklower if( hdr->tpdu_DRdref == 0 ) { 33136399Ssklower /* don't issue the DR */ 33236399Ssklower goto done; 33336399Ssklower } 33436399Ssklower hdr->tpdu_cdt = 0; 33536399Ssklower hdr->tpdu_DRsref = htons(tpcb->tp_lref); 33636399Ssklower hdr->tpdu_DRreason = (u_char)eot; /* WHICH BYTE OF THIS??? */ 33736399Ssklower 33836399Ssklower /* forget the add'l information variable part */ 33936399Ssklower IncStat(ts_DR_sent); 34036399Ssklower break; 34136399Ssklower 34236399Ssklower case DC_TPDU_type: /* not used in class 0 */ 34336399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); 34436399Ssklower hdr->tpdu_DCsref = htons(tpcb->tp_lref); 34536399Ssklower hdr->tpdu_cdt = 0; 34636399Ssklower data = (struct mbuf *)0; 34736399Ssklower IncStat(ts_DC_sent); 34836399Ssklower break; 34936399Ssklower 35036399Ssklower case XAK_TPDU_type: /* xak not used in class 0 */ 35136399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); /* fall through */ 35236399Ssklower hdr->tpdu_cdt = 0; 35336399Ssklower 35436399Ssklower IFTRACE(D_XPD) 35536399Ssklower tptraceTPCB(TPPTXack, seq, 0, 0, 0, 0); 35636399Ssklower ENDTRACE 35736399Ssklower data = (struct mbuf *)0; 35836399Ssklower if (tpcb->tp_xtd_format) { 35936399Ssklower #ifdef BYTE_ORDER 36048747Ssklower union seq_type seqeotX; 36148747Ssklower 36248747Ssklower seqeotX.s_seq = seq; 36348747Ssklower seqeotX.s_eot = 1; 36448747Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 36536399Ssklower #else 36636399Ssklower hdr->tpdu_XAKseqX = seq; 36736399Ssklower #endif BYTE_ORDER 36836399Ssklower } else { 36936399Ssklower hdr->tpdu_XAKseq = seq; 37036399Ssklower } 37136399Ssklower IncStat(ts_XAK_sent); 37236399Ssklower IncPStat(tpcb, tps_XAK_sent); 37336399Ssklower break; 37436399Ssklower 37536399Ssklower case XPD_TPDU_type: /* xpd not used in class 0 */ 37636399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); /* fall through */ 37736399Ssklower hdr->tpdu_cdt = 0; 37836399Ssklower if (tpcb->tp_xtd_format) { 37936399Ssklower #ifdef BYTE_ORDER 38036399Ssklower union seq_type seqeotX; 38136399Ssklower 38236399Ssklower seqeotX.s_seq = seq; 38336399Ssklower seqeotX.s_eot = 1; 38436399Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 38536399Ssklower #else 38636399Ssklower hdr->tpdu_XPDseqX = seq; 38736399Ssklower hdr->tpdu_XPDeotX = 1; /* always 1 for XPD tpdu */ 38836399Ssklower #endif BYTE_ORDER 38936399Ssklower } else { 39036399Ssklower hdr->tpdu_XPDseq = seq; 39136399Ssklower hdr->tpdu_XPDeot = 1; /* always 1 for XPD tpdu */ 39236399Ssklower } 39336399Ssklower IncStat(ts_XPD_sent); 39436399Ssklower IncPStat(tpcb, tps_XPD_sent); 39536399Ssklower 39636399Ssklower /* kludge to test the input size checking */ 39736399Ssklower IFDEBUG(D_SIZE_CHECK) 39837469Ssklower /*if(data->m_len <= 16 && data->m_off < (MLEN-18) ) { 39936399Ssklower printf("Sending too much data on XPD: 18 bytes\n"); 40036399Ssklower data->m_len = 18; 40137469Ssklower }*/ 40236399Ssklower ENDDEBUG 40336399Ssklower break; 40436399Ssklower 40536399Ssklower case DT_TPDU_type: 40636399Ssklower hdr->tpdu_cdt = 0; 40736399Ssklower IFTRACE(D_DATA) 40836399Ssklower tptraceTPCB(TPPTmisc, "emit DT: eot seq tpdu_li", eot, seq, 40936399Ssklower hdr->tpdu_li, 0); 41036399Ssklower ENDTRACE 41136399Ssklower if (tpcb->tp_xtd_format) { 41236399Ssklower #ifdef BYTE_ORDER 41336399Ssklower union seq_type seqeotX; 41436399Ssklower 41536399Ssklower seqeotX.s_seq = seq; 41636399Ssklower seqeotX.s_eot = eot; 41736399Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 41836399Ssklower #else 41936399Ssklower hdr->tpdu_DTseqX = seq; 42036399Ssklower hdr->tpdu_DTeotX = eot; 42136399Ssklower #endif BYTE_ORDER 42236399Ssklower } else if (tpcb->tp_class == TP_CLASS_0) { 42336399Ssklower IFDEBUG(D_EMIT) 42436399Ssklower printf("DT tpdu: class 0 m 0x%x hdr 0x%x\n", m, hdr); 42536399Ssklower dump_buf( hdr, hdr->tpdu_li + 1 ); 42636399Ssklower ENDDEBUG 42736399Ssklower ((struct tp0du *)hdr)->tp0du_eot = eot; 42836399Ssklower ((struct tp0du *)hdr)->tp0du_mbz = 0; 42936399Ssklower IFDEBUG(D_EMIT) 43036399Ssklower printf("DT 2 tpdu: class 0 m 0x%x hdr 0x%x\n", m, hdr); 43136399Ssklower dump_buf( hdr, hdr->tpdu_li + 1 ); 43236399Ssklower ENDDEBUG 43336399Ssklower } else { 43436399Ssklower hdr->tpdu_DTseq = seq; 43536399Ssklower hdr->tpdu_DTeot = eot; 43636399Ssklower } 43736399Ssklower if(eot) { 43836399Ssklower IncStat(ts_EOT_sent); 43936399Ssklower } 44036399Ssklower IncStat(ts_DT_sent); 44136399Ssklower IncPStat(tpcb, tps_DT_sent); 44236399Ssklower break; 44336399Ssklower 44436399Ssklower case AK_TPDU_type:/* ak not used in class 0 */ 44536399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); 44636399Ssklower data = (struct mbuf *)0; 44751204Ssklower olduwe = tpcb->tp_sent_uwe; 44836399Ssklower 44951204Ssklower if (seq != tpcb->tp_sent_rcvnxt || tpcb->tp_rsycnt == 0) { 45051204Ssklower LOCAL_CREDIT( tpcb ); 45136399Ssklower tpcb->tp_sent_uwe = 45236399Ssklower SEQ(tpcb,tpcb->tp_rcvnxt + tpcb->tp_lcredit -1); 45336399Ssklower tpcb->tp_sent_lcdt = tpcb->tp_lcredit; 45451204Ssklower acking_ooo = 0; 45551204Ssklower } else 45651204Ssklower acking_ooo = 1; 45736399Ssklower 45851204Ssklower IFDEBUG(D_RENEG) 45951204Ssklower /* occasionally fake a reneging so 46051204Ssklower you can test subsequencing */ 46151204Ssklower if( olduwe & 0x1 ) { 46236399Ssklower tpcb->tp_reneged = 1; 46351204Ssklower IncStat(ts_ldebug); 46436399Ssklower } 46551204Ssklower ENDDEBUG 46651204Ssklower /* Are we about to reneg on credit? 46751204Ssklower * When might we do so? 46851204Ssklower * a) when using optimistic credit (which we no longer do). 46951204Ssklower * b) when drain() gets implemented (not in the plans). 47051204Ssklower * c) when D_RENEG is on. 47151204Ssklower * d) when DEC BIT response is implemented. 47251204Ssklower * (not- when we do this, we'll need to implement flow control 47351204Ssklower * confirmation) 47451204Ssklower */ 47551204Ssklower if( SEQ_LT(tpcb, tpcb->tp_sent_uwe, olduwe) ) { 47651204Ssklower tpcb->tp_reneged = 1; 47751204Ssklower IncStat(ts_lcdt_reduced); 47851204Ssklower IFTRACE(D_CREDIT) 47951204Ssklower tptraceTPCB(TPPTmisc, 48051204Ssklower "RENEG: olduwe newuwe lcredit rcvnxt", 48151204Ssklower olduwe, 48251204Ssklower tpcb->tp_sent_uwe, tpcb->tp_lcredit, 48351204Ssklower tpcb->tp_rcvnxt); 48451204Ssklower ENDTRACE 48551204Ssklower } 48651204Ssklower IFPERF(tpcb) 48751204Ssklower /* new lwe is less than old uwe means we're 48851204Ssklower * acking before we received a whole window full 48951204Ssklower */ 49051204Ssklower if( SEQ_LT( tpcb, tpcb->tp_rcvnxt, olduwe) ) { 49151204Ssklower /* tmp1 = number of pkts fewer than the full window */ 49251204Ssklower register int tmp1 = 49351204Ssklower (int) SEQ_SUB( tpcb, olduwe, tpcb->tp_rcvnxt); 49436399Ssklower 49551204Ssklower if(tmp1 > TP_PM_MAX) 49651204Ssklower tmp1 = TP_PM_MAX; 49751204Ssklower IncPStat( tpcb, tps_ack_early[tmp1] ); 49836399Ssklower 49951204Ssklower /* tmp1 = amt of new cdt we're advertising */ 50051204Ssklower tmp1 = SEQ_SUB( tpcb, seq, tpcb->tp_sent_rcvnxt); 50151204Ssklower if(tmp1 > TP_PM_MAX ) 50251204Ssklower tmp1 = TP_PM_MAX; 50336399Ssklower 50451204Ssklower IncPStat( tpcb, 50551204Ssklower tps_cdt_acked [ tmp1 ] 50651204Ssklower [ ((tpcb->tp_lcredit > TP_PM_MAX)? 50751204Ssklower TP_PM_MAX:tpcb->tp_lcredit) ] ); 50836399Ssklower 50951204Ssklower } 51051204Ssklower ENDPERF 51136399Ssklower 51236399Ssklower IFTRACE(D_ACKSEND) 51336399Ssklower tptraceTPCB(TPPTack, seq, tpcb->tp_lcredit, tpcb->tp_sent_uwe, 51436399Ssklower tpcb->tp_r_subseq, 0); 51536399Ssklower ENDTRACE 51636399Ssklower if (tpcb->tp_xtd_format) { 51736399Ssklower #ifdef BYTE_ORDER 51848747Ssklower union seq_type seqeotX; 51948747Ssklower 52048747Ssklower seqeotX.s_seq = seq; 52148747Ssklower seqeotX.s_eot = 0; 52248747Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 52336399Ssklower hdr->tpdu_AKcdtX = htons(tpcb->tp_lcredit); 52436399Ssklower #else 52536399Ssklower hdr->tpdu_cdt = 0; 52636399Ssklower hdr->tpdu_AKseqX = seq; 52736399Ssklower hdr->tpdu_AKcdtX = tpcb->tp_lcredit; 52836399Ssklower #endif BYTE_ORDER 52936399Ssklower } else { 53036399Ssklower hdr->tpdu_AKseq = seq; 53136399Ssklower hdr->tpdu_AKcdt = tpcb->tp_lcredit; 53236399Ssklower } 53351204Ssklower if ((tpcb->tp_class == TP_CLASS_4) && 53451204Ssklower (tpcb->tp_reneged || acking_ooo)) { 53536399Ssklower /* 53636399Ssklower * Ack subsequence parameter req'd if WE reneged on 53736399Ssklower * credit offered. (ISO 8073, 12.2.3.8.2, p. 74) 53836399Ssklower */ 53936399Ssklower IFDEBUG(D_RENEG) 54036399Ssklower printf("Adding subseq 0x%x\n", tpcb->tp_s_subseq); 54136399Ssklower ENDDEBUG 54236399Ssklower tpcb->tp_s_subseq++; 54336399Ssklower /* 54436399Ssklower * add tmp subseq and do a htons on it. 54536399Ssklower */ 54636399Ssklower ADDOPTION(TPP_subseq, hdr, 54736399Ssklower sizeof(tpcb->tp_s_subseq), tpcb->tp_s_subseq); 54836399Ssklower } else 54936399Ssklower tpcb->tp_s_subseq = 0; 55036399Ssklower 55136399Ssklower if ( tpcb->tp_sendfcc || eot ) /* overloaded to mean SEND FCC */ { 55236399Ssklower /* 55336399Ssklower * Rules for sending FCC ("should" send when) : 55436399Ssklower * %a) received an ack from peer with NO NEWS whatsoever, 55536399Ssklower * and it did not contain an FCC 55636399Ssklower * b) received an ack from peer that opens its closed window. 55736399Ssklower * c) received an ack from peer after it reneged on its 55836399Ssklower * offered credit, AND this ack raises UWE but LWE is same 55936399Ssklower * and below UWE at time of reneging (reduction) 56036399Ssklower * Now, ISO 8073 12.2.3.8.3 says 56136399Ssklower * that a retransmitted AK shall not contain the FCC 56236399Ssklower * parameter. Now, how the hell you tell the difference 56336399Ssklower * between a retransmitted ack and an ack that's sent in 56436399Ssklower * response to a received ack, I don't know, because without 56536399Ssklower * any local activity, and w/o any received DTs, they 56636399Ssklower * will contain exactly the same credit/seq# information. 56736399Ssklower * Anyway, given that the "retransmission of acks" 56836399Ssklower * procedure (ISO 8073 12.2.3.8.3) is optional, and we 56936399Ssklower * don't do it (although the peer can't tell that), we 57036399Ssklower * ignore this last rule. 57136399Ssklower * 57236399Ssklower * We send FCC for reasons a) and b) only. 57336399Ssklower * To add reason c) would require a ridiculous amount of state. 57436399Ssklower * 57536399Ssklower */ 57636399Ssklower u_short bogus[4]; /* lwe(32), subseq(16), cdt(16) */ 57736399Ssklower SeqNum lwe; 57836399Ssklower u_short subseq, fcredit; 57936399Ssklower 58036399Ssklower tpcb->tp_sendfcc = 0; 58136399Ssklower 58236399Ssklower lwe = (SeqNum) htonl(tpcb->tp_snduna); 58336399Ssklower subseq = htons(tpcb->tp_r_subseq); 58436399Ssklower fcredit = htons(tpcb->tp_fcredit); 58536399Ssklower 58637469Ssklower bcopy((caddr_t) &lwe, (caddr_t)&bogus[0], sizeof(SeqNum)); 58737469Ssklower bcopy((caddr_t) &subseq, (caddr_t)&bogus[2], sizeof(u_short)); 58837469Ssklower bcopy((caddr_t) &fcredit, (caddr_t)&bogus[3], sizeof(u_short)); 58936399Ssklower 59036399Ssklower IFTRACE(D_ACKSEND) 59136399Ssklower tptraceTPCB(TPPTmisc, 59236399Ssklower "emit w/FCC: snduna r_subseq fcredit", 59336399Ssklower tpcb->tp_snduna, tpcb->tp_r_subseq, 59436399Ssklower tpcb->tp_fcredit, 0); 59536399Ssklower ENDTRACE 59636399Ssklower 59736399Ssklower IFDEBUG(D_ACKSEND) 59836399Ssklower printf("Calling ADDOPTION 0x%x, 0x%x, 0x%x,0x%x\n", 59936399Ssklower TPP_flow_cntl_conf, 60036399Ssklower hdr, sizeof(bogus), bogus[0]); 60136399Ssklower ENDDEBUG 60236399Ssklower ADDOPTION(TPP_flow_cntl_conf, hdr, sizeof(bogus), bogus[0]); 60336399Ssklower IFDEBUG(D_ACKSEND) 60436399Ssklower printf("after ADDOPTION hdr 0x%x hdr->tpdu_li 0x%x\n", 60536399Ssklower hdr, hdr->tpdu_li); 60636399Ssklower printf( 60736399Ssklower "after ADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 60836399Ssklower csum_offset, hdr->tpdu_li); 60936399Ssklower ENDDEBUG 61036399Ssklower 61136399Ssklower } 61236399Ssklower tpcb->tp_reneged = 0; 61336399Ssklower tpcb->tp_sent_rcvnxt = seq; 61451204Ssklower if (tpcb->tp_fcredit == 0) { 61551204Ssklower int timo = tpcb->tp_keepalive_ticks; 61651204Ssklower if (tpcb->tp_rxtshift < TP_MAXRXTSHIFT) 61751204Ssklower tpcb->tp_rxtshift++; 61851204Ssklower timo = min(timo, ((int)tpcb->tp_dt_ticks) << tpcb->tp_rxtshift); 61951204Ssklower tp_ctimeout(tpcb, TM_sendack, timo); 62051204Ssklower } else 62151204Ssklower tp_ctimeout(tpcb, TM_sendack, tpcb->tp_keepalive_ticks); 62236399Ssklower IncStat(ts_AK_sent); 62336399Ssklower IncPStat(tpcb, tps_AK_sent); 62436399Ssklower IFDEBUG(D_ACKSEND) 62536399Ssklower printf( 62636399Ssklower "2 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 62736399Ssklower csum_offset, hdr->tpdu_li); 62836399Ssklower ENDDEBUG 62936399Ssklower break; 63036399Ssklower 63136399Ssklower case ER_TPDU_type: 63236399Ssklower hdr->tpdu_ERreason = eot; 63336399Ssklower hdr->tpdu_cdt = 0; 63436399Ssklower /* no user data */ 63536399Ssklower data = (struct mbuf *)0; 63636399Ssklower IncStat(ts_ER_sent); 63736399Ssklower break; 63836399Ssklower } 63936399Ssklower 64036399Ssklower } 64136399Ssklower ASSERT( ((int)hdr->tpdu_li > 0) && ((int)hdr->tpdu_li < MLEN) ); 64236399Ssklower 64336399Ssklower m->m_next = data; 64436399Ssklower 64537469Ssklower ASSERT( hdr->tpdu_li < MLEN ); /* leave this in */ 64636399Ssklower ASSERT( hdr->tpdu_li != 0 ); /* leave this in */ 64736399Ssklower 64836399Ssklower m->m_len = hdr->tpdu_li ; 64936399Ssklower hdr->tpdu_li --; /* doesn't include the li field */ 65036399Ssklower 65136399Ssklower datalen = m_datalen( m ); /* total len */ 65236399Ssklower 65336399Ssklower ASSERT( datalen <= tpcb->tp_l_tpdusize ); /* may become a problem 65436399Ssklower when CLNP is used; leave in here for the time being */ 65536399Ssklower IFDEBUG(D_ACKSEND) 65636399Ssklower printf( 65736399Ssklower "4 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 65836399Ssklower csum_offset, hdr->tpdu_li); 65936399Ssklower ENDDEBUG 66036399Ssklower if( datalen > tpcb->tp_l_tpdusize ) { 66136399Ssklower printf("data len 0x%x tpcb->tp_l_tpdusize 0x%x\n", 66236399Ssklower datalen, tpcb->tp_l_tpdusize); 66336399Ssklower } 66436399Ssklower IFDEBUG(D_EMIT) 66536399Ssklower printf( 66636399Ssklower "tp_emit before gen_csum m_len 0x%x, csum_offset 0x%x, datalen 0x%x\n", 66736399Ssklower m->m_len, csum_offset, datalen); 66836399Ssklower ENDDEBUG 66936399Ssklower if( tpcb->tp_use_checksum || 67036399Ssklower (dutype == CR_TPDU_type && (tpcb->tp_class & TP_CLASS_4)) ) { 67136399Ssklower iso_gen_csum(m, csum_offset, datalen); 67236399Ssklower } 67336399Ssklower 67436399Ssklower IFDEBUG(D_EMIT) 67536399Ssklower printf("tp_emit before tpxxx_output tpcb 0x%x, dutype 0x%x, datalen 0x%x\n", 67636399Ssklower tpcb, dutype, datalen); 67737469Ssklower dump_buf(mtod(m, caddr_t), datalen); 67836399Ssklower ENDDEBUG 67936399Ssklower 68036399Ssklower IFPERF(tpcb) 68136399Ssklower if( dutype == DT_TPDU_type ) { 68236399Ssklower PStat(tpcb, Nb_to_ll) += (datalen - m->m_len); 68337469Ssklower tpmeas( tpcb->tp_lref, TPtime_to_ll, (struct timeval *)0, 68436399Ssklower seq, PStat(tpcb, Nb_to_ll), (datalen - m->m_len)); 68536399Ssklower } 68636399Ssklower ENDPERF 68736399Ssklower 68836399Ssklower IFTRACE(D_EMIT) 68936399Ssklower tptraceTPCB(TPPTtpduout, dutype, hdr, hdr->tpdu_li+1, datalen, 0); 69036399Ssklower ENDTRACE 69136399Ssklower IFDEBUG(D_EMIT) 69236399Ssklower printf("OUTPUT: tpcb 0x%x, isop 0x%x, so 0x%x\n", 69336399Ssklower tpcb, tpcb->tp_npcb, tpcb->tp_sock); 69436399Ssklower ENDDEBUG 69536399Ssklower 69636399Ssklower { extern char tp_delay; 69736399Ssklower 69836399Ssklower if( tp_delay ) 69936399Ssklower if( tpcb->tp_use_checksum == 0 ) { 70036399Ssklower register u_int i = tp_delay; 70136399Ssklower for (; i!= 0; i--) 70236399Ssklower (void) iso_check_csum(m, datalen); 70336399Ssklower } 70436399Ssklower } 70536399Ssklower ASSERT( m->m_len > 0 ); 70636399Ssklower error = (tpcb->tp_nlproto->nlp_output)(tpcb->tp_npcb, m, datalen, 70736399Ssklower !tpcb->tp_use_checksum); 70836399Ssklower IFDEBUG(D_EMIT) 70936399Ssklower printf("OUTPUT: returned 0x%x\n", error); 71036399Ssklower ENDDEBUG 71136399Ssklower IFTRACE(D_EMIT) 71236399Ssklower tptraceTPCB(TPPTmisc, 71336399Ssklower "tp_emit nlproto->output netservice returns datalen", 71436399Ssklower tpcb->tp_nlproto->nlp_output, tpcb->tp_netservice, error, datalen); 71536399Ssklower ENDTRACE 71636399Ssklower done: 71751204Ssklower if (error) { 71851204Ssklower if (dutype == AK_TPDU_type) 71951204Ssklower tp_ctimeout(tpcb, TM_sendack, 1); 72051204Ssklower if (error == E_CO_QFULL) { 72151204Ssklower tp_quench(tpcb, PRC_QUENCH); 72251204Ssklower return 0; 72351204Ssklower } 72436399Ssklower } 72536399Ssklower return error; 72636399Ssklower } 72736399Ssklower /* 72836399Ssklower * NAME: tp_error_emit() 72936399Ssklower * CALLED FROM: tp_input() when a DR or ER is to be issued in 73036399Ssklower * response to an input error. 73136399Ssklower * FUNCTION and ARGUMENTS: 73236399Ssklower * The error type is the first argument. 73336399Ssklower * The argument (sref) is the source reference on the bad incoming tpdu, 73436399Ssklower * and is used for a destination reference on the outgoing packet. 73536399Ssklower * (faddr) and (laddr) are the foreign and local addresses for this 73636399Ssklower * connection. 73736399Ssklower * (erdata) is a ptr to the errant incoming tpdu, and is copied into the 73836399Ssklower * outgoing ER, if an ER is to be issued. 73936399Ssklower * (erlen) is the number of octets of the errant tpdu that we should 74036399Ssklower * try to copy. 74136399Ssklower * (tpcb) is the pcb that describes the connection for which the bad tpdu 74236399Ssklower * arrived. 74336399Ssklower * RETURN VALUES: 74436399Ssklower * 0 OK 74536399Ssklower * ENOBUFS 74636399Ssklower * E* from net layer datagram output routine 74736399Ssklower * SIDE EFFECTS: 74836399Ssklower * 74936399Ssklower * NOTES: 75036399Ssklower */ 75136399Ssklower 75236399Ssklower int 75336399Ssklower tp_error_emit(error, sref, faddr, laddr, erdata, erlen, tpcb, cons_channel, 75436399Ssklower dgout_routine) 75536399Ssklower int error; 75636399Ssklower u_long sref; 75736399Ssklower struct sockaddr_iso *faddr, *laddr; 75836399Ssklower struct mbuf *erdata; 75936399Ssklower int erlen; 76036399Ssklower struct tp_pcb *tpcb; 76150535Ssklower caddr_t cons_channel; 76236399Ssklower int (*dgout_routine)(); 76336399Ssklower { 76436399Ssklower int dutype; 76536399Ssklower int datalen = 0; 76636399Ssklower register struct tpdu *hdr; 76736399Ssklower register struct mbuf *m; 76836399Ssklower int csum_offset; 76936399Ssklower 77036399Ssklower IFTRACE(D_ERROR_EMIT) 77136399Ssklower tptrace(TPPTmisc, "tp_error_emit error sref tpcb erlen", 77236399Ssklower error, sref, tpcb, erlen); 77336399Ssklower ENDTRACE 77436399Ssklower IFDEBUG(D_ERROR_EMIT) 77536399Ssklower printf( 77636399Ssklower "tp_error_emit error 0x%x sref 0x%x tpcb 0x%x erlen 0x%x chan 0x%x\n", 77736399Ssklower error, sref, tpcb, erlen, cons_channel); 77836399Ssklower ENDDEBUG 77936399Ssklower 78036399Ssklower MGET(m, M_DONTWAIT, TPMT_TPHDR); 78136399Ssklower if (m == NULL) { 78236399Ssklower return ENOBUFS; 78336399Ssklower } 78436399Ssklower m->m_len = sizeof(struct tpdu); 78536399Ssklower m->m_act = MNULL; 78636399Ssklower 78736399Ssklower hdr = mtod(m, struct tpdu *); 78836399Ssklower 78936399Ssklower IFDEBUG(D_ERROR_EMIT) 79036399Ssklower printf("[error 0x%x] [error&0xff 0x%x] [(char)error 0x%x]\n", 79136399Ssklower error, error&0xff, (char)error); 79236399Ssklower ENDDEBUG 79336399Ssklower 79436399Ssklower 79542494Ssklower if (error & TP_ERROR_SNDC) 79642494Ssklower dutype = DC_TPDU_type; 79742494Ssklower else if (error & 0x40) { 79836399Ssklower error &= ~0x40; 79936399Ssklower dutype = ER_TPDU_type; 80036399Ssklower } else 80136399Ssklower dutype = DR_TPDU_type; 80242494Ssklower error &= 0xff; 80336399Ssklower 80436399Ssklower hdr->tpdu_type = dutype; 80536399Ssklower hdr->tpdu_cdt = 0; 80636399Ssklower 80736399Ssklower switch( dutype ) { 80836399Ssklower 80942494Ssklower case DC_TPDU_type: 81042494Ssklower IncStat(ts_DC_sent); 81142494Ssklower hdr->tpdu_li = 6; 81242494Ssklower hdr->tpdu_DCdref = htons(sref); 81342494Ssklower hdr->tpdu_DCsref = tpcb ? htons(tpcb->tp_lref) : 0; 81442494Ssklower IFDEBUG(D_ERROR_EMIT) 81542494Ssklower printf("DC case:\n"); 81642494Ssklower dump_buf( hdr, 6); 81742494Ssklower ENDDEBUG 81842494Ssklower /* forget the add'l information variable part */ 81942494Ssklower break; 82042494Ssklower 82136399Ssklower case DR_TPDU_type: 82236399Ssklower IncStat(ts_DR_sent); 82336399Ssklower hdr->tpdu_li = 7; 82436399Ssklower hdr->tpdu_DRdref = htons(sref); 82542494Ssklower hdr->tpdu_DRsref = 0; 82636399Ssklower hdr->tpdu_DRreason = (char)error; 82736399Ssklower IFDEBUG(D_ERROR_EMIT) 82836399Ssklower printf("DR case:\n"); 82936399Ssklower dump_buf( hdr, 7); 83036399Ssklower ENDDEBUG 83136399Ssklower /* forget the add'l information variable part */ 83236399Ssklower break; 83336399Ssklower 83436399Ssklower case ER_TPDU_type: 83536399Ssklower IncStat(ts_ER_sent); 83636399Ssklower hdr->tpdu_li = 5; 83736399Ssklower hdr->tpdu_ERreason = (char)error; 83850535Ssklower hdr->tpdu_ERdref = htons(sref); 83936399Ssklower break; 84036399Ssklower 84136399Ssklower default: 84236399Ssklower ASSERT(0); 84336399Ssklower printf("TP PANIC: bad dutype 0x%x\n", dutype); 84436399Ssklower } 84536399Ssklower 84636399Ssklower if(tpcb) 84736399Ssklower if( tpcb->tp_use_checksum ) { 84836399Ssklower ADDOPTION(TPP_checksum, hdr, 2, csum_offset /* dummy argument */); 84936399Ssklower csum_offset = hdr->tpdu_li - 2; 85036399Ssklower } 85136399Ssklower 85237469Ssklower ASSERT( hdr->tpdu_li < MLEN ); 85336399Ssklower 85436399Ssklower if (dutype == ER_TPDU_type) { 85536399Ssklower /* copy the errant tpdu into another 'variable part' */ 85636399Ssklower register caddr_t P; 85736399Ssklower 85836399Ssklower IFTRACE(D_ERROR_EMIT) 85936399Ssklower tptrace(TPPTmisc, "error_emit ER len tpduli", erlen, hdr->tpdu_li, 86036399Ssklower 0,0); 86136399Ssklower ENDTRACE 86236399Ssklower IFDEBUG(D_ERROR_EMIT) 86336399Ssklower printf("error_emit ER len 0x%x tpduli 0x%x\n", erlen, hdr->tpdu_li); 86436399Ssklower ENDDEBUG 86536399Ssklower 86636399Ssklower /* copy at most as many octets for which you have room */ 86736399Ssklower if (erlen + hdr->tpdu_li + 2 > TP_MAX_HEADER_LEN) 86836399Ssklower erlen = TP_MAX_HEADER_LEN - hdr->tpdu_li - 2; 86936399Ssklower 87036399Ssklower /* add the "invalid tpdu" parameter : required in class 0 */ 87136399Ssklower P = (caddr_t)hdr + (int)(hdr->tpdu_li); 87236399Ssklower vbptr(P)->tpv_code = TPP_invalid_tpdu; /* parameter code */ 87336399Ssklower vbptr(P)->tpv_len = erlen; /* parameter length */ 87436399Ssklower m->m_len = hdr->tpdu_li + 2; /* 1 for code, 1 for length */ 87536399Ssklower 87636399Ssklower /* tp_input very likely handed us an mbuf chain w/ nothing in 87736399Ssklower * the first mbuf and the data following the empty mbuf 87836399Ssklower */ 87936399Ssklower if(erdata->m_len == 0) { 88036399Ssklower erdata = m_free(erdata); /* returns the next mbuf on the chain */ 88136399Ssklower } 88237469Ssklower /* 88337469Ssklower * copy only up to the bad octet 88437469Ssklower * (or max that will fit in a header 88537469Ssklower */ 88637469Ssklower m->m_next = m_copy(erdata, 0, erlen); 88736399Ssklower hdr->tpdu_li += erlen + 2; 88836399Ssklower m_freem(erdata); 88936399Ssklower } else { 89036399Ssklower IFDEBUG(D_ERROR_EMIT) 89136399Ssklower printf("error_emit DR error tpduli 0x%x\n", error, hdr->tpdu_li); 89236399Ssklower dump_buf( (char *)hdr, hdr->tpdu_li ); 89336399Ssklower ENDDEBUG 89436399Ssklower m->m_len = hdr->tpdu_li ; 89536399Ssklower m_freem(erdata); 89636399Ssklower } 89736399Ssklower 89836399Ssklower hdr->tpdu_li --; 89936399Ssklower IFTRACE(D_ERROR_EMIT) 90036399Ssklower tptrace(TPPTtpduout, 2, hdr, hdr->tpdu_li+1, 0, 0); 90136399Ssklower ENDTRACE 90236399Ssklower 90336399Ssklower datalen = m_datalen( m); 90450648Ssklower if (tpcb) { 90536399Ssklower if( tpcb->tp_use_checksum ) { 90636399Ssklower IFTRACE(D_ERROR_EMIT) 90736399Ssklower tptrace(TPPTmisc, "before gen csum datalen", datalen,0,0,0); 90836399Ssklower ENDTRACE 90936399Ssklower IFDEBUG(D_ERROR_EMIT) 91036399Ssklower printf("before gen csum datalen 0x%x, csum_offset 0x%x\n", 91136399Ssklower datalen, csum_offset); 91236399Ssklower ENDDEBUG 91336399Ssklower 91436399Ssklower iso_gen_csum(m, csum_offset, datalen); 91536399Ssklower } 91636399Ssklower 91736399Ssklower IFDEBUG(D_ERROR_EMIT) 91836399Ssklower printf("OUTPUT: tpcb 0x%x, isop 0x%x, so 0x%x\n", 91936399Ssklower tpcb, tpcb->tp_npcb, tpcb->tp_sock); 92036399Ssklower ENDDEBUG 92150648Ssklower } 92250648Ssklower if (cons_channel) { 92350648Ssklower #ifdef TPCONS 92450648Ssklower struct pklcd *lcp = (struct pklcd *)cons_channel; 92550648Ssklower struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext; 92636399Ssklower 92750648Ssklower tpcons_dg_output(cons_channel, m, datalen); 92850648Ssklower /* was if (tpcb == 0) iso_pcbdetach(isop); */ 92950648Ssklower /* but other side may want to try again over same VC, 93050648Ssklower so, we'll depend on him closing it, but in case it gets forgotten 93150648Ssklower we'll mark it for garbage collection */ 93250648Ssklower lcp->lcd_flags |= X25_DG_CIRCUIT; 93336399Ssklower IFDEBUG(D_ERROR_EMIT) 93450648Ssklower printf("OUTPUT: dutype 0x%x channel 0x%x\n", 93550648Ssklower dutype, cons_channel); 93650648Ssklower ENDDEBUG 93750648Ssklower #else 93850648Ssklower printf("TP panic! cons channel 0x%x but not cons configured\n", 93950648Ssklower cons_channel); 94050648Ssklower #endif 94150648Ssklower } else if (tpcb) { 94250648Ssklower 94350648Ssklower IFDEBUG(D_ERROR_EMIT) 94436399Ssklower printf("tp_error_emit 1 sending DG: Laddr\n"); 94537469Ssklower dump_addr((struct sockaddr *)laddr); 94636399Ssklower printf("Faddr\n"); 94737469Ssklower dump_addr((struct sockaddr *)faddr); 94836399Ssklower ENDDEBUG 94936399Ssklower return (tpcb->tp_nlproto->nlp_dgoutput)( 95036399Ssklower &laddr->siso_addr, 95136399Ssklower &faddr->siso_addr, 95236399Ssklower m, datalen, 95336399Ssklower /* no route */ (caddr_t)0, !tpcb->tp_use_checksum); 95450648Ssklower } else if (dgout_routine) { 95536399Ssklower IFDEBUG(D_ERROR_EMIT) 95636399Ssklower printf("tp_error_emit sending DG: Laddr\n"); 95737469Ssklower dump_addr((struct sockaddr *)laddr); 95836399Ssklower printf("Faddr\n"); 95937469Ssklower dump_addr((struct sockaddr *)faddr); 96036399Ssklower ENDDEBUG 96150648Ssklower return (*dgout_routine)( &laddr->siso_addr, &faddr->siso_addr, 96250648Ssklower m, datalen, /* no route */ 96350648Ssklower (caddr_t)0, /* nochecksum==false */0); 96450648Ssklower } else { 96536399Ssklower IFDEBUG(D_ERROR_EMIT) 96636399Ssklower printf("tp_error_emit DROPPING \n", m); 96736399Ssklower ENDDEBUG 96836399Ssklower IncStat(ts_send_drop); 96936399Ssklower m_freem(m); 97036399Ssklower return 0; 97136399Ssklower } 97236399Ssklower } 973