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*39924Ssklower * @(#)tp_emit.c 7.4 (Berkeley) 01/16/90 * 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 "argoxtwentyfive.h" 5436399Ssklower #include "param.h" 5536399Ssklower #include "mbuf.h" 5636399Ssklower #include "socket.h" 5736399Ssklower #include "socketvar.h" 5836399Ssklower #include "protosw.h" 5936399Ssklower #include "errno.h" 6036399Ssklower #include "types.h" 6136399Ssklower #include "time.h" 6237469Ssklower #include "iso.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 7436399Ssklower void iso_gen_csum(); 7536399Ssklower 7636399Ssklower 7736399Ssklower /* Here is a mighty kludge. The token ring misorders packets if you 7836399Ssklower * fire them at it too fast, and TP sans checksum is "too fast", so 7936399Ssklower * we have introduced a delay when checksumming isn't used. 8036399Ssklower */ 8136399Ssklower char tp_delay = 0x00; /* delay to keep token ring from blowing it */ 8236399Ssklower 8336399Ssklower /* 8436399Ssklower * NAME: tp_emit() 8536399Ssklower * 8636399Ssklower * CALLED FROM: tp.trans and from tp_sbsend() 8736399Ssklower * 8836399Ssklower * FUNCTION and ARGUMENTS: 8936399Ssklower * Emits one tpdu of the type (dutype), of the format appropriate 9036399Ssklower * to the connection described by the pcb (tpcb), with sequence 9136399Ssklower * number (seq) (where appropriate), end-of-tsdu bit (eot) where 9236399Ssklower * appropriate, and with the data in the mbuf chain (data). 9336399Ssklower * For DR and ER tpdus, the argument (eot) is 9436399Ssklower * the reason for issuing the tpdu rather than an end-of-tsdu indicator. 9536399Ssklower * 9636399Ssklower * RETURNS: 9736399Ssklower * 0 OK 9836399Ssklower * ENOBUFS 9936399Ssklower * E* returned from net layer output rtn 10036399Ssklower * 10136399Ssklower * SIDE EFFECTS: 10236399Ssklower * 10336399Ssklower * NOTES: 10436399Ssklower * 10536399Ssklower * WE ASSUME that the tp header + all options will fit in ONE mbuf. 10636399Ssklower * If mbufs are 256 this will most likely be true, but if they are 128 it's 10736399Ssklower * possible that they won't. 10836399Ssklower * If you used every option on the CR + max. user data you'd overrun 10936399Ssklower * 112 but unless you used > 115 bytes for the security 11036399Ssklower * parameter, it would fit in a 256-byte mbuf (240 bytes for the header) 11136399Ssklower * We don't support the security parameter, so this isn't a problem. 11236399Ssklower * If security is added, we ought to remove this assumption. 11336399Ssklower * 11436399Ssklower * We do not implement the flow control confirmation "element of procedure". 11536399Ssklower * A) it should not affect interoperability, 11636399Ssklower * B) it should not be necessary - the protocol will eventually 11736399Ssklower * straighten things out w/o FCC, as long as we don't have severely 11836399Ssklower * mismatched keepalive and inactivity timers, and 11936399Ssklower * C) it appears not to be REQUIRED, and 12036399Ssklower * D) it's incredibly grotesque, and no doubt will lengthen a few 12136399Ssklower * critical paths. 12236399Ssklower * HOWEVER, we're thinking about putting it in anyway, for 12336399Ssklower * completeness, just like we did with ack subsequencing. 12436399Ssklower */ 12536399Ssklower 12636399Ssklower int 12736399Ssklower tp_emit(dutype, tpcb, seq, eot, data) 12836399Ssklower int dutype; 12936399Ssklower struct tp_pcb *tpcb; 13036399Ssklower SeqNum seq; 13136399Ssklower u_int eot; 13236399Ssklower struct mbuf *data; 13336399Ssklower { 13436399Ssklower register struct tpdu *hdr; 13536399Ssklower register struct mbuf *m; 13636399Ssklower int csum_offset=0; 13736399Ssklower int datalen = 0; 13836399Ssklower int error = 0; 13936399Ssklower 14036399Ssklower /* NOTE: 14136399Ssklower * here we treat tpdu_li as if it DID include the li field, up until 14236399Ssklower * the end, at which time we subtract 1 14336399Ssklower * THis is because if we subtract 1 right away, we end up adding 14436399Ssklower * one every time we add an option. 14536399Ssklower */ 14636399Ssklower IFDEBUG(D_EMIT) 14736399Ssklower printf( 14837469Ssklower "tp_emit dutype 0x%x, tpcb 0x%x, eot 0x%x, seq 0x%x, data 0x%x", 14937469Ssklower dutype, tpcb, eot, seq, data); 15036399Ssklower ENDDEBUG 15136399Ssklower 15237469Ssklower if (dutype == CR_TPDU || dutype == CC_TPDU) { 15337469Ssklower m = (struct mbuf *) malloc((u_long)256, M_MBUF, M_DONTWAIT); 15437469Ssklower if (m) { 15537469Ssklower m->m_type = TPMT_TPHDR; 15637469Ssklower mbstat.m_mtypes[TPMT_TPHDR]++; 15737469Ssklower m->m_next = MNULL; 15837469Ssklower m->m_data = m->m_dat; 15937469Ssklower m->m_flags = 0; 16037469Ssklower } 16137469Ssklower } else { 16237469Ssklower MGET(m, M_DONTWAIT, TPMT_TPHDR); 16337469Ssklower } 16436399Ssklower if (m == NULL) { 16536399Ssklower if(data != (struct mbuf *)0) 16636399Ssklower m_freem(data); 16736399Ssklower error = ENOBUFS; 16836399Ssklower goto done; 16936399Ssklower } 17036399Ssklower m->m_len = sizeof(struct tpdu); 17136399Ssklower m->m_act = MNULL; 17236399Ssklower 17336399Ssklower hdr = mtod(m, struct tpdu *); 17437469Ssklower bzero((caddr_t)hdr, sizeof(struct tpdu)); 17536399Ssklower 17636399Ssklower { 17736399Ssklower int tp_headersize(); 17836399Ssklower 17936399Ssklower hdr->tpdu_type = dutype; 18036399Ssklower hdr->tpdu_li = tp_headersize(dutype, tpcb); 18136399Ssklower /* 18236399Ssklower * class 0 doesn't use this for DT 18336399Ssklower * it'll just get overwritten below 18436399Ssklower */ 18536399Ssklower hdr->tpdu_dref = htons(tpcb->tp_fref); 18636399Ssklower if( tpcb->tp_use_checksum || 18736399Ssklower (dutype == CR_TPDU_type && (tpcb->tp_class & TP_CLASS_4) )) { 18836399Ssklower csum_offset = hdr->tpdu_li + 2; /* DOESN'T include csum */ 18936399Ssklower ADDOPTION(TPP_checksum, hdr, 2, eot /* dummy arg */); 19036399Ssklower IFDEBUG(D_CHKSUM) 19136399Ssklower printf( 19236399Ssklower "tp_emit: csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 19336399Ssklower csum_offset, hdr->tpdu_li); 19436399Ssklower ENDDEBUG 19536399Ssklower } 19636399Ssklower /* 19736399Ssklower * VARIABLE PARTS... 19836399Ssklower */ 19936399Ssklower switch( dutype ) { 20036399Ssklower 20136399Ssklower case CR_TPDU_type: 20236399Ssklower hdr->tpdu_CRdref_0 = htons(0); /* must be zero */ 203*39924Ssklower if (!tpcb->tp_cebit_off) { 204*39924Ssklower tpcb->tp_win_recv = tp_start_win << 8; 205*39924Ssklower LOCAL_CREDIT(tpcb); 206*39924Ssklower CONG_INIT_SAMPLE(tpcb); 207*39924Ssklower tpcb->tp_ackrcvd = 0; 208*39924Ssklower } 209*39924Ssklower else 210*39924Ssklower LOCAL_CREDIT(tpcb); 21136399Ssklower 212*39924Ssklower 21336399Ssklower case CC_TPDU_type: 21436399Ssklower { 21536399Ssklower u_char x; 21636399Ssklower 21736399Ssklower hdr->tpdu_CCsref = htons(tpcb->tp_lref); /* same as CRsref */ 21836399Ssklower 21936399Ssklower if( tpcb->tp_class > TP_CLASS_1 ) { 220*39924Ssklower /* ifdef CE_BIT, we did this in tp_input when the CR came in */ 221*39924Ssklower if (tpcb->tp_cebit_off) 222*39924Ssklower LOCAL_CREDIT( tpcb ); 22336399Ssklower tpcb->tp_sent_uwe = tpcb->tp_lcredit -1; 22436399Ssklower tpcb->tp_sent_rcvnxt = 1; 22536399Ssklower tpcb->tp_sent_lcdt = tpcb->tp_lcredit; 22636399Ssklower hdr->tpdu_cdt = tpcb->tp_lcredit; 22736399Ssklower } else { 22836399Ssklower hdr->tpdu_cdt = 0; 22936399Ssklower } 23036399Ssklower hdr->tpdu_CCclass = tp_mask_to_num(tpcb->tp_class); 23136399Ssklower hdr->tpdu_CCoptions = 23236399Ssklower (tpcb->tp_xtd_format? TPO_XTD_FMT:0) | 23336399Ssklower (tpcb->tp_use_efc? TPO_USE_EFC:0); 23436399Ssklower 23536399Ssklower IFPERF(tpcb) 23636399Ssklower u_char perf_meas = tpcb->tp_perf_on; 23736399Ssklower ADDOPTION(TPP_perf_meas, hdr, sizeof(perf_meas), perf_meas); 23836399Ssklower ENDPERF 23936399Ssklower 24036399Ssklower if( dutype == CR_TPDU_type ) { 24136399Ssklower IncStat(ts_CR_sent); 24236399Ssklower 24336399Ssklower ASSERT( tpcb->tp_lsuffixlen > 0 ); 24436399Ssklower ASSERT( tpcb->tp_fsuffixlen > 0 ); 24536399Ssklower 24636399Ssklower ADDOPTION(TPP_calling_sufx, hdr, 24737469Ssklower tpcb->tp_lsuffixlen, tpcb->tp_lsuffix[0]); 24836399Ssklower ADDOPTION(TPP_called_sufx, hdr, 24937469Ssklower tpcb->tp_fsuffixlen, tpcb->tp_fsuffix[0]); 25036399Ssklower } else { 25136399Ssklower IncStat(ts_CC_sent); 25236399Ssklower } 25336399Ssklower 25436399Ssklower ADDOPTION(TPP_tpdu_size, hdr, 25536399Ssklower sizeof(tpcb->tp_tpdusize), tpcb->tp_tpdusize); 25636399Ssklower 25736399Ssklower if (tpcb->tp_class != TP_CLASS_0) { 25836399Ssklower short millisec = 500*(tpcb->tp_sendack_ticks); 25936399Ssklower 26036399Ssklower millisec = htons(millisec); 26136399Ssklower ADDOPTION(TPP_acktime, hdr, sizeof(short), millisec); 26236399Ssklower 26336399Ssklower x = (tpcb->tp_use_nxpd? TPAO_USE_NXPD: 0) 26436399Ssklower | (tpcb->tp_use_rcc? TPAO_USE_RCC : 0) 26536399Ssklower | (tpcb->tp_use_checksum?0: TPAO_NO_CSUM) 26636399Ssklower | (tpcb->tp_xpd_service? TPAO_USE_TXPD: 0); 26736399Ssklower ADDOPTION(TPP_addl_opt, hdr, 1, x); 26836399Ssklower 26936399Ssklower } 27036399Ssklower 27136399Ssklower if( (dutype == CR_TPDU_type) && (tpcb->tp_class != TP_CLASS_0)){ 27236399Ssklower 27336399Ssklower ASSERT( 1 == sizeof(tpcb->tp_vers) ); 27436399Ssklower ADDOPTION(TPP_vers, hdr, 1, tpcb->tp_vers); 27536399Ssklower 27636399Ssklower /* for each alt protocol class x, 27736399Ssklower * x = x<<4; 27836399Ssklower * option = concat(option, x); 27936399Ssklower * Well, for now we only have TP0 for an 28036399Ssklower * alternative so... this is easy. 28136399Ssklower * 28236399Ssklower * HOWEVER... There should be NO alt protocol 28336399Ssklower * class over CLNS. Need to see if the route suggests 28436399Ssklower * CONS, and iff so add alt class. 28536399Ssklower */ 28636399Ssklower x = 0; 28736399Ssklower ADDOPTION(TPP_alt_class, hdr, 1, x); 28836399Ssklower } 28936399Ssklower 29036399Ssklower if( hdr->tpdu_li > MLEN) 29136399Ssklower panic("tp_emit CR/CC"); 29236399Ssklower } 29336399Ssklower break; 29436399Ssklower 29536399Ssklower case DR_TPDU_type: 29636399Ssklower if( hdr->tpdu_DRdref == 0 ) { 29736399Ssklower /* don't issue the DR */ 29836399Ssklower goto done; 29936399Ssklower } 30036399Ssklower hdr->tpdu_cdt = 0; 30136399Ssklower hdr->tpdu_DRsref = htons(tpcb->tp_lref); 30236399Ssklower hdr->tpdu_DRreason = (u_char)eot; /* WHICH BYTE OF THIS??? */ 30336399Ssklower 30436399Ssklower /* forget the add'l information variable part */ 30536399Ssklower IncStat(ts_DR_sent); 30636399Ssklower break; 30736399Ssklower 30836399Ssklower case DC_TPDU_type: /* not used in class 0 */ 30936399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); 31036399Ssklower hdr->tpdu_DCsref = htons(tpcb->tp_lref); 31136399Ssklower hdr->tpdu_cdt = 0; 31236399Ssklower data = (struct mbuf *)0; 31336399Ssklower IncStat(ts_DC_sent); 31436399Ssklower break; 31536399Ssklower 31636399Ssklower case XAK_TPDU_type: /* xak not used in class 0 */ 31736399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); /* fall through */ 31836399Ssklower hdr->tpdu_cdt = 0; 31936399Ssklower 32036399Ssklower IFTRACE(D_XPD) 32136399Ssklower tptraceTPCB(TPPTXack, seq, 0, 0, 0, 0); 32236399Ssklower ENDTRACE 32336399Ssklower data = (struct mbuf *)0; 32436399Ssklower if (tpcb->tp_xtd_format) { 32536399Ssklower #ifdef BYTE_ORDER 32636399Ssklower hdr->tpdu_XAKseqX = htonl(seq); 32736399Ssklower #else 32836399Ssklower hdr->tpdu_XAKseqX = seq; 32936399Ssklower #endif BYTE_ORDER 33036399Ssklower } else { 33136399Ssklower hdr->tpdu_XAKseq = seq; 33236399Ssklower } 33336399Ssklower IncStat(ts_XAK_sent); 33436399Ssklower IncPStat(tpcb, tps_XAK_sent); 33536399Ssklower break; 33636399Ssklower 33736399Ssklower case XPD_TPDU_type: /* xpd not used in class 0 */ 33836399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); /* fall through */ 33936399Ssklower hdr->tpdu_cdt = 0; 34036399Ssklower if (tpcb->tp_xtd_format) { 34136399Ssklower #ifdef BYTE_ORDER 34236399Ssklower union seq_type seqeotX; 34336399Ssklower 34436399Ssklower seqeotX.s_seq = seq; 34536399Ssklower seqeotX.s_eot = 1; 34636399Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 34736399Ssklower #else 34836399Ssklower hdr->tpdu_XPDseqX = seq; 34936399Ssklower hdr->tpdu_XPDeotX = 1; /* always 1 for XPD tpdu */ 35036399Ssklower #endif BYTE_ORDER 35136399Ssklower } else { 35236399Ssklower hdr->tpdu_XPDseq = seq; 35336399Ssklower hdr->tpdu_XPDeot = 1; /* always 1 for XPD tpdu */ 35436399Ssklower } 35536399Ssklower IncStat(ts_XPD_sent); 35636399Ssklower IncPStat(tpcb, tps_XPD_sent); 35736399Ssklower 35836399Ssklower /* kludge to test the input size checking */ 35936399Ssklower IFDEBUG(D_SIZE_CHECK) 36037469Ssklower /*if(data->m_len <= 16 && data->m_off < (MLEN-18) ) { 36136399Ssklower printf("Sending too much data on XPD: 18 bytes\n"); 36236399Ssklower data->m_len = 18; 36337469Ssklower }*/ 36436399Ssklower ENDDEBUG 36536399Ssklower break; 36636399Ssklower 36736399Ssklower case DT_TPDU_type: 36836399Ssklower hdr->tpdu_cdt = 0; 36936399Ssklower IFTRACE(D_DATA) 37036399Ssklower tptraceTPCB(TPPTmisc, "emit DT: eot seq tpdu_li", eot, seq, 37136399Ssklower hdr->tpdu_li, 0); 37236399Ssklower ENDTRACE 37336399Ssklower if (tpcb->tp_xtd_format) { 37436399Ssklower #ifdef BYTE_ORDER 37536399Ssklower union seq_type seqeotX; 37636399Ssklower 37736399Ssklower seqeotX.s_seq = seq; 37836399Ssklower seqeotX.s_eot = eot; 37936399Ssklower hdr->tpdu_seqeotX = htonl(seqeotX.s_seqeot); 38036399Ssklower #else 38136399Ssklower hdr->tpdu_DTseqX = seq; 38236399Ssklower hdr->tpdu_DTeotX = eot; 38336399Ssklower #endif BYTE_ORDER 38436399Ssklower } else if (tpcb->tp_class == TP_CLASS_0) { 38536399Ssklower IFDEBUG(D_EMIT) 38636399Ssklower printf("DT tpdu: class 0 m 0x%x hdr 0x%x\n", m, hdr); 38736399Ssklower dump_buf( hdr, hdr->tpdu_li + 1 ); 38836399Ssklower ENDDEBUG 38936399Ssklower ((struct tp0du *)hdr)->tp0du_eot = eot; 39036399Ssklower ((struct tp0du *)hdr)->tp0du_mbz = 0; 39136399Ssklower IFDEBUG(D_EMIT) 39236399Ssklower printf("DT 2 tpdu: class 0 m 0x%x hdr 0x%x\n", m, hdr); 39336399Ssklower dump_buf( hdr, hdr->tpdu_li + 1 ); 39436399Ssklower ENDDEBUG 39536399Ssklower } else { 39636399Ssklower hdr->tpdu_DTseq = seq; 39736399Ssklower hdr->tpdu_DTeot = eot; 39836399Ssklower } 39936399Ssklower if(eot) { 40036399Ssklower IncStat(ts_EOT_sent); 40136399Ssklower } 40236399Ssklower IncStat(ts_DT_sent); 40336399Ssklower IncPStat(tpcb, tps_DT_sent); 40436399Ssklower break; 40536399Ssklower 40636399Ssklower case AK_TPDU_type:/* ak not used in class 0 */ 40736399Ssklower ASSERT( tpcb->tp_class != TP_CLASS_0); 40836399Ssklower data = (struct mbuf *)0; 40936399Ssklower { SeqNum olduwe = tpcb->tp_sent_uwe; 41036399Ssklower 41136399Ssklower tpcb->tp_sent_uwe = 41236399Ssklower SEQ(tpcb,tpcb->tp_rcvnxt + tpcb->tp_lcredit -1); 41336399Ssklower LOCAL_CREDIT( tpcb ); 41436399Ssklower tpcb->tp_sent_lcdt = tpcb->tp_lcredit; 41536399Ssklower 41636399Ssklower IFDEBUG(D_RENEG) 41736399Ssklower /* occasionally fake a reneging so 41836399Ssklower you can test subsequencing */ 41936399Ssklower if( olduwe & 0x1 ) { 42036399Ssklower tpcb->tp_reneged = 1; 42136399Ssklower IncStat(ts_ldebug); 42236399Ssklower } 42336399Ssklower ENDDEBUG 42436399Ssklower /* Are we about to reneg on credit? 42536399Ssklower * When might we do so? 42636399Ssklower * a) when using optimistic credit (which we no longer do). 42736399Ssklower * b) when drain() gets implemented (not in the plans). 42836399Ssklower * c) when D_RENEG is on. 42937469Ssklower * d) when DEC BIT response is implemented. 43036399Ssklower * (not- when we do this, we'll need to implement flow control 43136399Ssklower * confirmation) 43236399Ssklower */ 43336399Ssklower if( SEQ_LT(tpcb, tpcb->tp_sent_uwe, olduwe) ) { 43436399Ssklower tpcb->tp_reneged = 1; 43536399Ssklower IncStat(ts_lcdt_reduced); 43636399Ssklower IFTRACE(D_CREDIT) 43736399Ssklower tptraceTPCB(TPPTmisc, 43836399Ssklower "RENEG: olduwe newuwe lcredit rcvnxt", 43936399Ssklower olduwe, 44036399Ssklower tpcb->tp_sent_uwe, tpcb->tp_lcredit, 44136399Ssklower tpcb->tp_rcvnxt); 44236399Ssklower ENDTRACE 44336399Ssklower } 44436399Ssklower 44536399Ssklower IFPERF(tpcb) 44636399Ssklower /* new lwe is less than old uwe means we're 44736399Ssklower * acking before we received a whole window full 44836399Ssklower */ 44936399Ssklower if( SEQ_LT( tpcb, tpcb->tp_rcvnxt, olduwe) ) { 45036399Ssklower /* tmp1 = number of pkts fewer than the full window */ 45136399Ssklower register int tmp1 = 45236399Ssklower (int) SEQ_SUB( tpcb, olduwe, tpcb->tp_rcvnxt); 45336399Ssklower 45436399Ssklower if(tmp1 > TP_PM_MAX) 45536399Ssklower tmp1 = TP_PM_MAX; 45636399Ssklower IncPStat( tpcb, tps_ack_early[tmp1] ); 45736399Ssklower 45836399Ssklower /* tmp1 = amt of new cdt we're advertising */ 45936399Ssklower tmp1 = SEQ_SUB( tpcb, seq, tpcb->tp_sent_rcvnxt); 46036399Ssklower if(tmp1 > TP_PM_MAX ) 46136399Ssklower tmp1 = TP_PM_MAX; 46236399Ssklower 46336399Ssklower IncPStat( tpcb, 46436399Ssklower tps_cdt_acked [ tmp1 ] 46536399Ssklower [ ((tpcb->tp_lcredit > TP_PM_MAX)? 46636399Ssklower TP_PM_MAX:tpcb->tp_lcredit) ] ); 46736399Ssklower 46836399Ssklower } 46936399Ssklower ENDPERF 47036399Ssklower } 47136399Ssklower IFTRACE(D_ACKSEND) 47236399Ssklower tptraceTPCB(TPPTack, seq, tpcb->tp_lcredit, tpcb->tp_sent_uwe, 47336399Ssklower tpcb->tp_r_subseq, 0); 47436399Ssklower ENDTRACE 47536399Ssklower if (tpcb->tp_xtd_format) { 47636399Ssklower #ifdef BYTE_ORDER 47736399Ssklower hdr->tpdu_cdt = 0; 47836399Ssklower hdr->tpdu_AKseqX = htonl(seq); 47936399Ssklower hdr->tpdu_AKcdtX = htons(tpcb->tp_lcredit); 48036399Ssklower #else 48136399Ssklower hdr->tpdu_cdt = 0; 48236399Ssklower hdr->tpdu_AKseqX = seq; 48336399Ssklower hdr->tpdu_AKcdtX = tpcb->tp_lcredit; 48436399Ssklower #endif BYTE_ORDER 48536399Ssklower } else { 48636399Ssklower hdr->tpdu_AKseq = seq; 48736399Ssklower hdr->tpdu_AKcdt = tpcb->tp_lcredit; 48836399Ssklower } 48936399Ssklower if ((tpcb->tp_class == TP_CLASS_4) && tpcb->tp_reneged ) { 49036399Ssklower /* 49136399Ssklower * Ack subsequence parameter req'd if WE reneged on 49236399Ssklower * credit offered. (ISO 8073, 12.2.3.8.2, p. 74) 49336399Ssklower */ 49436399Ssklower IFDEBUG(D_RENEG) 49536399Ssklower printf("Adding subseq 0x%x\n", tpcb->tp_s_subseq); 49636399Ssklower ENDDEBUG 49736399Ssklower tpcb->tp_s_subseq++; 49836399Ssklower /* 49936399Ssklower * add tmp subseq and do a htons on it. 50036399Ssklower */ 50136399Ssklower ADDOPTION(TPP_subseq, hdr, 50236399Ssklower sizeof(tpcb->tp_s_subseq), tpcb->tp_s_subseq); 50336399Ssklower } else 50436399Ssklower tpcb->tp_s_subseq = 0; 50536399Ssklower 50636399Ssklower if ( tpcb->tp_sendfcc || eot ) /* overloaded to mean SEND FCC */ { 50736399Ssklower /* 50836399Ssklower * Rules for sending FCC ("should" send when) : 50936399Ssklower * %a) received an ack from peer with NO NEWS whatsoever, 51036399Ssklower * and it did not contain an FCC 51136399Ssklower * b) received an ack from peer that opens its closed window. 51236399Ssklower * c) received an ack from peer after it reneged on its 51336399Ssklower * offered credit, AND this ack raises UWE but LWE is same 51436399Ssklower * and below UWE at time of reneging (reduction) 51536399Ssklower * Now, ISO 8073 12.2.3.8.3 says 51636399Ssklower * that a retransmitted AK shall not contain the FCC 51736399Ssklower * parameter. Now, how the hell you tell the difference 51836399Ssklower * between a retransmitted ack and an ack that's sent in 51936399Ssklower * response to a received ack, I don't know, because without 52036399Ssklower * any local activity, and w/o any received DTs, they 52136399Ssklower * will contain exactly the same credit/seq# information. 52236399Ssklower * Anyway, given that the "retransmission of acks" 52336399Ssklower * procedure (ISO 8073 12.2.3.8.3) is optional, and we 52436399Ssklower * don't do it (although the peer can't tell that), we 52536399Ssklower * ignore this last rule. 52636399Ssklower * 52736399Ssklower * We send FCC for reasons a) and b) only. 52836399Ssklower * To add reason c) would require a ridiculous amount of state. 52936399Ssklower * 53036399Ssklower */ 53136399Ssklower u_short bogus[4]; /* lwe(32), subseq(16), cdt(16) */ 53236399Ssklower SeqNum lwe; 53336399Ssklower u_short subseq, fcredit; 53436399Ssklower 53536399Ssklower tpcb->tp_sendfcc = 0; 53636399Ssklower 53736399Ssklower lwe = (SeqNum) htonl(tpcb->tp_snduna); 53836399Ssklower subseq = htons(tpcb->tp_r_subseq); 53936399Ssklower fcredit = htons(tpcb->tp_fcredit); 54036399Ssklower 54137469Ssklower bcopy((caddr_t) &lwe, (caddr_t)&bogus[0], sizeof(SeqNum)); 54237469Ssklower bcopy((caddr_t) &subseq, (caddr_t)&bogus[2], sizeof(u_short)); 54337469Ssklower bcopy((caddr_t) &fcredit, (caddr_t)&bogus[3], sizeof(u_short)); 54436399Ssklower 54536399Ssklower IFTRACE(D_ACKSEND) 54636399Ssklower tptraceTPCB(TPPTmisc, 54736399Ssklower "emit w/FCC: snduna r_subseq fcredit", 54836399Ssklower tpcb->tp_snduna, tpcb->tp_r_subseq, 54936399Ssklower tpcb->tp_fcredit, 0); 55036399Ssklower ENDTRACE 55136399Ssklower 55236399Ssklower IFDEBUG(D_ACKSEND) 55336399Ssklower printf("Calling ADDOPTION 0x%x, 0x%x, 0x%x,0x%x\n", 55436399Ssklower TPP_flow_cntl_conf, 55536399Ssklower hdr, sizeof(bogus), bogus[0]); 55636399Ssklower ENDDEBUG 55736399Ssklower ADDOPTION(TPP_flow_cntl_conf, hdr, sizeof(bogus), bogus[0]); 55836399Ssklower IFDEBUG(D_ACKSEND) 55936399Ssklower printf("after ADDOPTION hdr 0x%x hdr->tpdu_li 0x%x\n", 56036399Ssklower hdr, hdr->tpdu_li); 56136399Ssklower printf( 56236399Ssklower "after ADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 56336399Ssklower csum_offset, hdr->tpdu_li); 56436399Ssklower ENDDEBUG 56536399Ssklower 56636399Ssklower } 56736399Ssklower tpcb->tp_reneged = 0; 56836399Ssklower tpcb->tp_sent_rcvnxt = seq; 56936399Ssklower tp_ctimeout(tpcb->tp_refp, TM_sendack, 57036399Ssklower (int)tpcb->tp_keepalive_ticks); 57136399Ssklower IncStat(ts_AK_sent); 57236399Ssklower IncPStat(tpcb, tps_AK_sent); 57336399Ssklower IFDEBUG(D_ACKSEND) 57436399Ssklower printf( 57536399Ssklower "2 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 57636399Ssklower csum_offset, hdr->tpdu_li); 57736399Ssklower ENDDEBUG 57836399Ssklower break; 57936399Ssklower 58036399Ssklower case ER_TPDU_type: 58136399Ssklower hdr->tpdu_ERreason = eot; 58236399Ssklower hdr->tpdu_cdt = 0; 58336399Ssklower /* no user data */ 58436399Ssklower data = (struct mbuf *)0; 58536399Ssklower IncStat(ts_ER_sent); 58636399Ssklower break; 58736399Ssklower } 58836399Ssklower 58936399Ssklower } 59036399Ssklower ASSERT( ((int)hdr->tpdu_li > 0) && ((int)hdr->tpdu_li < MLEN) ); 59136399Ssklower 59236399Ssklower m->m_next = data; 59336399Ssklower 59437469Ssklower ASSERT( hdr->tpdu_li < MLEN ); /* leave this in */ 59536399Ssklower ASSERT( hdr->tpdu_li != 0 ); /* leave this in */ 59636399Ssklower 59736399Ssklower m->m_len = hdr->tpdu_li ; 59836399Ssklower hdr->tpdu_li --; /* doesn't include the li field */ 59936399Ssklower 60036399Ssklower datalen = m_datalen( m ); /* total len */ 60136399Ssklower 60236399Ssklower ASSERT( datalen <= tpcb->tp_l_tpdusize ); /* may become a problem 60336399Ssklower when CLNP is used; leave in here for the time being */ 60436399Ssklower IFDEBUG(D_ACKSEND) 60536399Ssklower printf( 60636399Ssklower "4 after rADDOPTION csum_offset 0x%x, hdr->tpdu_li 0x%x\n", 60736399Ssklower csum_offset, hdr->tpdu_li); 60836399Ssklower ENDDEBUG 60936399Ssklower if( datalen > tpcb->tp_l_tpdusize ) { 61036399Ssklower printf("data len 0x%x tpcb->tp_l_tpdusize 0x%x\n", 61136399Ssklower datalen, tpcb->tp_l_tpdusize); 61236399Ssklower } 61336399Ssklower IFDEBUG(D_EMIT) 61436399Ssklower printf( 61536399Ssklower "tp_emit before gen_csum m_len 0x%x, csum_offset 0x%x, datalen 0x%x\n", 61636399Ssklower m->m_len, csum_offset, datalen); 61736399Ssklower ENDDEBUG 61836399Ssklower if( tpcb->tp_use_checksum || 61936399Ssklower (dutype == CR_TPDU_type && (tpcb->tp_class & TP_CLASS_4)) ) { 62036399Ssklower iso_gen_csum(m, csum_offset, datalen); 62136399Ssklower } 62236399Ssklower 62336399Ssklower IFDEBUG(D_EMIT) 62436399Ssklower printf("tp_emit before tpxxx_output tpcb 0x%x, dutype 0x%x, datalen 0x%x\n", 62536399Ssklower tpcb, dutype, datalen); 62637469Ssklower dump_buf(mtod(m, caddr_t), datalen); 62736399Ssklower ENDDEBUG 62836399Ssklower 62936399Ssklower IFPERF(tpcb) 63036399Ssklower if( dutype == DT_TPDU_type ) { 63136399Ssklower PStat(tpcb, Nb_to_ll) += (datalen - m->m_len); 63237469Ssklower tpmeas( tpcb->tp_lref, TPtime_to_ll, (struct timeval *)0, 63336399Ssklower seq, PStat(tpcb, Nb_to_ll), (datalen - m->m_len)); 63436399Ssklower } 63536399Ssklower ENDPERF 63636399Ssklower 63736399Ssklower IFTRACE(D_EMIT) 63836399Ssklower tptraceTPCB(TPPTtpduout, dutype, hdr, hdr->tpdu_li+1, datalen, 0); 63936399Ssklower ENDTRACE 64036399Ssklower IFDEBUG(D_EMIT) 64136399Ssklower printf("OUTPUT: tpcb 0x%x, isop 0x%x, so 0x%x\n", 64236399Ssklower tpcb, tpcb->tp_npcb, tpcb->tp_sock); 64336399Ssklower ENDDEBUG 64436399Ssklower 64536399Ssklower { extern char tp_delay; 64636399Ssklower 64736399Ssklower if( tp_delay ) 64836399Ssklower if( tpcb->tp_use_checksum == 0 ) { 64936399Ssklower register u_int i = tp_delay; 65036399Ssklower for (; i!= 0; i--) 65136399Ssklower (void) iso_check_csum(m, datalen); 65236399Ssklower } 65336399Ssklower } 65436399Ssklower ASSERT( m->m_len > 0 ); 65536399Ssklower error = (tpcb->tp_nlproto->nlp_output)(tpcb->tp_npcb, m, datalen, 65636399Ssklower !tpcb->tp_use_checksum); 65736399Ssklower IFDEBUG(D_EMIT) 65836399Ssklower printf("OUTPUT: returned 0x%x\n", error); 65936399Ssklower ENDDEBUG 66036399Ssklower IFTRACE(D_EMIT) 66136399Ssklower tptraceTPCB(TPPTmisc, 66236399Ssklower "tp_emit nlproto->output netservice returns datalen", 66336399Ssklower tpcb->tp_nlproto->nlp_output, tpcb->tp_netservice, error, datalen); 66436399Ssklower ENDTRACE 66536399Ssklower done: 66636399Ssklower if( error == E_CO_QFULL ) { 66737469Ssklower tp_quench(tpcb, PRC_QUENCH); 66836399Ssklower return 0; 66936399Ssklower } 67036399Ssklower return error; 67136399Ssklower } 67236399Ssklower /* 67336399Ssklower * NAME: tp_error_emit() 67436399Ssklower * CALLED FROM: tp_input() when a DR or ER is to be issued in 67536399Ssklower * response to an input error. 67636399Ssklower * FUNCTION and ARGUMENTS: 67736399Ssklower * The error type is the first argument. 67836399Ssklower * The argument (sref) is the source reference on the bad incoming tpdu, 67936399Ssklower * and is used for a destination reference on the outgoing packet. 68036399Ssklower * (faddr) and (laddr) are the foreign and local addresses for this 68136399Ssklower * connection. 68236399Ssklower * (erdata) is a ptr to the errant incoming tpdu, and is copied into the 68336399Ssklower * outgoing ER, if an ER is to be issued. 68436399Ssklower * (erlen) is the number of octets of the errant tpdu that we should 68536399Ssklower * try to copy. 68636399Ssklower * (tpcb) is the pcb that describes the connection for which the bad tpdu 68736399Ssklower * arrived. 68836399Ssklower * RETURN VALUES: 68936399Ssklower * 0 OK 69036399Ssklower * ENOBUFS 69136399Ssklower * E* from net layer datagram output routine 69236399Ssklower * SIDE EFFECTS: 69336399Ssklower * 69436399Ssklower * NOTES: 69536399Ssklower */ 69636399Ssklower 69736399Ssklower int 69836399Ssklower tp_error_emit(error, sref, faddr, laddr, erdata, erlen, tpcb, cons_channel, 69936399Ssklower dgout_routine) 70036399Ssklower int error; 70136399Ssklower u_long sref; 70236399Ssklower struct sockaddr_iso *faddr, *laddr; 70336399Ssklower struct mbuf *erdata; 70436399Ssklower int erlen; 70536399Ssklower struct tp_pcb *tpcb; 70636399Ssklower int cons_channel; 70736399Ssklower int (*dgout_routine)(); 70836399Ssklower { 70936399Ssklower int dutype; 71036399Ssklower int datalen = 0; 71136399Ssklower register struct tpdu *hdr; 71236399Ssklower register struct mbuf *m; 71336399Ssklower int csum_offset; 71436399Ssklower 71536399Ssklower IFTRACE(D_ERROR_EMIT) 71636399Ssklower tptrace(TPPTmisc, "tp_error_emit error sref tpcb erlen", 71736399Ssklower error, sref, tpcb, erlen); 71836399Ssklower ENDTRACE 71936399Ssklower IFDEBUG(D_ERROR_EMIT) 72036399Ssklower printf( 72136399Ssklower "tp_error_emit error 0x%x sref 0x%x tpcb 0x%x erlen 0x%x chan 0x%x\n", 72236399Ssklower error, sref, tpcb, erlen, cons_channel); 72336399Ssklower ENDDEBUG 72436399Ssklower 72536399Ssklower MGET(m, M_DONTWAIT, TPMT_TPHDR); 72636399Ssklower if (m == NULL) { 72736399Ssklower return ENOBUFS; 72836399Ssklower } 72936399Ssklower m->m_len = sizeof(struct tpdu); 73036399Ssklower m->m_act = MNULL; 73136399Ssklower 73236399Ssklower hdr = mtod(m, struct tpdu *); 73336399Ssklower 73436399Ssklower IFDEBUG(D_ERROR_EMIT) 73536399Ssklower printf("[error 0x%x] [error&0xff 0x%x] [(char)error 0x%x]\n", 73636399Ssklower error, error&0xff, (char)error); 73736399Ssklower ENDDEBUG 73836399Ssklower 73936399Ssklower error &= 0xff; 74036399Ssklower 74136399Ssklower if( error & 0x40 ) { 74236399Ssklower error &= ~0x40; 74336399Ssklower dutype = ER_TPDU_type; 74436399Ssklower } else 74536399Ssklower dutype = DR_TPDU_type; 74636399Ssklower 74736399Ssklower hdr->tpdu_type = dutype; 74836399Ssklower hdr->tpdu_cdt = 0; 74936399Ssklower 75036399Ssklower switch( dutype ) { 75136399Ssklower 75236399Ssklower case DR_TPDU_type: 75336399Ssklower IncStat(ts_DR_sent); 75436399Ssklower hdr->tpdu_li = 7; 75536399Ssklower hdr->tpdu_DRdref = htons(sref); 75636399Ssklower hdr->tpdu_DRsref = htons(0); 75736399Ssklower hdr->tpdu_DRreason = (char)error; 75836399Ssklower IFDEBUG(D_ERROR_EMIT) 75936399Ssklower printf("DR case:\n"); 76036399Ssklower dump_buf( hdr, 7); 76136399Ssklower ENDDEBUG 76236399Ssklower /* forget the add'l information variable part */ 76336399Ssklower break; 76436399Ssklower 76536399Ssklower case ER_TPDU_type: 76636399Ssklower IncStat(ts_ER_sent); 76736399Ssklower hdr->tpdu_li = 5; 76836399Ssklower hdr->tpdu_ERreason = (char)error; 76936399Ssklower break; 77036399Ssklower 77136399Ssklower default: 77236399Ssklower ASSERT(0); 77336399Ssklower printf("TP PANIC: bad dutype 0x%x\n", dutype); 77436399Ssklower } 77536399Ssklower 77636399Ssklower if(tpcb) 77736399Ssklower if( tpcb->tp_use_checksum ) { 77836399Ssklower ADDOPTION(TPP_checksum, hdr, 2, csum_offset /* dummy argument */); 77936399Ssklower csum_offset = hdr->tpdu_li - 2; 78036399Ssklower } 78136399Ssklower 78237469Ssklower ASSERT( hdr->tpdu_li < MLEN ); 78336399Ssklower 78436399Ssklower if (dutype == ER_TPDU_type) { 78536399Ssklower /* copy the errant tpdu into another 'variable part' */ 78636399Ssklower register caddr_t P; 78736399Ssklower 78836399Ssklower IFTRACE(D_ERROR_EMIT) 78936399Ssklower tptrace(TPPTmisc, "error_emit ER len tpduli", erlen, hdr->tpdu_li, 79036399Ssklower 0,0); 79136399Ssklower ENDTRACE 79236399Ssklower IFDEBUG(D_ERROR_EMIT) 79336399Ssklower printf("error_emit ER len 0x%x tpduli 0x%x\n", erlen, hdr->tpdu_li); 79436399Ssklower ENDDEBUG 79536399Ssklower 79636399Ssklower /* copy at most as many octets for which you have room */ 79736399Ssklower if (erlen + hdr->tpdu_li + 2 > TP_MAX_HEADER_LEN) 79836399Ssklower erlen = TP_MAX_HEADER_LEN - hdr->tpdu_li - 2; 79936399Ssklower 80036399Ssklower /* add the "invalid tpdu" parameter : required in class 0 */ 80136399Ssklower P = (caddr_t)hdr + (int)(hdr->tpdu_li); 80236399Ssklower vbptr(P)->tpv_code = TPP_invalid_tpdu; /* parameter code */ 80336399Ssklower vbptr(P)->tpv_len = erlen; /* parameter length */ 80436399Ssklower m->m_len = hdr->tpdu_li + 2; /* 1 for code, 1 for length */ 80536399Ssklower 80636399Ssklower /* tp_input very likely handed us an mbuf chain w/ nothing in 80736399Ssklower * the first mbuf and the data following the empty mbuf 80836399Ssklower */ 80936399Ssklower if(erdata->m_len == 0) { 81036399Ssklower erdata = m_free(erdata); /* returns the next mbuf on the chain */ 81136399Ssklower } 81237469Ssklower /* 81337469Ssklower * copy only up to the bad octet 81437469Ssklower * (or max that will fit in a header 81537469Ssklower */ 81637469Ssklower m->m_next = m_copy(erdata, 0, erlen); 81736399Ssklower hdr->tpdu_li += erlen + 2; 81836399Ssklower m_freem(erdata); 81936399Ssklower } else { 82036399Ssklower IFDEBUG(D_ERROR_EMIT) 82136399Ssklower printf("error_emit DR error tpduli 0x%x\n", error, hdr->tpdu_li); 82236399Ssklower dump_buf( (char *)hdr, hdr->tpdu_li ); 82336399Ssklower ENDDEBUG 82436399Ssklower m->m_len = hdr->tpdu_li ; 82536399Ssklower m_freem(erdata); 82636399Ssklower } 82736399Ssklower 82836399Ssklower hdr->tpdu_li --; 82936399Ssklower IFTRACE(D_ERROR_EMIT) 83036399Ssklower tptrace(TPPTtpduout, 2, hdr, hdr->tpdu_li+1, 0, 0); 83136399Ssklower ENDTRACE 83236399Ssklower 83336399Ssklower datalen = m_datalen( m); 83436399Ssklower 83536399Ssklower if(tpcb) { 83636399Ssklower if( tpcb->tp_use_checksum ) { 83736399Ssklower IFTRACE(D_ERROR_EMIT) 83836399Ssklower tptrace(TPPTmisc, "before gen csum datalen", datalen,0,0,0); 83936399Ssklower ENDTRACE 84036399Ssklower IFDEBUG(D_ERROR_EMIT) 84136399Ssklower printf("before gen csum datalen 0x%x, csum_offset 0x%x\n", 84236399Ssklower datalen, csum_offset); 84336399Ssklower ENDDEBUG 84436399Ssklower 84536399Ssklower iso_gen_csum(m, csum_offset, datalen); 84636399Ssklower } 84736399Ssklower 84836399Ssklower IFDEBUG(D_ERROR_EMIT) 84936399Ssklower printf("OUTPUT: tpcb 0x%x, isop 0x%x, so 0x%x\n", 85036399Ssklower tpcb, tpcb->tp_npcb, tpcb->tp_sock); 85136399Ssklower ENDDEBUG 85236399Ssklower /* Problem: if packet comes in on ISO but sock is listening 85336399Ssklower * in INET, this assertion will fail. 85436399Ssklower * Have to believe the argument, not the nlp_proto. 85536399Ssklower ASSERT( tpcb->tp_nlproto->nlp_dgoutput == dgout_routine ); 85636399Ssklower */ 85736399Ssklower 85836399Ssklower IFDEBUG(D_ERROR_EMIT) 85936399Ssklower printf("tp_error_emit 1 sending DG: Laddr\n"); 86037469Ssklower dump_addr((struct sockaddr *)laddr); 86136399Ssklower printf("Faddr\n"); 86237469Ssklower dump_addr((struct sockaddr *)faddr); 86336399Ssklower ENDDEBUG 86436399Ssklower return (tpcb->tp_nlproto->nlp_dgoutput)( 86536399Ssklower &laddr->siso_addr, 86636399Ssklower &faddr->siso_addr, 86736399Ssklower m, datalen, 86836399Ssklower /* no route */ (caddr_t)0, !tpcb->tp_use_checksum); 86936399Ssklower } else { 87036399Ssklower if( cons_channel ) { 87136399Ssklower #if NARGOXTWENTYFIVE > 0 87237469Ssklower #include "cons.h" 87336399Ssklower /* This is unfortunate... 87436399Ssklower cons_send_on_vc(cons_channel, m, datalen); 87536399Ssklower */ 87636399Ssklower cons_netcmd( CONN_CLOSE, (struct isopcb *)0, 87736399Ssklower cons_channel, CONS_NOT_DGM); 87836399Ssklower IFDEBUG(D_ERROR_EMIT) 87936399Ssklower printf("OUTPUT: dutype 0x%x channel 0x%x\n", 88036399Ssklower dutype, cons_channel); 88136399Ssklower ENDDEBUG 88236399Ssklower #else NARGOXTWENTYFIVE 88336399Ssklower printf("TP panic! cons channel 0x%x but not cons configured\n", 88436399Ssklower cons_channel); 88536399Ssklower #endif NARGOXTWENTYFIVE > 0 88636399Ssklower } else { 88737469Ssklower #ifndef notdef 88836399Ssklower IFDEBUG(D_ERROR_EMIT) 88936399Ssklower printf("tp_error_emit sending DG: Laddr\n"); 89037469Ssklower dump_addr((struct sockaddr *)laddr); 89136399Ssklower printf("Faddr\n"); 89237469Ssklower dump_addr((struct sockaddr *)faddr); 89336399Ssklower ENDDEBUG 89436399Ssklower return (*dgout_routine)( &laddr->siso_addr, &faddr->siso_addr, 89536399Ssklower m, datalen, /* no route */ 89636399Ssklower (caddr_t)0, /* nochecksum==false */0); 89737469Ssklower #else notdef 89836399Ssklower IFDEBUG(D_ERROR_EMIT) 89936399Ssklower printf("tp_error_emit DROPPING \n", m); 90036399Ssklower ENDDEBUG 90136399Ssklower IncStat(ts_send_drop); 90236399Ssklower m_freem(m); 90336399Ssklower return 0; 90437469Ssklower #endif notdef 90536399Ssklower } 90636399Ssklower } 90736399Ssklower } 908