summaryrefslogtreecommitdiffstats
path: root/ffd/send.c
diff options
context:
space:
mode:
Diffstat (limited to 'ffd/send.c')
-rw-r--r--ffd/send.c121
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) {
+
+}