|
|
1.1 ! root 1: /*- ! 2: * Copyright (c) 1991 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)tp_subr2.c 7.10 (Berkeley) 6/27/91 ! 34: */ ! 35: ! 36: /*********************************************************** ! 37: Copyright IBM Corporation 1987 ! 38: ! 39: All Rights Reserved ! 40: ! 41: Permission to use, copy, modify, and distribute this software and its ! 42: documentation for any purpose and without fee is hereby granted, ! 43: provided that the above copyright notice appear in all copies and that ! 44: both that copyright notice and this permission notice appear in ! 45: supporting documentation, and that the name of IBM not be ! 46: used in advertising or publicity pertaining to distribution of the ! 47: software without specific, written prior permission. ! 48: ! 49: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 50: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 51: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 52: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 53: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 54: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 55: SOFTWARE. ! 56: ! 57: ******************************************************************/ ! 58: ! 59: /* ! 60: * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison ! 61: */ ! 62: /* ! 63: * ARGO TP ! 64: * ! 65: * $Header: tp_subr2.c,v 5.5 88/11/18 17:28:55 nhall Exp $ ! 66: * $Source: /usr/argo/sys/netiso/RCS/tp_subr2.c,v $ ! 67: * ! 68: * Some auxiliary routines: ! 69: * tp_protocol_error: required by xebec- called when a combo of state, ! 70: * event, predicate isn't covered for by the transition file. ! 71: * tp_indicate: gives indications(signals) to the user process ! 72: * tp_getoptions: initializes variables that are affected by the options ! 73: * chosen. ! 74: */ ! 75: ! 76: /* this def'n is to cause the expansion of this macro in the ! 77: * routine tp_local_credit : ! 78: */ ! 79: #define LOCAL_CREDIT_EXPAND ! 80: ! 81: #include "param.h" ! 82: #include "systm.h" ! 83: #include "mbuf.h" ! 84: #include "socket.h" ! 85: #include "socketvar.h" ! 86: #include "domain.h" ! 87: #include "protosw.h" ! 88: #include "errno.h" ! 89: #include "types.h" ! 90: #include "time.h" ! 91: #include "kernel.h" ! 92: #undef MNULL ! 93: #include "argo_debug.h" ! 94: #include "tp_param.h" ! 95: #include "tp_ip.h" ! 96: #include "iso.h" ! 97: #include "iso_errno.h" ! 98: #include "iso_pcb.h" ! 99: #include "tp_timer.h" ! 100: #include "tp_stat.h" ! 101: #include "tp_tpdu.h" ! 102: #include "tp_pcb.h" ! 103: #include "tp_seq.h" ! 104: #include "tp_trace.h" ! 105: #include "tp_user.h" ! 106: #include "cons.h" ! 107: ! 108: #include "../net/if.h" ! 109: #ifdef TRUE ! 110: #undef FALSE ! 111: #undef TRUE ! 112: #endif ! 113: #include "../netccitt/x25.h" ! 114: #include "../netccitt/pk.h" ! 115: #include "../netccitt/pk_var.h" ! 116: ! 117: /* ! 118: * NAME: tp_local_credit() ! 119: * ! 120: * CALLED FROM: ! 121: * tp_emit(), tp_usrreq() ! 122: * ! 123: * FUNCTION and ARGUMENTS: ! 124: * Computes the local credit and stashes it in tpcb->tp_lcredit. ! 125: * It's a macro in the production system rather than a procdure. ! 126: * ! 127: * RETURNS: ! 128: * ! 129: * SIDE EFFECTS: ! 130: * ! 131: * NOTES: ! 132: * This doesn't actually get called in a production system - ! 133: * the macro gets expanded instead in place of calls to this proc. ! 134: * But for debugging, we call this and that allows us to add ! 135: * debugging messages easily here. ! 136: */ ! 137: void ! 138: tp_local_credit(tpcb) ! 139: struct tp_pcb *tpcb; ! 140: { ! 141: LOCAL_CREDIT(tpcb); ! 142: IFDEBUG(D_CREDIT) ! 143: printf("ref 0x%x lcdt 0x%x l_tpdusize 0x%x decbit 0x%x\n", ! 144: tpcb->tp_refp - tp_ref, ! 145: tpcb->tp_lcredit, ! 146: tpcb->tp_l_tpdusize, ! 147: tpcb->tp_decbit, ! 148: tpcb->tp_cong_win ! 149: ); ! 150: ENDDEBUG ! 151: IFTRACE(D_CREDIT) ! 152: tptraceTPCB(TPPTmisc, ! 153: "lcdt tpdusz \n", ! 154: tpcb->tp_lcredit, tpcb->tp_l_tpdusize, 0, 0); ! 155: ENDTRACE ! 156: } ! 157: ! 158: /* ! 159: * NAME: tp_protocol_error() ! 160: * ! 161: * CALLED FROM: ! 162: * tp_driver(), when it doesn't know what to do with ! 163: * a combo of event, state, predicate ! 164: * ! 165: * FUNCTION and ARGUMENTS: ! 166: * print error mesg ! 167: * ! 168: * RETURN VALUE: ! 169: * EIO - always ! 170: * ! 171: * SIDE EFFECTS: ! 172: * ! 173: * NOTES: ! 174: */ ! 175: int ! 176: tp_protocol_error(e,tpcb) ! 177: struct tp_event *e; ! 178: struct tp_pcb *tpcb; ! 179: { ! 180: printf("TP PROTOCOL ERROR! tpcb 0x%x event 0x%x, state 0x%x\n", ! 181: tpcb, e->ev_number, tpcb->tp_state); ! 182: IFTRACE(D_DRIVER) ! 183: tptraceTPCB(TPPTmisc, "PROTOCOL ERROR tpcb event state", ! 184: tpcb, e->ev_number, tpcb->tp_state, 0 ); ! 185: ENDTRACE ! 186: return EIO; /* for lack of anything better */ ! 187: } ! 188: ! 189: ! 190: /* Not used at the moment */ ! 191: ProtoHook ! 192: tp_drain() ! 193: { ! 194: return 0; ! 195: } ! 196: ! 197: ! 198: /* ! 199: * NAME: tp_indicate() ! 200: * ! 201: * CALLED FROM: ! 202: * tp.trans when XPD arrive, when a connection is being disconnected by ! 203: * the arrival of a DR or ER, and when a connection times out. ! 204: * ! 205: * FUNCTION and ARGUMENTS: ! 206: * (ind) is the type of indication : T_DISCONNECT, T_XPD ! 207: * (error) is an E* value that will be put in the socket structure ! 208: * to be passed along to the user later. ! 209: * Gives a SIGURG to the user process or group indicated by the socket ! 210: * attached to the tpcb. ! 211: * ! 212: * RETURNS: Rien ! 213: * ! 214: * SIDE EFFECTS: ! 215: * ! 216: * NOTES: ! 217: */ ! 218: void ! 219: tp_indicate(ind, tpcb, error) ! 220: int ind; ! 221: u_short error; ! 222: register struct tp_pcb *tpcb; ! 223: { ! 224: register struct socket *so = tpcb->tp_sock; ! 225: IFTRACE(D_INDICATION) ! 226: tptraceTPCB(TPPTindicate, ind, *(u_short *)(tpcb->tp_lsuffix), ! 227: *(u_short *)(tpcb->tp_fsuffix), error,so->so_pgid); ! 228: ENDTRACE ! 229: IFDEBUG(D_INDICATION) ! 230: char *ls, *fs; ! 231: ls = tpcb->tp_lsuffix, ! 232: fs = tpcb->tp_fsuffix, ! 233: ! 234: printf( ! 235: "indicate 0x%x lsuf 0x%02x%02x fsuf 0x%02x%02x err 0x%x noind 0x%x ref 0x%x\n", ! 236: ind, ! 237: *ls, *(ls+1), *fs, *(fs+1), ! 238: error, /*so->so_pgrp,*/ ! 239: tpcb->tp_no_disc_indications, ! 240: tpcb->tp_lref); ! 241: ENDDEBUG ! 242: ! 243: if (ind == ER_TPDU) { ! 244: register struct mbuf *m; ! 245: struct tp_disc_reason x; ! 246: ! 247: if ((so->so_state & SS_CANTRCVMORE) == 0 && ! 248: (m = m_get(M_DONTWAIT, MT_OOBDATA)) != 0) { ! 249: ! 250: x.dr_hdr.cmsg_len = m->m_len = sizeof(x); ! 251: x.dr_hdr.cmsg_level = SOL_TRANSPORT; ! 252: x.dr_hdr.cmsg_type= TPOPT_DISC_REASON; ! 253: x.dr_reason = error; ! 254: *mtod(m, struct tp_disc_reason *) = x; ! 255: sbappendrecord(&tpcb->tp_Xrcv, m); ! 256: error = 0; ! 257: } else ! 258: error = ECONNRESET; ! 259: } ! 260: so->so_error = error; ! 261: ! 262: if (ind == T_DISCONNECT) { ! 263: so->so_error = ENOTCONN; ! 264: if ( tpcb->tp_no_disc_indications ) ! 265: return; ! 266: } ! 267: IFTRACE(D_INDICATION) ! 268: tptraceTPCB(TPPTmisc, "doing sohasoutofband(so)", so,0,0,0); ! 269: ENDTRACE ! 270: sohasoutofband(so); ! 271: } ! 272: ! 273: /* ! 274: * NAME : tp_getoptions() ! 275: * ! 276: * CALLED FROM: ! 277: * tp.trans whenever we go into OPEN state ! 278: * ! 279: * FUNCTION and ARGUMENTS: ! 280: * sets the proper flags and values in the tpcb, to control ! 281: * the appropriate actions for the given class, options, ! 282: * sequence space, etc, etc. ! 283: * ! 284: * RETURNS: Nada ! 285: * ! 286: * SIDE EFFECTS: ! 287: * ! 288: * NOTES: ! 289: */ ! 290: void ! 291: tp_getoptions(tpcb) ! 292: struct tp_pcb *tpcb; ! 293: { ! 294: tpcb->tp_seqmask = ! 295: tpcb->tp_xtd_format ? TP_XTD_FMT_MASK : TP_NML_FMT_MASK ; ! 296: tpcb->tp_seqbit = ! 297: tpcb->tp_xtd_format ? TP_XTD_FMT_BIT : TP_NML_FMT_BIT ; ! 298: tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1; ! 299: tpcb->tp_dt_ticks = ! 300: MAX(tpcb->tp_dt_ticks, (tpcb->tp_peer_acktime + 2)); ! 301: ! 302: } ! 303: ! 304: /* ! 305: * NAME: tp_recycle_tsuffix() ! 306: * ! 307: * CALLED FROM: ! 308: * Called when a ref is frozen. ! 309: * ! 310: * FUNCTION and ARGUMENTS: ! 311: * allows the suffix to be reused. ! 312: * ! 313: * RETURNS: zilch ! 314: * ! 315: * SIDE EFFECTS: ! 316: * ! 317: * NOTES: ! 318: */ ! 319: void ! 320: tp_recycle_tsuffix(tpcb) ! 321: struct tp_pcb *tpcb; ! 322: { ! 323: bzero((caddr_t)tpcb->tp_lsuffix, sizeof( tpcb->tp_lsuffix)); ! 324: bzero((caddr_t)tpcb->tp_fsuffix, sizeof( tpcb->tp_fsuffix)); ! 325: tpcb->tp_fsuffixlen = tpcb->tp_lsuffixlen = 0; ! 326: ! 327: (tpcb->tp_nlproto->nlp_recycle_suffix)(tpcb->tp_npcb); ! 328: } ! 329: ! 330: /* ! 331: * NAME: tp_quench() ! 332: * ! 333: * CALLED FROM: ! 334: * tp{af}_quench() when ICMP source quench or similar thing arrives. ! 335: * ! 336: * FUNCTION and ARGUMENTS: ! 337: * Drop the congestion window back to 1. ! 338: * Congestion window scheme: ! 339: * Initial value is 1. ("slow start" as Nagle, et. al. call it) ! 340: * For each good ack that arrives, the congestion window is increased ! 341: * by 1 (up to max size of logical infinity, which is to say, ! 342: * it doesn't wrap around). ! 343: * Source quench causes it to drop back to 1. ! 344: * tp_send() uses the smaller of (regular window, congestion window). ! 345: * One retransmission strategy option is to have any retransmission ! 346: * cause reset the congestion window back to 1. ! 347: * ! 348: * (cmd) is either PRC_QUENCH: source quench, or ! 349: * PRC_QUENCH2: dest. quench (dec bit) ! 350: * ! 351: * RETURNS: ! 352: * ! 353: * SIDE EFFECTS: ! 354: * ! 355: * NOTES: ! 356: */ ! 357: void ! 358: tp_quench( tpcb, cmd ) ! 359: struct tp_pcb *tpcb; ! 360: int cmd; ! 361: { ! 362: IFDEBUG(D_QUENCH) ! 363: printf("tp_quench tpcb 0x%x ref 0x%x sufx 0x%x\n", ! 364: tpcb, tpcb->tp_lref, *(u_short *)(tpcb->tp_lsuffix)); ! 365: printf("cong_win 0x%x decbit 0x%x \n", ! 366: tpcb->tp_cong_win, tpcb->tp_decbit); ! 367: ENDDEBUG ! 368: switch(cmd) { ! 369: case PRC_QUENCH: ! 370: tpcb->tp_cong_win = 1; ! 371: IncStat(ts_quench); ! 372: break; ! 373: case PRC_QUENCH2: ! 374: tpcb->tp_cong_win = 1; /* might as well quench source also */ ! 375: tpcb->tp_decbit = TP_DECBIT_CLEAR_COUNT; ! 376: IncStat(ts_rcvdecbit); ! 377: break; ! 378: } ! 379: } ! 380: ! 381: ! 382: /* ! 383: * NAME: tp_netcmd() ! 384: * ! 385: * CALLED FROM: ! 386: * ! 387: * FUNCTION and ARGUMENTS: ! 388: * ! 389: * RETURNS: ! 390: * ! 391: * SIDE EFFECTS: ! 392: * ! 393: * NOTES: ! 394: */ ! 395: tp_netcmd( tpcb, cmd ) ! 396: struct tp_pcb *tpcb; ! 397: int cmd; ! 398: { ! 399: #ifdef TPCONS ! 400: struct isopcb *isop; ! 401: struct pklcd *lcp; ! 402: ! 403: if (tpcb->tp_netservice != ISO_CONS) ! 404: return; ! 405: isop = (struct isopcb *)tpcb->tp_npcb; ! 406: lcp = (struct pklcd *)isop->isop_chan; ! 407: switch (cmd) { ! 408: ! 409: case CONN_CLOSE: ! 410: case CONN_REFUSE: ! 411: if (isop->isop_refcnt == 1) ! 412: pk_disconnect(lcp); ! 413: isop->isop_chan = 0; ! 414: isop->isop_refcnt = 0; ! 415: break; ! 416: ! 417: default: ! 418: printf("tp_netcmd(0x%x, 0x%x) NOT IMPLEMENTED\n", tpcb, cmd); ! 419: break; ! 420: } ! 421: #else TPCONS ! 422: printf("tp_netcmd(): X25 NOT CONFIGURED!!\n"); ! 423: #endif ! 424: } ! 425: /* ! 426: * CALLED FROM: ! 427: * tp_ctloutput() and tp_emit() ! 428: * FUNCTION and ARGUMENTS: ! 429: * Convert a class mask to the highest numeric value it represents. ! 430: */ ! 431: ! 432: int ! 433: tp_mask_to_num(x) ! 434: u_char x; ! 435: { ! 436: register int j; ! 437: ! 438: for(j = 4; j>=0 ;j--) { ! 439: if(x & (1<<j)) ! 440: break; ! 441: } ! 442: ASSERT( (j == 4) || (j == 0) ); /* for now */ ! 443: if( (j != 4) && (j != 0) ) { ! 444: printf("ASSERTION ERROR: tp_mask_to_num: x 0x%x j %d\n", ! 445: x, j); ! 446: } ! 447: IFTRACE(D_TPINPUT) ! 448: tptrace(TPPTmisc, "tp_mask_to_num(x) returns j", x, j, 0, 0); ! 449: ENDTRACE ! 450: IFDEBUG(D_TPINPUT) ! 451: printf("tp_mask_to_num(0x%x) returns 0x%x\n", x, j); ! 452: ENDDEBUG ! 453: return j; ! 454: } ! 455: ! 456: static ! 457: copyQOSparms(src, dst) ! 458: struct tp_conn_param *src, *dst; ! 459: { ! 460: /* copy all but the bits stuff at the end */ ! 461: #define COPYSIZE (12 * sizeof(short)) ! 462: ! 463: bcopy((caddr_t)src, (caddr_t)dst, COPYSIZE); ! 464: dst->p_tpdusize = src->p_tpdusize; ! 465: dst->p_ack_strat = src->p_ack_strat; ! 466: dst->p_rx_strat = src->p_rx_strat; ! 467: #undef COPYSIZE ! 468: } ! 469: ! 470: /* ! 471: * CALLED FROM: ! 472: * tp_usrreq on PRU_CONNECT and tp_input on receipt of CR ! 473: * ! 474: * FUNCTION and ARGUMENTS: ! 475: * route directly to x.25 if the address is type 37 - GROT. ! 476: * furthermore, let TP0 handle only type-37 addresses ! 477: * ! 478: * Since this assumes that its address argument is in a mbuf, the ! 479: * parameter was changed to reflect this assumtion. This also ! 480: * implies that an mbuf must be allocated when this is ! 481: * called from tp_input ! 482: * ! 483: * RETURNS: ! 484: * errno value : ! 485: * EAFNOSUPPORT if can't find an nl_protosw for x.25 (really could panic) ! 486: * ECONNREFUSED if trying to run TP0 with non-type 37 address ! 487: * possibly other E* returned from cons_netcmd() ! 488: * NOTE: ! 489: * Would like to eliminate as much of this as possible -- ! 490: * only one set of defaults (let the user set the parms according ! 491: * to parameters provided in the directory service). ! 492: * Left here for now 'cause we don't yet have a clean way to handle ! 493: * it on the passive end. ! 494: */ ! 495: int ! 496: tp_route_to( m, tpcb, channel) ! 497: struct mbuf *m; ! 498: register struct tp_pcb *tpcb; ! 499: caddr_t channel; ! 500: { ! 501: register struct sockaddr_iso *siso; /* NOTE: this may be a sockaddr_in */ ! 502: extern struct tp_conn_param tp_conn_param[]; ! 503: struct pklcd *lcp = (struct pklcd *)channel; ! 504: int error = 0; ! 505: ! 506: siso = mtod(m, struct sockaddr_iso *); ! 507: IFTRACE(D_CONN) ! 508: tptraceTPCB(TPPTmisc, ! 509: "route_to: so afi netservice class", ! 510: tpcb->tp_sock, siso->siso_addr.isoa_genaddr[0], tpcb->tp_netservice, ! 511: tpcb->tp_class); ! 512: ENDTRACE ! 513: IFDEBUG(D_CONN) ! 514: printf("tp_route_to( m x%x, channel 0x%x, tpcb 0x%x netserv 0x%x)\n", ! 515: m, channel, tpcb, tpcb->tp_netservice); ! 516: printf("m->mlen x%x, m->m_data:\n", m->m_len); ! 517: dump_buf(mtod(m, caddr_t), m->m_len); ! 518: ENDDEBUG ! 519: if (siso->siso_family != tpcb->tp_domain) { ! 520: error = EAFNOSUPPORT; ! 521: goto done; ! 522: } ! 523: IFDEBUG(D_CONN) ! 524: printf("tp_route_to calling nlp_pcbconn, netserv %d\n", ! 525: tpcb->tp_netservice); ! 526: ENDDEBUG ! 527: #ifdef TPCONS ! 528: if (lcp) { ! 529: struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext, ! 530: *isop_new = (struct isopcb *)tpcb->tp_sock->so_pcb; ! 531: remque(isop_new); ! 532: free(isop_new, M_PCB); ! 533: tpcb->tp_sock->so_pcb = (caddr_t)isop; ! 534: if (isop->isop_refcnt == 0) { ! 535: extern struct isopcb tp_isopcb; ! 536: remque(isop); ! 537: insque(isop, &tp_isopcb); ! 538: isop->isop_head = &tp_isopcb; ! 539: iso_putsufx(isop, tpcb->tp_lsuffix, tpcb->tp_lsuffixlen, TP_LOCAL); ! 540: } ! 541: /* else there are already connections sharing this */ ! 542: isop->isop_refcnt++; ! 543: } else ! 544: #endif ! 545: error = (tpcb->tp_nlproto->nlp_pcbconn)(tpcb->tp_sock->so_pcb, m); ! 546: if( error ) ! 547: goto done; ! 548: ! 549: { ! 550: register int save_netservice = tpcb->tp_netservice; ! 551: ! 552: switch(tpcb->tp_netservice) { ! 553: case ISO_COSNS: ! 554: case ISO_CLNS: ! 555: /* This is a kludge but seems necessary so the passive end ! 556: * can get long enough timers. sigh. ! 557: if( siso->siso_addr.osinet_idi[1] == (u_char)IDI_OSINET ) ! 558: */ ! 559: #define IDI_OSINET 0x0004 /* bcd of "0004" */ ! 560: if( siso->siso_addr.isoa_genaddr[2] == (char)IDI_OSINET ) { ! 561: if( tpcb->tp_dont_change_params == 0) { ! 562: copyQOSparms( &tp_conn_param[ISO_COSNS], ! 563: &tpcb->_tp_param); ! 564: } ! 565: tpcb->tp_flags |= TPF_NLQOS_PDN; ! 566: } ! 567: /* drop through to IN_CLNS*/ ! 568: case IN_CLNS: ! 569: if (iso_localifa(siso)) ! 570: tpcb->tp_flags |= TPF_PEER_ON_SAMENET; ! 571: if( (tpcb->tp_class & TP_CLASS_4)==0 ) { ! 572: error = EPROTOTYPE; ! 573: break; ! 574: } ! 575: tpcb->tp_class = TP_CLASS_4; /* IGNORE dont_change_parms */ ! 576: break; ! 577: ! 578: case ISO_CONS: ! 579: #ifdef TPCONS ! 580: tpcb->tp_flags |= TPF_NLQOS_PDN; ! 581: if( tpcb->tp_dont_change_params == 0 ) { ! 582: copyQOSparms( &tp_conn_param[ISO_CONS], ! 583: &tpcb->_tp_param); ! 584: } ! 585: /* ! 586: * for use over x.25 really need a small receive window, ! 587: * need to start slowly, need small max negotiable tpdu size, ! 588: * and need to use the congestion window to the max ! 589: * IGNORES tp_dont_change_params for these! ! 590: */ ! 591: if( tpcb->tp_sock->so_snd.sb_hiwat > 512 ) { ! 592: (void) soreserve(tpcb->tp_sock, 512, 512 );/* GAG */ ! 593: } ! 594: tpcb->tp_rx_strat = TPRX_USE_CW; ! 595: ! 596: if( (tpcb->tp_nlproto != &nl_protosw[ISO_CONS]) ) { ! 597: IFDEBUG(D_CONN) ! 598: printf( ! 599: "tp_route_to( CHANGING nlproto old 0x%x new 0x%x)\n", ! 600: tpcb->tp_nlproto , &nl_protosw[ISO_CONS]); ! 601: ENDDEBUG ! 602: tpcb->tp_nlproto = &nl_protosw[ISO_CONS]; ! 603: } ! 604: /* class 4 doesn't need to open a vc now - may use one already ! 605: * opened or may open one only when it sends a pkt. ! 606: */ ! 607: #else TPCONS ! 608: error = ECONNREFUSED; ! 609: #endif TPCONS ! 610: break; ! 611: default: ! 612: error = EPROTOTYPE; ! 613: } ! 614: ! 615: ASSERT( save_netservice == tpcb->tp_netservice); ! 616: } ! 617: if (error) { ! 618: tp_netcmd( tpcb, CONN_CLOSE); ! 619: goto done; ! 620: } ! 621: { /* start with the global rtt, rtv stats */ ! 622: register int i = ! 623: (int) tpcb->tp_flags & (TPF_PEER_ON_SAMENET | TPF_NLQOS_PDN); ! 624: ! 625: tpcb->tp_rtt = tp_stat.ts_rtt[i]; ! 626: tpcb->tp_rtv = tp_stat.ts_rtv[i]; ! 627: } ! 628: done: ! 629: IFDEBUG(D_CONN) ! 630: printf("tp_route_to returns 0x%x\n", error); ! 631: ENDDEBUG ! 632: IFTRACE(D_CONN) ! 633: tptraceTPCB(TPPTmisc, "route_to: returns: error netserv class", error, ! 634: tpcb->tp_netservice, tpcb->tp_class, 0); ! 635: ENDTRACE ! 636: return error; ! 637: } ! 638: ! 639: ! 640: /* class zero version */ ! 641: void ! 642: tp0_stash( tpcb, e ) ! 643: register struct tp_pcb *tpcb; ! 644: register struct tp_event *e; ! 645: { ! 646: #ifndef lint ! 647: #define E e->ATTR(DT_TPDU) ! 648: #else lint ! 649: #define E e->ev_union.EV_DT_TPDU ! 650: #endif lint ! 651: ! 652: register struct sockbuf *sb = &tpcb->tp_sock->so_rcv; ! 653: register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; ! 654: ! 655: IFPERF(tpcb) ! 656: PStat(tpcb, Nb_from_ll) += E.e_datalen; ! 657: tpmeas(tpcb->tp_lref, TPtime_from_ll, &e->e_time, ! 658: E.e_seq, PStat(tpcb, Nb_from_ll), E.e_datalen); ! 659: ENDPERF ! 660: ! 661: IFDEBUG(D_STASH) ! 662: printf("stash EQ: seq 0x%x datalen 0x%x eot 0x%x", ! 663: E.e_seq, E.e_datalen, E.e_eot); ! 664: ENDDEBUG ! 665: ! 666: IFTRACE(D_STASH) ! 667: tptraceTPCB(TPPTmisc, "stash EQ: seq len eot", ! 668: E.e_seq, E.e_datalen, E.e_eot, 0); ! 669: ENDTRACE ! 670: ! 671: if ( E.e_eot ) { ! 672: register struct mbuf *n = E.e_data; ! 673: n->m_flags |= M_EOR; ! 674: n->m_act = MNULL; /* set on tp_input */ ! 675: } ! 676: sbappend(sb, E.e_data); ! 677: IFDEBUG(D_STASH) ! 678: dump_mbuf(sb->sb_mb, "stash 0: so_rcv after appending"); ! 679: ENDDEBUG ! 680: if (tpcb->tp_netservice != ISO_CONS) ! 681: printf("tp0_stash: tp running over something wierd\n"); ! 682: else { ! 683: register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; ! 684: pk_flowcontrol(lcp, sbspace(sb) <= 0, 1); ! 685: } ! 686: } ! 687: ! 688: void ! 689: tp0_openflow(tpcb) ! 690: register struct tp_pcb *tpcb; ! 691: { ! 692: register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb; ! 693: if (tpcb->tp_netservice != ISO_CONS) ! 694: printf("tp0_openflow: tp running over something wierd\n"); ! 695: else { ! 696: register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; ! 697: if (lcp->lcd_rxrnr_condition) ! 698: pk_flowcontrol(lcp, 0, 0); ! 699: } ! 700: } ! 701: #ifndef TPCONS ! 702: static ! 703: pk_flowcontrol() {} ! 704: #endif ! 705: ! 706: #ifdef TP_PERF_MEAS ! 707: /* ! 708: * CALLED FROM: ! 709: * tp_ctloutput() when the user sets TPOPT_PERF_MEAS on ! 710: * and tp_newsocket() when a new connection is made from ! 711: * a listening socket with tp_perf_on == true. ! 712: * FUNCTION and ARGUMENTS: ! 713: * (tpcb) is the usual; this procedure gets a clear cluster mbuf for ! 714: * a tp_pmeas structure, and makes tpcb->tp_p_meas point to it. ! 715: * RETURN VALUE: ! 716: * ENOBUFS if it cannot get a cluster mbuf. ! 717: */ ! 718: ! 719: int ! 720: tp_setup_perf(tpcb) ! 721: register struct tp_pcb *tpcb; ! 722: { ! 723: register struct mbuf *q; ! 724: ! 725: if( tpcb->tp_p_meas == 0 ) { ! 726: MGET(q, M_WAITOK, MT_PCB); ! 727: if (q == 0) ! 728: return ENOBUFS; ! 729: MCLGET(q, M_WAITOK); ! 730: if ((q->m_flags & M_EXT) == 0) { ! 731: (void) m_free(q); ! 732: return ENOBUFS; ! 733: } ! 734: q->m_len = sizeof (struct tp_pmeas); ! 735: tpcb->tp_p_mbuf = q; ! 736: tpcb->tp_p_meas = mtod(q, struct tp_pmeas *); ! 737: bzero( (caddr_t)tpcb->tp_p_meas, sizeof (struct tp_pmeas) ); ! 738: IFDEBUG(D_PERF_MEAS) ! 739: printf( ! 740: "tpcb 0x%x so 0x%x ref 0x%x tp_p_meas 0x%x tp_perf_on 0x%x\n", ! 741: tpcb, tpcb->tp_sock, tpcb->tp_lref, ! 742: tpcb->tp_p_meas, tpcb->tp_perf_on); ! 743: ENDDEBUG ! 744: tpcb->tp_perf_on = 1; ! 745: } ! 746: return 0; ! 747: } ! 748: #endif TP_PERF_MEAS ! 749: ! 750: #ifdef ARGO_DEBUG ! 751: dump_addr (addr) ! 752: register struct sockaddr *addr; ! 753: { ! 754: switch( addr->sa_family ) { ! 755: case AF_INET: ! 756: dump_inaddr((struct sockaddr_in *)addr); ! 757: break; ! 758: #ifdef ISO ! 759: case AF_ISO: ! 760: dump_isoaddr((struct sockaddr_iso *)addr); ! 761: break; ! 762: #endif ISO ! 763: default: ! 764: printf("BAD AF: 0x%x\n", addr->sa_family); ! 765: break; ! 766: } ! 767: } ! 768: ! 769: #define MAX_COLUMNS 8 ! 770: /* ! 771: * Dump the buffer to the screen in a readable format. Format is: ! 772: * ! 773: * hex/dec where hex is the hex format, dec is the decimal format. ! 774: * columns of hex/dec numbers will be printed, followed by the ! 775: * character representations (if printable). ! 776: */ ! 777: Dump_buf(buf, len) ! 778: caddr_t buf; ! 779: int len; ! 780: { ! 781: int i,j; ! 782: #define Buf ((u_char *)buf) ! 783: printf("Dump buf 0x%x len 0x%x\n", buf, len); ! 784: for (i = 0; i < len; i += MAX_COLUMNS) { ! 785: printf("+%d:\t", i); ! 786: for (j = 0; j < MAX_COLUMNS; j++) { ! 787: if (i + j < len) { ! 788: printf("%x/%d\t", Buf[i+j], Buf[i+j]); ! 789: } else { ! 790: printf(" "); ! 791: } ! 792: } ! 793: ! 794: for (j = 0; j < MAX_COLUMNS; j++) { ! 795: if (i + j < len) { ! 796: if (((Buf[i+j]) > 31) && ((Buf[i+j]) < 128)) ! 797: printf("%c", Buf[i+j]); ! 798: else ! 799: printf("."); ! 800: } ! 801: } ! 802: printf("\n"); ! 803: } ! 804: } ! 805: ! 806: ! 807: #endif ARGO_DEBUG ! 808:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.