xref: /original-bsd/sys/netiso/tp_subr2.c (revision 2a4161ef)
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) 09/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 
690