AC_ARG_WITH(
[charon-udp-port],
- AS_HELP_STRING([--with-charon-udp-port=port],[UDP port used by charon locally (default 500).]),
+ AS_HELP_STRING([--with-charon-udp-port=port],[UDP port used by charon locally (default 500). Set to 0 to allocate randomly.]),
[AC_DEFINE_UNQUOTED(CHARON_UDP_PORT, [$withval], [UDP port used by charon locally])
AC_SUBST(charon_udp_port, [$withval])],
[AC_SUBST(charon_udp_port, 500)]
AC_ARG_WITH(
[charon-natt-port],
- AS_HELP_STRING([--with-charon-natt-port=port],[UDP port used by charon locally in case a NAT is detected (must be different from charon-udp-port, default 4500)]),
+ AS_HELP_STRING([--with-charon-natt-port=port],[UDP port used by charon locally in case a NAT is detected (must be different from charon-udp-port, default 4500). Set to 0 to allocate randomly.]),
[AC_DEFINE_UNQUOTED(CHARON_NATT_PORT, [$withval], [UDP post used by charon locally in case a NAT is detected])
AC_SUBST(charon_natt_port, [$withval])],
[AC_SUBST(charon_natt_port, 4500)]
)
AC_MSG_CHECKING([configured UDP ports ($charon_udp_port, $charon_natt_port)])
-if test x$charon_udp_port == x$charon_natt_port; then
+if test x$charon_udp_port != x0 -a x$charon_udp_port = x$charon_natt_port; then
AC_MSG_ERROR(the ports have to be different)
else
AC_MSG_RESULT(ok)
socket_default_socket_t public;
/**
- * IPv4 socket (500)
+ * Configured port (or random, if initially 0)
+ */
+ u_int16_t port;
+
+ /**
+ * Configured port for NAT-T (or random, if initially 0)
+ */
+ u_int16_t natt;
+
+ /**
+ * IPv4 socket (500 or port)
*/
int ipv4;
/**
- * IPv4 socket for NATT (4500)
+ * IPv4 socket for NAT-T (4500 or natt)
*/
int ipv4_natt;
/**
- * IPv6 socket (500)
+ * IPv6 socket (500 or port)
*/
int ipv6;
/**
- * IPv6 socket for NATT (4500)
+ * IPv6 socket for NAT-T (4500 or natt)
*/
int ipv6_natt;
if (FD_ISSET(this->ipv4, &rfds))
{
- port = CHARON_UDP_PORT;
+ port = this->port;
selected = this->ipv4;
}
if (FD_ISSET(this->ipv4_natt, &rfds))
{
- port = CHARON_NATT_PORT;
+ port = this->natt;
selected = this->ipv4_natt;
}
if (FD_ISSET(this->ipv6, &rfds))
{
- port = CHARON_UDP_PORT;
+ port = this->port;
selected = this->ipv6;
}
if (FD_ISSET(this->ipv6_natt, &rfds))
{
- port = CHARON_NATT_PORT;
+ port = this->natt;
selected = this->ipv6_natt;
}
if (selected)
/* send data */
sport = src->get_port(src);
family = dst->get_family(dst);
- if (sport == 0 || sport == CHARON_UDP_PORT)
+ if (sport == 0 || sport == this->port)
{
if (family == AF_INET)
{
skt = this->ipv6;
}
}
- else if (sport == CHARON_NATT_PORT)
+ else if (sport == this->natt)
{
if (family == AF_INET)
{
METHOD(socket_t, get_port, u_int16_t,
private_socket_default_socket_t *this, bool nat_t)
{
- return nat_t ? CHARON_NATT_PORT : CHARON_UDP_PORT;
+ return nat_t ? this->natt : this->port;
}
/**
* open a socket to send and receive packets
*/
static int open_socket(private_socket_default_socket_t *this,
- int family, u_int16_t port)
+ int family, u_int16_t *port)
{
int on = TRUE;
struct sockaddr_storage addr;
{
struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
htoun32(&sin->sin_addr.s_addr, INADDR_ANY);
- htoun16(&sin->sin_port, port);
+ htoun16(&sin->sin_port, *port);
addrlen = sizeof(struct sockaddr_in);
sol = SOL_IP;
#ifdef IP_PKTINFO
{
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any));
- htoun16(&sin6->sin6_port, port);
+ htoun16(&sin6->sin6_port, *port);
addrlen = sizeof(struct sockaddr_in6);
sol = SOL_IPV6;
pktinfo = IPV6_RECVPKTINFO;
return 0;
}
+ /* retrieve randomly allocated port if needed */
+ if (*port == 0)
+ {
+ if (getsockname(skt, (struct sockaddr *)&addr, &addrlen) < 0)
+ {
+ DBG1(DBG_NET, "unable to determine port: %s", strerror(errno));
+ close(skt);
+ return 0;
+ }
+ switch (family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
+ *port = untoh16(&sin->sin_port);
+ break;
+ }
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
+ *port = untoh16(&sin6->sin6_port);
+ break;
+ }
+ }
+ }
+
/* get additional packet info on receive */
if (pktinfo > 0)
{
{
DBG1(DBG_NET, "installing IKE bypass policy failed");
}
-
- /* enable UDP decapsulation globally, only for one socket needed */
- if (family == AF_INET && port == CHARON_NATT_PORT &&
- !hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface,
- skt, family, port))
- {
- DBG1(DBG_NET, "enabling UDP decapsulation failed");
- }
-
return skt;
}
.destroy = _destroy,
},
},
+ .port = lib->settings->get_int(lib->settings,
+ "%s.port", CHARON_UDP_PORT, charon->name),
+ .natt = lib->settings->get_int(lib->settings,
+ "%s.port_nat_t", CHARON_NATT_PORT, charon->name),
.max_packet = lib->settings->get_int(lib->settings,
- "%s.max_packet", MAX_PACKET, charon->name),
+ "%s.max_packet", MAX_PACKET, charon->name),
);
- this->ipv4 = open_socket(this, AF_INET, CHARON_UDP_PORT);
- if (this->ipv4 == 0)
+ if (this->port && this->port == this->natt)
{
- DBG1(DBG_NET, "could not open IPv4 socket, IPv4 disabled");
+ DBG1(DBG_NET, "IKE ports can't be equal, will allocate NAT-T "
+ "port randomly");
+ this->natt = 0;
+ }
+
+ /* we allocate IPv6 sockets first as that will reserve randomly allocated
+ * ports also for IPv4 */
+ this->ipv6 = open_socket(this, AF_INET6, &this->port);
+ if (this->ipv6 == 0)
+ {
+ DBG1(DBG_NET, "could not open IPv6 socket, IPv6 disabled");
}
else
{
- this->ipv4_natt = open_socket(this, AF_INET, CHARON_NATT_PORT);
- if (this->ipv4_natt == 0)
+ this->ipv6_natt = open_socket(this, AF_INET6, &this->natt);
+ if (this->ipv6_natt == 0)
{
- DBG1(DBG_NET, "could not open IPv4 NAT-T socket");
+ DBG1(DBG_NET, "could not open IPv6 NAT-T socket");
}
}
- this->ipv6 = open_socket(this, AF_INET6, CHARON_UDP_PORT);
- if (this->ipv6 == 0)
+ this->ipv4 = open_socket(this, AF_INET, &this->port);
+ if (this->ipv4 == 0)
{
- DBG1(DBG_NET, "could not open IPv6 socket, IPv6 disabled");
+ DBG1(DBG_NET, "could not open IPv4 socket, IPv4 disabled");
}
else
{
- this->ipv6_natt = open_socket(this, AF_INET6, CHARON_NATT_PORT);
- if (this->ipv6_natt == 0)
+ this->ipv4_natt = open_socket(this, AF_INET, &this->natt);
+ if (this->ipv4_natt == 0)
{
- DBG1(DBG_NET, "could not open IPv6 NAT-T socket");
+ DBG1(DBG_NET, "could not open IPv4 NAT-T socket");
}
}
destroy(this);
return NULL;
}
+
+ /* enable UDP decapsulation globally, only for one socket needed */
+ if (!hydra->kernel_interface->enable_udp_decap(hydra->kernel_interface,
+ this->ipv6_natt ?: this->ipv4_natt,
+ this->ipv6_natt ? AF_INET6 : AF_INET, this->natt))
+ {
+ DBG1(DBG_NET, "enabling UDP decapsulation failed");
+ }
return &this->public;
}