mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-12-22 21:22:37 +01:00
netconfig: add ACD client for static configuration
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.
This commit is contained in:
parent
4e4ba6769d
commit
f39d1b4ac2
100
src/netconfig.c
100
src/netconfig.c
@ -64,6 +64,8 @@ struct netconfig {
|
|||||||
void *user_data;
|
void *user_data;
|
||||||
|
|
||||||
struct resolve *resolve;
|
struct resolve *resolve;
|
||||||
|
|
||||||
|
struct l_acd *acd;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct l_netlink *rtnl;
|
static struct l_netlink *rtnl;
|
||||||
@ -804,16 +806,88 @@ static void netconfig_dhcp6_event_handler(struct l_dhcp6_client *client,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void netconfig_ipv4_select_and_install(struct netconfig *netconfig)
|
static void netconfig_reset_v4(struct netconfig *netconfig)
|
||||||
{
|
{
|
||||||
netconfig->v4_address = netconfig_get_static4_address(netconfig);
|
if (netconfig->rtm_protocol) {
|
||||||
if (netconfig->v4_address) {
|
if (netconfig->v4_address) {
|
||||||
netconfig->rtm_protocol = RTPROT_STATIC;
|
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,
|
L_WARN_ON(!l_rtnl_ifaddr_add(rtnl, netconfig->ifindex,
|
||||||
netconfig->v4_address,
|
netconfig->v4_address,
|
||||||
netconfig_ipv4_ifaddr_add_cmd_cb,
|
netconfig_ipv4_ifaddr_add_cmd_cb,
|
||||||
netconfig, NULL));
|
netconfig, NULL));
|
||||||
return;
|
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;
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
netconfig->rtm_protocol = RTPROT_DHCP;
|
netconfig->rtm_protocol = RTPROT_DHCP;
|
||||||
@ -955,23 +1029,7 @@ bool netconfig_reset(struct netconfig *netconfig)
|
|||||||
if (netconfig->rtm_protocol || netconfig->rtm_v6_protocol)
|
if (netconfig->rtm_protocol || netconfig->rtm_v6_protocol)
|
||||||
resolve_revert(netconfig->resolve);
|
resolve_revert(netconfig->resolve);
|
||||||
|
|
||||||
if (netconfig->rtm_protocol) {
|
netconfig_reset_v4(netconfig);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (netconfig->rtm_v6_protocol) {
|
if (netconfig->rtm_v6_protocol) {
|
||||||
l_strfreev(netconfig->dns6_overrides);
|
l_strfreev(netconfig->dns6_overrides);
|
||||||
|
Loading…
Reference in New Issue
Block a user