aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/plugins/socket_default/socket_default_socket.c
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2013-05-06 17:04:36 +0200
committerMartin Willi <martin@revosec.ch>2013-05-06 17:07:36 +0200
commita8849e0713d3ae0f377f0b0e8c8fb83803d4eed4 (patch)
tree1c710356ddd17e17a9598cdc640e99210d897145 /src/libcharon/plugins/socket_default/socket_default_socket.c
parent922e2d1d62541454be7d84c7551a29a9948f853c (diff)
parentc9a323c1d970b4c28ae6a3c2bba1b55c539346d1 (diff)
downloadstrongswan-a8849e0713d3ae0f377f0b0e8c8fb83803d4eed4.tar.bz2
strongswan-a8849e0713d3ae0f377f0b0e8c8fb83803d4eed4.tar.xz
Merge branch 'tun-vip'
Beside some OS X love, this merge introduces virtual IP and route installation support on the pfkey/pfroute kernel interfaces. Each virtual IP gets installed on a dedicated TUN device. As Linux-like source routes are not supported, routes for the negotiated traffic selectors get installed using the TUN device. To prevent IKE packets from using those routes, special exclude routes get installed to the IKE gateway. This works for most road-warrior deployments, but certainly does not for some more exotic configurations, such as those using virtual-IP-to-host. Mobility is not yet supported, either.
Diffstat (limited to 'src/libcharon/plugins/socket_default/socket_default_socket.c')
-rw-r--r--src/libcharon/plugins/socket_default/socket_default_socket.c102
1 files changed, 54 insertions, 48 deletions
diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c
index c0b744a68..a9c298362 100644
--- a/src/libcharon/plugins/socket_default/socket_default_socket.c
+++ b/src/libcharon/plugins/socket_default/socket_default_socket.c
@@ -162,23 +162,26 @@ METHOD(socket_t, receiver, status_t,
FD_ZERO(&rfds);
- if (this->ipv4)
+ if (this->ipv4 != -1)
{
FD_SET(this->ipv4, &rfds);
+ max_fd = max(max_fd, this->ipv4);
}
- if (this->ipv4_natt)
+ if (this->ipv4_natt != -1)
{
FD_SET(this->ipv4_natt, &rfds);
+ max_fd = max(max_fd, this->ipv4_natt);
}
- if (this->ipv6)
+ if (this->ipv6 != -1)
{
FD_SET(this->ipv6, &rfds);
+ max_fd = max(max_fd, this->ipv6);
}
- if (this->ipv6_natt)
+ if (this->ipv6_natt != -1)
{
FD_SET(this->ipv6_natt, &rfds);
+ max_fd = max(max_fd, this->ipv6_natt);
}
- max_fd = max(max(this->ipv4, this->ipv4_natt), max(this->ipv6, this->ipv6_natt));
DBG2(DBG_NET, "waiting for data on sockets");
oldstate = thread_cancelability(TRUE);
@@ -326,7 +329,7 @@ METHOD(socket_t, receiver, status_t,
METHOD(socket_t, sender, status_t,
private_socket_default_socket_t *this, packet_t *packet)
{
- int sport, skt, family;
+ int sport, skt = -1, family;
ssize_t bytes_sent;
chunk_t data;
host_t *src, *dst;
@@ -376,9 +379,10 @@ METHOD(socket_t, sender, status_t,
return FAILED;
}
}
- else
+ if (skt == -1)
{
- DBG1(DBG_NET, "unable to locate a send socket for port %d", sport);
+ DBG1(DBG_NET, "no socket found to send IPv%d packet from port %d",
+ family == AF_INET ? 4 : 6, sport);
return FAILED;
}
@@ -537,20 +541,20 @@ static int open_socket(private_socket_default_socket_t *this,
pktinfo = IPV6_RECVPKTINFO;
break;
default:
- return 0;
+ return -1;
}
skt = socket(family, SOCK_DGRAM, IPPROTO_UDP);
if (skt < 0)
{
DBG1(DBG_NET, "could not open socket: %s", strerror(errno));
- return 0;
+ return -1;
}
if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
{
DBG1(DBG_NET, "unable to set SO_REUSEADDR on socket: %s", strerror(errno));
close(skt);
- return 0;
+ return -1;
}
/* bind the socket */
@@ -558,7 +562,7 @@ static int open_socket(private_socket_default_socket_t *this,
{
DBG1(DBG_NET, "unable to bind socket: %s", strerror(errno));
close(skt);
- return 0;
+ return -1;
}
/* retrieve randomly allocated port if needed */
@@ -568,7 +572,7 @@ static int open_socket(private_socket_default_socket_t *this,
{
DBG1(DBG_NET, "unable to determine port: %s", strerror(errno));
close(skt);
- return 0;
+ return -1;
}
switch (family)
{
@@ -588,7 +592,7 @@ static int open_socket(private_socket_default_socket_t *this,
{
DBG1(DBG_NET, "unable to set IP_PKTINFO on socket: %s", strerror(errno));
close(skt);
- return 0;
+ return -1;
}
}
@@ -610,22 +614,43 @@ static int open_socket(private_socket_default_socket_t *this,
return skt;
}
+/**
+ * Open a socket pair (normal an NAT traversal) for a given address family
+ */
+static void open_socketpair(private_socket_default_socket_t *this, int family,
+ int *skt, int *skt_natt, char *label)
+{
+ *skt = open_socket(this, family, &this->port);
+ if (*skt == -1)
+ {
+ DBG1(DBG_NET, "could not open %s socket, %s disabled", label, label);
+ }
+ else
+ {
+ *skt_natt = open_socket(this, family, &this->natt);
+ if (*skt_natt == -1)
+ {
+ DBG1(DBG_NET, "could not open %s NAT-T socket", label);
+ }
+ }
+}
+
METHOD(socket_t, destroy, void,
private_socket_default_socket_t *this)
{
- if (this->ipv4)
+ if (this->ipv4 != -1)
{
close(this->ipv4);
}
- if (this->ipv4_natt)
+ if (this->ipv4_natt != -1)
{
close(this->ipv4_natt);
}
- if (this->ipv6)
+ if (this->ipv6 != -1)
{
close(this->ipv6);
}
- if (this->ipv6_natt)
+ if (this->ipv6_natt != -1)
{
close(this->ipv6_natt);
}
@@ -667,36 +692,17 @@ socket_default_socket_t *socket_default_socket_create()
}
/* 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->ipv6_natt = open_socket(this, AF_INET6, &this->natt);
- if (this->ipv6_natt == 0)
- {
- DBG1(DBG_NET, "could not open IPv6 NAT-T socket");
- }
- }
-
- this->ipv4 = open_socket(this, AF_INET, &this->port);
- if (this->ipv4 == 0)
- {
- DBG1(DBG_NET, "could not open IPv4 socket, IPv4 disabled");
- }
- else
- {
- this->ipv4_natt = open_socket(this, AF_INET, &this->natt);
- if (this->ipv4_natt == 0)
- {
- DBG1(DBG_NET, "could not open IPv4 NAT-T socket");
- }
- }
-
- if (!this->ipv4 && !this->ipv6)
+ * ports also for IPv4. On OS X, we have to do it the other way round
+ * for the same effect. */
+#ifdef __APPLE__
+ open_socketpair(this, AF_INET, &this->ipv4, &this->ipv4_natt, "IPv4");
+ open_socketpair(this, AF_INET6, &this->ipv6, &this->ipv6_natt, "IPv6");
+#else /* !__APPLE__ */
+ open_socketpair(this, AF_INET6, &this->ipv6, &this->ipv6_natt, "IPv6");
+ open_socketpair(this, AF_INET, &this->ipv4, &this->ipv4_natt, "IPv4");
+#endif /* __APPLE__ */
+
+ if (this->ipv4 == -1 && this->ipv6 == -1)
{
DBG1(DBG_NET, "could not create any sockets");
destroy(this);