|
|
1.1 root 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) 7/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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.