diff options
| author | Michael Biebl <biebl@debian.org> | 2018-06-04 00:07:45 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2018-06-04 00:07:45 +0200 |
| commit | 04bc9e1cd3544445d883ad29ea108c1645c8e7b7 (patch) | |
| tree | d10c354b1b980ca8a7b9e48ec9019e8ed88bde2b /src/ppp | |
| parent | ee9c73a923909e23a649407be77e25235d769e25 (diff) | |
New upstream version 1.11.4 upstream/1.11.4
Diffstat (limited to 'src/ppp')
| -rw-r--r-- | src/ppp/meson.build | 41 | ||||
| -rw-r--r-- | src/ppp/nm-ppp-manager-call.c | 36 | ||||
| -rw-r--r-- | src/ppp/nm-ppp-manager-call.h | 14 | ||||
| -rw-r--r-- | src/ppp/nm-ppp-manager.c | 564 | ||||
| -rw-r--r-- | src/ppp/nm-ppp-manager.h | 8 | ||||
| -rw-r--r-- | src/ppp/nm-ppp-plugin-api.h | 14 | ||||
| -rw-r--r-- | src/ppp/nm-pppd-plugin.c | 32 |
7 files changed, 450 insertions, 259 deletions
diff --git a/src/ppp/meson.build b/src/ppp/meson.build new file mode 100644 index 00000000..38f9a0f1 --- /dev/null +++ b/src/ppp/meson.build @@ -0,0 +1,41 @@ +name = 'nm-pppd-plugin' + +deps = [ + dl_dep, + nm_core_dep +] + +nm_pppd_plugin = shared_module( + name, + name_prefix: '', + sources: name + '.c', + include_directories: src_inc, + dependencies: deps, + c_args: [ + '-DG_LOG_DOMAIN="@0@"'.format(name), + '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_GLIB', + ], + install: true, + install_dir: pppd_plugin_dir +) + +name = 'nm-ppp-plugin' + +deps = [ + nm_dep +] + +linker_script = join_paths(meson.current_source_dir(), 'nm-ppp-plugin.ver') + +core_plugins += shared_module( + name, + sources: 'nm-ppp-manager.c', + dependencies: deps, + c_args: '-DPPPD_PLUGIN_DIR="@0@"'.format(pppd_plugin_dir), + link_args: [ + '-Wl,--version-script,@0@'.format(linker_script), + ], + link_depends: linker_script, + install: true, + install_dir: nm_plugindir +) diff --git a/src/ppp/nm-ppp-manager-call.c b/src/ppp/nm-ppp-manager-call.c index ad3307a9..3d6fee49 100644 --- a/src/ppp/nm-ppp-manager-call.c +++ b/src/ppp/nm-ppp-manager-call.c @@ -44,11 +44,9 @@ nm_ppp_manager_create (const char *iface, GError **error) GError *error_local = NULL; NMPPPOps *ops; struct stat st; - int errsv; if (G_UNLIKELY (!ppp_ops)) { if (stat (PPP_PLUGIN_PATH, &st) != 0) { - errsv = errno; g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_MISSING_PLUGIN, "the PPP plugin " PPP_PLUGIN_PATH " is not installed"); @@ -84,9 +82,8 @@ nm_ppp_manager_create (const char *iface, GError **error) nm_assert (ops); nm_assert (ops->create); nm_assert (ops->start); - nm_assert (ops->stop_async); - nm_assert (ops->stop_finish); - nm_assert (ops->stop_sync); + nm_assert (ops->stop); + nm_assert (ops->stop_cancel); ppp_ops = ops; @@ -127,32 +124,21 @@ nm_ppp_manager_start (NMPPPManager *self, return ppp_ops->start (self, req, ppp_name, timeout_secs, baud_override, err); } -void -nm_ppp_manager_stop_async (NMPPPManager *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +NMPPPManagerStopHandle * +nm_ppp_manager_stop (NMPPPManager *self, + NMPPPManagerStopCallback callback, + gpointer user_data) { - g_return_if_fail (ppp_ops); + g_return_val_if_fail (ppp_ops, NULL); - ppp_ops->stop_async (self, cancellable, callback, user_data); -} - -gboolean -nm_ppp_manager_stop_finish (NMPPPManager *self, - GAsyncResult *res, - GError **error) -{ - g_return_val_if_fail (ppp_ops, FALSE); - - return ppp_ops->stop_finish (self, res, error); + return ppp_ops->stop (self, callback, user_data); } void -nm_ppp_manager_stop_sync (NMPPPManager *self) +nm_ppp_manager_stop_cancel (NMPPPManagerStopHandle *handle) { g_return_if_fail (ppp_ops); + g_return_if_fail (handle); - ppp_ops->stop_sync (self); + ppp_ops->stop_cancel (handle); } - diff --git a/src/ppp/nm-ppp-manager-call.h b/src/ppp/nm-ppp-manager-call.h index 2258ae08..daf8a82e 100644 --- a/src/ppp/nm-ppp-manager-call.h +++ b/src/ppp/nm-ppp-manager-call.h @@ -38,13 +38,11 @@ gboolean nm_ppp_manager_start (NMPPPManager *self, guint32 timeout_secs, guint baud_override, GError **error); -void nm_ppp_manager_stop_async (NMPPPManager *self, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -gboolean nm_ppp_manager_stop_finish (NMPPPManager *self, - GAsyncResult *res, - GError **error); -void nm_ppp_manager_stop_sync (NMPPPManager *self); + +NMPPPManagerStopHandle *nm_ppp_manager_stop (NMPPPManager *self, + NMPPPManagerStopCallback callback, + gpointer user_data); + +void nm_ppp_manager_stop_cancel (NMPPPManagerStopHandle *handle); #endif /* __NM_PPP_MANAGER_CALL_H__ */ diff --git a/src/ppp/nm-ppp-manager.c b/src/ppp/nm-ppp-manager.c index 743f80a2..fc658bec 100644 --- a/src/ppp/nm-ppp-manager.c +++ b/src/ppp/nm-ppp-manager.c @@ -50,13 +50,12 @@ #include "nm-act-request.h" #include "nm-ip4-config.h" #include "nm-ip6-config.h" +#include "nm-dbus-object.h" #include "nm-pppd-plugin.h" #include "nm-ppp-plugin-api.h" #include "nm-ppp-status.h" -#include "introspection/org.freedesktop.NetworkManager.PPP.h" - #define NM_PPPD_PLUGIN PPPD_PLUGIN_DIR "/nm-pppd-plugin.so" static NM_CACHED_QUARK_FCN ("ppp-manager-secret-tries", ppp_manager_secret_tries_quark) @@ -76,6 +75,7 @@ GType nm_ppp_manager_get_type (void); enum { STATE_CHANGED, + IFINDEX_SET, IP4_CONFIG, IP6_CONFIG, STATS, @@ -93,6 +93,8 @@ typedef struct { GPid pid; char *parent_iface; + char *ip_iface; + int ifindex; NMActRequest *act_req; GDBusMethodInvocation *pending_secrets_context; @@ -103,7 +105,6 @@ typedef struct { guint ppp_timeout_handler; /* Monitoring */ - char *ip_iface; int monitor_fd; guint monitor_id; @@ -114,17 +115,17 @@ typedef struct { } NMPPPManagerPrivate; struct _NMPPPManager { - NMExportedObject parent; + NMDBusObject parent; NMPPPManagerPrivate _priv; }; typedef struct { - NMExportedObjectClass parent; + NMDBusObjectClass parent; } NMPPPManagerClass; -G_DEFINE_TYPE (NMPPPManager, nm_ppp_manager, NM_TYPE_EXPORTED_OBJECT) +G_DEFINE_TYPE (NMPPPManager, nm_ppp_manager, NM_TYPE_DBUS_OBJECT) -#define NM_PPP_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMPPPManager, NM_IS_PPP_MANAGER) +#define NM_PPP_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMPPPManager, NM_IS_PPP_MANAGER, NMDBusObject) /*****************************************************************************/ @@ -133,8 +134,11 @@ G_DEFINE_TYPE (NMPPPManager, nm_ppp_manager, NM_TYPE_EXPORTED_OBJECT) /*****************************************************************************/ -static void _ppp_cleanup (NMPPPManager *manager); -static void _ppp_kill (NMPPPManager *manager); +static void _ppp_cleanup (NMPPPManager *self); + +static NMPPPManagerStopHandle *_ppp_manager_stop (NMPPPManager *self, + NMPPPManagerStopCallback callback, + gpointer user_data); /*****************************************************************************/ @@ -172,32 +176,36 @@ _ppp_manager_set_route_parameters (NMPPPManager *self, static gboolean monitor_cb (gpointer user_data) { - NMPPPManager *manager = NM_PPP_MANAGER (user_data); - NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager); - struct ifreq req; - struct ppp_stats stats; - - memset (&req, 0, sizeof (req)); - memset (&stats, 0, sizeof (stats)); - req.ifr_data = (caddr_t) &stats; - - strncpy (req.ifr_name, priv->ip_iface, sizeof (req.ifr_name)); - if (ioctl (priv->monitor_fd, SIOCGPPPSTATS, &req) < 0) { - if (errno != ENODEV) - _LOGW ("could not read ppp stats: %s", strerror (errno)); - } else { - g_signal_emit (manager, signals[STATS], 0, - (guint) stats.p.ppp_ibytes, - (guint) stats.p.ppp_obytes); + NMPPPManager *self = NM_PPP_MANAGER (user_data); + NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self); + const char *ifname; + + ifname = nm_platform_link_get_name (NM_PLATFORM_GET, priv->ifindex); + + if (ifname) { + struct ppp_stats stats = { }; + struct ifreq req = { + .ifr_data = (caddr_t) &stats, + }; + + nm_utils_ifname_cpy (req.ifr_name, ifname); + if (ioctl (priv->monitor_fd, SIOCGPPPSTATS, &req) < 0) { + if (errno != ENODEV) + _LOGW ("could not read ppp stats: %s", strerror (errno)); + } else { + g_signal_emit (self, signals[STATS], 0, + (guint) stats.p.ppp_ibytes, + (guint) stats.p.ppp_obytes); + } } - return TRUE; + return G_SOURCE_CONTINUE; } static void -monitor_stats (NMPPPManager *manager) +monitor_stats (NMPPPManager *self) { - NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager); + NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self); /* already monitoring */ if (priv->monitor_fd >= 0) @@ -208,7 +216,7 @@ monitor_stats (NMPPPManager *manager) g_warn_if_fail (priv->monitor_id == 0); if (priv->monitor_id) g_source_remove (priv->monitor_id); - priv->monitor_id = g_timeout_add_seconds (5, monitor_cb, manager); + priv->monitor_id = g_timeout_add_seconds (5, monitor_cb, self); } else _LOGW ("could not monitor PPP stats: %s", strerror (errno)); } @@ -326,21 +334,28 @@ ppp_secrets_cb (NMActRequest *req, * against libnm just to parse this. So instead, let's just send what * it needs. */ - g_dbus_method_invocation_return_value ( - priv->pending_secrets_context, - g_variant_new ("(ss)", username ? username : "", password ? password : "")); + g_dbus_method_invocation_return_value (priv->pending_secrets_context, + g_variant_new ("(ss)", + username ?: "", + password ?: "")); - out: +out: priv->pending_secrets_context = NULL; priv->secrets_id = NULL; priv->secrets_setting_name = NULL; } static void -impl_ppp_manager_need_secrets (NMPPPManager *manager, - GDBusMethodInvocation *context) +impl_ppp_manager_need_secrets (NMDBusObject *obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) { - NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager); + NMPPPManager *self = NM_PPP_MANAGER (obj); + NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self); NMConnection *applied_connection; const char *username = NULL; const char *password = NULL; @@ -358,8 +373,8 @@ impl_ppp_manager_need_secrets (NMPPPManager *manager, /* Use existing secrets from the connection */ if (extract_details_from_connection (applied_connection, NULL, &username, &password, &error)) { /* Send existing secrets to the PPP plugin */ - priv->pending_secrets_context = context; - ppp_secrets_cb (priv->act_req, priv->secrets_id, NULL, NULL, manager); + priv->pending_secrets_context = invocation; + ppp_secrets_cb (priv->act_req, priv->secrets_id, NULL, NULL, self); } else { _LOGW ("%s", error->message); g_dbus_method_invocation_take_error (priv->pending_secrets_context, error); @@ -381,41 +396,87 @@ impl_ppp_manager_need_secrets (NMPPPManager *manager, flags, hints ? g_ptr_array_index (hints, 0) : NULL, ppp_secrets_cb, - manager); + self); g_object_set_qdata (G_OBJECT (applied_connection), ppp_manager_secret_tries_quark (), GUINT_TO_POINTER (++tries)); - priv->pending_secrets_context = context; + priv->pending_secrets_context = invocation; if (hints) g_ptr_array_free (hints, TRUE); } static void -impl_ppp_manager_set_state (NMPPPManager *manager, - GDBusMethodInvocation *context, - guint32 state) +impl_ppp_manager_set_state (NMDBusObject *obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) { - g_signal_emit (manager, signals[STATE_CHANGED], 0, (guint) state); + NMPPPManager *self = NM_PPP_MANAGER (obj); + guint32 state; - g_dbus_method_invocation_return_value (context, NULL); + g_variant_get (parameters, "(u)", &state); + g_signal_emit (self, signals[STATE_CHANGED], 0, (guint) state); + g_dbus_method_invocation_return_value (invocation, NULL); +} + +static void +impl_ppp_manager_set_ifindex (NMDBusObject *obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) +{ + NMPPPManager *self = NM_PPP_MANAGER (obj); + NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self); + const NMPlatformLink *plink = NULL; + nm_auto_nmpobj const NMPObject *obj_keep_alive = NULL; + gint32 ifindex; + + g_variant_get (parameters, "(i)", &ifindex); + + _LOGD ("set-ifindex %d", (int) ifindex); + + if (priv->ifindex >= 0) { + _LOGW ("can't change the ifindex from %d to %d", priv->ifindex, (int) ifindex); + return; + } + + if (ifindex > 0) { + plink = nm_platform_link_get (NM_PLATFORM_GET, ifindex); + if (!plink) { + nm_platform_process_events (NM_PLATFORM_GET); + plink = nm_platform_link_get (NM_PLATFORM_GET, ifindex); + } + } + + if (!plink) { + _LOGW ("unknown interface with ifindex %d", ifindex); + ifindex = 0; + } + + priv->ifindex = ifindex; + + obj_keep_alive = nmp_object_ref (NMP_OBJECT_UP_CAST (plink)); + + g_signal_emit (self, signals[IFINDEX_SET], 0, ifindex, plink->name); + g_dbus_method_invocation_return_value (invocation, NULL); } static gboolean set_ip_config_common (NMPPPManager *self, GVariant *config_dict, - const char *iface_prop, guint32 *out_mtu) { NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self); NMConnection *applied_connection; NMSettingPpp *s_ppp; - const char *iface; - if (!g_variant_lookup (config_dict, iface_prop, "&s", &iface)) { - _LOGE ("no interface received!"); + if (priv->ifindex <= 0) return FALSE; - } - if (priv->ip_iface == NULL) - priv->ip_iface = g_strdup (iface); /* Got successful IP config; obviously the secrets worked */ applied_connection = nm_act_request_get_applied_connection (priv->act_req); @@ -432,29 +493,32 @@ set_ip_config_common (NMPPPManager *self, } static void -impl_ppp_manager_set_ip4_config (NMPPPManager *manager, - GDBusMethodInvocation *context, - GVariant *config_dict) +impl_ppp_manager_set_ip4_config (NMDBusObject *obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) { - NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager); + NMPPPManager *self = NM_PPP_MANAGER (obj); + NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self); gs_unref_object NMIP4Config *config = NULL; NMPlatformIP4Address address; guint32 u32, mtu; GVariantIter *iter; - int ifindex; + gs_unref_variant GVariant *config_dict = NULL; _LOGI ("(IPv4 Config Get) reply received."); - nm_clear_g_source (&priv->ppp_timeout_handler); + g_variant_get (parameters, "(@a{sv})", &config_dict); - if (!set_ip_config_common (manager, config_dict, NM_PPP_IP4_CONFIG_INTERFACE, &mtu)) - goto out; + nm_clear_g_source (&priv->ppp_timeout_handler); - ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->ip_iface); - if (ifindex <= 0) + if (!set_ip_config_common (self, config_dict, &mtu)) goto out; - config = nm_ip4_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET), ifindex); + config = nm_ip4_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET), priv->ifindex); if (mtu) nm_ip4_config_set_mtu (config, mtu, NM_IP_CONFIG_SOURCE_PPP); @@ -467,7 +531,7 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager, if (g_variant_lookup (config_dict, NM_PPP_IP4_CONFIG_GATEWAY, "u", &u32)) { const NMPlatformIP4Route r = { - .ifindex = ifindex, + .ifindex = priv->ifindex, .rt_source = NM_IP_CONFIG_SOURCE_PPP, .gateway = u32, .table_coerced = nm_platform_route_table_coerce (priv->ip4_route_table), @@ -503,10 +567,10 @@ impl_ppp_manager_set_ip4_config (NMPPPManager *manager, } /* Push the IP4 config up to the device */ - g_signal_emit (manager, signals[IP4_CONFIG], 0, priv->ip_iface, config); + g_signal_emit (self, signals[IP4_CONFIG], 0, config); out: - g_dbus_method_invocation_return_value (context, NULL); + g_dbus_method_invocation_return_value (invocation, NULL); } /* Converts the named Interface Identifier item to an IPv6 LL address and @@ -539,37 +603,40 @@ iid_value_to_ll6_addr (GVariant *dict, } static void -impl_ppp_manager_set_ip6_config (NMPPPManager *manager, - GDBusMethodInvocation *context, - GVariant *config_dict) +impl_ppp_manager_set_ip6_config (NMDBusObject *obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) { - NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager); + NMPPPManager *self = NM_PPP_MANAGER (obj); + NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self); gs_unref_object NMIP6Config *config = NULL; NMPlatformIP6Address addr; struct in6_addr a; NMUtilsIPv6IfaceId iid = NM_UTILS_IPV6_IFACE_ID_INIT; gboolean has_peer = FALSE; - int ifindex; + gs_unref_variant GVariant *config_dict = NULL; _LOGI ("(IPv6 Config Get) reply received."); - nm_clear_g_source (&priv->ppp_timeout_handler); + g_variant_get (parameters, "(@a{sv})", &config_dict); - if (!set_ip_config_common (manager, config_dict, NM_PPP_IP6_CONFIG_INTERFACE, NULL)) - goto out; + nm_clear_g_source (&priv->ppp_timeout_handler); - ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->ip_iface); - if (ifindex <= 0) + if (!set_ip_config_common (self, config_dict, NULL)) goto out; - config = nm_ip6_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET), ifindex); + config = nm_ip6_config_new (nm_platform_get_multi_idx (NM_PLATFORM_GET), priv->ifindex); memset (&addr, 0, sizeof (addr)); addr.plen = 64; if (iid_value_to_ll6_addr (config_dict, NM_PPP_IP6_CONFIG_PEER_IID, &a, NULL)) { const NMPlatformIP6Route r = { - .ifindex = ifindex, + .ifindex = priv->ifindex, .rt_source = NM_IP_CONFIG_SOURCE_PPP, .gateway = a, .table_coerced = nm_platform_route_table_coerce (priv->ip6_route_table), @@ -587,12 +654,12 @@ impl_ppp_manager_set_ip6_config (NMPPPManager *manager, nm_ip6_config_add_address (config, &addr); /* Push the IPv6 config and interface identifier up to the device */ - g_signal_emit (manager, signals[IP6_CONFIG], 0, priv->ip_iface, &iid, config); + g_signal_emit (self, signals[IP6_CONFIG], 0, &iid, config); } else _LOGE ("invalid IPv6 address received!"); out: - g_dbus_method_invocation_return_value (context, NULL); + g_dbus_method_invocation_return_value (invocation, NULL); } /*****************************************************************************/ @@ -680,8 +747,8 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (pppd_exit_code_to_str, int, static void ppp_watch_cb (GPid pid, int status, gpointer user_data) { - NMPPPManager *manager = NM_PPP_MANAGER (user_data); - NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager); + NMPPPManager *self = NM_PPP_MANAGER (user_data); + NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self); int err; const long long lpid = (long long) pid; @@ -706,20 +773,19 @@ ppp_watch_cb (GPid pid, int status, gpointer user_data) priv->pid = 0; priv->ppp_watch_id = 0; - _ppp_cleanup (manager); - g_signal_emit (manager, signals[STATE_CHANGED], 0, (guint) NM_PPP_STATUS_DEAD); + _ppp_cleanup (self); + g_signal_emit (self, signals[STATE_CHANGED], 0, (guint) NM_PPP_STATUS_DEAD); } static gboolean pppd_timed_out (gpointer data) { - NMPPPManager *manager = NM_PPP_MANAGER (data); + NMPPPManager *self = NM_PPP_MANAGER (data); _LOGW ("pppd timed out or didn't initialize our dbus module"); - _ppp_cleanup (manager); - _ppp_kill (manager); + _ppp_manager_stop (self, NULL, NULL); - g_signal_emit (manager, signals[STATE_CHANGED], 0, (guint) NM_PPP_STATUS_DEAD); + g_signal_emit (self, signals[STATE_CHANGED], 0, (guint) NM_PPP_STATUS_DEAD); return FALSE; } @@ -899,7 +965,7 @@ create_pppd_cmd_line (NMPPPManager *self, nm_cmd_line_add_int (cmd, 0); nm_cmd_line_add_string (cmd, "ipparam"); - nm_cmd_line_add_string (cmd, nm_exported_object_get_path (NM_EXPORTED_OBJECT (self))); + nm_cmd_line_add_string (cmd, nm_dbus_object_get_path (NM_DBUS_OBJECT (self))); nm_cmd_line_add_string (cmd, "plugin"); nm_cmd_line_add_string (cmd, NM_PPPD_PLUGIN); @@ -944,7 +1010,7 @@ pppoe_fill_defaults (NMSettingPpp *setting) } static gboolean -_ppp_manager_start (NMPPPManager *manager, +_ppp_manager_start (NMPPPManager *self, NMActRequest *req, const char *ppp_name, guint32 timeout_secs, @@ -964,10 +1030,10 @@ _ppp_manager_start (NMPPPManager *manager, gboolean ip6_enabled = FALSE; gboolean ip4_enabled = FALSE; - g_return_val_if_fail (NM_IS_PPP_MANAGER (manager), FALSE); + g_return_val_if_fail (NM_IS_PPP_MANAGER (self), FALSE); g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE); - priv = NM_PPP_MANAGER_GET_PRIVATE (manager); + priv = NM_PPP_MANAGER_GET_PRIVATE (self); #if !WITH_PPP /* PPP support disabled */ @@ -978,7 +1044,7 @@ _ppp_manager_start (NMPPPManager *manager, return FALSE; #endif - nm_exported_object_export (NM_EXPORTED_OBJECT (manager)); + nm_dbus_object_export (NM_DBUS_OBJECT (self)); priv->pid = 0; @@ -1013,7 +1079,7 @@ _ppp_manager_start (NMPPPManager *manager, ip6_method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); ip6_enabled = g_strcmp0 (ip6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0; - ppp_cmd = create_pppd_cmd_line (manager, + ppp_cmd = create_pppd_cmd_line (self, s_ppp, pppoe_setting, adsl_setting, @@ -1043,8 +1109,8 @@ _ppp_manager_start (NMPPPManager *manager, _LOGI ("pppd started with pid %lld", (long long) priv->pid); - priv->ppp_watch_id = g_child_watch_add (priv->pid, (GChildWatchFunc) ppp_watch_cb, manager); - priv->ppp_timeout_handler = g_timeout_add_seconds (timeout_secs, pppd_timed_out, manager); + priv->ppp_watch_id = g_child_watch_add (priv->pid, (GChildWatchFunc) ppp_watch_cb, self); + priv->ppp_timeout_handler = g_timeout_add_seconds (timeout_secs, pppd_timed_out, self); priv->act_req = g_object_ref (req); out: @@ -1052,42 +1118,27 @@ out: nm_cmd_line_destroy (ppp_cmd); if (priv->pid <= 0) - nm_exported_object_unexport (NM_EXPORTED_OBJECT (manager)); + nm_dbus_object_unexport (NM_DBUS_OBJECT (self)); return priv->pid > 0; } static void -_ppp_kill (NMPPPManager *manager) -{ - NMPPPManagerPrivate *priv; - - g_return_if_fail (NM_IS_PPP_MANAGER (manager)); - - priv = NM_PPP_MANAGER_GET_PRIVATE (manager); - - if (priv->pid) { - nm_utils_kill_child_async (priv->pid, SIGTERM, LOGD_PPP, "pppd", 2000, NULL, NULL); - priv->pid = 0; - } -} - -static void -_ppp_cleanup (NMPPPManager *manager) +_ppp_cleanup (NMPPPManager *self) { NMPPPManagerPrivate *priv; - g_return_if_fail (NM_IS_PPP_MANAGER (manager)); + g_return_if_fail (NM_IS_PPP_MANAGER (self)); - priv = NM_PPP_MANAGER_GET_PRIVATE (manager); + priv = NM_PPP_MANAGER_GET_PRIVATE (self); - cancel_get_secrets (manager); + cancel_get_secrets (self); nm_clear_g_source (&priv->monitor_id); if (priv->monitor_fd >= 0) { /* Get the stats one last time */ - monitor_cb (manager); + monitor_cb (self); nm_close (priv->monitor_fd); priv->monitor_fd = -1; } @@ -1098,108 +1149,133 @@ _ppp_cleanup (NMPPPManager *manager) /*****************************************************************************/ -typedef struct { - NMPPPManager *manager; - GSimpleAsyncResult *result; - GCancellable *cancellable; -} StopContext; +struct _NMPPPManagerStopHandle { + NMPPPManager *self; + NMPPPManagerStopCallback callback; + gpointer user_data; + + /* this object delays shutdown, because we still need to wait until + * pppd process terminated. */ + GObject *shutdown_waitobj; + + guint idle_id; +}; static void -stop_context_complete (StopContext *ctx) +_stop_handle_complete (NMPPPManagerStopHandle *handle, gboolean was_cancelled) { - if (ctx->cancellable) - g_object_unref (ctx->cancellable); - g_simple_async_result_complete_in_idle (ctx->result); - g_object_unref (ctx->result); - g_object_unref (ctx->manager); - g_slice_free (StopContext, ctx); -} + gs_unref_object NMPPPManager *self = NULL; + NMPPPManagerStopCallback callback; -static gboolean -stop_context_complete_if_cancelled (StopContext *ctx) -{ - GError *error = NULL; + self = g_steal_pointer (&handle->self); + if (!self) + return; - if (g_cancellable_set_error_if_cancelled (ctx->cancellable, &error)) { - g_simple_async_result_take_error (ctx->result, error); - stop_context_complete (ctx); - return TRUE; - } - return FALSE; + if (!handle->callback) + return; + + callback = handle->callback; + handle->callback = NULL; + callback (self, handle, was_cancelled, handle->user_data); } -static gboolean -_ppp_manager_stop_finish (NMPPPManager *manager, - GAsyncResult *res, - GError **error) +static void +_stop_handle_destroy (NMPPPManagerStopHandle *handle, gboolean was_cancelled) { - return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); + _stop_handle_complete (handle, was_cancelled); + nm_clear_g_source (&handle->idle_id); + g_clear_object (&handle->shutdown_waitobj); + g_slice_free (NMPPPManagerStopHandle, handle); } static void -kill_child_ready (pid_t pid, - gboolean success, - int child_status, - StopContext *ctx) +_stop_child_cb (pid_t pid, + gboolean success, + int child_status, + gpointer user_data) { - if (stop_context_complete_if_cancelled (ctx)) - return; - stop_context_complete (ctx); + _stop_handle_destroy (user_data, FALSE); } -static void -_ppp_manager_stop_async (NMPPPManager *manager, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +static gboolean +_stop_idle_cb (gpointer user_data) { - NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager); - StopContext *ctx; + NMPPPManagerStopHandle *handle = user_data; - nm_exported_object_unexport (NM_EXPORTED_OBJECT (manager)); + handle->idle_id = 0; + _stop_handle_destroy (handle, FALSE); + return G_SOURCE_REMOVE; +} - ctx = g_slice_new0 (StopContext); - ctx->manager = g_object_ref (manager); - ctx->result = g_simple_async_result_new (G_OBJECT (manager), - callback, - user_data, - _ppp_manager_stop_async); +static NMPPPManagerStopHandle * +_ppp_manager_stop (NMPPPManager *self, + NMPPPManagerStopCallback callback, + gpointer user_data) +{ + NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self); + NMDBusObject *dbus = NM_DBUS_OBJECT (self); + NMPPPManagerStopHandle *handle; - /* Setup cancellable */ - ctx->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - if (stop_context_complete_if_cancelled (ctx)) - return; + if (nm_dbus_object_is_exported (dbus)) + nm_dbus_object_unexport (dbus); + + _ppp_cleanup (self); + + if ( !priv->pid + && !callback) { + /* nothing to do further... + * + * In this case, we return a %NULL handle. The caller cannot cancel this + * event, but clearly he is not waiting for a callback anyway. */ + return NULL; + } - /* Cleanup internals */ - _ppp_cleanup (manager); + handle = g_slice_new0 (NMPPPManagerStopHandle); + handle->self = g_object_ref (self); + handle->callback = callback; + handle->user_data = user_data; - /* If no pppd running, we're done */ if (!priv->pid) { - stop_context_complete (ctx); - return; + /* No PID. There is nothing to kill, however, invoke the callback in + * an idle handler. + * + * Note that we don't register nm_shutdown_wait_obj_register(). + * In order for shutdown to work properly, the caller must always + * explicitly cancel the action to go down. With the idle-handler, + * cancelling the handle completes the request. */ + handle->idle_id = g_idle_add (_stop_idle_cb, handle); + return handle; } - /* No cancellable operation, so just wait until it returns always */ - nm_utils_kill_child_async (priv->pid, - SIGTERM, - LOGD_PPP, - "pppd", - 2000, - (NMUtilsKillChildAsyncCb) kill_child_ready, - ctx); - priv->pid = 0; + /* we really want to kill the process and delay shutdown of NetworkManager + * until the process terminated. We do that, by registering an object + * that delays shutdown. */ + handle->shutdown_waitobj = g_object_new (G_TYPE_OBJECT, NULL); + nm_shutdown_wait_obj_register (handle->shutdown_waitobj, "ppp-manager-wait-kill-pppd"); + nm_utils_kill_child_async (nm_steal_int (&priv->pid), + SIGTERM, LOGD_PPP, "pppd", + NM_SHUTDOWN_TIMEOUT_MS, + _stop_child_cb, handle); + + return handle; } static void -_ppp_manager_stop_sync (NMPPPManager *manager) +_ppp_manager_stop_cancel (NMPPPManagerStopHandle *handle) { - NMExportedObject *exported = NM_EXPORTED_OBJECT (manager); + g_return_if_fail (handle); + g_return_if_fail (NM_IS_PPP_MANAGER (handle->self)); - if (nm_exported_object_is_exported (exported)) - nm_exported_object_unexport (exported); + if (handle->idle_id) { + /* we can complete this fake handle right away. */ + _stop_handle_destroy (handle, TRUE); + return; + } - _ppp_cleanup (manager); - _ppp_kill (manager); + /* a real handle. Only invoke the callback (synchronously). This marks + * the handle as handled, but it keeps shutdown_waitobj around, until + * nm_utils_kill_child_async() returns. */ + _stop_handle_complete (handle, TRUE); } /*****************************************************************************/ @@ -1240,10 +1316,11 @@ set_property (GObject *object, guint prop_id, /*****************************************************************************/ static void -nm_ppp_manager_init (NMPPPManager *manager) +nm_ppp_manager_init (NMPPPManager *self) { - NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager); + NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self); + priv->ifindex = -1; priv->monitor_fd = -1; priv->ip4_route_table = RT_TABLE_MAIN; priv->ip4_route_metric = 460; @@ -1265,14 +1342,13 @@ static void dispose (GObject *object) { NMPPPManager *self = (NMPPPManager *) object; - NMExportedObject *exported = NM_EXPORTED_OBJECT (self); NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (self); - if (nm_exported_object_is_exported (exported)) - nm_exported_object_unexport (exported); - - _ppp_cleanup (self); - _ppp_kill (self); + /* we expect the user to first stop the manager. As fallback, + * still stop. */ + g_warn_if_fail (!priv->pid); + g_warn_if_fail (!nm_dbus_object_is_exported (NM_DBUS_OBJECT (self))); + _ppp_manager_stop (self, NULL, NULL); g_clear_object (&priv->act_req); @@ -1284,24 +1360,78 @@ finalize (GObject *object) { NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE ((NMPPPManager *) object); - g_free (priv->ip_iface); g_free (priv->parent_iface); G_OBJECT_CLASS (nm_ppp_manager_parent_class)->finalize (object); } +static const NMDBusInterfaceInfoExtended interface_info_ppp = { + .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( + NM_DBUS_INTERFACE_PPP, + .methods = NM_DEFINE_GDBUS_METHOD_INFOS ( + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( + NM_DEFINE_GDBUS_METHOD_INFO_INIT ( + "NeedSecrets", + .out_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("username", "s"), + NM_DEFINE_GDBUS_ARG_INFO ("password", "s"), + ), + ), + .handle = impl_ppp_manager_need_secrets, + ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( + NM_DEFINE_GDBUS_METHOD_INFO_INIT ( + "SetIp4Config", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("config", "a{sv}"), + ), + ), + .handle = impl_ppp_manager_set_ip4_config, + ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( + NM_DEFINE_GDBUS_METHOD_INFO_INIT ( + "SetIp6Config", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("config", "a{sv}"), + ), + ), + .handle = impl_ppp_manager_set_ip6_config, + ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( + NM_DEFINE_GDBUS_METHOD_INFO_INIT ( + "SetState", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("state", "u"), + ), + ), + .handle = impl_ppp_manager_set_state, + ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( + NM_DEFINE_GDBUS_METHOD_INFO_INIT ( + "SetIfindex", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("ifindex", "i"), + ), + ), + .handle = impl_ppp_manager_set_ifindex, + ), + ), + ), +}; + static void nm_ppp_manager_class_init (NMPPPManagerClass *manager_class) { GObjectClass *object_class = G_OBJECT_CLASS (manager_class); - NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (manager_class); + NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (manager_class); object_class->dispose = dispose; object_class->finalize = finalize; object_class->get_property = get_property; object_class->set_property = set_property; - exported_object_class->export_path = NM_EXPORT_PATH_NUMBERED (NM_DBUS_PATH"/PPP"); + dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED (NM_DBUS_PATH"/PPP"); + dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_ppp); obj_properties[PROP_PARENT_IFACE] = g_param_spec_string (NM_PPP_MANAGER_PARENT_IFACE, "", "", @@ -1320,14 +1450,23 @@ nm_ppp_manager_class_init (NMPPPManagerClass *manager_class) G_TYPE_NONE, 1, G_TYPE_UINT); + signals[IFINDEX_SET] = + g_signal_new (NM_PPP_MANAGER_SIGNAL_IFINDEX_SET, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 2, + G_TYPE_INT, + G_TYPE_STRING); + signals[IP4_CONFIG] = g_signal_new (NM_PPP_MANAGER_SIGNAL_IP4_CONFIG, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, - G_TYPE_NONE, 2, - G_TYPE_STRING, + G_TYPE_NONE, 1, G_TYPE_OBJECT); signals[IP6_CONFIG] = @@ -1336,7 +1475,9 @@ nm_ppp_manager_class_init (NMPPPManagerClass *manager_class) G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, - G_TYPE_NONE, 3, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_OBJECT); + G_TYPE_NONE, 2, + G_TYPE_POINTER, + G_TYPE_OBJECT); signals[STATS] = g_signal_new (NM_PPP_MANAGER_SIGNAL_STATS, @@ -1347,21 +1488,12 @@ nm_ppp_manager_class_init (NMPPPManagerClass *manager_class) G_TYPE_NONE, 2, G_TYPE_UINT /*guint32 in_bytes*/, G_TYPE_UINT /*guint32 out_bytes*/); - - nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (manager_class), - NMDBUS_TYPE_PPP_MANAGER_SKELETON, - "NeedSecrets", impl_ppp_manager_need_secrets, - "SetIp4Config", impl_ppp_manager_set_ip4_config, - "SetIp6Config", impl_ppp_manager_set_ip6_config, - "SetState", impl_ppp_manager_set_state, - NULL); } NMPPPOps ppp_ops = { .create = _ppp_manager_new, .set_route_parameters = _ppp_manager_set_route_parameters, .start = _ppp_manager_start, - .stop_async = _ppp_manager_stop_async, - .stop_finish = _ppp_manager_stop_finish, - .stop_sync = _ppp_manager_stop_sync, + .stop = _ppp_manager_stop, + .stop_cancel = _ppp_manager_stop_cancel, }; diff --git a/src/ppp/nm-ppp-manager.h b/src/ppp/nm-ppp-manager.h index 35fb1b60..ec0ca46e 100644 --- a/src/ppp/nm-ppp-manager.h +++ b/src/ppp/nm-ppp-manager.h @@ -25,10 +25,18 @@ #define NM_PPP_MANAGER_PARENT_IFACE "parent-iface" #define NM_PPP_MANAGER_SIGNAL_STATE_CHANGED "state-changed" +#define NM_PPP_MANAGER_SIGNAL_IFINDEX_SET "ifindex-set" #define NM_PPP_MANAGER_SIGNAL_IP4_CONFIG "ip4-config" #define NM_PPP_MANAGER_SIGNAL_IP6_CONFIG "ip6-config" #define NM_PPP_MANAGER_SIGNAL_STATS "stats" typedef struct _NMPPPManager NMPPPManager; +typedef struct _NMPPPManagerStopHandle NMPPPManagerStopHandle; + +typedef void (*NMPPPManagerStopCallback) (NMPPPManager *manager, + NMPPPManagerStopHandle *handle, + gboolean was_cancelled, + gpointer user_data); + #endif /* __NM_PPP_MANAGER_H__ */ diff --git a/src/ppp/nm-ppp-plugin-api.h b/src/ppp/nm-ppp-plugin-api.h index bb53690c..558de2c2 100644 --- a/src/ppp/nm-ppp-plugin-api.h +++ b/src/ppp/nm-ppp-plugin-api.h @@ -21,6 +21,8 @@ #ifndef __NM_PPP_PLUGIN_API_H__ #define __NM_PPP_PLUGIN_API_H__ +#include "nm-ppp-manager.h" + typedef const struct { NMPPPManager *(*create) (const char *iface); @@ -37,16 +39,12 @@ typedef const struct { guint baud_override, GError **err); - void (*stop_async) (NMPPPManager *manager, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); + NMPPPManagerStopHandle *(*stop) (NMPPPManager *manager, + NMPPPManagerStopCallback callback, + gpointer user_data); - gboolean (*stop_finish) (NMPPPManager *manager, - GAsyncResult *res, - GError **error); + void (*stop_cancel) (NMPPPManagerStopHandle *handle); - void (*stop_sync) (NMPPPManager *manager); } NMPPPOps; #endif /* __NM_PPP_PLUGIN_API_H__ */ diff --git a/src/ppp/nm-pppd-plugin.c b/src/ppp/nm-pppd-plugin.c index 0ac8f907..989f7433 100644 --- a/src/ppp/nm-pppd-plugin.c +++ b/src/ppp/nm-pppd-plugin.c @@ -28,6 +28,7 @@ #include <pppd/ipcp.h> #include <sys/socket.h> #include <netinet/in.h> +#include <net/if.h> #include <arpa/inet.h> #include <dlfcn.h> @@ -36,7 +37,9 @@ #include <pppd/ipv6cp.h> #include "nm-default.h" + #include "nm-dbus-interface.h" + #include "nm-pppd-plugin.h" #include "nm-ppp-status.h" @@ -50,7 +53,9 @@ static void nm_phasechange (void *data, int arg) { NMPPPStatus ppp_status = NM_PPP_STATUS_UNKNOWN; + char new_name[IF_NAMESIZE]; char *ppp_phase; + int index; g_return_if_fail (G_IS_DBUS_PROXY (proxy)); @@ -126,6 +131,25 @@ nm_phasechange (void *data, int arg) NULL, NULL, NULL); } + + if (ppp_status == PHASE_RUNNING) { + index = if_nametoindex (ifname); + /* Make a sync call to ensure that when the call + * terminates the interface already has its final + * name. */ + g_dbus_proxy_call_sync (proxy, + "SetIfindex", + g_variant_new ("(i)", index), + G_DBUS_CALL_FLAGS_NONE, + 25000, + NULL, NULL); + /* Update the name in pppd if NM changed it */ + if ( if_indextoname (index, new_name) + && !nm_streq0 (ifname, new_name)) { + g_message ("nm-ppp-plugin: interface name changed from '%s' to '%s'", ifname, new_name); + strncpy (ifname, new_name, IF_NAMESIZE); + } + } } static void @@ -148,6 +172,9 @@ nm_ip_up (void *data, int arg) g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); + /* Keep sending the interface name to be backwards compatible + * with older versions of NM during a package upgrade, where + * NM is not restarted and the pppd plugin was not loaded. */ g_variant_builder_add (&builder, "{sv}", NM_PPP_IP4_CONFIG_INTERFACE, g_variant_new_string (ifname)); @@ -242,6 +269,9 @@ nm_ip6_up (void *data, int arg) g_message ("nm-ppp-plugin: (%s): ip6-up event", __func__); g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); + /* Keep sending the interface name to be backwards compatible + * with older versions of NM during a package upgrade, where + * NM is not restarted and the pppd plugin was not loaded. */ g_variant_builder_add (&builder, "{sv}", NM_PPP_IP6_CONFIG_INTERFACE, g_variant_new_string (ifname)); @@ -361,8 +391,6 @@ plugin_init (void) GDBusConnection *bus; GError *err = NULL; - nm_g_type_init (); - g_message ("nm-ppp-plugin: (%s): initializing", __func__); bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &err); |