/* psaptcp.c - PPM: TCP backing */
static char *rcsid
= "$Header: /f/osi/psap2-lpp/RCS/ps2tcp.c,v 7.5 91/02/22 09:38:02 mrose Interim $";
* $Header: /f/osi/psap2-lpp/RCS/ps2tcp.c,v 7.5 91/02/22 09:38:02 mrose Interim $
* Contributed by The Wollongong Group, Inc.
* Revision 7.5 91/02/22 09:38:02 mrose
* Revision 7.4 90/12/11 10:53:05 mrose
* Revision 7.3 90/10/16 16:24:30 mrose
* Revision 7.2 90/07/09 14:45:01 mrose
* Revision 7.1 90/07/01 21:05:19 mrose
* Revision 7.0 89/11/23 22:15:50 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
static fd_set inprogress
;
static struct sockaddr_in
*peers
= NULL
;
int tcpopen (pb
, calling
, called
, pi
, async
)
register struct psapblk
*pb
;
struct NSAPaddr
*calling
,
struct PSAPindication
*pi
;
struct sockaddr_in lo_socket
,
register struct sockaddr_in
*lsock
= &lo_socket
,
register struct hostent
*hp
;
return psaplose (pi
, PC_PARAMETER
, NULLCP
,
"asynchronous not supported");
bzero ((char *) isock
, sizeof *isock
);
if (called
-> na_port
== 0)
return psaplose (pi
, PC_ADDRESS
, NULLCP
,
"TCP port of called address not specified");
isock
-> sin_port
= called
-> na_port
;
if ((hp
= gethostbystring (called
-> na_domain
)) == NULL
)
return psaplose (pi
, PC_ADDRESS
, NULLCP
, "%s: unknown host",
(void) strncpy (called
-> na_domain
, hp
-> h_name
,
sizeof called
-> na_domain
);
isock
-> sin_family
= hp
-> h_addrtype
;
(void) strcpy (called
-> na_domain
, inet_ntoa (isock
-> sin_addr
));
if (calling
&& calling
-> na_domain
[0]) {
bzero ((char *) lsock
, sizeof *lsock
);
if ((hp
= gethostbystring (calling
-> na_domain
)) == NULL
)
return psaplose (pi
, PC_ADDRESS
, NULLCP
, "%s: unknown host",
if ((lsock
-> sin_family
= hp
-> h_addrtype
) != isock
-> sin_family
)
return psaplose (pi
, PC_ADDRESS
, NULLCP
,
"address family mismatch");
if ((fd
= start_tcp_client (lsock
, 0)) == NOTOK
)
return psaplose (pi
, PC_CONGEST
, "socket", "unable to start");
(void) ioctl (fd
, FIONBIO
, (onoff
= 1, (char *) &onoff
));
if (join_tcp_server (fd
, isock
) == NOTOK
) {
peers
= (struct sockaddr_in
*)
calloc ((unsigned) getdtablesize (),
(void) psaplose (pi
, PC_CONGEST
, NULLCP
,
(void) close_tcp_socket (fd
);
return (pb
-> pb_fd
= NOTOK
);
FD_SET (fd
, &inprogress
);
peers
[fd
] = *isock
;/* struct copy */
(void) psaplose (pi
, PC_REFUSED
, "connection", "unable to establish");
(void) close_tcp_socket (fd
);
return (pb
-> pb_fd
= NOTOK
);
(void) ioctl (fd
, FIONBIO
, (onoff
= 0, (char *) &onoff
));
if (tcpready (pb
, pi
) == NOTOK
) {
(void) close_tcp_socket (fd
);
char *tcpsave (fd
, cp1
, cp2
, td
)
struct TSAPdisconnect
*td
;
static char buffer
[BUFSIZ
];
(void) sprintf (buffer
, "%c%d %s %s", PT_TCP
, fd
, cp1
, cp2
);
int tcprestore (pb
, buffer
, pi
)
register struct psapblk
*pb
;
struct PSAPindication
*pi
;
char domain1
[NSAP_DOMAINLEN
+ 1 + 5 + 1],
domain2
[NSAP_DOMAINLEN
+ 1 + 5 + 1];
register struct NSAPaddr
*na
;
na
= &pb
-> pb_initiating
;
na
-> na_community
= ts_comm_tcp_default
;
if (sscanf (buffer
, "%d %s %s", &fd
, domain1
, domain2
) != 3 || fd
< 0)
return psaplose (pi
, PC_PARAMETER
, NULLCP
,
"bad initialization vector");
if (cp
= index (domain1
, '+')) {
na
-> na_port
= htons ((u_short
) atoi (cp
));
(void) strncpy (na
-> na_domain
, domain1
, sizeof na
-> na_domain
);
na
= pb
-> pb_responding
.pa_addr
.sa_addr
.ta_addrs
;
na
-> na_community
= ts_comm_tcp_default
;
if (cp
= index (domain2
, '+')) {
na
-> na_port
= htons ((u_short
) atoi (cp
));
(void) strncpy (na
-> na_domain
, domain2
, sizeof na
-> na_domain
);
if ((pb
-> pb_stream
= ps_alloc (fdx_open
)) == NULLPS
|| fdx_setup (pb
-> pb_stream
, pb
-> pb_fd
) == NOTOK
)
return psaplose (pi
, PC_CONGEST
, NULLCP
, NULLCP
);
static int tcpretry (pb
, reason
, pi
)
register struct psapblk
*pb
;
struct PSAPindication
*pi
;
struct sockaddr_in
*isock
= &peers
[fd
];
if (!FD_SET (fd
, &inprogress
))
return psaplose (pi
, PC_PARAMETER
, NULLCP
,
"connection not in progress");
if (xselect (fd
+ 1, NULLFD
, &mask
, NULLFD
, 0) < 1)
if (join_tcp_server (fd
, isock
) == NOTOK
) {
case EINVAL
: /* UNIX bug: could be any socket errno, e.g.,
(void) psaplose (pi
, PC_REFUSED
, "connection", "unable to establish");
FD_CLR (fd
, &inprogress
);
(void) close_tcp_socket (fd
);
return (pb
-> pb_fd
= NOTOK
);
(void) ioctl (fd
, FIONBIO
, (onoff
= 0, (char *) &onoff
));
FD_CLR (fd
, &inprogress
);
if (tcpready (pb
, pi
) == NOTOK
) {
(void) close_tcp_socket (fd
);
return (pb
-> pb_fd
= NOTOK
);
return psaplose (pi
, PC_OPERATION
, NULLCP
, "connection not in progress");
static int tcpready (pb
, pi
)
register struct psapblk
*pb
;
struct PSAPindication
*pi
;
if ((pb
-> pb_stream
= ps_alloc (fdx_open
)) == NULLPS
|| fdx_setup (pb
-> pb_stream
, pb
-> pb_fd
) == NOTOK
)
return psaplose (pi
, PC_CONGEST
, NULLCP
, NULLCP
);
PLOGP (psap2_log
,PS_PDUs
, pb
-> pb_retry
, "ConnectRequest-PDU", 0);
if (pe2ps (ps
= pb
-> pb_stream
, pb
-> pb_retry
) == NOTOK
)
return pslose (pi
, ps
-> ps_errno
);
pe_free (pb
-> pb_retry
);
if ((pb
-> pb_response
= ps2pe (pb
-> pb_stream
)) == NULLPE
)
return pslose (pi
, ps
-> ps_errno
);
#define tcpclose close_tcp_socket
#define tcpselect select_tcp_socket
static int PTservice (pb
, fd
)
register struct psapblk
*pb
;
pb
-> pb_reliability
= HIGH_QUALITY
;
pb
-> pb_retryfnx
= tcpretry
;
pb
-> pb_closefnx
= tcpclose
;
pb
-> pb_selectfnx
= tcpselect
;