/* ftaminitiate.c - FPM: initiator */
static char *rcsid
= "$Header: /f/osi/ftam/RCS/ftaminitiate.c,v 7.3 91/02/22 09:23:00 mrose Interim $";
* $Header: /f/osi/ftam/RCS/ftaminitiate.c,v 7.3 91/02/22 09:23:00 mrose Interim $
* $Log: ftaminitiate.c,v $
* Revision 7.3 91/02/22 09:23:00 mrose
* Revision 7.2 91/01/07 12:40:10 mrose
* Revision 7.1 90/11/21 11:30:08 mrose
* Revision 7.0 89/11/23 21:53:41 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
#define FS_CTX "iso ftam"
#define FS_ASN "ftam pci"
/* \f F-INITIALIZE.REQUEST */
int FInitializeRequest (context
, callingtitle
, calledtitle
, callingaddr
,
calledaddr
, manage
, class, units
, attrs
, sharedASE
, fqos
, contents
,
initiator
, account
, password
, passlen
, qos
, tracing
, ftc
, fti
)
struct PSAPaddr
*callingaddr
,
struct FTAMcontentlist
*contents
;
struct FTAMindication
*fti
;
return ftamlose (fti
, FS_ACS_CONTEXT
, 1, NULLCP
, NULLCP
);
return ftamlose (fti
, FS_ACS_FUNIT
, 1, NULLCP
, NULLCP
);
if (!(units
& FUNIT_LIMITED
) && (units
& FUNIT_ENHANCED
))
return ftamlose (fti
, FS_GEN_NOREASON
, 1, NULLCP
,
"enhanced-file-management requires limited-file-management");
if ((class & FCLASS_TRANSFER
&& ((units
& FUNITS_TRANSFER
) != FUNITS_TRANSFER
))) {
return ftamlose (fti
, FS_GEN_NOREASON
, 1, NULLCP
,
"insufficient functional units for service class");
if ((class & FCLASS_TM
) && ((units
& FUNITS_TM
) != FUNITS_TM
))
if ((class & (FCLASS_TRANSFER
| FCLASS_TM
))
&& !(units
& (FUNIT_READ
| FUNIT_WRITE
)))
if ((class & FCLASS_ACCESS
) && ((units
& FUNITS_ACCESS
) != FUNITS_ACCESS
))
if ((class & FCLASS_MANAGE
) && ((units
& FUNITS_MANAGE
) != FUNITS_MANAGE
))
(FCLASS_TRANSFER
| FCLASS_TM
| FCLASS_MANAGE
| FCLASS_ACCESS
)))
return ftamlose (fti
, FS_ACS_CLASS
, 1, NULLCP
, NULLCP
);
if (!(units
& FUNIT_LIMITED
) && (units
& FUNIT_ENHANCED
))
return ftamlose (fti
, FS_GEN_NOREASON
, 1, NULLCP
,
"enhanced-file-management requires limited-file-management");
if (!(units
& FUNIT_GROUPING
)) /* XXX: should be OPTIONAL */
return ftamlose (fti
, FS_ACS_GRPSUP
, 1, NULLCP
, NULLCP
);
if ((attrs
& FATTR_SECURITY
) && !(attrs
& FATTR_STORAGE
))
return ftamlose (fti
, FS_ACS_GRP
, 1, NULLCP
, NULLCP
);
if (contents
&& contents
-> fc_ncontent
> NFCONT
)
return ftamlose (fti
, FS_GEN_NOREASON
, 1, NULLCP
,
"too many content types");
result
= FInitializeRequestAux (context
, callingtitle
, calledtitle
,
callingaddr
, calledaddr
, manage
, class, units
, attrs
, sharedASE
, fqos
,
contents
, initiator
, account
, password
, passlen
, qos
, tracing
, ftc
,
(void) sigiomask (smask
);
static int FInitializeRequestAux (context
, callingtitle
, calledtitle
,
callingaddr
, calledaddr
, manage
, class, units
, attrs
, sharedASE
, fqos
,
contents
, initiator
, account
, password
, passlen
, qos
, tracing
, ftc
,
struct PSAPaddr
*callingaddr
,
struct FTAMcontentlist
*contents
;
struct FTAMindication
*fti
;
register struct PSAPcontext
*px
;
register struct PSAPctxlist
*pl
= &pls
;
struct AcSAPconnect accs
;
register struct AcSAPconnect
*acc
= &accs
;
register struct PSAPconnect
*pc
= &acc
-> acc_connect
;
struct AcSAPindication acis
;
register struct AcSAPindication
*aci
= &acis
;
register struct AcSAPabort
*aca
= &aci
-> aci_abort
;
register struct FTAMcontent
*fx
;
register struct ftamblk
*fsb
;
struct type_FTAM_PDU
*pdu
;
register struct type_FTAM_F__INITIALIZE__request
*req
;
register struct type_FTAM_F__INITIALIZE__response
*rsp
;
if ((fsb
= newfsblk ()) == NULL
)
return ftamlose (fti
, FS_GEN_NOREASON
, 1, NULLCP
, "out of memory");
fsb
-> fsb_flags
|= FSB_INIT
;
fsb
-> fsb_trace
= tracing
;
ctx
= pci
= NULLOID
, pl
-> pc_nctx
= 0;
bzero ((char *) ftc
, sizeof *ftc
);
if (context
== NULLOID
&& (context
= ode2oid (FS_CTX
)) == NULLOID
) {
result
= ftamlose (fti
, FS_ACS_MGMT
, 1, NULLCP
, "%s: unknown", FS_CTX
);
if ((ctx
= oid_cpy (context
)) == NULLOID
) {
result
= ftamlose (fti
, FS_GEN_NOREASON
, 1, NULLCP
, "out of memory");
if ((pci
= ode2oid (FS_ASN
)) == NULLOID
) {
result
= ftamlose (fti
, FS_ACS_MGMT
, 1, NULLCP
, "%s: unknown", FS_ASN
);
if ((pci
= oid_cpy (pci
)) == NULLOID
)
px
= pl
-> pc_ctx
, pl
-> pc_nctx
= 0;
px
-> pc_id
= fsb
-> fsb_id
= idc
= 1;
if ((px
-> pc_asn
= ode2oid (FS_ASN
)) == NULLOID
) {
result
= ftamlose (fti
, FS_ACS_MGMT
, 1, NULLCP
, "%s: unknown", FS_ASN
);
if ((px
-> pc_asn
= oid_cpy (px
-> pc_asn
)) == NULLOID
)
if ((px
-> pc_atn
= ode2oid (BER
)) == NULLOID
) {
result
= ftamlose (fti
, FS_ACS_MGMT
, 1, NULLCP
, "%s: unknown", BER
);
if ((px
-> pc_atn
= oid_cpy (px
-> pc_atn
)) == NULLOID
)
register struct isodocument
*id
;
for (fx
= contents
-> fc_contents
, i
= contents
-> fc_ncontent
- 1;
if (fx
-> fc_dtn
== NULLOID
) {
result
= ftamlose (fti
, FS_GEN (fsb
), 1, NULLCP
,
"empty content type at slot %d",
contents
-> fc_ncontent
- i
- 1);
if ((id
= getisodocumentbytype (fx
-> fc_dtn
)) == NULL
) {
result
= ftamlose (fti
, FS_GEN (fsb
), 1, NULLCP
,
"unknown document type %s at slot %d",
sprintoid (fx
-> fc_dtn
),
contents
-> fc_ncontent
- i
- 1);
px
-> pc_id
= (idc
+= 2);
if ((px
-> pc_asn
= oid_cpy (id
-> id_abstract
)) == NULLOID
)
if ((px
-> pc_atn
= oid_cpy (id
-> id_transfer
)) == NULLOID
)
if ((pdu
= (struct type_FTAM_PDU
*) calloc (1, sizeof *pdu
)) == NULL
)
pdu
-> offset
= type_FTAM_PDU_f__initialize__request
;
if ((req
= (struct type_FTAM_F__INITIALIZE__request
*)
calloc (1, sizeof *req
)) == NULL
)
pdu
-> un
.f__initialize__request
= req
;
req
-> presentation__context__management
= manage
;
if (class != FCLASS_TRANSFER
&& (req
-> service__class
= bits2fpm (fsb
, fclass_pairs
, class,
if ((req
-> functional__units
= bits2fpm (fsb
, funit_pairs
, units
, fti
))
if (attrs
&& (req
-> attribute__groups
= bits2fpm (fsb
, fattr_pairs
,
&& (req
-> shared__ASE__information
=
shared2fpm (fsb
, sharedASE
, fti
)) == NULL
)
if ((req
-> ftam__quality__of__service
=
(struct type_FTAM_FTAM__Quality__Of__Service
*)
calloc (1, sizeof *req
-> ftam__quality__of__service
))
req
-> ftam__quality__of__service
-> parm
= fqos
;
req
-> ftam__quality__of__service
-> parm
= MY_FQOS
;
struct type_FTAM_Contents__Type__List
*fpm
;
register struct type_FTAM_Contents__Type__List
**fpc
;
fpc
= &req
-> contents__type__list
;
for (fx
= contents
-> fc_contents
, i
= contents
-> fc_ncontent
- 1;
if ((fpm
= (struct type_FTAM_Contents__Type__List
*)
calloc (1, sizeof *fpm
)) == NULL
)
if ((fpm
-> Document__Type__Name
= oid_cpy (fx
-> fc_dtn
))
&& (req
-> initiator__identity
= str2qb (initiator
,
&& (req
-> account
= str2qb (account
, strlen (account
), 1))
register struct type_FTAM_Password
*p
;
if ((p
= (struct type_FTAM_Password
*) calloc (1, sizeof *p
))
req
-> filestore__password
= p
;
p
-> offset
= type_FTAM_Password_binary
;
if ((p
-> un
.binary
= str2qb (password
, passlen
, 1)) == NULL
)
req
-> checkpoint__window
= 1;
if (encode_FTAM_PDU (&pe
, 1, 0, NULLCP
, pdu
) == NOTOK
) {
(void) ftamlose (fti
, FS_GEN (fsb
), 1, NULLCP
,
"error encoding PDU: %s", PY_pepy
);
pe
-> pe_context
= fsb
-> fsb_id
;
fsb
-> fsb_srequirements
= SR_DUPLEX
| SR_RESYNC
;
fsb
-> fsb_srequirements
&= ~SR_RESYNC
; /* XXX */
if (units
& (FUNIT_RECOVERY
| FUNIT_RESTART
))
fsb
-> fsb_srequirements
|= SR_MINORSYNC
;
isn
= (fsb
-> fsb_srequirements
& (SR_MINORSYNC
| SR_RESYNC
)) ? 1L
fsb
-> fsb_prequirements
= manage
? (PR_MANAGEMENT
| PR_RESTORATION
) : 0;
#define dotoken(requires,shift,bit,type) \
if (fsb -> fsb_srequirements & requires) \
settings |= ST_INIT_VALUE << shift; \
if ((sr
= addr2ref (PLocalHostName ())) == NULL
)
fsbtrace (fsb
, (fsb
-> fsb_fd
, "A-ASSOCIATE.REQUEST",
"F-INITIALIZE-request", pe
, 0));
result
= AcAssocRequest (ctx
, callingtitle
, calledtitle
, callingaddr
,
calledaddr
, pl
, NULLOID
/* pci */, fsb
-> fsb_prequirements
,
fsb
-> fsb_srequirements
, isn
, settings
, sr
, &pe
, 1,
(void) acs2ftamlose (fsb
, fti
, "AcAssocRequest", aca
);
fsb
-> fsb_fd
= acc
-> acc_sd
;
for (px
= pl
-> pc_ctx
, i
= pl
-> pc_nctx
- 1; i
>= 0; px
++, i
--) {
if (acc
-> acc_ninfo
< 1 || (pe
= acc
-> acc_info
[0]) == NULLPE
) {
if (acc
-> acc_result
!= ACS_ACCEPT
) {
register struct FTAMabort
*fta
= &fti
-> fti_abort
;
aca
-> aca_reason
= acc
-> acc_result
;
(void) acs2ftamlose (fsb
, fti
, "AcAssocRequest(pseudo)", aca
);
ftc
-> ftc_state
= FSTATE_FAILURE
;
ftc
-> ftc_action
= FACTION_PERM
;
*ftc
-> ftc_diags
= *fta
-> fta_diags
; /* struct copy */
ftc
-> ftc_ndiag
= fta
-> fta_ndiag
;
result
= fpktlose (fsb
, fti
, FS_PRO_ERR
, NULLCP
, NULLCP
);
if (decode_FTAM_PDU (pe
, 1, NULLIP
, NULLVP
, &pdu
) == NOTOK
) {
result
= fpktlose (fsb
, fti
, FS_PRO_ERRMSG
, NULLCP
,
"unable to parse PDU: %s", PY_pepy
);
if (pdu
-> offset
!= type_FTAM_PDU_f__initialize__response
) {
result
= fpktlose (fsb
, fti
, FS_PRO_ERRPROC
, NULLCP
,
"expecting F-INITIALIZE-response, got %d",
rsp
= pdu
-> un
.f__initialize__response
;
(fsb
-> fsb_fd
, "A-ASSOCIATE.CONFIRMATION", "F-INITIALIZE-response",
ftc
-> ftc_state
= rsp
-> state__result
? rsp
-> state__result
-> parm
: int_FTAM_State__Result_success
;
ftc
-> ftc_action
= rsp
-> action__result
? rsp
-> action__result
-> parm
: int_FTAM_Action__Result_success
;
switch (acc
-> acc_result
) {
if (ftc
-> ftc_state
!= FSTATE_SUCCESS
|| ftc
-> ftc_action
!= FACTION_SUCCESS
) {
result
= fpktlose (fsb
, fti
, FS_PRO_ERRPROC
, NULLCP
,
"state/action mismatch");
fsb
-> fsb_flags
|= FSB_CONN
;
fsb
-> fsb_srequirements
&= pc
-> pc_srequirements
;
#define dotoken(requires,shift,bit,type) \
if (fsb -> fsb_srequirements & requires) \
switch (pc -> pc_settings & (ST_MASK << shift)) { \
case ST_INIT_VALUE << shift: \
fsb -> fsb_owned |= bit; \
fsb -> fsb_avail |= bit; \
case ST_RESP_VALUE << shift: \
fsb -> fsb_avail |= bit; \
result = fpktlose (fsb, fti, FS_PRO_ERRPROC, NULLCP, \
"%s token management botched", type); \
if (fsb
-> fsb_owned
!= fsb
-> fsb_avail
) {
result
= fpktlose (fsb
, fti
, FS_PRO_ERRPROC
, NULLCP
,
"token management botched");
fsb
-> fsb_ssdusize
= pc
-> pc_ssdusize
;
if (pl
-> pc_nctx
> 0 && pl
-> pc_ctx
[0].pc_result
!= PC_ACCEPT
) {
result
= fpktlose (fsb
, fti
, FS_PRO_ERRPROC
, NULLCP
,
fsb
-> fsb_prequirements
&= pc
-> pc_prequirements
;
if (rsp
-> presentation__context__management
) {
if (!(fsb
-> fsb_prequirements
& PR_MANAGEMENT
)) {
result
= fpktlose (fsb
, fti
, FS_PRO_ERRPROC
, NULLCP
,
"presentation content management mismatch");
fsb
-> fsb_prequirements
&= ~PR_MANAGEMENT
;
if (rsp
-> service__class
) {
rcvd_bits
= fpm2bits (fsb
, fclass_pairs
, rsp
-> service__class
,
else if (rcvd_bits
> 1) {
result
= fpktlose (fsb
, fti
, FS_PRO_ERRPROC
, NULLCP
,
"illegal negotiation of service classes");
switch (fsb
-> fsb_class
= (bits
& class)) {
result
= fpktlose (fsb
, fti
, FS_PRO_ERRPROC
, NULLCP
,
"service class mismatch, offered 0x%x received 0x%x",
if (fpm2bits (fsb
, funit_pairs
, rsp
-> functional__units
, &bits
,
bits
|= i
; /* conservative... */
if ((fsb
-> fsb_units
= bits
) & ~units
) {
result
= fpktlose (fsb
, fti
, FS_PRO_ERRFUNIT
, NULLCP
,
"functional unit mismatch");
/* check for illegal and mandatory functional units */
switch (fsb
-> fsb_class
) {
if (!(fsb
-> fsb_units
& FUNITS_TRANSFER
))
if (!(fsb
-> fsb_units
& FUNITS_TM
))
if (!(fsb
-> fsb_units
& (FUNIT_READ
| FUNIT_WRITE
))) {
result
= fpktlose (fsb
, fti
, FS_PRO_ERRFUNIT
, NULLCP
,
"insufficient functional units for service class");
if (fsb
-> fsb_units
& (FUNIT_ACCESS
| FUNIT_FADULOCK
)) {
result
= fpktlose (fsb
, fti
, FS_PRO_ERRFUNIT
, NULLCP
,
"illegal functional units for service class");
if (!(fsb
-> fsb_units
& FUNITS_ACCESS
))
if (!(fsb
-> fsb_units
& FUNITS_MANAGE
))
if (fsb
-> fsb_units
& (FUNIT_READ
| FUNIT_WRITE
| FUNIT_ACCESS
| FUNIT_FADULOCK
if (rsp
-> attribute__groups
) {
if (fpm2bits (fsb
, fattr_pairs
, rsp
-> attribute__groups
,
result
= fpktlose (fsb
, fti
, FS_PRO_ERRPROC
, NULLCP
,
"attribute group mismatch");
if (rsp
-> ftam__quality__of__service
-> parm
!= MY_FQOS
) {
result
= fpktlose (fsb
, fti
, FS_ACS_ROLLBACK
, NULLCP
,
"class-%d-recovery not supported",
rsp
-> ftam__quality__of__service
-> parm
);
fsb
-> fsb_fqos
= MY_FQOS
;
ftc
-> ftc_sd
= fsb
-> fsb_fd
;
if (ftc
-> ftc_state
== FSTATE_SUCCESS
&& ftc
-> ftc_action
== FACTION_SUCCESS
) {
result
= fpktlose (fsb
, fti
, FS_PRO_ERRPROC
, NULLCP
,
"state/action mismatch");
register struct FTAMabort
*fta
= &fti
-> fti_abort
;
bzero ((char *) fta
, sizeof *fta
);
ftc
-> ftc_respondtitle
= acc
-> acc_respondtitle
; /* struct copy */
bzero ((char *) &acc
-> acc_respondtitle
, sizeof acc
-> acc_respondtitle
);
ftc
-> ftc_respondaddr
= pc
-> pc_responding
; /* struct copy */
ftc
-> ftc_context
= acc
-> acc_context
;
acc
-> acc_context
= NULLOID
;
ftc
-> ftc_manage
= (fsb
-> fsb_prequirements
& PR_MANAGEMENT
) ? 1 : 0;
ftc
-> ftc_class
= fsb
-> fsb_class
;
ftc
-> ftc_units
= fsb
-> fsb_units
;
ftc
-> ftc_attrs
= fsb
-> fsb_attrs
;
if (rsp
-> shared__ASE__information
&& fpm2shared (fsb
, rsp
-> shared__ASE__information
,
&ftc
-> ftc_sharedASE
, fti
) == NOTOK
)
ftc
-> ftc_fqos
= fsb
-> fsb_fqos
;
register struct type_FTAM_Contents__Type__List
*dtn
;
register struct FTAMcontent
*fx2
;
fx2
= ftc
-> ftc_contents
.fc_contents
;
for (fx
= contents
-> fc_contents
,
i
= contents
-> fc_ncontent
- 1;
for (dtn
= rsp
-> contents__type__list
; dtn
; dtn
= dtn
-> next
)
if (oid_cmp (fx
-> fc_dtn
, dtn
-> Document__Type__Name
) == 0)
px
= pl
-> pc_ctx
+ 1 + (fx
- contents
-> fc_contents
);
fx2
-> fc_dtn
= dtn
-> Document__Type__Name
;
fx2
-> fc_id
= px
-> pc_id
;
fx2
-> fc_result
= px
-> pc_result
;
fx2
++, ftc
-> ftc_contents
.fc_ncontent
++;
for (dtn
= rsp
-> contents__type__list
; dtn
; dtn
= dtn
-> next
) {
for (fx2
= ftc
-> ftc_contents
.fc_contents
,
i
= ftc
-> ftc_contents
.fc_ncontent
- 1;
if (dtn
-> Document__Type__Name
== fx2
-> fc_dtn
) {
dtn
-> Document__Type__Name
= NULLOID
;
(void) fpm2diag (fsb
, rsp
-> diagnostic
, ftc
-> ftc_diags
,
ftc
-> ftc_ssdusize
= fsb
-> fsb_ssdusize
;
ftc
-> ftc_qos
= pc
-> pc_qos
; /* struct copy */
if (acc
-> acc_result
!= ACS_ACCEPT
)
for (px
= pl
-> pc_ctx
, i
= pl
-> pc_nctx
- 1; i
>= 0; px
++, i
--) {