router: make RA flags configurable (FS#2019)
authorHans Dedecker <dedeckeh@gmail.com>
Fri, 17 May 2019 19:29:25 +0000 (21:29 +0200)
committerHans Dedecker <dedeckeh@gmail.com>
Fri, 17 May 2019 19:29:25 +0000 (21:29 +0200)
Replace the config option ra_management by the config options ra_flags
and ra_slaac. The latter allows to configure the autonomous-address
config flag used for stateless address configuration while the former
allows to configure the RA flags in the form of a list.
The list can hold the following values :
managed-config
other-config
home-agent
none

Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
README
src/config.c
src/dhcpv6-ia.c
src/odhcpd.h
src/router.c

diff --git a/README b/README
index a379c4cfbf5a028a3d05ad4ce3ab5d27b32af144..a5ed3199cf1b43f0f2909b11b6dca2b965895ebb 100644 (file)
--- a/README
+++ b/README
@@ -111,8 +111,10 @@ limit                      integer 150                     DHCPv4 pool size
 
 ra_default             integer 0                       Override default route
                        0: default, 1: ignore no public address, 2: ignore all
-ra_management          integer 1                       RA management mode
-                       0: no M-Flag but A-Flag, 1: both M and A, 2: M but not A
+ra_flags               list    other-config            List of RA flags to be
+                                                       advertised in RA messages
+                       [managed-config other-config home-agent none]
+ra_slaac               bool    1                       Announce slaac for a prefix
 ra_offlink             bool    0                       Announce prefixes off-link
 ra_preference          string  medium                  Route(r) preference
                        [medium|high|low]
index 3f64d16bd2f33fa47410c5bf97653fa2d6bac307..53528a0137cb285a92d1a77a2d5d3579fa56b6df 100644 (file)
@@ -59,7 +59,8 @@ enum {
        IFACE_ATTR_DHCPV6_PD,
        IFACE_ATTR_DHCPV6_NA,
        IFACE_ATTR_RA_DEFAULT,
-       IFACE_ATTR_RA_MANAGEMENT,
+       IFACE_ATTR_RA_FLAGS,
+       IFACE_ATTR_RA_SLAAC,
        IFACE_ATTR_RA_OFFLINK,
        IFACE_ATTR_RA_PREFERENCE,
        IFACE_ATTR_RA_ADVROUTER,
@@ -106,7 +107,8 @@ static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = {
        [IFACE_ATTR_PD_MANAGER] = { .name = "pd_manager", .type = BLOBMSG_TYPE_STRING },
        [IFACE_ATTR_PD_CER] = { .name = "pd_cer", .type = BLOBMSG_TYPE_STRING },
        [IFACE_ATTR_RA_DEFAULT] = { .name = "ra_default", .type = BLOBMSG_TYPE_INT32 },
-       [IFACE_ATTR_RA_MANAGEMENT] = { .name = "ra_management", .type = BLOBMSG_TYPE_INT32 },
+       [IFACE_ATTR_RA_FLAGS] = { .name = "ra_flags", . type = BLOBMSG_TYPE_ARRAY },
+       [IFACE_ATTR_RA_SLAAC] = { .name = "ra_slaac", .type = BLOBMSG_TYPE_BOOL },
        [IFACE_ATTR_RA_OFFLINK] = { .name = "ra_offlink", .type = BLOBMSG_TYPE_BOOL },
        [IFACE_ATTR_RA_PREFERENCE] = { .name = "ra_preference", .type = BLOBMSG_TYPE_STRING },
        [IFACE_ATTR_RA_ADVROUTER] = { .name = "ra_advrouter", .type = BLOBMSG_TYPE_BOOL },
@@ -182,6 +184,14 @@ const struct uci_blob_param_list odhcpd_attr_list = {
        .params = odhcpd_attrs,
 };
 
+static const struct { const char *name; uint8_t flag; } ra_flags[] = {
+       { .name = "managed-config", .flag = ND_RA_FLAG_MANAGED },
+       { .name = "other-config", .flag = ND_RA_FLAG_OTHER },
+       { .name = "home-agent", .flag = ND_RA_FLAG_HOME_AGENT },
+       { .name = "none", . flag = 0 },
+       { .name = NULL, },
+};
+
 static int mkdir_p(char *dir, mode_t mask)
 {
        char *l = strrchr(dir, '/');
@@ -221,7 +231,8 @@ static void set_interface_defaults(struct interface *iface)
        iface->dhcpv6_assignall = true;
        iface->dhcpv6_pd = true;
        iface->dhcpv6_na = true;
-       iface->ra_managed = RA_MANAGED_MFLAG;
+       iface->ra_flags = ND_RA_FLAG_OTHER;
+       iface->ra_slaac = true;
        iface->ra_maxinterval = 600;
        iface->ra_mininterval = iface->ra_maxinterval/3;
        iface->ra_lifetime = -1;
@@ -273,6 +284,34 @@ static int parse_mode(const char *mode)
                return -1;
 }
 
+static int parse_ra_flags(uint8_t *flags, struct blob_attr *attr)
+{
+       struct blob_attr *cur;
+       unsigned rem;
+
+       blobmsg_for_each_attr(cur, attr, rem) {
+               int i;
+
+               if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
+                       continue;
+
+                if (!blobmsg_check_attr(cur, false))
+                        continue;
+
+               for (i = 0; ra_flags[i].name; i++) {
+                       if (!strcmp(ra_flags[i].name, blobmsg_get_string(cur))) {
+                               *flags |= ra_flags[i].flag;
+                               break;
+                       }
+               }
+
+               if (!ra_flags[i].name)
+                       return -1;
+       }
+
+       return 0;
+}
+
 static void set_config(struct uci_section *s)
 {
        struct blob_attr *tb[ODHCPD_ATTR_MAX], *c;
@@ -695,8 +734,11 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr
        if ((c = tb[IFACE_ATTR_RA_DEFAULT]))
                iface->default_router = blobmsg_get_u32(c);
 
-       if ((c = tb[IFACE_ATTR_RA_MANAGEMENT]))
-               iface->ra_managed = blobmsg_get_u32(c);
+       if ((c = tb[IFACE_ATTR_RA_FLAGS])) {
+               iface->ra_flags = 0;
+               if (parse_ra_flags(&iface->ra_flags, c) < 0)
+                       goto err;
+       }
 
        if ((c = tb[IFACE_ATTR_RA_REACHABLETIME])) {
                uint32_t ra_reachabletime = blobmsg_get_u32(c);
@@ -730,6 +772,9 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr
                iface->ra_mtu = ra_mtu;
        }
 
+       if ((c = tb[IFACE_ATTR_RA_SLAAC]))
+               iface->ra_slaac = blobmsg_get_bool(c);
+
        if ((c = tb[IFACE_ATTR_RA_OFFLINK]))
                iface->ra_not_onlink = blobmsg_get_bool(c);
 
index c0dfa2d7d18cf3b05ce98742fe310fae5b9736f2..55b3cd4e8a34cbcb86db38c4e954a07fde085422 100644 (file)
@@ -687,7 +687,7 @@ static void handle_addrlist_change(struct netevent_handler_info *info)
        time_t now = odhcpd_time();
 
        list_for_each_entry(c, &iface->ia_assignments, head) {
-               if (c != border && iface->ra_managed == RA_MANAGED_NO_MFLAG
+               if (c != border && !(iface->ra_flags & ND_RA_FLAG_MANAGED)
                                && (c->flags & OAF_BOUND))
                        __apply_lease(iface, c, info->addrs_old.addrs,
                                        info->addrs_old.len, false);
index 37a5a4a4c6e448683f7f4daae924e3d84b983059..8715ca700bd236b17c851ca779f00d48611849ba 100644 (file)
@@ -246,6 +246,13 @@ struct interface {
        bool master;
        bool ignore;
        bool always_rewrite_dns;
+
+       // NDP
+       int learn_routes;
+
+       // RA
+       uint8_t ra_flags;
+       bool ra_slaac;
        bool ra_not_onlink;
        bool ra_advrouter;
        bool ra_useleasetime;
@@ -253,11 +260,7 @@ struct interface {
        bool no_dynamic_dhcp;
        uint8_t pio_filter_length;
        struct in6_addr pio_filter_addr;
-
-       // RA
-       int learn_routes;
        int default_router;
-       int ra_managed;
        int route_preference;
        int ra_maxinterval;
        int ra_mininterval;
@@ -303,10 +306,6 @@ struct interface {
 
 extern struct avl_tree interfaces;
 
-#define RA_MANAGED_NO_MFLAG    0
-#define RA_MANAGED_MFLAG       1
-#define RA_MANAGED_NO_AFLAG    2
-
 inline static void free_assignment(struct dhcp_assignment *a)
 {
        list_del(&a->head);
index 63571a3f025623242a187b20c7944fd66d3aea1f..50324283d4e5bca231b3ba3527d6fb89b10886d0 100644 (file)
@@ -436,12 +436,7 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
        if (hlim > 0)
                adv.h.nd_ra_curhoplimit = hlim;
 
-       if (iface->dhcpv6 != MODE_DISABLED) {
-               adv.h.nd_ra_flags_reserved = ND_RA_FLAG_OTHER;
-
-               if (iface->ra_managed >= RA_MANAGED_MFLAG)
-                       adv.h.nd_ra_flags_reserved |= ND_RA_FLAG_MANAGED;
-       }
+       adv.h.nd_ra_flags_reserved = iface->ra_flags;
 
        if (iface->route_preference < 0)
                adv.h.nd_ra_flags_reserved |= ND_RA_PREF_LOW;
@@ -558,7 +553,7 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
                p->nd_opt_pi_flags_reserved = 0;
                if (!iface->ra_not_onlink)
                        p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
-               if (iface->ra_managed < RA_MANAGED_NO_AFLAG && addr->prefix <= 64)
+               if (iface->ra_slaac && addr->prefix <= 64)
                        p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
                if (iface->ra_advrouter)
                        p->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_RADDR;