routing messages do not come with attached addresses
[unix-history] / usr / src / sys / netiso / tp_subr2.c
CommitLineData
3202a7cd
KS
1/***********************************************************
2 Copyright IBM Corporation 1987
3
4 All Rights Reserved
5
6Permission to use, copy, modify, and distribute this software and its
7documentation for any purpose and without fee is hereby granted,
8provided that the above copyright notice appear in all copies and that
9both that copyright notice and this permission notice appear in
10supporting documentation, and that the name of IBM not be
11used in advertising or publicity pertaining to distribution of the
12software without specific, written prior permission.
13
14IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20SOFTWARE.
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 $
9aed0596 32 * @(#)tp_subr2.c 7.4 (Berkeley) %G%
3202a7cd
KS
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
43static 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
a50e2bc0
KS
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"
3202a7cd
KS
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 */
99void
100tp_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 */
137int
138tp_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 */
153ProtoHook
154tp_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 */
180void
181tp_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)
9aed0596
KS
188 tptraceTPCB(TPPTindicate, ind, *(u_short *)(tpcb->tp_lsuffix),
189 *(u_short *)(tpcb->tp_fsuffix), error,so->so_pgid);
3202a7cd
KS
190 ENDTRACE
191 IFDEBUG(D_INDICATION)
a50e2bc0 192 char *ls, *fs;
3202a7cd
KS
193 ls = tpcb->tp_lsuffix,
194 fs = tpcb->tp_fsuffix,
195
196 printf(
a50e2bc0 197"indicate 0x%x lsuf 0x%02x%02x fsuf 0x%02x%02x err 0x%x noind 0x%x ref 0x%x\n",
3202a7cd
KS
198 ind,
199 *ls, *(ls+1), *fs, *(fs+1),
a50e2bc0 200 error, /*so->so_pgrp,*/
3202a7cd
KS
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 */
234void
235tp_getoptions(tpcb)
236struct 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 */
263void
264tp_recycle_tsuffix(tpcb)
265 struct tp_pcb *tpcb;
266{
a50e2bc0
KS
267 bzero((caddr_t)tpcb->tp_lsuffix, sizeof( tpcb->tp_lsuffix));
268 bzero((caddr_t)tpcb->tp_fsuffix, sizeof( tpcb->tp_fsuffix));
3202a7cd
KS
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 */
301void
302tp_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",
9aed0596 308 tpcb, tpcb->tp_lref, *(u_short *)(tpcb->tp_lsuffix));
3202a7cd
KS
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 */
339tp_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
369int
370tp_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
393static
394copyQOSparms(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
a50e2bc0 400 bcopy((caddr_t)src, (caddr_t)dst, COPYSIZE);
3202a7cd
KS
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 */
432int
433tp_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",
a50e2bc0 447 tpcb->tp_sock, siso->siso_addr.isoa_genaddr[0], tpcb->tp_netservice,
3202a7cd
KS
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 }
a50e2bc0
KS
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
3202a7cd
KS
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.
a50e2bc0 476 if( siso->siso_addr.osinet_idi[1] == (u_char)IDI_OSINET )
3202a7cd 477 */
44f52ea5 478#define IDI_OSINET 0x0004 /* bcd of "0004" */
a50e2bc0 479 if( siso->siso_addr.isoa_genaddr[2] == (char)IDI_OSINET ) {
3202a7cd
KS
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:
a50e2bc0
KS
488 if (iso_localifa(siso))
489 tpcb->tp_flags |= TPF_PEER_ON_SAMENET;
3202a7cd
KS
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 }
3202a7cd
KS
565 if( error && vc_to_kill ) {
566 tp_netcmd( tpcb, CONN_CLOSE);
567 goto done;
568 }
3202a7cd
KS
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 }
576done:
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
600int
601tp_setup_perf(tpcb)
602 register struct tp_pcb *tpcb;
603{
604 register struct mbuf *q;
605
a50e2bc0
KS
606 if( tpcb->tp_p_meas == 0 ) {
607 MGET(q, M_WAITOK, MT_PCB);
3202a7cd
KS
608 if (q == 0)
609 return ENOBUFS;
a50e2bc0
KS
610 MCLGET(q, M_WAITOK);
611 if ((q->m_flags & M_EXT) == 0) {
612 (void) m_free(q);
3202a7cd 613 return ENOBUFS;
3202a7cd 614 }
a50e2bc0
KS
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;
3202a7cd
KS
626 }
627 return 0;
628}
629#endif TP_PERF_MEAS
630
631#ifdef ARGO_DEBUG
632dump_addr (addr)
633 register struct sockaddr *addr;
634{
635 switch( addr->sa_family ) {
636 case AF_INET:
a50e2bc0 637 dump_inaddr((struct sockaddr_in *)addr);
3202a7cd 638 break;
a50e2bc0 639#ifdef ISO
3202a7cd 640 case AF_ISO:
a50e2bc0 641 dump_isoaddr((struct sockaddr_iso *)addr);
3202a7cd 642 break;
a50e2bc0 643#endif ISO
3202a7cd
KS
644 default:
645 printf("BAD AF: 0x%x\n", addr->sa_family);
646 break;
647 }
648}
649
a50e2bc0
KS
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 */
658Dump_buf(buf, len)
659caddr_t buf;
660int 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
3202a7cd
KS
688#endif ARGO_DEBUG
689