1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

tools/zep_dispatch: add simple ZEP dispatcher

This commit is contained in:
Benjamin Valentin 2020-08-13 17:30:47 +02:00 committed by Benjamin Valentin
parent b3e73521ed
commit 54eedd94ba
4 changed files with 237 additions and 1 deletions

2
dist/tools/Makefile vendored
View File

@ -1,4 +1,4 @@
HOST_TOOLS=ethos uhcpd sliptty
HOST_TOOLS=ethos uhcpd sliptty zep_dispatch
.PHONY: all $(HOST_TOOLS)

16
dist/tools/zep_dispatch/Makefile vendored Normal file
View File

@ -0,0 +1,16 @@
CFLAGS?=-g -O3 -Wall -Wextra
BINARY := bin/zep_dispatch
all: bin $(BINARY)
bin:
mkdir bin
RIOTBASE:=../../..
RIOT_INCLUDE=$(RIOTBASE)/core/include
SRCS:=$(wildcard *.c)
$(BINARY): $(SRCS)
$(CC) $(CFLAGS) $(CFLAGS_EXTRA) -I$(RIOT_INCLUDE) $(SRCS) -o $@
clean:
rm -f $(BINARY)

121
dist/tools/zep_dispatch/main.c vendored Normal file
View File

@ -0,0 +1,121 @@
/*
* Copyright (C) 2020 Benjamin Valentin
*
* This file is subject to the terms and conditions of the GNU General Public
* License v2. See the file LICENSE for more details.
*/
#ifndef ZEP_DISPATCH_PDU
#define ZEP_DISPATCH_PDU 256
#endif
#include <arpa/inet.h>
#include <netdb.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "list.h"
#include "kernel_defines.h"
typedef struct {
list_node_t node;
struct sockaddr_in6 addr;
} zep_client_t;
static void dispatch_loop(int sock)
{
list_node_t head = { .next = NULL };
puts("entering loop…");
while (1) {
char addr_str[INET6_ADDRSTRLEN];
uint8_t buffer[ZEP_DISPATCH_PDU];
struct sockaddr_in6 src_addr;
socklen_t addr_len = sizeof(src_addr);
/* receive incoming packet */
ssize_t bytes_in = recvfrom(sock, buffer, sizeof(buffer), 0,
(struct sockaddr*)&src_addr, &addr_len);
if (bytes_in <= 0 || addr_len != sizeof(src_addr)) {
continue;
}
/* send packet to all other clients */
bool known_node = false;
list_node_t *prev = &head;
for (list_node_t* n = head.next; n; n = n->next) {
struct sockaddr_in6 *addr = &container_of(n, zep_client_t, node)->addr;
/* don't echo packet back to sender */
if (memcmp(&src_addr, addr, addr_len) == 0) {
known_node = true;
/* remove client if sending fails */
} else if (sendto(sock, buffer, bytes_in, 0, (struct sockaddr*)addr, addr_len) < 0) {
inet_ntop(AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN);
printf("removing [%s]:%d\n", addr_str, ntohs(addr->sin6_port));
prev->next = n->next;
free(n);
continue;
}
prev = n;
}
/* if the client new, add it to the broadcast list */
if (!known_node) {
inet_ntop(AF_INET6, &src_addr.sin6_addr, addr_str, INET6_ADDRSTRLEN);
printf("adding [%s]:%d\n", addr_str, ntohs(src_addr.sin6_port));
zep_client_t *client = malloc(sizeof(zep_client_t));
memcpy(&client->addr, &src_addr, addr_len);
list_add(&head, &client->node);
}
}
}
int main(int argc, char **argv)
{
if (argc < 3) {
fprintf(stderr, "usage: %s <address> <port>\n",
argv[0]);
exit(1);
}
struct addrinfo hint = {
.ai_family = AF_INET6,
.ai_socktype = SOCK_DGRAM,
.ai_protocol = IPPROTO_UDP,
.ai_flags = AI_NUMERICHOST,
};
struct addrinfo *server_addr;
int res = getaddrinfo(argv[1], argv[2],
&hint, &server_addr);
if (res != 0) {
perror("getaddrinfo()");
exit(1);
}
int sock = socket(server_addr->ai_family, server_addr->ai_socktype,
server_addr->ai_protocol);
if (sock < 0) {
perror("socket() failed");
exit(1);
}
if (bind(sock, server_addr->ai_addr, server_addr->ai_addrlen) < 0) {
perror("bind() failed");
exit(1);
}
freeaddrinfo(server_addr);
dispatch_loop(sock);
close(sock);
return 0;
}

99
dist/tools/zep_dispatch/start_network.sh vendored Executable file
View File

@ -0,0 +1,99 @@
#!/usr/bin/env bash
ZEP_DISPATCH_DIR="$(cd "$(dirname "$0")" && pwd -P)"
UHCPD="$(cd "${ZEP_DISPATCH_DIR}/../uhcpd/bin" && pwd -P)/uhcpd"
DHCPD="$(cd "${ZEP_DISPATCH_DIR}/../dhcpv6-pd_ia/" && pwd -P)/dhcpv6-pd_ia.py"
ZEP_DISPATCH="${ZEP_DISPATCH_DIR}/bin/zep_dispatch"
TAP_GLB="fdea:dbee:f::1/64"
NOSUDO="sudo -u ${SUDO_USER}"
create_tap() {
ip tuntap add "${TAP}" mode tap user "${SUDO_USER}"
sysctl -w net.ipv6.conf."${TAP}".forwarding=1
sysctl -w net.ipv6.conf."${TAP}".accept_ra=0
ip link set "${TAP}" up
ip a a fe80::1/64 dev "${TAP}"
ip a a ${TAP_GLB} dev "${TAP}"
ip route add "${PREFIX}" via fe80::2 dev "${TAP}"
}
remove_tap() {
ip tuntap del "${TAP}" mode tap
}
cleanup() {
echo "Cleaning up..."
remove_tap
if [ -n "${UHCPD_PID}" ]; then
kill "${UHCPD_PID}"
fi
if [ -n "${ZEP_DISPATCH_PID}" ]; then
kill "${ZEP_DISPATCH_PID}"
fi
if [ -n "${DHCPD_PIDFILE}" ]; then
kill "$(cat "${DHCPD_PIDFILE}")"
rm "${DHCPD_PIDFILE}"
fi
trap "" INT QUIT TERM EXIT
}
start_uhcpd() {
${UHCPD} "${TAP}" "${PREFIX}" > /dev/null &
UHCPD_PID=$!
}
start_dhcpd() {
DHCPD_PIDFILE=$(mktemp)
${DHCPD} -d -p "${DHCPD_PIDFILE}" "${TAP}" "${PREFIX}" 2> /dev/null
}
start_zep_dispatch() {
${ZEP_DISPATCH} :: "${ZEP_PORT_BASE}" > /dev/null &
ZEP_DISPATCH_PID=$!
}
if [ "$1" = "-d" ] || [ "$1" = "--use-dhcpv6" ]; then
USE_DHCPV6=1
shift 1
else
USE_DHCPV6=0
fi
if [ "$1" = "-z" ] || [ "$1" = "--use-zep-dispatch" ]; then
USE_ZEP_DISPATCH=1
ZEP_PORT_BASE=$2
shift 2
else
USE_ZEP_DISPATCH=0
fi
ELFFILE=$1
PREFIX=$2
shift 2
# tap will be the last argument
for TAP in "$@"; do :; done
[[ -z "${ELFFILE}" || -z "${PREFIX}" || -z "${TAP}" ]] && {
echo "usage: $0 [-d|--use-dhcp] [-z|--use-zep <port>] " \
"<elffile> <prefix> [elf args]"
exit 1
}
trap "cleanup" INT QUIT TERM EXIT
create_tap
if [ ${USE_ZEP_DISPATCH} -eq 1 ]; then
start_zep_dispatch
fi
if [ ${USE_DHCPV6} -eq 1 ]; then
start_dhcpd
else
start_uhcpd
fi
${NOSUDO} "${ELFFILE}" "${TAP}" "$@"