diff options
author | Vincent Gross <vgross@cvs.openbsd.org> | 2016-09-03 09:20:08 +0000 |
---|---|---|
committer | Vincent Gross <vgross@cvs.openbsd.org> | 2016-09-03 09:20:08 +0000 |
commit | 831e8b66e17bcba92ec8600935c13295b89877f6 (patch) | |
tree | e9f1f58950d10aaea47ad9115875971ebe415783 /sbin | |
parent | f6883df8590c3f9d608fd7dd2432689c14121507 (diff) |
Add the missing bits to have NAT on enc(4) support in iked.
Ok mikeb@
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/iked/iked.h | 3 | ||||
-rw-r--r-- | sbin/iked/parse.y | 15 | ||||
-rw-r--r-- | sbin/iked/pfkey.c | 62 |
3 files changed, 56 insertions, 24 deletions
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h index 1c13cb960cb..6a6a3885bf2 100644 --- a/sbin/iked/iked.h +++ b/sbin/iked/iked.h @@ -1,4 +1,4 @@ -/* $OpenBSD: iked.h,v 1.96 2016/06/01 11:16:41 patrick Exp $ */ +/* $OpenBSD: iked.h,v 1.97 2016/09/03 09:20:07 vgross Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -140,6 +140,7 @@ struct iked_flow { struct iked_addr flow_src; struct iked_addr flow_dst; unsigned int flow_dir; /* in/out */ + struct iked_addr flow_prenat; unsigned int flow_loaded; /* pfkey done */ diff --git a/sbin/iked/parse.y b/sbin/iked/parse.y index c93a97874d2..bbf63e0353d 100644 --- a/sbin/iked/parse.y +++ b/sbin/iked/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.57 2016/08/06 07:08:59 pascal Exp $ */ +/* $OpenBSD: parse.y,v 1.58 2016/09/03 09:20:07 vgross Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -2418,7 +2418,7 @@ create_ike(char *name, int af, uint8_t ipproto, struct ipsec_hosts *hosts, { char idstr[IKED_ID_SIZE]; unsigned int idtype = IKEV2_ID_NONE; - struct ipsec_addr_wrap *ipa, *ipb; + struct ipsec_addr_wrap *ipa, *ipb, *ippn; struct iked_policy pol; struct iked_proposal prop[2]; unsigned int j; @@ -2640,6 +2640,17 @@ create_ike(char *name, int af, uint8_t ipproto, struct ipsec_hosts *hosts, flows[j].flow_dst.addr_net = ipb->netaddress; flows[j].flow_dst.addr_port = hosts->dport; + ippn = ipa->srcnat; + if (ippn) { + memcpy(&flows[j].flow_prenat.addr, &ippn->address, + sizeof(ippn->address)); + flows[j].flow_prenat.addr_af = ippn->af; + flows[j].flow_prenat.addr_mask = ippn->mask; + flows[j].flow_prenat.addr_net = ippn->netaddress; + } else { + flows[j].flow_prenat.addr_af = 0; + } + flows[j].flow_ipproto = ipproto; pol.pol_nflows++; diff --git a/sbin/iked/pfkey.c b/sbin/iked/pfkey.c index 72c2d3193ee..d5a582f0f07 100644 --- a/sbin/iked/pfkey.c +++ b/sbin/iked/pfkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkey.c,v 1.51 2016/03/07 19:33:26 mmcc Exp $ */ +/* $OpenBSD: pfkey.c,v 1.52 2016/09/03 09:20:07 vgross Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -173,6 +173,7 @@ int pfkey_flow(int sd, uint8_t satype, uint8_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; @@ -183,56 +184,75 @@ pfkey_flow(int sd, uint8_t satype, uint8_t action, struct iked_flow *flow) sa_srcid = sa_dstid = NULL; + flow_src = &flow->flow_src; + flow_dst = &flow->flow_dst; + + if (flow->flow_prenat.addr_af == flow_src->addr_af) { + 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)); - socket_af((struct sockaddr *)&ssrc, flow->flow_src.addr_port); - socket_af((struct sockaddr *)&smask, flow->flow_src.addr_port ? + memcpy(&ssrc, &flow_src->addr, sizeof(ssrc)); + memcpy(&smask, &flow_src->addr, sizeof(smask)); + socket_af((struct sockaddr *)&ssrc, flow_src->addr_port); + socket_af((struct sockaddr *)&smask, flow_src->addr_port ? 0xffff : 0); - 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, (uint32_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)); - socket_af((struct sockaddr *)&sdst, flow->flow_dst.addr_port); - socket_af((struct sockaddr *)&dmask, flow->flow_dst.addr_port ? + memcpy(&sdst, &flow_dst->addr, sizeof(sdst)); + memcpy(&dmask, &flow_dst->addr, sizeof(dmask)); + socket_af((struct sockaddr *)&sdst, flow_dst->addr_port); + socket_af((struct sockaddr *)&dmask, flow_dst->addr_port ? 0xffff : 0); - 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, (uint32_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; |