From f22dc0880f1b9348dc8c056cba0bbce223a39e62 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 7 Sep 2012 03:50:44 +0200 Subject: Basic code for the data distribution daemon --- CMakeLists.txt | 3 +- ffd/CMakeLists.txt | 10 +++ ffd/ffd.c | 162 +++++++++++++++++++++++++++++++++++++++++++++++ ffd/ffd.h | 70 +++++++++++++++++++++ ffd/netif.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++++++++ ffd/netif.h | 56 +++++++++++++++++ ffd/types.h | 44 +++++++++++++ ffd/util.c | 42 +++++++++++++ ffd/util.h | 51 +++++++++++++++ 9 files changed, 619 insertions(+), 1 deletion(-) create mode 100644 ffd/CMakeLists.txt create mode 100644 ffd/ffd.c create mode 100644 ffd/ffd.h create mode 100644 ffd/netif.c create mode 100644 ffd/netif.h create mode 100644 ffd/types.h create mode 100644 ffd/util.c create mode 100644 ffd/util.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 38e5e96..772feba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,4 +3,5 @@ project(FFD C) set(CMAKE_MODULE_PATH ${FFD_SOURCE_DIR}) -add_subdirectory(ffvisd) +add_subdirectory(ffd) +#add_subdirectory(ffvisd) diff --git a/ffd/CMakeLists.txt b/ffd/CMakeLists.txt new file mode 100644 index 0000000..d2d2a52 --- /dev/null +++ b/ffd/CMakeLists.txt @@ -0,0 +1,10 @@ +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${FFD_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +add_executable(ffd + ffd.c + netif.c + util.c +) +target_link_libraries(ffd rt) + +install(TARGETS ffd RUNTIME DESTINATION sbin) 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 + 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 +#include +#include +#include +#include +#include + +#include + + +#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; +} + diff --git a/ffd/ffd.h b/ffd/ffd.h new file mode 100644 index 0000000..3f9f81c --- /dev/null +++ b/ffd/ffd.h @@ -0,0 +1,70 @@ +/* + Copyright (c) 2012, Matthias Schiffer + 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 _FFD_FFD_H_ +#define _FFD_FFD_H_ + +#include "util.h" + + +typedef enum _ffd_msg_type_t { + MSG_UNSPEC = 0, + MSG_SERVICE, + MSG_ROUTE4, + MSG_ROUTE6, +} ffd_msg_type_t; + +typedef struct _ffd_msg_head_t { + struct _ffd_msg_head_t *next; + + uint16_t changed_rev; + bool deleted; + + ffd_msg_type_t type; + uint16_t len; + uint8_t data[]; +} ffd_msg_head_t; + +typedef struct _ffd_orig_t { + struct _ffd_orig_t *next; + + uint64_t id; + eth_addr_t addr; + uint16_t orig_interval; + uint16_t rev; + + ffd_msg_head_t *messages; +} ffd_orig_t; + +typedef struct _ffd_neigh_t { + struct _ffd_neigh_t *next; + + uint64_t id; + eth_addr_t addr; + uint16_t rev; +} ffd_neigh_t; + +#endif /* _FFD_FFD_H_ */ diff --git a/ffd/netif.c b/ffd/netif.c new file mode 100644 index 0000000..c63b19b --- /dev/null +++ b/ffd/netif.c @@ -0,0 +1,182 @@ +/* + Copyright (c) 2012, Matthias Schiffer + 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. +*/ + +#define _GNU_SOURCE + +#include "netif.h" +#include "util.h" + +#include +#include +#include +#include + +#include + +#include + +#include +#include + + +#define SYSFS_PATH_MAX 256 +#define SYSFS_CLASS_NET "/sys/class/net" + + +static bool netif_file_read(const char *ifname, const char *file, const char *format, ...) { + char filename[SYSFS_PATH_MAX]; + + snprintf(filename, SYSFS_PATH_MAX, SYSFS_CLASS_NET"/%s/%s", ifname, file); + + va_list ap; + va_start(ap, format); + bool ret = file_readv(filename, format, ap); + va_end(ap); + + return ret; +} + +static bool netif_file_exists(const char *ifname, const char *file) { + char filename[SYSFS_PATH_MAX]; + + snprintf(filename, SYSFS_PATH_MAX, SYSFS_CLASS_NET"/%s/%s", ifname, file); + + struct stat st; + return (stat(filename, &st) == 0); +} + +bool netif_is_mesh(const char *ifname) { + return netif_file_exists(ifname, "mesh"); +} + +char* netif_get_mesh(const char *ifname) { + char *mesh = NULL; + + if (!netif_file_read(ifname, "batman_adv/mesh_iface", "%as", &mesh) || !strcmp(mesh, "none")) { + free(mesh); + return NULL; + } + + return mesh; +} + +char* netif_get_bridge(const char *ifname) { + char filename[SYSFS_PATH_MAX], filename2[SYSFS_PATH_MAX] = {0}; + + snprintf(filename, SYSFS_PATH_MAX, SYSFS_CLASS_NET"/%s/brport/bridge", ifname); + if (readlink(filename, filename2, sizeof(filename2)) < 0) + return NULL; + + return strdup(basename(filename2)); +} + +eth_addr_t netif_get_eth_addr(const char *ifname) { + eth_addr_t ret; + uint8_t *a = ret.d; + + if (!netif_file_read(ifname, "address", "%x:%x:%x:%x:%x:%x", &a[0], &a[1], &a[2], &a[3], &a[4], &a[5])) + return ETH_ADDR_UNSPEC; + + return ret; +} + +struct in6_addr netif_get_addr(unsigned ifindex, int scope) { + struct msg { + struct nlmsghdr nh; + struct ifaddrmsg addr; + uint8_t attrbuf[16384]; + } msg; + + memset(&msg, 0, sizeof(msg)); + + int rtnetlink_sk = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + + msg.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + msg.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; + msg.nh.nlmsg_type = RTM_GETADDR; + + msg.addr.ifa_family = AF_INET6; + + if(write(rtnetlink_sk, &msg, msg.nh.nlmsg_len) <= 0) { + fprintf(stderr, "error: write: %m\n"); + close(rtnetlink_sk); + return in6addr_any; + } + + int readlen = read(rtnetlink_sk, &msg, sizeof(msg)); + + if (readlen <= 0) { + fprintf(stderr, "error: read: %m\n"); + close(rtnetlink_sk); + return in6addr_any; + } + + close(rtnetlink_sk); + + struct msg *chunk; + + for (chunk = &msg; readlen > sizeof(struct nlmsghdr);) { + int len = chunk->nh.nlmsg_len - sizeof(struct nlmsghdr); + + if (len < sizeof(struct ifaddrmsg) || readlen < len) + return in6addr_any; + + if (!NLMSG_OK(&chunk->nh, readlen)) + return in6addr_any; + + if (chunk->nh.nlmsg_type == RTM_NEWADDR && chunk->addr.ifa_scope == scope && chunk->addr.ifa_index == ifindex) { + struct rtattr *rta = (struct rtattr *)IFA_RTA(&chunk->addr); + int rtattrlen = IFA_PAYLOAD(&chunk->nh); + + for (; RTA_OK(rta, rtattrlen); rta = RTA_NEXT(rta, rtattrlen)) { + if(rta->rta_type == IFA_ADDRESS && rta->rta_len == RTA_LENGTH(16)) { + struct in6_addr ret; + memcpy(ret.s6_addr, RTA_DATA(rta), 16); + return ret; + } + } + } + + readlen -= NLMSG_ALIGN(chunk->nh.nlmsg_len); + chunk = (struct msg*)((uint8_t*)chunk + NLMSG_ALIGN(chunk->nh.nlmsg_len)); + } + + return in6addr_any; +} + +void netif_foreach(netif_cb cb, void *arg) { + struct if_nameindex *ifaces = if_nameindex(); + + if (!ifaces) { + fprintf(stderr, "error: if_nameindex: %m\n"); + return; + } + + int i; + for (i = 0; ifaces[i].if_name; i++) + cb(ifaces[i].if_name, ifaces[i].if_index, arg); + + if_freenameindex(ifaces); +} diff --git a/ffd/netif.h b/ffd/netif.h new file mode 100644 index 0000000..f1ae2b7 --- /dev/null +++ b/ffd/netif.h @@ -0,0 +1,56 @@ +/* + Copyright (c) 2012, Matthias Schiffer + 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 _FFD_NETIF_H_ +#define _FFD_NETIF_H_ + +#include "types.h" + +#include + + +typedef enum _netif_type_t { + IF_UNKNOWN = 0, + IF_WIRED, + IF_WIRELESS, + IF_VIRTUAL, + IF_BRIDGE, + IF_MESH, + IF_MAX +} netif_type_t; + +typedef void (*netif_cb)(const char *ifname, unsigned ifindex, void *arg); + + +bool netif_is_mesh(const char *ifname); +char* netif_get_mesh(const char *ifname); +char* netif_get_bridge(const char *ifname); +eth_addr_t netif_get_eth_addr(const char *ifname); +struct in6_addr netif_get_addr(unsigned ifindex, int scope); +void netif_foreach(netif_cb cb, void *arg); + + +#endif /* _FFD_NETIF_H_ */ diff --git a/ffd/types.h b/ffd/types.h new file mode 100644 index 0000000..5eaaf46 --- /dev/null +++ b/ffd/types.h @@ -0,0 +1,44 @@ +/* + Copyright (c) 2012, Matthias Schiffer + 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 _FFD_TYPES_H_ +#define _FFD_TYPES_H_ + +#include +#include + +#include + + +typedef struct __attribute__((__packed__)) _eth_addr_t { + uint8_t d[ETH_ALEN]; +} eth_addr_t; + + +#define ETH_ADDR_UNSPEC ((eth_addr_t){{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}) + + +#endif /* _FFD_TYPES_H_ */ diff --git a/ffd/util.c b/ffd/util.c new file mode 100644 index 0000000..c8bb90b --- /dev/null +++ b/ffd/util.c @@ -0,0 +1,42 @@ +/* + Copyright (c) 2012, Matthias Schiffer + 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 "util.h" + +#include + + +bool file_readv(const char *file, const char *format, va_list ap) { + FILE *f = fopen(file, "r"); + if (!f) + return false; + + int ret = vfscanf(f, format, ap); + + fclose(f); + + return (ret > 0); +} diff --git a/ffd/util.h b/ffd/util.h new file mode 100644 index 0000000..8020381 --- /dev/null +++ b/ffd/util.h @@ -0,0 +1,51 @@ +/* + Copyright (c) 2012, Matthias Schiffer + 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 _FFD_UTIL_H_ +#define _FFD_UTIL_H_ + +#include "types.h" + +#include +#include + + +bool file_readv(const char *file, const char *format, va_list ap); + + +static inline bool are_eth_addrs_equal(const eth_addr_t *address1, const eth_addr_t *address2) { + const uint8_t *a = address1->d; + const uint8_t *b = address2->d; + + return (a[0]==b[0] && a[1]==b[1] && a[2]==b[2] && a[3]==b[3] && a[4]==b[4] && a[5]==b[5]); +} + +/* returns (tp1 - tp2) in milliseconds */ +static inline int timespec_diff(const struct timespec *tp1, const struct timespec *tp2) { + return ((tp1->tv_sec - tp2->tv_sec))*1000 + (tp1->tv_nsec - tp2->tv_nsec)/1e6; +} + +#endif /* _FFD_UTIL_H_ */ -- cgit v1.2.3