935 lines
29 KiB
C
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
|
|
****************************************************************************
|
|
*/
|