original files of m241
This commit is contained in:
@@ -0,0 +1,983 @@
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
* INTERPEAK SOURCE FILE
|
||||
*
|
||||
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipl2tp_data.c,v $ $Revision: 1.7.14.1 $
|
||||
* $Source: /home/interpeak/CVSRoot/ipl2tp/src/ipl2tp_data.c,v $
|
||||
* $Author: hxu0 $
|
||||
* $State: Exp $ $Locker: $
|
||||
*
|
||||
* INTERPEAK_COPYRIGHT_STRING
|
||||
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 1 DESCRIPTION
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 2 CONFIGURATION
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 3 INCLUDE FILES
|
||||
****************************************************************************
|
||||
*/
|
||||
#include "ipl2tp_h.h"
|
||||
#include "ipl2tp_avp.h"
|
||||
#include "ipl2tp_data.h"
|
||||
#include "ipl2tp_state.h"
|
||||
#include "ipl2tp_attr.h"
|
||||
#include "ipl2tp_attr_h.h"
|
||||
#include "ipl2tp_message.h"
|
||||
|
||||
#include "ipl2tp_v2.h"
|
||||
#include "ipl2tp_v3.h"
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 4 DEFINES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 5 TYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 6 EXTERN PROTOTYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 7 LOCAL PROTOTYPES
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 8 DATA
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
IP_PUBLIC Ipl2tp_context ipl2tp;
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 9 STATIC FUNCTIONS
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_data_key_hash
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_STATIC unsigned
|
||||
ipl2tp_data_key_hash(Ipl2tp_key *key)
|
||||
{
|
||||
/* Hash the session ID */
|
||||
return ipcom_hash_update(key,
|
||||
sizeof(*key),
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_data_obj_hash_session
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_STATIC unsigned
|
||||
ipl2tp_data_obj_hash_session(Ipl2tp_session *session)
|
||||
{
|
||||
/* Hash the version & session ID */
|
||||
return ipcom_hash_update(&session->local.key,
|
||||
sizeof(session->local.key),
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_data_cmp_session
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_STATIC Ip_bool
|
||||
ipl2tp_data_cmp_session(Ipl2tp_session *session,
|
||||
Ipl2tp_key *key)
|
||||
{
|
||||
/* Version & ID must match */
|
||||
if (session->local.key.version == key->version &&
|
||||
session->local.key.ident == key->ident)
|
||||
return IP_TRUE;
|
||||
|
||||
return IP_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_data_obj_hash_tunnel
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_STATIC unsigned
|
||||
ipl2tp_data_obj_hash_tunnel(Ipl2tp_tunnel *tunnel)
|
||||
{
|
||||
/* Hash the tunnel ID */
|
||||
return ipcom_hash_update(&tunnel->local.key,
|
||||
sizeof(tunnel->local.key),
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_data_cmp_tunnel
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_STATIC Ip_bool
|
||||
ipl2tp_data_cmp_tunnel(Ipl2tp_tunnel *tunnel,
|
||||
Ipl2tp_key *key)
|
||||
{
|
||||
/* Version & ID must match */
|
||||
if (tunnel->local.key.version == key->version &&
|
||||
tunnel->local.key.ident == key->ident)
|
||||
return IP_TRUE;
|
||||
|
||||
return IP_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_data_obj_hash_addr
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_STATIC unsigned
|
||||
ipl2tp_data_obj_hash_addr(Ipl2tp_tunnel *tunnel)
|
||||
{
|
||||
/* Hash the version first */
|
||||
unsigned val = ipcom_hash_update(&tunnel->local.key.version,
|
||||
sizeof(tunnel->local.key.version),
|
||||
0);
|
||||
|
||||
/* Hash the tunnel ID */
|
||||
return ipcom_hash_update(&tunnel->remote.addr,
|
||||
tunnel->remote.addr.sa.sa_len,
|
||||
val);
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_data_key_hash_addr
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_STATIC unsigned
|
||||
ipl2tp_data_key_hash_addr(Ipl2tp_addr *key)
|
||||
{
|
||||
/* Hash the version first */
|
||||
unsigned val = ipcom_hash_update(&key->key.version,
|
||||
sizeof(key->key.version),
|
||||
0);
|
||||
|
||||
/* Hash the address */
|
||||
return ipcom_hash_update(key->addr,
|
||||
key->addr->sa.sa_len,
|
||||
val);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_data_cmp_addr
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_STATIC Ip_bool
|
||||
ipl2tp_data_cmp_addr(Ipl2tp_tunnel *tunnel,
|
||||
Ipl2tp_addr *key)
|
||||
{
|
||||
/* Version & addr must match; Tunnel must not be teardown. */
|
||||
if (tunnel->local.key.version == key->key.version &&
|
||||
IPL2TP_SOCKADDR_EQUAL(&tunnel->remote.addr.sa, &key->addr->sa) &&
|
||||
tunnel->state > IPL2TP_TSTATE_TEARDOWN)
|
||||
return IP_TRUE;
|
||||
|
||||
return IP_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_data_obj_hash_tunnel_assigned
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_STATIC unsigned
|
||||
ipl2tp_data_obj_hash_tunnel_assigned(Ipl2tp_tunnel *tunnel)
|
||||
{
|
||||
/* Hash the addr & version first */
|
||||
unsigned val = ipl2tp_data_obj_hash_addr(tunnel);
|
||||
|
||||
/* Hash the tunnel ID */
|
||||
return ipcom_hash_update(&tunnel->remote.key.ident,
|
||||
sizeof(tunnel->remote.key.ident),
|
||||
val);
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_data_key_hash_tunnel_assigned
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_STATIC unsigned
|
||||
ipl2tp_data_key_hash_tunnel_assigned(Ipl2tp_addr *key)
|
||||
{
|
||||
/* Hash the addr & version first */
|
||||
unsigned val = ipl2tp_data_key_hash_addr(key);
|
||||
|
||||
/* Hash the session ID */
|
||||
return ipcom_hash_update(&key->key.ident,
|
||||
sizeof(key->key.ident),
|
||||
val);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_data_cmp_tunnel_assigned
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_STATIC Ip_bool
|
||||
ipl2tp_data_cmp_tunnel_assigned(Ipl2tp_tunnel *tunnel,
|
||||
Ipl2tp_addr *key)
|
||||
{
|
||||
/* Addr, Version & ID must match */
|
||||
if (ipl2tp_data_cmp_addr(tunnel, key) &&
|
||||
tunnel->remote.key.ident == key->key.ident)
|
||||
return IP_TRUE;
|
||||
|
||||
return IP_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_data_obj_hash_tunnel_ifindex
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_STATIC unsigned
|
||||
ipl2tp_data_obj_hash_tunnel_ifindex(Ipl2tp_tunnel *tunnel)
|
||||
{
|
||||
/* Hash the tunnel ifindex ID */
|
||||
return ipcom_hash_update(&tunnel->attr.ifindex,
|
||||
sizeof(tunnel->attr.ifindex),
|
||||
0);
|
||||
}
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_data_key_hash_tunnel_assigned
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_STATIC unsigned
|
||||
ipl2tp_data_key_hash_tunnel_ifindex(Ip_u32 *ifindex)
|
||||
{
|
||||
/* Hash the tunnel ifindex ID */
|
||||
return ipcom_hash_update(ifindex,
|
||||
sizeof(*ifindex),
|
||||
0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_data_tunnel_close
|
||||
*===========================================================================
|
||||
* Description: Close down a tunnel.
|
||||
* Parameters: tunnel - The tunnel.
|
||||
* data - Opaque data (UNUSED)
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_STATIC void
|
||||
ipl2tp_data_tunnel_close(Ipl2tp_tunnel *tunnel,
|
||||
void *data)
|
||||
{
|
||||
IPL2TP_UNUSED(data);
|
||||
|
||||
/* Do teardown */
|
||||
ipl2tp_state_tunnel_teardown(tunnel);
|
||||
ipl2tp_tunnel_delete(tunnel);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_data_cmp_tunnel_assigned
|
||||
*===========================================================================
|
||||
* Description:
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*/
|
||||
IP_STATIC Ip_bool
|
||||
ipl2tp_data_cmp_tunnel_ifindex(Ipl2tp_tunnel *tunnel,
|
||||
Ip_u32 *ifindex)
|
||||
{
|
||||
/* The same? */
|
||||
return tunnel->attr.ifindex == *ifindex;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 10 GLOBAL FUNCTIONS
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_data_init
|
||||
*===========================================================================
|
||||
* Description: Init the global data object
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_GLOBAL Ipl2tp_status
|
||||
ipl2tp_data_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
ipcom_memset(&ipl2tp, 0, sizeof(ipl2tp));
|
||||
|
||||
#ifdef IPL2TP_USE_MUTEX
|
||||
/* Create synchronization mutex */
|
||||
(void)ipcom_mutex_create(&ipl2tp.mutex);
|
||||
#endif
|
||||
|
||||
/* Init other lists */
|
||||
ipcom_list_init(&ipl2tp.tunnel.v2.tunnels);
|
||||
ipcom_list_init(&ipl2tp.tunnel.v3.tunnels);
|
||||
ipcom_list_init(&ipl2tp.tunnel.free_list);
|
||||
ipcom_list_init(&ipl2tp.session.free_list);
|
||||
|
||||
/* The basic id tunnel hash */
|
||||
ipl2tp.tunnel.hash_id = ipcom_hash_new((Ipcom_hash_obj_func)ipl2tp_data_obj_hash_tunnel,
|
||||
(Ipcom_hash_key_func)ipl2tp_data_key_hash,
|
||||
(Ipcom_hash_cmp_func)ipl2tp_data_cmp_tunnel);
|
||||
|
||||
/* The basic remote id tunnel hash */
|
||||
ipl2tp.tunnel.hash_remote_id = ipcom_hash_new((Ipcom_hash_obj_func)ipl2tp_data_obj_hash_tunnel_assigned,
|
||||
(Ipcom_hash_key_func)ipl2tp_data_key_hash_tunnel_assigned,
|
||||
(Ipcom_hash_cmp_func)ipl2tp_data_cmp_tunnel_assigned);
|
||||
|
||||
/* The basic remote id tunnel hash */
|
||||
ipl2tp.tunnel.hash_ifindex = ipcom_hash_new((Ipcom_hash_obj_func)ipl2tp_data_obj_hash_tunnel_ifindex,
|
||||
(Ipcom_hash_key_func)ipl2tp_data_key_hash_tunnel_ifindex,
|
||||
(Ipcom_hash_cmp_func)ipl2tp_data_cmp_tunnel_ifindex);
|
||||
|
||||
/* The address tunnel hash */
|
||||
ipl2tp.tunnel.hash_remote_addr = ipcom_hash_new((Ipcom_hash_obj_func)ipl2tp_data_obj_hash_addr,
|
||||
(Ipcom_hash_key_func)ipl2tp_data_key_hash_addr,
|
||||
(Ipcom_hash_cmp_func)ipl2tp_data_cmp_addr);
|
||||
|
||||
/* The session hash */
|
||||
ipl2tp.session.hash_id = ipcom_hash_new((Ipcom_hash_obj_func)ipl2tp_data_obj_hash_session,
|
||||
(Ipcom_hash_key_func)ipl2tp_data_key_hash,
|
||||
(Ipcom_hash_cmp_func)ipl2tp_data_cmp_session);
|
||||
|
||||
/* Did they succeed? */
|
||||
if (ipl2tp.tunnel.hash_id == IP_NULL || ipl2tp.tunnel.hash_remote_addr == IP_NULL ||
|
||||
ipl2tp.tunnel.hash_remote_addr == IP_NULL || ipl2tp.tunnel.hash_ifindex == IP_NULL ||
|
||||
ipl2tp.session.hash_id == IP_NULL)
|
||||
{
|
||||
ipl2tp_data_exit();
|
||||
return IPL2TP_STATUS_NOMEM;
|
||||
}
|
||||
|
||||
/* Tunnel and session IDs start at 1 */
|
||||
ipl2tp.tunnel.v2.ident = 1;
|
||||
ipl2tp.tunnel.v3.ident = 1;
|
||||
ipl2tp.session.v2.ident = 1;
|
||||
ipl2tp.session.v3.ident = 1;
|
||||
|
||||
for (i = 1; i <= IPL2TP_PREALLOCATED_TUNNEL_NO; i++)
|
||||
{
|
||||
Ipl2tp_tunnel *tunnel;
|
||||
if ((tunnel = ipl2tp_tunnel_malloc()) == IP_NULL)
|
||||
{
|
||||
ipl2tp_data_exit();
|
||||
return IPL2TP_STATUS_NOMEM;
|
||||
}
|
||||
|
||||
ipcom_list_insert_first(&ipl2tp.tunnel.free_list,
|
||||
&tunnel->head);
|
||||
}
|
||||
|
||||
for (i = 1; i <= IPL2TP_PREALLOCATED_SESSION_NO; i++)
|
||||
{
|
||||
Ipl2tp_session *session;
|
||||
if ((session = ipl2tp_session_malloc()) == IP_NULL)
|
||||
{
|
||||
IPCOM_LOG1(ERR,
|
||||
"%s: Out of memory for session descriptors",
|
||||
ipl2tp_versions[0]);
|
||||
ipl2tp_data_exit();
|
||||
return IPL2TP_STATUS_NOMEM;
|
||||
}
|
||||
|
||||
ipcom_list_insert_first(&ipl2tp.session.free_list,
|
||||
&session->head);
|
||||
}
|
||||
|
||||
|
||||
/* Serial number starts at 1 */
|
||||
ipl2tp.call_serial_number = 1;
|
||||
|
||||
/* Set default attributes */
|
||||
ipcom_strncpy(ipl2tp.host_name, IPL2TP_HOST_NAME, IPL2TP_MAX_HOST_NAME_SIZE);
|
||||
ipl2tp.first_retransmit_sec = IPL2TP_FIRST_RETRANSMIT_SEC;
|
||||
ipl2tp.tunnel_zombie_sec = IPL2TP_TUNNEL_ZOMBIE_SEC;
|
||||
ipl2tp.hello_tick_sec = IPL2TP_HELLO_TICK_SEC;
|
||||
ipl2tp.establish_timeout_sec = IPL2TP_ESTABLISH_TIMEOUT_SEC;
|
||||
ipl2tp.open_exclusive = IPL2TP_OPEN_EXCLUSIVE;
|
||||
ipl2tp.admin_state = IPL2TP_MIB_ENABLED;
|
||||
ipl2tp.drain_tunnels = IPL2TP_MIB_NO;
|
||||
ipl2tp.enable_outgoing = IPL2TP_MIB_DISABLED;
|
||||
|
||||
ipl2tp.enable_v3 = IPL2TP_MIB_DISABLED;
|
||||
ipl2tp.enable_v2 = IPL2TP_MIB_DISABLED;
|
||||
ipl2tp.close_unused_tunnels = IPL2TP_MIB_YES;
|
||||
|
||||
/* Set default tunnel attributes */
|
||||
ipl2tp.tunnel.v2.attr.hello_interval_sec = IPL2TP_HELLO_INTERVAL_SEC;
|
||||
ipl2tp.tunnel.v2.attr.max_retransmit = IPL2TP_MAX_RETRANSMIT;
|
||||
ipl2tp.tunnel.v2.attr.max_backoff_sec = IPL2TP_MAX_BACKOFF_SEC;
|
||||
ipl2tp.tunnel.v2.attr.receive_window_size = IPL2TP_RECEIVE_WINDOW_SIZE;
|
||||
ipl2tp.tunnel.v2.attr.framing_capabilities = IPL2TP_MIB_FRAMING_NONE;
|
||||
ipl2tp.tunnel.v2.attr.authentication = IPL2TP_MIB_AUTH_NONE;
|
||||
ipl2tp.tunnel.v2.attr.sequencing = IPL2TP_MIB_NEVER;
|
||||
ipl2tp.tunnel.v2.attr.hide_avp = IPL2TP_MIB_NO;
|
||||
|
||||
ipl2tp.tunnel.v3.attr.hello_interval_sec = IPL2TP_HELLO_INTERVAL_SEC;
|
||||
ipl2tp.tunnel.v3.attr.max_retransmit = IPL2TP_MAX_RETRANSMIT;
|
||||
ipl2tp.tunnel.v3.attr.max_backoff_sec = IPL2TP_MAX_BACKOFF_SEC;
|
||||
ipl2tp.tunnel.v3.attr.receive_window_size = IPL2TP_RECEIVE_WINDOW_SIZE;
|
||||
ipl2tp.tunnel.v3.attr.framing_capabilities = IPL2TP_MIB_FRAMING_NONE;
|
||||
ipl2tp.tunnel.v3.attr.authentication = IPL2TP_MIB_AUTH_NONE;
|
||||
ipl2tp.tunnel.v3.attr.sequencing = IPL2TP_MIB_NEVER;
|
||||
ipl2tp.tunnel.v3.attr.hide_avp = IPL2TP_MIB_NO;
|
||||
|
||||
/* Set default session attributes */
|
||||
ipl2tp.session.v2.attr.framing_type = IPL2TP_MIB_FRAMING_NONE;
|
||||
|
||||
ipl2tp.session.v3.attr.circuit_status = IPL2TP_MIB_DOWN;
|
||||
ipl2tp.session.v3.attr.l2_out_of_order_reset = IPL2TP_L2_OUT_OF_ORDER_RESET;
|
||||
|
||||
/* Mark as initialized */
|
||||
ipl2tp.magic = IPL2TP_MAGIC;
|
||||
|
||||
return IPL2TP_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_data_exit
|
||||
*===========================================================================
|
||||
* Description: Free any resources allocated by ipl2tp_data_init.
|
||||
* Parameters:
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_GLOBAL void
|
||||
ipl2tp_data_exit(void)
|
||||
{
|
||||
Ipl2tp_tunnel *tunnel;
|
||||
Ipl2tp_session *session;
|
||||
|
||||
#ifdef IPL2TP_USE_MUTEX
|
||||
ipcom_mutex_delete(&ipl2tp.mutex);
|
||||
#endif
|
||||
|
||||
/* Close down the tunnels & sessions */
|
||||
ipcom_hash_for_each(ipl2tp.tunnel.hash_id,
|
||||
(Ipcom_hash_foreach_cb_func)ipl2tp_data_tunnel_close,
|
||||
IP_NULL);
|
||||
|
||||
/* Grab the first session */
|
||||
while ((session = IPCOM_LIST_FIRST(&ipl2tp.session.free_list)) != IP_NULL)
|
||||
{
|
||||
/* Remove it from the queue */
|
||||
ipcom_list_remove(&session->head);
|
||||
ipcom_free(session);
|
||||
}
|
||||
|
||||
/* Grab the first session */
|
||||
while ((tunnel = IPCOM_LIST_FIRST(&ipl2tp.tunnel.free_list)) != IP_NULL)
|
||||
{
|
||||
/* Remove it from the queue */
|
||||
ipcom_list_remove(&tunnel->head);
|
||||
ipcom_free(tunnel);
|
||||
}
|
||||
|
||||
/* Delete the hashes */
|
||||
if (ipl2tp.tunnel.hash_remote_addr)
|
||||
ipcom_hash_delete(ipl2tp.tunnel.hash_remote_addr);
|
||||
if (ipl2tp.tunnel.hash_remote_id)
|
||||
ipcom_hash_delete(ipl2tp.tunnel.hash_remote_id);
|
||||
if (ipl2tp.tunnel.hash_id)
|
||||
ipcom_hash_delete(ipl2tp.tunnel.hash_id);
|
||||
if (ipl2tp.tunnel.hash_ifindex)
|
||||
ipcom_hash_delete(ipl2tp.tunnel.hash_ifindex);
|
||||
if (ipl2tp.session.hash_id)
|
||||
ipcom_hash_delete(ipl2tp.session.hash_id);
|
||||
|
||||
ipcom_memset(&ipl2tp, 0, sizeof(ipl2tp));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_tunnel_new
|
||||
*===========================================================================
|
||||
* Description: Retrieve a tunnel descriptor.
|
||||
* Parameters: version - Version of the tunnel.
|
||||
* addr - The address of the peer.
|
||||
* Returns: A new tunnel.
|
||||
*
|
||||
*/
|
||||
IP_GLOBAL Ipl2tp_tunnel *
|
||||
ipl2tp_tunnel_new(Ipl2tp_version version,
|
||||
union Ip_sockaddr_union *addr)
|
||||
{
|
||||
Ipl2tp_tunnel *t;
|
||||
|
||||
/* Try to recycle an old descriptor */
|
||||
if ((t = IPCOM_LIST_FIRST(&ipl2tp.tunnel.free_list)) != IP_NULL)
|
||||
{
|
||||
ipcom_list_remove(&t->head);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = ipl2tp_tunnel_malloc();
|
||||
}
|
||||
|
||||
/* Initialize */
|
||||
if (t != IP_NULL)
|
||||
{
|
||||
/*lint -e419*/
|
||||
ipcom_memset(t, 0, sizeof(*t));
|
||||
ipcom_list_init(&t->session_list);
|
||||
ipcom_list_init(&t->message_list);
|
||||
IPCOM_TMO_INIT(&t->timer);
|
||||
|
||||
t->state = IPL2TP_TSTATE_IDLE;
|
||||
t->cwnd = 1;
|
||||
t->drain_tunnel = IPL2TP_MIB_NO;
|
||||
|
||||
ipl2tp.open_tunnels++;
|
||||
|
||||
/* Copy the address */
|
||||
ipcom_memset(&t->remote.addr, 0, sizeof(t->remote.addr));
|
||||
ipcom_memcpy(&t->remote.addr, addr, addr->sa.sa_len);
|
||||
|
||||
t->common.receive_window_size = IPL2TP_RECEIVE_WINDOW_SIZE;
|
||||
t->ssthresh = t->common.receive_window_size;
|
||||
|
||||
/* Create logheader and setup callback table*/
|
||||
switch (version)
|
||||
{
|
||||
case IPL2TP_VERSION_L2TPV2:
|
||||
ipl2tp_v2_tunnel_init(t);
|
||||
break;
|
||||
case IPL2TP_VERSION_L2TPV3:
|
||||
ipl2tp_v3_tunnel_init(t);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Add it to the ID and ADDR table */
|
||||
if ((ipcom_hash_add(ipl2tp.tunnel.hash_id, t) != IPCOM_SUCCESS) ||
|
||||
(ipcom_hash_add(ipl2tp.tunnel.hash_remote_addr, t) != IPCOM_SUCCESS))
|
||||
{
|
||||
IPCOM_LOG1(ERR,
|
||||
"%s: Unable to add a new tunnel",
|
||||
ipl2tp_versions[0]);
|
||||
ipcom_free (t);
|
||||
return IP_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_session_new
|
||||
*===========================================================================
|
||||
* Description: Retrieve a session descriptor
|
||||
* Parameters: tunnel - The tunnel this session belongs to.
|
||||
* cookie - Cookie for identification of the session.
|
||||
* cookie_size - Size of the cookie [max 8].
|
||||
* Returns: The session
|
||||
*
|
||||
*/
|
||||
IP_GLOBAL Ipl2tp_session *
|
||||
ipl2tp_session_new(Ipl2tp_tunnel *tunnel,
|
||||
void *cookie,
|
||||
Ip_u8 cookie_size)
|
||||
{
|
||||
Ipl2tp_session *s;
|
||||
|
||||
/* Try to recycle an old descriptor */
|
||||
if ((s = IPCOM_LIST_FIRST(&ipl2tp.session.free_list)) != IP_NULL)
|
||||
{
|
||||
ipcom_list_remove(&s->head);
|
||||
}
|
||||
else
|
||||
{
|
||||
s = ipl2tp_session_malloc();
|
||||
}
|
||||
|
||||
/* Initialize */
|
||||
if (s != IP_NULL)
|
||||
{
|
||||
ipcom_memset(s, 0, sizeof(*s));
|
||||
IPCOM_TMO_INIT(&s->timer);
|
||||
|
||||
/* */
|
||||
s->state = IPL2TP_SSTATE_IDLE;
|
||||
s->common.call_serial_number = ipl2tp.call_serial_number++;
|
||||
|
||||
/* Grab next session ID based on version */
|
||||
|
||||
if (cookie_size)
|
||||
{
|
||||
ipl2tp_util_vector_create(&s->local.cookie,
|
||||
cookie,
|
||||
cookie_size);
|
||||
}
|
||||
|
||||
s->tunnel = tunnel;
|
||||
|
||||
/* Initialize the tunnel */
|
||||
IPL2TP_TUNNEL_SESSION_INIT(s);
|
||||
|
||||
/* Set the tunnel ownership */
|
||||
ipcom_list_insert_last(&tunnel->session_list, &s->head);
|
||||
if (ipcom_hash_add(ipl2tp.session.hash_id, s) != IPCOM_SUCCESS)
|
||||
{
|
||||
IPCOM_LOG1(ERR,
|
||||
"%s: Unable to add a new session",
|
||||
ipl2tp_versions[0]);
|
||||
ipcom_free(s);
|
||||
return IP_NULL;
|
||||
}
|
||||
|
||||
ipl2tp.open_sessions++;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_tunnel_malloc
|
||||
*===========================================================================
|
||||
* Description: Allocate a new tunnel descriptor.
|
||||
* Parameters:
|
||||
* Returns: The tunnel.
|
||||
*
|
||||
*/
|
||||
IP_GLOBAL Ipl2tp_tunnel *
|
||||
ipl2tp_tunnel_malloc(void)
|
||||
{
|
||||
Ipl2tp_tunnel *t;
|
||||
|
||||
/* Limit the amount of tunnels */
|
||||
if (ipl2tp.tunnel.total > IPL2TP_TUNNEL_MAX)
|
||||
{
|
||||
IPCOM_LOG1(ERR,
|
||||
"%s: Max no of tunnels created",
|
||||
ipl2tp_versions[0]);
|
||||
return IP_NULL;
|
||||
}
|
||||
|
||||
/* Try to get new memory */
|
||||
if ((t = ipcom_malloc(sizeof(*t))) == IP_NULL)
|
||||
{
|
||||
IPCOM_LOG1(ERR,
|
||||
"%s: Out of memory for tunnel descriptor",
|
||||
ipl2tp_versions[0]);
|
||||
return IP_NULL;
|
||||
}
|
||||
|
||||
/* Increase the number of tunnels */
|
||||
ipl2tp.tunnel.total++;
|
||||
|
||||
/* Initialize state and ID */
|
||||
t->state = IPL2TP_TSTATE_VOID;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_session_malloc
|
||||
*===========================================================================
|
||||
* Description: Allocate a new session descriptor.
|
||||
* Parameters:
|
||||
* Returns: The session.
|
||||
*
|
||||
*/
|
||||
IP_GLOBAL Ipl2tp_session *
|
||||
ipl2tp_session_malloc(void)
|
||||
{
|
||||
Ipl2tp_session *s;
|
||||
|
||||
/* Limit the amount of sessions */
|
||||
if (ipl2tp.session.total > IPL2TP_SESSION_MAX)
|
||||
{
|
||||
IPCOM_LOG1(ERR,
|
||||
"%s: Max no of sessions created",
|
||||
ipl2tp_versions[0]);
|
||||
return IP_NULL;
|
||||
}
|
||||
|
||||
/* Try to get new memory */
|
||||
if ((s = ipcom_malloc(sizeof(*s))) == IP_NULL)
|
||||
{
|
||||
IPCOM_LOG1(ERR,
|
||||
"%s: Out of memory for sesssion descriptor",
|
||||
ipl2tp_versions[0]);
|
||||
return IP_NULL;
|
||||
}
|
||||
|
||||
/* One more session */
|
||||
ipl2tp.session.total++;
|
||||
|
||||
/* Initialize state and ID */
|
||||
s->state = IPL2TP_SSTATE_VOID;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_tunnel_delete
|
||||
*===========================================================================
|
||||
* Description: Delete a tunnel
|
||||
* Parameters: tunnel - The tunnel descriptor.
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_GLOBAL void
|
||||
ipl2tp_tunnel_delete(Ipl2tp_tunnel *tunnel)
|
||||
{
|
||||
/* */
|
||||
if (tunnel->slave != IP_NULL)
|
||||
{
|
||||
Ipl2tp_tunnel *slave = tunnel->slave;
|
||||
/* Clear all pointers */
|
||||
tunnel->slave = IP_NULL;
|
||||
slave->slave = IP_NULL;
|
||||
|
||||
/* Tear the slave down */
|
||||
ipl2tp_tunnel_delete(slave);
|
||||
}
|
||||
|
||||
/* Cancel any outstanding timer */
|
||||
ipcom_tmo_cancel(&tunnel->timer);
|
||||
|
||||
/* Remove it from the remote tunnel hash */
|
||||
ipcom_hash_remove(ipl2tp.tunnel.hash_remote_id, tunnel);
|
||||
/* Remove it from the tunnel hash */
|
||||
ipcom_hash_remove(ipl2tp.tunnel.hash_id, tunnel);
|
||||
/* Remove it from the remote address hash */
|
||||
ipcom_hash_remove(ipl2tp.tunnel.hash_remote_addr, tunnel);
|
||||
/* Remove it from the ifindex hash */
|
||||
ipcom_hash_remove(ipl2tp.tunnel.hash_ifindex, tunnel);
|
||||
|
||||
/* Flush any outstanding messages */
|
||||
ipl2tp_state_tunnel_flush(tunnel);
|
||||
|
||||
IPL2TP_SAFE_FREE(tunnel->sccrq.message);
|
||||
ipl2tp_avp_delete(tunnel->sccrq.avp);
|
||||
tunnel->sccrq.avp = IP_NULL;
|
||||
tunnel->sccrq.message = IP_NULL;
|
||||
|
||||
ipl2tp_attr_tunnel_attribute_free(&tunnel->attr);
|
||||
IPL2TP_SAFE_FREE(tunnel->last_result.error_message);
|
||||
IPL2TP_SAFE_FREE(tunnel->last_error.error_message);
|
||||
IPL2TP_SAFE_FREE(tunnel->expected_response.array);
|
||||
|
||||
IPL2TP_SAFE_FREE(tunnel->common.host_name);
|
||||
IPL2TP_SAFE_FREE(tunnel->common.vendor_name);
|
||||
IPL2TP_SAFE_FREE(tunnel->common.tie_breaker.array);
|
||||
|
||||
tunnel->state = IPL2TP_TSTATE_VOID;
|
||||
|
||||
IPL2TP_TUNNEL_DONE(tunnel);
|
||||
|
||||
ipcom_list_insert_last(&ipl2tp.tunnel.free_list, &tunnel->head);
|
||||
if (--ipl2tp.open_tunnels == 0 && ipl2tp.drain_tunnels == IPL2TP_MIB_YES)
|
||||
{
|
||||
ipl2tp.admin_state = IPL2TP_MIB_DISABLED;
|
||||
ipl2tp.drain_tunnels = IPL2TP_MIB_NO;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_session_delete
|
||||
*===========================================================================
|
||||
* Description: Delete a session
|
||||
* Parameters: session - The session descriptor.
|
||||
* Returns:
|
||||
*
|
||||
*/
|
||||
IP_GLOBAL void
|
||||
ipl2tp_session_delete(Ipl2tp_session *session)
|
||||
{
|
||||
ipl2tp_attr_session_attribute_free(&session->attr);
|
||||
|
||||
IPL2TP_SAFE_FREE(session->local.cookie.array);
|
||||
|
||||
/* Is it currently owned by a tunnel? */
|
||||
if (session->tunnel != IP_NULL)
|
||||
ipcom_list_remove(&session->head);
|
||||
|
||||
/* Remove from the hash */
|
||||
ipcom_hash_remove(ipl2tp.session.hash_id, session);
|
||||
|
||||
/* All done */
|
||||
IPL2TP_TUNNEL_SESSION_DONE(session);
|
||||
|
||||
/* */
|
||||
session->state = IPL2TP_SSTATE_VOID;
|
||||
ipcom_list_insert_last(&ipl2tp.session.free_list, &session->head);
|
||||
|
||||
ipl2tp.open_sessions--;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*===========================================================================
|
||||
* ipl2tp_disable
|
||||
*===========================================================================
|
||||
* Description: Disable IPL2TP temporarily. All tunnels and sessions
|
||||
* are closed and deleted.
|
||||
* Parameters:
|
||||
* Returns: IPL2TP_STATUS_OK if success.
|
||||
*
|
||||
*/
|
||||
IP_GLOBAL Ipl2tp_status
|
||||
ipl2tp_disable(void)
|
||||
{
|
||||
Ipl2tp_tunnel *tnext;
|
||||
Ipl2tp_tunnel *t;
|
||||
|
||||
/* Loop for tunnels */
|
||||
for (t = IPCOM_LIST_FIRST(&ipl2tp.tunnel.v2.tunnels);
|
||||
t != IP_NULL;
|
||||
t = tnext)
|
||||
{
|
||||
tnext = IPCOM_LIST_NEXT(&t->head);
|
||||
IPL2TP_TUNNEL_RESULT_SET(t,
|
||||
IPL2TP_STATUS_CLOSE,
|
||||
IPL2TP_RES_StopCCN_GENERAL_REQUEST,
|
||||
0,
|
||||
"Tunnel closed");
|
||||
ipl2tp_message_stopccn(t);
|
||||
ipl2tp_state_tunnel_teardown(t);
|
||||
}
|
||||
|
||||
/* Loop for tunnels */
|
||||
for (t = IPCOM_LIST_FIRST(&ipl2tp.tunnel.v3.tunnels);
|
||||
t != IP_NULL;
|
||||
t = tnext)
|
||||
{
|
||||
tnext = IPCOM_LIST_NEXT(&t->head);
|
||||
IPL2TP_TUNNEL_RESULT_SET(t,
|
||||
IPL2TP_STATUS_CLOSE,
|
||||
IPL2TP_RES_StopCCN_GENERAL_REQUEST,
|
||||
0,
|
||||
"Tunnel closed");
|
||||
ipl2tp_message_stopccn(t);
|
||||
ipl2tp_state_tunnel_teardown(t);
|
||||
}
|
||||
|
||||
return IPL2TP_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* 11 PUBLIC FUNCTIONS
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
****************************************************************************
|
||||
* END OF FILE
|
||||
****************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user