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