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

935 lines
29 KiB
C

/*
******************************************************************************
* SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipl2tp_api.c,v $ $Revision: 1.17.10.2 $
* $Source: /home/interpeak/CVSRoot/ipl2tp/src/ipl2tp_api.c,v $
* $Author: hxu0 $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
*
******************************************************************************
*/
/*
****************************************************************************
* DESCRIPTION
****************************************************************************
*
* Interpeak Layer 2 Tunneling Protocol - IPL2TP
* ---------------------------------------------
*
* Compliant with the following RFCs and internet drafts:
* RFC 2661 - L2TP
* RFC 2233 - Interfaces MIB
* RFC 2667 - IP Tunnel MIB
* RFC 3371 - L2TP Management Information Base
*
*/
/*
****************************************************************************
* CONFIGURATION
****************************************************************************
*/
/*
****************************************************************************
* INCLUDE FILES
****************************************************************************
*/
#include "ipl2tp_h.h"
#include "ipl2tp_api.h"
#include "ipl2tp_avp.h"
#include "ipl2tp_trpt.h"
#include "ipl2tp_util.h"
#include "ipl2tp_attr_h.h"
#include "ipl2tp_state.h"
#include "ipl2tp_message.h"
/*
****************************************************************************
* DEFINES
****************************************************************************
*/
#define IPL2TP_PORT_NUMBER 1701
/*
****************************************************************************
* TYPES
****************************************************************************
*/
/*
****************************************************************************
* LOCAL DATA
****************************************************************************
*/
/*
****************************************************************************
* PUBLIC DATA
****************************************************************************
*/
IP_PUBLIC int ipl2tp_occupied;
/*
****************************************************************************
* LOCAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipl2tp_api_attribute_vector_raw
*===========================================================================
* Description: Parse a raw vector
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_bool
ipl2tp_api_attribute_vector_raw(Ipl2tp_attrobj *attr,
Ipl2tp_attr_info *info,
char *ptr,
int len)
{
if (ptr == IP_NULL)
return IP_FALSE;
if (ipcom_strncmp(ptr, "0x", 2) == 0)
{
int i;
Ip_u8 *vec;
char tbuf[3];
ptr += 2;
len -= 2;
len /= 2;
vec = ipcom_malloc(len);
if(vec == IP_NULL)
{
return IP_FALSE;
}
tbuf[2] = '\0';
for (i = 0; i < len; i++)
{
ipcom_memcpy(tbuf, ptr + i * 2, 2);
vec[i] = (Ip_u8) ipcom_strtoul(tbuf, IP_NULL, 16);
}
ipl2tp_attr_vappend(attr, info->value, vec, len);
ipcom_free(vec);
return IP_TRUE;
}
return IP_FALSE;
}
/*
****************************************************************************
* PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipl2tp_version
*===========================================================================
* Description: Returns the IPL2TP version string.
* Parameters:
* Returns: Version string.
*
*/
IP_PUBLIC const char *
ipl2tp_version(void)
{
return "@(#) IPL2TP $Name: VXWORKS_ITER40_2019102207 $ - INTERPEAK_COPYRIGHT_STRING";
}
/*
*===========================================================================
* ipl2tp_api_version
*===========================================================================
* Description: Returns the API version number. This function can be used
* for applications to support older versions of IPL2TP.
* Parameters:
* Returns: The IPL2TP API version number.
*
*/
IP_PUBLIC int
ipl2tp_api_version(void)
{
return IPL2TP_VERSION_API;
}
/*
*===========================================================================
* ipl2tp_api_init
*===========================================================================
* Description: Initialize IPL2TP package
* Parameters:
* Returns: IPL2TP_STATUS_OK if success.
* IPL2TP_STATUS_NOMEM if out of memory.
*
*/
IP_PUBLIC Ipl2tp_status
ipl2tp_api_init(void)
{
Ipl2tp_status status;
/* Init data */
status = ipl2tp_data_init();
ipl2tp_occupied = 0;
ipl2tp.state = IPL2TP_STATE_INIT;
return status;
}
/*
*===========================================================================
* ipl2tp_api_exit
*===========================================================================
* Description: Free resources used by the IPL2TP package.
* Parameters:
* Returns: IPL2TP_STATUS_OK if success.
* IPL2TP_STATUS_STATE if wrong state.
* IPL2TP_STATUS_BUSY if tunnels/sessions open.
*/
IP_PUBLIC Ipl2tp_status
ipl2tp_api_exit(void)
{
Ipl2tp_status status = IPL2TP_STATUS_OK;
IPL2TP_OCCUPIED(return IPL2TP_STATUS_OCCUPIED);
if (ipl2tp.state != IPL2TP_STATE_INIT)
{
IPCOM_LOG1(ERR,
"%s: IPL2TP is open or not initialized",
ipl2tp_versions[0]);
status = IPL2TP_STATUS_STATE;
}
else if (ipl2tp.open_tunnels != 0 || ipl2tp.open_sessions != 0)
{
IPCOM_LOG1(ERR,
"%s: Called ipl2tp_exit() with open tunnels/sessions,",
ipl2tp_versions[0]);
IPCOM_LOG1(ERR,
"%s: possibly caused by pending retransmissions",
ipl2tp_versions[0]);
status = IPL2TP_STATUS_BUSY;
}
else
{
ipl2tp_data_exit();
ipl2tp.state = IPL2TP_STATE_IDLE;
}
IPL2TP_AVAILABLE();
return status;
}
/*
*===========================================================================
* ipl2tp_api_open
*===========================================================================
* Description: Open and configure IPL2TP with global attributes.
* Parameters: attr - Global attributes.
* tattr_v2 - Default V2 tunnel attributes.
* tattr_v3 - Default V3 tunnel attributes.
* sattr_v2 - Default V2 session attributes.
* sattr_v3 - Default V3 session attributes.
* Returns: IPL2TP_STATUS_OK if success.
* IPL2TP_STATUS_STATE if wrong state.
* IPL2TP_STATUS_BADPARAM if bad attribute object(s).
*/
IP_PUBLIC Ipl2tp_status
ipl2tp_api_open(Ipl2tp_attrobj attr,
Ipl2tp_attrobj tattr_v2,
Ipl2tp_attrobj tattr_v3,
Ipl2tp_attrobj sattr_v2,
Ipl2tp_attrobj sattr_v3)
{
Ipl2tp_status status;
IPL2TP_OCCUPIED(return IPL2TP_STATUS_OCCUPIED);
if (ipl2tp.state != IPL2TP_STATE_INIT)
{
IPCOM_LOG1(ERR,
"%s: IPL2TP is already open or not initialized",
ipl2tp_versions[0]);
status = IPL2TP_STATUS_STATE;
}
else if ((status = ipl2tp_attr_global_set(attr)) != IPL2TP_STATUS_OK)
{
}
else if ((status = ipl2tp_attr_tunnel_set(IP_NULL, &ipl2tp.tunnel.v2.attr, tattr_v2)) !=
IPL2TP_STATUS_OK)
{
}
else if ((status = ipl2tp_attr_tunnel_set(IP_NULL, &ipl2tp.tunnel.v3.attr, tattr_v3)) !=
IPL2TP_STATUS_OK)
{
}
else if ((status = ipl2tp_attr_session_set(IP_NULL, &ipl2tp.session.v2.attr, sattr_v2)) !=
IPL2TP_STATUS_OK)
{
}
else if ((status = ipl2tp_attr_session_set(IP_NULL, &ipl2tp.session.v3.attr, sattr_v3)) !=
IPL2TP_STATUS_OK)
{
}
else if (ipl2tp.wcallback == IP_NULL)
{
IPCOM_LOG1(ERR,
"%s: Missing attribute: IPL2TP_ATTR_SET_L2TP_WRITE_CALLBACK",
ipl2tp_versions[0]);
status = IPL2TP_STATUS_ERROR;
}
if (status == IPL2TP_STATUS_OK)
{
ipl2tp.state = IPL2TP_STATE_OPEN;
}
IPL2TP_AVAILABLE();
return status;
}
/*
*===========================================================================
* ipl2tp_api_close
*===========================================================================
* Description: Close IPL2TP. All tunnels and sessions are closed and deleted.
* Parameters:
* Returns: IPL2TP_STATUS_OK if success.
* IPL2TP_STATUS_STATE if wrong state.
*/
IP_PUBLIC Ipl2tp_status
ipl2tp_api_close(void)
{
Ipl2tp_status status = IPL2TP_STATUS_OK;
IPL2TP_OCCUPIED(return IPL2TP_STATUS_OCCUPIED);
if (ipl2tp.state != IPL2TP_STATE_OPEN)
{
IPCOM_LOG1(ERR,
"%s: IPL2TP is not opened",
ipl2tp_versions[0]);
status = IPL2TP_STATUS_STATE;
}
else
{
/* Teardown everything */
(void)ipl2tp_disable();
ipl2tp.state = IPL2TP_STATE_INIT;
}
IPL2TP_AVAILABLE();
return status;
}
/*
*===========================================================================
* ipl2tp_api_attribute_set
*===========================================================================
* Description: Set global IPL2TP parameters.
* Parameters: attr - Attribute object.
* Returns: IPL2TP_STATUS_OK if success.
* IPL2TP_STATUS_BADPARAM if bad attribute object.
*/
IP_PUBLIC Ipl2tp_status
ipl2tp_api_attribute_set(Ipl2tp_attrobj attr)
{
Ipl2tp_status status;
IPL2TP_OCCUPIED(return IPL2TP_STATUS_OCCUPIED);
if (ipl2tp.state != IPL2TP_STATE_OPEN)
{
IPCOM_LOG1(ERR,
"%s: IPL2TP is not opened",
ipl2tp_versions[0]);
status = IPL2TP_STATUS_STATE;
}
else
{
/* Set global attributes */
status = ipl2tp_attr_global_set(attr);
}
IPL2TP_AVAILABLE();
return status;
}
/*
*===========================================================================
* ipl2tp_api_attribute_get
*===========================================================================
* Description: Get global IPL2TP parameters.
* Parameters: attr - Attribute object.
* replies - Attribute replies.
* Returns: IPL2TP_STATUS_OK if success.
* IPL2TP_STATUS_BADPARAM if bad attribute object.
*/
IP_PUBLIC Ipl2tp_status
ipl2tp_api_attribute_get(Ipl2tp_attrobj attr,
Ipl2tp_attrobj *replies)
{
Ipl2tp_status status;
IPL2TP_OCCUPIED(return IPL2TP_STATUS_OCCUPIED);
if (ipl2tp.state != IPL2TP_STATE_OPEN)
{
IPCOM_LOG1(ERR,
"%s: IPL2TP is not opened",
ipl2tp_versions[0]);
status = IPL2TP_STATUS_STATE;
}
else
{
/* Set global attributes */
status = ipl2tp_attr_global_get(attr, replies);
}
IPL2TP_AVAILABLE();
return status;
}
/*
*===========================================================================
* ipl2tp_api_l2tp_input
*===========================================================================
* Description: Feed an incoming L2TP packet to the L2TP engine.
* Parameters: buffer - Memory buffer pointer.
* payload - Pointer to packet payload, i.e. L2TP header.
* length - Length of payload.
* addr - IP address of sender.
* transport - Transport type. UDP/IP.
* Returns: IPL2TP_STATUS_OK if success.
* IPL2TP_STATUS_BADID if the message session ID is invalid.
* IPL2TP_STATUS_NOTL2TP if this is a non-L2TP message.
* IPL2TP_STATUS_MALFORMED if the message is malformed.
* IPL2TP_STATUS_IGNORE if the message is ignored.
* IPL2TP_STATUS_TEARDOWN if a tunnel or session teardown is required.
* Additional error codes may be returned by the user-specified
* data callback routine.
*/
IP_PUBLIC Ipl2tp_status
ipl2tp_api_l2tp_input(void *buffer,
void *payload,
Ip_u16 length,
union Ip_sockaddr_union *addr,
int transport)
{
Ipl2tp_status status = IPL2TP_STATUS_OK;
Ip_u16 *flvp = payload;
IPL2TP_OCCUPIED(return IPL2TP_STATUS_OCCUPIED);
if (ipl2tp.state != IPL2TP_STATE_OPEN)
{
IPCOM_LOG1(ERR,
"%s: IPL2TP is not opened",
ipl2tp_versions[0]);
status = IPL2TP_STATUS_STATE;
goto leave;
}
switch (transport)
{
case IPL2TP_ATTR_TRANSPORT_UDP:
/* Basic transport for v2 and v3 */
switch (IP_GET_NTOHS(flvp) & IPL2TP_VERSION_MASK)
{
case IPL2TP_VERSION_L2TPV2:
if (ipl2tp.enable_v2 == IPL2TP_MIB_DISABLED)
{
if (ipl2tp.enable_v3 == IPL2TP_MIB_DISABLED)
{
IPCOM_LOG1(ERR,
"%s: IPL2TPV2 is not enabled",
ipl2tp_versions[0]);
status = IPL2TP_STATUS_STATE;
goto leave;
}
/* FALLTHROUGH TO v3 parsing */
}
else
{
status = ipl2tp_v2_l2tp_input(buffer,
payload,
length,
addr);
if (status != IPL2TP_STATUS_NEGOTIATION)
break;
/* FALLTHROUGH TO v3 parsing */
}
case IPL2TP_VERSION_L2TPV3:
if (ipl2tp.enable_v3 == IPL2TP_MIB_DISABLED)
{
IPCOM_LOG1(ERR,
"%s: IPL2TPV3 is not enabled",
ipl2tp_versions[0]);
status = IPL2TP_STATUS_STATE;
goto leave;
}
status = ipl2tp_v3_l2tp_input(buffer,
payload,
length,
addr,
transport);
break;
default:
IPCOM_LOG2(INFO,
"%s: Received non-L2TP message, Ver: %d",
ipl2tp_versions[0],
IP_GET_NTOHS(flvp) & IPL2TP_VERSION_MASK);
status = IPL2TP_STATUS_NOTL2TP;
goto leave;
}
break;
case IPL2TP_ATTR_TRANSPORT_IP:
/* Transport for v3 */
status = ipl2tp_v3_l2tp_input(buffer,
payload,
length,
addr,
transport);
break;
}
leave:
IPL2TP_AVAILABLE();
return status;
}
/*
*===========================================================================
* ipl2tp_api_errname
*===========================================================================
* Description: Get error message.
* Parameters: status Status code.
* Returns: A human readable description of the error.
*
*/
IP_PUBLIC CONST char *
ipl2tp_api_errname(Ipl2tp_status status)
{
static CONST char *ipl2tp_status_string[] =
{
"IPL2TP_STATUS_OK: Success",
"IPL2TP_STATUS_ERROR: General error",
"IPL2TP_STATUS_IGNORE: Message or AVP ignored",
"IPL2TP_STATUS_TEARDOWN: Tunnel or session teardown",
"IPL2TP_STATUS_BADAUTH: Authentication failure",
"IPL2TP_STATUS_BADAVP: Invalid attribute",
"IPL2TP_STATUS_BADBEARER: Bearer type not in capabilities",
"IPL2TP_STATUS_BADFRAMING: Framing type not in capabilities",
"IPL2TP_STATUS_BADID: An invalid ID was specified",
"IPL2TP_STATUS_BADMTYPE: Invalid message type",
"IPL2TP_STATUS_BADPARAM: Bad parameter",
"IPL2TP_STATUS_BADRECWIN: Invalid receive window size",
"IPL2TP_STATUS_BUSY: Tunnel or session open",
"IPL2TP_STATUS_CLOSE: Tunnel or session closed",
"IPL2TP_STATUS_DRAIN: Tunnel or session creation disabled",
"IPL2TP_STATUS_EXISTS: Tunnel or session exists",
"IPL2TP_STATUS_FRAMINGCAPS: No common framing capabilities",
"IPL2TP_STATUS_GOTCDN: Received CDN",
"IPL2TP_STATUS_GOTSTOPCCN: Received StopCCN",
"IPL2TP_STATUS_IDZERO: A zero ID was specified",
"IPL2TP_STATUS_MALFORMED: Malformed message",
"IPL2TP_STATUS_NOLNS: LNS operation not supported",
"IPL2TP_STATUS_NOMEM: Out of memory",
"IPL2TP_STATUS_NORAND: No random vector received",
"IPL2TP_STATUS_NOSECRET: No shared secret configured",
"IPL2TP_STATUS_NOTINIT: Item not initialized",
"IPL2TP_STATUS_NOTL2TP: Non-L2TP message received",
"IPL2TP_STATUS_OCCUPIED: API already occupied",
"IPL2TP_STATUS_PROTVERSION: Protocol version mismatch",
"IPL2TP_STATUS_RESERVEDNZ: Reserved bits non-zero",
"IPL2TP_STATUS_STATE: State machine error",
"IPL2TP_STATUS_TIMEOUT: Control channel timeout",
"IPL2TP_STATUS_VENDOR: Unsupported vendor-specific AVP",
"IPL2TP_STATUS_BADPW: Bad pseudowire type",
"IPL2TP_STATUS_BADL2: Unknown L2 Sublayer",
"IPL2TP_STATUS_BADSEQUENCING: Unknown data sequencing method, or no L2 Sublayer",
"IPL2TP_STATUS_BADVERSION: Bad version",
"IPL2TP_STATUS_CIRCUIT_DOWN: Circuit is down",
};
return (status <
(sizeof(ipl2tp_status_string) /
sizeof(ipl2tp_status_string[0])) ?
ipl2tp_status_string[status] : "<invalid>");
}
/*
*===========================================================================
* ipl2tp_api_attribute_find
*===========================================================================
* Description: Locate an attribute in the list based on name using strtok.
* Parameters: info - The attribute list.
* name - The attribute name
* value - The pointer to where the attribute value starts.
* Returns: The attribute information structure.
*
*/
IP_PUBLIC Ipl2tp_attr_info *
ipl2tp_api_attribute_find(Ipl2tp_attr_info *info,
char *name,
char **value)
{
int i;
char *token;
if ((token = ipcom_strtok_r(name, " \t=,", value)) == IP_NULL)
return IP_NULL;
for (i = 0; info[i].value != 0; i++)
{
if (ipcom_strcasecmp(info[i].name, token) == 0)
return &info[i];
}
return IP_NULL;
}
/*
*===========================================================================
* ipl2tp_api_attribute_parse
*===========================================================================
* Description: Parse an attribute value using strtok
* Parameters: attr - The attribute to append the value to.
* info - The attribute information object
* value - The pointer containing the value offset
* Returns:
*
*/
IP_PUBLIC Ip_bool
ipl2tp_api_attribute_parse(Ipl2tp_attrobj *attr,
Ipl2tp_attr_info *info,
char **value)
{
int i;
char *token;
switch (info->type)
{
case IPL2TP_ATTR_TYPE_STRING:
return (ipl2tp_attr_strappend(attr, info->value, *value) == IPL2TP_STATUS_OK) ?
IP_TRUE : IP_FALSE;
case IPL2TP_ATTR_TYPE_INT:
if (info->hr)
{
/* first token */
if ((token = ipcom_strtok_r(IP_NULL, " \t=,", value)) == IP_NULL)
return IP_FALSE;
for (i = 0; info->hr[i] != IP_NULL; i++)
{
if (ipcom_strlen(info->hr[i]) == 0)
continue;
if (ipcom_strcasecmp(info->hr[i], token) == 0)
{
return (ipl2tp_attr_iappend(attr, info->value, i) == IPL2TP_STATUS_OK) ?
IP_TRUE : IP_FALSE;
}
}
return IP_FALSE;
}
/* Fall through */
case IPL2TP_ATTR_TYPE_SEC:
/* first token */
if ((token = ipcom_strtok_r(IP_NULL, " \t=,", value)) == IP_NULL)
return IP_FALSE;
return (ipl2tp_attr_iappend(attr, info->value,
(int)ipcom_strtoul(token, IP_NULL, 10)) == IPL2TP_STATUS_OK) ?
IP_TRUE : IP_FALSE;
case IPL2TP_ATTR_TYPE_INT64:
if ((token = ipcom_strtok_r(IP_NULL, " \t=,", value)) == IP_NULL)
return IP_FALSE;
else
{
Ip_u64 val;
IP_U64_SET(val, 0, ipcom_strtoul(token, IP_NULL, 10));
ipl2tp_attr_iappend64(attr, info->value, &val);
}
return IP_TRUE;
case IPL2TP_ATTR_TYPE_ADDRESS:
{
union Ip_sockaddr_union uaddr;
/* first token */
if ((token = ipcom_strtok_r(IP_NULL, " \t=,", value)) == IP_NULL)
return IP_FALSE;
if (ipl2tp_api_attribute_address_parse(token, &uaddr) == IP_FALSE)
return IP_FALSE;
ipl2tp_attr_addrappend(attr, info->value, &uaddr);
}
return IP_TRUE;
case IPL2TP_ATTR_TYPE_FUNCTION:
case IPL2TP_ATTR_TYPE_POINTER:
if ((token = ipcom_strtok_r(IP_NULL, " \t=,", value)) == IP_NULL)
return IP_FALSE;
else
{
unsigned long data = ipcom_strtoul(token, IP_NULL, 10);
if (ipl2tp_attr_pappend(attr, info->value, (void *)data) != IPL2TP_STATUS_OK)
return IP_FALSE;
}
return IP_TRUE;
case IPL2TP_ATTR_TYPE_VECTOR:
{
int len;
if (*value == IP_NULL)
{
len = 0;
ipl2tp_attr_vappend(attr, info->value, *value, len);
return IP_TRUE;
}
len = (int)ipcom_strlen(*value);
if (ipl2tp_api_attribute_vector_raw(attr,info,*value,len) == IP_FALSE)
{
/* Append the vector */
ipl2tp_attr_vappend(attr, info->value, *value, len);
}
}
return IP_TRUE;
case IPL2TP_ATTR_TYPE_VEC8:
{
int len;
if (*value == IP_NULL)
len = 0;
else
len = (int)ipcom_strlen(*value);
if (ipl2tp_api_attribute_vector_raw(attr,info,*value,len) == IP_FALSE)
{
Ip_u8 *vec = ipcom_malloc(len * sizeof(Ip_u8));
if (vec == IP_NULL)
return IP_FALSE;
i = 0;
while ((token = ipcom_strtok_r(IP_NULL, " ,", value)) != IP_NULL)
{
Ip_u8 v8;
if (info->hr)
{
/* first token */
for (i = 0; info->hr[i] != IP_NULL; i++)
{
if (ipcom_strlen(info->hr[i]) == 0)
continue;
if (ipcom_strcasecmp(info->hr[i], token) == 0)
{
v8 = (Ip_u8)i;
goto set_vec8;
}
}
/* Didn't find it */
ipcom_free(vec);
return IP_FALSE;
}
else
{
v8 = (Ip_u8)ipcom_strtoul(token, IP_NULL, 10);
}
set_vec8:
vec[i++] = (Ip_u8)v8;
}
ipl2tp_attr_vappend(attr, info->value, vec, i);
ipcom_free(vec);
}
}
return IP_TRUE;
case IPL2TP_ATTR_TYPE_VEC16:
{
int len;
if (*value == IP_NULL)
len = 0;
else
len = (int)ipcom_strlen(*value);
if (ipl2tp_api_attribute_vector_raw(attr,info,*value,len) == IP_FALSE)
{
Ip_u16 *vec = ipcom_malloc(len * sizeof(Ip_u16));
if(vec == IP_NULL)
{
return IP_FALSE;
}
i = 0;
while ((token = ipcom_strtok_r(IP_NULL, " ,", value)) != IP_NULL)
{
Ip_u16 v16;
if (info->hr)
{
/* first token */
for (i = 0; info->hr[i] != IP_NULL; i++)
{
if (ipcom_strlen(info->hr[i]) == 0)
continue;
if (ipcom_strcasecmp(info->hr[i], token) == 0)
{
v16 = (Ip_u16)i;
goto set_vec16;
}
}
ipcom_free(vec);
return IP_FALSE;
}
else
{
v16 = (Ip_u16)ipcom_strtoul(token, IP_NULL, 10);
}
set_vec16:
vec[i++] = v16;
}
ipl2tp_attr_vappend(attr, info->value, vec, i * (int)sizeof(Ip_u16));
ipcom_free(vec);
}
}
return IP_TRUE;
default:
case IPL2TP_ATTR_TYPE_KEY:
case IPL2TP_ATTR_TYPE_NONE:
break;
}
return IP_FALSE;
}
/*
*===========================================================================
* ipl2tp_api_attribute_address_parse
*===========================================================================
* Description: Parse addresses. Both v4 and v6.
* Parameters: str - The address to parse.
* uaddr - Where to store the result.
* Returns: IP_TRUE if parsing was successful.
*
*/
IP_PUBLIC Ip_bool
ipl2tp_api_attribute_address_parse(char *str,
union Ip_sockaddr_union *uaddr)
{
ipcom_memset(uaddr, 0, sizeof(*uaddr));
if (ipcom_inet_pton(IP_AF_INET, str, &uaddr->sin.sin_addr) > 0)
{
uaddr->sin.sin_family = IP_AF_INET;
uaddr->sin.sin_len = sizeof(struct Ip_sockaddr_in);
uaddr->sin.sin_port = ip_htons(IPL2TP_PORT_NUMBER);
return IP_TRUE;
}
#ifdef IPCOM_USE_INET6
if (ipcom_inet_pton(IP_AF_INET6, str, &uaddr->sin6.sin6_addr) > 0)
{
uaddr->sin6.sin6_family = IP_AF_INET6;
uaddr->sin6.sin6_len = sizeof(struct Ip_sockaddr_in6);
uaddr->sin6.sin6_port = ip_htons(IPL2TP_PORT_NUMBER);
return IP_TRUE;
}
#endif
/* No go */
return IP_FALSE;
}
/*
*===========================================================================
* ipl2tp_api_attribute_info
*===========================================================================
* Description: Map a tag to an info structure
* Parameters: tag - The tag.
* Returns: The attribute's information structure.
*
*/
IP_PUBLIC Ipl2tp_attr_info *
ipl2tp_api_attribute_info(int tag)
{
int i;
Ipl2tp_attr_info *array;
if (tag < IPL2TP_ATTR_END_ENUM)
array = ipl2tp_tags;
else if (tag < IPL2TP_TATTR_END_ENUM)
array = ipl2tp_tunnel_tags;
else
array = ipl2tp_session_tags;
for (i = 0; array[i].value != 0; i++)
{
if (array[i].value == (Ip_u32)tag)
return &array[i];
}
return IP_NULL;
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/