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