/************************************************************************/ /* SISCO SOFTWARE MODULE HEADER *****************************************/ /************************************************************************/ /* (c) Copyright Systems Integration Specialists Company, Inc., */ /* 1996, All Rights Reserved. */ /* */ /* PROPRIETARY AND CONFIDENTIAL */ /* */ /* MODULE NAME : tp4_enc.c */ /* PRODUCT(S) : Lean-T Stack */ /* */ /* MODULE DESCRIPTION : */ /* This module implements the encoding of the TPDUs. */ /* */ /* For information see the: */ /* ISO 8073 "Information processing systems - Open Systems */ /* Interconnections - Connection oriented transport protocol */ /* specification. */ /* */ /* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ /* */ /* tp_encode_cx */ /* tp_encode_dr */ /* tp_encode_dc */ /* tp_encode_dt */ /* tp0_encode_dt */ /* tp_encode_ak */ /* */ /* MODIFICATION LOG : */ /* Date Who Rev Comments */ /* -------- --- ------ ------------------------------------------- */ /* 08/13/98 JRB 04 Fix indenting. */ /* 08/26/97 JRB 03 RFC1006 changes: */ /* - add TP0 encode */ /* - tp_encode_cx: if TPDU size = 65531, don't */ /* encode it. Peer should default to 65531. */ /* - Use TP_PDU_TYPE_* everywhere. */ /* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ /* 10/04/96 JRB 02 Use max_tpdu_len_enc (binary encoded value). */ /* 06/20/96 EJV 01 Created */ /************************************************************************/ static char *thisFileName = __FILE__; /* For TP4_EXCEPT and slog macros*/ #include "glbtypes.h" #include "sysincs.h" #include "checksum.h" #include "tp4api.h" /* User definitions for tp4 */ #include "tp4.h" #include "tp4_encd.h" #include "tp4_log.h" /* local functions prototypes */ static ST_VOID tp_enc_par_checksum (ST_UCHAR *buf, ST_UINT16 buf_len, ST_UINT16 par_pos); /************************************************************************/ /* tp_encode_cx */ /*----------------------------------------------------------------------*/ /* This function is used to encode a CR or CC TPDU. */ /* */ /* Parameters: */ /* ST_UCHAR *enc_buf Pointer where to encode the CX TPDU */ /* TPDU_CX *tpdu_cx Pointer to info struct for CX TPDU */ /* ST_UCHAR pdu_type TP_PDU_TYPE_CR or TP_PDU_TYPE_CC */ /* */ /* Return: */ /* ST_UINT16 The actual length of encoded TPDU */ /************************************************************************/ ST_UINT16 tp_encode_cx (ST_UCHAR *enc_buf, TPDU_CX *tpdu_cx, ST_UCHAR pdu_type) { ST_UINT16 enc_len; /* The actual length of encoded TPDU */ TP_FHDR_CX *pdu; TP_PAR *param; /* generic struct for a parameter */ ST_UINT16 idx; /* points to current offset into enc_buf*/ enc_len = 0; /*------------------------------------*/ /* encode TPDU header, fixed part */ /*------------------------------------*/ pdu = (TP_FHDR_CX *) enc_buf; /* compute actual header length (do not count the hdr_len byte) */ if (tpdu_cx->preferred_class == 0) pdu->hdr_len = (ST_UCHAR) (TP_FHDR_CX_LEN - sizeof(pdu->hdr_len)+ /* fixed part of header */ TP_PAR_FIX_LEN + tpdu_cx->loc_tsap [0] + /* local TSAP parameter */ TP_PAR_FIX_LEN + tpdu_cx->rem_tsap [0]); /* remote TSAP parameter*/ else pdu->hdr_len = (ST_UCHAR) (TP_FHDR_CX_LEN - sizeof(pdu->hdr_len)+ /* fixed part of header */ TP_PAR_FIX_LEN + tpdu_cx->loc_tsap [0] + /* local TSAP parameter */ TP_PAR_FIX_LEN + tpdu_cx->rem_tsap [0] + /* remote TSAP parameter*/ TP_PAR_LEN_VERSION + /* TP version parameter */ TP_PAR_LEN_ADD_OPTIONS + /* additional opt param */ TP_PAR_LEN_CHECKSUM); /* checksum parameter */ /* NOTE: if TPDU size gets encoded hdr_len must be increased. */ /* set TPDU type */ if (pdu_type == TP_PDU_TYPE_CR || pdu_type == TP_PDU_TYPE_CC) pdu->type_cdt = pdu_type; else { TP_LOG_ERR1 ("TP-ERROR: Encode CR or CC failed (invalid pdu_type %u passed to func)", pdu_type); TP4_EXCEPT (); return (enc_len); /* valid types are CR and CC */ } /* set CDT, if specified CDT is greater then max default to max */ if (tpdu_cx->cdt <= TP_MAX_CDT) pdu->type_cdt |= tpdu_cx->cdt; else pdu->type_cdt |= TP_MAX_CDT; /* copy to dest ref remote connection reference */ if (pdu_type == TP_PDU_TYPE_CR) pdu->dest_ref [0] = pdu->dest_ref [1] = 0; /* always 0 */ else memcpy (pdu->dest_ref, (ST_UCHAR *) &tpdu_cx->rem_ref, sizeof (pdu->dest_ref)); /* copy to src ref local connection reference */ memcpy (pdu->src_ref, (ST_UCHAR *) &tpdu_cx->loc_ref, sizeof (pdu->src_ref)); if (tpdu_cx->preferred_class == 4) pdu->class_opt = TP_CLASS_4_NORMAL; /* set the TP class */ else if (tpdu_cx->preferred_class == 0) pdu->class_opt = TP_CLASS_0; /* set the TP class */ else { /* only class 4 (normal format) implemented */ TP_LOG_ERR1 ("TP-ERROR: Encode CR or CC failed (not implemented class %u)", tpdu_cx->preferred_class); TP4_EXCEPT (); return (enc_len); } idx = TP_FHDR_CX_LEN; /*------------------------------------*/ /* encode calling TSAP parameter */ /*------------------------------------*/ param = (TP_PAR *) &enc_buf [idx]; param->code = TP_PAR_CODE_TSAP_CALLING; /* parameter code */ if (pdu_type == TP_PDU_TYPE_CR) { /* Copy len and local TSAP to enc_buf */ memcpy (¶m->len, tpdu_cx->loc_tsap, 1 + tpdu_cx->loc_tsap [0]); idx += (ST_UINT16) (TP_PAR_FIX_LEN + tpdu_cx->loc_tsap [0]); } else { /* for CC copy len and remote TSAP to enc_buf */ memcpy (¶m->len, tpdu_cx->rem_tsap, 1 + tpdu_cx->rem_tsap [0]); idx += (ST_UINT16) (TP_PAR_FIX_LEN + tpdu_cx->rem_tsap [0]); } /*------------------------------------*/ /* encode called TSAP parameter */ /*------------------------------------*/ param = (TP_PAR *) &enc_buf [idx]; param->code = TP_PAR_CODE_TSAP_CALLED; /* parameter code */ if (pdu_type == TP_PDU_TYPE_CR) { /* Copy len and remote TSAP to enc_buf */ memcpy (¶m->len, tpdu_cx->rem_tsap, 1 + tpdu_cx->rem_tsap [0]); idx += (ST_UINT16) (TP_PAR_FIX_LEN + tpdu_cx->rem_tsap [0]); } else { /* for CC copy len and local TSAP to enc_buf */ memcpy (¶m->len, tpdu_cx->loc_tsap, 1 + tpdu_cx->loc_tsap [0]); idx += (ST_UINT16) (TP_PAR_FIX_LEN + tpdu_cx->loc_tsap [0]); } /*------------------------------------*/ /* encode TPDU size parameter */ /*------------------------------------*/ /* Can't encode 65531. If not encoded, other side defaults to 65531. */ if (tpdu_cx->max_tpdu_len_enc != TP_PDU_MAX_SIZE_65531) { pdu->hdr_len += TP_PAR_LEN_TPDU_SIZE; /* Adjust "hdr_len" */ param = (TP_PAR *) &enc_buf [idx]; param->code = TP_PAR_CODE_TPDU_SIZE; /* parameter code */ param->len = 1; /* parameter len */ if (tpdu_cx->max_tpdu_len_enc < TP_PDU_MAX_SIZE_128 || tpdu_cx->max_tpdu_len_enc > TP_PDU_MAX_SIZE_8192) { TP_LOG_ERR1 ("TP-ERROR: Encode CR or CC failed (invalid TPDU size %u)", tpdu_cx->max_tpdu_len_enc); TP4_EXCEPT (); return (enc_len); } else param->value[0] = tpdu_cx->max_tpdu_len_enc; idx += TP_PAR_LEN_TPDU_SIZE; } /*------------------------------------*/ /* encode TP version */ /*------------------------------------*/ if (tpdu_cx->preferred_class != 0) { param = (TP_PAR *) &enc_buf [idx]; param->code = TP_PAR_CODE_VERSION; /* parameter code */ param->len = 1; /* parameter len */ param->value [0] = TP_VERSION; /* version number */ idx += TP_PAR_LEN_VERSION; } /*------------------------------------*/ /* encode TP additional options */ /*------------------------------------*/ if (tpdu_cx->preferred_class != 0) { param = (TP_PAR *) &enc_buf [idx]; param->code = TP_PAR_CODE_ADD_OPTIONS;/* parameter code */ param->len = 1; /* parameter len */ param->value [0] = TP_OPT_CHECKSUM_USE | TP_OPT_EXPEDITED_NON_USE; /* this param is 0 for our selected options */ idx += TP_PAR_LEN_ADD_OPTIONS; /* next param is checksum */ } /*-----------------------------------------------------*/ /* copy the user data (if any) after the last parameter*/ /* (in our case the last param will be checksum param) */ /*-----------------------------------------------------*/ enc_len = (ST_UINT16) (pdu->hdr_len+1); /* set the TPDU size and add to it */ /* user data len (if any); add 1 for the*/ /* len byte we didn't counted in hdr_len*/ if (tpdu_cx->udata_len > 0) { if (tpdu_cx->preferred_class == 4) /* leave room for checksum */ memcpy (&enc_buf [idx + TP_PAR_LEN_CHECKSUM], tpdu_cx->udata_buf, tpdu_cx->udata_len); else memcpy (&enc_buf [idx], tpdu_cx->udata_buf, tpdu_cx->udata_len); enc_len += tpdu_cx->udata_len; } /*------------------------------------*/ /* encode the checksum parameter */ /*------------------------------------*/ if (tpdu_cx->preferred_class == 4) { tp_enc_par_checksum (enc_buf, enc_len, idx); } return (enc_len); } /************************************************************************/ /* tp_encode_dr */ /*----------------------------------------------------------------------*/ /* This function is used to encode a DR TPDU. */ /* */ /* Parameters: */ /* ST_UCHAR *enc_buf Pointer where to encode the DR TPDU */ /* TPDU_DR *tpdu_dr Pointer to info struct for DR TPDU */ /* */ /* Return: */ /* ST_UINT16 The actual length of encoded TPDU */ /************************************************************************/ ST_UINT16 tp_encode_dr (ST_UCHAR *enc_buf, TPDU_DR *tpdu_dr) { ST_UINT16 enc_len; /* The actual length of encoded TPDU */ TP_FHDR_DR *pdu; enc_len = TP_MAX_LEN_DR; /*------------------------------------*/ /* encode the TPDU header, fixed part */ /*------------------------------------*/ pdu = (TP_FHDR_DR *) enc_buf; pdu->hdr_len = TP_MAX_LEN_DR - sizeof (pdu->hdr_len); /* header length */ /* don't count the hdr_len byte */ pdu->type = TP_PDU_TYPE_DR; /* TPDU type */ memcpy (pdu->dest_ref, (ST_UCHAR *) &tpdu_dr->rem_ref, sizeof (pdu->dest_ref)); /* Remote connection reference */ memcpy (pdu->src_ref, (ST_UCHAR *) &tpdu_dr->loc_ref, sizeof (pdu->src_ref)); /* Local connection reference */ pdu->reason = tpdu_dr->reason; /* reason for DR */ /*------------------------------------*/ /* encode the checksum parameter */ /*------------------------------------*/ tp_enc_par_checksum (enc_buf, /* buf on which checksum is computed */ enc_len, /* len of buffer (length of TPDU) */ TP_FHDR_DR_LEN); /* position of checksum param in enc_buf*/ return (enc_len); } /************************************************************************/ /* tp_encode_dc */ /*----------------------------------------------------------------------*/ /* This function is used to encode a DC TPDU. */ /* */ /* Parameters: */ /* ST_UCHAR *enc_buf Pointer where to encode the DC TPDU */ /* TPDU_DR *tpdu_dc Pointer to info struct for DC TPDU */ /* */ /* Return: */ /* ST_UINT16 The actual length of encoded TPDU */ /************************************************************************/ ST_UINT16 tp_encode_dc (ST_UCHAR *enc_buf, TPDU_DC *tpdu_dc) { ST_UINT16 enc_len; /* The actual length of encoded TPDU */ TP_FHDR_DC *pdu; enc_len = TP_MAX_LEN_DC; /*------------------------------------*/ /* encode the TPDU header, fixed part */ /*------------------------------------*/ pdu = (TP_FHDR_DC *) enc_buf; pdu->hdr_len = TP_MAX_LEN_DC - sizeof (pdu->hdr_len); /* header length */ /* don't count the hdr_len byte */ pdu->type = TP_PDU_TYPE_DC; /* TPDU type */ memcpy (pdu->dest_ref, (ST_UCHAR *) &tpdu_dc->rem_ref, sizeof (pdu->dest_ref)); /* Remote connection reference */ memcpy (pdu->src_ref, (ST_UCHAR *) &tpdu_dc->loc_ref, sizeof (pdu->src_ref)); /* Local connection reference */ /*------------------------------------*/ /* encode the checksum parameter */ /*------------------------------------*/ tp_enc_par_checksum (enc_buf, /* buf on which checksum is computed */ enc_len, /* len of buffer (length of TPDU) */ TP_FHDR_DC_LEN); /* position of checksum param in enc_buf*/ return (enc_len); } /************************************************************************/ /* tp_encode_dt */ /*----------------------------------------------------------------------*/ /* This function is used to encode a DT TPDU. */ /* */ /* Parameters: */ /* ST_UCHAR *enc_buf Pointer to buffer where the TPDU should */ /* be encoded. */ /* TPDU_DT *tpdu_dt Pointer data info structure */ /* */ /* Return: */ /* ST_UINT16 The actual length of encoded TPDU */ /************************************************************************/ ST_UINT16 tp_encode_dt (ST_UCHAR *enc_buf, TPDU_DT *tpdu_dt) { ST_UINT16 enc_len; /* The actual length of encoded TPDU */ TP_FHDR_DT *pdu; enc_len = (ST_UINT16) (TP_HEAD_LEN_DT + tpdu_dt->udata_len); /*------------------------------------*/ /* encode the TPDU header, fixed part */ /*------------------------------------*/ pdu = (TP_FHDR_DT *) enc_buf; pdu->hdr_len = TP_HEAD_LEN_DT - sizeof (pdu->hdr_len); /* header length */ /* don't count the hdr_len byte */ pdu->type = TP_PDU_TYPE_DT; /* TPDU type */ memcpy (pdu->dest_ref, (ST_UCHAR *) &tpdu_dt->dst_ref, sizeof (pdu->dest_ref)); /* Remote connection reference */ /* set sequence number (make sure that bit 8 is not set) */ pdu->eot_sn = (ST_UCHAR) (tpdu_dt->sn & TP_PDU_MASK_EOF); if (tpdu_dt->eot) pdu->eot_sn |= TP_PDU_EOF; /* set EOT flag */ /*------------------------------------*/ /* copy the udata to enc_buf */ /*------------------------------------*/ memcpy (&enc_buf [TP_HEAD_LEN_DT], tpdu_dt->udata_ptr, tpdu_dt->udata_len); /*------------------------------------*/ /* encode the checksum parameter */ /*------------------------------------*/ tp_enc_par_checksum (enc_buf, /* buf on which checksum is computed */ enc_len, /* len of buffer (length of TPDU) */ TP_FHDR_DT_LEN); /* position of checksum param in enc_buf*/ return (enc_len); } /************************************************************************/ /* tp0_encode_dt */ /* This function is used to encode a Class 0 DT TPDU. */ /* Same as tp_encode_dt except dest_ref and Checksum NOT encoded. */ /************************************************************************/ ST_UINT16 tp0_encode_dt (ST_UCHAR *enc_buf, TPDU_DT *tpdu_dt) { ST_UINT16 enc_len; /* The actual length of encoded TPDU */ TP0_FHDR_DT *tp0_fhdr_dt; enc_len = (ST_UINT16) (TP0_HEAD_LEN_DT + tpdu_dt->udata_len); /*------------------------------------*/ /* encode the TPDU header, fixed part */ /*------------------------------------*/ tp0_fhdr_dt = (TP0_FHDR_DT *) enc_buf; tp0_fhdr_dt->hdr_len = TP0_HEAD_LEN_DT - 1; /* header length */ /* don't count the hdr_len byte */ tp0_fhdr_dt->type = TP_PDU_TYPE_DT; /* TPDU type */ /* set sequence number (make sure that bit 8 is not set) */ tp0_fhdr_dt->eot_sn = (ST_UCHAR) 0; /* sequence number always 0 */ if (tpdu_dt->eot) tp0_fhdr_dt->eot_sn |= TP_PDU_EOF; /* set EOT flag */ /*------------------------------------*/ /* copy the udata to enc_buf */ /*------------------------------------*/ memcpy (&enc_buf [TP0_HEAD_LEN_DT], tpdu_dt->udata_ptr, tpdu_dt->udata_len); return (enc_len); } /************************************************************************/ /* tp_encode_ak */ /*----------------------------------------------------------------------*/ /* This function is used to encode an AK TPDU. */ /* */ /* Parameters: */ /* ST_UCHAR *enc_buf Pointer to buffer where the TPDU should */ /* be encoded. */ /* TPDU_AK *tpdu_ak Pointer to AK info struct */ /* */ /* Return: */ /* ST_UINT16 The actual length of encoded TPDU */ /************************************************************************/ ST_UINT16 tp_encode_ak (ST_UCHAR *enc_buf, TPDU_AK *tpdu_ak) { ST_UINT16 enc_len; /* The actual length of encoded TPDU */ TP_FHDR_AK *pdu; enc_len = TP_MAX_LEN_AK; /*------------------------------------*/ /* encode the TPDU header, fixed part */ /*------------------------------------*/ pdu = (TP_FHDR_AK *) enc_buf; pdu->hdr_len = TP_MAX_LEN_AK - sizeof (pdu->hdr_len); /* header length */ /* don't count the hdr_len byte */ pdu->type_cdt = TP_PDU_TYPE_AK; /* TPDU type */ /* encode the CDT (from cfg struct) */ if (tpdu_ak->cdt <= TP_MAX_CDT) pdu->type_cdt |= tpdu_ak->cdt; else pdu->type_cdt |= TP_MAX_CDT; memcpy (pdu->dest_ref, (ST_UCHAR *) &tpdu_ak->dst_ref, sizeof (pdu->dest_ref)); /* Remote connection reference */ pdu->sn = tpdu_ak->sn; /* set next expected seq number */ /*------------------------------------*/ /* encode the checksum parameter */ /*------------------------------------*/ tp_enc_par_checksum (enc_buf, /* buf on which checksum is computed */ enc_len, /* len of buffer (length of TPDU) */ TP_FHDR_AK_LEN); /* position of checksum param in enc_buf*/ return (enc_len); } /*======================================================================*/ /* LOCAL FUNCTIONS for ENCODING */ /*======================================================================*/ /************************************************************************/ /* tp_enc_par_checksum */ /*----------------------------------------------------------------------*/ /* This function is used to encode the checksum parameter in TPDU. */ /* */ /* Parameters: */ /* ST_UCHAR *buf Ptr to encoding buffer on which checksum*/ /* will be computed. */ /* ST_UINT16 buf_len Length of the buffer (TPDU). */ /* ST_UINT16 par_pos Position of checksum parameter in buf. */ /* */ /* Return: */ /* ST_VOID none */ /************************************************************************/ static ST_VOID tp_enc_par_checksum (ST_UCHAR *buf, ST_UINT16 buf_len, ST_UINT16 par_pos) { TP_PAR *param; param = (TP_PAR *) &buf [par_pos]; param->code = TP_PAR_CODE_CHECKSUM; /* parameter code */ param->len = 2; /* Parameter length */ /* compute the checksum of the entire TPDU, the position of the */ /* checksum first byte in the buf is computed as the difference */ /* between pointers */ checksum_insert (buf, buf_len, (ST_UINT16) (param->value - buf)); }