aboutsummaryrefslogtreecommitdiffstats
path: root/main/ipsec-tools
diff options
context:
space:
mode:
Diffstat (limited to 'main/ipsec-tools')
-rw-r--r--main/ipsec-tools/20-grekey-support.patch786
-rw-r--r--main/ipsec-tools/50-reverse-connect.patch197
-rw-r--r--main/ipsec-tools/70-defer-isakmp-ident-handling.patch179
-rw-r--r--main/ipsec-tools/75-racoonctl-rcvbuf.patch33
-rw-r--r--main/ipsec-tools/APKBUILD65
-rw-r--r--main/ipsec-tools/racoon.confd20
-rw-r--r--main/ipsec-tools/racoon.initd60
7 files changed, 1340 insertions, 0 deletions
diff --git a/main/ipsec-tools/20-grekey-support.patch b/main/ipsec-tools/20-grekey-support.patch
new file mode 100644
index 0000000000..17fea3e991
--- /dev/null
+++ b/main/ipsec-tools/20-grekey-support.patch
@@ -0,0 +1,786 @@
+Index: ipsec-tools-cvs-HEAD/src/racoon/racoonctl.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/racoonctl.c 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/racoonctl.c 2011-03-29 22:08:43.000000000 +0300
+@@ -232,7 +232,7 @@
+ "\n"
+ " <saopts>: \"isakmp\" <family> <src> <dst>\n"
+ " : {\"esp\",\"ah\"} <family> <src/prefixlen/port> <dst/prefixlen/port>\n"
+-" <ul_proto>\n"
++" <ul_proto> [grekey <grekey>]\n"
+ " <family>: \"inet\" or \"inet6\"\n"
+ " <ul_proto>: \"icmp\", \"tcp\", \"udp\", \"gre\" or \"any\"\n"
+ "\n",
+@@ -819,7 +819,7 @@
+ {
+ int family;
+
+- if (ac != 3 && ac != 4) {
++ if (ac < 3) {
+ errno = EINVAL;
+ return NULL;
+ }
+@@ -861,10 +861,8 @@
+ struct sockaddr *src = NULL, *dst = NULL;
+ int ulproto;
+
+- if (ac != 2 && ac != 3) {
+- errno = EINVAL;
+- return NULL;
+- }
++ if (ac < 2)
++ goto bad_args;
+
+ if (get_comindex(*av, &p_name, &p_port, &p_prefs) == -1)
+ goto bad;
+@@ -901,13 +899,34 @@
+
+ av++;
+ ac--;
+- if(ac){
++ if (ac) {
+ ulproto = get_ulproto(*av);
+ if (ulproto == -1)
+ goto bad;
+- }else
++ av++;
++ ac--;
++ } else
+ ulproto=0;
+
++ if (ac == 2 && strcmp(av[0], "grekey") == 0) {
++ int a, b, c, d;
++ unsigned long u;
++
++ if (sscanf(av[1], "%d.%d.%d.%d", &a, &b, &c, &d) == 4) {
++ set_port(src, (a << 8) + b);
++ set_port(dst, (c << 8) + d);
++ } else if (sscanf(av[1], "%lu", &u) == 1) {
++ set_port(src, u >> 16);
++ set_port(dst, u & 0xffff);
++ } else
++ goto bad_args;
++ av += 2;
++ ac -= 2;
++ }
++
++ if (ac != 0)
++ goto bad_args;
++
+ ci = (struct admin_com_indexes *)buf->v;
+ if(p_prefs)
+ ci->prefs = (u_int8_t)atoi(p_prefs); /* XXX should be handled error. */
+@@ -926,7 +945,9 @@
+
+ return buf;
+
+- bad:
++bad_args:
++ errno = EINVAL;
++bad:
+ if (p_name)
+ racoon_free(p_name);
+ if (p_port)
+Index: ipsec-tools-cvs-HEAD/src/racoon/admin.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/admin.c 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/admin.c 2011-03-30 09:41:46.000000000 +0300
+@@ -444,7 +444,7 @@
+
+ /* search appropreate configuration */
+ if (name == NULL)
+- rmconf = getrmconf(dst, 0);
++ rmconf = getrmconf(dst, 0, 0);
+ else
+ rmconf = getrmconf_by_name(name);
+ if (rmconf == NULL) {
+@@ -536,6 +536,7 @@
+ spidx.prefs = ndx->prefd;
+ spidx.prefd = ndx->prefs;
+ spidx.ul_proto = ndx->ul_proto;
++ spidx_normalize_ulports(&spidx);
+
+ sp_in = getsp_r(&spidx);
+ if (sp_in) {
+Index: ipsec-tools-cvs-HEAD/src/racoon/cftoken.l
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/cftoken.l 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/cftoken.l 2011-03-29 22:08:43.000000000 +0300
+@@ -288,6 +288,7 @@
+ <S_SAINF>any { YYD; return(ANY); }
+ <S_SAINF>from { YYD; return(FROM); }
+ <S_SAINF>group { YYD; return(GROUP); }
++<S_SAINF>grekey { YYD; return(GREKEY); }
+ /* sainfo spec */
+ <S_SAINF>{bcl} { BEGIN S_SAINFS; return(BOC); }
+ <S_SAINF>{semi} { BEGIN S_INI; return(EOS); }
+Index: ipsec-tools-cvs-HEAD/src/racoon/cfparse.y
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/cfparse.y 2011-03-14 19:12:41.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/cfparse.y 2011-03-29 22:08:43.000000000 +0300
+@@ -214,7 +214,7 @@
+ /* algorithm */
+ %token ALGORITHM_CLASS ALGORITHMTYPE STRENGTHTYPE
+ /* sainfo */
+-%token SAINFO FROM
++%token SAINFO FROM GREKEY
+ /* remote */
+ %token REMOTE ANONYMOUS CLIENTADDR INHERIT REMOTE_ADDRESS
+ %token EXCHANGE_MODE EXCHANGETYPE DOI DOITYPE SITUATION SITUATIONTYPE
+@@ -1302,6 +1302,35 @@
+ cur_sainfo->idsrc = $1;
+ cur_sainfo->iddst = $2;
+ }
++ | sainfo_id sainfo_id GREKEY ADDRSTRING
++ {
++ int a, b, c, d;
++
++ if (sscanf($4->v, "%d.%d.%d.%d", &a, &b, &c, &d) == 4) {
++ a = ipsecdoi_fixup_id_uldata(
++ $1, $2, IPPROTO_GRE,
++ (a << 8) + b, (c << 8) + d);
++ } else {
++ yyerror("grekey format unrecognized.");
++ return -1;
++ }
++ if (a != 0) {
++ yyerror("ul_proto needs to be 'gre' to use grekey.");
++ return -1;
++ }
++ cur_sainfo->idsrc = $1;
++ cur_sainfo->iddst = $2;
++ }
++ | sainfo_id sainfo_id GREKEY NUMBER
++ {
++ if (ipsecdoi_fixup_id_uldata($1, $2, IPPROTO_GRE,
++ ($4) >> 16, ($4) & 0xffff) != 0) {
++ yyerror("ul_proto needs to be 'gre' to use grekey.");
++ return -1;
++ }
++ cur_sainfo->idsrc = $1;
++ cur_sainfo->iddst = $2;
++ }
+ ;
+ sainfo_id
+ : IDENTIFIERTYPE ADDRSTRING prefix port ul_proto
+@@ -1668,7 +1697,7 @@
+ {
+ struct remoteconf *from, *new;
+
+- from = getrmconf($4, GETRMCONF_F_NO_ANONYMOUS);
++ from = getrmconf($4, GETRMCONF_F_NO_ANONYMOUS, 0);
+ if (from == NULL) {
+ yyerror("failed to get remoteconf for %s.",
+ saddr2str($4));
+Index: ipsec-tools-cvs-HEAD/src/racoon/ipsec_doi.h
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/ipsec_doi.h 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/ipsec_doi.h 2011-03-30 09:22:13.000000000 +0300
+@@ -227,6 +227,10 @@
+ extern int set_identifier_qual __P((vchar_t **, int, vchar_t *, int));
+ extern int ipsecdoi_setid2 __P((struct ph2handle *));
+ extern vchar_t *ipsecdoi_sockaddr2id __P((struct sockaddr *, u_int, u_int));
++extern int ipsecdoi_fixup_id_uldata __P((vchar_t *, vchar_t *, u_int16_t, u_int16_t, u_int16_t));
++extern int ipsecdoi_normalize_id_uldata __P((vchar_t *, vchar_t *));
++extern int ipsecdoi_id_has_port __P((vchar_t *));
++
+ extern int ipsecdoi_id2sockaddr __P((vchar_t *, struct sockaddr *,
+ u_int8_t *, u_int16_t *));
+ extern char *ipsecdoi_id2str __P((const vchar_t *));
+Index: ipsec-tools-cvs-HEAD/src/racoon/ipsec_doi.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/ipsec_doi.c 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/ipsec_doi.c 2011-03-30 16:59:49.000000000 +0300
+@@ -3308,6 +3308,7 @@
+ const vchar_t *subnet;
+ const vchar_t *address;
+ {
++ struct in_addr *a, *b;
+ struct in_addr *mask;
+
+ if (address->l != sizeof(struct in_addr))
+@@ -3316,12 +3317,15 @@
+ if (subnet->l != (sizeof(struct in_addr)*2))
+ return 1;
+
++ a = (struct in_addr*)(subnet->v);
++ b = (struct in_addr*)(address->v);
+ mask = (struct in_addr*)(subnet->v + sizeof(struct in_addr));
+
+- if (mask->s_addr!=0xffffffff)
+- return 1;
++ //if (mask->s_addr!=0xffffffff)
++ // return 1;
++ //return memcmp(subnet->v,address->v,address->l);
+
+- return memcmp(subnet->v,address->v,address->l);
++ return (a->s_addr & mask->s_addr) != (b->s_addr & mask->s_addr);
+ }
+
+ #ifdef INET6
+@@ -3371,6 +3375,7 @@
+ vchar_t ident_t;
+ vchar_t ident_s;
+ int result;
++ int check_ports = 0;
+
+ /* handle wildcard IDs */
+
+@@ -3410,12 +3415,14 @@
+
+ if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR)&&
+ (id_bt->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)) {
++ check_ports = 1;
+ result = ipsecdoi_subnetisaddr_v4(&ident_t,&ident_s);
+ goto cmpid_result;
+ }
+
+ if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)&&
+ (id_bt->type == IPSECDOI_ID_IPV4_ADDR)) {
++ check_ports = 1;
+ result = ipsecdoi_subnetisaddr_v4(&ident_s,&ident_t);
+ goto cmpid_result;
+ }
+@@ -3423,12 +3430,14 @@
+ #ifdef INET6
+ if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR)&&
+ (id_bt->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
++ check_ports = 1;
+ result = ipsecdoi_subnetisaddr_v6(&ident_t,&ident_s);
+ goto cmpid_result;
+ }
+
+ if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)&&
+ (id_bt->type == IPSECDOI_ID_IPV6_ADDR)) {
++ check_ports = 1;
+ result = ipsecdoi_subnetisaddr_v6(&ident_s,&ident_t);
+ goto cmpid_result;
+ }
+@@ -3460,6 +3469,7 @@
+
+ case IPSECDOI_ID_IPV4_ADDR:
+ /* validate lengths */
++ check_ports = 1;
+ if ((ident_t.l != sizeof(struct in_addr))||
+ (ident_s.l != sizeof(struct in_addr)))
+ goto cmpid_invalid;
+@@ -3468,6 +3478,7 @@
+ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+ case IPSECDOI_ID_IPV4_ADDR_RANGE:
+ /* validate lengths */
++ check_ports = 1;
+ if ((ident_t.l != (sizeof(struct in_addr)*2))||
+ (ident_s.l != (sizeof(struct in_addr)*2)))
+ goto cmpid_invalid;
+@@ -3476,6 +3487,7 @@
+ #ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR:
+ /* validate lengths */
++ check_ports = 1;
+ if ((ident_t.l != sizeof(struct in6_addr))||
+ (ident_s.l != sizeof(struct in6_addr)))
+ goto cmpid_invalid;
+@@ -3484,6 +3496,7 @@
+ case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+ case IPSECDOI_ID_IPV6_ADDR_RANGE:
+ /* validate lengths */
++ check_ports = 1;
+ if ((ident_t.l != (sizeof(struct in6_addr)*2))||
+ (ident_s.l != (sizeof(struct in6_addr)*2)))
+ goto cmpid_invalid;
+@@ -3502,12 +3515,18 @@
+ }
+
+ /* validate matching data and length */
+- if (ident_t.l == ident_s.l)
+- result = memcmp(ident_t.v,ident_s.v,ident_t.l);
+- else
++ if (ident_t.l != ident_s.l)
+ result = 1;
++ else
++ result = memcmp(ident_t.v,ident_s.v,ident_t.l);
+
+ cmpid_result:
++ if (check_ports &&
++ (id_bt->port != id_bs->port && id_bs->port != 0)) {
++ /* if target is wildcard, source should be too, otherwise
++ * specific rule matches wildcard request */
++ result = 1;
++ }
+
+ /* debug level output */
+ if(loglevel >= LLV_DEBUG) {
+@@ -4089,6 +4108,67 @@
+ return new;
+ }
+
++int ipsecdoi_fixup_id_uldata(srcid, dstid, ul_proto, ul_data1, ul_data2)
++ vchar_t *srcid, *dstid;
++ u_int16_t ul_proto;
++ u_int16_t ul_data1, ul_data2;
++{
++ struct ipsecdoi_id_b *src = (struct ipsecdoi_id_b *) srcid->v;
++ struct ipsecdoi_id_b *dst = (struct ipsecdoi_id_b *) dstid->v;
++
++ if (src->proto_id != ul_proto ||
++ dst->proto_id != ul_proto)
++ return -1;
++
++ src->port = htons(ul_data1);
++ dst->port = htons(ul_data2);
++
++ return 0;
++}
++
++int ipsecdoi_normalize_id_uldata(srcid, dstid)
++ vchar_t *srcid, *dstid;
++{
++ struct ipsecdoi_id_b *src = (struct ipsecdoi_id_b *) srcid->v;
++ struct ipsecdoi_id_b *dst = (struct ipsecdoi_id_b *) dstid->v;
++ u_int16_t tmp;
++
++ if (src->proto_id != dst->proto_id)
++ return -1;
++
++ switch (src->proto_id) {
++ case IPPROTO_ICMP:
++ case IPPROTO_ICMPV6:
++ case IPPROTO_GRE:
++ tmp = src->port;
++ src->port = dst->port;
++ dst->port = tmp;
++ break;
++ }
++
++ return 0;
++}
++
++int ipsecdoi_id_has_port(id)
++ vchar_t *id;
++{
++ struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *) id->v;
++
++ switch (id_b->type) {
++ case IPSECDOI_ID_IPV4_ADDR:
++ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
++ case IPSECDOI_ID_IPV4_ADDR_RANGE:
++ case IPSECDOI_ID_IPV6_ADDR:
++ case IPSECDOI_ID_IPV6_ADDR_SUBNET:
++ case IPSECDOI_ID_IPV6_ADDR_RANGE:
++ if (ntohs(id_b->port) != 0)
++ return 1;
++ break;
++ }
++ return 0;
++}
++
++
+ vchar_t *
+ ipsecdoi_sockrange2id(laddr, haddr, ul_proto)
+ struct sockaddr *laddr, *haddr;
+@@ -4318,7 +4398,7 @@
+ saddr.sa.sa_len = sizeof(struct sockaddr_in);
+ #endif
+ saddr.sa.sa_family = AF_INET;
+- saddr.sin.sin_port = IPSEC_PORT_ANY;
++ saddr.sin.sin_port = id_b->port;
+ memcpy(&saddr.sin.sin_addr,
+ id->v + sizeof(*id_b), sizeof(struct in_addr));
+ break;
+@@ -4331,7 +4411,7 @@
+ saddr.sa.sa_len = sizeof(struct sockaddr_in6);
+ #endif
+ saddr.sa.sa_family = AF_INET6;
+- saddr.sin6.sin6_port = IPSEC_PORT_ANY;
++ saddr.sin6.sin6_port = id_b->port;
+ memcpy(&saddr.sin6.sin6_addr,
+ id->v + sizeof(*id_b), sizeof(struct in6_addr));
+ saddr.sin6.sin6_scope_id =
+@@ -4347,7 +4427,7 @@
+ #ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR:
+ #endif
+- len = snprintf( buf, BUFLEN, "%s", saddrwop2str(&saddr.sa));
++ len = snprintf( buf, BUFLEN, "%s", saddr2str(&saddr.sa));
+ break;
+
+ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+@@ -4403,7 +4483,9 @@
+ plen += l;
+ }
+
+- len = snprintf( buf, BUFLEN, "%s/%i", saddrwop2str(&saddr.sa), plen);
++ len = snprintf(buf, BUFLEN, "%s/%i[%d]",
++ saddrwop2str(&saddr.sa), plen,
++ ntohs(id_b->port));
+ }
+ break;
+
+@@ -4415,12 +4497,12 @@
+ saddr.sa.sa_len = sizeof(struct sockaddr_in);
+ #endif
+ saddr.sa.sa_family = AF_INET;
+- saddr.sin.sin_port = IPSEC_PORT_ANY;
++ saddr.sin.sin_port = id_b->port;
+ memcpy(&saddr.sin.sin_addr,
+ id->v + sizeof(*id_b) + sizeof(struct in_addr),
+ sizeof(struct in_addr));
+
+- len += snprintf(buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr.sa));
++ len += snprintf(buf + len, BUFLEN - len, "%s", saddr2str(&saddr.sa));
+ break;
+
+ #ifdef INET6
+@@ -4431,7 +4513,7 @@
+ saddr.sa.sa_len = sizeof(struct sockaddr_in6);
+ #endif
+ saddr.sa.sa_family = AF_INET6;
+- saddr.sin6.sin6_port = IPSEC_PORT_ANY;
++ saddr.sin6.sin6_port = id_b->port;
+ memcpy(&saddr.sin6.sin6_addr,
+ id->v + sizeof(*id_b) + sizeof(struct in6_addr),
+ sizeof(struct in6_addr));
+@@ -4440,7 +4522,7 @@
+ ? ((struct sockaddr_in6 *)id_b)->sin6_scope_id
+ : 0);
+
+- len += snprintf(buf + len, BUFLEN - len, "%s", saddrwop2str(&saddr.sa));
++ len += snprintf(buf + len, BUFLEN - len, "%s", saddr2str(&saddr.sa));
+ break;
+ #endif
+
+Index: ipsec-tools-cvs-HEAD/src/racoon/sainfo.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/sainfo.c 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/sainfo.c 2011-03-29 22:08:44.000000000 +0300
+@@ -124,7 +124,7 @@
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "evaluating sainfo: %s\n", sainfostr);
+
+- if(s->remoteid != remoteid) {
++ if (remoteid != -1 && s->remoteid != remoteid) {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "remoteid mismatch: %u != %u\n",
+ s->remoteid, remoteid);
+@@ -234,16 +234,22 @@
+ int pri = 0;
+
+ if(s->remoteid)
+- pri += 3;
++ pri += 7;
+
+ if(s->id_i)
+- pri += 3;
++ pri += 7;
+
+- if(s->idsrc)
++ if(s->idsrc) {
+ pri++;
++ if (ipsecdoi_id_has_port(s->idsrc))
++ pri += 2;
++ }
+
+- if(s->iddst)
++ if(s->iddst) {
+ pri++;
++ if (ipsecdoi_id_has_port(s->iddst))
++ pri += 2;
++ }
+
+ return pri;
+ }
+Index: ipsec-tools-cvs-HEAD/src/racoon/isakmp.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/isakmp.c 2011-03-14 19:18:12.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/isakmp.c 2011-03-30 09:41:46.000000000 +0300
+@@ -2173,7 +2173,15 @@
+ * so no need to bother yet. --arno */
+
+ if (iph1hint == NULL || iph1hint->rmconf == NULL) {
+- rmconf = getrmconf(iph2->dst, nopassive ? GETRMCONF_F_NO_PASSIVE : 0);
++ int flags = 0;
++ uint32_t remoteid;
++ if (nopassive)
++ flags |= GETRMCONF_F_NO_PASSIVE;
++ if (iph2->sainfo != NULL) {
++ flags |= GETRMCONF_F_HAS_REMOTEID;
++ remoteid = iph2->sainfo->remoteid;
++ }
++ rmconf = getrmconf(iph2->dst, flags, remoteid);
+ if (rmconf == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "no configuration found for %s.\n",
+@@ -2249,7 +2257,7 @@
+ struct secpolicy *sp_out, *sp_in;
+ {
+ struct remoteconf *conf;
+- uint32_t remoteid = 0;
++ uint32_t remoteid = -1;
+
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "new acquire %s\n", spidx2str(&sp_out->spidx));
+@@ -2276,7 +2284,7 @@
+ return -1;
+ }
+
+- conf = getrmconf(iph2->dst, 0);
++ conf = getrmconf(iph2->dst, 0, 0);
+ if (conf != NULL)
+ remoteid = conf->ph1id;
+ else
+@@ -3582,6 +3590,8 @@
+
+ #undef _XIDT
+
++ spidx_normalize_ulports(&spidx);
++
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "get a src address from ID payload "
+ "%s prefixlen=%u ul_proto=%u\n",
+@@ -3654,6 +3664,7 @@
+ pref = spidx.prefs;
+ spidx.prefs = spidx.prefd;
+ spidx.prefd = pref;
++ spidx_normalize_ulports(&spidx);
+
+ if (pk_sendspddelete(iph2) < 0) {
+ plog(LLV_ERROR, LOCATION, NULL,
+Index: ipsec-tools-cvs-HEAD/src/racoon/remoteconf.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/remoteconf.c 2011-03-14 19:12:41.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/remoteconf.c 2011-03-29 22:08:44.000000000 +0300
+@@ -217,6 +217,13 @@
+ return MATCH_NONE;
+ }
+
++ if ((rmsel->flags & GETRMCONF_F_HAS_REMOTEID) &&
++ rmsel->remoteid != rmconf->ph1id){
++ plog(LLV_DEBUG2, LOCATION, rmsel->remote,
++ "Not matched: remote_id did not match.\n");
++ return MATCH_NONE;
++ }
++
+ ret |= MATCH_BASIC;
+
+ /* Check address */
+@@ -387,9 +394,10 @@
+ */
+
+ struct remoteconf *
+-getrmconf(remote, flags)
++getrmconf(remote, flags, remoteid)
+ struct sockaddr *remote;
+ int flags;
++ uint32_t remoteid;
+ {
+ struct rmconf_find_context ctx;
+ int n = 0;
+@@ -397,6 +405,7 @@
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.sel.flags = flags;
+ ctx.sel.remote = remote;
++ ctx.sel.remoteid = remoteid;
+
+ if (enumrmconf(&ctx.sel, rmconf_find, &ctx) != 0) {
+ plog(LLV_ERROR, LOCATION, remote,
+Index: ipsec-tools-cvs-HEAD/src/racoon/remoteconf.h
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/remoteconf.h 2011-03-14 19:12:41.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/remoteconf.h 2011-03-29 22:08:44.000000000 +0300
+@@ -178,6 +178,7 @@
+ int flags;
+ struct sockaddr *remote;
+ int etype;
++ uint32_t remoteid;
+ struct isakmpsa *approval;
+ vchar_t *identity;
+ vchar_t *certificate_request;
+@@ -191,12 +192,13 @@
+
+ #define GETRMCONF_F_NO_ANONYMOUS 0x0001
+ #define GETRMCONF_F_NO_PASSIVE 0x0002
++#define GETRMCONF_F_HAS_REMOTEID 0x0004
+
+ #define RMCONF_ERR_MULTIPLE ((struct remoteconf *) -1)
+
+ extern int rmconf_match_identity __P((struct remoteconf *rmconf,
+ vchar_t *id_p));
+-extern struct remoteconf *getrmconf __P((struct sockaddr *remote, int flags));
++extern struct remoteconf *getrmconf __P((struct sockaddr *remote, int flags, uint32_t remoteid));
+ extern struct remoteconf *getrmconf_by_ph1 __P((struct ph1handle *iph1));
+ extern struct remoteconf *getrmconf_by_name __P((const char *name));
+
+Index: ipsec-tools-cvs-HEAD/src/racoon/pfkey.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/pfkey.c 2011-03-14 19:18:13.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/pfkey.c 2011-03-30 08:21:09.000000000 +0300
+@@ -1886,6 +1886,7 @@
+ spidx.prefs = sp_out->spidx.prefd;
+ spidx.prefd = sp_out->spidx.prefs;
+ spidx.ul_proto = sp_out->spidx.ul_proto;
++ spidx_normalize_ulports(&spidx);
+
+ #ifdef HAVE_SECCTX
+ if (m_sec_ctx) {
+@@ -2898,7 +2899,7 @@
+
+ /* If we are not acting as initiator, let's just leave and
+ * let the remote peer handle the restart */
+- rmconf = getrmconf(ma->remote, 0);
++ rmconf = getrmconf(ma->remote, 0, 0);
+ if (rmconf == NULL || !rmconf->passive) {
+ iph1->status = PHASE1ST_EXPIRED;
+ sched_schedule(&iph1->sce, 1, isakmp_ph1delete_stub);
+@@ -3068,8 +3069,10 @@
+
+ if (iph2->ph1 && iph2->ph1->rmconf)
+ rmconf = iph2->ph1->rmconf;
++ else if (iph2->sainfo != NULL)
++ rmconf = getrmconf(iph2->dst, GETRMCONF_F_HAS_REMOTEID, iph2->sainfo->remoteid);
+ else
+- rmconf = getrmconf(iph2->dst, 0);
++ rmconf = getrmconf(iph2->dst, 0, 0);
+
+ if (rmconf && !rmconf->passive) {
+ struct ph1handle *iph1hint;
+Index: ipsec-tools-cvs-HEAD/src/setkey/setkey.8
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/setkey/setkey.8 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/setkey/setkey.8 2011-03-29 22:08:44.000000000 +0300
+@@ -453,7 +453,7 @@
+ .Pp
+ A second example of requiring transport mode encryption of specific
+ GRE tunnel:
+-.Dl spdadd 0.0.0.0 0.0.0.0 gre 1234 ipsec esp/transport//require ;
++.Dl spdadd 0.0.0.0 0.0.0.0 gre 1234 -P in ipsec esp/transport//require ;
+ .Pp
+ .Em Note :
+ .Ar upperspec
+Index: ipsec-tools-cvs-HEAD/src/racoon/racoon.conf.5
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/racoon.conf.5 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/racoon.conf.5 2011-03-29 22:08:44.000000000 +0300
+@@ -981,6 +981,7 @@
+ .Bl -tag -width Ds -compact
+ .It Ic sainfo Po Ar local_id | Ic anonymous Pc \
+ Po Ar remote_id | Ic clientaddr | Ic anonymous Pc \
++Bo Ic grekey Ar key Bc \
+ Bo Ic from Ar idtype Bo Ar string Bc Bc Bo Ic group Ar string Bc \
+ Ic { Ar statements Ic }
+ Defines the parameters of the IKE phase 2 (IPsec-SA establishment).
+@@ -1026,6 +1027,15 @@
+ to restrict policy generation when racoon is acting as a client gateway
+ for peers with dynamic ip addresses.
+ .Pp
++If both
++.Ar local_id
++and
++.Ar remote_id
++are specified with GRE as upper layer protocol, the upper layer GRE
++key match can be specified with
++.Ic grekey
++.Ar key .
++.Pp
+ The
+ .Ic from
+ keyword allows an sainfo to only match for peers that use a specific phase1
+Index: ipsec-tools-cvs-HEAD/src/setkey/parse.y
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/setkey/parse.y 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/setkey/parse.y 2011-03-29 22:08:44.000000000 +0300
+@@ -856,6 +856,17 @@
+ }
+ $$.len = strlen($$.buf);
+ }
++ | DECSTRING
++ {
++ char tmp[16];
++ sprintf(tmp, "%lu", $1);
++ $$.buf = strdup(tmp);
++ if (!$$.buf) {
++ yyerror("insufficient memory");
++ return -1;
++ }
++ $$.len = strlen(tmp);
++ }
+ ;
+
+ context_spec
+Index: ipsec-tools-cvs-HEAD/src/racoon/racoonctl.8
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/racoonctl.8 2011-03-05 09:23:59.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/racoonctl.8 2011-03-29 22:08:44.000000000 +0300
+@@ -158,8 +158,8 @@
+ has the following format:
+ .Bl -tag -width Bl
+ .It isakmp {inet|inet6} Ar src Ar dst
+-.It {esp|ah} {inet|inet6} Ar src/prefixlen/port Ar dst/prefixlen/port
+-{icmp|tcp|udp|gre|any}
++.It {esp|ah} {inet|inet6} Ar src/prefixlen/port Ar dst/prefixlen/port \
++ {icmp|tcp|udp|gre|any} Oo grekey Ar key Oc
+ .El
+ .It vpn-connect Oo Fl u Ar username Oc Ar vpn_gateway
+ This is a particular case of the previous command.
+Index: ipsec-tools-cvs-HEAD/src/racoon/isakmp_quick.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/isakmp_quick.c 2011-03-29 22:18:12.000000000 +0300
++++ ipsec-tools-cvs-HEAD/src/racoon/isakmp_quick.c 2011-03-30 09:23:13.000000000 +0300
+@@ -2168,6 +2168,8 @@
+ goto end;
+ }
+
++ ipsecdoi_normalize_id_uldata(idsrc, iddst);
++
+ #ifdef ENABLE_HYBRID
+
+ /* clientaddr check : obtain modecfg address */
+@@ -2494,6 +2496,7 @@
+ pref = spidx.prefs;
+ spidx.prefs = spidx.prefd;
+ spidx.prefd = pref;
++ spidx_normalize_ulports(&spidx);
+
+ sp_out = getsp_r(&spidx);
+ if (!sp_out) {
+Index: ipsec-tools-cvs-HEAD/src/racoon/policy.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/policy.c 2011-03-30 08:03:15.000000000 +0300
++++ ipsec-tools-cvs-HEAD/src/racoon/policy.c 2011-03-30 08:05:23.000000000 +0300
+@@ -444,6 +444,25 @@
+ return new;
+ }
+
++void
++spidx_normalize_ulports(spidx)
++ struct policyindex *spidx;
++{
++ u_int16_t tmp;
++
++ switch (spidx->ul_proto) {
++ case IPPROTO_ICMP:
++ case IPPROTO_ICMPV6:
++ case IPPROTO_GRE:
++ /* Ports are UL specific data, and should not get swapped */
++ tmp = extract_port((struct sockaddr *) &spidx->src);
++ set_port((struct sockaddr *) &spidx->src,
++ extract_port((struct sockaddr *) &spidx->dst));
++ set_port((struct sockaddr *) &spidx->dst, tmp);
++ break;
++ }
++}
++
+ const char *
+ spidx2str(spidx)
+ const struct policyindex *spidx;
+Index: ipsec-tools-cvs-HEAD/src/racoon/policy.h
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/policy.h 2011-03-30 08:15:44.000000000 +0300
++++ ipsec-tools-cvs-HEAD/src/racoon/policy.h 2011-03-30 08:16:21.000000000 +0300
+@@ -156,6 +156,7 @@
+ extern void flushsp __P((void));
+ extern void initsp __P((void));
+ extern struct ipsecrequest *newipsecreq __P((void));
++extern void spidx_normalize_ulports __P((struct policyindex *));
+
+ extern const char *spidx2str __P((const struct policyindex *));
+ #ifdef HAVE_SECCTX
diff --git a/main/ipsec-tools/50-reverse-connect.patch b/main/ipsec-tools/50-reverse-connect.patch
new file mode 100644
index 0000000000..54e77a3976
--- /dev/null
+++ b/main/ipsec-tools/50-reverse-connect.patch
@@ -0,0 +1,197 @@
+When new ISAKMP is required, allow incoming reverse connection to take
+
+From: Timo Teras <timo.teras@iki.fi>
+
+over pending phase1:s. Useful when the other party is firewalled or NATted.
+---
+
+ src/racoon/admin.c | 12 ++++++++++++
+ src/racoon/evt.c | 13 +++++++++++++
+ src/racoon/evt.h | 3 +++
+ src/racoon/handler.c | 28 +++++++++++++++++++++-------
+ src/racoon/isakmp.c | 39 ++++++++++++++++++++++++++++++++++-----
+ 5 files changed, 83 insertions(+), 12 deletions(-)
+
+
+Index: ipsec-tools-cvs-HEAD/src/racoon/admin.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/admin.c 2011-03-03 21:16:47.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/admin.c 2011-03-04 13:50:30.000000000 +0200
+@@ -414,11 +414,23 @@
+ struct sockaddr *dst;
+ struct sockaddr *src;
+ char *name = NULL;
++ char *loc, *rem;
+
+ ndx = (struct admin_com_indexes *) ((caddr_t)com + sizeof(*com));
+ src = (struct sockaddr *) &ndx->src;
+ dst = (struct sockaddr *) &ndx->dst;
+
++ loc = racoon_strdup(saddr2str(src));
++ rem = racoon_strdup(saddr2str(dst));
++ STRDUP_FATAL(loc);
++ STRDUP_FATAL(rem);
++
++ plog(LLV_INFO, LOCATION, NULL,
++ "admin establish-sa %x %s %s\n",
++ com->ac_proto, loc, rem);
++ racoon_free(loc);
++ racoon_free(rem);
++
+ if (com->ac_cmd == ADMIN_ESTABLISH_SA &&
+ com->ac_len > sizeof(*com) + sizeof(*ndx))
+ name = (char *) ((caddr_t) ndx + sizeof(*ndx));
+Index: ipsec-tools-cvs-HEAD/src/racoon/evt.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/evt.c 2011-03-03 19:25:50.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/evt.c 2011-03-04 13:50:30.000000000 +0200
+@@ -396,4 +396,17 @@
+ evt_unsubscribe(LIST_FIRST(list));
+ }
+
++void
++evt_list_move(from, to)
++ struct evt_listener_list *from, *to;
++{
++ struct evt_listener *l;
++
++ while (!LIST_EMPTY(from)) {
++ l = LIST_FIRST(from);
++ LIST_REMOVE(l, ll_chain);
++ LIST_INSERT_HEAD(to, l, ll_chain);
++ }
++}
++
+ #endif /* ENABLE_ADMINPORT */
+Index: ipsec-tools-cvs-HEAD/src/racoon/evt.h
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/evt.h 2011-03-03 19:25:50.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/evt.h 2011-03-04 13:50:30.000000000 +0200
+@@ -124,6 +124,8 @@
+ vchar_t *evt_dump __P((void));
+
+ int evt_subscribe __P((struct evt_listener_list *list, int fd));
++void evt_list_move __P((struct evt_listener_list *from,
++ struct evt_listener_list *to));
+ void evt_list_init __P((struct evt_listener_list *list));
+ void evt_list_cleanup __P((struct evt_listener_list *list));
+
+@@ -136,6 +138,7 @@
+ #define evt_phase2(ph2, type, optdata) ;
+
+ #define evt_subscribe(eventlist, fd) ;
++#deifne evt_list_move(from, to) ;
+ #define evt_list_init(eventlist) ;
+ #define evt_list_cleanup(eventlist) ;
+ #define evt_get_fdmask(nfds, fdset) nfds
+Index: ipsec-tools-cvs-HEAD/src/racoon/handler.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/handler.c 2011-03-03 19:29:31.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/handler.c 2011-03-04 13:53:01.000000000 +0200
+@@ -292,17 +292,32 @@
+ void migrate_dying_ph12(iph1)
+ struct ph1handle *iph1;
+ {
+- struct ph1handle *p;
++ struct ph1handle *p, *next;
+
+- LIST_FOREACH(p, &ph1tree, chain) {
++ for (p = LIST_FIRST(&ph1tree); p; p = next) {
++ next = LIST_NEXT(p, chain);
+ if (p == iph1)
+ continue;
+- if (p->status < PHASE1ST_DYING)
++
++ /* Same remote? */
++ if (cmpsaddr(iph1->local, p->local) > CMPSADDR_WOP_MATCH ||
++ cmpsaddr(iph1->remote, p->remote) > CMPSADDR_WOP_MATCH ||
++ iph1->rmconf != p->rmconf)
+ continue;
+
+- if (cmpsaddr(iph1->local, p->local) == CMPSADDR_MATCH
+- && cmpsaddr(iph1->remote, p->remote) == CMPSADDR_MATCH)
++ /* migrate phase2:s from expiring entries */
++ if (p->status >= PHASE1ST_DYING)
+ migrate_ph12(p, iph1);
++
++ /* and allow reverse connections to release
++ * pending connections that do not work due
++ * to firewall or nat */
++ if (iph1->side == RESPONDER && p->side == INITIATOR &&
++ p->status < PHASE1ST_MSG3RECEIVED) {
++ /* Do not delete ph1, since if the node is not NATted,
++ * and we delete it we might get phase2's lost */
++ evt_list_move(&p->evt_listeners, &iph1->evt_listeners);
++ }
+ }
+ }
+
+Index: ipsec-tools-cvs-HEAD/src/racoon/isakmp.c
+===================================================================
+--- ipsec-tools-cvs-HEAD.orig/src/racoon/isakmp.c 2011-03-03 21:14:13.000000000 +0200
++++ ipsec-tools-cvs-HEAD/src/racoon/isakmp.c 2011-03-04 13:50:30.000000000 +0200
+@@ -2138,13 +2138,33 @@
+
+ remph2(iph2);
+ delph2(iph2);
+-
+- return;
+ }
+
+ /* %%%
+ * Interface between PF_KEYv2 and ISAKMP
+ */
++
++static void
++isakmp_chkph2there(p)
++ struct sched *p;
++{
++ struct ph2handle *iph2 = container_of(p, struct ph2handle, sce);
++ struct ph2handle *tmp;
++
++ /* Check if a similar phase2 appared meanwhile */
++ remph2(iph2);
++ tmp = getph2byid(iph2->src, iph2->dst, iph2->spid);
++ if (tmp == NULL) {
++ /* Nope, lets start this then */
++ insph2(iph2);
++ isakmp_chkph1there(iph2);
++ } else {
++ /* Yes, delete this initiation attempt as redundant */
++ evt_phase2(iph2, EVT_PHASE2_UP, NULL);
++ delph2(iph2);
++ }
++}
++
+ /*
+ * receive ACQUIRE from kernel, and begin either phase1 or phase2.
+ * if phase1 has been finished, begin phase2.
+@@ -2235,8 +2255,14 @@
+ /*NOTREACHED*/
+ }
+
+- /* found established ISAKMP-SA */
+- /* i.e. iph1->status == PHASE1ST_ESTABLISHED */
++ /* found established ISAKMP-SA, if this is a RESPONDER ISAKMP-SA
++ * add a small delay; this will make sure the initiator gets
++ * an first attempt at rekeying, and usually avoids duplicate ph2:s */
++ if (iph1->side == RESPONDER) {
++ iph2->retry_checkph1 = 1;
++ sched_schedule(&iph2->sce, 1, isakmp_chkph2there);
++ return 0;
++ }
+
+ /* found ISAKMP-SA. */
+ plog(LLV_DEBUG, LOCATION, NULL, "begin QUICK mode.\n");
+@@ -2403,7 +2429,10 @@
+ plog(LLV_DEBUG2, LOCATION, NULL, "dst: %s\n", saddr2str(iph2->dst));
+
+ /* begin quick mode */
+- (void)isakmp_ph2begin_i(iph1, iph2);
++ if (isakmp_ph2begin_i(iph1, iph2)) {
++ remph2(iph2);
++ delph2(iph2);
++ }
+ return;
+ }
+
diff --git a/main/ipsec-tools/70-defer-isakmp-ident-handling.patch b/main/ipsec-tools/70-defer-isakmp-ident-handling.patch
new file mode 100644
index 0000000000..9be37aa154
--- /dev/null
+++ b/main/ipsec-tools/70-defer-isakmp-ident-handling.patch
@@ -0,0 +1,179 @@
+Index: src/racoon/isakmp.c
+===================================================================
+RCS file: /cvsroot/src/crypto/dist/ipsec-tools/src/racoon/isakmp.c,v
+retrieving revision 1.63
+diff -u -r1.63 isakmp.c
+--- a/src/racoon/isakmp.c 21 Oct 2010 06:15:28 -0000 1.63
++++ b/src/racoon/isakmp.c 29 Oct 2010 10:51:28 -0000
+@@ -130,6 +130,10 @@
+ # define SOL_UDP IPPROTO_UDP
+ # endif /* __NetBSD__ / __FreeBSD__ */
+
++vchar_t *postponed_buf;
++struct sockaddr_storage postponed_remote;
++struct sockaddr_storage postponed_local;
++
+ static int nostate1 __P((struct ph1handle *, vchar_t *));
+ static int nostate2 __P((struct ph2handle *, vchar_t *));
+
+@@ -177,7 +181,7 @@
+
+ static u_char r_ck0[] = { 0,0,0,0,0,0,0,0 }; /* used to verify the r_ck. */
+
+-static int isakmp_main __P((vchar_t *, struct sockaddr *, struct sockaddr *));
++/* static int isakmp_main __P((vchar_t *, struct sockaddr *, struct sockaddr *)); */
+ static int ph1_main __P((struct ph1handle *, vchar_t *));
+ static int quick_main __P((struct ph2handle *, vchar_t *));
+ static int isakmp_ph1begin_r __P((vchar_t *,
+@@ -374,10 +378,17 @@
+ }
+
+ /* isakmp main routine */
+- if (isakmp_main(buf, (struct sockaddr *)&remote,
+- (struct sockaddr *)&local) != 0) goto end;
+-
+- error = 0;
++ res = isakmp_main(buf, (struct sockaddr *)&remote,
++ (struct sockaddr *)&local);
++ if (res == 0) {
++ error = 0;
++ } else if (res == -42424 && postponed_buf == NULL) {
++ postponed_buf = buf;
++ postponed_remote = remote;
++ postponed_local = local;
++ buf = NULL;
++ error = 0;
++ }
+
+ end:
+ if (tmpbuf != NULL)
+@@ -390,7 +401,7 @@
+ /*
+ * main processing to handle isakmp payload
+ */
+-static int
++int
+ isakmp_main(msg, remote, local)
+ vchar_t *msg;
+ struct sockaddr *remote, *local;
+@@ -399,6 +410,7 @@
+ isakmp_index *index = (isakmp_index *)isakmp;
+ u_int32_t msgid = isakmp->msgid;
+ struct ph1handle *iph1;
++ int rc;
+
+ #ifdef HAVE_PRINT_ISAKMP_C
+ isakmp_printpacket(msg, remote, local, 0);
+@@ -604,12 +616,14 @@
+ #endif
+
+ /* call main process of phase 1 */
+- if (ph1_main(iph1, msg) < 0) {
+- plog(LLV_ERROR, LOCATION, iph1->remote,
+- "phase1 negotiation failed.\n");
+- remph1(iph1);
+- delph1(iph1);
+- return -1;
++ if ((rc=ph1_main(iph1, msg)) < 0) {
++ if (rc != -42424) {
++ plog(LLV_ERROR, LOCATION, iph1->remote,
++ "phase1 negotiation failed.\n");
++ remph1(iph1);
++ delph1(iph1);
++ }
++ return rc;
+ }
+ break;
+
+@@ -813,10 +827,11 @@
+ "failed to pre-process ph1 packet (side: %d, status %d).\n",
+ iph1->side, iph1->status);
+ return -1;
+- } else {
+- /* ignore the error and keep phase 1 handler */
+- return 0;
+ }
++ if (error == -42424)
++ return error;
++ /* ignore the error and keep phase 1 handler */
++ return 0;
+ }
+
+ #ifndef ENABLE_FRAG
+Index: src/racoon/isakmp_ident.c
+===================================================================
+RCS file: /cvsroot/src/crypto/dist/ipsec-tools/src/racoon/isakmp_ident.c,v
+retrieving revision 1.13
+diff -u -r1.13 isakmp_ident.c
+--- a/src/racoon/isakmp_ident.c 18 Sep 2009 10:31:11 -0000 1.13
++++ b/src/racoon/isakmp_ident.c 29 Oct 2010 10:51:29 -0000
+@@ -1128,6 +1128,11 @@
+ goto end;
+ }
+
++ if (postponed_buf != msg) {
++ error = -42424;
++ goto end;
++ }
++
+ /* validate the type of next payload */
+ pbuf = isakmp_parse(msg);
+ if (pbuf == NULL)
+Index: src/racoon/isakmp_var.h
+===================================================================
+RCS file: /cvsroot/src/crypto/dist/ipsec-tools/src/racoon/isakmp_var.h,v
+retrieving revision 1.16
+diff -u -r1.16 isakmp_var.h
+--- a/src/racoon/isakmp_var.h 3 Sep 2009 09:29:07 -0000 1.16
++++ b/src/racoon/isakmp_var.h 29 Oct 2010 10:51:29 -0000
+@@ -141,4 +141,10 @@
+ u_int32_t setscopeid __P((struct sockaddr *, struct sockaddr *));
+ #endif
+
++int isakmp_main __P((vchar_t *, struct sockaddr *, struct sockaddr *));
++
++extern vchar_t *postponed_buf;
++extern struct sockaddr_storage postponed_remote;
++extern struct sockaddr_storage postponed_local;
++
+ #endif /* _ISAKMP_VAR_H */
+Index: src/racoon/session.c
+===================================================================
+RCS file: /cvsroot/src/crypto/dist/ipsec-tools/src/racoon/session.c,v
+retrieving revision 1.28
+diff -u -r1.28 session.c
+--- a/src/racoon/session.c 21 Oct 2010 06:15:28 -0000 1.28
++++ b/src/racoon/session.c 29 Oct 2010 10:51:29 -0000
+@@ -172,7 +172,7 @@
+ int
+ session(void)
+ {
+- struct timeval *timeout;
++ struct timeval *timeout, to_zero = { 0, 0 };
+ int error;
+ char pid_file[MAXPATHLEN];
+ FILE *fp;
+@@ -295,6 +295,8 @@
+
+ /* scheduling */
+ timeout = schedular();
++ if (postponed_buf != NULL)
++ timeout = &to_zero;
+
+ /* schedular can change select() mask, so we reset
+ * the working copy here */
+@@ -332,6 +334,14 @@
+ break;
+ }
+
++ if (count == 0 && postponed_buf != NULL) {
++ (void) isakmp_main(
++ postponed_buf,
++ (struct sockaddr *) &postponed_remote,
++ (struct sockaddr *) &postponed_local);
++ vfree(postponed_buf);
++ postponed_buf = NULL;
++ }
+ }
+ }
+
diff --git a/main/ipsec-tools/75-racoonctl-rcvbuf.patch b/main/ipsec-tools/75-racoonctl-rcvbuf.patch
new file mode 100644
index 0000000000..3a68bfc2ae
--- /dev/null
+++ b/main/ipsec-tools/75-racoonctl-rcvbuf.patch
@@ -0,0 +1,33 @@
+Index: src/racoon/kmpstat.c
+===================================================================
+RCS file: /cvsroot/src/crypto/dist/ipsec-tools/src/racoon/kmpstat.c,v
+retrieving revision 1.6
+diff -u -r1.6 kmpstat.c
+--- a/src/racoon/kmpstat.c 2 Oct 2007 09:47:45 -0000 1.6
++++ b/src/racoon/kmpstat.c 14 Oct 2010 12:48:22 -0000
+@@ -99,6 +99,7 @@
+ com_init()
+ {
+ struct sockaddr_un name;
++ int rcvSize;
+
+ memset(&name, 0, sizeof(name));
+ name.sun_family = AF_UNIX;
+@@ -114,6 +115,17 @@
+ return -1;
+ }
+
++ /* set receive buffer size - should be relative large:
++ * racoon daemon will try to send all info in one go, if
++ * it does not fit we'll miss stuff */
++ rcvSize = 1024 * 1024;
++ if (setsockopt(so, SOL_SOCKET, SO_RCVBUF,
++ (void*) &rcvSize, sizeof(rcvSize)) < 0) {
++ rcvSize = 512 * 1024;
++ (void) setsockopt(so, SOL_SOCKET, SO_RCVBUF,
++ (void*) &rcvSize, sizeof(rcvSize));
++ }
++
+ return 0;
+ }
+
diff --git a/main/ipsec-tools/APKBUILD b/main/ipsec-tools/APKBUILD
new file mode 100644
index 0000000000..99804bce51
--- /dev/null
+++ b/main/ipsec-tools/APKBUILD
@@ -0,0 +1,65 @@
+# Maintainer: Natanael Copa <ncopa@alpinelinux.org>
+pkgname=ipsec-tools
+pkgver=0.8.0
+pkgrel=3
+pkgdesc="User-space IPsec tools for various IPsec implementations"
+url="http://ipsec-tools.sourceforge.net/"
+arch="all"
+license="BSD"
+depends=""
+makedepends="openssl-dev bison flex"
+subpackages="$pkgname-doc $pkgname-dev"
+source="http://downloads.sourceforge.net/$pkgname/$pkgname-$pkgver.tar.gz
+ racoon.initd
+ racoon.confd
+ 20-grekey-support.patch
+ 50-reverse-connect.patch
+ 70-defer-isakmp-ident-handling.patch
+ 75-racoonctl-rcvbuf.patch
+ "
+
+_builddir="$srcdir"/$pkgname-$pkgver
+prepare() {
+ cd "$_builddir"
+ for i in ../*.patch; do
+ msg "Applying $i..."
+ patch -p1 -i $i || return 1
+ done
+
+ sed -i 's:-Werror::g' configure
+}
+
+build() {
+ cd "$_builddir"
+ ./configure --prefix=/usr \
+ --sysconfdir=/etc \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --localstatedir=/var/lib \
+ --with-kernel-headers=/usr/include \
+ --disable-security-context \
+ --enable-adminport \
+ --enable-dpd \
+ --enable-frag \
+ --enable-hybrid \
+ --enable-ipv6 \
+ --enable-natt
+ make || return 1
+}
+
+package() {
+ cd "$_builddir"
+ make DESTDIR="$pkgdir" install
+ rm "$pkgdir"/usr/lib/*.la
+
+ install -D -m755 ../racoon.initd "$pkgdir"/etc/init.d/racoon
+ install -D -m644 ../racoon.confd "$pkgdir"/etc/conf.d/racoon
+}
+
+md5sums="c9a318cdbc0946f4e51464866d529739 ipsec-tools-0.8.0.tar.gz
+74f12ed04ed273a738229c0bfbf829cc racoon.initd
+2d00250cf72da7f2f559c91b65a48747 racoon.confd
+79b919ab23080f54dc3e7686877ca6bd 20-grekey-support.patch
+f97205eea3dc68d2437a2ad8720f4520 50-reverse-connect.patch
+94773c94233e14cdce0fa02ff780a43e 70-defer-isakmp-ident-handling.patch
+2d5d24c4a3684a38584f88720f71c7d6 75-racoonctl-rcvbuf.patch"
diff --git a/main/ipsec-tools/racoon.confd b/main/ipsec-tools/racoon.confd
new file mode 100644
index 0000000000..bf9926c5b5
--- /dev/null
+++ b/main/ipsec-tools/racoon.confd
@@ -0,0 +1,20 @@
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-firewall/ipsec-tools/files/racoon.conf.d,v 1.3 2004/07/14 23:29:57 agriffis Exp $
+
+# Config file for /etc/init.d/racoon
+
+# See the manual pages for racoon or run `racoon --help`
+# for valid command-line options
+
+RACOON_OPTS="-4"
+SETKEY_OPTS=""
+
+RACOON_CONF="/etc/racoon/racoon.conf"
+RACOON_PSK_FILE="/etc/racoon/psk.txt"
+SETKEY_CONF="/etc/ipsec.conf"
+
+# Comment or remove the following if you don't want the policy tables
+# to be flushed when racoon is stopped.
+
+RACOON_RESET_TABLES="true"
diff --git a/main/ipsec-tools/racoon.initd b/main/ipsec-tools/racoon.initd
new file mode 100644
index 0000000000..724eee0237
--- /dev/null
+++ b/main/ipsec-tools/racoon.initd
@@ -0,0 +1,60 @@
+#!/sbin/runscript
+# Copyright 1999-2004 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+depend() {
+ before netmount
+ use net
+ after firewall ntp-client
+ provide ipsec
+}
+
+checkconfig() {
+ if [ ! -e ${SETKEY_CONF} ] ; then
+ eerror "You need to configure setkey before starting racoon."
+ return 1
+ fi
+ if [ ! -e ${RACOON_CONF} ] ; then
+ eerror "You need a configuration file to start racoon."
+ return 1
+ fi
+ if [ ! -z ${RACOON_PSK_FILE} ] ; then
+ if [ ! -f ${RACOON_PSK_FILE} ] ; then
+ eerror "PSK file not found as specified."
+ eerror "Set RACOON_PSK_FILE in /etc/conf.d/racoon."
+ return 1
+ fi
+ case "`ls -Lldn ${RACOON_PSK_FILE}`" in
+ -r--------*)
+ ;;
+ *)
+ eerror "Your defined PSK file should be mode 400 for security!"
+ return 1
+ ;;
+ esac
+ fi
+}
+
+start() {
+ checkconfig || return 1
+ einfo "Loading ipsec policies from ${SETKEY_CONF}."
+ /usr/sbin/setkey ${SETKEY_OPTS} -f ${SETKEY_CONF}
+ if [ $? -eq 1 ] ; then
+ eerror "Error while loading ipsec policies"
+ fi
+ ebegin "Starting racoon"
+ start-stop-daemon -S -x /usr/sbin/racoon -- -f ${RACOON_CONF} ${RACOON_OPTS}
+ eend $?
+}
+
+stop() {
+ ebegin "Stopping racoon"
+ start-stop-daemon -K -p /var/run/racoon.pid
+ eend $?
+ if [ -n "${RACOON_RESET_TABLES}" ]; then
+ ebegin "Flushing policy entries"
+ /usr/sbin/setkey -F
+ /usr/sbin/setkey -FP
+ eend $?
+ fi
+}