From patchwork Thu Aug 19 08:48:20 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Asura Liu \\(asuliu\\)" X-Patchwork-Id: 1518524 X-Patchwork-Delegate: dedeckeh@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.openwrt.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=bombadil.20210309 header.b=Zav+1d8f; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Gqz5r4h8fz9t0T for ; Thu, 19 Aug 2021 18:51:44 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:Content-Type:List-Help: Reply-To:List-Archive:List-Unsubscribe:List-Subscribe:From:List-Post:List-Id: Message-ID:MIME-Version:Date:Subject:To:Cc:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Owner; bh=lTj2QT4IbjEsJjTp+mYPw6KzOWfzzf+OpL1SLFISTQo=; b=Zav+1d8f2YLzTXDvxymWYmMRyT /qzAGaUPUdLUgMZKF/zBqZB+HB77YM/mVCRW4O7wchnf5MexNH80j87W9o+Has7dUeE563T3G/mOn /olor1JpxWMvgHf+av9956svaljR1wf7ezracPq6Qp4CfC4cIImP+UUvuDkFJfQXpOnbfst8xcys+ 7cyySsICnG4ZyM95bwEV3u4a+er28BKMCi3+pzUNY7Dn4yb8ilo3mjIsdDTFtyX9jvEgtPkzDxmh7 K21jJLW2DBRZug1BSveVf3F0FNo9Rr0uylRicNM8xnkP8bN+Udd52yYmGUitdaUFnCIfHTH9Uzi3y ODUUXCzg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mGdjG-007lRB-Uw; Thu, 19 Aug 2021 08:48:51 +0000 To: Steven Barth Subject: [PATCH] odhcp6c: add DNS RA option lifetime support Date: Thu, 19 Aug 2021 08:48:20 +0000 MIME-Version: 1.0 Message-ID: List-Id: OpenWrt Development List List-Post: X-Patchwork-Original-From: "Asura Liu \(asuliu\) via openwrt-devel" From: "Asura Liu \\(asuliu\\)" Precedence: list X-Mailman-Version: 2.1.34 X-BeenThere: openwrt-devel@lists.openwrt.org List-Subscribe: , List-Unsubscribe: , List-Archive: Reply-To: "Asura Liu \(asuliu\)" List-Help: Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org The sender domain has a DMARC Reject/Quarantine policy which disallows sending mailing list messages using the original "From" header. To mitigate this problem, the original message has been wrapped automatically by the mailing list software. To support RFC 8106 DNS RA option lifetime, add timers for RA DNS and RA SEARCH options, when timer fires, expire invalid options in list. Signed-off-by: Asura Liu --- CMakeLists.txt | 2 +- src/dhcpv6.c | 2 +- src/odhcp6c.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++-- src/odhcp6c.h | 2 + 4 files changed, 111 insertions(+), 5 deletions(-) -- 2.27.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 94f279c..38e24f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ endif(${EXT_CER_ID}) set(SOURCES src/odhcp6c.c src/dhcpv6.c src/ra.c src/script.c) -set(LIBRARIES resolv) +set(LIBRARIES resolv rt) if(USE_LIBUBOX) add_definitions(-DUSE_LIBUBOX) diff --git a/src/dhcpv6.c b/src/dhcpv6.c index 51b9992..16961d2 100644 --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@ -1350,7 +1350,7 @@ static unsigned int dhcpv6_parse_ia(void *opt, void *end) // Update address IA dhcpv6_for_each_option(&ia_hdr[1], end, otype, olen, odata) { - struct odhcp6c_entry entry = {IN6ADDR_ANY_INIT, 0, 0, + struct odhcp6c_entry entry = {0, IN6ADDR_ANY_INIT, 0, 0, IN6ADDR_ANY_INIT, 0, 0, 0, 0, 0, 0}; entry.iaid = ia_hdr->iaid; diff --git a/src/odhcp6c.c b/src/odhcp6c.c index 227aef6..58302de 100644 --- a/src/odhcp6c.c +++ b/src/odhcp6c.c @@ -59,6 +59,10 @@ static volatile bool signal_io = false; static volatile bool signal_usr1 = false; static volatile bool signal_usr2 = false; static volatile bool signal_term = false; +static volatile bool signal_timer = false; + +static struct sigaction sa; +static struct sigevent se; static int urandom_fd = -1, allow_slaac_only = 0; static bool bound = false, release = true, ra = false; @@ -163,6 +167,77 @@ static struct odhcp6c_opt opts[] = { { .code = 0, .flags = 0, .str = NULL }, }; +static void timer_handler() +{ + syslog(LOG_DEBUG, "timer fired.\n"); + signal_timer = true; +} + +static int timer_init() +{ + int signo = SIGRTMIN; + + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = timer_handler; + + syslog(LOG_DEBUG, "in timer_init.\n"); + + sigemptyset(&sa.sa_mask); + if (sigaction(signo, &sa, NULL) == -1) + { + perror("sigaction install failed"); + return -1; + } + + /* Set and enable alarm */ + se.sigev_notify = SIGEV_SIGNAL; + se.sigev_signo = signo; + return 0; +} + +static int timer_set(timer_t timer, int count) +{ + struct itimerspec its; + its.it_interval.tv_sec = 0; + its.it_interval.tv_nsec = 0; + its.it_value.tv_sec = count; + its.it_value.tv_nsec = 0; + + syslog(LOG_DEBUG, "in timer_set, count = %d.\n", count); + + if (timer_settime(timer, 0, &its, NULL) == -1) + { + perror("timer settime failed"); + return -1; + } + + return 0; +} + +static int timer_add(timer_t *timer, int count) +{ + syslog(LOG_DEBUG, "in timer_add.\n"); + + if (timer_create(CLOCK_REALTIME, &se, timer) == -1) + { + perror("timer create failed"); + return -1; + } + + return timer_set(*timer, count); +} + +static int timer_del(timer_t *timer) +{ + int rc = 0; + + syslog(LOG_DEBUG, "in timer_del.\n"); + + rc = timer_delete(*timer); + *timer = 0; + return rc; +} + int main(_unused int argc, char* const argv[]) { static struct in6_addr ifid = IN6ADDR_ANY_INIT; @@ -404,6 +479,8 @@ int main(_unused int argc, char* const argv[]) if (help || !ifname) return usage(); + timer_init(); + signal(SIGIO, sighandler); signal(SIGHUP, sighandler); signal(SIGINT, sighandler); @@ -666,6 +743,16 @@ static uint8_t* odhcp6c_resize_state(enum odhcp6c_state state, ssize_t len) bool odhcp6c_signal_process(void) { + /* To apply the RFC 8106, DNS RA options could have a lower lifetime + * than MaxRtrAdvInterval. So the options could be expired between + * two RA messages, and need to be processed here. */ + if (signal_timer) { + signal_timer = false; + syslog(LOG_DEBUG, "timer arrived, expire invalid options...\n"); + odhcp6c_expire(); + script_call("ra-updated", 0, false); + } + while (signal_io) { signal_io = false; @@ -775,6 +862,9 @@ bool odhcp6c_update_entry(enum odhcp6c_state state, struct odhcp6c_entry *new, struct odhcp6c_entry *x = odhcp6c_find_entry(state, new); uint8_t *start = odhcp6c_get_state(state, &len); + syslog(LOG_ERR, "odhcp6c_update_entry state %d, valid %d, preferred %d", + state, new->valid, new->preferred); + if (x && x->valid > new->valid && new->valid < safe) new->valid = safe; @@ -793,10 +883,21 @@ bool odhcp6c_update_entry(enum odhcp6c_state state, struct odhcp6c_entry *new, x->t1 = new->t1; x->t2 = new->t2; x->iaid = new->iaid; - } else if (odhcp6c_add_state(state, new, odhcp6c_entry_size(new))) - return false; - } else if (x) + + if (state == STATE_RA_DNS || state == STATE_RA_SEARCH) + timer_set(x->timer, new->valid); + } else { + if (state == STATE_RA_DNS || state == STATE_RA_SEARCH) + timer_add(&new->timer, new->valid); + + if (odhcp6c_add_state(state, new, odhcp6c_entry_size(new))) + return false; + } + } else if (x) { + if (state == STATE_RA_DNS || state == STATE_RA_SEARCH) + timer_del(&x->timer); odhcp6c_remove_state(state, ((uint8_t*)x) - start, odhcp6c_entry_size(x)); + } return true; } @@ -831,6 +932,9 @@ static void odhcp6c_expire_list(enum odhcp6c_state state, uint32_t elapsed) c->valid -= elapsed; if (!c->valid) { + syslog(LOG_DEBUG, "in odhcp6c_expire_list expire state %d", state); + if (state == STATE_RA_DNS || state == STATE_RA_SEARCH) + timer_del(&c->timer); odhcp6c_remove_state(state, ((uint8_t*)c) - start, odhcp6c_entry_size(c)); start = odhcp6c_get_state(state, &len); } else diff --git a/src/odhcp6c.h b/src/odhcp6c.h index 14d0017..5a3d436 100644 --- a/src/odhcp6c.h +++ b/src/odhcp6c.h @@ -15,6 +15,7 @@ #pragma once #include #include +#include #include #define _unused __attribute__((unused)) @@ -345,6 +346,7 @@ enum odhcp6c_ia_mode { struct odhcp6c_entry { + timer_t timer; struct in6_addr router; uint8_t auxlen; uint8_t length;