149268Sbostic /*-
2*63222Sbostic * Copyright (c) 1991, 1993
3*63222Sbostic * The Regents of the University of California. All rights reserved.
449268Sbostic *
549268Sbostic * %sccs.include.redist.c%
649268Sbostic *
7*63222Sbostic * @(#)tp_pcb.c 8.1 (Berkeley) 06/10/93
849268Sbostic */
949268Sbostic
1036408Ssklower /***********************************************************
1139196Ssklower Copyright IBM Corporation 1987
1236408Ssklower
1336408Ssklower All Rights Reserved
1436408Ssklower
1536408Ssklower Permission to use, copy, modify, and distribute this software and its
1636408Ssklower documentation for any purpose and without fee is hereby granted,
1736408Ssklower provided that the above copyright notice appear in all copies and that
1836408Ssklower both that copyright notice and this permission notice appear in
1936408Ssklower supporting documentation, and that the name of IBM not be
2036408Ssklower used in advertising or publicity pertaining to distribution of the
2136408Ssklower software without specific, written prior permission.
2236408Ssklower
2336408Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
2436408Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
2536408Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
2636408Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2736408Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2836408Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2936408Ssklower SOFTWARE.
3036408Ssklower
3136408Ssklower ******************************************************************/
3236408Ssklower
3336408Ssklower /*
3436408Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
3536408Ssklower */
3636408Ssklower /*
3736408Ssklower * ARGO TP
3836408Ssklower *
3936408Ssklower * $Header: tp_pcb.c,v 5.4 88/11/18 17:28:24 nhall Exp $
4036408Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_pcb.c,v $
4136408Ssklower *
4236408Ssklower *
4336408Ssklower * This is the initialization and cleanup stuff -
4436408Ssklower * for the tp machine in general as well as for the individual pcbs.
4536408Ssklower * tp_init() is called at system startup. tp_attach() and tp_getref() are
4636408Ssklower * called when a socket is created. tp_detach() and tp_freeref()
4736408Ssklower * are called during the closing stage and/or when the reference timer
4836408Ssklower * goes off.
4936408Ssklower * tp_soisdisconnecting() and tp_soisdisconnected() are tp-specific
5036408Ssklower * versions of soisconnect*
5136408Ssklower * and are called (obviously) during the closing phase.
5236408Ssklower *
5336408Ssklower */
5436408Ssklower
5556533Sbostic #include <sys/param.h>
5656533Sbostic #include <sys/systm.h>
5756533Sbostic #include <sys/mbuf.h>
5856533Sbostic #include <sys/socket.h>
5956533Sbostic #include <sys/socketvar.h>
6056533Sbostic #include <sys/domain.h>
6156533Sbostic #include <sys/protosw.h>
6256533Sbostic #include <sys/errno.h>
6356533Sbostic #include <sys/time.h>
6436408Ssklower
6556533Sbostic #include <netiso/argo_debug.h>
6656533Sbostic #include <netiso/tp_param.h>
6756533Sbostic #include <netiso/tp_timer.h>
6856533Sbostic #include <netiso/tp_ip.h>
6956533Sbostic #include <netiso/tp_stat.h>
7056533Sbostic #include <netiso/tp_pcb.h>
7156533Sbostic #include <netiso/tp_tpdu.h>
7256533Sbostic #include <netiso/tp_trace.h>
7356533Sbostic #include <netiso/tp_meas.h>
7456533Sbostic #include <netiso/tp_seq.h>
7556533Sbostic #include <netiso/tp_clnp.h>
7656533Sbostic
7736408Ssklower /* ticks are in units of:
7836408Ssklower * 500 nano-fortnights ;-) or
7936408Ssklower * 500 ms or
8036408Ssklower * 1/2 second
8136408Ssklower */
8236408Ssklower
8336408Ssklower struct tp_conn_param tp_conn_param[] = {
8436408Ssklower /* ISO_CLNS: TP4 CONNECTION LESS */
8536408Ssklower {
8636408Ssklower TP_NRETRANS, /* short p_Nretrans; */
8736408Ssklower 20, /* 10 sec */ /* short p_dr_ticks; */
8836408Ssklower
8936408Ssklower 20, /* 10 sec */ /* short p_cc_ticks; */
9036408Ssklower 20, /* 10 sec */ /* short p_dt_ticks; */
9136408Ssklower
9236408Ssklower 40, /* 20 sec */ /* short p_x_ticks; */
9336408Ssklower 80, /* 40 sec */ /* short p_cr_ticks;*/
9436408Ssklower
9536408Ssklower 240, /* 2 min */ /* short p_keepalive_ticks;*/
9636408Ssklower 10, /* 5 sec */ /* short p_sendack_ticks; */
9736408Ssklower
9836408Ssklower 600, /* 5 min */ /* short p_ref_ticks; */
9936408Ssklower 360, /* 3 min */ /* short p_inact_ticks; */
10036408Ssklower
10136408Ssklower (short) 100, /* short p_lcdtfract */
10236408Ssklower (short) TP_SOCKBUFSIZE, /* short p_winsize */
10336408Ssklower TP_TPDUSIZE, /* u_char p_tpdusize */
10436408Ssklower
10536408Ssklower TPACK_WINDOW, /* 4 bits p_ack_strat */
10636408Ssklower TPRX_USE_CW | TPRX_FASTSTART,
10736408Ssklower /* 4 bits p_rx_strat*/
10836408Ssklower TP_CLASS_4 | TP_CLASS_0,/* 5 bits p_class */
10936408Ssklower 1, /* 1 bit xtd format */
11036408Ssklower 1, /* 1 bit xpd service */
11136408Ssklower 1, /* 1 bit use_checksum */
11236408Ssklower 0, /* 1 bit use net xpd */
11336408Ssklower 0, /* 1 bit use rcc */
11436408Ssklower 0, /* 1 bit use efc */
11538841Ssklower 1, /* no disc indications */
11636408Ssklower 0, /* don't change params */
11736408Ssklower ISO_CLNS, /* p_netservice */
11836408Ssklower },
11936408Ssklower /* IN_CLNS: TP4 CONNECTION LESS */
12036408Ssklower {
12136408Ssklower TP_NRETRANS, /* short p_Nretrans; */
12236408Ssklower 20, /* 10 sec */ /* short p_dr_ticks; */
12336408Ssklower
12436408Ssklower 20, /* 10 sec */ /* short p_cc_ticks; */
12536408Ssklower 20, /* 10 sec */ /* short p_dt_ticks; */
12636408Ssklower
12736408Ssklower 40, /* 20 sec */ /* short p_x_ticks; */
12836408Ssklower 80, /* 40 sec */ /* short p_cr_ticks;*/
12936408Ssklower
13036408Ssklower 240, /* 2 min */ /* short p_keepalive_ticks;*/
13136408Ssklower 10, /* 5 sec */ /* short p_sendack_ticks; */
13236408Ssklower
13336408Ssklower 600, /* 5 min */ /* short p_ref_ticks; */
13436408Ssklower 360, /* 3 min */ /* short p_inact_ticks; */
13536408Ssklower
13636408Ssklower (short) 100, /* short p_lcdtfract */
13736408Ssklower (short) TP_SOCKBUFSIZE, /* short p_winsize */
13836408Ssklower TP_TPDUSIZE, /* u_char p_tpdusize */
13936408Ssklower
14036408Ssklower TPACK_WINDOW, /* 4 bits p_ack_strat */
14136408Ssklower TPRX_USE_CW | TPRX_FASTSTART,
14236408Ssklower /* 4 bits p_rx_strat*/
14336408Ssklower TP_CLASS_4, /* 5 bits p_class */
14436408Ssklower 1, /* 1 bit xtd format */
14536408Ssklower 1, /* 1 bit xpd service */
14636408Ssklower 1, /* 1 bit use_checksum */
14736408Ssklower 0, /* 1 bit use net xpd */
14836408Ssklower 0, /* 1 bit use rcc */
14936408Ssklower 0, /* 1 bit use efc */
15038841Ssklower 1, /* no disc indications */
15136408Ssklower 0, /* don't change params */
15236408Ssklower IN_CLNS, /* p_netservice */
15336408Ssklower },
15436408Ssklower /* ISO_CONS: TP0 CONNECTION MODE */
15536408Ssklower {
15636408Ssklower TP_NRETRANS, /* short p_Nretrans; */
15736408Ssklower 0, /* n/a */ /* short p_dr_ticks; */
15836408Ssklower
15936408Ssklower 40, /* 20 sec */ /* short p_cc_ticks; */
16036408Ssklower 0, /* n/a */ /* short p_dt_ticks; */
16136408Ssklower
16236408Ssklower 0, /* n/a */ /* short p_x_ticks; */
16336408Ssklower 360, /* 3 min */ /* short p_cr_ticks;*/
16436408Ssklower
16536408Ssklower 0, /* n/a */ /* short p_keepalive_ticks;*/
16636408Ssklower 0, /* n/a */ /* short p_sendack_ticks; */
16736408Ssklower
16836408Ssklower 600, /* for cr/cc to clear *//* short p_ref_ticks; */
16936408Ssklower 0, /* n/a */ /* short p_inact_ticks; */
17036408Ssklower
17136408Ssklower /* Use tp4 defaults just in case the user changes ONLY
17236408Ssklower * the class
17336408Ssklower */
17436408Ssklower (short) 100, /* short p_lcdtfract */
17536408Ssklower (short) TP0_SOCKBUFSIZE, /* short p_winsize */
17636408Ssklower TP0_TPDUSIZE, /* 8 bits p_tpdusize */
17736408Ssklower
17836408Ssklower 0, /* 4 bits p_ack_strat */
17936408Ssklower 0, /* 4 bits p_rx_strat*/
18036408Ssklower TP_CLASS_0, /* 5 bits p_class */
18136408Ssklower 0, /* 1 bit xtd format */
18236408Ssklower 0, /* 1 bit xpd service */
18336408Ssklower 0, /* 1 bit use_checksum */
18436408Ssklower 0, /* 1 bit use net xpd */
18536408Ssklower 0, /* 1 bit use rcc */
18636408Ssklower 0, /* 1 bit use efc */
18736408Ssklower 0, /* no disc indications */
18836408Ssklower 0, /* don't change params */
18936408Ssklower ISO_CONS, /* p_netservice */
19036408Ssklower },
19136408Ssklower /* ISO_COSNS: TP4 CONNECTION LESS SERVICE over CONSNS */
19236408Ssklower {
19336408Ssklower TP_NRETRANS, /* short p_Nretrans; */
19436408Ssklower 40, /* 20 sec */ /* short p_dr_ticks; */
19536408Ssklower
19636408Ssklower 40, /* 20 sec */ /* short p_cc_ticks; */
19736408Ssklower 80, /* 40 sec */ /* short p_dt_ticks; */
19836408Ssklower
19936408Ssklower 120, /* 1 min */ /* short p_x_ticks; */
20036408Ssklower 360, /* 3 min */ /* short p_cr_ticks;*/
20136408Ssklower
20236408Ssklower 360, /* 3 min */ /* short p_keepalive_ticks;*/
20336408Ssklower 20, /* 10 sec */ /* short p_sendack_ticks; */
20436408Ssklower
20536408Ssklower 600, /* 5 min */ /* short p_ref_ticks; */
20636408Ssklower 480, /* 4 min */ /* short p_inact_ticks; */
20736408Ssklower
20836408Ssklower (short) 100, /* short p_lcdtfract */
20936408Ssklower (short) TP0_SOCKBUFSIZE, /* short p_winsize */
21036408Ssklower TP0_TPDUSIZE, /* u_char p_tpdusize */
21136408Ssklower
21236408Ssklower TPACK_WINDOW, /* 4 bits p_ack_strat */
21336408Ssklower TPRX_USE_CW , /* No fast start */
21436408Ssklower /* 4 bits p_rx_strat*/
21536408Ssklower TP_CLASS_4 | TP_CLASS_0,/* 5 bits p_class */
21636408Ssklower 0, /* 1 bit xtd format */
21736408Ssklower 1, /* 1 bit xpd service */
21836408Ssklower 1, /* 1 bit use_checksum */
21936408Ssklower 0, /* 1 bit use net xpd */
22036408Ssklower 0, /* 1 bit use rcc */
22136408Ssklower 0, /* 1 bit use efc */
22236408Ssklower 0, /* no disc indications */
22336408Ssklower 0, /* don't change params */
22436408Ssklower ISO_COSNS, /* p_netservice */
22536408Ssklower },
22636408Ssklower };
22736408Ssklower
22836408Ssklower #ifdef INET
22936408Ssklower int in_putnetaddr();
23036408Ssklower int in_getnetaddr();
23144423Ssklower int in_cmpnetaddr();
23236408Ssklower int in_putsufx();
23336408Ssklower int in_getsufx();
23436408Ssklower int in_recycle_tsuffix();
23536408Ssklower int tpip_mtu();
23636408Ssklower int in_pcbbind();
23736408Ssklower int in_pcbconnect();
23836408Ssklower int in_pcbdisconnect();
23936408Ssklower int in_pcbdetach();
24036408Ssklower int in_pcballoc();
24136408Ssklower int tpip_output();
24236408Ssklower int tpip_output_dg();
24336408Ssklower struct inpcb tp_inpcb;
24460359Sbostic #endif /* INET */
24536408Ssklower #ifdef ISO
24636408Ssklower int iso_putnetaddr();
24736408Ssklower int iso_getnetaddr();
24844423Ssklower int iso_cmpnetaddr();
24936408Ssklower int iso_putsufx();
25036408Ssklower int iso_getsufx();
25136408Ssklower int iso_recycle_tsuffix();
25236408Ssklower int tpclnp_mtu();
25336408Ssklower int iso_pcbbind();
25436408Ssklower int iso_pcbconnect();
25536408Ssklower int iso_pcbdisconnect();
25636408Ssklower int iso_pcbdetach();
25736408Ssklower int iso_pcballoc();
25836408Ssklower int tpclnp_output();
25936408Ssklower int tpclnp_output_dg();
26036408Ssklower int iso_nlctloutput();
26136408Ssklower struct isopcb tp_isopcb;
26260359Sbostic #endif /* ISO */
26345900Ssklower #ifdef TPCONS
26436408Ssklower int iso_putnetaddr();
26536408Ssklower int iso_getnetaddr();
26644423Ssklower int iso_cmpnetaddr();
26736408Ssklower int iso_putsufx();
26836408Ssklower int iso_getsufx();
26936408Ssklower int iso_recycle_tsuffix();
27036408Ssklower int iso_pcbbind();
27145900Ssklower int tpcons_pcbconnect();
27249258Ssklower int tpclnp_mtu();
27336408Ssklower int iso_pcbdisconnect();
27436408Ssklower int iso_pcbdetach();
27536408Ssklower int iso_pcballoc();
27636408Ssklower int tpcons_output();
27736408Ssklower struct isopcb tp_isopcb;
27860359Sbostic #endif /* TPCONS */
27936408Ssklower
28037469Ssklower
28136408Ssklower struct nl_protosw nl_protosw[] = {
28236408Ssklower /* ISO_CLNS */
28336408Ssklower #ifdef ISO
28444423Ssklower { AF_ISO, iso_putnetaddr, iso_getnetaddr, iso_cmpnetaddr,
28536408Ssklower iso_putsufx, iso_getsufx,
28636408Ssklower iso_recycle_tsuffix,
28736408Ssklower tpclnp_mtu, iso_pcbbind, iso_pcbconnect,
28836408Ssklower iso_pcbdisconnect, iso_pcbdetach,
28936408Ssklower iso_pcballoc,
29036408Ssklower tpclnp_output, tpclnp_output_dg, iso_nlctloutput,
29136408Ssklower (caddr_t) &tp_isopcb,
29236408Ssklower },
29337469Ssklower #else
29437469Ssklower { 0 },
29560359Sbostic #endif /* ISO */
29636408Ssklower /* IN_CLNS */
29736408Ssklower #ifdef INET
29844423Ssklower { AF_INET, in_putnetaddr, in_getnetaddr, in_cmpnetaddr,
29936408Ssklower in_putsufx, in_getsufx,
30036408Ssklower in_recycle_tsuffix,
30136408Ssklower tpip_mtu, in_pcbbind, in_pcbconnect,
30236408Ssklower in_pcbdisconnect, in_pcbdetach,
30336408Ssklower in_pcballoc,
30436408Ssklower tpip_output, tpip_output_dg, /* nl_ctloutput */ NULL,
30536408Ssklower (caddr_t) &tp_inpcb,
30636408Ssklower },
30737469Ssklower #else
30837469Ssklower { 0 },
30960359Sbostic #endif /* INET */
31036408Ssklower /* ISO_CONS */
31145900Ssklower #if defined(ISO) && defined(TPCONS)
31244423Ssklower { AF_ISO, iso_putnetaddr, iso_getnetaddr, iso_cmpnetaddr,
31336408Ssklower iso_putsufx, iso_getsufx,
31436408Ssklower iso_recycle_tsuffix,
31549258Ssklower tpclnp_mtu, iso_pcbbind, tpcons_pcbconnect,
31636408Ssklower iso_pcbdisconnect, iso_pcbdetach,
31736408Ssklower iso_pcballoc,
31845900Ssklower tpcons_output, tpcons_output, iso_nlctloutput,
31936408Ssklower (caddr_t) &tp_isopcb,
32036408Ssklower },
32137469Ssklower #else
32237469Ssklower { 0 },
32360359Sbostic #endif /* ISO_CONS */
32437469Ssklower /* End of protosw marker */
32537469Ssklower { 0 }
32636408Ssklower };
32736408Ssklower
32851264Ssklower u_long tp_sendspace = 1024 * 4;
32951264Ssklower u_long tp_recvspace = 1024 * 4;
33051264Ssklower
33136408Ssklower /*
33236408Ssklower * NAME: tp_init()
33336408Ssklower *
33436408Ssklower * CALLED FROM:
33536408Ssklower * autoconf through the protosw structure
33636408Ssklower *
33736408Ssklower * FUNCTION:
33836408Ssklower * initialize tp machine
33936408Ssklower *
34036408Ssklower * RETURNS: Nada
34136408Ssklower *
34236408Ssklower * SIDE EFFECTS:
34336408Ssklower *
34436408Ssklower * NOTES:
34536408Ssklower */
34637469Ssklower int
tp_init()34736408Ssklower tp_init()
34836408Ssklower {
34936408Ssklower static int init_done=0;
35036408Ssklower void tp_timerinit();
35136408Ssklower
35236408Ssklower if (init_done++)
35337469Ssklower return 0;
35436408Ssklower
35536408Ssklower
35636408Ssklower /* FOR INET */
35736408Ssklower tp_inpcb.inp_next = tp_inpcb.inp_prev = &tp_inpcb;
35836408Ssklower /* FOR ISO */
35936408Ssklower tp_isopcb.isop_next = tp_isopcb.isop_prev = &tp_isopcb;
36036408Ssklower
36139923Ssklower tp_start_win = 2;
36239923Ssklower
36336408Ssklower tp_timerinit();
36436408Ssklower bzero((caddr_t)&tp_stat, sizeof(struct tp_stat));
36537469Ssklower return 0;
36636408Ssklower }
36736408Ssklower
36836408Ssklower /*
36936408Ssklower * NAME: tp_soisdisconnecting()
37036408Ssklower *
37136408Ssklower * CALLED FROM:
37236408Ssklower * tp.trans
37336408Ssklower *
37436408Ssklower * FUNCTION and ARGUMENTS:
37536408Ssklower * Set state of the socket (so) to reflect that fact that we're disconnectING
37636408Ssklower *
37736408Ssklower * RETURNS: Nada
37836408Ssklower *
37936408Ssklower * SIDE EFFECTS:
38036408Ssklower *
38136408Ssklower * NOTES:
38236408Ssklower * This differs from the regular soisdisconnecting() in that the latter
38336408Ssklower * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags.
38436408Ssklower * We don't want to set those flags because those flags will cause
38536408Ssklower * a SIGPIPE to be delivered in sosend() and we don't like that.
38636408Ssklower * If anyone else is sleeping on this socket, wake 'em up.
38736408Ssklower */
38836408Ssklower void
tp_soisdisconnecting(so)38936408Ssklower tp_soisdisconnecting(so)
39036408Ssklower register struct socket *so;
39136408Ssklower {
39238841Ssklower soisdisconnecting(so);
39338841Ssklower so->so_state &= ~SS_CANTSENDMORE;
39436408Ssklower IFPERF(sototpcb(so))
39536408Ssklower register struct tp_pcb *tpcb = sototpcb(so);
39636408Ssklower u_int fsufx, lsufx;
39736408Ssklower
39837469Ssklower bcopy ((caddr_t)tpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) );
39937469Ssklower bcopy ((caddr_t)tpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) );
40036408Ssklower
40137469Ssklower tpmeas(tpcb->tp_lref, TPtime_close, &time, fsufx, lsufx, tpcb->tp_fref);
40236408Ssklower tpcb->tp_perf_on = 0; /* turn perf off */
40336408Ssklower ENDPERF
40436408Ssklower }
40536408Ssklower
40636408Ssklower
40736408Ssklower /*
40836408Ssklower * NAME: tp_soisdisconnected()
40936408Ssklower *
41036408Ssklower * CALLED FROM:
41136408Ssklower * tp.trans
41236408Ssklower *
41336408Ssklower * FUNCTION and ARGUMENTS:
41436408Ssklower * Set state of the socket (so) to reflect that fact that we're disconnectED
41536408Ssklower * Set the state of the reference structure to closed, and
41636408Ssklower * recycle the suffix.
41736408Ssklower * Start a reference timer.
41836408Ssklower *
41936408Ssklower * RETURNS: Nada
42036408Ssklower *
42136408Ssklower * SIDE EFFECTS:
42236408Ssklower *
42336408Ssklower * NOTES:
42436408Ssklower * This differs from the regular soisdisconnected() in that the latter
42536408Ssklower * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags.
42636408Ssklower * We don't want to set those flags because those flags will cause
42736408Ssklower * a SIGPIPE to be delivered in sosend() and we don't like that.
42836408Ssklower * If anyone else is sleeping on this socket, wake 'em up.
42936408Ssklower */
43036408Ssklower void
tp_soisdisconnected(tpcb)43136408Ssklower tp_soisdisconnected(tpcb)
43236408Ssklower register struct tp_pcb *tpcb;
43336408Ssklower {
43436408Ssklower register struct socket *so = tpcb->tp_sock;
43536408Ssklower
43638841Ssklower soisdisconnecting(so);
43738841Ssklower so->so_state &= ~SS_CANTSENDMORE;
43851007Ssklower IFPERF(tpcb)
43937469Ssklower register struct tp_pcb *ttpcb = sototpcb(so);
44036408Ssklower u_int fsufx, lsufx;
44136408Ssklower
44236408Ssklower /* CHOKE */
44337469Ssklower bcopy ((caddr_t)ttpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) );
44437469Ssklower bcopy ((caddr_t)ttpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) );
44536408Ssklower
44637469Ssklower tpmeas(ttpcb->tp_lref, TPtime_close,
44737469Ssklower &time, &lsufx, &fsufx, ttpcb->tp_fref);
44836408Ssklower tpcb->tp_perf_on = 0; /* turn perf off */
44936408Ssklower ENDPERF
45036408Ssklower
45151007Ssklower tpcb->tp_refstate = REF_FROZEN;
45251007Ssklower tp_recycle_tsuffix(tpcb);
45351204Ssklower tp_etimeout(tpcb, TM_reference, (int)tpcb->tp_refer_ticks);
45436408Ssklower }
45536408Ssklower
45636408Ssklower /*
45736408Ssklower * NAME: tp_freeref()
45836408Ssklower *
45936408Ssklower * CALLED FROM:
46036408Ssklower * tp.trans when the reference timer goes off, and
46136408Ssklower * from tp_attach() and tp_detach() when a tpcb is partially set up but not
46236408Ssklower * set up enough to have a ref timer set for it, and it's discarded
46336408Ssklower * due to some sort of error or an early close()
46436408Ssklower *
46536408Ssklower * FUNCTION and ARGUMENTS:
46636408Ssklower * Frees the reference represented by (r) for re-use.
46736408Ssklower *
46836408Ssklower * RETURNS: Nothing
46936408Ssklower *
47036408Ssklower * SIDE EFFECTS:
47136408Ssklower *
47236408Ssklower * NOTES: better be called at clock priority !!!!!
47336408Ssklower */
47436408Ssklower void
tp_freeref(n)47551213Ssklower tp_freeref(n)
47651213Ssklower RefNum n;
47736408Ssklower {
47851213Ssklower register struct tp_ref *r = tp_ref + n;
47951213Ssklower register struct tp_pcb *tpcb;
48051213Ssklower
48151213Ssklower tpcb = r->tpr_pcb;
48236408Ssklower IFDEBUG(D_TIMER)
48351213Ssklower printf("tp_freeref called for ref %d pcb %x maxrefopen %d\n",
48451213Ssklower n, tpcb, tp_refinfo.tpr_maxopen);
48536408Ssklower ENDDEBUG
48636408Ssklower IFTRACE(D_TIMER)
48751213Ssklower tptrace(TPPTmisc, "tp_freeref ref maxrefopen pcb",
48851213Ssklower n, tp_refinfo.tpr_maxopen, tpcb, 0);
48936408Ssklower ENDTRACE
49051213Ssklower if (tpcb == 0)
49151213Ssklower return;
49236408Ssklower IFDEBUG(D_CONN)
49351213Ssklower printf("tp_freeref: CLEARING tpr_pcb 0x%x\n", tpcb);
49436408Ssklower ENDDEBUG
49536408Ssklower r->tpr_pcb = (struct tp_pcb *)0;
49651213Ssklower tpcb->tp_refstate = REF_FREE;
49736408Ssklower
49851007Ssklower for (r = tp_ref + tp_refinfo.tpr_maxopen; r > tp_ref; r--)
49951007Ssklower if (r->tpr_pcb)
50051007Ssklower break;
50151007Ssklower tp_refinfo.tpr_maxopen = r - tp_ref;
50251007Ssklower tp_refinfo.tpr_numopen--;
50336408Ssklower
50436408Ssklower IFDEBUG(D_TIMER)
50551007Ssklower printf("tp_freeref ends w/ maxrefopen %d\n", tp_refinfo.tpr_maxopen);
50636408Ssklower ENDDEBUG
50736408Ssklower }
50836408Ssklower
50936408Ssklower /*
51036408Ssklower * NAME: tp_getref()
51136408Ssklower *
51236408Ssklower * CALLED FROM:
51336408Ssklower * tp_attach()
51436408Ssklower *
51536408Ssklower * FUNCTION and ARGUMENTS:
51636408Ssklower * obtains the next free reference and allocates the appropriate
51736408Ssklower * ref structure, links that structure to (tpcb)
51836408Ssklower *
51936408Ssklower * RETURN VALUE:
52036408Ssklower * a reference number
52136408Ssklower * or TP_ENOREF
52236408Ssklower *
52336408Ssklower * SIDE EFFECTS:
52436408Ssklower *
52536408Ssklower * NOTES:
52636408Ssklower */
52751204Ssklower u_long
tp_getref(tpcb)52836408Ssklower tp_getref(tpcb)
52936408Ssklower register struct tp_pcb *tpcb;
53036408Ssklower {
53151007Ssklower register struct tp_ref *r, *rlim;
53251007Ssklower register int i;
53351007Ssklower caddr_t obase;
53451007Ssklower unsigned size;
53536408Ssklower
53651007Ssklower if (++tp_refinfo.tpr_numopen < tp_refinfo.tpr_size)
53751007Ssklower for (r = tp_refinfo.tpr_base, rlim = r + tp_refinfo.tpr_size;
53851007Ssklower ++r < rlim; ) /* tp_ref[0] is never used */
53951007Ssklower if (r->tpr_pcb == 0)
54051007Ssklower goto got_one;
54151007Ssklower /* else have to allocate more space */
54236408Ssklower
54351007Ssklower obase = (caddr_t)tp_refinfo.tpr_base;
54451007Ssklower size = tp_refinfo.tpr_size * sizeof(struct tp_ref);
54551007Ssklower r = (struct tp_ref *) malloc(size + size, M_PCB, M_NOWAIT);
54651007Ssklower if (r == 0)
54751007Ssklower return (--tp_refinfo.tpr_numopen, TP_ENOREF);
54851007Ssklower tp_refinfo.tpr_base = tp_ref = r;
54951007Ssklower tp_refinfo.tpr_size *= 2;
55051007Ssklower bcopy(obase, (caddr_t)r, size);
55151007Ssklower free(obase, M_PCB);
55251007Ssklower r = (struct tp_ref *)(size + (caddr_t)r);
55351007Ssklower bzero((caddr_t)r, size);
55451007Ssklower
55551007Ssklower got_one:
55651007Ssklower r->tpr_pcb = tpcb;
55751213Ssklower tpcb->tp_refstate = REF_OPENING;
55851007Ssklower i = r - tp_refinfo.tpr_base;
55951007Ssklower if (tp_refinfo.tpr_maxopen < i)
56051007Ssklower tp_refinfo.tpr_maxopen = i;
56151213Ssklower return (u_long)i;
56236408Ssklower }
56336408Ssklower
56436408Ssklower /*
56550648Ssklower * NAME: tp_set_npcb()
56650648Ssklower *
56750648Ssklower * CALLED FROM:
56850648Ssklower * tp_attach(), tp_route_to()
56950648Ssklower *
57050648Ssklower * FUNCTION and ARGUMENTS:
57150648Ssklower * given a tpcb, allocate an appropriate lower-lever npcb, freeing
57250648Ssklower * any old ones that might need re-assigning.
57350648Ssklower */
tp_set_npcb(tpcb)57450648Ssklower tp_set_npcb(tpcb)
57550648Ssklower register struct tp_pcb *tpcb;
57650648Ssklower {
57750648Ssklower register struct socket *so = tpcb->tp_sock;
57850648Ssklower int error;
57950648Ssklower
58050648Ssklower if (tpcb->tp_nlproto && tpcb->tp_npcb) {
58150648Ssklower short so_state = so->so_state;
58250648Ssklower so->so_state &= ~SS_NOFDREF;
58350648Ssklower tpcb->tp_nlproto->nlp_pcbdetach(tpcb->tp_npcb);
58450648Ssklower so->so_state = so_state;
58550648Ssklower }
58650648Ssklower tpcb->tp_nlproto = &nl_protosw[tpcb->tp_netservice];
58750648Ssklower /* xx_pcballoc sets so_pcb */
58850648Ssklower error = tpcb->tp_nlproto->nlp_pcballoc(so, tpcb->tp_nlproto->nlp_pcblist);
58950648Ssklower tpcb->tp_npcb = so->so_pcb;
59050648Ssklower so->so_pcb = (caddr_t)tpcb;
59150648Ssklower return (error);
59250648Ssklower }
59350648Ssklower /*
59436408Ssklower * NAME: tp_attach()
59536408Ssklower *
59636408Ssklower * CALLED FROM:
59736408Ssklower * tp_usrreq, PRU_ATTACH
59836408Ssklower *
59936408Ssklower * FUNCTION and ARGUMENTS:
60036408Ssklower * given a socket (so) and a protocol family (dom), allocate a tpcb
60136408Ssklower * and ref structure, initialize everything in the structures that
60236408Ssklower * needs to be initialized.
60336408Ssklower *
60436408Ssklower * RETURN VALUE:
60536408Ssklower * 0 ok
60636408Ssklower * EINVAL if DEBUG(X) in is on and a disaster has occurred
60736408Ssklower * ENOPROTOOPT if TP hasn't been configured or if the
60836408Ssklower * socket wasn't created with tp as its protocol
60936408Ssklower * EISCONN if this socket is already part of a connection
61036408Ssklower * ETOOMANYREFS if ran out of tp reference numbers.
61136408Ssklower * E* whatever error is returned from soreserve()
61236408Ssklower * for from the network-layer pcb allocation routine
61336408Ssklower *
61436408Ssklower * SIDE EFFECTS:
61536408Ssklower *
61636408Ssklower * NOTES:
61736408Ssklower */
61850648Ssklower tp_attach(so, protocol)
61950648Ssklower struct socket *so;
62050648Ssklower int protocol;
62136408Ssklower {
62236408Ssklower register struct tp_pcb *tpcb;
62351264Ssklower int error = 0;
62450648Ssklower int dom = so->so_proto->pr_domain->dom_family;
62551204Ssklower u_long lref;
62636408Ssklower extern struct tp_conn_param tp_conn_param[];
62736408Ssklower
62836408Ssklower IFDEBUG(D_CONN)
62936408Ssklower printf("tp_attach:dom 0x%x so 0x%x ", dom, so);
63036408Ssklower ENDDEBUG
63136408Ssklower IFTRACE(D_CONN)
63236408Ssklower tptrace(TPPTmisc, "tp_attach:dom so", dom, so, 0, 0);
63336408Ssklower ENDTRACE
63436408Ssklower
63536408Ssklower if (so->so_pcb != NULL) {
63636408Ssklower return EISCONN; /* socket already part of a connection*/
63736408Ssklower }
63836408Ssklower
63951264Ssklower if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0)
64051266Ssklower error = soreserve(so, tp_sendspace, tp_recvspace);
64136408Ssklower /* later an ioctl will allow reallocation IF still in closed state */
64236408Ssklower
64336408Ssklower if (error)
64436408Ssklower goto bad2;
64536408Ssklower
64637469Ssklower MALLOC(tpcb, struct tp_pcb *, sizeof(*tpcb), M_PCB, M_NOWAIT);
64737469Ssklower if (tpcb == NULL) {
64836408Ssklower error = ENOBUFS;
64936408Ssklower goto bad2;
65036408Ssklower }
65136408Ssklower bzero( (caddr_t)tpcb, sizeof (struct tp_pcb) );
65236408Ssklower
65351204Ssklower if ( ((lref = tp_getref(tpcb)) & TP_ENOREF) != 0 ) {
65436408Ssklower error = ETOOMANYREFS;
65536408Ssklower goto bad3;
65636408Ssklower }
65751204Ssklower tpcb->tp_lref = lref;
65836408Ssklower tpcb->tp_sock = so;
65936408Ssklower tpcb->tp_domain = dom;
66053687Ssklower tpcb->tp_rhiwat = so->so_rcv.sb_hiwat;
66150648Ssklower /* tpcb->tp_proto = protocol; someday maybe? */
66250648Ssklower if (protocol && protocol<ISOPROTO_TP4) {
66336408Ssklower tpcb->tp_netservice = ISO_CONS;
66436408Ssklower tpcb->tp_snduna = (SeqNum) -1;/* kludge so the pseudo-ack from the CR/CC
66536408Ssklower * will generate correct fake-ack values
66636408Ssklower */
66736408Ssklower } else {
66836408Ssklower tpcb->tp_netservice = (dom== AF_INET)?IN_CLNS:ISO_CLNS;
66936408Ssklower /* the default */
67036408Ssklower }
67136408Ssklower tpcb->_tp_param = tp_conn_param[tpcb->tp_netservice];
67236408Ssklower
67336408Ssklower tpcb->tp_state = TP_CLOSED;
67436408Ssklower tpcb->tp_vers = TP_VERSION;
67550940Ssklower tpcb->tp_notdetached = 1;
67636408Ssklower
67736408Ssklower /* Spec says default is 128 octets,
67836408Ssklower * that is, if the tpdusize argument never appears, use 128.
67936408Ssklower * As the initiator, we will always "propose" the 2048
68036408Ssklower * size, that is, we will put this argument in the CR
68136408Ssklower * always, but accept what the other side sends on the CC.
68236408Ssklower * If the initiator sends us something larger on a CR,
68336408Ssklower * we'll respond w/ this.
68436408Ssklower * Our maximum is 4096. See tp_chksum.c comments.
68536408Ssklower */
68651204Ssklower tpcb->tp_cong_win =
68751204Ssklower tpcb->tp_l_tpdusize = 1 << tpcb->tp_tpdusize;
68836408Ssklower
68936408Ssklower tpcb->tp_seqmask = TP_NML_FMT_MASK;
69036408Ssklower tpcb->tp_seqbit = TP_NML_FMT_BIT;
69136408Ssklower tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1;
69236408Ssklower
69336408Ssklower /* attach to a network-layer protoswitch */
69450648Ssklower if ( error = tp_set_npcb(tpcb))
69550648Ssklower goto bad4;
69636408Ssklower ASSERT( tpcb->tp_nlproto->nlp_afamily == tpcb->tp_domain);
69736408Ssklower
69850648Ssklower /* nothing to do for iso case */
69936408Ssklower if( dom == AF_INET )
70036408Ssklower sotoinpcb(so)->inp_ppcb = (caddr_t) tpcb;
70136408Ssklower
70236408Ssklower return 0;
70336408Ssklower
70436408Ssklower bad4:
70536408Ssklower IFDEBUG(D_CONN)
70636408Ssklower printf("BAD4 in tp_attach, so 0x%x\n", so);
70736408Ssklower ENDDEBUG
70851213Ssklower tp_freeref(tpcb->tp_lref);
70936408Ssklower
71036408Ssklower bad3:
71136408Ssklower IFDEBUG(D_CONN)
71236408Ssklower printf("BAD3 in tp_attach, so 0x%x\n", so);
71336408Ssklower ENDDEBUG
71436408Ssklower
71537469Ssklower free((caddr_t)tpcb, M_PCB); /* never a cluster */
71636408Ssklower
71736408Ssklower bad2:
71836408Ssklower IFDEBUG(D_CONN)
71936408Ssklower printf("BAD2 in tp_attach, so 0x%x\n", so);
72036408Ssklower ENDDEBUG
72136408Ssklower so->so_pcb = 0;
72236408Ssklower
72337469Ssklower /*bad:*/
72436408Ssklower IFDEBUG(D_CONN)
72536408Ssklower printf("BAD in tp_attach, so 0x%x\n", so);
72636408Ssklower ENDDEBUG
72736408Ssklower return error;
72836408Ssklower }
72936408Ssklower
73036408Ssklower /*
73136408Ssklower * NAME: tp_detach()
73236408Ssklower *
73336408Ssklower * CALLED FROM:
73436408Ssklower * tp.trans, on behalf of a user close request
73536408Ssklower * and when the reference timer goes off
73636408Ssklower * (if the disconnect was initiated by the protocol entity
73736408Ssklower * rather than by the user)
73836408Ssklower *
73936408Ssklower * FUNCTION and ARGUMENTS:
74036408Ssklower * remove the tpcb structure from the list of active or
74136408Ssklower * partially active connections, recycle all the mbufs
74236408Ssklower * associated with the pcb, ref structure, sockbufs, etc.
74336408Ssklower * Only free the ref structure if you know that a ref timer
74436408Ssklower * wasn't set for this tpcb.
74536408Ssklower *
74636408Ssklower * RETURNS: Nada
74736408Ssklower *
74836408Ssklower * SIDE EFFECTS:
74936408Ssklower *
75036408Ssklower * NOTES:
75136408Ssklower * tp_soisdisconnected() was already when this is called
75236408Ssklower */
75336408Ssklower void
tp_detach(tpcb)75436408Ssklower tp_detach(tpcb)
75536408Ssklower register struct tp_pcb *tpcb;
75636408Ssklower {
75750904Ssklower void tp_freeref(), tp_rsyflush();
75836408Ssklower register struct socket *so = tpcb->tp_sock;
75936408Ssklower
76036408Ssklower IFDEBUG(D_CONN)
76137469Ssklower printf("tp_detach(tpcb 0x%x, so 0x%x)\n",
76237469Ssklower tpcb,so);
76336408Ssklower ENDDEBUG
76436408Ssklower IFTRACE(D_CONN)
76536408Ssklower tptraceTPCB(TPPTmisc, "tp_detach tpcb so lsufx",
76639196Ssklower tpcb, so, *(u_short *)(tpcb->tp_lsuffix), 0);
76736408Ssklower ENDTRACE
76836408Ssklower
76936408Ssklower IFDEBUG(D_CONN)
77047278Ssklower printf("so_snd at 0x%x so_rcv at 0x%x\n", &so->so_snd, &so->so_rcv);
77147278Ssklower dump_mbuf(so->so_snd.sb_mb, "so_snd at detach ");
77247278Ssklower printf("about to call LL detach, nlproto 0x%x, nl_detach 0x%x\n",
77347278Ssklower tpcb->tp_nlproto, tpcb->tp_nlproto->nlp_pcbdetach);
77447278Ssklower ENDDEBUG
77547278Ssklower
77650648Ssklower if (tpcb->tp_Xsnd.sb_mb) {
77750648Ssklower printf("Unsent Xdata on detach; would panic");
77850648Ssklower sbflush(&tpcb->tp_Xsnd);
77950648Ssklower }
78047278Ssklower if (tpcb->tp_ucddata)
78147278Ssklower m_freem(tpcb->tp_ucddata);
78247278Ssklower
78347278Ssklower IFDEBUG(D_CONN)
78450904Ssklower printf("reassembly info cnt %d rsyq 0x%x\n",
78550904Ssklower tpcb->tp_rsycnt, tpcb->tp_rsyq);
78650904Ssklower ENDDEBUG
78750904Ssklower if (tpcb->tp_rsyq)
78850904Ssklower tp_rsyflush(tpcb);
78950904Ssklower
79050940Ssklower if (tpcb->tp_next) {
79150940Ssklower remque(tpcb);
79250940Ssklower tpcb->tp_next = tpcb->tp_prev = 0;
79350940Ssklower }
79450940Ssklower tpcb->tp_notdetached = 0;
79550940Ssklower
79650904Ssklower IFDEBUG(D_CONN)
79736408Ssklower printf("calling (...nlproto->...)(0x%x, so 0x%x)\n",
79850435Ssklower tpcb->tp_npcb, so);
79936408Ssklower printf("so 0x%x so_head 0x%x, qlen %d q0len %d qlimit %d\n",
80036408Ssklower so, so->so_head,
80136408Ssklower so->so_q0len, so->so_qlen, so->so_qlimit);
80236408Ssklower ENDDEBUG
80336408Ssklower
80450435Ssklower (tpcb->tp_nlproto->nlp_pcbdetach)(tpcb->tp_npcb);
80550648Ssklower /* does an so->so_pcb = 0; sofree(so) */
80637469Ssklower
80736408Ssklower IFDEBUG(D_CONN)
80836408Ssklower printf("after xxx_pcbdetach\n");
80936408Ssklower ENDDEBUG
81036408Ssklower
81150940Ssklower if (tpcb->tp_state == TP_LISTENING) {
81250940Ssklower register struct tp_pcb **tt;
81350940Ssklower for (tt = &tp_listeners; *tt; tt = &((*tt)->tp_nextlisten))
81450940Ssklower if (*tt == tpcb)
81550940Ssklower break;
81650940Ssklower if (*tt)
81750940Ssklower *tt = tpcb->tp_nextlisten;
81850940Ssklower else
81950940Ssklower printf("tp_detach from listen: should panic\n");
82050940Ssklower }
82151213Ssklower if (tpcb->tp_refstate == REF_OPENING ) {
82236408Ssklower /* no connection existed here so no reference timer will be called */
82336408Ssklower IFDEBUG(D_CONN)
82451213Ssklower printf("SETTING ref %d to REF_FREE\n", tpcb->tp_lref);
82536408Ssklower ENDDEBUG
82636408Ssklower
82751213Ssklower tp_freeref(tpcb->tp_lref);
82836408Ssklower }
82950648Ssklower #ifdef TP_PERF_MEAS
83036408Ssklower /*
83136408Ssklower * Get rid of the cluster mbuf allocated for performance measurements, if
83236408Ssklower * there is one. Note that tpcb->tp_perf_on says nothing about whether or
83336408Ssklower * not a cluster mbuf was allocated, so you have to check for a pointer
83436408Ssklower * to one (that is, we need the TP_PERF_MEASs around the following section
83536408Ssklower * of code, not the IFPERFs)
83636408Ssklower */
83747278Ssklower if (tpcb->tp_p_mbuf) {
83837469Ssklower register struct mbuf *m = tpcb->tp_p_mbuf;
83937469Ssklower struct mbuf *n;
84036408Ssklower IFDEBUG(D_PERF_MEAS)
84136408Ssklower printf("freeing tp_p_meas 0x%x ", tpcb->tp_p_meas);
84236408Ssklower ENDDEBUG
84337469Ssklower do {
84437469Ssklower MFREE(m, n);
84537469Ssklower m = n;
84637469Ssklower } while (n);
84737469Ssklower tpcb->tp_p_meas = 0;
84837469Ssklower tpcb->tp_p_mbuf = 0;
84936408Ssklower }
85060359Sbostic #endif /* TP_PERF_MEAS */
85136408Ssklower
85236408Ssklower IFDEBUG(D_CONN)
85337469Ssklower printf( "end of detach, NOT single, tpcb 0x%x\n", tpcb);
85436408Ssklower ENDDEBUG
85537469Ssklower /* free((caddr_t)tpcb, M_PCB); WHere to put this ? */
85636408Ssklower }
85750501Ssklower
85850501Ssklower struct que {
85950501Ssklower struct tp_pcb *next;
86050501Ssklower struct tp_pcb *prev;
86150501Ssklower } tp_bound_pcbs =
86250501Ssklower {(struct tp_pcb *)&tp_bound_pcbs, (struct tp_pcb *)&tp_bound_pcbs};
86350501Ssklower
86450501Ssklower u_short tp_unique;
86550501Ssklower
tp_tselinuse(tlen,tsel,siso,reuseaddr)86650501Ssklower tp_tselinuse(tlen, tsel, siso, reuseaddr)
86750501Ssklower caddr_t tsel;
86850501Ssklower register struct sockaddr_iso *siso;
86950501Ssklower {
87050501Ssklower struct tp_pcb *b = tp_bound_pcbs.next, *l = tp_listeners;
87150501Ssklower register struct tp_pcb *t;
87250501Ssklower
87350501Ssklower for (;;) {
87450501Ssklower if (b != (struct tp_pcb *)&tp_bound_pcbs) {
87550501Ssklower t = b; b = t->tp_next;
87650501Ssklower } else if (l) {
87750501Ssklower t = l; l = t->tp_nextlisten;
87850501Ssklower } else
87950501Ssklower break;
88050501Ssklower if (tlen == t->tp_lsuffixlen && bcmp(tsel, t->tp_lsuffix, tlen) == 0) {
88150501Ssklower if (t->tp_flags & TPF_GENERAL_ADDR) {
88250501Ssklower if (siso == 0 || reuseaddr == 0)
88350501Ssklower return 1;
88450501Ssklower } else if (siso) {
88550501Ssklower if (siso->siso_family == t->tp_domain &&
88650501Ssklower t->tp_nlproto->nlp_cmpnetaddr(t->tp_npcb, siso, TP_LOCAL))
88750501Ssklower return 1;
88850501Ssklower } else if (reuseaddr == 0)
88950501Ssklower return 1;
89050501Ssklower }
89150501Ssklower }
89250501Ssklower return 0;
89350501Ssklower
89450501Ssklower }
89550501Ssklower
89650501Ssklower
tp_pcbbind(tpcb,nam)89750501Ssklower tp_pcbbind(tpcb, nam)
89850501Ssklower register struct tp_pcb *tpcb;
89950501Ssklower register struct mbuf *nam;
90050501Ssklower {
90150501Ssklower register struct sockaddr_iso *siso = 0;
90250501Ssklower int tlen = 0, wrapped = 0;
90350501Ssklower caddr_t tsel;
90450501Ssklower u_short tutil;
90550501Ssklower
90650501Ssklower if (tpcb->tp_state != TP_CLOSED)
90750501Ssklower return (EINVAL);
90850501Ssklower if (nam) {
90950501Ssklower siso = mtod(nam, struct sockaddr_iso *);
91050501Ssklower switch (siso->siso_family) {
91150501Ssklower default:
91250501Ssklower return (EAFNOSUPPORT);
91350501Ssklower #ifdef ISO
91450501Ssklower case AF_ISO:
91550501Ssklower tlen = siso->siso_tlen;
91650501Ssklower tsel = TSEL(siso);
91750501Ssklower if (siso->siso_nlen == 0)
91850501Ssklower siso = 0;
91950501Ssklower break;
92050501Ssklower #endif
92150501Ssklower #ifdef INET
92250501Ssklower case AF_INET:
92350501Ssklower tsel = (caddr_t)&tutil;
92450501Ssklower if (tutil = ((struct sockaddr_in *)siso)->sin_port) {
92550501Ssklower tlen = 2;
92650501Ssklower }
92750501Ssklower if (((struct sockaddr_in *)siso)->sin_addr.s_addr == 0)
92850501Ssklower siso = 0;
92950501Ssklower }
93050501Ssklower #endif
93150501Ssklower }
93250501Ssklower if (tpcb->tp_lsuffixlen == 0) {
93350501Ssklower if (tlen) {
93450648Ssklower if (tp_tselinuse(tlen, tsel, siso,
93550501Ssklower tpcb->tp_sock->so_options & SO_REUSEADDR))
93650501Ssklower return (EINVAL);
93753185Ssklower } else {
93853185Ssklower for (tsel = (caddr_t)&tutil, tlen = 2;;){
93953185Ssklower if (tp_unique++ < ISO_PORT_RESERVED ||
94053185Ssklower tp_unique > ISO_PORT_USERRESERVED) {
94153185Ssklower if (wrapped++)
94253185Ssklower return ESRCH;
94353185Ssklower tp_unique = ISO_PORT_RESERVED;
94453185Ssklower }
94553185Ssklower tutil = htons(tp_unique);
94653185Ssklower if (tp_tselinuse(tlen, tsel, siso, 0) == 0)
94753185Ssklower break;
94850501Ssklower }
94953185Ssklower if (siso) switch (siso->siso_family) {
95053185Ssklower #ifdef ISO
95153185Ssklower case AF_ISO:
95253185Ssklower bcopy(tsel, TSEL(siso), tlen);
95353185Ssklower siso->siso_tlen = tlen;
95453185Ssklower break;
95553185Ssklower #endif
95653185Ssklower #ifdef INET
95753185Ssklower case AF_INET:
95853185Ssklower ((struct sockaddr_in *)siso)->sin_port = tutil;
95953185Ssklower #endif
96053185Ssklower }
96150501Ssklower }
96250501Ssklower bcopy(tsel, tpcb->tp_lsuffix, (tpcb->tp_lsuffixlen = tlen));
96350501Ssklower insque(tpcb, &tp_bound_pcbs);
96450501Ssklower } else {
96550501Ssklower if (tlen || siso == 0)
96650501Ssklower return (EINVAL);
96750501Ssklower }
96850501Ssklower if (siso == 0) {
96950501Ssklower tpcb->tp_flags |= TPF_GENERAL_ADDR;
97050501Ssklower return (0);
97150501Ssklower }
97250501Ssklower return tpcb->tp_nlproto->nlp_pcbbind(tpcb->tp_npcb, nam);
97350501Ssklower }
974