From d11180932b2fb8784aaad0830c032e42b8bb64ac Mon Sep 17 00:00:00 2001 From: Hans Dedecker Date: Fri, 17 May 2019 21:29:25 +0200 Subject: [PATCH] router: make RA flags configurable (FS#2019) 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 --- README | 6 ++++-- src/config.c | 55 ++++++++++++++++++++++++++++++++++++++++++++----- src/dhcpv6-ia.c | 2 +- src/odhcpd.h | 15 +++++++------- src/router.c | 9 ++------ 5 files changed, 64 insertions(+), 23 deletions(-) diff --git a/README b/README index a379c4c..a5ed319 100644 --- 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] diff --git a/src/config.c b/src/config.c index 3f64d16..53528a0 100644 --- a/src/config.c +++ b/src/config.c @@ -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); diff --git a/src/dhcpv6-ia.c b/src/dhcpv6-ia.c index c0dfa2d..55b3cd4 100644 --- a/src/dhcpv6-ia.c +++ b/src/dhcpv6-ia.c @@ -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); diff --git a/src/odhcpd.h b/src/odhcpd.h index 37a5a4a..8715ca7 100644 --- a/src/odhcpd.h +++ b/src/odhcpd.h @@ -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); diff --git a/src/router.c b/src/router.c index 63571a3..5032428 100644 --- a/src/router.c +++ b/src/router.c @@ -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; -- 2.30.2