Hi,

The diff below bring into iked the same nat capabilities that isakmpd
already has.

Tested on a daily basis to tunnel from work to home over UMTS.

Comments ?

--
Vincent Gross


Index: iked.h
===================================================================
RCS file: /cvs/src/sbin/iked/iked.h,v
retrieving revision 1.83
diff -u -p -r1.83 iked.h
--- iked.h      16 Jan 2015 06:39:58 -0000      1.83
+++ iked.h      17 Mar 2015 21:51:33 -0000
@@ -140,6 +140,8 @@ struct iked_flow {
        struct iked_addr                 flow_src;
        struct iked_addr                 flow_dst;
        u_int                            flow_dir;      /* in/out */
+       struct iked_addr                 flow_prenat;   /* pre-nat source */
+       u_int                            flow_usenat;
 
        u_int                            flow_loaded;   /* pfkey done */
 
Index: parse.y
===================================================================
RCS file: /cvs/src/sbin/iked/parse.y,v
retrieving revision 1.46
diff -u -p -r1.46 parse.y
--- parse.y     8 Feb 2015 04:50:32 -0000       1.46
+++ parse.y     17 Mar 2015 21:51:38 -0000
@@ -2401,7 +2401,7 @@ create_ike(char *name, int af, u_int8_t 
 {
        char                     idstr[IKED_ID_SIZE];
        u_int                    idtype = IKEV2_ID_NONE;
-       struct ipsec_addr_wrap  *ipa, *ipb;
+       struct ipsec_addr_wrap  *ipa, *ipb, *ipn;
        struct iked_policy       pol;
        struct iked_proposal     prop[2];
        u_int                    j;
@@ -2622,6 +2622,16 @@ create_ike(char *name, int af, u_int8_t 
                flows[j].flow_dst.addr_mask = ipb->mask;
                flows[j].flow_dst.addr_net = ipb->netaddress;
                flows[j].flow_dst.addr_port = hosts->dport;
+
+               ipn = ipa->srcnat;
+               if (ipn) {
+                       memcpy(&flows[j].flow_prenat.addr, &ipn->address,
+                           sizeof(ipn->address));
+                       flows[j].flow_prenat.addr_af = ipn->af;
+                       flows[j].flow_prenat.addr_mask = ipn->mask;
+                       flows[j].flow_prenat.addr_net = ipn->netaddress;
+                       flows[j].flow_usenat = 1;
+               }
 
                flows[j].flow_ipproto = ipproto;
 
Index: pfkey.c
===================================================================
RCS file: /cvs/src/sbin/iked/pfkey.c,v
retrieving revision 1.41
diff -u -p -r1.41 pfkey.c
--- pfkey.c     16 Jan 2015 06:39:58 -0000      1.41
+++ pfkey.c     17 Mar 2015 21:51:39 -0000
@@ -179,6 +179,7 @@ int
 pfkey_flow(int sd, u_int8_t satype, u_int8_t action, struct iked_flow *flow)
 {
        struct sadb_msg          smsg;
+       struct iked_addr        *flow_src, *flow_dst;
        struct sadb_address      sa_src, sa_dst, sa_local, sa_peer, sa_smask,
                                 sa_dmask;
        struct sadb_protocol     sa_flowtype, sa_protocol;
@@ -191,58 +192,76 @@ pfkey_flow(int sd, u_int8_t satype, u_in
        sport = dport = 0;
        sa_srcid = sa_dstid = NULL;
 
+       flow_src = &flow->flow_src;
+       flow_dst = &flow->flow_dst;
+
+       if (flow->flow_usenat)
+               switch (flow->flow_type) {
+               case SADB_X_FLOW_TYPE_USE:
+                       flow_dst = &flow->flow_prenat;
+                       break;
+               case SADB_X_FLOW_TYPE_REQUIRE:
+                       flow_src = &flow->flow_prenat;
+                       break;
+               case 0:
+                       if (flow->flow_dir == IPSP_DIRECTION_IN)
+                               flow_dst = &flow->flow_prenat;
+                       else
+                               flow_src = &flow->flow_prenat;
+               }
+
        bzero(&ssrc, sizeof(ssrc));
        bzero(&smask, sizeof(smask));
-       memcpy(&ssrc, &flow->flow_src.addr, sizeof(ssrc));
-       memcpy(&smask, &flow->flow_src.addr, sizeof(smask));
-       if ((sport = flow->flow_src.addr_port) != 0)
+       memcpy(&ssrc, &flow_src->addr, sizeof(ssrc));
+       memcpy(&smask, &flow_src->addr, sizeof(smask));
+       if ((sport = flow_src->addr_port) != 0)
                dport = 0xffff;
        socket_af((struct sockaddr *)&ssrc, sport);
        socket_af((struct sockaddr *)&smask, dport);
 
-       switch (flow->flow_src.addr_af) {
+       switch (flow_src->addr_af) {
        case AF_INET:
                ((struct sockaddr_in *)&smask)->sin_addr.s_addr =
-                   prefixlen2mask(flow->flow_src.addr_net ?
-                   flow->flow_src.addr_mask : 32);
+                   prefixlen2mask(flow_src->addr_net ?
+                   flow_src->addr_mask : 32);
                break;
        case AF_INET6:
-               prefixlen2mask6(flow->flow_src.addr_net ?
-                   flow->flow_src.addr_mask : 128,
+               prefixlen2mask6(flow_src->addr_net ?
+                   flow_src->addr_mask : 128,
                    (u_int32_t *)((struct sockaddr_in6 *)
                    &smask)->sin6_addr.s6_addr);
                break;
        default:
                log_warnx("%s: unsupported address family %d",
-                   __func__, flow->flow_src.addr_af);
+                   __func__, flow_src->addr_af);
                return (-1);
        }
        smask.ss_len = ssrc.ss_len;
 
        bzero(&sdst, sizeof(sdst));
        bzero(&dmask, sizeof(dmask));
-       memcpy(&sdst, &flow->flow_dst.addr, sizeof(sdst));
-       memcpy(&dmask, &flow->flow_dst.addr, sizeof(dmask));
-       if ((sport = flow->flow_dst.addr_port) != 0)
+       memcpy(&sdst, &flow_dst->addr, sizeof(sdst));
+       memcpy(&dmask, &flow_dst->addr, sizeof(dmask));
+       if ((sport = flow_dst->addr_port) != 0)
                dport = 0xffff;
        socket_af((struct sockaddr *)&sdst, sport);
        socket_af((struct sockaddr *)&dmask, dport);
 
-       switch (flow->flow_dst.addr_af) {
+       switch (flow_dst->addr_af) {
        case AF_INET:
                ((struct sockaddr_in *)&dmask)->sin_addr.s_addr =
-                   prefixlen2mask(flow->flow_dst.addr_net ?
-                   flow->flow_dst.addr_mask : 32);
+                   prefixlen2mask(flow_dst->addr_net ?
+                   flow_dst->addr_mask : 32);
                break;
        case AF_INET6:
-               prefixlen2mask6(flow->flow_dst.addr_net ?
-                   flow->flow_dst.addr_mask : 128,
+               prefixlen2mask6(flow_dst->addr_net ?
+                   flow_dst->addr_mask : 128,
                    (u_int32_t *)((struct sockaddr_in6 *)
                    &dmask)->sin6_addr.s6_addr);
                break;
        default:
                log_warnx("%s: unsupported address family %d",
-                   __func__, flow->flow_dst.addr_af);
+                   __func__, flow_dst->addr_af);
                return (-1);
        }
        dmask.ss_len = sdst.ss_len;

Attachment: pgpNnI4Qr8dDm.pgp
Description: PGP signature

Reply via email to