summaryrefslogtreecommitdiffstats
path: root/ffd/ffd.c
diff options
context:
space:
mode:
Diffstat (limited to 'ffd/ffd.c')
-rw-r--r--ffd/ffd.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/ffd/ffd.c b/ffd/ffd.c
new file mode 100644
index 0000000..d182ee0
--- /dev/null
+++ b/ffd/ffd.c
@@ -0,0 +1,162 @@
+/*
+ Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
+ 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 "ffd.h"
+#include "netif.h"
+
+#include <errno.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <netpacket/packet.h>
+
+
+#define FFD_PROTO 0xffd
+#define FFD_VERSION 0
+
+static const eth_addr_t ffd_addr = {{0x03, 0x00, 0x00, 0x00, 0x0f, 0xfd}};
+
+#define ANNOUNCE_INTERVAL 10
+
+
+static char *mesh = "bat0";
+static unsigned mtu = 1500;
+
+static int sockfd;
+static struct timespec now;
+
+//static ffd_neigh_t self = {NULL, ETH_ADDR_UNSPEC, 0};
+//static ffd_orig_t own_data = {NULL, ETH_ADDR_UNSPEC, 0, NULL};
+
+//static ffd_neigh_t *neigh_data = NULL;
+static ffd_orig_t *orig_data = NULL;
+
+
+static void update_time() {
+ clock_gettime(CLOCK_MONOTONIC, &now);
+}
+
+static bool check_config() {
+ if (!netif_is_mesh(mesh)) {
+ fprintf(stderr, "error: configured interface is no mesh\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool init_socket() {
+ sockfd = socket(AF_PACKET, SOCK_DGRAM, htons(FFD_PROTO));
+ if (sockfd < 0) {
+ fprintf(stderr, "error: socket: %m\n");
+ return false;
+ }
+
+ return true;
+}
+
+static inline bool use_netif(const char *ifname) {
+ char *if_mesh = netif_get_mesh(ifname);
+ bool ret = (if_mesh && !strcmp(if_mesh, mesh));
+ free(if_mesh);
+
+ return ret;
+}
+
+static void join_mcast(const char *ifname, unsigned ifindex, void *arg) {
+ if (!use_netif(ifname))
+ return;
+
+ struct packet_mreq mr;
+ memset(&mr, 0, sizeof(mr));
+ mr.mr_ifindex = ifindex;
+ mr.mr_type = PACKET_MR_MULTICAST;
+ mr.mr_alen = ETH_ALEN;
+ memcpy(mr.mr_address, ffd_addr.d, ETH_ALEN);
+ if (setsockopt(sockfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) && errno != EADDRINUSE)
+ fprintf(stderr, "warning: setsockopt: %m\n");
+}
+
+static void send_announce() {
+ if (!orig_data)
+ return;
+}
+
+static void receive_packet() {
+ uint8_t buf[mtu];
+
+ int readlen = read(sockfd, buf, sizeof(buf));
+
+ if (readlen < 0) {
+ fprintf(stderr, "error: read: %m\n");
+ return;
+ }
+
+ fprintf(stderr, "debug: read %i bytes.\n", readlen);
+}
+
+int main() {
+ if (!check_config())
+ return 1;
+
+ if (!init_socket())
+ return 1;
+
+ update_time();
+
+ struct timespec next_announce = now;
+
+ while (true) {
+ netif_foreach(join_mcast, NULL);
+
+ int timeout = timespec_diff(&next_announce, &now);
+
+ if (timeout <= 0) {
+ send_announce();
+
+ next_announce.tv_sec += ANNOUNCE_INTERVAL;
+ continue;
+ }
+
+ struct pollfd fds[1];
+
+ fds[0].fd = sockfd;
+ fds[0].events = POLLIN;
+
+ poll(fds, 1, timeout);
+
+ update_time();
+
+ if (fds[0].revents & POLLIN)
+ receive_packet();
+ }
+
+ return 0;
+}
+