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.
--- Begin Message ---
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 <asu...@cisco.com>
---
CMakeLists.txt |   2 +-
src/dhcpv6.c   |   2 +-
src/odhcp6c.c  | 110 +++++++++++++++++++++++++++++++++++++++++++++++--
src/odhcp6c.h  |   2 +
4 files changed, 111 insertions(+), 5 deletions(-)

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



--- End Message ---
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to