FreeBSD/Linux Kernel Cross Reference
sys/netiso/tp_subr2.c
1 /* $NetBSD: tp_subr2.c,v 1.22 2003/08/11 15:17:31 itojun Exp $ */
2
3 /*-
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * @(#)tp_subr2.c 8.1 (Berkeley) 6/10/93
32 */
33
34 /***********************************************************
35 Copyright IBM Corporation 1987
36
37 All Rights Reserved
38
39 Permission to use, copy, modify, and distribute this software and its
40 documentation for any purpose and without fee is hereby granted,
41 provided that the above copyright notice appear in all copies and that
42 both that copyright notice and this permission notice appear in
43 supporting documentation, and that the name of IBM not be
44 used in advertising or publicity pertaining to distribution of the
45 software without specific, written prior permission.
46
47 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
48 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
49 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
50 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
51 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
52 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53 SOFTWARE.
54
55 ******************************************************************/
56
57 /*
58 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
59 */
60 /*
61 * Some auxiliary routines: tp_protocol_error: required by xebec- called when
62 * a combo of state, event, predicate isn't covered for by the transition
63 * file. tp_indicate: gives indications(signals) to the user process
64 * tp_getoptions: initializes variables that are affected by the options
65 * chosen.
66 */
67
68 #include <sys/cdefs.h>
69 __KERNEL_RCSID(0, "$NetBSD: tp_subr2.c,v 1.22 2003/08/11 15:17:31 itojun Exp $");
70
71 /*
72 * this def'n is to cause the expansion of this macro in the routine
73 * tp_local_credit :
74 */
75 #define LOCAL_CREDIT_EXPAND
76
77 #include "opt_inet.h"
78 #include "opt_ccitt.h"
79 #include "opt_iso.h"
80
81 #include <sys/param.h>
82 #include <sys/systm.h>
83 #include <sys/mbuf.h>
84 #include <sys/socket.h>
85 #include <sys/socketvar.h>
86 #include <sys/domain.h>
87 #include <sys/protosw.h>
88 #include <sys/errno.h>
89 #include <sys/time.h>
90 #include <sys/kernel.h>
91 #include <sys/queue.h>
92
93 #include <net/if.h>
94 #include <net/if_types.h>
95
96 #include <netiso/argo_debug.h>
97 #include <netiso/tp_param.h>
98 #include <netiso/tp_ip.h>
99 #include <netiso/iso.h>
100 #include <netiso/iso_errno.h>
101 #include <netiso/iso_pcb.h>
102 #include <netiso/iso_var.h>
103 #include <netiso/tp_timer.h>
104 #include <netiso/tp_stat.h>
105 #include <netiso/tp_tpdu.h>
106 #include <netiso/tp_pcb.h>
107 #include <netiso/tp_seq.h>
108 #include <netiso/tp_trace.h>
109 #include <netiso/tp_user.h>
110 #include <netiso/tp_var.h>
111 #include <netiso/cons.h>
112 #include <netiso/clnp.h>
113
114 #include <netccitt/x25.h>
115 #include <netccitt/pk.h>
116 #include <netccitt/pk_var.h>
117 #include <netccitt/pk_extern.h>
118
119 #if 0
120 static void copyQOSparms __P((struct tp_conn_param *, struct tp_conn_param *));
121 #endif
122
123 /*
124 * NAME: tp_local_credit()
125 *
126 * CALLED FROM:
127 * tp_emit(), tp_usrreq()
128 *
129 * FUNCTION and ARGUMENTS:
130 * Computes the local credit and stashes it in tpcb->tp_lcredit.
131 * It's a macro in the production system rather than a procdure.
132 *
133 * RETURNS:
134 *
135 * SIDE EFFECTS:
136 *
137 * NOTES:
138 * This doesn't actually get called in a production system -
139 * the macro gets expanded instead in place of calls to this proc.
140 * But for debugging, we call this and that allows us to add
141 * debugging messages easily here.
142 */
143 void
144 tp_local_credit(tpcb)
145 struct tp_pcb *tpcb;
146 {
147 LOCAL_CREDIT(tpcb);
148 #ifdef ARGO_DEBUG
149 if (argo_debug[D_CREDIT]) {
150 printf("ref 0x%x lcdt 0x%x l_tpdusize 0x%x decbit 0x%x cong_win 0x%lx\n",
151 tpcb->tp_lref,
152 tpcb->tp_lcredit,
153 tpcb->tp_l_tpdusize,
154 tpcb->tp_decbit,
155 tpcb->tp_cong_win
156 );
157 }
158 #endif
159 #ifdef TPPT
160 if (tp_traceflags[D_CREDIT]) {
161 tptraceTPCB(TPPTmisc,
162 "lcdt tpdusz \n",
163 tpcb->tp_lcredit, tpcb->tp_l_tpdusize, 0, 0);
164 }
165 #endif
166 }
167
168 /*
169 * NAME: tp_protocol_error()
170 *
171 * CALLED FROM:
172 * tp_driver(), when it doesn't know what to do with
173 * a combo of event, state, predicate
174 *
175 * FUNCTION and ARGUMENTS:
176 * print error mesg
177 *
178 * RETURN VALUE:
179 * EIO - always
180 *
181 * SIDE EFFECTS:
182 *
183 * NOTES:
184 */
185 int
186 tp_protocol_error(e, tpcb)
187 struct tp_event *e;
188 struct tp_pcb *tpcb;
189 {
190 printf("TP PROTOCOL ERROR! tpcb %p event 0x%x, state 0x%x\n",
191 tpcb, e->ev_number, tpcb->tp_state);
192 #ifdef TPPT
193 if (tp_traceflags[D_DRIVER]) {
194 tptraceTPCB(TPPTmisc, "PROTOCOL ERROR tpcb event state",
195 tpcb, e->ev_number, tpcb->tp_state, 0);
196 }
197 #endif
198 return EIO; /* for lack of anything better */
199 }
200
201
202 /* Not used at the moment */
203 void
204 tp_drain()
205 {
206 }
207
208
209 /*
210 * NAME: tp_indicate()
211 *
212 * CALLED FROM:
213 * tp.trans when XPD arrive, when a connection is being disconnected by
214 * the arrival of a DR or ER, and when a connection times out.
215 *
216 * FUNCTION and ARGUMENTS:
217 * (ind) is the type of indication : T_DISCONNECT, T_XPD
218 * (error) is an E* value that will be put in the socket structure
219 * to be passed along to the user later.
220 * Gives a SIGURG to the user process or group indicated by the socket
221 * attached to the tpcb.
222 *
223 * RETURNS: Rien
224 *
225 * SIDE EFFECTS:
226 *
227 * NOTES:
228 */
229 void
230 tp_indicate(ind, tpcb, error)
231 int ind;
232 u_short error;
233 struct tp_pcb *tpcb;
234 {
235 struct socket *so = tpcb->tp_sock;
236 #ifdef TPPT
237 if (tp_traceflags[D_INDICATION]) {
238 tptraceTPCB(TPPTindicate, ind, *(u_short *) (tpcb->tp_lsuffix),
239 *(u_short *) (tpcb->tp_fsuffix), error, so->so_pgid);
240 }
241 #endif
242 #ifdef ARGO_DEBUG
243 if (argo_debug[D_INDICATION]) {
244 char *ls, *fs;
245 ls = tpcb->tp_lsuffix,
246 fs = tpcb->tp_fsuffix,
247
248 printf(
249 "indicate 0x%x lsuf 0x%02x%02x fsuf 0x%02x%02x err 0x%x noind 0x%x ref 0x%x\n",
250 ind,
251 *ls, *(ls + 1), *fs, *(fs + 1),
252 error, /* so->so_pgrp, */
253 tpcb->tp_no_disc_indications,
254 tpcb->tp_lref);
255 }
256 #endif
257
258 if (ind == ER_TPDU) {
259 struct mbuf *m;
260 struct tp_disc_reason x;
261
262 if ((so->so_state & SS_CANTRCVMORE) == 0 &&
263 (m = m_get(M_DONTWAIT, MT_OOBDATA)) != 0) {
264
265 x.dr_hdr.cmsg_len = m->m_len = sizeof(x);
266 x.dr_hdr.cmsg_level = SOL_TRANSPORT;
267 x.dr_hdr.cmsg_type = TPOPT_DISC_REASON;
268 x.dr_reason = error;
269 *mtod(m, struct tp_disc_reason *) = x;
270 sbappendrecord(&tpcb->tp_Xrcv, m);
271 error = 0;
272 } else
273 error = ECONNRESET;
274 }
275 so->so_error = error;
276
277 if (ind == T_DISCONNECT) {
278 if (error == 0)
279 so->so_error = ENOTCONN;
280 if (tpcb->tp_no_disc_indications)
281 return;
282 }
283 #ifdef TPPT
284 if (tp_traceflags[D_INDICATION]) {
285 tptraceTPCB(TPPTmisc, "doing sohasoutofband(so)", so, 0, 0, 0);
286 }
287 #endif
288 sohasoutofband(so);
289 }
290
291 /*
292 * NAME : tp_getoptions()
293 *
294 * CALLED FROM:
295 * tp.trans whenever we go into OPEN state
296 *
297 * FUNCTION and ARGUMENTS:
298 * sets the proper flags and values in the tpcb, to control
299 * the appropriate actions for the given class, options,
300 * sequence space, etc, etc.
301 *
302 * RETURNS: Nada
303 *
304 * SIDE EFFECTS:
305 *
306 * NOTES:
307 */
308 void
309 tp_getoptions(tpcb)
310 struct tp_pcb *tpcb;
311 {
312 tpcb->tp_seqmask =
313 tpcb->tp_xtd_format ? TP_XTD_FMT_MASK : TP_NML_FMT_MASK;
314 tpcb->tp_seqbit =
315 tpcb->tp_xtd_format ? TP_XTD_FMT_BIT : TP_NML_FMT_BIT;
316 tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1;
317 tpcb->tp_dt_ticks =
318 max(tpcb->tp_dt_ticks, (tpcb->tp_peer_acktime + 2));
319 tp_rsyset(tpcb);
320
321 }
322
323 /*
324 * NAME: tp_recycle_tsuffix()
325 *
326 * CALLED FROM:
327 * Called when a ref is frozen.
328 *
329 * FUNCTION and ARGUMENTS:
330 * allows the suffix to be reused.
331 *
332 * RETURNS: zilch
333 *
334 * SIDE EFFECTS:
335 *
336 * NOTES:
337 */
338 void
339 tp_recycle_tsuffix(v)
340 void *v;
341 {
342 struct tp_pcb *tpcb = v;
343 bzero((caddr_t) tpcb->tp_lsuffix, sizeof(tpcb->tp_lsuffix));
344 bzero((caddr_t) tpcb->tp_fsuffix, sizeof(tpcb->tp_fsuffix));
345 tpcb->tp_fsuffixlen = tpcb->tp_lsuffixlen = 0;
346
347 (tpcb->tp_nlproto->nlp_recycle_suffix) (tpcb->tp_npcb);
348 }
349
350 /*
351 * NAME: tp_quench()
352 *
353 * CALLED FROM:
354 * tp{af}_quench() when ICMP source quench or similar thing arrives.
355 *
356 * FUNCTION and ARGUMENTS:
357 * Drop the congestion window back to 1.
358 * Congestion window scheme:
359 * Initial value is 1. ("slow start" as Nagle, et. al. call it)
360 * For each good ack that arrives, the congestion window is increased
361 * by 1 (up to max size of logical infinity, which is to say,
362 * it doesn't wrap around).
363 * Source quench causes it to drop back to 1.
364 * tp_send() uses the smaller of (regular window, congestion window).
365 * One retransmission strategy option is to have any retransmission
366 * cause reset the congestion window back to 1.
367 *
368 * (cmd) is either PRC_QUENCH: source quench, or
369 * PRC_QUENCH2: dest. quench (dec bit)
370 *
371 * RETURNS:
372 *
373 * SIDE EFFECTS:
374 *
375 * NOTES:
376 */
377 void
378 tp_quench(ipcb, cmd)
379 struct inpcb *ipcb;
380 int cmd;
381 {
382 struct tp_pcb *tpcb = (struct tp_pcb *) ipcb;
383 #ifdef ARGO_DEBUG
384 if (argo_debug[D_QUENCH]) {
385 printf("tp_quench tpcb %p ref 0x%x sufx 0x%x\n",
386 tpcb, tpcb->tp_lref, *(u_short *) (tpcb->tp_lsuffix));
387 printf("cong_win 0x%lx decbit 0x%x \n",
388 tpcb->tp_cong_win, tpcb->tp_decbit);
389 }
390 #endif
391 switch (cmd) {
392 case PRC_QUENCH:
393 tpcb->tp_cong_win = tpcb->tp_l_tpdusize;
394 IncStat(ts_quench);
395 break;
396 case PRC_QUENCH2:
397 /* might as well quench source also */
398 tpcb->tp_cong_win = tpcb->tp_l_tpdusize;
399 tpcb->tp_decbit = TP_DECBIT_CLEAR_COUNT;
400 IncStat(ts_rcvdecbit);
401 break;
402 }
403 }
404
405
406 /*
407 * NAME: tp_netcmd()
408 *
409 * CALLED FROM:
410 *
411 * FUNCTION and ARGUMENTS:
412 *
413 * RETURNS:
414 *
415 * SIDE EFFECTS:
416 *
417 * NOTES:
418 */
419 void
420 tp_netcmd(tpcb, cmd)
421 struct tp_pcb *tpcb;
422 int cmd;
423 {
424 #ifdef TPCONS
425 struct isopcb *isop;
426 struct pklcd *lcp;
427
428 if (tpcb->tp_netservice != ISO_CONS)
429 return;
430 isop = (struct isopcb *) tpcb->tp_npcb;
431 lcp = (struct pklcd *) isop->isop_chan;
432 switch (cmd) {
433
434 case CONN_CLOSE:
435 case CONN_REFUSE:
436 if (isop->isop_refcnt == 1) {
437 /*
438 * This is really superfluous, since it would happen
439 * anyway in iso_pcbdetach, although it is a courtesy
440 * to free up the x.25 channel before the refwait
441 * timer expires.
442 */
443 lcp->lcd_upper = 0;
444 lcp->lcd_upnext = 0;
445 pk_disconnect(lcp);
446 isop->isop_chan = 0;
447 isop->isop_refcnt = 0;
448 }
449 break;
450
451 default:
452 printf("tp_netcmd(0x%x, 0x%x) NOT IMPLEMENTED\n", tpcb, cmd);
453 break;
454 }
455 #else /* TPCONS */
456 printf("tp_netcmd(): X25 NOT CONFIGURED!!\n");
457 #endif
458 }
459
460 /*
461 * CALLED FROM:
462 * tp_ctloutput() and tp_emit()
463 * FUNCTION and ARGUMENTS:
464 * Convert a class mask to the highest numeric value it represents.
465 */
466 int
467 tp_mask_to_num(x)
468 u_char x;
469 {
470 int j;
471
472 for (j = 4; j >= 0; j--) {
473 if (x & (1 << j))
474 break;
475 }
476 ASSERT((j == 4) || (j == 0)); /* for now */
477 if ((j != 4) && (j != 0)) {
478 printf("ASSERTION ERROR: tp_mask_to_num: x 0x%x j %d\n",
479 x, j);
480 }
481 #ifdef TPPT
482 if (tp_traceflags[D_TPINPUT]) {
483 tptrace(TPPTmisc, "tp_mask_to_num(x) returns j", x, j, 0, 0);
484 }
485 #endif
486 #ifdef ARGO_DEBUG
487 if (argo_debug[D_TPINPUT]) {
488 printf("tp_mask_to_num(0x%x) returns 0x%x\n", x, j);
489 }
490 #endif
491 return j;
492 }
493
494 #if 0
495 static void
496 copyQOSparms(src, dst)
497 struct tp_conn_param *src, *dst;
498 {
499 /* copy all but the bits stuff at the end */
500 #define COPYSIZE (12 * sizeof(short))
501
502 bcopy((caddr_t) src, (caddr_t) dst, COPYSIZE);
503 dst->p_tpdusize = src->p_tpdusize;
504 dst->p_ack_strat = src->p_ack_strat;
505 dst->p_rx_strat = src->p_rx_strat;
506 #undef COPYSIZE
507 }
508 #endif
509
510 /*
511 * Determine a reasonable value for maxseg size.
512 * If the route is known, check route for mtu.
513 * We also initialize the congestion/slow start
514 * window to be a single segment if the destination isn't local.
515 * While looking at the routing entry, we also initialize other path-dependent
516 * parameters from pre-set or cached values in the routing entry.
517 */
518 void
519 tp_mss(tpcb, nhdr_size)
520 struct tp_pcb *tpcb;
521 int nhdr_size;
522 {
523 struct rtentry *rt;
524 struct ifnet *ifp;
525 int rtt, mss;
526 u_long bufsize;
527 int i, ssthresh = 0, rt_mss;
528 struct socket *so;
529
530 if (tpcb->tp_ptpdusize)
531 mss = tpcb->tp_ptpdusize << 7;
532 else
533 mss = 1 << tpcb->tp_tpdusize;
534 so = tpcb->tp_sock;
535 if ((rt = *(tpcb->tp_routep)) == 0) {
536 bufsize = so->so_rcv.sb_hiwat;
537 goto punt_route;
538 }
539 ifp = rt->rt_ifp;
540
541 #ifdef RTV_MTU /* if route characteristics exist ... */
542 /*
543 * While we're here, check if there's an initial rtt
544 * or rttvar. Convert from the route-table units
545 * to hz ticks for the smoothed timers and slow-timeout units
546 * for other inital variables.
547 */
548 if (tpcb->tp_rtt == 0 && (rtt = rt->rt_rmx.rmx_rtt)) {
549 tpcb->tp_rtt = rtt * hz / RTM_RTTUNIT;
550 if (rt->rt_rmx.rmx_rttvar)
551 tpcb->tp_rtv = rt->rt_rmx.rmx_rttvar
552 * hz / RTM_RTTUNIT;
553 else
554 tpcb->tp_rtv = tpcb->tp_rtt;
555 }
556 /*
557 * if there's an mtu associated with the route, use it
558 */
559 if (rt->rt_rmx.rmx_mtu)
560 rt_mss = rt->rt_rmx.rmx_mtu - nhdr_size;
561 else
562 #endif /* RTV_MTU */
563 rt_mss = (ifp->if_mtu - nhdr_size);
564 if (tpcb->tp_ptpdusize == 0 || /* assume application doesn't care */
565 mss > rt_mss /* network won't support what was asked for */ )
566 mss = rt_mss;
567 /* can propose mtu which are multiples of 128 */
568 mss &= ~0x7f;
569 /*
570 * If there's a pipesize, change the socket buffer
571 * to that size.
572 */
573 #ifdef RTV_SPIPE
574 if ((bufsize = rt->rt_rmx.rmx_sendpipe) > 0) {
575 #endif
576 bufsize = min(bufsize, so->so_snd.sb_hiwat);
577 (void) sbreserve(&so->so_snd, bufsize);
578 }
579 #ifdef RTV_SPIPE
580 if ((bufsize = rt->rt_rmx.rmx_recvpipe) > 0) {
581 #endif
582 bufsize = min(bufsize, so->so_rcv.sb_hiwat);
583 (void) sbreserve(&so->so_rcv, bufsize);
584 } else
585 bufsize = so->so_rcv.sb_hiwat;
586 #ifdef RTV_SSTHRESH
587 /*
588 * There's some sort of gateway or interface
589 * buffer limit on the path. Use this to set
590 * the slow start threshhold, but set the
591 * threshold to no less than 2*mss.
592 */
593 ssthresh = rt->rt_rmx.rmx_ssthresh;
594 punt_route:
595 /*
596 * The current mss is initialized to the default value.
597 * If we compute a smaller value, reduce the current mss.
598 * If we compute a larger value, return it for use in sending
599 * a max seg size option.
600 * If we received an offer, don't exceed it.
601 * However, do not accept offers under 128 bytes.
602 */
603 if (tpcb->tp_l_tpdusize)
604 mss = min(mss, tpcb->tp_l_tpdusize);
605 /*
606 * We want a minimum recv window of 4 packets to
607 * signal packet loss by duplicate acks.
608 */
609 mss = min(mss, bufsize >> 2) & ~0x7f;
610 mss = max(mss, 128); /* sanity */
611 tpcb->tp_cong_win =
612 (rt == 0 || (rt->rt_flags & RTF_GATEWAY)) ? mss : bufsize;
613 tpcb->tp_l_tpdusize = mss;
614 tp_rsyset(tpcb);
615 tpcb->tp_ssthresh = max(2 * mss, ssthresh);
616 /* Calculate log2 of mss */
617 for (i = TP_MIN_TPDUSIZE + 1; i <= TP_MAX_TPDUSIZE; i++)
618 if ((1 << i) > mss)
619 break;
620 i--;
621 tpcb->tp_tpdusize = i;
622 #endif /* RTV_MTU */
623 }
624
625 /*
626 * CALLED FROM:
627 * tp_usrreq on PRU_CONNECT and tp_input on receipt of CR
628 *
629 * FUNCTION and ARGUMENTS:
630 * -- An mbuf containing the peer's network address.
631 * -- Our control block, which will be modified
632 * -- In the case of cons, a control block for that layer.
633 *
634 *
635 * RETURNS:
636 * errno value :
637 * EAFNOSUPPORT if can't find an nl_protosw for x.25 (really could panic)
638 * ECONNREFUSED if trying to run TP0 with non-type 37 address
639 * possibly other E* returned from cons_netcmd()
640 *
641 * SIDE EFFECTS:
642 * Determines recommended tpdusize, buffering and intial delays
643 * based on information cached on the route.
644 */
645 int
646 tp_route_to(m, tpcb, channel)
647 struct mbuf *m;
648 struct tp_pcb *tpcb;
649 caddr_t channel;
650 {
651 struct sockaddr_iso *siso; /* NOTE: this may be a
652 * sockaddr_in */
653 int error = 0, save_netservice = tpcb->tp_netservice;
654 struct rtentry *rt = 0;
655 int nhdr_size;
656
657 siso = mtod(m, struct sockaddr_iso *);
658 #ifdef TPPT
659 if (tp_traceflags[D_CONN]) {
660 tptraceTPCB(TPPTmisc,
661 "route_to: so afi netservice class",
662 tpcb->tp_sock, siso->siso_addr.isoa_genaddr[0], tpcb->tp_netservice,
663 tpcb->tp_class);
664 }
665 #endif
666 #ifdef ARGO_DEBUG
667 if (argo_debug[D_CONN]) {
668 printf("tp_route_to( m %p, channel %p, tpcb %p netserv 0x%x)\n",
669 m, channel, tpcb, tpcb->tp_netservice);
670 printf("m->mlen x%x, m->m_data:\n", m->m_len);
671 dump_buf(mtod(m, caddr_t), m->m_len);
672 }
673 #endif
674 if (channel) {
675 #ifdef TPCONS
676 struct pklcd *lcp = (struct pklcd *) channel;
677 struct isopcb *isop = (struct isopcb *) lcp->lcd_upnext,
678 *isop_new = (struct isopcb *) tpcb->tp_npcb;
679 /*
680 * The next 2 lines believe that you haven't set any network
681 * level options or done a pcbconnect and XXXXXXX'edly apply
682 * to both inpcb's and isopcb's
683 */
684 remque(isop_new);
685 free(isop_new, M_PCB);
686 tpcb->tp_npcb = (caddr_t) isop;
687 tpcb->tp_netservice = ISO_CONS;
688 tpcb->tp_nlproto = nl_protosw + ISO_CONS;
689 if (isop->isop_refcnt++ == 0) {
690 iso_putsufx(isop, tpcb->tp_lsuffix,
691 tpcb->tp_lsuffixlen, TP_LOCAL);
692 isop->isop_socket = tpcb->tp_sock;
693 }
694 #endif
695 } else {
696 switch (siso->siso_family) {
697 default:
698 error = EAFNOSUPPORT;
699 goto done;
700 #ifdef ISO
701 case AF_ISO:
702 {
703 struct isopcb *isop = (struct isopcb *) tpcb->tp_npcb;
704 int flags = tpcb->tp_sock->so_options & SO_DONTROUTE;
705 tpcb->tp_netservice = ISO_CLNS;
706 if (clnp_route(&siso->siso_addr, &isop->isop_route,
707 flags, NULL, NULL) == 0) {
708 rt = isop->isop_route.ro_rt;
709 if (rt && rt->rt_flags & RTF_PROTO1)
710 tpcb->tp_netservice = ISO_CONS;
711 }
712 } break;
713 #endif
714 #ifdef INET
715 case AF_INET:
716 tpcb->tp_netservice = IN_CLNS;
717 #endif
718 }
719 if (tpcb->tp_nlproto->nlp_afamily != siso->siso_family) {
720 #ifdef ARGO_DEBUG
721 if (argo_debug[D_CONN]) {
722 printf("tp_route_to( CHANGING nlproto old 0x%x new 0x%x)\n",
723 save_netservice, tpcb->tp_netservice);
724 }
725 #endif
726 if ((error = tp_set_npcb(tpcb)) != 0)
727 goto done;
728 }
729 #ifdef ARGO_DEBUG
730 if (argo_debug[D_CONN]) {
731 printf("tp_route_to calling nlp_pcbconn, netserv %d\n",
732 tpcb->tp_netservice);
733 }
734 #endif
735 tpcb->tp_nlproto = nl_protosw + tpcb->tp_netservice;
736 error = (*tpcb->tp_nlproto->nlp_pcbconn) (tpcb->tp_npcb, m);
737 }
738 if (error)
739 goto done;
740 /* only gets common info */
741 nhdr_size = (*tpcb->tp_nlproto->nlp_mtu)(tpcb);
742 tp_mss(tpcb, nhdr_size);
743 done:
744 #ifdef ARGO_DEBUG
745 if (argo_debug[D_CONN]) {
746 printf("tp_route_to returns 0x%x\n", error);
747 }
748 #endif
749 #ifdef TPPT
750 if (tp_traceflags[D_CONN]) {
751 tptraceTPCB(TPPTmisc, "route_to: returns: error netserv class", error,
752 tpcb->tp_netservice, tpcb->tp_class, 0);
753 }
754 #endif
755 return error;
756 }
757
758 #ifndef CCITT
759 void
760 pk_flowcontrol(lcp, foo, bar)
761 struct pklcd *lcp;
762 int foo, bar;
763 {
764 }
765 #endif
766
767 /* class zero version */
768 void
769 tp0_stash(tpcb, e)
770 struct tp_pcb *tpcb;
771 struct tp_event *e;
772 {
773 #define E e->TPDU_ATTR(DT)
774
775 struct sockbuf *sb = &tpcb->tp_sock->so_rcv;
776 struct isopcb *isop = (struct isopcb *) tpcb->tp_npcb;
777
778 #ifdef TP_PERF_MEAS
779 if (DOPERF(tpcb)) {
780 PStat(tpcb, Nb_from_ll) += E.e_datalen;
781 tpmeas(tpcb->tp_lref, TPtime_from_ll, &e->e_time,
782 E.e_seq, PStat(tpcb, Nb_from_ll), E.e_datalen);
783 }
784 #endif
785
786 #ifdef ARGO_DEBUG
787 if (argo_debug[D_STASH]) {
788 printf("stash EQ: seq 0x%x datalen 0x%x eot 0x%x",
789 E.e_seq, E.e_datalen, E.e_eot);
790 }
791 #endif
792
793 #ifdef TPPT
794 if (tp_traceflags[D_STASH]) {
795 tptraceTPCB(TPPTmisc, "stash EQ: seq len eot",
796 E.e_seq, E.e_datalen, E.e_eot, 0);
797 }
798 #endif
799
800 if (E.e_eot) {
801 struct mbuf *n = E.e_data;
802 n->m_flags |= M_EOR;
803 n->m_nextpkt = NULL; /* set on tp_input */
804 }
805 sbappend(sb, E.e_data);
806 #ifdef ARGO_DEBUG
807 if (argo_debug[D_STASH]) {
808 dump_mbuf(sb->sb_mb, "stash 0: so_rcv after appending");
809 }
810 #endif
811 if (tpcb->tp_netservice != ISO_CONS)
812 printf("tp0_stash: tp running over something weird\n");
813 else {
814 struct pklcd *lcp = (struct pklcd *) isop->isop_chan;
815 pk_flowcontrol(lcp, sbspace(sb) <= 0, 1);
816 }
817 }
818
819 void
820 tp0_openflow(tpcb)
821 struct tp_pcb *tpcb;
822 {
823 struct isopcb *isop = (struct isopcb *) tpcb->tp_npcb;
824 if (tpcb->tp_netservice != ISO_CONS)
825 printf("tp0_openflow: tp running over something weird\n");
826 else {
827 struct pklcd *lcp = (struct pklcd *) isop->isop_chan;
828 if (lcp->lcd_rxrnr_condition)
829 pk_flowcontrol(lcp, 0, 0);
830 }
831 }
832
833 #ifdef TP_PERF_MEAS
834 /*
835 * CALLED FROM:
836 * tp_ctloutput() when the user sets TPOPT_PERF_MEAS on
837 * and tp_newsocket() when a new connection is made from
838 * a listening socket with tp_perf_on == true.
839 * FUNCTION and ARGUMENTS:
840 * (tpcb) is the usual; this procedure gets a clear cluster mbuf for
841 * a tp_pmeas structure, and makes tpcb->tp_p_meas point to it.
842 * RETURN VALUE:
843 * ENOBUFS if it cannot get a cluster mbuf.
844 */
845
846 int
847 tp_setup_perf(tpcb)
848 struct tp_pcb *tpcb;
849 {
850 if (tpcb->tp_p_meas == 0) {
851 tpcb->tp_p_meas = malloc(sizeof(struct tp_pmeas), M_PCB, M_WAITOK);
852 bzero((caddr_t)tpcb->tp_p_meas, sizeof(struct tp_pmeas));
853 #ifdef ARGO_DEBUG
854 if (argo_debug[D_PERF_MEAS]) {
855 printf(
856 "tpcb 0x%x so 0x%x ref 0x%x tp_p_meas 0x%x tp_perf_on 0x%x\n",
857 tpcb, tpcb->tp_sock, tpcb->tp_lref,
858 tpcb->tp_p_meas, tpcb->tp_perf_on);
859 }
860 #endif
861 tpcb->tp_perf_on = 1;
862 }
863 return 0;
864 }
865 #endif /* TP_PERF_MEAS */
866
867 #ifdef ARGO_DEBUG
868 void
869 dump_addr(addr)
870 struct sockaddr *addr;
871 {
872 switch (addr->sa_family) {
873 case AF_INET:
874 dump_inaddr(satosin(addr));
875 break;
876 #ifdef ISO
877 case AF_ISO:
878 dump_isoaddr(satosiso(addr));
879 break;
880 #endif /* ISO */
881 default:
882 printf("BAD AF: 0x%x\n", addr->sa_family);
883 break;
884 }
885 }
886
887 #define MAX_COLUMNS 8
888 /*
889 * Dump the buffer to the screen in a readable format. Format is:
890 *
891 * hex/dec where hex is the hex format, dec is the decimal format.
892 * columns of hex/dec numbers will be printed, followed by the
893 * character representations (if printable).
894 */
895 void
896 Dump_buf(buf, len)
897 caddr_t buf;
898 int len;
899 {
900 int i, j;
901 #define Buf ((u_char *)buf)
902 printf("Dump buf %p len 0x%x\n", buf, len);
903 for (i = 0; i < len; i += MAX_COLUMNS) {
904 printf("+%d:\t", i);
905 for (j = 0; j < MAX_COLUMNS; j++) {
906 if (i + j < len) {
907 printf("%x/%d\t", Buf[i + j], Buf[i + j]);
908 } else {
909 printf(" ");
910 }
911 }
912
913 for (j = 0; j < MAX_COLUMNS; j++) {
914 if (i + j < len) {
915 if (((Buf[i + j]) > 31) && ((Buf[i + j]) < 128))
916 printf("%c", Buf[i + j]);
917 else
918 printf(".");
919 }
920 }
921 printf("\n");
922 }
923 }
924 #endif /* ARGO_DEBUG */
Cache object: 33b12f967cc9e3a3792851b8d5fd37c7
|