diff options
Diffstat (limited to 'ffd/ffd.c')
-rw-r--r-- | ffd/ffd.c | 162 |
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; +} + |