diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | src/Makefile | 10 | ||||
-rw-r--r-- | src/fastd.c | 130 | ||||
-rw-r--r-- | src/fastd.h | 102 | ||||
-rw-r--r-- | src/method_null.c | 45 | ||||
-rw-r--r-- | src/packet.h | 67 |
6 files changed, 356 insertions, 0 deletions
@@ -1 +1,3 @@ *~ +*.o +fastd diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..90619ec --- /dev/null +++ b/src/Makefile @@ -0,0 +1,10 @@ +all : fastd + +fastd : fastd.o method_null.o + gcc -Wall -o $@ $^ + +fastd.o : fastd.c fastd.h packet.h + gcc -Wall -c -o $@ $< + +method_null.o : method_null.c fastd.h + gcc -Wall -c -o $@ $< diff --git a/src/fastd.c b/src/fastd.c index f500090..42478b2 100644 --- a/src/fastd.c +++ b/src/fastd.c @@ -23,3 +23,133 @@ 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 <fcntl.h> +#include <linux/if_ether.h> +#include <linux/if_tun.h> +#include <net/if.h> +#include <poll.h> +#include <stdio.h> +#include <string.h> +#include <sys/ioctl.h> +#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; + 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"); + + memset(&ifr, 0, sizeof(ifr)); + // strcpy(ifr.ifr_name, name); + 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"); + + return tunfd; +} + +static void configure(fastd_context *ctx, fastd_config *conf) { + conf->loglevel = LOG_DEBUG; + 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"); + } +} + +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"); + } +} + +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"); + } +} + +static void run(const fastd_context *ctx) { + int tunfd; + + tunfd = init_tuntap(ctx); + + struct pollfd fds[ctx->conf->n_peers+1]; + fds[0].fd = tunfd; + fds[0].events = POLLIN; + + while (1) { + int ret = poll(fds, 1, -1); + if (ret < 0) + exit_fatal_errno(ctx, "poll error"); + + if (fds[0].revents & POLLIN) { + size_t max_len = get_max_packet_size(ctx); + char buffer[max_len]; + + 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); + + 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]); + + ctx->conf->method->method_send(ctx, buffer, len); + } + } +} + + +int main() +{ + fastd_context ctx = { + .conf = NULL, + }; + + fastd_config conf; + configure(&ctx, &conf); + ctx.conf = &conf; + + run(&ctx); + + return 0; +} diff --git a/src/fastd.h b/src/fastd.h new file mode 100644 index 0000000..06b69b2 --- /dev/null +++ b/src/fastd.h @@ -0,0 +1,102 @@ +/* + 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_FASTD_H_ +#define _FASTD_FASTD_H_ + +#include <errno.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + + +typedef enum _fastd_loglevel { + LOG_FATAL = 0, + LOG_ERROR, + LOG_WARN, + LOG_INFO, + LOG_DEBUG, +} fastd_loglevel; + + +typedef enum _fastd_protocol { + PROTOCOL_ETHERNET, + PROTOCOL_IP, +} fastd_protocol; + +typedef struct _fastd_peer_config { + struct _fastd_peer_config *next; +} fastd_peer_config; + + +typedef struct _fastd_peer_state { + struct _fastd_peer_state *next; + + const fastd_peer_config *config; +} fastd_peer_state; + +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); +} fastd_method; + +typedef struct _fastd_config { + fastd_loglevel loglevel; + + 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; +}; + + +#define pr_log(context, level, args...) if ((context)->conf == NULL || (level) <= (context)->conf->loglevel) do { fprintf(stderr, args); fputs("\n", stderr); } while(0) + +#define pr_fatal(context, args...) pr_log(context, LOG_FATAL, args) +#define pr_error(context, args...) pr_log(context, LOG_ERROR, args) +#define pr_warn(context, args...) pr_log(context, LOG_WARN, args) +#define pr_info(context, args...) pr_log(context, LOG_INFO, args) +#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)) + +#endif /* _FASTD_FASTD_H_ */ diff --git a/src/method_null.c b/src/method_null.c new file mode 100644 index 0000000..fd41110 --- /dev/null +++ b/src/method_null.c @@ -0,0 +1,45 @@ +/* + 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 "fastd.h" + + +static void null_init(const fastd_context *ctx) { +} + +static void null_recv(const fastd_context *ctx, void *buffer, size_t len) { +} + +static void null_send(const fastd_context *ctx, void *buffer, size_t len) { +} + + +const fastd_method fastd_method_null = { + .name = "null", + .method_init = null_init, + .method_recv = null_recv, + .method_send = null_send, +}; diff --git a/src/packet.h b/src/packet.h new file mode 100644 index 0000000..79b1984 --- /dev/null +++ b/src/packet.h @@ -0,0 +1,67 @@ +/* + 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_PACKET_H_ +#define _FASTD_PACKET_H_ + + +typedef struct __attribute__ ((__packed__)) _fastd_packet_any { + unsigned type : 8; + unsigned reply : 1; + unsigned cp : 1; + unsigned req_id : 6; + unsigned rsv : 8; +} fastd_packet_any; + +typedef struct __attribute__ ((__packed__)) _fastd_packet_request { + unsigned type : 8; + unsigned reply : 1; + unsigned cp : 1; + unsigned req_id : 6; + unsigned rsv : 8; + unsigned flags : 8; + unsigned proto : 8; + unsigned method_len : 8; + char method_name[]; +} fastd_packet_request; + +typedef struct __attribute__ ((__packed__)) _fastd_packet_reply { + unsigned type : 8; + unsigned reply : 1; + unsigned cp : 1; + unsigned req_id : 6; + unsigned rsv : 8; + unsigned reply_code : 8; +} fastd_packet_reply; + +typedef union _fastd_packet { + fastd_packet_any any; + fastd_packet_request request; + fastd_packet_reply reply; +} fastd_packet; + +#endif /* _FASTD_PACKET_H_ */ |