From c82c5bbb29f2eb34ab90f3781f18d8367e67a77a Mon Sep 17 00:00:00 2001 From: initramfs Date: Mon, 12 Sep 2022 18:19:15 +0800 Subject: [PATCH] Add autoignoreprefixes option to interface --- gram.y | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ interface.c | 8 +++++++ radvd.conf.5.man | 18 +++++++++++++-- radvd.h | 10 +++++++++ scanner.l | 1 + send.c | 18 ++++++++++++++- 6 files changed, 109 insertions(+), 3 deletions(-) diff --git a/gram.y b/gram.y index 23a9f24..c9493c9 100644 --- a/gram.y +++ b/gram.y @@ -53,6 +53,7 @@ %token T_ABRO %token T_RASRCADDRESS %token T_NAT64PREFIX +%token T_AUTOIGNOREPREFIX %token STRING %token NUMBER @@ -139,6 +140,7 @@ %type number_or_infinity %type rasrcaddresslist v6addrlist_rasrcaddress %type nat64prefixdef +%type ignoreprefixlist ignoreprefixes %union { unsigned int num; @@ -155,6 +157,7 @@ struct AdvAbro *abroinfo; struct AdvRASrcAddress *rasrcaddressinfo; struct NAT64Prefix *nat64pinfo; + struct AutogenIgnorePrefix *igpinfo; }; %{ @@ -241,6 +244,7 @@ ifaceparam : ifaceval | abrodef { ADD_TO_LL(struct AdvAbro, AdvAbroList, $1); } | rasrcaddresslist { ADD_TO_LL(struct AdvRASrcAddress, AdvRASrcAddressList, $1); } | nat64prefixdef { ADD_TO_LL(struct NAT64Prefix, NAT64PrefixList, $1); } + | ignoreprefixlist { ADD_TO_LL(struct AutogenIgnorePrefix, IgnorePrefixList, $1); } ; ifaceval : T_MinRtrAdvInterval NUMBER ';' @@ -568,6 +572,59 @@ nat64prefixparms : T_AdvValidLifetime NUMBER ';' } ; +ignoreprefixlist : T_AUTOIGNOREPREFIX '{' ignoreprefixes '}' ';' + { + $$ = $3; + } + ; + +ignoreprefixes : IPV6ADDR '/' NUMBER ';' + { + struct AutogenIgnorePrefix *new = calloc(1, sizeof(struct AutogenIgnorePrefix)); + if (new == NULL) { + flog(LOG_CRIT, "calloc failed: %s", strerror(errno)); + ABORT; + } + + memcpy(&(new->Prefix), $1, sizeof(struct in6_addr)); + + // Create subnet mask from CIDR notation + int fullOctets = $3 / 8; + for (int i = 0; i < fullOctets; ++i) { + new->Mask.s6_addr[i] = 0xff; + } + + if (fullOctets != 16) { + new->Mask.s6_addr[fullOctets] = ~(1 << (8 - $3 % 8)) + 1; + } + + $$ = new; + } + | ignoreprefixes IPV6ADDR '/' NUMBER ';' + { + struct AutogenIgnorePrefix *new = calloc(1, sizeof(struct AutogenIgnorePrefix)); + if (new == NULL) { + flog(LOG_CRIT, "calloc failed: %s", strerror(errno)); + ABORT; + } + + memcpy(&(new->Prefix), $2, sizeof(struct in6_addr)); + + // Create subnet mask from CIDR notation + int fullOctets = $4 / 8; + for (int i = 0; i < fullOctets; ++i) { + new->Mask.s6_addr[i] = 0xff; + } + + if (fullOctets != 16) { + new->Mask.s6_addr[fullOctets] = ~(1 << (8 - $4 % 8)) + 1; + } + + new->next = $1; + $$ = new; + } + ; + prefixdef : prefixhead optional_prefixplist ';' { if (prefix) { diff --git a/interface.c b/interface.c index 1417d58..c2dd66b 100644 --- a/interface.c +++ b/interface.c @@ -436,6 +436,14 @@ static void free_iface_list(struct Interface *iface) dnssl = next_dnssl; } + struct AutogenIgnorePrefix *ignore_prefixes = iface->IgnorePrefixList; + while (ignore_prefixes) { + struct AutogenIgnorePrefix *next_ignore_prefix = ignore_prefixes->next; + + free(ignore_prefixes); + ignore_prefixes = next_ignore_prefix; + } + struct Clients *clients = iface->ClientList; while (clients) { struct Clients *next_client = clients->next; diff --git a/radvd.conf.5.man b/radvd.conf.5.man index 4a9a8b4..2666335 100644 --- a/radvd.conf.5.man +++ b/radvd.conf.5.man @@ -33,6 +33,7 @@ The file contains one or more interface definitions of the form: list of DNSSL definitions list of ABRO definitions list of NAT64 pref64 definitions + list of auto-ignore prefixes list of acceptable RA source addresses .B }; .fi @@ -56,8 +57,9 @@ Special prefix "::/64" is also supported on systems that implement getifaddrs() (on other systems, configuration activation fails and radvd exits). When configured, radvd picks all non-link-local prefix assigned to the interface and starts advertising -it. This may be applicable in non-6to4 scenarios where the upstream prefix might -change. This option is incompatible with Base6to4Interface option. +it (unless ignored with autoignoreprefixes). This may be applicable in non-6to4 +scenarios where the upstream prefix might change. This option is incompatible +with Base6to4Interface option. AdvRouterAddr option is always enabled when this configuration is used. All the possible prefix specific options are described below. Each @@ -144,6 +146,18 @@ The value of .B length can only be one of /32, /40, /48, /56, /64, or /96. +When using the special prefix "::/64" this option forms an ignore list for +prefixes that should not be automatically generated and advertised. Has no +effect on any other prefix definition. + +The definitions are of the form: + +.nf +.BR autoignoreprefixes " " { + list of IPv6 prefixes +.B }; +.fi + .SH INTERFACE SPECIFIC OPTIONS .TP diff --git a/radvd.h b/radvd.h index 0fa0456..9e636fc 100644 --- a/radvd.h +++ b/radvd.h @@ -30,6 +30,7 @@ extern int disableigmp6check; struct AdvPrefix; struct NAT64Prefix; +struct AutogenIgnorePrefix; struct Clients; #define HWADDR_MAX 16 @@ -107,6 +108,8 @@ struct Interface { struct NAT64Prefix *NAT64PrefixList; + struct AutogenIgnorePrefix *IgnorePrefixList; + uint32_t AdvLinkMTU; /* XXX: sllao also has an if_maxmtu value...Why? */ uint32_t AdvRAMTU; /* MTU used for RA */ @@ -179,6 +182,13 @@ struct NAT64Prefix { struct NAT64Prefix *next; }; +struct AutogenIgnorePrefix { + struct in6_addr Prefix; + struct in6_addr Mask; + + struct AutogenIgnorePrefix *next; +}; + /* More-Specific Routes extensions */ struct AdvRoute { diff --git a/scanner.l b/scanner.l index cb17c5a..e5bb721 100644 --- a/scanner.l +++ b/scanner.l @@ -52,6 +52,7 @@ clients { return T_CLIENTS; } lowpanco { return T_LOWPANCO; } abro { return T_ABRO; } nat64prefix { return T_NAT64PREFIX; } +autoignoreprefixes { return T_AUTOIGNOREPREFIX; } AdvRASrcAddress { return T_RASRCADDRESS; } diff --git a/send.c b/send.c index fecdf46..6e2fe59 100644 --- a/send.c +++ b/send.c @@ -415,8 +415,24 @@ static struct safe_buffer_list *add_auto_prefixes(struct safe_buffer_list *sbl, if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr)) continue; + struct in6_addr prefix6 = get_prefix6(&s6->sin6_addr, &mask->sin6_addr); + + int ignore = 0; + for (struct AutogenIgnorePrefix *current = iface->IgnorePrefixList; current; current = current->next) { + struct in6_addr candidatePrefix6 = get_prefix6(¤t->Prefix, ¤t->Mask); + + if (memcmp(&prefix6, &candidatePrefix6, sizeof(struct in6_addr)) == 0 && + memcmp(&mask->sin6_addr, ¤t->Mask, sizeof(struct in6_addr)) == 0) { + ignore = 1; + break; + } + } + + if (ignore) + continue; + xprefix = *prefix; - xprefix.Prefix = get_prefix6(&s6->sin6_addr, &mask->sin6_addr); + xprefix.Prefix = prefix6; xprefix.PrefixLen = count_mask(mask); char pfx_str[INET6_ADDRSTRLEN];