/* tsdu2spkt.c - read/write a SPDU to a TSDU */
static char *rcsid
= "$Header: /f/osi/ssap/RCS/tsdu2spkt.c,v 7.1 91/02/22 09:46:14 mrose Interim $";
* $Header: /f/osi/ssap/RCS/tsdu2spkt.c,v 7.1 91/02/22 09:46:14 mrose Interim $
* Revision 7.1 91/02/22 09:46:14 mrose
* Revision 7.0 89/11/23 22:25:55 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
char *top
; /* Top of buffer */
char *ptr
; /* Pointer to working buffer */
int pgi
; /* Offset of last PGI li */
int left
; /* Number of bytes left */
int li
; /* Running spdu length */
int allocli
; /* Allocated li */
int len
; /* Current buffer size */
#define PMASK_NODATA 0x000000
#define PMASK_CN_ID 0x000001 /* 1: Connection ID */
#define PMASK_CN_ITEMS 0x000002 /* 5: Connect/Accept Item */
#define PMASK_SYNC 0x000004 /* 15: Sync Type Item */
#define PMASK_TOKEN 0x000008 /* 16: Token Item */
#define PMASK_TDISC 0x000010 /* 17: Transport Disc */
#define PMASK_USER_REQ 0x000020 /* 20: Session User Req */
#define PMASK_VERSION 0x000040 /* 22: Version Number */
#define PMASK_PREPARE 0x000080 /* 24: Prepare type */
#define PMASK_ENCLOSE 0x000100 /* 25: Enclosure Item */
#define PMASK_TOKEN_SET 0x000200 /* 26: Token Setting Item */
#define PMASK_RESYNC 0x000400 /* 27: Resync type */
#define PMASK_LINK 0x000800 /* 33: Linking information */
#define PMASK_ACT_ID 0x001000 /* 41: Activity ID */
#define PMASK_SERIAL 0x002000 /* 42: Serial Number */
#define PMASK_MIA_DATA 0x004000 /* 46: MIA User Data */
#define PMASK_REFLECT 0x008000 /* 49: Reflect parameter */
#define PMASK_REASON 0x010000 /* 50: Refusal Reason */
#define PMASK_SSAP_CALLING 0x020000 /* 51: Calling SSAP ID */
#define PMASK_SSAP_CALLED 0x040000 /* 52: Called SSAP ID */
#define PMASK_UDATA 0x080000 /* 193: User data */
#define PMASK_XDATA 0x100000 /* 194: Extended user data */
#define PMASK_VARLEN 0x800000 /* PI is Variable Len */
#define PMASK_NOTSUPPORTED -1 /* Type not supported */
static int si_table
[] = {
PMASK_REFLECT
, /* 0x00: SPDU_ER */
PMASK_ENCLOSE
/* 0x01: SPDU_GT & SPDU_DT */
PMASK_TOKEN
/* 0x02: SPDU_PT */
PMASK_NOTSUPPORTED
, /* 0x03 */
PMASK_NOTSUPPORTED
, /* 0x04 */
PMASK_NODATA
, /* 0x05: SPDU_EX */
PMASK_NOTSUPPORTED
, /* 0x06 */
PMASK_PREPARE
, /* 0x07: SPDU_PR */
PMASK_ENCLOSE
/* 0x08: SPDU_NF */
PMASK_TDISC
/* 0x09: SPDU_FN */
PMASK_ENCLOSE
/* 0x0a: SPDU_DN */
PMASK_NOTSUPPORTED
, /* 0x0b */
PMASK_CN_ID
/* 0x0c: SPDU_RF */
PMASK_CN_ID
/* 0x0d: SPDU_CN */
PMASK_CN_ID
/* 0x0e: SPDU_AC */
PMASK_NOTSUPPORTED
, /* 0x0f */
PMASK_NOTSUPPORTED
, /* 0x10 */
PMASK_NOTSUPPORTED
, /* 0x11 */
PMASK_NOTSUPPORTED
, /* 0x12 */
PMASK_NOTSUPPORTED
, /* 0x13 */
PMASK_NOTSUPPORTED
, /* 0x14 */
PMASK_NODATA
, /* 0x15: SPDU_GTC */
PMASK_NODATA
, /* 0x16: SPDU_GTA */
PMASK_NOTSUPPORTED
, /* 0x17 */
PMASK_NOTSUPPORTED
, /* 0x18 */
PMASK_TDISC
/* 0x19: SPDU_AB & SPDU_AI */
PMASK_NODATA
, /* 0x1a: SPDU_AA & SPDU_AIA */
PMASK_NOTSUPPORTED
, /* 0x1b */
PMASK_NOTSUPPORTED
, /* 0x1c */
PMASK_LINK
/* 0x1d: SPDU_AR */
PMASK_NOTSUPPORTED
, /* 0x1e */
PMASK_NOTSUPPORTED
, /* 0x1f */
PMASK_NOTSUPPORTED
, /* 0x20 */
PMASK_ENCLOSE
, /* 0x21: SPDU_TD */
PMASK_TOKEN_SET
/* 0x22: SPDU_RA */
PMASK_NOTSUPPORTED
, /* 0x23 */
PMASK_NOTSUPPORTED
, /* 0x24 */
PMASK_NOTSUPPORTED
, /* 0x25 */
PMASK_NOTSUPPORTED
, /* 0x26 */
PMASK_NOTSUPPORTED
, /* 0x27 */
PMASK_NOTSUPPORTED
, /* 0x28 */
PMASK_SYNC
/* 0x29: SPDU_MAP & SPDU_AE */
PMASK_ENCLOSE
/* 0x2a: SPDU_MAA & SPDU_AEA */
PMASK_NOTSUPPORTED
, /* 0x2b */
PMASK_NOTSUPPORTED
, /* 0x2c */
PMASK_ENCLOSE
/* 0x2d: SPDU_AS */
PMASK_NOTSUPPORTED
, /* 0x2e */
PMASK_NOTSUPPORTED
, /* 0x2f */
PMASK_ENCLOSE
/* 0x30: SPDU_ED */
PMASK_SYNC
/* 0x31: SPDU_MIP */
PMASK_ENCLOSE
/* 0x32: SPDU_MIA */
PMASK_NOTSUPPORTED
, /* 0x33 */
PMASK_NOTSUPPORTED
, /* 0x34 */
PMASK_TOKEN_SET
/* 0x35: SPDU_RS */
PMASK_NOTSUPPORTED
, /* 0x36 */
PMASK_NOTSUPPORTED
, /* 0x37 */
PMASK_NOTSUPPORTED
, /* 0x38 */
PMASK_REASON
, /* 0x39: SPDU_AD */
PMASK_NODATA
, /* 0x3a: SPDU_ADA */
PMASK_NOTSUPPORTED
, /* 0x3b */
PMASK_NOTSUPPORTED
, /* 0x3c */
PMASK_ENCLOSE
/* 0x3d: SPDU_CD */
PMASK_ENCLOSE
/* 0x3e: SPDU_CDA */
#define SI_TABLE_LEN ((sizeof si_table) / (sizeof si_table[0]))
#define PI_PROTOCOL_OPT 19
#define PI_TSDU_MAXSIZ 21
#define PI_SSAP_CALLING 51
#define PI_SSAP_CALLED 52
static int pi_table
[] = {
PMASK_VARLEN
| PMASK_CN_ID
, /* 0x01: Connection ID */
PMASK_VARLEN
| PMASK_CN_ITEMS
, /* 0x05: Connect/Accept Item */
PMASK_VARLEN
| PMASK_CN_ID
| PMASK_LINK
,/* 0x09: Called Session SS */
PMASK_VARLEN
| PMASK_CN_ID
| PMASK_LINK
,/* 0x0a: Calling Session SS */
PMASK_VARLEN
| PMASK_CN_ID
| PMASK_LINK
,/* 0x0b: Common Reference */
PMASK_VARLEN
| PMASK_CN_ID
| PMASK_LINK
,/* 0x0c: Additional Info */
PMASK_SYNC
, /* 0x0f: Sync Type Item */
PMASK_TOKEN
, /* 0x10: Token Item */
PMASK_TDISC
, /* 0x11: Transport Disc */
PMASK_CN_ITEMS
, /* 0x13: Protocol Option */
PMASK_USER_REQ
, /* 0x14: Session User Req */
PMASK_VARLEN
| PMASK_CN_ITEMS
, /* 0x15: TSDU Max Size */
PMASK_VERSION
, /* 0x16: Version Number */
PMASK_VARLEN
| PMASK_CN_ITEMS
, /* 0x17: Initial Serial Num */
PMASK_PREPARE
, /* 0x18: Prepare Type */
PMASK_ENCLOSE
, /* 0x19: Enclosure Item */
PMASK_CN_ITEMS
| PMASK_TOKEN_SET
, /* 0x1a: Token setting item */
PMASK_RESYNC
, /* 0x1b: Resync type */
0, 0, 0, 0, 0, /* 0x1c-20 */
PMASK_VARLEN
| PMASK_LINK
, /* 0x21: Activity Link */
0, 0, 0, 0, 0, 0, 0, /* 0x22-28 */
PMASK_VARLEN
| PMASK_ACT_ID
, /* 0x29: Activity ID */
PMASK_VARLEN
| PMASK_SERIAL
, /* 0x2a: Serial Number */
PMASK_VARLEN
| PMASK_MIA_DATA
, /* 0x2e: MIA User Data */
PMASK_VARLEN
| PMASK_REFLECT
, /* 0x31: Reflect parameter */
PMASK_VARLEN
| PMASK_REASON
, /* 0x32: Refusal Reason */
PMASK_VARLEN
| PMASK_SSAP_CALLING
, /* 0x33: Calling SSAP ID */
PMASK_VARLEN
| PMASK_SSAP_CALLED
, /* 0x34: Called SSAP ID */
PMASK_VARLEN
| PMASK_CN_ITEMS
/* 0x17: 2nd initial s/n */
#define PI_TABLE_LEN ((sizeof pi_table) / (sizeof pi_table[0]))
static int pi_length
[PI_TABLE_LEN
] = {
SREF_USER_SIZE
/* 0x01: Connection ID */
1 + 4 + 1 + 6 + 1 + 10, /* 0x05: Connect/Accept Item */
SREF_USER_SIZE
, /* 0x09: Called Session SS */
SREF_USER_SIZE
, /* 0x0a: Calling Session SS */
SREF_COMM_SIZE
, /* 0x0b: Common Reference */
SREF_ADDT_SIZE
, /* 0x0c: Additional Info */
1, /* 0x0f: Sync Type Item */
1, /* 0x10: Token Item */
1, /* 0x11: Transport Disc */
1, /* 0x13: Protocol Option */
2, /* 0x14: Session User Req */
4, /* 0x15: TSDU Max Size */
1, /* 0x16: Version Number */
SIZE_CN_ISN
, /* 0x17: Initial Serial Num */
1, /* 0x18: Prepare Type */
1, /* 0x19: Enclosure Item */
1, /* 0x1a: Token setting item */
1, /* 0x1b: Resync type */
0, 0, 0, 0, 0, /* 0x1c-20 */
2 * SREF_USER_SIZE
/* 0x21: Activity Link */
0, 0, 0, 0, 0, 0, 0, /* 0x22-28 */
SID_DATA_SIZE
, /* 0x29: Activity ID */
SIZE_CN_ISN
, /* 0x2a: Serial Number */
SEGMENT_MAX
/* MIA_SIZE */, /* 0x2e: MIA User Data */
SEGMENT_MAX
, /* 0x31: Reflect parameter */
RF_SIZE
, /* 0x32: Refusal Reason */
SSSIZE
, /* 0x33: Calling SSAP ID */
SSSIZE
, /* 0x34: Called SSAP ID */
SIZE_CN_ISN
, /* 0x37: 2nd initial s/n */
#define If_Set(flag) if (s -> s_mask & (flag))
#define If_Reset(flag) if (!(s -> s_mask & (flag)))
#define Set(flag) s -> s_mask |= (flag)
#define Reset(flag) s -> s_mask &= ~(flag)
#define Put_Item(code,value) \
put2spdu((code), pi_length[(code)], (value), &c)
#define Put_Ref(r,code) \
start_pgi (PGI_CN_ID, &c); \
put2spdu (code, (int) r.sr_ulen, r.sr_udata, &c); \
put2spdu (PI_COMMON_REF, (int) r.sr_clen, r.sr_cdata, &c); \
put2spdu (PI_ADD_INFO, (int) r.sr_alen, r.sr_adata, &c); \
#define Put_SSN(code,ssn) \
if ((ssn) > SERIAL_MAX + 1) { \
s -> s_errno = SC_PROTOCOL; \
(void) sprintf (isn, "%lu", (ssn)); \
put2spdu ((code), strlen (isn), isn, &c); \
if (s -> s_ulen > (csize)) {
s -> s_errno = SC_PROTOCOL;
but with version 2 session, there's really no point... */
#define Put_UData(csize) \
put2spdu (PI_UDATA, s -> s_ulen, s -> s_udata, &c); \
#define Put_XData(csize) \
put2spdu (s -> s_ulen > csize ? PI_XDATA : PI_UDATA, s -> s_ulen, \
#define Put_MData(csize) \
put2spdu (PI_MIA_DATA, s -> s_ulen, s -> s_udata, &c); \
static start_spdu (s
, c
, basesize
)
case SPDU_DT
: /* caller responsible for this... */
basesize
+= s
-> s_ulen
+ (s
-> s_ulen
> 254 ? 4 : 2);
if (s
-> s_cn_reference
.sr_ulen
)
basesize
+= 2 + s
-> s_cn_reference
.sr_ulen
;
if (s
-> s_cn_reference
.sr_clen
)
basesize
+= 2 + s
-> s_cn_reference
.sr_clen
;
if (s
-> s_cn_reference
.sr_alen
)
basesize
+= 2 + s
-> s_cn_reference
.sr_alen
;
If_Set (SMASK_CN_CALLING
)
basesize
+= s
-> s_callinglen
+ 2;
basesize
+= s
-> s_calledlen
+ 2;
if (s
-> s_rf_reference
.sr_ulen
)
basesize
+= 2 + s
-> s_rf_reference
.sr_ulen
;
if (s
-> s_rf_reference
.sr_clen
)
basesize
+= 2 + s
-> s_rf_reference
.sr_clen
;
if (s
-> s_rf_reference
.sr_alen
)
basesize
+= 2 + s
-> s_rf_reference
.sr_alen
;
if (s
-> s_ar_reference
.sr_ulen
)
basesize
+= 2 + s
-> s_ar_reference
.sr_ulen
;
if (s
-> s_ar_reference
.sr_clen
)
basesize
+= 2 + s
-> s_ar_reference
.sr_clen
;
if (s
-> s_ar_reference
.sr_alen
)
basesize
+= 2 + s
-> s_ar_reference
.sr_alen
;
if (s
-> s_ar_reference
.sr_vlen
)
basesize
+= 2 + s
-> s_ar_reference
.sr_vlen
;
c
-> len
= basesize
+ ((basesize
> 254) ? 4 : 2);
if ((c
-> top
= malloc ((unsigned) c
-> len
)) == NULL
) {
s
-> s_errno
= SC_CONGEST
;
s
-> s_errno
= SC_ACCEPT
;
if ((c
-> allocli
= c
-> left
= basesize
) > 254)
static int end_spdu (code
, c
)
if (c
-> allocli
> 254) {
bcopy ((c
-> top
+ 2), c
-> top
, (c
-> len
- c
-> left
));
*(c
-> top
+ 1) = c
-> li
;
*(c
-> top
+ 2) = (c
-> li
>> 8) & 0xff;
*(c
-> top
+ 3) = c
-> li
& 0xff;
*(c
-> top
+ 1) = c
-> li
;
c
-> len
= c
-> ptr
- c
-> top
;
static start_pgi (code
, c
)
put2spdu ((int) code
, 0, NULLCP
, c
);
c
-> pgi
= (c
-> ptr
- c
-> top
- 1);
*(c
-> top
+ c
-> pgi
) = (c
-> len
- c
-> left
) - (c
-> pgi
+ 1);
static put2spdu (code
, li
, value
, c
)
cl
+= (li
< 255) ? 2 : 4;
/* XXX: this clause of Dwight's is all WRONG, WRONG, WRONG. I think we
should make start_spdu() smarter, if necessary and change this to
cp
= realloc (c
-> top
, (unsigned) (c
-> len
+= cl
));
c
-> ptr
= (c
-> top
= cp
) + (c
-> len
- c
-> left
);
if (c
-> allocli
< 255) {
cl
= c
-> len
- c
-> left
+ 2;
for (p1
= c
-> ptr
, p2
= p1
+ 2; cl
; cl
--)
*c
-> ptr
++ = code
& 0xff;
*c
-> ptr
++ = (li
>> 8) & 0xff;
bcopy (value
, c
-> ptr
, li
);
int spkt2tsdu (s
, base
, len
)
register struct ssapkt
*s
;
char isn
[SIZE_CN_ISN
+ 1];
start_spdu (s
, &c
, CN_BASE_SIZE
);
Put_Ref (s
-> s_cn_reference
, PI_CALLING_SS
);
If_Set (SMASK_CN_OPT
| SMASK_CN_TSDU
| SMASK_CN_VRSN
| SMASK_CN_ISN
start_pgi (PGI_CN_ITEMS
, &c
);
Put_Item (PI_PROTOCOL_OPT
, (char *) &s
-> s_options
);
u_long tsdu_maxsize
= (s
-> s_tsdu_init
& 0xffff) << 16
| s
-> s_tsdu_resp
& 0xffff;
tsdu_maxsize
= htonl (tsdu_maxsize
);
Put_Item (PI_TSDU_MAXSIZ
, (char *) &tsdu_maxsize
);
Put_Item (PI_VERSION
, (char *) &s
-> s_cn_version
);
Put_SSN (PI_ISN
, s
-> s_isn
);
Put_Item (PI_TOKEN_SET
, (char *) &s
-> s_settings
);
u_short requirements
= htons (s
-> s_cn_require
);
Put_Item (PI_USER_REQ
, (char *) &requirements
);
If_Set (SMASK_CN_CALLING
)
put2spdu (PI_SSAP_CALLING
, s
-> s_callinglen
,
put2spdu (PI_SSAP_CALLED
, s
-> s_calledlen
,
start_spdu (s
, &c
, AC_BASE_SIZE
);
Put_Ref (s
-> s_cn_reference
, PI_CALLED_SS
);
If_Set (SMASK_CN_OPT
| SMASK_CN_TSDU
| SMASK_CN_VRSN
| SMASK_CN_ISN
start_pgi (PGI_CN_ITEMS
, &c
);
Put_Item (PI_PROTOCOL_OPT
, (char *) &s
-> s_options
);
u_long tsdu_maxsize
= (s
-> s_tsdu_init
& 0xffff) << 16
| s
-> s_tsdu_resp
& 0xffff;
tsdu_maxsize
= htonl (tsdu_maxsize
);
Put_Item (PI_TSDU_MAXSIZ
, (char *) &tsdu_maxsize
);
Put_Item (PI_VERSION
, (char *) &s
-> s_cn_version
);
Put_SSN (PI_ISN
, s
-> s_isn
);
Put_Item (PI_TOKEN_SET
, (char *) &s
-> s_settings
);
Put_Item (PI_TOKEN
, (char *) &s
-> s_ac_token
);
u_short requirements
= htons (s
-> s_cn_require
);
Put_Item (PI_USER_REQ
, (char *) &requirements
);
If_Set (SMASK_CN_CALLING
)
put2spdu (PI_SSAP_CALLING
, s
-> s_callinglen
,
put2spdu (PI_SSAP_CALLED
, s
-> s_calledlen
,
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
start_spdu (s
, &c
, RF_BASE_SIZE
);
Put_Ref (s
-> s_rf_reference
, PI_CALLED_SS
);
Put_Item (PI_TDISC
, (char *) &s
-> s_rf_disconnect
);
u_short requirements
= htons (s
-> s_rf_require
);
Put_Item (PI_USER_REQ
, (char *) &requirements
);
Put_Item (PI_VERSION
, (char *) &s
-> s_rf_version
);
if (s
-> s_rlen
> RF_SIZE
) {
s
-> s_errno
= SC_PROTOCOL
;
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
put2spdu (PI_REASON
, s
-> s_rlen
, s
-> s_rdata
, &c
);
start_spdu (s
, &c
, FN_BASE_SIZE
);
Put_Item (PI_TDISC
, (char *) &s
-> s_fn_disconnect
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
start_spdu (s
, &c
, DN_BASE_SIZE
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
start_spdu (s
, &c
, NF_BASE_SIZE
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
case SPDU_AI
: /* aka SPDU_AB */
start_spdu (s
, &c
, AB_BASE_SIZE
);
If_Reset (SMASK_AB_DISC
) {
s
-> s_errno
= SC_PROTOCOL
;
Put_Item (PI_TDISC
, (char *) &s
-> s_ab_disconnect
);
put2spdu (PI_REFLECT
, AB_REFL_SIZE
,
(char *) s
-> s_reflect
, &c
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
start_spdu (s
, &c
, AI_BASE_SIZE
);
put2spdu (PI_REASON
, 1, (char *) &s
-> s_ai_reason
, &c
);
case SPDU_AIA
: /* aka SPDU_AA */
start_spdu (s
, &c
, AA_BASE_SIZE
);
start_spdu (s
, &c
, AIA_BASE_SIZE
);
case SPDU_DT
: /* aka SPDU_GT */
start_spdu (s
, &c
, GT_BASE_SIZE
);
Put_Item (PI_TOKEN
, (char *) &s
-> s_gt_token
);
start_spdu (s
, &c
, DT_BASE_SIZE
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
/* NB: caller responsible for mapping s -> s_udata to user info */
start_spdu (s
, &c
, TD_BASE_SIZE
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
/* NB: caller responsible for mapping s -> s_udata to user info */
start_spdu (s
, &c
, EX_BASE_SIZE
);
/* NB: caller responsible for mapping s -> s_udata to user info */
start_spdu (s
, &c
, CD_BASE_SIZE
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
start_spdu (s
, &c
, CDA_BASE_SIZE
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
start_spdu (s
, &c
, PT_BASE_SIZE
);
Put_Item (PI_TOKEN
, (char *) &s
-> s_pt_token
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
start_spdu (s
, &c
, GTC_BASE_SIZE
);
start_spdu (s
, &c
, GTA_BASE_SIZE
);
start_spdu (s
, &c
, MIP_BASE_SIZE
);
Put_Item (PI_SYNC
, (char *) &s
-> s_mip_sync
);
If_Reset (SMASK_MIP_SERIAL
) {
s
-> s_errno
= SC_PROTOCOL
;
Put_SSN (PI_SERIAL
, s
-> s_mip_serial
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
case SPDU_AE
: /* aka SPDU_MAP */
If_Set (SMASK_MAP_SYNC
) {
start_spdu (s
, &c
, MAP_BASE_SIZE
);
Put_Item (PI_SYNC
, (char *) &s
-> s_map_sync
);
start_spdu (s
, &c
, AE_BASE_SIZE
);
If_Reset (SMASK_MAP_SERIAL
) {
s
-> s_errno
= SC_PROTOCOL
;
Put_SSN (PI_SERIAL
, s
-> s_map_serial
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
start_spdu (s
, &c
, MIA_BASE_SIZE
);
If_Reset (SMASK_MIA_SERIAL
) {
s
-> s_errno
= SC_PROTOCOL
;
Put_SSN (PI_SERIAL
, s
-> s_mia_serial
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
case SPDU_AEA
: /* aka SPDU_MAA */
start_spdu (s
, &c
, MAA_BASE_SIZE
);
If_Reset (SMASK_MAA_SERIAL
) {
s
-> s_errno
= SC_PROTOCOL
;
Put_SSN (PI_SERIAL
, s
-> s_maa_serial
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
start_spdu (s
, &c
, RS_BASE_SIZE
);
Put_Item (PI_TOKEN_SET
, (char *) &s
-> s_rs_settings
);
If_Reset (SMASK_RS_TYPE
) {
s
-> s_errno
= SC_PROTOCOL
;
Put_Item (PI_RESYNC
, (char *) &s
-> s_rs_type
);
If_Reset (SMASK_RS_SSN
) {
s
-> s_errno
= SC_PROTOCOL
;
Put_SSN (PI_SERIAL
, s
-> s_rs_serial
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
start_spdu (s
, &c
, RA_BASE_SIZE
);
Put_Item (PI_TOKEN_SET
, (char *) &s
-> s_ra_settings
);
If_Reset (SMASK_RA_SSN
) {
s
-> s_errno
= SC_PROTOCOL
;
Put_SSN (PI_SERIAL
, s
-> s_ra_serial
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
start_spdu (s
, &c
, PR_BASE_SIZE
);
If_Reset (SMASK_PR_TYPE
) {
s
-> s_errno
= SC_PROTOCOL
;
Put_Item (PI_PREPARE
, (char *) &s
-> s_pr_type
);
case SPDU_ER
: /* we don't do these! */
s
-> s_errno
= SC_PROTOCOL
;
start_spdu (s
, &c
, ED_BASE_SIZE
);
If_Reset (SMASK_ED_REASON
) {
s
-> s_errno
= SC_PROTOCOL
;
put2spdu (PI_REASON
, 1, (char *) &s
-> s_ed_reason
, &c
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
start_spdu (s
, &c
, AS_BASE_SIZE
);
s
-> s_errno
= SC_PROTOCOL
;
put2spdu (PI_ACT_ID
, (int) s
-> s_as_id
.sd_len
,
s
-> s_as_id
.sd_data
, &c
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
start_spdu (s
, &c
, AR_BASE_SIZE
);
start_pgi (PGI_AR_LINK
, &c
);
if (s
-> s_ar_reference
.sr_called_len
)
(int) s
-> s_ar_reference
.sr_called_len
,
s
-> s_ar_reference
.sr_called
, &c
);
if (s
-> s_ar_reference
.sr_calling_len
)
(int) s
-> s_ar_reference
.sr_calling_len
,
s
-> s_ar_reference
.sr_calling
, &c
);
if (s
-> s_ar_reference
.sr_clen
)
put2spdu (PI_AR_COMMON
, (int) s
-> s_ar_reference
.sr_clen
,
s
-> s_ar_reference
.sr_cdata
, &c
);
if (s
-> s_ar_reference
.sr_alen
)
put2spdu (PI_AR_ADDT
, (int) s
-> s_ar_reference
.sr_alen
,
s
-> s_ar_reference
.sr_adata
, &c
);
If_Reset (SMASK_AR_OID
) {
s
-> s_errno
= SC_PROTOCOL
;
put2spdu (PI_ACT_ID
, (int) s
-> s_ar_oid
.sd_len
,
s
-> s_ar_oid
.sd_data
, &c
);
If_Reset (SMASK_AR_SSN
) {
s
-> s_errno
= SC_PROTOCOL
;
Put_SSN (PI_SERIAL
, s
-> s_ar_serial
);
s
-> s_errno
= SC_PROTOCOL
;
put2spdu (PI_ACT_ID
, (int) s
-> s_ar_id
.sd_len
,
s
-> s_ar_id
.sd_data
, &c
);
Put_Item (PI_ENCLOSE
, (char *) &s
-> s_enclose
);
start_spdu (s
, &c
, AD_BASE_SIZE
);
put2spdu (PI_REASON
, 1, (char *) &s
-> s_ad_reason
, &c
);
start_spdu (s
, &c
, ADA_BASE_SIZE
);
s
-> s_errno
= SC_PROTOCOL
;
if ((end_spdu (s
-> s_code
, &c
) == NOTOK
) || (s
-> s_errno
!= SC_ACCEPT
)) {
if (s
-> s_errno
== SC_ACCEPT
)
s
-> s_errno
= SC_CONGEST
;
if (ssap_log
-> ll_events
& LLOG_PDUS
)
spkt2text (ssap_log
, s
, 0);
return c
.len
? OK
: NOTOK
;
static u_long
str2ssn (s
, n
)
/* this is used to pull PCI, not user data... */
if ((base = pullqb (qb, (n))) == NULL) { \
s -> s_errno = SC_PROTOCOL; \
static char *pullqb (qb
, n
)
register struct qbuf
*qp
;
static char *buffer
= NULL
;
for (once
= 1, cp
= buffer
, qp
= NULL
; n
> 0; once
= 0, cp
+= i
, n
-= i
) {
if (qp
== NULL
&& (qp
= qb
-> qb_forw
) == qb
)
i
= min (qp
-> qb_len
, n
);
if (once
&& i
== n
) { /* special case */
qp
-> qb_data
+= i
, qp
-> qb_len
-= i
;
if ((buffer
= malloc ((unsigned) SEGMENT_MAX
)) == NULL
)
bcopy (qp
-> qb_data
, cp
, i
);
qp
-> qb_data
+= i
, qp
-> qb_len
-= i
;
struct ssapkt
*tsdu2spkt (qb
, len
, cc
)
register struct ssapkt
*s
;
if ((base
= pullqb (qb
, nread
= 2)) == NULL
|| (s
= newspkt ((int) (si
= *base
++))) == NULL
)
if (*((u_char
*) base
) == 255) {
if ((base
= pullqb (qb
, 2)) == NULL
) {
s
-> s_errno
= SC_PROTOCOL
;
(*((u_char
*) base
) << 8) + *((u_char
*) (base
+ 1));
s
-> s_li
= *((u_char
*) base
);
pgilen
= pktlen
= s
-> s_li
;
|| ((pmask
= si_table
[si
]) == PMASK_NOTSUPPORTED
)) {
s
-> s_errno
= SC_PROTOCOL
;
if (len
< pktlen
+ nread
) {
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_errno
= SC_ACCEPT
;
while (pktlen
&& (s
-> s_errno
== SC_ACCEPT
)) {
if (*((u_char
*) base
) == 255) {
li
= (*((u_char
*) base
) << 8) + *((u_char
*) (base
+ 1));
if (!(pmask
& PMASK_UDATA
))
s
-> s_errno
= SC_PROTOCOL
;
if (!(pmask
& PMASK_XDATA
))
s
-> s_errno
= SC_PROTOCOL
;
if (code
>= PI_TABLE_LEN
|| !(pmask
& pi_table
[code
]))
s
-> s_errno
= SC_PROTOCOL
;
if (s
-> s_errno
!= SC_ACCEPT
)
if (li
> (pgilen
-= xlen
)) {
s
-> s_errno
= SC_PROTOCOL
;
if (code
< PI_TABLE_LEN
) {
if (pi_table
[code
] & PMASK_VARLEN
) {
if (li
> pi_length
[code
]) {
s
-> s_errno
= SC_PROTOCOL
;
if (li
!= pi_length
[code
]) {
s
-> s_errno
= SC_PROTOCOL
;
Set (SMASK_AR_OID
);/* HACK! */
Set (SMASK_CN_REF
);/* fall */
s
-> s_cn_reference
.sr_ulen
= li
;
bcopy (base
, s
-> s_cn_reference
.sr_udata
, li
);
s
-> s_rf_reference
.sr_ulen
= li
;
bcopy (base
, s
-> s_rf_reference
.sr_udata
, li
);
s
-> s_ar_reference
.sr_called_len
= li
;
bcopy (base
, s
-> s_ar_reference
.sr_called
,
s
-> s_ar_reference
.sr_calling_len
= li
;
bcopy (base
, s
-> s_ar_reference
.sr_calling
,
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_cn_reference
.sr_clen
= li
;
bcopy (base
, s
-> s_cn_reference
.sr_cdata
, li
);
s
-> s_rf_reference
.sr_clen
= li
;
bcopy (base
, s
-> s_rf_reference
.sr_cdata
, li
);
s
-> s_ar_reference
.sr_clen
= li
;
bcopy (base
, s
-> s_ar_reference
.sr_cdata
, li
);
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_cn_reference
.sr_alen
= li
;
bcopy (base
, s
-> s_cn_reference
.sr_adata
, li
);
s
-> s_rf_reference
.sr_alen
= li
;
bcopy (base
, s
-> s_rf_reference
.sr_adata
, li
);
s
-> s_ar_reference
.sr_alen
= li
;
bcopy (base
, s
-> s_ar_reference
.sr_adata
, li
);
s
-> s_errno
= SC_PROTOCOL
;
if ((s
-> s_options
= *base
++) & ~CR_OPT_MASK
)
s
-> s_errno
= SC_PROTOCOL
;
bcopy (base
, (char *) &tsdu_maxsize
,
pi_length
[PI_TSDU_MAXSIZ
]);
tsdu_maxsize
= ntohl (tsdu_maxsize
);
s
-> s_tsdu_init
= (tsdu_maxsize
>> 16) & 0xffff;
s
-> s_tsdu_resp
= tsdu_maxsize
& 0xffff;
base
+= pi_length
[PI_TSDU_MAXSIZ
];
s
-> s_cn_version
= *base
++;
s
-> s_rf_version
= *base
++;
s
-> s_errno
= SC_PROTOCOL
;
if ((s
-> s_mip_sync
= *base
++) & ~MIP_SYNC_MASK
)
s
-> s_errno
= SC_PROTOCOL
;
if ((s
-> s_map_sync
= *base
++) & ~MAP_SYNC_MASK
)
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_settings
= *base
++;
s
-> s_rs_settings
= *base
++;
s
-> s_ra_settings
= *base
++;
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_ac_token
= *base
++;
If_Reset (SMASK_SPDU_GT
) {
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_gt_token
= *base
++;
s
-> s_pt_token
= *base
++;
s
-> s_errno
= SC_PROTOCOL
;
if ((s
-> s_rf_disconnect
= *base
++) & ~RF_DISC_MASK
)
s
-> s_errno
= SC_PROTOCOL
;
if ((s
-> s_fn_disconnect
= *base
++) & ~FN_DISC_MASK
)
s
-> s_errno
= SC_PROTOCOL
;
If_Reset (SMASK_SPDU_AB
) {
s
-> s_errno
= SC_PROTOCOL
;
if ((s
-> s_ab_disconnect
= *base
++) & ~AB_DISC_MASK
)
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_errno
= SC_PROTOCOL
;
bcopy (base
, (char *) &requirements
, 2);
requirements
= ntohs (requirements
);
s
-> s_cn_require
= requirements
;
s
-> s_rf_require
= requirements
;
s
-> s_isn
= str2ssn (base
, li
);
s
-> s_errno
= SC_PROTOCOL
;
case PI_ISN2
: /* not supported yet */
if ((si
== SPDU_DT
&& (s
-> s_mask
& SMASK_SPDU_GT
))
|| (si
== SPDU_AI
&& !(s
-> s_mask
& SMASK_SPDU_AB
))) {
s
-> s_errno
= SC_PROTOCOL
;
if ((s
-> s_enclose
= *base
++) & ~ENCL_MASK
)
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_rs_type
= *base
++;
if (SYNC_OK (s
-> s_rs_type
))
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_as_id
.sd_len
= li
;
bcopy (base
, s
-> s_as_id
.sd_data
, li
);
if ((s
-> s_mask
& SMASK_AR_OID
)
&& s
-> s_ar_oid
.sd_len
== 0) {
s
-> s_ar_oid
.sd_len
= li
;
bcopy (base
, s
-> s_ar_oid
.sd_data
, li
);
s
-> s_ar_id
.sd_len
= li
;
bcopy (base
, s
-> s_ar_id
.sd_data
, li
);
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_mip_serial
= str2ssn (base
, li
);
s
-> s_map_serial
= str2ssn (base
, li
);
s
-> s_mia_serial
= str2ssn (base
, li
);
s
-> s_maa_serial
= str2ssn (base
, li
);
s
-> s_rs_serial
= str2ssn (base
, li
);
s
-> s_ra_serial
= str2ssn (base
, li
);
s
-> s_ar_serial
= str2ssn (base
, li
);
s
-> s_errno
= SC_PROTOCOL
;
if (si
== SPDU_AB
&& !(s
-> s_mask
& SMASK_SPDU_AB
)) {
s
-> s_errno
= SC_PROTOCOL
;
if (li
> (code
!= PI_XDATA
? SEGMENT_MAX
: CONNECT_MAX
)) {
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_udata
= malloc ((unsigned) (s
-> s_ulen
= li
));
if (s
-> s_udata
== NULL
) {
s
-> s_errno
= SC_CONGEST
;
bcopy (base
, s
-> s_udata
, li
);
s
-> s_rdata
= malloc ((unsigned) (s
-> s_rlen
= li
));
if (s
-> s_rdata
== NULL
) {
s
-> s_errno
= SC_CONGEST
;
bcopy (base
, s
-> s_rdata
, li
);
s
-> s_ed_reason
= *base
++;
if (li
== 1 && SP_OK (s
-> s_ed_reason
))
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_ai_reason
= *base
++;
if (li
== 1 && SP_OK (s
-> s_ai_reason
))
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_ad_reason
= *base
++;
if (li
== 1 && SP_OK (s
-> s_ad_reason
))
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_errno
= SC_PROTOCOL
;
If_Reset (SMASK_SPDU_AB
) {
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_errno
= SC_PROTOCOL
;
bcopy (base
, (char *) s
-> s_reflect
, li
);
s
-> s_udata
= malloc ((unsigned) (s
-> s_ulen
= li
));
if (s
-> s_udata
== NULL
) {
s
-> s_errno
= SC_CONGEST
;
bcopy (base
, s
-> s_udata
, li
);
s
-> s_errno
= SC_PROTOCOL
;
bcopy (base
, s
-> s_calling
, s
-> s_callinglen
= li
);
bcopy (base
, s
-> s_called
, s
-> s_calledlen
= li
);
if ((s
-> s_pr_type
= *base
++) > PR_MAX
)
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_errno
= SC_PROTOCOL
;
/* NB: caller responsible for mapping user info to s -> s_qbuf */
register struct qbuf
*qp
;
if ((qp
= qb
-> qb_forw
) != qb
&& qp
-> qb_len
<= 0) {
s
-> s_errno
= SC_PROTOCOL
;
If_Reset (SMASK_MIP_SERIAL
)
s
-> s_errno
= SC_PROTOCOL
;
If_Reset (SMASK_MAP_SERIAL
)
s
-> s_errno
= SC_PROTOCOL
;
If_Reset (SMASK_MIA_SERIAL
)
s
-> s_errno
= SC_PROTOCOL
;
If_Reset (SMASK_MAA_SERIAL
)
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_errno
= SC_PROTOCOL
;
If_Reset (SMASK_ED_REASON
)
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_errno
= SC_PROTOCOL
;
s
-> s_errno
= SC_PROTOCOL
;
if (ssap_log
-> ll_events
& LLOG_PDUS
)
spkt2text (ssap_log
, s
, 1);
struct ssapkt
*newspkt (code
)
register struct ssapkt
*s
;
s
= (struct ssapkt
*) calloc (1, sizeof *s
);
s
-> s_qbuf
.qb_forw
= s
-> s_qbuf
.qb_back
= &s
-> s_qbuf
;
register struct ssapkt
*s
;
free (s
-> s_rdata
);/* and fall... */