|
|
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_subr2.c,v 5.5 88/11/18 17:28:55 nhall Exp $ ! 31: * $Source: /usr/argo/sys/netiso/RCS/tp_subr2.c,v $ ! 32: * @(#)tp_subr2.c 7.4 (Berkeley) 9/22/89 ! 33: * ! 34: * Some auxiliary routines: ! 35: * tp_protocol_error: required by xebec- called when a combo of state, ! 36: * event, predicate isn't covered for by the transition file. ! 37: * tp_indicate: gives indications(signals) to the user process ! 38: * tp_getoptions: initializes variables that are affected by the options ! 39: * chosen. ! 40: */ ! 41: ! 42: #ifndef lint ! 43: static char *rcsid = "$Header: tp_subr2.c,v 5.5 88/11/18 17:28:55 nhall Exp $"; ! 44: #endif lint ! 45: ! 46: #include "argoxtwentyfive.h" ! 47: ! 48: /* this def'n is to cause the expansion of this macro in the ! 49: * routine tp_local_credit : ! 50: */ ! 51: #define LOCAL_CREDIT_EXPAND ! 52: ! 53: #include "param.h" ! 54: #include "mbuf.h" ! 55: #include "socket.h" ! 56: #include "socketvar.h" ! 57: #include "domain.h" ! 58: #include "protosw.h" ! 59: #include "errno.h" ! 60: #include "types.h" ! 61: #include "time.h" ! 62: #include "kernel.h" ! 63: #undef MNULL ! 64: #include "argo_debug.h" ! 65: #include "tp_param.h" ! 66: #include "tp_ip.h" ! 67: #include "iso.h" ! 68: #include "iso_errno.h" ! 69: #include "iso_pcb.h" ! 70: #include "tp_timer.h" ! 71: #include "tp_stat.h" ! 72: #include "tp_tpdu.h" ! 73: #include "tp_pcb.h" ! 74: #include "tp_seq.h" ! 75: #include "tp_trace.h" ! 76: #include "tp_user.h" ! 77: #include "cons.h" ! 78: ! 79: /* ! 80: * NAME: tp_local_credit() ! 81: * ! 82: * CALLED FROM: ! 83: * tp_emit(), tp_usrreq() ! 84: * ! 85: * FUNCTION and ARGUMENTS: ! 86: * Computes the local credit and stashes it in tpcb->tp_lcredit. ! 87: * It's a macro in the production system rather than a procdure. ! 88: * ! 89: * RETURNS: ! 90: * ! 91: * SIDE EFFECTS: ! 92: * ! 93: * NOTES: ! 94: * This doesn't actually get called in a production system - ! 95: * the macro gets expanded instead in place of calls to this proc. ! 96: * But for debugging, we call this and that allows us to add ! 97: * debugging messages easily here. ! 98: */ ! 99: void ! 100: tp_local_credit(tpcb) ! 101: struct tp_pcb *tpcb; ! 102: { ! 103: LOCAL_CREDIT(tpcb); ! 104: IFDEBUG(D_CREDIT) ! 105: printf("ref 0x%x lcdt 0x%x l_tpdusize 0x%x decbit 0x%x\n", ! 106: tpcb->tp_refp - tp_ref, ! 107: tpcb->tp_lcredit, ! 108: tpcb->tp_l_tpdusize, ! 109: tpcb->tp_decbit, ! 110: tpcb->tp_cong_win ! 111: ); ! 112: ENDDEBUG ! 113: IFTRACE(D_CREDIT) ! 114: tptraceTPCB(TPPTmisc, ! 115: "lcdt tpdusz \n", ! 116: tpcb->tp_lcredit, tpcb->tp_l_tpdusize, 0, 0); ! 117: ENDTRACE ! 118: } ! 119: ! 120: /* ! 121: * NAME: tp_protocol_error() ! 122: * ! 123: * CALLED FROM: ! 124: * tp_driver(), when it doesn't know what to do with ! 125: * a combo of event, state, predicate ! 126: * ! 127: * FUNCTION and ARGUMENTS: ! 128: * print error mesg ! 129: * ! 130: * RETURN VALUE: ! 131: * EIO - always ! 132: * ! 133: * SIDE EFFECTS: ! 134: * ! 135: * NOTES: ! 136: */ ! 137: int ! 138: tp_protocol_error(e,tpcb) ! 139: struct tp_event *e; ! 140: struct tp_pcb *tpcb; ! 141: { ! 142: printf("TP PROTOCOL ERROR! tpcb 0x%x event 0x%x, state 0x%x\n", ! 143: tpcb, e->ev_number, tpcb->tp_state); ! 144: IFTRACE(D_DRIVER) ! 145: tptraceTPCB(TPPTmisc, "PROTOCOL ERROR tpcb event state", ! 146: tpcb, e->ev_number, tpcb->tp_state, 0 ); ! 147: ENDTRACE ! 148: return EIO; /* for lack of anything better */ ! 149: } ! 150: ! 151: ! 152: /* Not used at the moment */ ! 153: ProtoHook ! 154: tp_drain() ! 155: { ! 156: return 0; ! 157: } ! 158: ! 159: ! 160: /* ! 161: * NAME: tp_indicate() ! 162: * ! 163: * CALLED FROM: ! 164: * tp.trans when XPD arrive, when a connection is being disconnected by ! 165: * the arrival of a DR or ER, and when a connection times out. ! 166: * ! 167: * FUNCTION and ARGUMENTS: ! 168: * (ind) is the type of indication : T_DISCONNECT, T_XPD ! 169: * (error) is an E* value that will be put in the socket structure ! 170: * to be passed along to the user later. ! 171: * Gives a SIGURG to the user process or group indicated by the socket ! 172: * attached to the tpcb. ! 173: * ! 174: * RETURNS: Rien ! 175: * ! 176: * SIDE EFFECTS: ! 177: * ! 178: * NOTES: ! 179: */ ! 180: void ! 181: tp_indicate(ind, tpcb, error) ! 182: int ind; ! 183: u_short error; ! 184: register struct tp_pcb *tpcb; ! 185: { ! 186: register struct socket *so = tpcb->tp_sock; ! 187: IFTRACE(D_INDICATION) ! 188: tptraceTPCB(TPPTindicate, ind, *(u_short *)(tpcb->tp_lsuffix), ! 189: *(u_short *)(tpcb->tp_fsuffix), error,so->so_pgid); ! 190: ENDTRACE ! 191: IFDEBUG(D_INDICATION) ! 192: char *ls, *fs; ! 193: ls = tpcb->tp_lsuffix, ! 194: fs = tpcb->tp_fsuffix, ! 195: ! 196: printf( ! 197: "indicate 0x%x lsuf 0x%02x%02x fsuf 0x%02x%02x err 0x%x noind 0x%x ref 0x%x\n", ! 198: ind, ! 199: *ls, *(ls+1), *fs, *(fs+1), ! 200: error, /*so->so_pgrp,*/ ! 201: tpcb->tp_no_disc_indications, ! 202: tpcb->tp_lref); ! 203: ENDDEBUG ! 204: ! 205: so->so_error = error; ! 206: ! 207: if (ind == T_DISCONNECT) { ! 208: if ( tpcb->tp_no_disc_indications ) ! 209: return; ! 210: } ! 211: IFTRACE(D_INDICATION) ! 212: tptraceTPCB(TPPTmisc, "doing sohasoutofband(so)", so,0,0,0); ! 213: ENDTRACE ! 214: sohasoutofband(so); ! 215: } ! 216: ! 217: /* ! 218: * NAME : tp_getoptions() ! 219: * ! 220: * CALLED FROM: ! 221: * tp.trans whenever we go into OPEN state ! 222: * ! 223: * FUNCTION and ARGUMENTS: ! 224: * sets the proper flags and values in the tpcb, to control ! 225: * the appropriate actions for the given class, options, ! 226: * sequence space, etc, etc. ! 227: * ! 228: * RETURNS: Nada ! 229: * ! 230: * SIDE EFFECTS: ! 231: * ! 232: * NOTES: ! 233: */ ! 234: void ! 235: tp_getoptions(tpcb) ! 236: struct tp_pcb *tpcb; ! 237: { ! 238: tpcb->tp_seqmask = ! 239: tpcb->tp_xtd_format ? TP_XTD_FMT_MASK : TP_NML_FMT_MASK ; ! 240: tpcb->tp_seqbit = ! 241: tpcb->tp_xtd_format ? TP_XTD_FMT_BIT : TP_NML_FMT_BIT ; ! 242: tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1; ! 243: tpcb->tp_dt_ticks = ! 244: MAX(tpcb->tp_dt_ticks, (tpcb->tp_peer_acktime + 2)); ! 245: ! 246: } ! 247: ! 248: /* ! 249: * NAME: tp_recycle_tsuffix() ! 250: * ! 251: * CALLED FROM: ! 252: * Called when a ref is frozen. ! 253: * ! 254: * FUNCTION and ARGUMENTS: ! 255: * allows the suffix to be reused. ! 256: * ! 257: * RETURNS: zilch ! 258: * ! 259: * SIDE EFFECTS: ! 260: * ! 261: * NOTES: ! 262: */ ! 263: void ! 264: tp_recycle_tsuffix(tpcb) ! 265: struct tp_pcb *tpcb; ! 266: { ! 267: bzero((caddr_t)tpcb->tp_lsuffix, sizeof( tpcb->tp_lsuffix)); ! 268: bzero((caddr_t)tpcb->tp_fsuffix, sizeof( tpcb->tp_fsuffix)); ! 269: tpcb->tp_fsuffixlen = tpcb->tp_lsuffixlen = 0; ! 270: ! 271: (tpcb->tp_nlproto->nlp_recycle_suffix)(tpcb->tp_npcb); ! 272: } ! 273: ! 274: /* ! 275: * NAME: tp_quench() ! 276: * ! 277: * CALLED FROM: ! 278: * tp{af}_quench() when ICMP source quench or similar thing arrives. ! 279: * ! 280: * FUNCTION and ARGUMENTS: ! 281: * Drop the congestion window back to 1. ! 282: * Congestion window scheme: ! 283: * Initial value is 1. ("slow start" as Nagle, et. al. call it) ! 284: * For each good ack that arrives, the congestion window is increased ! 285: * by 1 (up to max size of logical infinity, which is to say, ! 286: * it doesn't wrap around). ! 287: * Source quench causes it to drop back to 1. ! 288: * tp_send() uses the smaller of (regular window, congestion window). ! 289: * One retransmission strategy option is to have any retransmission ! 290: * cause reset the congestion window back to 1. ! 291: * ! 292: * (cmd) is either PRC_QUENCH: source quench, or ! 293: * PRC_QUENCH2: dest. quench (dec bit) ! 294: * ! 295: * RETURNS: ! 296: * ! 297: * SIDE EFFECTS: ! 298: * ! 299: * NOTES: ! 300: */ ! 301: void ! 302: tp_quench( tpcb, cmd ) ! 303: struct tp_pcb *tpcb; ! 304: int cmd; ! 305: { ! 306: IFDEBUG(D_QUENCH) ! 307: printf("tp_quench tpcb 0x%x ref 0x%x sufx 0x%x\n", ! 308: tpcb, tpcb->tp_lref, *(u_short *)(tpcb->tp_lsuffix)); ! 309: printf("cong_win 0x%x decbit 0x%x \n", ! 310: tpcb->tp_cong_win, tpcb->tp_decbit); ! 311: ENDDEBUG ! 312: switch(cmd) { ! 313: case PRC_QUENCH: ! 314: tpcb->tp_cong_win = 1; ! 315: IncStat(ts_quench); ! 316: break; ! 317: case PRC_QUENCH2: ! 318: tpcb->tp_cong_win = 1; /* might as well quench source also */ ! 319: tpcb->tp_decbit = TP_DECBIT_CLEAR_COUNT; ! 320: IncStat(ts_rcvdecbit); ! 321: break; ! 322: } ! 323: } ! 324: ! 325: ! 326: /* ! 327: * NAME: tp_netcmd() ! 328: * ! 329: * CALLED FROM: ! 330: * ! 331: * FUNCTION and ARGUMENTS: ! 332: * ! 333: * RETURNS: ! 334: * ! 335: * SIDE EFFECTS: ! 336: * ! 337: * NOTES: ! 338: */ ! 339: tp_netcmd( tpcb, cmd ) ! 340: struct tp_pcb *tpcb; ! 341: int cmd; ! 342: { ! 343: #if NARGOXTWENTYFIVE > 0 ! 344: switch (cmd) { ! 345: ! 346: case CONN_CLOSE: ! 347: case CONN_REFUSE: ! 348: cons_netcmd( cmd, tpcb->tp_npcb, 0, tpcb->tp_class == TP_CLASS_4); ! 349: /* TODO: can this last param be replaced by ! 350: * tpcb->tp_netserv != ISO_CONS?) ! 351: */ ! 352: break; ! 353: ! 354: default: ! 355: printf("tp_netcmd(0x%x, 0x%x) NOT IMPLEMENTED\n", tpcb, cmd); ! 356: break; ! 357: } ! 358: #else NARGOXTWENTYFIVE ! 359: printf("tp_netcmd(): X25 NOT CONFIGURED!!\n"); ! 360: #endif NARGOXTWENTYFIVE > 0 ! 361: } ! 362: /* ! 363: * CALLED FROM: ! 364: * tp_ctloutput() and tp_emit() ! 365: * FUNCTION and ARGUMENTS: ! 366: * Convert a class mask to the highest numeric value it represents. ! 367: */ ! 368: ! 369: int ! 370: tp_mask_to_num(x) ! 371: u_char x; ! 372: { ! 373: register int j; ! 374: ! 375: for(j = 4; j>=0 ;j--) { ! 376: if(x & (1<<j)) ! 377: break; ! 378: } ! 379: ASSERT( (j == 4) || (j == 0) ); /* for now */ ! 380: if( (j != 4) && (j != 0) ) { ! 381: printf("ASSERTION ERROR: tp_mask_to_num: x 0x%x j %d\n", ! 382: x, j); ! 383: } ! 384: IFTRACE(D_TPINPUT) ! 385: tptrace(TPPTmisc, "tp_mask_to_num(x) returns j", x, j, 0, 0); ! 386: ENDTRACE ! 387: IFDEBUG(D_TPINPUT) ! 388: printf("tp_mask_to_num(0x%x) returns 0x%x\n", x, j); ! 389: ENDDEBUG ! 390: return j; ! 391: } ! 392: ! 393: static ! 394: copyQOSparms(src, dst) ! 395: struct tp_conn_param *src, *dst; ! 396: { ! 397: /* copy all but the bits stuff at the end */ ! 398: #define COPYSIZE (12 * sizeof(short)) ! 399: ! 400: bcopy((caddr_t)src, (caddr_t)dst, COPYSIZE); ! 401: dst->p_tpdusize = src->p_tpdusize; ! 402: dst->p_ack_strat = src->p_ack_strat; ! 403: dst->p_rx_strat = src->p_rx_strat; ! 404: #undef COPYSIZE ! 405: } ! 406: ! 407: /* ! 408: * CALLED FROM: ! 409: * tp_usrreq on PRU_CONNECT and tp_input on receipt of CR ! 410: * ! 411: * FUNCTION and ARGUMENTS: ! 412: * route directly to x.25 if the address is type 37 - GROT. ! 413: * furthermore, let TP0 handle only type-37 addresses ! 414: * ! 415: * Since this assumes that its address argument is in a mbuf, the ! 416: * parameter was changed to reflect this assumtion. This also ! 417: * implies that an mbuf must be allocated when this is ! 418: * called from tp_input ! 419: * ! 420: * RETURNS: ! 421: * errno value : ! 422: * EAFNOSUPPORT if can't find an nl_protosw for x.25 (really could panic) ! 423: * ECONNREFUSED if trying to run TP0 with non-type 37 address ! 424: * possibly other E* returned from cons_netcmd() ! 425: * NOTE: ! 426: * Would like to eliminate as much of this as possible -- ! 427: * only one set of defaults (let the user set the parms according ! 428: * to parameters provided in the directory service). ! 429: * Left here for now 'cause we don't yet have a clean way to handle ! 430: * it on the passive end. ! 431: */ ! 432: int ! 433: tp_route_to( m, tpcb, channel) ! 434: struct mbuf *m; ! 435: register struct tp_pcb *tpcb; ! 436: u_int channel; ! 437: { ! 438: register struct sockaddr_iso *siso; /* NOTE: this may be a sockaddr_in */ ! 439: extern struct tp_conn_param tp_conn_param[]; ! 440: int error = 0; ! 441: int vc_to_kill = 0; /* kludge */ ! 442: ! 443: siso = mtod(m, struct sockaddr_iso *); ! 444: IFTRACE(D_CONN) ! 445: tptraceTPCB(TPPTmisc, ! 446: "route_to: so afi netservice class", ! 447: tpcb->tp_sock, siso->siso_addr.isoa_genaddr[0], tpcb->tp_netservice, ! 448: tpcb->tp_class); ! 449: ENDTRACE ! 450: IFDEBUG(D_CONN) ! 451: printf("tp_route_to( m x%x, channel 0x%x, tpcb 0x%x netserv 0x%x)\n", ! 452: m, channel, tpcb, tpcb->tp_netservice); ! 453: printf("m->mlen x%x, m->m_data:\n", m->m_len); ! 454: dump_buf(mtod(m, caddr_t), m->m_len); ! 455: ENDDEBUG ! 456: if( siso->siso_family != tpcb->tp_domain ) { ! 457: error = EAFNOSUPPORT; ! 458: goto done; ! 459: } ! 460: IFDEBUG(D_CONN) ! 461: printf("tp_route_to calling nlp_pcbconn, netserv %d\n", ! 462: tpcb->tp_netservice); ! 463: ENDDEBUG ! 464: error = (tpcb->tp_nlproto->nlp_pcbconn)(tpcb->tp_sock->so_pcb, m); ! 465: if( error ) ! 466: goto done; ! 467: ! 468: { ! 469: register int save_netservice = tpcb->tp_netservice; ! 470: ! 471: switch(tpcb->tp_netservice) { ! 472: case ISO_COSNS: ! 473: case ISO_CLNS: ! 474: /* This is a kludge but seems necessary so the passive end ! 475: * can get long enough timers. sigh. ! 476: if( siso->siso_addr.osinet_idi[1] == (u_char)IDI_OSINET ) ! 477: */ ! 478: #define IDI_OSINET 0x0004 /* bcd of "0004" */ ! 479: if( siso->siso_addr.isoa_genaddr[2] == (char)IDI_OSINET ) { ! 480: if( tpcb->tp_dont_change_params == 0) { ! 481: copyQOSparms( &tp_conn_param[ISO_COSNS], ! 482: &tpcb->_tp_param); ! 483: } ! 484: tpcb->tp_flags |= TPF_NLQOS_PDN; ! 485: } ! 486: /* drop through to IN_CLNS*/ ! 487: case IN_CLNS: ! 488: if (iso_localifa(siso)) ! 489: tpcb->tp_flags |= TPF_PEER_ON_SAMENET; ! 490: if( (tpcb->tp_class & TP_CLASS_4)==0 ) { ! 491: error = EPROTOTYPE; ! 492: break; ! 493: } ! 494: tpcb->tp_class = TP_CLASS_4; /* IGNORE dont_change_parms */ ! 495: break; ! 496: ! 497: case ISO_CONS: ! 498: #if NARGOXTWENTYFIVE > 0 ! 499: tpcb->tp_flags |= TPF_NLQOS_PDN; ! 500: if( tpcb->tp_dont_change_params == 0 ) { ! 501: copyQOSparms( &tp_conn_param[ISO_CONS], ! 502: &tpcb->_tp_param); ! 503: } ! 504: /* ! 505: * for use over x.25 really need a small receive window, ! 506: * need to start slowly, need small max negotiable tpdu size, ! 507: * and need to use the congestion window to the max ! 508: * IGNORES tp_dont_change_params for these! ! 509: */ ! 510: if( tpcb->tp_sock->so_snd.sb_hiwat > 512 ) { ! 511: (void) soreserve(tpcb->tp_sock, 512, 512 );/* GAG */ ! 512: } ! 513: tpcb->tp_rx_strat = TPRX_USE_CW; ! 514: ! 515: if( (tpcb->tp_nlproto != &nl_protosw[ISO_CONS]) ) { ! 516: /* if the listener was restricting us to clns, ! 517: * ( we never get here if the listener isn't af_iso ) ! 518: * refuse the connection : ! 519: * but we don't have a way to restrict thus - it's ! 520: * utterly permissive. ! 521: if(channel) { ! 522: (void) cons_netcmd(CONN_REFUSE, tpcb->tp_npcb, ! 523: channel, tpcb->tp_class == TP_CLASS_4); ! 524: error = EPFNOSUPPORT; ! 525: goto done; ! 526: } ! 527: */ ! 528: IFDEBUG(D_CONN) ! 529: printf( ! 530: "tp_route_to( CHANGING nlproto old 0x%x new 0x%x)\n", ! 531: tpcb->tp_nlproto , &nl_protosw[ISO_CONS]); ! 532: ENDDEBUG ! 533: tpcb->tp_nlproto = &nl_protosw[ISO_CONS]; ! 534: } ! 535: /* Now we've got the right nl_protosw. ! 536: * If we already have a channel (we were called from tp_input()) ! 537: * tell cons that we'll hang onto this channel. ! 538: * If we don't already have one (we were called from usrreq()) ! 539: * -and if it's TP0 open a net connection and wait for it to finish. ! 540: */ ! 541: if( channel ) { ! 542: error = cons_netcmd( CONN_CONFIRM, tpcb->tp_npcb, ! 543: channel, tpcb->tp_class == TP_CLASS_4); ! 544: vc_to_kill ++; ! 545: } else if( tpcb->tp_class != TP_CLASS_4 /* class 4 only */) { ! 546: /* better open vc if any possibility of ending up ! 547: * in non-multiplexing class ! 548: */ ! 549: error = cons_openvc(tpcb->tp_npcb, siso, tpcb->tp_sock); ! 550: vc_to_kill ++; ! 551: } ! 552: /* class 4 doesn't need to open a vc now - may use one already ! 553: * opened or may open one only when it sends a pkt. ! 554: */ ! 555: #else NARGOXTWENTYFIVE > 0 ! 556: error = ECONNREFUSED; ! 557: #endif NARGOXTWENTYFIVE > 0 ! 558: break; ! 559: default: ! 560: error = EPROTOTYPE; ! 561: } ! 562: ! 563: ASSERT( save_netservice == tpcb->tp_netservice); ! 564: } ! 565: if( error && vc_to_kill ) { ! 566: tp_netcmd( tpcb, CONN_CLOSE); ! 567: goto done; ! 568: } ! 569: { /* start with the global rtt, rtv stats */ ! 570: register int i = ! 571: (int) tpcb->tp_flags & (TPF_PEER_ON_SAMENET | TPF_NLQOS_PDN); ! 572: ! 573: tpcb->tp_rtt = tp_stat.ts_rtt[i]; ! 574: tpcb->tp_rtv = tp_stat.ts_rtv[i]; ! 575: } ! 576: done: ! 577: IFDEBUG(D_CONN) ! 578: printf("tp_route_to returns 0x%x\n", error); ! 579: ENDDEBUG ! 580: IFTRACE(D_CONN) ! 581: tptraceTPCB(TPPTmisc, "route_to: returns: error netserv class", error, ! 582: tpcb->tp_netservice, tpcb->tp_class, 0); ! 583: ENDTRACE ! 584: return error; ! 585: } ! 586: ! 587: #ifdef TP_PERF_MEAS ! 588: /* ! 589: * CALLED FROM: ! 590: * tp_ctloutput() when the user sets TPOPT_PERF_MEAS on ! 591: * and tp_newsocket() when a new connection is made from ! 592: * a listening socket with tp_perf_on == true. ! 593: * FUNCTION and ARGUMENTS: ! 594: * (tpcb) is the usual; this procedure gets a clear cluster mbuf for ! 595: * a tp_pmeas structure, and makes tpcb->tp_p_meas point to it. ! 596: * RETURN VALUE: ! 597: * ENOBUFS if it cannot get a cluster mbuf. ! 598: */ ! 599: ! 600: int ! 601: tp_setup_perf(tpcb) ! 602: register struct tp_pcb *tpcb; ! 603: { ! 604: register struct mbuf *q; ! 605: ! 606: if( tpcb->tp_p_meas == 0 ) { ! 607: MGET(q, M_WAITOK, MT_PCB); ! 608: if (q == 0) ! 609: return ENOBUFS; ! 610: MCLGET(q, M_WAITOK); ! 611: if ((q->m_flags & M_EXT) == 0) { ! 612: (void) m_free(q); ! 613: return ENOBUFS; ! 614: } ! 615: q->m_len = sizeof (struct tp_pmeas); ! 616: tpcb->tp_p_mbuf = q; ! 617: tpcb->tp_p_meas = mtod(q, struct tp_pmeas *); ! 618: bzero( (caddr_t)tpcb->tp_p_meas, sizeof (struct tp_pmeas) ); ! 619: IFDEBUG(D_PERF_MEAS) ! 620: printf( ! 621: "tpcb 0x%x so 0x%x ref 0x%x tp_p_meas 0x%x tp_perf_on 0x%x\n", ! 622: tpcb, tpcb->tp_sock, tpcb->tp_lref, ! 623: tpcb->tp_p_meas, tpcb->tp_perf_on); ! 624: ENDDEBUG ! 625: tpcb->tp_perf_on = 1; ! 626: } ! 627: return 0; ! 628: } ! 629: #endif TP_PERF_MEAS ! 630: ! 631: #ifdef ARGO_DEBUG ! 632: dump_addr (addr) ! 633: register struct sockaddr *addr; ! 634: { ! 635: switch( addr->sa_family ) { ! 636: case AF_INET: ! 637: dump_inaddr((struct sockaddr_in *)addr); ! 638: break; ! 639: #ifdef ISO ! 640: case AF_ISO: ! 641: dump_isoaddr((struct sockaddr_iso *)addr); ! 642: break; ! 643: #endif ISO ! 644: default: ! 645: printf("BAD AF: 0x%x\n", addr->sa_family); ! 646: break; ! 647: } ! 648: } ! 649: ! 650: #define MAX_COLUMNS 8 ! 651: /* ! 652: * Dump the buffer to the screen in a readable format. Format is: ! 653: * ! 654: * hex/dec where hex is the hex format, dec is the decimal format. ! 655: * columns of hex/dec numbers will be printed, followed by the ! 656: * character representations (if printable). ! 657: */ ! 658: Dump_buf(buf, len) ! 659: caddr_t buf; ! 660: int len; ! 661: { ! 662: int i,j; ! 663: ! 664: printf("Dump buf 0x%x len 0x%x\n", buf, len); ! 665: for (i = 0; i < len; i += MAX_COLUMNS) { ! 666: printf("+%d:\t", i); ! 667: for (j = 0; j < MAX_COLUMNS; j++) { ! 668: if (i + j < len) { ! 669: printf("%x/%d\t", buf[i+j]&0xff, buf[i+j]); ! 670: } else { ! 671: printf(" "); ! 672: } ! 673: } ! 674: ! 675: for (j = 0; j < MAX_COLUMNS; j++) { ! 676: if (i + j < len) { ! 677: if (((buf[i+j]) > 31) && ((buf[i+j]) < 128)) ! 678: printf("%c", buf[i+j]&0xff); ! 679: else ! 680: printf("."); ! 681: } ! 682: } ! 683: printf("\n"); ! 684: } ! 685: } ! 686: ! 687: ! 688: #endif ARGO_DEBUG ! 689:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.