diff --git a/ChangeLog b/ChangeLog index 27cdff8de..d6862439a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2004-10-23 Dan Williams + + * info-daemon/NetworkManagerInfoDbus.c + - Trap the "DeviceActivationFailed" signal + + * docs/NetworkManager DBUS API.txt + - Add "DeviceActivationFailed" signal + + * panel-applet/NMWirelessAppletDbus.c + - Quash the "NetworkManager service not available" message + + * src/NetworkManagerDbus.[ch] + - Add the "DeviceActivationFailed" signal + + * src/NetworkManagerDevice.c + - Add support for activation_failed flag + - Fix deadlock where activation thread didn't clean itself up, making + main thread still believe it was alive forever (didn't reset activation + flags like activating, just_activated, etc when IP configuration + failed) + + * src/NetworkManagerPolicy.c + - Implement logic for DeviceActivationFailed signal, and when activation fails + for wireless networks, try to fall back to some other access point + 2004-10-23 Dan Williams * panel-applet/NMWirelessApplet.[ch] diff --git a/docs/NetworkManager DBUS API.txt b/docs/NetworkManager DBUS API.txt index b8ede6195..7a7c9e8d6 100644 --- a/docs/NetworkManager DBUS API.txt +++ b/docs/NetworkManager DBUS API.txt @@ -65,6 +65,10 @@ Signals: Name: DevicesChanged Signals that a device was either added or removed from the system Args: 1) Device object (DBUS_TYPE_STRING) - The device which was added or removed + Name: DeviceActivationFailed Signals that activation for a device could not complete (dhcp failed or so) + Args: 1) Device object (DBUS_TYPE_STRING) - The device for which activation failed + 2) Network name (DBUS_TYPE_STRING, optional) - ESSID of failed wireless network + NOTE: the following 3 Signals are likely to change in the near future Name: DeviceIP4AddressChange Signals that a device's IPv4 address was changed diff --git a/info-daemon/NetworkManagerInfoDbus.c b/info-daemon/NetworkManagerInfoDbus.c index c8feec346..a047e8a9d 100644 --- a/info-daemon/NetworkManagerInfoDbus.c +++ b/info-daemon/NetworkManagerInfoDbus.c @@ -32,6 +32,29 @@ #include "NetworkManagerInfoPassphraseDialog.h" +/* + * nmi_show_warning_dialog + * + * pop up a warning or error dialog with certain text + * + */ +static void nmi_show_warning_dialog (gboolean error, gchar *mesg, ...) +{ + GtkWidget *dialog; + char *tmp; + va_list ap; + + va_start (ap,mesg); + tmp = g_strdup_vprintf (mesg,ap); + dialog = gtk_message_dialog_new (NULL, 0, error ? GTK_MESSAGE_ERROR : GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, mesg, NULL); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + g_free (tmp); + va_end (ap); +} + + /* * nmi_network_type_valid * @@ -629,7 +652,34 @@ static DBusHandlerResult nmi_dbus_filter (DBusConnection *connection, DBusMessag if (dbus_error_is_set (&error)) dbus_error_free (&error); + } + else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceActivationFailed")) + { + char *dev = NULL; + char *net = NULL; + DBusError error; + dbus_error_init (&error); + if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &dev, DBUS_TYPE_STRING, &net, DBUS_TYPE_INVALID)) + { + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + dbus_error_init (&error); + dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &dev, DBUS_TYPE_INVALID); + } + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + if (dev && net) + { + char *string = g_strdup_printf ("Connection to the wireless network '%s' failed.\n", net); + nmi_show_warning_dialog (TRUE, string); + g_free (string); + } + else if (dev) + nmi_show_warning_dialog (TRUE, "Connection to the wired network failed.\n"); + + dbus_free (dev); + dbus_free (net); } if (appeared || disappeared) diff --git a/panel-applet/NMWirelessAppletDbus.c b/panel-applet/NMWirelessAppletDbus.c index aeaa7f95d..d24868f37 100644 --- a/panel-applet/NMWirelessAppletDbus.c +++ b/panel-applet/NMWirelessAppletDbus.c @@ -93,7 +93,7 @@ static int nmwa_dbus_call_nm_method (DBusConnection *con, const char *path, cons else if (!strcmp (error.name, NM_DBUS_NO_NETWORKS_ERROR)) ret = RETURN_SUCCESS; - if (ret != RETURN_SUCCESS) + if ((ret != RETURN_SUCCESS) && (ret != RETURN_NO_NM)) fprintf (stderr, "nmwa_dbus_call_nm_method(): %s raised:\n %s\n\n", error.name, error.message); dbus_error_free (&error); diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c index 79e7d1c84..cd4849e36 100644 --- a/src/NetworkManagerDbus.c +++ b/src/NetworkManagerDbus.c @@ -402,6 +402,7 @@ void nm_dbus_signal_device_status_change (DBusConnection *connection, NMDevice * DBusMessage *message; unsigned char *dev_path; unsigned char *signal = NULL; + NMAccessPoint *ap = NULL; g_return_if_fail (connection != NULL); g_return_if_fail (dev != NULL); @@ -423,6 +424,9 @@ void nm_dbus_signal_device_status_change (DBusConnection *connection, NMDevice * case (DEVICE_LIST_CHANGE): signal = "DevicesChanged"; break; + case (DEVICE_ACTIVATION_FAILED): + signal = "DeviceActivationFailed"; + break; default: syslog (LOG_ERR, "nm_dbus_signal_device_status_change(): got a bad signal name"); return; @@ -435,7 +439,13 @@ void nm_dbus_signal_device_status_change (DBusConnection *connection, NMDevice * return; } - dbus_message_append_args (message, DBUS_TYPE_STRING, dev_path, DBUS_TYPE_INVALID); + if ((status == DEVICE_ACTIVATION_FAILED) && nm_device_is_wireless (dev)) + ap = nm_device_get_best_ap (dev); + /* If the device was wireless, attach the name of the wireless network that failed to activate */ + if (ap && nm_ap_get_essid (ap)) + dbus_message_append_args (message, DBUS_TYPE_STRING, dev_path, DBUS_TYPE_STRING, nm_ap_get_essid (ap), DBUS_TYPE_INVALID); + else + dbus_message_append_args (message, DBUS_TYPE_STRING, dev_path, DBUS_TYPE_INVALID); g_free (dev_path); if (!dbus_connection_send (connection, message, NULL)) diff --git a/src/NetworkManagerDbus.h b/src/NetworkManagerDbus.h index 008229922..cd6cebda6 100644 --- a/src/NetworkManagerDbus.h +++ b/src/NetworkManagerDbus.h @@ -34,6 +34,7 @@ typedef enum DEVICE_NOW_ACTIVE, DEVICE_NO_LONGER_ACTIVE, DEVICE_ACTIVATING, + DEVICE_ACTIVATION_FAILED, DEVICE_LIST_CHANGE } DeviceStatus; diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c index f1e0c18cb..f081363ea 100644 --- a/src/NetworkManagerDevice.c +++ b/src/NetworkManagerDevice.c @@ -121,6 +121,7 @@ struct NMDevice gboolean activating; /* Set by main thread before beginning activation */ gboolean just_activated; /* Set by activation thread after successful activation */ gboolean quit_activation; /* Flag to signal activation thread to stop activating */ + gboolean activation_failed; /* Did the activation fail? */ gboolean test_device; gboolean test_device_up; @@ -812,7 +813,7 @@ void nm_device_set_enc_key (NMDevice *dev, const char *key) keylen = iw_in_key_full(iwlib_socket, nm_device_get_iface (dev), safe_key, &parsed_key[0], &wreq.u.data.flags); if (keylen > 0) { - wreq.u.data.flags |= IW_ENCODE_RESTRICTED; // FIXME: what about restricted/Shared Key? + wreq.u.data.flags |= IW_ENCODE_RESTRICTED; /* FIXME: what about restricted/Shared Key? */ wreq.u.data.pointer = (caddr_t) &parsed_key; wreq.u.data.length = keylen; set_key = TRUE; @@ -997,7 +998,7 @@ void nm_device_update_ip4_address (NMDevice *dev) if (socket < 0) return; - strncpy ((char *)(&req.ifr_name), nm_device_get_iface (dev), 16); // 16 == IF_NAMESIZE + strncpy ((char *)(&req.ifr_name), nm_device_get_iface (dev), 16); /* 16 == IF_NAMESIZE */ err = ioctl (socket, SIOCGIFADDR, &req); close (socket); if (err != 0) @@ -1197,7 +1198,7 @@ gboolean nm_device_activation_begin (NMDevice *dev) NMData *data = (NMData *)dev->app_data; g_return_val_if_fail (dev != NULL, FALSE); - g_return_val_if_fail (!dev->activating, TRUE); // Return if activation has already begun + g_return_val_if_fail (!dev->activating, TRUE); /* Return if activation has already begun */ g_return_val_if_fail (data != NULL, FALSE); /* Ref the device so it doesn't go away while worker function is active */ @@ -1227,6 +1228,7 @@ gboolean nm_device_activation_begin (NMDevice *dev) dev->activating = TRUE; dev->just_activated = FALSE; dev->quit_activation = FALSE; + dev->activation_failed = FALSE; if (nm_device_is_wireless (dev)) { dev->options.wireless.now_scanning = FALSE; @@ -1263,6 +1265,8 @@ static gboolean nm_device_activation_should_cancel (NMDevice *dev) syslog (LOG_DEBUG, "nm_device_activation_worker(%s): activation canceled.", nm_device_get_iface (dev)); dev->activating = FALSE; dev->just_activated = FALSE; + dev->activation_failed = TRUE; + dev->quit_activation = FALSE; return (TRUE); } @@ -1520,10 +1524,7 @@ static gpointer nm_device_activation_worker (gpointer user_data) /* If we were told to quit activation, stop the thread and return */ if (nm_device_activation_should_cancel (dev)) - { - nm_device_unref (dev); - return (NULL); - } + goto out; syslog (LOG_DEBUG, "nm_device_activation_worker(%s): using ESSID '%s'", nm_device_get_iface (dev), nm_ap_get_essid (nm_device_get_best_ap (dev))); @@ -1555,10 +1556,16 @@ static gpointer nm_device_activation_worker (gpointer user_data) sethostname (hostname, strlen (hostname)); /* If we were told to quit activation, stop the thread and return */ - if (nm_device_activation_should_cancel (dev) || !success) + if (nm_device_activation_should_cancel (dev)) + goto out; + + if (!success) { - nm_device_unref (dev); - return (NULL); + dev->activating = FALSE; + dev->just_activated = FALSE; + dev->activation_failed = TRUE; + dev->quit_activation = FALSE; + goto out; } /* Make system aware of any new DNS settings from resolv.conf */ @@ -1567,16 +1574,18 @@ static gpointer nm_device_activation_worker (gpointer user_data) /* If we were told to quit activation, stop the thread and return */ if (nm_device_activation_should_cancel (dev)) - { - nm_device_unref (dev); - return (NULL); - } + goto out; - dev->just_activated = TRUE; - syslog (LOG_DEBUG, "nm_device_activation_worker(%s): device activated", nm_device_get_iface (dev)); nm_device_update_ip4_address (dev); + dev->just_activated = TRUE; dev->activating = FALSE; + dev->activation_failed = FALSE; + dev->quit_activation = FALSE; + + syslog (LOG_DEBUG, "nm_device_activation_worker(%s): device activated", nm_device_get_iface (dev)); + +out: nm_device_unref (dev); return (NULL); } @@ -1617,6 +1626,21 @@ gboolean nm_device_is_activating (NMDevice *dev) } +/* + * nm_device_did_activation_fail + * + * Return whether or not activation on the device failed (was cancelled or + * activation process encountered and error) + * + */ +gboolean nm_device_did_activation_fail (NMDevice *dev) +{ + g_return_val_if_fail (dev != NULL, FALSE); + + return (dev->activation_failed); +} + + /* * nm_device_activation_cancel * diff --git a/src/NetworkManagerDevice.h b/src/NetworkManagerDevice.h index 6d1c6d417..192d735db 100644 --- a/src/NetworkManagerDevice.h +++ b/src/NetworkManagerDevice.h @@ -91,6 +91,7 @@ gboolean nm_device_activation_begin (NMDevice *dev); void nm_device_activation_cancel (NMDevice *dev); gboolean nm_device_is_just_activated (NMDevice *dev); gboolean nm_device_is_activating (NMDevice *dev); +gboolean nm_device_did_activation_fail (NMDevice *dev); gboolean nm_device_deactivate (NMDevice *dev, gboolean just_added); gboolean nm_device_is_scanning (NMDevice *dev); diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index 15d528b86..2e5e94847 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -350,6 +350,26 @@ gboolean nm_state_modification_monitor (gpointer user_data) nm_dbus_signal_device_status_change (data->dbus_connection, data->active_device, DEVICE_NOW_ACTIVE); syslog (LOG_INFO, "nm_state_modification_monitor() activated device %s", nm_device_get_iface (data->active_device)); } + else if (data->active_device && nm_device_did_activation_fail (data->active_device)) + { + NMAccessPoint *ap = NULL; + nm_dbus_signal_device_status_change (data->dbus_connection, data->active_device, DEVICE_ACTIVATION_FAILED); + if (nm_device_is_wireless (data->active_device)) + { + ap = nm_device_get_best_ap (data->active_device); + nm_ap_ref (ap); + /* Add the AP to the invalid list and force a best ap update */ + nm_ap_list_append_ap (data->invalid_ap_list, ap); + nm_device_update_best_ap (data->active_device); + } + if (ap && nm_ap_get_essid (ap)) + syslog (LOG_INFO, "nm_state_modification_monitor() failed to activate device %s (%s)", nm_device_get_iface (data->active_device), nm_ap_get_essid (ap)); + else + syslog (LOG_INFO, "nm_state_modification_monitor() failed to activate device %s", nm_device_get_iface (data->active_device)); + nm_data_mark_state_changed (data); + if (ap) + nm_ap_unref (ap); + } /* Clear the starting up flag, so we will now take over and have our way with * any device we find out about.