diff mbox series

odhcp6c: add DNS RA option lifetime support

Message ID mailman.16142.1629362917.1072.openwrt-devel@lists.openwrt.org
State New
Delegated to: Hans Dedecker
Headers show
Series odhcp6c: add DNS RA option lifetime support | expand

Commit Message

Asura Liu \(asuliu\) Aug. 19, 2021, 8:48 a.m. UTC
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 <asuliu@cisco.com>
---
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 mbox series

Patch

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 <stdint.h>
#include <stdbool.h>
+#include <time.h>
#include <netinet/in.h>

#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;