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

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