/************************************************************************/ /* SISCO SOFTWARE MODULE HEADER *****************************************/ /************************************************************************/ /* (c) Copyright Systems Integration Specialists Company, Inc., */ /* 1997 All Rights Reserved */ /* */ /* MODULE NAME : tp0_dec.c */ /* PRODUCT(S) : Lean-T Stack */ /* */ /* MODULE DESCRIPTION : */ /* TP0 decode functions. */ /* */ /* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ /* np_data_ind () */ /* np_disconnect_ind () */ /* np_connect_cnf_pos () */ /* */ /* MODIFICATION LOG : */ /* Date Who Rev Comments */ /* -------- --- ------ ------------------------------------------- */ /* 10/22/08 JRB 06 TPDU must be at least 2 bytes to decode. */ /* Chg tp_decode_er to really decode ER TPDU. */ /* 04/07/03 JRB 05 Add SPDU_RX_NO_PREALLOCATE option. */ /* 04/13/00 JRB 04 Lint cleanup. */ /* 08/13/98 JRB 03 Lint cleanup. */ /* 09/25/97 JRB 02 Don't generate exception for invalid state. */ /* 08/01/97 JRB 01 Created (compatible with MMS-EASE 7.0). */ /************************************************************************/ #include "glbtypes.h" #include "sysincs.h" #include "mem_chk.h" #include "tp4api.h" /* User definitions for tp4 */ #include "tp4.h" /* Internal definitions for tp4 */ #include "tp4_encd.h" #include "tp4_log.h" #ifdef DEBUG_SISCO SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; #endif /************************************************************************/ /* np_data_ind */ /* This "np_data_ind" funct is similar to "tp_decode_nsdu" used for TP4.*/ /* It calls one function to decode the PDU, then another function to */ /* process it. The "decode" functions are shared with TP4. */ /************************************************************************/ ST_VOID np_data_ind (SOCK_INFO *sock_info, ST_UCHAR *pdu_ptr, ST_UINT16 pdu_len) { ST_UCHAR type; ST_UINT16 len; /* len of processed TPDU by a dec func */ TPDU_CX tpdu_cx_rx; /* tpdu_cr_rx or tpdu_cc_rx */ TPDU_DR tpdu_dr_rx; TPDU_DT tpdu_dt_rx; TPDU_ER tpdu_er_rx; /* TP0 TPDU starts after TPKT hdr (RFC1006_HEAD_LEN bytes). */ /* TPDU must be at least 2 bytes (len and TPDU code) to safely decode.*/ if (pdu_len < RFC1006_HEAD_LEN + 2) { TP_LOG_ERR0 ("TP0 TPDU too short to decode. Ignored."); return; } /* Strip off TPKT header. */ pdu_len -= RFC1006_HEAD_LEN; pdu_ptr += RFC1006_HEAD_LEN; /* get the TPDU type (from the second octet, bits 4-7) */ type = pdu_ptr [1] & TP_PDU_MASK_CDT; /* Based on type of TPDU (CR, CC, DT, etc.) call appropriate decode */ /* subfunction. */ switch (type) { case TP_PDU_TYPE_CR: case TP_PDU_TYPE_CC: if ((len = tp_decode_cx (&tpdu_cx_rx, pdu_ptr, pdu_len, type, TP_PDU_MAX_SIZE_65531)) != 0) /* Default TPDU size=65531*/ { tpdu_cx_rx.sock_info = sock_info; tp_log_tsdu ((ST_VOID *) &tpdu_cx_rx, type, TP_IND); /* This is the only step different in processing CR or CC. */ if (type == TP_PDU_TYPE_CR) tp0_process_cr (&tpdu_cx_rx); else tp0_process_cc (&tpdu_cx_rx); } break; case TP_PDU_TYPE_DR: if ((len = tp_decode_dr (&tpdu_dr_rx, pdu_ptr, pdu_len)) != 0) { tpdu_dr_rx.sock_info = sock_info; tp_log_tsdu ((ST_VOID *) &tpdu_dr_rx, TP_PDU_TYPE_DR, TP_IND); tp0_process_dr (&tpdu_dr_rx); } break; case TP_PDU_TYPE_DT: if ((len = tp0_decode_dt (&tpdu_dt_rx, pdu_ptr, pdu_len)) != 0) { tpdu_dt_rx.sock_info = sock_info; tp_log_tsdu ((ST_VOID *) &tpdu_dt_rx, TP_PDU_TYPE_DT, TP_IND); tp0_process_dt (&tpdu_dt_rx); } break; case TP_PDU_TYPE_ER: /* NOTE: the last arg indicates this is Transport Class 0. */ if ((len = tp_decode_er (&tpdu_er_rx, pdu_ptr, pdu_len, 0)) > 0) { /* decode succeeded but we ignore ER TPDU. Log so user knows.*/ TP_LOG_ERR0 ("DEBUG: processing of TPDU-ER.ind not implemented yet."); } break; case TP_PDU_TYPE_ED: /* we do not support expedited data */ case TP_PDU_TYPE_EA: TP_LOG_ERR0 ("TP-ERROR: decode ED or EA TPDU failed (not supported)"); break; /* Do nothing */ default: /* type unknown, we should exit decoding */ TP_LOG_ERR1 ("TP-ERROR: decode TPDU failed (invalid type 0x%2.2X)", (unsigned) type); break; } /* end "switch" */ } /************************************************************************/ /* np_disconnect_ind */ /************************************************************************/ ST_VOID np_disconnect_ind (SOCK_INFO *sock_info) { TP0_CONN *tp_conn; ST_INT reason; /* Transport Disconnect reason */ if (sock_info->user_conn_id == INVALID_CONN_ID) return; /* Transport doesn't know about connection yet. IGNORE. */ tp_conn = (TP0_CONN *) sock_info->user_conn_id; switch (tp_conn->state) { case TP_STATE_WFNC: case TP_STATE_WFCC: case TP_STATE_OPEN: case TP_STATE_WFTRESP: reason = 0; /* Normal disconnection */ /* NOTE: To save memory, user data is never passed up to user. */ tp4_disconnect_ind (tp_conn->user_conn_id, reason, 0, NULL); /* No user data passed up. */ tp_conn->state = TP_STATE_CLOSED; #if defined(SPDU_RX_NO_PREALLOCATE) M_FREE (MSMEM_STARTUP, tp_conn->spdu_rx.spdu_ptr); #endif break; default: TP_LOG_ERR1 ("TP-ERROR: invalid state (%d) for N-DISCONNECT.ind. Ignored.", tp_conn->state); break; } } /************************************************************************/ /* np_connect_cnf_pos */ /************************************************************************/ ST_VOID np_connect_cnf_pos (SOCK_INFO *sock_info, ST_LONG user_conn_id) { TP0_CONN *tp_conn = (TP0_CONN *) user_conn_id; /* Save sock_info ptr in tp_conn. */ tp_conn->sock_info = sock_info; /* CRITICAL: Save sock_info in tp_conn->tpdu_cx before calling tp0_send_cr*/ tp_conn->tpdu_cx.sock_info = tp_conn->sock_info; /* Send T-CONNECT.req */ tp0_send_cr (&tp_conn->tpdu_cx); tp_conn->state = TP_STATE_WFCC; }