diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2017-11-23 18:40:27 +0100 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2017-11-23 18:40:27 +0100 |
commit | f71a2bf8fe4dbbb338b3779f8193e28e8dc3df55 (patch) | |
tree | 35a8b9fc2312df479dbbd154cfc4039a95be8268 | |
parent | 2b88418efcf415d7ce13eb3b283601370e93be95 (diff) | |
download | NetworkManager-bg/ppp.tar.gz |
ppp: fix IPv6 supportbg/ppp
-rw-r--r-- | src/devices/nm-device-ppp.c | 172 |
1 files changed, 141 insertions, 31 deletions
diff --git a/src/devices/nm-device-ppp.c b/src/devices/nm-device-ppp.c index 8b3968d513..72a8cc695e 100644 --- a/src/devices/nm-device-ppp.c +++ b/src/devices/nm-device-ppp.c @@ -21,6 +21,8 @@ #include "nm-device-private.h" #include "nm-manager.h" #include "nm-setting-pppoe.h" +#include "nm-setting-ip4-config.h" +#include "nm-setting-ip6-config.h" #include "platform/nm-platform.h" #include "ppp/nm-ppp-manager.h" #include "ppp/nm-ppp-manager-call.h" @@ -35,8 +37,9 @@ _LOG_DECLARE_SELF(NMDevicePpp); typedef struct _NMDevicePppPrivate { NMPPPManager *ppp_manager; - NMIP4Config *pending_ip4_config; - char *pending_ifname; + NMIP4Config *ip4_config; + NMIP6Config *ip6_config; + char *iface; } NMDevicePppPrivate; struct _NMDevicePpp { @@ -88,9 +91,6 @@ ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_ case NM_PPP_STATUS_DEAD: nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED); break; - case NM_PPP_STATUS_RUNNING: - nm_device_activate_schedule_stage3_ip_config_start (device); - break; default: break; } @@ -111,23 +111,86 @@ ppp_ip4_config (NMPPPManager *ppp_manager, if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG) { if (nm_device_activate_ip4_state_in_conf (device)) { - if (!nm_device_take_over_link (device, iface, &renamed)) { - nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); - return; - } - if (renamed) - nm_manager_remove_device (nm_manager_get (), iface, NM_DEVICE_TYPE_PPP); - nm_device_activate_schedule_ip4_config_result (device, config); + } + return; + } + + /* We are not yet in the IP configuration stage: cache the + * configuration for later. + */ + if (priv->ip4_config) + g_object_unref (priv->ip4_config); + priv->ip4_config = g_object_ref (config); + + if (priv->iface) + g_assert_cmpstr (priv->iface, ==, iface); + else { + /* Complete device initialization when we receive the first + * IP{4,6} configuration and we know the name of the interface + * created by pppd. + */ + priv->iface = g_strdup (iface); + if (!nm_device_take_over_link (device, iface, &renamed)) { + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + return; + } + if (renamed) + nm_manager_remove_device (nm_manager_get (), iface, NM_DEVICE_TYPE_PPP); + + /* Once the device gets an ifindex, start with IP configuration */ + nm_device_activate_schedule_stage3_ip_config_start (device); + } +} + +static void +ppp_ip6_config (NMPPPManager *ppp_manager, + const char *iface, + const NMUtilsIPv6IfaceId *iid, + NMIP6Config *config, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDevicePpp *self = NM_DEVICE_PPP (device); + NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE (self); + gboolean renamed; + + _LOGT (LOGD_DEVICE | LOGD_PPP, "received IPv6 config from pppd"); + + if (nm_device_get_state (device) == NM_DEVICE_STATE_IP_CONFIG) { + if (nm_device_activate_ip6_state_in_conf (device)) { + nm_device_set_ac_ip6_config (device, config); + nm_device_activate_schedule_ip6_config_result (device); + } + return; + } + + /* We are not yet in the IP configuration stage: cache the + * configuration for later. + */ + if (priv->ip6_config) + g_object_unref (priv->ip6_config); + priv->ip6_config = g_object_ref (config); + + if (priv->iface) + g_assert_cmpstr (priv->iface, ==, iface); + else { + /* Complete device initialization when we receive the first + * IP{4,6} configuration and we know the name of the interface + * created by pppd. + */ + priv->iface = g_strdup (iface); + if (!nm_device_take_over_link (device, iface, &renamed)) { + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); return; } - } else { - if (priv->pending_ip4_config) - g_object_unref (priv->pending_ip4_config); - priv->pending_ip4_config = g_object_ref (config); - g_free (priv->pending_ifname); - priv->pending_ifname = g_strdup (iface); + if (renamed) + nm_manager_remove_device (nm_manager_get (), iface, NM_DEVICE_TYPE_PPP); + + /* Once the device gets an ifindex, start with IP configuration */ + nm_device_activate_schedule_stage3_ip_config_start (device); } } @@ -146,8 +209,9 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) s_pppoe = (NMSettingPppoe *) nm_device_get_applied_setting ((NMDevice *) self, NM_TYPE_SETTING_PPPOE); g_return_val_if_fail (s_pppoe, NM_ACT_STAGE_RETURN_FAILURE); - g_clear_object (&priv->pending_ip4_config); - nm_clear_g_free (&priv->pending_ifname); + g_clear_object (&priv->ip4_config); + g_clear_object (&priv->ip6_config); + nm_clear_g_free (&priv->iface); priv->ppp_manager = nm_ppp_manager_create (nm_setting_pppoe_get_parent (s_pppoe), &error); @@ -178,6 +242,9 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, G_CALLBACK (ppp_ip4_config), self); + g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_IP6_CONFIG, + G_CALLBACK (ppp_ip6_config), + self); return NM_ACT_STAGE_RETURN_POSTPONE; } @@ -189,17 +256,25 @@ act_stage3_ip4_config_start (NMDevice *device, { NMDevicePpp *self = NM_DEVICE_PPP (device); NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE (self); - gboolean renamed; + NMSettingIPConfig *s_ip4; + NMDeviceClass *dev_class; + + _LOGT (LOGD_DEVICE | LOGD_PPP, "ip4 config start"); + + s_ip4 = (NMSettingIPConfig *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_IP4_CONFIG); + if (!nm_streq0 (nm_setting_ip_config_get_method (s_ip4), + NM_SETTING_IP4_CONFIG_METHOD_AUTO)) { + dev_class = NM_DEVICE_CLASS (nm_device_ppp_parent_class); + return dev_class->act_stage3_ip4_config_start (device, + out_config, + out_failure_reason); + } - if (priv->pending_ip4_config) { - if (!nm_device_take_over_link (device, priv->pending_ifname, &renamed)) - return NM_ACT_STAGE_RETURN_FAILURE; - if (renamed) - nm_manager_remove_device (nm_manager_get (), priv->pending_ifname, NM_DEVICE_TYPE_PPP); + if (priv->ip4_config) { if (out_config) - *out_config = g_steal_pointer (&priv->pending_ip4_config); + *out_config = g_steal_pointer (&priv->ip4_config); else - g_clear_object (&priv->pending_ip4_config); + g_clear_object (&priv->ip4_config); return NM_ACT_STAGE_RETURN_SUCCESS; } @@ -207,6 +282,39 @@ act_stage3_ip4_config_start (NMDevice *device, return NM_ACT_STAGE_RETURN_POSTPONE; } +static NMActStageReturn +act_stage3_ip6_config_start (NMDevice *device, + NMIP6Config **out_config, + NMDeviceStateReason *out_failure_reason) +{ + NMDevicePpp *self = NM_DEVICE_PPP (device); + NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE (self); + NMSettingIPConfig *s_ip6; + NMDeviceClass *dev_class; + + _LOGT (LOGD_DEVICE | LOGD_PPP, "ip6 config start"); + + s_ip6 = (NMSettingIPConfig *) nm_device_get_applied_setting (device, NM_TYPE_SETTING_IP6_CONFIG); + if (!nm_streq0 (nm_setting_ip_config_get_method (s_ip6), + NM_SETTING_IP6_CONFIG_METHOD_AUTO)) { + dev_class = NM_DEVICE_CLASS (nm_device_ppp_parent_class); + return dev_class->act_stage3_ip6_config_start (device, + out_config, + out_failure_reason); + } + + if (priv->ip6_config) { + if (out_config) + *out_config = g_steal_pointer (&priv->ip6_config); + else + g_clear_object (&priv->ip6_config); + return NM_ACT_STAGE_RETURN_SUCCESS; + } + + /* Wait IPV6CP termination */ + return NM_ACT_STAGE_RETURN_POSTPONE; +} + static gboolean create_and_realize (NMDevice *device, NMConnection *connection, @@ -255,8 +363,9 @@ dispose (GObject *object) NMDevicePpp *self = NM_DEVICE_PPP (object); NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE (self); - g_clear_object (&priv->pending_ip4_config); - nm_clear_g_free (&priv->pending_ifname); + g_clear_object (&priv->ip4_config); + g_clear_object (&priv->ip6_config); + nm_clear_g_free (&priv->iface); G_OBJECT_CLASS (nm_device_ppp_parent_class)->dispose (object); } @@ -273,6 +382,7 @@ nm_device_ppp_class_init (NMDevicePppClass *klass) parent_class->act_stage2_config = act_stage2_config; parent_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start; + parent_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start; parent_class->check_connection_compatible = check_connection_compatible; parent_class->create_and_realize = create_and_realize; parent_class->deactivate = deactivate; |