summaryrefslogtreecommitdiff
path: root/sbin/ipsecadm/ipsecadm.c
diff options
context:
space:
mode:
authorAngelos D. Keromytis <angelos@cvs.openbsd.org>1999-02-24 22:53:48 +0000
committerAngelos D. Keromytis <angelos@cvs.openbsd.org>1999-02-24 22:53:48 +0000
commit89f13b6fea2755ea949385e3046726cb1a3a695e (patch)
treefbc98a9ee6ebd618bd94a66ce00952506500396e /sbin/ipsecadm/ipsecadm.c
parent7b06ca56d8a31a610cbe1bb13453fd8722b68bc4 (diff)
Almost rewritten ipsecadm to use pfkey. Error reporting is a bit lacking still.
Diffstat (limited to 'sbin/ipsecadm/ipsecadm.c')
-rw-r--r--sbin/ipsecadm/ipsecadm.c1370
1 files changed, 989 insertions, 381 deletions
diff --git a/sbin/ipsecadm/ipsecadm.c b/sbin/ipsecadm/ipsecadm.c
index 1930fdc1b3b..3d7c6c38cf7 100644
--- a/sbin/ipsecadm/ipsecadm.c
+++ b/sbin/ipsecadm/ipsecadm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipsecadm.c,v 1.3 1999/02/17 20:39:16 deraadt Exp $ */
+/* $OpenBSD: ipsecadm.c,v 1.4 1999/02/24 22:53:37 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
@@ -56,9 +56,9 @@
#include <stdlib.h>
#include <string.h>
#include <paths.h>
-#include "net/encap.h"
+#include <sys/uio.h>
+#include "net/pfkeyv2.h"
#include "netinet/ip_ipsp.h"
-#include "netinet/ip_esp.h"
#define ESP_OLD 0x01
#define ESP_NEW 0x02
@@ -78,423 +78,1031 @@
#define iscmd(x,y) (((x) & CMD_MASK) == (y))
typedef struct {
- char *name;
- int id, flags;
-} transform;
-
-int xf_esp_new __P((struct in_addr, struct in_addr, u_int32_t, int, int,
- u_char *, u_char *, u_char *, struct in_addr, struct in_addr, int));
-int xf_esp_old __P((struct in_addr, struct in_addr, u_int32_t, int, u_char *,
- u_char *, struct in_addr, struct in_addr));
-int xf_ah_new __P((struct in_addr, struct in_addr, u_int32_t, int, u_char *,
- struct in_addr, struct in_addr));
-int xf_ah_old __P((struct in_addr, struct in_addr, u_int32_t, int, u_char *,
- struct in_addr, struct in_addr));
-
-int xf_delspi __P((struct in_addr, u_int32_t, int, int));
-int xf_grp __P((struct in_addr, u_int32_t, int, struct in_addr, u_int32_t, int));
-int xf_flow __P((struct in_addr, u_int32_t, int, struct in_addr,
- struct in_addr, struct in_addr, struct in_addr, int, int, int, int, int));
-int xf_ip4 __P((struct in_addr, struct in_addr, u_int32_t,
- struct in_addr, struct in_addr));
+ char *name;
+ int id, flags;
+} transform;
transform xf[] = {
- {"des", ALG_ENC_DES, XF_ENC |ESP_OLD|ESP_NEW},
- {"3des", ALG_ENC_3DES, XF_ENC |ESP_OLD|ESP_NEW},
- {"blf", ALG_ENC_BLF, XF_ENC | ESP_NEW},
- {"cast", ALG_ENC_CAST, XF_ENC | ESP_NEW},
- {"skipjack", ALG_ENC_SKIPJACK, XF_ENC | ESP_NEW},
- {"md5", ALG_AUTH_MD5, XF_AUTH|AH_OLD|AH_NEW|ESP_NEW},
- {"sha1", ALG_AUTH_SHA1,XF_AUTH|AH_OLD|AH_NEW|ESP_NEW},
- {"rmd160", ALG_AUTH_RMD160, XF_AUTH|AH_NEW|ESP_NEW},
+ {"des", SADB_EALG_DESCBC, XF_ENC |ESP_OLD|ESP_NEW},
+ {"3des", SADB_EALG_3DESCBC, XF_ENC |ESP_OLD|ESP_NEW},
+ {"blf", SADB_EALG_X_BLF, XF_ENC | ESP_NEW},
+ {"cast", SADB_EALG_X_CAST, XF_ENC | ESP_NEW},
+ {"skipjack", SADB_EALG_X_SKIPJACK, XF_ENC | ESP_NEW},
+ {"md5", SADB_AALG_MD5HMAC96, XF_AUTH|AH_NEW|ESP_NEW},
+ {"sha1", SADB_AALG_SHA1HMAC96,XF_AUTH|AH_NEW|ESP_NEW},
+ {"md5", SADB_AALG_X_MD5, XF_AUTH|AH_OLD},
+ {"sha1", SADB_AALG_X_SHA1,XF_AUTH|AH_OLD},
+ {"rmd160", SADB_AALG_X_RIPEMD160HMAC96, XF_AUTH|AH_NEW|ESP_NEW},
};
-char buf[1024];
+/* XXX Depending on message type, we should listen for message replies */
+void
+xf_set(struct iovec *iov, int cnt, int len)
+{
+ int sd;
+
+ sd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
+ if (sd < 0)
+ {
+ perror("socket");
+ exit(1);
+ }
+
+ if (writev(sd, iov, cnt) != len)
+ {
+ perror("write");
+ exit(1);
+ }
+
+ close(sd);
+}
int
x2i(char *s)
{
- char ss[3];
- ss[0] = s[0];
- ss[1] = s[1];
- ss[2] = 0;
+ char ss[3];
+ ss[0] = s[0];
+ ss[1] = s[1];
+ ss[2] = 0;
- if (!isxdigit(s[0]) || !isxdigit(s[1])) {
- fprintf(stderr,
- "Keys and IVs should be specified in hex digits.\n");
- exit(-1);
- }
- return strtoul(ss, NULL, 16);
+ if (!isxdigit(s[0]) || !isxdigit(s[1]))
+ {
+ fprintf(stderr, "Keys should be specified in hex digits.\n");
+ exit(-1);
+ }
+
+ return strtoul(ss, NULL, 16);
}
int
isvalid(char *option, int type, int mode)
{
- int i;
-
- for (i = sizeof(xf) / sizeof(transform) - 1; i >= 0; i--)
- if (!strcmp(option, xf[i].name)) {
- if ((xf[i].flags & CMD_MASK) == type &&
- (xf[i].flags & mode))
- return xf[i].id;
- else
- return 0;
- }
- return 0;
+ int i;
+
+ for (i = sizeof(xf) / sizeof(transform) - 1; i >= 0; i--)
+ if (!strcmp(option, xf[i].name))
+ {
+ if ((xf[i].flags & CMD_MASK) == type &&
+ (xf[i].flags & mode))
+ return xf[i].id;
+ else
+ return 0;
+ }
+
+ return 0;
}
void
usage()
{
- fprintf( stderr, "usage: ipsecadm [command] <modifier...>\n"
- "\tCommands: new esp, old esp, new ah, old ah, group, delspi, ip4, flow\n"
- "\tPossible modifiers:\n"
- "\t\t-enc <alg>\t encryption algorithm\n"
- "\t\t-auth <alg>\t authentication algorithm\n"
- "\t\t-src <ip>\t source address to be used\n"
- "\t\t-tunnel <ip> <ip> tunneling addresses\n"
- "\t\t-dst <ip>\t destination address to be used\n"
- "\t\t-spi <val>\t SPI to be used\n"
- "\t\t-key <val>\t key material to be used\n"
- "\t\t-authkey <val>\t key material for auth in new esp\n"
- "\t\t-iv <val>\t iv to be used\n"
- "\t\t-proto <val>\t security protocol\n"
- "\t\t-chain\t\t SPI chain delete\n"
- "\t\t-newpadding\t new style padding for new ESP\n"
- "\t\t-transport <val>\t protocol number for flow\n"
- "\t\t-addr <ip> <net> <ip> <net>\t subnets for flow\n"
- "\t\t-delete\t\t delete specified flow\n"
- "\t\t-local\t\t also create a local flow\n"
- "\talso: dst2, spi2, proto2\n"
- );
+ fprintf(stderr, "usage: ipsecadm [command] <modifier...>\n"
+ "\tCommands: new esp, old esp, new ah, old ah, group, delspi, ip4, flow\n"
+ "\tPossible modifiers:\n"
+ "\t\t-enc <alg>\t encryption algorithm\n"
+ "\t\t-auth <alg>\t authentication algorithm\n"
+ "\t\t-src <ip>\t source address to be used\n"
+ "\t\t-halfiv\t use 4-byte IV in old ESP\n"
+ "\t\t-forcetunnel\t force tunneling even when not necessary\n"
+ "\t\t-dst <ip>\t destination address to be used\n"
+ "\t\t-proxy <ip>\t proxy address to be used\n"
+ "\t\t-spi <val>\t SPI to be used\n"
+ "\t\t-key <val>\t key material to be used\n"
+ "\t\t-authkey <val>\t key material for auth in new esp\n"
+ "\t\t-proto <val>\t security protocol\n"
+ "\t\t-chain\t\t SPI chain delete\n"
+ "\t\t-transport <val>\t protocol number for flow\n"
+ "\t\t-addr <ip> <net> <ip> <net>\t subnets for flow\n"
+ "\t\t-delete\t\t delete specified flow\n"
+ "\t\t-local\t\t also create a local flow\n"
+ "\talso: dst2, spi2, proto2\n"
+ );
}
int
-main(argc, argv)
- int argc;
- char **argv;
+main(int argc, char **argv)
{
- int i;
- int mode = ESP_NEW, new = 1, flag = 0, newpadding = 0;
- int auth = 0, enc = 0, ivlen = 0, klen = 0, alen = 0;
- int proto = IPPROTO_ESP, proto2 = IPPROTO_AH;
- int dport = -1, sport = -1, tproto = -1;
- int delete = 0, local = 0, result;
- int chain = 0;
- u_int32_t spi = 0, spi2 = 0;
- struct in_addr src, dst, dst2, osrc, odst, osmask, odmask;
- u_char *ivp = NULL, *keyp = NULL, *authp = NULL;
- struct protoent *tp;
- struct servent *svp;
- char *transportproto = NULL;
-
- osrc.s_addr = odst.s_addr = src.s_addr = dst.s_addr = dst2.s_addr = 0;
- osmask.s_addr = odmask.s_addr = 0;
-
- if (argc < 2) {
- usage();
+ int auth = 0, enc = 0, klen = 0, alen = 0, mode = ESP_NEW, i = 0;
+ int proto = IPPROTO_ESP, proto2 = IPPROTO_AH;
+ int dport = -1, sport = -1, tproto = -1;
+ u_int32_t spi = 0, spi2 = 0;
+ union sockaddr_union src, dst, dst2, osrc, odst, osmask, odmask, proxy;
+ u_char *keyp = NULL, *authp = NULL;
+ struct protoent *tp;
+ struct servent *svp;
+ char *transportproto = NULL;
+ struct sadb_msg smsg;
+ struct sadb_sa sa;
+ struct sadb_sa sa2;
+ struct sadb_address sad1; /* src */
+ struct sadb_address sad2; /* dst */
+ struct sadb_address sad3; /* proxy */
+ struct sadb_address sad4; /* osrc */
+ struct sadb_address sad5; /* odst */
+ struct sadb_address sad6; /* osmask */
+ struct sadb_address sad7; /* odmask */
+ struct sadb_address sad8; /* dst2 */
+ struct sadb_key skey1;
+ struct sadb_key skey2;
+ struct sadb_protocol sprotocol;
+ struct iovec iov[20];
+ int cnt = 0;
+ u_char realkey[8192], realakey[8192];
+
+ if (argc < 2)
+ {
+ usage();
+ exit(1);
+ }
+
+ /* Zero out */
+ bzero(&smsg, sizeof(smsg));
+ bzero(&sa, sizeof(sa));
+ bzero(&sa2, sizeof(sa2));
+ bzero(&skey1, sizeof(skey1));
+ bzero(&skey2, sizeof(skey2));
+ bzero(&sad1, sizeof(sad1));
+ bzero(&sad2, sizeof(sad2));
+ bzero(&sad3, sizeof(sad3));
+ bzero(&sad4, sizeof(sad4));
+ bzero(&sad5, sizeof(sad5));
+ bzero(&sad6, sizeof(sad6));
+ bzero(&sad7, sizeof(sad7));
+ bzero(&sad8, sizeof(sad8));
+ bzero(&sprotocol, sizeof(sprotocol));
+ bzero(iov, sizeof(iov));
+ bzero(realkey, sizeof(realkey));
+ bzero(realakey, sizeof(realakey));
+
+ /* Initialize */
+ smsg.sadb_msg_version = PF_KEY_V2;
+ smsg.sadb_msg_seq = 1;
+ smsg.sadb_msg_pid = getpid();
+ smsg.sadb_msg_len = sizeof(smsg) / 8;
+
+ /* Initialize */
+ sa.sadb_sa_exttype = SADB_EXT_SA;
+ sa.sadb_sa_len = sizeof(sa) / 8;
+ sa.sadb_sa_replay = 0;
+ sa.sadb_sa_state = SADB_SASTATE_MATURE;
+
+ /* Initialize */
+ sa2.sadb_sa_exttype = SADB_EXT_X_SA2;
+ sa2.sadb_sa_len = sizeof(sa2) / 8;
+ sa2.sadb_sa_replay = 0;
+ sa2.sadb_sa_state = SADB_SASTATE_MATURE;
+
+ /* Initialize */
+ bzero(&src, sizeof(union sockaddr_union));
+ bzero(&dst, sizeof(union sockaddr_union));
+ bzero(&dst2, sizeof(union sockaddr_union));
+ bzero(&osrc, sizeof(union sockaddr_union));
+ bzero(&odst, sizeof(union sockaddr_union));
+ bzero(&osmask, sizeof(union sockaddr_union));
+ bzero(&odmask, sizeof(union sockaddr_union));
+ bzero(&proxy, sizeof(union sockaddr_union));
+
+ if (!strcmp(argv[1], "new") && argc > 3)
+ {
+ if (!strcmp(argv[2], "esp"))
+ {
+ mode = ESP_NEW;
+ smsg.sadb_msg_type = SADB_ADD;
+ smsg.sadb_msg_satype = SADB_SATYPE_ESP;
+ }
+ else
+ if (!strcmp(argv[2], "ah"))
+ {
+ mode = AH_NEW;
+ smsg.sadb_msg_type = SADB_ADD;
+ smsg.sadb_msg_satype = SADB_SATYPE_AH;
+ }
+ else
+ {
+ fprintf(stderr, "%s: unexpected identifier %s\n", argv[0],
+ argv[2]);
+ exit(1);
+ }
+
+ i += 2;
+ }
+ else
+ if (!strcmp(argv[1], "old") && argc > 3)
+ {
+ if (!strcmp(argv[2], "esp"))
+ {
+ mode = ESP_OLD;
+ smsg.sadb_msg_type = SADB_ADD;
+ smsg.sadb_msg_satype = SADB_SATYPE_X_ESP_OLD;
+ }
+ else
+ if (!strcmp(argv[2], "ah"))
+ {
+ mode = AH_OLD;
+ smsg.sadb_msg_type = SADB_ADD;
+ smsg.sadb_msg_satype = SADB_SATYPE_X_AH_OLD;
+ }
+ else
+ {
+ fprintf(stderr, "%s: unexpected identifier %s\n", argv[0],
+ argv[2]);
exit(1);
+ }
+
+ i += 2;
+ }
+ else
+ if (!strcmp(argv[1], "delspi"))
+ {
+ smsg.sadb_msg_type = SADB_DELETE;
+ mode = DEL_SPI;
+ i++;
}
-
- for (i=1; i < argc; i++) {
- if (!strcmp(argv[i], "new") && !flag) {
- flag = 1;
- new = 1;
- } else if (!strcmp(argv[i], "old") && !flag) {
- flag = 1;
- new = 0;
- } else if (!strcmp(argv[i], "esp") && flag < 2) {
- flag = 2;
- mode = new ? ESP_NEW : ESP_OLD;
- } else if (!strcmp(argv[i], "ah") && flag < 2) {
- flag = 2;
- mode = new ? AH_NEW : AH_OLD;
- } else if (!strcmp(argv[i], "delspi") && flag < 2) {
- flag = 2;
- mode = DEL_SPI;
- } else if (!strcmp(argv[i], "group") && flag < 2) {
- flag = 2;
- mode = GRP_SPI;
- } else if (!strcmp(argv[i], "flow") && flag < 2) {
- flag = 2;
- mode = FLOW;
- } else if (!strcmp(argv[i], "ip4") && flag < 2) {
- flag = 2;
+ else
+ if (!strcmp(argv[1], "group"))
+ {
+ smsg.sadb_msg_type = SADB_X_GRPSPIS;
+ mode = GRP_SPI;
+ i++;
+ }
+ else
+ if (!strcmp(argv[1], "flow"))
+ {
+ /* It may not be ADDFLOW, but never mind that for now */
+ smsg.sadb_msg_type = SADB_X_ADDFLOW;
+ mode = FLOW;
+ i++;
+ }
+ else
+ if (!strcmp(argv[1], "ip4"))
+ {
mode = ENC_IP;
- } else if (argv[i][0] == '-') {
- break;
- } else {
+ smsg.sadb_msg_type = SADB_ADD;
+ smsg.sadb_msg_satype = SADB_SATYPE_X_IPIP;
+ i++;
+ }
+ else
+ {
fprintf(stderr, "%s: Unknown command: %s", argv[0], argv[i]);
exit(1);
- }
+ }
+
+ for (i++; i < argc; i++)
+ {
+ if (argv[i][0] != '-')
+ {
+ fprintf(stderr, "%s: Expected option, got %s\n",
+ argv[0], argv[i]);
+ exit(1);
}
- for (; i < argc; i++) {
- if (argv[i][0] != '-') {
- fprintf(stderr, "%s: Expected option, got %s\n",
- argv[0], argv[i]);
- exit(1);
- } else if (!strcmp(argv[i]+1, "enc") && enc == 0 && i+1 < argc) {
- if ((enc = isvalid(argv[i+1], XF_ENC, mode)) == 0) {
- fprintf(stderr, "%s: Invalid encryption algorithm %s\n",
- argv[0], argv[i+1]);
- exit(1);
- }
- i++;
- } else if (!strcmp(argv[i]+1, "auth") && auth == 0 && i+1 < argc) {
- if ((auth = isvalid(argv[i+1], XF_AUTH, mode)) == 0) {
- fprintf(stderr, "%s: Invalid auth algorithm %s\n",
- argv[0], argv[i+1]);
- exit(1);
- }
- i++;
- } else if (!strcmp(argv[i]+1, "key") && keyp == NULL && i+1 < argc) {
- keyp = argv[++i];
- klen = strlen(keyp);
- } else if (!strcmp(argv[i]+1, "authkey") && authp == NULL && i+1 < argc) {
- if (!(mode & ESP_NEW)) {
- fprintf(stderr, "%s: Invalid option %s for selected mode\n",
- argv[0], argv[i]);
- exit(1);
- }
- authp = argv[++i];
- alen = strlen(authp);
- } else if (!strcmp(argv[i]+1, "iv") && ivp == NULL && i+1 < argc) {
- if (mode & (AH_OLD|AH_NEW)) {
- fprintf(stderr, "%s: Invalid option %s with auth\n",
- argv[0], argv[i]);
- exit(1);
- }
- ivp = argv[++i];
- ivlen = strlen(ivp);
- } else if (!strcmp(argv[i]+1, "spi") && spi == 0 && i+1 < argc) {
- if ((spi = htonl(strtoul(argv[i+1], NULL, 16))) == 0) {
- fprintf(stderr, "%s: Invalid spi %s\n",
- argv[0], argv[i+1]);
- exit(1);
- }
- i++;
- } else if (!strcmp(argv[i]+1, "spi2") && spi2 == 0 &&
- iscmd(mode, GRP_SPI) && i+1 < argc) {
- if ((spi2 = htonl(strtoul(argv[i+1], NULL, 16))) == 0) {
- fprintf(stderr, "%s: Invalid spi2 %s\n",
- argv[0], argv[i+1]);
- exit(1);
- }
- i++;
- } else if (!strcmp(argv[i]+1, "src") && i+1 < argc) {
- src.s_addr = inet_addr(argv[i+1]);
- i++;
- } else if (!strcmp(argv[i]+1, "newpadding") && (mode & ESP_NEW)) {
- newpadding = 1;
- } else if (!strcmp(argv[i]+1, "delete") && iscmd(mode, FLOW)) {
- delete = 1;
- } else if (!strcmp(argv[i]+1, "local") && iscmd(mode, FLOW)) {
- local = 1;
- } else if (!strcmp(argv[i]+1, "tunnel") &&
- (isencauth(mode) || mode == ENC_IP) && i+2 < argc) {
- osrc.s_addr = inet_addr(argv[i+1]);
- i++;
- odst.s_addr = inet_addr(argv[i+1]);
- i++;
- } else if (!strcmp(argv[i]+1, "addr") &&
- iscmd(mode, FLOW) && i+4 < argc) {
- osrc.s_addr = inet_addr(argv[i+1]); i++;
- osmask.s_addr = inet_addr(argv[i+1]); i++;
- odst.s_addr = inet_addr(argv[i+1]); i++;
- odmask.s_addr = inet_addr(argv[i+1]); i++;
- } else if (!strcmp(argv[i]+1, "transport") &&
- iscmd(mode, FLOW) && i+1 < argc) {
- if (isalpha(argv[i+1][0])) {
- tp = getprotobyname(argv[i+1]);
- if (tp == NULL) {
- fprintf(stderr, "%s: unknown protocol %s\n", argv[0], argv[i+1]);
- exit(1);
- }
- tproto = tp->p_proto;
- transportproto = argv[i+1];
- } else {
- tproto = atoi(argv[i+1]);
- tp = getprotobynumber(tproto);
- if (tp == NULL)
- transportproto = "UNKNOWN";
- else
- transportproto = tp->p_name; /* This is static, but it doesn't matter for this application */
+ if (!strcmp(argv[i] + 1, "enc") && enc == 0 && (i + 1 < argc))
+ {
+ if ((enc = isvalid(argv[i + 1], XF_ENC, mode)) == 0)
+ {
+ fprintf(stderr, "%s: Invalid encryption algorithm %s\n",
+ argv[0], argv[i + 1]);
+ exit(1);
+ }
+
+ skey1.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
+ sa.sadb_sa_encrypt = enc;
+ i++;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "auth") && auth == 0 && (i + 1 < argc))
+ {
+ if ((auth = isvalid(argv[i + 1], XF_AUTH, mode)) == 0)
+ {
+ fprintf(stderr, "%s: Invalid auth algorithm %s\n",
+ argv[0], argv[i + 1]);
+ exit(1);
+ }
+
+ skey2.sadb_key_exttype = SADB_EXT_KEY_AUTH;
+ sa.sadb_sa_auth = auth;
+ i++;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "key") && keyp == NULL &&
+ (i + 1 < argc))
+ {
+ if (mode & (AH_NEW | AH_OLD))
+ {
+ authp = argv[++i];
+ alen = strlen(authp) / 2;
+ }
+ else
+ {
+ keyp = argv[++i];
+ klen = strlen(keyp) / 2;
+ }
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "authkey") && authp == NULL &&
+ (i + 1 < argc))
+ {
+ if (!(mode & ESP_NEW))
+ {
+ fprintf(stderr, "%s: Invalid option %s for selected mode\n",
+ argv[0], argv[i]);
+ exit(1);
+ }
+
+ authp = argv[++i];
+ alen = strlen(authp) / 2;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "iv") && (i + 1 < argc))
+ {
+ if (mode & (AH_OLD | AH_NEW))
+ {
+ fprintf(stderr, "%s: Invalid option %s with auth\n",
+ argv[0], argv[i]);
+ exit(1);
+ }
+
+ fprintf(stderr,
+ "%s: Warning: option iv has been deprecated\n", argv[0]);
+
+ if (mode & ESP_OLD)
+ if (strlen(argv[i + 2]) == 4)
+ sa.sadb_sa_flags |= SADB_SAFLAGS_X_HALFIV;
+
+ i++;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "spi") && spi == 0 && (i + 1 < argc))
+ {
+ if ((spi = htonl(strtoul(argv[i + 1], NULL, 16))) == 0)
+ {
+ fprintf(stderr, "%s: Invalid spi %s\n", argv[0], argv[i + 1]);
+ exit(1);
+ }
+
+ sa.sadb_sa_spi = spi;
+ i++;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "spi2") && spi2 == 0 &&
+ iscmd(mode, GRP_SPI) && (i + 1 < argc))
+ {
+ if ((spi2 = htonl(strtoul(argv[i + 1], NULL, 16))) == 0) {
+ fprintf(stderr, "%s: Invalid spi2 %s\n", argv[0], argv[i + 1]);
+ exit(1);
+ }
+
+ sa2.sadb_sa_spi = spi2;
+ i++;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "src") && (i + 1 < argc))
+ {
+ src.sin.sin_family = AF_INET;
+ src.sin.sin_len = sizeof(struct sockaddr_in);
+ src.sin.sin_addr.s_addr = inet_addr(argv[i + 1]);
+ sad1.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
+ sad1.sadb_address_len = 1 + sizeof(struct sockaddr_in) / 8;
+ i++;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "proxy") && (i + 1 < argc))
+ {
+ proxy.sin.sin_family = AF_INET;
+ proxy.sin.sin_len = sizeof(struct sockaddr_in);
+ proxy.sin.sin_addr.s_addr = inet_addr(argv[i + 1]);
+ sad3.sadb_address_exttype = SADB_EXT_ADDRESS_PROXY;
+ sad3.sadb_address_len = 1 + sizeof(struct sockaddr_in) / 8;
+ i++;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "newpadding"))
+ {
+ fprintf(stderr,
+ "%s: Warning: option newpadding has been deprecated\n",
+ argv[0]);
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "forcetunnel") && isencauth(mode))
+ {
+ sa.sadb_sa_flags |= SADB_SAFLAGS_X_TUNNEL;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "halfiv"))
+ {
+ if (!(mode & ESP_OLD))
+ {
+ fprintf(stderr,
+ "%s: option halfiv can be used only with old ESP\n",
+ argv[0]);
+ exit(1);
+ }
+
+ sa.sadb_sa_flags |= SADB_SAFLAGS_X_HALFIV;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "delete") && iscmd(mode, FLOW))
+ {
+ smsg.sadb_msg_type = SADB_X_DELFLOW;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "local") && iscmd(mode, FLOW))
+ {
+ sa.sadb_sa_flags |= SADB_SAFLAGS_X_LOCALFLOW;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "tunnel") &&
+ (isencauth(mode) || mode == ENC_IP) && ( i + 2 < argc))
+ {
+ i += 2;
+ sa.sadb_sa_flags |= SADB_SAFLAGS_X_TUNNEL;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "addr") && iscmd(mode, FLOW) &&
+ (i + 4 < argc))
+ {
+ sad4.sadb_address_exttype = SADB_EXT_X_SRC_FLOW;
+ sad5.sadb_address_exttype = SADB_EXT_X_DST_FLOW;
+ sad6.sadb_address_exttype = SADB_EXT_X_SRC_MASK;
+ sad7.sadb_address_exttype = SADB_EXT_X_DST_MASK;
+
+ sad4.sadb_address_len = (sizeof(sad4) +
+ sizeof(struct sockaddr_in)) / 8;
+ sad5.sadb_address_len = (sizeof(sad5) +
+ sizeof(struct sockaddr_in)) / 8;
+ sad6.sadb_address_len = (sizeof(sad6) +
+ sizeof(struct sockaddr_in)) / 8;
+ sad7.sadb_address_len = (sizeof(sad7) +
+ sizeof(struct sockaddr_in)) / 8;
+
+ osrc.sin.sin_family = odst.sin.sin_family = AF_INET;
+ osmask.sin.sin_family = odmask.sin.sin_family = AF_INET;
+ osrc.sin.sin_len = odst.sin.sin_len = sizeof(struct sockaddr_in);
+ osmask.sin.sin_len = sizeof(struct sockaddr_in);
+ odmask.sin.sin_len = sizeof(struct sockaddr_in);
+
+ osrc.sin.sin_addr.s_addr = inet_addr(argv[i + 1]); i++;
+ osmask.sin.sin_addr.s_addr = inet_addr(argv[i + 1]); i++;
+ odst.sin.sin_addr.s_addr = inet_addr(argv[i + 1]); i++;
+ odmask.sin.sin_addr.s_addr = inet_addr(argv[i + 1]); i++;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "transport") &&
+ iscmd(mode, FLOW) && (i + 1 < argc))
+ {
+ if (isalpha(argv[i + 1][0]))
+ {
+ tp = getprotobyname(argv[i + 1]);
+ if (tp == NULL)
+ {
+ fprintf(stderr,
+ "%s: unknown protocol %s\n", argv[0], argv[i + 1]);
+ exit(1);
+ }
+
+ tproto = tp->p_proto;
+ transportproto = argv[i + 1];
+ }
+ else
+ {
+ tproto = atoi(argv[i + 1]);
+ tp = getprotobynumber(tproto);
+ if (tp == NULL)
+ transportproto = "UNKNOWN";
+ else
+ transportproto = tp->p_name;
+ }
+
+ sprotocol.sadb_protocol_len = 1;
+ sprotocol.sadb_protocol_exttype = SADB_EXT_X_PROTOCOL;
+ sprotocol.sadb_protocol_proto = tproto;
+ i++;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "sport") &&
+ iscmd(mode, FLOW) && (i + 1 < argc))
+ {
+ if (isalpha(argv[i + 1][0]))
+ {
+ svp = getservbyname(argv[i + 1], transportproto);
+ if (svp == NULL)
+ {
+ fprintf(stderr,
+ "%s: unknown service port %s for protocol %s\n",
+ argv[0], argv[i + 1], transportproto);
+ exit(1);
+ }
+
+ sport = svp->s_port;
+ }
+ else
+ sport = atoi(argv[i+1]);
+
+ osrc.sin.sin_port = sport;
+ osmask.sin.sin_port = 0xffff;
+ i++;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "dport") &&
+ iscmd(mode, FLOW) && (i + 1 < argc))
+ {
+ if (isalpha(argv[i + 1][0]))
+ {
+ svp = getservbyname(argv[i + 1], transportproto);
+ if (svp == NULL)
+ {
+ fprintf(stderr,
+ "%s: unknown service port %s for protocol %s\n",
+ argv[0], argv[i + 1], transportproto);
+ exit(1);
+ }
+ dport = svp->s_port;
+ }
+ else
+ dport = atoi(argv[i + 1]);
+
+ odst.sin.sin_port = dport;
+ odmask.sin.sin_port = 0xffff;
+ i++;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "dst") && (i + 1 < argc))
+ {
+ sad2.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
+ sad2.sadb_address_len = (sizeof(sad2) +
+ sizeof(struct sockaddr_in)) / 8;
+ dst.sin.sin_family = AF_INET;
+ dst.sin.sin_len = sizeof(struct sockaddr_in);
+ dst.sin.sin_addr.s_addr = inet_addr(argv[i + 1]);
+ i++;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "dst2") &&
+ iscmd(mode, GRP_SPI) && (i + 1 < argc))
+ {
+ sad8.sadb_address_len = (sizeof(sad8) +
+ sizeof(struct sockaddr_in)) / 8;
+ sad8.sadb_address_exttype = SADB_EXT_X_DST2;
+ dst2.sin.sin_family = AF_INET;
+ dst2.sin.sin_len = sizeof(struct sockaddr_in);
+ dst2.sin.sin_addr.s_addr = inet_addr(argv[i + 1]);
+ i++;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "proto") && (i + 1 < argc) &&
+ (iscmd(mode, FLOW) || iscmd(mode, GRP_SPI) ||
+ iscmd(mode, DEL_SPI)))
+ {
+ if (isalpha(argv[i + 1][0]))
+ {
+ if (!strcasecmp(argv[i + 1], "esp"))
+ {
+ smsg.sadb_msg_satype = SADB_SATYPE_ESP;
+ proto = IPPROTO_ESP;
+ }
+ else
+ if (!strcasecmp(argv[i + 1], "ah"))
+ {
+ smsg.sadb_msg_satype = SADB_SATYPE_AH;
+ proto = IPPROTO_AH;
}
- i++;
- } else if (!strcmp(argv[i]+1, "sport") &&
- iscmd(mode, FLOW) && i+1 < argc) {
- if (isalpha(argv[i+1][0])) {
- svp = getservbyname(argv[i+1], transportproto);
- if (svp == NULL) {
- fprintf(stderr, "%s: unknown service port %s for protocol %s\n", argv[0], argv[i+1], transportproto);
- exit(1);
- }
- sport = svp->s_port;
- } else
- sport = atoi(argv[i+1]);
- i++;
- } else if (!strcmp(argv[i]+1, "dport") &&
- iscmd(mode, FLOW) && i+1 < argc) {
- if (isalpha(argv[i+1][0])) {
- svp = getservbyname(argv[i+1], transportproto);
- if (svp == NULL) {
- fprintf(stderr, "%s: unknown service port %s for protocol %s\n", argv[0], argv[i+1], transportproto);
- exit(1);
- }
- dport = svp->s_port;
- } else
- dport = atoi(argv[i+1]);
- i++;
- } else if (!strcmp(argv[i]+1, "dst") && i+1 < argc) {
- dst.s_addr = inet_addr(argv[i+1]);
- i++;
- } else if (!strcmp(argv[i]+1, "dst2") &&
- iscmd(mode, GRP_SPI) && i+1 < argc) {
- dst2.s_addr = inet_addr(argv[i+1]);
- i++;
- } else if (!strcmp(argv[i]+1, "proto") && i+1 < argc) {
- if (isalpha(argv[i+1][0])) {
- if (!strcasecmp(argv[i+1], "esp"))
- proto = IPPROTO_ESP;
- else if (!strcasecmp(argv[i+1], "ah"))
- proto = IPPROTO_AH;
- else if (!strcasecmp(argv[i+1], "ip4"))
- proto = IPPROTO_IPIP;
- else {
- fprintf(stderr, "%s: unknown security protocol type %s\n", argv[0], argv[i+1]);
- exit(1);
- }
- } else {
- proto = atoi(argv[i+1]);
- if (proto != IPPROTO_ESP && proto != IPPROTO_AH &&
- proto != IPPROTO_IPIP) {
- fprintf(stderr, "%s: unknown security protocol %d\n", argv[0], proto);
+ else
+ if (!strcasecmp(argv[i + 1], "ip4"))
+ {
+ smsg.sadb_msg_satype = SADB_SATYPE_X_IPIP;
+ proto = IPPROTO_IPIP;
+ }
+ else
+ {
+ fprintf(stderr,
+ "%s: unknown security protocol type %s\n",
+ argv[0], argv[i + 1]);
exit(1);
- }
+ }
+ }
+ else
+ {
+ proto = atoi(argv[i + 1]);
+ if (proto != IPPROTO_ESP && proto != IPPROTO_AH &&
+ proto != IPPROTO_IPIP)
+ {
+ fprintf(stderr,
+ "%s: unknown security protocol %d\n",
+ argv[0], proto);
+ exit(1);
+ }
+
+ if (proto == IPPROTO_ESP)
+ smsg.sadb_msg_satype = SADB_SATYPE_ESP;
+ else
+ if (proto == IPPROTO_AH)
+ smsg.sadb_msg_satype = SADB_SATYPE_AH;
+ else
+ if (proto == IPPROTO_IPIP)
+ smsg.sadb_msg_satype = SADB_SATYPE_X_IPIP;
+ }
+
+ i++;
+ continue;
+ }
+
+ if (!strcmp(argv[i] + 1, "proto2") &&
+ iscmd(mode, GRP_SPI) && (i + 1 < argc))
+ {
+ if (isalpha(argv[i + 1][0]))
+ {
+ if (!strcasecmp(argv[i + 1], "esp"))
+ {
+ sprotocol.sadb_protocol_proto = SADB_SATYPE_ESP;
+ proto2 = IPPROTO_ESP;
+ }
+ else
+ if (!strcasecmp(argv[i + 1], "ah"))
+ {
+ sprotocol.sadb_protocol_proto = SADB_SATYPE_AH;
+ proto2 = IPPROTO_AH;
}
- i++;
- } else if (!strcmp(argv[i]+1, "proto2") &&
- iscmd(mode, GRP_SPI) && i+1 < argc) {
- if (isalpha(argv[i+1][0])) {
- if (!strcasecmp(argv[i+1], "esp"))
- proto2 = IPPROTO_ESP;
- else if (!strcasecmp(argv[i+1], "ah"))
- proto2 = IPPROTO_AH;
- else if (!strcasecmp(argv[i+1], "ip4"))
- proto2 = IPPROTO_IPIP;
- else {
- fprintf(stderr, "%s: unknown security protocol2 type %s\n", argv[0], argv[i+1]);
- exit(1);
- }
- } else
- proto2 = atoi(argv[i+1]);
- if (proto2 != IPPROTO_ESP && proto2 != IPPROTO_AH &&
- proto2 != IPPROTO_IPIP) {
- fprintf(stderr, "%s: unknown security protocol %d\n", argv[0], proto);
- exit(1);
- }
- i++;
- } else if (!strcmp(argv[i]+1, "chain") && chain == 0 &&
- iscmd(mode, DEL_SPI)) {
- chain = 1;
- } else {
- fprintf(stderr, "%s: Unkown option: %s\n", argv[0], argv[i]);
- exit(1);
- }
+ else
+ if (!strcasecmp(argv[i + 1], "ip4"))
+ {
+ sprotocol.sadb_protocol_proto = SADB_SATYPE_X_IPIP;
+ proto2 = IPPROTO_IPIP;
+ }
+ else
+ {
+ fprintf(stderr,
+ "%s: unknown security protocol2 type %s\n",
+ argv[0], argv[i+1]);
+ exit(1);
+ }
+ }
+ else
+ proto2 = atoi(argv[i + 1]);
+
+ if (proto2 != IPPROTO_ESP && proto2 != IPPROTO_AH &&
+ proto2 != IPPROTO_IPIP)
+ {
+ fprintf(stderr,
+ "%s: unknown security protocol2 %d\n", argv[0], proto);
+ exit(1);
+ }
+
+ sprotocol.sadb_protocol_exttype = SADB_EXT_X_PROTOCOL;
+ sprotocol.sadb_protocol_len = 1;
+ i++;
+ continue;
}
+ if (!strcmp(argv[i] + 1, "chain") &&
+ !(sa.sadb_sa_flags & SADB_SAFLAGS_X_CHAINDEL) &&
+ iscmd(mode, DEL_SPI))
+ {
+ sa.sadb_sa_flags |= SADB_SAFLAGS_X_CHAINDEL;
+ continue;
+ }
+
+ /* No match */
+ fprintf(stderr,
+ "%s: Unknown or invalid option: %s\n", argv[0], argv[i]);
+ exit(1);
+ }
+
+ /* Sanity checks */
+ if ((mode & (ESP_NEW | ESP_OLD)) && enc == 0)
+ {
+ fprintf(stderr, "%s: No encryption algorithm specified\n", argv[0]);
+ exit(1);
+ }
+
+ if ((mode & (AH_NEW | AH_OLD)) && auth == 0)
+ {
+ fprintf(stderr, "%s: No authentication algorithm specified\n",
+ argv[0]);
+ exit(1);
+ }
+
+ if (isencauth(mode) && keyp == NULL)
+ {
+ fprintf(stderr, "%s: No key material specified\n", argv[0]);
+ exit(1);
+ }
+
+ if ((mode & ESP_NEW) && auth && authp == NULL)
+ {
+ fprintf(stderr, "%s: No auth key material specified\n", argv[0]);
+ exit(1);
+ }
+
+ if (spi == 0)
+ {
+ fprintf(stderr, "%s: No SPI specified\n", argv[0]);
+ exit(1);
+ }
+
+ if (iscmd(mode, GRP_SPI) && spi2 == 0)
+ {
+ fprintf(stderr, "%s: No SPI2 specified\n", argv[0]);
+ exit(1);
+ }
+
+ if ((isencauth(mode) || iscmd(mode, ENC_IP)) &&
+ src.sin.sin_addr.s_addr == 0)
+ {
+ fprintf(stderr, "%s: No source address specified\n", argv[0]);
+ exit(1);
+ }
- /* Sanity checks */
- if ((mode & (ESP_NEW|ESP_OLD)) && enc == 0) {
- fprintf(stderr, "%s: No encryption algorithm specified\n",
- argv[0]);
- exit(1);
- } else if ((mode & (AH_NEW|AH_OLD)) && auth == 0) {
- fprintf(stderr, "%s: No authenication algorithm specified\n",
- argv[0]);
- exit(1);
- } else if (isencauth(mode) && keyp == NULL) {
- fprintf(stderr, "%s: No key material specified\n", argv[0]);
- exit(1);
- } else if ((mode & ESP_NEW) && auth && authp == NULL) {
- fprintf(stderr, "%s: No auth key material specified\n", argv[0]);
- exit(1);
- } else if (spi == 0) {
- fprintf(stderr, "%s: No SPI specified\n", argv[0]);
- exit(1);
- } else if (iscmd(mode, GRP_SPI) && spi2 == 0) {
- fprintf(stderr, "%s: No SPI2 specified\n", argv[0]);
- exit(1);
- } else if ((isencauth(mode) || iscmd(mode, ENC_IP)) &&
- src.s_addr == 0) {
- fprintf(stderr, "%s: No source address specified\n", argv[0]);
- exit(1);
- } else if ((iscmd(mode, DEL_SPI) || iscmd(mode, GRP_SPI) ||
- iscmd(mode, FLOW)) &&
- proto != IPPROTO_ESP && proto != IPPROTO_AH &&
- proto != IPPROTO_IPIP) {
- fprintf(stderr, "%s: Security protocol is none of AH, ESP or IPIP\n", argv[0]);
- exit(1);
- } else if (iscmd(mode, GRP_SPI) &&
- proto2 != IPPROTO_ESP && proto2 != IPPROTO_AH &&
- proto2 != IPPROTO_IPIP) {
- fprintf(stderr, "%s: Security protocol2 is none of AH, ESP or IPIP\n", argv[0]);
- exit(1);
- } else if (dst.s_addr == 0) {
- fprintf(stderr, "%s: No destination address specified\n",
- argv[0]);
- exit(1);
- } else if (iscmd(mode, ENC_IP) &&
- (odst.s_addr == 0 || osrc.s_addr == 0)) {
- fprintf(stderr, "%s: No tunnel addresses specified\n",
- argv[0]);
- exit(1);
- } else if (iscmd(mode, FLOW) &&
- (odst.s_addr == 0 && odmask.s_addr == 0 &&
- osrc.s_addr == 0 && osmask.s_addr == 0)) {
- fprintf(stderr, "%s: No subnets for flow specified\n",
- argv[0]);
- exit(1);
- } else if (iscmd(mode, GRP_SPI) && dst2.s_addr == 0) {
- fprintf(stderr, "%s: No destination address2 specified\n",
- argv[0]);
- exit(1);
+ if ((iscmd(mode, DEL_SPI) || iscmd(mode, GRP_SPI) || iscmd(mode, FLOW)) &&
+ proto != IPPROTO_ESP && proto != IPPROTO_AH && proto != IPPROTO_IPIP)
+ {
+ fprintf(stderr, "%s: Security protocol is none of AH, ESP or IPIP\n",
+ argv[0]);
+ exit(1);
+ }
+
+ if (iscmd(mode, GRP_SPI) && proto2 != IPPROTO_ESP &&
+ proto2 != IPPROTO_AH && proto2 != IPPROTO_IPIP)
+ {
+ fprintf(stderr, "%s: Security protocol2 is none of AH, ESP or IPIP\n",
+ argv[0]);
+ exit(1);
+ }
+
+ if (dst.sin.sin_addr.s_addr == 0)
+ {
+ fprintf(stderr, "%s: No destination address for the SA specified\n",
+ argv[0]);
+ exit(1);
+ }
+
+ if (iscmd(mode, FLOW) && (odst.sin.sin_addr.s_addr == 0 &&
+ odmask.sin.sin_addr.s_addr == 0 &&
+ osrc.sin.sin_addr.s_addr == 0 &&
+ osmask.sin.sin_addr.s_addr == 0))
+ {
+ fprintf(stderr, "%s: No subnets for flow specified\n", argv[0]);
+ exit(1);
+ }
+
+ if (iscmd(mode, FLOW) && (sprotocol.sadb_protocol_proto == 0) &&
+ (odst.sin.sin_port || osrc.sin.sin_port))
+ {
+ fprintf(stderr, "%s: No transport protocol supplied with source/destination ports\n", argv[0]);
+ exit(1);
+ }
+
+ if (iscmd(mode, GRP_SPI) && dst2.sin.sin_addr.s_addr == 0)
+ {
+ fprintf(stderr, "%s: No destination address2 specified\n", argv[0]);
+ exit(1);
+ }
+
+ if ((klen > 2 * 8100) || (alen > 2 * 8100))
+ {
+ fprintf(stderr, "%s: key too long\n", argv[0]);
+ exit(1);
+ }
+
+ if (keyp != NULL)
+ {
+ for (i = 0; i < klen; i++)
+ realkey[i] = x2i(keyp + 2 * i);
+ }
+
+ if (authp != NULL)
+ {
+ for (i = 0; i < alen; i++)
+ realakey[i] = x2i(authp + 2 * i);
+ }
+
+ /* message header */
+ iov[cnt].iov_base = &smsg;
+ iov[cnt++].iov_len = sizeof(smsg);
+
+ if (isencauth(mode))
+ {
+ /* SA header */
+ iov[cnt].iov_base = &sa;
+ iov[cnt++].iov_len = sizeof(sa);
+ smsg.sadb_msg_len += sa.sadb_sa_len;
+
+ /* Destination address header */
+ iov[cnt].iov_base = &sad2;
+ iov[cnt++].iov_len = sizeof(sad2);
+ /* Destination address */
+ iov[cnt].iov_base = &dst;
+ iov[cnt++].iov_len = sizeof(struct sockaddr_in);
+ smsg.sadb_msg_len += sad2.sadb_address_len;
+
+ if (src.sin.sin_addr.s_addr)
+ {
+ /* Source address header */
+ iov[cnt].iov_base = &sad1;
+ iov[cnt++].iov_len = sizeof(sad1);
+ /* Source address */
+ iov[cnt].iov_base = &src;
+ iov[cnt++].iov_len = sizeof(struct sockaddr_in);
+ smsg.sadb_msg_len += sad1.sadb_address_len;
}
- if (isencauth(mode)) {
- switch(mode) {
- case ESP_NEW:
- result = xf_esp_new(src, dst, spi, enc, auth, ivp, keyp,
- authp, osrc, odst, newpadding);
- break;
- case ESP_OLD:
- result = xf_esp_old(src, dst, spi, enc, ivp, keyp, osrc, odst);
- break;
- case AH_NEW:
- result = xf_ah_new(src, dst, spi, auth, keyp, osrc, odst);
- break;
- case AH_OLD:
- result = xf_ah_old(src, dst, spi, auth, keyp, osrc, odst);
- break;
- }
- } else {
- switch(mode & CMD_MASK) {
- case GRP_SPI:
- result = xf_grp(dst, spi, proto, dst2, spi2, proto2);
- break;
- case DEL_SPI:
- result = xf_delspi(dst, spi, proto, chain);
- break;
- case ENC_IP:
- result = xf_ip4(src, dst, spi, osrc, odst);
- break;
+ if (proxy.sin.sin_addr.s_addr)
+ {
+ /* Proxy address header */
+ iov[cnt].iov_base = &sad3;
+ iov[cnt++].iov_len = sizeof(sad3);
+ /* Proxy address */
+ iov[cnt].iov_base = &proxy;
+ iov[cnt++].iov_len = sizeof(struct sockaddr_in);
+ smsg.sadb_msg_len += sad3.sadb_address_len;
+ }
+
+ if (keyp)
+ {
+ /* Key header */
+ iov[cnt].iov_base = &skey1;
+ iov[cnt++].iov_len = sizeof(skey1);
+ /* Key */
+ iov[cnt].iov_base = realkey;
+ iov[cnt++].iov_len = ((klen + 7) / 8) * 8;
+ skey1.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
+ skey1.sadb_key_len = (sizeof(skey1) + ((klen + 7) / 8) * 8) / 8;
+ skey1.sadb_key_bits = 8 * klen;
+ smsg.sadb_msg_len += skey1.sadb_key_len;
+ }
+
+ if (authp)
+ {
+ /* Auth key header */
+ iov[cnt].iov_base = &skey2;
+ iov[cnt++].iov_len = sizeof(skey2);
+ /* Auth key */
+ iov[cnt].iov_base = realakey;
+ iov[cnt++].iov_len = ((alen + 7) / 8) * 8;
+ skey2.sadb_key_exttype = SADB_EXT_KEY_AUTH;
+ skey2.sadb_key_len = (sizeof(skey2) + ((alen + 7) / 8) * 8) / 8;
+ skey2.sadb_key_bits = 8 * alen;
+ smsg.sadb_msg_len += skey2.sadb_key_len;
+ }
+ }
+ else
+ {
+ switch(mode & CMD_MASK)
+ {
+ case GRP_SPI:
+ /* SA header */
+ iov[cnt].iov_base = &sa;
+ iov[cnt++].iov_len = sizeof(sa);
+ smsg.sadb_msg_len += sa.sadb_sa_len;
+
+ /* Destination address header */
+ iov[cnt].iov_base = &sad2;
+ iov[cnt++].iov_len = sizeof(sad2);
+ /* Destination address */
+ iov[cnt].iov_base = &dst;
+ iov[cnt++].iov_len = sizeof(struct sockaddr_in);
+ smsg.sadb_msg_len += sad2.sadb_address_len;
+
+ /* SA header */
+ iov[cnt].iov_base = &sa2;
+ iov[cnt++].iov_len = sizeof(sa2);
+ smsg.sadb_msg_len += sa2.sadb_sa_len;
+
+ /* Destination2 address header */
+ iov[cnt].iov_base = &sad8;
+ iov[cnt++].iov_len = sizeof(sad8);
+ /* Destination2 address */
+ iov[cnt].iov_base = &dst2;
+ iov[cnt++].iov_len = sizeof(struct sockaddr_in);
+ smsg.sadb_msg_len += sad8.sadb_address_len;
+
+ /* Protocol2 */
+ iov[cnt].iov_base = &sprotocol;
+ iov[cnt++].iov_len = sizeof(sprotocol);
+ smsg.sadb_msg_len += sprotocol.sadb_protocol_len;
+ break;
+
+ case DEL_SPI:
+ /* SA header */
+ iov[cnt].iov_base = &sa;
+ iov[cnt++].iov_len = sizeof(sa);
+ smsg.sadb_msg_len += sa.sadb_sa_len;
+
+ /* Destination address header */
+ iov[cnt].iov_base = &sad2;
+ iov[cnt++].iov_len = sizeof(sad2);
+ /* Destination address */
+ iov[cnt].iov_base = &dst;
+ iov[cnt++].iov_len = sizeof(struct sockaddr_in);
+ smsg.sadb_msg_len += sad2.sadb_address_len;
+ break;
+
+ case ENC_IP:
+ /* SA header */
+ iov[cnt].iov_base = &sa;
+ iov[cnt++].iov_len = sizeof(sa);
+ smsg.sadb_msg_len += sa.sadb_sa_len;
+
+ /* Destination address header */
+ iov[cnt].iov_base = &sad2;
+ iov[cnt++].iov_len = sizeof(sad2);
+ /* Destination address */
+ iov[cnt].iov_base = &dst;
+ iov[cnt++].iov_len = sizeof(struct sockaddr_in);
+ smsg.sadb_msg_len += sad2.sadb_address_len;
+
+ if (src.sin.sin_addr.s_addr)
+ {
+ /* Source address header */
+ iov[cnt].iov_base = &sad1;
+ iov[cnt++].iov_len = sizeof(sad1);
+ /* Source address */
+ iov[cnt].iov_base = &src;
+ iov[cnt++].iov_len = sizeof(struct sockaddr_in);
+ smsg.sadb_msg_len += sad1.sadb_address_len;
+ }
+ break;
+
case FLOW:
- result = xf_flow(dst, spi, proto, osrc, osmask, odst, odmask,
- tproto, sport, dport, delete, local);
- break;
- }
+ if (smsg.sadb_msg_type != SADB_X_DELFLOW)
+ {
+ /* Destination address header */
+ iov[cnt].iov_base = &sad2;
+ iov[cnt++].iov_len = sizeof(sad2);
+ /* Destination address */
+ iov[cnt].iov_base = &dst;
+ iov[cnt++].iov_len = sizeof(struct sockaddr_in);
+ smsg.sadb_msg_len += sad2.sadb_address_len;
+ }
+
+ /* SA header */
+ iov[cnt].iov_base = &sa;
+ iov[cnt++].iov_len = sizeof(sa);
+ smsg.sadb_msg_len += sa.sadb_sa_len;
+
+ if (sprotocol.sadb_protocol_len)
+ {
+ /* Protocol2 */
+ iov[cnt].iov_base = &sprotocol;
+ iov[cnt++].iov_len = sizeof(sprotocol);
+ smsg.sadb_msg_len += sprotocol.sadb_protocol_len;
+ }
+
+ /* Flow source address header */
+ iov[cnt].iov_base = &sad4;
+ iov[cnt++].iov_len = sizeof(sad4);
+ /* Flow source addressaddress */
+ iov[cnt].iov_base = &osrc;
+ iov[cnt++].iov_len = sizeof(struct sockaddr_in);
+ smsg.sadb_msg_len += sad4.sadb_address_len;
+
+ /* Flow destination address header */
+ iov[cnt].iov_base = &sad5;
+ iov[cnt++].iov_len = sizeof(sad5);
+ /* Flow destination address */
+ iov[cnt].iov_base = &odst;
+ iov[cnt++].iov_len = sizeof(struct sockaddr_in);
+ smsg.sadb_msg_len += sad5.sadb_address_len;
+
+ /* Flow source address mask header */
+ iov[cnt].iov_base = &sad6;
+ iov[cnt++].iov_len = sizeof(sad6);
+ /* Flow source address mask */
+ iov[cnt].iov_base = &osmask;
+ iov[cnt++].iov_len = sizeof(struct sockaddr_in);
+ smsg.sadb_msg_len += sad6.sadb_address_len;
+
+ /* Flow destination address mask header */
+ iov[cnt].iov_base = &sad7;
+ iov[cnt++].iov_len = sizeof(sad7);
+ /* Flow destination address mask */
+ iov[cnt].iov_base = &odmask;
+ iov[cnt++].iov_len = sizeof(struct sockaddr_in);
+ smsg.sadb_msg_len += sad7.sadb_address_len;
+ break;
}
+ }
- exit (result ? 0 : 1);
+ xf_set(iov, cnt, smsg.sadb_msg_len * 8);
+ exit (0);
}
+