/* tsapinitiate.c - TPM: initiator */
static char *rcsid
= "$Header: /f/osi/tsap/RCS/tsapinitiate.c,v 7.4 91/02/22 09:47:27 mrose Interim $";
* $Header: /f/osi/tsap/RCS/tsapinitiate.c,v 7.4 91/02/22 09:47:27 mrose Interim $
* $Log: tsapinitiate.c,v $
* Revision 7.4 91/02/22 09:47:27 mrose
* Revision 7.3 90/08/08 14:03:13 mrose
* Revision 7.2 90/07/09 14:51:26 mrose
* Revision 7.1 90/03/23 17:31:34 mrose
* Revision 7.0 89/11/23 22:30:44 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
NA_BRG
, TS_BRG
, bridgeopen
,
NA_NSAP
, TS_TP4
, tp4open
,
struct TSAPaddr
*newtaddr (), *ta2norm (), *maketsbaddr ();
/* \f T-(ASYN-)CONNECT.REQUEST */
int TAsynConnRequest (calling
, called
, expedited
, data
, cc
, qos
,
struct TSAPaddr
*calling
,
struct TSAPdisconnect
*td
;
if ((n
= called
-> ta_naddr
) <= 0)
return tsaplose (td
, DR_PARAMETER
, NULLCP
,
"no NSAP addresses in called parameter");
return tsaplose (td
, DR_PARAMETER
, NULLCP
,
"too many NSAP addresses in called parameter");
if ((called
= ta2norm (called
)) == NULLTA
)
return tsaplose (td
, DR_PARAMETER
, "invalid called parameter");
toomuchP (data
, cc
, TS_SIZE
, "initial");
result
= TConnRequestAux (calling
, called
, expedited
, data
, cc
, qos
,
(void) sigiomask (smask
);
static int TConnRequestAux (calling
, called
, expedited
, data
, cc
, qos
,
struct TSAPaddr
*calling
,
register struct TSAPconnect
*tc
;
register struct TSAPdisconnect
*td
;
register struct tsapblk
*tb
;
if ((tb
= newtblk ()) == NULL
)
return tsaplose (td
, DR_CONGEST
, NULLCP
, "out of memory");
static struct TSAPaddr tas
;
bzero ((char *) calling
, sizeof *calling
);
if (called
-> ta_selectlen
> 0 && calling
-> ta_selectlen
== 0) {
calling
-> ta_port
= htons ((u_short
) (0x8000 | (getpid () & 0x7fff)));
calling
-> ta_selectlen
= sizeof calling
-> ta_port
;
tb
-> tb_qos
= *qos
; /* struct copy */
if ((tb
-> tb_calling
= (struct TSAPaddr
*)
calloc (1, sizeof *tb
-> tb_calling
)) == NULL
)
*tb
-> tb_calling
= *calling
; /* struct copy */
bcopy (calling
-> ta_selector
, tb
-> tb_initiating
.ta_selector
,
tb
-> tb_initiating
.ta_selectlen
= calling
-> ta_selectlen
);
if ((tb
-> tb_called
= (struct TSAPaddr
*)
calloc (1, sizeof *tb
-> tb_called
)) == NULL
)
*tb
-> tb_called
= *called
; /* struct copy */
if ((tb
-> tb_cc
= cc
) > 0) {
if ((tb
-> tb_data
= malloc ((unsigned) cc
)) == NULLCP
) {
(void) tsaplose (td
, DR_CONGEST
, NULLCP
, "out of memory");
bcopy (data
, tb
-> tb_data
, cc
);
tb
-> tb_expedited
= expedited
;
if ((result
= TConnAttempt (tb
, td
, async
)) == NOTOK
) {
(*tb
-> tb_manfnx
) (OPREQOUTBAD
, tb
);
tc
-> tc_sd
= tb
-> tb_fd
;
if ((result
= (*tb
-> tb_retryPfnx
) (tb
, async
, tc
, td
)) == DONE
&& !async
)
static int TConnAttempt (tb
, td
, async
)
struct TSAPdisconnect
*td
;
register struct TSAPaddr
*called
, *calling
;
struct TSAPaddr
*realcalled
;
register struct NSAPaddr
*na
, *la
;
register struct TSAPdisconnect
*te
= td
;
struct TSAPdisconnect tds
;
calling
= tb
-> tb_calling
;
called
= tb
-> tb_called
;
for (na
= called
-> ta_addrs
, n
= called
-> ta_naddr
- 1;
register struct nsapent
*ns
;
for (ip
= ts_communities
; *ip
; ip
++)
if (*ip
== na
-> na_community
)
for (ip
= tsb_communities
, ap
= tsb_addresses
; *ip
; ip
++, ap
++)
if (*ip
== na
-> na_community
) {
if ((realcalled
= maketsbaddr (*ap
, na
, called
)) == NULLTA
)
realna
= realcalled
-> ta_addrs
;
for (la
= calling
-> ta_addrs
, l
= calling
-> ta_naddr
- 1;
if (la
-> na_community
== na
-> na_community
)
for (ns
= nsaps
; ns
-> ns_open
; ns
++)
if (ns
-> ns_type
== realna
-> na_stack
&& (ns
-> ns_stack
& ts_stacks
))
if ((result
= (*ns
-> ns_open
) (tb
, calling
, la
,
if ((result
= (*ns
-> ns_open
) (tb
, la
, realna
, te
, async
))
if (tb
-> tb_fd
== NOTOK
) {
return tsaplose (td
, DR_PARAMETER
, NULLCP
,
"no supported NSAP addresses in, nor known TSBridges for, called parameter");
tb
-> tb_initiating
.ta_present
= 1;
tb
-> tb_initiating
.ta_addr
= *la
; /* struct copy */
if (la
&& la
!= calling
-> ta_addrs
) {
ns
= calling
-> ta_addrs
[0]; /* struct copy */
calling
-> ta_addrs
[0] = *la
; /* .. */
la
= calling
-> ta_addrs
; /* .. */
bcopy (realcalled
-> ta_selector
, tb
-> tb_responding
.ta_selector
,
tb
-> tb_responding
.ta_selectlen
= realcalled
-> ta_selectlen
);
tb
-> tb_responding
.ta_present
= 1;
tb
-> tb_responding
.ta_addr
= *realna
; /* struct copy */
if ((result
= (*tb
-> tb_connPfnx
) (tb
, tb
-> tb_expedited
, tb
-> tb_data
,
tb
-> tb_cc
, td
)) == NOTOK
)
/* \f T-ASYN-RETRY.REQUEST (pseudo) */
int TAsynRetryRequest (sd
, tc
, td
)
struct TSAPdisconnect
*td
;
register struct tsapblk
*tb
;
if ((tb
= findtblk (sd
)) == NULL
) {
(void) sigiomask (smask
);
return tsaplose (td
, DR_PARAMETER
, NULLCP
,
"invalid transport descriptor");
if (tb
-> tb_flags
& TB_CONN
) {
(void) sigiomask (smask
);
return tsaplose (td
, DR_OPERATION
, NULLCP
,
"transport descriptor connected");
switch (result
= (*tb
-> tb_retryPfnx
) (tb
, 1, tc
, td
)) {
case NOTOK
: /* try next nsap in list */
if (ta
-> ta_naddr
<= 1) {
*tb
-> tb_called
= *newtaddr (ta
, &ta
-> ta_addrs
[1],
ta
-> ta_naddr
- 1); /* struct copy */
switch (result
= TConnAttempt (tb
, td
, 1)) {
(void) dup2 (tb
-> tb_fd
, sd
);
(void) close (tb
-> tb_fd
);
(void) sigiomask (smask
);
/* \f T-ASYN-NEXT.REQUEST (pseudo) */
int TAsynNextRequest (sd
, tc
, td
)
struct TSAPdisconnect
*td
;
register struct tsapblk
*tb
;
if ((tb
= findtblk (sd
)) == NULL
) {
(void) sigiomask (smask
);
return tsaplose (td
, DR_PARAMETER
, NULLCP
,
"invalid transport descriptor");
if (tb
-> tb_flags
& TB_CONN
) {
(void) sigiomask (smask
);
return tsaplose (td
, DR_OPERATION
, NULLCP
,
"transport descriptor connected");
/* close previous connection attempt */
if (tb
-> tb_fd
!= NOTOK
)
(void) (*tb
-> tb_closefnx
) (tb
-> tb_fd
);
if (ta
-> ta_naddr
<= 1) {
(void) sigiomask (smask
);
return tsaplose (td
, DR_PARAMETER
, NULLCP
, "no more NSAPs to try");
*tb
-> tb_called
= *newtaddr (ta
, &ta
-> ta_addrs
[1],
ta
-> ta_naddr
- 1); /* struct copy */
switch (result
= TConnAttempt (tb
, td
, 1)) {
(void) dup2 (tb
-> tb_fd
, sd
);
(void) close (tb
-> tb_fd
);
(void) sigiomask (smask
);
static struct TSAPaddr
*newtaddr (ta
, na
, n
)
register struct TSAPaddr
*ta
;
register struct NSAPaddr
*na
;
static struct TSAPaddr tzs
;
register struct TSAPaddr
*tz
= &tzs
;
register struct NSAPaddr
*nz
= tz
-> ta_addrs
;
bzero ((char *) tz
, sizeof *tz
);
if (tz
-> ta_selectlen
= ta
-> ta_selectlen
)
bcopy (ta
-> ta_selector
, tz
-> ta_selector
, ta
-> ta_selectlen
);
for (tz
-> ta_naddr
= n
; n
> 0; n
--)
*nz
++ = *na
++; /* struct copy */
struct TSAPaddr
*ta2norm (ta
)
register struct TSAPaddr
*ta
;
static struct TSAPaddr tzs
;
register struct TSAPaddr
*tz
= &tzs
;
register struct NSAPaddr
*na
,
SLOG (addr_log
, LLOG_TRACE
, NULLCP
,
("ta2norm %s", taddr2str (ta
)));
for (na
= ta
-> ta_addrs
, n
= ta
-> ta_naddr
- 1; n
>= 0; na
++, n
--)
if (na
-> na_community
== 0) {
SLOG (addr_log
, LLOG_EXCEPTIONS
, NULLCP
,
("ta2norm: empty subnet in NSAP address at offset %d",
bzero ((char *) tz
, sizeof *tz
);
bcopy (ta
-> ta_selector
, tz
-> ta_selector
,
tz
-> ta_selectlen
= ta
-> ta_selectlen
);
for (ip
= ts_communities
; *ip
; ip
++)
for (na
= ta
-> ta_addrs
, n
= ta
-> ta_naddr
- 1;
if (*ip
== na
-> na_community
) {
*ca
++ = *na
; /* struct copy */
for (na
= ta
-> ta_addrs
, n
= ta
-> ta_naddr
- 1; n
>= 0; na
++, n
--) {
for (ip
= ts_communities
; *ip
; ip
++)
if (*ip
== na
-> na_community
)
*ca
++ = *na
; /* struct copy */
SLOG (addr_log
, LLOG_TRACE
, NULLCP
,
("ta2norm returns %s", taddr2str (tz
)));
static struct TSAPaddr
*maketsbaddr (cp
, na
, ta
)
static struct TSAPaddr newta
;
register struct TSAPaddr
*nta
= &newta
;
if ((taz
= str2taddr (cp
)) == NULLTA
)
*nta
= *taz
; /* struct copy */
if ((nna
= na2norm (na
)) == NULLNA
)
if ((nta
-> ta_selectlen
= 2 + nna
-> na_addrlen
+ ta
-> ta_selectlen
)
bcopy (nna
-> na_address
, &nta
-> ta_selector
[2], nna
-> na_addrlen
);
bcopy (ta
-> ta_selector
, &nta
-> ta_selector
[2 + nna
-> na_addrlen
],
nta
-> ta_selector
[0] = nta
-> ta_selector
[1] = nna
-> na_addrlen
;