From d3e4930177548162b122b6dddfd0935a1cbc75fc Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 20 Nov 2012 17:54:04 -0600 Subject: [PATCH] mobile: assume IFF_NOARP when given a /32 prefix Trying to ARP with no other machines in the broadcast domain is pretty pointless, and in many cases doesn't work (ZTE MF691 /T-Mobile Rocket 2), so turn it off. --- src/modem-manager/nm-modem.c | 21 +++++++++++++++++ src/modem-manager/nm-modem.h | 2 ++ src/nm-device-modem.c | 7 ++++++ src/nm-system.c | 44 ++++++++++++++++++++++++++++++++++++ src/nm-system.h | 2 ++ 5 files changed, 76 insertions(+) diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index 45d1bdf71d..2d24a3ea78 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -311,6 +311,27 @@ nm_modem_stage3_ip4_config_start (NMModem *self, return ret; } +void +nm_modem_ip4_pre_commit (NMModem *modem, + NMDevice *device, + NMIP4Config *config) +{ + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (modem); + + /* If the modem has an ethernet-type data interface (ie, not PPP and thus + * not point-to-point) and IP config has a /32 prefix, then we assume that + * ARP will be pointless and we turn it off. + */ + if ( priv->ip_method == MM_MODEM_IP_METHOD_STATIC + || priv->ip_method == MM_MODEM_IP_METHOD_DHCP) { + NMIP4Address *addr = nm_ip4_config_get_address (config, 0); + + g_assert (addr); + if (nm_ip4_address_get_prefix (addr) == 32) + nm_system_iface_set_arp (nm_device_get_ip_ifindex (device), FALSE); + } +} + /*****************************************************************************/ NMActStageReturn diff --git a/src/modem-manager/nm-modem.h b/src/modem-manager/nm-modem.h index 31e73c39db..d01aaf2cbe 100644 --- a/src/modem-manager/nm-modem.h +++ b/src/modem-manager/nm-modem.h @@ -148,6 +148,8 @@ NMActStageReturn nm_modem_stage3_ip6_config_start (NMModem *modem, NMDeviceClass *device_class, NMDeviceStateReason *reason); +void nm_modem_ip4_pre_commit (NMModem *modem, NMDevice *device, NMIP4Config *config); + gboolean nm_modem_get_secrets (NMModem *modem, const char *setting_name, gboolean request_new, diff --git a/src/nm-device-modem.c b/src/nm-device-modem.c index 3573cf8288..57f0bf8ef3 100644 --- a/src/nm-device-modem.c +++ b/src/nm-device-modem.c @@ -309,6 +309,12 @@ act_stage3_ip4_config_start (NMDevice *device, reason); } +static void +ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) +{ + nm_modem_ip4_pre_commit (NM_DEVICE_MODEM_GET_PRIVATE (device)->modem, device, config); +} + static NMActStageReturn act_stage3_ip6_config_start (NMDevice *device, NMIP6Config **out_config, @@ -509,6 +515,7 @@ nm_device_modem_class_init (NMDeviceModemClass *mclass) device_class->act_stage2_config = act_stage2_config; device_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start; device_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start; + device_class->ip4_config_pre_commit = ip4_config_pre_commit; device_class->get_enabled = get_enabled; device_class->set_enabled = set_enabled; diff --git a/src/nm-system.c b/src/nm-system.c index 4f422bf1aa..891907eabb 100644 --- a/src/nm-system.c +++ b/src/nm-system.c @@ -896,6 +896,50 @@ out: return success; } +/** + * nm_system_iface_set_arp: + * @ifindex: interface index + * @enable: %TRUE to enable ARP, or %FALSE to disable + * + * Sets a flag to indicate that ARP should or should not be used on the + * interface. Point-to-point or IPv4 /32 interfaces often require that ARP + * be disabled. + * + * Returns: %TRUE on success, %FALSE on failure + **/ +gboolean +nm_system_iface_set_arp (int ifindex, gboolean enable) +{ + struct rtnl_link *request = NULL, *old = NULL; + struct nl_sock *nlh; + gboolean success = FALSE; + int err; + + g_return_val_if_fail (ifindex > 0, FALSE); + + if (!(request = rtnl_link_alloc ())) + return FALSE; + + if (enable) + rtnl_link_unset_flags (request, IFF_NOARP); + else + rtnl_link_set_flags (request, IFF_NOARP); + + old = nm_netlink_index_to_rtnl_link (ifindex); + if (old) { + nlh = nm_netlink_get_default_handle (); + if (nlh) { + err = rtnl_link_change (nlh, old, request, 0); + if (err == 0) + success = TRUE; + } + } + + rtnl_link_put (old); + rtnl_link_put (request); + return success; +} + static struct rtnl_route * add_ip4_route_to_gateway (int ifindex, guint32 gw, guint32 mss) { diff --git a/src/nm-system.h b/src/nm-system.h index 102d116b78..9b7c8caada 100644 --- a/src/nm-system.h +++ b/src/nm-system.h @@ -94,6 +94,8 @@ gboolean nm_system_iface_set_mtu (int ifindex, guint32 mtu); gboolean nm_system_iface_set_mac (int ifindex, const struct ether_addr *mac); +gboolean nm_system_iface_set_arp (int ifindex, gboolean arp); + gboolean nm_system_apply_bonding_config (const char *iface, NMSettingBond *s_bond); gboolean nm_system_add_bonding_master (const char *iface);