3826 lines
133 KiB
C
3826 lines
133 KiB
C
/*
|
|
******************************************************************************
|
|
* INTERPEAK SOURCE FILE
|
|
*
|
|
* Document no: @(#) $Name: VXWORKS_ITER40_RCPL8_2024030303 $ $RCSfile: ipipsec_cmd_keyadm.c,v $ $Revision: 1.64.2.13 $
|
|
* $Source: /home/interpeak/CVSRoot/ipipsec2/src/ipipsec_cmd_keyadm.c,v $
|
|
* $Author: jren $
|
|
* $State: Exp $ $Locker: $
|
|
*
|
|
* INTERPEAK_COPYRIGHT_STRING
|
|
* Design and implementation by Lennart Bang <lob@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 1 DESCRIPTION.
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 2 CONFIGURATION
|
|
****************************************************************************
|
|
*/
|
|
|
|
#ifdef IPCOM_KERNEL
|
|
#undef IPCOM_KERNEL
|
|
#endif
|
|
#include "ipipsec_config.h"
|
|
#define IPCOM_USE_CLIB_PROTO
|
|
#include "ipipsec_h.h"
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 3 INCLUDE FILES.
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
|
|
/* IPCOM */
|
|
#include <ipcom_clib.h>
|
|
#if IPCOM_USE_SHELL != IPCOM_SHELL_NONE || defined(IP_PORT_LAS)
|
|
#include <ipcom_clib2.h>
|
|
#endif
|
|
#include <ipcom_sock.h>
|
|
#include <ipcom_inet.h>
|
|
#include <ipcom_os.h>
|
|
|
|
#include <ipcom_tags.h>
|
|
#include <ipcom_getopt.h>
|
|
#include <ipcom_sysvar.h>
|
|
#include <ipcom_syslog.h>
|
|
#include <ipcom_cmd.h>
|
|
|
|
/* Interpeak IPSEC */
|
|
#include "ipipsec.h"
|
|
#include "ipipsec_pfkeyv2.h"
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 4 MACROS/TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
/* Should not be evenly dividable by 8 in order to detect truncated SADB messages */
|
|
#define MAX_RCVBUF_SIZE (2048 - 1)
|
|
|
|
#define IPCOM_SYSLOG_PRIORITY IPIPSEC_SYSTEM_PRIORITY
|
|
#define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPIPSEC
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 5 TYPES
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* sadb_address_full
|
|
*===========================================================================
|
|
*/
|
|
struct sadb_address_full
|
|
{
|
|
struct sadb_address addr;
|
|
union Ip_sockaddr_union sock;
|
|
Ip_u8 pad[8];
|
|
};
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Ipipsec_sadb_extbits
|
|
*===========================================================================
|
|
*/
|
|
typedef struct Extbits_struct
|
|
{
|
|
Ip_u64 in_req;
|
|
}
|
|
Extbits;
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Variables - Vars
|
|
*===========================================================================
|
|
*/
|
|
typedef struct Vars_struct
|
|
{
|
|
int argc;
|
|
char **argv;
|
|
Ip_fd fd;
|
|
void *exthdr[SADB_EXT_MAX+1];
|
|
Ipipsec_pfkeyv2_sadb *sadb;
|
|
struct sadb_msg sadbmsg;
|
|
|
|
Ip_u8 *orgbuf;
|
|
char *stdoutbuf;
|
|
Ip_u8 *msgbuf;
|
|
|
|
/* options */
|
|
Ip_u32 minspi, maxspi;
|
|
Ip_u32 spi_n, spi2_n;
|
|
union Ip_sockaddr_union srcaddr;
|
|
union Ip_sockaddr_union dstaddr;
|
|
union Ip_sockaddr_union proxyaddr;
|
|
union Ip_sockaddr_union srctunnel;
|
|
union Ip_sockaddr_union dsttunnel;
|
|
union Ip_sockaddr_union dstaddr2;
|
|
Ip_s8 satype, satype2;
|
|
Ip_u8 have_satype;
|
|
Ip_u8 flow_type;
|
|
Ip_u8 dscp;
|
|
Ip_u32 flow_id;
|
|
union Ip_sockaddr_union srcmask;
|
|
union Ip_sockaddr_union dstmask;
|
|
union Ip_sockaddr_union srcflow;
|
|
union Ip_sockaddr_union dstflow;
|
|
union Ip_sockaddr_union srcmaxflow;
|
|
union Ip_sockaddr_union dstmaxflow;
|
|
union Ip_sockaddr_union zeroaddr;
|
|
Ip_u16 dstport_n, srcport_n;
|
|
Ip_u16 dstmaxport_n, srcmaxport_n;
|
|
Ip_u16 udpencap_port; /*NOTE: port in host endian! */
|
|
Ip_u8 transport_proto;
|
|
Ip_u8 have_transport_proto;
|
|
Ip_u8 ports0, ports1;
|
|
int replay;
|
|
int flow_priority, sa_priority;
|
|
Ip_u32 ls_sec, lh_sec;
|
|
Ip_u64 ls_bytes, lh_bytes;
|
|
|
|
Ip_u8 encrypt_type;
|
|
Ip_u8 encrypt_bytes;
|
|
struct sadb_key encrypt_sadb;
|
|
Ip_u8 encrypt_key[128];
|
|
|
|
Ip_u8 auth_type;
|
|
Ip_u8 auth_bytes;
|
|
struct sadb_key auth_sadb;
|
|
Ip_u8 auth_key[IPIPSEC_AUTH_MAXKEYLEN];
|
|
|
|
Ip_u32 test;
|
|
Ip_u64 extmap;
|
|
int syslog, silent, count;
|
|
Ip_u32 sa_flags;
|
|
Ip_u32 timeout_seconds;
|
|
#ifdef IPIPSEC_USE_LINUX_PFKEYV2_API
|
|
Ip_bool is_linux;
|
|
Ip_u32 reqid; /* For unique mode (-u setkey option) */
|
|
#endif
|
|
}
|
|
Vars;
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Command
|
|
*===========================================================================
|
|
*/
|
|
typedef struct Command_struct
|
|
{
|
|
char *name;
|
|
int (*func)(Vars *vars);
|
|
void (*usage)(Vars *vars);
|
|
int type;
|
|
}
|
|
Command;
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* Ctrl
|
|
*===========================================================================
|
|
*/
|
|
#define CTRL_GET 1
|
|
#define CTRL_SET 2
|
|
typedef struct Ctrl_struct
|
|
{
|
|
char *name;
|
|
Ip_tag id;
|
|
Ip_u32 mode; /* 1=get, 2=set, 3=get&set */
|
|
}
|
|
Ctrl;
|
|
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 6 PROTOTYPES.
|
|
****************************************************************************
|
|
*/
|
|
|
|
IP_EXTERN IP_CONST char *ipipsec_pfkeyv2_command[SADB_MAX + 2];
|
|
IP_EXTERN int ipipsec_pfkeyv2_ext_size[SADB_EXT_MAX+1];
|
|
|
|
IP_PUBLIC int ipipsec_cmd_keyadm(int argc, char **argv);
|
|
|
|
static int keyadm_dump(Vars *vars);
|
|
static int keyadm_getspi(Vars *vars);
|
|
static int keyadm_flush(Vars *vars);
|
|
static int keyadm_get(Vars *vars);
|
|
static int keyadm_update(Vars *vars);
|
|
static int keyadm_add(Vars *vars);
|
|
static int keyadm_delete(Vars *vars);
|
|
static int keyadm_addflow(Vars *vars);
|
|
static int keyadm_delflow(Vars *vars);
|
|
static int keyadm_grpspis(Vars *vars);
|
|
static int keyadm_findflow(Vars *vars);
|
|
static int keyadm_dumpflow(Vars *vars);
|
|
static int keyadm_monitor(Vars *vars);
|
|
static int keyadm_register(Vars *vars);
|
|
|
|
static void keyadm_add_usage(Vars *vars);
|
|
static void keyadm_delete_usage(Vars *vars);
|
|
static void keyadm_get_usage(Vars *vars);
|
|
static void keyadm_grpspis_usage(Vars *vars);
|
|
static void keyadm_getspi_usage(Vars *vars);
|
|
static void keyadm_update_usage(Vars *vars);
|
|
|
|
static void keyadm_addflow_usage(Vars *vars);
|
|
static void keyadm_delflow_usage(Vars *vars);
|
|
static void keyadm_findflow_usage(Vars *vars);
|
|
|
|
static IP_CONST char *
|
|
keyadm_cmd_bits_to_str(char **map, Ip_u32 bits, char *str, Ip_size_t str_len);
|
|
|
|
|
|
#ifdef IPIPSEC_USE_LINUX_PFKEYV2_API
|
|
static int keyadm_spdadd(Vars *vars);
|
|
static void keyadm_spdadd_usage(Vars *vars);
|
|
|
|
static int keyadm_spdupdate(Vars *vars);
|
|
static void keyadm_spdupdate_usage(Vars *vars);
|
|
|
|
static int keyadm_spddelete(Vars *vars);
|
|
static void keyadm_spddelete_usage(Vars *vars);
|
|
|
|
static int keyadm_spdflush(Vars *vars);
|
|
|
|
#endif /* #ifdef IPIPSEC_USE_LINUX_PFKEYV2_API */
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 7 DATA.
|
|
****************************************************************************
|
|
*/
|
|
|
|
static IP_CONST char *keyadm_sa_flags_bitmap[] =
|
|
{
|
|
"pfs",
|
|
"0x2",
|
|
"0x4",
|
|
"0x8",
|
|
"0x10",
|
|
"0x20",
|
|
"0x40",
|
|
"0x80",
|
|
"0x100",
|
|
"ecn",
|
|
"tunnel",
|
|
"chaindel",
|
|
"0x1000",
|
|
"replaceflow",
|
|
"ingress",
|
|
"randompad",
|
|
"noreplay",
|
|
"udpencap",
|
|
"egress",
|
|
"tfc",
|
|
"esn",
|
|
"srcreq",
|
|
"clrdf",
|
|
"setdf",
|
|
"0x1000000",
|
|
"0x2000000",
|
|
"0x4000000",
|
|
"0x8000000",
|
|
"0x10000000",
|
|
"nopmtudisc",
|
|
"decap_dscp",
|
|
"noecn",
|
|
""
|
|
};
|
|
|
|
static Ip_u32 sadbmsgseq = 1;
|
|
|
|
static IP_CONST Command commands[] =
|
|
{
|
|
/* name, function */
|
|
{ "dump", keyadm_dump, IP_NULL, SADB_DUMP },
|
|
{ "flush", keyadm_flush, IP_NULL, SADB_FLUSH },
|
|
{ "get", keyadm_get, keyadm_get_usage, SADB_GET },
|
|
{ "getspi", keyadm_getspi, keyadm_getspi_usage, SADB_GETSPI },
|
|
{ "update", keyadm_update, keyadm_update_usage, SADB_UPDATE },
|
|
{ "add", keyadm_add, keyadm_add_usage, SADB_ADD },
|
|
{ "delete", keyadm_delete, keyadm_delete_usage, SADB_DELETE },
|
|
{ "addflow", keyadm_addflow, keyadm_addflow_usage, SADB_X_ADDFLOW },
|
|
{ "delflow", keyadm_delflow, keyadm_delflow_usage, SADB_X_DELFLOW },
|
|
{ "group", keyadm_grpspis, keyadm_grpspis_usage, SADB_X_GRPSPIS },
|
|
{ "findflow", keyadm_findflow, keyadm_findflow_usage, SADB_X_FINDFLOW },
|
|
{ "dumpflow", keyadm_dumpflow, IP_NULL, SADB_X_DUMPFLOW },
|
|
{ "monitor", keyadm_monitor, IP_NULL, 0 },
|
|
{ "register", keyadm_register, IP_NULL, SADB_REGISTER },
|
|
#ifdef IPIPSEC_USE_LINUX_PFKEYV2_API
|
|
{ "spdadd", keyadm_spdadd, keyadm_spdadd_usage, SADB_X_SPDADD },
|
|
{ "spdupdate", keyadm_spdupdate, keyadm_spdupdate_usage, SADB_X_SPDUPDATE },
|
|
{ "spddelete", keyadm_spddelete, keyadm_spddelete_usage, SADB_X_SPDDELETE },
|
|
{ "spdflush", keyadm_spdflush, IP_NULL, SADB_X_SPDFLUSH },
|
|
#endif
|
|
{ 0, IP_NULL, IP_NULL, 0 }
|
|
};
|
|
|
|
#define EXT_SADBADDR_SIZE_MIN (int)(sizeof(struct sadb_address) + IP_ROUNDUP(sizeof(struct Ip_sockaddr_in),8))
|
|
#define EXT_SADBADDR_SIZE_IN 24 /* same expression as above */
|
|
#define EXT_SADBADDR_SIZE_IN6 40 /* 8+sizeof(struct Ip_sockaddr_in6) = 8+28 = 36 -> rounded up = 40 */
|
|
|
|
#define SOCKADDR_SIZE IP_ROUNDUP(sizeof(struct Ip_sockaddr_in),8)
|
|
#define SOCKADDR6_SIZE IP_ROUNDUP(sizeof(struct Ip_sockaddr_in6),8)
|
|
|
|
|
|
static IP_CONST Extbits extbits[SADB_MAX+1] =
|
|
{
|
|
/* 0 SADB_RESERVED */
|
|
{ 0 /* in_req */ },
|
|
|
|
/* 1 SADB_GETSPI */
|
|
{ SEBIT_SPIRANGE | SEBIT_ADDRESS_SRC | SEBIT_ADDRESS_DST },
|
|
|
|
/* 2 SADB_UPDATE */
|
|
{ SEBIT_SA | SEBIT_ADDRESS_SRC | SEBIT_ADDRESS_DST },
|
|
|
|
/* 3 SADB_ADD */
|
|
{ SEBIT_SA | SEBIT_ADDRESS_DST | SEBIT_ADDRESS_SRC },
|
|
|
|
/* 4 SADB_DELETE */
|
|
{ SEBIT_SA | SEBIT_ADDRESS_DST | SEBIT_ADDRESS_SRC },
|
|
|
|
/* 5 SADB_GET */
|
|
{ SEBIT_SA | SEBIT_ADDRESS_SRC | SEBIT_ADDRESS_DST },
|
|
|
|
/* 6 SADB_ACQUIRE */
|
|
{ 0 },
|
|
|
|
/* 7 SADB_REGISTER */
|
|
{ 0 },
|
|
|
|
/* 8 SADB_EXPIRE */
|
|
{ SEBIT_SA | SEBIT_ADDRESS_SRC | SEBIT_ADDRESS_DST },
|
|
|
|
/* 9 SADB_FLUSH */
|
|
{ 0 },
|
|
|
|
/* 10 SADB_DUMP */
|
|
{ 0 },
|
|
|
|
{ 0 }, /* 11 SADB_LX_PROMISC */
|
|
{ 0 }, /* 12 SADB_LX_PCHANGE */
|
|
|
|
/* 13 SADB_X_SPDUPDATE */
|
|
/* NOTE: Acctually SEBIT_ADDRESS_SRC | SEBIT_ADDRESS_DST | SEBIT_LX_POLICY */
|
|
{ SEBIT_X_FLOW },
|
|
|
|
/* 14 SADB_X_SPDADD */
|
|
/* Note: Acctually SEBIT_ADDRESS_SRC | SEBIT_ADDRESS_DST | SEBIT_LX_POLICY */
|
|
{ SEBIT_X_FLOW },
|
|
|
|
/* 15 LX_SPDDELETE */
|
|
/* Note: Acctually SEBIT_ADDRESS_SRC | SEBIT_ADDRESS_DST | SEBIT_LX_POLICY */
|
|
{ SEBIT_X_FLOW },
|
|
|
|
{ 0 }, /* 16 LX_SPDGET */
|
|
{ 0 }, /* 17 LX_SPDACQUIRE */
|
|
{ 0 }, /* 18 LX_SPDDUMP */
|
|
{ 0 }, /* 19 LX_SPDFLUSH */
|
|
{ 0 }, /* 20 LX_SPDSETIDX */
|
|
{ 0 }, /* 21 LX_SPDEXPIRE */
|
|
{ 0 }, /* 22 LX_SPDDELETE2 */
|
|
{ 0 }, /* 23 LX_NAT_T_NEW_MAPPING */
|
|
{ 0 }, /* 24 LX_MIGRATE */
|
|
|
|
{ 0 }, /* 25 */
|
|
{ 0 }, /* 26 */
|
|
{ 0 }, /* 27 */
|
|
{ 0 }, /* 28 */
|
|
{ 0 }, /* 29 */
|
|
{ 0 }, /* 30 */
|
|
{ 0 }, /* 31 */
|
|
{ 0 }, /* 32 */
|
|
|
|
/* 33 SADB_X_PROMISC */
|
|
{ 0 },
|
|
|
|
/* 34 SADB_X_ADDFLOW */
|
|
{ SEBIT_X_FLOW },
|
|
|
|
/* 35 SADB_X_DELFLOW */
|
|
{ 0 },
|
|
|
|
/* 36 SADB_X_GRPSPIS */
|
|
{
|
|
SEBIT_SA | SEBIT_X_SA2 | SEBIT_X_DST2 | SEBIT_ADDRESS_DST | SEBIT_X_PROTOCOL
|
|
},
|
|
|
|
/* 37 SADB_X_BINDSA */
|
|
{
|
|
SEBIT_SA | SEBIT_X_SA2 | SEBIT_X_DST2 | SEBIT_ADDRESS_DST | SEBIT_X_PROTOCOL
|
|
},
|
|
|
|
/* 38 SADB_X_FINDFLOW */
|
|
{
|
|
SEBIT_X_FLOW /* not checked this way: SEBIT_X_PROTOCOL */
|
|
|
|
},
|
|
|
|
/* 39 SADB_X_DUMPFLOW */
|
|
{ 0 },
|
|
|
|
/* 40 SADB_X_MIGRATE */
|
|
{
|
|
SEBIT_X_EXT_KMADDRESS
|
|
}
|
|
};
|
|
|
|
|
|
static IP_CONST char *ext_types[SADB_EXT_MAX+2] =
|
|
{
|
|
"RESERVED",
|
|
"-spi",
|
|
"LIFETIME_CURRENT",
|
|
"LIFETIME_HARD",
|
|
"LIFETIME_SOFT",
|
|
"-src",
|
|
"-dst",
|
|
"ADDRESS_PROXY",
|
|
"KEY_AUTH",
|
|
"KEY_ENCRYPT",
|
|
"IDENTITY_SRC",
|
|
"IDENTITY_DST",
|
|
"SENSITIVITY",
|
|
"PROPOSAL",
|
|
"SUPPORTED",
|
|
"SUPPORTED_ENCRYPT",
|
|
"-minspi",
|
|
"LX_KMPRIVATE",
|
|
"LX_POLICY",
|
|
"LX_SA2",
|
|
"LX_NAT_TYPE",
|
|
"LX_NAT_SPORT",
|
|
"LX_NAT_DPORT",
|
|
"LX_NAT_OA",
|
|
"LX_SEC_CTX",
|
|
"EXT25",
|
|
"EXT26",
|
|
"EXT27",
|
|
"EXT28",
|
|
"EXT29",
|
|
"EXT30",
|
|
"EXT31",
|
|
"EXT32",
|
|
"-srcmask",
|
|
"-dstmask",
|
|
"-proto2",
|
|
"-spi2",
|
|
"-srcflow",
|
|
"-dstflow",
|
|
"-dst2",
|
|
"-flowopt",
|
|
"UDPENCAP",
|
|
"-srcmax(port)",
|
|
"-dstmax(port)",
|
|
"SA_OPTIONS",
|
|
"KMADDRESS",
|
|
"\n"
|
|
};
|
|
|
|
#define EXT_TYPE(x) ((x > SADB_EXT_MAX) ? "ILLEGAL" : ext_types[x])
|
|
|
|
#define MSG_TYPE(x) ((x > SADB_MAX) ? "ILLEGAL" : ipipsec_pfkeyv2_command[x])
|
|
|
|
static IP_CONST char *msg_satypes[SADB_SATYPE_MAX+2] =
|
|
{
|
|
"NONE",
|
|
"UNSPEC_1",
|
|
"AH",
|
|
"ESP",
|
|
"UNSPEC_4",
|
|
"RSVP",
|
|
"OSPFV2",
|
|
"RIPV2",
|
|
"MIP",
|
|
"IPCOMP",
|
|
"IPIP",
|
|
"TCPSIGNATURE",
|
|
"BYPASS",
|
|
"\n"
|
|
};
|
|
#define MSG_SATYPE(x) ((x > SADB_SATYPE_MAX) ? "ILLEGAL" : msg_satypes[x])
|
|
|
|
static Ipcom_cmd_int_str_map sa_auth_id_map[] =
|
|
{
|
|
{ SADB_AALG_NONE, "NONE" },
|
|
{ SADB_AALG_MD5HMAC, "MD5" },
|
|
{ SADB_AALG_SHA1HMAC, "SHA" },
|
|
{ SADB_AALG_SHA1HMAC, "SHA1" },
|
|
{ SADB_X_AALG_SHA2_256_HMAC, "SHA256" },
|
|
{ SADB_X_AALG_SHA2_384_HMAC, "SHA384" },
|
|
{ SADB_X_AALG_SHA2_512_HMAC, "SHA512" },
|
|
{ SADB_X_AALG_RIPEMD160HMAC, "RMD160" },
|
|
{ SADB_X_AALG_AES_XCBC_MAC, "AESMAC" },
|
|
{ SADB_X_AALG_NULL, "NULL" },
|
|
{ -1, IP_NULL }
|
|
};
|
|
#define SADB_AALG_UNSET (SADB_AALG_MAX + 1)
|
|
|
|
static Ipcom_cmd_int_str_map sa_encrypt_id_map[] =
|
|
{
|
|
{ SADB_EALG_NONE, "NONE" },
|
|
{ SADB_EALG_DESCBC, "DES" },
|
|
{ SADB_EALG_3DESCBC, "3DES" },
|
|
{ SADB_X_EALG_BLOWFISHCBC, "BLF" },
|
|
{ SADB_X_EALG_CASTCBC, "CAST" },
|
|
{ SADB_X_EALG_AESCBC, "AES" },
|
|
{ SADB_X_EALG_AESCBC, "AESCBC" },
|
|
{ SADB_X_EALG_AESCTR, "AESCTR" },
|
|
{ SADB_EALG_NULL, "NULL" },
|
|
{ -1, IP_NULL }
|
|
};
|
|
#define SADB_EALG_UNSET (SADB_EALG_MAX + 1)
|
|
|
|
|
|
static IP_CONST char *sa_state[SADB_SASTATE_MAX+2] =
|
|
{
|
|
"LARVAL",
|
|
"MATURE",
|
|
"DYING",
|
|
"DEAD",
|
|
"\n"
|
|
};
|
|
|
|
#define SA_STATE(x) ((x > SADB_SASTATE_MAX) ? "ILLEGAL" : sa_state[x])
|
|
|
|
|
|
static IP_CONST char *flow_types[] =
|
|
{
|
|
"unspec",
|
|
"use",
|
|
"acquire",
|
|
"require",
|
|
"bypass",
|
|
"deny",
|
|
"dontacq"
|
|
};
|
|
|
|
#define FLOW_TYPE(x) ((x) > 6 ? "ILLEGAL" : flow_types[x])
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* LINUX vars
|
|
*===========================================================================
|
|
*/
|
|
#ifdef IPIPSEC_USE_LINUX_PFKEYV2_API
|
|
|
|
static IP_CONST char *ipsec_policy_linux[5] =
|
|
{
|
|
"discard",
|
|
"none",
|
|
"ipsec",
|
|
"entrust",
|
|
"bypass"
|
|
};
|
|
|
|
/* sadb_x_policy_dir; */
|
|
static IP_CONST char *ipsec_dir_linux[6] =
|
|
{
|
|
"any",
|
|
"inbound",
|
|
"outbound",
|
|
"fwd",
|
|
"max",
|
|
"invalid"
|
|
};
|
|
|
|
#endif /* #ifdef IPIPSEC_USE_LINUX_PFKEYV2_API */
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 8 FUNCTIONS.
|
|
****************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_printf
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*/
|
|
static void
|
|
keyadm_printf(Vars *vars, const char *format, ...)
|
|
{
|
|
#if IPCOM_USE_SHELL != IPCOM_SHELL_NONE || defined(IP_PORT_LAS)
|
|
if (vars->silent == 0)
|
|
{
|
|
va_list ap;
|
|
int retval;
|
|
|
|
va_start(ap, format);
|
|
retval = ipcom_vsprintf(vars->stdoutbuf, format, ap);
|
|
va_end(ap);
|
|
|
|
ip_assert(retval < 512);
|
|
if (retval > 0)
|
|
{
|
|
if (vars->syslog)
|
|
IPCOM_LOG1(DEBUG, "%s", vars->stdoutbuf);
|
|
else
|
|
(void)ipcom_printf(vars->stdoutbuf);
|
|
}
|
|
}
|
|
#else
|
|
IPCOM_UNUSED_ARG(vars);
|
|
IPCOM_UNUSED_ARG(format);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_cmd_bits_to_str
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static IP_CONST char *
|
|
keyadm_cmd_bits_to_str(char **map, Ip_u32 bits, char *str, Ip_size_t str_len)
|
|
{
|
|
int i;
|
|
int len = 0;
|
|
|
|
str[0] = '\0';
|
|
|
|
for (i = 0; i < 32 && *map[i] != '\0'; i++)
|
|
if (IP_BIT_ISSET(bits, 1 << i))
|
|
len += ipcom_snprintf(str + len, str_len - len, "%s ", map[i]);
|
|
|
|
return str;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_strcasecmp
|
|
*===========================================================================
|
|
*/
|
|
static int
|
|
keyadm_strcasecmp(IP_CONST char *s1, IP_CONST char *s2)
|
|
{
|
|
while (ipcom_toupper(*s1) == ipcom_toupper(*s2))
|
|
{
|
|
if (*s1 == '\0')
|
|
return 0;
|
|
s1++;
|
|
s2++;
|
|
}
|
|
return ipcom_toupper(*s1) - ipcom_toupper(*s2);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_search_block
|
|
*===========================================================================
|
|
*/
|
|
static int
|
|
keyadm_search_block(char *arg, IP_CONST char **list)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; **(list + i) != '\n'; i++)
|
|
if (!keyadm_strcasecmp(arg, *(list + i)))
|
|
return (i);
|
|
|
|
return (-1);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_hex_to_long
|
|
*===========================================================================
|
|
*/
|
|
static int
|
|
keyadm_hex_to_long(Vars *vars, char *s, int *do_exit)
|
|
{
|
|
char ss[3];
|
|
ss[0] = s[0];
|
|
ss[1] = s[1];
|
|
ss[2] = 0;
|
|
|
|
if (!ipcom_isxdigit((int)s[0]) || !ipcom_isxdigit((int)s[1]))
|
|
{
|
|
keyadm_printf(vars, "keyadm: keys should be specified in hex digits"IP_LF);
|
|
*do_exit = 1;
|
|
}
|
|
else
|
|
*do_exit = 0;
|
|
|
|
return ipcom_strtoul(ss, IP_NULL, 16);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_read_addr
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_read_addr(IP_CONST char *string, union Ip_sockaddr_union *sockaddr)
|
|
{
|
|
int af;
|
|
|
|
#if defined(IPCOM_USE_INET) && defined(IPCOM_USE_INET6)
|
|
if (ipcom_strchr(string, ':'))
|
|
af = IP_AF_INET6;
|
|
else
|
|
af = IP_AF_INET;
|
|
#elif defined(IPCOM_USE_INET6)
|
|
af = IP_AF_INET6;
|
|
#else
|
|
af = IP_AF_INET;
|
|
#endif
|
|
|
|
return ipcom_getsockaddrbyaddrname(af, IP_TRUE /* do not use dns */, string, &sockaddr->sa);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_ipaddr_to_extaddr
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static void
|
|
keyadm_ipaddr_to_extaddr(struct sadb_address_full *address, union Ip_sockaddr_union *sockaddr)
|
|
{
|
|
int addrsize;
|
|
#if defined(IPCOM_USE_INET) && defined(IPCOM_USE_INET6)
|
|
addrsize = sockaddr->sa.sa_family == IP_AF_INET ? EXT_SADBADDR_SIZE_IN : EXT_SADBADDR_SIZE_IN6;
|
|
#elif defined(IPCOM_USE_INET6)
|
|
addrsize = EXT_SADBADDR_SIZE_IN6;
|
|
#else
|
|
addrsize = EXT_SADBADDR_SIZE_IN;
|
|
#endif
|
|
address->addr.sadb_address_len = (uint16_t)(addrsize >> 3);
|
|
address->addr.sadb_address_proto = 0; /*!! non-zero ports -> UDP OR TCP else 0 */
|
|
address->addr.sadb_address_prefixlen = 0;
|
|
address->addr.sadb_address_reserved = 0;
|
|
|
|
ipcom_memcpy(&address->sock, sockaddr, sizeof(union Ip_sockaddr_union));
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_send_command
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_send_command(Vars *vars, Ip_u8 type, Ip_u8 satype)
|
|
{
|
|
int retval = 0, i, length;
|
|
Ip_u8 *orgbuf, *msgbuf;
|
|
struct sadb_address_full src, dst, dst2, proxy, srcflow, srcmaxflow, dstflow, dstmaxflow, srcmask, dstmask;
|
|
struct sadb_spirange spi;
|
|
struct sadb_sa sa, sa2;
|
|
struct sadb_protocol proto2;
|
|
struct sadb_lifetime ls, lh;
|
|
struct sadb_x_flowopt flowopt;
|
|
struct sadb_x_saopt saopt;
|
|
struct sadb_x_udpencap udpencap;
|
|
#ifdef IPIPSEC_USE_LINUX_PFKEYV2_API
|
|
struct sadb_x_sa2 lx_sa2;
|
|
#endif
|
|
|
|
/** Auto build some extension headers **/
|
|
|
|
/* SADB_EXT_SA */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_SA))
|
|
{
|
|
ipcom_memset(&sa, 0, sizeof(struct sadb_sa));
|
|
vars->sadb->sa = &sa;
|
|
vars->sadb->sa->sadb_sa_len = sizeof(struct sadb_sa) / sizeof(Ip_u64);
|
|
vars->sadb->sa->sadb_sa_exttype = SADB_EXT_SA;
|
|
vars->sadb->sa->sadb_sa_spi = vars->spi_n;
|
|
vars->sadb->sa->sadb_sa_replay = (Ip_u8)vars->replay;
|
|
vars->sadb->sa->sadb_sa_auth = vars->auth_type;
|
|
if (vars->sadb->sa->sadb_sa_auth == SADB_AALG_UNSET)
|
|
vars->sadb->sa->sadb_sa_auth = SADB_AALG_NONE;
|
|
vars->sadb->sa->sadb_sa_encrypt = vars->encrypt_type;
|
|
if (vars->sadb->sa->sadb_sa_encrypt == SADB_EALG_UNSET)
|
|
vars->sadb->sa->sadb_sa_encrypt = SADB_EALG_NONE;
|
|
vars->sadb->sa->sadb_sa_flags = vars->sa_flags;
|
|
if (type == SADB_UPDATE || type == SADB_ADD)
|
|
{
|
|
vars->sadb->sa->sadb_sa_state = SADB_SASTATE_MATURE;
|
|
if (IP_BIT_ISSET(vars->sa_flags, SADB_X_SAFLAGS_UDPENCAP))
|
|
{
|
|
vars->sadb->udpencap = (struct sadb_x_udpencap *)&udpencap;
|
|
vars->sadb->udpencap->sadb_x_udpencap_len = sizeof(struct sadb_x_udpencap) / sizeof(Ip_u64);
|
|
vars->sadb->udpencap->sadb_x_udpencap_exttype = SADB_X_EXT_UDPENCAP;
|
|
vars->sadb->udpencap->sadb_x_udpencap_src_port = ip_htons(vars->udpencap_port);
|
|
vars->sadb->udpencap->sadb_x_udpencap_dst_port = vars->sadb->udpencap->sadb_x_udpencap_src_port;
|
|
}
|
|
#ifdef IPIPSEC_USE_LINUX_PFKEYV2_API
|
|
if (vars->is_linux)
|
|
{
|
|
vars->sadb->lx_sa2 = (struct sadb_x_sa2 *)&lx_sa2;
|
|
vars->sadb->lx_sa2->sadb_x_sa2_len = sizeof(struct sadb_x_sa2) >> 3;
|
|
vars->sadb->lx_sa2->sadb_x_sa2_exttype = SADB_LX_EXT_SA2;
|
|
if (IP_BIT_ISSET(vars->sa_flags, SADB_X_SAFLAGS_TUNNEL))
|
|
vars->sadb->lx_sa2->sadb_x_sa2_mode = IPSEC_MODE_TUNNEL;
|
|
else
|
|
vars->sadb->lx_sa2->sadb_x_sa2_mode = IPSEC_MODE_TRANSPORT;
|
|
vars->sadb->lx_sa2->sadb_x_sa2_sequence = 0;
|
|
vars->sadb->lx_sa2->sadb_x_sa2_reqid = vars->reqid;
|
|
}
|
|
#endif /* #ifdef IPIPSEC_USE_LINUX_PFKEYV2_API */
|
|
}
|
|
}
|
|
|
|
/* SADB_EXT_SPIRANGE */
|
|
if (vars->maxspi && IP_BIT_ISSET(vars->extmap, SEBIT_SPIRANGE))
|
|
{
|
|
vars->sadb->spirange = (struct sadb_spirange *)&spi;
|
|
vars->sadb->spirange->sadb_spirange_len = sizeof(struct sadb_spirange) / sizeof(Ip_u64);
|
|
vars->sadb->spirange->sadb_spirange_exttype = SADB_EXT_SPIRANGE;
|
|
vars->sadb->spirange->sadb_spirange_min = vars->minspi;
|
|
vars->sadb->spirange->sadb_spirange_max = vars->maxspi;
|
|
vars->sadb->spirange->sadb_spirange_reserved = 0;
|
|
}
|
|
|
|
/* SADB_EXT_ADDRESS_SRC */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_ADDRESS_SRC))
|
|
{
|
|
vars->sadb->address_src = (struct sadb_address *)&src;
|
|
keyadm_ipaddr_to_extaddr(&src, &vars->srcaddr);
|
|
vars->sadb->address_src->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
|
|
}
|
|
|
|
/* SADB_EXT_ADDRESS_DST */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_ADDRESS_DST))
|
|
{
|
|
vars->sadb->address_dst = (struct sadb_address *)&dst;
|
|
keyadm_ipaddr_to_extaddr(&dst, &vars->dstaddr);
|
|
vars->sadb->address_dst->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
|
|
}
|
|
|
|
/* SADB_EXT_ADDRESS_PROXY */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_ADDRESS_PROXY))
|
|
{
|
|
vars->sadb->address_proxy = (struct sadb_address *)&proxy;
|
|
keyadm_ipaddr_to_extaddr(&proxy, &vars->proxyaddr);
|
|
vars->sadb->address_proxy->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY;
|
|
}
|
|
|
|
/* SADB_EXT_KEY_ENCRYPT */
|
|
if (vars->encrypt_bytes > 0)
|
|
{
|
|
vars->sadb->key_encrypt = &vars->encrypt_sadb;
|
|
vars->sadb->key_encrypt->sadb_key_len = (uint16_t)((sizeof(struct sadb_key) + IP_ROUNDUP(vars->encrypt_bytes, 8)) / sizeof(Ip_u64));
|
|
vars->sadb->key_encrypt->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
|
|
vars->sadb->key_encrypt->sadb_key_bits = (uint16_t)(vars->encrypt_bytes * 8);
|
|
vars->sadb->key_encrypt->sadb_key_reserved = 0;
|
|
}
|
|
|
|
/* SADB_EXT_KEY_AUTH */
|
|
if (vars->auth_bytes > 0)
|
|
{
|
|
vars->sadb->key_auth = &vars->auth_sadb;
|
|
vars->sadb->key_auth->sadb_key_len = (uint16_t)((sizeof(struct sadb_key) + IP_ROUNDUP(vars->auth_bytes, 8)) / sizeof(Ip_u64));
|
|
vars->sadb->key_auth->sadb_key_exttype = SADB_EXT_KEY_AUTH;
|
|
vars->sadb->key_auth->sadb_key_bits = (uint16_t)(vars->auth_bytes * 8);
|
|
vars->sadb->key_auth->sadb_key_reserved = 0;
|
|
}
|
|
|
|
/* SEBIT_X_SRC_FLOW */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_X_SRC_FLOW))
|
|
{
|
|
vars->sadb->src_flow = (struct sadb_address *)&srcflow;
|
|
keyadm_ipaddr_to_extaddr(&srcflow, &vars->srcflow);
|
|
srcflow.sock.sin.sin_port = vars->srcport_n;
|
|
vars->sadb->src_flow->sadb_address_exttype = SADB_X_EXT_SRC_FLOW;
|
|
|
|
/* SEBIT_X_SRCMAX_FLOW */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_X_SRCMAX_FLOW))
|
|
{
|
|
vars->sadb->srcmax_flow = (struct sadb_address *)&srcmaxflow;
|
|
if (ipcom_memcmp(&vars->srcmaxflow, &vars->zeroaddr, sizeof(union Ip_sockaddr_union)))
|
|
keyadm_ipaddr_to_extaddr(&srcmaxflow, &vars->srcmaxflow);
|
|
else
|
|
keyadm_ipaddr_to_extaddr(&srcmaxflow, &vars->srcflow);
|
|
if (vars->srcmaxport_n != 0)
|
|
srcmaxflow.sock.sin.sin_port = vars->srcmaxport_n;
|
|
else
|
|
srcmaxflow.sock.sin.sin_port = vars->srcport_n;
|
|
vars->sadb->srcmax_flow->sadb_address_exttype = SADB_X_EXT_SRCMAX_FLOW;
|
|
}
|
|
}
|
|
|
|
/* SEBIT_X_DST_FLOW */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_X_DST_FLOW))
|
|
{
|
|
vars->sadb->dst_flow = (struct sadb_address *)&dstflow;
|
|
keyadm_ipaddr_to_extaddr(&dstflow, &vars->dstflow);
|
|
dstflow.sock.sin.sin_port = vars->dstport_n;
|
|
vars->sadb->dst_flow->sadb_address_exttype = SADB_X_EXT_DST_FLOW;
|
|
|
|
/* SEBIT_X_DSTMAX_FLOW */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_X_DSTMAX_FLOW))
|
|
{
|
|
vars->sadb->dstmax_flow = (struct sadb_address *)&dstmaxflow;
|
|
if (ipcom_memcmp(&vars->dstmaxflow, &vars->zeroaddr, sizeof(union Ip_sockaddr_union)))
|
|
keyadm_ipaddr_to_extaddr(&dstmaxflow, &vars->dstmaxflow);
|
|
else
|
|
keyadm_ipaddr_to_extaddr(&dstmaxflow, &vars->dstflow);
|
|
if (vars->dstmaxport_n != 0)
|
|
dstmaxflow.sock.sin.sin_port = vars->dstmaxport_n;
|
|
else
|
|
dstmaxflow.sock.sin.sin_port = vars->dstport_n;
|
|
vars->sadb->dstmax_flow->sadb_address_exttype = SADB_X_EXT_DSTMAX_FLOW;
|
|
}
|
|
}
|
|
|
|
/* SEBIT_X_SRC_MASK */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_X_SRC_MASK))
|
|
{
|
|
vars->sadb->src_mask = (struct sadb_address *)&srcmask;
|
|
keyadm_ipaddr_to_extaddr(&srcmask, &vars->srcmask);
|
|
vars->sadb->src_mask->sadb_address_exttype = SADB_X_EXT_SRC_MASK;
|
|
}
|
|
|
|
/* SEBIT_X_DST_MASK */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_X_DST_MASK))
|
|
{
|
|
vars->sadb->dst_mask = (struct sadb_address *)&dstmask;
|
|
keyadm_ipaddr_to_extaddr(&dstmask, &vars->dstmask);
|
|
vars->sadb->dst_mask->sadb_address_exttype = SADB_X_EXT_DST_MASK;
|
|
}
|
|
|
|
/* SEBIT_X_DST2 */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_X_DST2))
|
|
{
|
|
vars->sadb->dst2 = (struct sadb_address *)&dst2;
|
|
keyadm_ipaddr_to_extaddr(&dst2, &vars->dstaddr2);
|
|
vars->sadb->dst2->sadb_address_exttype = SADB_X_EXT_DST2;
|
|
}
|
|
|
|
/* SEBIT_X_SA2 */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_X_SA2))
|
|
{
|
|
ipcom_memset(&sa2, 0, sizeof(struct sadb_sa));
|
|
vars->sadb->sa2 = &sa2;
|
|
vars->sadb->sa2->sadb_sa_spi = vars->spi2_n;
|
|
vars->sadb->sa2->sadb_sa_len = sizeof(struct sadb_sa) / sizeof(Ip_u64);
|
|
vars->sadb->sa2->sadb_sa_exttype = SADB_X_EXT_SA2;
|
|
vars->sadb->sa2->sadb_sa_state = SADB_SASTATE_MATURE;
|
|
}
|
|
|
|
/* SEBIT_LIFETIME_SOFT - soft lifetime */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_LIFETIME_SOFT))
|
|
{
|
|
ipcom_memset(&ls, 0, sizeof(struct sadb_lifetime));
|
|
vars->sadb->lifetime_soft = &ls;
|
|
vars->sadb->lifetime_soft->sadb_lifetime_len = sizeof(struct sadb_lifetime) / sizeof(Ip_u64);
|
|
vars->sadb->lifetime_soft->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
|
|
vars->sadb->lifetime_soft->sadb_lifetime_bytes = vars->ls_bytes;
|
|
IP_U64_SETLO(vars->sadb->lifetime_soft->sadb_lifetime_addtime, vars->ls_sec);
|
|
}
|
|
|
|
/* SEBIT_LIFETIME_HARD - hard lifetime */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_LIFETIME_HARD))
|
|
{
|
|
ipcom_memset(&lh, 0, sizeof(struct sadb_lifetime));
|
|
vars->sadb->lifetime_hard = &lh;
|
|
vars->sadb->lifetime_hard->sadb_lifetime_len = sizeof(struct sadb_lifetime) / sizeof(Ip_u64);
|
|
vars->sadb->lifetime_hard->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
|
|
vars->sadb->lifetime_hard->sadb_lifetime_bytes = vars->lh_bytes;
|
|
IP_U64_SETLO(vars->sadb->lifetime_hard->sadb_lifetime_addtime, vars->lh_sec);
|
|
}
|
|
|
|
/* "-proto2" SEBIT_X_PROTOCOL - security protocol */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_X_PROTOCOL))
|
|
{
|
|
ipcom_memset(&proto2, 0, sizeof(struct sadb_protocol));
|
|
vars->sadb->protocol = (struct sadb_protocol *)&proto2;
|
|
vars->sadb->protocol->sadb_protocol_len = sizeof(struct sadb_protocol) / sizeof(Ip_u64);
|
|
vars->sadb->protocol->sadb_protocol_exttype = SADB_X_EXT_PROTOCOL;
|
|
vars->sadb->protocol->sadb_protocol_proto = vars->satype2;
|
|
}
|
|
/* "-transport" SEBIT_X_PROTOCOL - transport protocol */
|
|
else if (vars->have_transport_proto || vars->ports0 || vars->ports1)
|
|
{
|
|
ipcom_memset(&proto2, 0, sizeof(struct sadb_protocol));
|
|
vars->sadb->protocol = (struct sadb_protocol *)&proto2;
|
|
vars->sadb->protocol->sadb_protocol_len = sizeof(struct sadb_protocol) / sizeof(Ip_u64);
|
|
vars->sadb->protocol->sadb_protocol_exttype = SADB_X_EXT_PROTOCOL;
|
|
vars->sadb->protocol->sadb_protocol_proto = vars->transport_proto;
|
|
vars->sadb->protocol->sadb_protocol_ports0 = vars->ports0;
|
|
vars->sadb->protocol->sadb_protocol_ports1 = vars->ports1;
|
|
}
|
|
|
|
/* SEBIT_X_FLOW_OPTIONS - flow type, id, direction and/or priority */
|
|
if ((type == SADB_X_ADDFLOW || type == SADB_X_DELFLOW
|
|
|| type == SADB_X_FINDFLOW || type == SADB_X_DUMPFLOW)
|
|
&& IP_BIT_ISSET(vars->extmap, SEBIT_X_FLOW_OPTIONS))
|
|
{
|
|
ipcom_memset(&flowopt, 0, sizeof(struct sadb_x_flowopt));
|
|
vars->sadb->flowopt = (struct sadb_x_flowopt *)&flowopt;
|
|
vars->sadb->flowopt->sadb_flowopt_len = sizeof(struct sadb_x_flowopt) / sizeof(Ip_u64);
|
|
vars->sadb->flowopt->sadb_flowopt_exttype = SADB_X_EXT_FLOW_OPTIONS;
|
|
vars->sadb->flowopt->sadb_flowopt_type = vars->flow_type;
|
|
if (IP_BIT_ISSET(vars->sa_flags, SADB_X_SAFLAGS_EGRESS_SA))
|
|
vars->sadb->flowopt->sadb_flowopt_direction = 2;
|
|
if (IP_BIT_ISSET(vars->sa_flags, SADB_X_SAFLAGS_INGRESS_SA))
|
|
vars->sadb->flowopt->sadb_flowopt_direction = 1;
|
|
vars->sadb->flowopt->sadb_flowopt_priority = (signed char)vars->flow_priority;
|
|
vars->sadb->flowopt->sadb_flowopt_dscp = vars->dscp;
|
|
vars->sadb->flowopt->sadb_flowopt_id = vars->flow_id;
|
|
}
|
|
|
|
/* SEBIT_X_EXT_SA_OPTIONS */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_X_EXT_SA_OPTIONS))
|
|
{
|
|
ipcom_memset(&saopt, 0, sizeof(struct sadb_x_saopt));
|
|
vars->sadb->saopt = (struct sadb_x_saopt *)&saopt;
|
|
vars->sadb->saopt->sadb_saopt_len = sizeof(struct sadb_x_saopt) / sizeof(Ip_u64);
|
|
vars->sadb->saopt->sadb_saopt_exttype = SADB_X_EXT_SA_OPTIONS;
|
|
vars->sadb->saopt->sadb_saopt_priority = (signed char)vars->sa_priority;
|
|
}
|
|
|
|
/* Calculate message length */
|
|
for (length = sizeof(struct sadb_msg), i = 1; i <= SADB_EXT_MAX; i++)
|
|
if (vars->exthdr[i] != IP_NULL)
|
|
length += (((struct sadb_ext *)vars->exthdr[i])->sadb_ext_len * sizeof(Ip_u64));
|
|
|
|
/* Allocate memory for the PFKEY write */
|
|
orgbuf = (Ip_u8 *)ipcom_malloc(length + sizeof(Ip_u64));
|
|
if (orgbuf == IP_NULL)
|
|
{
|
|
keyadm_printf(vars, "keyadm: out of memory"IP_LF);
|
|
return -1;
|
|
}
|
|
msgbuf = IP_PTR_ALIGN(orgbuf, 8); /* 64-bit align msgbuf */
|
|
ip_assert(((Ip_ptrdiff_t)msgbuf & 0x7L) == 0);
|
|
ipcom_memset(msgbuf, 0, length);
|
|
|
|
/* Set SADB_MSG */
|
|
vars->sadb->msg->sadb_msg_version = PF_KEY_V2;
|
|
vars->sadb->msg->sadb_msg_type = type;
|
|
vars->sadb->msg->sadb_msg_errno = 0;
|
|
vars->sadb->msg->sadb_msg_satype = satype;
|
|
vars->sadb->msg->sadb_msg_reserved = 0;
|
|
vars->sadb->msg->sadb_msg_len = (uint16_t)(length / sizeof(Ip_u64));
|
|
vars->sadb->msg->sadb_msg_seq = sadbmsgseq++;
|
|
vars->sadb->msg->sadb_msg_pid = ipcom_getpid();
|
|
|
|
/* Copy over all headers */
|
|
ipcom_memcpy(msgbuf, vars->sadb->msg, sizeof(struct sadb_msg));
|
|
for (length = sizeof(struct sadb_msg), i = 1; i <= SADB_EXT_MAX; i++)
|
|
if (vars->exthdr[i] != IP_NULL)
|
|
{
|
|
ipcom_memcpy(msgbuf + length,
|
|
vars->exthdr[i],
|
|
((struct sadb_ext *)vars->exthdr[i])->sadb_ext_len * sizeof(Ip_u64));
|
|
length += ((struct sadb_ext *)vars->exthdr[i])->sadb_ext_len * sizeof(Ip_u64);
|
|
}
|
|
|
|
/* Write the SADB message */
|
|
if (ipcom_send(vars->fd, (char*)msgbuf, length, 0) != length)
|
|
{
|
|
keyadm_printf(vars, "keyadm: ipcom_send() failed: %s (%d)"IP_LF,
|
|
ipcom_strerror(ipcom_errno), ipcom_errno);
|
|
if (ipcom_errno == IP_ERRNO_EINVAL || ipcom_errno == IP_ERRNO_ENOMEM
|
|
|| ipcom_errno == IP_ERRNO_ENOBUFS)
|
|
retval = -1;
|
|
}
|
|
|
|
if (orgbuf)
|
|
ipcom_free(orgbuf);
|
|
|
|
return retval;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_send_command_linux
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
#ifdef IPIPSEC_USE_LINUX_PFKEYV2_API
|
|
static int
|
|
keyadm_send_command_linux(Vars *vars, Ip_u8 type, Ip_u8 satype)
|
|
{
|
|
int retval = 0, i, length;
|
|
Ip_u8 *orgbuf, *msgbuf;
|
|
struct sadb_address_full src, dst;
|
|
struct policy
|
|
{
|
|
struct sadb_x_policy policy;
|
|
struct sadb_x_ipsecrequest xisr;
|
|
union Ip_sockaddr_union sockbuf[2];
|
|
} pol;
|
|
Ip_u16 policy_type;
|
|
|
|
/** Auto build some extension headers **/
|
|
|
|
/* SADB_EXT_ADDRESS_SRC */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_X_SRC_FLOW))
|
|
{
|
|
vars->sadb->address_src = (struct sadb_address *)&src;
|
|
keyadm_ipaddr_to_extaddr(&src, &vars->srcflow);
|
|
src.sock.sin.sin_port = vars->srcport_n;
|
|
vars->sadb->address_src->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
|
|
vars->sadb->address_src->sadb_address_proto = vars->transport_proto;
|
|
|
|
if (vars->srcmask.sa.sa_family==0)
|
|
{
|
|
#if defined(IPCOM_USE_INET)
|
|
if (vars->srcflow.sa.sa_family == IP_AF_INET)
|
|
vars->sadb->address_src->sadb_address_prefixlen=32;
|
|
#endif
|
|
#if defined(IPCOM_USE_INET6)
|
|
if (vars->srcflow.sa.sa_family == IP_AF_INET6)
|
|
vars->sadb->address_src->sadb_address_prefixlen=128;
|
|
#endif
|
|
|
|
}
|
|
else
|
|
{
|
|
vars->sadb->address_src->sadb_address_prefixlen = ipcom_sockaddr_to_prefixlen(&vars->srcmask.sa);
|
|
}
|
|
}
|
|
|
|
/* SADB_EXT_ADDRESS_DST */
|
|
if (IP_BIT_ISSET(vars->extmap, SEBIT_X_DST_FLOW))
|
|
{
|
|
vars->sadb->address_dst = (struct sadb_address *)&dst;
|
|
keyadm_ipaddr_to_extaddr(&dst, &vars->dstflow);
|
|
dst.sock.sin.sin_port = vars->dstport_n;
|
|
vars->sadb->address_dst->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
|
|
vars->sadb->address_dst->sadb_address_proto = vars->transport_proto;
|
|
if (vars->dstmask.sa.sa_family==0)
|
|
{
|
|
#if defined(IPCOM_USE_INET)
|
|
if (vars->dstflow.sa.sa_family == IP_AF_INET)
|
|
vars->sadb->address_dst->sadb_address_prefixlen=32;
|
|
#endif
|
|
#if defined(IPCOM_USE_INET6)
|
|
if (vars->dstflow.sa.sa_family == IP_AF_INET6)
|
|
vars->sadb->address_dst->sadb_address_prefixlen=128;
|
|
#endif
|
|
|
|
}
|
|
else
|
|
{
|
|
vars->sadb->address_dst->sadb_address_prefixlen = ipcom_sockaddr_to_prefixlen(&vars->dstmask.sa);
|
|
}
|
|
}
|
|
|
|
/* SADB_X_EXT_POLICY */
|
|
ipcom_memset(&pol, 0, sizeof(struct policy));
|
|
vars->sadb->lx_policy = &pol.policy;
|
|
pol.policy.sadb_x_policy_len = sizeof(struct sadb_x_policy) / sizeof(Ip_u64);
|
|
pol.policy.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
|
|
switch (vars->flow_type) /*!!WHAT IS? IPSEC_POLICY_ENTRUST*/
|
|
{
|
|
case SADB_X_FLOW_TYPE_BYPASS: /* Send without applying security, i.e. cleartext */
|
|
policy_type = IPSEC_POLICY_BYPASS;
|
|
break;
|
|
case SADB_X_FLOW_TYPE_DENY: /* Silent discard */
|
|
policy_type = IPSEC_POLICY_DISCARD;
|
|
break;
|
|
case SADB_X_FLOW_TYPE_USE: /* Apply security (standard flow) */
|
|
case SADB_X_FLOW_TYPE_ACQUIRE: /* Generate acquire message, send packet in cleartext */
|
|
case SADB_X_FLOW_TYPE_REQUIRE: /* Generate require message, discard packet */
|
|
default:
|
|
policy_type = IPSEC_POLICY_IPSEC;
|
|
break;
|
|
}
|
|
pol.policy.sadb_x_policy_type = policy_type;
|
|
if (IP_BIT_ISSET(vars->sa_flags, SADB_X_SAFLAGS_EGRESS_SA))
|
|
pol.policy.sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
|
|
else if (IP_BIT_ISSET(vars->sa_flags, SADB_X_SAFLAGS_INGRESS_SA))
|
|
pol.policy.sadb_x_policy_dir = IPSEC_DIR_INBOUND;
|
|
else
|
|
pol.policy.sadb_x_policy_dir = IPSEC_DIR_INVALID;
|
|
pol.policy.sadb_x_policy_id = vars->flow_id;
|
|
/*!!CHECK: that -127 is negative, i.e. 0x80000000 bit set */
|
|
pol.policy.sadb_x_policy_priority = (uint32_t)vars->flow_priority;
|
|
|
|
/* IPSECREQUEST (Used as a SA-selector) */
|
|
pol.xisr.sadb_x_ipsecrequest_len = sizeof(struct sadb_x_ipsecrequest);
|
|
/* Protocol */
|
|
switch (vars->satype)
|
|
{
|
|
case SADB_SATYPE_AH:
|
|
pol.xisr.sadb_x_ipsecrequest_proto = IP_IPPROTO_AH;
|
|
break;
|
|
default:
|
|
pol.xisr.sadb_x_ipsecrequest_proto = IP_IPPROTO_ESP;
|
|
break;
|
|
}
|
|
if (IP_BIT_ISSET(vars->sa_flags, SADB_X_SAFLAGS_TUNNEL))
|
|
pol.xisr.sadb_x_ipsecrequest_mode = IPSEC_MODE_TUNNEL;
|
|
else
|
|
pol.xisr.sadb_x_ipsecrequest_mode = IPSEC_MODE_TRANSPORT;
|
|
|
|
/* Mode */
|
|
if (vars->reqid != 0)
|
|
{
|
|
pol.xisr.sadb_x_ipsecrequest_reqid = vars->reqid;
|
|
pol.xisr.sadb_x_ipsecrequest_level = IPSEC_LEVEL_UNIQUE;
|
|
}
|
|
else
|
|
{
|
|
switch (vars->flow_type)
|
|
{
|
|
case SADB_X_FLOW_TYPE_REQUIRE: /* Generate require message, discard packet */
|
|
pol.xisr.sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
|
|
break;
|
|
/*!!TODO: support for MODE_ANY */
|
|
case SADB_X_FLOW_TYPE_ACQUIRE: /* Generate acquire message, send packet in cleartext */
|
|
default:
|
|
pol.xisr.sadb_x_ipsecrequest_level = IPSEC_LEVEL_USE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pol.xisr.sadb_x_ipsecrequest_mode == IPSEC_MODE_TUNNEL)
|
|
{
|
|
/* Add source&destination tunnel endpoints */
|
|
#ifdef IPCOM_USE_INET
|
|
if (vars->srctunnel.sa.sa_family == IP_AF_INET
|
|
|| vars->dsttunnel.sa.sa_family == IP_AF_INET)
|
|
{
|
|
struct Ip_sockaddr_in *src_sinp = (struct Ip_sockaddr_in *)&pol.sockbuf;
|
|
struct Ip_sockaddr_in *dst_sinp = (struct Ip_sockaddr_in *)((Ip_caddr_t)&pol.sockbuf + sizeof(struct Ip_sockaddr_in));
|
|
|
|
/* Tunnel source */
|
|
src_sinp->sin_len = sizeof(struct Ip_sockaddr_in);
|
|
src_sinp->sin_family = IP_AF_INET;
|
|
src_sinp->sin_port = vars->srctunnel.sin.sin_port;
|
|
src_sinp->sin_addr.s_addr = vars->srctunnel.sin.sin_addr.s_addr;
|
|
|
|
/* Tunnel destination */
|
|
dst_sinp->sin_len = sizeof(struct Ip_sockaddr_in);
|
|
dst_sinp->sin_family = IP_AF_INET;
|
|
dst_sinp->sin_port = vars->dsttunnel.sin.sin_port;
|
|
dst_sinp->sin_addr.s_addr = vars->dsttunnel.sin.sin_addr.s_addr;
|
|
|
|
pol.xisr.sadb_x_ipsecrequest_len += (2 * sizeof(struct Ip_sockaddr_in));
|
|
}
|
|
#endif /* IPCOM_USE_INET */
|
|
|
|
#ifdef IPCOM_USE_INET6
|
|
if (vars->srctunnel.sa.sa_family == IP_AF_INET6
|
|
|| vars->dsttunnel.sa.sa_family == IP_AF_INET6)
|
|
{
|
|
struct Ip_sockaddr_in6 *src_sin6p = (struct Ip_sockaddr_in6 *)&pol.sockbuf;
|
|
struct Ip_sockaddr_in6 *dst_sin6p = (struct Ip_sockaddr_in6 *)((Ip_caddr_t)&pol.sockbuf + sizeof(struct Ip_sockaddr_in6));
|
|
|
|
/* Tunnel source */
|
|
src_sin6p->sin6_len = sizeof(struct Ip_sockaddr_in6);
|
|
src_sin6p->sin6_family = IP_AF_INET6;
|
|
src_sin6p->sin6_port = vars->srctunnel.sin6.sin6_port;
|
|
ipcom_memcpy(&src_sin6p->sin6_addr, &vars->srctunnel.sin6.sin6_addr, sizeof(struct Ip_in6_addr));
|
|
|
|
/* Tunnel destination */
|
|
dst_sin6p->sin6_len = sizeof(struct Ip_sockaddr_in6);
|
|
dst_sin6p->sin6_family = IP_AF_INET6;
|
|
dst_sin6p->sin6_port = vars->dsttunnel.sin6.sin6_port;
|
|
ipcom_memcpy(&dst_sin6p->sin6_addr, &vars->dsttunnel.sin6.sin6_addr, sizeof(struct Ip_in6_addr));
|
|
pol.xisr.sadb_x_ipsecrequest_len += (2 * sizeof(struct Ip_sockaddr_in6));
|
|
}
|
|
#endif /* IPCOM_USE_INET6 */
|
|
}
|
|
|
|
pol.policy.sadb_x_policy_len += (IP_ROUNDUP(pol.xisr.sadb_x_ipsecrequest_len, 8) / sizeof(Ip_u64));
|
|
|
|
|
|
/* Calculate message length */
|
|
for (length = sizeof(struct sadb_msg), i = 1; i <= SADB_EXT_MAX; i++)
|
|
if (vars->exthdr[i] != IP_NULL)
|
|
length += (((struct sadb_ext *)vars->exthdr[i])->sadb_ext_len * sizeof(Ip_u64));
|
|
|
|
/* Allocate memory for the PFKEY write */
|
|
orgbuf = (Ip_u8 *)ipcom_malloc(length + sizeof(Ip_u64));
|
|
if (orgbuf == IP_NULL)
|
|
{
|
|
keyadm_printf(vars, "keyadm: out of memory"IP_LF);
|
|
return -1;
|
|
}
|
|
msgbuf = IP_PTR_ALIGN(orgbuf, 8); /* 64-bit align msgbuf */
|
|
ip_assert(((Ip_ptrdiff_t)msgbuf & 0x7L) == 0);
|
|
ipcom_memset(msgbuf, 0, length);
|
|
|
|
/* Set SADB_MSG */
|
|
vars->sadb->msg->sadb_msg_version = PF_KEY_V2;
|
|
vars->sadb->msg->sadb_msg_type = type;
|
|
vars->sadb->msg->sadb_msg_errno = 0;
|
|
vars->sadb->msg->sadb_msg_satype = satype;
|
|
vars->sadb->msg->sadb_msg_reserved = 0;
|
|
vars->sadb->msg->sadb_msg_len = (uint16_t)(length / sizeof(Ip_u64));
|
|
vars->sadb->msg->sadb_msg_seq = sadbmsgseq++;
|
|
vars->sadb->msg->sadb_msg_pid = ipcom_getpid();
|
|
|
|
/* Copy over all headers */
|
|
ipcom_memcpy(msgbuf, vars->sadb->msg, sizeof(struct sadb_msg));
|
|
for (length = sizeof(struct sadb_msg), i = 1; i <= SADB_EXT_MAX; i++)
|
|
if (vars->exthdr[i] != IP_NULL)
|
|
{
|
|
ipcom_memcpy(msgbuf + length,
|
|
vars->exthdr[i],
|
|
((struct sadb_ext *)vars->exthdr[i])->sadb_ext_len * sizeof(Ip_u64));
|
|
length += ((struct sadb_ext *)vars->exthdr[i])->sadb_ext_len * sizeof(Ip_u64);
|
|
}
|
|
|
|
/* Write the SADB message */
|
|
if (ipcom_send(vars->fd, (char*)msgbuf, length, 0) != length)
|
|
{
|
|
keyadm_printf(vars, "keyadm: ipcom_send() failed: %s (%d)"IP_LF,
|
|
ipcom_strerror(ipcom_errno), ipcom_errno);
|
|
if (ipcom_errno == IP_ERRNO_EINVAL || ipcom_errno == IP_ERRNO_ENOMEM
|
|
|| ipcom_errno == IP_ERRNO_ENOBUFS)
|
|
retval = -1;
|
|
}
|
|
|
|
if (orgbuf)
|
|
ipcom_free(orgbuf);
|
|
|
|
return retval;
|
|
}
|
|
#endif /* #ifdef IPIPSEC_USE_LINUX_PFKEYV2_API */
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_receive_command
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters: vars and timeout_seconds (0 = block)
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_receive_command(Vars *vars, Ip_u32 timeout_seconds)
|
|
{
|
|
int length;
|
|
int retval = -IP_ERRNO_EINVAL;
|
|
struct sadb_ext *ext;
|
|
|
|
/* Release previous memory */
|
|
if (vars->orgbuf)
|
|
{
|
|
ipcom_free(vars->orgbuf);
|
|
vars->orgbuf = IP_NULL;
|
|
}
|
|
|
|
/* Prepare ext array */
|
|
ipcom_memset(&vars->sadb->sa, 0, SADB_EXT_MAX * sizeof(void*)); /*lint !e419 */
|
|
|
|
/* Get buffer memory */
|
|
vars->orgbuf = (Ip_u8 *)ipcom_malloc(MAX_RCVBUF_SIZE + sizeof(Ip_u64));
|
|
if (vars->orgbuf == IP_NULL)
|
|
{
|
|
keyadm_printf(vars, "keyadm: out of memory, can't receive"IP_LF);
|
|
goto leave;
|
|
}
|
|
vars->msgbuf = IP_PTR_ALIGN(vars->orgbuf, 8); /* 64-bit align msgbuf */
|
|
ip_assert(((Ip_ptrdiff_t)vars->msgbuf & 0x7L) == 0);
|
|
ipcom_memset(vars->msgbuf, 0, MAX_RCVBUF_SIZE);
|
|
|
|
if (timeout_seconds != 0)
|
|
{
|
|
/* Set receive timeout */
|
|
struct Ip_timeval tv;
|
|
tv.tv_sec = timeout_seconds;
|
|
tv.tv_usec = 0;
|
|
length = ipcom_setsockopt(vars->fd, IP_SOL_SOCKET, IP_SO_RCVTIMEO, &tv, sizeof(tv));
|
|
if (length < 0)
|
|
{
|
|
keyadm_printf(vars, "ipcom_setsockopt() IP_SO_RCVTIMEO ");
|
|
return -IP_ERRNO_EINVAL;
|
|
}
|
|
}
|
|
|
|
/* Read a SADB message */
|
|
vars->sadb->msg = (struct sadb_msg *)vars->msgbuf;
|
|
length = (int)ipcom_recv(vars->fd, (char *)vars->msgbuf, MAX_RCVBUF_SIZE, 0);
|
|
if (length < (int)sizeof(struct sadb_msg))
|
|
{
|
|
if (length < 0)
|
|
{
|
|
if (ipcom_errno == IP_ERRNO_EWOULDBLOCK)
|
|
{
|
|
keyadm_printf(vars, "keyadm timeout"IP_LF);
|
|
return -IP_ERRNO_EWOULDBLOCK;
|
|
}
|
|
|
|
keyadm_printf(vars, "keyadm: ipcom_recv() failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
|
|
keyadm_printf(vars, " (try raise key socket buffer size with -b option)"IP_LF);
|
|
}
|
|
else if (length >= 3 && vars->sadb->msg->sadb_msg_errno != 0)
|
|
keyadm_printf(vars, "keyadm: ipcom_recv() msgerrno=%s"IP_LF, ipcom_strerror(vars->sadb->msg->sadb_msg_errno));
|
|
else
|
|
keyadm_printf(vars, "keyadm: ipcom_recv() truncated SADB (%d)"IP_LF, length);
|
|
goto leave;
|
|
}
|
|
else if (length == MAX_RCVBUF_SIZE)
|
|
keyadm_printf(vars, "keyadm: received too large SADB (%d)"IP_LF, length);
|
|
|
|
/* Verify the SADB_MSG header */
|
|
if (vars->sadb->msg->sadb_msg_version != PF_KEY_V2)
|
|
keyadm_printf(vars, "keyadm: illegal sadb_msg_version (%d)"IP_LF, vars->sadb->msg->sadb_msg_version);
|
|
else if (vars->sadb->msg->sadb_msg_type > SADB_MAX
|
|
|| vars->sadb->msg->sadb_msg_type == SADB_RESERVED)
|
|
keyadm_printf(vars, "keyadm: illegal sadb_msg_type (%d)"IP_LF, vars->sadb->msg->sadb_msg_type);
|
|
else if (vars->sadb->msg->sadb_msg_reserved != 0)
|
|
keyadm_printf(vars, "keyadm: illegal sadb_msg_reserved (%d)"IP_LF, vars->sadb->msg->sadb_msg_reserved);
|
|
else if ((int) (vars->sadb->msg->sadb_msg_len * sizeof(Ip_u64)) != length)
|
|
keyadm_printf(vars, "keyadm: length mismatch (sadb_msg_len=%d, length=%d)"IP_LF,
|
|
vars->sadb->msg->sadb_msg_len * sizeof(Ip_u64), length);
|
|
|
|
vars->msgbuf += sizeof(struct sadb_msg);
|
|
length -= sizeof(struct sadb_msg);
|
|
|
|
/* Verify the extensions */
|
|
for (ext = (struct sadb_ext *)vars->msgbuf;
|
|
length >= (int)sizeof(struct sadb_ext);
|
|
ext = (struct sadb_ext *)vars->msgbuf)
|
|
{
|
|
int ext_len;
|
|
|
|
/* Extension headers must start at 64-bit alignment */
|
|
if (((Ip_ptrdiff_t)ext & 0x7L) != 0)
|
|
keyadm_printf(vars, "keyadm: bad alignment for extension %d"IP_LF, ext->sadb_ext_type);
|
|
|
|
ext_len = ext->sadb_ext_len * sizeof(Ip_u64);
|
|
if (ext_len == 0 || length < ext_len)
|
|
{
|
|
keyadm_printf(vars, "keyadm: illegal EXT length (%d)"IP_LF, ext_len);
|
|
return -IP_ERRNO_EINVAL;
|
|
}
|
|
if (ext->sadb_ext_type == SADB_EXT_RESERVED || ext->sadb_ext_type > SADB_EXT_MAX)
|
|
{
|
|
keyadm_printf(vars, "keyadm: illegal/unknown EXT type (%d)"IP_LF, ext->sadb_ext_type);
|
|
return -IP_ERRNO_EINVAL;
|
|
}
|
|
else
|
|
{
|
|
/* [2.3] Only one instance of an extension header */
|
|
if (vars->exthdr[ext->sadb_ext_type] != IP_NULL)
|
|
keyadm_printf(vars, "keyadm: duplicate EXT type (%d)"IP_LF, ext->sadb_ext_type);
|
|
else
|
|
vars->exthdr[ext->sadb_ext_type] = ext;
|
|
|
|
/* _Exact_ extension header size check */
|
|
if (ipipsec_pfkeyv2_ext_size[ext->sadb_ext_type] > 0
|
|
&& ipipsec_pfkeyv2_ext_size[ext->sadb_ext_type] != ext_len)
|
|
return -IP_ERRNO_EINVAL;
|
|
|
|
/* _Minimum_ extension header size check */
|
|
if (ipipsec_pfkeyv2_ext_size[ext->sadb_ext_type] < 0
|
|
&& ext_len < -ipipsec_pfkeyv2_ext_size[ext->sadb_ext_type])
|
|
return -IP_ERRNO_EINVAL;
|
|
|
|
/* next extension header */
|
|
length -= ext_len;
|
|
vars->msgbuf += ext_len;
|
|
}
|
|
}
|
|
|
|
if (vars->sadb->msg->sadb_msg_errno != 0)
|
|
(void)ipcom_errno_set(vars->sadb->msg->sadb_msg_errno);
|
|
|
|
if (length != 0)
|
|
keyadm_printf(vars, "keyadm: trailing SADB bytes (%d)"IP_LF, length);
|
|
return 0;
|
|
|
|
leave:
|
|
return retval;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_print_command
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_print_command(Vars *vars)
|
|
{
|
|
union Ip_sockaddr_union *sockaddr;
|
|
union Ip_sockaddr_union *sockaddr_max;
|
|
char str[128];
|
|
int addr_offset;
|
|
Ip_time_t addtime, usetime;
|
|
Ip_u32 bytes;
|
|
Ip_u16 min_port;
|
|
Ip_u16 max_port;
|
|
|
|
ip_assert(vars->sadb);
|
|
ip_assert(vars->sadb->msg);
|
|
|
|
keyadm_printf(vars, "SADB_MSG: msgtype=%s err=%d satype=%s len=%d seq=%d pid=0x%x"IP_LF,
|
|
MSG_TYPE(vars->sadb->msg->sadb_msg_type),
|
|
vars->sadb->msg->sadb_msg_errno,
|
|
MSG_SATYPE(vars->sadb->msg->sadb_msg_satype),
|
|
vars->sadb->msg->sadb_msg_len * sizeof(Ip_u64),
|
|
vars->sadb->msg->sadb_msg_seq,
|
|
vars->sadb->msg->sadb_msg_pid);
|
|
if (vars->sadb->msg->sadb_msg_errno)
|
|
{
|
|
keyadm_printf(vars, " ERRNO: %s (%d)"IP_LF,
|
|
ipcom_strerror(vars->sadb->msg->sadb_msg_errno),
|
|
vars->sadb->msg->sadb_msg_errno);
|
|
}
|
|
|
|
/* SADB_EXT_SA */
|
|
if (vars->sadb->sa)
|
|
{
|
|
char authbuf[32];
|
|
char encryptbuf[32];
|
|
|
|
keyadm_printf(vars, " SA: spi=%x sta=%s auth=%s enc=%s replay=%d %s"IP_LF,
|
|
ip_ntohl(vars->sadb->sa->sadb_sa_spi),
|
|
SA_STATE(vars->sadb->sa->sadb_sa_state),
|
|
ipcom_cmd_key_to_str(sa_auth_id_map, vars->sadb->sa->sadb_sa_auth,
|
|
authbuf, sizeof(authbuf)),
|
|
ipcom_cmd_key_to_str(sa_encrypt_id_map, vars->sadb->sa->sadb_sa_encrypt,
|
|
encryptbuf, sizeof(encryptbuf)),
|
|
(int)vars->sadb->sa->sadb_sa_replay,
|
|
keyadm_cmd_bits_to_str((char **)keyadm_sa_flags_bitmap,
|
|
vars->sadb->sa->sadb_sa_flags,
|
|
str, sizeof(str)));
|
|
}
|
|
|
|
/* SADB_EXT_ADDRESS_SRC */
|
|
if (vars->sadb->address_src)
|
|
{
|
|
sockaddr = (union Ip_sockaddr_union *)((Ip_u8 *)vars->sadb->address_src + sizeof(struct sadb_address));
|
|
addr_offset = (sockaddr->sa.sa_family == IP_AF_INET) ? 2 : 6;
|
|
|
|
keyadm_printf(vars, " SRC: addr=%s",
|
|
ipcom_inet_ntop(sockaddr->sa.sa_family,
|
|
&sockaddr->sa.sa_data[addr_offset],
|
|
str, sizeof(str)));
|
|
if (vars->sadb->address_src->sadb_address_proto != 0)
|
|
keyadm_printf(vars, " proto=%s",
|
|
ipcom_ipproto_name(vars->sadb->address_src->sadb_address_proto));
|
|
if (sockaddr->sa.sa_family == IP_AF_INET)
|
|
{
|
|
if (sockaddr->sin.sin_port)
|
|
keyadm_printf(vars, " port=%d",
|
|
ip_ntohs(sockaddr->sin.sin_port));
|
|
}
|
|
#ifdef IPCOM_USE_INET6
|
|
if (sockaddr->sa.sa_family == IP_AF_INET6)
|
|
{
|
|
if (sockaddr->sin6.sin6_port)
|
|
keyadm_printf(vars, " port=%d",
|
|
ip_ntohs(sockaddr->sin6.sin6_port));
|
|
}
|
|
#endif
|
|
keyadm_printf(vars, IP_LF);
|
|
}
|
|
|
|
/* SADB_EXT_ADDRESS_DST */
|
|
if (vars->sadb->address_dst)
|
|
{
|
|
sockaddr = (union Ip_sockaddr_union *)((Ip_u8 *)vars->sadb->address_dst + sizeof(struct sadb_address));
|
|
addr_offset = (sockaddr->sa.sa_family == IP_AF_INET) ? 2 : 6;
|
|
if (sockaddr->sa.sa_family)
|
|
keyadm_printf(vars, " DST: addr=%s",
|
|
ipcom_inet_ntop(sockaddr->sa.sa_family, &sockaddr->sa.sa_data[addr_offset],
|
|
str, sizeof(str)));
|
|
if (vars->sadb->address_dst->sadb_address_proto != 0)
|
|
keyadm_printf(vars, " proto=%s",
|
|
ipcom_ipproto_name(vars->sadb->address_dst->sadb_address_proto));
|
|
if (sockaddr->sa.sa_family == IP_AF_INET)
|
|
{
|
|
if (sockaddr->sin.sin_port)
|
|
keyadm_printf(vars, " port=%d",
|
|
ip_ntohs(sockaddr->sin.sin_port));
|
|
|
|
}
|
|
#ifdef IPCOM_USE_INET6
|
|
if (sockaddr->sa.sa_family == IP_AF_INET6)
|
|
{
|
|
if (sockaddr->sin6.sin6_port)
|
|
keyadm_printf(vars, " port=%d",
|
|
ip_ntohs(sockaddr->sin6.sin6_port));
|
|
}
|
|
#endif
|
|
|
|
keyadm_printf(vars, IP_LF);
|
|
}
|
|
|
|
/* SADB_EXT_ADDRESS_PROXY */
|
|
if (vars->sadb->address_proxy)
|
|
{
|
|
sockaddr = (union Ip_sockaddr_union *)((Ip_u8 *)vars->sadb->address_proxy + sizeof(struct sadb_address));
|
|
addr_offset = (sockaddr->sa.sa_family == IP_AF_INET) ? 2 : 6;
|
|
keyadm_printf(vars, " PROXY: addr=%s"IP_LF,
|
|
ipcom_inet_ntop(sockaddr->sa.sa_family,
|
|
&sockaddr->sa.sa_data[addr_offset],
|
|
str, sizeof(str)));
|
|
}
|
|
|
|
/* SADB_EXT_KEY_AUTH */
|
|
if (vars->sadb->key_auth)
|
|
{
|
|
keyadm_printf(vars, " AUTHKEY: bits=%d"IP_LF,
|
|
(int)vars->sadb->key_auth->sadb_key_bits);
|
|
}
|
|
|
|
/* SADB_EXT_KEY_ENCRYPT */
|
|
if (vars->sadb->key_encrypt)
|
|
{
|
|
keyadm_printf(vars, " ENCKEY: bits=%d"IP_LF,
|
|
(int)vars->sadb->key_encrypt->sadb_key_bits);
|
|
}
|
|
|
|
/* SADB_X_EXT_PROTOCOL */
|
|
if (vars->sadb->protocol)
|
|
{
|
|
char port0[16], port1[16];
|
|
|
|
keyadm_printf(vars, "PROTOCOL: proto=%s",
|
|
ipcom_ipproto_name(vars->sadb->protocol->sadb_protocol_proto));
|
|
|
|
if (vars->sadb->protocol->sadb_protocol_ports0)
|
|
ipcom_sprintf(port0, "%d", vars->sadb->protocol->sadb_protocol_ports0);
|
|
else
|
|
ipcom_strcpy(port0, "any");
|
|
if (vars->sadb->protocol->sadb_protocol_ports1)
|
|
ipcom_sprintf(port1, "%d", vars->sadb->protocol->sadb_protocol_ports1);
|
|
else
|
|
ipcom_strcpy(port1, "any");
|
|
switch (vars->sadb->protocol->sadb_protocol_proto)
|
|
{
|
|
case IP_IPPROTO_ICMP:
|
|
case IP_IPPROTO_ICMPV6:
|
|
keyadm_printf(vars, " type=%s code=%s", port0, port1);
|
|
break;
|
|
case IP_IPPROTO_MH:
|
|
keyadm_printf(vars, " type=%s", port0);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
keyadm_printf(vars, IP_LF);
|
|
}
|
|
|
|
/* SADB_X_EXT_SRC_FLOW */
|
|
if (vars->sadb->src_flow)
|
|
{
|
|
sockaddr = (union Ip_sockaddr_union *)((Ip_u8 *)vars->sadb->src_flow + sizeof(struct sadb_address));
|
|
addr_offset = (sockaddr->sa.sa_family == IP_AF_INET) ? 2 : 6;
|
|
min_port = ip_ntohs(sockaddr->sin.sin_port);
|
|
|
|
if (sockaddr->sa.sa_family)
|
|
keyadm_printf(vars, " SRCFLOW: addr=%s",
|
|
ipcom_inet_ntop(sockaddr->sa.sa_family, &sockaddr->sa.sa_data[addr_offset],
|
|
str, sizeof(str)));
|
|
if (vars->sadb->srcmax_flow)
|
|
{
|
|
sockaddr_max = (union Ip_sockaddr_union *)((Ip_u8 *)vars->sadb->srcmax_flow + sizeof(struct sadb_address));
|
|
if (sockaddr_max->sa.sa_family
|
|
&& ipcom_memcmp(&sockaddr->sa.sa_data[addr_offset], &sockaddr_max->sa.sa_data[addr_offset],
|
|
sockaddr_max->sa.sa_family == IP_AF_INET ? 4 : 16))
|
|
keyadm_printf(vars, "-%s",
|
|
ipcom_inet_ntop(sockaddr_max->sa.sa_family, &sockaddr_max->sa.sa_data[addr_offset],
|
|
str, sizeof(str)));
|
|
}
|
|
if (vars->sadb->src_mask)
|
|
{
|
|
sockaddr = (union Ip_sockaddr_union *)((Ip_u8 *)vars->sadb->src_mask + sizeof(struct sadb_address));
|
|
addr_offset = (sockaddr->sa.sa_family == IP_AF_INET) ? 2 : 6;
|
|
if (sockaddr->sa.sa_family)
|
|
keyadm_printf(vars, "/%d",
|
|
ipipsec_addrmasklen(sockaddr->sa.sa_family, &sockaddr->sa.sa_data[addr_offset]));
|
|
}
|
|
if (vars->sadb->srcmax_flow)
|
|
{
|
|
sockaddr = (union Ip_sockaddr_union *)((Ip_u8 *)vars->sadb->srcmax_flow + sizeof(struct sadb_address));
|
|
max_port = ip_ntohs(sockaddr->sin.sin_port);
|
|
}
|
|
else
|
|
max_port = 0;
|
|
if (min_port)
|
|
{
|
|
if (max_port)
|
|
keyadm_printf(vars, " ports=%d-%d", min_port, max_port);
|
|
else
|
|
keyadm_printf(vars, " port=%d", min_port);
|
|
}
|
|
keyadm_printf(vars, IP_LF);
|
|
}
|
|
|
|
/* SADB_X_EXT_DST_FLOW */
|
|
if (vars->sadb->dst_flow)
|
|
{
|
|
sockaddr = (union Ip_sockaddr_union *)((Ip_u8 *)vars->sadb->dst_flow + sizeof(struct sadb_address));
|
|
addr_offset = (sockaddr->sa.sa_family == IP_AF_INET) ? 2 : 6;
|
|
min_port = ip_ntohs(sockaddr->sin.sin_port);
|
|
if (sockaddr->sa.sa_family)
|
|
keyadm_printf(vars, " DSTFLOW: addr=%s",
|
|
ipcom_inet_ntop(sockaddr->sa.sa_family, &sockaddr->sa.sa_data[addr_offset],
|
|
str, sizeof(str)));
|
|
if (vars->sadb->dstmax_flow)
|
|
{
|
|
sockaddr_max = (union Ip_sockaddr_union *)((Ip_u8 *)vars->sadb->dstmax_flow + sizeof(struct sadb_address));
|
|
if (sockaddr_max->sa.sa_family
|
|
&& ipcom_memcmp(&sockaddr->sa.sa_data[addr_offset], &sockaddr_max->sa.sa_data[addr_offset],
|
|
sockaddr_max->sa.sa_family == IP_AF_INET ? 4 : 16))
|
|
keyadm_printf(vars, "-%s",
|
|
ipcom_inet_ntop(sockaddr_max->sa.sa_family, &sockaddr_max->sa.sa_data[addr_offset],
|
|
str, sizeof(str)));
|
|
}
|
|
if (vars->sadb->dst_mask)
|
|
{
|
|
sockaddr = (union Ip_sockaddr_union *)((Ip_u8 *)vars->sadb->dst_mask + sizeof(struct sadb_address));
|
|
addr_offset = (sockaddr->sa.sa_family == IP_AF_INET) ? 2 : 6;
|
|
if (sockaddr->sa.sa_family)
|
|
keyadm_printf(vars, "/%d",
|
|
ipipsec_addrmasklen(sockaddr->sa.sa_family, &sockaddr->sa.sa_data[addr_offset]));
|
|
}
|
|
if (vars->sadb->dstmax_flow)
|
|
{
|
|
sockaddr = (union Ip_sockaddr_union *)((Ip_u8 *)vars->sadb->dstmax_flow + sizeof(struct sadb_address));
|
|
max_port = ip_ntohs(sockaddr->sin.sin_port);
|
|
}
|
|
else
|
|
max_port = 0;
|
|
if (min_port)
|
|
{
|
|
if (max_port)
|
|
keyadm_printf(vars, " ports=%d-%d", min_port, max_port);
|
|
else
|
|
keyadm_printf(vars, " port=%d", min_port);
|
|
}
|
|
keyadm_printf(vars, IP_LF);
|
|
}
|
|
|
|
/* SADB_X_EXT_FLOW_OPTIONS */
|
|
if (vars->sadb->flowopt)
|
|
{
|
|
keyadm_printf(vars, " FLOWOPT: type=%s prio=%d dscp=0x%x dir=%s id=%d"IP_LF,
|
|
FLOW_TYPE(vars->sadb->flowopt->sadb_flowopt_type),
|
|
(int)vars->sadb->flowopt->sadb_flowopt_priority,
|
|
vars->sadb->flowopt->sadb_flowopt_dscp,
|
|
vars->sadb->flowopt->sadb_flowopt_direction == 1 ? "in" :
|
|
vars->sadb->flowopt->sadb_flowopt_direction == 2 ? "out" : "?",
|
|
(int)vars->sadb->flowopt->sadb_flowopt_id);
|
|
}
|
|
|
|
/* SADB_X_EXT_SA_OPTIONS */
|
|
if (vars->sadb->saopt)
|
|
{
|
|
keyadm_printf(vars, " SAOPT: priority=%d"IP_LF,
|
|
vars->sadb->saopt->sadb_saopt_priority);
|
|
}
|
|
|
|
/* SADB_EXT_SPIRANGE */
|
|
if (vars->sadb->spirange)
|
|
{
|
|
keyadm_printf(vars, "SPIRANGE: min=0x%x max=0x%x"IP_LF,
|
|
vars->sadb->spirange->sadb_spirange_min,
|
|
vars->sadb->spirange->sadb_spirange_max);
|
|
}
|
|
|
|
/* SADB_EXT_LIFETIME_CURRENT */
|
|
if (vars->sadb->lifetime_current)
|
|
{
|
|
addtime = (Ip_time_t)IP_U64_GETLO(vars->sadb->lifetime_current->sadb_lifetime_addtime);
|
|
usetime = (Ip_time_t)IP_U64_GETLO(vars->sadb->lifetime_current->sadb_lifetime_usetime);
|
|
bytes = IP_U64_GETLO(vars->sadb->lifetime_current->sadb_lifetime_bytes);
|
|
#ifdef _WRS_CONFIG_TIME_T_LONG_LONG
|
|
keyadm_printf(vars, " CURRENT: addtime=%lld usetime=%lld bytes=%ld"IP_LF,
|
|
addtime, usetime, bytes);
|
|
#else
|
|
keyadm_printf(vars, " CURRENT: addtime=%ld usetime=%ld bytes=%ld"IP_LF,
|
|
addtime, usetime, bytes);
|
|
#endif
|
|
}
|
|
|
|
/* SADB_EXT_LIFETIME_SOFT */
|
|
if (vars->sadb->lifetime_soft)
|
|
{
|
|
addtime = (Ip_time_t)IP_U64_GETLO(vars->sadb->lifetime_soft->sadb_lifetime_addtime);
|
|
usetime = (Ip_time_t)IP_U64_GETLO(vars->sadb->lifetime_soft->sadb_lifetime_usetime);
|
|
bytes = IP_U64_GETLO(vars->sadb->lifetime_soft->sadb_lifetime_bytes);
|
|
#ifdef _WRS_CONFIG_TIME_T_LONG_LONG
|
|
keyadm_printf(vars, " SOFT: addtime=%lld usetime=%lld bytes=%ld"IP_LF,
|
|
addtime, usetime, bytes);
|
|
#else
|
|
keyadm_printf(vars, " SOFT: addtime=%ld usetime=%ld bytes=%ld"IP_LF,
|
|
addtime, usetime, bytes);
|
|
#endif
|
|
}
|
|
|
|
/* SADB_EXT_LIFETIME_HARD */
|
|
if (vars->sadb->lifetime_hard)
|
|
{
|
|
addtime = (Ip_time_t)IP_U64_GETLO(vars->sadb->lifetime_hard->sadb_lifetime_addtime);
|
|
usetime = (Ip_time_t)IP_U64_GETLO(vars->sadb->lifetime_hard->sadb_lifetime_usetime);
|
|
bytes = IP_U64_GETLO(vars->sadb->lifetime_hard->sadb_lifetime_bytes);
|
|
#ifdef _WRS_CONFIG_TIME_T_LONG_LONG
|
|
keyadm_printf(vars, " HARD: addtime=%lld usetime=%lld bytes=%ld"IP_LF,
|
|
addtime, usetime, bytes);
|
|
#else
|
|
keyadm_printf(vars, " HARD: addtime=%ld usetime=%ld bytes=%ld"IP_LF,
|
|
addtime, usetime, bytes);
|
|
#endif
|
|
}
|
|
|
|
/* SADB_X_SAFLAGS_UDPENCAP */
|
|
if (vars->sadb->udpencap)
|
|
keyadm_printf(vars, "UDPENCAP: port=%d"IP_LF, ip_ntohs(vars->sadb->udpencap->sadb_x_udpencap_src_port));
|
|
|
|
#ifdef IPIPSEC_USE_LINUX_PFKEYV2_API
|
|
if (vars->sadb->lx_policy)
|
|
{
|
|
keyadm_printf(vars, " POLICY: type=%s prio=%d dir=%s id=%d"IP_LF,
|
|
ipsec_policy_linux[vars->sadb->lx_policy->sadb_x_policy_type],
|
|
(int)vars->sadb->lx_policy->sadb_x_policy_priority,
|
|
ipsec_dir_linux[vars->sadb->lx_policy->sadb_x_policy_dir],
|
|
(int)vars->sadb->lx_policy->sadb_x_policy_id);
|
|
if (vars->sadb->lx_policy->sadb_x_policy_len * 8
|
|
>= (int)(sizeof(struct sadb_x_policy) + sizeof(struct sadb_x_ipsecrequest)))
|
|
{
|
|
struct sadb_x_ipsecrequest *xisr;
|
|
xisr = (struct sadb_x_ipsecrequest *)(vars->sadb->lx_policy + 1);
|
|
keyadm_printf(vars, " len=%d proto=%d mode=%d level=%d reqid=%d"IP_LF,
|
|
(int)xisr->sadb_x_ipsecrequest_len,
|
|
(int)xisr->sadb_x_ipsecrequest_proto,
|
|
(int)xisr->sadb_x_ipsecrequest_mode,
|
|
(int)xisr->sadb_x_ipsecrequest_level,
|
|
(int)xisr->sadb_x_ipsecrequest_reqid);
|
|
if (vars->sadb->lx_policy->sadb_x_policy_len * 8
|
|
>= (int)(sizeof(struct sadb_x_policy) + sizeof(struct sadb_x_ipsecrequest) + 2 * sizeof(struct Ip_sockaddr_in)))
|
|
{
|
|
/* Extract source/tunnel endpoints */
|
|
sockaddr = (union Ip_sockaddr_union *)((Ip_caddr_t)xisr + sizeof(*xisr));
|
|
#ifdef IPCOM_USE_INET
|
|
if (sockaddr->sa.sa_family == IP_AF_INET)
|
|
{
|
|
keyadm_printf(vars, " srctunnel=%s",
|
|
ipcom_inet_ntop(IP_AF_INET, &sockaddr->sin.sin_addr.s_addr,
|
|
str, sizeof(str)));
|
|
sockaddr = (union Ip_sockaddr_union *)((Ip_caddr_t)sockaddr
|
|
+ sizeof(struct Ip_sockaddr_in));
|
|
keyadm_printf(vars, " dsttunnel=%s"IP_LF,
|
|
ipcom_inet_ntop(IP_AF_INET, &sockaddr->sin.sin_addr.s_addr,
|
|
str, sizeof(str)));
|
|
}
|
|
#endif /* IPCOM_USE_INET */
|
|
|
|
#ifdef IPCOM_USE_INET6
|
|
if (sockaddr->sa.sa_family == IP_AF_INET6)
|
|
{
|
|
if (vars->sadb->lx_policy->sadb_x_policy_len * 8
|
|
>= (int)(sizeof(struct sadb_x_policy) + sizeof(struct sadb_x_ipsecrequest) + 2 * sizeof(struct Ip_sockaddr_in6)))
|
|
{
|
|
keyadm_printf(vars, " srctunnel=%s",
|
|
ipcom_inet_ntop(IP_AF_INET6, &sockaddr->sin6.sin6_addr, str, sizeof(str)));
|
|
sockaddr = (union Ip_sockaddr_union *)((Ip_caddr_t)sockaddr
|
|
+ sizeof(struct Ip_sockaddr_in6));
|
|
keyadm_printf(vars, " dsttunnel=%s"IP_LF,
|
|
ipcom_inet_ntop(IP_AF_INET6, &sockaddr->sin6.sin6_addr, str, sizeof(str)));
|
|
}
|
|
}
|
|
#endif /* IPCOM_USE_INET6 */
|
|
}
|
|
}
|
|
}
|
|
if (vars->sadb->lx_sa2)
|
|
{
|
|
keyadm_printf(vars, " SA2: mode=%s reqid=%d"IP_LF,
|
|
vars->sadb->lx_sa2->sadb_x_sa2_mode == IPSEC_MODE_ANY ? "any" :
|
|
vars->sadb->lx_sa2->sadb_x_sa2_mode == IPSEC_MODE_TRANSPORT ? "transport" :
|
|
vars->sadb->lx_sa2->sadb_x_sa2_mode == IPSEC_MODE_TUNNEL ? "tunnel" : "?",
|
|
vars->sadb->lx_sa2->sadb_x_sa2_reqid);
|
|
}
|
|
#endif /* #ifdef IPIPSEC_USE_LINUX_PFKEYV2_API */
|
|
|
|
keyadm_printf(vars, "------------------------------------------"IP_LF);
|
|
|
|
return vars->sadb->msg->sadb_msg_errno == 0 ? 0 : -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_get_usage
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static void
|
|
keyadm_get_usage(Vars *vars)
|
|
{
|
|
keyadm_printf(vars,
|
|
"Get (info about) a Security Association (SA)"IP_LF
|
|
" usage: keyadm get <selectors>"IP_LF);
|
|
keyadm_printf(vars,
|
|
" mandatory selectors: "IP_LF
|
|
" -spi <val> SPI (in hex without the 0x)"IP_LF
|
|
" -src <ip> source IP address"IP_LF
|
|
" -dst <ip> destination IP address"IP_LF
|
|
" -proto <name> security protocol <esp|ah|ipip>"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional selectors: "IP_LF
|
|
" -sapri <val> priority (-128=highest to 127=lowest)"IP_LF
|
|
" -egress output SA (default)"IP_LF
|
|
" -ingress input SA"IP_LF
|
|
);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_get
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_get(Vars *vars)
|
|
{
|
|
if (vars->have_satype == 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: missing modifier '-proto'"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
if (keyadm_send_command(vars, SADB_GET, vars->satype) == 0)
|
|
{
|
|
(void)keyadm_receive_command(vars, 0);
|
|
return keyadm_print_command(vars);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_dump
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_dump(Vars *vars)
|
|
{
|
|
if (keyadm_send_command(vars, SADB_DUMP, vars->satype) == 0)
|
|
{
|
|
struct Ip_timeval tv;
|
|
int count = 0;
|
|
|
|
tv.tv_sec = 3;
|
|
tv.tv_usec = 0;
|
|
|
|
if (ipcom_setsockopt(vars->fd, IP_SOL_SOCKET, IP_SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: setsockopt(IP_SO_RCVTIMEO,x) failed : %s ",
|
|
ipcom_strerror(ipcom_errno));
|
|
return 0;
|
|
}
|
|
|
|
do
|
|
{
|
|
if (keyadm_receive_command(vars, 0) != 0)
|
|
break;
|
|
if (keyadm_print_command(vars) == 0)
|
|
count++;
|
|
|
|
}
|
|
while (vars->sadb->msg->sadb_msg_errno == 0
|
|
&& vars->sadb->msg->sadb_msg_seq);
|
|
|
|
keyadm_printf(vars, "Total of %d security associations"IP_LF, count);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_flush
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_flush(Vars *vars)
|
|
{
|
|
if (keyadm_send_command(vars, SADB_FLUSH, vars->satype) == 0)
|
|
{
|
|
(void)keyadm_receive_command(vars, 0);
|
|
return keyadm_print_command(vars);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_getspi_usage
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static void
|
|
keyadm_getspi_usage(Vars *vars)
|
|
{
|
|
keyadm_printf(vars,
|
|
"Create a larval Security Association (SA) with a (random) SPI"IP_LF
|
|
" usage: keyadm getspi <selectors> <modifiers>"IP_LF);
|
|
keyadm_printf(vars,
|
|
" mandatory selectors: "IP_LF
|
|
" -src <ip> source IP address"IP_LF
|
|
" -dst <ip> destination IP address"IP_LF
|
|
" -proto <name> security protocol <esp|ah|ipip>"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional selectors: "IP_LF
|
|
" -sapri <val> priority (-128=highest to 127=lowest)"IP_LF
|
|
" -egress output SA (default)"IP_LF
|
|
" -ingress input SA"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" mandatory modifiers:"IP_LF
|
|
" -minspi <val> min SPI value (in hex)"IP_LF
|
|
" -maxspi <val> max SPI value (in hex)"IP_LF
|
|
);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_getspi
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_getspi(Vars *vars)
|
|
{
|
|
if (vars->have_satype == 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: missing modifier '-proto'"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
if (keyadm_send_command(vars, SADB_GETSPI, vars->satype) == 0)
|
|
{
|
|
(void)keyadm_receive_command(vars, 0);
|
|
return keyadm_print_command(vars);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_sacheck
|
|
*===========================================================================
|
|
*/
|
|
static int
|
|
keyadm_sacheck(Vars *vars, Ip_bool update)
|
|
{
|
|
if (vars->test)
|
|
return 0;
|
|
|
|
if (vars->have_satype == 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: missing modifier '-proto'"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
if (update == IP_FALSE)
|
|
{
|
|
if (vars->satype == SADB_SATYPE_ESP)
|
|
{
|
|
if (vars->encrypt_type == SADB_EALG_UNSET)
|
|
{
|
|
keyadm_printf(vars, "keyadm: missing modifier '-enc'"IP_LF);
|
|
return -1;
|
|
}
|
|
if (vars->encrypt_type > SADB_EALG_NONE
|
|
&& vars->encrypt_type <= SADB_EALG_MAX
|
|
&& vars->encrypt_bytes == 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: missing modifier '-ekey'"IP_LF);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (vars->satype == SADB_SATYPE_ESP || vars->satype == SADB_SATYPE_AH)
|
|
{
|
|
if (vars->auth_type == SADB_AALG_UNSET)
|
|
{
|
|
keyadm_printf(vars, "keyadm: missing modifier '-auth'"IP_LF);
|
|
return -1;
|
|
}
|
|
if (vars->auth_type > SADB_AALG_NONE
|
|
&& vars->auth_type <= SADB_AALG_MAX
|
|
&& vars->auth_bytes == 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: missing modifier '-akey'"IP_LF);
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_update_usage
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static void
|
|
keyadm_update_usage(Vars *vars)
|
|
{
|
|
keyadm_printf(vars,
|
|
"Update a Security Association (SA)"IP_LF
|
|
" usage: keyadm update <selectors> <modifiers>"IP_LF);
|
|
keyadm_printf(vars,
|
|
" mandatory selectors: "IP_LF
|
|
" -spi <val> SPI (in hex without the 0x)"IP_LF
|
|
" -src <ip> source IP address"IP_LF
|
|
" -dst <ip> destination IP address"IP_LF
|
|
" -proto <name> security protocol <esp|ah|ipip>"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional selectors: "IP_LF
|
|
" -sapri <val> priority (-128=highest to 127=lowest)"IP_LF
|
|
" -egress output SA (default)"IP_LF
|
|
" -ingress input SA"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" mandatory modifiers:"IP_LF
|
|
" -enc <alg> encryption algorithm <des|3des|blf|cast|aes|aesctr>"IP_LF
|
|
" -ekey <key> encryption key (in hex, each char is 4 bits)"IP_LF
|
|
" -auth <alg> authentication algorithm <md5|sha1|sha256|sha384|sha512|rmd160|aesmac>"IP_LF
|
|
" -akey <key> authentication key (in hex, each char is 4 bits)"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional modifiers:"IP_LF
|
|
" -proxy <ip> proxy IP address (for tunneling)"IP_LF
|
|
" -replay <val> replay counter (0-255, 0=disabled)"IP_LF
|
|
" -forcetunnel force tunneling mode"IP_LF
|
|
" -esn enable Extended Sequence Numbers (ESN)"IP_LF
|
|
" -srcreq source IP must match in SA lookup"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" -tfc enable TFC (ESP only)"IP_LF
|
|
" -udpencap <port> enable ESP UDP encap using <port> (ESP only)"IP_LF
|
|
" -clrdf clear DF-bit on outer IPv4 header"IP_LF
|
|
" -setdf set DF-bit on outer IPv4 header"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" -ls <sec> soft add-lifetime in seconds"IP_LF
|
|
" -lh <sec> hard add-lifetime in seconds"IP_LF
|
|
" -bs <bytes> soft lifetime in bytes"IP_LF
|
|
" -bh <bytes> hard lifetime in bytes"IP_LF
|
|
" -ecn enable ECN handling (ESP tunnel mode only)"IP_LF
|
|
);
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_update
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_update(Vars *vars)
|
|
{
|
|
if (keyadm_sacheck(vars, IP_TRUE) != 0)
|
|
return -1;
|
|
|
|
if (keyadm_send_command(vars, SADB_UPDATE, vars->satype) == 0)
|
|
{
|
|
(void)keyadm_receive_command(vars, 0);
|
|
return keyadm_print_command(vars);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_add_usage
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static void
|
|
keyadm_add_usage(Vars *vars)
|
|
{
|
|
keyadm_printf(vars,
|
|
"Add a Security Association (SA)"IP_LF
|
|
" usage: keyadm add <selectors> <modifiers>"IP_LF);
|
|
keyadm_printf(vars,
|
|
" mandatory selectors: "IP_LF
|
|
" -spi <val> SPI (in hex without the 0x)"IP_LF
|
|
" -src <ip> source IP address"IP_LF
|
|
" -dst <ip> destination IP address"IP_LF
|
|
" -proto <name> security protocol <esp|ah|ipip>"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional selectors: "IP_LF
|
|
" -sapri <val> priority (-128=highest to 127=lowest)"IP_LF
|
|
" -egress output SA (default)"IP_LF
|
|
" -ingress input SA"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" mandatory modifiers:"IP_LF
|
|
" -enc <alg> encryption algorithm <des|3des|blf|cast|aes|aesctr>"IP_LF
|
|
" -ekey <key> encryption key (in hex, each char is 4 bits)"IP_LF
|
|
" -auth <alg> authentication algorithm <md5|sha1|sha256|sha384|sha512|rmd160|aesmac>"IP_LF
|
|
" -akey <key> authentication key (in hex, each char is 4 bits)"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional modifiers:"IP_LF
|
|
" -proxy <ip> proxy IP address (for tunneling)"IP_LF
|
|
" -replay <val> replay counter (0-255, 0=disabled)"IP_LF
|
|
" -forcetunnel force tunneling mode"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" -ls <sec> soft add-lifetime in seconds"IP_LF
|
|
" -lh <sec> hard add-lifetime in seconds"IP_LF
|
|
" -bs <bytes> soft lifetime in bytes"IP_LF
|
|
" -bh <bytes> hard lifetime in bytes"IP_LF
|
|
" -ecn enable ECN handling (ESP tunnel mode only)"IP_LF
|
|
" -esn enable ESN (Extended Sequence Numbers)"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" -srcreq source IP must match in SA lookup"IP_LF
|
|
" -tfc enable TFC (ESP only)"IP_LF
|
|
" -udpencap <port> enable ESP UDP encap using <port> (ESP only)"IP_LF
|
|
" -clrdf clear DF-bit on outer IPv4 header"IP_LF
|
|
" -setdf set DF-bit on outer IPv4 header"IP_LF
|
|
" -linux enable Linux style SADB_ADD"IP_LF
|
|
" -u <id> Linux policy entry identifier"IP_LF
|
|
);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_add
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_add(Vars *vars)
|
|
{
|
|
if (keyadm_sacheck(vars, IP_FALSE) != 0)
|
|
return -1;
|
|
|
|
if (keyadm_send_command(vars, SADB_ADD, vars->satype) == 0)
|
|
{
|
|
(void)keyadm_receive_command(vars, 0);
|
|
return keyadm_print_command(vars);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_delete_usage
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static void
|
|
keyadm_delete_usage(Vars *vars)
|
|
{
|
|
keyadm_printf(vars,
|
|
"Delete a Security Association (SA)"IP_LF
|
|
" usage: keyadm delete <selectors | -id <id>> [-chain]"IP_LF);
|
|
keyadm_printf(vars,
|
|
" mandatory selectors: "IP_LF
|
|
" -spi <val> SPI (in hex without the 0x)"IP_LF
|
|
" -src <ip> source IP address"IP_LF
|
|
" -dst <ip> destination IP address"IP_LF
|
|
" -proto <name> security protocol <esp|ah|ipip>"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional selectors: "IP_LF
|
|
" -sapri <val> priority (-128=highest to 127=lowest)"IP_LF
|
|
" -egress output SA (default)"IP_LF
|
|
" -ingress input SA"IP_LF
|
|
);
|
|
|
|
keyadm_printf(vars,
|
|
" optional modifier:"IP_LF
|
|
" -chain used to remove the whole chain"IP_LF
|
|
);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_delete
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_delete(Vars *vars)
|
|
{
|
|
if (vars->test == 0 && vars->have_satype == 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: missing modifier '-proto'"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
if (keyadm_send_command(vars, SADB_DELETE, vars->satype) == 0)
|
|
{
|
|
(void)keyadm_receive_command(vars, 0);
|
|
return keyadm_print_command(vars);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_addflow_usage
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static void
|
|
keyadm_addflow_usage(Vars *vars)
|
|
{
|
|
keyadm_printf(vars,
|
|
"Add a Flow (Security Policy)"IP_LF
|
|
" usage: keyadm addflow <selectors> <type> [SA selectors] [-replace]"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" mandatory selectors:"IP_LF
|
|
" -srcflow <ip> source address"IP_LF
|
|
" -dstflow <ip> destination address"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional selectors:"IP_LF
|
|
" -srcmask <mask> source mask (default all 1's)"IP_LF
|
|
" -dstmask <mask> destination mask (default all 1's)"IP_LF
|
|
" -egress output flow (default)"IP_LF
|
|
" -ingress input flow"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" -srcmaxflow <ip> source max address (for linear range)"IP_LF
|
|
" -dstmaxflow <ip> destination max address (for linear range)"IP_LF
|
|
" -flowpri <prio> flow priority (-128 to +127, -128=highest)"IP_LF
|
|
" -dscp <val> DSCP value (in hex without the 0x)"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional IP protocol specific selectors:"IP_LF
|
|
" -transport <val> IP protocol (ANY=0, TCP=6, UDP=17 etc)"IP_LF
|
|
" -srcport <port> UDP/TCP source port"IP_LF
|
|
" -dstport <port> UDP/TCP destination port"IP_LF
|
|
" -srcmaxport <port> UDP/TCP source max port (for linear range)"IP_LF
|
|
" -dstmaxport <port> UDP/TCP destination port (for linear range)"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" -icmptype <val> ICMP type (specified as value)"IP_LF
|
|
" -icmpcode <val> ICMP code (specified as value)"IP_LF
|
|
" -mhtype <val> MH type (specified as value)"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional type:"IP_LF
|
|
" -use use flow (default)"IP_LF
|
|
" -bypass bypass flow"IP_LF
|
|
" -deny deny flow"IP_LF
|
|
" -acquire acquire flow"IP_LF
|
|
" -require require flow"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional SA selectors (for '-use' flows): "IP_LF
|
|
" -spi <val> SPI (in hex without the 0x)"IP_LF
|
|
" -src <ip> source IP address"IP_LF
|
|
" -dst <ip> destination IP address"IP_LF
|
|
" -proto <name> security protocol <esp|ah|ipip>"IP_LF
|
|
" -sapri <val> priority (-128=highest to 127=lowest)"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional modifier: "IP_LF
|
|
" -replace replace flow if duplicate"IP_LF
|
|
);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_addflow
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_addflow(Vars *vars)
|
|
{
|
|
if (keyadm_send_command(vars, SADB_X_ADDFLOW, vars->satype) == 0)
|
|
{
|
|
(void)keyadm_receive_command(vars, 0);
|
|
return keyadm_print_command(vars);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_delflow_usage
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static void
|
|
keyadm_delflow_usage(Vars *vars)
|
|
{
|
|
keyadm_printf(vars,
|
|
"Delete a Flow (Security Policy)"IP_LF
|
|
" usage: keyadm delflow <selectors>"IP_LF
|
|
" keyadm delflow -id <flowid>"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" mandatory selectors:"IP_LF
|
|
" -srcflow <ip> source flow address"IP_LF
|
|
" -srcmask <mask> source flow mask"IP_LF
|
|
" -dstflow <ip> destination flow address"IP_LF
|
|
" -dstmask <mask> destination flow mask"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional selectors:"IP_LF
|
|
" -egress output flow (default)"IP_LF
|
|
" -ingress input flow"IP_LF
|
|
" -srcmaxflow <ip> source flow max address (for linear range)"IP_LF
|
|
" -dstmaxflow <ip> destination flow max address (for linear range)"IP_LF
|
|
" -flowpri <prio> flow priority (-128 to +127, -128=highest)"IP_LF
|
|
" -dscp <val> DSCP value (in hex without the 0x)"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional IP protocol specific selectors:"IP_LF
|
|
" -transport <val> IP protocol (ANY=0, TCP=6, UDP=17 etc)"IP_LF
|
|
" -srcport <port> UDP/TCP source port"IP_LF
|
|
" -dstport <port> UDP/TCP destination port"IP_LF
|
|
" -srcmaxport <port> UDP/TCP source max port (for linear range)"IP_LF
|
|
" -dstmaxport <port> UDP/TCP destination port (for linear range)"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" -icmptype <val> ICMP type (specified as value)"IP_LF
|
|
" -icmpcode <val> ICMP code (specified as value)"IP_LF
|
|
" -mhtype <val> MH type (specified as value)"IP_LF
|
|
);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_delflow
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_delflow(Vars *vars)
|
|
{
|
|
if (!(vars->flow_id != 0
|
|
|| ((vars->extmap & SEBIT_X_FLOW) == SEBIT_X_FLOW)))
|
|
{
|
|
keyadm_printf(vars, "keyadm: missing modifier(s) '-id' or '-srcflow and -dstflow'"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
if (keyadm_send_command(vars, SADB_X_DELFLOW, vars->satype) == 0)
|
|
{
|
|
(void)keyadm_receive_command(vars, 0);
|
|
return keyadm_print_command(vars);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_findflow_usage
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static void
|
|
keyadm_findflow_usage(Vars *vars)
|
|
{
|
|
keyadm_printf(vars,
|
|
"Lookup a Flow (Security Policy)"IP_LF
|
|
" usage: keyadm findflow <selectors>"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" mandatory selectors:"IP_LF
|
|
" -srcflow <ip> source address"IP_LF
|
|
" -dstflow <ip> destination address"IP_LF
|
|
" -transport <val> IP protocol (ANY=0, TCP=6, UDP=17 etc)"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional selectors:"IP_LF
|
|
" -egress output packet (default)"IP_LF
|
|
" -ingress input packet "IP_LF
|
|
" -dscp <val> DSCP value (in hex without the 0x)"IP_LF
|
|
" -srcport <port> UDP/TCP source port"IP_LF
|
|
" -dstport <port> UDP/TCP destination port"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" -icmptype <val> ICMP type (specified as value)"IP_LF
|
|
" -icmpcode <val> ICMP code (specified as value)"IP_LF
|
|
" -mhtype <val> MH type (specified as value)"IP_LF
|
|
);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_findflow
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_findflow(Vars *vars)
|
|
{
|
|
if (vars->have_transport_proto == 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: missing modifier '-transport'"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
if (keyadm_send_command(vars, SADB_X_FINDFLOW, vars->satype) == 0)
|
|
{
|
|
(void)keyadm_receive_command(vars, 0);
|
|
return keyadm_print_command(vars);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_dumpflow
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_dumpflow(Vars *vars)
|
|
{
|
|
if (keyadm_send_command(vars, SADB_X_DUMPFLOW, vars->satype) == 0)
|
|
{
|
|
struct Ip_timeval tv;
|
|
int count = 0;
|
|
|
|
tv.tv_sec = 3;
|
|
tv.tv_usec = 0;
|
|
|
|
if (ipcom_setsockopt(vars->fd, IP_SOL_SOCKET, IP_SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: setsockopt(IP_SO_RCVTIMEO,x) failed : %s ",
|
|
ipcom_strerror(ipcom_errno));
|
|
return 0;
|
|
}
|
|
|
|
do
|
|
{
|
|
if (keyadm_receive_command(vars, 0) != 0)
|
|
break;
|
|
if (keyadm_print_command(vars) == 0)
|
|
count++;
|
|
}
|
|
while (vars->sadb->msg->sadb_msg_errno == 0
|
|
&& vars->sadb->msg->sadb_msg_seq);
|
|
|
|
keyadm_printf(vars, "Total of %d flows"IP_LF, count);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_grpspis_usage
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static void
|
|
keyadm_grpspis_usage(Vars *vars)
|
|
{
|
|
keyadm_printf(vars,
|
|
"Group two Security Associations (SAs)"IP_LF
|
|
" usage: keyadm group <SA1 selectors> <SA2 selectors>"IP_LF);
|
|
keyadm_printf(vars,
|
|
" 1st SA mandatory selectors: "IP_LF
|
|
" -spi <val> SPI (in hex without the 0x)"IP_LF
|
|
" -src <ip> source IP address"IP_LF
|
|
" -dst <ip> destination IP address"IP_LF
|
|
" -proto <name> security protocol <esp|ah|ipip>"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" 1st SA optional selectors: "IP_LF
|
|
" -sapri <val> priority (-128=highest to 127=lowest)"IP_LF
|
|
" -egress output SA (default)"IP_LF
|
|
" -ingress input SA"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" 2nd SA mandatory selectors: "IP_LF
|
|
" -spi2 <val> SPI (in hex without the 0x)"IP_LF
|
|
" -dst2 <ip> destination IP address"IP_LF
|
|
" -proto2 <name> security protocol <esp|ah|ipip>"IP_LF
|
|
" NOTE: SA2 is always outbound"IP_LF
|
|
);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_grpspis
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_grpspis(Vars *vars)
|
|
{
|
|
if (vars->test == 0)
|
|
{
|
|
if (vars->have_satype == 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: missing modifier '-proto'"IP_LF);
|
|
return -1;
|
|
}
|
|
if (IP_BIT_ISFALSE(vars->extmap, SEBIT_X_DST2))
|
|
{
|
|
keyadm_printf(vars, "keyadm: missing modifier '-dst2'"IP_LF);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (keyadm_send_command(vars, SADB_X_GRPSPIS, vars->satype) == 0)
|
|
{
|
|
(void)keyadm_receive_command(vars, 0);
|
|
return keyadm_print_command(vars);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_register
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_register(Vars *vars)
|
|
{
|
|
if (vars->have_satype == 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: missing modifier '-proto'"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
if (keyadm_send_command(vars, SADB_REGISTER, vars->satype) == 0)
|
|
{
|
|
(void)keyadm_receive_command(vars, 0);
|
|
return keyadm_print_command(vars);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_monitor
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_monitor(Vars *vars)
|
|
{
|
|
int i;
|
|
|
|
if (vars->count == 0)
|
|
{
|
|
keyadm_printf(vars,
|
|
"Monitor PFKey kernel messages"IP_LF
|
|
" usage: keyadm monitor [-c <count>] [-W <timeout>]"IP_LF
|
|
" options: "IP_LF
|
|
" -c <count> maximum number of packets received"IP_LF
|
|
" -W <timeout> maximum timeout (in seconds) per read"IP_LF
|
|
" -proto <name> security protocol <esp|ah|ipip>"IP_LF
|
|
);
|
|
return 0;
|
|
}
|
|
|
|
if (keyadm_send_command(vars, SADB_REGISTER, vars->satype) == 0)
|
|
{
|
|
if (keyadm_receive_command(vars, 0) != 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: failed to register"IP_LF);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
ipcom_printf(IP_LF"Starting MONITOR loop [satype=%s]"IP_LF,
|
|
MSG_SATYPE(vars->satype));
|
|
|
|
for (i = 0; i < vars->count; i++)
|
|
{
|
|
if (keyadm_receive_command(vars, vars->timeout_seconds) != 0)
|
|
break;
|
|
(void)keyadm_print_command(vars);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_run_command
|
|
*===========================================================================
|
|
*/
|
|
static int
|
|
keyadm_run_command(int argc, char *name, Vars *vars)
|
|
{
|
|
int i;
|
|
Ip_u64 ext;
|
|
|
|
for (i = 0; commands[i].name; i++)
|
|
if (ipcom_strcmp(name, commands[i].name) == 0)
|
|
{
|
|
if (argc == 2 && commands[i].usage != IP_NULL)
|
|
{
|
|
commands[i].usage(vars);
|
|
return 0;
|
|
}
|
|
if (vars->test == 0 && commands[i].type > 0)
|
|
{
|
|
for (ext = 1; ext < SADB_EXT_MAX; ext++)
|
|
if (IP_BIT_ISSET(extbits[commands[i].type].in_req, (1ULL << ext))
|
|
&& IP_BIT_ISFALSE(vars->extmap, (1ULL << ext)))
|
|
{
|
|
keyadm_printf(vars, "keyadm: missing modifier '%s'"IP_LF, EXT_TYPE(ext));
|
|
return -1;
|
|
}
|
|
if (commands[i].type == SADB_GETSPI && vars->maxspi == 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: missing modifier '-maxspi'"IP_LF);
|
|
return -1;
|
|
}
|
|
}
|
|
return commands[i].func(vars);
|
|
}
|
|
|
|
keyadm_printf(vars, "keyadm: unknown command"IP_LF);
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 9 LINUX FUNCTIONS.
|
|
****************************************************************************
|
|
*/
|
|
#ifdef IPIPSEC_USE_LINUX_PFKEYV2_API
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_spdadd_usage / keyadm_spdupdate_usage
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*
|
|
spdadd 10.1.2.90 10.1.2.100 any -P out ipsec esp/transport/10.1.2.90-10.1.2.100/use ah/transport/10.1.2.90-10.1.2.100/use;
|
|
|
|
spdadd 192.168.0.10/32[5066] 192.168.0.11/32[5064] udp -P in
|
|
|
|
spdadd ::/0 ::/0 icmp6 135,0 -P in none; "=bypass"
|
|
|
|
spdadd 10.0.11.0/24[any] 10.0.11.33/32[any] any -P out ipsec esp/tunnel/192.168.0.1[4500]-192.168.1.2[30000]/require ;
|
|
|
|
keyadm spdadd -srcmask 255.255.255.255 -dstmask 255.255.255.255 -srcflow 10.1.2.110 -dstflow 10.1.2.100 -ingress -use
|
|
|
|
POLICY: -dst 10.1.2.100 -spi 603 -proto esp
|
|
|
|
*/
|
|
static void
|
|
keyadm_spdadd_usage_internal(Vars *vars, int type)
|
|
{
|
|
if (type == SADB_X_SPDADD)
|
|
keyadm_printf(vars,
|
|
"Add a Flow (Security Policy) using linux API"IP_LF
|
|
" usage: keyadm spdadd <selectors> <type>"IP_LF
|
|
);
|
|
else
|
|
keyadm_printf(vars,
|
|
"Update a Flow (Security Policy) using linux API"IP_LF
|
|
" usage: keyadm spdupdate <selectors> <type> [SA selectors] [-replace]"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" mandatory selectors:"IP_LF
|
|
" -srcflow <ip> source address"IP_LF
|
|
" -dstflow <ip> destination address"IP_LF
|
|
" -egress | -ingress flow direction (default out)"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional selectors:"IP_LF
|
|
" -srcmask <mask> source mask (default all 1's)"IP_LF
|
|
" -dstmask <mask> destination mask (default all 1's)"IP_LF
|
|
" -srctunnel <ip> tunnel source address"IP_LF
|
|
" -dsttunnel <ip> tunnel destination address"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" -flowpri <prio> flow priority (-128 to +127, -128=highest)"IP_LF
|
|
" -u <id> policy entry identifier"IP_LF
|
|
" -proto <ah|esp> desired SA security protocol"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional IP protocol specific selectors:"IP_LF
|
|
" -transport <val> IP protocol (ANY=0, TCP=6, UDP=17 etc)"IP_LF
|
|
" -srcport <port> UDP/TCP source port"IP_LF
|
|
" -dstport <port> UDP/TCP destination port"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional type:"IP_LF
|
|
" -use use flow (default)"IP_LF
|
|
" -bypass bypass flow"IP_LF
|
|
" -deny deny flow"IP_LF
|
|
" -acquire acquire flow"IP_LF
|
|
" -require require flow"IP_LF
|
|
);
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
keyadm_spdadd_usage(Vars *vars)
|
|
{
|
|
keyadm_spdadd_usage_internal(vars, SADB_X_SPDADD);
|
|
}
|
|
|
|
static void
|
|
keyadm_spdupdate_usage(Vars *vars)
|
|
{
|
|
keyadm_spdadd_usage_internal(vars, SADB_X_SPDUPDATE);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_spdadd
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_spdadd(Vars *vars)
|
|
{
|
|
vars->is_linux = IP_TRUE;
|
|
|
|
if (keyadm_send_command_linux(vars, SADB_X_SPDADD, vars->satype) == 0)
|
|
{
|
|
(void)keyadm_receive_command(vars, 0);
|
|
return keyadm_print_command(vars);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_spdupdate
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_spdupdate(Vars *vars)
|
|
{
|
|
vars->is_linux = IP_TRUE;
|
|
|
|
if (keyadm_send_command_linux(vars, SADB_X_SPDUPDATE, vars->satype) == 0)
|
|
{
|
|
(void)keyadm_receive_command(vars, 0);
|
|
return keyadm_print_command(vars);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_spddelete_usage
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static void
|
|
keyadm_spddelete_usage(Vars *vars)
|
|
{
|
|
keyadm_printf(vars,
|
|
"Delete a Flow (Security Policy)"IP_LF
|
|
" usage: keyadm spddelete <selectors>"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" mandatory selectors:"IP_LF
|
|
" -srcflow <ip> source flow address"IP_LF
|
|
" -dstflow <ip> destination flow address"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional selectors:"IP_LF
|
|
" -srcmask <mask> source flow mask"IP_LF
|
|
" -dstmask <mask> destination flow mask"IP_LF
|
|
" -egress output flow (default)"IP_LF
|
|
" -ingress input flow"IP_LF
|
|
" -flowpri <prio> flow priority (-128 to +127, -128=highest)"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" optional IP protocol specific selectors:"IP_LF
|
|
" -transport <val> IP protocol (ANY=0, TCP=6, UDP=17 etc)"IP_LF
|
|
" -srcport <port> UDP/TCP source port"IP_LF
|
|
" -dstport <port> UDP/TCP destination port"IP_LF
|
|
);
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_spddelete
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_spddelete(Vars *vars)
|
|
{
|
|
if (keyadm_send_command_linux(vars, SADB_X_SPDDELETE, vars->satype) == 0)
|
|
{
|
|
(void)keyadm_receive_command(vars, 0);
|
|
return keyadm_print_command(vars);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
*===========================================================================
|
|
* keyadm_spdflush
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
static int
|
|
keyadm_spdflush(Vars *vars)
|
|
{
|
|
if (keyadm_send_command(vars, SADB_X_SPDFLUSH, 0) == 0)
|
|
{
|
|
(void)keyadm_receive_command(vars, 0);
|
|
return keyadm_print_command(vars);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
#endif /* #ifdef IPIPSEC_USE_LINUX_PFKEYV2_API */
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 10 PUBLIC FUNCTIONS.
|
|
****************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_cmd_keyadm_private
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_STATIC int
|
|
ipipsec_cmd_keyadm_private(Vars *vars, int argc, char **argv)
|
|
{
|
|
int i, c, id, doexit;
|
|
int ret = 1;
|
|
Ipcom_getopt opt;
|
|
|
|
static struct Ip_option long_options[] =
|
|
{
|
|
{"spi", 1, 0, 0},
|
|
{"src", 1, 0, 0},
|
|
{"dst", 1, 0, 0},
|
|
{"proto", 1, 0, 0},
|
|
{"minspi", 1, 0, 0},
|
|
{"maxspi", 1, 0, 0},
|
|
{"ekey", 1, 0, 0},
|
|
{"akey", 1, 0, 0},
|
|
{"enc", 1, 0, 0},
|
|
{"auth", 1, 0, 0},
|
|
{"xxxold", 0, 0, 0},
|
|
{"xxxhalfiv", 0, 0, 0},
|
|
{"forcetunnel", 0, 0, 0},
|
|
{"srcmask", 1, 0, 0},
|
|
{"dstmask", 1, 0, 0},
|
|
{"srcflow", 1, 0, 0},
|
|
{"dstflow", 1, 0, 0},
|
|
{"spi2", 1, 0, 0},
|
|
{"dst2", 1, 0, 0},
|
|
{"proto2", 1, 0, 0},
|
|
{"new", 0, 0, 0},
|
|
{"ingress", 0, 0, 0},
|
|
{"srcport", 1, 0, 0},
|
|
{"dstport", 1, 0, 0},
|
|
{"transport", 1, 0, 0},
|
|
{"replace", 0, 0, 0},
|
|
{"bypass", 0, 0, 0},
|
|
{"replay", 1, 0, 0},
|
|
{"chain", 0, 0, 0},
|
|
{"proxy", 1, 0, 0},
|
|
{"egress", 0, 0, 0},
|
|
{"silent", 0, 0, 0},
|
|
{"ls", 1, 0, 0},
|
|
{"lh", 1, 0, 0},
|
|
{"deny", 0, 0, 0},
|
|
{"acquire", 0, 0, 0},
|
|
{"require", 0, 0, 0},
|
|
{"b", 1, 0, 0},
|
|
{"srcmaxport", 1, 0, 0},
|
|
{"dstmaxport", 1, 0, 0},
|
|
{"tfc", 0, 0, 0},
|
|
{"esn", 0, 0, 0},
|
|
{"flowpri", 1, 0, 0},
|
|
{"c", 1, 0, 0},
|
|
{"id", 1, 0, 0},
|
|
{"srcreq", 0, 0, 0},
|
|
{"icmptype", 1, 0, 0},
|
|
{"icmpcode", 1, 0, 0},
|
|
{"sapri", 1, 0, 0},
|
|
{"use", 0, 0, 0},
|
|
{"W", 1, 0, 0},
|
|
{"mhtype", 1, 0, 0},
|
|
{"srcmaxflow", 1, 0, 0},
|
|
{"dstmaxflow", 1, 0, 0},
|
|
{"setdf", 0, 0, 0},
|
|
{"clrdf", 0, 0, 0},
|
|
{"dscp", 1, 0, 0},
|
|
{"udpencap", 1, 0, 0},
|
|
{"srctunnel", 1, 0, 0},
|
|
{"dsttunnel", 1, 0, 0},
|
|
{"syslog", 0, 0, 0},
|
|
{"linux", 0, 0, 0},
|
|
{"u", 1, 0, 0},
|
|
{"ecn", 0, 0, 0},
|
|
{"bs", 1, 0, 0},
|
|
{"bh", 1, 0, 0},
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
/* prepare data */
|
|
ipcom_memset(vars, 0, sizeof(Vars));
|
|
vars->sadb = (Ipipsec_pfkeyv2_sadb *)vars->exthdr;
|
|
vars->sadb->msg = &vars->sadbmsg;
|
|
vars->encrypt_type = SADB_EALG_UNSET;
|
|
vars->auth_type = SADB_AALG_UNSET;
|
|
vars->argc = argc;
|
|
vars->argv = argv;
|
|
vars->fd = -1;
|
|
|
|
ipcom_getopt_clear_r(&opt);
|
|
|
|
/* Check -silent flag first, to disable all prints */
|
|
for (i = 0; i < argc; i++)
|
|
if (ipcom_strstr(argv[i], "-silent"))
|
|
{
|
|
vars->silent = 1;
|
|
opt.opterr = 0;
|
|
break;
|
|
}
|
|
for (i = 0; i < argc; i++)
|
|
if (ipcom_strstr(argv[i], "-syslog"))
|
|
{
|
|
vars->syslog = 1;
|
|
opt.opterr = 0;
|
|
break;
|
|
}
|
|
if (vars->silent == 0)
|
|
{
|
|
vars->stdoutbuf = ipcom_malloc(512);
|
|
if (vars->stdoutbuf == IP_NULL)
|
|
return 1;
|
|
}
|
|
|
|
if (argc < 2)
|
|
goto usage;
|
|
|
|
if (vars->syslog)
|
|
{
|
|
c = ipcom_sprintf(vars->stdoutbuf, "> ");
|
|
for (c = 2, i = 0; i < argc; i++)
|
|
c += ipcom_sprintf(vars->stdoutbuf + c, "%s ", argv[i]);
|
|
IPCOM_LOG1(DEBUG, "%s", vars->stdoutbuf);
|
|
}
|
|
|
|
vars->fd = ipcom_socket(IP_PF_KEY, IP_SOCK_RAW, PF_KEY_V2);
|
|
if (vars->fd == IP_SOCKERR)
|
|
{
|
|
keyadm_printf(vars, "keyadm: ipcom_socket() failed (%s)"IP_LF, ipcom_strerror(ipcom_errno));
|
|
goto leave2;
|
|
}
|
|
|
|
opt.long_only = 1;
|
|
opt.long_options = long_options;
|
|
|
|
while ((c = ipcom_getopt_r(argc - 1, argv + 1, "t", &opt)) != -1)
|
|
{
|
|
switch (c)
|
|
{
|
|
case 0:
|
|
switch(opt.long_index)
|
|
{
|
|
case 0: /* -spi */
|
|
vars->spi_n = ipcom_strtoul(opt.optarg, IP_NULL, 16);
|
|
vars->spi_n = ip_htonl(vars->spi_n);
|
|
IP_BIT_SET(vars->extmap, SEBIT_SA);
|
|
break;
|
|
case 1: /* -src */
|
|
if (keyadm_read_addr(opt.optarg, &vars->srcaddr) != 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: bad '-src' address"IP_LF);
|
|
goto leave;
|
|
}
|
|
IP_BIT_SET(vars->extmap, SEBIT_ADDRESS_SRC);
|
|
break;
|
|
case 2: /* -dst */
|
|
if (keyadm_read_addr(opt.optarg, &vars->dstaddr) != 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: bad '-dst' address"IP_LF);
|
|
goto leave;
|
|
}
|
|
IP_BIT_SET(vars->extmap, SEBIT_ADDRESS_DST);
|
|
break;
|
|
case 3: /* -proto */
|
|
if ((vars->satype = (Ip_s8)keyadm_search_block(opt.optarg, msg_satypes)) == -1)
|
|
{
|
|
keyadm_printf(vars, "keyadm: unknown security protocol type '%s'"IP_LF, opt.optarg);
|
|
goto leave;
|
|
}
|
|
vars->have_satype = 1;
|
|
break;
|
|
case 4: /* -minspi */
|
|
vars->minspi = ipcom_strtoul(opt.optarg, IP_NULL, 16);
|
|
IP_BIT_SET(vars->extmap, SEBIT_SPIRANGE);
|
|
break;
|
|
case 5: /* -maxspi */
|
|
vars->maxspi = ipcom_strtoul(opt.optarg, IP_NULL, 16);
|
|
break;
|
|
case 6: /* -ekey */
|
|
if (ipcom_strlen(opt.optarg) > (sizeof(vars->encrypt_key) * 2))
|
|
{
|
|
keyadm_printf(vars, "keyadm: too long encryption key '%s'"IP_LF, opt.optarg);
|
|
goto leave;
|
|
}
|
|
vars->encrypt_bytes = (Ip_u8)(ipcom_strlen(opt.optarg) / 2);
|
|
for (i = 0; i < vars->encrypt_bytes; i++)
|
|
{
|
|
vars->encrypt_key[i] = (Ip_u8)keyadm_hex_to_long(vars, opt.optarg + 2 * i, &doexit);
|
|
if (doexit)
|
|
goto leave;
|
|
}
|
|
break;
|
|
case 7: /* -akey */
|
|
if (ipcom_strlen(opt.optarg) > (sizeof(vars->auth_key) * 2))
|
|
{
|
|
keyadm_printf(vars, "keyadm: too long authentication key '%s'"IP_LF, opt.optarg);
|
|
goto leave;
|
|
}
|
|
vars->auth_bytes = (Ip_u8)(ipcom_strlen(opt.optarg) / 2);
|
|
for (i = 0; i < vars->auth_bytes; i++)
|
|
{
|
|
vars->auth_key[i] = (Ip_u8)keyadm_hex_to_long(vars, opt.optarg + 2 * i, &doexit);
|
|
if (doexit)
|
|
goto leave;
|
|
}
|
|
break;
|
|
case 8: /* -enc */
|
|
id = ipcom_cmd_str_to_key(sa_encrypt_id_map, opt.optarg);
|
|
if (id == -1)
|
|
{
|
|
keyadm_printf(vars, "keyadm: unknown encryption algorithm '%s'"IP_LF, opt.optarg);
|
|
goto leave;
|
|
}
|
|
vars->encrypt_type = (Ip_u8)id;
|
|
vars->satype = SADB_SATYPE_ESP; /* auto pick ESP */
|
|
vars->have_satype = 1;
|
|
break;
|
|
case 9: /* -auth */
|
|
id = ipcom_cmd_str_to_key(sa_auth_id_map, opt.optarg);
|
|
if (id == -1)
|
|
{
|
|
keyadm_printf(vars, "keyadm: unknown authentication algorithm '%s'"IP_LF, opt.optarg);
|
|
goto leave;
|
|
}
|
|
vars->auth_type = (Ip_u8)id;
|
|
break;
|
|
case 12: /* -forcetunnel */
|
|
IP_BIT_SET(vars->sa_flags, SADB_X_SAFLAGS_TUNNEL);
|
|
break;
|
|
case 13: /* -srcmask */
|
|
if (keyadm_read_addr(opt.optarg, &vars->srcmask) != 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: bad '-srcmask' mask"IP_LF);
|
|
goto leave;
|
|
}
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_SRC_MASK);
|
|
break;
|
|
case 14: /* -dstmask */
|
|
if (keyadm_read_addr(opt.optarg, &vars->dstmask) != 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: bad '-dstmask' mask"IP_LF);
|
|
goto leave;
|
|
}
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_DST_MASK);
|
|
break;
|
|
case 15: /* -srcflow */
|
|
if (keyadm_read_addr(opt.optarg, &vars->srcflow) != 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: bad '-srcflow' flow"IP_LF);
|
|
goto leave;
|
|
}
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_SRC_FLOW);
|
|
break;
|
|
case 16: /* -dstflow */
|
|
if (keyadm_read_addr(opt.optarg, &vars->dstflow) != 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: bad '-dstflow' flow"IP_LF);
|
|
goto leave;
|
|
}
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_DST_FLOW);
|
|
break;
|
|
case 17: /* -spi2 */
|
|
vars->spi2_n = ipcom_strtoul(opt.optarg, IP_NULL, 16);
|
|
vars->spi2_n = ip_htonl(vars->spi2_n);
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_SA2);
|
|
break;
|
|
case 18: /* -dst2 */
|
|
if (keyadm_read_addr(opt.optarg, &vars->dstaddr2) != 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: bad '-dst2' address"IP_LF);
|
|
goto leave;
|
|
}
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_DST2);
|
|
break;
|
|
case 19: /* -proto2 */
|
|
if ((vars->satype2 = (Ip_s8)keyadm_search_block(opt.optarg, msg_satypes)) == -1)
|
|
{
|
|
keyadm_printf(vars, "keyadm: unknown security protocol type '%s'"IP_LF, opt.optarg);
|
|
goto leave;
|
|
}
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_PROTOCOL);
|
|
break;
|
|
case 20: /* new (redundant, included only to simplify scripts) */
|
|
break;
|
|
case 21: /* -ingress flow/sa */
|
|
IP_BIT_SET(vars->sa_flags, SADB_X_SAFLAGS_INGRESS_SA);
|
|
IP_BIT_SET(vars->extmap, SEBIT_SA);
|
|
break;
|
|
case 22: /* -srcport */
|
|
if (*opt.optarg < '0' || *opt.optarg > '9')
|
|
{
|
|
keyadm_printf(vars, "keyadm: flow srcport must be specified by number"IP_LF);
|
|
goto leave;
|
|
}
|
|
vars->srcport_n = (Ip_u16)ipcom_atoi(opt.optarg);
|
|
vars->srcport_n = ip_htons(vars->srcport_n);
|
|
break;
|
|
case 23: /* -dstport */
|
|
if (*opt.optarg < '0' || *opt.optarg > '9')
|
|
{
|
|
keyadm_printf(vars, "keyadm: flow dstport must be specified by number"IP_LF);
|
|
goto leave;
|
|
}
|
|
vars->dstport_n = (Ip_u16)ipcom_atoi(opt.optarg);
|
|
vars->dstport_n = ip_htons(vars->dstport_n);
|
|
break;
|
|
case 24: /* -transport (flow protocol) */
|
|
if (*opt.optarg < '0' || *opt.optarg > '9')
|
|
{
|
|
keyadm_printf(vars, "keyadm: transport protocol must be specified by its protocol number"IP_LF);
|
|
goto leave;
|
|
}
|
|
vars->transport_proto = (Ip_u8)ipcom_atoi(opt.optarg);
|
|
vars->have_transport_proto = 1;
|
|
break;
|
|
case 25: /* -replace flow */
|
|
IP_BIT_SET(vars->sa_flags, SADB_X_SAFLAGS_REPLACEFLOW);
|
|
break;
|
|
case 26: /* -bypass flow */
|
|
vars->spi_n = 0;
|
|
IP_BIT_SET(vars->extmap, SEBIT_SA); /* spi = 0 */
|
|
IP_BIT_SET(vars->extmap, SEBIT_ADDRESS_DST); /* dst = 0.0.0.0 */
|
|
vars->satype = SADB_X_SATYPE_BYPASS;
|
|
vars->have_satype = 1;
|
|
vars->flow_type = SADB_X_FLOW_TYPE_BYPASS;
|
|
break;
|
|
case 27: /* -replay */
|
|
if (*opt.optarg < '0' || *opt.optarg > '9')
|
|
{
|
|
keyadm_printf(vars, "keyadm: replay counter must be a number"IP_LF);
|
|
goto leave;
|
|
}
|
|
vars->replay = ipcom_atoi(opt.optarg);
|
|
vars->replay = IP_ROUNDUP(vars->replay, 8);
|
|
if (vars->replay < 0 || vars->replay > 255)
|
|
{
|
|
keyadm_printf(vars, "keyadm: replay counter must be between 0 and 248"IP_LF);
|
|
goto leave;
|
|
}
|
|
break;
|
|
case 28: /* -chain */
|
|
IP_BIT_SET(vars->sa_flags, SADB_X_SAFLAGS_CHAINDEL);
|
|
break;
|
|
case 29: /* -proxy */
|
|
if (keyadm_read_addr(opt.optarg, &vars->proxyaddr) != 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: bad '-proxy' address"IP_LF);
|
|
goto leave;
|
|
}
|
|
IP_BIT_SET(vars->extmap, SEBIT_ADDRESS_PROXY);
|
|
break;
|
|
case 30: /* -egress sa */
|
|
IP_BIT_SET(vars->sa_flags, SADB_X_SAFLAGS_EGRESS_SA);
|
|
IP_BIT_SET(vars->extmap, SEBIT_SA);
|
|
break;
|
|
case 31: /* -silent mode, no printfs */
|
|
break;
|
|
case 32: /* -ls = lifetime soft (in time) */
|
|
vars->ls_sec = (Ip_u32)ipcom_atoi(opt.optarg);
|
|
IP_BIT_SET(vars->extmap, SEBIT_LIFETIME_SOFT);
|
|
break;
|
|
case 33: /* -lh = lifetime hard (in time) */
|
|
vars->lh_sec = (Ip_u32)ipcom_atoi(opt.optarg);
|
|
IP_BIT_SET(vars->extmap, SEBIT_LIFETIME_HARD);
|
|
break;
|
|
case 34: /* -deny flow */
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_FLOW_OPTIONS);
|
|
vars->flow_type = SADB_X_FLOW_TYPE_DENY;
|
|
break;
|
|
case 35: /* -acquire flow */
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_FLOW_OPTIONS);
|
|
vars->flow_type = SADB_X_FLOW_TYPE_ACQUIRE;
|
|
break;
|
|
case 36: /* -require flow */
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_FLOW_OPTIONS);
|
|
vars->flow_type = SADB_X_FLOW_TYPE_REQUIRE;
|
|
break;
|
|
case 37: /* -b = socker buffer size */
|
|
{
|
|
int sockbufsize = ipcom_atoi(opt.optarg);
|
|
if (sockbufsize > 0)
|
|
{
|
|
if (ipcom_setsockopt(vars->fd, IP_SOL_SOCKET, IP_SO_RCVBUF, (char *)&sockbufsize, sizeof(sockbufsize)) < 0)
|
|
keyadm_printf(vars, "keyadm: ipcom_setsockopt(RCVBUF) failed : %s"IP_LF, ipcom_strerror(ipcom_errno));
|
|
}
|
|
}
|
|
break;
|
|
case 38: /* -srcmaxport */
|
|
if (*opt.optarg < '0' || *opt.optarg > '9')
|
|
{
|
|
keyadm_printf(vars, "keyadm: flow srcmaxport must be specified by number"IP_LF);
|
|
goto leave;
|
|
}
|
|
vars->srcmaxport_n = (Ip_u16)ipcom_atoi(opt.optarg);
|
|
vars->srcmaxport_n = ip_htons(vars->srcmaxport_n);
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_SRCMAX_FLOW);
|
|
break;
|
|
case 39: /* -dstmaxport */
|
|
if (*opt.optarg < '0' || *opt.optarg > '9')
|
|
{
|
|
keyadm_printf(vars, "keyadm: flow dstmaxport must be specified by number"IP_LF);
|
|
goto leave;
|
|
}
|
|
vars->dstmaxport_n = (Ip_u16)ipcom_atoi(opt.optarg);
|
|
vars->dstmaxport_n = ip_htons(vars->dstmaxport_n);
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_DSTMAX_FLOW);
|
|
break;
|
|
case 40: /* -tfc */
|
|
IP_BIT_SET(vars->sa_flags, SADB_X_SAFLAGS_TFC);
|
|
break;
|
|
case 41: /* -esn */
|
|
IP_BIT_SET(vars->sa_flags, SADB_X_SAFLAGS_ESN);
|
|
break;
|
|
case 42: /* -flowpri */
|
|
vars->flow_priority = ipcom_atoi(opt.optarg);
|
|
if (vars->flow_priority < -128 || vars->flow_priority > 127)
|
|
{
|
|
keyadm_printf(vars, "keyadm: flow priority must be between -128 and 127"IP_LF);
|
|
goto leave;
|
|
}
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_FLOW_OPTIONS);
|
|
break;
|
|
case 43: /* -c */
|
|
vars->count = ipcom_atoi(opt.optarg);
|
|
if (vars->count < 1)
|
|
{
|
|
keyadm_printf(vars, "keyadm: count must be > 0"IP_LF);
|
|
goto leave;
|
|
}
|
|
break;
|
|
case 44: /* -id */
|
|
vars->flow_id = (Ip_u32)ipcom_atol(opt.optarg);
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_FLOW_OPTIONS);
|
|
break;
|
|
case 45: /* -srcreq */
|
|
IP_BIT_SET(vars->sa_flags, SADB_X_SAFLAGS_SRCREQ);
|
|
break;
|
|
case 46: /* -icmptype */
|
|
vars->ports0 = (Ip_u8)ipcom_atoi(opt.optarg);
|
|
break;
|
|
case 47: /* -icmpcode */
|
|
vars->ports1 = (Ip_u8)ipcom_atoi(opt.optarg);
|
|
break;
|
|
case 48: /* -sapri */
|
|
vars->sa_priority = ipcom_atoi(opt.optarg);
|
|
if (vars->sa_priority < -128 || vars->sa_priority > 127)
|
|
{
|
|
keyadm_printf(vars, "keyadm: SA priority must be between -128 and 127"IP_LF);
|
|
goto leave;
|
|
}
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_EXT_SA_OPTIONS);
|
|
break;
|
|
case 49: /* -use */
|
|
/* Use flow -> do not need to do anything */
|
|
break;
|
|
case 50: /* '-W' */
|
|
vars->timeout_seconds = ipcom_atoi(opt.optarg);
|
|
break;
|
|
case 51: /* -mhtype */
|
|
vars->ports0 = (Ip_u8)ipcom_atoi(opt.optarg);
|
|
break;
|
|
case 52: /* -srcmaxflow */
|
|
if (keyadm_read_addr(opt.optarg, &vars->srcmaxflow) != 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: bad '-srcmaxflow' flow"IP_LF);
|
|
goto leave;
|
|
}
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_SRCMAX_FLOW);
|
|
break;
|
|
case 53: /* -dstmaxflow */
|
|
if (keyadm_read_addr(opt.optarg, &vars->dstmaxflow) != 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: bad '-dstmaxflow' flow"IP_LF);
|
|
goto leave;
|
|
}
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_DSTMAX_FLOW);
|
|
break;
|
|
case 54: /* -setdf */
|
|
IP_BIT_SET(vars->sa_flags, SADB_X_SAFLAGS_SETDF);
|
|
break;
|
|
case 55: /* -clrdf */
|
|
IP_BIT_SET(vars->sa_flags, SADB_X_SAFLAGS_CLRDF);
|
|
break;
|
|
case 56: /* -dscp */
|
|
vars->dscp = (Ip_u8)ipcom_strtoul(opt.optarg, IP_NULL, 16);
|
|
IP_BIT_SET(vars->extmap, SEBIT_X_FLOW_OPTIONS);
|
|
break;
|
|
case 57: /* -udpencap */
|
|
if (*opt.optarg < '0' || *opt.optarg > '9')
|
|
{
|
|
keyadm_printf(vars, "keyadm: udpencap port must be specified by number"IP_LF);
|
|
goto leave;
|
|
}
|
|
vars->udpencap_port = (Ip_u16)ipcom_atoi(opt.optarg);
|
|
IP_BIT_SET(vars->sa_flags, SADB_X_SAFLAGS_UDPENCAP);
|
|
break;
|
|
case 58: /* -srctunnel */
|
|
if (keyadm_read_addr(opt.optarg, &vars->srctunnel) != 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: bad '-srctunnel' address"IP_LF);
|
|
goto leave;
|
|
}
|
|
IP_BIT_SET(vars->sa_flags, SADB_X_SAFLAGS_TUNNEL);
|
|
break;
|
|
case 59: /* -dsttunnel */
|
|
if (keyadm_read_addr(opt.optarg, &vars->dsttunnel) != 0)
|
|
{
|
|
keyadm_printf(vars, "keyadm: bad '-dsttunnel' address"IP_LF);
|
|
goto leave;
|
|
}
|
|
IP_BIT_SET(vars->sa_flags, SADB_X_SAFLAGS_TUNNEL);
|
|
break;
|
|
case 60: /* -syslog */
|
|
break;
|
|
#ifdef IPIPSEC_USE_LINUX_PFKEYV2_API
|
|
case 61: /* -linux */
|
|
vars->is_linux = IP_TRUE;
|
|
break;
|
|
case 62: /* -u */
|
|
vars->is_linux = IP_TRUE;
|
|
vars->reqid = ipcom_atol(opt.optarg);
|
|
break;
|
|
#endif
|
|
case 63: /* -ecn */
|
|
keyadm_printf(vars, "keyadm: Enabling ECN support\n");
|
|
IP_BIT_SET(vars->sa_flags, SADB_X_SAFLAGS_ECN);
|
|
break;
|
|
|
|
case 64: /* -bs = bytes soft */
|
|
vars->ls_bytes = (Ip_u64)ipcom_atol(opt.optarg);
|
|
IP_BIT_SET(vars->extmap, SEBIT_LIFETIME_SOFT);
|
|
break;
|
|
|
|
case 65: /* -bh = bytes hard */
|
|
vars->lh_bytes = (Ip_u64)ipcom_atol(opt.optarg);
|
|
IP_BIT_SET(vars->extmap, SEBIT_LIFETIME_HARD);
|
|
break;
|
|
|
|
default:
|
|
keyadm_printf(vars, "keyadm: unknown option %s", long_options[opt.long_index].name);
|
|
if (opt.optarg)
|
|
keyadm_printf(vars, " with arg %s", opt.optarg);
|
|
keyadm_printf(vars, IP_LF);
|
|
goto leave;
|
|
}
|
|
break;
|
|
case 't':
|
|
/* testmode */
|
|
vars->test = 1;
|
|
keyadm_printf(vars, "using testmode"IP_LF);
|
|
break;
|
|
default:
|
|
goto leave;
|
|
}
|
|
}
|
|
|
|
|
|
/****** Initial checks ******/
|
|
if (vars->test == 0)
|
|
{
|
|
if (IP_BIT_ISSET(vars->sa_flags, SADB_X_SAFLAGS_EGRESS_SA)
|
|
&& IP_BIT_ISSET(vars->sa_flags, SADB_X_SAFLAGS_INGRESS_SA))
|
|
{
|
|
keyadm_printf(vars, "keyadm: cannot specify \"-egress\" and \"-ingress\" simultaneously"IP_LF);
|
|
goto leave;
|
|
}
|
|
if (vars->satype != SADB_SATYPE_ESP && IP_BIT_ISSET(vars->sa_flags, SADB_X_SAFLAGS_TFC))
|
|
{
|
|
keyadm_printf(vars,
|
|
"keyadm: cannot specify \"-tfc\" for SAs using security protocols other than ESP"IP_LF);
|
|
goto leave;
|
|
}
|
|
}
|
|
|
|
|
|
/****** Run the command ******/
|
|
ret = keyadm_run_command(argc, argv[1], vars);
|
|
|
|
goto leave;
|
|
|
|
|
|
/* Generic usage */
|
|
usage:
|
|
keyadm_printf(vars,
|
|
"IPsec PFKey admin command, version 4.0"IP_LF
|
|
"Copyright (c) 2000-2010, Interpeak AB <www.interpeak.com>"IP_LF
|
|
" usage: keyadm <command> [modifier(s)...]"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" General commands: "IP_LF
|
|
" flush remove all SAs and flows"IP_LF
|
|
" monitor monitor PFKey kernel messages"IP_LF
|
|
#ifdef IP_DEBUG
|
|
" register send register PFkey message"IP_LF
|
|
#endif
|
|
);
|
|
keyadm_printf(vars,
|
|
" SA commands: "IP_LF
|
|
" add add a Security Association (SA)"IP_LF
|
|
" delete delete a Security Association (SA)"IP_LF
|
|
" get get (info about) a Security Association (SA)"IP_LF
|
|
" getspi create a larval SA with a (random) SPI"IP_LF
|
|
" update update a Security Association (SA)"IP_LF
|
|
" group group two Security Associations (SAs)"IP_LF
|
|
" dump list SA database"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" Flow commands: "IP_LF
|
|
" addflow add a Flow (Security Policy)"IP_LF
|
|
" delflow delete a Flow (Security Policy)"IP_LF
|
|
" findflow lookup a Flow (Security Policy)"IP_LF
|
|
" dumpflow list Flow (Security Policy) database"IP_LF
|
|
);
|
|
#ifdef IPIPSEC_USE_LINUX_PFKEYV2_API
|
|
keyadm_printf(vars,
|
|
" Linux PFKEY commands: "IP_LF
|
|
" spdadd add policy"IP_LF
|
|
" spdupdate update policy"IP_LF
|
|
" spddelete delete policy"IP_LF
|
|
" spdflush flush policies"IP_LF
|
|
);
|
|
#endif
|
|
keyadm_printf(vars,
|
|
" Generic command modifiers: "IP_LF
|
|
" -b <size> set pfkey socket receive buffer size"IP_LF
|
|
" -silent do not send any output to stdout/stderr"IP_LF
|
|
" -syslog send command output to syslog"IP_LF
|
|
);
|
|
keyadm_printf(vars,
|
|
" NOTE:"IP_LF
|
|
" Type 'keyadm <command>' for command help menu!"IP_LF
|
|
" (except for dump and flush which can be used without args)"IP_LF
|
|
);
|
|
|
|
leave:
|
|
if (vars->orgbuf)
|
|
ipcom_free(vars->orgbuf);
|
|
if (vars->fd != IP_INVALID_SOCKET)
|
|
ipcom_socketclose(vars->fd);
|
|
leave2:
|
|
if (vars->stdoutbuf)
|
|
ipcom_free(vars->stdoutbuf);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
*===========================================================================
|
|
* ipipsec_cmd_keyadm
|
|
*===========================================================================
|
|
* Description:
|
|
* Parameters:
|
|
* Returns:
|
|
*
|
|
*/
|
|
IP_PUBLIC int
|
|
ipipsec_cmd_keyadm(int argc, char **argv)
|
|
{
|
|
Vars *vars;
|
|
int ret;
|
|
|
|
/* Allocate the vars variable dynamically to reduce
|
|
* stack space allocated
|
|
*/
|
|
vars = ipcom_malloc(sizeof(*vars));
|
|
if (vars == IP_NULL)
|
|
return -1;
|
|
ret = ipipsec_cmd_keyadm_private(vars, argc, argv);
|
|
ipcom_free(vars);
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*
|
|
****************************************************************************
|
|
* END OF FILE
|
|
*===========================================================================
|
|
*/
|
|
|