244 lines
9.7 KiB
C
244 lines
9.7 KiB
C
|
|
/************************************************************************/
|
||
|
|
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
||
|
|
/************************************************************************/
|
||
|
|
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
||
|
|
/* 1997-2005 All Rights Reserved */
|
||
|
|
/* */
|
||
|
|
/* MODULE NAME : tp0callg.c */
|
||
|
|
/* PRODUCT(S) : Lean-T Stack */
|
||
|
|
/* */
|
||
|
|
/* MODULE DESCRIPTION : */
|
||
|
|
/* TP0 functions for handling of "Calling" side of connections. */
|
||
|
|
/* */
|
||
|
|
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
||
|
|
/* tp0_connect */
|
||
|
|
/* tp0_process_cc */
|
||
|
|
/* */
|
||
|
|
/* MODIFICATION LOG : */
|
||
|
|
/* Date Who Rev Comments */
|
||
|
|
/* -------- --- ------ ------------------------------------------- */
|
||
|
|
/* 11/12/08 MDE 15 Added tpdu_cc->sock_info->user_conn_id check */
|
||
|
|
/* 07/30/08 JRB 14 Use DR reason codes valid for TP0. */
|
||
|
|
/* 05/06/05 EJV 13 Added port param to np_connect_req call. */
|
||
|
|
/* 03/29/05 EJV 12 Added MMSEASE_MOSI support. */
|
||
|
|
/* 09/17/04 JRB 11 Chg tp0_connect to return connection ID. */
|
||
|
|
/* 02/02/04 JRB 10 tp0_connect: fix tp_type, bind_id checks. */
|
||
|
|
/* 07/30/03 EJV 09 Added encrypt_ctrl to tp0_connect. */
|
||
|
|
/* 04/07/03 JRB 08 Add SPDU_RX_NO_PREALLOCATE option. */
|
||
|
|
/* 06/20/02 JRB 07 Pass ip addr as ulong to np_connect_req. */
|
||
|
|
/* 06/08/99 JRB 06 Chg to support 1024 connections. */
|
||
|
|
/* 08/13/98 JRB 05 Lint cleanup. */
|
||
|
|
/* 06/17/98 JRB 04 Increment loc_ref_offset before encoding CR */
|
||
|
|
/* to avoid sending duplicate CR. */
|
||
|
|
/* 12/04/97 JRB 03 Don't chk TSAPs on CC (may not be sent). */
|
||
|
|
/* 09/25/97 JRB 02 Don't generate exception for invalid state. */
|
||
|
|
/* 08/01/97 JRB 01 Created (compatible with MMS-EASE 7.0). */
|
||
|
|
/************************************************************************/
|
||
|
|
static char *thisFileName = __FILE__; /* For TP4_EXCEPT and slog macros*/
|
||
|
|
|
||
|
|
#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"
|
||
|
|
|
||
|
|
/************************************************************************/
|
||
|
|
/* tp0_connect */
|
||
|
|
/* This function is called by the user to initiate a connect request to */
|
||
|
|
/* a remote node */
|
||
|
|
/* RETURNS: connection ID if successful, (-1) on error */
|
||
|
|
/* CRITICAL: connection ID = (conn_id+MIN_TP0_CONN_ID). Remember that */
|
||
|
|
/* this is hoe we distinguish between TP0 and TP4 connections. */
|
||
|
|
/************************************************************************/
|
||
|
|
|
||
|
|
ST_LONG tp0_connect (ST_LONG tp0_bind_id, ST_LONG user_conn_id,
|
||
|
|
TP4_ADDR *rem_tp4_addr,
|
||
|
|
ST_INT conndata_len,
|
||
|
|
char *conndata,
|
||
|
|
S_SEC_ENCRYPT_CTRL *encrypt_ctrl)
|
||
|
|
{
|
||
|
|
ST_UINT16 conn_id; /* index into "tp0_conn_arr" array. */
|
||
|
|
TP0_CONN *tp_conn;
|
||
|
|
TPDU_CX *tpdu_cr;
|
||
|
|
ST_UCHAR *tp0_loc_tsap;
|
||
|
|
|
||
|
|
if (rem_tp4_addr->tp_type == TP_TYPE_TCP)
|
||
|
|
{
|
||
|
|
#if defined(MMSEASE_MOSI)
|
||
|
|
if (tp0_check_bind_id (tp0_bind_id, &tp0_loc_tsap) != SD_SUCCESS)
|
||
|
|
#else
|
||
|
|
tp0_loc_tsap = only_tp0_loc_tsap;
|
||
|
|
if (tp0_bind_id != only_tp0_bind_id)
|
||
|
|
#endif
|
||
|
|
{
|
||
|
|
TP_LOG_ERR1 ("tp0_connect: bind id %ld invalid. TCP must be enabled in config.", tp0_bind_id);
|
||
|
|
return (-1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else /* Transport type not TP0, this is error. */
|
||
|
|
{
|
||
|
|
TP_LOG_ERR0 ("tp0_connect: invalid transport type");
|
||
|
|
return (-1);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (rem_tp4_addr->tp4_sel_len > MAX_TSEL_LEN)
|
||
|
|
{
|
||
|
|
TP4_EXCEPT (); /* If this happens, user code is invalid. */
|
||
|
|
return (-1);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Look for available connection. */
|
||
|
|
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)
|
||
|
|
break; /* Found one!! "tp_conn" points to it now. */
|
||
|
|
} /* end "for" */
|
||
|
|
if (conn_id >= tp0_cfg.max_num_conns)
|
||
|
|
{ /* Didn't find one!! */
|
||
|
|
TP_LOG_ERR0 ("TP-ERROR: tp0_connect: all connections in use");
|
||
|
|
return (-1);
|
||
|
|
}
|
||
|
|
/* "tp_conn" now points to a connection in TP_STATE_CLOSED state. */
|
||
|
|
tp0_conn_clean (tp_conn); /* Good time to clean up conn struct. */
|
||
|
|
|
||
|
|
/* Increment "loc_ref_offset" to avoid duplicate CR. */
|
||
|
|
inc_loc_ref_offset (tp_conn->loc_ref_offset);
|
||
|
|
|
||
|
|
/* Set "tpdu_cr" pointing to "tp_conn->tpdu_cx" and fill in. */
|
||
|
|
/* Info stored in "tp_conn" in case retransmissions needed. */
|
||
|
|
tpdu_cr = &tp_conn->tpdu_cx;
|
||
|
|
memcpy (tpdu_cr->loc_tsap, tp0_loc_tsap, tp0_loc_tsap [0]+1);
|
||
|
|
tpdu_cr->rem_tsap [0] = (ST_UCHAR) rem_tp4_addr->tp4_sel_len;
|
||
|
|
memcpy (&tpdu_cr->rem_tsap [1], rem_tp4_addr->tp4_sel, rem_tp4_addr->tp4_sel_len);
|
||
|
|
tpdu_cr->loc_ref = calc_loc_ref (conn_id, tp_conn->loc_ref_offset);
|
||
|
|
tpdu_cr->rem_ref = 0;
|
||
|
|
tpdu_cr->max_tpdu_len_enc = tp0_cfg.max_tpdu_len_enc;
|
||
|
|
tpdu_cr->preferred_class = 0;
|
||
|
|
tpdu_cr->cdt = 0;
|
||
|
|
tpdu_cr->udata_len = min ((ST_UINT16) conndata_len, TP_MAX_CONN_UDATA);
|
||
|
|
memcpy (tpdu_cr->udata_buf, conndata, tpdu_cr->udata_len);
|
||
|
|
|
||
|
|
/* Set state before calling np_connect_req (may complete immediately).*/
|
||
|
|
tp_conn->user_conn_id = user_conn_id; /* Save User's ID for confirm. */
|
||
|
|
tp_conn->state = TP_STATE_WFNC;
|
||
|
|
if ((tp_conn->sock_info = np_connect_req ((ST_LONG) tp_conn, rem_tp4_addr->netAddr.ip,
|
||
|
|
rem_tp4_addr->port, encrypt_ctrl)) == NULL)
|
||
|
|
{
|
||
|
|
tp_conn->state = TP_STATE_CLOSED; /* CRITICAL: so tp_conn can be reused.*/
|
||
|
|
#if defined(SPDU_RX_NO_PREALLOCATE)
|
||
|
|
M_FREE (MSMEM_STARTUP, tp_conn->spdu_rx.spdu_ptr);
|
||
|
|
#endif
|
||
|
|
return (-1); /* Network connect failed immediately. */
|
||
|
|
}
|
||
|
|
|
||
|
|
/* CRITICAL: For TP0, connection ID = (conn_id+MIN_TP0_CONN_ID). */
|
||
|
|
return (conn_id+MIN_TP0_CONN_ID);
|
||
|
|
}
|
||
|
|
|
||
|
|
/************************************************************************/
|
||
|
|
/* tp0_process_cc */
|
||
|
|
/************************************************************************/
|
||
|
|
ST_VOID tp0_process_cc (TPDU_CX *tpdu_cc)
|
||
|
|
{
|
||
|
|
ST_ULONG 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_INT unacceptable_cc = SD_FALSE;
|
||
|
|
ST_INT reason;
|
||
|
|
|
||
|
|
|
||
|
|
/* Fill in TPDU_DR struct in case DR needs to be sent. */
|
||
|
|
/* Do not fill in "reason" yet. */
|
||
|
|
tpdu_dr.loc_ref = tpdu_cc->loc_ref;
|
||
|
|
tpdu_dr.rem_ref = tpdu_cc->rem_ref;
|
||
|
|
tpdu_dr.sock_info = tpdu_cc->sock_info;
|
||
|
|
|
||
|
|
/* Check connection ID. */
|
||
|
|
if (tpdu_cc->sock_info->user_conn_id == INVALID_CONN_ID)
|
||
|
|
{
|
||
|
|
/* Invalid ID means CR has not been sent, so this CC is unexpected. */
|
||
|
|
/* CC most likely received from "abnormal" application. */
|
||
|
|
TP_LOG_ERR0 ("TP-ERROR: tp0_process_cc: Invalid tp_conn");
|
||
|
|
/* May be intentional attack, so disconnect immediately. */
|
||
|
|
np_disconnect_req (tpdu_cc->sock_info);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Find the correct "tp_conn". It should have been saved in sock_info.*/
|
||
|
|
tp_conn = (TP0_CONN *) tpdu_cc->sock_info->user_conn_id;
|
||
|
|
|
||
|
|
|
||
|
|
conn_id = tp_conn - tp0_conn_arr; /* conn_id = index into array */
|
||
|
|
|
||
|
|
switch (tp_conn->state)
|
||
|
|
{
|
||
|
|
case TP_STATE_CLOSED:
|
||
|
|
tpdu_dr.reason = TP_DR_NO_SESSION; /* We're not trying to connect*/
|
||
|
|
tp0_send_dr (&tpdu_dr);
|
||
|
|
break;
|
||
|
|
case TP_STATE_WFCC:
|
||
|
|
/* Check for Transport Class 0. Don't allow any other. */
|
||
|
|
if (tpdu_cc->preferred_class != 0)
|
||
|
|
{
|
||
|
|
unacceptable_cc = SD_TRUE;
|
||
|
|
}
|
||
|
|
/* Save negotiated TPDU len in tp_conn->max_tpdu_len. */
|
||
|
|
switch (tpdu_cc->max_tpdu_len_enc)
|
||
|
|
{
|
||
|
|
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 to ILLEGAL value (i.e. 0) */
|
||
|
|
default: tp_conn->max_tpdu_len = 0; break;
|
||
|
|
} /* end "switch" */
|
||
|
|
/* If max_tpdu_len ILLEGAL or ">" proposed, this is protocol error.*/
|
||
|
|
if (tp_conn->max_tpdu_len == 0 || /* ILLEGAL */
|
||
|
|
tp_conn->max_tpdu_len > tp0_cfg.max_tpdu_len) /* ">" proposed */
|
||
|
|
{
|
||
|
|
tpdu_dr.reason = TP_DR_NO_REASON;
|
||
|
|
unacceptable_cc = SD_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (unacceptable_cc)
|
||
|
|
{ /* UN-ACCEPTABLE CLASS 0 CC TPDU. */
|
||
|
|
reason = 0xff; /* Local user error */
|
||
|
|
tp4_disconnect_ind (tp_conn->user_conn_id, reason,
|
||
|
|
0, NULL); /* No user data passed up. */
|
||
|
|
np_disconnect_req (tp_conn->sock_info);
|
||
|
|
tp_conn->state = TP_STATE_CLOSED;
|
||
|
|
#if defined(SPDU_RX_NO_PREALLOCATE)
|
||
|
|
M_FREE (MSMEM_STARTUP, tp_conn->spdu_rx.spdu_ptr);
|
||
|
|
#endif
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{ /* ACCEPTABLE CLASS 0 CC TPDU. */
|
||
|
|
/* Save "rem_ref" in "tp_conn". */
|
||
|
|
tp_conn->rem_ref = tpdu_cc->rem_ref;
|
||
|
|
|
||
|
|
/* CRITICAL: set state before tp4_connect_cnf because may */
|
||
|
|
/* send first Transport data from within tp4_connect_cnf. */
|
||
|
|
tp_conn->state = TP_STATE_OPEN;
|
||
|
|
tp4_connect_cnf (tp_conn->user_conn_id, conn_id+MIN_TP0_CONN_ID,
|
||
|
|
(ST_UINT) tpdu_cc->udata_len, tpdu_cc->udata_buf);
|
||
|
|
tp_conn->state = TP_STATE_OPEN;
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
|
||
|
|
default:
|
||
|
|
TP_LOG_ERR1 ("TP-ERROR: invalid state (%d) for received CC. Ignored.",
|
||
|
|
tp_conn->state);
|
||
|
|
break;
|
||
|
|
} /* end "switch" */
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|