summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2012-02-26 23:13:08 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2012-02-26 23:13:08 +0100
commit13306fc146b4839d511287f29df8572a80bf8914 (patch)
tree081330075fabb3a93b0c9c49b9f9f2317934381e
parent57a63fc9304e71ddd2cf434cc4c8789a1a3a3c88 (diff)
downloadfastd-13306fc146b4839d511287f29df8572a80bf8914.tar
fastd-13306fc146b4839d511287f29df8572a80bf8914.zip
Implement I/O for a fixed peer
-rw-r--r--src/Makefile13
-rw-r--r--src/fastd.c219
-rw-r--r--src/fastd.h64
-rw-r--r--src/handshake.c95
-rw-r--r--src/handshake.h36
-rw-r--r--src/method_null.c18
-rw-r--r--src/packet.h7
-rw-r--r--src/queue.h74
-rw-r--r--src/task.c63
-rw-r--r--src/task.h69
10 files changed, 582 insertions, 76 deletions
diff --git a/src/Makefile b/src/Makefile
index 90619ec..caa6f9f 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,10 +1,11 @@
all : fastd
-fastd : fastd.o method_null.o
- gcc -Wall -o $@ $^
+fastd : fastd.o method_null.o task.o handshake.o
-fastd.o : fastd.c fastd.h packet.h
- gcc -Wall -c -o $@ $<
+fastd.o : fastd.c fastd.h task.h queue.h handshake.h
+handshake.o : handshake.c packet.h handshake.h
+method_null.o : method_null.c fastd.h task.h
+task.o : task.c task.h queue.h
-method_null.o : method_null.c fastd.h
- gcc -Wall -c -o $@ $<
+clean :
+ rm -f fastd fastd.o method_null.o task.o
diff --git a/src/fastd.c b/src/fastd.c
index 42478b2..b0cf3b4 100644
--- a/src/fastd.c
+++ b/src/fastd.c
@@ -25,8 +25,12 @@
*/
+#include "fastd.h"
+#include "handshake.h"
+#include "task.h"
+
+#include <arpa/inet.h>
#include <fcntl.h>
-#include <linux/if_ether.h>
#include <linux/if_tun.h>
#include <net/if.h>
#include <poll.h>
@@ -36,120 +40,227 @@
#include <sys/socket.h>
#include <unistd.h>
-#include "fastd.h"
-#include "packet.h"
-
extern fastd_method fastd_method_null;
-static int init_tuntap(const fastd_context *ctx) {
- int tunfd;
+static void init_tuntap(fastd_context *ctx) {
struct ifreq ifr;
pr_debug(ctx, "Initializing tun/tap device...");
- if ((tunfd = open("/dev/net/tun", O_RDWR)) < 0)
- exit_fatal_errno(ctx, "Could not open tun/tap device file");
+ if ((ctx->tunfd = open("/dev/net/tun", O_RDWR)) < 0)
+ exit_errno(ctx, "Could not open tun/tap device file");
memset(&ifr, 0, sizeof(ifr));
- // strcpy(ifr.ifr_name, name);
+
+ if (ctx->conf->ifname)
+ strncpy(ifr.ifr_name, ctx->conf->ifname, IF_NAMESIZE-1);
+
ifr.ifr_flags = IFF_TAP;
ifr.ifr_flags |= IFF_NO_PI;
- if (ioctl(tunfd, TUNSETIFF, (void *)&ifr) < 0)
- exit_fatal_errno(ctx, "TUNSETIFF ioctl failed");
+ if (ioctl(ctx->tunfd, TUNSETIFF, (void *)&ifr) < 0)
+ exit_errno(ctx, "TUNSETIFF ioctl failed");
- return tunfd;
+ pr_debug(ctx, "Tun/tap device initialized.");
+}
+
+static void init_socket(fastd_context *ctx) {
+ pr_debug(ctx, "Initializing UDP socket...");
+
+ if ((ctx->sockfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ exit_errno(ctx, "socket");
+
+ struct sockaddr_in bindaddr;
+ bindaddr.sin_family = AF_INET;
+ bindaddr.sin_addr.s_addr = ctx->conf->bind_address;
+ bindaddr.sin_port = ctx->conf->bind_port;
+
+ if (bind(ctx->sockfd, (struct sockaddr*)&bindaddr, sizeof(struct sockaddr_in)))
+ exit_errno(ctx, "bind");
+
+ pr_debug(ctx, "UDP socket initialized.");
}
static void configure(fastd_context *ctx, fastd_config *conf) {
conf->loglevel = LOG_DEBUG;
+ conf->ifname = NULL;
+ conf->bind_address = htonl(INADDR_ANY);
+ conf->bind_port = htons(1337);
conf->mtu = 1500;
conf->protocol = PROTOCOL_ETHERNET;
conf->method = &fastd_method_null;
- conf->n_peers = 0;
- conf->peers = NULL;
-}
-static size_t get_max_packet_size(const fastd_context *ctx) {
- switch (ctx->conf->protocol) {
- case PROTOCOL_ETHERNET:
- return ctx->conf->mtu+ETH_HLEN;
- case PROTOCOL_IP:
- return ctx->conf->mtu;
- default:
- exit_fatal_bug(ctx, "invalid protocol");
+ conf->peers = malloc(sizeof(fastd_peer_config));
+ conf->peers->next = NULL;
+ conf->peers->address = inet_addr("172.22.184.1");
+ conf->peers->port = htons(1337);
+
+ ctx->peers = NULL;
+ fastd_peer **current_peer = &ctx->peers;
+
+ for (fastd_peer_config *peer_conf = conf->peers; peer_conf; peer_conf = peer_conf->next) {
+ *current_peer = malloc(sizeof(fastd_peer));
+ (*current_peer)->next = NULL;
+ (*current_peer)->config = peer_conf;
+ (*current_peer)->address = peer_conf->address;
+ (*current_peer)->port = peer_conf->port;
+ (*current_peer)->state = STATE_WAIT;
+ (*current_peer)->last_req_id = 0;
+ (*current_peer)->addresses = NULL;
+
+ current_peer = &(*current_peer)->next;
}
}
-static void *get_source_address(const fastd_context *ctx, void *buffer) {
+static void* get_source_address(const fastd_context *ctx, void *buffer) {
switch (ctx->conf->protocol) {
case PROTOCOL_ETHERNET:
return &((struct ethhdr*)buffer)->h_source;
case PROTOCOL_IP:
return NULL;
default:
- exit_fatal_bug(ctx, "invalid protocol");
+ exit_bug(ctx, "invalid protocol");
}
}
-static void *get_dest_address(const fastd_context *ctx, void *buffer) {
+static void* get_dest_address(const fastd_context *ctx, void *buffer) {
switch (ctx->conf->protocol) {
case PROTOCOL_ETHERNET:
return &((struct ethhdr*)buffer)->h_dest;
case PROTOCOL_IP:
return NULL;
default:
- exit_fatal_bug(ctx, "invalid protocol");
+ exit_bug(ctx, "invalid protocol");
}
}
-static void run(const fastd_context *ctx) {
- int tunfd;
+static void handle_tasks(fastd_context *ctx) {
+ fastd_task *task;
+ while ((task = fastd_task_get(ctx)) != NULL) {
+ switch (task->type) {
+ case TASK_SEND:
+ if (task->send.peer) {
+ struct msghdr msg;
+ memset(&msg, 0, sizeof(msg));
+
+ struct sockaddr_in sendaddr;
+ sendaddr.sin_family = AF_INET;
+ sendaddr.sin_addr.s_addr = task->send.peer->address;
+ sendaddr.sin_port = task->send.peer->port;
+
+ msg.msg_name = &sendaddr;
+ msg.msg_namelen = sizeof(sendaddr);
+
+ struct iovec vec[2] = { { .iov_base = &task->send.packet_type, .iov_len = 1 }, task->send.buffer };
+
+ msg.msg_iov = vec;
+ msg.msg_iovlen = 2;
+
+ sendmsg(ctx->sockfd, &msg, 0);
+ }
+
+ free(task->send.buffer.iov_base);
+ break;
+
+ case TASK_HANDLE_RECV:
+ // TODO Handle source address
+ writev(ctx->tunfd, &task->handle_recv.buffer, 1);
+ free(task->handle_recv.buffer.iov_base);
+ break;
+
+ default:
+ exit_bug(ctx, "invalid task type");
+ }
- tunfd = init_tuntap(ctx);
+ free(task);
+ }
+}
- struct pollfd fds[ctx->conf->n_peers+1];
- fds[0].fd = tunfd;
+static void handle_input(fastd_context *ctx) {
+ struct pollfd fds[2];
+ fds[0].fd = ctx->tunfd;
fds[0].events = POLLIN;
+ fds[1].fd = ctx->sockfd;
+ fds[1].events = POLLIN;
- while (1) {
- int ret = poll(fds, 1, -1);
- if (ret < 0)
- exit_fatal_errno(ctx, "poll error");
+ int ret = poll(fds, 2, -1);
+ if (ret < 0)
+ exit_errno(ctx, "poll");
+
+ if (fds[0].revents & POLLIN) {
+ size_t max_len = fastd_max_packet_size(ctx);
+ void *buffer = malloc(max_len);
- if (fds[0].revents & POLLIN) {
- size_t max_len = get_max_packet_size(ctx);
- char buffer[max_len];
+ ssize_t len = read(ctx->tunfd, buffer, max_len);
+ if (len < 0)
+ exit_errno(ctx, "read");
- unsigned len = read(tunfd, buffer, max_len);
- if (len < 0)
- exit_fatal_errno(ctx, "read");
+ uint8_t *src_addr = get_source_address(ctx, buffer);
+ uint8_t *dest_addr = get_dest_address(ctx, buffer);
- uint8_t *src_addr = get_source_address(ctx, buffer);
- uint8_t *dest_addr = get_dest_address(ctx, buffer);
+ pr_debug(ctx, "A packet with length %u is to be sent from %02x:%02x:%02x:%02x:%02x:%02x to %02x:%02x:%02x:%02x:%02x:%02x",
+ (unsigned)len, src_addr[0], src_addr[1], src_addr[2], src_addr[3], src_addr[4], src_addr[5],
+ dest_addr[0], dest_addr[1], dest_addr[2], dest_addr[3], dest_addr[4], dest_addr[5]);
- pr_debug(ctx, "A packet with length %u was received from %02x:%02x:%02x:%02x:%02x:%02x to %02x:%02x:%02x:%02x:%02x:%02x",
- len, src_addr[0], src_addr[1], src_addr[2], src_addr[3], src_addr[4], src_addr[5],
- dest_addr[0], dest_addr[1], dest_addr[2], dest_addr[3], dest_addr[4], dest_addr[5]);
+ // TODO find correct peer
- ctx->conf->method->method_send(ctx, buffer, len);
+ struct iovec vec = { .iov_base = buffer, .iov_len = len };
+ ctx->conf->method->method_send(ctx, ctx->peers, vec);
+ }
+ if (fds[1].revents & POLLIN) {
+ size_t max_len = ctx->conf->method->method_max_packet_size(ctx); // 1 is the packet type header
+ void *buffer = malloc(max_len);
+
+ uint8_t packet_type;
+
+ struct iovec vec[2] = {{ .iov_base = &packet_type, .iov_len = 1 }, { .iov_base = buffer, .iov_len = max_len }};
+ struct sockaddr_in recvaddr;
+
+ struct msghdr msg;
+ memset(&msg, 0, sizeof(msg));
+
+ msg.msg_name = &recvaddr;
+ msg.msg_namelen = sizeof(recvaddr);
+ msg.msg_iov = vec;
+ msg.msg_iovlen = 2;
+
+ ssize_t len = recvmsg(ctx->sockfd, &msg, 0);
+ if (len < 0)
+ pr_warn(ctx, "recvfrom: %s", strerror(errno));
+
+ // TODO get peer
+
+ switch (packet_type) {
+ case 0:
+ vec[1].iov_len = len - 1;
+ ctx->conf->method->method_handle_recv(ctx, NULL, vec[1]);
+ break;
+
+ default:
+ fastd_handshake_handle(ctx, NULL, packet_type, vec[1]);
+ free(buffer);
+ break;
}
}
}
-int main()
-{
- fastd_context ctx = {
- .conf = NULL,
- };
+int main() {
+ fastd_context ctx;
+ memset(&ctx, 0, sizeof(ctx));
fastd_config conf;
configure(&ctx, &conf);
ctx.conf = &conf;
- run(&ctx);
+ init_tuntap(&ctx);
+ init_socket(&ctx);
+
+ while (1) {
+ handle_tasks(&ctx);
+ handle_input(&ctx);
+ }
return 0;
}
diff --git a/src/fastd.h b/src/fastd.h
index 06b69b2..16be512 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -28,11 +28,16 @@
#ifndef _FASTD_FASTD_H_
#define _FASTD_FASTD_H_
+#include "queue.h"
+
#include <errno.h>
+#include <linux/if_ether.h>
+#include <netinet/in.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/uio.h>
typedef enum _fastd_loglevel {
@@ -51,39 +56,68 @@ typedef enum _fastd_protocol {
typedef struct _fastd_peer_config {
struct _fastd_peer_config *next;
+
+ in_addr_t address;
+ in_port_t port;
} fastd_peer_config;
+typedef enum _fastd_peer_state {
+ STATE_WAIT,
+ STATE_HANDSHAKE_SENT,
+ STATE_ESTABLISHED,
+} fastd_peer_state;
-typedef struct _fastd_peer_state {
- struct _fastd_peer_state *next;
+typedef struct _fastd_peer {
+ struct _fastd_peer *next;
const fastd_peer_config *config;
-} fastd_peer_state;
+
+ in_addr_t address;
+ in_port_t port;
+
+ fastd_peer_state state;
+ uint8_t last_req_id;
+
+ void **addresses;
+} fastd_peer;
typedef struct _fastd_context fastd_context;
typedef struct _fastd_method {
const char *name;
- void (*method_init)(const fastd_context *ctx);
- void (*method_recv)(const fastd_context *ctx, void *buffer, size_t len);
- void (*method_send)(const fastd_context *ctx, void *buffer, size_t len);
+ size_t (*method_max_packet_size)(fastd_context *ctx);
+
+ void (*method_init)(fastd_context *ctx, const fastd_peer *peer);
+
+ void (*method_handle_recv)(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer);
+ void (*method_send)(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer);
} fastd_method;
typedef struct _fastd_config {
fastd_loglevel loglevel;
+ char *ifname;
+
+ in_addr_t bind_address;
+ in_port_t bind_port;
+
uint16_t mtu;
fastd_protocol protocol;
fastd_method *method;
- unsigned n_peers;
fastd_peer_config *peers;
} fastd_config;
struct _fastd_context {
const fastd_config *conf;
+
+ fastd_peer *peers;
+ fastd_queue task_queue;
+
+ int tunfd;
+ int sockfd;
};
@@ -96,7 +130,19 @@ struct _fastd_context {
#define pr_debug(context, args...) pr_log(context, LOG_DEBUG, args)
#define exit_fatal(context, args...) do { pr_fatal(context, args); exit(1); } while(0)
-#define exit_fatal_bug(context, message) exit_fatal(context, "BUG: %s", message)
-#define exit_fatal_errno(context, message) exit_fatal(context, "%s: %s", message, strerror(errno))
+#define exit_bug(context, message) exit_fatal(context, "BUG: %s", message)
+#define exit_errno(context, message) exit_fatal(context, "%s: %s", message, strerror(errno))
+
+
+static inline size_t fastd_max_packet_size(const fastd_context *ctx) {
+ switch (ctx->conf->protocol) {
+ case PROTOCOL_ETHERNET:
+ return ctx->conf->mtu+ETH_HLEN;
+ case PROTOCOL_IP:
+ return ctx->conf->mtu;
+ default:
+ exit_bug(ctx, "invalid protocol");
+ }
+}
#endif /* _FASTD_FASTD_H_ */
diff --git a/src/handshake.c b/src/handshake.c
new file mode 100644
index 0000000..f9a1734
--- /dev/null
+++ b/src/handshake.c
@@ -0,0 +1,95 @@
+/*
+ Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
+ Partly based on QuickTun Copyright (c) 2010, Ivo Smits <Ivo@UCIS.nl>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "handshake.h"
+#include "packet.h"
+#include "task.h"
+
+#include <string.h>
+
+
+void fastd_handshake_send(fastd_context *ctx, const fastd_peer *peer) {
+ size_t method_len = strlen(ctx->conf->method->name);
+ size_t len = sizeof(fastd_packet_request)+method_len;
+ fastd_packet_request *request = malloc(len);
+
+ request->reply = 0;
+ request->cp = 0;
+ request->req_id = 0;
+ request->rsv = 0;
+ request->flags = 0;
+ request->proto = ctx->conf->protocol;
+ request->method_len = method_len;
+ strncpy(request->method_name, ctx->conf->method->name, method_len);
+
+ struct iovec buffer = { .iov_base = request, .iov_len = len };
+ fastd_task_put_send_handshake(ctx, peer, buffer);
+}
+
+void fastd_handshake_handle(fastd_context *ctx, const fastd_peer *peer, uint8_t packet_type, struct iovec buffer) {
+ if (packet_type != 1)
+ return; // TODO
+
+ if (buffer.iov_len < sizeof(fastd_packet_any))
+ return;
+
+ fastd_packet *packet = buffer.iov_base;
+
+ if (!packet->any.reply && !packet->any.cp) {
+ if (buffer.iov_len < sizeof(fastd_packet_request))
+ return;
+
+ if (buffer.iov_len < sizeof(fastd_packet_request) + packet->request.method_len)
+ return;
+
+ if (packet->request.flags)
+ return; // TODO
+
+ if (packet->request.proto != ctx->conf->protocol)
+ return; // TODO
+
+ if (packet->request.method_len != strlen(ctx->conf->method->name) ||
+ strncmp(packet->request.method_name, ctx->conf->method->name, packet->request.method_len))
+ return; // TODO
+
+
+ fastd_packet_reply *reply = malloc(sizeof(fastd_packet_reply));
+
+ reply->reply = 1;
+ reply->cp = 0;
+ reply->req_id = packet->request.req_id;
+ reply->rsv = 0;
+ reply->reply_code = REPLY_SUCCESS;
+
+ free(packet);
+
+ buffer.iov_base = reply;
+ buffer.iov_len = sizeof(fastd_packet_reply);
+
+ fastd_task_put_send_handshake(ctx, peer, buffer);
+ }
+}
diff --git a/src/handshake.h b/src/handshake.h
new file mode 100644
index 0000000..7fbc549
--- /dev/null
+++ b/src/handshake.h
@@ -0,0 +1,36 @@
+/*
+ Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
+ Partly based on QuickTun Copyright (c) 2010, Ivo Smits <Ivo@UCIS.nl>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef _FASTD_HANDSHAKE_H_
+#define _FASTD_HANDSHAKE_H_
+
+#include "fastd.h"
+
+void fastd_handshake_send(fastd_context *ctx, const fastd_peer *peer);
+void fastd_handshake_handle(fastd_context *ctx, const fastd_peer *peer, uint8_t packet_type, struct iovec buffer);
+
+#endif /* _FASTD_HANDSHAKE_H_ */
diff --git a/src/method_null.c b/src/method_null.c
index fd41110..dea84d4 100644
--- a/src/method_null.c
+++ b/src/method_null.c
@@ -25,21 +25,31 @@
*/
#include "fastd.h"
+#include "task.h"
-static void null_init(const fastd_context *ctx) {
+static size_t null_max_packet_size(fastd_context *ctx) {
+ return fastd_max_packet_size(ctx);
}
-static void null_recv(const fastd_context *ctx, void *buffer, size_t len) {
+static void null_init(fastd_context *ctx, const fastd_peer *peer) {
+ struct iovec buffer = { .iov_base = NULL, .iov_len = 0 };
+ fastd_task_put_send(ctx, peer, buffer);
}
-static void null_send(const fastd_context *ctx, void *buffer, size_t len) {
+static void null_handle_recv(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer) {
+ fastd_task_put_handle_recv(ctx, peer, buffer);
+}
+
+static void null_send(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer) {
+ fastd_task_put_send(ctx, peer, buffer);
}
const fastd_method fastd_method_null = {
.name = "null",
+ .method_max_packet_size = null_max_packet_size,
.method_init = null_init,
- .method_recv = null_recv,
+ .method_handle_recv = null_handle_recv,
.method_send = null_send,
};
diff --git a/src/packet.h b/src/packet.h
index 79b1984..548b9a4 100644
--- a/src/packet.h
+++ b/src/packet.h
@@ -29,8 +29,11 @@
#define _FASTD_PACKET_H_
+typedef enum _fastd_reply_code {
+ REPLY_SUCCESS = 0,
+} fastd_reply_code;
+
typedef struct __attribute__ ((__packed__)) _fastd_packet_any {
- unsigned type : 8;
unsigned reply : 1;
unsigned cp : 1;
unsigned req_id : 6;
@@ -38,7 +41,6 @@ typedef struct __attribute__ ((__packed__)) _fastd_packet_any {
} fastd_packet_any;
typedef struct __attribute__ ((__packed__)) _fastd_packet_request {
- unsigned type : 8;
unsigned reply : 1;
unsigned cp : 1;
unsigned req_id : 6;
@@ -50,7 +52,6 @@ typedef struct __attribute__ ((__packed__)) _fastd_packet_request {
} fastd_packet_request;
typedef struct __attribute__ ((__packed__)) _fastd_packet_reply {
- unsigned type : 8;
unsigned reply : 1;
unsigned cp : 1;
unsigned req_id : 6;
diff --git a/src/queue.h b/src/queue.h
new file mode 100644
index 0000000..a196153
--- /dev/null
+++ b/src/queue.h
@@ -0,0 +1,74 @@
+/*
+ Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
+ Partly based on QuickTun Copyright (c) 2010, Ivo Smits <Ivo@UCIS.nl>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef _FASTD_QUEUE_H_
+#define _FASTD_QUEUE_H_
+
+#include <stdlib.h>
+
+
+typedef struct _fastd_queue_entry fastd_queue_entry;
+
+struct _fastd_queue_entry {
+ fastd_queue_entry *next;
+ void *data;
+};
+
+typedef struct _fastd_queue {
+ fastd_queue_entry *head;
+ fastd_queue_entry *tail;
+} fastd_queue;
+
+
+static inline void fastd_queue_put(fastd_queue *queue, void *data) {
+ fastd_queue_entry *entry = malloc(sizeof(fastd_queue_entry));
+ entry->next = NULL;
+ entry->data = data;
+
+ if (queue->tail)
+ queue->tail->next = entry;
+ else
+ queue->head = entry;
+
+ queue->tail = entry;
+}
+
+static inline void* fastd_queue_get(fastd_queue *queue) {
+ if (!queue->head)
+ return NULL;
+
+ fastd_queue_entry *entry = queue->head;
+ queue->head = entry->next;
+ if (!queue->head)
+ queue->tail = NULL;
+
+ void *data = entry->data;
+ free(entry);
+ return data;
+}
+
+#endif /* _FASTD_QUEUE_H_ */
diff --git a/src/task.c b/src/task.c
new file mode 100644
index 0000000..e2c4e99
--- /dev/null
+++ b/src/task.c
@@ -0,0 +1,63 @@
+/*
+ Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
+ Partly based on QuickTun Copyright (c) 2010, Ivo Smits <Ivo@UCIS.nl>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "task.h"
+#include "queue.h"
+
+
+fastd_task* fastd_task_get(fastd_context *ctx) {
+ return fastd_queue_get(&ctx->task_queue);
+}
+
+static void fastd_task_put_send_type(fastd_context *ctx, const fastd_peer *peer, uint8_t packet_type, struct iovec buffer) {
+ fastd_task_send *task = malloc(sizeof(fastd_task_send));
+
+ task->type = TASK_SEND;
+ task->peer = peer;
+ task->packet_type = packet_type;
+ task->buffer = buffer;
+
+ fastd_queue_put(&ctx->task_queue, task);
+}
+
+void fastd_task_put_send_handshake(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer) {
+ fastd_task_put_send_type(ctx, peer, 1, buffer);
+}
+
+void fastd_task_put_send(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer) {
+ fastd_task_put_send_type(ctx, peer, 0, buffer);
+}
+
+void fastd_task_put_handle_recv(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer) {
+ fastd_task_handle_recv *task = malloc(sizeof(fastd_task_handle_recv));
+
+ task->type = TASK_HANDLE_RECV;
+ task->peer = peer;
+ task->buffer = buffer;
+
+ fastd_queue_put(&ctx->task_queue, task);
+}
diff --git a/src/task.h b/src/task.h
new file mode 100644
index 0000000..4c7bd65
--- /dev/null
+++ b/src/task.h
@@ -0,0 +1,69 @@
+/*
+ Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
+ Partly based on QuickTun Copyright (c) 2010, Ivo Smits <Ivo@UCIS.nl>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef _FASTD_TASK_H_
+#define _FASTD_TASK_H_
+
+#include "fastd.h"
+
+#include <sys/uio.h>
+
+
+typedef enum _fastd_task_type {
+ TASK_SEND,
+ TASK_HANDLE_RECV,
+} fastd_task_type;
+
+typedef struct _fastd_task_send {
+ fastd_task_type type;
+ const fastd_peer *peer;
+ uint8_t packet_type;
+ struct iovec buffer;
+} fastd_task_send;
+
+typedef struct _fastd_task_handle_recv {
+ fastd_task_type type;
+ const fastd_peer *peer;
+ uint8_t packet_type;
+ struct iovec buffer;
+} fastd_task_handle_recv;
+
+typedef union _fastd_task {
+ fastd_task_type type;
+ fastd_task_send send;
+ fastd_task_handle_recv handle_recv;
+} fastd_task;
+
+
+fastd_task* fastd_task_get(fastd_context *ctx);
+
+void fastd_task_put_send_handshake(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer);
+
+void fastd_task_put_send(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer);
+void fastd_task_put_handle_recv(fastd_context *ctx, const fastd_peer *peer, struct iovec buffer);
+
+#endif /* _FASTD_TASK_H_ */