2397 lines
69 KiB
C
2397 lines
69 KiB
C
/*
|
|
******************************************************************************
|
|
* SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipl2tp_cmd.c,v $ $Revision: 1.21.14.2 $
|
|
* $Source: /home/interpeak/CVSRoot/ipl2tp/src/ipl2tp_cmd.c,v $
|
|
* $Author: jren $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
*
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* DESCRIPTION
|
|
****************************************************************************
|
|
*
|
|
* Command-line service routines.
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include "ipcom.h"
|
|
#include "ipcom_os.h"
|
|
#include "ipcom_shell.h"
|
|
#include "ipcom_sock2.h"
|
|
#include "ipcom_sock6.h"
|
|
#include "ipcom_cmd.h"
|
|
|
|
#include "ipl2tp.h"
|
|
#include "ipl2tp_api.h"
|
|
#include "ipl2tp_api_session.h"
|
|
#include "ipl2tp_api_tunnel.h"
|
|
#include "ipl2tp_attr.h"
|
|
#include "ipl2tp_cmd.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/* L2TP control port */
|
|
#define IPL2TP_PORT_NUMBER 1701
|
|
|
|
/* Extra header space allocated before L2TP header */
|
|
#define HEADER_SPACE 0
|
|
|
|
#define IPL2TP_CMD_ATTR_DELIM " \t=,"
|
|
|
|
/* "poke" command used for debugging */
|
|
#ifdef IPL2TP_ALLOW_CMD_POKE
|
|
#undef IPL2TP_ALLOW_CMD_POKE
|
|
#endif
|
|
|
|
/*lint -e534*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* TYPES
|
|
****************************************************************************
|
|
*/
|
|
typedef struct Ipl2tp_cmd_session_key
|
|
{
|
|
Ip_u32 ifindex;
|
|
Ipl2tp_key key;
|
|
}
|
|
Ipl2tp_cmd_session_key;
|
|
|
|
/*
|
|
****************************************************************************
|
|
* LOCAL DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/* Output formatting */
|
|
#define IPL2TP_CMD_GET 1
|
|
#define IPL2TP_CMD_SET 2
|
|
IP_STATIC Ipcom_cmd_int_str_map ipl2tp_cmd_getset[] =
|
|
{
|
|
{ IPL2TP_CMD_GET, "get" },
|
|
{ IPL2TP_CMD_SET, "set" },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
|
|
#define IPL2TP_CMD_POKE 1
|
|
#define IPL2TP_CMD_ATTR 2
|
|
#define IPL2TP_CMD_SATTR 3
|
|
#define IPL2TP_CMD_TATTR 4
|
|
#define IPL2TP_CMD_STATS 5
|
|
#define IPL2TP_CMD_SSTATS 6
|
|
#define IPL2TP_CMD_TSTATS 7
|
|
#define IPL2TP_CMD_TOPEN 8
|
|
#define IPL2TP_CMD_TCLOSE 9
|
|
#define IPL2TP_CMD_SOPEN 10
|
|
#define IPL2TP_CMD_SCLOSE 11
|
|
IP_STATIC Ipcom_cmd_int_str_map ipl2tp_cmd_cmds[] =
|
|
{
|
|
#ifdef IPL2TP_ALLOW_CMD_POKE
|
|
{ IPL2TP_CMD_POKE, "poke" },
|
|
#endif
|
|
{ IPL2TP_CMD_ATTR, "attr" },
|
|
{ IPL2TP_CMD_SATTR, "sattr" },
|
|
{ IPL2TP_CMD_TATTR, "tattr" },
|
|
{ IPL2TP_CMD_STATS, "stats" },
|
|
{ IPL2TP_CMD_SSTATS, "sstats" },
|
|
{ IPL2TP_CMD_TSTATS, "tstats" },
|
|
{ IPL2TP_CMD_TOPEN, "topen" },
|
|
{ IPL2TP_CMD_TCLOSE, "tclose" },
|
|
{ IPL2TP_CMD_SOPEN, "sopen" },
|
|
{ IPL2TP_CMD_SCLOSE, "sclose" },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
|
|
/* List of sessions per interface */
|
|
IP_STATIC Ipcom_hash *ipl2tp_cmd_session_hash_table = IP_NULL;
|
|
IP_STATIC Ipcom_once_t ipl2tp_cmd_session_once = IPCOM_ONCE_INIT;
|
|
|
|
/*
|
|
****************************************************************************
|
|
* PUBLIC DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
/* Poke vars */
|
|
IP_PUBLIC int poke_count = 0;
|
|
IP_PUBLIC int poke_mtype = 0;
|
|
IP_PUBLIC int poke_avp = 0;
|
|
IP_PUBLIC int poke_offset = 0;
|
|
IP_PUBLIC int poke_value = 0;
|
|
IP_PUBLIC int poke_skip = 0;
|
|
IP_PUBLIC char ipl2tp_poke_abort[4] = "";
|
|
|
|
/*
|
|
****************************************************************************
|
|
* PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* LOCAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_attr_print_hdr
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipl2tp_cmd_attr_print_hdr(Ipl2tp_attr_info *attr)
|
|
{
|
|
int len = (int)ipcom_strlen(attr->name);
|
|
ipcom_printf(" %s", attr->name);
|
|
|
|
if (len < 32)
|
|
{
|
|
char buf[64];
|
|
ipcom_snprintf(buf, sizeof(buf), "%%%ds", 32 - len);
|
|
ipcom_printf(buf, ": ");
|
|
}
|
|
else
|
|
{
|
|
ipcom_printf(":");
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_attr_print_attr
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipl2tp_cmd_attr_print_attr(Ipl2tp_attr a,
|
|
Ipl2tp_attr_info *attr)
|
|
{
|
|
if (attr->type == IPL2TP_ATTR_TYPE_VECTOR ||
|
|
attr->type == IPL2TP_ATTR_TYPE_NONE)
|
|
return;
|
|
|
|
ipl2tp_cmd_attr_print_hdr(attr);
|
|
|
|
switch (attr->type)
|
|
{
|
|
case IPL2TP_ATTR_TYPE_STRING:
|
|
ipcom_printf("%s"IP_LF, ipl2tp_attr_strdata(a));
|
|
break;
|
|
case IPL2TP_ATTR_TYPE_SEC:
|
|
ipcom_printf("%u s"IP_LF, ipl2tp_attr_idata(a));
|
|
break;
|
|
case IPL2TP_ATTR_TYPE_INT:
|
|
if (attr->hr != IP_NULL)
|
|
{
|
|
ipcom_printf("%s"IP_LF, attr->hr[ipl2tp_attr_idata(a)]);
|
|
}
|
|
else
|
|
{
|
|
ipcom_printf("%u"IP_LF, ipl2tp_attr_idata(a));
|
|
}
|
|
break;
|
|
case IPL2TP_ATTR_TYPE_INT64:
|
|
{
|
|
Ip_u64 v;
|
|
ipl2tp_attr_idata64(a, &v);
|
|
ipcom_printf("hi=%lu lo=%lu"IP_LF, IP_U64_GETHI(v), IP_U64_GETLO(v));
|
|
}
|
|
break;
|
|
case IPL2TP_ATTR_TYPE_ADDRESS:
|
|
{
|
|
union Ip_sockaddr_union *addr = ipl2tp_attr_addrdata(a);
|
|
char buf[64];
|
|
|
|
if(addr == IP_NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
switch (addr->sa.sa_family)
|
|
{
|
|
case IP_AF_INET:
|
|
ipcom_inet_ntop(IP_AF_INET, &addr->sin.sin_addr, buf, sizeof(buf));
|
|
break;
|
|
#ifdef IPCOM_USE_INET6
|
|
case IP_AF_INET6:
|
|
ipcom_inet_ntop(IP_AF_INET6, &addr->sin6.sin6_addr, buf, sizeof(buf));
|
|
break;
|
|
#endif
|
|
default:
|
|
ipcom_strcpy(buf, "<unknown address family>");
|
|
break;
|
|
}
|
|
|
|
ipcom_printf("%s"IP_LF, buf);
|
|
}
|
|
break;
|
|
case IPL2TP_ATTR_TYPE_KEY:
|
|
{
|
|
Ipl2tp_key *key = ipl2tp_attr_keydata(a);
|
|
if(key == IP_NULL)
|
|
{
|
|
return;
|
|
}
|
|
ipcom_printf("v%u %u"IP_LF, key->version, key->ident);
|
|
}
|
|
break;
|
|
case IPL2TP_ATTR_TYPE_FUNCTION:
|
|
case IPL2TP_ATTR_TYPE_POINTER:
|
|
ipcom_printf("%p"IP_LF, ipl2tp_attr_pdata(a));
|
|
break;
|
|
case IPL2TP_ATTR_TYPE_VEC8:
|
|
{
|
|
Ip_size_t len = ipl2tp_attr_length(a);
|
|
Ip_u8 *vdata = ipl2tp_attr_vdata(a);
|
|
Ip_size_t i;
|
|
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
if (attr->hr)
|
|
{
|
|
ipcom_printf("%s%s", i? "," : "", attr->hr[vdata[i]]);
|
|
}
|
|
else
|
|
{
|
|
ipcom_printf("%s%u", i? "," : "", (int)vdata[i]);
|
|
}
|
|
}
|
|
ipcom_printf(IP_LF);
|
|
|
|
}
|
|
break;
|
|
case IPL2TP_ATTR_TYPE_VEC16:
|
|
{
|
|
Ip_size_t len = ipl2tp_attr_length(a);
|
|
Ip_u16 *vdata = (Ip_u16 *)ipl2tp_attr_vdata(a);
|
|
Ip_size_t i;
|
|
|
|
len /= 2;
|
|
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
Ip_u16 val;
|
|
ipcom_memcpy(&val, vdata + i, sizeof(val));
|
|
if (attr->hr)
|
|
{
|
|
ipcom_printf("%s%s", i? "," : "", attr->hr[val]);
|
|
}
|
|
else
|
|
{
|
|
ipcom_printf("%s%u", i? "," : "", (int) val);
|
|
}
|
|
}
|
|
ipcom_printf(IP_LF);
|
|
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_attr_list
|
|
*===========================================================================
|
|
* Description: List all available attributes
|
|
* Parameters: info - The attribute list.
|
|
* rw - IP_TRUE if we're only interested in RW attr.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipl2tp_cmd_attr_list(Ipl2tp_attr_info *info,
|
|
Ip_bool rw)
|
|
{
|
|
int i;
|
|
|
|
ipcom_printf("Available %s attributes:"IP_LF,
|
|
rw? "Read/Write" : "Read");
|
|
for (i = 0; info[i].value != 0; i++)
|
|
{
|
|
/* If we're looking at read/write */
|
|
if (rw && info->rw != rw)
|
|
continue;
|
|
|
|
ipcom_printf(" %s"IP_LF, info[i].name);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_attr_print_syntax
|
|
*===========================================================================
|
|
* Description: Print the syntax of an attribute
|
|
* Parameters: info - The attribute
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC void
|
|
ipl2tp_cmd_attr_print_syntax(Ipl2tp_attr_info *info)
|
|
{
|
|
int i;
|
|
|
|
ipcom_printf("%s: ", info->name);
|
|
|
|
switch (info->type)
|
|
{
|
|
case IPL2TP_ATTR_TYPE_STRING:
|
|
ipcom_printf("<string>"IP_LF);
|
|
break;
|
|
case IPL2TP_ATTR_TYPE_SEC:
|
|
ipcom_printf("<seconds>"IP_LF);
|
|
break;
|
|
case IPL2TP_ATTR_TYPE_INT:
|
|
if (info->hr)
|
|
{
|
|
int first = 0;
|
|
for (i = 0; info->hr[i] != IP_NULL; i++)
|
|
{
|
|
if (ipcom_strlen(info->hr[i]) == 0)
|
|
continue;
|
|
|
|
ipcom_printf("%s%s", first == 0? "<" : "|", info->hr[i]);
|
|
first++;
|
|
}
|
|
ipcom_printf(">"IP_LF);
|
|
}
|
|
else
|
|
{
|
|
ipcom_printf("<32 bit integer>"IP_LF);
|
|
}
|
|
break;
|
|
case IPL2TP_ATTR_TYPE_INT64:
|
|
ipcom_printf("<64 bit integer>"IP_LF);
|
|
break;
|
|
case IPL2TP_ATTR_TYPE_ADDRESS:
|
|
ipcom_printf("<inet4 address|inet6 address>"IP_LF);
|
|
break;
|
|
case IPL2TP_ATTR_TYPE_KEY:
|
|
ipcom_printf("<version> <identifier>"IP_LF);
|
|
break;
|
|
case IPL2TP_ATTR_TYPE_FUNCTION:
|
|
case IPL2TP_ATTR_TYPE_POINTER:
|
|
ipcom_printf("<function/pointer address>"IP_LF);
|
|
break;
|
|
case IPL2TP_ATTR_TYPE_VECTOR:
|
|
ipcom_printf("<hexadecimal array (0xabcd) or string>"IP_LF);
|
|
break;
|
|
case IPL2TP_ATTR_TYPE_VEC8:
|
|
if (info->hr)
|
|
{
|
|
int first = 0;
|
|
ipcom_printf("<array of ");
|
|
for (i = 0; info->hr[i] != IP_NULL; i++)
|
|
{
|
|
if (ipcom_strlen(info->hr[i]) == 0)
|
|
continue;
|
|
|
|
ipcom_printf("%s%s", first == 0? "" : "|", info->hr[i]);
|
|
first++;
|
|
}
|
|
ipcom_printf(" or hexadecimal array (0xabcd)>"IP_LF);
|
|
}
|
|
else
|
|
{
|
|
ipcom_printf("<hexadecimal array (0xabcd) or array of 8 bit values>"IP_LF);
|
|
}
|
|
break;
|
|
case IPL2TP_ATTR_TYPE_VEC16:
|
|
if (info->hr)
|
|
{
|
|
int first = 0;
|
|
ipcom_printf("<array of ");
|
|
for (i = 0; info->hr[i] != IP_NULL; i++)
|
|
{
|
|
if (ipcom_strlen(info->hr[i]) == 0)
|
|
continue;
|
|
|
|
ipcom_printf("%s%s", first == 0? "" : "|", info->hr[i]);
|
|
first++;
|
|
}
|
|
ipcom_printf(" or hexadecimal array (0xabcd)>"IP_LF);
|
|
}
|
|
else
|
|
{
|
|
ipcom_printf("<hexadecimal array (0xabcd) or array of 16 bit values>"IP_LF);
|
|
}
|
|
break;
|
|
default:
|
|
case IPL2TP_ATTR_TYPE_NONE:
|
|
ipcom_printf("no available input method"IP_LF);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_session_obj_hash_ifindex
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*/
|
|
IP_STATIC unsigned
|
|
ipl2tp_cmd_session_obj_hash_ifindex(Ipl2tp_cmd_session_key *key)
|
|
{
|
|
/* Hash the tunnel ifindex ID */
|
|
return ipcom_hash_update(&key->ifindex,
|
|
sizeof(key->ifindex),
|
|
0);
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_session_key_hash_ifindex
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*/
|
|
IP_STATIC unsigned
|
|
ipl2tp_cmd_session_key_hash_ifindex(Ip_u32 *ifindex)
|
|
{
|
|
/* Hash the tunnel ifindex ID */
|
|
return ipcom_hash_update(ifindex,
|
|
sizeof(*ifindex),
|
|
0);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_session_cmp_ifindex
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*/
|
|
IP_STATIC Ip_bool
|
|
ipl2tp_cmd_session_cmp_ifindex(Ipl2tp_cmd_session_key *key,
|
|
Ip_u32 *ifindex)
|
|
{
|
|
return key->ifindex == *ifindex;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipcom_shellalias_init
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ip_err
|
|
ipl2tp_cmd_session_init(void *unused)
|
|
{
|
|
(void)unused;
|
|
|
|
|
|
/* The address tunnel hash */
|
|
ipl2tp_cmd_session_hash_table = ipcom_hash_new((Ipcom_hash_obj_func)ipl2tp_cmd_session_obj_hash_ifindex,
|
|
(Ipcom_hash_key_func)ipl2tp_cmd_session_key_hash_ifindex,
|
|
(Ipcom_hash_cmp_func)ipl2tp_cmd_session_cmp_ifindex);
|
|
|
|
return IPCOM_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_session_wait_establish
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipl2tp_status
|
|
ipl2tp_cmd_session_wait_establish(Ipl2tp_key *key,
|
|
int timeout)
|
|
{
|
|
Ipl2tp_attrobj attr = IP_NULL;
|
|
Ipl2tp_attrobj replies = IP_NULL;
|
|
Ipl2tp_status status = IPL2TP_STATUS_TIMEOUT;
|
|
|
|
/* While we've gotten timeout left */
|
|
while (timeout--)
|
|
{
|
|
int oper;
|
|
Ipl2tp_attr a;
|
|
|
|
/* Retrieve the administrative status of the tunnel, wait
|
|
* until we're established or we've failed, or the timeout's
|
|
* elapsed */
|
|
ipl2tp_attr_clear(attr);
|
|
ipl2tp_attr_clear(replies);
|
|
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsState);
|
|
if ((status = ipl2tp_api_session_attribute_get(key,attr,&replies)) != IPL2TP_STATUS_OK)
|
|
break;
|
|
|
|
if((a = ipl2tp_attr_first(replies)) == IP_NULL)
|
|
break;
|
|
|
|
oper = ipl2tp_attr_idata(a);
|
|
|
|
if (oper == IPL2TP_MIB_CONNECTING)
|
|
{
|
|
status = IPL2TP_STATUS_TIMEOUT;
|
|
if (timeout)
|
|
ipcom_sleep(1);
|
|
|
|
}
|
|
else if (oper == IPL2TP_MIB_ESTABLISHED)
|
|
{
|
|
/* We're done */
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
/* We're in disconnecting or idle state */
|
|
status = IPL2TP_STATUS_TEARDOWN;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ipl2tp_attr_delete(&attr);
|
|
ipl2tp_attr_delete(&replies);
|
|
|
|
/* OK */
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_tunnel_wait_establish
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC Ipl2tp_status
|
|
ipl2tp_cmd_tunnel_wait_establish(Ipl2tp_key *key,
|
|
int timeout)
|
|
{
|
|
Ipl2tp_attrobj attr = IP_NULL;
|
|
Ipl2tp_attrobj replies = IP_NULL;
|
|
Ipl2tp_status status = IPL2TP_STATUS_TIMEOUT;
|
|
|
|
/* While we've gotten timeout left */
|
|
while (timeout--)
|
|
{
|
|
int oper;
|
|
Ipl2tp_attr a;
|
|
|
|
/* Retrieve the administrative status of the tunnel, wait
|
|
* until we're established or we've failed, or the timeout's
|
|
* elapsed */
|
|
ipl2tp_attr_clear(attr);
|
|
ipl2tp_attr_clear(replies);
|
|
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsState);
|
|
if ((status = ipl2tp_api_tunnel_attribute_get(key,attr,&replies)) != IPL2TP_STATUS_OK)
|
|
break;
|
|
|
|
if((a = ipl2tp_attr_first(replies)) == IP_NULL)
|
|
break;
|
|
|
|
oper = ipl2tp_attr_idata(a);
|
|
|
|
if (oper == IPL2TP_MIB_CONNECTING)
|
|
{
|
|
status = IPL2TP_STATUS_TIMEOUT;
|
|
if (timeout)
|
|
ipcom_sleep(1);
|
|
}
|
|
else if (oper == IPL2TP_MIB_ESTABLISHED)
|
|
{
|
|
/* We're done */
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
/* We're in disconnecting or idle state */
|
|
status = IPL2TP_STATUS_TEARDOWN;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ipl2tp_attr_delete(&attr);
|
|
ipl2tp_attr_delete(&replies);
|
|
|
|
/* OK */
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_session_key
|
|
*===========================================================================
|
|
* Description: Find a session key based on ifindex
|
|
* Parameters: ifindex - The interface index.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC Ipl2tp_key *
|
|
ipl2tp_cmd_session_key(Ip_u32 ifindex)
|
|
{
|
|
Ipl2tp_cmd_session_key *key;
|
|
Ip_err err;
|
|
|
|
err = ipcom_once(&ipl2tp_cmd_session_once,
|
|
ipl2tp_cmd_session_init,
|
|
IP_NULL);
|
|
if (err != IPCOM_SUCCESS)
|
|
return IP_NULL;
|
|
|
|
key = ipcom_hash_get(ipl2tp_cmd_session_hash_table, &ifindex);
|
|
if (key)
|
|
return &key->key;
|
|
|
|
return IP_NULL;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_session_hash_add
|
|
*===========================================================================
|
|
* Description: Add an interface index - session ID pair to the hash table.
|
|
* Parameters: ifindex - The interface index.
|
|
* skey - pointer to key having session ID.
|
|
* Returns: None.
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
ipl2tp_cmd_session_hash_add(Ip_u32 ifindex, Ipl2tp_key *skey)
|
|
{
|
|
Ip_err err;
|
|
Ipl2tp_cmd_session_key *ikey = ipcom_malloc(sizeof(*ikey));
|
|
|
|
if(ikey == IP_NULL)
|
|
{
|
|
return IPCOM_ERR_FAILED;
|
|
}
|
|
|
|
err = ipcom_once(&ipl2tp_cmd_session_once,
|
|
ipl2tp_cmd_session_init,
|
|
IP_NULL);
|
|
if (err != IPCOM_SUCCESS)
|
|
{
|
|
ipcom_free(ikey);
|
|
return err;
|
|
}
|
|
|
|
ikey->ifindex = ifindex;
|
|
ipcom_memcpy(&ikey->key, skey, sizeof(Ipl2tp_key));
|
|
return (ipcom_hash_add(ipl2tp_cmd_session_hash_table, ikey));
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_session_hash_remove
|
|
*===========================================================================
|
|
* Description: Find a session key based on ifindex
|
|
* Parameters: ifindex - The interface index.
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC Ip_err
|
|
ipl2tp_cmd_session_hash_remove(Ip_u32 ifindex)
|
|
{
|
|
Ipl2tp_cmd_session_key *key;
|
|
Ip_err err;
|
|
|
|
err = ipcom_once(&ipl2tp_cmd_session_once,
|
|
ipl2tp_cmd_session_init,
|
|
IP_NULL);
|
|
if (err != IPCOM_SUCCESS)
|
|
return err;
|
|
|
|
key = ipcom_hash_get(ipl2tp_cmd_session_hash_table, &ifindex);
|
|
if (key == IP_NULL)
|
|
return IPCOM_ERR_NOT_FOUND;
|
|
|
|
return(ipcom_hash_remove(ipl2tp_cmd_session_hash_table, key));
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_topen
|
|
*===========================================================================
|
|
* Description: Tunnel open command.
|
|
* Parameters: argc - No of arguments.
|
|
* argv - Argument vector.
|
|
* Returns: 0 if success.
|
|
*
|
|
*/
|
|
|
|
IP_PUBLIC int
|
|
ipl2tp_cmd_topen(int argc, char **argv)
|
|
{
|
|
Ipl2tp_attrobj tattr = IP_NULL;
|
|
union Ip_sockaddr_union uaddr;
|
|
Ipl2tp_key tkey[2];
|
|
Ipl2tp_status status;
|
|
int establish = 1;
|
|
int opt;
|
|
int timeout = 10;
|
|
Ip_bool hs = IP_FALSE;
|
|
|
|
if (argc < 2)
|
|
goto usage;
|
|
|
|
ipcom_getopt_clear();
|
|
|
|
ipcom_memset(tkey, 0, sizeof(tkey));
|
|
|
|
/* Get options */
|
|
tkey[0].version = IPL2TP_VERSION_L2TPV2;
|
|
while ((opt = ipcom_getopt(argc, argv, "d23w:")) != -1)
|
|
{
|
|
switch (opt)
|
|
{
|
|
case '3':
|
|
tkey[0].version = IPL2TP_VERSION_L2TPV3;
|
|
break;
|
|
case '2':
|
|
hs = IP_TRUE;
|
|
break;
|
|
case 'd':
|
|
establish = 0;
|
|
break;
|
|
case 'w':
|
|
timeout = (int)ipcom_strtoul(ip_optarg, IP_NULL, 10);
|
|
break;
|
|
default:
|
|
goto usage;
|
|
}
|
|
}
|
|
|
|
/* Host address must be supplied */
|
|
if (ip_optind == argc)
|
|
goto usage;
|
|
|
|
/* Get host */
|
|
if ((ipcom_strchr(argv[ip_optind], '.') == IP_NULL) ||
|
|
(ipl2tp_api_attribute_address_parse(argv[ip_optind], &uaddr) == IP_FALSE))
|
|
{
|
|
ipcom_printf("l2tp topen: unknown host %s"IP_LF, argv[ip_optind]);
|
|
return -1;
|
|
}
|
|
|
|
/* Move past the host */
|
|
ip_optind++;
|
|
|
|
/* Set some default tunnel attributes */
|
|
if (hs || tkey[0].version == IPL2TP_VERSION_L2TPV2)
|
|
{
|
|
if ((status = ipl2tp_attr_iappend(&tattr, IPL2TP_TATTR_SET_FRAMING_CAPABILITIES,
|
|
IPL2TP_MIB_FRAMING_ASYNC)) != IPL2TP_STATUS_OK ||
|
|
(status = ipl2tp_attr_iappend(&tattr, IPL2TP_TATTR_SET_BEARER_CAPABILITIES,
|
|
IPL2TP_MIB_BEARER_ANALOG)) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("l2tp topen: failed to set default attributes: error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Do go through the remaining attributes */
|
|
for (; ip_optind < argc; ip_optind++)
|
|
{
|
|
Ipl2tp_attr_info *info;
|
|
char *value = IP_NULL;
|
|
|
|
if ((info = ipl2tp_api_attribute_find(ipl2tp_tunnel_tags, argv[ip_optind], &value)) == IP_NULL)
|
|
{
|
|
ipcom_printf("l2tp topen: unknown attribute name %s"IP_LF, argv[ip_optind]);
|
|
return -1;
|
|
}
|
|
|
|
/* Parse the value */
|
|
if (ipl2tp_api_attribute_parse(&tattr, info, &value) == IP_FALSE)
|
|
{
|
|
ipcom_printf("l2tp topen: error parsing value"IP_LF);
|
|
ipl2tp_cmd_attr_print_syntax(info);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Open session */
|
|
if ((status = ipl2tp_api_tunnel_open(tkey, &uaddr, tattr, establish, hs)) == IPL2TP_STATUS_OK)
|
|
{
|
|
/* If the second key's version field is zero, we don't have a versioning */
|
|
if (tkey[1].version == 0)
|
|
hs = IP_FALSE;
|
|
|
|
if (establish)
|
|
{
|
|
Ipl2tp_key *key = &tkey[0];
|
|
|
|
if (hs)
|
|
{
|
|
while (timeout)
|
|
{
|
|
int ret = ipl2tp_api_tunnel_negotiation(tkey, &key);
|
|
|
|
if (ret == IPL2TP_STATUS_OK)
|
|
break;
|
|
|
|
if (ret == IPL2TP_STATUS_NEGOTIATION)
|
|
{
|
|
timeout--;
|
|
ipcom_sleep(1);
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (key == IP_NULL)
|
|
{
|
|
ipcom_printf("l2tp topen: failed to negotiate tunnel: %s"IP_LF,
|
|
ipl2tp_api_errname(status));
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
if ((status = ipl2tp_cmd_tunnel_wait_establish(key, timeout)) != IPL2TP_STATUS_OK)
|
|
{
|
|
if (status != IPL2TP_STATUS_TIMEOUT)
|
|
{
|
|
ipcom_printf("l2tp topen: failed to create tunnel: %s"IP_LF,
|
|
ipl2tp_api_errname(status));
|
|
}
|
|
else
|
|
{
|
|
ipcom_printf("l2tp topen: tunnel still connecting"IP_LF);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ipcom_printf("l2tp topen: tunnel v%u ident=%u successfully opened"IP_LF,
|
|
key->version, key->ident);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ipcom_printf("l2tp topen: tunnel v%u ident=%u opened in passive mode"IP_LF,
|
|
tkey[0].version, tkey[0].ident);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ipcom_printf("l2tp topen: error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
}
|
|
|
|
done:
|
|
/* Release attribute object */
|
|
ipl2tp_attr_delete(&tattr);
|
|
return status == IPL2TP_STATUS_OK ? 0 : -1;
|
|
|
|
usage:
|
|
ipcom_printf("usage: l2tp topen [-3] [-2] [-d] [-w timeout] <host> [ATTRIBUTES]"IP_LF
|
|
"Parameters:"IP_LF
|
|
"-3 L2TP v3"IP_LF
|
|
"-d Open tunnel in DOWN state."IP_LF
|
|
"-w timeout Number of seconds to wait and see if the tunnel was established"IP_LF
|
|
"<host> Host name or IP address."IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_topen
|
|
*===========================================================================
|
|
* Description: Tunnel open command.
|
|
* Parameters: argc - No of arguments.
|
|
* argv - Argument vector.
|
|
* Returns: 0 if success.
|
|
*
|
|
*/
|
|
IP_PUBLIC int
|
|
ipl2tp_cmd_tclose(int argc, char **argv)
|
|
{
|
|
int opt;
|
|
Ipl2tp_key tkey;
|
|
Ipl2tp_status status;
|
|
|
|
ipcom_getopt_clear();
|
|
|
|
/**/
|
|
tkey.version = IPL2TP_VERSION_L2TPV2;
|
|
tkey.ident = 0;
|
|
|
|
/* Get options */
|
|
while ((opt = ipcom_getopt(argc, argv, "23")) != -1)
|
|
{
|
|
switch (opt)
|
|
{
|
|
case '3':
|
|
tkey.version = IPL2TP_VERSION_L2TPV3;
|
|
break;
|
|
case '2':
|
|
tkey.version = IPL2TP_VERSION_L2TPV2;
|
|
break;
|
|
default:
|
|
goto usage;
|
|
}
|
|
}
|
|
|
|
if (ip_optind == argc)
|
|
goto usage;
|
|
|
|
tkey.ident = 0;
|
|
if (ipcom_strcmp(argv[ip_optind], "all") == 0)
|
|
{
|
|
Ipl2tp_key nkey;
|
|
|
|
/* Nothing at all */
|
|
if (ipl2tp_api_tunnel_next(&tkey, &nkey) != IPL2TP_STATUS_OK)
|
|
return 0;
|
|
|
|
do
|
|
{
|
|
/* Copy data */
|
|
ipcom_memcpy(&tkey, &nkey, sizeof(tkey));
|
|
|
|
/* TKEY contains current, get next */
|
|
status = ipl2tp_api_tunnel_next(&tkey, &nkey);
|
|
|
|
ipcom_printf("ipl2tp tclose: disconnecting tunnel v%u %u"IP_LF,
|
|
tkey.version, tkey.ident);
|
|
|
|
/* Close the tunnel */
|
|
ipl2tp_api_tunnel_close(&tkey);
|
|
|
|
/* Next version? */
|
|
if (tkey.version != nkey.version)
|
|
break;
|
|
|
|
} while (status == IPL2TP_STATUS_OK);
|
|
}
|
|
else
|
|
{
|
|
/* Grab the tunnel key */
|
|
tkey.ident = (Ip_u32)ipcom_strtoul(argv[ip_optind], IP_NULL, 10);
|
|
|
|
/* Get id */
|
|
if (tkey.ident == 0)
|
|
{
|
|
ipcom_printf("l2tp tclose: invalid tunnel ID: %s"IP_LF, argv[ip_optind]);
|
|
return -1;
|
|
}
|
|
|
|
/* Close tunnel */
|
|
if ((status = ipl2tp_api_tunnel_close(&tkey)) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("l2tp tclose: error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
}
|
|
}
|
|
|
|
return status == IPL2TP_STATUS_OK ? 0 : -1;
|
|
|
|
usage:
|
|
ipcom_printf("usage: l2tp tclose [-3] <id>"IP_LF
|
|
"Parameters:"IP_LF
|
|
"[-3] L2TP v3"IP_LF
|
|
"<id> Tunnel ID."IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_sopen
|
|
*===========================================================================
|
|
* Description: Session open command.
|
|
* Parameters: argc - No of arguments.
|
|
* argv - Argument vector.
|
|
* Returns: 0 if success.
|
|
*
|
|
*/
|
|
IP_PUBLIC int
|
|
ipl2tp_cmd_sopen(int argc, char **argv)
|
|
{
|
|
Ipl2tp_attrobj sattr = IP_NULL;
|
|
Ipl2tp_attrobj tattr = IP_NULL;
|
|
Ipl2tp_attrobj *attr;
|
|
Ipl2tp_attr_info *tags;
|
|
Ipl2tp_key tkey;
|
|
Ipl2tp_key skey;
|
|
Ipl2tp_status status;
|
|
int use_confreq = 0;
|
|
int proxy = 0;
|
|
int opt;
|
|
char *ifname = IP_NULL;
|
|
Ip_u32 ifindex = 0;
|
|
union Ip_sockaddr_union uaddr;
|
|
int timeout = 10;
|
|
Ip_bool incoming = IP_TRUE;
|
|
|
|
if (argc < 2)
|
|
goto usage;
|
|
|
|
ipcom_getopt_clear();
|
|
|
|
tkey.version = IPL2TP_VERSION_L2TPV2;
|
|
skey.version = IPL2TP_VERSION_L2TPV2;
|
|
/* Get options */
|
|
while ((opt = ipcom_getopt(argc, argv, "o23dxi:w:")) != -1)
|
|
{
|
|
switch (opt)
|
|
{
|
|
case '3':
|
|
tkey.version = IPL2TP_VERSION_L2TPV3;
|
|
skey.version = IPL2TP_VERSION_L2TPV3;
|
|
break;
|
|
case '2':
|
|
tkey.version = IPL2TP_VERSION_L2TPV2;
|
|
skey.version = IPL2TP_VERSION_L2TPV2;
|
|
break;
|
|
case 'o':
|
|
incoming = IP_FALSE;
|
|
break;
|
|
case 'd':
|
|
use_confreq = 1;
|
|
break;
|
|
case 'x':
|
|
proxy = 1;
|
|
break;
|
|
case 'i':
|
|
ifname = ip_optarg;
|
|
break;
|
|
case 'w':
|
|
timeout = (int)ipcom_strtoul(ip_optarg, IP_NULL, 10);
|
|
break;
|
|
default:
|
|
goto usage;
|
|
}
|
|
}
|
|
|
|
/* Tunnel identifier must be supplied */
|
|
if (ip_optind == argc)
|
|
goto usage;
|
|
|
|
/* Get host */
|
|
tkey.ident = 0;
|
|
|
|
if ((ipcom_strchr(argv[ip_optind], '.') == IP_NULL) ||
|
|
(ipl2tp_api_attribute_address_parse(argv[ip_optind], &uaddr) == IP_FALSE))
|
|
{
|
|
/* Get tunnel key, we failed to do uaddr */
|
|
tkey.ident = (Ip_u32)ipcom_strtoul(argv[ip_optind], IP_NULL, 10);
|
|
if (tkey.ident == 0)
|
|
{
|
|
ipcom_printf("l2tp sopen: unknown tunnel identifier %s"IP_LF, argv[ip_optind]);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
ip_optind++;
|
|
|
|
/* Get interface index */
|
|
if (ifname != IP_NULL)
|
|
{
|
|
if ((ifindex = ipcom_if_nametoindex(ifname)) == 0)
|
|
{
|
|
/* Not running yet */
|
|
ipcom_printf("l2tp sopen: cannot find interface %s"IP_LF, ifname);
|
|
return -1;
|
|
}
|
|
|
|
if (ipl2tp_cmd_session_key(ifindex))
|
|
{
|
|
ipcom_printf("l2tp sopen: already tunneling interface %s"IP_LF, ifname);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
/* Set session attributes */
|
|
|
|
/* Do append some default values; Last found value will always win,
|
|
* so even if the user overrides a few, it's OK */
|
|
if (skey.version == IPL2TP_VERSION_L2TPV2)
|
|
{
|
|
if ((status = ipl2tp_attr_iappend(&sattr, IPL2TP_SATTR_SET_TX_CONNECT_SPEED, 38400)) != IPL2TP_STATUS_OK ||
|
|
(status = ipl2tp_attr_iappend(&sattr, IPL2TP_SATTR_SET_FRAMING_TYPE, IPL2TP_MIB_FRAMING_ASYNC)) != IPL2TP_STATUS_OK ||
|
|
(status = ipl2tp_attr_iappend(&sattr, IPL2TP_SATTR_SET_BEARER_TYPE, IPL2TP_MIB_BEARER_ANALOG)) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("l2tp sopen: failed to set default attributes: error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
return -1;
|
|
}
|
|
|
|
/* Append user data ifindex */
|
|
if (ifindex)
|
|
{
|
|
unsigned long ifindexul = (unsigned long)ifindex;
|
|
if ((status = ipl2tp_attr_pappend(&sattr, IPL2TP_SATTR_SET_USER_DATA, (void *)ifindexul)) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("l2tp sopen: failed to set interface: error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Ip_u64 v;
|
|
IP_U64_SET(v,0,38400);
|
|
ipl2tp_attr_iappend64(&sattr, IPL2TP_SATTR_SET_TX_CONNECT_SPEED64, &v);
|
|
}
|
|
|
|
|
|
/* Do go through the remaining attributes */
|
|
tags = ipl2tp_session_tags;
|
|
attr = &sattr;
|
|
for (; ip_optind < argc; ip_optind++)
|
|
{
|
|
Ipl2tp_attr_info *info;
|
|
char *value = IP_NULL;
|
|
|
|
/* Tunnel attribute delimiter */
|
|
if (ipcom_strcmp("--", argv[ip_optind]) == 0)
|
|
{
|
|
if (tkey.ident != 0)
|
|
{
|
|
ipcom_printf("l2tp sopen: when creating tunnels, the address of the peer must be specified."IP_LF);
|
|
ipl2tp_attr_delete(&sattr);
|
|
ipl2tp_attr_delete(&tattr);
|
|
return -1;
|
|
}
|
|
|
|
tags = ipl2tp_tunnel_tags;
|
|
attr = &tattr;
|
|
continue;
|
|
}
|
|
|
|
if ((info = ipl2tp_api_attribute_find(tags, argv[ip_optind], &value)) == IP_NULL)
|
|
{
|
|
ipcom_printf("l2tp sopen: unknown attribute name %s"IP_LF, argv[ip_optind]);
|
|
ipl2tp_attr_delete(&sattr);
|
|
ipl2tp_attr_delete(&tattr);
|
|
return -1;
|
|
}
|
|
|
|
/* Parse the value */
|
|
if (ipl2tp_api_attribute_parse(attr, info, &value) == IP_FALSE)
|
|
{
|
|
ipcom_printf("l2tp sopen: error parsing value"IP_LF);
|
|
ipl2tp_cmd_attr_print_syntax(info);
|
|
ipl2tp_attr_delete(&sattr);
|
|
ipl2tp_attr_delete(&tattr);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (use_confreq)
|
|
{
|
|
static char fr_confreq[] = "FR";
|
|
static char lr_confreq[] = "LR";
|
|
static char ls_confreq[] = "LS";
|
|
|
|
ipl2tp_attr_vappend(&sattr, IPL2TP_SATTR_SET_FIRST_RECEIVED_CONFREQ,
|
|
fr_confreq, sizeof(fr_confreq));
|
|
|
|
ipl2tp_attr_vappend(&sattr, IPL2TP_SATTR_SET_LAST_RECEIVED_CONFREQ,
|
|
lr_confreq, sizeof(lr_confreq));
|
|
|
|
ipl2tp_attr_vappend(&sattr, IPL2TP_SATTR_SET_LAST_SENT_CONFREQ,
|
|
ls_confreq, sizeof(ls_confreq));
|
|
}
|
|
|
|
if (proxy)
|
|
{
|
|
static char proxy_challenge[] = "CH";
|
|
static char proxy_response[] = "RS";
|
|
|
|
if ((status = ipl2tp_attr_vappend(&sattr, IPL2TP_SATTR_SET_PROXY_AUTHEN_CHALLENGE,
|
|
proxy_challenge, sizeof(proxy_challenge))) != IPL2TP_STATUS_OK ||
|
|
(status = ipl2tp_attr_iappend(&sattr, IPL2TP_SATTR_SET_PROXY_AUTHEN_ID, 1)) != IPL2TP_STATUS_OK ||
|
|
(status = ipl2tp_attr_pappend(&sattr, IPL2TP_SATTR_SET_PROXY_AUTHEN_NAME, "NM")) != IPL2TP_STATUS_OK ||
|
|
(status = ipl2tp_attr_vappend(&sattr, IPL2TP_SATTR_SET_PROXY_AUTHEN_RESPONSE,
|
|
proxy_response, sizeof(proxy_response))) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("l2tp sopen: failed to set proxy attributes: error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
}
|
|
}
|
|
|
|
/* Open session */
|
|
if ((status = ipl2tp_api_session_open(&skey, &tkey, tkey.ident? IP_NULL : &uaddr,
|
|
tattr, sattr, incoming)) == IPL2TP_STATUS_OK)
|
|
{
|
|
/* Save session ID */
|
|
if (ifindex != 0)
|
|
{
|
|
Ipl2tp_cmd_session_key *ikey = ipcom_malloc(sizeof(*ikey));
|
|
|
|
ikey->ifindex = ifindex;
|
|
ipcom_memcpy(&ikey->key, &skey, sizeof(skey));
|
|
ipcom_hash_add(ipl2tp_cmd_session_hash_table, ikey);
|
|
}
|
|
|
|
if ((status = ipl2tp_cmd_session_wait_establish(&skey, timeout)) != IPL2TP_STATUS_OK)
|
|
{
|
|
if (status != IPL2TP_STATUS_TIMEOUT)
|
|
{
|
|
ipcom_printf("l2tp sopen: failed to create session: %s"IP_LF,
|
|
ipl2tp_api_errname(status));
|
|
}
|
|
else
|
|
{
|
|
ipcom_printf("l2tp sopen: session still connecting"IP_LF);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ipcom_printf("l2tp sopen: session v%u ident=%u successfully opened"IP_LF, skey.version, skey.ident);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ipcom_printf("l2tp sopen: error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
}
|
|
|
|
/* Release attribute objects */
|
|
ipl2tp_attr_delete(&sattr);
|
|
return status == IPL2TP_STATUS_OK ? 0 : -1;
|
|
|
|
usage:
|
|
ipcom_printf("usage: l2tp sopen [-2] [-3] [-w <timeout>] [-x] [-d] [-o] [-i name] <id|host> [ATTRIBUTE_LIST]"IP_LF
|
|
"Parameters:"IP_LF
|
|
"-d Send dummy PPP CONFREQ packets to LNS."IP_LF
|
|
"-x Send dummy proxy packets to LNS."IP_LF
|
|
"-o Open an outbound tunnel (OCRQ) instead of inbound"IP_LF
|
|
"-2 Version 2"IP_LF
|
|
"-3 Version 3"IP_LF
|
|
"-w <timeout> Number of seconds to wait for establishment"IP_LF
|
|
"<id|host> Tunnel ID or peer address to create session in"IP_LF
|
|
"[ATTRIBUTES] List of attributes and their values"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_sclose
|
|
*===========================================================================
|
|
* Description: Session close command.
|
|
* Parameters: argc - No of arguments.
|
|
* argv - Argument vector.
|
|
* Returns: 0 if success.
|
|
*
|
|
*/
|
|
IP_PUBLIC int
|
|
ipl2tp_cmd_sclose(int argc, char **argv)
|
|
{
|
|
int opt;
|
|
Ipl2tp_key skey;
|
|
Ipl2tp_status status;
|
|
|
|
ipcom_getopt_clear();
|
|
|
|
/**/
|
|
skey.version = IPL2TP_VERSION_L2TPV2;
|
|
skey.ident = 0;
|
|
|
|
/* Get options */
|
|
while ((opt = ipcom_getopt(argc, argv, "23")) != -1)
|
|
{
|
|
switch (opt)
|
|
{
|
|
case '3':
|
|
skey.version = IPL2TP_VERSION_L2TPV3;
|
|
break;
|
|
case '2':
|
|
skey.version = IPL2TP_VERSION_L2TPV2;
|
|
break;
|
|
default:
|
|
goto usage;
|
|
}
|
|
}
|
|
|
|
if (ip_optind == argc)
|
|
goto usage;
|
|
|
|
/* Grab the tunnel key */
|
|
skey.ident = (Ip_u32)ipcom_strtoul(argv[ip_optind], IP_NULL, 10);
|
|
|
|
/* Get id */
|
|
if (skey.ident == 0)
|
|
{
|
|
ipcom_printf("l2tp sclose: invalid session ID: %s"IP_LF, argv[ip_optind]);
|
|
return -1;
|
|
}
|
|
|
|
/* Close session */
|
|
if ((status = ipl2tp_api_session_close(&skey)) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("l2tp sclose: error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
}
|
|
|
|
return status == IPL2TP_STATUS_OK ? 0 : -1;
|
|
|
|
usage:
|
|
ipcom_printf("usage: l2tp sclose [-3] <id>"IP_LF
|
|
"Parameters:"IP_LF
|
|
"[-3] L2TP v3."IP_LF
|
|
"<id> Session ID."IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_attr
|
|
*===========================================================================
|
|
* Description: Attribute command.
|
|
* Parameters: argc - No of arguments.
|
|
* argv - Argument vector.
|
|
* Returns: 0 if success
|
|
*
|
|
*/
|
|
IP_PUBLIC int
|
|
ipl2tp_cmd_attr(int argc, char **argv)
|
|
{
|
|
Ipl2tp_status status = IPL2TP_STATUS_OK;
|
|
int op_val;
|
|
Ipl2tp_attr_info *info;
|
|
char *value = IP_NULL;
|
|
int i;
|
|
|
|
if (argc < 2)
|
|
goto usage;
|
|
|
|
/* Set or get */
|
|
if ((op_val = ipcom_cmd_str_to_key(ipl2tp_cmd_getset, argv[1])) == -1)
|
|
goto usage;
|
|
|
|
if (argc == 2)
|
|
{
|
|
ipl2tp_cmd_attr_list(ipl2tp_tags, op_val == IPL2TP_CMD_SET);
|
|
return 0;
|
|
}
|
|
|
|
for (i = 2; i < argc; i++)
|
|
{
|
|
Ipl2tp_attrobj attr = IP_NULL;
|
|
Ipl2tp_attrobj replies = IP_NULL;
|
|
|
|
/* Try find the attribute */
|
|
if ((info = ipl2tp_api_attribute_find(ipl2tp_tags, argv[i], &value)) == IP_NULL)
|
|
{
|
|
ipcom_printf("Error: Unknown attribute %s"IP_LF, argv[i]);
|
|
return -1;
|
|
}
|
|
|
|
/* Is it a set request but the attribute is RO? */
|
|
if (info->rw == IP_FALSE && op_val == IPL2TP_CMD_SET)
|
|
{
|
|
ipcom_printf("Error: Attempting to 'set' RO attribute %s"IP_LF, argv[2]);
|
|
return -1;
|
|
}
|
|
|
|
if (op_val == IPL2TP_CMD_GET)
|
|
{
|
|
Ipl2tp_attr a;
|
|
get_value:
|
|
ipl2tp_attr_add_query(&attr, info->value);
|
|
if ((status = ipl2tp_api_attribute_get(attr, &replies)) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("Error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
ipl2tp_attr_delete(&attr);
|
|
return -1;
|
|
}
|
|
|
|
/* Delete the query object */
|
|
ipl2tp_attr_delete(&attr);
|
|
|
|
a = ipl2tp_attr_first(replies);
|
|
|
|
if(a == IP_NULL)
|
|
{
|
|
ipl2tp_attr_delete(&replies);
|
|
return -1;
|
|
}
|
|
|
|
if (ipl2tp_attr_status(a) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("Error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
ipl2tp_attr_delete(&replies);
|
|
return -1;
|
|
}
|
|
|
|
/* Print the attribute */
|
|
ipl2tp_cmd_attr_print_attr(a, info);
|
|
ipl2tp_attr_delete(&replies);
|
|
continue;
|
|
}
|
|
|
|
/* Parse the value */
|
|
if (ipl2tp_api_attribute_parse(&attr, info, &value) == IP_FALSE)
|
|
{
|
|
ipcom_printf("Error parsing value"IP_LF);
|
|
ipl2tp_cmd_attr_print_syntax(info);
|
|
return -1;
|
|
}
|
|
|
|
if ((status = ipl2tp_api_attribute_set(attr)) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("Error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
}
|
|
else
|
|
{
|
|
ipl2tp_attr_clear(attr);
|
|
goto get_value;
|
|
}
|
|
|
|
ipl2tp_attr_delete(&attr);
|
|
}
|
|
|
|
return status == IPL2TP_STATUS_OK ? 0 : -1;
|
|
|
|
usage:
|
|
ipcom_printf("usage: l2tp attr get|set <name> [<value>]"IP_LF
|
|
"Parameters:"IP_LF
|
|
"<name> Attribute name."IP_LF
|
|
"<value> Attribute value."IP_LF
|
|
IP_LF);
|
|
ipl2tp_cmd_attr_list(ipl2tp_tags, IP_FALSE);
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_tattr
|
|
*===========================================================================
|
|
* Description: Tunnel attribute command.
|
|
* Parameters: argc - No of arguments.
|
|
* argv - Argument vector.
|
|
* Returns: 0 if success
|
|
*
|
|
*/
|
|
IP_PUBLIC int
|
|
ipl2tp_cmd_tattr(int argc, char **argv)
|
|
{
|
|
int opt;
|
|
Ipl2tp_attrobj attr = IP_NULL;
|
|
Ipl2tp_attrobj replies = IP_NULL;
|
|
Ipl2tp_status status = IPL2TP_STATUS_OK;
|
|
int op_val;
|
|
Ipl2tp_attr_info *info;
|
|
Ipl2tp_key tkey;
|
|
char *value = IP_NULL;
|
|
int i;
|
|
|
|
ipcom_getopt_clear();
|
|
|
|
/**/
|
|
tkey.version = IPL2TP_VERSION_L2TPV2;
|
|
tkey.ident = 0;
|
|
|
|
/* Get options */
|
|
while ((opt = ipcom_getopt(argc, argv, "23")) != -1)
|
|
{
|
|
switch (opt)
|
|
{
|
|
case '3':
|
|
tkey.version = IPL2TP_VERSION_L2TPV3;
|
|
break;
|
|
case '2':
|
|
tkey.version = IPL2TP_VERSION_L2TPV2;
|
|
break;
|
|
default:
|
|
goto usage;
|
|
}
|
|
}
|
|
|
|
if (ip_optind == argc)
|
|
goto usage;
|
|
|
|
/* Set or get */
|
|
if ((op_val = ipcom_cmd_str_to_key(ipl2tp_cmd_getset, argv[ip_optind++])) == -1)
|
|
goto usage;
|
|
|
|
if (argc == ip_optind)
|
|
{
|
|
ipl2tp_cmd_attr_list(ipl2tp_tunnel_tags, op_val == IPL2TP_CMD_SET);
|
|
return 0;
|
|
}
|
|
|
|
if ((argc - ip_optind) < 2)
|
|
goto usage;
|
|
|
|
/* Grab the tunnel key */
|
|
/* Grab the session key */
|
|
if (ipcom_strcasecmp(argv[ip_optind], "default") == 0)
|
|
{
|
|
tkey.ident = 0;
|
|
}
|
|
else
|
|
{
|
|
tkey.ident = (Ip_u32)ipcom_strtoul(argv[ip_optind], IP_NULL, 10);
|
|
}
|
|
|
|
for (i = ip_optind + 1; i < argc; i++)
|
|
{
|
|
/* Try find the attribute */
|
|
if ((info = ipl2tp_api_attribute_find(ipl2tp_tunnel_tags, argv[i], &value)) == IP_NULL)
|
|
{
|
|
ipcom_printf("Error: Unknown attribute %s"IP_LF, argv[i]);
|
|
return -1;
|
|
}
|
|
|
|
/* Is it a set request but the attribute is RO? */
|
|
if (info->rw == IP_FALSE && op_val == IPL2TP_CMD_SET)
|
|
{
|
|
ipcom_printf("Error: Attempting to 'set' RO attribute %s"IP_LF, info->name);
|
|
return -1;
|
|
}
|
|
|
|
if (op_val == IPL2TP_CMD_GET)
|
|
{
|
|
Ipl2tp_attr a;
|
|
get_value:
|
|
ipl2tp_attr_add_query(&attr, info->value);
|
|
if ((status = ipl2tp_api_tunnel_attribute_get(&tkey, attr, &replies)) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("Error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
ipl2tp_attr_delete(&attr);
|
|
return -1;
|
|
}
|
|
|
|
/* Delete the query object */
|
|
ipl2tp_attr_delete(&attr);
|
|
|
|
a = ipl2tp_attr_first(replies);
|
|
|
|
|
|
if (a == IP_NULL || ipl2tp_attr_status(a) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("Error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
ipl2tp_attr_delete(&replies);
|
|
return -1;
|
|
}
|
|
|
|
/* Print the attribute */
|
|
ipl2tp_cmd_attr_print_attr(a, info);
|
|
ipl2tp_attr_delete(&replies);
|
|
continue;
|
|
}
|
|
|
|
/* Set request */
|
|
if (ipl2tp_api_attribute_parse(&attr, info, &value) == IP_FALSE)
|
|
{
|
|
ipcom_printf("Error parsing value"IP_LF);
|
|
ipl2tp_cmd_attr_print_syntax(info);
|
|
return -1;
|
|
}
|
|
|
|
|
|
if ((status = ipl2tp_api_tunnel_attribute_set(&tkey, attr)) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("Error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
}
|
|
else
|
|
{
|
|
ipl2tp_attr_clear(attr);
|
|
goto get_value;
|
|
}
|
|
|
|
ipl2tp_attr_delete(&attr);
|
|
}
|
|
|
|
return status == IPL2TP_STATUS_OK ? 0 : -1;
|
|
|
|
usage:
|
|
ipcom_printf("usage: l2tp tattr [-2] [-3] get|set <id> [ATTRIBUTES]"IP_LF
|
|
"Parameters:"IP_LF
|
|
"[-3] L2TP v3."IP_LF
|
|
"[-2] L2TP v2."IP_LF
|
|
"<id> Tunnel ID or 'default'."IP_LF
|
|
"ATTRIBUTES Attribute list."IP_LF);
|
|
|
|
ipl2tp_cmd_attr_list(ipl2tp_tunnel_tags, IP_FALSE);
|
|
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_sattr
|
|
*===========================================================================
|
|
* Description: Session attribute command.
|
|
* Parameters: argc - No of arguments.
|
|
* argv - Argument vector.
|
|
* Returns: 0 if success
|
|
*
|
|
*/
|
|
IP_PUBLIC int
|
|
ipl2tp_cmd_sattr(int argc, char **argv)
|
|
{
|
|
int opt;
|
|
Ipl2tp_attrobj attr = IP_NULL;
|
|
Ipl2tp_attrobj replies = IP_NULL;
|
|
Ipl2tp_status status = IPL2TP_STATUS_OK;
|
|
Ipl2tp_attr_info *info;
|
|
Ipl2tp_key skey;
|
|
int op_val;
|
|
char *value = IP_NULL;
|
|
int i;
|
|
|
|
ipcom_getopt_clear();
|
|
|
|
/**/
|
|
skey.version = IPL2TP_VERSION_L2TPV2;
|
|
skey.ident = 0;
|
|
|
|
/* Get options */
|
|
while ((opt = ipcom_getopt(argc, argv, "23")) != -1)
|
|
{
|
|
switch (opt)
|
|
{
|
|
case '3':
|
|
skey.version = IPL2TP_VERSION_L2TPV3;
|
|
break;
|
|
case '2':
|
|
skey.version = IPL2TP_VERSION_L2TPV2;
|
|
break;
|
|
default:
|
|
goto usage;
|
|
}
|
|
}
|
|
|
|
if (ip_optind == argc)
|
|
goto usage;
|
|
|
|
/* Set or get */
|
|
if ((op_val = ipcom_cmd_str_to_key(ipl2tp_cmd_getset, argv[ip_optind++])) == -1)
|
|
goto usage;
|
|
|
|
if (ip_optind == argc)
|
|
{
|
|
ipl2tp_cmd_attr_list(ipl2tp_session_tags, op_val == IPL2TP_CMD_SET);
|
|
return 0;
|
|
}
|
|
|
|
if ((argc - ip_optind) < 2)
|
|
goto usage;
|
|
|
|
/* Grab the session key */
|
|
if (ipcom_strcasecmp(argv[ip_optind], "default") == 0)
|
|
{
|
|
skey.ident = 0;
|
|
}
|
|
else
|
|
{
|
|
skey.ident = (Ip_u32)ipcom_strtoul(argv[ip_optind], IP_NULL, 10);
|
|
}
|
|
|
|
for (i = ip_optind + 1; i < argc; i++)
|
|
{
|
|
/* Try find the attribute */
|
|
if ((info = ipl2tp_api_attribute_find(ipl2tp_session_tags, argv[i], &value)) == IP_NULL)
|
|
{
|
|
ipcom_printf("Error: Unknown attribute %s"IP_LF, argv[i]);
|
|
return -1;
|
|
}
|
|
|
|
/* Is it a set request but the attribute is RO? */
|
|
if (info->rw == IP_FALSE && op_val == IPL2TP_CMD_SET)
|
|
{
|
|
ipcom_printf("Error: Attempting to 'set' RO attribute %s"IP_LF, argv[3]);
|
|
return -1;
|
|
}
|
|
|
|
if (op_val == IPL2TP_CMD_GET)
|
|
{
|
|
Ipl2tp_attr a;
|
|
get_value:
|
|
ipl2tp_attr_add_query(&attr, info->value);
|
|
if ((status = ipl2tp_api_session_attribute_get(&skey, attr, &replies)) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("Error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
ipl2tp_attr_delete(&attr);
|
|
return -1;
|
|
}
|
|
|
|
/* Delete the query object */
|
|
ipl2tp_attr_delete(&attr);
|
|
|
|
a = ipl2tp_attr_first(replies);
|
|
|
|
if(a == IP_NULL)
|
|
{
|
|
ipl2tp_attr_delete(&replies);
|
|
return -1;
|
|
}
|
|
|
|
if (ipl2tp_attr_status(a) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("Error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
ipl2tp_attr_delete(&replies);
|
|
return -1;
|
|
}
|
|
|
|
/* Print the attribute */
|
|
ipl2tp_cmd_attr_print_attr(a, info);
|
|
ipl2tp_attr_delete(&replies);
|
|
continue;
|
|
}
|
|
|
|
/* Parse the value */
|
|
if (ipl2tp_api_attribute_parse(&attr, info, &value) == IP_FALSE)
|
|
{
|
|
ipcom_printf("Error parsing value"IP_LF);
|
|
ipl2tp_cmd_attr_print_syntax(info);
|
|
return -1;
|
|
}
|
|
|
|
|
|
if ((status = ipl2tp_api_session_attribute_set(&skey, attr)) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("Error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
}
|
|
else
|
|
{
|
|
ipl2tp_attr_clear(attr);
|
|
goto get_value;
|
|
}
|
|
|
|
ipl2tp_attr_delete(&attr);
|
|
}
|
|
|
|
return status == IPL2TP_STATUS_OK ? 0 : -1;
|
|
|
|
usage:
|
|
ipcom_printf("usage: l2tp sattr [-2] [-3] set|get <id> [ATTRIBUTES]"IP_LF
|
|
"Parameters:"IP_LF
|
|
"[-3] L2TP v3."IP_LF
|
|
"[-2] L2TP v2."IP_LF
|
|
"<id> Session ID or 'default'."IP_LF
|
|
"ATTRIBUTES Attributes"IP_LF);
|
|
|
|
ipl2tp_cmd_attr_list(ipl2tp_session_tags, IP_FALSE);
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_stats
|
|
*===========================================================================
|
|
* Description: Statistics command.
|
|
* Parameters: argc - No of arguments.
|
|
* argv - Argument vector.
|
|
* Returns: 0 if success.
|
|
*
|
|
*/
|
|
IP_PUBLIC int
|
|
ipl2tp_cmd_stats(int argc, char **argv)
|
|
{
|
|
Ipl2tp_status status;
|
|
Ipl2tp_attrobj attr = IP_NULL;
|
|
Ipl2tp_attrobj replies = IP_NULL;
|
|
Ipl2tp_attr a;
|
|
int i;
|
|
|
|
(void)argv;
|
|
|
|
if (argc != 1)
|
|
goto usage;
|
|
|
|
/* Query all global attributes */
|
|
for (i = 0; ipl2tp_tags[i].value != 0; i++)
|
|
ipl2tp_attr_add_query(&attr, ipl2tp_tags[i].value);
|
|
|
|
/* Get attributes */
|
|
if ((status = ipl2tp_api_attribute_get(attr, &replies)) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("Error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
}
|
|
else
|
|
{
|
|
for (a = ipl2tp_attr_first(replies); a != IP_NULL; a = ipl2tp_attr_next(a))
|
|
{
|
|
Ipl2tp_attr_info * info;
|
|
/* */
|
|
if (ipl2tp_attr_status(a) != IPL2TP_STATUS_OK)
|
|
continue;
|
|
|
|
/* Print the attribute */
|
|
if((info = ipl2tp_api_attribute_info(ipl2tp_attr_tag(a)))!= IP_NULL)
|
|
ipl2tp_cmd_attr_print_attr(a, info);
|
|
}
|
|
|
|
ipl2tp_attr_delete(&replies);
|
|
}
|
|
|
|
ipl2tp_attr_delete(&attr);
|
|
|
|
|
|
return status == IPL2TP_STATUS_OK ? 0 : -1;
|
|
|
|
usage:
|
|
ipcom_printf("usage: l2tp stats"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_tstats
|
|
*===========================================================================
|
|
* Description: Tunnel statistics command.
|
|
* Parameters: argc - No of arguments.
|
|
* argv - Argument vector.
|
|
* Returns: 0 if success.
|
|
*
|
|
*/
|
|
IP_PUBLIC int
|
|
ipl2tp_cmd_tstats(int argc,
|
|
char **argv)
|
|
{
|
|
int opt;
|
|
Ipl2tp_status status;
|
|
Ipl2tp_attrobj attr = IP_NULL;
|
|
Ipl2tp_attrobj replies = IP_NULL;
|
|
Ipl2tp_attr a;
|
|
Ipl2tp_key tkey;
|
|
Ip_bool have_ident = IP_FALSE;
|
|
|
|
|
|
ipcom_getopt_clear();
|
|
|
|
/**/
|
|
tkey.version = IPL2TP_VERSION_L2TPV2;
|
|
tkey.ident = 0;
|
|
|
|
/* Get options */
|
|
while ((opt = ipcom_getopt(argc, argv, "23")) != -1)
|
|
{
|
|
switch (opt)
|
|
{
|
|
case '3':
|
|
tkey.version = IPL2TP_VERSION_L2TPV3;
|
|
break;
|
|
case '2':
|
|
tkey.version = IPL2TP_VERSION_L2TPV2;
|
|
break;
|
|
default:
|
|
goto usage;
|
|
}
|
|
}
|
|
|
|
if (ip_optind < argc)
|
|
{
|
|
if (ipcom_strcasecmp(argv[ip_optind], "default") == 0)
|
|
{
|
|
tkey.ident = 0;
|
|
}
|
|
else
|
|
{
|
|
tkey.ident = (Ip_u32)ipcom_strtoul(argv[ip_optind], IP_NULL, 10);
|
|
}
|
|
have_ident = IP_TRUE;
|
|
|
|
}
|
|
|
|
if (have_ident)
|
|
{
|
|
int i;
|
|
|
|
/* Add all non-vector queries */
|
|
for (i = 0; ipl2tp_tunnel_tags[i].value != 0; i++)
|
|
{
|
|
if (ipl2tp_tunnel_tags[i].type != IPL2TP_ATTR_TYPE_VECTOR)
|
|
ipl2tp_attr_add_query(&attr, ipl2tp_tunnel_tags[i].value);
|
|
}
|
|
|
|
if ((status = ipl2tp_api_tunnel_attribute_get(&tkey, attr, &replies)) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("Error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
}
|
|
else
|
|
{
|
|
for (a = ipl2tp_attr_first(replies); a != IP_NULL; a = ipl2tp_attr_next(a))
|
|
{
|
|
Ipl2tp_attr_info* info = IP_NULL;
|
|
|
|
/* */
|
|
if (ipl2tp_attr_status(a) != IPL2TP_STATUS_OK)
|
|
continue;
|
|
|
|
/* Print the attribute */
|
|
if ((info = ipl2tp_api_attribute_info(ipl2tp_attr_tag(a))) != IP_NULL)
|
|
ipl2tp_cmd_attr_print_attr(a, info);
|
|
}
|
|
|
|
ipl2tp_attr_delete(&replies);
|
|
}
|
|
ipl2tp_attr_delete(&attr);
|
|
}
|
|
else do
|
|
{
|
|
Ipl2tp_key nkey;
|
|
|
|
if ((status = ipl2tp_api_tunnel_next(&tkey, &nkey)) != IPL2TP_STATUS_OK)
|
|
break;
|
|
|
|
for (;;)
|
|
{
|
|
/* Don't go past the version */
|
|
if (tkey.version != nkey.version)
|
|
break;
|
|
|
|
ipcom_memcpy(&tkey, &nkey, sizeof(tkey));
|
|
|
|
attr = IP_NULL;
|
|
replies = IP_NULL;
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsState);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsDrainingTunnel);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsControlRecvPackets);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsControlSendPackets);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsControlAckTimeouts);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsControlOutOfSequence);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsControlOutOfWindow);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsInitiated);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelConfigAuthentication);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_HIDE_AVP);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsActiveSessions);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsRemoteHostName);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_tunnelRemoteAddress);
|
|
|
|
if ((status = ipl2tp_api_tunnel_attribute_get(&tkey, attr, &replies)) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("Error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
ipl2tp_attr_delete(&attr);
|
|
return -1;
|
|
}
|
|
|
|
ipcom_printf("v%u %u:"IP_LF, tkey.version, tkey.ident);
|
|
for (a = ipl2tp_attr_first(replies); a != IP_NULL; a = ipl2tp_attr_next(a))
|
|
{
|
|
Ipl2tp_attr_info * info;
|
|
/* */
|
|
if (ipl2tp_attr_status(a) != IPL2TP_STATUS_OK)
|
|
continue;
|
|
|
|
/* Print the attribute */
|
|
if((info = ipl2tp_api_attribute_info(ipl2tp_attr_tag(a)))!= IP_NULL)
|
|
ipl2tp_cmd_attr_print_attr(a, info);
|
|
}
|
|
|
|
ipl2tp_attr_delete(&replies);
|
|
ipl2tp_attr_delete(&attr);
|
|
|
|
if (ipl2tp_api_tunnel_next(&tkey, &nkey) != IPL2TP_STATUS_OK)
|
|
break;
|
|
}
|
|
} while (0);
|
|
|
|
return status == IPL2TP_STATUS_OK ? 0 : -1;
|
|
|
|
usage:
|
|
ipcom_printf("usage: l2tp tstats [-2] [-3] [<id>]"IP_LF
|
|
"Parameters:"IP_LF
|
|
"-2 Version 2"IP_LF
|
|
"-3 Version 3"IP_LF
|
|
"id Tunnel ID or 'default'"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_sstats
|
|
*===========================================================================
|
|
* Description: Session statistics command.
|
|
* Parameters: argc - No of arguments.
|
|
* argv - Argument vector.
|
|
* Returns: 0 if success.
|
|
*
|
|
*/
|
|
IP_PUBLIC int
|
|
ipl2tp_cmd_sstats(int argc, char **argv)
|
|
{
|
|
int opt;
|
|
Ipl2tp_status status;
|
|
Ipl2tp_attrobj attr = IP_NULL;
|
|
Ipl2tp_attrobj replies = IP_NULL;
|
|
Ipl2tp_attr a;
|
|
Ipl2tp_key skey;
|
|
Ipl2tp_key tkey;
|
|
Ip_bool have_ident = IP_FALSE;
|
|
|
|
ipcom_getopt_clear();
|
|
|
|
/**/
|
|
skey.version = IPL2TP_VERSION_L2TPV2;
|
|
tkey.version = IPL2TP_VERSION_L2TPV2;
|
|
skey.ident = 0;
|
|
tkey.ident = 0;
|
|
|
|
/* Get options */
|
|
while ((opt = ipcom_getopt(argc, argv, "23t:")) != -1)
|
|
{
|
|
switch (opt)
|
|
{
|
|
case '3':
|
|
tkey.version = IPL2TP_VERSION_L2TPV3;
|
|
skey.version = IPL2TP_VERSION_L2TPV3;
|
|
break;
|
|
case '2':
|
|
tkey.version = IPL2TP_VERSION_L2TPV2;
|
|
skey.version = IPL2TP_VERSION_L2TPV2;
|
|
break;
|
|
case 't':
|
|
tkey.ident = (Ip_u32)ipcom_strtoul(ip_optarg, IP_NULL, 10);
|
|
break;
|
|
default:
|
|
goto usage;
|
|
}
|
|
}
|
|
|
|
if (ip_optind < argc)
|
|
{
|
|
have_ident = IP_TRUE;
|
|
if (ipcom_strcasecmp(argv[ip_optind], "default") != 0)
|
|
skey.ident = (Ip_u32)ipcom_strtoul(argv[ip_optind], IP_NULL, 10);;
|
|
}
|
|
|
|
if (have_ident)
|
|
{
|
|
int i;
|
|
|
|
/* Add all non-vector queries */
|
|
for (i = 0; ipl2tp_session_tags[i].value != 0; i++)
|
|
{
|
|
if (ipl2tp_session_tags[i].type != IPL2TP_ATTR_TYPE_VECTOR)
|
|
{
|
|
/**/
|
|
ipl2tp_attr_add_query(&attr, ipl2tp_session_tags[i].value);
|
|
}
|
|
}
|
|
|
|
if ((status = ipl2tp_api_session_attribute_get(&skey, attr, &replies)) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("Error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
}
|
|
else
|
|
{
|
|
for (a = ipl2tp_attr_first(replies); a != IP_NULL; a = ipl2tp_attr_next(a))
|
|
{
|
|
Ipl2tp_attr_info* info = IP_NULL;
|
|
|
|
/* */
|
|
if (ipl2tp_attr_status(a) != IPL2TP_STATUS_OK)
|
|
continue;
|
|
|
|
/* Print the attribute */
|
|
if ((info = ipl2tp_api_attribute_info(ipl2tp_attr_tag(a))) != IP_NULL)
|
|
ipl2tp_cmd_attr_print_attr(a, info);
|
|
}
|
|
|
|
ipl2tp_attr_delete(&replies);
|
|
}
|
|
ipl2tp_attr_delete(&attr);
|
|
}
|
|
else do
|
|
{
|
|
Ipl2tp_key nkey;
|
|
|
|
if ((status = ipl2tp_api_session_next(&tkey, IP_NULL, &nkey)) != IPL2TP_STATUS_OK)
|
|
break;
|
|
|
|
for (;;)
|
|
{
|
|
ipcom_memcpy(&skey, &nkey, sizeof(skey));
|
|
|
|
attr = IP_NULL;
|
|
replies = IP_NULL;
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsState);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsCallType);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsCallBearerType);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsFramingType);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsSendSeq);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsRecvSeq);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsTxConnectSpeed);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsRxConnectSpeed);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsCLID);
|
|
ipl2tp_attr_add_query(&attr, IPL2TP_SATTR_GET_l2tpSessionStatsDNIS);
|
|
|
|
if ((status = ipl2tp_api_session_attribute_get(&skey, attr, &replies)) != IPL2TP_STATUS_OK)
|
|
{
|
|
ipcom_printf("Error %d, %s"IP_LF,
|
|
(int)status, ipl2tp_api_errname(status));
|
|
ipl2tp_attr_delete(&attr);
|
|
return -1;
|
|
}
|
|
|
|
ipcom_printf("v%u %u:"IP_LF, skey.version, skey.ident);
|
|
for (a = ipl2tp_attr_first(replies); a != IP_NULL; a = ipl2tp_attr_next(a))
|
|
{
|
|
Ipl2tp_attr_info * info;
|
|
|
|
/* */
|
|
if (ipl2tp_attr_status(a) != IPL2TP_STATUS_OK)
|
|
continue;
|
|
|
|
/* Print the attribute */
|
|
if((info = ipl2tp_api_attribute_info(ipl2tp_attr_tag(a)))!= IP_NULL)
|
|
ipl2tp_cmd_attr_print_attr(a, info);
|
|
}
|
|
|
|
ipl2tp_attr_delete(&replies);
|
|
ipl2tp_attr_delete(&attr);
|
|
|
|
if (ipl2tp_api_session_next(&tkey, &skey, &nkey) != IPL2TP_STATUS_OK)
|
|
break;
|
|
}
|
|
} while (0);
|
|
|
|
return status == IPL2TP_STATUS_OK ? 0 : -1;
|
|
|
|
usage:
|
|
ipcom_printf("usage: l2tp sstats [-2] [-3] [-t tid] [<sid>]"IP_LF
|
|
"Parameters:"IP_LF
|
|
"-2 Version 2"IP_LF
|
|
"-3 Version 3"IP_LF
|
|
"-t <tid> Tunnel ID."IP_LF
|
|
"id Session ID or 'default'"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_poke
|
|
*===========================================================================
|
|
* Description: Setup poke information for incoming messages.
|
|
* Parameters: argc - No of arguments.
|
|
* argv - Argument vector.
|
|
* Returns: 0 if success
|
|
*
|
|
*/
|
|
IP_PUBLIC int
|
|
ipl2tp_cmd_poke(int argc, char **argv)
|
|
{
|
|
int opt;
|
|
|
|
if (argc < 2)
|
|
{
|
|
goto usage;
|
|
}
|
|
|
|
ipcom_getopt_clear();
|
|
|
|
poke_count = 1;
|
|
poke_mtype = 0;
|
|
poke_avp = 0;
|
|
poke_offset = 0;
|
|
poke_value = 0;
|
|
poke_skip = 0;
|
|
ipl2tp_poke_abort[0] = '\0';
|
|
|
|
/* Get options */
|
|
while ((opt = ipcom_getopt(argc, argv, "a:cim:n:o:r:")) != -1)
|
|
{
|
|
switch (opt)
|
|
{
|
|
case 'a':
|
|
poke_avp = ipcom_atoi(ip_optarg);
|
|
break;
|
|
|
|
case 'c':
|
|
poke_count = 0;
|
|
break;
|
|
|
|
case 'i':
|
|
poke_skip = 1;
|
|
break;
|
|
|
|
case 'm':
|
|
poke_mtype = ipcom_atoi(ip_optarg);
|
|
break;
|
|
|
|
case 'n':
|
|
poke_count = ipcom_atoi(ip_optarg);
|
|
break;
|
|
|
|
case 'o':
|
|
poke_offset = ipcom_atoi(ip_optarg);
|
|
break;
|
|
|
|
case 'r':
|
|
strncpy(ipl2tp_poke_abort, ip_optarg, 3);
|
|
ipl2tp_poke_abort[3] = '\0';
|
|
break;
|
|
|
|
default:
|
|
goto usage;
|
|
}
|
|
}
|
|
|
|
if (ip_optind == argc )
|
|
{
|
|
if (poke_count != 0 && poke_skip != 1 && ipl2tp_poke_abort[0] == '\0')
|
|
{
|
|
goto usage;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
poke_value = ipcom_atoi(argv[ip_optind]);
|
|
}
|
|
|
|
return IP_NULL;
|
|
|
|
usage:
|
|
ipcom_printf("usage: l2tp poke [options] <value>"IP_LF
|
|
"Parameters:"IP_LF
|
|
"-a <num> Poke AVP with number <num>."IP_LF
|
|
"-c Clear a pending poke."IP_LF
|
|
"-i Ignore message altogether."IP_LF
|
|
"-m <mtype> Poke messages of type <mtype>. Default all messages."IP_LF
|
|
"-n <num> Set number of messages to poke. Default 1."IP_LF
|
|
"-o <off> Offset in octets from start of message. Default 0."IP_LF
|
|
"-r <code> Return 1 from status callback <code>."IP_LF
|
|
"<value> Value to insert."IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipl2tp_cmd_main
|
|
*===========================================================================
|
|
* Description: Main L2TP command.
|
|
* Parameters: argc - No of arguments.
|
|
* argv - Argument vector.
|
|
* Returns: 0 if success
|
|
*
|
|
*/
|
|
IP_PUBLIC int
|
|
ipl2tp_cmd_main(int argc, char **argv)
|
|
{
|
|
int op_val;
|
|
|
|
/* Check if call for help */
|
|
if (argc <= 1)
|
|
goto usage;
|
|
|
|
/* Set or get */
|
|
if ((op_val = ipcom_cmd_str_to_key(ipl2tp_cmd_cmds, argv[1])) == -1)
|
|
goto usage;
|
|
|
|
switch (op_val)
|
|
{
|
|
#ifdef IPL2TP_ALLOW_CMD_POKE
|
|
case IPL2TP_CMD_POKE:
|
|
return ipl2tp_cmd_poke(argc - 1, argv + 1);
|
|
#endif
|
|
case IPL2TP_CMD_ATTR:
|
|
return ipl2tp_cmd_attr(argc - 1, argv + 1);
|
|
case IPL2TP_CMD_SATTR:
|
|
return ipl2tp_cmd_sattr(argc - 1, argv + 1);
|
|
case IPL2TP_CMD_TATTR:
|
|
return ipl2tp_cmd_tattr(argc - 1, argv + 1);
|
|
case IPL2TP_CMD_STATS:
|
|
return ipl2tp_cmd_stats(argc - 1, argv + 1);
|
|
case IPL2TP_CMD_SSTATS:
|
|
return ipl2tp_cmd_sstats(argc - 1, argv + 1);
|
|
case IPL2TP_CMD_TSTATS:
|
|
return ipl2tp_cmd_tstats(argc - 1, argv + 1);
|
|
case IPL2TP_CMD_TOPEN:
|
|
return ipl2tp_cmd_topen(argc - 1, argv + 1);
|
|
case IPL2TP_CMD_TCLOSE:
|
|
return ipl2tp_cmd_tclose(argc - 1, argv + 1);
|
|
case IPL2TP_CMD_SOPEN:
|
|
return ipl2tp_cmd_sopen(argc - 1, argv + 1);
|
|
case IPL2TP_CMD_SCLOSE:
|
|
return ipl2tp_cmd_sclose(argc - 1, argv + 1);
|
|
default:
|
|
break;
|
|
}
|
|
|
|
usage:
|
|
/* Command summary */
|
|
ipcom_printf("Available l2tp commands:"IP_LF
|
|
#ifdef IPL2TP_ALLOW_CMD_POKE
|
|
" poke - Set poke values"IP_LF
|
|
#endif
|
|
" attr - Set global attributes"IP_LF
|
|
" tattr - Set tunnel attributes"IP_LF
|
|
" sattr - Set session attributes"IP_LF
|
|
" topen - Open a tunnel"IP_LF
|
|
" tclose - Close a tunnel"IP_LF
|
|
" sopen - Open a session"IP_LF
|
|
" sclose - Close a session"IP_LF
|
|
" stats - Show global stats"IP_LF
|
|
" tstats - Show tunnel stats"IP_LF
|
|
" sstats - Show session stats"IP_LF);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|