From e17045e901fc097da104e485ee6b57dd7f6ee0ce Mon Sep 17 00:00:00 2001 From: Kaspar Schleiser Date: Wed, 30 Mar 2016 12:29:20 +0200 Subject: [PATCH] dist: tools: add UHCP daemon --- dist/tools/uhcpd/.gitignore | 1 + dist/tools/uhcpd/Makefile | 17 +++++ dist/tools/uhcpd/project.py | 5 ++ dist/tools/uhcpd/uhcpd.c | 146 ++++++++++++++++++++++++++++++++++++ 4 files changed, 169 insertions(+) create mode 100644 dist/tools/uhcpd/.gitignore create mode 100644 dist/tools/uhcpd/Makefile create mode 100644 dist/tools/uhcpd/project.py create mode 100644 dist/tools/uhcpd/uhcpd.c diff --git a/dist/tools/uhcpd/.gitignore b/dist/tools/uhcpd/.gitignore new file mode 100644 index 0000000000..ba077a4031 --- /dev/null +++ b/dist/tools/uhcpd/.gitignore @@ -0,0 +1 @@ +bin diff --git a/dist/tools/uhcpd/Makefile b/dist/tools/uhcpd/Makefile new file mode 100644 index 0000000000..177b3434f1 --- /dev/null +++ b/dist/tools/uhcpd/Makefile @@ -0,0 +1,17 @@ +CFLAGS?=-g -O3 -Wall +CFLAGS_EXTRA=-DUHCP_SERVER +all: bin bin/uhcpd + +bin: + mkdir bin + +RIOTBASE:=../../.. +UHCP_DIR:=$(RIOTBASE)/sys/net/application_layer/uhcp +RIOT_INCLUDE=$(RIOTBASE)/sys/include +SRCS:=$(UHCP_DIR)/uhcp.c uhcpd.c +HDRS:=$(RIOT_INCLUDE)/net/uhcp.h +bin/uhcpd: $(SRCS) $(HDRS) + $(CC) $(CFLAGS) $(CFLAGS_EXTRA) -I$(RIOT_INCLUDE) $(SRCS) -o $@ + +clean: + rm -f bin/uhcpd diff --git a/dist/tools/uhcpd/project.py b/dist/tools/uhcpd/project.py new file mode 100644 index 0000000000..99fe1d986b --- /dev/null +++ b/dist/tools/uhcpd/project.py @@ -0,0 +1,5 @@ +# pyjam build file. See https://github.com/kaspar030/pyjam for info. + +default.CFLAGS = "-O3 -DUHCP_SYSTEM_LINUX -DUHCP_SERVER" + +Main("uhcpd") diff --git a/dist/tools/uhcpd/uhcpd.c b/dist/tools/uhcpd/uhcpd.c new file mode 100644 index 0000000000..18982511fc --- /dev/null +++ b/dist/tools/uhcpd/uhcpd.c @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2016 Kaspar Schleiser + * + * This file is subject to the terms and conditions of the GNU General Public + * License v2. See the file LICENSE for more details. + */ + +#define UHCP_MCAST_ADDR "ff15::ABCD" + +#include +#include +#include +#include +#include +#include +#include + +#include "net/uhcp.h" + +char _prefix[16]; +unsigned _prefix_len; + +int ipv6_addr_split(char *addr_str, char seperator, int _default) +{ + char *sep = addr_str; + while(*++sep) { + if (*sep == seperator) { + *sep++ = '\0'; + if (*sep) { + _default = atoi(sep); + } + break; + } + } + + return _default; +} + +int main(int argc, char *argv[]) +{ + static unsigned ifindex; + + if (argc < 3) { + fprintf(stderr, "usage: uhcpd \n"); + exit(1); + } + + ifindex = if_nametoindex(argv[1]); + if (!ifindex) { + fprintf(stderr, "error: invalid interface \"%s\"\n", argv[1]); + exit(1); + } + + _prefix_len = ipv6_addr_split(argv[2], '/', 64); + if ((!inet_pton(AF_INET6, argv[2], _prefix)) || (_prefix_len > 128)) { + fprintf(stderr, "error: cannot parse prefix\n"); + exit(1); + } + + char *addr_str = UHCP_MCAST_ADDR; + + struct addrinfo hint; + memset(&hint, 0, sizeof(hint)); + hint.ai_family = AF_INET6; + hint.ai_socktype = SOCK_DGRAM; + hint.ai_protocol = IPPROTO_UDP; + hint.ai_flags |= AI_NUMERICHOST; + + struct addrinfo *mcast_addr; + int res = getaddrinfo(addr_str, UHCP_PORT_STR, + &hint, &mcast_addr); + if (res != 0) { + perror("getaddrinfo()"); + exit(1); + } + + int sock = socket(mcast_addr->ai_family, mcast_addr->ai_socktype, + mcast_addr->ai_protocol); + if (sock < 0) { + perror("socket() failed"); + exit(1); + } + + if (bind(sock, mcast_addr->ai_addr, mcast_addr->ai_addrlen) < 0) { + perror("bind() failed"); + exit(1); + } + + /* join multicast group */ + struct ipv6_mreq mreq; + memcpy(&mreq.ipv6mr_multiaddr, + &((struct sockaddr_in6 *)mcast_addr->ai_addr)->sin6_addr, + sizeof(struct in6_addr)); + + mreq.ipv6mr_interface = ifindex; + + puts("Joining IPv6 multicast group..."); + if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, + &mreq, sizeof(mreq)) < 0) { + perror("setsockopt(IPV6_JOIN_GROUP) failed"); + exit(1); + } + freeaddrinfo(mcast_addr); + + char buf[2048]; + struct sockaddr_in6 src_addr; + unsigned n = sizeof(src_addr);; + + puts("entering loop..."); + while(1) { + int nbytes = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr*)&src_addr, &n); + if (nbytes < 0) { + perror("recvfrom() failed"); + continue; + } + uhcp_handle_udp((uint8_t *)buf, nbytes, (uint8_t *)&src_addr.sin6_addr, ntohs(src_addr.sin6_port), ifindex); + } + + close(sock); + exit(0); +} + +int udp_sendto(uint8_t *buf, size_t len, uint8_t *dst, uint16_t dst_port, uhcp_iface_t iface) +{ + struct sockaddr_in6 dst_addr; + memset(&dst_addr, '\0', sizeof(dst_addr)); + dst_addr.sin6_family = AF_INET6; + memcpy(&dst_addr.sin6_addr, dst, 16); + dst_addr.sin6_port = htons(dst_port); + dst_addr.sin6_scope_id = iface; + + int fd = socket(AF_INET6, SOCK_DGRAM, 0); + if (fd == -1) { + perror("creating send socket"); + return -1; + } + + ssize_t res; + if ((res = sendto(fd, buf, len, 0, (struct sockaddr *)&dst_addr, sizeof(dst_addr))) == -1) { + perror("udp_sendto(): sendto()"); + } + + close(fd); + + return res; +}