xref: /csrg-svn/sys/netiso/tp_emit.c (revision 39924)
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