/* tsaplisten.c - "network" listening */
static char *rcsid
= "$Header: /f/osi/tsap/RCS/tsaplisten.c,v 7.20 91/03/09 11:58:23 mrose Exp $";
* $Header: /f/osi/tsap/RCS/tsaplisten.c,v 7.20 91/03/09 11:58:23 mrose Exp $
* RFC1085 (LPP) support contributed by the Wollongong Group, Inc.
* Revision 7.20 91/03/09 11:58:23 mrose
* Revision 7.19 91/02/22 09:47:29 mrose
* Revision 7.18 91/01/24 14:50:52 mrose
* Revision 7.17 91/01/07 12:41:30 mrose
* Revision 7.16 90/12/17 22:18:03 mrose
* Revision 7.15 90/10/16 16:24:20 mrose
* Revision 7.14 90/10/16 11:21:27 mrose
* Revision 7.13 90/07/27 08:48:16 mrose
* Revision 7.12 90/07/09 14:51:28 mrose
* Revision 7.11 90/05/08 08:55:45 mrose
* Revision 7.10 90/03/23 17:31:37 mrose
* Revision 7.9 90/02/19 13:07:29 mrose
* Revision 7.8 89/12/19 22:02:35 mrose
* Revision 7.7 89/12/19 16:21:35 mrose
* Revision 7.6 89/12/13 07:05:50 mrose
* Revision 7.5 89/12/11 09:35:37 mrose
* Revision 7.4 89/12/11 09:20:30 mrose
* Revision 7.3 89/12/07 22:15:45 mrose
* Revision 7.2 89/12/07 01:07:43 mrose
* Revision 7.1 89/11/25 16:31:39 mrose
* Revision 7.0 89/11/23 22:30:46 mrose
* Acquisition, use, and distribution of this module and related
* materials are subject to the restrictions of a license agreement.
* Consult the Preface in the User's Manual for the full terms of
struct sockaddr_in lb_un_isock
;
#if defined(X25) || defined(BRIDGE_X25)
struct NSAPaddr lb_un_xsock
;
struct TSAPaddr lb_un_tsock
;
struct listenblk
*lb_forw
; /* doubly-linked list */
struct listenblk
*lb_back
; /* .. */
int lb_fd
; /* network handle */
#define LISTEN_EXCEPTED (-2) /* magic value */
int lb_type
; /* either listener, or exception handler */
struct TSAPaddr lb_addr
; /* transport address */
#define lb_loc_isock lb_un1.lb_un_isock
#define lb_loc_xsock lb_un1.lb_un_xsock
#define lb_loc_nsock lb_un1.lb_un_nsock
#define lb_loc_tsock lb_un1.lb_un_tsock
#define lb_rem_isock lb_un3.lb_un_isock
#define lb_rem_xsock lb_un3.lb_un_xsock
#define lb_rem_nsock lb_un3.lb_un_nsock
#define lb_rem_tsock lb_un3.lb_un_tsock
IFP accept1
; /* accept 1 function */
IFP accept2
; /* accept 2 function */
IFP lb_un_except
; /* exception function */
#define lb_accept1 lb_un2.lb_un_accept.accept1
#define lb_accept2 lb_un2.lb_un_accept.accept2
#define lb_except lb_un2.lb_un_except
IFP lb_close
; /* close function */
#define NULLLBP ((struct listenblk *) 0)
static int once_only
= 0;
static struct listenblk listenque
;
static struct listenblk
*LHead
= &listenque
;
struct listenblk
*findlblk (), *newlblk (), *findlblkbyfd ();
* Event block abstraction. An event block is generated by interfaces
* that might need to do things occasionally. Currently this is only
* the bridge but other things should be slot inable.
* The idea is you but a listenblk of the exception type on a fd.
* If the fd `goes off' the listenblk is destroyed and an eventblk
* created which will be called every 60 seconds for blocking listens,
* and before each listen otherwise.
struct eventblk
*ev_forw
; /* doubly-linked list */
struct eventblk
*ev_back
; /* .. */
struct TSAPaddr ev_taddr
; /* associated address */
IFP ev_eventfnx
; /* the function to call */
#define NULLEVP ((struct eventblk *) 0)
static struct eventblk eventqueue
;
static struct eventblk
*EHead
= &eventqueue
;
static int ev_onceonly
= 0;
struct eventblk
*neweblk ();
FD_SET (fd, &acl_mask); \
if ((fd) + 1 == acl_nfds) \
FD_CLR (fd, &acl_mask); \
static int acl_count
= 0;
int startlb (), uniqlb ();
int tcplisten (), tcpaccept1 (), tcpaccept2 (), tcpunique ();
int x25listen (), x25accept1 (), x25accept2 (), x25unique ();
int bridgelisten (), bridgeaccept1 (), bridgeaccept2 (), bridgeunique ();
int close_bridge_socket (), bridge_except ();
int tp4listen (), tp4accept1 (), tp4accept2 (), tp4unique ();
tcplisten
, tcpaccept1
, tcpaccept2
, tcpunique
, close_tcp_socket
,
x25listen
, x25accept1
, x25accept2
, x25unique
, close_x25_socket
,
bridgelisten
, bridgeaccept1
, bridgeaccept2
, bridgeunique
, close_bridge_socket
,
tp4listen
, tp4accept1
, tp4accept2
, tp4unique
, close_tp4_socket
,
static int _lpp_fd
= NOTOK
;
u_short _lpp_lastport
; /* MOBY HACK */
register struct TSAPaddr
*ta
;
struct TSAPdisconnect
*td
;
return TNetWork (ta
, td
, startlb
, NULLIFP
);
int TNetListenAux (ta
, magic
, td
)
register struct TSAPaddr
*ta
;
struct TSAPdisconnect
*td
;
return TNetWork (ta
, td
, startlb
, magic
);
register struct TSAPaddr
*ta
;
struct TSAPdisconnect
*td
;
return TNetWork (ta
, td
, uniqlb
, NULLIFP
);
static int TNetWork (ta
, td
, fnx
, magic
)
register struct TSAPaddr
*ta
;
struct TSAPdisconnect
*td
;
register struct NSAPaddr
*na
;
register struct nsapent
*ns
;
struct TSAPdisconnect tds
;
register struct NSAPaddr
*ca
;
if ((n
= ta
-> ta_naddr
) > NTADDR
)
return tsaplose (td
, DR_PARAMETER
, NULLCP
,
"illegal number of network addresses");
for (ns
= nsaps
; ns
-> ns_listen
; ns
++)
if (ns
-> ns_type
== NA_NSAP
&& (ns
-> ns_stack
& ts_stacks
))
return tsaplose (td
, DR_PARAMETER
, NULLCP
,
"unsupported network address (%d)", NA_NSAP
);
fd
= (*fnx
) (ta
, NULLNA
, ns
, magic
, td
);
(void) TManGen (STARTLISTEN
, NULLBP
, ta
);
for (ns
= nsaps
; ns
-> ns_listen
; ns
++)
if (ns
-> ns_stack
& ts_stacks
) {
na
-> na_stack
= ns
-> ns_type
;
if ((n
= ta
-> ta_naddr
= na
- ta
-> ta_addrs
) == 0)
return tsaplose (td
, DR_PARAMETER
, NULLCP
,
"no transport stacks active!?!");
bzero ((char *) &tas
, sizeof tas
);
if (tas
.ta_selectlen
= ta
-> ta_selectlen
)
bcopy (ta
-> ta_selector
, tas
.ta_selector
, ta
-> ta_selectlen
);
* stricter checking in force, the proposed listen address must
* now be in the communities and not in the tsb communities.
* This allows us to give a list of addresses and let this code
* sort out the useful from the useless.
for (na
= ta
-> ta_addrs
; n
-- > 0; na
++) {
for (ns
= nsaps
; ns
-> ns_listen
; ns
++)
if (ns
-> ns_type
== na
-> na_stack
&& (ns
-> ns_stack
& ts_stacks
))
if (!ns
-> ns_listen
) /* not one of our supported stacks */
for (ip
= ts_communities
; *ip
; ip
++)
if (na
-> na_subnet
== *ip
)
if (!*ip
) /* stack ok, community wrong */
for (ip
= tsb_communities
; *ip
; ip
++)
if (na
-> na_subnet
== *ip
)
if (*ip
) /* only reachable via tsbridge - ignore */
if ((fd
= (*fnx
) (ta
, na
, ns
, magic
, td
)) == NOTOK
)
*ca
++ = *na
; /* struct copy */
tas
.ta_naddr
= ca
- tas
.ta_addrs
;
(void) TManGen (STARTLISTEN
, NULLBP
, &tas
);
(void) tsaplose (td
, DR_PARAMETER
, NULLCP
,
"no supported network addresses");
(void) TNetClose (ta
, &tds
);
static int startlb (ta
, na
, ns
, magic
, td
)
register struct TSAPaddr
*ta
;
register struct NSAPaddr
*na
;
register struct nsapent
*ns
;
struct TSAPdisconnect
*td
;
register struct listenblk
*lb
;
bzero ((char *) &tas
, sizeof tas
);
bcopy (ta
-> ta_selector
, tas
.ta_selector
,
tas
.ta_selectlen
= ta
-> ta_selectlen
);
tas
.ta_addrs
[0] = *na
; /* struct copy */
if (lb
= findlblk (ta
, LB_LISTEN
))
return tsaplose (td
, DR_OPERATION
, NULLCP
,
"already listening on %s", taddr2str (ta
));
if ((lb
= newlblk (LB_LISTEN
, ta
)) == NULLLBP
)
return tsaplose (td
, DR_CONGEST
, NULLCP
, NULLCP
);
lb
-> lb_accept1
= ns
-> ns_accept1
;
lb
-> lb_accept2
= ns
-> ns_accept2
;
lb
-> lb_close
= ns
-> ns_close
;
if ((lb
-> lb_fd
= (*ns
-> ns_listen
) (lb
, ta
, td
)) == NOTOK
) {
if (lb
-> lb_fd
== LISTEN_EXCEPTED
)
static int uniqlb (ta
, na
, ns
, magic
, td
)
register struct TSAPaddr
*ta
;
register struct NSAPaddr
*na
;
register struct nsapent
*ns
;
struct TSAPdisconnect
*td
;
register struct listenblk
*lb
;
bzero ((char *) &tas
, sizeof tas
);
bcopy (ta
-> ta_selector
, tas
.ta_selector
,
tas
.ta_selectlen
= ta
-> ta_selectlen
);
tas
.ta_addrs
[0] = *na
; /* struct copy */
if ((fd
= (*ns
-> ns_unique
) (&tas
, td
)) == NOTOK
)
bcopy (tas
.ta_selector
, ta
-> ta_selector
,
ta
-> ta_selectlen
= tas
.ta_selectlen
);
*na
= tas
.ta_addrs
[0]; /* struct copy */
if ((lb
= newlblk (LB_LISTEN
, ta
)) == NULLLBP
)
return tsaplose (td
, DR_CONGEST
, NULLCP
, NULLCP
);
lb
-> lb_accept1
= ns
-> ns_accept1
;
lb
-> lb_accept2
= ns
-> ns_accept2
;
lb
-> lb_close
= ns
-> ns_close
;
int TNetAcceptAux (vecp
, vec
, newfd
, ta
, nfds
, rfds
, wfds
, efds
, secs
, td
)
struct TSAPdisconnect
*td
;
register struct listenblk
*lb
, *lb2
;
(void) signal (SIGCHLD
, chldser
);
(void) signal (SIGCLD
, SIG_IGN
);
bzero ((char *) ta
, sizeof *ta
);
if (acl_count
== 0 && ev_count
== 0 && qw_count
== 0) {
if ((n
= xselect (nfds
, rfds
, wfds
, efds
, secs
)) == NOTOK
) {
if (errno
== EINTR
&& chldhit
)
(void) tsaplose (td
, DR_CONGEST
, "failed", "xselect");
for (fd
= 0; fd
< nfds
; fd
++)
for (fd
= 0; fd
< nfds
; fd
++)
xfds
= *efds
; /* struct copy */
xsecs
= 60; /* infinite timeout, arrange for periodic */
check_events (); /* single attempt */
switch (n
= xselect (nfds
, &ifds
, &ofds
, efds
, xsecs
)) {
if (secs
== NOTOK
&& ev_count
) { /* just a timeout */
if (errno
== EINTR
&& chldhit
)
return tsaplose (td
, DR_CONGEST
, "failed", "xselect");
for (lb
= LHead
-> lb_forw
; lb
!= LHead
; ) {
lb
= (lb2
= lb
) -> lb_forw
;
if ((fd
= lb2
-> lb_fd
) == NOTOK
)
if (lb2
-> lb_type
== LB_QUEUED
) {
if (FD_ISSET (fd
, &ofds
)) {
if (TDoQueues (lb2
, td
) == NOTOK
) {
if (rfds
&& FD_ISSET (fd
, rfds
)) {
/* on error, force caller to look at it */
SLOG (tsap_log
, LLOG_EXCEPTIONS
, NULLCP
,
("unable to propagate failure of queued write"));
if (FD_ISSET (fd
, &ifds
)) {
n
--; /* we are using one up */
switch (lb2
-> lb_type
) {
if ((fd2
= (*lb2
-> lb_accept1
) (lb2
, td
))
if (errno
== EWOULDBLOCK
)
if ((lb2
= findlblkbyfd (fd2
)) == NULL
)
if (lb2
-> lb_type
!= LB_ACCEPTNOW
)
/* take care - lb2 is free'd by accept2 */
IFP closefnx
= lb2
-> lb_close
,
magicfnx
= lb2
-> lb_magic
;
if (accepted
) /* only 1 accept at a time */
break; /* we'll get it next time */
*ta
= lb2
-> lb_addr
; /* struct copy */
if ((*lb2
-> lb_accept2
) (lb2
, vecp
, vec
,
&& (*magicfnx
) (vecp
, vec
, td
)
if (exception (lb2
, td
) == NOTOK
)
return tsaplose (td
, DR_UNKNOWN
, NULLCP
,
for (fd
= 0 ; fd
< nfds
; fd
++)
|| (efds
&& FD_ISSET (fd
, efds
)))
*rfds
= ifds
; /* struct copy */
*wfds
= ofds
; /* struct copy */
for (fd
= 0; fd
< nfds
; fd
++)
for (fd
= 0; fd
< nfds
; fd
++)
static int exception (lb
, td
)
struct TSAPdisconnect
*td
;
register struct listenblk
*lb2
;
register struct eventblk
*eb
;
if ((lb2
= findlblk (&lb
-> lb_addr
, LB_LISTEN
)) != NULLLBP
)
if ((eb
= neweblk (&lb
-> lb_addr
)) == NULLEVP
)
return tsaplose (td
, DR_CONGEST
, NULLCP
, "out of memory");
eb
-> ev_eventfnx
= lb
-> lb_except
;
SLOG (tsap_log
, LLOG_EXCEPTIONS
, NULLCP
,
("exception on %s", taddr2str (&lb
-> lb_addr
)));
register struct eventblk
*eb
,
struct TSAPdisconnect tds
;
for (eb
= EHead
-> ev_forw
; eb
!= EHead
; eb
= ep
) {
(void) (*eb
-> ev_eventfnx
) (eb
, &tds
);
register struct TSAPaddr
*ta
;
struct TSAPdisconnect
*td
;
register struct listenblk
*lb
,
for (lb
= LHead
-> lb_forw
; lb
!= LHead
; lb
= lp
) {
if (ta
-> ta_naddr
> 1) {
register int n
= ta
-> ta_naddr
;
register struct NSAPaddr
*na
= ta
-> ta_addrs
;
tas
= *ta
; /* struct copy */
for (na
= ta
-> ta_addrs
, n
= ta
-> ta_naddr
; n
> 0; na
++, n
--) {
tas
.ta_addrs
[0] = *na
; /* struct copy */
if (lb
= findlblk (&tas
, LB_LISTEN
)) {
return tsaplose (td
, DR_PARAMETER
, NULLCP
,
"no such transport addressess");
if ((lb
= findlblk (ta
, LB_LISTEN
)) == NULLLBP
)
return tsaplose (td
, DR_PARAMETER
, NULLCP
,
"no such transport addressess");
static SFD
chldser (sig
, code
, sc
)
while (wait3 (&status
, WNOHANG
, (struct rusage
*) NULL
) > 0)
int TNetFork (vecp
, vec
, td
)
struct TSAPdisconnect
*td
;
(void) tsaplose (td
, DR_CONGEST
, "connection",
"unable to fork, so rejecting");
register struct TSAPstart
*ts
= &tss
;
register struct tsapblk
*tb
;
if (TInit (vecp
, vec
, ts
, td
) == NOTOK
) {
SLOG (tsap_log
, LLOG_EXCEPTIONS
, NULLCP
,
("TNetFork: TInit returns [%s]",
TErrString (td
-> td_reason
)));
if ((tb
= findtblk (ts
-> ts_sd
)) == NULL
) {
SLOG (tsap_log
, LLOG_EXCEPTIONS
, NULLCP
,
("TNetFork: findtblk fails"));
(void) (*tb
-> tb_closefnx
) (tb
-> tb_fd
);
(void) close_tcp_socket (_lpp_fd
);
(void) TNetClose (NULLTA
, td
);
if ((sd
= open ("/dev/tty", O_RDWR
)) != NOTOK
) {
(void) ioctl (sd
, TIOCNOTTY
, NULLCP
);
(void) signal (SIGINT
, SIG_IGN
);
(void) signal (SIGQUIT
, SIG_IGN
);
(void) signal (SIGCHLD
, SIG_DFL
);
(void) signal (SIGCLD
, SIG_DFL
);
static int tcplisten (lb
, ta
, td
)
register struct listenblk
*lb
;
register struct TSAPaddr
*ta
;
struct TSAPdisconnect
*td
;
register struct sockaddr_in
*isock
= &lb
-> lb_loc_isock
;
register struct hostent
*hp
;
register struct NSAPaddr
*na
;
return tsaplose (td
, DR_ADDRESS
, NULLCP
, "TCP address not specified");
if (na
-> na_domain
[0]) {
if ((hp
= gethostbystring (na
-> na_domain
)) == NULL
)
return tsaplose (td
, DR_ADDRESS
, NULLCP
, "%s: unknown host",
bzero ((char *) isock
, sizeof *isock
);
isock
-> sin_family
= hp
? hp
-> h_addrtype
: AF_INET
;
if (na
-> na_port
== 0) {
register struct servent
*sp
;
if ((sp
= getservbyname ("tsap", "tcp")) == NULL
)
sp
= getservbyname ("iso-tsap", "tcp");
isock
-> sin_port
= sp
? sp
-> s_port
: htons ((u_short
) 102);
isock
-> sin_port
= na
-> na_port
;
if ((fd
= start_udp_server (isock
, 0, 0, 0)) == NOTOK
)
return tsaplose (td
, DR_CONGEST
, "failed", "start_udp_server");
if ((fd
= start_tcp_server (isock
, SOMAXCONN
, 0, 0)) == NOTOK
)
return tsaplose (td
, DR_CONGEST
, "failed", "start_tcp_server");
lb
-> lb_addr
.ta_addrs
-> na_tset
= na
-> na_tset
;
static int tcpaccept1 (lb
, td
)
register struct listenblk
*lb
;
struct TSAPdisconnect
*td
;
tset
= lb
-> lb_addr
.ta_addrs
-> na_tset
;
register struct tsapblk
*tb
= NULL
;
register struct tsapkt
*t
= NULL
;
if ((lb2
= newlblk (LB_ACCEPT
, NULLTA
)) == NULL
) {
(void) tsaplose (td
, DR_CONGEST
, NULLCP
, "out of memory");
if ((fd
= join_udp_client (lb
-> lb_fd
, &lb2
-> lb_rem_isock
))
return tsaplose (td
, DR_NETWORK
, "failed", "join_udp_client");
if ((fd
= join_tcp_client (lb
-> lb_fd
, &lb2
-> lb_rem_isock
))
return tsaplose (td
, DR_NETWORK
, "failed", "join_tcp_client");
_lpp_lastport
= lb
-> lb_loc_isock
.sin_port
;
if ((lb
-> lb_fd
= start_tcp_server (&lb
-> lb_loc_isock
,
SOMAXCONN
, 0, 0)) != NOTOK
) {
lb2
-> lb_addr
= lb
-> lb_addr
;
lb2
-> lb_loc_isock
= lb
-> lb_loc_isock
;
lb2
-> lb_accept2
= lb
-> lb_accept2
;
lb2
-> lb_close
= lb
-> lb_close
;
lb2
-> lb_magic
= lb
-> lb_magic
;
if ((tb
= newtblk ()) == NULL
) {
(void) tsaplose (td
, DR_CONGEST
, NULLCP
, "out of memory");
lb2
-> lb_type
= LB_ACCEPTNOW
;
static int tcpaccept2 (lb
, vecp
, vec
, td
)
register struct listenblk
*lb
;
struct TSAPdisconnect
*td
;
int tset
= lb
-> lb_addr
.ta_addrs
-> na_tset
;
struct sockaddr_in in_socket
;
struct sockaddr_in
*isock
= &in_socket
;
register struct tsapblk
*tb
= lb
-> lb_tb
;
register struct tsapkt
*t
= NULL
;
(void) sprintf (buffer1
, "%s+%d",
inet_ntoa (lb
-> lb_rem_isock
.sin_addr
),
ntohs (lb
-> lb_rem_isock
.sin_port
));
if (getsockname (fd
, (struct sockaddr
*) isock
, &len
) != NOTOK
) {
(void) sprintf (buffer2
, "%s+%d",
inet_ntoa (isock
-> sin_addr
),
ntohs (isock
-> sin_port
));
(void) sprintf (buffer2
, "%s", TLocalHostName ());
if ((t
= fd2tpkt (fd
, tb
-> tb_initfnx
,
tb
-> tb_readfnx
)) == NULL
|| t
-> t_errno
!= OK
) {
(void) tpktlose (tb
, td
, t
? t
-> t_errno
: DR_CONGEST
, NULLCP
,
if (TPDU_CODE (t
) != TPDU_CR
) {
(void) tpktlose (tb
, td
, DR_PROTOCOL
, NULLCP
,
"transport protocol mangled: expecting 0x%x, got 0x%x",
if (lb
-> lb_addr
.ta_selectlen
> 0
&& (lb
-> lb_addr
.ta_selectlen
!= t
-> t_calledlen
|| bcmp (lb
-> lb_addr
.ta_selector
,
lb
-> lb_addr
.ta_selectlen
))) {
(void) tpktlose (tb
, td
, DR_SESSION
, NULLCP
,
"not expecting connection for tsap/%s",
sel2str (t
-> t_called
, t
-> t_calledlen
, 1));
vec
[0] = "tsaplisten"; /* any value will do */
if ((vec
[1] = tcpsave (fd
, buffer1
, buffer2
, td
)) == NULL
)
if ((vec
[2] = tpkt2str (t
)) == NULL
) {
(void) tsaplose (td
, DR_CONGEST
, NULLCP
, NULLCP
);
if ((vec
[1] = udpsave (fd
, buffer1
, buffer2
, td
)) == NULL
)
if ((vec
[1] = tcpsave (fd
, buffer1
, buffer2
, td
)) == NULL
)
static int tcpunique (ta
, td
)
register struct TSAPaddr
*ta
;
struct TSAPdisconnect
*td
;
struct sockaddr_in in_socket
;
register struct sockaddr_in
*isock
= &in_socket
;
register struct hostent
*hp
;
register struct NSAPaddr
*na
= ta
-> ta_addrs
;
cp
= na
-> na_domain
[0] ? na
-> na_domain
: TLocalHostName ();
if ((hp
= gethostbystring (cp
)) == NULL
)
return tsaplose (td
, DR_ADDRESS
, NULLCP
, "%s: unknown host", cp
);
bzero ((char *) isock
, sizeof *isock
);
isock
-> sin_family
= hp
-> h_addrtype
;
if ((fd
= start_udp_server (isock
, 0, 0, 0)) == NOTOK
)
return tsaplose (td
, DR_CONGEST
, "failed", "start_udp_server");
if ((fd
= start_tcp_server (isock
, SOMAXCONN
, 0, 0)) == NOTOK
)
return tsaplose (td
, DR_CONGEST
, "failed", "start_tcp_server");
(void) strcpy (na
-> na_domain
, inet_ntoa (isock
-> sin_addr
));
na
-> na_port
= isock
-> sin_port
;
static int x25listen (lb
, ta
, td
)
struct TSAPdisconnect
*td
;
return tsaplose (td
, DR_ADDRESS
, NULLCP
, "X.121 DTE not specified");
if ((fd
= start_x25_server (ta
-> ta_addrs
, SOMAXCONN
, 0, SO_KEEPALIVE
))
return tsaplose (td
, DR_CONGEST
, "failed", "start_x25_server");
lb
-> lb_loc_xsock
= *ta
-> ta_addrs
;
static int x25accept1 (lb
, td
)
register struct listenblk
*lb
;
struct TSAPdisconnect
*td
;
register struct tsapblk
*tb
;
if ((lb2
= newlblk (LB_ACCEPT
, NULLTA
)) == NULL
) {
tsaplose (td
, DR_CONGEST
, NULLCP
, "out of memory");
lb2
-> lb_accept2
= lb
-> lb_accept2
;
lb2
-> lb_addr
= lb
-> lb_addr
;
lb2
-> lb_close
= lb
-> lb_close
;
lb2
-> lb_loc_xsock
= lb
-> lb_loc_xsock
;
lb2
-> lb_magic
= lb
-> lb_magic
;
if ((fd
= join_x25_client (lb
-> lb_fd
, &lb2
-> lb_rem_xsock
)) == NOTOK
) {
return tsaplose (td
, DR_NETWORK
, "failed", "join_x25_client");
if ((tb
= newtblk ()) == NULL
) {
(void) tsaplose (td
, DR_CONGEST
, NULLCP
, "out of memory");
static int x25accept2 (lb
, vecp
, vec
, td
)
register struct listenblk
*lb
;
struct TSAPdisconnect
*td
;
register struct tsapblk
*tb
= lb
-> lb_tb
;
register struct tsapkt
*t
= NULL
;
if ((t
= fd2tpkt (fd
= tb
-> tb_fd
, tb
-> tb_initfnx
,
tb
-> tb_readfnx
)) == NULL
|| t
-> t_errno
!= OK
) {
(void) tpktlose (tb
, td
, t
? t
-> t_errno
: DR_CONGEST
, NULLCP
,
if (TPDU_CODE (t
) != TPDU_CR
) {
(void) tpktlose (tb
, td
, DR_PROTOCOL
, NULLCP
,
"transport protocol mangled: expecting 0x%x, got 0x%x",
if (lb
-> lb_addr
.ta_selectlen
> 0
&& (lb
-> lb_addr
.ta_selectlen
!= t
-> t_calledlen
|| bcmp (lb
-> lb_addr
.ta_selector
,
lb
-> lb_addr
.ta_selectlen
))) {
(void) tpktlose (tb
, td
, DR_SESSION
, NULLCP
,
"not expecting connection for tsap/%s",
sel2str (t
-> t_called
, t
-> t_calledlen
, 1));
vec
[0] = "tsaplisten"; /* any value will do */
if ((vec
[1] = x25save (fd
, lb
-> lb_rem_xsock
.na_dte
,
lb
-> lb_rem_xsock
.na_dtelen
,
lb
-> lb_loc_xsock
.na_dte
,
lb
-> lb_loc_xsock
.na_dtelen
, td
)) == NULL
)
if ((vec
[2] = tpkt2str (t
)) == NULL
) {
(void) tsaplose (td
, DR_CONGEST
, NULLCP
, NULLCP
);
static int x25unique (ta
, td
)
struct TSAPdisconnect
*td
;
register struct NSAPaddr
*na
= ta
-> ta_addrs
;
bzero ((char *) na
, sizeof *na
);
if ((fd
= start_x25_server (na
, SOMAXCONN
, 0, SO_KEEPALIVE
)) == NOTOK
)
return tsaplose (td
, DR_CONGEST
, "failed", "start_x25_server");
static int bridgelisten (lb
, ta
, td
)
register struct listenblk
*lb
;
register struct TSAPaddr
*ta
;
struct TSAPdisconnect
*td
;
register struct eventblk
*eb
;
if ((fd
= bridgelisten_aux (lb
, ta
, td
)) != NOTOK
)
if ((eb
= neweblk (ta
)) == NULLEVP
)
return tsaplose (td
, DR_CONGEST
, NULLCP
, "out of memory");
eb
-> ev_eventfnx
= bridge_except
;
static int bridge_except (eb
, td
)
register struct eventblk
*eb
;
struct TSAPdisconnect
*td
;
register struct listenblk
*lb
;
register struct TSAPaddr
*ta
= &eb
-> ev_taddr
;
if ((lb
= newlblk (LB_LISTEN
, ta
)) == NULLLBP
)
return tsaplose (td
, DR_CONGEST
, NULLCP
, "out of memory");
if ((lb
-> lb_fd
= bridgelisten_aux (lb
, ta
, td
)) == NOTOK
) {
SLOG (tsap_log
, LLOG_EXCEPTIONS
, NULLCP
,
("reconnection on %s", taddr2str (ta
)));
lb
-> lb_close
= close_bridge_socket
;
lb
-> lb_accept1
= bridgeaccept1
;
lb
-> lb_accept2
= bridgeaccept2
;
static int bridgelisten_aux (lb
, ta
, td
)
register struct listenblk
*lb
;
register struct TSAPaddr
*ta
;
struct TSAPdisconnect
*td
;
register struct listenblk
*lb2
;
return tsaplose (td
, DR_ADDRESS
, NULLCP
, "X.121 DTE not specified");
if ((fd
= start_bridge_server (ta
-> ta_addrs
, SOMAXCONN
, 0, SO_KEEPALIVE
))
return tsaplose (td
, DR_CONGEST
, "failed", "start_bridge_server");
lb
-> lb_loc_xsock
= *ta
-> ta_addrs
;
if ((lb2
= newlblk (LB_EXCEPTION
, ta
)) == NULLLBP
) {
close_bridge_socket (fd
);
lb2
-> lb_fd
= get_bridge_assfd (fd
);
lb2
-> lb_except
= bridge_except
;
lb2
-> lb_close
= close_bridge_socket
;
static int bridgeaccept1 (lb
, td
)
register struct listenblk
*lb
;
struct TSAPdisconnect
*td
;
register struct tsapblk
*tb
;
register struct tsapkt
*t
= NULL
;
if ((lb2
= newlblk (LB_ACCEPT
, NULLTA
)) == NULL
) {
(void) tsaplose (td
, DR_CONGEST
, NULLCP
, "out of memory");
lb2
-> lb_accept2
= lb
-> lb_accept2
;
lb2
-> lb_addr
= lb
-> lb_addr
;
lb2
-> lb_close
= lb
-> lb_close
;
lb2
-> lb_loc_xsock
= lb
-> lb_loc_xsock
;
lb2
-> lb_magic
= lb
-> lb_magic
;
if ((fd
= join_bridge_client (lb
-> lb_fd
, &lb2
-> lb_rem_xsock
))
return tsaplose (td
, DR_NETWORK
, "failed", "join_bridge_client");
if ((tb
= newtblk ()) == NULL
) {
(void) tsaplose (td
, DR_CONGEST
, NULLCP
, "out of memory");
static int bridgeaccept2 (lb
, vecp
, vec
, td
)
register struct listenblk
*lb
;
struct TSAPdisconnect
*td
;
register struct tsapblk
*tb
= lb
-> lb_tb
;
register struct tsapkt
*t
= NULL
;
if ((t
= fd2tpkt (tb
-> tb_fd
, tb
-> tb_initfnx
, tb
-> tb_readfnx
)) == NULL
(void) tpktlose (tb
, td
, t
? t
-> t_errno
: DR_CONGEST
, NULLCP
,
if (TPDU_CODE (t
) != TPDU_CR
) {
(void) tpktlose (tb
, td
, DR_PROTOCOL
, NULLCP
,
"transport protocol mangled: expecting 0x%x, got 0x%x",
if (lb
-> lb_addr
.ta_selectlen
> 0
&& (lb
-> lb_addr
.ta_selectlen
!= t
-> t_calledlen
|| bcmp (lb
-> lb_addr
.ta_selector
,
lb
-> lb_addr
.ta_selectlen
))) {
(void) tpktlose (tb
, td
, DR_SESSION
, NULLCP
,
"not expecting connection for tsap/%s",
sel2str (t
-> t_called
, t
-> t_calledlen
, 1));
vec
[0] = "tsaplisten"; /* any value will do */
if ((vec
[1] = bridgesave (tb
-> tb_fd
, lb
-> lb_rem_xsock
.na_dte
,
lb
-> lb_rem_xsock
.na_dtelen
,
lb
-> lb_loc_xsock
.na_dte
,
lb
-> lb_loc_xsock
.na_dtelen
, td
)) == NULL
)
if ((vec
[2] = tpkt2str (t
)) == NULL
) {
(void) tsaplose (td
, DR_CONGEST
, NULLCP
, NULLCP
);
static int bridgeunique (ta
, td
)
struct TSAPdisconnect
*td
;
return tsaplose (td
, DR_ADDRESS
, NULLCP
,
"unique listens not supported at the X.25 bridge");
static int tp4listen (lb
, ta
, td
)
register struct TSAPaddr
*ta
;
struct TSAPdisconnect
*td
;
return start_tp4_server (ta
, SOMAXCONN
, SO_KEEPALIVE
, 0, td
);
static int tp4accept1 (lb
, td
)
register struct listenblk
*lb
;
struct TSAPdisconnect
*td
;
register struct tsapblk
*tb
;
if ((lb2
= newlblk (LB_ACCEPTNOW
, NULLTA
)) == NULL
) {
(void) tsaplose (td
, DR_CONGEST
, NULLCP
, "out of memory");
lb2
-> lb_accept2
= lb
-> lb_accept2
;
lb2
-> lb_addr
= lb
-> lb_addr
;
lb2
-> lb_close
= lb
-> lb_close
;
lb2
-> lb_loc_tsock
= lb
-> lb_loc_tsock
;
if ((fd
= join_tp4_client (lb
-> lb_fd
, &lb2
-> lb_rem_tsock
, td
))
if ((tb
= newtblk ()) == NULL
) {
(void) tsaplose (td
, DR_CONGEST
, NULLCP
, "out of memory");
copyTSAPaddrY (&tb
-> tb_responding
, &lb2
-> lb_rem_tsock
);
static int tp4accept2 (lb
, vecp
, vec
, td
)
register struct listenblk
*lb
;
struct TSAPdisconnect
*td
;
register struct tsapblk
*tb
= lb
-> lb_tb
;
struct sockaddr_iso
*ifaddr
= &sock
.osi_sockaddr
;
static char buffer
[BUFSIZ
];
if (getsockname (fd
, (struct sockaddr
*) ifaddr
, &len
) != NOTOK
) {
ifaddr
-> siso_len
= len
;
(void) tp42genX (&tb
-> tb_initiating
, &sock
);
SLOG (tsap_log
, LLOG_EXCEPTIONS
, "failed",
("getsockname on incoming connection"));
if (tp4getCmsg (fd
, &cc
, &cmsgtype
, udata
) == NOTOK
) {
(void) tsaplose (td
, DR_CONGEST
, "TPOPT_CONN_DATA", "unable to get");
if (cmsgtype
!= TPOPT_CONN_DATA
)
vec
[0] = "tsaplisten"; /* any value will do */
if ((vec
[1] = tp4save (tb
-> tb_fd
, td
)) == NULL
)
len
+= explode (buffer
+ len
, (u_char
*) udata
, cc
);
static int tp4unique (ta
, td
)
struct TSAPdisconnect
*td
;
register struct NSAPaddr
*na
= ta
-> ta_addrs
;
bzero ((char *) na
, sizeof *na
);
na
-> na_stack
= NA_NSAP
;
return start_tp4_server (na
, SOMAXCONN
, SO_KEEPALIVE
, 0, td
);
/* \f TP4 from SunLink OSI */
static int tp4listen (lb
, ta
, td
)
register struct TSAPaddr
*ta
;
struct TSAPdisconnect
*td
;
return start_tp4_server (ta
, SOMAXCONN
, 0, 0, td
);
static int tp4accept1 (lb
, td
)
register struct listenblk
*lb
;
struct TSAPdisconnect
*td
;
register struct tsapblk
*tb
;
if ((lb2
= newlblk (LB_ACCEPT
, NULLTA
)) == NULL
) {
(void) tsaplose (td
, DR_CONGEST
, NULLCP
, "out of memory");
lb2
-> lb_loc_isock
= lb
-> lb_loc_isock
;
lb2
-> lb_addr
= lb
-> lb_addr
;
lb2
-> lb_accept2
= lb
-> lb_accept2
;
lb2
-> lb_close
= lb
-> lb_close
;
lb2
-> lb_magic
= lb
-> lb_magic
;
if ((fd
= join_tp4_client (lb
-> lb_fd
, &lb
-> lb_rem_tsock
, td
))
if ((tb
= newtblk ()) == NULL
) {
(void) tsaplose (td
, DR_CONGEST
, NULLCP
, "out of memory");
static int tp4accept2 (lb
, vecp
, vec
, td
)
register struct listenblk
*lb
;
struct TSAPdisconnect
*td
;
register struct tsapblk
*tb
= lb
-> lb_tb
;
register struct tp4pkt
*tp
= NULL
;
static char buffer
[BUFSIZ
];
if ((tp
= newtp4pkt ((TP_EVENT
) 0)) == NULL
) {
(void) tsaplose (td
, DR_CONGEST
, NULLCP
, NULLCP
);
header_len
= sizeof (TP_MSG_CONNECT
);
if ((cc
= recvfrom (fd
, data
, sizeof data
, 0, (struct sockaddr
*) tp
,
&header_len
)) == NOTOK
) {
(void) tpktlose (tb
, td
, DR_CONGEST
, "failed", "recvfrom");
if (tp
-> tp4_event
!= TP_CONNECT_IND
) {
(void) tpktlose (tb
, td
, DR_REMOTE
, NULLCP
,
"transport protocol mangled: expecting 0x%x got 0x%x",
TP_CONNECT_IND
, tp
-> tp4_event
);
(void) tp42genX (&tb
-> tb_responding
, &tp
-> tp4_called
);
(void) tp42genX (&tb
-> tb_initiating
, &tp
-> tp4_calling
);
vec
[0] = "tsaplisten"; /* any value will do */
if ((vec
[1] = tp4save (tb
-> tb_fd
, td
)) == NULL
)
len
= explode (buffer
, (u_char
*) tp
, sizeof (TP_MSG_CONNECT
));
len
+= explode (buffer
+ len
, (u_char
*) data
, cc
);
static int tp4unique (ta
, td
)
struct TSAPdisconnect
*td
;
return tsaplose (td
, DR_ADDRESS
, NULLCP
,
"unique listens not yet supported with SunLink OSI");
static struct listenblk
*newlblk (type
, ta
)
register struct listenblk
*lb
;
lb
= (struct listenblk
*) calloc (1, sizeof *lb
);
lb
-> lb_addr
= *ta
; /* struct copy */
LHead
-> lb_forw
= LHead
-> lb_back
= LHead
;
insque (lb
, LHead
-> lb_back
);
register struct listenblk
*lb
;
if (lb
-> lb_type
== LB_LISTEN
)
(void) TManGen (ENDLISTEN
, NULLBP
, &lb
-> lb_addr
);
if (lb
-> lb_type
!= LB_QUEUED
)
if (lb
-> lb_fd
!= NOTOK
) {
(void) (*lb
-> lb_close
) (lb
-> lb_fd
);
static struct listenblk
*findlblk (ta
, type
)
register struct TSAPaddr
*ta
;
register struct listenblk
*lb
;
for (lb
= LHead
-> lb_forw
; lb
!= LHead
; lb
= lb
-> lb_forw
)
if (lb
-> lb_type
== type
&& bcmp ((char *) &lb
-> lb_addr
, (char *) ta
, sizeof *ta
) ==0)
static struct listenblk
*findlblkbyfd (fd
)
register struct listenblk
*lb
;
for (lb
= LHead
-> lb_forw
; lb
!= LHead
; lb
= lb
-> lb_forw
)
if (lb
-> lb_type
!= LB_QUEUED
)
static struct eventblk
*neweblk (ta
)
register struct eventblk
*eb
;
eb
= (struct eventblk
*) calloc (1, sizeof *eb
);
eb
-> ev_taddr
= *ta
; /* struct copy */
EHead
-> ev_forw
= EHead
-> ev_back
= EHead
;
insque (eb
, EHead
-> ev_back
);
register struct eventblk
*eb
;
int tsaplose (td
, reason
, what
, fmt
)
struct TSAPdisconnect
*td
;
return tsaplose (td
, reason
, what
, fmt
);
static int TNetQueue (tb
, insert
, td
)
register struct tsapblk
*tb
;
struct TSAPdisconnect
*td
;
register struct listenblk
*lb
;
LHead
-> lb_forw
= LHead
-> lb_back
= LHead
;
for (lb
= LHead
-> lb_forw
; lb
!= LHead
; lb
= lb
-> lb_forw
)
if (lb
-> lb_type
== LB_QUEUED
&& lb
-> lb_tb
== tb
)
if (lb
!= LHead
) /* should "never happen" */
if ((lb
= newlblk (LB_QUEUED
, NULLTA
)) == NULLLBP
) {
SLOG (tsap_log
, LLOG_EXCEPTIONS
, NULLCP
,
("unable to allocate listenblk for queued writes"));
return tsaplose (td
, DR_CONGEST
, NULLCP
, "out of memory");
lb
-> lb_fd
= (lb
-> lb_tb
= tb
) -> tb_fd
;
if (lb
-> lb_fd
>= qw_nfds
)
qw_nfds
= lb
-> lb_fd
+ 1;
FD_SET (lb
-> lb_fd
, &qw_mask
);
static int TDoQueues (lb
, td
)
register struct listenblk
*lb
;
struct TSAPdisconnect
*td
;
register struct tsapblk
*tb
= lb
-> lb_tb
;
switch ((*tb
-> tb_drainPfnx
) (tb
, td
)) {
static int TFreeQueues (lb
)
register struct listenblk
*lb
;
if (lb
-> lb_fd
+ 1 == qw_nfds
)
FD_CLR (lb
-> lb_fd
, &qw_mask
);
int TSetQueuesOK (sd
, onoff
, td
)
struct TSAPdisconnect
*td
;
register struct tsapblk
*tb
;
if (tb
-> tb_drainPfnx
== NULLIFP
)
result
= tsaplose (td
, DR_OPERATION
, NULLCP
,
"queued writes not supported by TS-stack");
tb
-> tb_flags
|= TB_QWRITES
;
tb
-> tb_queuePfnx
= TNetQueue
;
if (tb
-> tb_qwrites
.qb_forw
!= &tb
-> tb_qwrites
)
result
= tsaplose (td
, DR_WAITING
, NULLCP
,
"queued writes still waiting to drain");
tb
-> tb_flags
&= ~TB_QWRITES
;
tb
-> tb_queuePfnx
= NULLIFP
;
(void) sigiomask (smask
);