diff options
| author | Michael Biebl <biebl@debian.org> | 2011-04-21 10:43:09 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2011-04-21 10:43:09 +0200 |
| commit | 8aefc77115a9b89e96ff224e659e2271912a8295 (patch) | |
| tree | 2aeaf38cdc77553c0bf417fb632c2a3d5e7adbc7 /src | |
| parent | 2fbd59597fe985d6feb382bf35145dcf2f481060 (diff) | |
| parent | 8baa1aca8dfd35e3190d7d5655eb83b5b901e263 (diff) | |
Merge commit 'upstream/0.8.4.0'
Diffstat (limited to 'src')
| -rw-r--r-- | src/bluez-manager/Makefile.am | 3 | ||||
| -rw-r--r-- | src/bluez-manager/Makefile.in | 3 | ||||
| -rw-r--r-- | src/dns-manager/nm-dns-manager.c | 49 | ||||
| -rw-r--r-- | src/dns-manager/nm-dns-manager.h | 2 | ||||
| -rw-r--r-- | src/ip6-manager/nm-ip6-manager.c | 19 | ||||
| -rw-r--r-- | src/main.c | 110 | ||||
| -rw-r--r-- | src/modem-manager/nm-modem.c | 17 | ||||
| -rw-r--r-- | src/modem-manager/nm-modem.h | 1 | ||||
| -rw-r--r-- | src/nm-device.c | 2 | ||||
| -rw-r--r-- | src/nm-manager.c | 162 | ||||
| -rw-r--r-- | src/nm-system.c | 4 | ||||
| -rw-r--r-- | src/nm-udev-manager.c | 46 | ||||
| -rw-r--r-- | src/ppp-manager/nm-ppp-manager.c | 33 | ||||
| -rw-r--r-- | src/ppp-manager/nm-ppp-manager.h | 2 | ||||
| -rw-r--r-- | src/vpn-manager/nm-vpn-connection.c | 11 | ||||
| -rw-r--r-- | src/vpn-manager/nm-vpn-connection.h | 5 | ||||
| -rw-r--r-- | src/vpn-manager/nm-vpn-manager.c | 4 | ||||
| -rw-r--r-- | src/vpn-manager/nm-vpn-manager.h | 3 | ||||
| -rw-r--r-- | src/vpn-manager/nm-vpn-service.c | 4 | ||||
| -rw-r--r-- | src/vpn-manager/nm-vpn-service.h | 2 |
20 files changed, 289 insertions, 193 deletions
diff --git a/src/bluez-manager/Makefile.am b/src/bluez-manager/Makefile.am index 6c199e8c..623c1060 100644 --- a/src/bluez-manager/Makefile.am +++ b/src/bluez-manager/Makefile.am @@ -4,8 +4,7 @@ INCLUDES = \ -I${top_srcdir}/libnm-util \ -I${top_srcdir}/src \ -I${top_srcdir}/src/logging \ - -I${top_builddir}/marshallers \ - -I$(top_srcdir)/src/nm-bluez-manager + -I${top_builddir}/marshallers noinst_LTLIBRARIES = libbluez-manager.la diff --git a/src/bluez-manager/Makefile.in b/src/bluez-manager/Makefile.in index fad2ec6e..369028c7 100644 --- a/src/bluez-manager/Makefile.in +++ b/src/bluez-manager/Makefile.in @@ -286,8 +286,7 @@ INCLUDES = \ -I${top_srcdir}/libnm-util \ -I${top_srcdir}/src \ -I${top_srcdir}/src/logging \ - -I${top_builddir}/marshallers \ - -I$(top_srcdir)/src/nm-bluez-manager + -I${top_builddir}/marshallers noinst_LTLIBRARIES = libbluez-manager.la libbluez_manager_la_SOURCES = \ diff --git a/src/dns-manager/nm-dns-manager.c b/src/dns-manager/nm-dns-manager.c index 32800d0b..fc582327 100644 --- a/src/dns-manager/nm-dns-manager.c +++ b/src/dns-manager/nm-dns-manager.c @@ -61,7 +61,9 @@ G_DEFINE_TYPE(NMDnsManager, nm_dns_manager, G_TYPE_OBJECT) NM_TYPE_DNS_MANAGER, \ NMDnsManagerPrivate)) -struct NMDnsManagerPrivate { +typedef struct { + gboolean disposed; + NMIP4Config *ip4_vpn_config; NMIP4Config *ip4_device_config; NMIP6Config *ip6_vpn_config; @@ -84,7 +86,7 @@ struct NMDnsManagerPrivate { * associated with a network interface (like hostnames). */ char *last_iface; -}; +} NMDnsManagerPrivate; typedef struct { @@ -1074,18 +1076,46 @@ nm_dns_manager_init (NMDnsManager *mgr) } static void -nm_dns_manager_finalize (GObject *object) +dispose (GObject *object) +{ + NMDnsManager *self = NM_DNS_MANAGER (object); + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); + GError *error = NULL; + + if (priv->disposed == FALSE) { + priv->disposed = TRUE; + + g_slist_foreach (priv->plugins, (GFunc) g_object_unref, NULL); + g_slist_free (priv->plugins); + priv->plugins = NULL; + + /* If we're quitting leave a valid resolv.conf in place, not one + * pointing to 127.0.0.1 if any plugins were active. Thus update + * DNS after disposing of all plugins. + */ + if (!update_dns (self, priv->last_iface, TRUE, &error)) { + nm_log_warn (LOGD_DNS, "could not commit DNS changes on shutdown: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + } + + g_slist_foreach (priv->configs, (GFunc) g_object_unref, NULL); + g_slist_free (priv->configs); + priv->configs = NULL; + } + + G_OBJECT_CLASS (nm_dns_manager_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) { NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (object); - g_slist_foreach (priv->configs, (GFunc) g_object_unref, NULL); - g_slist_free (priv->configs); g_free (priv->hostname); g_free (priv->last_iface); - g_slist_foreach (priv->plugins, (GFunc) g_object_unref, NULL); - g_slist_free (priv->plugins); - G_OBJECT_CLASS (nm_dns_manager_parent_class)->finalize (object); } @@ -1094,7 +1124,8 @@ nm_dns_manager_class_init (NMDnsManagerClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->finalize = nm_dns_manager_finalize; + object_class->dispose = dispose; + object_class->finalize = finalize; g_type_class_add_private (object_class, sizeof (NMDnsManagerPrivate)); } diff --git a/src/dns-manager/nm-dns-manager.h b/src/dns-manager/nm-dns-manager.h index eb1c73a7..a48130b2 100644 --- a/src/dns-manager/nm-dns-manager.h +++ b/src/dns-manager/nm-dns-manager.h @@ -55,8 +55,6 @@ G_BEGIN_DECLS #define NM_IS_DNS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), NM_TYPE_DNS_MANAGER)) #define NM_DNS_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), NM_TYPE_DNS_MANAGER, NMDnsManagerClass)) -typedef struct NMDnsManagerPrivate NMDnsManagerPrivate; - typedef struct { GObject parent; } NMDnsManager; diff --git a/src/ip6-manager/nm-ip6-manager.c b/src/ip6-manager/nm-ip6-manager.c index 0eb40302..4a5dee58 100644 --- a/src/ip6-manager/nm-ip6-manager.c +++ b/src/ip6-manager/nm-ip6-manager.c @@ -30,7 +30,6 @@ #include "NetworkManagerUtils.h" #include "nm-marshal.h" #include "nm-logging.h" -#include "nm-system.h" /* Pre-DHCP addrconf timeout, in seconds */ #define NM_IP6_TIMEOUT 20 @@ -261,7 +260,7 @@ static gboolean rdnss_expired (gpointer user_data) { NMIP6Device *device = user_data; - CallbackInfo info = { device, IP6_DHCP_OPT_NONE }; + CallbackInfo info = { device, IP6_DHCP_OPT_NONE, FALSE }; nm_log_dbg (LOGD_IP6, "(%s): IPv6 RDNSS information expired", device->iface); @@ -308,9 +307,9 @@ set_rdnss_timeout (NMIP6Device *device) } if (expires) { - device->rdnss_timeout_id = g_timeout_add_seconds (expires - now, - rdnss_expired, - device); + device->rdnss_timeout_id = g_timeout_add_seconds (MIN (expires - now, G_MAXUINT32 - 1), + rdnss_expired, + device); } } @@ -363,7 +362,7 @@ set_dnssl_timeout (NMIP6Device *device) } if (expires) { - device->dnssl_timeout_id = g_timeout_add_seconds (expires - now, + device->dnssl_timeout_id = g_timeout_add_seconds (MIN (expires - now, G_MAXUINT32 - 1), dnssl_expired, device); } @@ -689,9 +688,12 @@ process_nduseropt_rdnss (NMIP6Device *device, struct nd_opt_hdr *opt) for (addr = (struct in6_addr *) (rdnss_opt + 1); opt_len >= 2; addr++, opt_len -= 2) { char buf[INET6_ADDRSTRLEN + 1]; - if (!inet_ntop (AF_INET6, addr, buf, sizeof (buf))) - strcpy(buf, "[invalid]"); + if (!inet_ntop (AF_INET6, addr, buf, sizeof (buf))) { + nm_log_warn (LOGD_IP6, "(%s): received invalid RA-provided nameserver", device->iface); + continue; + } + /* Update the cached timeout if we already saw this server */ for (i = 0; i < device->rdnss_servers->len; i++) { cur_server = &(g_array_index (device->rdnss_servers, NMIP6RDNSS, i)); @@ -834,6 +836,7 @@ process_nduseropt_dnssl (NMIP6Device *device, struct nd_opt_hdr *opt) if (domain_str[0] == '\0') continue; + /* Update cached domain information if we've seen this domain before */ for (i = 0; i < device->dnssl_domains->len; i++) { cur_domain = &(g_array_index (device->dnssl_domains, NMIP6DNSSL, i)); diff --git a/src/main.c b/src/main.c index b22c769d..da63930b 100644 --- a/src/main.c +++ b/src/main.c @@ -65,6 +65,7 @@ */ static NMManager *manager = NULL; static GMainLoop *main_loop = NULL; +static int quit_pipe[2] = { -1, -1 }; typedef struct { time_t time; @@ -145,62 +146,62 @@ static gboolean quit_early = FALSE; static void nm_signal_handler (int signo) { - static int in_fatal = 0; + static int in_fatal = 0, x; /* avoid loops */ if (in_fatal > 0) return; ++in_fatal; - switch (signo) - { - case SIGSEGV: - case SIGBUS: - case SIGILL: - case SIGABRT: - nm_log_warn (LOGD_CORE, "caught signal %d. Generating backtrace...", signo); - nm_logging_backtrace (); - exit (1); - break; - - case SIGFPE: - case SIGPIPE: - /* let the fatal signals interrupt us */ - --in_fatal; - - nm_log_warn (LOGD_CORE, "caught signal %d, shutting down abnormally. Generating backtrace...", signo); - nm_logging_backtrace (); - g_main_loop_quit (main_loop); - break; - - case SIGINT: - case SIGTERM: - /* let the fatal signals interrupt us */ - --in_fatal; - - nm_log_info (LOGD_CORE, "caught signal %d, shutting down normally.", signo); - quit_early = TRUE; - g_main_loop_quit (main_loop); - break; - - case SIGHUP: - --in_fatal; - /* FIXME: - * Reread config stuff like system config files, VPN service files, etc - */ - break; - - case SIGUSR1: - --in_fatal; - /* FIXME: - * Play with log levels or something - */ - break; - - default: - signal (signo, nm_signal_handler); - break; + switch (signo) { + case SIGSEGV: + case SIGBUS: + case SIGILL: + case SIGABRT: + nm_log_warn (LOGD_CORE, "caught signal %d. Generating backtrace...", signo); + nm_logging_backtrace (); + exit (1); + break; + case SIGFPE: + case SIGPIPE: + /* let the fatal signals interrupt us */ + --in_fatal; + nm_log_warn (LOGD_CORE, "caught signal %d, shutting down abnormally. Generating backtrace...", signo); + nm_logging_backtrace (); + x = write (quit_pipe[1], "X", 1); + break; + case SIGINT: + case SIGTERM: + /* let the fatal signals interrupt us */ + --in_fatal; + nm_log_info (LOGD_CORE, "caught signal %d, shutting down normally.", signo); + quit_early = TRUE; + x = write (quit_pipe[1], "X", 1); + break; + case SIGHUP: + --in_fatal; + /* Reread config stuff like system config files, VPN service files, etc */ + break; + case SIGUSR1: + --in_fatal; + /* Play with log levels or something */ + break; + default: + signal (signo, nm_signal_handler); + break; + } +} + +static gboolean +quit_watch (GIOChannel *src, GIOCondition condition, gpointer user_data) +{ + + if (condition & G_IO_IN) { + nm_log_warn (LOGD_CORE, "quit request received, terminating..."); + g_main_loop_quit (main_loop); } + + return FALSE; } static void @@ -208,6 +209,17 @@ setup_signals (void) { struct sigaction action; sigset_t mask; + GIOChannel *quit_channel; + + /* Set up our quit pipe */ + if (pipe (quit_pipe) < 0) { + fprintf (stderr, "Failed to initialze SIGTERM pipe: %d", errno); + exit (1); + } + fcntl (quit_pipe[1], F_SETFL, O_NONBLOCK | fcntl (quit_pipe[1], F_GETFL)); + + quit_channel = g_io_channel_unix_new (quit_pipe[0]); + g_io_add_watch_full (quit_channel, G_PRIORITY_HIGH, G_IO_IN | G_IO_ERR, quit_watch, NULL, NULL); sigemptyset (&mask); action.sa_handler = nm_signal_handler; diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index b3f7eaa1..9471ef87 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -85,14 +85,6 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -NMPPPManager * -nm_modem_get_ppp_manager (NMModem *self) -{ - g_return_val_if_fail (NM_IS_MODEM (self), NULL); - - return NM_MODEM_GET_PRIVATE (self)->ppp_manager; -} - gboolean nm_modem_get_mm_enabled (NMModem *self) { @@ -651,12 +643,13 @@ real_deactivate_quickly (NMModem *self, NMDevice *device) priv->in_bytes = priv->out_bytes = 0; + if (priv->ppp_manager) { + g_object_unref (priv->ppp_manager); + priv->ppp_manager = NULL; + } + switch (priv->ip_method) { case MM_MODEM_IP_METHOD_PPP: - if (priv->ppp_manager) { - g_object_unref (priv->ppp_manager); - priv->ppp_manager = NULL; - } break; case MM_MODEM_IP_METHOD_STATIC: case MM_MODEM_IP_METHOD_DHCP: diff --git a/src/modem-manager/nm-modem.h b/src/modem-manager/nm-modem.h index a2aed57e..6e47c903 100644 --- a/src/modem-manager/nm-modem.h +++ b/src/modem-manager/nm-modem.h @@ -97,7 +97,6 @@ GType nm_modem_get_type (void); /* Protected */ -NMPPPManager *nm_modem_get_ppp_manager (NMModem *modem); DBusGProxy * nm_modem_get_proxy (NMModem *modem, const char *interface); const char * nm_modem_get_iface (NMModem *modem); const char * nm_modem_get_path (NMModem *modem); diff --git a/src/nm-device.c b/src/nm-device.c index 9c771c2a..8675bf62 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -1617,7 +1617,7 @@ dhcp6_start (NMDevice *self, */ err = nm_system_set_ip6_route (priv->ip_iface ? priv->ip_ifindex : priv->ifindex, &dest, 8, NULL, 256, 0, RTPROT_BOOT, RT_TABLE_LOCAL, NULL); - if (err) { + if (err && (nl_get_errno () != EEXIST)) { nm_log_err (LOGD_DEVICE | LOGD_IP6, "(%s): failed to add IPv6 multicast route: %s", priv->ip_iface ? priv->ip_iface : priv->iface, nl_geterror ()); diff --git a/src/nm-manager.c b/src/nm-manager.c index 8b24aa51..e34e9014 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -188,6 +188,7 @@ struct PendingActivation { typedef struct { gboolean user_enabled; + gboolean daemon_enabled; gboolean sw_enabled; gboolean hw_enabled; RfKillType rtype; @@ -196,6 +197,7 @@ typedef struct { const char *prop; const char *hw_prop; RfKillState (*other_enabled_func) (NMManager *); + RfKillState (*daemon_enabled_func) (NMManager *); } RadioState; typedef struct { @@ -917,7 +919,6 @@ static GPtrArray * get_active_connections (NMManager *manager, NMConnection *filter) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - NMVPNManager *vpn_manager; GPtrArray *active; GSList *iter; @@ -939,9 +940,7 @@ get_active_connections (NMManager *manager, NMConnection *filter) } /* Add active VPN connections */ - vpn_manager = nm_vpn_manager_get (); - nm_vpn_manager_add_active_connections (vpn_manager, filter, active); - g_object_unref (vpn_manager); + nm_vpn_manager_add_active_connections (priv->vpn_manager, filter, active); return active; } @@ -1651,21 +1650,28 @@ write_value_to_state_file (const char *filename, } static gboolean -radio_enabled_for_rstate (RadioState *rstate) +radio_enabled_for_rstate (RadioState *rstate, gboolean check_daemon_enabled) { - return rstate->user_enabled && rstate->sw_enabled && rstate->hw_enabled; + gboolean enabled; + + enabled = rstate->user_enabled && rstate->sw_enabled && rstate->hw_enabled; + if (rstate->daemon_enabled_func && check_daemon_enabled) + enabled &= rstate->daemon_enabled; + return enabled; } static gboolean -radio_enabled_for_type (NMManager *self, RfKillType rtype) +radio_enabled_for_type (NMManager *self, RfKillType rtype, gboolean check_daemon_enabled) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - return radio_enabled_for_rstate (&priv->radio_states[rtype]); + return radio_enabled_for_rstate (&priv->radio_states[rtype], check_daemon_enabled); } static void -manager_update_radio_enabled (NMManager *self, RadioState *rstate) +manager_update_radio_enabled (NMManager *self, + RadioState *rstate, + gboolean enabled) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); GSList *iter; @@ -1683,7 +1689,6 @@ manager_update_radio_enabled (NMManager *self, RadioState *rstate) /* enable/disable wireless devices as required */ for (iter = priv->devices; iter; iter = iter->next) { RfKillType devtype = RFKILL_TYPE_UNKNOWN; - gboolean enabled = radio_enabled_for_rstate (rstate); g_object_get (G_OBJECT (iter->data), NM_DEVICE_INTERFACE_RFKILL_TYPE, &devtype, NULL); if (devtype == rstate->rtype) { @@ -1830,9 +1835,9 @@ manager_rfkill_update_one_type (NMManager *self, RfKillState other_state = RFKILL_UNBLOCKED; RfKillState composite; gboolean old_enabled, new_enabled, old_rfkilled, new_rfkilled; - gboolean old_hwe; + gboolean old_hwe, old_daemon_enabled = FALSE; - old_enabled = radio_enabled_for_rstate (rstate); + old_enabled = radio_enabled_for_rstate (rstate, TRUE); old_rfkilled = rstate->hw_enabled && rstate->sw_enabled; old_hwe = rstate->hw_enabled; @@ -1851,9 +1856,26 @@ manager_rfkill_update_one_type (NMManager *self, update_rstate_from_rfkill (rstate, composite); + /* If the device has a management daemon that can affect enabled state, check that now */ + if (rstate->daemon_enabled_func) { + old_daemon_enabled = rstate->daemon_enabled; + rstate->daemon_enabled = (rstate->daemon_enabled_func (self) == RFKILL_UNBLOCKED); + if (old_daemon_enabled != rstate->daemon_enabled) { + nm_log_info (LOGD_RFKILL, "%s now %s by management service", + rstate->desc, + rstate->daemon_enabled ? "enabled" : "disabled"); + } + } + + /* Print out all states affecting device enablement */ if (rstate->desc) { - nm_log_dbg (LOGD_RFKILL, "%s hw-enabled %d sw-enabled %d", - rstate->desc, rstate->hw_enabled, rstate->sw_enabled); + if (rstate->daemon_enabled_func) { + nm_log_dbg (LOGD_RFKILL, "%s hw-enabled %d sw-enabled %d daemon-enabled %d", + rstate->desc, rstate->hw_enabled, rstate->sw_enabled, rstate->daemon_enabled); + } else { + nm_log_dbg (LOGD_RFKILL, "%s hw-enabled %d sw-enabled %d", + rstate->desc, rstate->hw_enabled, rstate->sw_enabled); + } } /* Log new killswitch state */ @@ -1870,10 +1892,14 @@ manager_rfkill_update_one_type (NMManager *self, g_object_notify (G_OBJECT (self), rstate->hw_prop); } - /* And finally update the actual device radio state itself */ - new_enabled = radio_enabled_for_rstate (rstate); + /* And finally update the actual device radio state itself; respect the + * daemon state here because this is never called from user-triggered + * radio changes and we only want to ignore the daemon enabled state when + * handling user radio change requests. + */ + new_enabled = radio_enabled_for_rstate (rstate, TRUE); if (new_enabled != old_enabled) - manager_update_radio_enabled (self, rstate); + manager_update_radio_enabled (self, rstate, new_enabled); } static void @@ -1882,14 +1908,13 @@ nm_manager_rfkill_update (NMManager *self, RfKillType rtype) NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); guint i; - if (rtype != RFKILL_TYPE_UNKNOWN) { + if (rtype != RFKILL_TYPE_UNKNOWN) manager_rfkill_update_one_type (self, &priv->radio_states[rtype], rtype); - return; + else { + /* Otherwise sync all radio types */ + for (i = 0; i < RFKILL_TYPE_MAX; i++) + manager_rfkill_update_one_type (self, &priv->radio_states[i], i); } - - /* Otherwise sync all radio types */ - for (i = 0; i < RFKILL_TYPE_MAX; i++) - manager_rfkill_update_one_type (self, &priv->radio_states[i], i); } static void @@ -2084,6 +2109,7 @@ add_device (NMManager *self, NMDevice *device) GHashTableIter iter; gpointer value; gboolean managed = FALSE, enabled = FALSE; + RfKillType rtype = RFKILL_TYPE_UNKNOWN; iface = nm_device_get_ip_iface (device); g_assert (iface); @@ -2117,26 +2143,21 @@ add_device (NMManager *self, NMDevice *device) g_signal_connect (device, "notify::" NM_DEVICE_WIFI_IPW_RFKILL_STATE, G_CALLBACK (manager_ipw_rfkill_state_changed), self); - - /* Update global rfkill state with this device's rfkill state, and - * then set this device's rfkill state based on the global state. - */ - nm_manager_rfkill_update (self, RFKILL_TYPE_WLAN); - enabled = radio_enabled_for_type (self, RFKILL_TYPE_WLAN); - nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), enabled); + rtype = RFKILL_TYPE_WLAN; } else if (NM_IS_DEVICE_MODEM (device)) { g_signal_connect (device, NM_DEVICE_MODEM_ENABLE_CHANGED, G_CALLBACK (manager_modem_enabled_changed), self); + rtype = RFKILL_TYPE_WWAN; + } - nm_manager_rfkill_update (self, RFKILL_TYPE_WWAN); - enabled = radio_enabled_for_type (self, RFKILL_TYPE_WWAN); - /* Until we start respecting WWAN rfkill switches the modem itself - * is the source of the enabled/disabled state, so the manager shouldn't - * touch it here. - nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), - priv->radio_states[RFKILL_TYPE_WWAN].enabled); - */ + if (rtype != RFKILL_TYPE_UNKNOWN) { + /* Update global rfkill state with this device's rfkill state, and + * then set this device's rfkill state based on the global state. + */ + nm_manager_rfkill_update (self, rtype); + enabled = radio_enabled_for_type (self, rtype, TRUE); + nm_device_interface_set_enabled (NM_DEVICE_INTERFACE (device), enabled); } type_desc = nm_device_get_type_desc (device); @@ -2597,6 +2618,7 @@ user_get_secrets_cb (DBusGProxy *proxy, gpointer user_data) { GetSecretsInfo *info = (GetSecretsInfo *) user_data; + NMManagerPrivate *priv; GHashTable *settings = NULL; GError *error = NULL; GObject *provider; @@ -2605,6 +2627,15 @@ user_get_secrets_cb (DBusGProxy *proxy, g_return_if_fail (info->provider); g_return_if_fail (info->setting_name); + /* Remove the GetSecretsInfo from our internal list just in case + * calling the secrets provider's get_secrets_result() function tries + * to cancel the secrets request, which would cause us to double-free + * the GetSecretsInfo. We know we're going to free it at the end here, + * so there's no need to track it anymore. + */ + priv = NM_MANAGER_GET_PRIVATE (info->manager); + priv->secrets_calls = g_slist_remove (priv->secrets_calls, info); + provider = g_object_ref (info->provider); if (dbus_g_proxy_end_call (proxy, call, &error, @@ -2905,10 +2936,8 @@ nm_manager_activate_connection (NMManager *manager, if (!strcmp (nm_setting_connection_get_connection_type (s_con), NM_SETTING_VPN_SETTING_NAME)) { NMActRequest *req = NULL; - NMVPNManager *vpn_manager; /* VPN connection */ - if (specific_object) { /* Find the specifc connection the client requested we use */ req = nm_manager_get_act_request_by_path (manager, specific_object, &device); @@ -2942,10 +2971,8 @@ nm_manager_activate_connection (NMManager *manager, return NULL; } - vpn_manager = nm_vpn_manager_get (); - vpn_connection = nm_vpn_manager_activate_connection (vpn_manager, + vpn_connection = nm_vpn_manager_activate_connection (priv->vpn_manager, connection, - req, device, error); if (vpn_connection) { @@ -2955,7 +2982,6 @@ nm_manager_activate_connection (NMManager *manager, G_CALLBACK (provider_cancel_secrets), manager); path = nm_vpn_connection_get_active_connection_path (vpn_connection); } - g_object_unref (vpn_manager); } else { NMDeviceState state; @@ -3136,7 +3162,6 @@ nm_manager_deactivate_connection (NMManager *manager, GError **error) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - NMVPNManager *vpn_manager; GSList *iter; gboolean success = FALSE; NMVPNConnectionStateReason vpn_reason = NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED; @@ -3160,17 +3185,15 @@ nm_manager_deactivate_connection (NMManager *manager, } /* Check for VPN connections next */ - vpn_manager = nm_vpn_manager_get (); if (reason == NM_DEVICE_STATE_REASON_CONNECTION_REMOVED) vpn_reason = NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED; - if (nm_vpn_manager_deactivate_connection (vpn_manager, connection_path, vpn_reason)) { + if (nm_vpn_manager_deactivate_connection (priv->vpn_manager, connection_path, vpn_reason)) { success = TRUE; } else { g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, "%s", "The connection was not active."); } - g_object_unref (vpn_manager); done: g_object_notify (G_OBJECT (manager), NM_MANAGER_ACTIVE_CONNECTIONS); @@ -3383,7 +3406,7 @@ do_sleep_wake (NMManager *self) */ for (i = 0; i < RFKILL_TYPE_MAX; i++) { RadioState *rstate = &priv->radio_states[i]; - gboolean enabled = radio_enabled_for_rstate (rstate); + gboolean enabled = radio_enabled_for_rstate (rstate, TRUE); RfKillType devtype = RFKILL_TYPE_UNKNOWN; if (rstate->desc) { @@ -3997,6 +4020,7 @@ nm_manager_start (NMManager *self) for (i = 0; i < RFKILL_TYPE_MAX; i++) { RadioState *rstate = &priv->radio_states[i]; RfKillState udev_state; + gboolean enabled; if (!rstate->desc) continue; @@ -4010,7 +4034,8 @@ nm_manager_start (NMManager *self) (rstate->hw_enabled && rstate->sw_enabled) ? "enabled" : "disabled", rstate->user_enabled ? "enabled" : "disabled"); } - manager_update_radio_enabled (self, rstate); + enabled = radio_enabled_for_rstate (rstate, TRUE); + manager_update_radio_enabled (self, rstate, enabled); } /* Log overall networking status - enabled/disabled */ @@ -4344,7 +4369,7 @@ dispose (GObject *object) { NMManager *manager = NM_MANAGER (object); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - GSList *iter; + GSList *iter, *list; DBusGConnection *bus; DBusConnection *dbus_connection; @@ -4390,6 +4415,20 @@ dispose (GObject *object) priv->sys_settings = NULL; } + /* Make sure we disconnect signal handlers from VPN connections that + * might still be alive when the manager dies. + */ + list = nm_vpn_manager_get_active_connections (priv->vpn_manager); + for (iter = list; iter; iter = g_slist_next (iter)) { + g_signal_handlers_disconnect_by_func (G_OBJECT (iter->data), + G_CALLBACK (provider_get_secrets), + manager); + g_signal_handlers_disconnect_by_func (G_OBJECT (iter->data), + G_CALLBACK (provider_cancel_secrets), + manager); + /* unref to balance returned objects from the VPN manager */ + g_object_unref (iter->data); + } if (priv->vpn_manager_id) { g_source_remove (priv->vpn_manager_id); priv->vpn_manager_id = 0; @@ -4472,11 +4511,20 @@ manager_radio_user_toggled (NMManager *self, } } - old_enabled = radio_enabled_for_rstate (rstate); + /* When the user toggles the radio, their request should override any + * daemon (like ModemManager) enabled state that can be changed. For WWAN + * for example, we want the WwanEnabled property to reflect the daemon state + * too so that users can toggle the modem powered, but we don't want that + * daemon state to affect whether or not the user *can* turn it on, which is + * what the kernel rfkill state does. So we ignore daemon enabled state + * when determining what the new state should be since it shouldn't block + * the user's request. + */ + old_enabled = radio_enabled_for_rstate (rstate, TRUE); rstate->user_enabled = enabled; - new_enabled = radio_enabled_for_rstate (rstate); + new_enabled = radio_enabled_for_rstate (rstate, FALSE); if (new_enabled != old_enabled) - manager_update_radio_enabled (self, rstate); + manager_update_radio_enabled (self, rstate, new_enabled); } static void @@ -4526,13 +4574,13 @@ get_property (GObject *object, guint prop_id, g_value_set_boolean (value, priv->net_enabled); break; case PROP_WIRELESS_ENABLED: - g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WLAN)); + g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WLAN, TRUE)); break; case PROP_WIRELESS_HARDWARE_ENABLED: g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WLAN].hw_enabled); break; case PROP_WWAN_ENABLED: - g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WWAN)); + g_value_set_boolean (value, radio_enabled_for_type (self, RFKILL_TYPE_WWAN, TRUE)); break; case PROP_WWAN_HARDWARE_ENABLED: g_value_set_boolean (value, priv->radio_states[RFKILL_TYPE_WWAN].hw_enabled); @@ -4599,7 +4647,7 @@ nm_manager_init (NMManager *manager) priv->radio_states[RFKILL_TYPE_WWAN].prop = NM_MANAGER_WWAN_ENABLED; priv->radio_states[RFKILL_TYPE_WWAN].hw_prop = NM_MANAGER_WWAN_HARDWARE_ENABLED; priv->radio_states[RFKILL_TYPE_WWAN].desc = "WWAN"; - priv->radio_states[RFKILL_TYPE_WWAN].other_enabled_func = nm_manager_get_modem_enabled_state; + priv->radio_states[RFKILL_TYPE_WWAN].daemon_enabled_func = nm_manager_get_modem_enabled_state; priv->radio_states[RFKILL_TYPE_WWAN].rtype = RFKILL_TYPE_WWAN; priv->radio_states[RFKILL_TYPE_WIMAX].user_enabled = TRUE; diff --git a/src/nm-system.c b/src/nm-system.c index e8b8fec1..88db6596 100644 --- a/src/nm-system.c +++ b/src/nm-system.c @@ -312,10 +312,10 @@ sync_addresses (const char *iface, int ifindex, int family, } err = rtnl_addr_add (nlh, addrs[i], 0); - if (err < 0) { + if (err < 0 && (nl_get_errno () != EEXIST)) { nm_log_err (log_domain, "(%s): error %d returned from rtnl_addr_add():\n%s", - iface, err, nl_geterror ()); + iface, err, nl_geterror ()); } rtnl_addr_put (addrs[i]); diff --git a/src/nm-udev-manager.c b/src/nm-udev-manager.c index ff0ef68c..3ec8e7c9 100644 --- a/src/nm-udev-manager.c +++ b/src/nm-udev-manager.c @@ -88,7 +88,7 @@ rfkill_type_to_desc (RfKillType rtype) if (rtype == 0) return "WiFi"; else if (rtype == 1) - return "WWan"; + return "WWAN"; else if (rtype == 2) return "WiMAX"; return "unknown"; @@ -373,8 +373,12 @@ device_creator (NMUdevManager *manager, } if (!driver) { - nm_log_warn (LOGD_HW, "%s: couldn't determine device driver; ignoring...", path); - goto out; + if (g_str_has_prefix (ifname, "easytether")) { + driver = "easytether"; + } else { + nm_log_warn (LOGD_HW, "%s: couldn't determine device driver; ignoring...", path); + goto out; + } } ifindex = g_udev_device_get_sysfs_attr_as_int (udev_device, "ifindex"); @@ -403,14 +407,24 @@ net_add (NMUdevManager *self, GUdevDevice *device) { gint etype; const char *iface; - const char *devtype; + const char *tmp; g_return_if_fail (device != NULL); + iface = g_udev_device_get_name (device); + if (!iface) { + nm_log_dbg (LOGD_HW, "failed to get device's interface"); + return; + } + + /* Ignore devices that don't report Ethernet encapsulation, except for + * s390 CTC-type devices that report 256 for some reason. + * FIXME: use something other than interface name to detect CTC here. + */ etype = g_udev_device_get_sysfs_attr_as_int (device, "type"); - if (etype != 1) { + if ((etype != 1) && (!strncmp (iface, "ctc", 3) && (etype != 256))) { nm_log_dbg (LOGD_HW, "ignoring interface with type %d", etype); - return; /* Not using ethernet encapsulation, don't care */ + return; } /* Not all ethernet devices are immediately usable; newer mobile broadband @@ -420,16 +434,22 @@ net_add (NMUdevManager *self, GUdevDevice *device) * subclass. ModemManager will pick it up though and so we'll handle it * through the mobile broadband stuff. */ - devtype = g_udev_device_get_property (device, "DEVTYPE"); - if (devtype && !strcmp (devtype, "wwan")) { - nm_log_dbg (LOGD_HW, "ignoring interface with devtype '%s'", devtype); + tmp = g_udev_device_get_property (device, "DEVTYPE"); + if (g_strcmp0 (tmp, "wwan") == 0) { + nm_log_dbg (LOGD_HW, "ignoring interface with devtype '%s'", tmp); return; } - iface = g_udev_device_get_name (device); - if (!iface) { - nm_log_dbg (LOGD_HW, "failed to get device's interface"); - return; + /* Ignore Nokia cdc-ether interfaces in PC-Suite mode since we need to + * talk phonet to use them, which ModemManager doesn't do yet. + */ + tmp = g_udev_device_get_property (device, "ID_VENDOR_ID"); + if (g_strcmp0 (tmp, "0421") == 0) { /* Nokia vendor ID */ + tmp = g_udev_device_get_property (device, "ID_MODEL"); + if (tmp && (strstr (tmp, "PC-Suite") || strstr (tmp, "PC Suite"))) { + nm_log_dbg (LOGD_HW, "ignoring Nokia PC-Suite ethernet interface"); + return; + } } g_signal_emit (self, signals[DEVICE_ADDED], 0, device, device_creator); diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c index 31a5e57a..1258b8f6 100644 --- a/src/ppp-manager/nm-ppp-manager.c +++ b/src/ppp-manager/nm-ppp-manager.c @@ -66,10 +66,14 @@ static gboolean impl_ppp_manager_set_ip4_config (NMPPPManager *manager, #include "nm-ppp-manager-glue.h" +static void _ppp_cleanup (NMPPPManager *manager); + #define NM_PPPD_PLUGIN PLUGINDIR "/nm-pppd-plugin.so" #define PPP_MANAGER_SECRET_TRIES "ppp-manager-secret-tries" typedef struct { + gboolean disposed; + GPid pid; NMDBusManager *dbus_manager; char *dbus_path; @@ -163,11 +167,19 @@ dispose (GObject *object) { NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (object); - nm_ppp_manager_stop (NM_PPP_MANAGER (object)); + if (priv->disposed == FALSE) { + priv->disposed = TRUE; - if (priv->act_req) - g_object_unref (priv->act_req); - g_object_unref (priv->dbus_manager); + _ppp_cleanup (NM_PPP_MANAGER (object)); + + if (priv->act_req) { + g_object_unref (priv->act_req); + priv->act_req = NULL; + } + + g_object_unref (priv->dbus_manager); + priv->dbus_manager = NULL; + } G_OBJECT_CLASS (nm_ppp_manager_parent_class)->dispose (object); } @@ -315,9 +327,12 @@ monitor_stats (NMPPPManager *manager) NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager); priv->monitor_fd = socket (AF_INET, SOCK_DGRAM, 0); - if (priv->monitor_fd > 0) + if (priv->monitor_fd > 0) { + 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); - else + } else nm_log_warn (LOGD_PPP, "could not monitor PPP stats: %s", strerror (errno)); } @@ -706,7 +721,7 @@ pppd_timed_out (gpointer data) NMPPPManager *manager = NM_PPP_MANAGER (data); nm_log_warn (LOGD_PPP, "pppd timed out or didn't initialize our dbus module"); - nm_ppp_manager_stop (manager); + _ppp_cleanup (manager); g_signal_emit (manager, signals[STATE_CHANGED], 0, NM_PPP_STATUS_DEAD); @@ -1023,8 +1038,8 @@ ensure_killed (gpointer data) return FALSE; } -void -nm_ppp_manager_stop (NMPPPManager *manager) +static void +_ppp_cleanup (NMPPPManager *manager) { NMPPPManagerPrivate *priv; diff --git a/src/ppp-manager/nm-ppp-manager.h b/src/ppp-manager/nm-ppp-manager.h index a0200973..51684157 100644 --- a/src/ppp-manager/nm-ppp-manager.h +++ b/src/ppp-manager/nm-ppp-manager.h @@ -69,8 +69,6 @@ void nm_ppp_manager_update_secrets (NMPPPManager *manager, const char *password, const char *error_message); -void nm_ppp_manager_stop (NMPPPManager *manager); - #define NM_PPP_MANAGER_ERROR nm_ppp_manager_error_quark() #define NM_TYPE_PPP_MANAGER_ERROR (nm_ppp_manager_error_get_type ()) diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index 03e213ff..823b6149 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -61,8 +61,6 @@ typedef struct { NMConnection *connection; - NMActRequest *act_request; - NMDevice *parent_dev; gulong device_monitor; gulong device_ip4; @@ -199,15 +197,12 @@ device_ip4_config_changed (NMDevice *device, } NMVPNConnection * -nm_vpn_connection_new (NMConnection *connection, - NMActRequest *act_request, - NMDevice *parent_device) +nm_vpn_connection_new (NMConnection *connection, NMDevice *parent_device) { NMVPNConnection *self; NMVPNConnectionPrivate *priv; g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - g_return_val_if_fail (NM_IS_ACT_REQUEST (act_request), NULL); g_return_val_if_fail (NM_IS_DEVICE (parent_device), NULL); self = (NMVPNConnection *) g_object_new (NM_TYPE_VPN_CONNECTION, NULL); @@ -218,7 +213,6 @@ nm_vpn_connection_new (NMConnection *connection, priv->connection = g_object_ref (connection); priv->parent_dev = g_object_ref (parent_device); - priv->act_request = g_object_ref (act_request); priv->device_monitor = g_signal_connect (parent_device, "state-changed", G_CALLBACK (device_state_changed), @@ -925,7 +919,7 @@ connection_state_changed (NMVPNConnection *connection, { NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); - nm_secrets_provider_interface_cancel_get_secrets (NM_SECRETS_PROVIDER_INTERFACE (priv->act_request)); + nm_secrets_provider_interface_cancel_get_secrets (NM_SECRETS_PROVIDER_INTERFACE (connection)); switch (state) { case NM_VPN_CONNECTION_STATE_NEED_AUTH: @@ -989,7 +983,6 @@ dispose (GObject *object) if (priv->proxy) g_object_unref (priv->proxy); - g_object_unref (priv->act_request); g_object_unref (priv->connection); G_OBJECT_CLASS (nm_vpn_connection_parent_class)->dispose (object); diff --git a/src/vpn-manager/nm-vpn-connection.h b/src/vpn-manager/nm-vpn-connection.h index ab880b17..8da7d512 100644 --- a/src/vpn-manager/nm-vpn-connection.h +++ b/src/vpn-manager/nm-vpn-connection.h @@ -26,7 +26,6 @@ #include <glib-object.h> #include "NetworkManagerVPN.h" #include "nm-device.h" -#include "nm-activation-request.h" #include "nm-secrets-provider-interface.h" #include "nm-vpn-connection-base.h" @@ -57,9 +56,7 @@ typedef struct { GType nm_vpn_connection_get_type (void); -NMVPNConnection * nm_vpn_connection_new (NMConnection *connection, - NMActRequest *act_request, - NMDevice *parent_device); +NMVPNConnection * nm_vpn_connection_new (NMConnection *connection, NMDevice *parent_device); void nm_vpn_connection_activate (NMVPNConnection *connection); NMConnection * nm_vpn_connection_get_connection (NMVPNConnection *connection); diff --git a/src/vpn-manager/nm-vpn-manager.c b/src/vpn-manager/nm-vpn-manager.c index d3cd10a8..38b06b19 100644 --- a/src/vpn-manager/nm-vpn-manager.c +++ b/src/vpn-manager/nm-vpn-manager.c @@ -157,7 +157,6 @@ connection_vpn_state_changed (NMVPNConnection *connection, NMVPNConnection * nm_vpn_manager_activate_connection (NMVPNManager *manager, NMConnection *connection, - NMActRequest *act_request, NMDevice *device, GError **error) { @@ -168,7 +167,6 @@ nm_vpn_manager_activate_connection (NMVPNManager *manager, g_return_val_if_fail (NM_IS_VPN_MANAGER (manager), NULL); g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - g_return_val_if_fail (NM_IS_ACT_REQUEST (act_request), NULL); g_return_val_if_fail (NM_IS_DEVICE (device), NULL); g_return_val_if_fail (error != NULL, NULL); g_return_val_if_fail (*error == NULL, NULL); @@ -205,7 +203,7 @@ nm_vpn_manager_activate_connection (NMVPNManager *manager, return NULL; } - vpn = nm_vpn_service_activate (service, connection, act_request, device, error); + vpn = nm_vpn_service_activate (service, connection, device, error); if (vpn) { g_signal_connect (vpn, "vpn-state-changed", G_CALLBACK (connection_vpn_state_changed), diff --git a/src/vpn-manager/nm-vpn-manager.h b/src/vpn-manager/nm-vpn-manager.h index f14844a9..b9cf7daf 100644 --- a/src/vpn-manager/nm-vpn-manager.h +++ b/src/vpn-manager/nm-vpn-manager.h @@ -25,8 +25,6 @@ #include <glib.h> #include <glib-object.h> #include "nm-vpn-connection.h" -#include "nm-activation-request.h" - #define NM_TYPE_VPN_MANAGER (nm_vpn_manager_get_type ()) #define NM_VPN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_MANAGER, NMVPNManager)) #define NM_VPN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_VPN_MANAGER, NMVPNManagerClass)) @@ -69,7 +67,6 @@ NMVPNManager *nm_vpn_manager_get (void); NMVPNConnection *nm_vpn_manager_activate_connection (NMVPNManager *manager, NMConnection *connection, - NMActRequest *act_request, NMDevice *device, GError **error); diff --git a/src/vpn-manager/nm-vpn-service.c b/src/vpn-manager/nm-vpn-service.c index 3d44d900..68cfadb7 100644 --- a/src/vpn-manager/nm-vpn-service.c +++ b/src/vpn-manager/nm-vpn-service.c @@ -323,7 +323,6 @@ connection_vpn_state_changed (NMVPNConnection *connection, NMVPNConnection * nm_vpn_service_activate (NMVPNService *service, NMConnection *connection, - NMActRequest *act_request, NMDevice *device, GError **error) { @@ -332,7 +331,6 @@ nm_vpn_service_activate (NMVPNService *service, g_return_val_if_fail (NM_IS_VPN_SERVICE (service), NULL); g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL); - g_return_val_if_fail (NM_IS_ACT_REQUEST (act_request), NULL); g_return_val_if_fail (NM_IS_DEVICE (device), NULL); g_return_val_if_fail (error != NULL, NULL); g_return_val_if_fail (*error == NULL, NULL); @@ -341,7 +339,7 @@ nm_vpn_service_activate (NMVPNService *service, clear_quit_timeout (service); - vpn = nm_vpn_connection_new (connection, act_request, device); + vpn = nm_vpn_connection_new (connection, device); g_signal_connect (vpn, "vpn-state-changed", G_CALLBACK (connection_vpn_state_changed), service); diff --git a/src/vpn-manager/nm-vpn-service.h b/src/vpn-manager/nm-vpn-service.h index c7c1b036..0c7030e4 100644 --- a/src/vpn-manager/nm-vpn-service.h +++ b/src/vpn-manager/nm-vpn-service.h @@ -26,7 +26,6 @@ #include <glib-object.h> #include "nm-device.h" #include "nm-vpn-connection.h" -#include "nm-activation-request.h" #define NM_TYPE_VPN_SERVICE (nm_vpn_service_get_type ()) #define NM_VPN_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VPN_SERVICE, NMVPNService)) @@ -57,7 +56,6 @@ const char *nm_vpn_service_get_name_file (NMVPNService *service); NMVPNConnection * nm_vpn_service_activate (NMVPNService *service, NMConnection *connection, - NMActRequest *act_request, NMDevice *device, GError **error); |