Files
m241Neelima/components/ip_net2-6.9/ipl2tp/src/ipl2tp_data.c
T
2026-07-30 11:19:44 +05:30

984 lines
30 KiB
C

/*
******************************************************************************
* 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
****************************************************************************
*/