1 /* $NetBSD: tp_pcb.c,v 1.40 2009/03/18 17:06:53 cegger Exp $ */
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
31 * @(#)tp_pcb.c 8.1 (Berkeley) 6/10/93
34 /***********************************************************
35 Copyright IBM Corporation 1987
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.
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
55 ******************************************************************/
58 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
61 * This is the initialization and cleanup stuff - for the tp machine in
62 * general as well as for the individual pcbs. tp_init() is called at system
63 * startup. tp_attach() and tp_getref() are called when a socket is created.
64 * tp_detach() and tp_freeref() are called during the closing stage and/or
65 * when the reference timer goes off. tp_soisdisconnecting() and
66 * tp_soisdisconnected() are tp-specific versions of soisconnect* and are
67 * called (obviously) during the closing phase.
70 #include <sys/cdefs.h>
71 __KERNEL_RCSID(0, "$NetBSD: tp_pcb.c,v 1.40 2009/03/18 17:06:53 cegger Exp $");
76 #include <sys/param.h>
77 #include <sys/systm.h>
79 #include <sys/socket.h>
80 #include <sys/socketvar.h>
81 #include <sys/domain.h>
82 #include <sys/protosw.h>
83 #include <sys/errno.h>
86 #include <netiso/argo_debug.h>
87 #include <netiso/tp_param.h>
88 #include <netiso/tp_timer.h>
89 #include <netiso/tp_ip.h>
90 #include <netiso/tp_stat.h>
91 #include <netiso/tp_pcb.h>
92 #include <netiso/tp_tpdu.h>
93 #include <netiso/tp_trace.h>
94 #include <netiso/tp_meas.h>
95 #include <netiso/tp_seq.h>
96 #include <netiso/tp_clnp.h>
97 #include <netiso/tp_var.h>
100 * ticks are in units of: 500 nano-fortnights ;-) or 500 ms or 1/2 second
103 const struct tp_conn_param tp_conn_param
[] = {
104 /* ISO_CLNS: TP4 CONNECTION LESS */
106 TP_NRETRANS
, /* short p_Nretrans; */
107 20, /* 10 sec *//* short p_dr_ticks; */
109 20, /* 10 sec *//* short p_cc_ticks; */
110 20, /* 10 sec *//* short p_dt_ticks; */
112 40, /* 20 sec *//* short p_x_ticks; */
113 80, /* 40 sec *//* short p_cr_ticks; */
115 240, /* 2 min *//* short p_keepalive_ticks; */
116 10, /* 5 sec *//* short p_sendack_ticks; */
118 600, /* 5 min *//* short p_ref_ticks; */
119 360, /* 3 min *//* short p_inact_ticks; */
121 (short) 100, /* short p_lcdtfract */
122 (short) TP_SOCKBUFSIZE
, /* short p_winsize */
123 TP_TPDUSIZE
, /* u_char p_tpdusize */
125 TPACK_WINDOW
, /* 4 bits p_ack_strat */
126 TPRX_USE_CW
| TPRX_FASTSTART
,
127 /* 4 bits p_rx_strat */
128 TP_CLASS_4
| TP_CLASS_0
, /* 5 bits p_class */
129 1, /* 1 bit xtd format */
130 1, /* 1 bit xpd service */
131 1, /* 1 bit use_checksum */
132 0, /* 1 bit use net xpd */
133 0, /* 1 bit use rcc */
134 0, /* 1 bit use efc */
135 1, /* no disc indications */
136 0, /* don't change params */
137 ISO_CLNS
, /* p_netservice */
140 /* IN_CLNS: TP4 CONNECTION LESS */
142 TP_NRETRANS
, /* short p_Nretrans; */
143 20, /* 10 sec *//* short p_dr_ticks; */
145 20, /* 10 sec *//* short p_cc_ticks; */
146 20, /* 10 sec *//* short p_dt_ticks; */
148 40, /* 20 sec *//* short p_x_ticks; */
149 80, /* 40 sec *//* short p_cr_ticks; */
151 240, /* 2 min *//* short p_keepalive_ticks; */
152 10, /* 5 sec *//* short p_sendack_ticks; */
154 600, /* 5 min *//* short p_ref_ticks; */
155 360, /* 3 min *//* short p_inact_ticks; */
157 (short) 100, /* short p_lcdtfract */
158 (short) TP_SOCKBUFSIZE
, /* short p_winsize */
159 TP_TPDUSIZE
, /* u_char p_tpdusize */
161 TPACK_WINDOW
, /* 4 bits p_ack_strat */
162 TPRX_USE_CW
| TPRX_FASTSTART
,
163 /* 4 bits p_rx_strat */
164 TP_CLASS_4
, /* 5 bits p_class */
165 1, /* 1 bit xtd format */
166 1, /* 1 bit xpd service */
167 1, /* 1 bit use_checksum */
168 0, /* 1 bit use net xpd */
169 0, /* 1 bit use rcc */
170 0, /* 1 bit use efc */
171 1, /* no disc indications */
172 0, /* don't change params */
173 IN_CLNS
, /* p_netservice */
176 /* ISO_CONS: TP0 CONNECTION MODE */
178 TP_NRETRANS
, /* short p_Nretrans; */
179 0, /* n/a *//* short p_dr_ticks; */
181 40, /* 20 sec *//* short p_cc_ticks; */
182 0, /* n/a *//* short p_dt_ticks; */
184 0, /* n/a *//* short p_x_ticks; */
185 360, /* 3 min *//* short p_cr_ticks; */
187 0, /* n/a *//* short p_keepalive_ticks; */
188 0, /* n/a *//* short p_sendack_ticks; */
190 600, /* for cr/cc to clear *//* short p_ref_ticks; */
191 0, /* n/a *//* short p_inact_ticks; */
194 * Use tp4 defaults just in case the user changes ONLY the
197 (short) 100, /* short p_lcdtfract */
198 (short) TP0_SOCKBUFSIZE
, /* short p_winsize */
199 TP0_TPDUSIZE
, /* 8 bits p_tpdusize */
201 0, /* 4 bits p_ack_strat */
202 0, /* 4 bits p_rx_strat */
203 TP_CLASS_0
, /* 5 bits p_class */
204 0, /* 1 bit xtd format */
205 0, /* 1 bit xpd service */
206 0, /* 1 bit use_checksum */
207 0, /* 1 bit use net xpd */
208 0, /* 1 bit use rcc */
209 0, /* 1 bit use efc */
210 0, /* no disc indications */
211 0, /* don't change params */
212 ISO_CONS
, /* p_netservice */
215 /* ISO_COSNS: TP4 CONNECTION LESS SERVICE over CONSNS */
217 TP_NRETRANS
, /* short p_Nretrans; */
218 40, /* 20 sec *//* short p_dr_ticks; */
220 40, /* 20 sec *//* short p_cc_ticks; */
221 80, /* 40 sec *//* short p_dt_ticks; */
223 120, /* 1 min *//* short p_x_ticks; */
224 360, /* 3 min *//* short p_cr_ticks; */
226 360, /* 3 min *//* short p_keepalive_ticks; */
227 20, /* 10 sec *//* short p_sendack_ticks; */
229 600, /* 5 min *//* short p_ref_ticks; */
230 480, /* 4 min *//* short p_inact_ticks; */
232 (short) 100, /* short p_lcdtfract */
233 (short) TP0_SOCKBUFSIZE
, /* short p_winsize */
234 TP0_TPDUSIZE
, /* u_char p_tpdusize */
236 TPACK_WINDOW
, /* 4 bits p_ack_strat */
237 TPRX_USE_CW
, /* No fast start */
238 /* 4 bits p_rx_strat */
239 TP_CLASS_4
| TP_CLASS_0
, /* 5 bits p_class */
240 0, /* 1 bit xtd format */
241 1, /* 1 bit xpd service */
242 1, /* 1 bit use_checksum */
243 0, /* 1 bit use net xpd */
244 0, /* 1 bit use rcc */
245 0, /* 1 bit use efc */
246 0, /* no disc indications */
247 0, /* don't change params */
248 ISO_COSNS
, /* p_netservice */
254 struct inpcbtable tp_inpcb
;
257 struct isopcb tp_isopcb
;
260 struct tp_stat tp_stat
;
263 struct nl_protosw nl_protosw
[] = {
266 {AF_ISO
, iso_putnetaddr
, iso_getnetaddr
, iso_cmpnetaddr
,
267 iso_putsufx
, iso_getsufx
,
269 tpclnp_mtu
, iso_pcbbind
, iso_pcbconnect
,
270 iso_pcbdisconnect
, iso_pcbdetach
,
272 tpclnp_output
, tpclnp_output_dg
, iso_nlctloutput
,
273 (void *) & tp_isopcb
,
276 { .nlp_afamily
= 0, },
280 {AF_INET
, in_putnetaddr
, in_getnetaddr
, in_cmpnetaddr
,
281 in_putsufx
, in_getsufx
,
283 tpip_mtu
, in_pcbbind
, in_pcbconnect
,
284 in_pcbdisconnect
, in_pcbdetach
,
286 tpip_output
, tpip_output_dg
, /* nl_ctloutput */ NULL
,
290 { .nlp_afamily
= 0, },
293 { .nlp_afamily
= 0, },
294 /* End of protosw marker */
295 { .nlp_afamily
= 0, },
298 u_long tp_sendspace
= 1024 * 4;
299 u_long tp_recvspace
= 1024 * 4;
305 * autoconf through the protosw structure
308 * initialize tp machine
319 static int init_done
= 0;
326 in_pcbinit(&tp_inpcb
, 1, 1);
330 tp_isopcb
.isop_next
= tp_isopcb
.isop_prev
= &tp_isopcb
;
336 memset((void *) & tp_stat
, 0, sizeof(struct tp_stat
));
340 * NAME: tp_soisdisconnecting()
345 * FUNCTION and ARGUMENTS:
346 * Set state of the socket (so) to reflect that fact that we're disconnectING
353 * This differs from the regular soisdisconnecting() in that the latter
354 * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags.
355 * We don't want to set those flags because those flags will cause
356 * a SIGPIPE to be delivered in sosend() and we don't like that.
357 * If anyone else is sleeping on this socket, wake 'em up.
360 tp_soisdisconnecting(struct socket
*so
)
362 soisdisconnecting(so
);
363 so
->so_state
&= ~SS_CANTSENDMORE
;
365 if (DOPERF(sototpcb(so
))) {
366 struct tp_pcb
*tpcb
= sototpcb(so
);
370 memcpy((void *) &fsufx
, (void *) tpcb
->tp_fsuffix
,
372 memcpy((void *) &lsufx
, (void *) tpcb
->tp_lsuffix
,
376 tpmeas(tpcb
->tp_lref
, TPtime_close
, &now
, fsufx
, lsufx
,
378 tpcb
->tp_perf_on
= 0; /* turn perf off */
385 * NAME: tp_soisdisconnected()
390 * FUNCTION and ARGUMENTS:
391 * Set state of the socket (so) to reflect that fact that we're disconnectED
392 * Set the state of the reference structure to closed, and
393 * recycle the suffix.
394 * Start a reference timer.
401 * This differs from the regular soisdisconnected() in that the latter
402 * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags.
403 * We don't want to set those flags because those flags will cause
404 * a SIGPIPE to be delivered in sosend() and we don't like that.
405 * If anyone else is sleeping on this socket, wake 'em up.
408 tp_soisdisconnected(struct tp_pcb
*tpcb
)
410 struct socket
*so
= tpcb
->tp_sock
;
412 soisdisconnecting(so
);
413 so
->so_state
&= ~SS_CANTSENDMORE
;
416 struct tp_pcb
*ttpcb
= sototpcb(so
);
421 memcpy((void *) &fsufx
, (void *) ttpcb
->tp_fsuffix
,
423 memcpy((void *) &lsufx
, (void *) ttpcb
->tp_lsuffix
,
427 tpmeas(ttpcb
->tp_lref
, TPtime_close
,
428 &now
, &lsufx
, &fsufx
, ttpcb
->tp_fref
);
429 tpcb
->tp_perf_on
= 0; /* turn perf off */
433 tpcb
->tp_refstate
= REF_FROZEN
;
434 tp_recycle_tsuffix(tpcb
);
435 tp_etimeout(tpcb
, TM_reference
, (int) tpcb
->tp_refer_ticks
);
442 * tp.trans when the reference timer goes off, and
443 * from tp_attach() and tp_detach() when a tpcb is partially set up but not
444 * set up enough to have a ref timer set for it, and it's discarded
445 * due to some sort of error or an early close()
447 * FUNCTION and ARGUMENTS:
448 * Frees the reference represented by (r) for re-use.
454 * NOTES: better be called at clock priority !!!!!
459 struct tp_ref
*r
= tp_ref
+ n
;
464 if (argo_debug
[D_TIMER
]) {
465 printf("tp_freeref called for ref %d pcb %p maxrefopen %d\n",
466 n
, tpcb
, tp_refinfo
.tpr_maxopen
);
470 if (tp_traceflags
[D_TIMER
]) {
471 tptrace(TPPTmisc
, "tp_freeref ref maxrefopen pcb",
472 n
, tp_refinfo
.tpr_maxopen
, tpcb
, 0);
478 if (argo_debug
[D_CONN
]) {
479 printf("tp_freeref: CLEARING tpr_pcb %p\n", tpcb
);
482 r
->tpr_pcb
= (struct tp_pcb
*) 0;
483 tpcb
->tp_refstate
= REF_FREE
;
485 for (r
= tp_ref
+ tp_refinfo
.tpr_maxopen
; r
> tp_ref
; r
--)
488 tp_refinfo
.tpr_maxopen
= r
- tp_ref
;
489 tp_refinfo
.tpr_numopen
--;
492 if (argo_debug
[D_TIMER
]) {
493 printf("tp_freeref ends w/ maxrefopen %d\n", tp_refinfo
.tpr_maxopen
);
504 * FUNCTION and ARGUMENTS:
505 * obtains the next free reference and allocates the appropriate
506 * ref structure, links that structure to (tpcb)
517 tp_getref(struct tp_pcb
*tpcb
)
519 struct tp_ref
*r
, *rlim
;
524 if (++tp_refinfo
.tpr_numopen
< tp_refinfo
.tpr_size
)
525 for (r
= tp_refinfo
.tpr_base
, rlim
= r
+ tp_refinfo
.tpr_size
;
526 ++r
< rlim
;) /* tp_ref[0] is never used */
529 /* else have to allocate more space */
531 obase
= (void *) tp_refinfo
.tpr_base
;
532 size
= tp_refinfo
.tpr_size
* sizeof(struct tp_ref
);
533 r
= (struct tp_ref
*) malloc(size
+ size
, M_PCB
, M_NOWAIT
);
535 return (--tp_refinfo
.tpr_numopen
, TP_ENOREF
);
536 tp_refinfo
.tpr_base
= tp_ref
= r
;
537 tp_refinfo
.tpr_size
*= 2;
538 memcpy(r
, obase
, size
);
540 r
= (struct tp_ref
*)(size
+ (char *)r
);
541 memset((void *) r
, 0, size
);
545 tpcb
->tp_refstate
= REF_OPENING
;
546 i
= r
- tp_refinfo
.tpr_base
;
547 if (tp_refinfo
.tpr_maxopen
< i
)
548 tp_refinfo
.tpr_maxopen
= i
;
553 * NAME: tp_set_npcb()
556 * tp_attach(), tp_route_to()
558 * FUNCTION and ARGUMENTS:
559 * given a tpcb, allocate an appropriate lower-lever npcb, freeing
560 * any old ones that might need re-assigning.
563 tp_set_npcb(struct tp_pcb
*tpcb
)
565 struct socket
*so
= tpcb
->tp_sock
;
568 if (tpcb
->tp_nlproto
&& tpcb
->tp_npcb
) {
569 short so_state
= so
->so_state
;
570 so
->so_state
&= ~SS_NOFDREF
;
571 (*tpcb
->tp_nlproto
->nlp_pcbdetach
)(tpcb
->tp_npcb
);
572 so
->so_state
= so_state
;
574 tpcb
->tp_nlproto
= &nl_protosw
[tpcb
->tp_netservice
];
575 /* xx_pcballoc sets so_pcb */
576 error
= (*tpcb
->tp_nlproto
->nlp_pcballoc
)(so
,
577 tpcb
->tp_nlproto
->nlp_pcblist
);
578 tpcb
->tp_npcb
= so
->so_pcb
;
586 * tp_usrreq, PRU_ATTACH
588 * FUNCTION and ARGUMENTS:
589 * given a socket (so) and a protocol family (dom), allocate a tpcb
590 * and ref structure, initialize everything in the structures that
591 * needs to be initialized.
595 * EINVAL if DEBUG(X) in is on and a disaster has occurred
596 * ENOPROTOOPT if TP hasn't been configured or if the
597 * socket wasn't created with tp as its protocol
598 * EISCONN if this socket is already part of a connection
599 * ETOOMANYREFS if ran out of tp reference numbers.
600 * E* whatever error is returned from soreserve()
601 * for from the network-layer pcb allocation routine
608 tp_attach(struct socket
*so
, int protocol
)
612 int dom
= so
->so_proto
->pr_domain
->dom_family
;
616 if (argo_debug
[D_CONN
]) {
617 printf("tp_attach:dom 0x%x so %p ", dom
, so
);
621 if (tp_traceflags
[D_CONN
]) {
622 tptrace(TPPTmisc
, "tp_attach:dom so", dom
, so
, 0, 0);
626 if (so
->so_pcb
!= NULL
) {
627 return EISCONN
; /* socket already part of a connection */
629 if (so
->so_snd
.sb_hiwat
== 0 || so
->so_rcv
.sb_hiwat
== 0)
630 error
= soreserve(so
, tp_sendspace
, tp_recvspace
);
631 /* later an ioctl will allow reallocation IF still in closed state */
636 tpcb
= malloc(sizeof(*tpcb
), M_PCB
, M_NOWAIT
|M_ZERO
);
642 if (((lref
= tp_getref(tpcb
)) & TP_ENOREF
) != 0) {
643 error
= ETOOMANYREFS
;
646 tpcb
->tp_lref
= lref
;
648 tpcb
->tp_domain
= dom
;
649 tpcb
->tp_rhiwat
= so
->so_rcv
.sb_hiwat
;
650 /* tpcb->tp_proto = protocol; someday maybe? */
651 if (protocol
&& protocol
< ISOPROTO_TP4
) {
652 tpcb
->tp_netservice
= ISO_CONS
;
653 tpcb
->tp_snduna
= (SeqNum
) - 1; /* kludge so the pseudo-ack
654 * from the CR/CC will
655 * generate correct fake-ack
658 tpcb
->tp_netservice
= (dom
== AF_INET
) ? IN_CLNS
: ISO_CLNS
;
661 tpcb
->_tp_param
= tp_conn_param
[tpcb
->tp_netservice
];
663 tpcb
->tp_state
= TP_CLOSED
;
664 tpcb
->tp_vers
= TP_VERSION
;
665 tpcb
->tp_notdetached
= 1;
668 * Spec says default is 128 octets, that is, if the tpdusize argument
669 * never appears, use 128. As the initiator, we will always "propose"
670 * the 2048 size, that is, we will put this argument in the CR
671 * always, but accept what the other side sends on the CC. If the
672 * initiator sends us something larger on a CR, we'll respond w/
673 * this. Our maximum is 4096. See tp_chksum.c comments.
676 tpcb
->tp_l_tpdusize
= 1 << tpcb
->tp_tpdusize
;
678 tpcb
->tp_seqmask
= TP_NML_FMT_MASK
;
679 tpcb
->tp_seqbit
= TP_NML_FMT_BIT
;
680 tpcb
->tp_seqhalf
= tpcb
->tp_seqbit
>> 1;
682 /* attach to a network-layer protoswitch */
683 if ((error
= tp_set_npcb(tpcb
)) != 0)
685 ASSERT(tpcb
->tp_nlproto
->nlp_afamily
== tpcb
->tp_domain
);
687 /* nothing to do for iso case */
688 if (dom
== AF_INET
) {
689 /* tp_set_npcb sets it */
690 KASSERT(so
->so_pcb
!= NULL
);
691 sotoinpcb(so
)->inp_ppcb
= (void *) tpcb
;
698 if (argo_debug
[D_CONN
]) {
699 printf("BAD4 in tp_attach, so %p\n", so
);
702 tp_freeref(tpcb
->tp_lref
);
706 if (argo_debug
[D_CONN
]) {
707 printf("BAD3 in tp_attach, so %p\n", so
);
711 free((void *) tpcb
, M_PCB
); /* never a cluster */
715 if (argo_debug
[D_CONN
]) {
716 printf("BAD2 in tp_attach, so %p\n", so
);
723 if (argo_debug
[D_CONN
]) {
724 printf("BAD in tp_attach, so %p\n", so
);
734 * tp.trans, on behalf of a user close request
735 * and when the reference timer goes off
736 * (if the disconnect was initiated by the protocol entity
737 * rather than by the user)
739 * FUNCTION and ARGUMENTS:
740 * remove the tpcb structure from the list of active or
741 * partially active connections, recycle all the mbufs
742 * associated with the pcb, ref structure, sockbufs, etc.
743 * Only free the ref structure if you know that a ref timer
744 * wasn't set for this tpcb.
751 * tp_soisdisconnected() was already when this is called
754 tp_detach(struct tp_pcb
*tpcb
)
756 struct socket
*so
= tpcb
->tp_sock
;
759 if (argo_debug
[D_CONN
]) {
760 printf("tp_detach(tpcb %p, so %p)\n",
765 if (tp_traceflags
[D_CONN
]) {
766 tptraceTPCB(TPPTmisc
, "tp_detach tpcb so lsufx",
767 tpcb
, so
, *(u_short
*) (tpcb
->tp_lsuffix
), 0);
772 if (argo_debug
[D_CONN
]) {
773 printf("so_snd at %p so_rcv at %p\n", &so
->so_snd
, &so
->so_rcv
);
774 dump_mbuf(so
->so_snd
.sb_mb
, "so_snd at detach ");
775 printf("about to call LL detach, nlproto %p, nl_detach %p\n",
776 tpcb
->tp_nlproto
, tpcb
->tp_nlproto
->nlp_pcbdetach
);
780 if (tpcb
->tp_Xsnd
.sb_mb
) {
781 printf("Unsent Xdata on detach; would panic");
782 sbflush(&tpcb
->tp_Xsnd
);
784 if (tpcb
->tp_ucddata
)
785 m_freem(tpcb
->tp_ucddata
);
788 if (argo_debug
[D_CONN
]) {
789 printf("reassembly info cnt %d rsyq %p\n",
790 tpcb
->tp_rsycnt
, tpcb
->tp_rsyq
);
798 tpcb
->tp_next
= tpcb
->tp_prev
= 0;
800 tpcb
->tp_notdetached
= 0;
803 if (argo_debug
[D_CONN
]) {
804 printf("calling (...nlproto->...)(%p, so %p)\n",
806 printf("so %p so_head %p, qlen %d q0len %d qlimit %d\n",
808 so
->so_q0len
, so
->so_qlen
, so
->so_qlimit
);
812 (*tpcb
->tp_nlproto
->nlp_pcbdetach
)(tpcb
->tp_npcb
);
813 /* does an so->so_pcb = 0; sofree(so) */
816 if (argo_debug
[D_CONN
]) {
817 printf("after xxx_pcbdetach\n");
821 if (tpcb
->tp_state
== TP_LISTENING
) {
823 for (tt
= &tp_listeners
; *tt
; tt
= &((*tt
)->tp_nextlisten
))
827 *tt
= tpcb
->tp_nextlisten
;
829 printf("tp_detach from listen: should panic\n");
831 if (tpcb
->tp_refstate
== REF_OPENING
) {
833 * no connection existed here so no reference timer will be
837 if (argo_debug
[D_CONN
]) {
838 printf("SETTING ref %d to REF_FREE\n", tpcb
->tp_lref
);
842 tp_freeref(tpcb
->tp_lref
);
846 * Get rid of the cluster mbuf allocated for performance
847 * measurements, if there is one. Note that tpcb->tp_perf_on says
848 * nothing about whether or not a cluster mbuf was allocated, so you
849 * have to check for a pointer to one (that is, we need the
850 * TP_PERF_MEASs around the following section of code, not the
853 if (tpcb
->tp_p_meas
) {
854 struct mbuf
*m
= tpcb
->tp_p_mbuf
;
857 if (argo_debug
[D_PERF_MEAS
]) {
858 printf("freeing tp_p_meas 0x%x ", tpcb
->tp_p_meas
);
861 free(tpcb
->tp_p_meas
, M_PCB
);
864 #endif /* TP_PERF_MEAS */
867 if (argo_debug
[D_CONN
]) {
868 printf("end of detach, NOT single, tpcb %p\n", tpcb
);
871 /* free((void *)tpcb, M_PCB); WHere to put this ? */
879 (struct tp_pcb
*) & tp_bound_pcbs
, (struct tp_pcb
*) & tp_bound_pcbs
885 tp_tselinuse(int tlen
, const char *tsel
, struct sockaddr_iso
*siso
,
888 struct tp_pcb
*b
= tp_bound_pcbs
.next
, *l
= tp_listeners
;
892 if (b
!= (struct tp_pcb
*) & tp_bound_pcbs
) {
897 l
= t
->tp_nextlisten
;
900 if (tlen
== t
->tp_lsuffixlen
&& memcmp(tsel
, t
->tp_lsuffix
, tlen
) == 0) {
901 if (t
->tp_flags
& TPF_GENERAL_ADDR
) {
902 if (siso
== 0 || reuseaddr
== 0)
905 if (siso
->siso_family
== t
->tp_domain
&&
906 (*t
->tp_nlproto
->nlp_cmpnetaddr
)(t
->tp_npcb
,
907 (struct sockaddr
*) siso
, TP_LOCAL
))
909 } else if (reuseaddr
== 0)
919 tp_pcbbind(void *v
, struct mbuf
*nam
, struct lwp
*l
)
921 struct tp_pcb
*tpcb
= v
;
922 struct sockaddr_iso
*siso
= 0;
923 int tlen
= 0, wrapped
= 0;
924 const char *tsel
= NULL
;
927 if (tpcb
->tp_state
!= TP_CLOSED
)
930 siso
= mtod(nam
, struct sockaddr_iso
*);
931 switch (siso
->siso_family
) {
933 return (EAFNOSUPPORT
);
936 tlen
= siso
->siso_tlen
;
938 if (siso
->siso_nlen
== 0)
944 tsel
= (void *) & tutil
;
945 if ((tutil
= satosin(siso
)->sin_port
) != 0)
947 if (satosin(siso
)->sin_addr
.s_addr
== 0)
952 if (tpcb
->tp_lsuffixlen
== 0) {
954 if (tp_tselinuse(tlen
, tsel
, siso
,
955 tpcb
->tp_sock
->so_options
& SO_REUSEADDR
))
958 for (tsel
= (void *) & tutil
, tlen
= 2;;) {
959 if (tp_unique
++ < ISO_PORT_RESERVED
||
960 tp_unique
> ISO_PORT_USERRESERVED
) {
963 tp_unique
= ISO_PORT_RESERVED
;
965 tutil
= htons(tp_unique
);
966 if (tp_tselinuse(tlen
, tsel
, siso
, 0) == 0)
970 switch (siso
->siso_family
) {
973 memcpy(WRITABLE_TSEL(siso
), tsel
, tlen
);
974 siso
->siso_tlen
= tlen
;
979 satosin(siso
)->sin_port
= tutil
;
983 memcpy(tpcb
->tp_lsuffix
, tsel
, (tpcb
->tp_lsuffixlen
= tlen
));
984 iso_insque(tpcb
, &tp_bound_pcbs
);
986 if (tlen
|| siso
== 0)
990 tpcb
->tp_flags
|= TPF_GENERAL_ADDR
;
993 return (*tpcb
->tp_nlproto
->nlp_pcbbind
)(tpcb
->tp_npcb
, nam
, l
);