#include <sys/types.h>
#include <sys/param.h>
-#ifdef __linux__
-#include <linux/udp.h>
-#endif
-#if defined(__NetBSD__) || defined (__FreeBSD__)
#include <netinet/udp.h>
-#endif
#include <stdlib.h>
#include <stdio.h>
#include "ike_session.h"
struct natt_ka_addrs {
- struct sockaddr *src;
- struct sockaddr *dst;
+ struct sockaddr_storage *src;
+ struct sockaddr_storage *dst;
unsigned in_use;
TAILQ_ENTRY(natt_ka_addrs) chain;
};
-static TAILQ_HEAD(_natt_ka_addrs, natt_ka_addrs) ka_tree;
-
/*
* check if the given vid is NAT-T.
*/
}
vchar_t *
-natt_hash_addr (struct ph1handle *iph1, struct sockaddr *addr)
+natt_hash_addr (phase1_handle_t *iph1, struct sockaddr_storage *addr)
{
vchar_t *natd;
vchar_t *buf;
void *addr_ptr, *addr_port;
size_t buf_size, addr_size;
- plog (LLV_INFO, LOCATION, addr, "Hashing %s with algo #%d %s\n",
- saddr2str(addr), iph1->approval->hashtype,
- (iph1->rmconf->nat_traversal == NATT_FORCE)?"(NAT-T forced)":"");
+ if (iph1->approval) {
+ plog(ASL_LEVEL_NOTICE, "Hashing %s with algo #%d %s\n",
+ saddr2str((struct sockaddr *)addr), iph1->approval->hashtype,
+ (iph1->rmconf->nat_traversal == NATT_FORCE)?"(NAT-T forced)":"");
+ }
- if (addr->sa_family == AF_INET) {
+ if (addr->ss_family == AF_INET) {
addr_size = sizeof (struct in_addr); /* IPv4 address */
addr_ptr = &((struct sockaddr_in *)addr)->sin_addr;
addr_port = &((struct sockaddr_in *)addr)->sin_port;
}
- else if (addr->sa_family == AF_INET6) {
+ else if (addr->ss_family == AF_INET6) {
addr_size = sizeof (struct in6_addr); /* IPv6 address */
addr_ptr = &((struct sockaddr_in6 *)addr)->sin6_addr;
addr_port = &((struct sockaddr_in6 *)addr)->sin6_port;
}
else {
- plog (LLV_ERROR, LOCATION, addr, "Unsupported address family #0x%x\n", addr->sa_family);
+ plog(ASL_LEVEL_ERR, "Unsupported address family #0x%x\n", addr->ss_family);
return NULL;
}
}
int
-natt_compare_addr_hash (struct ph1handle *iph1, vchar_t *natd_received,
+natt_compare_addr_hash (phase1_handle_t *iph1, vchar_t *natd_received,
int natd_seq)
{
vchar_t *natd_computed;
if (iph1->rmconf->nat_traversal == NATT_FORCE)
return verified;
-#ifdef __APPLE__
/* old APPLE version sends natd payload in the wrong order */
if (iph1->natt_options->version == VENDORID_NATT_APPLE) {
if (natd_seq == 0) {
flag = NAT_DETECTED_ME;
}
} else
-#endif
{
if (natd_seq == 0) {
natd_computed = natt_hash_addr (iph1, iph1->local);
opts->version = version;
switch (version) {
-#ifndef __APPLE__
- case VENDORID_NATT_00:
- case VENDORID_NATT_01:
- opts->float_port = 0; /* No port floating for those drafts */
- opts->payload_nat_d = ISAKMP_NPTYPE_NATD_DRAFT;
- opts->payload_nat_oa = ISAKMP_NPTYPE_NATOA_DRAFT;
- opts->mode_udp_tunnel = IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT;
- opts->mode_udp_transport = IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT;
- opts->encaps_type = UDP_ENCAP_ESPINUDP_NON_IKE;
- break;
-#endif
-
case VENDORID_NATT_02:
case VENDORID_NATT_02_N:
case VENDORID_NATT_03:
case VENDORID_NATT_06:
case VENDORID_NATT_07:
case VENDORID_NATT_08:
-#ifdef __APPLE__
case VENDORID_NATT_APPLE:
opts->float_port = lcconf->port_isakmp_natt;
opts->payload_nat_d = ISAKMP_NPTYPE_NATD_BADDRAFT;
opts->mode_udp_transport = IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC;
opts->encaps_type = UDP_ENCAP_ESPINUDP;
break;
-#endif
case VENDORID_NATT_RFC:
opts->float_port = lcconf->port_isakmp_natt;
opts->payload_nat_d = ISAKMP_NPTYPE_NATD_RFC;
opts->encaps_type = UDP_ENCAP_ESPINUDP;
break;
default:
- plog(LLV_ERROR, LOCATION, NULL,
+ plog(ASL_LEVEL_ERR,
"unsupported NAT-T version: %s\n",
vid_string_by_id(version));
return -1;
}
int
-create_natoa_payloads(struct ph2handle *iph2, vchar_t **natoa_i, vchar_t **natoa_r)
+create_natoa_payloads(phase2_handle_t *iph2, vchar_t **natoa_i, vchar_t **natoa_r)
{
int natoa_type = 0;
vchar_t *i;
vchar_t *r;
u_int8_t *p;
- struct sockaddr *i_addr;
- struct sockaddr *r_addr;
+ struct sockaddr_storage *i_addr;
+ struct sockaddr_storage *r_addr;
size_t i_size;
size_t r_size;
r_addr = iph2->src;
}
- switch (i_addr->sa_family) {
+ switch (i_addr->ss_family) {
case AF_INET:
i_size = sizeof(in_addr_t);
break;
break;
#endif
default:
- plog(LLV_ERROR, LOCATION, NULL,
- "invalid address family: %d\n", i_addr->sa_family);
+ plog(ASL_LEVEL_ERR,
+ "invalid address family: %d\n", i_addr->ss_family);
return -1;
}
- switch (r_addr->sa_family) {
+ switch (r_addr->ss_family) {
case AF_INET:
r_size = sizeof(in_addr_t);
break;
break;
#endif
default:
- plog(LLV_ERROR, LOCATION, NULL,
- "invalid address family: %d\n", r_addr->sa_family);
+ plog(ASL_LEVEL_ERR,
+ "invalid address family: %d\n", r_addr->ss_family);
return -1;
}
i = vmalloc(sizeof(struct isakmp_pl_natoa) + i_size - sizeof(struct isakmp_gen));
if (i == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
+ plog(ASL_LEVEL_ERR,
"failed to get buffer for natoa payload.\n");
return -1;
}
r = vmalloc(sizeof(struct isakmp_pl_natoa) + r_size - sizeof(struct isakmp_gen));
if (r == NULL) {
vfree(i);
- plog(LLV_ERROR, LOCATION, NULL,
+ plog(ASL_LEVEL_ERR,
"failed to get buffer for natoa payload.\n");
return -1;
}
/* copy src address */
p = (__typeof__(p))i->v;
- switch (i_addr->sa_family) {
+ switch (i_addr->ss_family) {
case AF_INET:
*p = IPSECDOI_ID_IPV4_ADDR;
bcopy(&(((struct sockaddr_in *)i_addr)->sin_addr.s_addr), p + sizeof(u_int32_t), i_size);
/* copy dst address */
p = (__typeof__(p))r->v;
- switch (r_addr->sa_family) {
+ switch (r_addr->ss_family) {
case AF_INET:
*p = IPSECDOI_ID_IPV4_ADDR;
bcopy(&(((struct sockaddr_in *)r_addr)->sin_addr.s_addr), p + sizeof(u_int32_t), r_size);
return natoa_type;
}
-struct sockaddr *
+struct sockaddr_storage *
process_natoa_payload(vchar_t *buf)
{
- struct sockaddr *saddr = NULL;
- struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)buf->v;
+ struct sockaddr_storage *saddr = NULL;
+ struct ipsecdoi_id_b *id_b = ALIGNED_CAST(struct ipsecdoi_id_b *)buf->v;
switch (id_b->type) {
case IPSECDOI_ID_IPV4_ADDR:
saddr = racoon_malloc(sizeof(struct sockaddr_in));
if (!saddr) {
- plog(LLV_ERROR, LOCATION, NULL,
+ plog(ASL_LEVEL_ERR,
"error allocating addr for NAT-OA payload\n");
return NULL;
}
- saddr->sa_len = sizeof(struct sockaddr_in);
- saddr->sa_family = AF_INET;
+ saddr->ss_len = sizeof(struct sockaddr_in);
+ saddr->ss_family = AF_INET;
((struct sockaddr_in *)saddr)->sin_port = IPSEC_PORT_ANY;
memcpy(&((struct sockaddr_in *)saddr)->sin_addr,
buf->v + sizeof(*id_b), sizeof(struct in_addr));
case IPSECDOI_ID_IPV6_ADDR:
saddr = racoon_malloc(sizeof(struct sockaddr_in6));
if (!saddr) {
- plog(LLV_ERROR, LOCATION, NULL,
+ plog(ASL_LEVEL_ERR,
"error allocating addr for NAT-OA payload\n");
return NULL;
}
- saddr->sa_len = sizeof(struct sockaddr_in6);
- saddr->sa_family = AF_INET6;
+ saddr->ss_len = sizeof(struct sockaddr_in6);
+ saddr->ss_family = AF_INET6;
((struct sockaddr_in6 *)saddr)->sin6_port = IPSEC_PORT_ANY;
memcpy(&((struct sockaddr_in6 *)saddr)->sin6_addr,
buf->v + sizeof(*id_b), sizeof(struct in6_addr));
break;
#endif
default:
- plog(LLV_ERROR, LOCATION, NULL,
+ plog(ASL_LEVEL_ERR,
"invalid NAT-OA payload %d\n", id_b->type);
return NULL;
}
}
void
-natt_float_ports (struct ph1handle *iph1)
+natt_float_ports (phase1_handle_t *iph1)
{
- if (! (iph1->natt_flags && NAT_DETECTED) )
+ if (! (iph1->natt_flags & NAT_DETECTED) )
return;
if (! iph1->natt_options->float_port){
/* Drafts 00 / 01, just schedule keepalive */
-#ifndef __APPLE__
- natt_keepalive_add_ph1 (iph1);
-#endif
return;
}
set_port (iph1->remote, iph1->natt_options->float_port);
iph1->natt_flags |= NAT_PORTS_CHANGED | NAT_ADD_NON_ESP_MARKER;
- ike_session_ikev1_float_ports(iph1);
-
-#ifndef __APPLE__
- natt_keepalive_add_ph1 (iph1);
-#endif
+ if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1)
+ ike_session_ikev1_float_ports(iph1);
}
void
-natt_handle_vendorid (struct ph1handle *iph1, int vid_numeric)
+natt_handle_vendorid (phase1_handle_t *iph1, int vid_numeric)
{
+ int version;
+
if (! iph1->natt_options)
iph1->natt_options = racoon_calloc (1, sizeof (*iph1->natt_options));
if (! iph1->natt_options) {
- plog (LLV_ERROR, LOCATION, NULL,
+ plog (ASL_LEVEL_ERR,
"Allocating memory for natt_options failed!\n");
return;
}
-
- if (iph1->natt_options->version < vid_numeric)
- if (natt_fill_options (iph1->natt_options, vid_numeric) == 0)
- iph1->natt_flags |= NAT_ANNOUNCED;
-}
-#ifndef __APPLE__
-/* NAT keepalive functions */
-static void
-natt_keepalive_send (void *param)
-{
- struct natt_ka_addrs *ka, *next = NULL;
- char keepalive_packet[] = { 0xff };
- size_t len;
- int s;
-
- for (ka = TAILQ_FIRST(&ka_tree); ka; ka = next) {
- next = TAILQ_NEXT(ka, chain);
-
- s = getsockmyaddr(ka->src);
- if (s == -1) {
- TAILQ_REMOVE (&ka_tree, ka, chain);
- racoon_free (ka);
- continue;
- }
- plog (LLV_DEBUG, LOCATION, NULL, "KA: %s\n",
- saddr2str_fromto("%s->%s", ka->src, ka->dst));
- len = sendfromto(s, keepalive_packet, sizeof (keepalive_packet),
- ka->src, ka->dst, 1);
- if (len == -1)
- plog(LLV_ERROR, LOCATION, NULL, "KA: sendfromto failed: %s\n",
- strerror (errno));
+ // stick to the version we already selected on a previous phase1
+ version = ike_session_get_natt_version(iph1);
+ if (version) {
+ vid_numeric = version;
}
-
- sched_new (lcconf->natt_ka_interval, natt_keepalive_send, NULL);
-}
-void
-natt_keepalive_init (void)
-{
- TAILQ_INIT(&ka_tree);
-
- /* To disable sending KAs set natt_ka_interval=0 */
- if (lcconf->natt_ka_interval > 0)
- sched_new (lcconf->natt_ka_interval, natt_keepalive_send, NULL);
-}
-
-int
-natt_keepalive_add (struct sockaddr *src, struct sockaddr *dst)
-{
- struct natt_ka_addrs *ka = NULL, *new_addr;
-
- TAILQ_FOREACH (ka, &ka_tree, chain) {
- if (cmpsaddrstrict(ka->src, src) == 0 &&
- cmpsaddrstrict(ka->dst, dst) == 0) {
- ka->in_use++;
- plog (LLV_INFO, LOCATION, NULL, "KA found: %s (in_use=%u)\n",
- saddr2str_fromto("%s->%s", src, dst), ka->in_use);
- return 0;
- }
- }
-
- plog (LLV_INFO, LOCATION, NULL, "KA list add: %s\n", saddr2str_fromto("%s->%s", src, dst));
-
- new_addr = (struct natt_ka_addrs *)racoon_malloc(sizeof(*new_addr));
- if (! new_addr) {
- plog (LLV_ERROR, LOCATION, NULL, "Can't allocate new KA list item\n");
- return -1;
- }
-
- if ((new_addr->src = dupsaddr(src)) == NULL) {
- racoon_free(new_addr);
- plog (LLV_ERROR, LOCATION, NULL, "Can't allocate new KA list item\n");
- return -1;
- }
- if ((new_addr->dst = dupsaddr(dst)) == NULL) {
- racoon_free(new_addr);
- plog (LLV_ERROR, LOCATION, NULL, "Can't allocate new KA list item\n");
- return -1;
- }
- new_addr->in_use = 1;
- TAILQ_INSERT_TAIL(&ka_tree, new_addr, chain);
-
- return 0;
-}
-
-int
-natt_keepalive_add_ph1 (struct ph1handle *iph1)
-{
- int ret = 0;
-
- /* Should only the NATed host send keepalives?
- If yes, add '(iph1->natt_flags & NAT_DETECTED_ME)'
- to the following condition. */
- if (iph1->natt_flags & NAT_DETECTED &&
- ! (iph1->natt_flags & NAT_KA_QUEUED)) {
- ret = natt_keepalive_add (iph1->local, iph1->remote);
- if (ret == 0)
- iph1->natt_flags |= NAT_KA_QUEUED;
- }
-
- return ret;
-}
-
-void
-natt_keepalive_remove (struct sockaddr *src, struct sockaddr *dst)
-{
- struct natt_ka_addrs *ka, *next = NULL;
-
- plog (LLV_INFO, LOCATION, NULL, "KA remove: %s\n", saddr2str_fromto("%s->%s", src, dst));
-
- for (ka = TAILQ_FIRST(&ka_tree); ka; ka = next) {
- next = TAILQ_NEXT(ka, chain);
-
- plog (LLV_DEBUG, LOCATION, NULL, "KA tree dump: %s (in_use=%u)\n",
- saddr2str_fromto("%s->%s", src, dst), ka->in_use);
-
- if (cmpsaddrstrict(ka->src, src) == 0 &&
- cmpsaddrstrict(ka->dst, dst) == 0 &&
- -- ka->in_use <= 0) {
-
- plog (LLV_DEBUG, LOCATION, NULL, "KA removing this one...\n");
-
- TAILQ_REMOVE (&ka_tree, ka, chain);
- racoon_free (ka);
- /* Should we break here? Every pair of addresses should
- be inserted only once, but who knows :-) Lets traverse
- the whole list... */
- }
- }
+ if (iph1->natt_options->version < vid_numeric)
+ if (natt_fill_options (iph1->natt_options, vid_numeric) == 0)
+ iph1->natt_flags |= NAT_ANNOUNCED;
}
-#endif /* __APPLE__ */
static struct remoteconf *
natt_enabled_in_rmconf_stub (struct remoteconf *rmconf, void *data)