get rid of useless tp_param global structure.
[unix-history] / usr / src / sys / netiso / tp_subr2.c
CommitLineData
7bcd1bb8
KB
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
378ea02c 7 * @(#)tp_subr2.c 7.16 (Berkeley) %G%
7bcd1bb8
KB
8 */
9
3202a7cd
KS
10/***********************************************************
11 Copyright IBM Corporation 1987
12
13 All Rights Reserved
14
15Permission to use, copy, modify, and distribute this software and its
16documentation for any purpose and without fee is hereby granted,
17provided that the above copyright notice appear in all copies and that
18both that copyright notice and this permission notice appear in
19supporting documentation, and that the name of IBM not be
20used in advertising or publicity pertaining to distribution of the
21software without specific, written prior permission.
22
23IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
24ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
25IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
26ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
27WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
28ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
29SOFTWARE.
30
31******************************************************************/
32
33/*
34 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
35 */
36/*
37 * ARGO TP
38 *
39 * $Header: tp_subr2.c,v 5.5 88/11/18 17:28:55 nhall Exp $
40 * $Source: /usr/argo/sys/netiso/RCS/tp_subr2.c,v $
41 *
42 * Some auxiliary routines:
7bcd1bb8
KB
43 * tp_protocol_error: required by xebec- called when a combo of state,
44 * event, predicate isn't covered for by the transition file.
45 * tp_indicate: gives indications(signals) to the user process
46 * tp_getoptions: initializes variables that are affected by the options
47 * chosen.
3202a7cd
KS
48 */
49
3202a7cd
KS
50/* this def'n is to cause the expansion of this macro in the
51 * routine tp_local_credit :
52 */
53#define LOCAL_CREDIT_EXPAND
54
55#include "param.h"
b7f6af29 56#include "systm.h"
3202a7cd
KS
57#include "mbuf.h"
58#include "socket.h"
59#include "socketvar.h"
60#include "domain.h"
61#include "protosw.h"
62#include "errno.h"
63#include "types.h"
64#include "time.h"
65#include "kernel.h"
66#undef MNULL
a50e2bc0
KS
67#include "argo_debug.h"
68#include "tp_param.h"
69#include "tp_ip.h"
70#include "iso.h"
71#include "iso_errno.h"
72#include "iso_pcb.h"
73#include "tp_timer.h"
74#include "tp_stat.h"
75#include "tp_tpdu.h"
76#include "tp_pcb.h"
77#include "tp_seq.h"
78#include "tp_trace.h"
79#include "tp_user.h"
80#include "cons.h"
3202a7cd 81
194a383a 82#include "../net/if.h"
01acbfa1 83#include "../net/if_types.h"
194a383a
KS
84#ifdef TRUE
85#undef FALSE
86#undef TRUE
87#endif
88#include "../netccitt/x25.h"
89#include "../netccitt/pk.h"
90#include "../netccitt/pk_var.h"
91
3202a7cd
KS
92/*
93 * NAME: tp_local_credit()
94 *
95 * CALLED FROM:
96 * tp_emit(), tp_usrreq()
97 *
98 * FUNCTION and ARGUMENTS:
99 * Computes the local credit and stashes it in tpcb->tp_lcredit.
100 * It's a macro in the production system rather than a procdure.
101 *
102 * RETURNS:
103 *
104 * SIDE EFFECTS:
105 *
106 * NOTES:
107 * This doesn't actually get called in a production system -
108 * the macro gets expanded instead in place of calls to this proc.
109 * But for debugging, we call this and that allows us to add
110 * debugging messages easily here.
111 */
112void
113tp_local_credit(tpcb)
114 struct tp_pcb *tpcb;
115{
116 LOCAL_CREDIT(tpcb);
117 IFDEBUG(D_CREDIT)
118 printf("ref 0x%x lcdt 0x%x l_tpdusize 0x%x decbit 0x%x\n",
378ea02c 119 tpcb->tp_lref,
3202a7cd
KS
120 tpcb->tp_lcredit,
121 tpcb->tp_l_tpdusize,
122 tpcb->tp_decbit,
123 tpcb->tp_cong_win
124 );
125 ENDDEBUG
126 IFTRACE(D_CREDIT)
127 tptraceTPCB(TPPTmisc,
128 "lcdt tpdusz \n",
129 tpcb->tp_lcredit, tpcb->tp_l_tpdusize, 0, 0);
130 ENDTRACE
131}
132
133/*
134 * NAME: tp_protocol_error()
135 *
136 * CALLED FROM:
137 * tp_driver(), when it doesn't know what to do with
138 * a combo of event, state, predicate
139 *
140 * FUNCTION and ARGUMENTS:
141 * print error mesg
142 *
143 * RETURN VALUE:
144 * EIO - always
145 *
146 * SIDE EFFECTS:
147 *
148 * NOTES:
149 */
150int
151tp_protocol_error(e,tpcb)
152 struct tp_event *e;
153 struct tp_pcb *tpcb;
154{
155 printf("TP PROTOCOL ERROR! tpcb 0x%x event 0x%x, state 0x%x\n",
156 tpcb, e->ev_number, tpcb->tp_state);
157 IFTRACE(D_DRIVER)
158 tptraceTPCB(TPPTmisc, "PROTOCOL ERROR tpcb event state",
159 tpcb, e->ev_number, tpcb->tp_state, 0 );
160 ENDTRACE
161 return EIO; /* for lack of anything better */
162}
163
164
165/* Not used at the moment */
166ProtoHook
167tp_drain()
168{
169 return 0;
170}
171
172
173/*
174 * NAME: tp_indicate()
175 *
176 * CALLED FROM:
177 * tp.trans when XPD arrive, when a connection is being disconnected by
178 * the arrival of a DR or ER, and when a connection times out.
179 *
180 * FUNCTION and ARGUMENTS:
181 * (ind) is the type of indication : T_DISCONNECT, T_XPD
182 * (error) is an E* value that will be put in the socket structure
183 * to be passed along to the user later.
184 * Gives a SIGURG to the user process or group indicated by the socket
185 * attached to the tpcb.
186 *
187 * RETURNS: Rien
188 *
189 * SIDE EFFECTS:
190 *
191 * NOTES:
192 */
193void
194tp_indicate(ind, tpcb, error)
195 int ind;
196 u_short error;
197 register struct tp_pcb *tpcb;
198{
199 register struct socket *so = tpcb->tp_sock;
200 IFTRACE(D_INDICATION)
9aed0596
KS
201 tptraceTPCB(TPPTindicate, ind, *(u_short *)(tpcb->tp_lsuffix),
202 *(u_short *)(tpcb->tp_fsuffix), error,so->so_pgid);
3202a7cd
KS
203 ENDTRACE
204 IFDEBUG(D_INDICATION)
a50e2bc0 205 char *ls, *fs;
3202a7cd
KS
206 ls = tpcb->tp_lsuffix,
207 fs = tpcb->tp_fsuffix,
208
209 printf(
a50e2bc0 210"indicate 0x%x lsuf 0x%02x%02x fsuf 0x%02x%02x err 0x%x noind 0x%x ref 0x%x\n",
3202a7cd
KS
211 ind,
212 *ls, *(ls+1), *fs, *(fs+1),
a50e2bc0 213 error, /*so->so_pgrp,*/
3202a7cd
KS
214 tpcb->tp_no_disc_indications,
215 tpcb->tp_lref);
216 ENDDEBUG
217
6726a5f3
KS
218 if (ind == ER_TPDU) {
219 register struct mbuf *m;
220 struct tp_disc_reason x;
221
222 if ((so->so_state & SS_CANTRCVMORE) == 0 &&
223 (m = m_get(M_DONTWAIT, MT_OOBDATA)) != 0) {
224
225 x.dr_hdr.cmsg_len = m->m_len = sizeof(x);
226 x.dr_hdr.cmsg_level = SOL_TRANSPORT;
227 x.dr_hdr.cmsg_type= TPOPT_DISC_REASON;
228 x.dr_reason = error;
229 *mtod(m, struct tp_disc_reason *) = x;
230 sbappendrecord(&tpcb->tp_Xrcv, m);
231 error = 0;
232 } else
233 error = ECONNRESET;
234 }
3202a7cd
KS
235 so->so_error = error;
236
237 if (ind == T_DISCONNECT) {
05b32603
KS
238 if (error == 0)
239 so->so_error = ENOTCONN;
3202a7cd
KS
240 if ( tpcb->tp_no_disc_indications )
241 return;
242 }
243 IFTRACE(D_INDICATION)
244 tptraceTPCB(TPPTmisc, "doing sohasoutofband(so)", so,0,0,0);
245 ENDTRACE
246 sohasoutofband(so);
247}
248
249/*
250 * NAME : tp_getoptions()
251 *
252 * CALLED FROM:
253 * tp.trans whenever we go into OPEN state
254 *
255 * FUNCTION and ARGUMENTS:
256 * sets the proper flags and values in the tpcb, to control
257 * the appropriate actions for the given class, options,
258 * sequence space, etc, etc.
259 *
260 * RETURNS: Nada
261 *
262 * SIDE EFFECTS:
263 *
264 * NOTES:
265 */
266void
267tp_getoptions(tpcb)
268struct tp_pcb *tpcb;
269{
270 tpcb->tp_seqmask =
271 tpcb->tp_xtd_format ? TP_XTD_FMT_MASK : TP_NML_FMT_MASK ;
272 tpcb->tp_seqbit =
273 tpcb->tp_xtd_format ? TP_XTD_FMT_BIT : TP_NML_FMT_BIT ;
274 tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1;
275 tpcb->tp_dt_ticks =
276 MAX(tpcb->tp_dt_ticks, (tpcb->tp_peer_acktime + 2));
7893315b
KS
277 (void) tp_rsyset(tpcb);
278
3202a7cd
KS
279}
280
281/*
282 * NAME: tp_recycle_tsuffix()
283 *
284 * CALLED FROM:
285 * Called when a ref is frozen.
286 *
287 * FUNCTION and ARGUMENTS:
288 * allows the suffix to be reused.
289 *
290 * RETURNS: zilch
291 *
292 * SIDE EFFECTS:
293 *
294 * NOTES:
295 */
296void
297tp_recycle_tsuffix(tpcb)
298 struct tp_pcb *tpcb;
299{
a50e2bc0
KS
300 bzero((caddr_t)tpcb->tp_lsuffix, sizeof( tpcb->tp_lsuffix));
301 bzero((caddr_t)tpcb->tp_fsuffix, sizeof( tpcb->tp_fsuffix));
3202a7cd
KS
302 tpcb->tp_fsuffixlen = tpcb->tp_lsuffixlen = 0;
303
304 (tpcb->tp_nlproto->nlp_recycle_suffix)(tpcb->tp_npcb);
305}
306
307/*
308 * NAME: tp_quench()
309 *
310 * CALLED FROM:
311 * tp{af}_quench() when ICMP source quench or similar thing arrives.
312 *
313 * FUNCTION and ARGUMENTS:
314 * Drop the congestion window back to 1.
315 * Congestion window scheme:
316 * Initial value is 1. ("slow start" as Nagle, et. al. call it)
317 * For each good ack that arrives, the congestion window is increased
318 * by 1 (up to max size of logical infinity, which is to say,
319 * it doesn't wrap around).
320 * Source quench causes it to drop back to 1.
321 * tp_send() uses the smaller of (regular window, congestion window).
322 * One retransmission strategy option is to have any retransmission
323 * cause reset the congestion window back to 1.
324 *
325 * (cmd) is either PRC_QUENCH: source quench, or
326 * PRC_QUENCH2: dest. quench (dec bit)
327 *
328 * RETURNS:
329 *
330 * SIDE EFFECTS:
331 *
332 * NOTES:
333 */
334void
335tp_quench( tpcb, cmd )
336 struct tp_pcb *tpcb;
337 int cmd;
338{
339 IFDEBUG(D_QUENCH)
340 printf("tp_quench tpcb 0x%x ref 0x%x sufx 0x%x\n",
9aed0596 341 tpcb, tpcb->tp_lref, *(u_short *)(tpcb->tp_lsuffix));
3202a7cd
KS
342 printf("cong_win 0x%x decbit 0x%x \n",
343 tpcb->tp_cong_win, tpcb->tp_decbit);
344 ENDDEBUG
345 switch(cmd) {
346 case PRC_QUENCH:
bdf41b09 347 tpcb->tp_cong_win = tpcb->tp_l_tpdusize;
3202a7cd
KS
348 IncStat(ts_quench);
349 break;
350 case PRC_QUENCH2:
bdf41b09 351 tpcb->tp_cong_win = tpcb->tp_l_tpdusize; /* might as well quench source also */
3202a7cd
KS
352 tpcb->tp_decbit = TP_DECBIT_CLEAR_COUNT;
353 IncStat(ts_rcvdecbit);
354 break;
355 }
356}
357
358
359/*
360 * NAME: tp_netcmd()
361 *
362 * CALLED FROM:
363 *
364 * FUNCTION and ARGUMENTS:
365 *
366 * RETURNS:
367 *
368 * SIDE EFFECTS:
369 *
370 * NOTES:
371 */
372tp_netcmd( tpcb, cmd )
373 struct tp_pcb *tpcb;
374 int cmd;
375{
194a383a
KS
376#ifdef TPCONS
377 struct isopcb *isop;
378 struct pklcd *lcp;
379
380 if (tpcb->tp_netservice != ISO_CONS)
381 return;
382 isop = (struct isopcb *)tpcb->tp_npcb;
383 lcp = (struct pklcd *)isop->isop_chan;
3202a7cd
KS
384 switch (cmd) {
385
386 case CONN_CLOSE:
387 case CONN_REFUSE:
01acbfa1
KS
388 if (isop->isop_refcnt == 1) {
389 /* This is really superfluous, since it would happen
390 anyway in iso_pcbdetach, although it is a courtesy
391 to free up the x.25 channel before the refwait timer
392 expires. */
393 lcp->lcd_upper = 0;
394 lcp->lcd_upnext = 0;
194a383a 395 pk_disconnect(lcp);
01acbfa1
KS
396 isop->isop_chan = 0;
397 isop->isop_refcnt = 0;
398 }
3202a7cd
KS
399 break;
400
401 default:
402 printf("tp_netcmd(0x%x, 0x%x) NOT IMPLEMENTED\n", tpcb, cmd);
403 break;
404 }
194a383a 405#else TPCONS
3202a7cd 406 printf("tp_netcmd(): X25 NOT CONFIGURED!!\n");
194a383a 407#endif
3202a7cd
KS
408}
409/*
410 * CALLED FROM:
411 * tp_ctloutput() and tp_emit()
412 * FUNCTION and ARGUMENTS:
413 * Convert a class mask to the highest numeric value it represents.
414 */
415
416int
417tp_mask_to_num(x)
418 u_char x;
419{
420 register int j;
421
422 for(j = 4; j>=0 ;j--) {
423 if(x & (1<<j))
424 break;
425 }
426 ASSERT( (j == 4) || (j == 0) ); /* for now */
427 if( (j != 4) && (j != 0) ) {
428 printf("ASSERTION ERROR: tp_mask_to_num: x 0x%x j %d\n",
429 x, j);
430 }
431 IFTRACE(D_TPINPUT)
432 tptrace(TPPTmisc, "tp_mask_to_num(x) returns j", x, j, 0, 0);
433 ENDTRACE
434 IFDEBUG(D_TPINPUT)
435 printf("tp_mask_to_num(0x%x) returns 0x%x\n", x, j);
436 ENDDEBUG
437 return j;
438}
439
440static
441copyQOSparms(src, dst)
442 struct tp_conn_param *src, *dst;
443{
444 /* copy all but the bits stuff at the end */
445#define COPYSIZE (12 * sizeof(short))
446
a50e2bc0 447 bcopy((caddr_t)src, (caddr_t)dst, COPYSIZE);
3202a7cd
KS
448 dst->p_tpdusize = src->p_tpdusize;
449 dst->p_ack_strat = src->p_ack_strat;
450 dst->p_rx_strat = src->p_rx_strat;
451#undef COPYSIZE
452}
453
454/*
455 * CALLED FROM:
456 * tp_usrreq on PRU_CONNECT and tp_input on receipt of CR
457 *
458 * FUNCTION and ARGUMENTS:
459 * route directly to x.25 if the address is type 37 - GROT.
460 * furthermore, let TP0 handle only type-37 addresses
461 *
462 * Since this assumes that its address argument is in a mbuf, the
463 * parameter was changed to reflect this assumtion. This also
464 * implies that an mbuf must be allocated when this is
465 * called from tp_input
466 *
467 * RETURNS:
468 * errno value :
469 * EAFNOSUPPORT if can't find an nl_protosw for x.25 (really could panic)
470 * ECONNREFUSED if trying to run TP0 with non-type 37 address
471 * possibly other E* returned from cons_netcmd()
472 * NOTE:
473 * Would like to eliminate as much of this as possible --
474 * only one set of defaults (let the user set the parms according
475 * to parameters provided in the directory service).
476 * Left here for now 'cause we don't yet have a clean way to handle
477 * it on the passive end.
478 */
479int
480tp_route_to( m, tpcb, channel)
481 struct mbuf *m;
482 register struct tp_pcb *tpcb;
194a383a 483 caddr_t channel;
3202a7cd
KS
484{
485 register struct sockaddr_iso *siso; /* NOTE: this may be a sockaddr_in */
486 extern struct tp_conn_param tp_conn_param[];
01acbfa1
KS
487 int error = 0, save_netservice = tpcb->tp_netservice;
488 register struct rtentry *rt = 0;
3202a7cd
KS
489
490 siso = mtod(m, struct sockaddr_iso *);
491 IFTRACE(D_CONN)
492 tptraceTPCB(TPPTmisc,
493 "route_to: so afi netservice class",
a50e2bc0 494 tpcb->tp_sock, siso->siso_addr.isoa_genaddr[0], tpcb->tp_netservice,
3202a7cd
KS
495 tpcb->tp_class);
496 ENDTRACE
497 IFDEBUG(D_CONN)
498 printf("tp_route_to( m x%x, channel 0x%x, tpcb 0x%x netserv 0x%x)\n",
499 m, channel, tpcb, tpcb->tp_netservice);
500 printf("m->mlen x%x, m->m_data:\n", m->m_len);
501 dump_buf(mtod(m, caddr_t), m->m_len);
502 ENDDEBUG
01acbfa1 503 if (channel) {
194a383a 504#ifdef TPCONS
01acbfa1 505 struct pklcd *lcp = (struct pklcd *)channel;
194a383a 506 struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext,
f15f73d2 507 *isop_new = (struct isopcb *)tpcb->tp_npcb;
01acbfa1
KS
508 /* The next 2 lines believe that you haven't
509 set any network level options or done a pcbconnect
510 and XXXXXXX'edly apply to both inpcb's and isopcb's */
194a383a
KS
511 remque(isop_new);
512 free(isop_new, M_PCB);
f15f73d2 513 tpcb->tp_npcb = (caddr_t)isop;
01acbfa1
KS
514 tpcb->tp_netservice = ISO_CONS;
515 tpcb->tp_nlproto = nl_protosw + ISO_CONS;
516 isop->isop_socket = tpcb->tp_sock;
517 if (isop->isop_refcnt == 0)
194a383a 518 iso_putsufx(isop, tpcb->tp_lsuffix, tpcb->tp_lsuffixlen, TP_LOCAL);
01acbfa1
KS
519 else
520 /* there are already connections sharing this */;
194a383a 521 isop->isop_refcnt++;
194a383a 522#endif
01acbfa1
KS
523 } else {
524 switch (siso->siso_family) {
525 default:
526 error = EAFNOSUPPORT;
527 goto done;
528#ifdef ISO
529 case AF_ISO:
530 tpcb->tp_netservice = ISO_CLNS;
531 if (rt = rtalloc1((struct sockaddr *)siso, 0)) {
532 rt->rt_refcnt--;
533 if (rt->rt_flags & RTF_PROTO1)
534 tpcb->tp_netservice = ISO_CONS;
535 }
536 break;
537#endif
538#ifdef INET
539 case AF_INET:
540 tpcb->tp_netservice = IN_CLNS;
541 }
542#endif
543 if (tpcb->tp_nlproto->nlp_afamily != siso->siso_family) {
544 IFDEBUG(D_CONN)
545 printf("tp_route_to( CHANGING nlproto old 0x%x new 0x%x)\n",
546 save_netservice, tpcb->tp_netservice);
547 ENDDEBUG
548 if (error = tp_set_npcb(tpcb))
549 goto done;
550 }
551 IFDEBUG(D_CONN)
552 printf("tp_route_to calling nlp_pcbconn, netserv %d\n",
553 tpcb->tp_netservice);
554 ENDDEBUG
555 tpcb->tp_nlproto = nl_protosw + tpcb->tp_netservice;
f15f73d2 556 error = (tpcb->tp_nlproto->nlp_pcbconn)(tpcb->tp_npcb, m);
01acbfa1 557 }
a50e2bc0
KS
558 if( error )
559 goto done;
560
3202a7cd 561 {
3202a7cd
KS
562 switch(tpcb->tp_netservice) {
563 case ISO_COSNS:
564 case ISO_CLNS:
565 /* This is a kludge but seems necessary so the passive end
566 * can get long enough timers. sigh.
a50e2bc0 567 if( siso->siso_addr.osinet_idi[1] == (u_char)IDI_OSINET )
3202a7cd 568 */
01acbfa1 569 if (rt && rt->rt_ifp && rt->rt_ifp->if_type == IFT_X25) {
3202a7cd
KS
570 if( tpcb->tp_dont_change_params == 0) {
571 copyQOSparms( &tp_conn_param[ISO_COSNS],
572 &tpcb->_tp_param);
573 }
574 tpcb->tp_flags |= TPF_NLQOS_PDN;
575 }
576 /* drop through to IN_CLNS*/
577 case IN_CLNS:
a50e2bc0
KS
578 if (iso_localifa(siso))
579 tpcb->tp_flags |= TPF_PEER_ON_SAMENET;
01acbfa1 580 if((tpcb->tp_class & TP_CLASS_4) == 0) {
3202a7cd
KS
581 error = EPROTOTYPE;
582 break;
583 }
584 tpcb->tp_class = TP_CLASS_4; /* IGNORE dont_change_parms */
585 break;
586
587 case ISO_CONS:
194a383a 588#ifdef TPCONS
3202a7cd
KS
589 tpcb->tp_flags |= TPF_NLQOS_PDN;
590 if( tpcb->tp_dont_change_params == 0 ) {
591 copyQOSparms( &tp_conn_param[ISO_CONS],
592 &tpcb->_tp_param);
593 }
594 /*
595 * for use over x.25 really need a small receive window,
596 * need to start slowly, need small max negotiable tpdu size,
597 * and need to use the congestion window to the max
598 * IGNORES tp_dont_change_params for these!
599 */
600 if( tpcb->tp_sock->so_snd.sb_hiwat > 512 ) {
601 (void) soreserve(tpcb->tp_sock, 512, 512 );/* GAG */
602 }
603 tpcb->tp_rx_strat = TPRX_USE_CW;
604
3202a7cd
KS
605 /* class 4 doesn't need to open a vc now - may use one already
606 * opened or may open one only when it sends a pkt.
607 */
194a383a 608#else TPCONS
3202a7cd 609 error = ECONNREFUSED;
194a383a 610#endif TPCONS
3202a7cd
KS
611 break;
612 default:
613 error = EPROTOTYPE;
614 }
615
3202a7cd 616 }
194a383a 617 if (error) {
3202a7cd
KS
618 tp_netcmd( tpcb, CONN_CLOSE);
619 goto done;
620 }
3202a7cd
KS
621 { /* start with the global rtt, rtv stats */
622 register int i =
623 (int) tpcb->tp_flags & (TPF_PEER_ON_SAMENET | TPF_NLQOS_PDN);
624
625 tpcb->tp_rtt = tp_stat.ts_rtt[i];
626 tpcb->tp_rtv = tp_stat.ts_rtv[i];
627 }
628done:
629 IFDEBUG(D_CONN)
630 printf("tp_route_to returns 0x%x\n", error);
631 ENDDEBUG
632 IFTRACE(D_CONN)
633 tptraceTPCB(TPPTmisc, "route_to: returns: error netserv class", error,
634 tpcb->tp_netservice, tpcb->tp_class, 0);
635 ENDTRACE
636 return error;
637}
638
74d56f78
KS
639
640/* class zero version */
641void
642tp0_stash( tpcb, e )
643 register struct tp_pcb *tpcb;
644 register struct tp_event *e;
645{
646#ifndef lint
647#define E e->ATTR(DT_TPDU)
648#else lint
649#define E e->ev_union.EV_DT_TPDU
650#endif lint
651
652 register struct sockbuf *sb = &tpcb->tp_sock->so_rcv;
653 register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb;
654
655 IFPERF(tpcb)
656 PStat(tpcb, Nb_from_ll) += E.e_datalen;
657 tpmeas(tpcb->tp_lref, TPtime_from_ll, &e->e_time,
658 E.e_seq, PStat(tpcb, Nb_from_ll), E.e_datalen);
659 ENDPERF
660
661 IFDEBUG(D_STASH)
662 printf("stash EQ: seq 0x%x datalen 0x%x eot 0x%x",
663 E.e_seq, E.e_datalen, E.e_eot);
664 ENDDEBUG
665
666 IFTRACE(D_STASH)
667 tptraceTPCB(TPPTmisc, "stash EQ: seq len eot",
668 E.e_seq, E.e_datalen, E.e_eot, 0);
669 ENDTRACE
670
671 if ( E.e_eot ) {
672 register struct mbuf *n = E.e_data;
673 n->m_flags |= M_EOR;
674 n->m_act = MNULL; /* set on tp_input */
675 }
676 sbappend(sb, E.e_data);
677 IFDEBUG(D_STASH)
678 dump_mbuf(sb->sb_mb, "stash 0: so_rcv after appending");
679 ENDDEBUG
680 if (tpcb->tp_netservice != ISO_CONS)
681 printf("tp0_stash: tp running over something wierd\n");
682 else {
683 register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
684 pk_flowcontrol(lcp, sbspace(sb) <= 0, 1);
685 }
686}
687
688void
689tp0_openflow(tpcb)
690register struct tp_pcb *tpcb;
691{
692 register struct isopcb *isop = (struct isopcb *)tpcb->tp_npcb;
693 if (tpcb->tp_netservice != ISO_CONS)
694 printf("tp0_openflow: tp running over something wierd\n");
695 else {
696 register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
697 if (lcp->lcd_rxrnr_condition)
698 pk_flowcontrol(lcp, 0, 0);
699 }
700}
701#ifndef TPCONS
702static
703pk_flowcontrol() {}
704#endif
705
3202a7cd
KS
706#ifdef TP_PERF_MEAS
707/*
708 * CALLED FROM:
709 * tp_ctloutput() when the user sets TPOPT_PERF_MEAS on
710 * and tp_newsocket() when a new connection is made from
711 * a listening socket with tp_perf_on == true.
712 * FUNCTION and ARGUMENTS:
713 * (tpcb) is the usual; this procedure gets a clear cluster mbuf for
714 * a tp_pmeas structure, and makes tpcb->tp_p_meas point to it.
715 * RETURN VALUE:
716 * ENOBUFS if it cannot get a cluster mbuf.
717 */
718
719int
720tp_setup_perf(tpcb)
721 register struct tp_pcb *tpcb;
722{
723 register struct mbuf *q;
724
a50e2bc0
KS
725 if( tpcb->tp_p_meas == 0 ) {
726 MGET(q, M_WAITOK, MT_PCB);
3202a7cd
KS
727 if (q == 0)
728 return ENOBUFS;
a50e2bc0
KS
729 MCLGET(q, M_WAITOK);
730 if ((q->m_flags & M_EXT) == 0) {
731 (void) m_free(q);
3202a7cd 732 return ENOBUFS;
3202a7cd 733 }
a50e2bc0
KS
734 q->m_len = sizeof (struct tp_pmeas);
735 tpcb->tp_p_mbuf = q;
736 tpcb->tp_p_meas = mtod(q, struct tp_pmeas *);
737 bzero( (caddr_t)tpcb->tp_p_meas, sizeof (struct tp_pmeas) );
738 IFDEBUG(D_PERF_MEAS)
739 printf(
740 "tpcb 0x%x so 0x%x ref 0x%x tp_p_meas 0x%x tp_perf_on 0x%x\n",
741 tpcb, tpcb->tp_sock, tpcb->tp_lref,
742 tpcb->tp_p_meas, tpcb->tp_perf_on);
743 ENDDEBUG
744 tpcb->tp_perf_on = 1;
3202a7cd
KS
745 }
746 return 0;
747}
748#endif TP_PERF_MEAS
749
750#ifdef ARGO_DEBUG
751dump_addr (addr)
752 register struct sockaddr *addr;
753{
754 switch( addr->sa_family ) {
755 case AF_INET:
a50e2bc0 756 dump_inaddr((struct sockaddr_in *)addr);
3202a7cd 757 break;
a50e2bc0 758#ifdef ISO
3202a7cd 759 case AF_ISO:
a50e2bc0 760 dump_isoaddr((struct sockaddr_iso *)addr);
3202a7cd 761 break;
a50e2bc0 762#endif ISO
3202a7cd
KS
763 default:
764 printf("BAD AF: 0x%x\n", addr->sa_family);
765 break;
766 }
767}
768
a50e2bc0
KS
769#define MAX_COLUMNS 8
770/*
771 * Dump the buffer to the screen in a readable format. Format is:
772 *
773 * hex/dec where hex is the hex format, dec is the decimal format.
774 * columns of hex/dec numbers will be printed, followed by the
775 * character representations (if printable).
776 */
777Dump_buf(buf, len)
778caddr_t buf;
779int len;
780{
781 int i,j;
67857e5a 782#define Buf ((u_char *)buf)
a50e2bc0
KS
783 printf("Dump buf 0x%x len 0x%x\n", buf, len);
784 for (i = 0; i < len; i += MAX_COLUMNS) {
785 printf("+%d:\t", i);
786 for (j = 0; j < MAX_COLUMNS; j++) {
787 if (i + j < len) {
67857e5a 788 printf("%x/%d\t", Buf[i+j], Buf[i+j]);
a50e2bc0
KS
789 } else {
790 printf(" ");
791 }
792 }
793
794 for (j = 0; j < MAX_COLUMNS; j++) {
795 if (i + j < len) {
67857e5a
KS
796 if (((Buf[i+j]) > 31) && ((Buf[i+j]) < 128))
797 printf("%c", Buf[i+j]);
a50e2bc0
KS
798 else
799 printf(".");
800 }
801 }
802 printf("\n");
803 }
804}
805
806
3202a7cd
KS
807#endif ARGO_DEBUG
808