* [PATCH 02/13] icmp6: Parse extra options
@ 2022-04-22 18:59 Andrew Zaborowski
0 siblings, 0 replies; 2+ messages in thread
From: Andrew Zaborowski @ 2022-04-22 18:59 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 6390 bytes --]
Parse Route Information and New Advertisement Interval options. Route
Information options (RIOs) are supported by radvd and a few clients that
I checked.
---
ell/icmp6-private.h | 6 ++-
ell/icmp6.c | 118 +++++++++++++++++++++++++++++++++++++++-----
2 files changed, 110 insertions(+), 14 deletions(-)
diff --git a/ell/icmp6-private.h b/ell/icmp6-private.h
index 2433087..77df0b8 100644
--- a/ell/icmp6-private.h
+++ b/ell/icmp6-private.h
@@ -22,6 +22,7 @@
struct route_info {
uint8_t address[16];
+ bool onlink : 1;
uint8_t prefix_len;
uint8_t preference;
uint32_t preferred_lifetime;
@@ -36,8 +37,9 @@ struct l_icmp6_router {
uint64_t start_time;
uint16_t lifetime;
uint32_t mtu;
- uint32_t n_prefixes;
- struct route_info *prefixes;
+ uint32_t max_rtr_adv_interval_ms;
+ uint32_t n_routes;
+ struct route_info *routes;
};
struct l_icmp6_router *_icmp6_router_new();
diff --git a/ell/icmp6.c b/ell/icmp6.c
index 0422a59..158cfa8 100644
--- a/ell/icmp6.c
+++ b/ell/icmp6.c
@@ -51,6 +51,11 @@
#include "icmp6.h"
#include "icmp6-private.h"
+/* RFC4191 */
+#ifndef ND_OPT_ROUTE_INFORMATION
+#define ND_OPT_ROUTE_INFORMATION 24
+#endif
+
#define CLIENT_DEBUG(fmt, args...) \
l_util_debug(client->debug_handler, client->debug_data, \
"%s:%i " fmt, __func__, __LINE__, ## args)
@@ -328,16 +333,24 @@ static void icmp6_client_setup_routes(struct l_icmp6_client *client)
l_rtnl_route_add(client->rtnl, client->ifindex, rt,
NULL, NULL, NULL);
- for (i = 0; i < ra->n_prefixes; i++) {
- struct route_info *info = &ra->prefixes[i];
+ for (i = 0; i < ra->n_routes; i++) {
+ char prefix_buf[INET6_ADDRSTRLEN];
+ struct route_info *info = &ra->routes[i];
if (info->valid_lifetime == 0)
continue;
- if (!inet_ntop(AF_INET6, info->address, buf, sizeof(buf)))
+ if (!inet_ntop(AF_INET6, info->address, prefix_buf,
+ sizeof(prefix_buf)))
continue;
- rt = l_rtnl_route_new_prefix(buf, info->prefix_len);
+ if (info->onlink)
+ rt = l_rtnl_route_new_prefix(prefix_buf,
+ info->prefix_len);
+ else
+ rt = l_rtnl_route_new_static(buf, prefix_buf,
+ info->prefix_len);
+
if (!rt)
continue;
@@ -669,7 +682,7 @@ struct l_icmp6_router *_icmp6_router_new()
void _icmp6_router_free(struct l_icmp6_router *r)
{
- l_free(r->prefixes);
+ l_free(r->routes);
l_free(r);
}
@@ -681,7 +694,7 @@ struct l_icmp6_router *_icmp6_router_parse(const struct nd_router_advert *ra,
struct l_icmp6_router *r;
const uint8_t *opts;
uint32_t opts_len;
- uint32_t n_prefixes = 0;
+ uint32_t n_routes = 0;
if (ra->nd_ra_type != ND_ROUTER_ADVERT)
return NULL;
@@ -718,7 +731,35 @@ struct l_icmp6_router *_icmp6_router_parse(const struct nd_router_advert *ra,
return NULL;
if (opts[3] & ND_OPT_PI_FLAG_ONLINK)
- n_prefixes += 1;
+ n_routes += 1;
+ break;
+ case ND_OPT_ROUTE_INFORMATION:
+ if (l < 8)
+ return NULL;
+
+ if (opts[2] > 128 || opts[2] > (l - 8) * 8)
+ return NULL;
+
+ /*
+ * RFC 4191 Section 2.3:
+ * "If the Reserved (10) value is received, the Route
+ * Information Option MUST be ignored."
+ */
+ if (bit_field(opts[3], 3, 2) == 2)
+ break;
+
+ /*
+ * RFC 4191 Section 3.1:
+ * "The Router Preference and Lifetime values in a ::/0
+ * Route Information Option override the preference and
+ * lifetime values in the Router Advertisement header."
+ *
+ * Don't count ::/0 routes.
+ */
+ if (opts[2] == 0)
+ break;
+
+ n_routes += 1;
break;
}
@@ -728,8 +769,8 @@ struct l_icmp6_router *_icmp6_router_parse(const struct nd_router_advert *ra,
r = _icmp6_router_new();
memcpy(r->address, src, sizeof(r->address));
- r->prefixes = l_new(struct route_info, n_prefixes);
- r->n_prefixes = n_prefixes;
+ r->routes = l_new(struct route_info, n_routes);
+ r->n_routes = n_routes;
if (ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
r->managed = true;
@@ -746,7 +787,7 @@ struct l_icmp6_router *_icmp6_router_parse(const struct nd_router_advert *ra,
opts = (uint8_t *) (ra + 1);
opts_len = len - sizeof(struct nd_router_advert);
- n_prefixes = 0;
+ n_routes = 0;
while (opts_len) {
uint8_t t = opts[0];
@@ -764,17 +805,70 @@ struct l_icmp6_router *_icmp6_router_parse(const struct nd_router_advert *ra,
break;
case ND_OPT_PREFIX_INFORMATION:
{
- struct route_info *i = &r->prefixes[n_prefixes];
+ struct route_info *i = &r->routes[n_routes];
if (!(opts[3] & ND_OPT_PI_FLAG_ONLINK))
break;
i->prefix_len = opts[2];
+ i->onlink = true;
i->valid_lifetime = l_get_be32(opts + 4);
i->preferred_lifetime = l_get_be32(opts + 8);
memcpy(i->address, opts + 16, 16);
- n_prefixes += 1;
+ n_routes += 1;
+ break;
+ }
+ case ND_OPT_RTR_ADV_INTERVAL:
+ if (l < 8)
+ break;
+
+ r->max_rtr_adv_interval_ms = l_get_be32(opts + 4);
+ break;
+ case ND_OPT_ROUTE_INFORMATION:
+ {
+ struct route_info *i = &r->routes[n_routes];
+ uint8_t preference = bit_field(opts[3], 3, 2);
+
+ if (preference == 2)
+ break;
+
+ /*
+ * RFC 4191 Section 3.1:
+ * "The Router Preference and Lifetime values in a ::/0
+ * Route Information Option override the preference and
+ * lifetime values in the Router Advertisement header."
+ */
+ if (opts[2] == 0) {
+ if (r->lifetime == 0 && l_get_be32(opts + 4)) {
+ /*
+ * A ::/0 route received from a
+ * non-default router? Should issue
+ * a warning?
+ */
+ break;
+ }
+
+ r->pref = preference;
+ r->lifetime = l_get_be16(opts + 4) ? 0xffff :
+ l_get_be16(opts + 6);
+ break;
+ }
+
+ /*
+ * Don't check or warn if the route lifetime is longer
+ * than the router lifetime because that refers to its
+ * time as the default router. It may be configured to
+ * route packets for us for specific prefixes without
+ * being a default router.
+ */
+ i->prefix_len = opts[2];
+ i->onlink = false;
+ i->preference = preference;
+ i->valid_lifetime = l_get_be32(opts + 4);
+ memcpy(i->address, opts + 8, (i->prefix_len + 7) / 8);
+
+ n_routes += 1;
break;
}
}
--
2.32.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH 02/13] icmp6: Parse extra options
@ 2022-04-22 21:39 Denis Kenzior
0 siblings, 0 replies; 2+ messages in thread
From: Denis Kenzior @ 2022-04-22 21:39 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 441 bytes --]
Hi Andrew,
On 4/22/22 13:59, Andrew Zaborowski wrote:
> Parse Route Information and New Advertisement Interval options. Route
> Information options (RIOs) are supported by radvd and a few clients that
> I checked.
> ---
> ell/icmp6-private.h | 6 ++-
> ell/icmp6.c | 118 +++++++++++++++++++++++++++++++++++++++-----
> 2 files changed, 110 insertions(+), 14 deletions(-)
>
Applied, thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-04-22 21:39 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-22 18:59 [PATCH 02/13] icmp6: Parse extra options Andrew Zaborowski
2022-04-22 21:39 Denis Kenzior
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).