* Re: [PATCH 02/11] netconfig: Add DHCP override and static IP API
@ 2022-04-18 19:15 Denis Kenzior
0 siblings, 0 replies; 3+ messages in thread
From: Denis Kenzior @ 2022-04-18 19:15 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 7738 bytes --]
Hi Andrew,
On 4/11/22 09:20, Andrew Zaborowski wrote:
> Add API to override things like DNS, gateway/router address, domain
> names, etc. received from DHCP or disable DHCP completely by setting
> a static address.
> ---
> ell/ell.sym | 8 +
> ell/netconfig.c | 413 +++++++++++++++++++++++++++++++++++++++++++++++-
> ell/netconfig.h | 16 ++
> 3 files changed, 432 insertions(+), 5 deletions(-)
>
<snip>
> +LIB_EXPORT bool l_netconfig_set_static_addr(struct l_netconfig *netconfig,
> + uint8_t family,
> + const struct l_rtnl_address *addr)
> +{
> + if (unlikely(!netconfig || netconfig->started))
> + return false;
> +
> + if (addr && l_rtnl_address_get_family(addr) != family)
> + return false;
> +
> + switch (family) {
> + case AF_INET:
> + l_rtnl_address_free(l_steal_ptr(netconfig->v4_static_addr));
> +
> + if (addr)
> + break;
I take it this should be !addr?
> +
> + netconfig->v4_static_addr = l_rtnl_address_clone(addr);
> + l_rtnl_address_set_lifetimes(netconfig->v4_static_addr, 0, 0);
> +
> + /*
> + * We could leave the decision about this flag up to the
> + * caller but for simplicity override to true.
> + */
> + l_rtnl_address_set_noprefixroute(netconfig->v4_static_addr,
> + true);
> + return true;
> + case AF_INET6:
> + l_rtnl_address_free(l_steal_ptr(netconfig->v6_static_addr));
> +
> + if (addr)
> + break;
> +
And here as well?
> + netconfig->v6_static_addr = l_rtnl_address_clone(addr);
> + l_rtnl_address_set_lifetimes(netconfig->v6_static_addr, 0, 0);
> + l_rtnl_address_set_noprefixroute(netconfig->v6_static_addr,
> + true);
> + return true;
> + }
> +
> + return false;
> +}
> +
<snip>
> +static bool netconfig_check_v4_config(struct l_netconfig *netconfig)
> +{
> + struct in_addr local;
> + struct in_addr gateway;
> + uint8_t prefix_len = 0;
> + unsigned int dns_num = 0;
> + _auto_(l_free) struct in_addr *dns_list = NULL;
> +
> + if (!netconfig->v4_enabled)
> + return true;
> +
> + if (netconfig->v4_static_addr) {
> + char str[INET_ADDRSTRLEN];
> +
> + prefix_len = l_rtnl_address_get_prefix_length(
> + netconfig->v4_static_addr);
> + if (prefix_len > 30)
> + return false;
> +
> + l_rtnl_address_get_address(netconfig->v4_static_addr, str);
> + inet_pton(AF_INET, str, &local);
> + }
> +
> + if (netconfig->v4_gateway_override) {
> + if (inet_pton(AF_INET, netconfig->v4_gateway_override,
> + &gateway) != 1)
> + return false;
> + }
> +
> + if (netconfig->v4_dns_override &&
> + (dns_num = l_strv_length(netconfig->v4_dns_override))) {
> + unsigned int i;
> +
> + dns_list = l_new(struct in_addr, dns_num);
> +
> + for (i = 0; i < dns_num; i++)
> + if (inet_pton(AF_INET, netconfig->v4_dns_override[i],
> + &dns_list[i]) != 1)
> + return false;
> + }
> +
> + /*
> + * If using a static IP, we can validate right now that the gateway is
> + * in the local subnet.
> + */
> + if (netconfig->v4_static_addr && netconfig->v4_gateway_override)
> + if (!l_net_subnet_matches(&local, &gateway, prefix_len))
> + return false;
> +
> + /*
> + * If using a static IP and there's no gateway all the DNSes mut be on
typo: mut -> must
> + * the local subnet too.
> + */
> + if (netconfig->v4_static_addr && !netconfig->v4_gateway_override &&
> + netconfig->v4_dns_override) {
> + unsigned int i;
> +
> + for (i = 0; i < dns_num; i++)
> + if (!l_net_subnet_matches(&local, &dns_list[i],
> + prefix_len))
> + return false;
> + }
> +
> + return true;
> +}
> +
> +static bool netconfig_check_v6_config(struct l_netconfig *netconfig)
> +{
> + struct in_addr local;
> + struct in_addr gateway;
> + uint8_t prefix_len = 0;
> + unsigned int dns_num = 0;
> + _auto_(l_free) struct in6_addr *dns_list = NULL;
> +
> + if (!netconfig->v6_enabled)
> + return true;
> +
> + if (netconfig->v6_static_addr) {
> + char str[INET6_ADDRSTRLEN];
> +
> + prefix_len = l_rtnl_address_get_prefix_length(
> + netconfig->v6_static_addr);
> + if (prefix_len > 126)
> + return false;
> +
> + l_rtnl_address_get_address(netconfig->v6_static_addr, str);
> + inet_pton(AF_INET6, str, &local);
> + }
> +
> + if (netconfig->v6_gateway_override) {
> + if (inet_pton(AF_INET6, netconfig->v6_gateway_override,
> + &gateway) != 1)
> + return false;
> + }
> +
> + if (netconfig->v6_dns_override &&
> + (dns_num = l_strv_length(netconfig->v6_dns_override))) {
> + unsigned int i;
> +
> + dns_list = l_new(struct in6_addr, dns_num);
> +
> + for (i = 0; i < dns_num; i++)
> + if (inet_pton(AF_INET6, netconfig->v6_dns_override[i],
> + &dns_list[i]) != 1)
> + return false;
> + }
> +
> + /*
> + * If using a static IP, we can validate right now that the gateway is
> + * in the local subnet.
> + */
> + if (netconfig->v6_static_addr && netconfig->v6_gateway_override)
> + if (!l_net_subnet_matches(&local, &gateway, prefix_len))
> + return false;
Not sure this is true? AFAIK the default gateway could be a link local address...
> +
> + /*
> + * If using a static IP and there's no gateway all the DNSes mut be on
Same typo as above.
> + * the local subnet too.
> + */
> + if (netconfig->v6_static_addr && !netconfig->v6_gateway_override &&
> + netconfig->v6_dns_override) {
> + unsigned int i;
> +
> + for (i = 0; i < dns_num; i++)
> + if (!l_net_subnet_matches(&local, &dns_list[i],
> + prefix_len))
> + return false;
This whole block maybe should be a static convenience function? In fact, much
of these checks are the same as in v4 version of this function and could be
combined?
> + }
> +
> + return true;
> +}
> +
<snip>
> LIB_EXPORT bool l_netconfig_start(struct l_netconfig *netconfig)
> {
> if (unlikely(!netconfig || netconfig->started))
> return false;
>
> - if (netconfig->v4_enabled &&
> - !l_dhcp_client_start(netconfig->dhcp_client))
> + if (!netconfig_check_config(netconfig))
> return false;
>
Can we check that both v4_enabled and v6_enabled are false and return appropriately?
> - netconfig->started = true;
> + if (netconfig->v4_enabled) {
I'd prefer less nesting, so something like:
if (!netconfig->v4_enabled)
goto configure_ipv6;
> + if (netconfig->v4_static_addr) {
> + /*
> + * We're basically ready to configure the interface
> + * but do this in an idle callback.
> + */
> + netconfig->do_static_work = l_idle_create(
> + netconfig_do_static_config,
> + netconfig, NULL);
goto here..
> + } else {
> + if (!l_dhcp_client_start(netconfig->dhcp_client))
> + return false;
> + }
> + }
>
> + netconfig->started = true;
> return true;
> }
>
<snip>
> diff --git a/ell/netconfig.h b/ell/netconfig.h
> index 682f4aa..aab9d3f 100644
> --- a/ell/netconfig.h
> +++ b/ell/netconfig.h
> @@ -53,6 +53,22 @@ typedef void (*l_netconfig_destroy_cb_t)(void *user_data);
>
> struct l_netconfig *l_netconfig_new(uint32_t ifindex);
> void l_netconfig_destroy(struct l_netconfig *netconfig);
> +bool l_netconfig_set_af_enabled(struct l_netconfig *netconfig, uint8_t family,
> + bool enabled);
Can we call it family_enabled?
> +bool l_netconfig_set_static_addr(struct l_netconfig *netconfig, uint8_t family,
> + const struct l_rtnl_address *addr);
> +bool l_netconfig_set_gateway_override(struct l_netconfig *netconfig,
> + uint8_t family,
> + const char *gateway_str);
Wonder why you use l_rtnl_address for 'set_static_addr' and a string for the
gateway?
Regards,
-Denis
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 02/11] netconfig: Add DHCP override and static IP API
@ 2022-04-19 7:59 Andrew Zaborowski
0 siblings, 0 replies; 3+ messages in thread
From: Andrew Zaborowski @ 2022-04-19 7:59 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 5525 bytes --]
On Mon, 18 Apr 2022 at 21:15, Denis Kenzior <denkenz(a)gmail.com> wrote:
> On 4/11/22 09:20, Andrew Zaborowski wrote:
> > + switch (family) {
> > + case AF_INET:
> > + l_rtnl_address_free(l_steal_ptr(netconfig->v4_static_addr));
> > +
> > + if (addr)
> > + break;
>
> I take it this should be !addr?
Yep.
>
> > +
> > + netconfig->v4_static_addr = l_rtnl_address_clone(addr);
> > + l_rtnl_address_set_lifetimes(netconfig->v4_static_addr, 0, 0);
> > +
> > + /*
> > + * We could leave the decision about this flag up to the
> > + * caller but for simplicity override to true.
> > + */
> > + l_rtnl_address_set_noprefixroute(netconfig->v4_static_addr,
> > + true);
> > + return true;
> > + case AF_INET6:
> > + l_rtnl_address_free(l_steal_ptr(netconfig->v6_static_addr));
> > +
> > + if (addr)
> > + break;
> > +
>
> And here as well?
Yep.
> > + /*
> > + * If using a static IP and there's no gateway all the DNSes mut be on
>
> typo: mut -> must
Right.
>
> > + /*
> > + * If using a static IP, we can validate right now that the gateway is
> > + * in the local subnet.
> > + */
> > + if (netconfig->v6_static_addr && netconfig->v6_gateway_override)
> > + if (!l_net_subnet_matches(&local, &gateway, prefix_len))
> > + return false;
>
> Not sure this is true? AFAIK the default gateway could be a link local address...
True, that's also a good catch. I'll add a check for that (unless you
prefer we don't validate this address.)
>
> > +
> > + /*
> > + * If using a static IP and there's no gateway all the DNSes mut be on
>
> Same typo as above.
>
> > + * the local subnet too.
> > + */
> > + if (netconfig->v6_static_addr && !netconfig->v6_gateway_override &&
> > + netconfig->v6_dns_override) {
> > + unsigned int i;
> > +
> > + for (i = 0; i < dns_num; i++)
> > + if (!l_net_subnet_matches(&local, &dns_list[i],
> > + prefix_len))
> > + return false;
>
> This whole block maybe should be a static convenience function? In fact, much
> of these checks are the same as in v4 version of this function and could be
> combined?
Ok, let me try to combine them.
>
> > + }
> > +
> > + return true;
> > +}
> > +
>
> <snip>
>
> > LIB_EXPORT bool l_netconfig_start(struct l_netconfig *netconfig)
> > {
> > if (unlikely(!netconfig || netconfig->started))
> > return false;
> >
> > - if (netconfig->v4_enabled &&
> > - !l_dhcp_client_start(netconfig->dhcp_client))
> > + if (!netconfig_check_config(netconfig))
> > return false;
> >
>
> Can we check that both v4_enabled and v6_enabled are false and return appropriately?
Ok. We effectively do but let me add one at the beginning.
>
> > - netconfig->started = true;
> > + if (netconfig->v4_enabled) {
>
> I'd prefer less nesting, so something like:
>
> if (!netconfig->v4_enabled)
> goto configure_ipv6;
Ok.
>
> > + if (netconfig->v4_static_addr) {
> > + /*
> > + * We're basically ready to configure the interface
> > + * but do this in an idle callback.
> > + */
> > + netconfig->do_static_work = l_idle_create(
> > + netconfig_do_static_config,
> > + netconfig, NULL);
>
> goto here..
>
> > + } else {
> > + if (!l_dhcp_client_start(netconfig->dhcp_client))
> > + return false;
> > + }
> > + }
> >
> > + netconfig->started = true;
> > return true;
> > }
> >
>
> <snip>
>
> > diff --git a/ell/netconfig.h b/ell/netconfig.h
> > index 682f4aa..aab9d3f 100644
> > --- a/ell/netconfig.h
> > +++ b/ell/netconfig.h
> > @@ -53,6 +53,22 @@ typedef void (*l_netconfig_destroy_cb_t)(void *user_data);
> >
> > struct l_netconfig *l_netconfig_new(uint32_t ifindex);
> > void l_netconfig_destroy(struct l_netconfig *netconfig);
> > +bool l_netconfig_set_af_enabled(struct l_netconfig *netconfig, uint8_t family,
> > + bool enabled);
>
> Can we call it family_enabled?
Sure.
>
> > +bool l_netconfig_set_static_addr(struct l_netconfig *netconfig, uint8_t family,
> > + const struct l_rtnl_address *addr);
> > +bool l_netconfig_set_gateway_override(struct l_netconfig *netconfig,
> > + uint8_t family,
> > + const char *gateway_str);
>
> Wonder why you use l_rtnl_address for 'set_static_addr' and a string for the
> gateway?
So l_rtnl_address includes the prefix length and such, so the struct
maps to our own addresses. The gateway would map to the next-hop
address in the l_rtnl_route struct so it didn't seem fitting. Note
that l_rtnl_route doesn't use l_rtnl_address for that in its API.
Best regards
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 02/11] netconfig: Add DHCP override and static IP API
@ 2022-04-11 14:20 Andrew Zaborowski
0 siblings, 0 replies; 3+ messages in thread
From: Andrew Zaborowski @ 2022-04-11 14:20 UTC (permalink / raw)
To: ell
[-- Attachment #1: Type: text/plain, Size: 15315 bytes --]
Add API to override things like DNS, gateway/router address, domain
names, etc. received from DHCP or disable DHCP completely by setting
a static address.
---
ell/ell.sym | 8 +
ell/netconfig.c | 413 +++++++++++++++++++++++++++++++++++++++++++++++-
ell/netconfig.h | 16 ++
3 files changed, 432 insertions(+), 5 deletions(-)
diff --git a/ell/ell.sym b/ell/ell.sym
index a03dc69..ec995fc 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -735,6 +735,14 @@ global:
/* netconfig */
l_netconfig_new;
l_netconfig_destroy;
+ l_netconfig_set_af_enabled;
+ l_netconfig_set_hostname;
+ l_netconfig_set_route_priority;
+ l_netconfig_set_static_addr;
+ l_netconfig_set_gateway_override;
+ l_netconfig_set_dns_override;
+ l_netconfig_set_domain_names_override;
+ l_netconfig_check_config;
l_netconfig_start;
l_netconfig_stop;
l_netconfig_get_dhcp_client;
diff --git a/ell/netconfig.c b/ell/netconfig.c
index 2808536..d0f87b3 100644
--- a/ell/netconfig.c
+++ b/ell/netconfig.c
@@ -37,16 +37,32 @@
#include "rtnl.h"
#include "queue.h"
#include "time.h"
+#include "idle.h"
+#include "strv.h"
+#include "net.h"
#include "netconfig.h"
struct l_netconfig {
uint32_t ifindex;
- bool v4_enabled;
- bool started;
uint32_t route_priority;
+ bool v4_enabled;
+ struct l_rtnl_address *v4_static_addr;
+ char *v4_gateway_override;
+ char **v4_dns_override;
+ char **v4_domain_names_override;
+
+ bool v6_enabled;
+ struct l_rtnl_address *v6_static_addr;
+ char *v6_gateway_override;
+ char **v6_dns_override;
+ char **v6_domain_names_override;
+
+ bool started;
+ struct l_idle *do_static_work;
bool v4_configured;
struct l_dhcp_client *dhcp_client;
+
/* These objects, if not NULL, are owned by @addresses and @routes */
struct l_rtnl_address *v4_address;
struct l_rtnl_route *v4_subnet_route;
@@ -128,6 +144,11 @@ static void netconfig_add_v4_routes(struct l_netconfig *nc, const char *ip,
/* Gateway route */
+ if (nc->v4_gateway_override) {
+ gateway = nc->v4_gateway_override;
+ rtm_protocol = RTPROT_STATIC;
+ }
+
if (!gateway)
return;
@@ -310,6 +331,15 @@ LIB_EXPORT void l_netconfig_destroy(struct l_netconfig *netconfig)
l_netconfig_stop(netconfig);
+ l_netconfig_set_static_addr(netconfig, AF_INET, NULL);
+ l_netconfig_set_gateway_override(netconfig, AF_INET, NULL);
+ l_netconfig_set_dns_override(netconfig, AF_INET, NULL);
+ l_netconfig_set_domain_names_override(netconfig, AF_INET, NULL);
+ l_netconfig_set_static_addr(netconfig, AF_INET6, NULL);
+ l_netconfig_set_gateway_override(netconfig, AF_INET6, NULL);
+ l_netconfig_set_dns_override(netconfig, AF_INET6, NULL);
+ l_netconfig_set_domain_names_override(netconfig, AF_INET6, NULL);
+
l_dhcp_client_destroy(netconfig->dhcp_client);
l_netconfig_set_event_handler(netconfig, NULL, NULL, NULL);
l_queue_destroy(netconfig->addresses.current, NULL);
@@ -323,17 +353,387 @@ LIB_EXPORT void l_netconfig_destroy(struct l_netconfig *netconfig)
l_free(netconfig);
}
+/*
+ * The following l_netconfig_set_* functions configure the l_netconfig's
+ * client settings. The setters can be called independently, without
+ * following a specific order. Most of the setters will not validate the
+ * values passed, l_netconfig_start() will fail if settings are incorrect
+ * or inconsistent between themselves, e.g. if the static local IP and
+ * gateway IP are not in the same subnet. Alternatively
+ * l_netconfig_check_config() can be called at any point to validate the
+ * current configuration. The configuration can only be changed while
+ * the l_netconfig state machine is stopped, i.e. before
+ * l_netconfig_start() and after l_netconfig_stop().
+ *
+ * l_netconfig_set_hostname, l_netconfig_set_static_addr,
+ * l_netconfig_set_gateway_override, l_netconfig_set_dns_override and
+ * l_netconfig_set_domain_names_override can be passed NULL to unset a
+ * value that had been set before (revert to auto). This is why the
+ * family parameter is needed even when it could otherwise be derived
+ * from the new value that is passed.
+ */
+LIB_EXPORT bool l_netconfig_set_af_enabled(struct l_netconfig *netconfig,
+ uint8_t family, bool enabled)
+{
+ if (unlikely(!netconfig || netconfig->started))
+ return false;
+
+ switch (family) {
+ case AF_INET:
+ netconfig->v4_enabled = enabled;
+ return true;
+ }
+
+ return false;
+}
+
+LIB_EXPORT bool l_netconfig_set_hostname(struct l_netconfig *netconfig,
+ const char *hostname)
+{
+ if (unlikely(!netconfig || netconfig->started))
+ return false;
+
+ return l_dhcp_client_set_hostname(netconfig->dhcp_client, hostname);
+}
+
+LIB_EXPORT bool l_netconfig_set_route_priority(struct l_netconfig *netconfig,
+ uint32_t priority)
+{
+ if (unlikely(!netconfig || netconfig->started))
+ return false;
+
+ netconfig->route_priority = priority;
+ return true;
+}
+
+LIB_EXPORT bool l_netconfig_set_static_addr(struct l_netconfig *netconfig,
+ uint8_t family,
+ const struct l_rtnl_address *addr)
+{
+ if (unlikely(!netconfig || netconfig->started))
+ return false;
+
+ if (addr && l_rtnl_address_get_family(addr) != family)
+ return false;
+
+ switch (family) {
+ case AF_INET:
+ l_rtnl_address_free(l_steal_ptr(netconfig->v4_static_addr));
+
+ if (addr)
+ break;
+
+ netconfig->v4_static_addr = l_rtnl_address_clone(addr);
+ l_rtnl_address_set_lifetimes(netconfig->v4_static_addr, 0, 0);
+
+ /*
+ * We could leave the decision about this flag up to the
+ * caller but for simplicity override to true.
+ */
+ l_rtnl_address_set_noprefixroute(netconfig->v4_static_addr,
+ true);
+ return true;
+ case AF_INET6:
+ l_rtnl_address_free(l_steal_ptr(netconfig->v6_static_addr));
+
+ if (addr)
+ break;
+
+ netconfig->v6_static_addr = l_rtnl_address_clone(addr);
+ l_rtnl_address_set_lifetimes(netconfig->v6_static_addr, 0, 0);
+ l_rtnl_address_set_noprefixroute(netconfig->v6_static_addr,
+ true);
+ return true;
+ }
+
+ return false;
+}
+
+LIB_EXPORT bool l_netconfig_set_gateway_override(struct l_netconfig *netconfig,
+ uint8_t family,
+ const char *gateway_str)
+{
+ if (unlikely(!netconfig || netconfig->started))
+ return false;
+
+ switch (family) {
+ case AF_INET:
+ l_free(l_steal_ptr(netconfig->v4_gateway_override));
+
+ if (!gateway_str)
+ break;
+
+ netconfig->v4_gateway_override = l_strdup(gateway_str);
+ return true;
+ case AF_INET6:
+ l_free(l_steal_ptr(netconfig->v6_gateway_override));
+
+ if (!gateway_str)
+ break;
+
+ netconfig->v6_gateway_override = l_strdup(gateway_str);
+ return true;
+ }
+
+ return false;
+}
+
+LIB_EXPORT bool l_netconfig_set_dns_override(struct l_netconfig *netconfig,
+ uint8_t family, char **dns_list)
+{
+ if (unlikely(!netconfig || netconfig->started))
+ return false;
+
+ switch (family) {
+ case AF_INET:
+ l_strv_free(l_steal_ptr(netconfig->v4_dns_override));
+
+ if (!dns_list)
+ break;
+
+ netconfig->v4_dns_override = l_strv_copy(dns_list);
+ return true;
+ case AF_INET6:
+ l_strv_free(l_steal_ptr(netconfig->v6_dns_override));
+
+ if (!dns_list)
+ break;
+
+ netconfig->v6_dns_override = l_strv_copy(dns_list);
+ return true;
+ }
+
+ return false;
+}
+
+LIB_EXPORT bool l_netconfig_set_domain_names_override(
+ struct l_netconfig *netconfig,
+ uint8_t family, char **names)
+{
+ if (unlikely(!netconfig || netconfig->started))
+ return false;
+
+ switch (family) {
+ case AF_INET:
+ l_strv_free(l_steal_ptr(netconfig->v4_domain_names_override));
+
+ if (!names)
+ break;
+
+ netconfig->v4_domain_names_override = l_strv_copy(names);
+ return true;
+ case AF_INET6:
+ l_strv_free(l_steal_ptr(netconfig->v6_domain_names_override));
+
+ if (!names)
+ break;
+
+ netconfig->v6_domain_names_override = l_strv_copy(names);
+ return true;
+ }
+
+ return false;
+}
+
+static bool netconfig_check_v4_config(struct l_netconfig *netconfig)
+{
+ struct in_addr local;
+ struct in_addr gateway;
+ uint8_t prefix_len = 0;
+ unsigned int dns_num = 0;
+ _auto_(l_free) struct in_addr *dns_list = NULL;
+
+ if (!netconfig->v4_enabled)
+ return true;
+
+ if (netconfig->v4_static_addr) {
+ char str[INET_ADDRSTRLEN];
+
+ prefix_len = l_rtnl_address_get_prefix_length(
+ netconfig->v4_static_addr);
+ if (prefix_len > 30)
+ return false;
+
+ l_rtnl_address_get_address(netconfig->v4_static_addr, str);
+ inet_pton(AF_INET, str, &local);
+ }
+
+ if (netconfig->v4_gateway_override) {
+ if (inet_pton(AF_INET, netconfig->v4_gateway_override,
+ &gateway) != 1)
+ return false;
+ }
+
+ if (netconfig->v4_dns_override &&
+ (dns_num = l_strv_length(netconfig->v4_dns_override))) {
+ unsigned int i;
+
+ dns_list = l_new(struct in_addr, dns_num);
+
+ for (i = 0; i < dns_num; i++)
+ if (inet_pton(AF_INET, netconfig->v4_dns_override[i],
+ &dns_list[i]) != 1)
+ return false;
+ }
+
+ /*
+ * If using a static IP, we can validate right now that the gateway is
+ * in the local subnet.
+ */
+ if (netconfig->v4_static_addr && netconfig->v4_gateway_override)
+ if (!l_net_subnet_matches(&local, &gateway, prefix_len))
+ return false;
+
+ /*
+ * If using a static IP and there's no gateway all the DNSes mut be on
+ * the local subnet too.
+ */
+ if (netconfig->v4_static_addr && !netconfig->v4_gateway_override &&
+ netconfig->v4_dns_override) {
+ unsigned int i;
+
+ for (i = 0; i < dns_num; i++)
+ if (!l_net_subnet_matches(&local, &dns_list[i],
+ prefix_len))
+ return false;
+ }
+
+ return true;
+}
+
+static bool netconfig_check_v6_config(struct l_netconfig *netconfig)
+{
+ struct in_addr local;
+ struct in_addr gateway;
+ uint8_t prefix_len = 0;
+ unsigned int dns_num = 0;
+ _auto_(l_free) struct in6_addr *dns_list = NULL;
+
+ if (!netconfig->v6_enabled)
+ return true;
+
+ if (netconfig->v6_static_addr) {
+ char str[INET6_ADDRSTRLEN];
+
+ prefix_len = l_rtnl_address_get_prefix_length(
+ netconfig->v6_static_addr);
+ if (prefix_len > 126)
+ return false;
+
+ l_rtnl_address_get_address(netconfig->v6_static_addr, str);
+ inet_pton(AF_INET6, str, &local);
+ }
+
+ if (netconfig->v6_gateway_override) {
+ if (inet_pton(AF_INET6, netconfig->v6_gateway_override,
+ &gateway) != 1)
+ return false;
+ }
+
+ if (netconfig->v6_dns_override &&
+ (dns_num = l_strv_length(netconfig->v6_dns_override))) {
+ unsigned int i;
+
+ dns_list = l_new(struct in6_addr, dns_num);
+
+ for (i = 0; i < dns_num; i++)
+ if (inet_pton(AF_INET6, netconfig->v6_dns_override[i],
+ &dns_list[i]) != 1)
+ return false;
+ }
+
+ /*
+ * If using a static IP, we can validate right now that the gateway is
+ * in the local subnet.
+ */
+ if (netconfig->v6_static_addr && netconfig->v6_gateway_override)
+ if (!l_net_subnet_matches(&local, &gateway, prefix_len))
+ return false;
+
+ /*
+ * If using a static IP and there's no gateway all the DNSes mut be on
+ * the local subnet too.
+ */
+ if (netconfig->v6_static_addr && !netconfig->v6_gateway_override &&
+ netconfig->v6_dns_override) {
+ unsigned int i;
+
+ for (i = 0; i < dns_num; i++)
+ if (!l_net_subnet_matches(&local, &dns_list[i],
+ prefix_len))
+ return false;
+ }
+
+ return true;
+}
+
+static bool netconfig_check_config(struct l_netconfig *netconfig)
+{
+ /* TODO: error reporting through a debug log handler or otherwise */
+
+ return netconfig_check_v4_config(netconfig) &&
+ netconfig_check_v6_config(netconfig);
+}
+
+LIB_EXPORT bool l_netconfig_check_config(struct l_netconfig *netconfig)
+{
+ if (unlikely(!netconfig || netconfig->started))
+ return false;
+
+ return netconfig_check_config(netconfig);
+}
+
+static void netconfig_add_static_address_routes(struct l_netconfig *nc)
+{
+ char ip[INET_ADDRSTRLEN];
+ uint32_t prefix_len;
+
+ nc->v4_address = l_rtnl_address_clone(nc->v4_static_addr);
+ l_queue_push_tail(nc->addresses.current, nc->v4_address);
+ l_queue_push_tail(nc->addresses.added, nc->v4_address);
+
+ l_rtnl_address_get_address(nc->v4_static_addr, ip);
+ prefix_len = l_rtnl_address_get_prefix_length(nc->v4_static_addr);
+ netconfig_add_v4_routes(nc, ip, prefix_len, NULL, RTPROT_STATIC);
+}
+
+static void netconfig_do_static_config(struct l_idle *idle, void *user_data)
+{
+ struct l_netconfig *nc = user_data;
+
+ l_idle_remove(l_steal_ptr(nc->do_static_work));
+
+ if (nc->v4_static_addr && !nc->v4_configured) {
+ netconfig_add_static_address_routes(nc);
+ nc->v4_configured = true;
+ netconfig_emit_event(nc, AF_INET, L_NETCONFIG_EVENT_CONFIGURE);
+ }
+}
+
LIB_EXPORT bool l_netconfig_start(struct l_netconfig *netconfig)
{
if (unlikely(!netconfig || netconfig->started))
return false;
- if (netconfig->v4_enabled &&
- !l_dhcp_client_start(netconfig->dhcp_client))
+ if (!netconfig_check_config(netconfig))
return false;
- netconfig->started = true;
+ if (netconfig->v4_enabled) {
+ if (netconfig->v4_static_addr) {
+ /*
+ * We're basically ready to configure the interface
+ * but do this in an idle callback.
+ */
+ netconfig->do_static_work = l_idle_create(
+ netconfig_do_static_config,
+ netconfig, NULL);
+ } else {
+ if (!l_dhcp_client_start(netconfig->dhcp_client))
+ return false;
+ }
+ }
+ netconfig->started = true;
return true;
}
@@ -344,6 +744,9 @@ LIB_EXPORT void l_netconfig_stop(struct l_netconfig *netconfig)
netconfig->started = false;
+ if (netconfig->do_static_work)
+ l_idle_remove(l_steal_ptr(netconfig->do_static_work));
+
netconfig_update_cleanup(netconfig);
l_queue_clear(netconfig->routes.current,
(l_queue_destroy_func_t) l_rtnl_route_free);
diff --git a/ell/netconfig.h b/ell/netconfig.h
index 682f4aa..aab9d3f 100644
--- a/ell/netconfig.h
+++ b/ell/netconfig.h
@@ -53,6 +53,22 @@ typedef void (*l_netconfig_destroy_cb_t)(void *user_data);
struct l_netconfig *l_netconfig_new(uint32_t ifindex);
void l_netconfig_destroy(struct l_netconfig *netconfig);
+bool l_netconfig_set_af_enabled(struct l_netconfig *netconfig, uint8_t family,
+ bool enabled);
+bool l_netconfig_set_hostname(struct l_netconfig *netconfig,
+ const char *hostname);
+bool l_netconfig_set_route_priority(struct l_netconfig *netconfig,
+ uint32_t priority);
+bool l_netconfig_set_static_addr(struct l_netconfig *netconfig, uint8_t family,
+ const struct l_rtnl_address *addr);
+bool l_netconfig_set_gateway_override(struct l_netconfig *netconfig,
+ uint8_t family,
+ const char *gateway_str);
+bool l_netconfig_set_dns_override(struct l_netconfig *netconfig, uint8_t family,
+ char **dns_list);
+bool l_netconfig_set_domain_names_override(struct l_netconfig *netconfig,
+ uint8_t family, char **names);
+bool l_netconfig_check_config(struct l_netconfig *netconfig);
bool l_netconfig_start(struct l_netconfig *netconfig);
void l_netconfig_stop(struct l_netconfig *netconfig);
--
2.32.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2022-04-19 7:59 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-18 19:15 [PATCH 02/11] netconfig: Add DHCP override and static IP API Denis Kenzior
-- strict thread matches above, loose matches on Subject: below --
2022-04-19 7:59 Andrew Zaborowski
2022-04-11 14:20 Andrew Zaborowski
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.