diff options
Diffstat (limited to 'ffd/send.c')
-rw-r--r-- | ffd/send.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/ffd/send.c b/ffd/send.c new file mode 100644 index 0000000..d020aca --- /dev/null +++ b/ffd/send.c @@ -0,0 +1,121 @@ +/* + 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 "neigh.h" +#include "packet.h" +#include "tlv.h" +#include "tlv_types.h" + +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#include <netpacket/packet.h> + +#include <sys/socket.h> +#include <sys/uio.h> + + +static bool send_eth(const eth_addr_t *addr, unsigned ifindex, void *buf, size_t len) { + static const uint8_t zeros[46] = {0}; + + struct sockaddr_ll sa; + memset(&sa, 0, sizeof(sa)); + sa.sll_family = AF_PACKET; + sa.sll_protocol = htons(FFD_PROTO); + sa.sll_ifindex = ifindex; + sa.sll_halen = ETH_ALEN; + memcpy(sa.sll_addr, addr->d, ETH_ALEN); + + struct iovec vec[2] = { + { .iov_base = buf, .iov_len = len }, + { .iov_base = (void*)zeros, .iov_len = sizeof(zeros) - len }, + }; + + struct msghdr msg; + memset(&msg, 0, sizeof(msg)); + msg.msg_name = &sa; + msg.msg_namelen = sizeof(sa); + msg.msg_iov = vec; + msg.msg_iovlen = (len < 46) ? 2 : 1; + + + while (sendmsg(sockfd, &msg, 0) < 0) { + if (errno != EINTR) + return false; + } + + return true; +} + +static void add_ihus(ffd_packet_t *packet, size_t max_len, const ffd_iface_t *iface) { + const ffd_neigh_t *neigh; + + for (neigh = iface->neigh_list; neigh; neigh = neigh->next) { + ffd_tlv_ihu_t *ihu = ffd_tlv_add(packet, FFD_PACKET_MAX, TLV_IHU, sizeof(ffd_tlv_ihu_t)+sizeof(eth_addr_t)); + if (!ihu) + return; + + ihu->ae = ADDR_ENC_ETH; + ihu->reserved = 0; + ihu->rxcost = htons(ffd_neigh_get_rxcost(neigh)); + ihu->interval = htons(FFD_IHU_INTERVAL); + memcpy(ihu->address, &neigh->addr, sizeof(eth_addr_t)); + } +} + +void ffd_send_hellos() { + ffd_packet_t *packet = alloca(sizeof(ffd_packet_t)+FFD_PACKET_MAX); + + packet->version_magic = htons(FFD_VERSION_MAGIC); + packet->len = 0; + + ffd_tlv_hello_t *hello = ffd_tlv_add(packet, FFD_PACKET_MAX, TLV_HELLO, sizeof(ffd_tlv_hello_t)); + if (!hello) + return; + + hello->reserved = 0; + hello->interval = htons(FFD_HELLO_INTERVAL); + + uint16_t len = packet->len; + + ffd_iface_t *iface; + for (iface = iface_list; iface; iface = iface->next) { + hello->seqno = htons(iface->seqno++); + + packet->len = len; + + add_ihus(packet, FFD_PACKET_MAX, iface); + + if (!send_eth(&ffd_addr, iface->ifindex, packet, sizeof(ffd_packet_t)+ntohs(packet->len))) + fprintf(stderr, "send_eth: %m\n"); + } +} + +void ffd_send_announce_request(ffd_iface_t *iface, ffd_neigh_t *neigh, void *announce) { + +} |