summaryrefslogtreecommitdiffstats
path: root/src/peer.c
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2012-02-29 22:44:40 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2012-02-29 22:44:40 +0100
commit0f2e170ea6edee4df0f90a3821d5c054db6bd6b7 (patch)
tree6d90aea5c094eec471e6aa2f25f9f080741d1320 /src/peer.c
parentb5892c34186707a50b2afb713e13cbfc3e859920 (diff)
downloadfastd-0f2e170ea6edee4df0f90a3821d5c054db6bd6b7.tar
fastd-0f2e170ea6edee4df0f90a3821d5c054db6bd6b7.zip
Only send packets to the right host in ethernet mode
Diffstat (limited to 'src/peer.c')
-rw-r--r--src/peer.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/peer.c b/src/peer.c
new file mode 100644
index 0000000..f050ebe
--- /dev/null
+++ b/src/peer.c
@@ -0,0 +1,139 @@
+/*
+ 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 "peer.h"
+#include "task.h"
+
+
+const fastd_eth_addr* fastd_get_source_address(const fastd_context *ctx, fastd_buffer buffer) {
+ switch (ctx->conf->protocol) {
+ case PROTOCOL_ETHERNET:
+ return (fastd_eth_addr*)&((struct ethhdr*)buffer.data)->h_source;
+ default:
+ exit_bug(ctx, "invalid protocol");
+ }
+}
+
+const fastd_eth_addr* fastd_get_dest_address(const fastd_context *ctx, fastd_buffer buffer) {
+ switch (ctx->conf->protocol) {
+ case PROTOCOL_ETHERNET:
+ return (fastd_eth_addr*)&((struct ethhdr*)buffer.data)->h_dest;
+ default:
+ exit_bug(ctx, "invalid protocol");
+ }
+}
+
+fastd_peer* fastd_peer_init(fastd_context *ctx, fastd_peer_config *peer_conf) {
+ fastd_peer *peer = malloc(sizeof(fastd_peer));
+
+ peer->next = NULL;
+
+ peer->config = peer_conf;
+ peer->address = peer_conf->address;
+ peer->port = peer_conf->port;
+ peer->state = STATE_WAIT;
+ peer->last_req_id = 0;
+
+ fastd_task_schedule_handshake(ctx, peer, 0);
+
+ return peer;
+}
+
+void fastd_peer_free(fastd_context *ctx, fastd_peer *peer) {
+ int i, deleted = 0;
+
+ for (i = 0; i < ctx->n_eth_addr; i++) {
+ if (ctx->eth_addr[i].peer == peer) {
+ deleted++;
+ }
+ else if (deleted) {
+ ctx->eth_addr[i-deleted] = ctx->eth_addr[i];
+ }
+ }
+
+ ctx->n_eth_addr -= deleted;
+
+ free(peer);
+}
+
+static inline int fastd_eth_addr_cmp(const fastd_eth_addr *addr1, const fastd_eth_addr *addr2) {
+ return memcmp(addr1->data, addr2->data, ETH_ALEN);
+}
+
+static inline int fastd_peer_eth_addr_cmp(const fastd_peer_eth_addr *addr1, const fastd_peer_eth_addr *addr2) {
+ return fastd_eth_addr_cmp(&addr1->addr, &addr2->addr);
+}
+
+static inline fastd_peer_eth_addr* peer_get_by_addr(fastd_context *ctx, const fastd_eth_addr *addr) {
+ return bsearch(((uint8_t*)addr)-offsetof(fastd_peer_eth_addr, addr), ctx->eth_addr, ctx->n_eth_addr, sizeof(fastd_peer_eth_addr),
+ (int (*)(const void *, const void *))fastd_peer_eth_addr_cmp);
+}
+
+void fastd_peer_add_eth_addr(fastd_context *ctx, fastd_peer *peer, const fastd_eth_addr *addr) {
+ int min = 0, max = ctx->n_eth_addr;
+
+ while (max > min) {
+ int cur = (min+max)/2;
+ int cmp = fastd_eth_addr_cmp(addr, &ctx->eth_addr[cur].addr);
+
+ if (cmp == 0) {
+ ctx->eth_addr[cur].peer = peer;
+ return; /* We're done here. */
+ }
+ else if (cmp < 0) {
+ max = cur;
+ }
+ else {
+ min = cur+1;
+ }
+ }
+
+ ctx->n_eth_addr++;
+ if (ctx->n_eth_addr > ctx->eth_addr_size) {
+ if (ctx->eth_addr_size == 0)
+ ctx->eth_addr_size = 16;
+ else
+ ctx->eth_addr_size *= 2;
+
+ ctx->eth_addr = realloc(ctx->eth_addr, ctx->eth_addr_size*sizeof(fastd_peer_eth_addr));
+ }
+
+ int i;
+ for (i = ctx->n_eth_addr-1; i > min+1; i--)
+ ctx->eth_addr[i] = ctx->eth_addr[i-1];
+
+ ctx->eth_addr[min] = (fastd_peer_eth_addr){ *addr, peer };
+}
+
+fastd_peer *fastd_peer_find_by_eth_addr(fastd_context *ctx, const fastd_eth_addr *addr) {
+ fastd_peer_eth_addr *peer_eth_addr = peer_get_by_addr(ctx, addr);
+
+ if (peer_eth_addr)
+ return peer_eth_addr->peer;
+ else
+ return NULL;
+}