summaryrefslogtreecommitdiff
path: root/src/charon/network/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/network/socket.c')
-rw-r--r--src/charon/network/socket.c93
1 files changed, 52 insertions, 41 deletions
diff --git a/src/charon/network/socket.c b/src/charon/network/socket.c
index 97c88be79..81f860b15 100644
--- a/src/charon/network/socket.c
+++ b/src/charon/network/socket.c
@@ -23,7 +23,6 @@
#define __EXTENSIONS__
#endif
-#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
@@ -35,7 +34,6 @@
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
-#include <netinet/ip6.h>
#include <netinet/udp.h>
#include <net/if.h>
#ifdef __APPLE__
@@ -45,6 +43,7 @@
#include "socket.h"
#include <daemon.h>
+#include <threading/thread.h>
/* length of non-esp marker */
#define MARKER_LEN sizeof(u_int32_t)
@@ -72,9 +71,16 @@
/* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that
* previously defined IPV6_PKTINFO */
#ifndef IPV6_RECVPKTINFO
-#define IPV6_RECVPKTINFO IPV6_PKTINFO;
+#define IPV6_RECVPKTINFO IPV6_PKTINFO
#endif
+#ifndef IN6ADDR_ANY_INIT
+#define IN6ADDR_ANY_INIT {{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}
+#endif
+
+#ifndef HAVE_IN6ADDR_ANY
+static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+#endif
typedef struct private_socket_t private_socket_t;
@@ -86,22 +92,22 @@ struct private_socket_t {
* public functions
*/
socket_t public;
-
+
/**
* IPv4 socket (500)
*/
int ipv4;
-
+
/**
* IPv4 socket for NATT (4500)
*/
int ipv4_natt;
-
+
/**
* IPv6 socket (500)
*/
int ipv6;
-
+
/**
* IPv6 socket for NATT (4500)
*/
@@ -117,14 +123,15 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
chunk_t data;
packet_t *pkt;
host_t *source = NULL, *dest = NULL;
- int bytes_read = 0;
- int data_offset, oldstate;
+ int bytes_read = 0, data_offset;
+ bool oldstate;
+
fd_set rfds;
int max_fd = 0, selected = 0;
u_int16_t port = 0;
-
+
FD_ZERO(&rfds);
-
+
if (this->ipv4)
{
FD_SET(this->ipv4, &rfds);
@@ -142,16 +149,16 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
FD_SET(this->ipv6_natt, &rfds);
}
max_fd = max(max(this->ipv4, this->ipv4_natt), max(this->ipv6, this->ipv6_natt));
-
+
DBG2(DBG_NET, "waiting for data on sockets");
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
+ oldstate = thread_cancelability(TRUE);
if (select(max_fd + 1, &rfds, NULL, NULL, NULL) <= 0)
{
- pthread_setcancelstate(oldstate, NULL);
+ thread_cancelability(oldstate);
return FAILED;
}
- pthread_setcancelstate(oldstate, NULL);
-
+ thread_cancelability(oldstate);
+
if (FD_ISSET(this->ipv4, &rfds))
{
port = IKEV2_UDP_PORT;
@@ -182,7 +189,7 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
struct sockaddr_in in4;
struct sockaddr_in6 in6;
} src;
-
+
msg.msg_name = &src;
msg.msg_namelen = sizeof(src);
iov.iov_base = buffer;
@@ -199,14 +206,14 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
return FAILED;
}
DBG3(DBG_NET, "received packet %b", buffer, bytes_read);
-
+
if (bytes_read < MARKER_LEN)
{
DBG3(DBG_NET, "received packet too short (%d bytes)",
bytes_read);
return FAILED;
}
-
+
/* read ancillary data to get destination address */
for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
cmsgptr = CMSG_NXTHDR(&msg, cmsgptr))
@@ -216,20 +223,22 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
DBG1(DBG_NET, "error reading ancillary data");
return FAILED;
}
-
+
+#ifdef HAVE_IN6_PKTINFO
if (cmsgptr->cmsg_level == SOL_IPV6 &&
cmsgptr->cmsg_type == IPV6_PKTINFO)
{
struct in6_pktinfo *pktinfo;
pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsgptr);
struct sockaddr_in6 dst;
-
+
memset(&dst, 0, sizeof(dst));
memcpy(&dst.sin6_addr, &pktinfo->ipi6_addr, sizeof(dst.sin6_addr));
dst.sin6_family = AF_INET6;
dst.sin6_port = htons(port);
dest = host_create_from_sockaddr((sockaddr_t*)&dst);
}
+#endif /* HAVE_IN6_PKTINFO */
if (cmsgptr->cmsg_level == SOL_IP &&
#ifdef IP_PKTINFO
cmsgptr->cmsg_type == IP_PKTINFO
@@ -252,7 +261,7 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
#endif
memset(&dst, 0, sizeof(dst));
memcpy(&dst.sin_addr, addr, sizeof(dst.sin_addr));
-
+
dst.sin_family = AF_INET;
dst.sin_port = htons(port);
dest = host_create_from_sockaddr((sockaddr_t*)&dst);
@@ -268,13 +277,13 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
return FAILED;
}
source = host_create_from_sockaddr((sockaddr_t*)&src);
-
+
pkt = packet_create();
pkt->set_source(pkt, source);
pkt->set_destination(pkt, dest);
DBG2(DBG_NET, "received packet: from %#H to %#H", source, dest);
data_offset = 0;
- /* remove non esp marker */
+ /* remove non esp marker */
if (dest->get_port(dest) == IKEV2_NATT_PORT)
{
data_offset += MARKER_LEN;
@@ -307,13 +316,13 @@ status_t sender(private_socket_t *this, packet_t *packet)
struct msghdr msg;
struct cmsghdr *cmsg;
struct iovec iov;
-
+
src = packet->get_source(packet);
dst = packet->get_destination(packet);
data = packet->get_data(packet);
DBG2(DBG_NET, "sending packet: from %#H to %#H", src, dst);
-
+
/* send data */
sport = src->get_port(src);
family = dst->get_family(dst);
@@ -361,7 +370,7 @@ status_t sender(private_socket_t *this, packet_t *packet)
DBG1(DBG_NET, "unable to locate a send socket for port %d", sport);
return FAILED;
}
-
+
memset(&msg, 0, sizeof(struct msghdr));
msg.msg_name = dst->get_sockaddr(dst);;
msg.msg_namelen = *dst->get_sockaddr_len(dst);
@@ -370,7 +379,7 @@ status_t sender(private_socket_t *this, packet_t *packet)
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_flags = 0;
-
+
if (!src->is_anyaddr(src))
{
if (family == AF_INET)
@@ -403,12 +412,13 @@ status_t sender(private_socket_t *this, packet_t *packet)
memcpy(addr, &sin->sin_addr, sizeof(struct in_addr));
#endif /* IP_PKTINFO || IP_SENDSRCADDR */
}
+#ifdef HAVE_IN6_PKTINFO
else
{
char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
struct in6_pktinfo *pktinfo;
struct sockaddr_in6 *sin;
-
+
msg.msg_control = buf;
msg.msg_controllen = sizeof(buf);
cmsg = CMSG_FIRSTHDR(&msg);
@@ -420,8 +430,9 @@ status_t sender(private_socket_t *this, packet_t *packet)
sin = (struct sockaddr_in6*)src->get_sockaddr(src);
memcpy(&pktinfo->ipi6_addr, &sin->sin6_addr, sizeof(struct in6_addr));
}
+#endif /* HAVE_IN6_PKTINFO */
}
-
+
bytes_sent = sendmsg(skt, &msg, 0);
if (bytes_sent != data.len)
@@ -442,7 +453,7 @@ static int open_socket(private_socket_t *this, int family, u_int16_t port)
socklen_t addrlen;
u_int sol, pktinfo = 0;
int skt;
-
+
memset(&addr, 0, sizeof(addr));
/* precalculate constants depending on address family */
switch (family)
@@ -476,7 +487,7 @@ static int open_socket(private_socket_t *this, int family, u_int16_t port)
default:
return 0;
}
-
+
skt = socket(family, SOCK_DGRAM, IPPROTO_UDP);
if (skt < 0)
{
@@ -489,7 +500,7 @@ static int open_socket(private_socket_t *this, int family, u_int16_t port)
close(skt);
return 0;
}
-
+
/* bind the socket */
if (bind(skt, (struct sockaddr *)&addr, addrlen) < 0)
{
@@ -497,7 +508,7 @@ static int open_socket(private_socket_t *this, int family, u_int16_t port)
close(skt);
return 0;
}
-
+
/* get additional packet info on receive */
if (pktinfo > 0)
{
@@ -550,7 +561,7 @@ static bool enumerate(socket_enumerator_t *this, int *fd, int *family, int *port
{ offsetof(private_socket_t, ipv4_natt), AF_INET, IKEV2_NATT_PORT },
{ offsetof(private_socket_t, ipv6_natt), AF_INET6, IKEV2_NATT_PORT }
};
-
+
while(++this->index < countof(sockets))
{
int sock = *(int*)((char*)this->socket + sockets[this->index].fd_offset);
@@ -572,7 +583,7 @@ static bool enumerate(socket_enumerator_t *this, int *fd, int *family, int *port
static enumerator_t *create_enumerator(private_socket_t *this)
{
socket_enumerator_t *enumerator;
-
+
enumerator = malloc_thing(socket_enumerator_t);
enumerator->index = -1;
enumerator->socket = this;
@@ -617,7 +628,7 @@ socket_t *socket_create()
this->public.receive = (status_t(*)(socket_t*, packet_t**))receiver;
this->public.create_enumerator = (enumerator_t*(*)(socket_t*))create_enumerator;
this->public.destroy = (void(*)(socket_t*)) destroy;
-
+
this->ipv4 = 0;
this->ipv6 = 0;
this->ipv4_natt = 0;
@@ -634,7 +645,7 @@ socket_t *socket_create()
}
}
#endif
-
+
this->ipv4 = open_socket(this, AF_INET, IKEV2_UDP_PORT);
if (this->ipv4 == 0)
{
@@ -648,7 +659,7 @@ socket_t *socket_create()
DBG1(DBG_NET, "could not open IPv4 NAT-T socket");
}
}
-
+
this->ipv6 = open_socket(this, AF_INET6, IKEV2_UDP_PORT);
if (this->ipv6 == 0)
{
@@ -662,13 +673,13 @@ socket_t *socket_create()
DBG1(DBG_NET, "could not open IPv6 NAT-T socket");
}
}
-
+
if (!this->ipv4 && !this->ipv6)
{
DBG1(DBG_NET, "could not create any sockets");
destroy(this);
charon->kill(charon, "socket initialization failed");
- }
+ }
return (socket_t*)this;
}