136399Ssklower /*********************************************************** 236399Ssklower Copyright IBM Corporation 1987 336399Ssklower 436399Ssklower All Rights Reserved 536399Ssklower 636399Ssklower Permission to use, copy, modify, and distribute this software and its 736399Ssklower documentation for any purpose and without fee is hereby granted, 836399Ssklower provided that the above copyright notice appear in all copies and that 936399Ssklower both that copyright notice and this permission notice appear in 1036399Ssklower supporting documentation, and that the name of IBM not be 1136399Ssklower used in advertising or publicity pertaining to distribution of the 1236399Ssklower software without specific, written prior permission. 1336399Ssklower 1436399Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1536399Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 1636399Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 1736399Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 1836399Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 1936399Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2036399Ssklower SOFTWARE. 2136399Ssklower 2236399Ssklower ******************************************************************/ 2336399Ssklower 2436399Ssklower /* 2536399Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 2636399Ssklower */ 2736399Ssklower /* 2836399Ssklower * ARGO TP 2936399Ssklower * 3036399Ssklower * $Header: tp_emit.c,v 5.5 88/11/18 17:27:20 nhall Exp $ 3136399Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_emit.c,v $ 32*48747Ssklower * @(#)tp_emit.c 7.7 (Berkeley) 04/26/91 * 3336399Ssklower * 3436399Ssklower * This file contains tp_emit() and tp_error_emit(), which 3536399Ssklower * form TPDUs and hand them to ip. 3636399Ssklower * They take data in the form of mbuf chain, allocate mbufs as 3736399Ssklower * necessary for headers, and set the fields as appropriate from 3836399Ssklower * information found in the tpcb and net-level pcb. 3936399Ssklower * 4036399Ssklower * The worst thing about this code is adding the variable-length 4136399Ssklower * options on a machine that requires alignment for any memory access 4236399Ssklower * that isn't of size 1. See the macro ADDOPTION() below. 4336399Ssklower * 4436399Ssklower * We don't do any concatenation. (There's a kludge to test the 4536399Ssklower * basic mechanism of separation under the 'w' tpdebug option, that's all.) 4636399Ssklower */ 4736399Ssklower 4836399Ssklower #ifndef lint 4936399Ssklower static char *rcsid = "$Header: tp_emit.c,v 5.5 88/11/18 17:27:20 nhall Exp $"; 5036399Ssklower #endif lint 5136399Ssklower 5236399Ssklower 5336399Ssklower #include "param.h" 5436399Ssklower #include "mbuf.h" 5536399Ssklower #include "socket.h" 5636399Ssklower #include "socketvar.h" 5736399Ssklower #include "protosw.h" 5836399Ssklower #include "errno.h" 5936399Ssklower #include "types.h" 6036399Ssklower #include "time.h" 6137469Ssklower #include "iso.h" 6245900Ssklower #include "iso_pcb.h" 6337469Ssklower #include "argo_debug.h" 6437469Ssklower #include "tp_timer.h" 6537469Ssklower #include "tp_param.h" 6637469Ssklower #include "tp_stat.h" 6737469Ssklower #include "tp_pcb.h" 6837469Ssklower #include "tp_tpdu.h" 6937469Ssklower #include "tp_trace.h" 7037469Ssklower #include "tp_meas.h" 7137469Ssklower #include "tp_seq.h" 7237469Ssklower #include "iso_errno.h" 7336399Ssklower 7445900Ssklower #include "../net/if.h" 7545900Ssklower #ifdef TRUE 7645900Ssklower #undef FALSE 7745900Ssklower #undef TRUE 7845900Ssklower #endif 7945900Ssklower #include "../netccitt/x25.h" 8045900Ssklower #include "../netccitt/pk.h" 8145900Ssklower #include "../netccitt/pk_var.h" 8245900Ssklower 8336399Ssklower void iso_gen_csum(); 8436399Ssklower 8536399Ssklower 8636399Ssklower /* Here is a mighty kludge. The token ring misorders packets if you 8736399Ssklower * fire them at it too fast, and TP sans checksum is "too fast", so 8836399Ssklower * we have introduced a delay when checksumming isn't used. 8936399Ssklower */ 9036399Ssklower char tp_delay = 0x00; /* delay to keep token ring from blowing it */ 9136399Ssklower 9236399Ssklower /* 9336399Ssklower * NAME: tp_emit() 9436399Ssklower * 9536399Ssklower * CALLED FROM: tp.trans and from tp_sbsend() 9636399Ssklower * 9736399Ssklower * FUNCTION and ARGUMENTS: 9836399Ssklower * Emits one tpdu of the type (dutype), of the format appropriate 9936399Ssklower * to the connection described by the pcb (tpcb), with sequence 10036399Ssklower * number (seq) (where appropriate), end-of-tsdu bit (eot) where 10136399Ssklower * appropriate, and with the data in the mbuf chain (data). 10236399Ssklower * For DR and ER tpdus, the argument (eot) is 10336399Ssklower * the reason for issuing the tpdu rather than an end-of-tsdu indicator. 10436399Ssklower * 10536399Ssklower * RETURNS: 10636399Ssklower * 0 OK 10736399Ssklower * ENOBUFS 10836399Ssklower * E* returned from net layer output rtn 10936399Ssklower * 11036399Ssklower * SIDE EFFECTS: 11136399Ssklower * 11236399Ssklower * NOTES: 11336399Ssklower * 11436399Ssklower * WE ASSUME that the tp header + all options will fit in ONE mbuf. 11536399Ssklower * If mbufs are 256 this will most likely be true, but if they are 128 it's 11636399Ssklower * possible that they won't. 11736399Ssklower * If you used every option on the CR + max. user data you'd overrun 11836399Ssklower * 112 but unless you used > 115 bytes for the security 11936399Ssklower * parameter, it would fit in a 256-byte mbuf (240 bytes for the header) 12036399Ssklower * We don't support the security parameter, so this isn't a problem. 12136399Ssklower * If security is added, we ought to remove this assumption. 12236399Ssklower * 12336399Ssklower * We do not implement the flow control confirmation "element of procedure". 12436399Ssklower * A) it should not affect interoperability, 12536399Ssklower * B) it should not be necessary - the protocol will eventually 12636399Ssklower * straighten things out w/o FCC, as long as we don't have severely 12736399Ssklower * mismatched keepalive and inactivity timers, and 12836399Ssklower * C) it appears not to be REQUIRED, and 12936399Ssklower * D) it's incredibly grotesque, and no doubt will lengthen a few 13036399Ssklower * critical paths. 13136399Ssklower * HOWEVER, we're thinking about putting it in anyway, for 13236399Ssklower * completeness, just like we did with ack subsequencing. 13336399Ssklower */ 13436399Ssklower 13536399Ssklower int 13636399Ssklower tp_emit(dutype, tpcb, seq, eot, data) 13736399Ssklower int dutype; 13836399Ssklower struct tp_pcb *tpcb; 13936399Ssklower SeqNum seq; 14036399Ssklower u_int eot; 14136399Ssklower struct mbuf *data; 14236399Ssklower { 14336399Ssklower register struct tpdu *hdr; 14436399Ssklower register struct mbuf *m; 14536399Ssklower int csum_offset=0; 14636399Ssklower int datalen = 0; 14736399Ssklower int error = 0; 14836399Ssklower 14936399Ssklower /* NOTE: 15036399Ssklower * here we treat tpdu_li as if it DID include the li field, up until 15136399Ssklower * the end, at which time we subtract 1 15236399Ssklower * THis is because if we subtract 1 right away, we end up adding 15336399Ssklower * one every time we add an option. 15436399Ssklower */ 15536399Ssklower IFDEBUG(D_EMIT) 15636399Ssklower printf( 15737469Ssklower "tp_emit dutype 0x%x, tpcb 0x%x, eot 0x%x, seq 0x%x, data 0x%x", 15837469Ssklower dutype, tpcb, eot, seq, data); 15936399Ssklower ENDDEBUG 16036399Ssklower 16137469Ssklower if (dutype == CR_TPDU || dutype == CC_TPDU) { 16237469Ssklower m = (struct mbuf *) malloc((u_long)256, M_MBUF, M_DONTWAIT); 16337469Ssklower if (m) { 16437469Ssklower m->m_type = TPMT_TPHDR; 16537469Ssklower mbstat.m_mtypes[TPMT_TPHDR]++; 16637469Ssklower m->m_next = MNULL; 16737469Ssklower m->m_data = m->m_dat; 16837469Ssklower m->m_flags = 0; 16937469Ssklower } 17037469Ssklower } else { 17137469Ssklower MGET(m, M_DONTWAIT, TPMT_TPHDR); 17237469Ssklower } 17336399Ssklower if (m == NULL) { 17436399Ssklower if(data != (struct mbuf *)0) 17536399Ssklower m_freem(data); 17636399Ssklower error = ENOBUFS; 17736399Ssklower goto done; 17836399Ssklower } 17936399Ssklower m->m_len = sizeof(struct tpdu); 18036399Ssklower m->m_act = MNULL; 18136399Ssklower 18236399Ssklower hdr = mtod(m, struct tpdu *); 18337469Ssklower bzero((caddr_t)hdr, sizeof(struct tpdu)); 18436399Ssklower 18536399Ssklower { 18636399Ssklower int tp_headersize(); 18736399Ssklower 18836399Ssklower hdr->tpdu_type = dutype; 18936399Ssklower hdr->tpdu_li = tp_headersize(dutype, tpcb); 19036399Ssklower /* 19136399Ssklower * class 0 doesn't use this for DT 19236399Ssklower * it'll just get overwritten below 19336399Ssklower */ 19436399Ssklower hdr->tpdu_dref = htons(tpcb->tp_fref); 19536399Ssklower if( tpcb->tp_use_checksum || 19636399Ssklower (dutype == CR_TPDU_type && (tpcb->tp_class & TP_CLASS_4) )) { 19736399Ssklower csum_offset = hdr->tpdu_li + 2; /* DOESN'T include csum */ 19836399Ssklower ADDOPTION(TPP_checksum, hdr, 2, eot /* dummy arg */); 19936399Ssklower IFDEBUG(D_CHKSUM) 20036399Ssklower printf( 20136399Ssklower "tp_emit: csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 20236399Ssklower csum_offset, hdr->tpdu_li); 20336399Ssklower ENDDEBUG 20436399Ssklower } 20536399Ssklower /* 20636399Ssklower * VARIABLE PARTS... 20736399Ssklower */ 20836399Ssklower switch( dutype ) { 20936399Ssklower 21036399Ssklower case CR_TPDU_type: 21142494Ssklower hdr->tpdu_CRdref_0 = 0; /* must be zero */ 21239924Ssklower if (!tpcb->tp_cebit_off) { 21339924Ssklower tpcb->tp_win_recv = tp_start_win << 8; 21439924Ssklower LOCAL_CREDIT(tpcb); 21539924Ssklower CONG_INIT_SAMPLE(tpcb); 21639924Ssklower tpcb->tp_ackrcvd = 0; 21739924Ssklower } 21839924Ssklower else 21939924Ssklower LOCAL_CREDIT(tpcb); 22036399Ssklower 22139924Ssklower 22236399Ssklower case CC_TPDU_type: 22336399Ssklower { 22436399Ssklower u_char x; 22536399Ssklower 22636399Ssklower hdr->tpdu_CCsref = htons(tpcb->tp_lref); /* same as CRsref */ 22736399Ssklower 22836399Ssklower if( tpcb->tp_class > TP_CLASS_1 ) { 22939924Ssklower /* ifdef CE_BIT, we did this in tp_input when the CR came in */ 23039924Ssklower if (tpcb->tp_cebit_off) 23139924Ssklower LOCAL_CREDIT( tpcb ); 23236399Ssklower tpcb->tp_sent_uwe = tpcb->tp_lcredit -1; 23336399Ssklower tpcb->tp_sent_rcvnxt = 1; 23436399Ssklower tpcb->tp_sent_lcdt = tpcb->tp_lcredit; 23536399Ssklower hdr->tpdu_cdt = tpcb->tp_lcredit; 23636399Ssklower } else { 23745900Ssklower #ifdef TPCONS 23845900Ssklower if (tpcb->tp_netservice == ISO_CONS) { 23945900Ssklower struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; 24045900Ssklower struct pklcd *lcp = (struct pklcd *)(isop->isop_chan); 24145900Ssklower lcp->lcd_flags &= ~X25_DG_CIRCUIT; 24245900Ssklower } 24345900Ssklower #endif 24436399Ssklower hdr->tpdu_cdt = 0; 24536399Ssklower } 24636399Ssklower hdr->tpdu_CCclass = tp_mask_to_num(tpcb->tp_class); 24736399Ssklower hdr->tpdu_CCoptions = 24836399Ssklower (tpcb->tp_xtd_format? TPO_XTD_FMT:0) | 24936399Ssklower (tpcb->tp_use_efc? TPO_USE_EFC:0); 25036399Ssklower 25136399Ssklower IFPERF(tpcb) 25236399Ssklower u_char perf_meas = tpcb->tp_perf_on; 25336399Ssklower ADDOPTION(TPP_perf_meas, hdr, sizeof(perf_meas), perf_meas); 25436399Ssklower ENDPERF 25536399Ssklower 25636399Ssklower if( dutype == CR_TPDU_type ) { 25736399Ssklower IncStat(ts_CR_sent); 25836399Ssklower 25936399Ssklower ASSERT( tpcb->tp_lsuffixlen > 0 ); 26036399Ssklower ASSERT( tpcb->tp_fsuffixlen > 0 ); 26136399Ssklower 26236399Ssklower ADDOPTION(TPP_calling_sufx, hdr, 26337469Ssklower tpcb->tp_lsuffixlen, tpcb->tp_lsuffix[0]); 26436399Ssklower ADDOPTION(TPP_called_sufx, hdr, 26537469Ssklower tpcb->tp_fsuffixlen, tpcb->tp_fsuffix[0]); 26636399Ssklower } else { 26736399Ssklower IncStat(ts_CC_sent); 26836399Ssklower } 26936399Ssklower 27036399Ssklower ADDOPTION(TPP_tpdu_size, hdr, 27136399Ssklower sizeof(tpcb->tp_tpdusize), tpcb->tp_tpdusize); 27236399Ssklower 27336399Ssklower if (tpcb->tp_class != TP_CLASS_0) { 27436399Ssklower short millisec = 500*(tpcb->tp_sendack_ticks); 27536399Ssklower 27636399Ssklower millisec = htons(millisec); 27736399Ssklower ADDOPTION(TPP_acktime, hdr, sizeof(short), millisec); 27836399Ssklower 27936399Ssklower x = (tpcb->tp_use_nxpd? TPAO_USE_NXPD: 0) 28036399Ssklower | (tpcb->tp_use_rcc? TPAO_USE_RCC : 0) 28136399Ssklower | (tpcb->tp_use_checksum?0: TPAO_NO_CSUM) 28236399Ssklower | (tpcb->tp_xpd_service? TPAO_USE_TXPD: 0); 28336399Ssklower ADDOPTION(TPP_addl_opt, hdr, 1, x); 28436399Ssklower 28536399Ssklower } 28636399Ssklower 28736399Ssklower if( (dutype == CR_TPDU_type) && (tpcb->tp_class != TP_CLASS_0)){ 28836399Ssklower 28936399Ssklower ASSERT( 1 == sizeof(tpcb->tp_vers) ); 29036399Ssklower ADDOPTION(TPP_vers, hdr, 1, tpcb->tp_vers); 29136399Ssklower 29236399Ssklower /* for each alt protocol class x, 29336399Ssklower * x = x<<4; 29436399Ssklower * option = concat(option, x); 29536399Ssklower * Well, for now we only have TP0 for an 29636399Ssklower * alternative so... this is easy. 29736399Ssklower * 29836399Ssklower * HOWEVER... There should be NO alt protocol 29936399Ssklower * class over CLNS. Need to see if the route suggests 30036399Ssklower * CONS, and iff so add alt class. 30136399Ssklower */ 30236399Ssklower x = 0; 30336399Ssklower ADDOPTION(TPP_alt_class, hdr, 1, x); 30436399Ssklower } 30536399Ssklower 30636399Ssklower if( hdr->tpdu_li > MLEN) 30736399Ssklower panic("tp_emit CR/CC"); 30836399Ssklower } 30936399Ssklower break; 31036399Ssklower 31136399Ssklower case DR_TPDU_type: 31236399Ssklower if( hdr->tpdu_DRdref == 0 ) { 31336399Ssklower /* don't issue the DR */ 31436399Ssklower goto done; 31536399Ssklower } 31636399Ssklower hdr->tpdu_cdt = 0; 31736399Ssklower hdr->tpdu_DRsref = htons(tpcb->tp_lref); 31836399Ssklower hdr->tpdu_DRreason = (u_char)eot; /* WHICH BYTE OF THIS??? */ 31936399Ssklower 32036399Ssklower /* forget the add'l information variable part */ 32136399Ssklower IncStat(ts_DR_sent); 32236399Ssklower break; 32336399Ssklower 32436399Ssklower case DC_TPDU_type: /* not used in class 0 */ 32536399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); 32636399Ssklower hdr->tpdu_DCsref = htons(tpcb->tp_lref); 32736399Ssklower hdr->tpdu_cdt = 0; 32836399Ssklower data = (struct mbuf *)0; 32936399Ssklower IncStat(ts_DC_sent); 33036399Ssklower break; 33136399Ssklower 33236399Ssklower case XAK_TPDU_type: /* xak not used in class 0 */ 33336399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); /* fall through */ 33436399Ssklower hdr->tpdu_cdt = 0; 33536399Ssklower 33636399Ssklower IFTRACE(D_XPD) 33736399Ssklower tptraceTPCB(TPPTXack, seq, 0, 0, 0, 0); 33836399Ssklower ENDTRACE 33936399Ssklower data = (struct mbuf *)0; 34036399Ssklower if (tpcb->tp_xtd_format) { 34136399Ssklower #ifdef BYTE_ORDER 342*48747Ssklower union seq_type seqeotX; 343*48747Ssklower 344*48747Ssklower seqeotX.s_seq = seq; 345*48747Ssklower seqeotX.s_eot = 1; 346*48747Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 34736399Ssklower #else 34836399Ssklower hdr->tpdu_XAKseqX = seq; 34936399Ssklower #endif BYTE_ORDER 35036399Ssklower } else { 35136399Ssklower hdr->tpdu_XAKseq = seq; 35236399Ssklower } 35336399Ssklower IncStat(ts_XAK_sent); 35436399Ssklower IncPStat(tpcb, tps_XAK_sent); 35536399Ssklower break; 35636399Ssklower 35736399Ssklower case XPD_TPDU_type: /* xpd not used in class 0 */ 35836399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); /* fall through */ 35936399Ssklower hdr->tpdu_cdt = 0; 36036399Ssklower if (tpcb->tp_xtd_format) { 36136399Ssklower #ifdef BYTE_ORDER 36236399Ssklower union seq_type seqeotX; 36336399Ssklower 36436399Ssklower seqeotX.s_seq = seq; 36536399Ssklower seqeotX.s_eot = 1; 36636399Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 36736399Ssklower #else 36836399Ssklower hdr->tpdu_XPDseqX = seq; 36936399Ssklower hdr->tpdu_XPDeotX = 1; /* always 1 for XPD tpdu */ 37036399Ssklower #endif BYTE_ORDER 37136399Ssklower } else { 37236399Ssklower hdr->tpdu_XPDseq = seq; 37336399Ssklower hdr->tpdu_XPDeot = 1; /* always 1 for XPD tpdu */ 37436399Ssklower } 37536399Ssklower IncStat(ts_XPD_sent); 37636399Ssklower IncPStat(tpcb, tps_XPD_sent); 37736399Ssklower 37836399Ssklower /* kludge to test the input size checking */ 37936399Ssklower IFDEBUG(D_SIZE_CHECK) 38037469Ssklower /*if(data->m_len <= 16 && data->m_off < (MLEN-18) ) { 38136399Ssklower printf("Sending too much data on XPD: 18 bytes\n"); 38236399Ssklower data->m_len = 18; 38337469Ssklower }*/ 38436399Ssklower ENDDEBUG 38536399Ssklower break; 38636399Ssklower 38736399Ssklower case DT_TPDU_type: 38836399Ssklower hdr->tpdu_cdt = 0; 38936399Ssklower IFTRACE(D_DATA) 39036399Ssklower tptraceTPCB(TPPTmisc, "emit DT: eot seq tpdu_li", eot, seq, 39136399Ssklower hdr->tpdu_li, 0); 39236399Ssklower ENDTRACE 39336399Ssklower if (tpcb->tp_xtd_format) { 39436399Ssklower #ifdef BYTE_ORDER 39536399Ssklower union seq_type seqeotX; 39636399Ssklower 39736399Ssklower seqeotX.s_seq = seq; 39836399Ssklower seqeotX.s_eot = eot; 39936399Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 40036399Ssklower #else 40136399Ssklower hdr->tpdu_DTseqX = seq; 40236399Ssklower hdr->tpdu_DTeotX = eot; 40336399Ssklower #endif BYTE_ORDER 40436399Ssklower } else if (tpcb->tp_class == TP_CLASS_0) { 40536399Ssklower IFDEBUG(D_EMIT) 40636399Ssklower printf("DT tpdu: class 0 m 0x%x hdr 0x%x\n", m, hdr); 40736399Ssklower dump_buf( hdr, hdr->tpdu_li + 1 ); 40836399Ssklower ENDDEBUG 40936399Ssklower ((struct tp0du *)hdr)->tp0du_eot = eot; 41036399Ssklower ((struct tp0du *)hdr)->tp0du_mbz = 0; 41136399Ssklower IFDEBUG(D_EMIT) 41236399Ssklower printf("DT 2 tpdu: class 0 m 0x%x hdr 0x%x\n", m, hdr); 41336399Ssklower dump_buf( hdr, hdr->tpdu_li + 1 ); 41436399Ssklower ENDDEBUG 41536399Ssklower } else { 41636399Ssklower hdr->tpdu_DTseq = seq; 41736399Ssklower hdr->tpdu_DTeot = eot; 41836399Ssklower } 41936399Ssklower if(eot) { 42036399Ssklower IncStat(ts_EOT_sent); 42136399Ssklower } 42236399Ssklower IncStat(ts_DT_sent); 42336399Ssklower IncPStat(tpcb, tps_DT_sent); 42436399Ssklower break; 42536399Ssklower 42636399Ssklower case AK_TPDU_type:/* ak not used in class 0 */ 42736399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); 42836399Ssklower data = (struct mbuf *)0; 42936399Ssklower { SeqNum olduwe = tpcb->tp_sent_uwe; 43036399Ssklower 43136399Ssklower tpcb->tp_sent_uwe = 43236399Ssklower SEQ(tpcb,tpcb->tp_rcvnxt + tpcb->tp_lcredit -1); 43336399Ssklower LOCAL_CREDIT( tpcb ); 43436399Ssklower tpcb->tp_sent_lcdt = tpcb->tp_lcredit; 43536399Ssklower 43636399Ssklower IFDEBUG(D_RENEG) 43736399Ssklower /* occasionally fake a reneging so 43836399Ssklower you can test subsequencing */ 43936399Ssklower if( olduwe & 0x1 ) { 44036399Ssklower tpcb->tp_reneged = 1; 44136399Ssklower IncStat(ts_ldebug); 44236399Ssklower } 44336399Ssklower ENDDEBUG 44436399Ssklower /* Are we about to reneg on credit? 44536399Ssklower * When might we do so? 44636399Ssklower * a) when using optimistic credit (which we no longer do). 44736399Ssklower * b) when drain() gets implemented (not in the plans). 44836399Ssklower * c) when D_RENEG is on. 44937469Ssklower * d) when DEC BIT response is implemented. 45036399Ssklower * (not- when we do this, we'll need to implement flow control 45136399Ssklower * confirmation) 45236399Ssklower */ 45336399Ssklower if( SEQ_LT(tpcb, tpcb->tp_sent_uwe, olduwe) ) { 45436399Ssklower tpcb->tp_reneged = 1; 45536399Ssklower IncStat(ts_lcdt_reduced); 45636399Ssklower IFTRACE(D_CREDIT) 45736399Ssklower tptraceTPCB(TPPTmisc, 45836399Ssklower "RENEG: olduwe newuwe lcredit rcvnxt", 45936399Ssklower olduwe, 46036399Ssklower tpcb->tp_sent_uwe, tpcb->tp_lcredit, 46136399Ssklower tpcb->tp_rcvnxt); 46236399Ssklower ENDTRACE 46336399Ssklower } 46436399Ssklower 46536399Ssklower IFPERF(tpcb) 46636399Ssklower /* new lwe is less than old uwe means we're 46736399Ssklower * acking before we received a whole window full 46836399Ssklower */ 46936399Ssklower if( SEQ_LT( tpcb, tpcb->tp_rcvnxt, olduwe) ) { 47036399Ssklower /* tmp1 = number of pkts fewer than the full window */ 47136399Ssklower register int tmp1 = 47236399Ssklower (int) SEQ_SUB( tpcb, olduwe, tpcb->tp_rcvnxt); 47336399Ssklower 47436399Ssklower if(tmp1 > TP_PM_MAX) 47536399Ssklower tmp1 = TP_PM_MAX; 47636399Ssklower IncPStat( tpcb, tps_ack_early[tmp1] ); 47736399Ssklower 47836399Ssklower /* tmp1 = amt of new cdt we're advertising */ 47936399Ssklower tmp1 = SEQ_SUB( tpcb, seq, tpcb->tp_sent_rcvnxt); 48036399Ssklower if(tmp1 > TP_PM_MAX ) 48136399Ssklower tmp1 = TP_PM_MAX; 48236399Ssklower 48336399Ssklower IncPStat( tpcb, 48436399Ssklower tps_cdt_acked [ tmp1 ] 48536399Ssklower [ ((tpcb->tp_lcredit > TP_PM_MAX)? 48636399Ssklower TP_PM_MAX:tpcb->tp_lcredit) ] ); 48736399Ssklower 48836399Ssklower } 48936399Ssklower ENDPERF 49036399Ssklower } 49136399Ssklower IFTRACE(D_ACKSEND) 49236399Ssklower tptraceTPCB(TPPTack, seq, tpcb->tp_lcredit, tpcb->tp_sent_uwe, 49336399Ssklower tpcb->tp_r_subseq, 0); 49436399Ssklower ENDTRACE 49536399Ssklower if (tpcb->tp_xtd_format) { 49636399Ssklower #ifdef BYTE_ORDER 497*48747Ssklower union seq_type seqeotX; 498*48747Ssklower 499*48747Ssklower seqeotX.s_seq = seq; 500*48747Ssklower seqeotX.s_eot = 0; 501*48747Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 50236399Ssklower hdr->tpdu_AKcdtX = htons(tpcb->tp_lcredit); 50336399Ssklower #else 50436399Ssklower hdr->tpdu_cdt = 0; 50536399Ssklower hdr->tpdu_AKseqX = seq; 50636399Ssklower hdr->tpdu_AKcdtX = tpcb->tp_lcredit; 50736399Ssklower #endif BYTE_ORDER 50836399Ssklower } else { 50936399Ssklower hdr->tpdu_AKseq = seq; 51036399Ssklower hdr->tpdu_AKcdt = tpcb->tp_lcredit; 51136399Ssklower } 51236399Ssklower if ((tpcb->tp_class == TP_CLASS_4) && tpcb->tp_reneged ) { 51336399Ssklower /* 51436399Ssklower * Ack subsequence parameter req'd if WE reneged on 51536399Ssklower * credit offered. (ISO 8073, 12.2.3.8.2, p. 74) 51636399Ssklower */ 51736399Ssklower IFDEBUG(D_RENEG) 51836399Ssklower printf("Adding subseq 0x%x\n", tpcb->tp_s_subseq); 51936399Ssklower ENDDEBUG 52036399Ssklower tpcb->tp_s_subseq++; 52136399Ssklower /* 52236399Ssklower * add tmp subseq and do a htons on it. 52336399Ssklower */ 52436399Ssklower ADDOPTION(TPP_subseq, hdr, 52536399Ssklower sizeof(tpcb->tp_s_subseq), tpcb->tp_s_subseq); 52636399Ssklower } else 52736399Ssklower tpcb->tp_s_subseq = 0; 52836399Ssklower 52936399Ssklower if ( tpcb->tp_sendfcc || eot ) /* overloaded to mean SEND FCC */ { 53036399Ssklower /* 53136399Ssklower * Rules for sending FCC ("should" send when) : 53236399Ssklower * %a) received an ack from peer with NO NEWS whatsoever, 53336399Ssklower * and it did not contain an FCC 53436399Ssklower * b) received an ack from peer that opens its closed window. 53536399Ssklower * c) received an ack from peer after it reneged on its 53636399Ssklower * offered credit, AND this ack raises UWE but LWE is same 53736399Ssklower * and below UWE at time of reneging (reduction) 53836399Ssklower * Now, ISO 8073 12.2.3.8.3 says 53936399Ssklower * that a retransmitted AK shall not contain the FCC 54036399Ssklower * parameter. Now, how the hell you tell the difference 54136399Ssklower * between a retransmitted ack and an ack that's sent in 54236399Ssklower * response to a received ack, I don't know, because without 54336399Ssklower * any local activity, and w/o any received DTs, they 54436399Ssklower * will contain exactly the same credit/seq# information. 54536399Ssklower * Anyway, given that the "retransmission of acks" 54636399Ssklower * procedure (ISO 8073 12.2.3.8.3) is optional, and we 54736399Ssklower * don't do it (although the peer can't tell that), we 54836399Ssklower * ignore this last rule. 54936399Ssklower * 55036399Ssklower * We send FCC for reasons a) and b) only. 55136399Ssklower * To add reason c) would require a ridiculous amount of state. 55236399Ssklower * 55336399Ssklower */ 55436399Ssklower u_short bogus[4]; /* lwe(32), subseq(16), cdt(16) */ 55536399Ssklower SeqNum lwe; 55636399Ssklower u_short subseq, fcredit; 55736399Ssklower 55836399Ssklower tpcb->tp_sendfcc = 0; 55936399Ssklower 56036399Ssklower lwe = (SeqNum) htonl(tpcb->tp_snduna); 56136399Ssklower subseq = htons(tpcb->tp_r_subseq); 56236399Ssklower fcredit = htons(tpcb->tp_fcredit); 56336399Ssklower 56437469Ssklower bcopy((caddr_t) &lwe, (caddr_t)&bogus[0], sizeof(SeqNum)); 56537469Ssklower bcopy((caddr_t) &subseq, (caddr_t)&bogus[2], sizeof(u_short)); 56637469Ssklower bcopy((caddr_t) &fcredit, (caddr_t)&bogus[3], sizeof(u_short)); 56736399Ssklower 56836399Ssklower IFTRACE(D_ACKSEND) 56936399Ssklower tptraceTPCB(TPPTmisc, 57036399Ssklower "emit w/FCC: snduna r_subseq fcredit", 57136399Ssklower tpcb->tp_snduna, tpcb->tp_r_subseq, 57236399Ssklower tpcb->tp_fcredit, 0); 57336399Ssklower ENDTRACE 57436399Ssklower 57536399Ssklower IFDEBUG(D_ACKSEND) 57636399Ssklower printf("Calling ADDOPTION 0x%x, 0x%x, 0x%x,0x%x\n", 57736399Ssklower TPP_flow_cntl_conf, 57836399Ssklower hdr, sizeof(bogus), bogus[0]); 57936399Ssklower ENDDEBUG 58036399Ssklower ADDOPTION(TPP_flow_cntl_conf, hdr, sizeof(bogus), bogus[0]); 58136399Ssklower IFDEBUG(D_ACKSEND) 58236399Ssklower printf("after ADDOPTION hdr 0x%x hdr->tpdu_li 0x%x\n", 58336399Ssklower hdr, hdr->tpdu_li); 58436399Ssklower printf( 58536399Ssklower "after ADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 58636399Ssklower csum_offset, hdr->tpdu_li); 58736399Ssklower ENDDEBUG 58836399Ssklower 58936399Ssklower } 59036399Ssklower tpcb->tp_reneged = 0; 59136399Ssklower tpcb->tp_sent_rcvnxt = seq; 59236399Ssklower tp_ctimeout(tpcb->tp_refp, TM_sendack, 59336399Ssklower (int)tpcb->tp_keepalive_ticks); 59436399Ssklower IncStat(ts_AK_sent); 59536399Ssklower IncPStat(tpcb, tps_AK_sent); 59636399Ssklower IFDEBUG(D_ACKSEND) 59736399Ssklower printf( 59836399Ssklower "2 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 59936399Ssklower csum_offset, hdr->tpdu_li); 60036399Ssklower ENDDEBUG 60136399Ssklower break; 60236399Ssklower 60336399Ssklower case ER_TPDU_type: 60436399Ssklower hdr->tpdu_ERreason = eot; 60536399Ssklower hdr->tpdu_cdt = 0; 60636399Ssklower /* no user data */ 60736399Ssklower data = (struct mbuf *)0; 60836399Ssklower IncStat(ts_ER_sent); 60936399Ssklower break; 61036399Ssklower } 61136399Ssklower 61236399Ssklower } 61336399Ssklower ASSERT( ((int)hdr->tpdu_li > 0) && ((int)hdr->tpdu_li < MLEN) ); 61436399Ssklower 61536399Ssklower m->m_next = data; 61636399Ssklower 61737469Ssklower ASSERT( hdr->tpdu_li < MLEN ); /* leave this in */ 61836399Ssklower ASSERT( hdr->tpdu_li != 0 ); /* leave this in */ 61936399Ssklower 62036399Ssklower m->m_len = hdr->tpdu_li ; 62136399Ssklower hdr->tpdu_li --; /* doesn't include the li field */ 62236399Ssklower 62336399Ssklower datalen = m_datalen( m ); /* total len */ 62436399Ssklower 62536399Ssklower ASSERT( datalen <= tpcb->tp_l_tpdusize ); /* may become a problem 62636399Ssklower when CLNP is used; leave in here for the time being */ 62736399Ssklower IFDEBUG(D_ACKSEND) 62836399Ssklower printf( 62936399Ssklower "4 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 63036399Ssklower csum_offset, hdr->tpdu_li); 63136399Ssklower ENDDEBUG 63236399Ssklower if( datalen > tpcb->tp_l_tpdusize ) { 63336399Ssklower printf("data len 0x%x tpcb->tp_l_tpdusize 0x%x\n", 63436399Ssklower datalen, tpcb->tp_l_tpdusize); 63536399Ssklower } 63636399Ssklower IFDEBUG(D_EMIT) 63736399Ssklower printf( 63836399Ssklower "tp_emit before gen_csum m_len 0x%x, csum_offset 0x%x, datalen 0x%x\n", 63936399Ssklower m->m_len, csum_offset, datalen); 64036399Ssklower ENDDEBUG 64136399Ssklower if( tpcb->tp_use_checksum || 64236399Ssklower (dutype == CR_TPDU_type && (tpcb->tp_class & TP_CLASS_4)) ) { 64336399Ssklower iso_gen_csum(m, csum_offset, datalen); 64436399Ssklower } 64536399Ssklower 64636399Ssklower IFDEBUG(D_EMIT) 64736399Ssklower printf("tp_emit before tpxxx_output tpcb 0x%x, dutype 0x%x, datalen 0x%x\n", 64836399Ssklower tpcb, dutype, datalen); 64937469Ssklower dump_buf(mtod(m, caddr_t), datalen); 65036399Ssklower ENDDEBUG 65136399Ssklower 65236399Ssklower IFPERF(tpcb) 65336399Ssklower if( dutype == DT_TPDU_type ) { 65436399Ssklower PStat(tpcb, Nb_to_ll) += (datalen - m->m_len); 65537469Ssklower tpmeas( tpcb->tp_lref, TPtime_to_ll, (struct timeval *)0, 65636399Ssklower seq, PStat(tpcb, Nb_to_ll), (datalen - m->m_len)); 65736399Ssklower } 65836399Ssklower ENDPERF 65936399Ssklower 66036399Ssklower IFTRACE(D_EMIT) 66136399Ssklower tptraceTPCB(TPPTtpduout, dutype, hdr, hdr->tpdu_li+1, datalen, 0); 66236399Ssklower ENDTRACE 66336399Ssklower IFDEBUG(D_EMIT) 66436399Ssklower printf("OUTPUT: tpcb 0x%x, isop 0x%x, so 0x%x\n", 66536399Ssklower tpcb, tpcb->tp_npcb, tpcb->tp_sock); 66636399Ssklower ENDDEBUG 66736399Ssklower 66836399Ssklower { extern char tp_delay; 66936399Ssklower 67036399Ssklower if( tp_delay ) 67136399Ssklower if( tpcb->tp_use_checksum == 0 ) { 67236399Ssklower register u_int i = tp_delay; 67336399Ssklower for (; i!= 0; i--) 67436399Ssklower (void) iso_check_csum(m, datalen); 67536399Ssklower } 67636399Ssklower } 67736399Ssklower ASSERT( m->m_len > 0 ); 67836399Ssklower error = (tpcb->tp_nlproto->nlp_output)(tpcb->tp_npcb, m, datalen, 67936399Ssklower !tpcb->tp_use_checksum); 68036399Ssklower IFDEBUG(D_EMIT) 68136399Ssklower printf("OUTPUT: returned 0x%x\n", error); 68236399Ssklower ENDDEBUG 68336399Ssklower IFTRACE(D_EMIT) 68436399Ssklower tptraceTPCB(TPPTmisc, 68536399Ssklower "tp_emit nlproto->output netservice returns datalen", 68636399Ssklower tpcb->tp_nlproto->nlp_output, tpcb->tp_netservice, error, datalen); 68736399Ssklower ENDTRACE 68836399Ssklower done: 68936399Ssklower if( error == E_CO_QFULL ) { 69037469Ssklower tp_quench(tpcb, PRC_QUENCH); 69136399Ssklower return 0; 69236399Ssklower } 69336399Ssklower return error; 69436399Ssklower } 69536399Ssklower /* 69636399Ssklower * NAME: tp_error_emit() 69736399Ssklower * CALLED FROM: tp_input() when a DR or ER is to be issued in 69836399Ssklower * response to an input error. 69936399Ssklower * FUNCTION and ARGUMENTS: 70036399Ssklower * The error type is the first argument. 70136399Ssklower * The argument (sref) is the source reference on the bad incoming tpdu, 70236399Ssklower * and is used for a destination reference on the outgoing packet. 70336399Ssklower * (faddr) and (laddr) are the foreign and local addresses for this 70436399Ssklower * connection. 70536399Ssklower * (erdata) is a ptr to the errant incoming tpdu, and is copied into the 70636399Ssklower * outgoing ER, if an ER is to be issued. 70736399Ssklower * (erlen) is the number of octets of the errant tpdu that we should 70836399Ssklower * try to copy. 70936399Ssklower * (tpcb) is the pcb that describes the connection for which the bad tpdu 71036399Ssklower * arrived. 71136399Ssklower * RETURN VALUES: 71236399Ssklower * 0 OK 71336399Ssklower * ENOBUFS 71436399Ssklower * E* from net layer datagram output routine 71536399Ssklower * SIDE EFFECTS: 71636399Ssklower * 71736399Ssklower * NOTES: 71836399Ssklower */ 71936399Ssklower 72036399Ssklower int 72136399Ssklower tp_error_emit(error, sref, faddr, laddr, erdata, erlen, tpcb, cons_channel, 72236399Ssklower dgout_routine) 72336399Ssklower int error; 72436399Ssklower u_long sref; 72536399Ssklower struct sockaddr_iso *faddr, *laddr; 72636399Ssklower struct mbuf *erdata; 72736399Ssklower int erlen; 72836399Ssklower struct tp_pcb *tpcb; 72936399Ssklower int cons_channel; 73036399Ssklower int (*dgout_routine)(); 73136399Ssklower { 73236399Ssklower int dutype; 73336399Ssklower int datalen = 0; 73436399Ssklower register struct tpdu *hdr; 73536399Ssklower register struct mbuf *m; 73636399Ssklower int csum_offset; 73736399Ssklower 73836399Ssklower IFTRACE(D_ERROR_EMIT) 73936399Ssklower tptrace(TPPTmisc, "tp_error_emit error sref tpcb erlen", 74036399Ssklower error, sref, tpcb, erlen); 74136399Ssklower ENDTRACE 74236399Ssklower IFDEBUG(D_ERROR_EMIT) 74336399Ssklower printf( 74436399Ssklower "tp_error_emit error 0x%x sref 0x%x tpcb 0x%x erlen 0x%x chan 0x%x\n", 74536399Ssklower error, sref, tpcb, erlen, cons_channel); 74636399Ssklower ENDDEBUG 74736399Ssklower 74836399Ssklower MGET(m, M_DONTWAIT, TPMT_TPHDR); 74936399Ssklower if (m == NULL) { 75036399Ssklower return ENOBUFS; 75136399Ssklower } 75236399Ssklower m->m_len = sizeof(struct tpdu); 75336399Ssklower m->m_act = MNULL; 75436399Ssklower 75536399Ssklower hdr = mtod(m, struct tpdu *); 75636399Ssklower 75736399Ssklower IFDEBUG(D_ERROR_EMIT) 75836399Ssklower printf("[error 0x%x] [error&0xff 0x%x] [(char)error 0x%x]\n", 75936399Ssklower error, error&0xff, (char)error); 76036399Ssklower ENDDEBUG 76136399Ssklower 76236399Ssklower 76342494Ssklower if (error & TP_ERROR_SNDC) 76442494Ssklower dutype = DC_TPDU_type; 76542494Ssklower else if (error & 0x40) { 76636399Ssklower error &= ~0x40; 76736399Ssklower dutype = ER_TPDU_type; 76836399Ssklower } else 76936399Ssklower dutype = DR_TPDU_type; 77042494Ssklower error &= 0xff; 77136399Ssklower 77236399Ssklower hdr->tpdu_type = dutype; 77336399Ssklower hdr->tpdu_cdt = 0; 77436399Ssklower 77536399Ssklower switch( dutype ) { 77636399Ssklower 77742494Ssklower case DC_TPDU_type: 77842494Ssklower IncStat(ts_DC_sent); 77942494Ssklower hdr->tpdu_li = 6; 78042494Ssklower hdr->tpdu_DCdref = htons(sref); 78142494Ssklower hdr->tpdu_DCsref = tpcb ? htons(tpcb->tp_lref) : 0; 78242494Ssklower IFDEBUG(D_ERROR_EMIT) 78342494Ssklower printf("DC case:\n"); 78442494Ssklower dump_buf( hdr, 6); 78542494Ssklower ENDDEBUG 78642494Ssklower /* forget the add'l information variable part */ 78742494Ssklower break; 78842494Ssklower 78936399Ssklower case DR_TPDU_type: 79036399Ssklower IncStat(ts_DR_sent); 79136399Ssklower hdr->tpdu_li = 7; 79236399Ssklower hdr->tpdu_DRdref = htons(sref); 79342494Ssklower hdr->tpdu_DRsref = 0; 79436399Ssklower hdr->tpdu_DRreason = (char)error; 79536399Ssklower IFDEBUG(D_ERROR_EMIT) 79636399Ssklower printf("DR case:\n"); 79736399Ssklower dump_buf( hdr, 7); 79836399Ssklower ENDDEBUG 79936399Ssklower /* forget the add'l information variable part */ 80036399Ssklower break; 80136399Ssklower 80236399Ssklower case ER_TPDU_type: 80336399Ssklower IncStat(ts_ER_sent); 80436399Ssklower hdr->tpdu_li = 5; 80536399Ssklower hdr->tpdu_ERreason = (char)error; 80636399Ssklower break; 80736399Ssklower 80836399Ssklower default: 80936399Ssklower ASSERT(0); 81036399Ssklower printf("TP PANIC: bad dutype 0x%x\n", dutype); 81136399Ssklower } 81236399Ssklower 81336399Ssklower if(tpcb) 81436399Ssklower if( tpcb->tp_use_checksum ) { 81536399Ssklower ADDOPTION(TPP_checksum, hdr, 2, csum_offset /* dummy argument */); 81636399Ssklower csum_offset = hdr->tpdu_li - 2; 81736399Ssklower } 81836399Ssklower 81937469Ssklower ASSERT( hdr->tpdu_li < MLEN ); 82036399Ssklower 82136399Ssklower if (dutype == ER_TPDU_type) { 82236399Ssklower /* copy the errant tpdu into another 'variable part' */ 82336399Ssklower register caddr_t P; 82436399Ssklower 82536399Ssklower IFTRACE(D_ERROR_EMIT) 82636399Ssklower tptrace(TPPTmisc, "error_emit ER len tpduli", erlen, hdr->tpdu_li, 82736399Ssklower 0,0); 82836399Ssklower ENDTRACE 82936399Ssklower IFDEBUG(D_ERROR_EMIT) 83036399Ssklower printf("error_emit ER len 0x%x tpduli 0x%x\n", erlen, hdr->tpdu_li); 83136399Ssklower ENDDEBUG 83236399Ssklower 83336399Ssklower /* copy at most as many octets for which you have room */ 83436399Ssklower if (erlen + hdr->tpdu_li + 2 > TP_MAX_HEADER_LEN) 83536399Ssklower erlen = TP_MAX_HEADER_LEN - hdr->tpdu_li - 2; 83636399Ssklower 83736399Ssklower /* add the "invalid tpdu" parameter : required in class 0 */ 83836399Ssklower P = (caddr_t)hdr + (int)(hdr->tpdu_li); 83936399Ssklower vbptr(P)->tpv_code = TPP_invalid_tpdu; /* parameter code */ 84036399Ssklower vbptr(P)->tpv_len = erlen; /* parameter length */ 84136399Ssklower m->m_len = hdr->tpdu_li + 2; /* 1 for code, 1 for length */ 84236399Ssklower 84336399Ssklower /* tp_input very likely handed us an mbuf chain w/ nothing in 84436399Ssklower * the first mbuf and the data following the empty mbuf 84536399Ssklower */ 84636399Ssklower if(erdata->m_len == 0) { 84736399Ssklower erdata = m_free(erdata); /* returns the next mbuf on the chain */ 84836399Ssklower } 84937469Ssklower /* 85037469Ssklower * copy only up to the bad octet 85137469Ssklower * (or max that will fit in a header 85237469Ssklower */ 85337469Ssklower m->m_next = m_copy(erdata, 0, erlen); 85436399Ssklower hdr->tpdu_li += erlen + 2; 85536399Ssklower m_freem(erdata); 85636399Ssklower } else { 85736399Ssklower IFDEBUG(D_ERROR_EMIT) 85836399Ssklower printf("error_emit DR error tpduli 0x%x\n", error, hdr->tpdu_li); 85936399Ssklower dump_buf( (char *)hdr, hdr->tpdu_li ); 86036399Ssklower ENDDEBUG 86136399Ssklower m->m_len = hdr->tpdu_li ; 86236399Ssklower m_freem(erdata); 86336399Ssklower } 86436399Ssklower 86536399Ssklower hdr->tpdu_li --; 86636399Ssklower IFTRACE(D_ERROR_EMIT) 86736399Ssklower tptrace(TPPTtpduout, 2, hdr, hdr->tpdu_li+1, 0, 0); 86836399Ssklower ENDTRACE 86936399Ssklower 87036399Ssklower datalen = m_datalen( m); 87136399Ssklower 87236399Ssklower if(tpcb) { 87336399Ssklower if( tpcb->tp_use_checksum ) { 87436399Ssklower IFTRACE(D_ERROR_EMIT) 87536399Ssklower tptrace(TPPTmisc, "before gen csum datalen", datalen,0,0,0); 87636399Ssklower ENDTRACE 87736399Ssklower IFDEBUG(D_ERROR_EMIT) 87836399Ssklower printf("before gen csum datalen 0x%x, csum_offset 0x%x\n", 87936399Ssklower datalen, csum_offset); 88036399Ssklower ENDDEBUG 88136399Ssklower 88236399Ssklower iso_gen_csum(m, csum_offset, datalen); 88336399Ssklower } 88436399Ssklower 88536399Ssklower IFDEBUG(D_ERROR_EMIT) 88636399Ssklower printf("OUTPUT: tpcb 0x%x, isop 0x%x, so 0x%x\n", 88736399Ssklower tpcb, tpcb->tp_npcb, tpcb->tp_sock); 88836399Ssklower ENDDEBUG 88936399Ssklower /* Problem: if packet comes in on ISO but sock is listening 89036399Ssklower * in INET, this assertion will fail. 89136399Ssklower * Have to believe the argument, not the nlp_proto. 89236399Ssklower ASSERT( tpcb->tp_nlproto->nlp_dgoutput == dgout_routine ); 89336399Ssklower */ 89436399Ssklower 89536399Ssklower IFDEBUG(D_ERROR_EMIT) 89636399Ssklower printf("tp_error_emit 1 sending DG: Laddr\n"); 89737469Ssklower dump_addr((struct sockaddr *)laddr); 89836399Ssklower printf("Faddr\n"); 89937469Ssklower dump_addr((struct sockaddr *)faddr); 90036399Ssklower ENDDEBUG 90136399Ssklower return (tpcb->tp_nlproto->nlp_dgoutput)( 90236399Ssklower &laddr->siso_addr, 90336399Ssklower &faddr->siso_addr, 90436399Ssklower m, datalen, 90536399Ssklower /* no route */ (caddr_t)0, !tpcb->tp_use_checksum); 90636399Ssklower } else { 90736399Ssklower if( cons_channel ) { 90845900Ssklower #ifdef TPCONS 90945900Ssklower tpcons_dg_output(cons_channel, m, datalen); 91045900Ssklower pk_disconnect((struct pklcd *)cons_channel); 91136399Ssklower IFDEBUG(D_ERROR_EMIT) 91236399Ssklower printf("OUTPUT: dutype 0x%x channel 0x%x\n", 91336399Ssklower dutype, cons_channel); 91436399Ssklower ENDDEBUG 91545900Ssklower #else 91636399Ssklower printf("TP panic! cons channel 0x%x but not cons configured\n", 91736399Ssklower cons_channel); 91845900Ssklower #endif 91936399Ssklower } else { 92037469Ssklower #ifndef notdef 92136399Ssklower IFDEBUG(D_ERROR_EMIT) 92236399Ssklower printf("tp_error_emit sending DG: Laddr\n"); 92337469Ssklower dump_addr((struct sockaddr *)laddr); 92436399Ssklower printf("Faddr\n"); 92537469Ssklower dump_addr((struct sockaddr *)faddr); 92636399Ssklower ENDDEBUG 92736399Ssklower return (*dgout_routine)( &laddr->siso_addr, &faddr->siso_addr, 92836399Ssklower m, datalen, /* no route */ 92936399Ssklower (caddr_t)0, /* nochecksum==false */0); 93037469Ssklower #else notdef 93136399Ssklower IFDEBUG(D_ERROR_EMIT) 93236399Ssklower printf("tp_error_emit DROPPING \n", m); 93336399Ssklower ENDDEBUG 93436399Ssklower IncStat(ts_send_drop); 93536399Ssklower m_freem(m); 93636399Ssklower return 0; 93737469Ssklower #endif notdef 93836399Ssklower } 93936399Ssklower } 94036399Ssklower } 941