xref: /original-bsd/sys/netiso/tp_input.c (revision 9b5efc43)
1 /***********************************************************
2 		Copyright IBM Corporation 1987
3 
4                       All Rights Reserved
5 
6 Permission to use, copy, modify, and distribute this software and its
7 documentation for any purpose and without fee is hereby granted,
8 provided that the above copyright notice appear in all copies and that
9 both that copyright notice and this permission notice appear in
10 supporting documentation, and that the name of IBM not be
11 used in advertising or publicity pertaining to distribution of the
12 software without specific, written prior permission.
13 
14 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20 SOFTWARE.
21 
22 ******************************************************************/
23 
24 /*
25  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26  */
27 /*
28  * ARGO TP
29  *
30  * $Header: tp_input.c,v 5.6 88/11/18 17:27:38 nhall Exp $
31  * $Source: /usr/argo/sys/netiso/RCS/tp_input.c,v $
32  *	@(#)tp_input.c	7.15 (Berkeley) 01/09/91 *
33  *
34  * tp_input() gets an mbuf chain from ip.  Actually, not directly
35  * from ip, because ip calls a net-level routine that strips off
36  * the net header and then calls tp_input(), passing the proper type
37  * of addresses for the address family in use (how it figures out
38  * which AF is not yet determined.
39  *
40  * Decomposing the tpdu is some of the most laughable code.  The variable-length
41  * parameters and the problem of non-aligned memory references
42  * necessitates such abominations as the macros WHILE_OPTIONS (q.v. below)
43  * to loop through the header and decompose it.
44  *
45  * The routine tp_newsocket() is called when a CR comes in for a listening
46  * socket.  tp_input calls sonewconn() and tp_newsocket() to set up the
47  * "child" socket.  Most tpcb values are copied from the parent tpcb into
48  * the child.
49  *
50  * Also in here is tp_headersize() (grot) which tells the expected size
51  * of a tp header, to be used by other layers.  It's in here because it
52  * uses the static structure tpdu_info.
53  */
54 
55 #ifndef lint
56 static char *rcsid = "$Header: tp_input.c,v 5.6 88/11/18 17:27:38 nhall Exp $";
57 #endif lint
58 
59 #include "param.h"
60 #include "systm.h"
61 #include "mbuf.h"
62 #include "socket.h"
63 #include "socketvar.h"
64 #include "domain.h"
65 #include "protosw.h"
66 #include "errno.h"
67 #include "time.h"
68 #include "kernel.h"
69 #include "types.h"
70 #include "iso.h"
71 #include "iso_errno.h"
72 #include "iso_pcb.h"
73 #include "tp_param.h"
74 #include "tp_timer.h"
75 #include "tp_stat.h"
76 #include "tp_pcb.h"
77 #include "argo_debug.h"
78 #include "tp_trace.h"
79 #include "tp_tpdu.h"
80 
81 #include "../net/if.h"
82 #ifdef TRUE
83 #undef FALSE
84 #undef TRUE
85 #endif
86 #include "../netccitt/x25.h"
87 #include "../netccitt/pk.h"
88 #include "../netccitt/pk_var.h"
89 
90 int 	iso_check_csum(), tp_driver(), tp_headersize(), tp_error_emit();
91 
92 /*
93 	#ifdef lint
94 	#undef ATTR
95 	#define ATTR(X)ev_number
96 	#endif lint
97 */
98 
99 struct mbuf *
100 tp_inputprep(m)
101 	register struct mbuf *m;
102 {
103 	int hdrlen;
104 
105 	IFDEBUG(D_TPINPUT)
106 		printf("tp_inputprep: m 0x%x\n", m) ;
107 	ENDDEBUG
108 
109 	while(  m->m_len < 1 ) {
110 		if( (m = m_free(m)) == MNULL ) {
111 			return (struct mbuf *)0;
112 		}
113 	}
114 	if(((int)m->m_data) & 0x3) {
115 		/* If we are not 4-byte aligned, we have to be
116 		 * above the beginning of the mbuf, and it is ok just
117 		 * to slide it back.
118 		 */
119 		caddr_t ocp = m->m_data;
120 
121 		m->m_data = (caddr_t)(((int)m->m_data) & ~0x3);
122 		ovbcopy(ocp, m->m_data, (unsigned)m->m_len);
123 	}
124 	CHANGE_MTYPE(m, TPMT_DATA);
125 
126 	/* we KNOW that there is at least 1 byte in this mbuf
127 	   and that it is hdr->tpdu_li XXXXXXX!  */
128 
129 	hdrlen = 1 + *mtod( m, u_char *);
130 
131 	/*
132 	 * now pull up the whole tp header
133 	 */
134 	if ( m->m_len < hdrlen) {
135 		if ((m = m_pullup(m, hdrlen)) == MNULL ) {
136 			IncStat(ts_recv_drop);
137 			return (struct mbuf *)0;
138 		}
139 	}
140 	IFDEBUG(D_INPUT)
141 	printf(
142 	" at end: m 0x%x hdr->tpdu_li 0x%x m_len 0x%x\n",m,
143 		hdrlen, m->m_len);
144 	ENDDEBUG
145 	return m;
146 }
147 
148 /* begin groan
149  * -- this array and the following macros allow you to step through the
150  * parameters of the variable part of a header
151  * note that if for any reason the values of the **_TPDU macros (in tp_events.h)
152  * should change, this array has to be rearranged
153  */
154 
155 #define TP_LEN_CLASS_0_INDEX	2
156 #define TP_MAX_DATA_INDEX 3
157 
158 static u_char tpdu_info[][4] =
159 {
160 /*								length						 max data len */
161 /*								reg fmt 	xtd fmt  class 0  		 	  */
162  	/* UNUSED		0x0 */		0x0 ,		0x0,	0x0,		0x0,
163  	/* XPD_TPDU_type 0x1 */		0x5,		0x8,	0x0,		TP_MAX_XPD_DATA,
164  	/* XAK_TPDU_type 0x2 */		0x5 ,		0x8,	0x0,		0x0,
165  	/* GR_TPDU_type	0x3 */		0x0 ,		0x0,	0x0,		0x0,
166  	/* UNUSED		0x4 */		0x0 ,		0x0,	0x0,		0x0,
167  	/* UNUSED		0x5 */		0x0 ,		0x0,	0x0,		0x0,
168  	/* AK_TPDU_type 0x6 */		0x5,		0xa,	0x0,		0x0,
169 	/* ER_TPDU_type 0x7 */		0x5,		0x5,	0x0,		0x0,
170  	/* DR_TPDU_type 0x8 */		0x7,		0x7,	0x7,		TP_MAX_DR_DATA,
171  	/* UNUSED		0x9 */		0x0 ,		0x0,	0x0,		0x0,
172  	/* UNUSED		0xa */		0x0 ,		0x0,	0x0,		0x0,
173  	/* UNUSED		0xb */		0x0 ,		0x0,	0x0,		0x0,
174  	/* DC_TPDU_type 0xc */		0x6,		0x6,	0x0,		0x0,
175  	/* CC_TPDU_type 0xd */		0x7,		0x7,	0x7,		TP_MAX_CC_DATA,
176  	/* CR_TPDU_type 0xe */		0x7,		0x7,	0x7,		TP_MAX_CR_DATA,
177  	/* DT_TPDU_type 0xf */		0x5,		0x8,	0x3,		0x0,
178 };
179 
180 #define CHECK(Phrase, Erval, Stat, Whattodo, Loc)\
181 	if (Phrase) {error = (Erval); errlen = (int)(Loc); IncStat(Stat); tpibrk();\
182 	goto Whattodo; }
183 
184 tpibrk() {}
185 
186 /*
187  * WHENEVER YOU USE THE FOLLOWING MACRO,
188  * BE SURE THE TPDUTYPE IS A LEGIT VALUE FIRST!
189  */
190 
191 #define WHILE_OPTIONS(P, hdr, format)\
192 {	register caddr_t P = tpdu_info[(hdr)->tpdu_type][(format)] + (caddr_t)hdr;\
193 	caddr_t PLIM = 1 + hdr->tpdu_li + (caddr_t)hdr;\
194 	for (;; P += 2 + ((struct tp_vbp *)P)->tpv_len) {\
195 		CHECK((P > PLIM), E_TP_LENGTH_INVAL, ts_inv_length,\
196 				respond, P - (caddr_t)hdr);\
197 		if (P == PLIM) break;
198 
199 #define END_WHILE_OPTIONS(P) } }
200 
201 /* end groan */
202 
203 /*
204  * NAME:  tp_newsocket()
205  *
206  * CALLED FROM:
207  *  tp_input() on incoming CR, when a socket w/ the called suffix
208  * is awaiting a  connection request
209  *
210  * FUNCTION and ARGUMENTS:
211  *  Create a new socket structure, attach to it a new transport pcb,
212  *  using a copy of the net level pcb for the parent socket.
213  *  (so) is the parent socket.
214  *  (fname) is the foreign address (all that's used is the nsap portion)
215  *
216  * RETURN VALUE:
217  *  a new socket structure, being this end of the newly formed connection.
218  *
219  * SIDE EFFECTS:
220  *  Sets a few things in the tpcb and net level pcb
221  *
222  * NOTES:
223  */
224 static struct socket *
225 tp_newsocket(so, fname, cons_channel, class_to_use, netservice)
226 	struct socket				*so;
227 	struct sockaddr				*fname;
228 	u_int						cons_channel;
229 	u_char						class_to_use;
230 	u_int						netservice;
231 {
232 	register struct tp_pcb	*tpcb = sototpcb(so); /* old tpcb, needed below */
233 	register struct tp_pcb	*newtpcb;
234 
235 	/*
236 	 * sonewconn() gets a new socket structure,
237 	 * a new lower layer pcb and a new tpcb,
238 	 * but the pcbs are unnamed (not bound)
239 	 */
240 	IFTRACE(D_NEWSOCK)
241 		tptraceTPCB(TPPTmisc, "newsock: listg_so, _tpcb, so_head",
242 			so, tpcb, so->so_head, 0);
243 	ENDTRACE
244 
245 	if ((so = sonewconn(so, SS_ISCONFIRMING)) == (struct socket *)0)
246 		return so;
247 	IFTRACE(D_NEWSOCK)
248 		tptraceTPCB(TPPTmisc, "newsock: after newconn so, so_head",
249 			so, so->so_head, 0, 0);
250 	ENDTRACE
251 
252 	IFDEBUG(D_NEWSOCK)
253 		printf("tp_newsocket(channel 0x%x)  after sonewconn so 0x%x \n",
254 				cons_channel, so);
255 		dump_addr(fname);
256 		{
257 			struct socket *t, *head ;
258 
259 			head = so->so_head;
260 			t = so;
261 			printf("so 0x%x so_head 0x%x so_q0 0x%x, q0len %d\n",
262 					t, t->so_head, t->so_q0, t->so_q0len);
263 			while( (t=t->so_q0)  && t!= so  && t!= head)
264 				printf("so 0x%x so_head 0x%x so_q0 0x%x, q0len %d\n",
265 					t, t->so_head, t->so_q0, t->so_q0len);
266 		}
267 	ENDDEBUG
268 
269 	/*
270 	 * before we clobber the old tpcb ptr, get these items from the parent pcb
271 	 */
272 	newtpcb = sototpcb(so);
273 	newtpcb->_tp_param = tpcb->_tp_param;
274 	newtpcb->tp_flags = tpcb->tp_flags;
275 	newtpcb->tp_lcredit = tpcb->tp_lcredit;
276 	newtpcb->tp_l_tpdusize = tpcb->tp_l_tpdusize;
277 	newtpcb->tp_lsuffixlen = tpcb->tp_lsuffixlen;
278 	bcopy( tpcb->tp_lsuffix, newtpcb->tp_lsuffix, newtpcb->tp_lsuffixlen);
279 	soreserve(so, (u_long)tpcb->tp_winsize, (u_long)tpcb->tp_winsize);
280 
281 	if( /* old */ tpcb->tp_ucddata) {
282 		/*
283 		 * These data are the connect- , confirm- or disconnect- data.
284 		 */
285 		struct mbuf *conndata;
286 
287 		conndata = m_copy(tpcb->tp_ucddata, 0, (int)M_COPYALL);
288 		IFDEBUG(D_CONN)
289 			dump_mbuf(conndata, "conndata after mcopy");
290 		ENDDEBUG
291 		newtpcb->tp_ucddata = conndata;
292 	}
293 
294 	tpcb = newtpcb;
295 	tpcb->tp_state = TP_LISTENING;
296 	tpcb->tp_class = class_to_use;
297 	tpcb->tp_netservice = netservice;
298 
299 
300 	ASSERT( fname != 0 ) ; /* just checking */
301 	if ( fname ) {
302 		/*
303 		 *	tp_route_to takes its address argument in the form of an mbuf.
304 		 */
305 		struct mbuf	*m;
306 		int			err;
307 
308 		MGET(m, M_DONTWAIT, MT_SONAME);	/* mbuf type used is confusing */
309 		if (m) {
310 			/*
311 			 * this seems a bit grotesque, but tp_route_to expects
312 			 * an mbuf * instead of simply a sockaddr; it calls the ll
313 			 * pcb_connect, which expects the name/addr in an mbuf as well.
314 			 * sigh.
315 			 */
316 			bcopy((caddr_t)fname, mtod(m, caddr_t), fname->sa_len);
317 			m->m_len = fname->sa_len;
318 
319 			/* grot  : have to say the kernel can override params in
320 			 * the passive open case
321 			 */
322 			tpcb->tp_dont_change_params = 0;
323 			err = tp_route_to( m, tpcb, cons_channel);
324 			m_free(m);
325 
326 			if (!err)
327 				goto ok;
328 		}
329 		IFDEBUG(D_CONN)
330 			printf("tp_route_to FAILED! detaching tpcb 0x%x, so 0x%x\n",
331 				tpcb, so);
332 		ENDDEBUG
333 		(void) tp_detach(tpcb);
334 		return 0;
335 	}
336 ok:
337 	IFDEBUG(D_TPINPUT)
338 		printf("tp_newsocket returning so 0x%x, sototpcb(so) 0x%x\n",
339 			so, sototpcb(so));
340 	ENDDEBUG
341 	return so;
342 }
343 
344 #ifndef TPCONS
345 tpcons_output()
346 {
347 	return(0);
348 }
349 #endif !CONS
350 
351 /*
352  * NAME: 	tp_input()
353  *
354  * CALLED FROM:
355  *  net layer input routine
356  *
357  * FUNCTION and ARGUMENTS:
358  *  Process an incoming TPDU (m), finding the associated tpcb if there
359  *  is one. Create the appropriate type of event and call the driver.
360  *  (faddr) and (laddr) are the foreign and local addresses.
361  *
362  * 	When tp_input() is called we KNOW that the ENTIRE TP HEADER
363  * 	has been m_pullup-ed.
364  *
365  * RETURN VALUE: Nada
366  *
367  * SIDE EFFECTS:
368  *	When using COSNS it may affect the state of the net-level pcb
369  *
370  * NOTE:
371  *  The initial value of acktime is 2 so that we will never
372  *  have a 0 value for tp_peer_acktime.  It gets used in the
373  *  computation of the retransmission timer value, and so it
374  *  mustn't be zero.
375  *  2 seems like a reasonable minimum.
376  */
377 ProtoHook
378 tp_input(m, faddr, laddr, cons_channel, dgout_routine, ce_bit)
379 	register	struct mbuf 	*m;
380 	struct sockaddr 			*faddr, *laddr; /* NSAP addresses */
381 	u_int 						cons_channel;
382 	int 						(*dgout_routine)();
383 	int							ce_bit;
384 
385 {
386 	register struct tp_pcb 	*tpcb = (struct tp_pcb *)0;
387 	register struct tpdu 	*hdr;
388 	struct socket 			*so;
389 	struct tp_event 		e;
390 	int 					error = 0;
391 	unsigned 				dutype;
392 	u_short 				dref, sref = 0, acktime = 2, subseq = 0; /*VAX*/
393 	u_char 					preferred_class = 0, class_to_use = 0;
394 	u_char					opt, dusize = TP_DFL_TPDUSIZE, addlopt = 0, version;
395 #ifdef TP_PERF_MEAS
396 	u_char					perf_meas;
397 #endif TP_PERF_MEAS
398 	u_char					fsufxlen = 0, lsufxlen = 0, intercepted = 0;
399 	caddr_t					fsufxloc = 0, lsufxloc = 0;
400 	int						tpdu_len = 0;
401 	u_int 					takes_data = FALSE;
402 	u_int					fcc_present = FALSE;
403 	int						errlen = 0;
404 	struct tp_conn_param 	tpp;
405 	int						tpcons_output();
406 
407 again:
408 	hdr = mtod(m, struct tpdu *);
409 #ifdef TP_PERF_MEAS
410 	GET_CUR_TIME( &e.e_time ); perf_meas = 0;
411 #endif TP_PERF_MEAS
412 
413 	IFDEBUG(D_TPINPUT)
414 		printf("tp_input(0x%x, ... 0x%x)\n", m, cons_channel);
415 	ENDDEBUG
416 
417 
418 	/*
419 	 * get the actual tpdu length - necessary for monitoring
420 	 * and for checksumming
421 	 *
422 	 * Also, maybe measure the mbuf chain lengths and sizes.
423 	 */
424 
425 	{ 	register struct mbuf *n=m;
426 #	ifdef ARGO_DEBUG
427 		int chain_length = 0;
428 #	endif ARGO_DEBUG
429 
430 		for(;;) {
431 			tpdu_len += n->m_len;
432 			IFDEBUG(D_MBUF_MEAS)
433 				if( n->m_flags & M_EXT) {
434 					IncStat(ts_mb_cluster);
435 				} else {
436 					IncStat(ts_mb_small);
437 				}
438 				chain_length ++;
439 			ENDDEBUG
440 			if (n->m_next == MNULL ) {
441 				break;
442 			}
443 			n = n->m_next;
444 		}
445 		IFDEBUG(D_MBUF_MEAS)
446 			if(chain_length > 16)
447 				chain_length = 0; /* zero used for anything > 16 */
448 			tp_stat.ts_mb_len_distr[chain_length] ++;
449 		ENDDEBUG
450 	}
451 	IFTRACE(D_TPINPUT)
452 		tptraceTPCB(TPPTtpduin, hdr->tpdu_type, hdr, hdr->tpdu_li+1, tpdu_len,
453 			0);
454 	ENDTRACE
455 
456 	dref = ntohs((short)hdr->tpdu_dref);
457 	sref = ntohs((short)hdr->tpdu_sref);
458 	dutype = (int)hdr->tpdu_type;
459 
460 	IFDEBUG(D_TPINPUT)
461 		printf("input: dutype 0x%x cons_channel 0x%x dref 0x%x\n", dutype,
462 			cons_channel, dref);
463 		printf("input: dref 0x%x sref 0x%x\n", dref, sref);
464 	ENDDEBUG
465 	IFTRACE(D_TPINPUT)
466 		tptrace(TPPTmisc, "channel dutype dref ",
467 			cons_channel, dutype, dref, 0);
468 	ENDTRACE
469 
470 
471 #ifdef ARGO_DEBUG
472 	if( (dutype < TP_MIN_TPDUTYPE) || (dutype > TP_MAX_TPDUTYPE)) {
473 		printf("BAD dutype! 0x%x, channel 0x%x dref 0x%x\n",
474 			dutype, cons_channel, dref);
475 		dump_buf (m, sizeof( struct mbuf ));
476 
477 		IncStat(ts_inv_dutype);
478 		goto discard;
479 	}
480 #endif ARGO_DEBUG
481 
482 	CHECK( (dutype < TP_MIN_TPDUTYPE || dutype > TP_MAX_TPDUTYPE),
483 		E_TP_INV_TPDU, ts_inv_dutype, respond,
484 		2 );
485 		/* unfortunately we can't take the address of the tpdu_type field,
486 		 * since it's a bit field - so we just use the constant offset 2
487 		 */
488 
489 	/* Now this isn't very neat but since you locate a pcb one way
490 	 * at the beginning of connection establishment, and by
491 	 * the dref for each tpdu after that, we have to treat CRs differently
492 	 */
493 	if ( dutype == CR_TPDU_type ) {
494 		u_char alt_classes = 0;
495 
496 		preferred_class = 1 << hdr->tpdu_CRclass;
497 		opt = hdr->tpdu_CRoptions;
498 
499 		WHILE_OPTIONS(P, hdr, 1 ) /* { */
500 
501 			switch( vbptr(P)->tpv_code ) {
502 
503 			case	TPP_tpdu_size:
504 				vb_getval(P, u_char, dusize);
505 				IFDEBUG(D_TPINPUT)
506 					printf("CR dusize 0x%x\n", dusize);
507 				ENDDEBUG
508 				/* COS tests: NBS IA (Dec. 1987) Sec. 4.5.2.1 */
509 				if (dusize < TP_MIN_TPDUSIZE || dusize > TP_MAX_TPDUSIZE)
510 						dusize = TP_DFL_TPDUSIZE;
511 				break;
512 			case	TPP_addl_opt:
513 				vb_getval(P, u_char, addlopt);
514 				break;
515 			case	TPP_calling_sufx:
516 				/* could use vb_getval, but we want to save the loc & len
517 				 * for later use
518 				 */
519 				fsufxloc = (caddr_t) &vbptr(P)->tpv_val;
520 				fsufxlen = vbptr(P)->tpv_len;
521 				IFDEBUG(D_TPINPUT)
522 					printf("CR fsufx:");
523 					{ register int j;
524 						for(j=0; j<fsufxlen; j++ ) {
525 							printf(" 0x%x. ", *((caddr_t)(fsufxloc+j)) );
526 						}
527 						printf("\n");
528 					}
529 				ENDDEBUG
530 				break;
531 			case	TPP_called_sufx:
532 				/* could use vb_getval, but we want to save the loc & len
533 				 * for later use
534 				 */
535 				lsufxloc = (caddr_t) &vbptr(P)->tpv_val;
536 				lsufxlen = vbptr(P)->tpv_len;
537 				IFDEBUG(D_TPINPUT)
538 					printf("CR lsufx:");
539 					{ register int j;
540 						for(j=0; j<lsufxlen; j++ ) {
541 							printf(" 0x%x. ", *((u_char *)(lsufxloc+j)) );
542 						}
543 						printf("\n");
544 					}
545 				ENDDEBUG
546 				break;
547 
548 #ifdef TP_PERF_MEAS
549 			case	TPP_perf_meas:
550 				vb_getval(P, u_char, perf_meas);
551 				break;
552 #endif TP_PERF_MEAS
553 
554 			case	TPP_vers:
555 				/* not in class 0; 1 octet; in CR_TPDU only */
556 				/* COS tests says if version wrong, use default version!?XXX */
557 				CHECK( (vbval(P, u_char) != TP_VERSION ),
558 					E_TP_INV_PVAL, ts_inv_pval, setversion,
559 					(1 + (caddr_t)&vbptr(P)->tpv_val - (caddr_t)hdr) );
560 			setversion:
561 				version = vbval(P, u_char);
562 				break;
563 			case	TPP_acktime:
564 				vb_getval(P, u_short, acktime);
565 				acktime = ntohs(acktime);
566 				acktime = acktime/500; /* convert to slowtimo ticks */
567 				if((short)acktime <=0 )
568 					acktime = 2; /* don't allow a bad peer to screw us up */
569 				IFDEBUG(D_TPINPUT)
570 					printf("CR acktime 0x%x\n", acktime);
571 				ENDDEBUG
572 				break;
573 
574 			case	TPP_alt_class:
575 				{
576 					u_char *aclass = 0;
577 					register int i;
578 					static u_char bad_alt_classes[5] =
579 						{ ~0, ~3, ~5, ~0xf, ~0x1f};
580 
581 					aclass =
582 						(u_char *) &(((struct tp_vbp *)P)->tpv_val);
583 					for (i = ((struct tp_vbp *)P)->tpv_len; i>0; i--) {
584 						alt_classes |= (1<<((*aclass++)>>4));
585 					}
586 					CHECK( (bad_alt_classes[hdr->tpdu_CRclass] & alt_classes),
587 						E_TP_INV_PVAL, ts_inv_aclass, respond,
588 						((caddr_t)aclass) - (caddr_t)hdr);
589 					IFDEBUG(D_TPINPUT)
590 						printf("alt_classes 0x%x\n", alt_classes);
591 					ENDDEBUG
592 				}
593 				break;
594 
595 			case	TPP_security:
596 			case	TPP_residER:
597 			case	TPP_priority:
598 			case	TPP_transdelay:
599 			case	TPP_throughput:
600 			case	TPP_addl_info:
601 			case	TPP_subseq:
602 			default:
603 				IFDEBUG(D_TPINPUT)
604 					printf("param ignored CR_TPDU code= 0x%x\n",
605 						 vbptr(P)->tpv_code);
606 				ENDDEBUG
607 				IncStat(ts_param_ignored);
608 				break;
609 
610 			case	TPP_checksum:
611 				IFDEBUG(D_TPINPUT)
612 					printf("CR before cksum\n");
613 				ENDDEBUG
614 
615 				CHECK( iso_check_csum(m, tpdu_len),
616 					E_TP_INV_PVAL, ts_bad_csum, discard, 0)
617 
618 				IFDEBUG(D_TPINPUT)
619 					printf("CR before cksum\n");
620 				ENDDEBUG
621 				break;
622 			}
623 
624 		/* } */ END_WHILE_OPTIONS(P)
625 
626 		if (lsufxlen == 0) {
627 			/* can't look for a tpcb w/o any called sufx */
628 			error =  E_TP_LENGTH_INVAL;
629 			IncStat(ts_inv_sufx);
630 			goto respond;
631 		} else {
632 			register struct tp_pcb *t;
633 
634 			for (t = tp_intercepts; t ; t = t->tp_nextlisten) {
635 				if (laddr->sa_family != t->tp_nlproto->nlp_afamily)
636 					continue;
637 				if ((*t->tp_nlproto->nlp_cmpnetaddr)(
638 						t->tp_npcb, laddr, TP_LOCAL)) {
639 							intercepted = 1;
640 							goto check_duplicate_cr;
641 				}
642 			}
643 			for (t = tp_listeners; t ; t = t->tp_nextlisten)
644 				if (bcmp(lsufxloc, t->tp_lsuffix, lsufxlen) == 0 &&
645 					laddr->sa_family == t->tp_nlproto->nlp_afamily)
646 						break;
647 			CHECK(t == 0, E_TP_NO_SESSION, ts_inv_sufx, respond,
648 				(1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr))
649 				/* _tpduf is the fixed part; add 2 to get the dref bits of
650 				 * the fixed part (can't take the address of a bit field)
651 				 */
652 			IFDEBUG(D_TPINPUT)
653 				printf("checking if dup CR\n");
654 			ENDDEBUG
655 		check_duplicate_cr:
656 			tpcb = t;
657 			for (t = tpcb->tp_next; t != tpcb; t = t->tp_next) {
658 				if (sref != t->tp_fref)
659 					continue;
660 				if ((*tpcb->tp_nlproto->nlp_cmpnetaddr)(
661 						t->tp_npcb, faddr, TP_FOREIGN)) {
662 					IFDEBUG(D_TPINPUT)
663 						printf("duplicate CR discarded\n");
664 					ENDDEBUG
665 					goto discard;
666 				}
667 			}
668 			IFTRACE(D_TPINPUT)
669 				tptrace(TPPTmisc, "tp_input: tpcb *lsufxloc tpstate",
670 					tpcb, *lsufxloc, tpcb->tp_state, 0);
671 			ENDTRACE
672 		}
673 
674 		/*
675 		 * WE HAVE A TPCB
676 		 * already know that the classes in the CR match at least
677 		 * one class implemented, but we don't know yet if they
678 		 * include any classes permitted by this server.
679 		 */
680 
681 		IFDEBUG(D_TPINPUT)
682 			printf("HAVE A TPCB 1: 0x%x\n", tpcb);
683 		ENDDEBUG
684 		IFDEBUG(D_CONN)
685 			printf(
686 "CR: bef CHKS: flags 0x%x class_to_use 0x%x alt 0x%x opt 0x%x tp_class 0x%x\n",
687 				tpcb->tp_flags, class_to_use, alt_classes, opt, tpcb->tp_class);
688 		ENDDEBUG
689 		/* tpcb->tp_class doesn't include any classes not implemented  */
690 		class_to_use = (preferred_class & tpcb->tp_class);
691 		if( (class_to_use = preferred_class & tpcb->tp_class) == 0 )
692 			class_to_use = alt_classes & tpcb->tp_class;
693 
694 		class_to_use = 1 << tp_mask_to_num(class_to_use);
695 
696 		{
697 			tpp = tpcb->_tp_param;
698 			tpp.p_class = class_to_use;
699 			tpp.p_tpdusize = dusize;
700 			tpp.p_xtd_format = (opt & TPO_XTD_FMT) == TPO_XTD_FMT;
701 			tpp.p_xpd_service = (addlopt & TPAO_USE_TXPD) == TPAO_USE_TXPD;
702 			tpp.p_use_checksum = (tpp.p_class == TP_CLASS_0)?0:
703 				(addlopt & TPAO_NO_CSUM) == 0;
704 			tpp.p_version = version;
705 #ifdef notdef
706 			tpp.p_use_efc = (opt & TPO_USE_EFC) == TPO_USE_EFC;
707 			tpp.p_use_nxpd = (addlopt & TPAO_USE_NXPD) == TPAO_USE_NXPD;
708 			tpp.p_use_rcc = (addlopt & TPAO_USE_RCC) == TPAO_USE_RCC;
709 #endif notdef
710 
711 		CHECK(
712 			tp_consistency(tpcb, 0 /* not force or strict */, &tpp) != 0,
713 			E_TP_NEGOT_FAILED, ts_negotfailed, respond,
714 			(1 + 2 + (caddr_t)&hdr->_tpdufr.CRCC - (caddr_t)hdr)
715 				/* ^ more or less the location of class */
716 			)
717 		}
718 		IFTRACE(D_CONN)
719 			tptrace(TPPTmisc,
720 				"after 1 consist class_to_use class, out, tpconsout",
721 				class_to_use,
722 				tpcb->tp_class, dgout_routine, tpcons_output
723 				);
724 		ENDTRACE
725 		CHECK(
726 			((class_to_use == TP_CLASS_0)&&(dgout_routine != tpcons_output)),
727 			E_TP_NEGOT_FAILED, ts_negotfailed, respond,
728 			(1 + 2 + (caddr_t)&hdr->_tpdufr.CRCC - (caddr_t)hdr)
729 				/* ^ more or less the location of class */
730 			)
731 		IFDEBUG(D_CONN)
732 			printf("CR: after CRCCCHECKS: tpcb 0x%x, flags 0x%x\n",
733 				tpcb, tpcb->tp_flags);
734 		ENDDEBUG
735 		takes_data = TRUE;
736 		e.ATTR(CR_TPDU).e_cdt  =  hdr->tpdu_CRcdt;
737 		e.ev_number = CR_TPDU;
738 
739 		so = tpcb->tp_sock;
740 		if (so->so_options & SO_ACCEPTCONN) {
741 			struct tp_pcb *parent_tpcb = tpcb;
742 			/*
743 			 * Create a socket, tpcb, ll pcb, etc.
744 			 * for this newborn connection, and fill in all the values.
745 			 */
746 			IFDEBUG(D_CONN)
747 				printf("abt to call tp_newsocket(0x%x, 0x%x, 0x%x, 0x%x)\n",
748 					so, laddr, faddr, cons_channel);
749 			ENDDEBUG
750 			if( (so =
751 				tp_newsocket(so, faddr, cons_channel,
752 					class_to_use,
753 					((tpcb->tp_netservice == IN_CLNS) ? IN_CLNS :
754 					(dgout_routine == tpcons_output)?ISO_CONS:ISO_CLNS))
755 					) == (struct socket *)0 ) {
756 				/* note - even if netservice is IN_CLNS, as far as
757 				 * the tp entity is concerned, the only differences
758 				 * are CO vs CL
759 				 */
760 				IFDEBUG(D_CONN)
761 					printf("tp_newsocket returns 0\n");
762 				ENDDEBUG
763 				goto discard;
764 			}
765 			tpcb = sototpcb(so);
766 			insque(tpcb, parent_tpcb);
767 
768 			/*
769 			 * Stash the addresses in the net level pcb
770 			 * kind of like a pcbconnect() but don't need
771 			 * or want all those checks.
772 			 */
773 			(tpcb->tp_nlproto->nlp_putnetaddr)(so->so_pcb, faddr, TP_FOREIGN);
774 			(tpcb->tp_nlproto->nlp_putnetaddr)(so->so_pcb, laddr, TP_LOCAL);
775 
776 			/* stash the f suffix in the new tpcb */
777 			bcopy(fsufxloc, tpcb->tp_fsuffix, fsufxlen);
778 			/* l suffix is already there, unless this is an intercept case */
779 			if (intercepted)
780 				bcopy(lsufxloc, tpcb->tp_lsuffix, lsufxlen);
781 			(tpcb->tp_nlproto->nlp_putsufx)
782 					(so->so_pcb, fsufxloc, fsufxlen, TP_FOREIGN);
783 			(tpcb->tp_nlproto->nlp_putsufx)
784 					(so->so_pcb, lsufxloc, lsufxlen, TP_LOCAL);
785 #ifdef TP_PERF_MEAS
786 			if( tpcb->tp_perf_on = perf_meas ) { /* assignment */
787 				/* ok, let's create an mbuf for stashing the
788 				 * statistics if one doesn't already exist
789 				 */
790 				(void) tp_setup_perf(tpcb);
791 			}
792 #endif TP_PERF_MEAS
793 			tpcb->tp_fref = sref;
794 
795 			/* We've already checked for consistency with the options
796 			 * set in tpp,  but we couldn't set them earlier because
797 			 * we didn't want to change options in the LISTENING tpcb.
798 			 * Now we set the options in the new socket's tpcb.
799 			 */
800 			(void) tp_consistency( tpcb, TP_FORCE, &tpp);
801 
802 			if(!tpcb->tp_use_checksum)
803 				IncStat(ts_csum_off);
804 			if(tpcb->tp_xpd_service)
805 				IncStat(ts_use_txpd);
806 			if(tpcb->tp_xtd_format)
807 				IncStat(ts_xtd_fmt);
808 
809 			/*
810 			 * Get the maximum transmission unit from the lower layer(s)
811 			 * so we can negotiate a reasonable max TPDU size.
812 			 */
813 			(tpcb->tp_nlproto->nlp_mtu)(so, so->so_pcb,
814 						&tpcb->tp_l_tpdusize, &tpcb->tp_tpdusize, 0);
815 			tpcb->tp_peer_acktime = acktime;
816 
817 			/*
818 			 * The following kludge is used to test retransmissions and
819 			 * timeout during connection establishment.
820 			 */
821 			IFDEBUG(D_ZDREF)
822 				IncStat(ts_zdebug);
823 				/*tpcb->tp_fref = 0;*/
824 			ENDDEBUG
825 		}
826 		IncStat(ts_CR_rcvd);
827 		if (!tpcb->tp_cebit_off) {
828 			tpcb->tp_win_recv = tp_start_win << 8;
829 			tpcb->tp_cong_sample.cs_size = 0;
830 			LOCAL_CREDIT(tpcb);
831 			CONG_INIT_SAMPLE(tpcb);
832 			CONG_UPDATE_SAMPLE(tpcb, ce_bit);
833 		}
834 		tpcb->tp_ackrcvd = 0;
835 	} else if ( dutype == ER_TPDU_type ) {
836 		/*
837 		 * ER TPDUs have to be recognized separately
838 		 * because they don't necessarily have a tpcb
839 		 * with them and we don't want err out looking for such
840 		 * a beast.
841 		 * We could put a bunch of little kludges in the
842 		 * next section of code so it would avoid references to tpcb
843 		 * if dutype == ER_TPDU_type but we don't want code for ERs to
844 		 * mess up code for data transfer.
845 		 */
846 		IncStat(ts_ER_rcvd);
847 		e.ev_number = ER_TPDU;
848 		e.ATTR(ER_TPDU).e_reason =  (u_char)hdr->tpdu_ERreason;
849 		takes_data = 1;
850 	} else {
851 		/* tpdu type is CC, XPD, XAK, GR, AK, DR, DC, or DT */
852 
853 		/* In the next 4 checks,
854 		 * _tpduf is the fixed part; add 2 to get the dref bits of
855 		 * the fixed part (can't take the address of a bit field)
856 		 */
857 #ifdef old_history
858 		if(cons_channel) {
859 #ifdef NARGOXTWENTYFIVE
860 			extern struct tp_pcb *cons_chan_to_tpcb();
861 
862 			tpcb = cons_chan_to_tpcb( cons_channel );
863 			/* Problem:  We may have a legit
864 			 * error situation yet we may or may not have
865 			 * a correspondence between the tpcb and the vc,
866 			 * e.g., TP4cr--> <no dice, respond w/ DR on vc>
867 			 *          <---  DR
868 			 * Now it's up to TP to look at the tpdu and do one of:
869 			 * confirm(dgm)(cr),  confirm(circuit)(cr), reject(cr), or
870 			 * nothing, if the circuit is already open (any other tpdu).
871 			 * Sigh.
872 			 */
873 
874 			/* I don't know about this error value */
875 			CHECK( (tpcb == (struct tp_pcb *)0) ,
876 				E_TP_NO_CR_ON_NC, ts_inv_dref, respond,
877 				(1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr))
878 #else
879 			printf("tp_input(): X25 NOT CONFIGURED!!\n");
880 #endif
881 		} else
882 			/* we've now made the error reporting thing check for
883 			multiple channels and not close out if more than
884 			one in use */
885 #endif old_history
886 		{
887 
888 			CHECK( ((int)dref <= 0 || dref >= N_TPREF) ,
889 				E_TP_MISM_REFS,ts_inv_dref, nonx_dref,
890 				(1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr))
891 			CHECK( ((tpcb = tp_ref[dref].tpr_pcb ) == (struct tp_pcb *) 0 ),
892 				E_TP_MISM_REFS,ts_inv_dref, nonx_dref,
893 				(1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr))
894 			CHECK( (tpcb->tp_refp->tpr_state == REF_FREE),
895 				E_TP_MISM_REFS,ts_inv_dref, nonx_dref,
896 				(1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr))
897 		}
898 
899 		IFDEBUG(D_TPINPUT)
900 			printf("HAVE A TPCB 2: 0x%x\n", tpcb);
901 		ENDDEBUG
902 
903 		/* causes a DR to be sent for CC; ER for all else */
904 		CHECK( (tpcb->tp_refp->tpr_state == REF_FROZEN),
905 			(dutype == CC_TPDU_type?E_TP_NO_SESSION:E_TP_MISM_REFS),
906 			ts_inv_dref, respond,
907 			(1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr))
908 
909 		IFDEBUG(D_TPINPUT)
910 			printf("state of dref %d ok, tpcb 0x%x\n", dref,tpcb);
911 		ENDDEBUG
912 		/*
913 		 * At this point the state of the dref could be
914 		 * FROZEN: tpr_pcb == NULL,  has ( reference only) timers
915 		 *		   for example, DC may arrive after the close() has detached
916 		 *         the tpcb (e.g., if user turned off SO_LISTEN option)
917 		 * OPENING : a tpcb exists but no timers yet
918 		 * OPEN  : tpcb exists & timers are outstanding
919 		 */
920 
921         if (!tpcb->tp_cebit_off)
922             CONG_UPDATE_SAMPLE(tpcb, ce_bit);
923 
924 		dusize = tpcb->tp_tpdusize;
925 
926 		dutype = hdr->tpdu_type << 8; /* for the switch below */
927 
928 		WHILE_OPTIONS(P, hdr, tpcb->tp_xtd_format) /* { */
929 
930 #define caseof(x,y) case (((x)<<8)+(y))
931 		switch( dutype | vbptr(P)->tpv_code ) {
932 
933 			caseof( CC_TPDU_type, TPP_addl_opt ):
934 					/* not in class 0; 1 octet */
935 					vb_getval(P, u_char, addlopt);
936 					break;
937 			caseof( CC_TPDU_type, TPP_tpdu_size ):
938 				{
939 					u_char odusize = dusize;
940 					vb_getval(P, u_char, dusize);
941 					CHECK( (dusize < TP_MIN_TPDUSIZE ||
942 							dusize > TP_MAX_TPDUSIZE || dusize > odusize),
943 						E_TP_INV_PVAL, ts_inv_pval, respond,
944 						(1 + (caddr_t)&vbptr(P)->tpv_val - (caddr_t)hdr) )
945 					IFDEBUG(D_TPINPUT)
946 						printf("CC dusize 0x%x\n", dusize);
947 					ENDDEBUG
948 				}
949 					break;
950 			caseof( CC_TPDU_type, TPP_calling_sufx):
951 					IFDEBUG(D_TPINPUT)
952 						printf("CC calling (local) sufxlen 0x%x\n", lsufxlen);
953 					ENDDEBUG
954 					lsufxloc = (caddr_t) &vbptr(P)->tpv_val;
955 					lsufxlen = vbptr(P)->tpv_len;
956 					break;
957 			caseof(	CC_TPDU_type, TPP_acktime ):
958 					/* class 4 only, 2 octets */
959 					vb_getval(P, u_short, acktime);
960 					acktime = ntohs(acktime);
961 					acktime = acktime/500; /* convert to slowtimo ticks */
962 					if( (short)acktime <=0 )
963 						acktime = 2;
964 					break;
965 			caseof(	CC_TPDU_type, TPP_called_sufx):
966 					fsufxloc = (caddr_t) &vbptr(P)->tpv_val;
967 					fsufxlen = vbptr(P)->tpv_len;
968 					IFDEBUG(D_TPINPUT)
969 						printf("CC called (foreign) sufx len %d\n", fsufxlen);
970 					ENDDEBUG
971 					break;
972 
973 			caseof( CC_TPDU_type,	TPP_checksum):
974 			caseof( DR_TPDU_type,	TPP_checksum):
975 			caseof( DT_TPDU_type,	TPP_checksum):
976 			caseof( XPD_TPDU_type,	TPP_checksum):
977 					if( tpcb->tp_use_checksum )  {
978 						CHECK( iso_check_csum(m, tpdu_len),
979 							E_TP_INV_PVAL, ts_bad_csum, discard, 0)
980 					}
981 					break;
982 
983 			/*  this is different from the above because in the context
984 			 *  of concat/ sep tpdu_len might not be the same as hdr len
985 			 */
986 			caseof( AK_TPDU_type,	TPP_checksum):
987 			caseof( XAK_TPDU_type,	TPP_checksum):
988 			caseof( DC_TPDU_type,	TPP_checksum):
989 					if( tpcb->tp_use_checksum )  {
990 						CHECK( iso_check_csum(m, (int)hdr->tpdu_li + 1),
991 							E_TP_INV_PVAL, ts_bad_csum, discard, 0)
992 					}
993 					break;
994 #ifdef notdef
995 			caseof( DR_TPDU_type, TPP_addl_info ):
996 				/* ignore - its length and meaning are
997 				 * user defined and there's no way
998 				 * to pass this info to the user anyway
999 				 */
1000 				break;
1001 #endif notdef
1002 
1003 			caseof( AK_TPDU_type, TPP_subseq ):
1004 				/* used after reduction of window */
1005 				vb_getval(P, u_short, subseq);
1006 				subseq = ntohs(subseq);
1007 				IFDEBUG(D_ACKRECV)
1008 					printf("AK Subsequence # 0x%x\n", subseq);
1009 				ENDDEBUG
1010 				break;
1011 
1012 			caseof( AK_TPDU_type, TPP_flow_cntl_conf ):
1013 				{
1014 					u_int 	ylwe;
1015 					u_short ysubseq, ycredit;
1016 
1017 					fcc_present = TRUE;
1018 					vb_getval(P, u_int,	 	ylwe);
1019 					vb_getval(P, u_short, 	ysubseq);
1020 					vb_getval(P, u_short, 	ycredit);
1021 					ylwe = ntohl(ylwe);
1022 					ysubseq = ntohs(ysubseq);
1023 					ycredit = ntohs(ycredit);
1024 					IFDEBUG(D_ACKRECV)
1025 						printf("AK FCC lwe 0x%x, subseq 0x%x, cdt 0x%x\n",
1026 							ylwe, ysubseq, ycredit);
1027 					ENDDEBUG
1028 				}
1029 				break;
1030 
1031 			default:
1032 				IFDEBUG(D_TPINPUT)
1033 					printf("param ignored dutype 0x%x, code  0x%x\n",
1034 						dutype, vbptr(P)->tpv_code);
1035 				ENDDEBUG
1036 				IFTRACE(D_TPINPUT)
1037 					tptrace(TPPTmisc, "param ignored dutype code ",
1038 						dutype, vbptr(P)->tpv_code ,0,0);
1039 				ENDTRACE
1040 				IncStat(ts_param_ignored);
1041 				break;
1042 #undef caseof
1043 		}
1044 		/* } */ END_WHILE_OPTIONS(P)
1045 
1046 		/* NOTE: the variable dutype has been shifted left! */
1047 
1048 		switch( hdr->tpdu_type ) {
1049 		case CC_TPDU_type:
1050 			/* If CC comes back with an unacceptable class
1051 			 * respond with a DR or ER
1052 			 */
1053 
1054 			opt = hdr->tpdu_CCoptions; /* 1 byte */
1055 
1056 			{
1057 				tpp = tpcb->_tp_param;
1058 				tpp.p_class = (1<<hdr->tpdu_CCclass);
1059 				tpp.p_tpdusize = dusize;
1060 				tpp.p_dont_change_params = 0;
1061 				tpp.p_xtd_format = (opt & TPO_XTD_FMT) == TPO_XTD_FMT;
1062 				tpp.p_xpd_service = (addlopt & TPAO_USE_TXPD) == TPAO_USE_TXPD;
1063 				tpp.p_use_checksum = (addlopt & TPAO_NO_CSUM) == 0;
1064 #ifdef notdef
1065 				tpp.p_use_efc = (opt & TPO_USE_EFC) == TPO_USE_EFC;
1066 				tpp.p_use_nxpd = (addlopt & TPAO_USE_NXPD) == TPAO_USE_NXPD;
1067 				tpp.p_use_rcc = (addlopt & TPAO_USE_RCC) == TPAO_USE_RCC;
1068 #endif notdef
1069 
1070 			CHECK(
1071 				tp_consistency(tpcb, TP_FORCE, &tpp) != 0,
1072 				E_TP_NEGOT_FAILED, ts_negotfailed, respond,
1073 				(1 + 2 + (caddr_t)&hdr->_tpdufr.CRCC - (caddr_t)hdr)
1074 					/* ^ more or less the location of class */
1075 				)
1076 			IFTRACE(D_CONN)
1077 				tptrace(TPPTmisc,
1078 					"after 1 consist class, out, tpconsout",
1079 					tpcb->tp_class, dgout_routine, tpcons_output, 0
1080 					);
1081 			ENDTRACE
1082 			CHECK(
1083 				((class_to_use == TP_CLASS_0)&&
1084 					(dgout_routine != tpcons_output)),
1085 				E_TP_NEGOT_FAILED, ts_negotfailed, respond,
1086 				(1 + 2 + (caddr_t)&hdr->_tpdufr.CRCC - (caddr_t)hdr)
1087 					/* ^ more or less the location of class */
1088 				)
1089 #ifdef TPCONS
1090 				if (tpcb->tp_netservice == ISO_CONS &&
1091 					class_to_use == TP_CLASS_0) {
1092 					struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb;
1093 					struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
1094 					lcp->lcd_flags &= ~X25_DG_CIRCUIT;
1095 				}
1096 #endif
1097 			}
1098 			if( ! tpcb->tp_use_checksum)
1099 				IncStat(ts_csum_off);
1100 			if(tpcb->tp_xpd_service)
1101 				IncStat(ts_use_txpd);
1102 			if(tpcb->tp_xtd_format)
1103 				IncStat(ts_xtd_fmt);
1104 
1105 			IFTRACE(D_CONN)
1106 				tptrace(TPPTmisc, "after CC class flags dusize CCclass",
1107 					tpcb->tp_class, tpcb->tp_flags, tpcb->tp_tpdusize,
1108 					hdr->tpdu_CCclass);
1109 			ENDTRACE
1110 
1111 			/*
1112 			 * Get the maximum transmission unit from the lower layer(s)
1113 			 * so we can decide how large a TPDU size to negotiate.
1114 			 * It would be nice if the arguments to this
1115 			 * were more reasonable.
1116 			 */
1117 			(tpcb->tp_nlproto->nlp_mtu)(tpcb->tp_sock, tpcb->tp_sock->so_pcb,
1118 						&tpcb->tp_l_tpdusize, &tpcb->tp_tpdusize, 0);
1119 
1120 
1121 			/* if called or calling suffices appeared on the CC,
1122 			 * they'd better jive with what's in the pcb
1123 			 */
1124 			if( fsufxlen ) {
1125 				CHECK( ((tpcb->tp_fsuffixlen != fsufxlen) ||
1126 					bcmp(fsufxloc, tpcb->tp_fsuffix, fsufxlen)),
1127 					E_TP_INV_PVAL,ts_inv_sufx, respond,
1128 					(1+fsufxloc - (caddr_t)hdr))
1129 			}
1130 			if( lsufxlen ) {
1131 				CHECK( ((tpcb->tp_lsuffixlen != lsufxlen) ||
1132 					bcmp(lsufxloc, tpcb->tp_lsuffix, lsufxlen)),
1133 					E_TP_INV_PVAL,ts_inv_sufx, respond,
1134 					(1+lsufxloc - (caddr_t)hdr))
1135 			}
1136 
1137 			e.ATTR(CC_TPDU).e_sref =  sref;
1138 			e.ATTR(CC_TPDU).e_cdt  =  hdr->tpdu_CCcdt;
1139 			takes_data = TRUE;
1140 			e.ev_number = CC_TPDU;
1141 			IncStat(ts_CC_rcvd);
1142 			break;
1143 
1144 		case DC_TPDU_type:
1145 			if (sref != tpcb->tp_fref)
1146 				printf("INPUT: inv sufx DCsref 0x%x, tp_fref 0x%x\n",
1147 					sref, tpcb->tp_fref);
1148 
1149 			CHECK( (sref != tpcb->tp_fref),
1150 				E_TP_MISM_REFS, ts_inv_sufx, discard,
1151 				(1 + (caddr_t)&hdr->tpdu_DCsref - (caddr_t)hdr))
1152 
1153 			e.ev_number = DC_TPDU;
1154 			IncStat(ts_DC_rcvd);
1155 			break;
1156 
1157 		case DR_TPDU_type:
1158 			IFTRACE(D_TPINPUT)
1159 				tptrace(TPPTmisc, "DR recvd", hdr->tpdu_DRreason, 0, 0, 0);
1160 			ENDTRACE
1161 			if (sref != tpcb->tp_fref) {
1162 				printf("INPUT: inv sufx DRsref 0x%x tp_fref 0x%x\n",
1163 					sref, tpcb->tp_fref);
1164 			}
1165 
1166 			CHECK( (sref != 0 && sref != tpcb->tp_fref &&
1167 					tpcb->tp_state != TP_CRSENT),
1168 				(TP_ERROR_SNDC | E_TP_MISM_REFS),ts_inv_sufx, respond,
1169 				(1 + (caddr_t)&hdr->tpdu_DRsref - (caddr_t)hdr))
1170 
1171 			e.ATTR(DR_TPDU).e_reason = hdr->tpdu_DRreason;
1172 			e.ATTR(DR_TPDU).e_sref =  (u_short)sref;
1173 			takes_data = TRUE;
1174 			e.ev_number = DR_TPDU;
1175 			IncStat(ts_DR_rcvd);
1176 			break;
1177 
1178 		case ER_TPDU_type:
1179 			IFTRACE(D_TPINPUT)
1180 				tptrace(TPPTmisc, "ER recvd", hdr->tpdu_ERreason,0,0,0);
1181 			ENDTRACE
1182 			e.ev_number = ER_TPDU;
1183 			e.ATTR(ER_TPDU).e_reason = hdr->tpdu_ERreason;
1184 			IncStat(ts_ER_rcvd);
1185 			break;
1186 
1187 		case AK_TPDU_type:
1188 
1189 			e.ATTR(AK_TPDU).e_subseq = subseq;
1190 			e.ATTR(AK_TPDU).e_fcc_present = fcc_present;
1191 
1192 			if (tpcb->tp_xtd_format) {
1193 #ifdef BYTE_ORDER
1194 				union seq_type seqeotX;
1195 
1196 				seqeotX.s_seqeot = ntohl(hdr->tpdu_seqeotX);
1197 				e.ATTR(AK_TPDU).e_seq = seqeotX.s_seq;
1198 				e.ATTR(AK_TPDU).e_cdt = ntohs(hdr->tpdu_AKcdtX);
1199 #else
1200 				e.ATTR(AK_TPDU).e_cdt = hdr->tpdu_AKcdtX;
1201 				e.ATTR(AK_TPDU).e_seq = hdr->tpdu_AKseqX;
1202 #endif BYTE_ORDER
1203 			} else {
1204 				e.ATTR(AK_TPDU).e_cdt = hdr->tpdu_AKcdt;
1205 				e.ATTR(AK_TPDU).e_seq = hdr->tpdu_AKseq;
1206 			}
1207 			IFTRACE(D_TPINPUT)
1208 				tptrace(TPPTmisc, "AK recvd seq cdt subseq fcc_pres",
1209 					e.ATTR(AK_TPDU).e_seq, e.ATTR(AK_TPDU).e_cdt,
1210 					subseq, fcc_present);
1211 			ENDTRACE
1212 
1213 			e.ev_number = AK_TPDU;
1214 			IncStat(ts_AK_rcvd);
1215 			IncPStat(tpcb, tps_AK_rcvd);
1216 			break;
1217 
1218 		case XAK_TPDU_type:
1219 			if (tpcb->tp_xtd_format) {
1220 #ifdef BYTE_ORDER
1221 				union seq_type seqeotX;
1222 
1223 				seqeotX.s_seqeot = ntohl(hdr->tpdu_seqeotX);
1224 				e.ATTR(XAK_TPDU).e_seq = seqeotX.s_seq;
1225 #else
1226 				e.ATTR(XAK_TPDU).e_seq = hdr->tpdu_XAKseqX;
1227 #endif BYTE_ORDER
1228 			} else {
1229 				e.ATTR(XAK_TPDU).e_seq = hdr->tpdu_XAKseq;
1230 			}
1231 			e.ev_number = XAK_TPDU;
1232 			IncStat(ts_XAK_rcvd);
1233 			IncPStat(tpcb, tps_XAK_rcvd);
1234 			break;
1235 
1236 		case XPD_TPDU_type:
1237 			if (tpcb->tp_xtd_format) {
1238 #ifdef BYTE_ORDER
1239 				union seq_type seqeotX;
1240 
1241 				seqeotX.s_seqeot = ntohl(hdr->tpdu_seqeotX);
1242 				e.ATTR(XPD_TPDU).e_seq = seqeotX.s_seq;
1243 #else
1244 				e.ATTR(XPD_TPDU).e_seq = hdr->tpdu_XPDseqX;
1245 #endif BYTE_ORDER
1246 			} else {
1247 				e.ATTR(XPD_TPDU).e_seq = hdr->tpdu_XPDseq;
1248 			}
1249 			takes_data = TRUE;
1250 			e.ev_number = XPD_TPDU;
1251 			IncStat(ts_XPD_rcvd);
1252 			IncPStat(tpcb, tps_XPD_rcvd);
1253 			break;
1254 
1255 		case DT_TPDU_type:
1256 			{ /* the y option will cause occasional packets to be dropped.
1257 			   * A little crude but it works.
1258 			   */
1259 
1260 				IFDEBUG(D_DROP)
1261 					if(time.tv_usec & 0x4 && hdr->tpdu_DTseq & 0x1) {
1262 						IncStat(ts_ydebug);
1263 						goto discard;
1264 					}
1265 				ENDDEBUG
1266 			}
1267 			if (tpcb->tp_class == TP_CLASS_0) {
1268 				e.ATTR(DT_TPDU).e_seq = 0; /* actually don't care */
1269 				e.ATTR(DT_TPDU).e_eot = (((struct tp0du *)hdr)->tp0du_eot);
1270 			} else if (tpcb->tp_xtd_format) {
1271 #ifdef BYTE_ORDER
1272 				union seq_type seqeotX;
1273 
1274 				seqeotX.s_seqeot = ntohl(hdr->tpdu_seqeotX);
1275 				e.ATTR(DT_TPDU).e_seq = seqeotX.s_seq;
1276 				e.ATTR(DT_TPDU).e_eot = seqeotX.s_eot;
1277 #else
1278 				e.ATTR(DT_TPDU).e_seq = hdr->tpdu_DTseqX;
1279 				e.ATTR(DT_TPDU).e_eot = hdr->tpdu_DTeotX;
1280 #endif BYTE_ORDER
1281 			} else {
1282 				e.ATTR(DT_TPDU).e_seq = hdr->tpdu_DTseq;
1283 				e.ATTR(DT_TPDU).e_eot = hdr->tpdu_DTeot;
1284 			}
1285 			if(e.ATTR(DT_TPDU).e_eot)
1286 				IncStat(ts_eot_input);
1287 			takes_data = TRUE;
1288 			e.ev_number = DT_TPDU;
1289 			IncStat(ts_DT_rcvd);
1290 			IncPStat(tpcb, tps_DT_rcvd);
1291 			break;
1292 
1293 		case GR_TPDU_type:
1294 			tp_indicate(T_DISCONNECT, tpcb, ECONNABORTED);
1295 			/* drop through */
1296 		default:
1297 			/* this should NEVER happen because there is a
1298 			 * check for dutype well above here
1299 			 */
1300 			error = E_TP_INV_TPDU; /* causes an ER  */
1301 			IFDEBUG(D_TPINPUT)
1302 				printf("INVALID dutype 0x%x\n", hdr->tpdu_type);
1303 			ENDDEBUG
1304 			IncStat(ts_inv_dutype);
1305 			goto respond;
1306 		}
1307 	}
1308 	/* peel off the tp header;
1309 	 * remember that the du_li doesn't count itself.
1310 	 * This may leave us w/ an empty mbuf at the front of a chain.
1311 	 * We can't just throw away the empty mbuf because hdr still points
1312 	 * into the mbuf's data area and we're still using hdr (the tpdu header)
1313 	 */
1314 	m->m_len -= ((int)hdr->tpdu_li + 1);
1315 	m->m_data += ((int)hdr->tpdu_li + 1);
1316 
1317 	if (takes_data) {
1318 		int max = tpdu_info[ hdr->tpdu_type ] [TP_MAX_DATA_INDEX];
1319 		int datalen = tpdu_len - hdr->tpdu_li - 1, mbtype = MT_DATA;
1320 		struct cmsghdr c_hdr;
1321 		struct mbuf *n;
1322 
1323 		CHECK( (max && datalen > max), E_TP_LENGTH_INVAL,
1324 		        ts_inv_length, respond, (max + hdr->tpdu_li + 1) );
1325 		switch( hdr->tpdu_type ) {
1326 
1327 		case CR_TPDU_type:
1328 			c_hdr.cmsg_type = TPOPT_CONN_DATA;
1329 			goto make_control_msg;
1330 
1331 		case CC_TPDU_type:
1332 			c_hdr.cmsg_type = TPOPT_CFRM_DATA;
1333 			goto make_control_msg;
1334 
1335 		case DR_TPDU_type:
1336 			c_hdr.cmsg_type = TPOPT_DISC_DATA;
1337 		make_control_msg:
1338 			c_hdr.cmsg_level = SOL_TRANSPORT;
1339 			mbtype = MT_CONTROL;
1340 			MGET(n, M_DONTWAIT, MT_DATA);
1341 			if (n) {
1342 				datalen += sizeof(c_hdr);
1343 				n->m_len = sizeof(c_hdr);
1344 				c_hdr.cmsg_len = datalen;
1345 				*mtod(n, struct cmsghdr *) = c_hdr;
1346 				n->m_next = m;
1347 				m = n;
1348 			} else {m_freem(m); m = 0; goto invoke;}
1349 			/* FALLTHROUGH */
1350 
1351 		case XPD_TPDU_type:
1352 			if (mbtype != MT_CONTROL)
1353 				mbtype = MT_OOBDATA;
1354 			m->m_flags |= M_EOR;
1355 			/* FALLTHROUGH */
1356 
1357 		case DT_TPDU_type:
1358 			for (n = m; n; n = n->m_next) {
1359 				MCHTYPE(n, mbtype);
1360 			}
1361 		invoke:
1362 			e.ATTR(DT_TPDU).e_datalen = datalen;
1363 			e.ATTR(DT_TPDU).e_data =  m;
1364 			break;
1365 
1366 		default:
1367 			printf(
1368 				"ERROR in tp_input! hdr->tpdu_type 0x%x takes_data 0x%x m 0x%x\n",
1369 				hdr->tpdu_type, takes_data, m);
1370 			break;
1371 		}
1372 		/* prevent m_freem() after tp_driver() from throwing it all away */
1373 		m = MNULL;
1374 	}
1375 
1376 	IncStat(ts_tpdu_rcvd);
1377 
1378 	IFDEBUG(D_TPINPUT)
1379 		printf( "tp_input: before driver, state 0x%x event 0x%x m 0x%x",
1380 			tpcb->tp_state, e.ev_number, m );
1381 		printf(" e.e_data 0x%x\n", e.ATTR(DT_TPDU).e_data);
1382 		printf("takes_data 0x%x m_len 0x%x, tpdu_len 0x%x\n",
1383 			takes_data, (m==MNULL)?0:m->m_len,  tpdu_len);
1384 	ENDDEBUG
1385 
1386 	error = tp_driver(tpcb, &e);
1387 
1388 	ASSERT(tpcb != (struct tp_pcb *)0);
1389 	ASSERT(tpcb->tp_sock != (struct socket *)0);
1390 	if( tpcb->tp_sock->so_error == 0 )
1391 		tpcb->tp_sock->so_error = error;
1392 
1393 	/* Kludge to keep the state tables under control (adding
1394 	 * data on connect & disconnect & freeing the mbuf containing
1395 	 * the data would have exploded the tables and made a big mess ).
1396 	 */
1397 	switch(e.ev_number) {
1398 		case CC_TPDU:
1399 		case DR_TPDU:
1400 		case CR_TPDU:
1401 			m = e.ATTR(CC_TPDU).e_data; /* same field for all three dutypes */
1402 			IFDEBUG(D_TPINPUT)
1403 				printf("after driver, restoring m to 0x%x, takes_data 0x%x\n",
1404 				m, takes_data);
1405 			ENDDEBUG
1406 			break;
1407 		default:
1408 			break;
1409 	}
1410 	/* Concatenated sequences are terminated by any tpdu that
1411 	 * carries data: CR, CC, DT, XPD, DR.
1412 	 * All other tpdu types may be concatenated: AK, XAK, DC, ER.
1413 	 */
1414 
1415 separate:
1416 	if ( takes_data == 0 )  {
1417 		ASSERT( m != MNULL );
1418 		/*
1419 		 * we already peeled off the prev. tp header so
1420 		 * we can just pull up some more and repeat
1421 		 */
1422 
1423 		if( m = tp_inputprep(m) ) {
1424 		IFDEBUG(D_TPINPUT)
1425 			hdr = mtod(m, struct tpdu *);
1426 			printf("tp_input @ separate: hdr 0x%x size %d m 0x%x\n",
1427 			hdr, (int) hdr->tpdu_li + 1, m);
1428 			dump_mbuf(m, "tp_input after driver, at separate");
1429 		ENDDEBUG
1430 
1431 			IncStat(ts_concat_rcvd);
1432 			goto again;
1433 		}
1434 	}
1435 	if ( m != MNULL ) {
1436 		IFDEBUG(D_TPINPUT)
1437 			printf("tp_input : m_freem(0x%x)\n", m);
1438 		ENDDEBUG
1439 		m_freem(m);
1440 		IFDEBUG(D_TPINPUT)
1441 			printf("tp_input : after m_freem 0x%x\n", m);
1442 		ENDDEBUG
1443 	}
1444 	return (ProtoHook) tpcb;
1445 
1446 discard:
1447 	/* class 4: drop the tpdu */
1448 	/* class 2,0: Should drop the net connection, if you can figure out
1449 	 * to which connection it applies
1450 	 */
1451 	IFDEBUG(D_TPINPUT)
1452 		printf("tp_input DISCARD\n");
1453 	ENDDEBUG
1454 	IFTRACE(D_TPINPUT)
1455 		tptrace(TPPTmisc, "tp_input DISCARD m",  m,0,0,0);
1456 	ENDTRACE
1457 	m_freem(m);
1458 	IncStat(ts_recv_drop);
1459 	return (ProtoHook)0;
1460 
1461 nonx_dref:
1462 	switch (dutype) {
1463 	default:
1464 		goto discard;
1465 	case CC_TPDU_type:
1466 		/* error = E_TP_MISM_REFS; */
1467 		break;
1468 	case DR_TPDU_type:
1469 		error |= TP_ERROR_SNDC;
1470 	}
1471 respond:
1472 	IFDEBUG(D_TPINPUT)
1473 		printf("RESPOND: error 0x%x, errlen 0x%x\n", error, errlen);
1474 	ENDDEBUG
1475 	IFTRACE(D_TPINPUT)
1476 		tptrace(TPPTmisc, "tp_input RESPOND m error sref", m, error, sref, 0);
1477 	ENDTRACE
1478 	if (sref == 0)
1479 		goto discard;
1480 	(void) tp_error_emit(error, (u_long)sref, (struct sockaddr_iso *)faddr,
1481 				(struct sockaddr_iso *)laddr, m, errlen, tpcb,
1482 				(int)cons_channel, dgout_routine);
1483 	IFDEBUG(D_ERROR_EMIT)
1484 		printf("tp_input after error_emit\n");
1485 	ENDDEBUG
1486 
1487 #ifdef lint
1488 	printf("",sref,opt);
1489 #endif lint
1490 	IncStat(ts_recv_drop);
1491 	return (ProtoHook)0;
1492 }
1493 
1494 
1495 /*
1496  * NAME: tp_headersize()
1497  *
1498  * CALLED FROM:
1499  *  tp_emit() and tp_sbsend()
1500  *  TP needs to know the header size so it can figure out how
1501  *  much data to put in each tpdu.
1502  *
1503  * FUNCTION, ARGUMENTS, and RETURN VALUE:
1504  *  For a given connection, represented by (tpcb), and
1505  *  tpdu type (dutype), return the size of a tp header.
1506  *
1507  * RETURNS:	  the expected size of the heade in bytesr
1508  *
1509  * SIDE EFFECTS:
1510  *
1511  * NOTES:	 It would be nice if it got the network header size as well.
1512  */
1513 int
1514 tp_headersize(dutype, tpcb)
1515 	int 			dutype;
1516 	struct tp_pcb 	*tpcb;
1517 {
1518 	register int size = 0;
1519 
1520 	IFTRACE(D_CONN)
1521 		tptrace(TPPTmisc, "tp_headersize dutype class xtd_format",
1522 			dutype, tpcb->tp_class, tpcb->tp_xtd_format, 0);
1523 	ENDTRACE
1524 	if( !( (tpcb->tp_class == TP_CLASS_0) ||
1525 			(tpcb->tp_class == TP_CLASS_4) ||
1526 			(dutype == DR_TPDU_type) ||
1527 			(dutype == CR_TPDU_type) )) {
1528 				printf("tp_headersize:dutype 0x%x, class 0x%x",
1529 			dutype, tpcb->tp_class);
1530 	/* TODO: identify this and GET RID OF IT */
1531 	}
1532 	ASSERT( (tpcb->tp_class == TP_CLASS_0) ||
1533 			(tpcb->tp_class == TP_CLASS_4) ||
1534 			(dutype == DR_TPDU_type) ||
1535 			(dutype == CR_TPDU_type) );
1536 
1537 	if( tpcb->tp_class == TP_CLASS_0 ) {
1538 		size =  tpdu_info[ dutype ] [TP_LEN_CLASS_0_INDEX];
1539 	} else  {
1540 		size = tpdu_info[ dutype ] [tpcb->tp_xtd_format];
1541 	}
1542 	return size;
1543 	/* caller must get network level header size separately */
1544 }
1545