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