1- From 62a8c0e6db9de52493842c982a723dd155ac7736 Mon Sep 17 00:00:00 2001
1+ From 9ee21c537eea6321ed644e284a1d9c13de342fef Mon Sep 17 00:00:00 2001
2+ From: skbeh <60107333+skbeh@users.noreply.github.com>
23Date: Sat, 16 Sep 2023 15:04:12 +0000
3- Subject: [PATCH] odhcpd: RFC 9096 compliance
4+ Subject: [PATCH] config: allow configuring max limit for preferred and valid
5+ lifetime
46
5- and allow configuring upper limit for preferred and valid lifetime.
67---
7- README | 9 +++++-- --
8- src/config.c | 34 +++++++++++++++++++++++++++++++++-
8+ README | 5 +++--
9+ src/config.c | 32 ++++++++++++++++++++++++++++++++
910 src/dhcpv6-ia.c | 9 +++++++++
1011 src/odhcpd.h | 6 ++++++
11- src/router.c | 23 +++++++++++++++++------
12- src/router.h | 2 +-
13- 6 files changed, 71 insertions(+), 12 deletions(-)
12+ src/router.c | 37 +++++++++++++++++++++++++++++--------
13+ 5 files changed, 79 insertions(+), 10 deletions(-)
1414
1515diff --git a/README b/README
16- index 8f0e6a4..c899cd5 100644
16+ index 8f0e6a4..ddf8534 100644
1717--- a/README
1818+++ b/README
19- @@ -126,12 +126,13 @@ ra_slaac bool 1 Announce slaac for a prefix
20- ra_offlink bool 0 Announce prefixes off-link
21- ra_preference string medium Route(r) preference
22- [medium|high|low]
23- - ra_maxinterval integer 600 Maximum time allowed between
24- + ra_maxinterval integer 900 Maximum time allowed between
19+ @@ -130,8 +130,9 @@ ra_maxinterval integer 600 Maximum time allowed between
2520 sending unsolicited RA
26- - ra_mininterval integer 200 Minimum time allowed between
27- + ra_mininterval integer 300 Minimum time allowed between
21+ ra_mininterval integer 200 Minimum time allowed between
2822 sending unsolicited RA
2923- ra_lifetime integer 1800 Value to be placed in Router
3024- Lifetime field of RA
@@ -35,7 +29,7 @@ index 8f0e6a4..c899cd5 100644
3529 limit for the preferred and
3630 valid lifetime of a prefix
3731diff --git a/src/config.c b/src/config.c
38- index e631814..d8ff6f7 100644
32+ index e631814..3281b5f 100644
3933--- a/src/config.c
4034+++ b/src/config.c
4135@@ -92,6 +92,8 @@ enum {
@@ -56,15 +50,6 @@ index e631814..d8ff6f7 100644
5650 [IFACE_ATTR_NTP] = { .name = "ntp", .type = BLOBMSG_TYPE_ARRAY },
5751 };
5852
59- @@ -224,7 +228,7 @@ static void set_interface_defaults(struct interface *iface)
60- iface->dns_service = true;
61- iface->ra_flags = ND_RA_FLAG_OTHER;
62- iface->ra_slaac = true;
63- - iface->ra_maxinterval = 600;
64- + iface->ra_maxinterval = 900;
65- iface->ra_mininterval = iface->ra_maxinterval/3;
66- iface->ra_lifetime = -1;
67- iface->ra_dns = true;
6853@@ -648,6 +652,34 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr
6954
7055 }
@@ -145,28 +130,27 @@ index 08b4920..58ab155 100644
145130 // DHCP
146131 uint32_t dhcp_leasetime;
147132diff --git a/src/router.c b/src/router.c
148- index d5ef7f8..b4d52aa 100644
133+ index d5ef7f8..55eaa6d 100644
149134--- a/src/router.c
150135+++ b/src/router.c
151- @@ -371,7 +371,7 @@ static int calc_adv_interval(struct interface *iface, uint32_t minvalid,
152-
153- static uint32_t calc_ra_lifetime(struct interface *iface, uint32_t maxival)
154- {
155- - uint32_t lifetime = 3*maxival;
156- + uint32_t lifetime = maxival * 3;
157-
158- if (iface->ra_lifetime >= 0) {
159- lifetime = iface->ra_lifetime;
160- @@ -452,7 +452,7 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
136+ @@ -452,7 +452,8 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
161137 size_t dns_sz = 0, search_sz = 0, pref64_sz = 0;
162138 size_t pfxs_cnt = 0, routes_cnt = 0;
163139 ssize_t valid_addr_cnt = 0, invalid_addr_cnt = 0;
164140- uint32_t minvalid = UINT32_MAX, maxival, lifetime;
165- + uint32_t minvalid = ND_VALID_LIMIT, maxival, lifetime;
141+ + uint32_t minvalid = UINT32_MAX, maxival, lifetime, max_prefix_vlt = ND_VALID_LIMIT;
142+ + uint32_t calculated_ra_lifetime;
166143 int msecs, mtu = iface->ra_mtu, hlim = iface->ra_hoplimit;
167144 bool default_route = false;
168145 bool valid_prefix = false;
169- @@ -602,6 +602,17 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
146+ @@ -598,10 +599,24 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
147+ if (addr->valid > (uint32_t)now) {
148+ valid = TIME_LEFT(addr->valid, now);
149+
150+ + if (valid < max_prefix_vlt)
151+ + max_prefix_vlt = valid;
152+ +
153+ if (iface->ra_useleasetime && valid > iface->dhcp_leasetime)
170154 valid = iface->dhcp_leasetime;
171155 }
172156
@@ -184,13 +168,25 @@ index d5ef7f8..b4d52aa 100644
184168 if (minvalid > valid)
185169 minvalid = valid;
186170
187- @@ -637,15 +648,15 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
171+ @@ -629,24 +644,30 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
172+
173+ /* Calculate periodic transmit */
174+ msecs = calc_adv_interval(iface, minvalid, &maxival);
175+ - lifetime = calc_ra_lifetime(iface, maxival);
176+ + calculated_ra_lifetime = min(calc_ra_lifetime(iface, maxival), UINT16_MAX);
177+ + lifetime = min(calculated_ra_lifetime, max_prefix_vlt);
178+
179+ if (!iface->have_link_local) {
180+ syslog(LOG_NOTICE, "Skip sending a RA on %s as no link local address is available", iface->name);
181+ goto out;
188182 }
189183
190- if (default_route && valid_prefix) {
184+ - if (default_route && valid_prefix) {
191185- adv.h.nd_ra_router_lifetime = htons(lifetime < UINT16_MAX ? lifetime : UINT16_MAX);
192- + adv.h.nd_ra_router_lifetime = htons(lifetime);
193- } else {
186+ - } else {
187+ + /* RFC9096: CE routers SHOULD set the "Router Lifetime" of Router Advertisement (RA) messages to ND_PREFERRED_LIMIT. */
188+ + adv.h.nd_ra_router_lifetime = htons(ND_PREFERRED_LIMIT);
189+ + if (!(default_route && valid_prefix)) {
194190 adv.h.nd_ra_router_lifetime = 0;
195191
196192 if (default_route) {
@@ -201,9 +197,15 @@ index d5ef7f8..b4d52aa 100644
201197- syslog(LOG_WARNING, "No default route present, overriding ra_lifetime!");
202198+ syslog(LOG_WARNING, "No default route present, setting ra_lifetime to zero!");
203199 }
200+ + } else if (iface->ra_lifetime >= 0) {
201+ + adv.h.nd_ra_router_lifetime = htons(calculated_ra_lifetime);
202+ + if (calculated_ra_lifetime == 0)
203+ + syslog(LOG_WARNING, "A default route is present and there is public prefix "
204+ + "but ra_lifetime on iface was set to zero, setting ra_lifetime to zero!");
204205 }
205206
206- @@ -710,7 +721,7 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
207+ syslog(LOG_DEBUG, "Using a RA lifetime of %d seconds on %s", ntohs(adv.h.nd_ra_router_lifetime), iface->name);
208+ @@ -710,7 +731,7 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr
207209
208210 if (iface->pref64_length) {
209211 /* RFC 8781 § 4.1 rounding up lifetime to multiply of 8 */
@@ -212,18 +214,5 @@ index d5ef7f8..b4d52aa 100644
212214 uint8_t prefix_length_code;
213215 uint32_t mask_a1, mask_a2;
214216
215- diff --git a/src/router.h b/src/router.h
216- index 0444da8..a994892 100644
217- --- a/src/router.h
218- +++ b/src/router.h
219- @@ -32,7 +32,7 @@ struct icmpv6_opt {
220-
221- #define MaxInitialRtrAdvInterval 16
222- #define MaxInitialRtAdvs 3
223- - #define MaxRtrAdvInterval 1800
224- + #define MaxRtrAdvInterval 2700
225- #define MinRtrAdvInterval 3
226-
227- #define ND_RA_FLAG_PROXY 0x4
228217- -
2292182.42.0
0 commit comments