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