mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-28 08:40:09 +01:00
devices: send ARPs when configuring static IPv4 addresses (rh #1073447)
After applying a configuration with static IPv4 addresses, call /sbin/arping to announce the new addresses to the host's neighbors. (Basic idea copied from Fedora ifup-eth.)
This commit is contained in:
parent
7ff7df7640
commit
01f41506fb
1 changed files with 99 additions and 1 deletions
|
|
@ -262,6 +262,7 @@ typedef struct {
|
|||
NMDHCP4Config * dhcp4_config;
|
||||
NMIP4Config * vpn4_config; /* routes added by a VPN which uses this device */
|
||||
|
||||
guint arp_round2_id;
|
||||
PingInfo gw_ping;
|
||||
|
||||
/* dnsmasq stuff for shared connections */
|
||||
|
|
@ -4344,6 +4345,99 @@ start_sharing (NMDevice *self, NMIP4Config *config)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
send_arps (NMDevice *self, const char *mode_arg)
|
||||
{
|
||||
const char *argv[] = { "/sbin/arping", mode_arg, "-q", "-I", nm_device_get_ip_iface (self), "-c", "1", NULL, NULL };
|
||||
int ip_arg = G_N_ELEMENTS (argv) - 2;
|
||||
NMConnection *connection;
|
||||
NMSettingIP4Config *s_ip4;
|
||||
int i, num;
|
||||
NMIP4Address *addr;
|
||||
guint32 ipaddr;
|
||||
GError *error = NULL;
|
||||
|
||||
connection = nm_device_get_connection (self);
|
||||
if (!connection)
|
||||
return;
|
||||
s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
||||
if (!s_ip4)
|
||||
return;
|
||||
num = nm_setting_ip4_config_get_num_addresses (s_ip4);
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
addr = nm_setting_ip4_config_get_address (s_ip4, i);
|
||||
ipaddr = nm_ip4_address_get_address (addr);
|
||||
argv[ip_arg] = (char *) nm_utils_inet4_ntop (ipaddr, NULL);
|
||||
|
||||
nm_log_dbg (LOGD_DEVICE | LOGD_IP4,
|
||||
"Running arping %s -I %s %s",
|
||||
mode_arg, nm_device_get_iface (self), argv[ip_arg]);
|
||||
g_spawn_async (NULL, (char **) argv, NULL,
|
||||
G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
|
||||
nm_unblock_posix_signals,
|
||||
NULL, NULL, &error);
|
||||
if (error) {
|
||||
nm_log_warn (LOGD_DEVICE | LOGD_IP4,
|
||||
"Could not send ARP for local address %s: %s",
|
||||
argv[ip_arg], error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
arp_announce_round2 (gpointer self)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
priv->arp_round2_id = 0;
|
||||
|
||||
if ( priv->state >= NM_DEVICE_STATE_IP_CONFIG
|
||||
&& priv->state <= NM_DEVICE_STATE_ACTIVATED)
|
||||
send_arps (self, "-U");
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
arp_cleanup (NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if (priv->arp_round2_id) {
|
||||
g_source_remove (priv->arp_round2_id);
|
||||
priv->arp_round2_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
arp_announce (NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMConnection *connection;
|
||||
NMSettingIP4Config *s_ip4;
|
||||
int num;
|
||||
|
||||
arp_cleanup (self);
|
||||
|
||||
/* We only care about manually-configured addresses; DHCP- and autoip-configured
|
||||
* ones should already have been seen on the network at this point.
|
||||
*/
|
||||
connection = nm_device_get_connection (self);
|
||||
if (!connection)
|
||||
return;
|
||||
s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
||||
if (!s_ip4)
|
||||
return;
|
||||
num = nm_setting_ip4_config_get_num_addresses (s_ip4);
|
||||
if (num == 0)
|
||||
return;
|
||||
|
||||
send_arps (self, "-A");
|
||||
priv->arp_round2_id = g_timeout_add_seconds (2, arp_announce_round2, self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nm_device_activate_ip4_config_commit (gpointer user_data)
|
||||
{
|
||||
|
|
@ -4392,6 +4486,8 @@ nm_device_activate_ip4_config_commit (gpointer user_data)
|
|||
}
|
||||
}
|
||||
|
||||
arp_announce (self);
|
||||
|
||||
/* Enter the IP_CHECK state if this is the first method to complete */
|
||||
priv->ip4_state = IP_DONE;
|
||||
if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG)
|
||||
|
|
@ -4799,6 +4895,7 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason)
|
|||
priv->ip4_state = priv->ip6_state = IP_NONE;
|
||||
|
||||
dhcp4_cleanup (self, TRUE, FALSE);
|
||||
arp_cleanup (self);
|
||||
dhcp6_cleanup (self, TRUE, FALSE);
|
||||
linklocal6_cleanup (self);
|
||||
addrconf6_cleanup (self);
|
||||
|
|
@ -5581,8 +5678,9 @@ dispose (GObject *object)
|
|||
nm_device_queued_state_clear (self);
|
||||
nm_device_queued_ip_config_change_clear (self);
|
||||
|
||||
/* Clean up and stop DHCP */
|
||||
/* Clean up and stop address configuration */
|
||||
dhcp4_cleanup (self, deconfigure, FALSE);
|
||||
arp_cleanup (self);
|
||||
dhcp6_cleanup (self, deconfigure, FALSE);
|
||||
linklocal6_cleanup (self);
|
||||
addrconf6_cleanup (self);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue