FreeBSD/Linux Kernel Cross Reference
sys/netiso/tp_subr2.c
1 /* $NetBSD: tp_subr2.c,v 1.26 2004/04/22 01:01:41 matt 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.26 2004/04/22 01:01:41 matt 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 (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(struct tp_pcb *tpcb)
145 {
146 LOCAL_CREDIT(tpcb);
147 #ifdef ARGO_DEBUG
148 if (argo_debug[D_CREDIT]) {
149 printf("ref 0x%x lcdt 0x%x l_tpdusize 0x%x decbit 0x%x cong_win 0x%lx\n",
150 tpcb->tp_lref,
151 tpcb->tp_lcredit,
152 tpcb->tp_l_tpdusize,
153 tpcb->tp_decbit,
154 tpcb->tp_cong_win
155 );
156 }
157 #endif
158 #ifdef TPPT
159 if (tp_traceflags[D_CREDIT]) {
160 tptraceTPCB(TPPTmisc,
161 "lcdt tpdusz \n",
162 tpcb->tp_lcredit, tpcb->tp_l_tpdusize, 0, 0);
163 }
164 #endif
165 }
166
167 /*
168 * NAME: tp_protocol_error()
169 *
170 * CALLED FROM:
171 * tp_driver(), when it doesn't know what to do with
172 * a combo of event, state, predicate
173 *
174 * FUNCTION and ARGUMENTS:
175 * print error mesg
176 *
177 * RETURN VALUE:
178 * EIO - always
179 *
180 * SIDE EFFECTS:
181 *
182 * NOTES:
183 */
184 int
185 tp_protocol_error(struct tp_event *e, struct tp_pcb *tpcb)
186 {
187 printf("TP PROTOCOL ERROR! tpcb %p event 0x%x, state 0x%x\n",
188 tpcb, e->ev_number, tpcb->tp_state);
189 #ifdef TPPT
190 if (tp_traceflags[D_DRIVER]) {
191 tptraceTPCB(TPPTmisc, "PROTOCOL ERROR tpcb event state",
192 tpcb, e->ev_number, tpcb->tp_state, 0);
193 }
194 #endif
195 return EIO; /* for lack of anything better */
196 }
197
198
199 /* Not used at the moment */
200 void
201 tp_drain(void)
202 {
203 }
204
205
206 /*
207 * NAME: tp_indicate()
208 *
209 * CALLED FROM:
210 * tp.trans when XPD arrive, when a connection is being disconnected by
211 * the arrival of a DR or ER, and when a connection times out.
212 *
213 * FUNCTION and ARGUMENTS:
214 * (ind) is the type of indication : T_DISCONNECT, T_XPD
215 * (error) is an E* value that will be put in the socket structure
216 * to be passed along to the user later.
217 * Gives a SIGURG to the user process or group indicated by the socket
218 * attached to the tpcb.
219 *
220 * RETURNS: Rien
221 *
222 * SIDE EFFECTS:
223 *
224 * NOTES:
225 */
226 void
227 tp_indicate(int ind, struct tp_pcb *tpcb, u_int error)
228 {
229 struct socket *so = tpcb->tp_sock;
230 #ifdef TPPT
231 if (tp_traceflags[D_INDICATION]) {
232 tptraceTPCB(TPPTindicate, ind, *(u_short *) (tpcb->tp_lsuffix),
233 *(u_short *) (tpcb->tp_fsuffix), error, so->so_pgid);
234 }
235 #endif
236 #ifdef ARGO_DEBUG
237 if (argo_debug[D_INDICATION]) {
238 char *ls, *fs;
239 ls = tpcb->tp_lsuffix,
240 fs = tpcb->tp_fsuffix,
241
242 printf(
243 "indicate 0x%x lsuf 0x%02x%02x fsuf 0x%02x%02x err 0x%x noind 0x%x ref 0x%x\n",
244 ind,
245 *ls, *(ls + 1), *fs, *(fs + 1),
246 error, /* so->so_pgrp, */
247 tpcb->tp_no_disc_indications,
248 tpcb->tp_lref);
249 }
250 #endif
251
252 if (ind == ER_TPDU) {
253 struct mbuf *m;
254 struct tp_disc_reason x;
255
256 if ((so->so_state & SS_CANTRCVMORE) == 0 &&
257 (m = m_get(M_DONTWAIT, MT_OOBDATA)) != 0) {
258
259 x.dr_hdr.cmsg_len = m->m_len = sizeof(x);
260 x.dr_hdr.cmsg_level = SOL_TRANSPORT;
261 x.dr_hdr.cmsg_type = TPOPT_DISC_REASON;
262 x.dr_reason = error;
263 *mtod(m, struct tp_disc_reason *) = x;
264 sbappendrecord(&tpcb->tp_Xrcv, m);
265 error = 0;
266 } else
267 error = ECONNRESET;
268 }
269 so->so_error = error;
270
271 if (ind == T_DISCONNECT) {
272 if (error == 0)
273 so->so_error = ENOTCONN;
274 if (tpcb->tp_no_disc_indications)
275 return;
276 }
277 #ifdef TPPT
278 if (tp_traceflags[D_INDICATION]) {
279 tptraceTPCB(TPPTmisc, "doing sohasoutofband(so)", so, 0, 0, 0);
280 }
281 #endif
282 sohasoutofband(so);
283 }
284
285 /*
286 * NAME : tp_getoptions()
287 *
288 * CALLED FROM:
289 * tp.trans whenever we go into OPEN state
290 *
291 * FUNCTION and ARGUMENTS:
292 * sets the proper flags and values in the tpcb, to control
293 * the appropriate actions for the given class, options,
294 * sequence space, etc, etc.
295 *
296 * RETURNS: Nada
297 *
298 * SIDE EFFECTS:
299 *
300 * NOTES:
301 */
302 void
303 tp_getoptions(struct tp_pcb *tpcb)
304 {
305 tpcb->tp_seqmask =
306 tpcb->tp_xtd_format ? TP_XTD_FMT_MASK : TP_NML_FMT_MASK;
307 tpcb->tp_seqbit =
308 tpcb->tp_xtd_format ? TP_XTD_FMT_BIT : TP_NML_FMT_BIT;
309 tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1;
310 tpcb->tp_dt_ticks =
311 max(tpcb->tp_dt_ticks, (tpcb->tp_peer_acktime + 2));
312 tp_rsyset(tpcb);
313
314 }
315
316 /*
317 * NAME: tp_recycle_tsuffix()
318 *
319 * CALLED FROM:
320 * Called when a ref is frozen.
321 *
322 * FUNCTION and ARGUMENTS:
323 * allows the suffix to be reused.
324 *
325 * RETURNS: zilch
326 *
327 * SIDE EFFECTS:
328 *
329 * NOTES:
330 */
331 void
332 tp_recycle_tsuffix(void *v)
333 {
334 struct tp_pcb *tpcb = v;
335 bzero((caddr_t) tpcb->tp_lsuffix, sizeof(tpcb->tp_lsuffix));
336 bzero((caddr_t) tpcb->tp_fsuffix, sizeof(tpcb->tp_fsuffix));
337 tpcb->tp_fsuffixlen = tpcb->tp_lsuffixlen = 0;
338
339 (tpcb->tp_nlproto->nlp_recycle_suffix) (tpcb->tp_npcb);
340 }
341
342 /*
343 * NAME: tp_quench()
344 *
345 * CALLED FROM:
346 * tp{af}_quench() when ICMP source quench or similar thing arrives.
347 *
348 * FUNCTION and ARGUMENTS:
349 * Drop the congestion window back to 1.
350 * Congestion window scheme:
351 * Initial value is 1. ("slow start" as Nagle, et. al. call it)
352 * For each good ack that arrives, the congestion window is increased
353 * by 1 (up to max size of logical infinity, which is to say,
354 * it doesn't wrap around).
355 * Source quench causes it to drop back to 1.
356 * tp_send() uses the smaller of (regular window, congestion window).
357 * One retransmission strategy option is to have any retransmission
358 * cause reset the congestion window back to 1.
359 *
360 * (cmd) is either PRC_QUENCH: source quench, or
361 * PRC_QUENCH2: dest. quench (dec bit)
362 *
363 * RETURNS:
364 *
365 * SIDE EFFECTS:
366 *
367 * NOTES:
368 */
369 void
370 tp_quench(struct inpcb *ipcb, int cmd)
371 {
372 struct tp_pcb *tpcb = (struct tp_pcb *) ipcb;
373 #ifdef ARGO_DEBUG
374 if (argo_debug[D_QUENCH]) {
375 printf("tp_quench tpcb %p ref 0x%x sufx 0x%x\n",
376 tpcb, tpcb->tp_lref, *(u_short *) (tpcb->tp_lsuffix));
377 printf("cong_win 0x%lx decbit 0x%x \n",
378 tpcb->tp_cong_win, tpcb->tp_decbit);
379 }
380 #endif
381 switch (cmd) {
382 case PRC_QUENCH:
383 tpcb->tp_cong_win = tpcb->tp_l_tpdusize;
384 IncStat(ts_quench);
385 break;
386 case PRC_QUENCH2:
387 /* might as well quench source also */
388 tpcb->tp_cong_win = tpcb->tp_l_tpdusize;
389 tpcb->tp_decbit = TP_DECBIT_CLEAR_COUNT;
390 IncStat(ts_rcvdecbit);
391 break;
392 }
393 }
394
395
396 /*
397 * NAME: tp_netcmd()
398 *
399 * CALLED FROM:
400 *
401 * FUNCTION and ARGUMENTS:
402 *
403 * RETURNS:
404 *
405 * SIDE EFFECTS:
406 *
407 * NOTES:
408 */
409 void
410 tp_netcmd(struct tp_pcb *tpcb, int cmd)
411 {
412 #ifdef TPCONS
413 struct isopcb *isop;
414 struct pklcd *lcp;
415
416 if (tpcb->tp_netservice != ISO_CONS)
417 return;
418 isop = (struct isopcb *) tpcb->tp_npcb;
419 lcp = (struct pklcd *) isop->isop_chan;
420 switch (cmd) {
421
422 case CONN_CLOSE:
423 case CONN_REFUSE:
424 if (isop->isop_refcnt == 1) {
425 /*
426 * This is really superfluous, since it would happen
427 * anyway in iso_pcbdetach, although it is a courtesy
428 * to free up the x.25 channel before the refwait
429 * timer expires.
430 */
431 lcp->lcd_upper = 0;
432 lcp->lcd_upnext = 0;
433 pk_disconnect(lcp);
434 isop->isop_chan = 0;
435 isop->isop_refcnt = 0;
436 }
437 break;
438
439 default:
440 printf("tp_netcmd(%p, %#x) NOT IMPLEMENTED\n", tpcb, cmd);
441 break;
442 }
443 #else /* TPCONS */
444 printf("tp_netcmd(): X25 NOT CONFIGURED!!\n");
445 #endif
446 }
447
448 /*
449 * CALLED FROM:
450 * tp_ctloutput() and tp_emit()
451 * FUNCTION and ARGUMENTS:
452 * Convert a class mask to the highest numeric value it represents.
453 */
454 int
455 tp_mask_to_num(u_char x)
456 {
457 int j;
458
459 for (j = 4; j >= 0; j--) {
460 if (x & (1 << j))
461 break;
462 }
463 ASSERT((j == 4) || (j == 0)); /* for now */
464 if ((j != 4) && (j != 0)) {
465 printf("ASSERTION ERROR: tp_mask_to_num: x 0x%x j %d\n",
466 x, j);
467 }
468 #ifdef TPPT
469 if (tp_traceflags[D_TPINPUT]) {
470 tptrace(TPPTmisc, "tp_mask_to_num(x) returns j", x, j, 0, 0);
471 }
472 #endif
473 #ifdef ARGO_DEBUG
474 if (argo_debug[D_TPINPUT]) {
475 printf("tp_mask_to_num(0x%x) returns 0x%x\n", x, j);
476 }
477 #endif
478 return j;
479 }
480
481 #if 0
482 static void
483 copyQOSparms(const struct tp_conn_param *src, struct tp_conn_params *dst)
484 {
485 /* copy all but the bits stuff at the end */
486 #define COPYSIZE (12 * sizeof(short))
487
488 bcopy((caddr_t) src, (caddr_t) dst, COPYSIZE);
489 dst->p_tpdusize = src->p_tpdusize;
490 dst->p_ack_strat = src->p_ack_strat;
491 dst->p_rx_strat = src->p_rx_strat;
492 #undef COPYSIZE
493 }
494 #endif
495
496 /*
497 * Determine a reasonable value for maxseg size.
498 * If the route is known, check route for mtu.
499 * We also initialize the congestion/slow start
500 * window to be a single segment if the destination isn't local.
501 * While looking at the routing entry, we also initialize other path-dependent
502 * parameters from pre-set or cached values in the routing entry.
503 */
504 void
505 tp_mss(struct tp_pcb *tpcb, int nhdr_size)
506 {
507 struct rtentry *rt;
508 struct ifnet *ifp;
509 int rtt, mss;
510 u_long bufsize;
511 int i, ssthresh = 0, rt_mss;
512 struct socket *so;
513
514 if (tpcb->tp_ptpdusize)
515 mss = tpcb->tp_ptpdusize << 7;
516 else
517 mss = 1 << tpcb->tp_tpdusize;
518 so = tpcb->tp_sock;
519 if ((rt = *(tpcb->tp_routep)) == 0) {
520 bufsize = so->so_rcv.sb_hiwat;
521 goto punt_route;
522 }
523 ifp = rt->rt_ifp;
524
525 #ifdef RTV_MTU /* if route characteristics exist ... */
526 /*
527 * While we're here, check if there's an initial rtt
528 * or rttvar. Convert from the route-table units
529 * to hz ticks for the smoothed timers and slow-timeout units
530 * for other inital variables.
531 */
532 if (tpcb->tp_rtt == 0 && (rtt = rt->rt_rmx.rmx_rtt)) {
533 tpcb->tp_rtt = rtt * hz / RTM_RTTUNIT;
534 if (rt->rt_rmx.rmx_rttvar)
535 tpcb->tp_rtv = rt->rt_rmx.rmx_rttvar
536 * hz / RTM_RTTUNIT;
537 else
538 tpcb->tp_rtv = tpcb->tp_rtt;
539 }
540 /*
541 * if there's an mtu associated with the route, use it
542 */
543 if (rt->rt_rmx.rmx_mtu)
544 rt_mss = rt->rt_rmx.rmx_mtu - nhdr_size;
545 else
546 #endif /* RTV_MTU */
547 rt_mss = (ifp->if_mtu - nhdr_size);
548 if (tpcb->tp_ptpdusize == 0 || /* assume application doesn't care */
549 mss > rt_mss /* network won't support what was asked for */ )
550 mss = rt_mss;
551 /* can propose mtu which are multiples of 128 */
552 mss &= ~0x7f;
553 /*
554 * If there's a pipesize, change the socket buffer
555 * to that size.
556 */
557 #ifdef RTV_SPIPE
558 if ((bufsize = rt->rt_rmx.rmx_sendpipe) > 0) {
559 #endif
560 bufsize = min(bufsize, so->so_snd.sb_hiwat);
561 (void) sbreserve(&so->so_snd, bufsize, so);
562 }
563 #ifdef RTV_SPIPE
564 if ((bufsize = rt->rt_rmx.rmx_recvpipe) > 0) {
565 #endif
566 bufsize = min(bufsize, so->so_rcv.sb_hiwat);
567 (void) sbreserve(&so->so_rcv, bufsize, so);
568 } else
569 bufsize = so->so_rcv.sb_hiwat;
570 #ifdef RTV_SSTHRESH
571 /*
572 * There's some sort of gateway or interface
573 * buffer limit on the path. Use this to set
574 * the slow start threshhold, but set the
575 * threshold to no less than 2*mss.
576 */
577 ssthresh = rt->rt_rmx.rmx_ssthresh;
578 punt_route:
579 /*
580 * The current mss is initialized to the default value.
581 * If we compute a smaller value, reduce the current mss.
582 * If we compute a larger value, return it for use in sending
583 * a max seg size option.
584 * If we received an offer, don't exceed it.
585 * However, do not accept offers under 128 bytes.
586 */
587 if (tpcb->tp_l_tpdusize)
588 mss = min(mss, tpcb->tp_l_tpdusize);
589 /*
590 * We want a minimum recv window of 4 packets to
591 * signal packet loss by duplicate acks.
592 */
593 mss = min(mss, bufsize >> 2) & ~0x7f;
594 mss = max(mss, 128); /* sanity */
595 tpcb->tp_cong_win =
596 (rt == 0 || (rt->rt_flags & RTF_GATEWAY)) ? mss : bufsize;
597 tpcb->tp_l_tpdusize = mss;
598 tp_rsyset(tpcb);
599 tpcb->tp_ssthresh = max(2 * mss, ssthresh);
600 /* Calculate log2 of mss */
601 for (i = TP_MIN_TPDUSIZE + 1; i <= TP_MAX_TPDUSIZE; i++)
602 if ((1 << i) > mss)
603 break;
604 i--;
605 tpcb->tp_tpdusize = i;
606 #endif /* RTV_MTU */
607 }
608
609 /*
610 * CALLED FROM:
611 * tp_usrreq on PRU_CONNECT and tp_input on receipt of CR
612 *
613 * FUNCTION and ARGUMENTS:
614 * -- An mbuf containing the peer's network address.
615 * -- Our control block, which will be modified
616 * -- In the case of cons, a control block for that layer.
617 *
618 *
619 * RETURNS:
620 * errno value :
621 * EAFNOSUPPORT if can't find an nl_protosw for x.25 (really could panic)
622 * ECONNREFUSED if trying to run TP0 with non-type 37 address
623 * possibly other E* returned from cons_netcmd()
624 *
625 * SIDE EFFECTS:
626 * Determines recommended tpdusize, buffering and intial delays
627 * based on information cached on the route.
628 */
629 int
630 tp_route_to(struct mbuf *m, struct tp_pcb *tpcb, caddr_t channel)
631 {
632 struct sockaddr_iso *siso; /* NOTE: this may be a
633 * sockaddr_in */
634 int error = 0, save_netservice = tpcb->tp_netservice;
635 struct rtentry *rt = 0;
636 int nhdr_size;
637
638 siso = mtod(m, struct sockaddr_iso *);
639 #ifdef TPPT
640 if (tp_traceflags[D_CONN]) {
641 tptraceTPCB(TPPTmisc,
642 "route_to: so afi netservice class",
643 tpcb->tp_sock, siso->siso_addr.isoa_genaddr[0], tpcb->tp_netservice,
644 tpcb->tp_class);
645 }
646 #endif
647 #ifdef ARGO_DEBUG
648 if (argo_debug[D_CONN]) {
649 printf("tp_route_to( m %p, channel %p, tpcb %p netserv 0x%x)\n",
650 m, channel, tpcb, tpcb->tp_netservice);
651 printf("m->mlen x%x, m->m_data:\n", m->m_len);
652 dump_buf(mtod(m, caddr_t), m->m_len);
653 }
654 #endif
655 if (channel) {
656 #ifdef TPCONS
657 struct pklcd *lcp = (struct pklcd *) channel;
658 struct isopcb *isop = (struct isopcb *) lcp->lcd_upnext,
659 *isop_new = (struct isopcb *) tpcb->tp_npcb;
660 /*
661 * The next 2 lines believe that you haven't set any network
662 * level options or done a pcbconnect and XXXXXXX'edly apply
663 * to both inpcb's and isopcb's
664 */
665 remque(isop_new);
666 free(isop_new, M_PCB);
667 tpcb->tp_npcb = (caddr_t) isop;
668 tpcb->tp_netservice = ISO_CONS;
669 tpcb->tp_nlproto = nl_protosw + ISO_CONS;
670 if (isop->isop_refcnt++ == 0) {
671 iso_putsufx(isop, tpcb->tp_lsuffix,
672 tpcb->tp_lsuffixlen, TP_LOCAL);
673 isop->isop_socket = tpcb->tp_sock;
674 }
675 #endif
676 } else {
677 switch (siso->siso_family) {
678 default:
679 error = EAFNOSUPPORT;
680 goto done;
681 #ifdef ISO
682 case AF_ISO:
683 {
684 struct isopcb *isop = (struct isopcb *) tpcb->tp_npcb;
685 int flags = tpcb->tp_sock->so_options & SO_DONTROUTE;
686 tpcb->tp_netservice = ISO_CLNS;
687 if (clnp_route(&siso->siso_addr, &isop->isop_route,
688 flags, NULL, NULL) == 0) {
689 rt = isop->isop_route.ro_rt;
690 if (rt && rt->rt_flags & RTF_PROTO1)
691 tpcb->tp_netservice = ISO_CONS;
692 }
693 } break;
694 #endif
695 #ifdef INET
696 case AF_INET:
697 tpcb->tp_netservice = IN_CLNS;
698 #endif
699 }
700 if (tpcb->tp_nlproto->nlp_afamily != siso->siso_family) {
701 #ifdef ARGO_DEBUG
702 if (argo_debug[D_CONN]) {
703 printf("tp_route_to( CHANGING nlproto old 0x%x new 0x%x)\n",
704 save_netservice, tpcb->tp_netservice);
705 }
706 #endif
707 if ((error = tp_set_npcb(tpcb)) != 0)
708 goto done;
709 }
710 #ifdef ARGO_DEBUG
711 if (argo_debug[D_CONN]) {
712 printf("tp_route_to calling nlp_pcbconn, netserv %d\n",
713 tpcb->tp_netservice);
714 }
715 #endif
716 tpcb->tp_nlproto = nl_protosw + tpcb->tp_netservice;
717 error = (*tpcb->tp_nlproto->nlp_pcbconn) (tpcb->tp_npcb, m);
718 }
719 if (error)
720 goto done;
721 /* only gets common info */
722 nhdr_size = (*tpcb->tp_nlproto->nlp_mtu)(tpcb);
723 tp_mss(tpcb, nhdr_size);
724 done:
725 #ifdef ARGO_DEBUG
726 if (argo_debug[D_CONN]) {
727 printf("tp_route_to returns 0x%x\n", error);
728 }
729 #endif
730 #ifdef TPPT
731 if (tp_traceflags[D_CONN]) {
732 tptraceTPCB(TPPTmisc, "route_to: returns: error netserv class", error,
733 tpcb->tp_netservice, tpcb->tp_class, 0);
734 }
735 #endif
736 return error;
737 }
738
739 #ifndef CCITT
740 void
741 pk_flowcontrol(struct pklcd *lcp, int foo, int bar)
742 {
743 }
744 #endif
745
746 /* class zero version */
747 void
748 tp0_stash(struct tp_pcb *tpcb, struct tp_event *e)
749 {
750 #define E e->TPDU_ATTR(DT)
751
752 struct sockbuf *sb = &tpcb->tp_sock->so_rcv;
753 struct isopcb *isop = (struct isopcb *) tpcb->tp_npcb;
754
755 #ifdef TP_PERF_MEAS
756 if (DOPERF(tpcb)) {
757 PStat(tpcb, Nb_from_ll) += E.e_datalen;
758 tpmeas(tpcb->tp_lref, TPtime_from_ll, &e->e_time,
759 E.e_seq, PStat(tpcb, Nb_from_ll), E.e_datalen);
760 }
761 #endif
762
763 #ifdef ARGO_DEBUG
764 if (argo_debug[D_STASH]) {
765 printf("stash EQ: seq 0x%x datalen 0x%x eot 0x%x",
766 E.e_seq, E.e_datalen, E.e_eot);
767 }
768 #endif
769
770 #ifdef TPPT
771 if (tp_traceflags[D_STASH]) {
772 tptraceTPCB(TPPTmisc, "stash EQ: seq len eot",
773 E.e_seq, E.e_datalen, E.e_eot, 0);
774 }
775 #endif
776
777 if (E.e_eot) {
778 struct mbuf *n = E.e_data;
779 n->m_flags |= M_EOR;
780 n->m_nextpkt = NULL; /* set on tp_input */
781 }
782 sbappend(sb, E.e_data);
783 #ifdef ARGO_DEBUG
784 if (argo_debug[D_STASH]) {
785 dump_mbuf(sb->sb_mb, "stash 0: so_rcv after appending");
786 }
787 #endif
788 if (tpcb->tp_netservice != ISO_CONS)
789 printf("tp0_stash: tp running over something weird\n");
790 else {
791 struct pklcd *lcp = (struct pklcd *) isop->isop_chan;
792 pk_flowcontrol(lcp, sbspace(sb) <= 0, 1);
793 }
794 }
795
796 void
797 tp0_openflow(struct tp_pcb *tpcb)
798 {
799 struct isopcb *isop = (struct isopcb *) tpcb->tp_npcb;
800 if (tpcb->tp_netservice != ISO_CONS)
801 printf("tp0_openflow: tp running over something weird\n");
802 else {
803 struct pklcd *lcp = (struct pklcd *) isop->isop_chan;
804 if (lcp->lcd_rxrnr_condition)
805 pk_flowcontrol(lcp, 0, 0);
806 }
807 }
808
809 #ifdef TP_PERF_MEAS
810 /*
811 * CALLED FROM:
812 * tp_ctloutput() when the user sets TPOPT_PERF_MEAS on
813 * and tp_newsocket() when a new connection is made from
814 * a listening socket with tp_perf_on == true.
815 * FUNCTION and ARGUMENTS:
816 * (tpcb) is the usual; this procedure gets a clear cluster mbuf for
817 * a tp_pmeas structure, and makes tpcb->tp_p_meas point to it.
818 * RETURN VALUE:
819 * ENOBUFS if it cannot get a cluster mbuf.
820 */
821
822 int
823 tp_setup_perf(struct tp_pcb *tpcb)
824 {
825 if (tpcb->tp_p_meas == 0) {
826 tpcb->tp_p_meas = malloc(sizeof(struct tp_pmeas), M_PCB, M_WAITOK|M_ZERO);
827 #ifdef ARGO_DEBUG
828 if (argo_debug[D_PERF_MEAS]) {
829 printf(
830 "tpcb 0x%x so 0x%x ref 0x%x tp_p_meas 0x%x tp_perf_on 0x%x\n",
831 tpcb, tpcb->tp_sock, tpcb->tp_lref,
832 tpcb->tp_p_meas, tpcb->tp_perf_on);
833 }
834 #endif
835 tpcb->tp_perf_on = 1;
836 }
837 return 0;
838 }
839 #endif /* TP_PERF_MEAS */
840
841 #ifdef ARGO_DEBUG
842 void
843 dump_addr(struct sockaddr *addr)
844 {
845 switch (addr->sa_family) {
846 case AF_INET:
847 dump_inaddr(satosin(addr));
848 break;
849 #ifdef ISO
850 case AF_ISO:
851 dump_isoaddr(satosiso(addr));
852 break;
853 #endif /* ISO */
854 default:
855 printf("BAD AF: 0x%x\n", addr->sa_family);
856 break;
857 }
858 }
859
860 #define MAX_COLUMNS 8
861 /*
862 * Dump the buffer to the screen in a readable format. Format is:
863 *
864 * hex/dec where hex is the hex format, dec is the decimal format.
865 * columns of hex/dec numbers will be printed, followed by the
866 * character representations (if printable).
867 */
868 void
869 Dump_buf(caddr_t buf, int len)
870 {
871 int i, j;
872 #define Buf ((u_char *)buf)
873 printf("Dump buf %p len 0x%x\n", buf, len);
874 for (i = 0; i < len; i += MAX_COLUMNS) {
875 printf("+%d:\t", i);
876 for (j = 0; j < MAX_COLUMNS; j++) {
877 if (i + j < len) {
878 printf("%x/%d\t", Buf[i + j], Buf[i + j]);
879 } else {
880 printf(" ");
881 }
882 }
883
884 for (j = 0; j < MAX_COLUMNS; j++) {
885 if (i + j < len) {
886 if (((Buf[i + j]) > 31) && ((Buf[i + j]) < 128))
887 printf("%c", Buf[i + j]);
888 else
889 printf(".");
890 }
891 }
892 printf("\n");
893 }
894 }
895 #endif /* ARGO_DEBUG */
Cache object: 40846a280002c6da70c6ee9d6e194f68
|