From c180cf207fc2a377c390ecce7c3a5c910f80296b Mon Sep 17 00:00:00 2001 From: sup39 Date: Fri, 1 Jul 2022 16:04:37 +0900 Subject: [PATCH] handle SIGHUP --- Makefile | 2 +- src/options.c | 2 + src/ra.c | 1 + src/supRA.c | 206 ++++++++++++++++++++++++++------------------------ 4 files changed, 112 insertions(+), 99 deletions(-) diff --git a/Makefile b/Makefile index 7fc50db..15e5b45 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION = 0.1.0-beta.1 +VERSION = 0.1.0-beta.2 CFLAGS = -Os $(and $(LUA_ROOT),-I$(LUA_ROOT)) $(MYCFLAGS) LDFLAGS = $(and $(LUA_ROOT),-L$(LUA_ROOT)) -llua -lm $(MYLDFLAGS) diff --git a/src/options.c b/src/options.c index fab9a33..041ce80 100644 --- a/src/options.c +++ b/src/options.c @@ -203,5 +203,7 @@ int supRA_read_option(const char *path) { intvl->interval = htonl(val); } + // done + lua_close(L); return rc; } diff --git a/src/ra.c b/src/ra.c index 3de6bc5..fcd00e0 100644 --- a/src/ra.c +++ b/src/ra.c @@ -15,6 +15,7 @@ static uint8_t *ra_msg_buflim = NULL; void init_ra_msg_buf(size_t bufsize) { + free(ra_msg_buf); // free previous ra_msg_ptr = ra_msg_buf = malloc(bufsize); ra_msg_buflim = ra_msg_buf+bufsize; diff --git a/src/supRA.c b/src/supRA.c index bd571c6..b160531 100644 --- a/src/supRA.c +++ b/src/supRA.c @@ -15,8 +15,7 @@ #include #include #include -#include -#include +#include #include "icmpv6.h" #include "ra.h" #include "options.h" @@ -39,6 +38,8 @@ static void init_ra_msg(int if_mtu, uint8_t if_macaddr[6]) { mtu->mtu = htonl(if_mtu); } +static void empty_handler(int sig) {} + #define PERROR_EXIT(msg) {perror(msg); exit(errno);} int main(int argc, char *argv[]) { if (argc <= 2) { @@ -46,105 +47,114 @@ int main(int argc, char *argv[]) { return 1; } - const char *ifname = argv[1]; - int ifid = if_nametoindex(ifname); - if (ifid == 0) PERROR_EXIT("Bad Interface"); - - /** get link info (man netdevice) **/ - int if_mtu; - uint8_t if_macaddr[6]; - struct ifreq ifr; - strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - int iofd = socket(AF_INET6, SOCK_DGRAM, 0); - if (iofd < 0) PERROR_EXIT("Fail to create socket"); - // macaddr - if (ioctl(iofd, SIOCGIFHWADDR, &ifr)) PERROR_EXIT("Fail to ioctl(HWADDR)"); - memcpy(if_macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(if_macaddr)); - // mtu - if (if_mtu <= 0) { - if (ioctl(iofd, SIOCGIFMTU, &ifr)) PERROR_EXIT("Fail to ioctl(MTU)"); - if_mtu = ifr.ifr_mtu; - } - // clean - close(iofd); - - int sfd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); - if (sfd < 0) PERROR_EXIT("Fail to create socket"); - - /* prepare ra message */ - init_ra_msg_buf(if_mtu-40); // sizeof ICMPv6 header = 40 - init_ra_msg(if_mtu, if_macaddr); - if (supRA_read_option(argv[2])) return 1; - - /** join ff02::2 **/ - struct ipv6_mreq mreq; - int hoplimit; - inet_pton(AF_INET6, "ff02::2", &mreq.ipv6mr_multiaddr); - mreq.ipv6mr_interface = ifid; - if (setsockopt(sfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) - PERROR_EXIT("Fail to setsockopt(ADD_MEMBERSHIP)"); - hoplimit = 255; - if (setsockopt(sfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hoplimit, sizeof(hoplimit)) < 0) - PERROR_EXIT("Fail to setsockopt(HOPS)"); - if (setsockopt(sfd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hoplimit, sizeof(hoplimit)) < 0) - PERROR_EXIT("Fail to setsockopt(HOPS)"); - if (setsockopt(sfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)) < 0) - PERROR_EXIT("Fail to setsockopt(BINDTODEVICE)"); - - struct icmp6_filter filter; - ICMP6_FILTER_SETBLOCKALL(&filter); - ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter); - if (setsockopt(sfd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter)) < 0) - PERROR_EXIT("Fail to setsockopt(ICMP6_FILTER)"); - - /** ff02::1 **/ - struct sockaddr_in6 bcaddr; - bcaddr.sin6_family = AF_INET6; - bcaddr.sin6_port = 0; - inet_pton(AF_INET6, "ff02::1", &bcaddr.sin6_addr); - bcaddr.sin6_scope_id = ifid; - socklen_t bcaddrlen = sizeof(bcaddr); - - /** epoll **/ - int epfd = epoll_create1(0); - if (epfd < 0) PERROR_EXIT("Fail to create epoll"); - struct epoll_event ev = { - .events = EPOLLIN, - .data.fd = sfd, - }; - if (epoll_ctl(epfd, EPOLL_CTL_ADD, sfd, &ev)) - PERROR_EXIT("Fail to epoll_ctl(ADD)"); - const int evcnt = 1; - struct epoll_event evs[evcnt]; - - /** loop **/ - srand(time(NULL)); - time_t tnext = time(NULL); + signal(SIGHUP, empty_handler); while (1) { - time_t now = time(NULL); - if (now >= tnext) { // advertise right now - send_ra(sfd, (struct sockaddr*)&bcaddr, bcaddrlen); - tnext = now + 200 + 400*rand()/RAND_MAX; // TODO - puts("to ff02::1"); + const char *ifname = argv[1]; + int ifid = if_nametoindex(ifname); + if (ifid == 0) PERROR_EXIT("Bad Interface"); + + /** get link info (man netdevice) **/ + struct ifreq ifr; + strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + int iofd = socket(AF_INET6, SOCK_DGRAM, 0); + if (iofd < 0) PERROR_EXIT("Fail to create socket"); + // macaddr + uint8_t if_macaddr[6]; + if (ioctl(iofd, SIOCGIFHWADDR, &ifr)) PERROR_EXIT("Fail to ioctl(HWADDR)"); + memcpy(if_macaddr, &ifr.ifr_hwaddr.sa_data, sizeof(if_macaddr)); + // mtu + if (ioctl(iofd, SIOCGIFMTU, &ifr)) PERROR_EXIT("Fail to ioctl(MTU)"); + int if_mtu = ifr.ifr_mtu; + // clean + close(iofd); + + /* open icmpv6 socket */ + int sfd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); + if (sfd < 0) PERROR_EXIT("Fail to create socket"); + + /* prepare ra message */ + init_ra_msg_buf(if_mtu-40); // sizeof ICMPv6 header = 40 + init_ra_msg(if_mtu, if_macaddr); + if (supRA_read_option(argv[2])) return 1; + + /** join ff02::2 **/ + struct ipv6_mreq mreq; + int hoplimit; + inet_pton(AF_INET6, "ff02::2", &mreq.ipv6mr_multiaddr); + mreq.ipv6mr_interface = ifid; + if (setsockopt(sfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) + PERROR_EXIT("Fail to setsockopt(ADD_MEMBERSHIP)"); + hoplimit = 255; + if (setsockopt(sfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hoplimit, sizeof(hoplimit)) < 0) + PERROR_EXIT("Fail to setsockopt(HOPS)"); + if (setsockopt(sfd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hoplimit, sizeof(hoplimit)) < 0) + PERROR_EXIT("Fail to setsockopt(HOPS)"); + if (setsockopt(sfd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)) < 0) + PERROR_EXIT("Fail to setsockopt(BINDTODEVICE)"); + + struct icmp6_filter filter; + ICMP6_FILTER_SETBLOCKALL(&filter); + ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filter); + if (setsockopt(sfd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, sizeof(filter)) < 0) + PERROR_EXIT("Fail to setsockopt(ICMP6_FILTER)"); + + /** ff02::1 **/ + struct sockaddr_in6 bcaddr; + bcaddr.sin6_family = AF_INET6; + bcaddr.sin6_port = 0; + inet_pton(AF_INET6, "ff02::1", &bcaddr.sin6_addr); + bcaddr.sin6_scope_id = ifid; + socklen_t bcaddrlen = sizeof(bcaddr); + + /** epoll **/ + int epfd = epoll_create1(0); + if (epfd < 0) PERROR_EXIT("Fail to create epoll"); + struct epoll_event ev = { + .events = EPOLLIN, + .data.fd = sfd, + }; + if (epoll_ctl(epfd, EPOLL_CTL_ADD, sfd, &ev)) + PERROR_EXIT("Fail to epoll_ctl(ADD)"); + const int evcnt = 1; + struct epoll_event evs[evcnt]; + + /** loop **/ + srand(time(NULL)); + time_t tnext = time(NULL); + while (1) { + time_t now = time(NULL); + if (now >= tnext) { // advertise right now + send_ra(sfd, (struct sockaddr*)&bcaddr, bcaddrlen); + tnext = now + 200 + 400*rand()/RAND_MAX; // TODO + } + + // wait for message or timeout + int evc = epoll_wait(epfd, evs, evcnt, tnext-now); + if (evc < 0) { + // interrupt => reload settings + if (errno == EINTR) break; + // other error + PERROR_EXIT("Fail to epoll_wait"); + } + + // received message + if (evc) { + struct sockaddr_in6 caddr; + socklen_t caddrlen = sizeof(caddr); + struct icmpv6_head msg; + ssize_t msglen = recvfrom(sfd, &msg, sizeof msg, 0, (struct sockaddr*)&caddr, &caddrlen); + if (msglen < 0) PERROR_EXIT("Fail to recvfrom()"); + // only response to RS + if (msglen == sizeof msg && msg.type == ICMPV6_RS) { + send_ra(sfd, (struct sockaddr*)&caddr, caddrlen); + } + } } - int evc = epoll_wait(epfd, evs, evcnt, tnext-now); - if (evc < 0) PERROR_EXIT("Fail to epoll_wait"); - while (evc--) { - uint32_t fd = evs[evc].data.fd; - uint8_t buf[4096]; - char caddr_p[INET6_ADDRSTRLEN]; - struct sockaddr_in6 caddr; - socklen_t caddrlen = sizeof(caddr); - ssize_t buflen = recvfrom(sfd, buf, sizeof(buf), 0, (struct sockaddr*)&caddr, &caddrlen); - if (buflen < 0) PERROR_EXIT("Fail to recvfrom()"); - if (buflen < sizeof(struct icmpv6_head)) continue; // bad message - // if (caddr.sin6_scope_id != ifid) continue; - inet_ntop(AF_INET6, &caddr.sin6_addr, caddr_p, sizeof(caddr_p)); - // struct icmpv6_head *h = (struct icmpv6_head*)buf; - send_ra(sfd, (struct sockaddr*)&caddr, caddrlen); - printf("to %s%%%d\n", caddr_p, caddr.sin6_scope_id); - } + // clean up + close(sfd); + close(epfd); + puts("Reloading..."); } return 0; }