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