summaryrefslogtreecommitdiff
path: root/src/charon/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/network')
-rw-r--r--src/charon/network/packet.c16
-rw-r--r--src/charon/network/packet.h46
-rw-r--r--src/charon/network/receiver.c84
-rw-r--r--src/charon/network/receiver.h12
-rw-r--r--src/charon/network/sender.c39
-rw-r--r--src/charon/network/sender.h10
-rw-r--r--src/charon/network/socket-raw.c106
-rw-r--r--src/charon/network/socket.c93
-rw-r--r--src/charon/network/socket.h28
9 files changed, 220 insertions, 214 deletions
diff --git a/src/charon/network/packet.c b/src/charon/network/packet.c
index fd3a274bd..19a62603d 100644
--- a/src/charon/network/packet.c
+++ b/src/charon/network/packet.c
@@ -27,17 +27,17 @@ struct private_packet_t {
* Public part of a packet_t object.
*/
packet_t public;
-
+
/**
* source address
*/
host_t *source;
-
+
/**
* destination address
*/
host_t *destination;
-
+
/**
* message data
*/
@@ -77,7 +77,7 @@ static host_t *get_destination(private_packet_t *this)
{
return this->destination;
}
-
+
/**
* Implements packet_t.get_data
*/
@@ -103,7 +103,7 @@ static void destroy(private_packet_t *this)
if (this->source != NULL)
{
this->source->destroy(this->source);
- }
+ }
if (this->destination != NULL)
{
this->destination->destroy(this->destination);
@@ -118,7 +118,7 @@ static void destroy(private_packet_t *this)
static packet_t *clone_(private_packet_t *this)
{
private_packet_t *other = (private_packet_t*)packet_create();
-
+
if (this->destination != NULL)
{
other->destination = this->destination->clone(this->destination);
@@ -150,10 +150,10 @@ packet_t *packet_create(void)
this->public.get_destination = (host_t*(*) (packet_t *)) get_destination;
this->public.clone = (packet_t*(*) (packet_t *))clone_;
this->public.destroy = (void(*) (packet_t *)) destroy;
-
+
this->destination = NULL;
this->source = NULL;
this->data = chunk_empty;
-
+
return &(this->public);
}
diff --git a/src/charon/network/packet.h b/src/charon/network/packet.h
index aacb203e9..18d82c6fc 100644
--- a/src/charon/network/packet.h
+++ b/src/charon/network/packet.h
@@ -34,71 +34,71 @@ struct packet_t {
/**
* Set the source address.
- *
+ *
* Set host_t is now owned by packet_t, it will destroy
* it if necessary.
- *
+ *
* @param source address to set as source
*/
void (*set_source) (packet_t *packet, host_t *source);
-
+
/**
* Set the destination address.
- *
+ *
* Set host_t is now owned by packet_t, it will destroy
* it if necessary.
- *
+ *
* @param source address to set as destination
*/
void (*set_destination) (packet_t *packet, host_t *destination);
-
+
/**
* Get the source address.
- *
+ *
* Set host_t is still owned by packet_t, clone it
* if needed.
- *
+ *
* @return source address
*/
host_t *(*get_source) (packet_t *packet);
-
+
/**
* Get the destination address.
- *
+ *
* Set host_t is still owned by packet_t, clone it
* if needed.
- *
+ *
* @return destination address
*/
host_t *(*get_destination) (packet_t *packet);
-
+
/**
* Get the data from the packet.
- *
- * The data pointed by the chunk is still owned
+ *
+ * The data pointed by the chunk is still owned
* by the packet. Clone it if needed.
- *
+ *
* @return chunk containing the data
*/
chunk_t (*get_data) (packet_t *packet);
-
+
/**
* Set the data in the packet.
- *
- * Supplied chunk data is now owned by the
+ *
+ * Supplied chunk data is now owned by the
* packet. It will free it.
- *
+ *
* @param data chunk with data to set
*/
void (*set_data) (packet_t *packet, chunk_t data);
-
+
/**
* Clones a packet_t object.
- *
+ *
* @param clone clone of the packet
*/
packet_t* (*clone) (packet_t *packet);
-
+
/**
* Destroy the packet, freeing contained data.
*/
@@ -107,7 +107,7 @@ struct packet_t {
/**
* create an empty packet
- *
+ *
* @return packet_t object
*/
packet_t *packet_create(void);
diff --git a/src/charon/network/receiver.c b/src/charon/network/receiver.c
index ab4d6d592..6cd99439b 100644
--- a/src/charon/network/receiver.c
+++ b/src/charon/network/receiver.c
@@ -17,7 +17,6 @@
#include <stdlib.h>
#include <unistd.h>
-#include <pthread.h>
#include "receiver.h"
@@ -50,57 +49,52 @@ struct private_receiver_t {
* Public part of a receiver_t object.
*/
receiver_t public;
-
+
/**
* Threads job receiving packets
*/
callback_job_t *job;
-
- /**
- * Assigned thread.
- */
- pthread_t assigned_thread;
-
+
/**
* current secret to use for cookie calculation
*/
char secret[SECRET_LENGTH];
-
+
/**
* previous secret used to verify older cookies
*/
char secret_old[SECRET_LENGTH];
-
+
/**
* how many times we have used "secret" so far
*/
u_int32_t secret_used;
-
+
/**
* time we did the cookie switch
*/
u_int32_t secret_switch;
-
+
/**
* time offset to use, hides our system time
*/
u_int32_t secret_offset;
-
+
/**
* the RNG to use for secret generation
*/
rng_t *rng;
-
+
/**
* hasher to use for cookie calculation
*/
hasher_t *hasher;
-
+
/**
* require cookies after this many half open IKE_SAs
*/
u_int32_t cookie_threshold;
-
+
/**
* how many half open IKE_SAs per peer before blocking
*/
@@ -119,7 +113,7 @@ static void send_notify(message_t *request, notify_type_t type, chunk_t data)
host_t *src, *dst;
packet_t *packet;
ike_sa_id_t *ike_sa_id;
-
+
response = message_create();
dst = request->get_source(request);
src = request->get_destination(request);
@@ -149,7 +143,7 @@ static chunk_t cookie_build(private_receiver_t *this, message_t *message,
u_int64_t spi = message->get_initiator_spi(message);
host_t *ip = message->get_source(message);
chunk_t input, hash;
-
+
/* COOKIE = t | sha1( IPi | SPIi | t | secret ) */
input = chunk_cata("cccc", ip->get_address(ip), chunk_from_thing(spi),
chunk_from_thing(t), secret);
@@ -167,18 +161,18 @@ static bool cookie_verify(private_receiver_t *this, message_t *message,
u_int32_t t, now;
chunk_t reference;
chunk_t secret;
-
- now = time(NULL);
+
+ now = time_monotonic(NULL);
t = *(u_int32_t*)cookie.ptr;
-
+
if (cookie.len != sizeof(u_int32_t) +
- this->hasher->get_hash_size(this->hasher) ||
+ this->hasher->get_hash_size(this->hasher) ||
t < now - this->secret_offset - COOKIE_LIFETIME)
{
DBG2(DBG_NET, "received cookie lifetime expired, rejecting");
- return FALSE;
+ return FALSE;
}
-
+
/* check if cookie is derived from old_secret */
if (t + this->secret_offset > this->secret_switch)
{
@@ -188,7 +182,7 @@ static bool cookie_verify(private_receiver_t *this, message_t *message,
{
secret = chunk_from_thing(this->secret_old);
}
-
+
/* compare own calculation against received */
reference = cookie_build(this, message, t, secret);
if (chunk_equals(reference, cookie))
@@ -206,20 +200,20 @@ static bool cookie_verify(private_receiver_t *this, message_t *message,
static bool cookie_required(private_receiver_t *this, message_t *message)
{
bool failed = FALSE;
-
+
if (charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager,
NULL) >= this->cookie_threshold)
{
/* check for a cookie. We don't use our parser here and do it
- * quick and dirty for performance reasons.
- * we assume the cookie is the first payload (which is a MUST), and
+ * quick and dirty for performance reasons.
+ * we assume the cookie is the first payload (which is a MUST), and
* the cookie's SPI length is zero. */
packet_t *packet = message->get_packet(message);
chunk_t data = packet->get_data(packet);
- if (data.len <
+ if (data.len <
IKE_HEADER_LENGTH + NOTIFY_PAYLOAD_HEADER_LENGTH +
sizeof(u_int32_t) + this->hasher->get_hash_size(this->hasher) ||
- *(data.ptr + 16) != NOTIFY ||
+ *(data.ptr + 16) != NOTIFY ||
*(u_int16_t*)(data.ptr + IKE_HEADER_LENGTH + 6) != htons(COOKIE))
{
/* no cookie found */
@@ -261,14 +255,14 @@ static job_requeue_t receive_packets(private_receiver_t *this)
packet_t *packet;
message_t *message;
job_t *job;
-
+
/* read in a packet */
if (charon->socket->receive(charon->socket, &packet) != SUCCESS)
{
DBG2(DBG_NET, "receiving from socket failed!");
return JOB_REQUEUE_FAIR;
}
-
+
/* parse message header */
message = message_create_from_packet(packet);
if (message->parse_header(message) != SUCCESS)
@@ -278,28 +272,28 @@ static job_requeue_t receive_packets(private_receiver_t *this)
message->destroy(message);
return JOB_REQUEUE_DIRECT;
}
-
+
/* check IKE major version */
if (message->get_major_version(message) != IKE_MAJOR_VERSION)
{
DBG1(DBG_NET, "received unsupported IKE version %d.%d from %H, "
- "sending INVALID_MAJOR_VERSION", message->get_major_version(message),
+ "sending INVALID_MAJOR_VERSION", message->get_major_version(message),
message->get_minor_version(message), packet->get_source(packet));
send_notify(message, INVALID_MAJOR_VERSION, chunk_empty);
message->destroy(message);
return JOB_REQUEUE_DIRECT;
}
-
+
if (message->get_request(message) &&
message->get_exchange_type(message) == IKE_SA_INIT)
{
/* check for cookies */
if (this->cookie_threshold && cookie_required(this, message))
{
- u_int32_t now = time(NULL);
+ u_int32_t now = time_monotonic(NULL);
chunk_t cookie = cookie_build(this, message, now - this->secret_offset,
- chunk_from_thing(this->secret));
-
+ chunk_from_thing(this->secret));
+
DBG2(DBG_NET, "received packet from: %#H to %#H",
message->get_source(message),
message->get_destination(message));
@@ -312,7 +306,7 @@ static job_requeue_t receive_packets(private_receiver_t *this)
/* create new cookie */
DBG1(DBG_NET, "generating new cookie secret after %d uses",
this->secret_used);
- memcpy(this->secret_old, this->secret, SECRET_LENGTH);
+ memcpy(this->secret_old, this->secret, SECRET_LENGTH);
this->rng->get_bytes(this->rng, SECRET_LENGTH, this->secret);
this->secret_switch = now;
this->secret_used = 0;
@@ -320,7 +314,7 @@ static job_requeue_t receive_packets(private_receiver_t *this)
message->destroy(message);
return JOB_REQUEUE_DIRECT;
}
-
+
/* check if peer has not too many IKE_SAs half open */
if (this->block_threshold && peer_to_aggressive(this, message))
{
@@ -352,10 +346,10 @@ static void destroy(private_receiver_t *this)
receiver_t *receiver_create()
{
private_receiver_t *this = malloc_thing(private_receiver_t);
- u_int32_t now = time(NULL);
-
+ u_int32_t now = time_monotonic(NULL);
+
this->public.destroy = (void(*)(receiver_t*)) destroy;
-
+
this->hasher = lib->crypto->create_hasher(lib->crypto, HASH_PREFERRED);
if (this->hasher == NULL)
{
@@ -385,11 +379,11 @@ receiver_t *receiver_create()
this->cookie_threshold = 0;
this->block_threshold = 0;
}
-
+
this->job = callback_job_create((callback_job_cb_t)receive_packets,
this, NULL, NULL);
charon->processor->queue_job(charon->processor, (job_t*)this->job);
-
+
return &this->public;
}
diff --git a/src/charon/network/receiver.h b/src/charon/network/receiver.h
index 87797634e..690d8dbab 100644
--- a/src/charon/network/receiver.h
+++ b/src/charon/network/receiver.h
@@ -29,7 +29,7 @@ typedef struct receiver_t receiver_t;
/**
* Receives packets from the socket and adds them to the job queue.
- *
+ *
* The receiver starts a thread, wich reads on the blocking socket. A received
* packet is preparsed and a process_message_job is queued in the job queue.
*
@@ -41,16 +41,16 @@ typedef struct receiver_t receiver_t;
* find out wich key was used for cookie creation. Further, we can set a
* lifetime for the cookie, which allows us to reuse the secret for a longer
* time.
- * COOKIE = time | sha1( IPi | SPIi | time | secret )
+ * COOKIE = time | sha1( IPi | SPIi | time | secret )
*
* The secret is changed after a certain amount of cookies sent. The old
* secret is stored to allow a clean migration between secret changes.
- *
+ *
* Further, the number of half-initiated IKE_SAs is limited per peer. This
* mades it impossible for a peer to flood the server with its real IP address.
*/
struct receiver_t {
-
+
/**
* Destroys a receiver_t object.
*/
@@ -59,10 +59,10 @@ struct receiver_t {
/**
* Create a receiver_t object.
- *
+ *
* The receiver thread will start working, get data
* from the socket and add those packets to the job queue.
- *
+ *
* @return receiver_t object, NULL if initialization fails
*/
receiver_t * receiver_create(void);
diff --git a/src/charon/network/sender.c b/src/charon/network/sender.c
index 19f589115..3be5861dd 100644
--- a/src/charon/network/sender.c
+++ b/src/charon/network/sender.c
@@ -15,14 +15,15 @@
*/
#include <stdlib.h>
-#include <pthread.h>
#include "sender.h"
#include <daemon.h>
#include <network/socket.h>
#include <processing/jobs/callback_job.h>
-#include <utils/mutex.h>
+#include <threading/thread.h>
+#include <threading/condvar.h>
+#include <threading/mutex.h>
typedef struct private_sender_t private_sender_t;
@@ -40,7 +41,7 @@ struct private_sender_t {
* Sender threads job.
*/
callback_job_t *job;
-
+
/**
* The packets are stored in a linked list
*/
@@ -55,7 +56,7 @@ struct private_sender_t {
* condvar to signal for packets added to list
*/
condvar_t *got;
-
+
/**
* condvar to signal for packets sent
*/
@@ -68,11 +69,11 @@ struct private_sender_t {
static void send_(private_sender_t *this, packet_t *packet)
{
host_t *src, *dst;
-
+
src = packet->get_source(packet);
dst = packet->get_destination(packet);
DBG1(DBG_NET, "sending packet: from %#H to %#H", src, dst);
-
+
this->mutex->lock(this->mutex);
this->list->insert_last(this->list, packet);
this->got->signal(this->got);
@@ -85,24 +86,24 @@ static void send_(private_sender_t *this, packet_t *packet)
static job_requeue_t send_packets(private_sender_t * this)
{
packet_t *packet;
- int oldstate;
-
+ bool oldstate;
+
this->mutex->lock(this->mutex);
while (this->list->get_count(this->list) == 0)
{
/* add cleanup handler, wait for packet, remove cleanup handler */
- pthread_cleanup_push((void(*)(void*))this->mutex->unlock, this->mutex);
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
-
+ thread_cleanup_push((thread_cleanup_t)this->mutex->unlock, this->mutex);
+ oldstate = thread_cancelability(TRUE);
+
this->got->wait(this->got, this->mutex);
-
- pthread_setcancelstate(oldstate, NULL);
- pthread_cleanup_pop(0);
+
+ thread_cancelability(oldstate);
+ thread_cleanup_pop(FALSE);
}
this->list->remove_first(this->list, (void**)&packet);
this->sent->signal(this->sent);
this->mutex->unlock(this->mutex);
-
+
charon->socket->send(charon->socket, packet);
packet->destroy(packet);
return JOB_REQUEUE_DIRECT;
@@ -134,19 +135,19 @@ static void destroy(private_sender_t *this)
sender_t * sender_create()
{
private_sender_t *this = malloc_thing(private_sender_t);
-
+
this->public.send = (void(*)(sender_t*,packet_t*))send_;
this->public.destroy = (void(*)(sender_t*)) destroy;
-
+
this->list = linked_list_create();
this->mutex = mutex_create(MUTEX_TYPE_DEFAULT);
this->got = condvar_create(CONDVAR_TYPE_DEFAULT);
this->sent = condvar_create(CONDVAR_TYPE_DEFAULT);
-
+
this->job = callback_job_create((callback_job_cb_t)send_packets,
this, NULL, NULL);
charon->processor->queue_job(charon->processor, (job_t*)this->job);
-
+
return &this->public;
}
diff --git a/src/charon/network/sender.h b/src/charon/network/sender.h
index 55f67af70..f77fadab2 100644
--- a/src/charon/network/sender.h
+++ b/src/charon/network/sender.h
@@ -31,7 +31,7 @@ typedef struct sender_t sender_t;
* Thread responsible for sending packets over the socket.
*/
struct sender_t {
-
+
/**
* Send a packet over the network.
*
@@ -39,10 +39,10 @@ struct sender_t {
* Whenever the sender thread thinks it's good to send the packet,
* it'll do so.
*
- * @param packet packet to send
+ * @param packet packet to send
*/
void (*send) (sender_t *this, packet_t *packet);
-
+
/**
* Destroys a sender object.
*/
@@ -51,10 +51,10 @@ struct sender_t {
/**
* Create the sender thread.
- *
+ *
* The thread will start to work, getting packets
* from its queue and sends them out.
- *
+ *
* @return created sender object
*/
sender_t * sender_create(void);
diff --git a/src/charon/network/socket-raw.c b/src/charon/network/socket-raw.c
index 148be486c..6cc0463b2 100644
--- a/src/charon/network/socket-raw.c
+++ b/src/charon/network/socket-raw.c
@@ -18,7 +18,6 @@
/* for struct in6_pktinfo */
#define _GNU_SOURCE
-#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
@@ -38,6 +37,7 @@
#include "socket.h"
#include <daemon.h>
+#include <threading/thread.h>
/* constants for packet handling */
#define IP_LEN sizeof(struct iphdr)
@@ -85,12 +85,12 @@ struct private_socket_t{
* port used for nat-t
*/
int natt_port;
-
+
/**
* raw receiver socket for IPv4
*/
int recv4;
-
+
/**
* raw receiver socket for IPv6
*/
@@ -127,12 +127,12 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
packet_t *pkt;
struct udphdr *udp;
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;
FD_ZERO(&rfds);
-
+
if (this->recv4)
{
FD_SET(this->recv4, &rfds);
@@ -141,24 +141,24 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
{
FD_SET(this->recv6, &rfds);
}
-
+
DBG2(DBG_NET, "waiting for data on raw sockets");
-
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
+
+ oldstate = thread_cancelability(TRUE);
if (select(max(this->recv4, this->recv6) + 1, &rfds, NULL, NULL, NULL) <= 0)
{
- pthread_setcancelstate(oldstate, NULL);
+ thread_cancelability(oldstate);
return FAILED;
}
- pthread_setcancelstate(oldstate, NULL);
-
+ thread_cancelability(oldstate);
+
if (this->recv4 && FD_ISSET(this->recv4, &rfds))
{
/* IPv4 raw sockets return the IP header. We read src/dest
* information directly from the raw header */
struct iphdr *ip;
struct sockaddr_in src, dst;
-
+
bytes_read = recv(this->recv4, buffer, MAX_PACKET, 0);
if (bytes_read < 0)
{
@@ -166,7 +166,7 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
return FAILED;
}
DBG3(DBG_NET, "received IPv4 packet %b", buffer, bytes_read);
-
+
/* read source/dest from raw IP/UDP header */
if (bytes_read < IP_LEN + UDP_LEN + MARKER_LEN)
{
@@ -184,13 +184,13 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
dst.sin_port = udp->dest;
source = host_create_from_sockaddr((sockaddr_t*)&src);
dest = host_create_from_sockaddr((sockaddr_t*)&dst);
-
+
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 = IP_LEN + UDP_LEN;
- /* remove non esp marker */
+ /* remove non esp marker */
if (dest->get_port(dest) == IKEV2_NATT_PORT)
{
data_offset += MARKER_LEN;
@@ -210,7 +210,7 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
struct sockaddr_in6 src, dst;
struct iovec iov;
char ancillary[64];
-
+
msg.msg_name = &src;
msg.msg_namelen = sizeof(src);
iov.iov_base = buffer;
@@ -220,7 +220,7 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
msg.msg_control = ancillary;
msg.msg_controllen = sizeof(ancillary);
msg.msg_flags = 0;
-
+
bytes_read = recvmsg(this->recv6, &msg, 0);
if (bytes_read < 0)
{
@@ -228,14 +228,14 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
return FAILED;
}
DBG3(DBG_NET, "received IPv6 packet %b", buffer, bytes_read);
-
+
if (bytes_read < IP_LEN + UDP_LEN + MARKER_LEN)
{
DBG3(DBG_NET, "received IPv6 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))
@@ -244,13 +244,13 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
{
DBG1(DBG_NET, "error reading IPv6 ancillary data");
return FAILED;
- }
+ }
if (cmsgptr->cmsg_level == SOL_IPV6 &&
cmsgptr->cmsg_type == IPV6_2292PKTINFO)
{
struct in6_pktinfo *pktinfo;
pktinfo = (struct in6_pktinfo*)CMSG_DATA(cmsgptr);
-
+
memset(&dst, 0, sizeof(dst));
memcpy(&dst.sin6_addr, &pktinfo->ipi6_addr, sizeof(dst.sin6_addr));
dst.sin6_family = AF_INET6;
@@ -266,15 +266,15 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
DBG1(DBG_NET, "error reading IPv6 packet header");
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 = UDP_LEN;
- /* remove non esp marker */
+ /* remove non esp marker */
if (dest->get_port(dest) == IKEV2_NATT_PORT)
{
data_offset += MARKER_LEN;
@@ -290,7 +290,7 @@ static status_t receiver(private_socket_t *this, packet_t **packet)
/* oops, shouldn't happen */
return FAILED;
}
-
+
/* return packet */
*packet = pkt;
return SUCCESS;
@@ -308,13 +308,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);
@@ -362,7 +362,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);
@@ -371,7 +371,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)
@@ -379,7 +379,7 @@ status_t sender(private_socket_t *this, packet_t *packet)
char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
struct in_pktinfo *pktinfo;
struct sockaddr_in *sin;
-
+
msg.msg_control = buf;
msg.msg_controllen = sizeof(buf);
cmsg = CMSG_FIRSTHDR(&msg);
@@ -396,7 +396,7 @@ status_t sender(private_socket_t *this, packet_t *packet)
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);
@@ -409,7 +409,7 @@ status_t sender(private_socket_t *this, packet_t *packet)
memcpy(&pktinfo->ipi6_addr, &sin->sin6_addr, sizeof(struct in6_addr));
}
}
-
+
bytes_sent = sendmsg(skt, &msg, 0);
if (bytes_sent != data.len)
@@ -430,7 +430,7 @@ static int open_send_socket(private_socket_t *this, int family, u_int16_t port)
struct sockaddr_storage addr;
u_int sol;
int skt;
-
+
memset(&addr, 0, sizeof(addr));
/* precalculate constants depending on address family */
switch (family)
@@ -456,14 +456,14 @@ static int open_send_socket(private_socket_t *this, int family, u_int16_t port)
default:
return 0;
}
-
+
skt = socket(family, SOCK_DGRAM, IPPROTO_UDP);
if (skt < 0)
{
DBG1(DBG_NET, "could not open send socket: %s", strerror(errno));
return 0;
}
-
+
if (setsockopt(skt, SOL_SOCKET, SO_REUSEADDR, (void*)&on, sizeof(on)) < 0)
{
DBG1(DBG_NET, "unable to set SO_REUSEADDR on send socket: %s",
@@ -471,7 +471,7 @@ static int open_send_socket(private_socket_t *this, int family, u_int16_t port)
close(skt);
return 0;
}
-
+
/* bind the send socket */
if (bind(skt, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
@@ -480,7 +480,7 @@ static int open_send_socket(private_socket_t *this, int family, u_int16_t port)
close(skt);
return 0;
}
-
+
if (family == AF_INET)
{
/* enable UDP decapsulation globally, only for one socket needed */
@@ -490,7 +490,7 @@ static int open_send_socket(private_socket_t *this, int family, u_int16_t port)
strerror(errno));
}
}
-
+
return skt;
}
@@ -502,7 +502,7 @@ static int open_recv_socket(private_socket_t *this, int family)
int skt;
int on = TRUE;
u_int proto_offset, ip_len, sol, udp_header, ike_header;
-
+
/* precalculate constants depending on address family */
switch (family)
{
@@ -521,7 +521,7 @@ static int open_recv_socket(private_socket_t *this, int family)
}
udp_header = ip_len;
ike_header = ip_len + UDP_LEN;
-
+
/* This filter code filters out all non-IKEv2 traffic on
* a SOCK_RAW IP_PROTP_UDP socket. Handling of other
* IKE versions is done in pluto.
@@ -560,7 +560,7 @@ static int open_recv_socket(private_socket_t *this, int family)
sizeof(ikev2_filter_code) / sizeof(struct sock_filter),
ikev2_filter_code
};
-
+
/* set up a raw socket */
skt = socket(family, SOCK_RAW, IPPROTO_UDP);
if (skt < 0)
@@ -568,7 +568,7 @@ static int open_recv_socket(private_socket_t *this, int family)
DBG1(DBG_NET, "unable to create raw socket: %s", strerror(errno));
return 0;
}
-
+
if (setsockopt(skt, SOL_SOCKET, SO_ATTACH_FILTER,
&ikev2_filter, sizeof(ikev2_filter)) < 0)
{
@@ -577,7 +577,7 @@ static int open_recv_socket(private_socket_t *this, int family)
close(skt);
return 0;
}
-
+
if (family == AF_INET6 &&
/* we use IPV6_2292PKTINFO, as IPV6_PKTINFO is defined as
* 2 or 50 depending on kernel header version */
@@ -588,7 +588,7 @@ static int open_recv_socket(private_socket_t *this, int family)
close(skt);
return 0;
}
-
+
return skt;
}
@@ -621,7 +621,7 @@ static bool enumerate(socket_enumerator_t *this, int *fd, int *family, int *port
{ offsetof(private_socket_t, send4_natt), AF_INET, IKEV2_NATT_PORT },
{ offsetof(private_socket_t, send6_natt), AF_INET6, IKEV2_NATT_PORT }
};
-
+
while(++this->index < countof(sockets))
{
int sock = *(int*)((char*)this->socket + sockets[this->index].fd_offset);
@@ -643,7 +643,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;
@@ -690,20 +690,20 @@ static void destroy(private_socket_t *this)
socket_t *socket_create()
{
private_socket_t *this = malloc_thing(private_socket_t);
-
+
/* public functions */
this->public.send = (status_t(*)(socket_t*, packet_t*))sender;
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->recv4 = 0;
this->recv6 = 0;
this->send4 = 0;
this->send6 = 0;
this->send4_natt = 0;
this->send6_natt = 0;
-
+
this->recv4 = open_recv_socket(this, AF_INET);
if (this->recv4 == 0)
{
@@ -726,7 +726,7 @@ socket_t *socket_create()
}
}
}
-
+
this->recv6 = open_recv_socket(this, AF_INET6);
if (this->recv6 == 0)
{
@@ -749,13 +749,13 @@ socket_t *socket_create()
}
}
}
-
+
if (!(this->send4 || this->send6) || !(this->recv4 || this->recv6))
{
DBG1(DBG_NET, "could not create any sockets");
destroy(this);
charon->kill(charon, "socket initialization failed");
}
-
+
return (socket_t*)this;
}
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;
}
diff --git a/src/charon/network/socket.h b/src/charon/network/socket.h
index 81f2ec5fe..83bb9d4c9 100644
--- a/src/charon/network/socket.h
+++ b/src/charon/network/socket.h
@@ -44,48 +44,48 @@ typedef struct socket_t socket_t;
* All available sockets are bound and the receive function
* reads from them. There are actually two implementations:
* The first uses raw sockets to allow binding of other daemons (pluto) to
- * UDP/500. An installed "Linux socket filter" filters out all non-IKEv2
- * traffic and handles just IKEv2 messages. An other daemon (pluto) must
- * handle all traffic separately, e.g. ignore IKEv2 traffic, since charon
+ * UDP/500. An installed "Linux socket filter" filters out all non-IKEv2
+ * traffic and handles just IKEv2 messages. An other daemon (pluto) must
+ * handle all traffic separately, e.g. ignore IKEv2 traffic, since charon
* handles that.
* The other implementation uses normal sockets and is built if
* --disable-pluto is given to the configure script.
*/
struct socket_t {
-
+
/**
* Receive a packet.
- *
+ *
* Reads a packet from the socket and sets source/dest
* appropriately.
- *
+ *
* @param packet pinter gets address from allocated packet_t
- * @return
+ * @return
* - SUCCESS when packet successfully received
* - FAILED when unable to receive
*/
status_t (*receive) (socket_t *this, packet_t **packet);
-
+
/**
* Send a packet.
- *
+ *
* Sends a packet to the net using source and destination addresses of
* the packet.
- *
+ *
* @param packet packet_t to send
- * @return
+ * @return
* - SUCCESS when packet successfully sent
* - FAILED when unable to send
*/
status_t (*send) (socket_t *this, packet_t *packet);
-
+
/**
* Enumerate all underlying socket file descriptors.
- *
+ *
* @return enumerator over (int fd, int family, int port)
*/
enumerator_t *(*create_enumerator) (socket_t *this);
-
+
/**
* Destroy socket.
*/