/************************************************************************/ /* SISCO SOFTWARE MODULE HEADER *****************************************/ /************************************************************************/ /* (c) Copyright Systems Integration Specialists Company, Inc., */ /* 1997 - 2005 All Rights Reserved */ /* */ /* MODULE NAME : tp0calld.c */ /* PRODUCT(S) : Lean-T Stack */ /* */ /* MODULE DESCRIPTION : */ /* TP0 functions for handling of "Called" side of connections. */ /* */ /* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ /* tp0_accept () */ /* tp0_process_cr () */ /* */ /* MODIFICATION LOG : */ /* Date Who Rev Comments */ /* -------- --- ------ ------------------------------------------- */ /* 07/30/08 JRB 08 Use DR reason codes valid for TP0. */ /* 03/29/05 EJV 07 Added MMSEASE_MOSI support. */ /* 06/20/02 JRB 06 Chg addr args to tp4_connect_ind. */ /* 05/09/01 JRB 05 On T-CONNECT.ind, save TSAPs in TP0_CONN. */ /* 04/25/00 JRB 04 Lint cleanup. */ /* 06/08/99 JRB 03 Chg to support 1024 connections. */ /* 08/13/98 JRB 02 Lint cleanup. */ /* 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" /* Encode/decode defs for tp4 */ #include "tp4_log.h" #ifdef DEBUG_SISCO SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; #endif /*======================================================================*/ /*======================================================================*/ /* FUNCTIONS BELOW CALLED BY USER TO ENCODE AND SEND TPDUs. */ /*======================================================================*/ /*======================================================================*/ /************************************************************************/ /* tp0_accept */ /* This function is called by the user to accept a connect request from */ /* a remote node */ /************************************************************************/ ST_RET tp0_accept (ST_LONG tp0_conn_id, ST_LONG user_conn_id, ST_INT conndata_len, char *conndata) { TP0_CONN *tp_conn; if ((ST_ULONG) (tp0_conn_id-MIN_TP0_CONN_ID) >= tp0_cfg.max_num_conns) return (TP4E_BADCONN); tp_conn = &tp0_conn_arr [tp0_conn_id-MIN_TP0_CONN_ID]; if (tp_conn->state != TP_STATE_WFTRESP) return (TP4E_BADCONN); tp_conn->user_conn_id = user_conn_id; /* Save User's ID */ /* Save User Data in tp_conn for retransmission. */ /* DEBUG: Can we blow this off to save space? */ tp_conn->tpdu_cx.udata_len = min ((ST_UINT16) conndata_len, TP_MAX_CONN_UDATA); memcpy (tp_conn->tpdu_cx.udata_buf, conndata, tp_conn->tpdu_cx.udata_len); tp_conn->state = TP_STATE_OPEN; tp0_send_cc (&tp_conn->tpdu_cx); return (SD_SUCCESS); } /*======================================================================*/ /*======================================================================*/ /* FUNCTIONS BELOW CALLED BY TP0 TO PROCESS TPDUs RECEIVED */ /* (TPDUs ALREADY DECODED BY TP0). */ /*======================================================================*/ /*======================================================================*/ /************************************************************************/ /* tp0_process_cr */ /* Process a CR (Connection Request) TPDU. */ /************************************************************************/ ST_VOID tp0_process_cr (TPDU_CX *tpdu_cr_rx) { ST_UINT16 conn_id; /* index into "tp0_conn_arr" array (Unsigned so */ /* no sign-extension on compare to tp0_cfg.max_num_conns).*/ TP0_CONN *tp_conn; /* ptr to struct in "tp0_conn_arr" array. */ TPDU_DR tpdu_dr; ST_LONG tp0_user_bind_id; /* Fill in TPDU_DR struct in case DR needs to be sent. */ /* Do not fill in "reason" yet. */ tpdu_dr.loc_ref = 0; /* src-ref = 0 (always) */ tpdu_dr.rem_ref = tpdu_cr_rx->rem_ref; tpdu_dr.sock_info = tpdu_cr_rx->sock_info; /* Check if Local TSAP is correct. */ #if defined(MMSEASE_MOSI) if (tp0_check_tsel (tpdu_cr_rx->loc_tsap, &tp0_user_bind_id) != SD_SUCCESS) #else tp0_user_bind_id = only_tp0_user_bind_id; if (memcmp (tpdu_cr_rx->loc_tsap, only_tp0_loc_tsap, only_tp0_loc_tsap[0]+1)) #endif { TP_LOG_ERR0 ("TP-ERROR: received CR with invalid TSAP. Sending DR."); TP_LOGH_ERR (tpdu_cr_rx->loc_tsap[0], &tpdu_cr_rx->loc_tsap[1]); tpdu_dr.reason = TP_DR_ADDR_UNKNOWN; tp0_send_dr (&tpdu_dr); return; } /* Check for Transport Class 0. Don't allow any other. */ if (tpdu_cr_rx->preferred_class != 0) { TP_LOG_ERR1 ("TP-ERROR: received CR with invalid class %d. Sending DR.", tpdu_cr_rx->preferred_class); /* NOTE: this DR "reason" is not legal for Class 0, but caller */ /* proposed different class, so they should recognize this reason. */ tpdu_dr.reason = TP_DR_CLASS_UNSUPPORTED; /* illegal for TP0 but OK here*/ tp0_send_dr (&tpdu_dr); return; } /* Local Ref must equal 0. If not, it is protocol error. */ if (tpdu_cr_rx->loc_ref != 0) { TP_LOG_ERR0 ("TP-ERROR: received CR with invalid reference. Sending DR."); tpdu_dr.reason = TP_DR_NO_REASON; tp0_send_dr (&tpdu_dr); return; } /* Look for a position in "tp0_conn_arr" where state = TP_STATE_CLOSED */ tp_conn = &tp0_conn_arr [0]; for (conn_id = 0; conn_id < tp0_cfg.max_num_conns; conn_id++, tp_conn++) { if (tp_conn->state == TP_STATE_CLOSED) { tp0_conn_clean (tp_conn); /* Good time to clean up conn struct. */ inc_loc_ref_offset (tp_conn->loc_ref_offset); /* Save sock_info in "tp_conn". */ tp_conn->sock_info = tpdu_cr_rx->sock_info; /* Save tp_conn (as user_conn_id) in "sock_info". */ tp_conn->sock_info->user_conn_id = (ST_LONG) tp_conn; /* Copy the CR info to the tp_conn struct and modify it for the CC.*/ /* Most parameters we send back exactly as received (all except */ /* max_tpdu_len, loc_ref, cdt, udata_buf/len). */ /* NOTE: udata_buf/len not changed until tp0_accept. */ memcpy (&tp_conn->tpdu_cx, tpdu_cr_rx, sizeof (TPDU_CX)); tp_conn->tpdu_cx.max_tpdu_len_enc = min (tp0_cfg.max_tpdu_len_enc, tpdu_cr_rx->max_tpdu_len_enc); /* Save negotiated TPDU len in tp_conn. */ switch (tp_conn->tpdu_cx.max_tpdu_len_enc) { /* code for PDU size */ case TP_PDU_MAX_SIZE_128 : tp_conn->max_tpdu_len = 128; break; case TP_PDU_MAX_SIZE_256 : tp_conn->max_tpdu_len = 256; break; case TP_PDU_MAX_SIZE_512 : tp_conn->max_tpdu_len = 512; break; case TP_PDU_MAX_SIZE_1024 : tp_conn->max_tpdu_len = 1024; break; case TP_PDU_MAX_SIZE_2048 : tp_conn->max_tpdu_len = 2048; break; case TP_PDU_MAX_SIZE_4096 : tp_conn->max_tpdu_len = 4096; break; case TP_PDU_MAX_SIZE_8192 : tp_conn->max_tpdu_len = 8192; break; case TP_PDU_MAX_SIZE_65531: tp_conn->max_tpdu_len = 65531; break; default: TP_LOG_ERR0 ("TP-ERROR: received CR with illegal TPDU size. Sending DR."); tpdu_dr.reason = TP_DR_NO_REASON; tp0_send_dr (&tpdu_dr); return; } /* end "switch" */ tp_conn->tpdu_cx.loc_ref = calc_loc_ref (conn_id, tp_conn->loc_ref_offset); tp_conn->tpdu_cx.cdt = 0; /* CDT always 0 for Class 0 */ /* Set "tp_conn" parameters for new connection. */ tp_conn->rem_ref = tpdu_cr_rx->rem_ref; /* need for sending AKs */ tp_conn->state = TP_STATE_WFTRESP; /* Save TSAPs in TP0_CONN struct. */ memcpy (tp_conn->loc_tsap, tpdu_cr_rx->loc_tsap, tpdu_cr_rx->loc_tsap[0]+1); memcpy (tp_conn->rem_tsap, tpdu_cr_rx->rem_tsap, tpdu_cr_rx->rem_tsap[0]+1); tp4_connect_ind (tp0_user_bind_id, conn_id+MIN_TP0_CONN_ID, tpdu_cr_rx->loc_tsap, tpdu_cr_rx->rem_tsap, NULL, /* NSAP: not used */ tp_conn->sock_info->ip_addr, (ST_INT) tpdu_cr_rx->udata_len, tpdu_cr_rx->udata_buf); break; /* BREAK OUT OF LOOP. Only want 1 connection!!! */ } } /* end "for" loop */ if (conn_id >= tp0_cfg.max_num_conns) { /* Did not find an available conn_id. */ TP_LOG_ERR0 ("TP-ERROR: not enough resources for received CR. Sending DR."); tpdu_dr.reason = TP_DR_CONGESTION_AT_TSAP; /* legal for TP0 */ tp0_send_dr (&tpdu_dr); return; } return; }