1522 lines
54 KiB
C
1522 lines
54 KiB
C
|
|
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipnet_cmd_ip_xfrm.c,v $ $Revision: 1.2.16.3 $
|
|
* $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_cmd_ip_xfrm.c,v $
|
|
* $Author: hxie $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#ifdef IPCOM_KERNEL
|
|
#undef IPCOM_KERNEL
|
|
#endif
|
|
#include "ipnet_config.h"
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES
|
|
****************************************************************************
|
|
*/
|
|
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include <ipcom_clib.h>
|
|
#include <ipcom_cmd.h>
|
|
#include <ipcom_getopt.h>
|
|
#include <ipcom_shell.h>
|
|
#include <ipcom_sysctl.h>
|
|
#include <ipcom_netlink_xfrm.h>
|
|
|
|
#include "ipnet.h"
|
|
#include "ipnet_cmd.h"
|
|
#include "ipnet_ctrl.h"
|
|
#include "ipnet_h.h"
|
|
#include "ipnet_sysctl.h"
|
|
|
|
#include "ipnet_cmd_ip.h"
|
|
|
|
#ifdef IPNET_USE_NETLINK
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 DEFINES
|
|
****************************************************************************
|
|
*/
|
|
|
|
enum
|
|
{
|
|
IPNET_IP_XFRM_MAIN_STATE,
|
|
IPNET_IP_XFRM_MAIN_POLICY,
|
|
IPNET_IP_XFRM_MAIN_MAX,
|
|
IPNET_IP_XFRM_MAIN_MONITOR,
|
|
IPNET_IP_XFRM_MAIN_HELP,
|
|
IPNET_IP_XFRM_MAIN_ALL
|
|
};
|
|
|
|
enum
|
|
{
|
|
IPNET_IP_XFRM_STATE_HELP,
|
|
IPNET_IP_XFRM_STATE_LIST,
|
|
IPNET_IP_XFRM_STATE_ADD,
|
|
IPNET_IP_XFRM_STATE_UPDATE,
|
|
IPNET_IP_XFRM_STATE_DEL,
|
|
IPNET_IP_XFRM_STATE_GET,
|
|
IPNET_IP_XFRM_STATE_DELALL,
|
|
IPNET_IP_XFRM_STATE_FLUSH,
|
|
IPNET_IP_XFRM_STATE_MONITOR
|
|
};
|
|
|
|
enum
|
|
{
|
|
IPNET_IP_XFRM_STATE_ATTRIBUTE_SRC,
|
|
IPNET_IP_XFRM_STATE_ATTRIBUTE_DST,
|
|
IPNET_IP_XFRM_STATE_ATTRIBUTE_SPI,
|
|
IPNET_IP_XFRM_STATE_ATTRIBUTE_REQID,
|
|
IPNET_IP_XFRM_STATE_ATTRIBUTE_PROTO,
|
|
IPNET_IP_XFRM_STATE_ATTRIBUTE_MODE,
|
|
IPNET_IP_XFRM_STATE_ATTRIBUTE_ENC,
|
|
IPNET_IP_XFRM_STATE_ATTRIBUTE_AUTH,
|
|
IPNET_IP_XFRM_STATE_ATTRIBUTE_REPLAY_WINDOW,
|
|
IPNET_IP_XFRM_STATE_ATTRIBUTE_SEQUENCE,
|
|
IPNET_IP_XFRM_STATE_ATTRIBUTE_LIMIT,
|
|
IPNET_IP_XFRM_STATE_ATTRIBUTE_ENCAP
|
|
};
|
|
|
|
enum
|
|
{
|
|
IPNET_IP_XFRM_POLICY_ATTRIBUTE_LIMIT,
|
|
IPNET_IP_XFRM_POLICY_ATTRIBUTE_INDEX,
|
|
IPNET_IP_XFRM_POLICY_ATTRIBUTE_PRIO,
|
|
IPNET_IP_XFRM_POLICY_ATTRIBUTE_PTYPE,
|
|
IPNET_IP_XFRM_POLICY_ATTRIBUTE_DIR,
|
|
IPNET_IP_XFRM_POLICY_ATTRIBUTE_ACTION
|
|
};
|
|
|
|
enum
|
|
{
|
|
IPNET_IP_XFRM_ATTRIBUTE_LIMIT_TIME_SOFT = 32,
|
|
IPNET_IP_XFRM_ATTRIBUTE_LIMIT_TIME_HARD,
|
|
IPNET_IP_XFRM_ATTRIBUTE_LIMIT_TIME_USE_SOFT,
|
|
IPNET_IP_XFRM_ATTRIBUTE_LIMIT_TIME_USE_HARD,
|
|
IPNET_IP_XFRM_ATTRIBUTE_LIMIT_BYTE_SOFT,
|
|
IPNET_IP_XFRM_ATTRIBUTE_LIMIT_BYTE_HARD,
|
|
|
|
IPNET_IP_XFRM_ATTRIBUTE_SELECTOR_SRC,
|
|
IPNET_IP_XFRM_ATTRIBUTE_SELECTOR_DST,
|
|
IPNET_IP_XFRM_ATTRIBUTE_SELECTOR_DEV,
|
|
IPNET_IP_XFRM_ATTRIBUTE_SELECTOR_PROTO,
|
|
IPNET_IP_XFRM_ATTRIBUTE_SELECTOR_SPORT,
|
|
IPNET_IP_XFRM_ATTRIBUTE_SELECTOR_DPORT,
|
|
IPNET_IP_XFRM_ATTRIBUTE_SELECTOR_TYPE,
|
|
IPNET_IP_XFRM_ATTRIBUTE_SELECTOR_CODE
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
typedef struct Ipnet_cmd_ip_module_xfrm_state_filter_struct
|
|
{
|
|
Ip_u64 mask;
|
|
|
|
Ip_u32 proto;
|
|
Ip_u32 mode;
|
|
Ip_u32 reqid;
|
|
Ip_u32 spi;
|
|
|
|
Ipnet_ip_prefix_t src;
|
|
Ipnet_ip_prefix_t dst;
|
|
} Ipnet_cmd_ip_module_xfrm_state_filter_t;
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 EXTERN PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 LOCAL PROTOTYPES
|
|
****************************************************************************
|
|
*/
|
|
IP_STATIC Ip_ssize_t ipnet_cmd_ip_module_xfrm_monitor_modules(Ipnet_ip_config_t *cfg, Ip_u32 modules);
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 DATA
|
|
****************************************************************************
|
|
*/
|
|
|
|
static Ipcom_cmd_int_str_map ipnet_ip_xfrm_main[] =
|
|
{
|
|
{ IPNET_IP_XFRM_MAIN_HELP, "help" },
|
|
{ IPNET_IP_XFRM_MAIN_STATE, "state" },
|
|
{ IPNET_IP_XFRM_MAIN_POLICY, "policy" },
|
|
{ IPNET_IP_XFRM_MAIN_MONITOR, "monitor" },
|
|
{ IPNET_IP_XFRM_MAIN_ALL, "all" },
|
|
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
static Ipcom_cmd_int_str_map ipnet_ip_xfrm_state[] =
|
|
{
|
|
{ IPNET_IP_XFRM_STATE_HELP, "help" },
|
|
|
|
{ IPNET_IP_XFRM_STATE_LIST, "show" },
|
|
{ IPNET_IP_XFRM_STATE_LIST, "list" },
|
|
{ IPNET_IP_XFRM_STATE_LIST, "lst" },
|
|
{ IPNET_IP_XFRM_STATE_ADD, "add" },
|
|
{ IPNET_IP_XFRM_STATE_UPDATE, "update" },
|
|
{ IPNET_IP_XFRM_STATE_GET, "get" },
|
|
{ IPNET_IP_XFRM_STATE_DEL, "del" },
|
|
{ IPNET_IP_XFRM_STATE_DEL, "delete" },
|
|
{ IPNET_IP_XFRM_STATE_DELALL, "delall" },
|
|
{ IPNET_IP_XFRM_STATE_DELALL, "deleteall" },
|
|
{ IPNET_IP_XFRM_STATE_FLUSH, "flush" },
|
|
{ IPNET_IP_XFRM_STATE_MONITOR, "monitor" },
|
|
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
static Ipcom_cmd_int_str_map ipnet_ip_xfrm_state_attributes[] =
|
|
{
|
|
{ IPNET_IP_XFRM_STATE_ATTRIBUTE_SRC, "src" },
|
|
{ IPNET_IP_XFRM_STATE_ATTRIBUTE_DST, "dst" },
|
|
{ IPNET_IP_XFRM_STATE_ATTRIBUTE_SPI, "spi" },
|
|
{ IPNET_IP_XFRM_STATE_ATTRIBUTE_REQID, "reqid" },
|
|
{ IPNET_IP_XFRM_STATE_ATTRIBUTE_PROTO, "proto" },
|
|
{ IPNET_IP_XFRM_STATE_ATTRIBUTE_MODE, "mode" },
|
|
{ IPNET_IP_XFRM_STATE_ATTRIBUTE_ENC, "enc" },
|
|
{ IPNET_IP_XFRM_STATE_ATTRIBUTE_AUTH, "auth" },
|
|
{ IPNET_IP_XFRM_STATE_ATTRIBUTE_ENCAP, "encap" },
|
|
{ IPNET_IP_XFRM_STATE_ATTRIBUTE_SEQUENCE, "seq" },
|
|
{ IPNET_IP_XFRM_STATE_ATTRIBUTE_REPLAY_WINDOW, "replay-window" },
|
|
{ IPNET_IP_XFRM_STATE_ATTRIBUTE_LIMIT, "limit" },
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
|
|
static Ipcom_cmd_int_str_map ipnet_ip_xfrm_limit_attributes[] =
|
|
{
|
|
{ IPNET_IP_XFRM_ATTRIBUTE_LIMIT_TIME_SOFT, "time-soft" },
|
|
{ IPNET_IP_XFRM_ATTRIBUTE_LIMIT_TIME_HARD, "time-hard" },
|
|
{ IPNET_IP_XFRM_ATTRIBUTE_LIMIT_TIME_USE_SOFT, "time-use-soft" },
|
|
{ IPNET_IP_XFRM_ATTRIBUTE_LIMIT_TIME_USE_HARD, "time-use-hard" },
|
|
{ IPNET_IP_XFRM_ATTRIBUTE_LIMIT_BYTE_SOFT, "byte-soft" },
|
|
{ IPNET_IP_XFRM_ATTRIBUTE_LIMIT_BYTE_HARD, "byte-hard" },
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
Ipcom_cmd_int_str_map ipnet_ip_xfrm_proto[] =
|
|
{
|
|
{ IP_IPPROTO_ESP, "esp" },
|
|
{ IP_IPPROTO_AH, "ah" },
|
|
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
Ipcom_cmd_int_str_map ipnet_ip_xfrm_mode[] =
|
|
{
|
|
{ IP_XFRM_MODE_TRANSPORT, "transport" },
|
|
{ IP_XFRM_MODE_TUNNEL, "tunnel" },
|
|
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
|
|
#define IP_XFRM_ENCAP_ESPINUDP_NONIKE 1
|
|
#define IP_XFRM_ENCAP_ESPINUDP 2
|
|
Ipcom_cmd_int_str_map ipnet_ip_xfrm_encap_type[] =
|
|
{
|
|
{ IP_XFRM_ENCAP_ESPINUDP_NONIKE, "espinudp-nonike" },
|
|
{ IP_XFRM_ENCAP_ESPINUDP, "espinudp" },
|
|
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
Ipcom_cmd_int_str_map ipnet_ip_xfrm_policy_dir[] =
|
|
{
|
|
{ IP_XFRM_POLICY_IN, "in" },
|
|
{ IP_XFRM_POLICY_OUT, "out" },
|
|
{ IP_XFRM_POLICY_FWD, "fwd" },
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
Ipcom_cmd_int_str_map ipnet_ip_xfrm_policy_ptype[] =
|
|
{
|
|
{ IP_XFRM_POLICY_TYPE_MAIN, "main" },
|
|
{ IP_XFRM_POLICY_TYPE_SUB, "sub" },
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
Ipcom_cmd_int_str_map ipnet_ip_xfrm_policy_action[] =
|
|
{
|
|
{ IP_XFRM_POLICY_ALLOW, "allow" },
|
|
{ IP_XFRM_POLICY_BLOCK, "block" },
|
|
{ -1, IP_NULL },
|
|
};
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 STATIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
/** COMMON FUNCTIONS **/
|
|
|
|
IP_STATIC void
|
|
ipnet_cmd_ip_module_xfrm_init_lft(struct Ip_xfrm_lifetime_cfg *lft)
|
|
{
|
|
lft->hard_byte_limit = IP_XFRM_INF;
|
|
lft->hard_packet_limit = IP_XFRM_INF;
|
|
lft->soft_byte_limit = IP_XFRM_INF;
|
|
lft->soft_packet_limit = IP_XFRM_INF;
|
|
}
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_module_xfrm_parse_lft(Ipnet_ip_config_t *cfg, struct Ip_xfrm_lifetime_cfg *lft)
|
|
{
|
|
char *sarg;
|
|
int arg;
|
|
Ip_u64 uarg64;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "limit <LIMIT>");
|
|
|
|
if (IP_FALSE == ipnet_ip_str_to_key(&arg, ipnet_ip_xfrm_limit_attributes, sarg))
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_XFRM_ATTRIBUTE_LIMIT_TIME_SOFT:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "limit time-soft <time>", arg))
|
|
return -1;
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint64(&uarg64, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "limit time-soft <time>");
|
|
lft->soft_add_expires_seconds = uarg64;
|
|
break;
|
|
|
|
case IPNET_IP_XFRM_ATTRIBUTE_LIMIT_TIME_HARD:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "limit time-hard <time>", arg))
|
|
return -1;
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint64(&uarg64, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "limit time-hard <time>");
|
|
lft->hard_add_expires_seconds = uarg64;
|
|
break;
|
|
|
|
case IPNET_IP_XFRM_ATTRIBUTE_LIMIT_TIME_USE_SOFT:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "limit time-use-soft <time>", arg))
|
|
return -1;
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint64(&uarg64, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "limit time-use-soft <time>");
|
|
lft->soft_use_expires_seconds = uarg64;
|
|
break;
|
|
|
|
case IPNET_IP_XFRM_ATTRIBUTE_LIMIT_TIME_USE_HARD:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "limit time-use-hard <time>", arg))
|
|
return -1;
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint64(&uarg64, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "limit time-use-hard <time>");
|
|
lft->hard_use_expires_seconds = uarg64;
|
|
break;
|
|
|
|
case IPNET_IP_XFRM_ATTRIBUTE_LIMIT_BYTE_SOFT:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "limit byte-soft <bytes>", arg))
|
|
return -1;
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint64(&uarg64, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "limit byte-soft <bytes>");
|
|
lft->soft_byte_limit = uarg64;
|
|
break;
|
|
|
|
case IPNET_IP_XFRM_ATTRIBUTE_LIMIT_BYTE_HARD:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "limit byte-hard <bytes>", arg))
|
|
return -1;
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint64(&uarg64, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "limit byte-hard <bytes>");
|
|
lft->hard_byte_limit = uarg64;
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/** STATE FUNCTIONS **/
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_xfrm_state_usage(Ipnet_ip_config_t *cfg, int ret)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "NAME"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip xfrm state - Display and modify the IPSEC security association"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "SYNOPSIS"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip xfrm state list [mode <tunnel|transport>] [proto <esp|ah|num>]"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " [src <source>] [dst <dest>] [reqid <reqid>] [spi <spi>]"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip xfrm state help"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "DESCRIPTION"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " help Display usage information"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " list Display security associations."IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " Selector Decription:"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " src <src> - Source address"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " dst <dst> - Destination address"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " mode <tunnel|transport> - SA mode"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " reqid <reqid> - Request ID"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " spi <spi> - Security index"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " proto <esp|ah|num> - Protocol type"IP_LF);
|
|
return ret;
|
|
}
|
|
|
|
IP_STATIC struct Ip_xfrm_usersa_info *
|
|
ipnet_cmd_ip_module_xfrm_state_hdr(Ipnet_ip_handle_msg_t *nlmsg)
|
|
{
|
|
Ip_size_t rta_off;
|
|
struct Ip_xfrm_usersa_info *sa_info = IP_NLMSG_DATA(nlmsg->hdr);
|
|
|
|
switch (nlmsg->hdr->nlmsg_type)
|
|
{
|
|
case IP_XFRM_MSG_DELSA:
|
|
rta_off = sizeof(struct Ip_xfrm_usersa_id);
|
|
break;
|
|
case IP_XFRM_MSG_EXPIRE:
|
|
rta_off = sizeof(struct Ip_xfrm_user_expire);
|
|
break;
|
|
default:
|
|
rta_off = sizeof(struct Ip_xfrm_usersa_info);
|
|
break;
|
|
}
|
|
|
|
ipnet_ip_parse_reply(nlmsg, IP_XFRMA_MAX, rta_off);
|
|
|
|
if (nlmsg->hdr->nlmsg_type == IP_XFRM_MSG_DELSA)
|
|
sa_info = IP_RTA_DATA(nlmsg->rta[IP_XFRMA_SA]);
|
|
|
|
return sa_info;
|
|
}
|
|
|
|
IP_STATIC char *
|
|
ipnet_cmd_ip_module_xfrm_state_print_inf(char *buf, Ip_u64 val)
|
|
{
|
|
if (val == IP_XFRM_INF)
|
|
return "(INF)";
|
|
|
|
ipcom_sprintf(buf, "%llu", val);
|
|
return buf;
|
|
}
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_module_xfrm_state_print(Ipnet_ip_config_t *cfg, Ipnet_ip_handle_msg_t *nlmsg)
|
|
{
|
|
char buf[128];
|
|
struct Ip_xfrm_usersa_info *sa_info;
|
|
unsigned int i;
|
|
struct Ip_xfrm_algo *alginfo;
|
|
|
|
if (cfg->is_silent)
|
|
return 0;
|
|
|
|
sa_info = ipnet_cmd_ip_module_xfrm_state_hdr(nlmsg);
|
|
switch (nlmsg->hdr->nlmsg_type)
|
|
{
|
|
case IP_XFRM_MSG_DELSA:
|
|
ipnet_ip_stdio_printf(cfg, "Deleted ");
|
|
break;
|
|
case IP_XFRM_MSG_EXPIRE:
|
|
ipnet_ip_stdio_printf(cfg, "Expired ");
|
|
break;
|
|
case IP_XFRM_MSG_UPDSA:
|
|
ipnet_ip_stdio_printf(cfg, "Updated ");
|
|
break;
|
|
}
|
|
|
|
ipnet_ip_stdio_printf(cfg, "src %s", ipnet_ip_format_host(sa_info->family, &sa_info->saddr, -1, buf, sizeof(buf), "any"));
|
|
ipnet_ip_stdio_printf(cfg, " dst %s", ipnet_ip_format_host(sa_info->family, &sa_info->id.daddr, -1, buf, sizeof(buf), "any"));
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, "\tproto %s", ipnet_ip_key_to_str(ipnet_ip_xfrm_proto, sa_info->id.proto, buf, sizeof(buf)));
|
|
ipnet_ip_stdio_printf(cfg, " spi 0x%08x", sa_info->id.spi);
|
|
ipnet_ip_stdio_printf(cfg, " reqid %u", sa_info->reqid);
|
|
ipnet_ip_stdio_printf(cfg, " mode %s", ipnet_ip_key_to_str(ipnet_ip_xfrm_mode, sa_info->mode, buf, sizeof(buf)));
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, "\treplay-window %u", sa_info->replay_window);
|
|
if (cfg->show_stats)
|
|
ipnet_ip_stdio_printf(cfg, " seq %u", sa_info->seq);
|
|
|
|
if (IP_NULL != nlmsg->rta[IP_XFRMA_ALG_CRYPT])
|
|
{
|
|
alginfo = IP_RTA_DATA(nlmsg->rta[IP_XFRMA_ALG_CRYPT]);
|
|
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, "\tenc %s", alginfo->alg_name);
|
|
|
|
if (0 != alginfo->alg_key_len)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, " 0x");
|
|
for (i = 0; i < alginfo->alg_key_len/8; i++)
|
|
ipnet_ip_stdio_printf(cfg, "%02x", (Ip_u8)alginfo->alg_key[i]);
|
|
}
|
|
}
|
|
|
|
|
|
if (IP_NULL != nlmsg->rta[IP_XFRMA_ALG_AUTH])
|
|
{
|
|
alginfo = IP_RTA_DATA(nlmsg->rta[IP_XFRMA_ALG_AUTH]);
|
|
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, "\tauth %s", alginfo->alg_name);
|
|
|
|
if (0 != alginfo->alg_key_len)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, " 0x");
|
|
for (i = 0; i < alginfo->alg_key_len/8; i++)
|
|
ipnet_ip_stdio_printf(cfg, "%02x", (Ip_u8)alginfo->alg_key[i]);
|
|
}
|
|
}
|
|
|
|
if (IP_NULL != nlmsg->rta[IP_XFRMA_ENCAP])
|
|
{
|
|
struct Ip_xfrm_encap_tmpl *encap = IP_RTA_DATA(nlmsg->rta[IP_XFRMA_ENCAP]);
|
|
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, "\tencap type %s", ipnet_ip_key_to_str(ipnet_ip_xfrm_encap_type, encap->encap_type, buf, sizeof(buf)));
|
|
ipnet_ip_stdio_printf(cfg, " sport %u dport %u", IP_GET_NTOHS(&encap->encap_sport), IP_GET_NTOHS(&encap->encap_dport));
|
|
ipnet_ip_stdio_printf(cfg, " addr %s", ipnet_ip_format_host(sa_info->family, &encap->encap_oa, -1, buf, sizeof(buf), IP_NULL));
|
|
}
|
|
|
|
if (cfg->show_stats)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, "\tlifetime config:");
|
|
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, "\t limit: soft %s(bytes),", ipnet_cmd_ip_module_xfrm_state_print_inf(buf, sa_info->lft.soft_byte_limit));
|
|
ipnet_ip_stdio_printf(cfg, " hard %s(bytes)", ipnet_cmd_ip_module_xfrm_state_print_inf(buf, sa_info->lft.hard_byte_limit));
|
|
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, "\t expire add: soft %llu(sec), hard %llu(sec)", (unsigned long long) sa_info->lft.soft_add_expires_seconds, (unsigned long long) sa_info->lft.hard_add_expires_seconds);
|
|
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, "\t expire use: soft %llu(sec), hard %llu(sec)", (unsigned long long) sa_info->lft.soft_use_expires_seconds, (unsigned long long) sa_info->lft.hard_use_expires_seconds);
|
|
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, "\tlifetime current:");
|
|
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, "\t %llu(bytes)", (unsigned long long)sa_info->curlft.bytes);
|
|
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, "\t add %u use %u", (Ip_u32)sa_info->curlft.add_time, (Ip_u32)sa_info->curlft.use_time);
|
|
}
|
|
|
|
if (nlmsg->hdr->nlmsg_type == IP_XFRM_MSG_EXPIRE)
|
|
{
|
|
struct Ip_xfrm_user_expire *xexp = (struct Ip_xfrm_user_expire *)sa_info;
|
|
|
|
ipnet_ip_stdio_printf(cfg, cfg->oneline);
|
|
ipnet_ip_stdio_printf(cfg, "\thard %u", xexp->hard);
|
|
}
|
|
|
|
ipnet_ip_stdio_printf(cfg, IP_LF);
|
|
return 0;
|
|
}
|
|
|
|
IP_STATIC void
|
|
ipnet_cmd_ip_module_xfrm_state_filter(Ipnet_ip_config_t *cfg, Ipnet_cmd_ip_module_xfrm_state_filter_t *filter)
|
|
{
|
|
Ipnet_ip_handle_msg_t *nlmsg, *nnlmsg;
|
|
struct Ip_xfrm_usersa_info *sa_info;
|
|
|
|
nlmsg = IPCOM_LIST_FIRST(&cfg->handle->replies);
|
|
for ( ; IP_NULL != nlmsg; nlmsg = nnlmsg)
|
|
{
|
|
unsigned i;
|
|
|
|
nnlmsg = IPCOM_LIST_NEXT(&nlmsg->next);
|
|
|
|
sa_info = ipnet_cmd_ip_module_xfrm_state_hdr(nlmsg);
|
|
for (i = 0; i < sizeof(filter->mask) * 8; i++)
|
|
{
|
|
if (IP_BIT_ISSET(filter->mask, IP_BIT_UVAL64(i)))
|
|
{
|
|
switch (i)
|
|
{
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_SRC:
|
|
if (filter->src.prefix_family != sa_info->family)
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
goto next_message;
|
|
}
|
|
|
|
if (IP_FALSE == ipnet_ip_match_prefix(&filter->src, &sa_info->saddr))
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
goto next_message;
|
|
}
|
|
|
|
break;
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_DST:
|
|
if (filter->dst.prefix_family != sa_info->family)
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
goto next_message;
|
|
}
|
|
|
|
if (IP_FALSE == ipnet_ip_match_prefix(&filter->dst, &sa_info->id.daddr))
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
goto next_message;
|
|
}
|
|
|
|
break;
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_SPI:
|
|
if (filter->spi != sa_info->id.spi)
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
goto next_message;
|
|
}
|
|
break;
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_REQID:
|
|
if (filter->reqid != sa_info->reqid)
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
goto next_message;
|
|
}
|
|
break;
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_PROTO:
|
|
if (filter->proto != sa_info->id.proto)
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
goto next_message;
|
|
}
|
|
break;
|
|
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_MODE:
|
|
if (filter->mode != sa_info->mode)
|
|
{
|
|
ipnet_ip_free_reply(nlmsg);
|
|
goto next_message;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
next_message:
|
|
IP_NOOP;
|
|
}
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_xfrm_state_list_delall(Ipnet_ip_config_t *cfg, Ipnet_cmd_ip_module_xfrm_state_filter_t *filter)
|
|
{
|
|
char *sarg;
|
|
int arg;
|
|
|
|
/* Time to go through the filter parameters */
|
|
while (IP_FALSE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
{
|
|
if (IP_FALSE == ipnet_ip_str_to_key(&arg, ipnet_ip_xfrm_state_attributes, sarg))
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
|
|
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_SRC:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "src <source>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_prefix(cfg->family, &filter->src, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "src <source>");
|
|
|
|
break;
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_DST:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "dst <destination>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_prefix(cfg->family, &filter->dst, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "dst <destination>");
|
|
|
|
break;
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_SPI:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "spi <spi>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&filter->spi, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "spi <spi>");
|
|
break;
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_REQID:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "reqid <reqid>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&filter->reqid, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "reqid <reqid>");
|
|
break;
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_PROTO:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "proto <num|esp|ah>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&filter->proto, cfg, ipnet_ip_xfrm_proto))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "proto <num|esp|ah>");
|
|
break;
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_MODE:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "mode <tunnel|transport>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&filter->mode, cfg, ipnet_ip_xfrm_mode))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "mode <tunnel|transport>");
|
|
break;
|
|
default:
|
|
/* Dont handle this keyword in list/flush */
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
|
|
}
|
|
}
|
|
|
|
/* All parameters are parsed
|
|
* Store the argument match mask
|
|
*/
|
|
ipcom_memcpy(&filter->mask, &cfg->mask, sizeof(filter->mask));
|
|
|
|
return 0;
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_xfrm_state_list(Ipnet_ip_config_t *cfg)
|
|
{
|
|
Ipnet_ip_handle_msg_t *nlmsg;
|
|
Ipnet_cmd_ip_module_xfrm_state_filter_t filter;
|
|
Ip_ssize_t ret = ipnet_cmd_ip_module_xfrm_state_list_delall(cfg, &filter);
|
|
|
|
/* Dump the NETLINK information */
|
|
if (0 <= (ret = ipnet_ip_dump_netlink(cfg, cfg->handle, IP_XFRM_MSG_GETSA, cfg->family, cfg->core, IP_TRUE)))
|
|
{
|
|
ipnet_cmd_ip_module_xfrm_state_filter(cfg, &filter);
|
|
for (nlmsg = IPCOM_LIST_FIRST(&cfg->handle->replies); IP_NULL != nlmsg; nlmsg = IPCOM_LIST_NEXT(&nlmsg->next))
|
|
ipnet_cmd_ip_module_xfrm_state_print(cfg, nlmsg);
|
|
}
|
|
else
|
|
ipnet_ip_stdio_printf(cfg, "Unable to dump security association table, error = %d"IP_LF, (int)ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_xfrm_state_delall(Ipnet_ip_config_t *cfg)
|
|
{
|
|
Ipnet_ip_handle_msg_t *nlmsg;
|
|
Ipnet_cmd_ip_module_xfrm_state_filter_t filter;
|
|
Ip_ssize_t ret = ipnet_cmd_ip_module_xfrm_state_list_delall(cfg, &filter);
|
|
|
|
/* Dump the NETLINK information */
|
|
if (0 <= (ret = ipnet_ip_dump_netlink(cfg, cfg->handle, IP_XFRM_MSG_GETSA, cfg->family, cfg->core, IP_TRUE)))
|
|
{
|
|
ipnet_cmd_ip_module_xfrm_state_filter(cfg, &filter);
|
|
for (nlmsg = IPCOM_LIST_FIRST(&cfg->handle->replies); IP_NULL != nlmsg; nlmsg = IPCOM_LIST_NEXT(&nlmsg->next))
|
|
{
|
|
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
|
|
struct Ip_xfrm_usersa_id *sa_id;
|
|
struct Ip_xfrm_usersa_info *sa_info;
|
|
|
|
ipcom_memset(nlh, 0, sizeof(*nlh));
|
|
nlh->nlmsg_flags = IP_NLM_F_REQUEST|IP_NLM_F_ACK;
|
|
nlh->nlmsg_type = IP_XFRM_MSG_DELSA;
|
|
nlh->nlmsg_len = IP_NLMSG_LENGTH(0);
|
|
|
|
/* Start of the routing message */
|
|
sa_id = (struct Ip_xfrm_usersa_id *)IP_NLMSG_DATA(nlh);
|
|
ipcom_memset(sa_id, 0, sizeof(*sa_id));
|
|
|
|
/* Move past the routing header */
|
|
nlh->nlmsg_len = (Ip_u32) (IP_NLMSG_ALIGN(nlh->nlmsg_len) + sizeof(*sa_id));
|
|
|
|
sa_info = IP_NLMSG_DATA(nlmsg->hdr);
|
|
sa_id->family = sa_info->family;
|
|
sa_id->proto = sa_info->id.proto;
|
|
sa_id->spi = sa_info->id.spi;
|
|
ipcom_memcpy(&sa_id->daddr, &sa_info->id.daddr, sizeof(sa_info->id.daddr));
|
|
ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_XFRMA_SRCADDR, &sa_info->saddr, sizeof(sa_info->saddr));
|
|
|
|
if (0 > (ret = ipnet_ip_request_netlink(cfg, cfg->handle, IP_NULL, cfg->core, IP_TRUE)))
|
|
ipnet_ip_stdio_printf(cfg, "XFRM answers: %s"IP_LF, ipcom_strerror(-(int)ret));
|
|
else
|
|
ipnet_cmd_ip_module_xfrm_state_print(cfg, nlmsg);
|
|
}
|
|
}
|
|
else
|
|
ipnet_ip_stdio_printf(cfg, "Unable to dump security association table, error = %d"IP_LF, (int)ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
IP_STATIC Ip_size_t
|
|
ipnet_cmd_ip_module_xfrm_parse_hexkey(char *key, Ip_u8 *key_buf)
|
|
{
|
|
Ip_size_t key_len = ipcom_strlen(key);
|
|
Ip_size_t alg_len = 0;
|
|
|
|
if (key_len > 2 && ipcom_strncmp(key, "0x", 2) == 0)
|
|
{
|
|
key_len -= 2;
|
|
key += 2;
|
|
|
|
alg_len = (key_len + 1) / 2;
|
|
if (IP_NULL != key_buf)
|
|
{
|
|
char values[3];
|
|
unsigned int i, off;
|
|
|
|
values[2] = '\0';
|
|
|
|
off = i = 0;
|
|
if ((key_len & 1) != 0)
|
|
{
|
|
values[0] = '0';
|
|
values[1] = key[i++];
|
|
|
|
key_buf[off++] = (Ip_u8)ipcom_strtoul(&values[0], IP_NULL, 16);
|
|
}
|
|
|
|
for (; i < key_len; i += 2)
|
|
{
|
|
values[0] = key[i];
|
|
values[1] = key[i + 1];
|
|
key_buf[off++] = (Ip_u8)ipcom_strtoul(&values[0], IP_NULL, 16);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
alg_len = key_len;
|
|
if (IP_NULL != key_buf)
|
|
ipcom_memcpy(key_buf, key, alg_len);
|
|
}
|
|
|
|
return alg_len;
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_xfrm_state_add_update_modify(Ipnet_ip_config_t *cfg)
|
|
{
|
|
char *sarg;
|
|
int arg;
|
|
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
|
|
struct Ip_xfrm_usersa_info *sa_info;
|
|
struct Ip_rtattr *rta;
|
|
Ip_u32 uarg;
|
|
|
|
ipcom_memset(nlh, 0, sizeof(*nlh));
|
|
nlh->nlmsg_len = IP_NLMSG_LENGTH(0);
|
|
|
|
/* Start of the routing message */
|
|
sa_info = (struct Ip_xfrm_usersa_info *)IP_NLMSG_DATA(nlh);
|
|
ipcom_memset(sa_info, 0, sizeof(*sa_info));
|
|
sa_info->family = cfg->family;
|
|
|
|
/* Move past the routing header */
|
|
nlh->nlmsg_len = (Ip_u32) (IP_NLMSG_ALIGN(nlh->nlmsg_len) + sizeof(*sa_info));
|
|
|
|
ipnet_cmd_ip_module_xfrm_init_lft(&sa_info->lft);
|
|
|
|
/* Time to go through the filter parameters */
|
|
while (IP_FALSE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
{
|
|
Ipnet_ip_prefix_t addr;
|
|
|
|
if (IP_FALSE == ipnet_ip_str_to_key(&arg, ipnet_ip_xfrm_state_attributes, sarg))
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
|
|
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_SRC:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "src <source>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_prefix(sa_info->family, &addr, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "src <source>");
|
|
|
|
if (sa_info->family == IP_AF_UNSPEC)
|
|
sa_info->family = addr.prefix_family;
|
|
|
|
ipcom_memcpy(&sa_info->saddr, &addr.prefix, addr.prefix_max/8);
|
|
break;
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_DST:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "dst <destination>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_prefix(sa_info->family, &addr, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "dst <destination>");
|
|
|
|
if (sa_info->family == IP_AF_UNSPEC)
|
|
sa_info->family = addr.prefix_family;
|
|
|
|
ipcom_memcpy(&sa_info->id.daddr, &addr.prefix, addr.prefix_max/8);
|
|
break;
|
|
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_SPI:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "spi <spi>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "spi <spi>");
|
|
|
|
sa_info->id.spi = uarg;
|
|
break;
|
|
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_REQID:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "reqid <reqid>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "reqid <reqid>");
|
|
|
|
sa_info->reqid = uarg;
|
|
break;
|
|
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_PROTO:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "proto <num|ah|esp>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, ipnet_ip_xfrm_proto))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "proto <num|ah|esp>");
|
|
|
|
sa_info->id.proto = (Ip_u8)uarg;
|
|
break;
|
|
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_REPLAY_WINDOW:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "replay-window <num>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "replay-window <num>");
|
|
|
|
sa_info->replay_window = (Ip_u8)uarg;
|
|
break;
|
|
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_SEQUENCE:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "seq <num>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "seq <num>");
|
|
|
|
sa_info->seq = uarg;
|
|
break;
|
|
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_MODE:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "proto <tunnel|transport>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, ipnet_ip_xfrm_mode))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "proto <tunnel|transport>");
|
|
|
|
sa_info->mode = (Ip_u8) uarg;
|
|
break;
|
|
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_ENC:
|
|
{
|
|
char *alg_name, *alg_key;
|
|
struct Ip_xfrm_algo *alginfo;
|
|
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "enc <algorithm> <key>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&alg_name, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "enc <algorithm> <key>");
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&alg_key, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "enc <algorithm> <key>");
|
|
|
|
/* Time to create the ENC attribute */
|
|
rta = ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_XFRMA_ALG_CRYPT, IP_NULL,
|
|
ip_offsetof(struct Ip_xfrm_algo, alg_key) + ipnet_cmd_ip_module_xfrm_parse_hexkey(alg_key, IP_NULL));
|
|
alginfo = IP_RTA_DATA(rta);
|
|
ipcom_strncpy(alginfo->alg_name, alg_name, sizeof(alginfo->alg_name));
|
|
alginfo->alg_name[sizeof(alginfo->alg_name)-1] = '\0';
|
|
alginfo->alg_key_len = (unsigned int)ipnet_cmd_ip_module_xfrm_parse_hexkey(alg_key, (Ip_u8 *)alginfo->alg_key) * 8;
|
|
}
|
|
break;
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_AUTH:
|
|
{
|
|
char *alg_name, *alg_key;
|
|
struct Ip_xfrm_algo *alginfo;
|
|
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "auth <algorithm> <key>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&alg_name, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "auth <algorithm> <key>");
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&alg_key, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "auth <algorithm> <key>");
|
|
|
|
/* Time to create the ENC attribute */
|
|
rta = ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_XFRMA_ALG_AUTH, IP_NULL,
|
|
ip_offsetof(struct Ip_xfrm_algo, alg_key) + ipnet_cmd_ip_module_xfrm_parse_hexkey(alg_key, IP_NULL));
|
|
alginfo = IP_RTA_DATA(rta);
|
|
ipcom_strncpy(alginfo->alg_name, alg_name, sizeof(alginfo->alg_name));
|
|
alginfo->alg_name[sizeof(alginfo->alg_name)-1] = '\0';
|
|
alginfo->alg_key_len = (unsigned int)ipnet_cmd_ip_module_xfrm_parse_hexkey(alg_key, (Ip_u8 *)alginfo->alg_key) * 8;
|
|
}
|
|
break;
|
|
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_ENCAP:
|
|
{
|
|
struct Ip_xfrm_encap_tmpl encap;
|
|
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "encap <espinudp|espinudp-nonike> <sport> <dport> <oaddr>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, ipnet_ip_xfrm_encap_type))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "encap <espinudp|espinudp-nonike> <sport> <dport> <oaddr>");
|
|
encap.encap_type = (Ip_u16)uarg;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "encap <espinudp|espinudp-nonike> <sport> <dport> <oaddr>");
|
|
encap.encap_sport = ip_htons((Ip_u16)uarg);
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "encap <espinudp|espinudp-nonike> <sport> <dport> <oaddr>");
|
|
encap.encap_dport = ip_htons((Ip_u16)uarg);
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_prefix(sa_info->family, &addr, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "encap <espinudp|espinudp-nonike> <sport> <dport> <oaddr>");
|
|
|
|
ipcom_memcpy(&encap.encap_oa, &addr.prefix, addr.prefix_max/8);
|
|
ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_XFRMA_ENCAP, &encap, sizeof(encap));
|
|
}
|
|
break;
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_LIMIT:
|
|
if (0 > ipnet_cmd_ip_module_xfrm_parse_lft(cfg, &sa_info->lft))
|
|
return -1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_xfrm_state_add(Ipnet_ip_config_t *cfg)
|
|
{
|
|
Ip_ssize_t ret = ipnet_cmd_ip_module_xfrm_state_add_update_modify(cfg);
|
|
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
|
|
|
|
if (0 <= ret)
|
|
{
|
|
nlh->nlmsg_flags = IP_NLM_F_CREATE|IP_NLM_F_EXCL|IP_NLM_F_REQUEST|IP_NLM_F_ACK;
|
|
nlh->nlmsg_type = IP_XFRM_MSG_NEWSA;
|
|
|
|
if (0 > (ret = ipnet_ip_request_netlink(cfg, cfg->handle, IP_NULL, cfg->core, IP_TRUE)))
|
|
ipnet_ip_stdio_printf(cfg, "XFRM answers: %s"IP_LF, ipcom_strerror(-(int)ret));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_xfrm_state_update(Ipnet_ip_config_t *cfg)
|
|
{
|
|
Ip_ssize_t ret = ipnet_cmd_ip_module_xfrm_state_add_update_modify(cfg);
|
|
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
|
|
|
|
if (0 <= ret)
|
|
{
|
|
nlh->nlmsg_flags = IP_NLM_F_CREATE|IP_NLM_F_EXCL|IP_NLM_F_REQUEST|IP_NLM_F_ACK;
|
|
nlh->nlmsg_type = IP_XFRM_MSG_UPDSA;
|
|
|
|
if (0 > (ret = ipnet_ip_request_netlink(cfg, cfg->handle, IP_NULL, cfg->core, IP_TRUE)))
|
|
ipnet_ip_stdio_printf(cfg, "XFRM answers: %s"IP_LF, ipcom_strerror(-(int)ret));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_xfrm_state_del_get_modify(Ipnet_ip_config_t *cfg)
|
|
{
|
|
char *sarg;
|
|
int arg;
|
|
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
|
|
struct Ip_xfrm_usersa_id *sa_id;
|
|
Ip_u32 uarg;
|
|
|
|
ipcom_memset(nlh, 0, sizeof(*nlh));
|
|
nlh->nlmsg_len = IP_NLMSG_LENGTH(0);
|
|
|
|
/* Start of the routing message */
|
|
sa_id = (struct Ip_xfrm_usersa_id *)IP_NLMSG_DATA(nlh);
|
|
ipcom_memset(sa_id, 0, sizeof(*sa_id));
|
|
sa_id->family = cfg->family;
|
|
|
|
/* Move past the routing header */
|
|
nlh->nlmsg_len = (Ip_u32) (IP_NLMSG_ALIGN(nlh->nlmsg_len) + sizeof(*sa_id));
|
|
|
|
/* Time to go through the filter parameters */
|
|
while (IP_FALSE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
{
|
|
Ipnet_ip_prefix_t addr;
|
|
|
|
if (IP_FALSE == ipnet_ip_str_to_key(&arg, ipnet_ip_xfrm_state_attributes, sarg))
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
|
|
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_SRC:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "src <source>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_prefix(sa_id->family, &addr, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "src <source>");
|
|
|
|
if (sa_id->family == IP_AF_UNSPEC)
|
|
sa_id->family = addr.prefix_family;
|
|
|
|
ipcom_netlink_addattr_l(nlh, IPNET_IP_HANDLE_BUFFER, IP_XFRMA_SRCADDR, &addr.prefix, addr.prefix_max/8);
|
|
break;
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_DST:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "dst <destination>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_prefix(sa_id->family, &addr, cfg))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "dst <destination>");
|
|
|
|
if (sa_id->family == IP_AF_UNSPEC)
|
|
sa_id->family = addr.prefix_family;
|
|
|
|
ipcom_memcpy(&sa_id->daddr, &addr.prefix, addr.prefix_max/8);
|
|
break;
|
|
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_SPI:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "spi <spi>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, IP_NULL))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "spi <spi>");
|
|
|
|
sa_id->spi = uarg;
|
|
break;
|
|
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_PROTO:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "proto <num|ah|esp>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, ipnet_ip_xfrm_proto))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "proto <num|ah|esp>");
|
|
|
|
sa_id->proto = (Ip_u8)uarg;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_xfrm_state_del(Ipnet_ip_config_t *cfg)
|
|
{
|
|
Ip_ssize_t ret = ipnet_cmd_ip_module_xfrm_state_del_get_modify(cfg);
|
|
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
|
|
|
|
if (0 <= ret)
|
|
{
|
|
Ip_u64 req_mask = IP_BIT_UVAL64(IPNET_IP_XFRM_STATE_ATTRIBUTE_SRC) | IP_BIT_UVAL64(IPNET_IP_XFRM_STATE_ATTRIBUTE_DST) |
|
|
IP_BIT_UVAL64(IPNET_IP_XFRM_STATE_ATTRIBUTE_PROTO) | IP_BIT_UVAL64(IPNET_IP_XFRM_STATE_ATTRIBUTE_SPI);
|
|
if ((cfg->mask & req_mask) != req_mask)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Missing required arguments [src, dst, proto] for delete command"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
nlh->nlmsg_flags = IP_NLM_F_REQUEST|IP_NLM_F_ACK;
|
|
nlh->nlmsg_type = IP_XFRM_MSG_DELSA;
|
|
|
|
if (0 > (ret = ipnet_ip_request_netlink(cfg, cfg->handle, IP_NULL, cfg->core, IP_TRUE)))
|
|
ipnet_ip_stdio_printf(cfg, "XFRM answers: %s"IP_LF, ipcom_strerror(-(int)ret));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_xfrm_state_get(Ipnet_ip_config_t *cfg)
|
|
{
|
|
Ip_ssize_t ret = ipnet_cmd_ip_module_xfrm_state_del_get_modify(cfg);
|
|
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
|
|
|
|
if (0 <= ret)
|
|
{
|
|
Ip_u64 req_mask = IP_BIT_UVAL64(IPNET_IP_XFRM_STATE_ATTRIBUTE_SRC) | IP_BIT_UVAL64(IPNET_IP_XFRM_STATE_ATTRIBUTE_DST) |
|
|
IP_BIT_UVAL64(IPNET_IP_XFRM_STATE_ATTRIBUTE_PROTO) | IP_BIT_UVAL64(IPNET_IP_XFRM_STATE_ATTRIBUTE_SPI);
|
|
if ((cfg->mask & req_mask) != req_mask)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "Missing required arguments [src, dst, proto] for delete command"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
nlh->nlmsg_flags = IP_NLM_F_REQUEST;
|
|
nlh->nlmsg_type = IP_XFRM_MSG_GETSA;
|
|
|
|
if (0 > (ret = ipnet_ip_request_netlink(cfg, cfg->handle, IP_NULL, cfg->core, IP_TRUE)))
|
|
ipnet_ip_stdio_printf(cfg, "XFRM answers: %s"IP_LF, ipcom_strerror(-(int)ret));
|
|
else
|
|
{
|
|
Ipnet_ip_handle_msg_t *nlmsg;
|
|
for (nlmsg = IPCOM_LIST_FIRST(&cfg->handle->replies); IP_NULL != nlmsg; nlmsg = IPCOM_LIST_NEXT(&nlmsg->next))
|
|
ipnet_cmd_ip_module_xfrm_state_print(cfg, nlmsg);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_xfrm_state_flush_modify(Ipnet_ip_config_t *cfg)
|
|
{
|
|
char *sarg;
|
|
int arg;
|
|
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
|
|
struct Ip_xfrm_usersa_flush *sa_flush;
|
|
Ip_u32 uarg;
|
|
|
|
ipcom_memset(nlh, 0, sizeof(*nlh));
|
|
nlh->nlmsg_len = IP_NLMSG_LENGTH(0);
|
|
|
|
/* Start of the routing message */
|
|
sa_flush = (struct Ip_xfrm_usersa_flush *)IP_NLMSG_DATA(nlh);
|
|
ipcom_memset(sa_flush, 0, sizeof(*sa_flush));
|
|
|
|
/* Move past the routing header */
|
|
nlh->nlmsg_len = (Ip_u32) (IP_NLMSG_ALIGN(nlh->nlmsg_len) + sizeof(*sa_flush));
|
|
|
|
/* Time to go through the filter parameters */
|
|
while (IP_FALSE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
{
|
|
if (IP_FALSE == ipnet_ip_str_to_key(&arg, ipnet_ip_xfrm_state_attributes, sarg))
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
|
|
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_XFRM_STATE_ATTRIBUTE_PROTO:
|
|
if (IP_TRUE != ipnet_cmd_ip_check_mask(cfg, "proto <num|ah|esp>", arg))
|
|
return -1;
|
|
|
|
if (IP_TRUE != ipnet_ip_cmd_param_uint(&uarg, cfg, ipnet_ip_xfrm_proto))
|
|
return ipnet_cmd_ip_requires_argument(cfg, "proto <num|ah|esp>");
|
|
|
|
sa_flush->proto = (Ip_u8)uarg;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_xfrm_state_flush(Ipnet_ip_config_t *cfg)
|
|
{
|
|
Ip_ssize_t ret = ipnet_cmd_ip_module_xfrm_state_flush_modify(cfg);
|
|
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->tx[0];
|
|
|
|
if (0 <= ret)
|
|
{
|
|
nlh->nlmsg_flags = IP_NLM_F_REQUEST|IP_NLM_F_ACK;
|
|
nlh->nlmsg_type = IP_XFRM_MSG_FLUSHSA;
|
|
|
|
if (0 > (ret = ipnet_ip_request_netlink(cfg, cfg->handle, IP_NULL, cfg->core, IP_TRUE)))
|
|
ipnet_ip_stdio_printf(cfg, "XFRM answers: %s"IP_LF, ipcom_strerror(-(int)ret));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
IP_STATIC Ip_u32
|
|
ipnet_cmd_ip_module_xfrm_state_monitor_groups(Ipnet_ip_config_t *cfg)
|
|
{
|
|
(void) cfg;
|
|
return IP_NLMSG_GROUP_MASK(IP_XFRMNLGRP_SA);
|
|
}
|
|
|
|
IP_STATIC Ip_bool
|
|
ipnet_cmd_ip_module_xfrm_state_monitor(Ipnet_ip_config_t *cfg, Ipnet_ip_handle_msg_t *nlmsg)
|
|
{
|
|
switch (nlmsg->hdr->nlmsg_type)
|
|
{
|
|
case IP_XFRM_MSG_DELSA:
|
|
case IP_XFRM_MSG_EXPIRE:
|
|
case IP_XFRM_MSG_UPDSA:
|
|
case IP_XFRM_MSG_NEWSA:
|
|
ipnet_cmd_ip_module_xfrm_state_print(cfg, nlmsg);
|
|
return IP_TRUE;
|
|
}
|
|
|
|
return IP_FALSE;
|
|
}
|
|
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_xfrm_state(Ipnet_ip_config_t *cfg)
|
|
{
|
|
int arg;
|
|
char *sparam;
|
|
|
|
cfg->handle = ipnet_ip_open_netlink(cfg, 0, IP_NETLINK_XFRM);
|
|
if (IP_NULL == cfg->handle)
|
|
return -1;
|
|
|
|
/* START */
|
|
|
|
/* Resolve the subcommand */
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sparam, cfg))
|
|
return ipnet_cmd_ip_xfrm_state_usage(cfg, -1);
|
|
|
|
/* Resolve the module */
|
|
if (IP_FALSE == ipnet_ip_str_to_key(&arg, ipnet_ip_xfrm_state, sparam))
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sparam);
|
|
else
|
|
{
|
|
ipnet_cmd_ip_clear_mask(cfg);
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_XFRM_STATE_LIST:
|
|
return ipnet_cmd_ip_module_xfrm_state_list(cfg);
|
|
case IPNET_IP_XFRM_STATE_DELALL:
|
|
return ipnet_cmd_ip_module_xfrm_state_delall(cfg);
|
|
case IPNET_IP_XFRM_STATE_ADD:
|
|
return ipnet_cmd_ip_module_xfrm_state_add(cfg);
|
|
case IPNET_IP_XFRM_STATE_UPDATE:
|
|
return ipnet_cmd_ip_module_xfrm_state_update(cfg);
|
|
case IPNET_IP_XFRM_STATE_DEL:
|
|
return ipnet_cmd_ip_module_xfrm_state_del(cfg);
|
|
case IPNET_IP_XFRM_STATE_GET:
|
|
return ipnet_cmd_ip_module_xfrm_state_get(cfg);
|
|
case IPNET_IP_XFRM_STATE_FLUSH:
|
|
return ipnet_cmd_ip_module_xfrm_state_flush(cfg);
|
|
case IPNET_IP_XFRM_STATE_MONITOR:
|
|
return ipnet_cmd_ip_module_xfrm_monitor_modules(cfg, IP_BIT_VAL(IPNET_IP_XFRM_MAIN_STATE));
|
|
case IPNET_IP_XFRM_STATE_HELP:
|
|
return ipnet_cmd_ip_xfrm_state_usage(cfg, 0);
|
|
|
|
/* MONITOR */
|
|
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_xfrm_usage(Ipnet_ip_config_t *cfg, int ret)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "NAME"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip xfrm - Display and modify the IPSEC security association and policies"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "SYNOPSIS"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip xfrm state <help|list>"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip xfrm help"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "DESCRIPTION"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " help Display usage information"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " state Display and modify security associations."IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " Use 'ip xfrm state help' for more help ."IP_LF);
|
|
return ret;
|
|
}
|
|
|
|
IP_STATIC int
|
|
ipnet_cmd_ip_xfrm_monitor_usage(Ipnet_ip_config_t *cfg, int ret)
|
|
{
|
|
int i;
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "NAME"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip xfrm monitor - Monitor changes done to XFRM"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, ""IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, "SYNOPSIS"IP_LF);
|
|
ipnet_ip_stdio_printf(cfg, " ip xfrm monitor");
|
|
for (i = 0; i < IPNET_IP_XFRM_MAIN_MAX; i++)
|
|
ipnet_ip_stdio_printf(cfg, " [%s]", ipnet_ip_key_to_str(ipnet_ip_xfrm_main, i , IP_NULL, 0));
|
|
ipnet_ip_stdio_printf(cfg, " [all]"IP_LF);
|
|
return ret;
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_xfrm_monitor_modules(Ipnet_ip_config_t *cfg, Ip_u32 modules)
|
|
{
|
|
unsigned i;
|
|
Ip_u32 groups = 0;
|
|
Ip_ssize_t val;
|
|
|
|
for (i = 0; i < IPNET_IP_XFRM_MAIN_MAX; i++)
|
|
{
|
|
if (IP_BIT_ISSET(modules, IP_BIT_UVAL(i)))
|
|
{
|
|
switch (i)
|
|
{
|
|
case IPNET_IP_XFRM_MAIN_STATE:
|
|
groups |= ipnet_cmd_ip_module_xfrm_state_monitor_groups(cfg);
|
|
break;
|
|
case IPNET_IP_XFRM_MAIN_POLICY:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (groups == 0)
|
|
{
|
|
ipnet_ip_stdio_printf(cfg, "No groups selected"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
cfg->handle = ipnet_ip_open_netlink(cfg, groups, IP_NETLINK_XFRM);
|
|
if (IP_NULL == cfg->handle)
|
|
return -1;
|
|
|
|
while (0 < (val = ipnet_ip_recv_netlink(cfg, cfg->handle)))
|
|
{
|
|
struct Ip_nlmsghdr *nlh = (struct Ip_nlmsghdr *)&cfg->handle->rx[0];
|
|
|
|
while (IP_NLMSG_OK(nlh, (unsigned)val))
|
|
{
|
|
Ipnet_ip_handle_msg_t *nlmsg = ipnet_ip_alloc_reply(nlh->nlmsg_len);
|
|
|
|
if (IP_NULL == nlmsg)
|
|
return -1;
|
|
|
|
ipcom_memcpy(nlmsg->hdr, nlh, nlh->nlmsg_len);
|
|
for (i = 0; i < IPNET_IP_MODULE_MAX; i++)
|
|
{
|
|
if (IP_BIT_ISSET(modules, IP_BIT_UVAL(i)))
|
|
{
|
|
switch (i)
|
|
{
|
|
case IPNET_IP_XFRM_MAIN_STATE:
|
|
if (ipnet_cmd_ip_module_xfrm_state_monitor(cfg, nlmsg))
|
|
goto next_frame;
|
|
break;
|
|
case IPNET_IP_XFRM_MAIN_POLICY:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
next_frame:
|
|
nlh = IP_NLMSG_NEXT(nlh, val);
|
|
ipnet_ip_free_reply(nlmsg);
|
|
|
|
/* Flush output */
|
|
ipnet_ip_stdio_flush(cfg);
|
|
}
|
|
}
|
|
ipnet_ip_stdio_printf(cfg, "VAL = %d"IP_LF, val);
|
|
return val < 0? val : 0;
|
|
}
|
|
|
|
IP_STATIC Ip_ssize_t
|
|
ipnet_cmd_ip_module_xfrm_monitor(Ipnet_ip_config_t *cfg)
|
|
{
|
|
char *sarg;
|
|
int arg;
|
|
Ip_u32 modules = 0;
|
|
|
|
while (IP_FALSE != ipnet_ip_cmd_param_str(&sarg, cfg))
|
|
{
|
|
if (IP_FALSE == ipnet_ip_str_to_key(&arg, ipnet_ip_xfrm_main, sarg))
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sarg);
|
|
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_XFRM_MAIN_HELP:
|
|
return ipnet_cmd_ip_xfrm_monitor_usage(cfg, 0);
|
|
case IPNET_IP_XFRM_MAIN_ALL:
|
|
for (arg = 0; arg < IPNET_IP_XFRM_MAIN_MAX; arg++)
|
|
modules |= IP_BIT_UVAL(arg);
|
|
break;
|
|
default:
|
|
modules |= IP_BIT_UVAL(arg);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (modules == 0)
|
|
{
|
|
for (arg = 0; arg < IPNET_IP_XFRM_MAIN_MAX; arg++)
|
|
modules |= IP_BIT_UVAL(arg);
|
|
}
|
|
|
|
return ipnet_cmd_ip_module_xfrm_monitor_modules(cfg, modules);
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 GLOBAL FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
IP_GLOBAL Ip_ssize_t
|
|
ipnet_cmd_ip_module_xfrm(Ipnet_ip_config_t *cfg)
|
|
{
|
|
int arg;
|
|
char *sparam;
|
|
|
|
/* START */
|
|
|
|
/* Resolve the subcommand */
|
|
if (IP_TRUE != ipnet_ip_cmd_param_str(&sparam, cfg))
|
|
return ipnet_cmd_ip_xfrm_usage(cfg, -1);
|
|
|
|
/* Resolve the module */
|
|
if (IP_FALSE == ipnet_ip_str_to_key(&arg, ipnet_ip_xfrm_main, sparam))
|
|
return ipnet_cmd_ip_unknown_keyword(cfg, sparam);
|
|
else
|
|
{
|
|
ipnet_cmd_ip_clear_mask(cfg);
|
|
switch (arg)
|
|
{
|
|
case IPNET_IP_XFRM_MAIN_STATE:
|
|
return ipnet_cmd_ip_module_xfrm_state(cfg);
|
|
case IPNET_IP_XFRM_MAIN_MONITOR:
|
|
return ipnet_cmd_ip_module_xfrm_monitor(cfg);
|
|
case IPNET_IP_XFRM_MAIN_HELP:
|
|
return ipnet_cmd_ip_xfrm_usage(cfg, 0);
|
|
default:
|
|
return ipnet_cmd_ip_xfrm_usage(cfg, -1);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 11 PUBLIC FUNCTIONS
|
|
****************************************************************************
|
|
*/
|
|
|
|
#endif /* IPNET_USE_NETLINK */
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
****************************************************************************
|
|
*/
|