149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*53687Ssklower * @(#)tp_pcb.c 7.24 (Berkeley) 05/27/92 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 5536408Ssklower #include "param.h" 5650648Ssklower #include "systm.h" 5736408Ssklower #include "mbuf.h" 5836408Ssklower #include "socket.h" 5936408Ssklower #include "socketvar.h" 6050648Ssklower #include "domain.h" 6136408Ssklower #include "protosw.h" 6236408Ssklower #include "errno.h" 6336408Ssklower #include "time.h" 6437469Ssklower #include "argo_debug.h" 6537469Ssklower #include "tp_param.h" 6637469Ssklower #include "tp_timer.h" 6737469Ssklower #include "tp_ip.h" 6837469Ssklower #include "tp_stat.h" 6937469Ssklower #include "tp_pcb.h" 7037469Ssklower #include "tp_tpdu.h" 7137469Ssklower #include "tp_trace.h" 7237469Ssklower #include "tp_meas.h" 7337469Ssklower #include "tp_seq.h" 7437469Ssklower #include "tp_clnp.h" 7536408Ssklower 7636408Ssklower /* ticks are in units of: 7736408Ssklower * 500 nano-fortnights ;-) or 7836408Ssklower * 500 ms or 7936408Ssklower * 1/2 second 8036408Ssklower */ 8136408Ssklower 8236408Ssklower struct tp_conn_param tp_conn_param[] = { 8336408Ssklower /* ISO_CLNS: TP4 CONNECTION LESS */ 8436408Ssklower { 8536408Ssklower TP_NRETRANS, /* short p_Nretrans; */ 8636408Ssklower 20, /* 10 sec */ /* short p_dr_ticks; */ 8736408Ssklower 8836408Ssklower 20, /* 10 sec */ /* short p_cc_ticks; */ 8936408Ssklower 20, /* 10 sec */ /* short p_dt_ticks; */ 9036408Ssklower 9136408Ssklower 40, /* 20 sec */ /* short p_x_ticks; */ 9236408Ssklower 80, /* 40 sec */ /* short p_cr_ticks;*/ 9336408Ssklower 9436408Ssklower 240, /* 2 min */ /* short p_keepalive_ticks;*/ 9536408Ssklower 10, /* 5 sec */ /* short p_sendack_ticks; */ 9636408Ssklower 9736408Ssklower 600, /* 5 min */ /* short p_ref_ticks; */ 9836408Ssklower 360, /* 3 min */ /* short p_inact_ticks; */ 9936408Ssklower 10036408Ssklower (short) 100, /* short p_lcdtfract */ 10136408Ssklower (short) TP_SOCKBUFSIZE, /* short p_winsize */ 10236408Ssklower TP_TPDUSIZE, /* u_char p_tpdusize */ 10336408Ssklower 10436408Ssklower TPACK_WINDOW, /* 4 bits p_ack_strat */ 10536408Ssklower TPRX_USE_CW | TPRX_FASTSTART, 10636408Ssklower /* 4 bits p_rx_strat*/ 10736408Ssklower TP_CLASS_4 | TP_CLASS_0,/* 5 bits p_class */ 10836408Ssklower 1, /* 1 bit xtd format */ 10936408Ssklower 1, /* 1 bit xpd service */ 11036408Ssklower 1, /* 1 bit use_checksum */ 11136408Ssklower 0, /* 1 bit use net xpd */ 11236408Ssklower 0, /* 1 bit use rcc */ 11336408Ssklower 0, /* 1 bit use efc */ 11438841Ssklower 1, /* no disc indications */ 11536408Ssklower 0, /* don't change params */ 11636408Ssklower ISO_CLNS, /* p_netservice */ 11736408Ssklower }, 11836408Ssklower /* IN_CLNS: TP4 CONNECTION LESS */ 11936408Ssklower { 12036408Ssklower TP_NRETRANS, /* short p_Nretrans; */ 12136408Ssklower 20, /* 10 sec */ /* short p_dr_ticks; */ 12236408Ssklower 12336408Ssklower 20, /* 10 sec */ /* short p_cc_ticks; */ 12436408Ssklower 20, /* 10 sec */ /* short p_dt_ticks; */ 12536408Ssklower 12636408Ssklower 40, /* 20 sec */ /* short p_x_ticks; */ 12736408Ssklower 80, /* 40 sec */ /* short p_cr_ticks;*/ 12836408Ssklower 12936408Ssklower 240, /* 2 min */ /* short p_keepalive_ticks;*/ 13036408Ssklower 10, /* 5 sec */ /* short p_sendack_ticks; */ 13136408Ssklower 13236408Ssklower 600, /* 5 min */ /* short p_ref_ticks; */ 13336408Ssklower 360, /* 3 min */ /* short p_inact_ticks; */ 13436408Ssklower 13536408Ssklower (short) 100, /* short p_lcdtfract */ 13636408Ssklower (short) TP_SOCKBUFSIZE, /* short p_winsize */ 13736408Ssklower TP_TPDUSIZE, /* u_char p_tpdusize */ 13836408Ssklower 13936408Ssklower TPACK_WINDOW, /* 4 bits p_ack_strat */ 14036408Ssklower TPRX_USE_CW | TPRX_FASTSTART, 14136408Ssklower /* 4 bits p_rx_strat*/ 14236408Ssklower TP_CLASS_4, /* 5 bits p_class */ 14336408Ssklower 1, /* 1 bit xtd format */ 14436408Ssklower 1, /* 1 bit xpd service */ 14536408Ssklower 1, /* 1 bit use_checksum */ 14636408Ssklower 0, /* 1 bit use net xpd */ 14736408Ssklower 0, /* 1 bit use rcc */ 14836408Ssklower 0, /* 1 bit use efc */ 14938841Ssklower 1, /* no disc indications */ 15036408Ssklower 0, /* don't change params */ 15136408Ssklower IN_CLNS, /* p_netservice */ 15236408Ssklower }, 15336408Ssklower /* ISO_CONS: TP0 CONNECTION MODE */ 15436408Ssklower { 15536408Ssklower TP_NRETRANS, /* short p_Nretrans; */ 15636408Ssklower 0, /* n/a */ /* short p_dr_ticks; */ 15736408Ssklower 15836408Ssklower 40, /* 20 sec */ /* short p_cc_ticks; */ 15936408Ssklower 0, /* n/a */ /* short p_dt_ticks; */ 16036408Ssklower 16136408Ssklower 0, /* n/a */ /* short p_x_ticks; */ 16236408Ssklower 360, /* 3 min */ /* short p_cr_ticks;*/ 16336408Ssklower 16436408Ssklower 0, /* n/a */ /* short p_keepalive_ticks;*/ 16536408Ssklower 0, /* n/a */ /* short p_sendack_ticks; */ 16636408Ssklower 16736408Ssklower 600, /* for cr/cc to clear *//* short p_ref_ticks; */ 16836408Ssklower 0, /* n/a */ /* short p_inact_ticks; */ 16936408Ssklower 17036408Ssklower /* Use tp4 defaults just in case the user changes ONLY 17136408Ssklower * the class 17236408Ssklower */ 17336408Ssklower (short) 100, /* short p_lcdtfract */ 17436408Ssklower (short) TP0_SOCKBUFSIZE, /* short p_winsize */ 17536408Ssklower TP0_TPDUSIZE, /* 8 bits p_tpdusize */ 17636408Ssklower 17736408Ssklower 0, /* 4 bits p_ack_strat */ 17836408Ssklower 0, /* 4 bits p_rx_strat*/ 17936408Ssklower TP_CLASS_0, /* 5 bits p_class */ 18036408Ssklower 0, /* 1 bit xtd format */ 18136408Ssklower 0, /* 1 bit xpd service */ 18236408Ssklower 0, /* 1 bit use_checksum */ 18336408Ssklower 0, /* 1 bit use net xpd */ 18436408Ssklower 0, /* 1 bit use rcc */ 18536408Ssklower 0, /* 1 bit use efc */ 18636408Ssklower 0, /* no disc indications */ 18736408Ssklower 0, /* don't change params */ 18836408Ssklower ISO_CONS, /* p_netservice */ 18936408Ssklower }, 19036408Ssklower /* ISO_COSNS: TP4 CONNECTION LESS SERVICE over CONSNS */ 19136408Ssklower { 19236408Ssklower TP_NRETRANS, /* short p_Nretrans; */ 19336408Ssklower 40, /* 20 sec */ /* short p_dr_ticks; */ 19436408Ssklower 19536408Ssklower 40, /* 20 sec */ /* short p_cc_ticks; */ 19636408Ssklower 80, /* 40 sec */ /* short p_dt_ticks; */ 19736408Ssklower 19836408Ssklower 120, /* 1 min */ /* short p_x_ticks; */ 19936408Ssklower 360, /* 3 min */ /* short p_cr_ticks;*/ 20036408Ssklower 20136408Ssklower 360, /* 3 min */ /* short p_keepalive_ticks;*/ 20236408Ssklower 20, /* 10 sec */ /* short p_sendack_ticks; */ 20336408Ssklower 20436408Ssklower 600, /* 5 min */ /* short p_ref_ticks; */ 20536408Ssklower 480, /* 4 min */ /* short p_inact_ticks; */ 20636408Ssklower 20736408Ssklower (short) 100, /* short p_lcdtfract */ 20836408Ssklower (short) TP0_SOCKBUFSIZE, /* short p_winsize */ 20936408Ssklower TP0_TPDUSIZE, /* u_char p_tpdusize */ 21036408Ssklower 21136408Ssklower TPACK_WINDOW, /* 4 bits p_ack_strat */ 21236408Ssklower TPRX_USE_CW , /* No fast start */ 21336408Ssklower /* 4 bits p_rx_strat*/ 21436408Ssklower TP_CLASS_4 | TP_CLASS_0,/* 5 bits p_class */ 21536408Ssklower 0, /* 1 bit xtd format */ 21636408Ssklower 1, /* 1 bit xpd service */ 21736408Ssklower 1, /* 1 bit use_checksum */ 21836408Ssklower 0, /* 1 bit use net xpd */ 21936408Ssklower 0, /* 1 bit use rcc */ 22036408Ssklower 0, /* 1 bit use efc */ 22136408Ssklower 0, /* no disc indications */ 22236408Ssklower 0, /* don't change params */ 22336408Ssklower ISO_COSNS, /* p_netservice */ 22436408Ssklower }, 22536408Ssklower }; 22636408Ssklower 22736408Ssklower #ifdef INET 22836408Ssklower int in_putnetaddr(); 22936408Ssklower int in_getnetaddr(); 23044423Ssklower int in_cmpnetaddr(); 23136408Ssklower int in_putsufx(); 23236408Ssklower int in_getsufx(); 23336408Ssklower int in_recycle_tsuffix(); 23436408Ssklower int tpip_mtu(); 23536408Ssklower int in_pcbbind(); 23636408Ssklower int in_pcbconnect(); 23736408Ssklower int in_pcbdisconnect(); 23836408Ssklower int in_pcbdetach(); 23936408Ssklower int in_pcballoc(); 24036408Ssklower int tpip_output(); 24136408Ssklower int tpip_output_dg(); 24236408Ssklower struct inpcb tp_inpcb; 24336408Ssklower #endif INET 24436408Ssklower #ifdef ISO 24536408Ssklower int iso_putnetaddr(); 24636408Ssklower int iso_getnetaddr(); 24744423Ssklower int iso_cmpnetaddr(); 24836408Ssklower int iso_putsufx(); 24936408Ssklower int iso_getsufx(); 25036408Ssklower int iso_recycle_tsuffix(); 25136408Ssklower int tpclnp_mtu(); 25236408Ssklower int iso_pcbbind(); 25336408Ssklower int iso_pcbconnect(); 25436408Ssklower int iso_pcbdisconnect(); 25536408Ssklower int iso_pcbdetach(); 25636408Ssklower int iso_pcballoc(); 25736408Ssklower int tpclnp_output(); 25836408Ssklower int tpclnp_output_dg(); 25936408Ssklower int iso_nlctloutput(); 26036408Ssklower struct isopcb tp_isopcb; 26136408Ssklower #endif ISO 26245900Ssklower #ifdef TPCONS 26336408Ssklower int iso_putnetaddr(); 26436408Ssklower int iso_getnetaddr(); 26544423Ssklower int iso_cmpnetaddr(); 26636408Ssklower int iso_putsufx(); 26736408Ssklower int iso_getsufx(); 26836408Ssklower int iso_recycle_tsuffix(); 26936408Ssklower int iso_pcbbind(); 27045900Ssklower int tpcons_pcbconnect(); 27149258Ssklower int tpclnp_mtu(); 27236408Ssklower int iso_pcbdisconnect(); 27336408Ssklower int iso_pcbdetach(); 27436408Ssklower int iso_pcballoc(); 27536408Ssklower int tpcons_output(); 27636408Ssklower struct isopcb tp_isopcb; 27745900Ssklower #endif TPCONS 27836408Ssklower 27937469Ssklower 28036408Ssklower struct nl_protosw nl_protosw[] = { 28136408Ssklower /* ISO_CLNS */ 28236408Ssklower #ifdef ISO 28344423Ssklower { AF_ISO, iso_putnetaddr, iso_getnetaddr, iso_cmpnetaddr, 28436408Ssklower iso_putsufx, iso_getsufx, 28536408Ssklower iso_recycle_tsuffix, 28636408Ssklower tpclnp_mtu, iso_pcbbind, iso_pcbconnect, 28736408Ssklower iso_pcbdisconnect, iso_pcbdetach, 28836408Ssklower iso_pcballoc, 28936408Ssklower tpclnp_output, tpclnp_output_dg, iso_nlctloutput, 29036408Ssklower (caddr_t) &tp_isopcb, 29136408Ssklower }, 29237469Ssklower #else 29337469Ssklower { 0 }, 29436408Ssklower #endif ISO 29536408Ssklower /* IN_CLNS */ 29636408Ssklower #ifdef INET 29744423Ssklower { AF_INET, in_putnetaddr, in_getnetaddr, in_cmpnetaddr, 29836408Ssklower in_putsufx, in_getsufx, 29936408Ssklower in_recycle_tsuffix, 30036408Ssklower tpip_mtu, in_pcbbind, in_pcbconnect, 30136408Ssklower in_pcbdisconnect, in_pcbdetach, 30236408Ssklower in_pcballoc, 30336408Ssklower tpip_output, tpip_output_dg, /* nl_ctloutput */ NULL, 30436408Ssklower (caddr_t) &tp_inpcb, 30536408Ssklower }, 30637469Ssklower #else 30737469Ssklower { 0 }, 30836408Ssklower #endif INET 30936408Ssklower /* ISO_CONS */ 31045900Ssklower #if defined(ISO) && defined(TPCONS) 31144423Ssklower { AF_ISO, iso_putnetaddr, iso_getnetaddr, iso_cmpnetaddr, 31236408Ssklower iso_putsufx, iso_getsufx, 31336408Ssklower iso_recycle_tsuffix, 31449258Ssklower tpclnp_mtu, iso_pcbbind, tpcons_pcbconnect, 31536408Ssklower iso_pcbdisconnect, iso_pcbdetach, 31636408Ssklower iso_pcballoc, 31745900Ssklower tpcons_output, tpcons_output, iso_nlctloutput, 31836408Ssklower (caddr_t) &tp_isopcb, 31936408Ssklower }, 32037469Ssklower #else 32137469Ssklower { 0 }, 32237469Ssklower #endif ISO_CONS 32337469Ssklower /* End of protosw marker */ 32437469Ssklower { 0 } 32536408Ssklower }; 32636408Ssklower 32751264Ssklower u_long tp_sendspace = 1024 * 4; 32851264Ssklower u_long tp_recvspace = 1024 * 4; 32951264Ssklower 33036408Ssklower /* 33136408Ssklower * NAME: tp_init() 33236408Ssklower * 33336408Ssklower * CALLED FROM: 33436408Ssklower * autoconf through the protosw structure 33536408Ssklower * 33636408Ssklower * FUNCTION: 33736408Ssklower * initialize tp machine 33836408Ssklower * 33936408Ssklower * RETURNS: Nada 34036408Ssklower * 34136408Ssklower * SIDE EFFECTS: 34236408Ssklower * 34336408Ssklower * NOTES: 34436408Ssklower */ 34537469Ssklower int 34636408Ssklower tp_init() 34736408Ssklower { 34836408Ssklower static int init_done=0; 34936408Ssklower void tp_timerinit(); 35036408Ssklower 35136408Ssklower if (init_done++) 35237469Ssklower return 0; 35336408Ssklower 35436408Ssklower 35536408Ssklower /* FOR INET */ 35636408Ssklower tp_inpcb.inp_next = tp_inpcb.inp_prev = &tp_inpcb; 35736408Ssklower /* FOR ISO */ 35836408Ssklower tp_isopcb.isop_next = tp_isopcb.isop_prev = &tp_isopcb; 35936408Ssklower 36039923Ssklower tp_start_win = 2; 36139923Ssklower 36236408Ssklower tp_timerinit(); 36336408Ssklower bzero((caddr_t)&tp_stat, sizeof(struct tp_stat)); 36437469Ssklower return 0; 36536408Ssklower } 36636408Ssklower 36736408Ssklower /* 36836408Ssklower * NAME: tp_soisdisconnecting() 36936408Ssklower * 37036408Ssklower * CALLED FROM: 37136408Ssklower * tp.trans 37236408Ssklower * 37336408Ssklower * FUNCTION and ARGUMENTS: 37436408Ssklower * Set state of the socket (so) to reflect that fact that we're disconnectING 37536408Ssklower * 37636408Ssklower * RETURNS: Nada 37736408Ssklower * 37836408Ssklower * SIDE EFFECTS: 37936408Ssklower * 38036408Ssklower * NOTES: 38136408Ssklower * This differs from the regular soisdisconnecting() in that the latter 38236408Ssklower * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags. 38336408Ssklower * We don't want to set those flags because those flags will cause 38436408Ssklower * a SIGPIPE to be delivered in sosend() and we don't like that. 38536408Ssklower * If anyone else is sleeping on this socket, wake 'em up. 38636408Ssklower */ 38736408Ssklower void 38836408Ssklower tp_soisdisconnecting(so) 38936408Ssklower register struct socket *so; 39036408Ssklower { 39138841Ssklower soisdisconnecting(so); 39238841Ssklower so->so_state &= ~SS_CANTSENDMORE; 39336408Ssklower IFPERF(sototpcb(so)) 39436408Ssklower register struct tp_pcb *tpcb = sototpcb(so); 39536408Ssklower u_int fsufx, lsufx; 39636408Ssklower 39737469Ssklower bcopy ((caddr_t)tpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) ); 39837469Ssklower bcopy ((caddr_t)tpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) ); 39936408Ssklower 40037469Ssklower tpmeas(tpcb->tp_lref, TPtime_close, &time, fsufx, lsufx, tpcb->tp_fref); 40136408Ssklower tpcb->tp_perf_on = 0; /* turn perf off */ 40236408Ssklower ENDPERF 40336408Ssklower } 40436408Ssklower 40536408Ssklower 40636408Ssklower /* 40736408Ssklower * NAME: tp_soisdisconnected() 40836408Ssklower * 40936408Ssklower * CALLED FROM: 41036408Ssklower * tp.trans 41136408Ssklower * 41236408Ssklower * FUNCTION and ARGUMENTS: 41336408Ssklower * Set state of the socket (so) to reflect that fact that we're disconnectED 41436408Ssklower * Set the state of the reference structure to closed, and 41536408Ssklower * recycle the suffix. 41636408Ssklower * Start a reference timer. 41736408Ssklower * 41836408Ssklower * RETURNS: Nada 41936408Ssklower * 42036408Ssklower * SIDE EFFECTS: 42136408Ssklower * 42236408Ssklower * NOTES: 42336408Ssklower * This differs from the regular soisdisconnected() in that the latter 42436408Ssklower * also sets the SS_CANTRECVMORE and SS_CANTSENDMORE flags. 42536408Ssklower * We don't want to set those flags because those flags will cause 42636408Ssklower * a SIGPIPE to be delivered in sosend() and we don't like that. 42736408Ssklower * If anyone else is sleeping on this socket, wake 'em up. 42836408Ssklower */ 42936408Ssklower void 43036408Ssklower tp_soisdisconnected(tpcb) 43136408Ssklower register struct tp_pcb *tpcb; 43236408Ssklower { 43336408Ssklower register struct socket *so = tpcb->tp_sock; 43436408Ssklower 43538841Ssklower soisdisconnecting(so); 43638841Ssklower so->so_state &= ~SS_CANTSENDMORE; 43751007Ssklower IFPERF(tpcb) 43837469Ssklower register struct tp_pcb *ttpcb = sototpcb(so); 43936408Ssklower u_int fsufx, lsufx; 44036408Ssklower 44136408Ssklower /* CHOKE */ 44237469Ssklower bcopy ((caddr_t)ttpcb->tp_fsuffix, (caddr_t)&fsufx, sizeof(u_int) ); 44337469Ssklower bcopy ((caddr_t)ttpcb->tp_lsuffix, (caddr_t)&lsufx, sizeof(u_int) ); 44436408Ssklower 44537469Ssklower tpmeas(ttpcb->tp_lref, TPtime_close, 44637469Ssklower &time, &lsufx, &fsufx, ttpcb->tp_fref); 44736408Ssklower tpcb->tp_perf_on = 0; /* turn perf off */ 44836408Ssklower ENDPERF 44936408Ssklower 45051007Ssklower tpcb->tp_refstate = REF_FROZEN; 45151007Ssklower tp_recycle_tsuffix(tpcb); 45251204Ssklower tp_etimeout(tpcb, TM_reference, (int)tpcb->tp_refer_ticks); 45336408Ssklower } 45436408Ssklower 45536408Ssklower /* 45636408Ssklower * NAME: tp_freeref() 45736408Ssklower * 45836408Ssklower * CALLED FROM: 45936408Ssklower * tp.trans when the reference timer goes off, and 46036408Ssklower * from tp_attach() and tp_detach() when a tpcb is partially set up but not 46136408Ssklower * set up enough to have a ref timer set for it, and it's discarded 46236408Ssklower * due to some sort of error or an early close() 46336408Ssklower * 46436408Ssklower * FUNCTION and ARGUMENTS: 46536408Ssklower * Frees the reference represented by (r) for re-use. 46636408Ssklower * 46736408Ssklower * RETURNS: Nothing 46836408Ssklower * 46936408Ssklower * SIDE EFFECTS: 47036408Ssklower * 47136408Ssklower * NOTES: better be called at clock priority !!!!! 47236408Ssklower */ 47336408Ssklower void 47451213Ssklower tp_freeref(n) 47551213Ssklower RefNum n; 47636408Ssklower { 47751213Ssklower register struct tp_ref *r = tp_ref + n; 47851213Ssklower register struct tp_pcb *tpcb; 47951213Ssklower 48051213Ssklower tpcb = r->tpr_pcb; 48136408Ssklower IFDEBUG(D_TIMER) 48251213Ssklower printf("tp_freeref called for ref %d pcb %x maxrefopen %d\n", 48351213Ssklower n, tpcb, tp_refinfo.tpr_maxopen); 48436408Ssklower ENDDEBUG 48536408Ssklower IFTRACE(D_TIMER) 48651213Ssklower tptrace(TPPTmisc, "tp_freeref ref maxrefopen pcb", 48751213Ssklower n, tp_refinfo.tpr_maxopen, tpcb, 0); 48836408Ssklower ENDTRACE 48951213Ssklower if (tpcb == 0) 49051213Ssklower return; 49136408Ssklower IFDEBUG(D_CONN) 49251213Ssklower printf("tp_freeref: CLEARING tpr_pcb 0x%x\n", tpcb); 49336408Ssklower ENDDEBUG 49436408Ssklower r->tpr_pcb = (struct tp_pcb *)0; 49551213Ssklower tpcb->tp_refstate = REF_FREE; 49636408Ssklower 49751007Ssklower for (r = tp_ref + tp_refinfo.tpr_maxopen; r > tp_ref; r--) 49851007Ssklower if (r->tpr_pcb) 49951007Ssklower break; 50051007Ssklower tp_refinfo.tpr_maxopen = r - tp_ref; 50151007Ssklower tp_refinfo.tpr_numopen--; 50236408Ssklower 50336408Ssklower IFDEBUG(D_TIMER) 50451007Ssklower printf("tp_freeref ends w/ maxrefopen %d\n", tp_refinfo.tpr_maxopen); 50536408Ssklower ENDDEBUG 50636408Ssklower } 50736408Ssklower 50836408Ssklower /* 50936408Ssklower * NAME: tp_getref() 51036408Ssklower * 51136408Ssklower * CALLED FROM: 51236408Ssklower * tp_attach() 51336408Ssklower * 51436408Ssklower * FUNCTION and ARGUMENTS: 51536408Ssklower * obtains the next free reference and allocates the appropriate 51636408Ssklower * ref structure, links that structure to (tpcb) 51736408Ssklower * 51836408Ssklower * RETURN VALUE: 51936408Ssklower * a reference number 52036408Ssklower * or TP_ENOREF 52136408Ssklower * 52236408Ssklower * SIDE EFFECTS: 52336408Ssklower * 52436408Ssklower * NOTES: 52536408Ssklower */ 52651204Ssklower u_long 52736408Ssklower tp_getref(tpcb) 52836408Ssklower register struct tp_pcb *tpcb; 52936408Ssklower { 53051007Ssklower register struct tp_ref *r, *rlim; 53151007Ssklower register int i; 53251007Ssklower caddr_t obase; 53351007Ssklower unsigned size; 53436408Ssklower 53551007Ssklower if (++tp_refinfo.tpr_numopen < tp_refinfo.tpr_size) 53651007Ssklower for (r = tp_refinfo.tpr_base, rlim = r + tp_refinfo.tpr_size; 53751007Ssklower ++r < rlim; ) /* tp_ref[0] is never used */ 53851007Ssklower if (r->tpr_pcb == 0) 53951007Ssklower goto got_one; 54051007Ssklower /* else have to allocate more space */ 54136408Ssklower 54251007Ssklower obase = (caddr_t)tp_refinfo.tpr_base; 54351007Ssklower size = tp_refinfo.tpr_size * sizeof(struct tp_ref); 54451007Ssklower r = (struct tp_ref *) malloc(size + size, M_PCB, M_NOWAIT); 54551007Ssklower if (r == 0) 54651007Ssklower return (--tp_refinfo.tpr_numopen, TP_ENOREF); 54751007Ssklower tp_refinfo.tpr_base = tp_ref = r; 54851007Ssklower tp_refinfo.tpr_size *= 2; 54951007Ssklower bcopy(obase, (caddr_t)r, size); 55051007Ssklower free(obase, M_PCB); 55151007Ssklower r = (struct tp_ref *)(size + (caddr_t)r); 55251007Ssklower bzero((caddr_t)r, size); 55351007Ssklower 55451007Ssklower got_one: 55551007Ssklower r->tpr_pcb = tpcb; 55651213Ssklower tpcb->tp_refstate = REF_OPENING; 55751007Ssklower i = r - tp_refinfo.tpr_base; 55851007Ssklower if (tp_refinfo.tpr_maxopen < i) 55951007Ssklower tp_refinfo.tpr_maxopen = i; 56051213Ssklower return (u_long)i; 56136408Ssklower } 56236408Ssklower 56336408Ssklower /* 56450648Ssklower * NAME: tp_set_npcb() 56550648Ssklower * 56650648Ssklower * CALLED FROM: 56750648Ssklower * tp_attach(), tp_route_to() 56850648Ssklower * 56950648Ssklower * FUNCTION and ARGUMENTS: 57050648Ssklower * given a tpcb, allocate an appropriate lower-lever npcb, freeing 57150648Ssklower * any old ones that might need re-assigning. 57250648Ssklower */ 57350648Ssklower tp_set_npcb(tpcb) 57450648Ssklower register struct tp_pcb *tpcb; 57550648Ssklower { 57650648Ssklower register struct socket *so = tpcb->tp_sock; 57750648Ssklower int error; 57850648Ssklower 57950648Ssklower if (tpcb->tp_nlproto && tpcb->tp_npcb) { 58050648Ssklower short so_state = so->so_state; 58150648Ssklower so->so_state &= ~SS_NOFDREF; 58250648Ssklower tpcb->tp_nlproto->nlp_pcbdetach(tpcb->tp_npcb); 58350648Ssklower so->so_state = so_state; 58450648Ssklower } 58550648Ssklower tpcb->tp_nlproto = &nl_protosw[tpcb->tp_netservice]; 58650648Ssklower /* xx_pcballoc sets so_pcb */ 58750648Ssklower error = tpcb->tp_nlproto->nlp_pcballoc(so, tpcb->tp_nlproto->nlp_pcblist); 58850648Ssklower tpcb->tp_npcb = so->so_pcb; 58950648Ssklower so->so_pcb = (caddr_t)tpcb; 59050648Ssklower return (error); 59150648Ssklower } 59250648Ssklower /* 59336408Ssklower * NAME: tp_attach() 59436408Ssklower * 59536408Ssklower * CALLED FROM: 59636408Ssklower * tp_usrreq, PRU_ATTACH 59736408Ssklower * 59836408Ssklower * FUNCTION and ARGUMENTS: 59936408Ssklower * given a socket (so) and a protocol family (dom), allocate a tpcb 60036408Ssklower * and ref structure, initialize everything in the structures that 60136408Ssklower * needs to be initialized. 60236408Ssklower * 60336408Ssklower * RETURN VALUE: 60436408Ssklower * 0 ok 60536408Ssklower * EINVAL if DEBUG(X) in is on and a disaster has occurred 60636408Ssklower * ENOPROTOOPT if TP hasn't been configured or if the 60736408Ssklower * socket wasn't created with tp as its protocol 60836408Ssklower * EISCONN if this socket is already part of a connection 60936408Ssklower * ETOOMANYREFS if ran out of tp reference numbers. 61036408Ssklower * E* whatever error is returned from soreserve() 61136408Ssklower * for from the network-layer pcb allocation routine 61236408Ssklower * 61336408Ssklower * SIDE EFFECTS: 61436408Ssklower * 61536408Ssklower * NOTES: 61636408Ssklower */ 61750648Ssklower tp_attach(so, protocol) 61850648Ssklower struct socket *so; 61950648Ssklower int protocol; 62036408Ssklower { 62136408Ssklower register struct tp_pcb *tpcb; 62251264Ssklower int error = 0; 62350648Ssklower int dom = so->so_proto->pr_domain->dom_family; 62451204Ssklower u_long lref; 62536408Ssklower extern struct tp_conn_param tp_conn_param[]; 62636408Ssklower 62736408Ssklower IFDEBUG(D_CONN) 62836408Ssklower printf("tp_attach:dom 0x%x so 0x%x ", dom, so); 62936408Ssklower ENDDEBUG 63036408Ssklower IFTRACE(D_CONN) 63136408Ssklower tptrace(TPPTmisc, "tp_attach:dom so", dom, so, 0, 0); 63236408Ssklower ENDTRACE 63336408Ssklower 63436408Ssklower if (so->so_pcb != NULL) { 63536408Ssklower return EISCONN; /* socket already part of a connection*/ 63636408Ssklower } 63736408Ssklower 63851264Ssklower if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) 63951266Ssklower error = soreserve(so, tp_sendspace, tp_recvspace); 64036408Ssklower /* later an ioctl will allow reallocation IF still in closed state */ 64136408Ssklower 64236408Ssklower if (error) 64336408Ssklower goto bad2; 64436408Ssklower 64537469Ssklower MALLOC(tpcb, struct tp_pcb *, sizeof(*tpcb), M_PCB, M_NOWAIT); 64637469Ssklower if (tpcb == NULL) { 64736408Ssklower error = ENOBUFS; 64836408Ssklower goto bad2; 64936408Ssklower } 65036408Ssklower bzero( (caddr_t)tpcb, sizeof (struct tp_pcb) ); 65136408Ssklower 65251204Ssklower if ( ((lref = tp_getref(tpcb)) & TP_ENOREF) != 0 ) { 65336408Ssklower error = ETOOMANYREFS; 65436408Ssklower goto bad3; 65536408Ssklower } 65651204Ssklower tpcb->tp_lref = lref; 65736408Ssklower tpcb->tp_sock = so; 65836408Ssklower tpcb->tp_domain = dom; 659*53687Ssklower tpcb->tp_rhiwat = so->so_rcv.sb_hiwat; 66050648Ssklower /* tpcb->tp_proto = protocol; someday maybe? */ 66150648Ssklower if (protocol && protocol<ISOPROTO_TP4) { 66236408Ssklower tpcb->tp_netservice = ISO_CONS; 66336408Ssklower tpcb->tp_snduna = (SeqNum) -1;/* kludge so the pseudo-ack from the CR/CC 66436408Ssklower * will generate correct fake-ack values 66536408Ssklower */ 66636408Ssklower } else { 66736408Ssklower tpcb->tp_netservice = (dom== AF_INET)?IN_CLNS:ISO_CLNS; 66836408Ssklower /* the default */ 66936408Ssklower } 67036408Ssklower tpcb->_tp_param = tp_conn_param[tpcb->tp_netservice]; 67136408Ssklower 67236408Ssklower tpcb->tp_state = TP_CLOSED; 67336408Ssklower tpcb->tp_vers = TP_VERSION; 67450940Ssklower tpcb->tp_notdetached = 1; 67536408Ssklower 67636408Ssklower /* Spec says default is 128 octets, 67736408Ssklower * that is, if the tpdusize argument never appears, use 128. 67836408Ssklower * As the initiator, we will always "propose" the 2048 67936408Ssklower * size, that is, we will put this argument in the CR 68036408Ssklower * always, but accept what the other side sends on the CC. 68136408Ssklower * If the initiator sends us something larger on a CR, 68236408Ssklower * we'll respond w/ this. 68336408Ssklower * Our maximum is 4096. See tp_chksum.c comments. 68436408Ssklower */ 68551204Ssklower tpcb->tp_cong_win = 68651204Ssklower tpcb->tp_l_tpdusize = 1 << tpcb->tp_tpdusize; 68736408Ssklower 68836408Ssklower tpcb->tp_seqmask = TP_NML_FMT_MASK; 68936408Ssklower tpcb->tp_seqbit = TP_NML_FMT_BIT; 69036408Ssklower tpcb->tp_seqhalf = tpcb->tp_seqbit >> 1; 69136408Ssklower 69236408Ssklower /* attach to a network-layer protoswitch */ 69350648Ssklower if ( error = tp_set_npcb(tpcb)) 69450648Ssklower goto bad4; 69536408Ssklower ASSERT( tpcb->tp_nlproto->nlp_afamily == tpcb->tp_domain); 69636408Ssklower 69750648Ssklower /* nothing to do for iso case */ 69836408Ssklower if( dom == AF_INET ) 69936408Ssklower sotoinpcb(so)->inp_ppcb = (caddr_t) tpcb; 70036408Ssklower 70136408Ssklower return 0; 70236408Ssklower 70336408Ssklower bad4: 70436408Ssklower IFDEBUG(D_CONN) 70536408Ssklower printf("BAD4 in tp_attach, so 0x%x\n", so); 70636408Ssklower ENDDEBUG 70751213Ssklower tp_freeref(tpcb->tp_lref); 70836408Ssklower 70936408Ssklower bad3: 71036408Ssklower IFDEBUG(D_CONN) 71136408Ssklower printf("BAD3 in tp_attach, so 0x%x\n", so); 71236408Ssklower ENDDEBUG 71336408Ssklower 71437469Ssklower free((caddr_t)tpcb, M_PCB); /* never a cluster */ 71536408Ssklower 71636408Ssklower bad2: 71736408Ssklower IFDEBUG(D_CONN) 71836408Ssklower printf("BAD2 in tp_attach, so 0x%x\n", so); 71936408Ssklower ENDDEBUG 72036408Ssklower so->so_pcb = 0; 72136408Ssklower 72237469Ssklower /*bad:*/ 72336408Ssklower IFDEBUG(D_CONN) 72436408Ssklower printf("BAD in tp_attach, so 0x%x\n", so); 72536408Ssklower ENDDEBUG 72636408Ssklower return error; 72736408Ssklower } 72836408Ssklower 72936408Ssklower /* 73036408Ssklower * NAME: tp_detach() 73136408Ssklower * 73236408Ssklower * CALLED FROM: 73336408Ssklower * tp.trans, on behalf of a user close request 73436408Ssklower * and when the reference timer goes off 73536408Ssklower * (if the disconnect was initiated by the protocol entity 73636408Ssklower * rather than by the user) 73736408Ssklower * 73836408Ssklower * FUNCTION and ARGUMENTS: 73936408Ssklower * remove the tpcb structure from the list of active or 74036408Ssklower * partially active connections, recycle all the mbufs 74136408Ssklower * associated with the pcb, ref structure, sockbufs, etc. 74236408Ssklower * Only free the ref structure if you know that a ref timer 74336408Ssklower * wasn't set for this tpcb. 74436408Ssklower * 74536408Ssklower * RETURNS: Nada 74636408Ssklower * 74736408Ssklower * SIDE EFFECTS: 74836408Ssklower * 74936408Ssklower * NOTES: 75036408Ssklower * tp_soisdisconnected() was already when this is called 75136408Ssklower */ 75236408Ssklower void 75336408Ssklower tp_detach(tpcb) 75436408Ssklower register struct tp_pcb *tpcb; 75536408Ssklower { 75650904Ssklower void tp_freeref(), tp_rsyflush(); 75736408Ssklower register struct socket *so = tpcb->tp_sock; 75836408Ssklower 75936408Ssklower IFDEBUG(D_CONN) 76037469Ssklower printf("tp_detach(tpcb 0x%x, so 0x%x)\n", 76137469Ssklower tpcb,so); 76236408Ssklower ENDDEBUG 76336408Ssklower IFTRACE(D_CONN) 76436408Ssklower tptraceTPCB(TPPTmisc, "tp_detach tpcb so lsufx", 76539196Ssklower tpcb, so, *(u_short *)(tpcb->tp_lsuffix), 0); 76636408Ssklower ENDTRACE 76736408Ssklower 76836408Ssklower IFDEBUG(D_CONN) 76947278Ssklower printf("so_snd at 0x%x so_rcv at 0x%x\n", &so->so_snd, &so->so_rcv); 77047278Ssklower dump_mbuf(so->so_snd.sb_mb, "so_snd at detach "); 77147278Ssklower printf("about to call LL detach, nlproto 0x%x, nl_detach 0x%x\n", 77247278Ssklower tpcb->tp_nlproto, tpcb->tp_nlproto->nlp_pcbdetach); 77347278Ssklower ENDDEBUG 77447278Ssklower 77550648Ssklower if (tpcb->tp_Xsnd.sb_mb) { 77650648Ssklower printf("Unsent Xdata on detach; would panic"); 77750648Ssklower sbflush(&tpcb->tp_Xsnd); 77850648Ssklower } 77947278Ssklower if (tpcb->tp_ucddata) 78047278Ssklower m_freem(tpcb->tp_ucddata); 78147278Ssklower 78247278Ssklower IFDEBUG(D_CONN) 78350904Ssklower printf("reassembly info cnt %d rsyq 0x%x\n", 78450904Ssklower tpcb->tp_rsycnt, tpcb->tp_rsyq); 78550904Ssklower ENDDEBUG 78650904Ssklower if (tpcb->tp_rsyq) 78750904Ssklower tp_rsyflush(tpcb); 78850904Ssklower 78950940Ssklower if (tpcb->tp_next) { 79050940Ssklower remque(tpcb); 79150940Ssklower tpcb->tp_next = tpcb->tp_prev = 0; 79250940Ssklower } 79350940Ssklower tpcb->tp_notdetached = 0; 79450940Ssklower 79550904Ssklower IFDEBUG(D_CONN) 79636408Ssklower printf("calling (...nlproto->...)(0x%x, so 0x%x)\n", 79750435Ssklower tpcb->tp_npcb, so); 79836408Ssklower printf("so 0x%x so_head 0x%x, qlen %d q0len %d qlimit %d\n", 79936408Ssklower so, so->so_head, 80036408Ssklower so->so_q0len, so->so_qlen, so->so_qlimit); 80136408Ssklower ENDDEBUG 80236408Ssklower 80350435Ssklower (tpcb->tp_nlproto->nlp_pcbdetach)(tpcb->tp_npcb); 80450648Ssklower /* does an so->so_pcb = 0; sofree(so) */ 80537469Ssklower 80636408Ssklower IFDEBUG(D_CONN) 80736408Ssklower printf("after xxx_pcbdetach\n"); 80836408Ssklower ENDDEBUG 80936408Ssklower 81050940Ssklower if (tpcb->tp_state == TP_LISTENING) { 81150940Ssklower register struct tp_pcb **tt; 81250940Ssklower for (tt = &tp_listeners; *tt; tt = &((*tt)->tp_nextlisten)) 81350940Ssklower if (*tt == tpcb) 81450940Ssklower break; 81550940Ssklower if (*tt) 81650940Ssklower *tt = tpcb->tp_nextlisten; 81750940Ssklower else 81850940Ssklower printf("tp_detach from listen: should panic\n"); 81950940Ssklower } 82051213Ssklower if (tpcb->tp_refstate == REF_OPENING ) { 82136408Ssklower /* no connection existed here so no reference timer will be called */ 82236408Ssklower IFDEBUG(D_CONN) 82351213Ssklower printf("SETTING ref %d to REF_FREE\n", tpcb->tp_lref); 82436408Ssklower ENDDEBUG 82536408Ssklower 82651213Ssklower tp_freeref(tpcb->tp_lref); 82736408Ssklower } 82850648Ssklower #ifdef TP_PERF_MEAS 82936408Ssklower /* 83036408Ssklower * Get rid of the cluster mbuf allocated for performance measurements, if 83136408Ssklower * there is one. Note that tpcb->tp_perf_on says nothing about whether or 83236408Ssklower * not a cluster mbuf was allocated, so you have to check for a pointer 83336408Ssklower * to one (that is, we need the TP_PERF_MEASs around the following section 83436408Ssklower * of code, not the IFPERFs) 83536408Ssklower */ 83647278Ssklower if (tpcb->tp_p_mbuf) { 83737469Ssklower register struct mbuf *m = tpcb->tp_p_mbuf; 83837469Ssklower struct mbuf *n; 83936408Ssklower IFDEBUG(D_PERF_MEAS) 84036408Ssklower printf("freeing tp_p_meas 0x%x ", tpcb->tp_p_meas); 84136408Ssklower ENDDEBUG 84237469Ssklower do { 84337469Ssklower MFREE(m, n); 84437469Ssklower m = n; 84537469Ssklower } while (n); 84637469Ssklower tpcb->tp_p_meas = 0; 84737469Ssklower tpcb->tp_p_mbuf = 0; 84836408Ssklower } 84936408Ssklower #endif TP_PERF_MEAS 85036408Ssklower 85136408Ssklower IFDEBUG(D_CONN) 85237469Ssklower printf( "end of detach, NOT single, tpcb 0x%x\n", tpcb); 85336408Ssklower ENDDEBUG 85437469Ssklower /* free((caddr_t)tpcb, M_PCB); WHere to put this ? */ 85536408Ssklower } 85650501Ssklower 85750501Ssklower struct que { 85850501Ssklower struct tp_pcb *next; 85950501Ssklower struct tp_pcb *prev; 86050501Ssklower } tp_bound_pcbs = 86150501Ssklower {(struct tp_pcb *)&tp_bound_pcbs, (struct tp_pcb *)&tp_bound_pcbs}; 86250501Ssklower 86350501Ssklower u_short tp_unique; 86450501Ssklower 86550501Ssklower tp_tselinuse(tlen, tsel, siso, reuseaddr) 86650501Ssklower caddr_t tsel; 86750501Ssklower register struct sockaddr_iso *siso; 86850501Ssklower { 86950501Ssklower struct tp_pcb *b = tp_bound_pcbs.next, *l = tp_listeners; 87050501Ssklower register struct tp_pcb *t; 87150501Ssklower 87250501Ssklower for (;;) { 87350501Ssklower if (b != (struct tp_pcb *)&tp_bound_pcbs) { 87450501Ssklower t = b; b = t->tp_next; 87550501Ssklower } else if (l) { 87650501Ssklower t = l; l = t->tp_nextlisten; 87750501Ssklower } else 87850501Ssklower break; 87950501Ssklower if (tlen == t->tp_lsuffixlen && bcmp(tsel, t->tp_lsuffix, tlen) == 0) { 88050501Ssklower if (t->tp_flags & TPF_GENERAL_ADDR) { 88150501Ssklower if (siso == 0 || reuseaddr == 0) 88250501Ssklower return 1; 88350501Ssklower } else if (siso) { 88450501Ssklower if (siso->siso_family == t->tp_domain && 88550501Ssklower t->tp_nlproto->nlp_cmpnetaddr(t->tp_npcb, siso, TP_LOCAL)) 88650501Ssklower return 1; 88750501Ssklower } else if (reuseaddr == 0) 88850501Ssklower return 1; 88950501Ssklower } 89050501Ssklower } 89150501Ssklower return 0; 89250501Ssklower 89350501Ssklower } 89450501Ssklower 89550501Ssklower 89650501Ssklower tp_pcbbind(tpcb, nam) 89750501Ssklower register struct tp_pcb *tpcb; 89850501Ssklower register struct mbuf *nam; 89950501Ssklower { 90050501Ssklower register struct sockaddr_iso *siso = 0; 90150501Ssklower int tlen = 0, wrapped = 0; 90250501Ssklower caddr_t tsel; 90350501Ssklower u_short tutil; 90450501Ssklower 90550501Ssklower if (tpcb->tp_state != TP_CLOSED) 90650501Ssklower return (EINVAL); 90750501Ssklower if (nam) { 90850501Ssklower siso = mtod(nam, struct sockaddr_iso *); 90950501Ssklower switch (siso->siso_family) { 91050501Ssklower default: 91150501Ssklower return (EAFNOSUPPORT); 91250501Ssklower #ifdef ISO 91350501Ssklower case AF_ISO: 91450501Ssklower tlen = siso->siso_tlen; 91550501Ssklower tsel = TSEL(siso); 91650501Ssklower if (siso->siso_nlen == 0) 91750501Ssklower siso = 0; 91850501Ssklower break; 91950501Ssklower #endif 92050501Ssklower #ifdef INET 92150501Ssklower case AF_INET: 92250501Ssklower tsel = (caddr_t)&tutil; 92350501Ssklower if (tutil = ((struct sockaddr_in *)siso)->sin_port) { 92450501Ssklower tlen = 2; 92550501Ssklower } 92650501Ssklower if (((struct sockaddr_in *)siso)->sin_addr.s_addr == 0) 92750501Ssklower siso = 0; 92850501Ssklower } 92950501Ssklower #endif 93050501Ssklower } 93150501Ssklower if (tpcb->tp_lsuffixlen == 0) { 93250501Ssklower if (tlen) { 93350648Ssklower if (tp_tselinuse(tlen, tsel, siso, 93450501Ssklower tpcb->tp_sock->so_options & SO_REUSEADDR)) 93550501Ssklower return (EINVAL); 93653185Ssklower } else { 93753185Ssklower for (tsel = (caddr_t)&tutil, tlen = 2;;){ 93853185Ssklower if (tp_unique++ < ISO_PORT_RESERVED || 93953185Ssklower tp_unique > ISO_PORT_USERRESERVED) { 94053185Ssklower if (wrapped++) 94153185Ssklower return ESRCH; 94253185Ssklower tp_unique = ISO_PORT_RESERVED; 94353185Ssklower } 94453185Ssklower tutil = htons(tp_unique); 94553185Ssklower if (tp_tselinuse(tlen, tsel, siso, 0) == 0) 94653185Ssklower break; 94750501Ssklower } 94853185Ssklower if (siso) switch (siso->siso_family) { 94953185Ssklower #ifdef ISO 95053185Ssklower case AF_ISO: 95153185Ssklower bcopy(tsel, TSEL(siso), tlen); 95253185Ssklower siso->siso_tlen = tlen; 95353185Ssklower break; 95453185Ssklower #endif 95553185Ssklower #ifdef INET 95653185Ssklower case AF_INET: 95753185Ssklower ((struct sockaddr_in *)siso)->sin_port = tutil; 95853185Ssklower #endif 95953185Ssklower } 96050501Ssklower } 96150501Ssklower bcopy(tsel, tpcb->tp_lsuffix, (tpcb->tp_lsuffixlen = tlen)); 96250501Ssklower insque(tpcb, &tp_bound_pcbs); 96350501Ssklower } else { 96450501Ssklower if (tlen || siso == 0) 96550501Ssklower return (EINVAL); 96650501Ssklower } 96750501Ssklower if (siso == 0) { 96850501Ssklower tpcb->tp_flags |= TPF_GENERAL_ADDR; 96950501Ssklower return (0); 97050501Ssklower } 97150501Ssklower return tpcb->tp_nlproto->nlp_pcbbind(tpcb->tp_npcb, nam); 97250501Ssklower } 973