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