From: James Prestwood <prestwoj@gmail.com>
To: iwd@lists.01.org
Subject: [PATCH v2 1/2] netconfig: add ACD client for static configuration
Date: Thu, 10 Dec 2020 13:22:09 -0800 [thread overview]
Message-ID: <20201210212210.880245-1-prestwoj@gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 4556 bytes --]
When the IP is configured to be static we can now use ACD in
order to check that the IP is available and not already in
use. If a conflict is found netconfig will be reset and no IP
will be set on the interface. The ACD client is left with
the default 'defend once' policy, and probes are not turned
off. This will increase connection time, but for static IP's
it is the best approach.
---
src/netconfig.c | 94 +++++++++++++++++++++++++++++++++++++++----------
1 file changed, 76 insertions(+), 18 deletions(-)
v2:
* Added netconfig_reset_v4 to allow a failed ACD attempt to
reset only the IPv4 data.
* Distinguish between CONFLICT/LOST events. For conflicts
no IP was ever set in the kernel, so we can just clean up
the rtnl address directly. For LOST events an address was
set, so it would need to be deleted.
diff --git a/src/netconfig.c b/src/netconfig.c
index f48a789a..e7a6a402 100644
--- a/src/netconfig.c
+++ b/src/netconfig.c
@@ -64,6 +64,8 @@ struct netconfig {
void *user_data;
struct resolve *resolve;
+
+ struct l_acd *acd;
};
static struct l_netlink *rtnl;
@@ -804,15 +806,87 @@ static void netconfig_dhcp6_event_handler(struct l_dhcp6_client *client,
}
}
+static void netconfig_reset_v4(struct netconfig *netconfig)
+{
+ if (netconfig->rtm_protocol) {
+ if (netconfig->v4_address) {
+ L_WARN_ON(!l_rtnl_ifaddr_delete(rtnl,
+ netconfig->ifindex,
+ netconfig->v4_address,
+ netconfig_ifaddr_del_cmd_cb,
+ netconfig, NULL));
+ l_rtnl_address_free(netconfig->v4_address);
+ netconfig->v4_address = NULL;
+ }
+
+ l_strfreev(netconfig->dns4_overrides);
+ netconfig->dns4_overrides = NULL;
+
+ l_dhcp_client_stop(netconfig->dhcp_client);
+ netconfig->rtm_protocol = 0;
+ }
+}
+
+static void netconfig_ipv4_acd_event(enum l_acd_event event, void *user_data)
+{
+ struct netconfig *netconfig = user_data;
+
+ switch (event) {
+ case L_ACD_EVENT_AVAILABLE:
+ L_WARN_ON(!l_rtnl_ifaddr_add(rtnl, netconfig->ifindex,
+ netconfig->v4_address,
+ netconfig_ipv4_ifaddr_add_cmd_cb,
+ netconfig, NULL));
+ return;
+ case L_ACD_EVENT_CONFLICT:
+ /*
+ * Conflict found, no IP was actually set so just free/unset
+ * anything we set prior to starting ACD.
+ */
+ l_error("netconfig: statically configured address conflict!");
+ l_rtnl_address_free(netconfig->v4_address);
+ netconfig->v4_address = NULL;
+ netconfig->rtm_protocol = 0;
+ break;
+ case L_ACD_EVENT_LOST:
+ /*
+ * Set IP but lost it some time after. Full (IPv4) reset in this
+ * case.
+ */
+ l_error("netconfig: statically configured address was lost");
+ netconfig_reset_v4(netconfig);
+ break;
+ }
+}
+
static void netconfig_ipv4_select_and_install(struct netconfig *netconfig)
{
netconfig->v4_address = netconfig_get_static4_address(netconfig);
if (netconfig->v4_address) {
+ char ip[INET6_ADDRSTRLEN];
+
netconfig->rtm_protocol = RTPROT_STATIC;
- L_WARN_ON(!l_rtnl_ifaddr_add(rtnl, netconfig->ifindex,
+ netconfig->acd = l_acd_new(netconfig->ifindex);
+ l_acd_set_event_handler(netconfig->acd,
+ netconfig_ipv4_acd_event, netconfig,
+ NULL);
+ if (getenv("IWD_ACD_DEBUG"))
+ l_acd_set_debug(netconfig->acd, do_debug,
+ "[ACD] ", NULL);
+
+ l_rtnl_address_get_address(netconfig->v4_address, ip);
+
+ if (!l_acd_start(netconfig->acd, ip)) {
+ l_error("failed to start ACD, continuing anyways");
+ l_acd_destroy(netconfig->acd);
+ netconfig->acd = NULL;
+
+ L_WARN_ON(!l_rtnl_ifaddr_add(rtnl, netconfig->ifindex,
netconfig->v4_address,
netconfig_ipv4_ifaddr_add_cmd_cb,
netconfig, NULL));
+ }
+
return;
}
@@ -955,23 +1029,7 @@ bool netconfig_reset(struct netconfig *netconfig)
if (netconfig->rtm_protocol || netconfig->rtm_v6_protocol)
resolve_revert(netconfig->resolve);
- if (netconfig->rtm_protocol) {
- if (netconfig->v4_address) {
- L_WARN_ON(!l_rtnl_ifaddr_delete(rtnl,
- netconfig->ifindex,
- netconfig->v4_address,
- netconfig_ifaddr_del_cmd_cb,
- netconfig, NULL));
- l_rtnl_address_free(netconfig->v4_address);
- netconfig->v4_address = NULL;
- }
-
- l_strfreev(netconfig->dns4_overrides);
- netconfig->dns4_overrides = NULL;
-
- l_dhcp_client_stop(netconfig->dhcp_client);
- netconfig->rtm_protocol = 0;
- }
+ netconfig_reset_v4(netconfig);
if (netconfig->rtm_v6_protocol) {
l_strfreev(netconfig->dns6_overrides);
--
2.26.2
next reply other threads:[~2020-12-10 21:22 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-10 21:22 James Prestwood [this message]
2020-12-10 21:22 ` [PATCH v2 2/2] auto-t: add static netconfig test James Prestwood
2020-12-10 22:20 ` [PATCH v2 1/2] netconfig: add ACD client for static configuration Denis Kenzior
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201210212210.880245-1-prestwoj@gmail.com \
--to=prestwoj@gmail.com \
--cc=iwd@lists.01.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox