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

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