summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author(no author) <(no author)>2005-06-18 04:47:23 +0000
committer(no author) <(no author)@4912f4e0-d625-0410-9fb7-b9a5a253dbdc>2005-06-18 04:47:23 +0000
commitb450082c16a69ea94b205e36efc938fb3c5c0acf (patch)
tree31a638bff327c7d578078679798ba5d8f454e6b0
parent68bcb9cceb5d87c2776e91efb680f9441ac92aa0 (diff)
This commit was manufactured by cvs2svn to create tagSTABLE_0_3_5_RELEASE
'STABLE_0_3_5_RELEASE'. git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/tags/STABLE_0_3_5_RELEASE@717 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
-rw-r--r--ChangeLog310
-rw-r--r--NetworkManager.h18
-rw-r--r--configure.in4
-rw-r--r--dhcpcd/client.c16
-rw-r--r--dhcpcd/dhcpcd.c2
-rw-r--r--info-daemon/NetworkManagerInfo.c64
-rw-r--r--info-daemon/NetworkManagerInfo.h3
-rw-r--r--info-daemon/NetworkManagerInfoDbus.c56
-rw-r--r--info-daemon/NetworkManagerInfoDbus.h2
-rw-r--r--initscript/RedHat/Makefile.am2
-rwxr-xr-xinitscript/RedHat/nm-sleep.py10
-rwxr-xr-xinitscript/RedHat/nm-wake.py10
-rw-r--r--panel-applet/Makefile.am6
-rw-r--r--panel-applet/NMWirelessApplet.c410
-rw-r--r--panel-applet/NMWirelessApplet.h24
-rw-r--r--panel-applet/NMWirelessAppletDbus.c218
-rw-r--r--panel-applet/NMWirelessAppletOtherNetworkDialog.c22
-rw-r--r--panel-applet/gtkcellrendererprogress.c387
-rw-r--r--panel-applet/gtkcellrendererprogress.h79
-rw-r--r--panel-applet/gtkcellview.c1018
-rw-r--r--panel-applet/gtkcellview.h95
-rw-r--r--panel-applet/icons/Makefile.am1
-rw-r--r--panel-applet/icons/nm-no-connection.pngbin0 -> 1024 bytes
-rw-r--r--panel-applet/menu-info.c43
-rw-r--r--panel-applet/wireless-applet.glade514
-rw-r--r--po/POTFILES.in3
-rw-r--r--src/Makefile.am1
-rw-r--r--src/NetworkManager.c110
-rw-r--r--src/NetworkManagerAP.c2
-rw-r--r--src/NetworkManagerAP.h2
-rw-r--r--src/NetworkManagerAPList.c194
-rw-r--r--src/NetworkManagerAPList.h2
-rw-r--r--src/NetworkManagerDbus.c69
-rw-r--r--src/NetworkManagerDbus.h2
-rw-r--r--src/NetworkManagerDevice.c1223
-rw-r--r--src/NetworkManagerDevice.h3
-rw-r--r--src/NetworkManagerDevicePrivate.h3
-rw-r--r--src/NetworkManagerMain.h3
-rw-r--r--src/NetworkManagerPolicy.c61
-rw-r--r--src/NetworkManagerPolicy.h1
-rw-r--r--src/NetworkManagerSystem.c185
-rw-r--r--src/NetworkManagerSystem.h5
-rw-r--r--src/NetworkManagerUtils.c372
-rw-r--r--src/NetworkManagerUtils.h54
-rw-r--r--src/autoip.c22
-rw-r--r--src/backends/NetworkManagerDebian.c3
-rw-r--r--src/backends/NetworkManagerRedHat.c109
-rw-r--r--src/backends/shvar.c6
-rw-r--r--src/nm-dbus-device.c58
-rw-r--r--src/nm-dbus-nm.c91
50 files changed, 3514 insertions, 2384 deletions
diff --git a/ChangeLog b/ChangeLog
index 6e5c821d2a..31a7e7bab6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,313 @@
+2005-06-17 Dan Williams <dcbw@redhat.com>
+
+ * Tag 0.3.5 release
+
+2005-06-17 Dan Williams <dcbw@redhat.com>
+
+ * panel-applet/NMWirelessAppletDbus.c
+ - Alphabetize wireless networks in the applet menu
+
+2005-06-17 Dan Williams <dcbw@redhat.com>
+
+ Backport Wireless Scan Methods from HEAD
+
+2005-06-17 Dan Williams <dcbw@redhat.com>
+
+ Backport static IP DNS fixup patch from HEAD
+
+2005-06-17 Dan Williams <dcbw@redhat.com>
+
+ Backport Robert Love's applet beautification patch from HEAD
+
+2005-05-16 Dan Williams <dcbw@redhat.com>
+
+ * Remove unused variables
+
+2005-05-16 Dan Williams <dcbw@redhat.com>
+
+ * dhcpcd/client.c
+ - (dhcp_handle_transaction): Fix condition that may have resulted
+ in incorrect return of RET_DHCP_SUCCESS when we really timed out.
+
+2005-05-05 Dan Williams <dcbw@redhat.com>
+
+ * src/nm-dbus-nm.c: Fix misuse of a g_assert() (Colin Walters)
+
+ Patch from Bill Moss:
+ * src/NetworkManagerDevice.c:
+ - (nm_device_set_up_down): Fix return value checking of ioctl()
+ * src/NetworkManagerPolicy.c:
+ - (nm_policy_allowed_ap_list_update): Improve handling of
+ non-ESSID broadcasting access points
+ * src/NetworkManagerAPList.c:
+ - (nm_ap_list_remove_duplicate_essids):
+ (nm_ap_list_merge_scanned_ap):
+ Improve handling of non-ESSID broadcasting access points
+
+ Patch from Tom Parker:
+ * src/NetworkManagerDevice.c:
+ - Use g_thread_join() rather than spinning when shutting down
+ device worker threads
+ * src/NetworkMangaer.c:
+ - (nm_data_free): unref the signal handler GIOChannel
+ * src/NetworkManagerAPList.c
+ - (nm_ap_list_unref): don't leak the list object
+
+ Patch from Peter Jones:
+ - Remove usage of varargs so that we work on PPC too
+
+2005-04-06 Dan Williams <dcbw@redhat.com>
+
+ Add debug code for socket/file descriptor leaks. We register every socket
+ that we open (except for stuff in dhcpcd/) for tracking, and print out the
+ list of sockets that we forgot to close on shutdown. This also consolidates
+ about 4 places where we opened sockets into 1 function in NetworkManagerUtils.c
+
+2005-04-06 Dan Williams <dcbw@redhat.com>
+
+ * src/NetworkManagerAPList.[ch]
+ - (nm_ap_list_remove_ap_by_essid): new function
+
+ * src/NetworkManagerDevice.c
+ - (nm_device_wireless_force_use): remove access points from the ignore list
+ when the user forces them
+
+2005-04-06 Dan Williams <dcbw@redhat.com>
+
+ * dhcpcd/dhcpcd.c
+ - (dhcp_interface_free): fix a file descriptor leak that may have
+ caused network drivers to not unload due to refcounts > 0
+
+2005-04-04 Dan Williams <dcbw@redhat.com>
+
+ * src/NetworkManagerDevice.c:
+ - (nm_completion_scan_has_results): restore pre-completion-patch behavior
+ of only erroring after the second consecutive scan times out. Also
+ don't exit when the card requires more time than we can give it, just
+ log the event and continue.
+
+2005-04-01 Dan Williams <dcbw@redhat.com>
+
+ Perform scans during device activation, if needed. Both activation
+ and scans run in the same GMainContext. Therefore, if an access point
+ is not found by the time the device starts activation, it will not
+ be available until after activation. We now try to scan during
+ activation (in nm_wa_test) every 15s so that all available access
+ points are more likely to be found and available for the activation
+ procedure.
+
+ Also change nm_wireless_link_state_handle() to only update the "best"
+ AP if we are not forcing a device and if we are not about to change
+ state. This attempts to work around a race when forcing a device,
+ where the forced AP would get cleared out too soon by the link state
+ checking timeout in the main thread, and the activation attempt with
+ that AP would fail.
+
+2005-04-01 Dan Williams <dcbw@redhat.com>
+
+ * src/NetworkManagerAPList.c
+ - (nm_ap_list_print_members): print out MAC addresses in text for,
+ not as a hex number
+
+2005-04-01 Dan Williams <dcbw@redhat.com>
+
+ * po/POTFILES.in
+ - Update with new translatables
+
+2005-03-31 Dan Williams <dcbw@redhat.com>
+
+ Tighten up handling of wireless devices that don't support wireless
+ scanning (ie, Orinoco). Due to restructuring of code, these devices
+ hadn't been doing pseudo-scanning for a while either and would just
+ spin waiting for an access point. They are now manual devices where
+ the user must choose the access point from the menu every time. All
+ "allowed" access points are listed in the applet's menu regardless
+ of whether or not they can be seen by the card, since it can't scan
+ anyway.
+
+ * src/NetworkManager.c
+ - (nm_wireless_link_state_handle): new function, but only update
+ the "best" ap for non-scanning devices when its not activating,
+ and when no device is being forced on the card
+ - (nm_link_state_monitor): split wireless link state handling out
+ into separate function
+
+ * src/NetworkManagerDevice.c
+ - (nm_device_copy_allowed_to_dev_list): new function
+ - (nm_device_new): populate non-scanning cards' AP lists with
+ access points from the "allowed" list
+ - (nm_device_new): don't start a scanning timeout for devices that
+ can't scan
+ - (nm_device_activation_schedule_finish): new parameter, should be
+ the AP that failed to be connected to, pass it on to the
+ activation finish function in NetworkManagerPolicy.c
+ - (nm_device_activate_wireless): don't ever try to get a new AP
+ for non-scanning devices, just fail. The user must choose
+ a new access point manually.
+ - (nm_device_activate): grab the AP that failed connection and
+ pass it on
+ - (nm_device_update_best_ap): Clear the best AP if we don't have
+ a link to it, user must manually choose a new one
+ - (nm_device_do_pseudo_scan): remove function
+ - (nm_device_wireless_process_scan_results): remove bits for non-
+ scanning cards since they never get here
+ - (nm_device_wireless_scan): remove bits for non-scanning devices,
+ and fake the scan list for test devices a bit earlier
+
+ * src/NetworkManagerPolicy.c
+ - (nm_policy_activation_finish): use the failed_ap that we get
+ passed rather than getting the best_ap from the card, which
+ may have changed since we were scheduled
+ - (nm_policy_allowed_ap_list_update): for non-scanning devices,
+ update their scan list directly from the allowed list when
+ we get updates to the allowed list from NetworkManagerInfo
+
+ * src/NetworkManagerPolicy.h
+ - New member for failed access point in NMActivationResult
+
+2005-03-31 Dan Williams <dcbw@redhat.com>
+
+ * src/NetworkManagerDevice.c
+ - (nm_device_wireless_scan): Fix leak of scan results in some
+ instances
+
+2005-03-29 Dan Williams <dcbw@redhat.com>
+
+ * src/NetworkManagerDevice.c
+ - (nm_device_set_essid): Work around Orinoco cards which need
+ extra time after setting the ESSID
+
+2005-03-29 Dan Williams <dcbw@redhat.com>
+
+ * src/NetworkManagerDevice.c
+ - Merge one more bit of Peter Jones' completion patch
+
+2005-03-29 Dan Williams <dcbw@redhat.com>
+
+ * src/NetworkManagerDevice.c
+ - (nm_device_force_use): Fix possible segfault
+
+2005-03-29 Dan Williams <dcbw@redhat.com>
+
+ * src/NetworkManagerDevice.c
+ - Use iw_get_ext() where we should rather than iw_set_ext()
+
+2005-03-29 Dan Williams <dcbw@redhat.com>
+
+ * src/NetworkManagerDevice.c
+ - (nm_device_set_up_down): remove check for unsupported devices
+ that caused NM to not bring devices up when they were
+ added to the device list.
+
+2005-03-28 Dan Williams <dcbw@redhat.com>
+
+ Driver Notification patch: notifies the user when their driver
+ sucks. Gives them the option to ignore further insertions
+ of the card that has the sucky driver.
+
+ * NetworkManager.h
+ - Remove the SEMI_SUPPORTED member from the NMDriverSupportLevel
+ enum and replace it with NO_CARRIER_DETECT and
+ NO_WIRELESS_SCAN
+
+ * panel-applet/NMWirelessApplet.[ch]
+ - Merge essid.glade -> wireless-applet.glade
+ - Implement the "Your driver sucks" notification dialog
+
+ * panel-applet/NMWirelessAppletDbus.c
+ - Change stuff from getSupportsCarrierDetect->getDriverSupportLevel
+ - Grab hardware address for each device from NM too
+ - Check whether the driver for each device sucks or not whenever
+ a new device is noticed
+
+ * panel-applet/NMWirelessAppletOtherNetworkDialog.c
+ - Deal with stuff being in wireless-applet.glade now rather than essid.glade
+
+ * src/NetworkManager.c
+ - Fix a double-unref on device removal
+
+ * src/NetworkManagerUtils.c
+ - Set appropriate driver support level on a device that doesn't
+ support scanning or carrier detection
+
+ * src/nm-dbus-device.c
+ - New "getHWAddress" dbus method on devices
+ - getSupportsCarrierDetect -> getDriverSupportLevel
+
+2005-03-28 Dan Williams <dcbw@redhat.com>
+
+ Merge sleep functionality from HEAD
+
+ * panel-applet/NMWirelessApplet.c
+ - Applet now sticks around when there is no connection
+ - Hook up the "Stop/Start all wireless devices" function
+
+ * src/NetworkManager.c
+ - Don't perform wireless link state updates when asleep or
+ when wireless devices are stopped
+
+ * src/NetworkManagerDbus.c
+ - New "status" value: "asleep"
+
+ * src/NetworkManagerDevice.c
+ - Don't do wireless scans when asleep
+
+ * src/NetworkManagerPolicy.c
+ - When asleep, return no "best" device
+
+ * src/nm-dbus-nm.c
+ - New sleep/wake dbus APIs
+ - Actually hook up the wireless enable stuff so that stopping
+ all wireless devices works
+
+2005-03-28 Dan Williams <dcbw@redhat.com>
+
+ * Merge Peter Jones' completion patch, reducing latency and speeding
+ up wait times for device activation and wireless scanning
+
+2005-03-28 Dan Williams <dcbw@redhat.com>
+
+ Patch from Bill Moss:
+ * src/NetworkManagerPolicy.c
+ - (nm_policy_allowed_ap_list_update): merge properties
+ for all wireless devices on update, not just active device
+
+2005-03-28 Dan Williams <dcbw@redhat.com>
+
+ * panel-applet/NMWirelessApplet.c
+ - Add some more contributors to the About dialog
+
+2005-03-28 Dan Williams <dcbw@redhat.com>
+
+ * src/NetworkManagerDevice.c
+ - (mdio_read): Fix two bugs that caused all devices to fail
+ the MII carrier detection support checks
+
+2005-03-22 Dan Williams <dcbw@redhat.com>
+
+ Patch from Bill Moss:
+ * src/NetworkManagerInfoDbus.c
+ - (nmi_dbus_update_network_auth_method, nmi_dbus_get_network_properties):
+ free leaked GConf values
+
+2005-03-12 Dan Williams <dcbw@redhat.com>
+
+ Patch from Nathaniel McCallum:
+ * src/NetworkManagerDevice.c
+ - (nm_device_set_wireless_config): Increase timeout for some devices
+
+2005-03-04 Dan Williams <dcbw@redhat.com>
+
+ Patch from Peter Jones:
+ - Make stuff work with gcc 4.0
+
+2005-02-28 Dan Williams <dcbw@redhat.com>
+
+ Tag STABLE_0_3_4_RELEASE
+
+ * configure.in:
+ - Bump version to 0.3.4
+
2005-02-27 Jim Huang <jserv@kaffe.org>
* configure.in: Added "zh_TW" (Traditional Chinese) to ALL_LINGUAS.
diff --git a/NetworkManager.h b/NetworkManager.h
index 992849f91f..10c19f412e 100644
--- a/NetworkManager.h
+++ b/NetworkManager.h
@@ -78,7 +78,8 @@ typedef enum NMEncKeyType
typedef enum NMDriverSupportLevel
{
NM_DRIVER_UNSUPPORTED = 0,
- NM_DRIVER_SEMI_SUPPORTED,
+ NM_DRIVER_NO_CARRIER_DETECT,
+ NM_DRIVER_NO_WIRELESS_SCAN,
NM_DRIVER_FULLY_SUPPORTED
} NMDriverSupportLevel;
@@ -132,6 +133,19 @@ typedef enum NMDeviceAuthMethod
/*
* Info-daemon specific preference locations
*/
-#define NMI_GCONF_WIRELESS_NETWORKS_PATH "/system/networking/wireless/networks"
+#define NMI_GCONF_WIRELESS_NETWORKS_PATH "/system/networking/wireless/networks"
+#define NMI_GCONF_WIRELESS_PATH "/system/networking/wireless"
+
+/*
+ * Wireless scanning methods
+ *
+ */
+typedef enum NMWirelessScanMethod
+{
+ NM_SCAN_METHOD_UNKNOWN = 0,
+ NM_SCAN_METHOD_ALWAYS,
+ NM_SCAN_METHOD_NEVER,
+ NM_SCAN_METHOD_WHEN_UNASSOCIATED
+} NMWirelessScanMethod;
#endif
diff --git a/configure.in b/configure.in
index f64b7c44f5..ca76908aec 100644
--- a/configure.in
+++ b/configure.in
@@ -1,6 +1,6 @@
AC_PREREQ(2.52)
-AC_INIT(NetworkManager, 0.3.3, dcbw@redhat.com, NetworkManager)
+AC_INIT(NetworkManager, 0.3.5, dcbw@redhat.com, NetworkManager)
AM_INIT_AUTOMAKE([subdir-objects])
AM_MAINTAINER_MODE
@@ -243,7 +243,7 @@ if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then
AC_MSG_RESULT(yes)
CFLAGS="-Wall -Werror -std=gnu89 $CFLAGS"
- for option in -Wno-unused -Wno-strict-aliasing -Wno-sign-compare -Wdeclaration-after-statement; do
+ for option in -Wno-unused -Wno-strict-aliasing -Wno-sign-compare -Wdeclaration-after-statement -Wno-pointer-sign ; do
SAVE_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $option"
AC_MSG_CHECKING([whether gcc understands $option])
diff --git a/dhcpcd/client.c b/dhcpcd/client.c
index 2c55b3a980..dbf796b630 100644
--- a/dhcpcd/client.c
+++ b/dhcpcd/client.c
@@ -492,8 +492,8 @@ int dhcp_handle_transaction (dhcp_interface *iface, unsigned int expected_reply_
char foobuf[512];
struct sockaddr_ll server_hw_addr;
int data_good = 0;
- int min_data_len = (sizeof (struct iphdr) + sizeof (struct udphdr));
-
+ int min_data_len = (sizeof (struct iphdr) + sizeof (struct udphdr));
+ int int_err = RET_DHCP_TIMEOUT;
if (iface->cease)
goto out;
@@ -513,11 +513,11 @@ int dhcp_handle_transaction (dhcp_interface *iface, unsigned int expected_reply_
memset (&addr, 0, sizeof (struct sockaddr));
memcpy (addr.sa_data, iface->iface, strlen (iface->iface));
- err = sendto (iface->sk, udp_send, udp_send_len, MSG_DONTWAIT, (struct sockaddr *)&addr, sizeof (struct sockaddr));
- if (iface->cease || ((err == -1) && (errno != EAGAIN)))
+ int_err = sendto (iface->sk, udp_send, udp_send_len, MSG_DONTWAIT, (struct sockaddr *)&addr, sizeof (struct sockaddr));
+ if (iface->cease || ((int_err == -1) && (errno != EAGAIN)))
{
#ifdef DEBUG
- syslog (LOG_INFO, "DHCP: error sending, cease = %d, err = %d, errno = %d", iface->cease, err, errno);
+ syslog (LOG_INFO, "DHCP: error sending, cease = %d, err = %d, errno = %d", iface->cease, int_err, errno);
#endif
err = iface->cease ? RET_DHCP_CEASED : RET_DHCP_ERROR;
goto out;
@@ -530,7 +530,7 @@ int dhcp_handle_transaction (dhcp_interface *iface, unsigned int expected_reply_
err = RET_DHCP_TIMEOUT;
goto out;
}
- } while ((err == -1) && (errno == EAGAIN));
+ } while ((int_err == -1) && (errno == EAGAIN));
/* Set up the future time at which point to stop waiting for data
* on our socket and try the request again. If that future point is
@@ -559,9 +559,9 @@ int dhcp_handle_transaction (dhcp_interface *iface, unsigned int expected_reply_
char ethPacket[ETH_FRAME_LEN];
/* Wait for some kind of data to appear on the socket */
- if ((err = peekfd (iface, recv_sk, min_data_len, &recv_end)) != RET_DHCP_SUCCESS)
+ if ((int_err = peekfd (iface, recv_sk, min_data_len, &recv_end)) != RET_DHCP_SUCCESS)
{
- if (err == RET_DHCP_TIMEOUT)
+ if (int_err == RET_DHCP_TIMEOUT)
break;
goto out;
}
diff --git a/dhcpcd/dhcpcd.c b/dhcpcd/dhcpcd.c
index e56c2da38c..ecf4b7677a 100644
--- a/dhcpcd/dhcpcd.c
+++ b/dhcpcd/dhcpcd.c
@@ -245,6 +245,8 @@ void dhcp_interface_free (dhcp_interface *iface)
if (iface->foo_sk >= 0)
close (iface->foo_sk);
+ if (iface->sk)
+ close (iface->sk);
free (iface->iface);
free (iface->client_options);
free (iface);
diff --git a/info-daemon/NetworkManagerInfo.c b/info-daemon/NetworkManagerInfo.c
index 02666bfa4e..f214a021fd 100644
--- a/info-daemon/NetworkManagerInfo.c
+++ b/info-daemon/NetworkManagerInfo.c
@@ -47,13 +47,45 @@
static void nmi_spawn_notification_icon (NMIAppInfo *info);
+
+/*
+ * nmi_gconf_get_wireless_scan_method
+ *
+ * Grab the wireless scan method from GConf
+ *
+ */
+NMWirelessScanMethod nmi_gconf_get_wireless_scan_method (NMIAppInfo *info)
+{
+ NMWirelessScanMethod method = NM_SCAN_METHOD_ALWAYS;
+ GConfEntry * entry;
+
+ g_return_val_if_fail (info, NM_SCAN_METHOD_ALWAYS);
+ g_return_val_if_fail (info->gconf_client, NM_SCAN_METHOD_ALWAYS);
+
+ if ((entry = gconf_client_get_entry (info->gconf_client, NMI_GCONF_WIRELESS_PATH "/scan_method", NULL, TRUE, NULL)))
+ {
+ GConfValue * value = gconf_entry_get_value (entry);
+
+ if (value && (value->type == GCONF_VALUE_INT))
+ {
+ NMWirelessScanMethod temp_method = gconf_value_get_int (value);
+
+ if ((method == NM_SCAN_METHOD_ALWAYS) || (method == NM_SCAN_METHOD_NEVER) || (method == NM_SCAN_METHOD_WHEN_UNASSOCIATED))
+ method = temp_method;
+ }
+ }
+
+ return method;
+}
+
+
/*
- * nmi_gconf_notify_callback
+ * nmi_gconf_prefs_notify_callback
*
- * Callback from gconf when wireless networking key/values have changed.
+ * Callback from gconf when wireless key/values have changed.
*
*/
-void nmi_gconf_notify_callback (GConfClient *client, guint connection_id, GConfEntry *entry, gpointer user_data)
+void nmi_gconf_prefs_notify_callback (GConfClient *client, guint connection_id, GConfEntry *entry, gpointer user_data)
{
NMIAppInfo *info = (NMIAppInfo *)user_data;
const char *key = NULL;
@@ -64,11 +96,23 @@ void nmi_gconf_notify_callback (GConfClient *client, guint connection_id, GConfE
if ((key = gconf_entry_get_key (entry)))
{
- int path_len = strlen (NMI_GCONF_WIRELESS_NETWORKS_PATH) + 1;
+ int net_path_len = strlen (NMI_GCONF_WIRELESS_PATH) + 1;
+
+ if (strcmp (NMI_GCONF_WIRELESS_PATH "/scan_method", key) == 0)
+ {
+ GConfValue * value = gconf_entry_get_value (entry);
- if (strncmp (NMI_GCONF_WIRELESS_NETWORKS_PATH"/", key, path_len) == 0)
+ if (value && (value->type == GCONF_VALUE_INT))
+ {
+ NMWirelessScanMethod method = gconf_value_get_int (value);
+
+ if ((method == NM_SCAN_METHOD_ALWAYS) || (method == NM_SCAN_METHOD_NEVER) || (method == NM_SCAN_METHOD_WHEN_UNASSOCIATED))
+ nmi_dbus_signal_update_scan_method (info->connection);
+ }
+ }
+ if (strncmp (NMI_GCONF_WIRELESS_NETWORKS_PATH"/", key, net_path_len) == 0)
{
- char *network = g_strdup ((key + path_len));
+ char *network = g_strdup ((key + net_path_len));
char *slash_pos;
char *unescaped_network;
@@ -178,7 +222,6 @@ int main( int argc, char *argv[] )
DBusConnection *dbus_connection;
int err;
NMIAppInfo *app_info = NULL;
- GMainLoop *loop;
guint notify_id;
struct poptOption options[] =
@@ -235,10 +278,9 @@ int main( int argc, char *argv[] )
* get change notifications for our wireless networking data.
*/
app_info->gconf_client = gconf_client_get_default ();
- gconf_client_add_dir (app_info->gconf_client, NMI_GCONF_WIRELESS_NETWORKS_PATH,
- GCONF_CLIENT_PRELOAD_NONE, NULL);
- notify_id = gconf_client_notify_add (app_info->gconf_client, NMI_GCONF_WIRELESS_NETWORKS_PATH,
- nmi_gconf_notify_callback, app_info, NULL, NULL);
+ gconf_client_add_dir (app_info->gconf_client, NMI_GCONF_WIRELESS_PATH, GCONF_CLIENT_PRELOAD_NONE, NULL);
+ notify_id = gconf_client_notify_add (app_info->gconf_client, NMI_GCONF_WIRELESS_PATH,
+ nmi_gconf_prefs_notify_callback, app_info, NULL, NULL);
/* Create our own dbus service */
err = nmi_dbus_service_init (dbus_connection, app_info);
diff --git a/info-daemon/NetworkManagerInfo.h b/info-daemon/NetworkManagerInfo.h
index 4b1845a101..2c51636557 100644
--- a/info-daemon/NetworkManagerInfo.h
+++ b/info-daemon/NetworkManagerInfo.h
@@ -31,6 +31,7 @@
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <gconf/gconf-client.h>
+#include "NetworkManager.h"
struct NMIAppInfo
{
@@ -58,4 +59,6 @@ struct NMIAppInfo
};
typedef struct NMIAppInfo NMIAppInfo;
+NMWirelessScanMethod nmi_gconf_get_wireless_scan_method (NMIAppInfo *info);
+
#endif
diff --git a/info-daemon/NetworkManagerInfoDbus.c b/info-daemon/NetworkManagerInfoDbus.c
index 1cd5123754..fc12adc6cf 100644
--- a/info-daemon/NetworkManagerInfoDbus.c
+++ b/info-daemon/NetworkManagerInfoDbus.c
@@ -222,6 +222,55 @@ void nmi_dbus_return_vpn_password (DBusConnection *connection, DBusMessage *mess
}
/*
+ * nmi_dbus_signal_update_scan_method
+ *
+ * Signal NetworkManager that it needs to update its wireless scanning method
+ *
+ */
+void nmi_dbus_signal_update_scan_method (DBusConnection *connection)
+{
+ DBusMessage *message;
+
+ g_return_if_fail (connection != NULL);
+
+ message = dbus_message_new_signal (NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "WirelessScanMethodUpdate");
+ if (!message)
+ {
+ syslog (LOG_WARNING, "nmi_dbus_signal_update_scan_method(): Not enough memory for new dbus message!");
+ return;
+ }
+
+ if (!dbus_connection_send (connection, message, NULL))
+ syslog (LOG_WARNING, "nmi_dbus_signal_update_scan_method(): Could not raise the 'WirelessScanMethodUpdate' signal!");
+
+ dbus_message_unref (message);
+}
+
+
+/*
+ * nmi_dbus_get_wireless_scan_method
+ *
+ * Tell NetworkManager what wireless scanning method it should use
+ *
+ */
+static DBusMessage *nmi_dbus_get_wireless_scan_method (NMIAppInfo *info, DBusMessage *message)
+{
+ DBusMessage * reply = NULL;
+ NMWirelessScanMethod method = NM_SCAN_METHOD_ALWAYS;
+ GConfEntry * entry;
+
+ g_return_val_if_fail (info != NULL, NULL);
+ g_return_val_if_fail (message != NULL, NULL);
+
+ method = nmi_gconf_get_wireless_scan_method (info);
+ reply = dbus_message_new_method_return (message);
+ dbus_message_append_args (reply, DBUS_TYPE_UINT32, &method, DBUS_TYPE_INVALID);
+
+ return (reply);
+}
+
+
+/*
* nmi_dbus_signal_update_network
*
* Signal NetworkManager that it needs to update info associated with a particular
@@ -486,7 +535,8 @@ static DBusMessage *nmi_dbus_get_network_properties (NMIAppInfo *info, DBusMessa
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, array, num_items,
DBUS_TYPE_INVALID);
}
- gconf_value_free (ap_addrs_value);
+ if (ap_addrs_value)
+ gconf_value_free (ap_addrs_value);
g_free (essid);
g_free (key);
@@ -538,6 +588,8 @@ static DBusMessage *nmi_dbus_update_network_auth_method (NMIAppInfo *info, DBusM
gconf_client_set_int (info->gconf_client, key, auth_method, NULL);
g_free (key);
}
+ if (value)
+ gconf_value_free (value);
g_free (escaped_network);
@@ -697,6 +749,8 @@ static DBusHandlerResult nmi_dbus_nmi_message_handler (DBusConnection *connectio
gtk_widget_destroy (GTK_WIDGET (dialog));
}
}
+ else if (strcmp ("getWirelessScanMethod", method) == 0)
+ reply_message = nmi_dbus_get_wireless_scan_method (info, message);
else if (strcmp ("getNetworks", method) == 0)
reply_message = nmi_dbus_get_networks (info, message);
else if (strcmp ("getNetworkProperties", method) == 0)
diff --git a/info-daemon/NetworkManagerInfoDbus.h b/info-daemon/NetworkManagerInfoDbus.h
index 423ca44be9..d8918f70aa 100644
--- a/info-daemon/NetworkManagerInfoDbus.h
+++ b/info-daemon/NetworkManagerInfoDbus.h
@@ -41,6 +41,8 @@ void nmi_dbus_return_user_key (DBusConnection *connection, const char *devi
void nmi_dbus_return_vpn_password (DBusConnection *connection, DBusMessage *message, const char *password);
+void nmi_dbus_signal_update_scan_method (DBusConnection *connection);
+
void nmi_dbus_signal_update_network (DBusConnection *connection, const char *network, NMNetworkType type);
#endif
diff --git a/initscript/RedHat/Makefile.am b/initscript/RedHat/Makefile.am
index 3ce9ed4a51..942b6f5eb9 100644
--- a/initscript/RedHat/Makefile.am
+++ b/initscript/RedHat/Makefile.am
@@ -1,4 +1,4 @@
-EXTRA_DIST = NetworkManager
+EXTRA_DIST = NetworkManager nm-sleep.py nm-wake.py
initddir = $(sysconfdir)/rc.d/init.d
initd_SCRIPTS = NetworkManager
diff --git a/initscript/RedHat/nm-sleep.py b/initscript/RedHat/nm-sleep.py
new file mode 100755
index 0000000000..c8d89ac9ac
--- /dev/null
+++ b/initscript/RedHat/nm-sleep.py
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+
+import dbus
+service = "org.freedesktop.NetworkManager"
+object_path = "/org/freedesktop/NetworkManager"
+interface = "org.freedesktop.NetworkManager"
+bus = dbus.Bus (dbus.Bus.TYPE_SYSTEM)
+NWM_service = bus.get_service (service)
+nm = NWM_service.get_object (object_path, interface)
+nm.sleep()
diff --git a/initscript/RedHat/nm-wake.py b/initscript/RedHat/nm-wake.py
new file mode 100755
index 0000000000..ef1059606f
--- /dev/null
+++ b/initscript/RedHat/nm-wake.py
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+
+import dbus
+service = "org.freedesktop.NetworkManager"
+object_path = "/org/freedesktop/NetworkManager"
+interface = "org.freedesktop.NetworkManager"
+bus = dbus.Bus (dbus.Bus.TYPE_SYSTEM)
+NWM_service = bus.get_service (service)
+nm = NWM_service.get_object (object_path, interface)
+nm.wake()
diff --git a/panel-applet/Makefile.am b/panel-applet/Makefile.am
index f535a374c4..c3c066fdaf 100644
--- a/panel-applet/Makefile.am
+++ b/panel-applet/Makefile.am
@@ -8,7 +8,7 @@ INCLUDES = -I${top_srcdir}
noinst_LTLIBRARIES = libnm_notification_applet.la
gladedir = $(datadir)/NetworkManagerNotification
-glade_DATA = essid.glade
+glade_DATA = wireless-applet.glade
libnm_notification_applet_la_CPPFLAGS = \
$(DBUS_CFLAGS) \
@@ -39,10 +39,6 @@ libnm_notification_applet_la_SOURCES = \
NMWirelessAppletOtherNetworkDialog.h \
menu-info.c \
menu-info.h \
- gtkcellview.c \
- gtkcellview.h \
- gtkcellrendererprogress.c \
- gtkcellrendererprogress.h \
$(NULL)
libnm_notification_applet_la_SOURCES += \
diff --git a/panel-applet/NMWirelessApplet.c b/panel-applet/NMWirelessApplet.c
index 90e6804d85..750a68d599 100644
--- a/panel-applet/NMWirelessApplet.c
+++ b/panel-applet/NMWirelessApplet.c
@@ -58,6 +58,7 @@
#include "menu-info.h"
#define CFG_UPDATE_INTERVAL 1
+#define NMWA_GCONF_PATH "/apps/NetworkManagerNotification"
/* Compat for GTK 2.4 and lower... */
#if (GTK_MAJOR_VERSION <= 2 && GTK_MINOR_VERSION < 6)
@@ -121,10 +122,16 @@ void nmwa_about_cb (NMWirelessApplet *applet)
static const gchar *authors[] =
{
"The Red Hat Desktop Team, including:\n",
- "Dan Williams <dcbw@redhat.com>",
"Jonathan Blandford <jrb@redhat.com>",
"John Palmieri <johnp@redhat.com>",
+ "Ray Strode <rstrode@redhat.com>",
"Colin Walters <walters@redhat.com>",
+ "Dan Williams <dcbw@redhat.com>",
+ "\nAnd others, including:\n",
+ "Bill Moss",
+ "Tom Parker",
+ "j@bootlab.org",
+ "Peter Jones <pjones@redhat.com>",
NULL
};
@@ -171,6 +178,279 @@ void nmwa_about_cb (NMWirelessApplet *applet)
/*
+ * nmwa_gconf_get_wireless_scan_method
+ *
+ * Grab the wireless scan method from GConf
+ *
+ */
+NMWirelessScanMethod nmwa_gconf_get_wireless_scan_method (NMWirelessApplet *applet)
+{
+ NMWirelessScanMethod method = NM_SCAN_METHOD_ALWAYS;
+ GConfEntry * entry;
+
+ g_return_val_if_fail (applet, NM_SCAN_METHOD_ALWAYS);
+ g_return_val_if_fail (applet->gconf_client, NM_SCAN_METHOD_ALWAYS);
+
+ if ((entry = gconf_client_get_entry (applet->gconf_client, NMI_GCONF_WIRELESS_PATH "/scan_method", NULL, TRUE, NULL)))
+ {
+ GConfValue * value = gconf_entry_get_value (entry);
+
+ if (value && (value->type == GCONF_VALUE_INT))
+ {
+ NMWirelessScanMethod temp_method = gconf_value_get_int (value);
+
+ if ((method == NM_SCAN_METHOD_ALWAYS) || (method == NM_SCAN_METHOD_NEVER) || (method == NM_SCAN_METHOD_WHEN_UNASSOCIATED))
+ method = temp_method;
+ }
+ }
+
+ return method;
+}
+
+
+/*
+ * nmwa_driver_notify_get_ignored_list
+ *
+ * Return list of devices for which we are supposed to ignore driver
+ * notifications for from GConf.
+ *
+ */
+GSList *nmwa_driver_notify_get_ignored_list (NMWirelessApplet *applet)
+{
+ char *key;
+ GConfValue *value;
+ GSList *mac_list = NULL;
+
+ g_return_val_if_fail (applet != NULL, NULL);
+ g_return_val_if_fail (applet->gconf_client != NULL, NULL);
+
+ /* Get current list of access point MAC addresses for this AP from GConf */
+ key = g_strdup_printf ("%s/non_notify_cards", NMWA_GCONF_PATH);
+ value = gconf_client_get (applet->gconf_client, key, NULL);
+
+ if (value && (value->type == GCONF_VALUE_LIST) && (gconf_value_get_list_type (value) == GCONF_VALUE_STRING))
+ mac_list = gconf_client_get_list (applet->gconf_client, key, GCONF_VALUE_STRING, NULL);
+
+ if (value)
+ gconf_value_free (value);
+ g_free (key);
+
+ return (mac_list);
+}
+
+
+/*
+ * nmwa_driver_notify_is_device_ignored
+ *
+ * Look in GConf and determine whether or not we are supposed to
+ * ignore driver notifications for a particular device.
+ *
+ */
+gboolean nmwa_driver_notify_is_device_ignored (NMWirelessApplet *applet, NetworkDevice *dev)
+{
+ gboolean found = FALSE;
+ GSList *mac_list = NULL;
+ GSList *elt;
+
+ g_return_val_if_fail (applet != NULL, TRUE);
+ g_return_val_if_fail (applet->gconf_client != NULL, TRUE);
+ g_return_val_if_fail (dev != NULL, TRUE);
+ g_return_val_if_fail (dev->addr != NULL, TRUE);
+ g_return_val_if_fail (strlen (dev->addr) > 0, TRUE);
+
+ mac_list = nmwa_driver_notify_get_ignored_list (applet);
+
+ /* Ensure that the MAC isn't already in the list */
+ for (elt = mac_list; elt; elt = g_slist_next (elt))
+ {
+ if (elt->data && !strcmp (dev->addr, elt->data))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ /* Free the list, since gconf_client_set_list deep-copies it */
+ g_slist_foreach (mac_list, (GFunc)g_free, NULL);
+ g_slist_free (mac_list);
+
+ return found;
+}
+
+
+/*
+ * nmwa_driver_notify_ignore_device
+ *
+ * Add a device's MAC address to the list of ones that we ignore
+ * in GConf. Stores user's pref for "Don't remind me".
+ *
+ */
+void nmwa_driver_notify_ignore_device (NMWirelessApplet *applet, NetworkDevice *dev)
+{
+ gboolean found = FALSE;
+ GSList *new_mac_list = NULL;
+ GSList *elt;
+
+ g_return_if_fail (applet != NULL);
+ g_return_if_fail (applet->gconf_client != NULL);
+ g_return_if_fail (dev != NULL);
+ g_return_if_fail (dev->addr != NULL);
+ g_return_if_fail (strlen (dev->addr) > 0);
+
+ new_mac_list = nmwa_driver_notify_get_ignored_list (applet);
+
+ /* Ensure that the MAC isn't already in the list */
+ for (elt = new_mac_list; elt; elt = g_slist_next (elt))
+ {
+ if (elt->data && !strcmp (dev->addr, elt->data))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ /* Add the new MAC address to the end of the list */
+ if (!found)
+ {
+ char *key = g_strdup_printf ("%s/non_notify_cards", NMWA_GCONF_PATH);
+
+ new_mac_list = g_slist_append (new_mac_list, g_strdup (dev->addr));
+ gconf_client_set_list (applet->gconf_client, key, GCONF_VALUE_STRING, new_mac_list, NULL);
+ g_free (key);
+ }
+
+ /* Free the list, since gconf_client_set_list deep-copies it */
+ g_slist_foreach (new_mac_list, (GFunc)g_free, NULL);
+ g_slist_free (new_mac_list);
+}
+
+gboolean nmwa_driver_notify_dialog_delete_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data)
+{
+ gtk_widget_destroy (widget);
+ return FALSE;
+}
+
+gboolean nmwa_driver_notify_dialog_destroy_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data)
+{
+ DriverNotifyCBData *cb_data = (DriverNotifyCBData *)(user_data);
+ NetworkDevice *dev;
+
+ g_return_val_if_fail (cb_data != NULL, FALSE);
+ g_return_val_if_fail (cb_data->xml != NULL, FALSE);
+
+ dev = cb_data->dev;
+ g_return_val_if_fail (dev != NULL, FALSE);
+
+ network_device_unref (dev);
+
+ g_object_unref (cb_data->xml);
+ g_free (cb_data);
+
+ return FALSE;
+}
+
+
+gboolean nmwa_driver_notify_ok_cb (GtkButton *button, gpointer user_data)
+{
+ DriverNotifyCBData *cb_data = (DriverNotifyCBData *)(user_data);
+ NetworkDevice *dev;
+ NMWirelessApplet *applet;
+ GtkWidget *dialog;
+ GtkWidget *checkbox;
+
+ g_return_val_if_fail (cb_data != NULL, FALSE);
+ g_return_val_if_fail (cb_data->xml != NULL, FALSE);
+
+ dev = cb_data->dev;
+ g_return_val_if_fail (dev != NULL, FALSE);
+
+ applet = cb_data->applet;
+ g_return_val_if_fail (applet != NULL, FALSE);
+
+ checkbox = glade_xml_get_widget (cb_data->xml, "dont_remind_checkbox");
+ if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox)))
+ nmwa_driver_notify_ignore_device (applet, dev);
+
+ dialog = glade_xml_get_widget (cb_data->xml, "driver_sucks_dialog");
+ gtk_widget_destroy (dialog);
+
+ return FALSE;
+}
+
+
+/*
+ * nmwa_driver_notify
+ *
+ * Notify the user if there's some problem with the driver
+ * of a specific network device.
+ *
+ */
+gboolean nmwa_driver_notify (gpointer user_data)
+{
+ DriverNotifyCBData *cb_data = (DriverNotifyCBData *)(user_data);
+ NetworkDevice *dev;
+ NMWirelessApplet *applet;
+ GtkDialog *dialog;
+ GtkLabel *label;
+ char *label_text = NULL;
+ GtkButton *button;
+
+ g_return_val_if_fail (cb_data != NULL, FALSE);
+
+ dev = cb_data->dev;
+ g_return_val_if_fail (dev != NULL, FALSE);
+
+ applet = cb_data->applet;
+ g_return_val_if_fail (applet != NULL, FALSE);
+ g_return_val_if_fail (applet->glade_file != NULL, FALSE);
+
+ /* If the user has already requested that we ignore notifications for
+ * this device, don't do anything.
+ */
+ if (nmwa_driver_notify_is_device_ignored (applet, dev))
+ return FALSE;
+
+ cb_data->xml = glade_xml_new (applet->glade_file, "driver_sucks_dialog", NULL);
+ if (cb_data->xml == NULL)
+ {
+ show_warning_dialog (TRUE, _("The NetworkManager Applet could not find some required resources (the glade file was not found)."));
+ return FALSE;
+ }
+
+ dialog = GTK_DIALOG (glade_xml_get_widget (cb_data->xml, "driver_sucks_dialog"));
+ g_signal_connect (G_OBJECT (dialog), "destroy-event", GTK_SIGNAL_FUNC (nmwa_driver_notify_dialog_destroy_cb), cb_data);
+ g_signal_connect (G_OBJECT (dialog), "delete-event", GTK_SIGNAL_FUNC (nmwa_driver_notify_dialog_delete_cb), cb_data);
+
+ label = GTK_LABEL (glade_xml_get_widget (cb_data->xml, "driver_sucks_label"));
+ if (dev->driver_support_level == NM_DRIVER_NO_WIRELESS_SCAN)
+ {
+ char *temp = g_strdup_printf (_("The network device \"%s (%s)\" does not support wireless scanning."),
+ dev->hal_name, dev->nm_name);
+
+ label_text = g_strdup_printf (gtk_label_get_label (label), temp);
+ g_free (temp);
+ }
+ if (dev->driver_support_level == NM_DRIVER_NO_CARRIER_DETECT)
+ {
+ char *temp = g_strdup_printf (_("The network device \"%s (%s)\" does not support link detection."),
+ dev->hal_name, dev->nm_name);
+
+ label_text = g_strdup_printf (gtk_label_get_label (label), temp);
+ g_free (temp);
+ }
+ if (label_text)
+ gtk_label_set_markup (label, label_text);
+
+ button = GTK_BUTTON (glade_xml_get_widget (cb_data->xml, "ok_button"));
+ g_signal_connect (G_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (nmwa_driver_notify_ok_cb), cb_data);
+
+ gtk_widget_show_all (GTK_WIDGET (dialog));
+
+ return (FALSE);
+}
+
+
+/*
* nmwa_update_network_state
*
* Update our state based on what NetworkManager's network state is
@@ -375,7 +655,7 @@ nmwa_update_state (NMWirelessApplet *applet)
switch (applet->applet_state)
{
case (APPLET_STATE_NO_CONNECTION):
- show_applet = FALSE;
+ pixbuf = applet->no_connection_icon;
tip = g_strdup (_("No network connection"));
break;
@@ -702,6 +982,50 @@ static void nmwa_menu_item_activate (GtkMenuItem *item, gpointer user_data)
}
+static void scanning_menu_update (GtkWidget *menu_item, GtkCheckMenuItem *active_item)
+{
+ g_return_if_fail (active_item != NULL);
+
+ g_object_set_data (G_OBJECT (menu_item), "block-activate", GINT_TO_POINTER(1));
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), (GTK_CHECK_MENU_ITEM (menu_item) == active_item) ? TRUE : FALSE);
+ g_object_set_data (G_OBJECT (menu_item), "block-activate", GINT_TO_POINTER(0));
+}
+
+
+/*
+ * nmwa_menu_scanning_item_activate
+ *
+ * Handle a request to change scanning behavior
+ *
+ */
+static void nmwa_menu_scanning_item_activate (GtkMenuItem *item, gpointer user_data)
+{
+ NMWirelessApplet * applet = (NMWirelessApplet *)user_data;
+ char * tag;
+
+ g_return_if_fail (item != NULL);
+ g_return_if_fail (applet != NULL);
+
+ if ((tag = g_object_get_data (G_OBJECT (item), "block-activate")))
+ if (GPOINTER_TO_INT(tag) == 1)
+ return;
+
+ if ((tag = g_object_get_data (G_OBJECT (item), "scan_method")))
+ {
+ NMWirelessScanMethod method = GPOINTER_TO_UINT (tag);
+
+ if ((method == NM_SCAN_METHOD_ALWAYS) || (method == NM_SCAN_METHOD_NEVER) || (method == NM_SCAN_METHOD_WHEN_UNASSOCIATED))
+ gconf_client_set_int (applet->gconf_client, NMI_GCONF_WIRELESS_PATH "/scan_method", method, NULL);
+ }
+
+ /* Check only this menu item */
+ if (!applet->scanning_menu)
+ return;
+
+ gtk_container_foreach (GTK_CONTAINER (applet->scanning_menu), (GtkCallback) scanning_menu_update, (gpointer) item);
+}
+
+
/*
* nmwa_menu_add_separator_item
*
@@ -948,18 +1272,11 @@ static void nmwa_menu_add_devices (GtkWidget *menu, NMWirelessApplet *applet)
}
-static void nmwa_set_scanning_enabled_cb (GtkWidget *widget, NMWirelessApplet *applet)
-{
- g_return_if_fail (applet != NULL);
-
- nmwa_dbus_enable_scanning (applet, !applet->scanning_enabled);
-}
-
static void nmwa_set_wireless_enabled_cb (GtkWidget *widget, NMWirelessApplet *applet)
{
g_return_if_fail (applet != NULL);
- nmwa_dbus_enable_scanning (applet, !applet->wireless_enabled);
+ nmwa_dbus_enable_wireless (applet, !applet->wireless_enabled);
}
@@ -1094,29 +1411,12 @@ static void nmwa_context_menu_update (NMWirelessApplet *applet)
GtkWidget *image;
g_return_if_fail (applet != NULL);
- g_return_if_fail (applet->pause_scanning_item != NULL);
g_return_if_fail (applet->stop_wireless_item != NULL);
g_mutex_lock (applet->data_mutex);
- gtk_widget_destroy (applet->pause_scanning_item);
gtk_widget_destroy (applet->stop_wireless_item);
- if (applet->scanning_enabled)
- {
- applet->pause_scanning_item = gtk_image_menu_item_new_with_label (_("Pause Wireless Scanning"));
- image = gtk_image_new_from_stock (GTK_STOCK_MEDIA_PAUSE, GTK_ICON_SIZE_MENU);
- }
- else
- {
- applet->pause_scanning_item = gtk_image_menu_item_new_with_label (_("Resume Wireless Scanning"));
- image = gtk_image_new_from_stock (GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU);
- }
- g_signal_connect (G_OBJECT (applet->pause_scanning_item), "activate", G_CALLBACK (nmwa_set_scanning_enabled_cb), applet);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (applet->pause_scanning_item), image);
- gtk_menu_shell_insert (GTK_MENU_SHELL (applet->context_menu), applet->pause_scanning_item, 0);
- gtk_widget_show_all (applet->pause_scanning_item);
-
if (applet->wireless_enabled)
{
applet->stop_wireless_item = gtk_image_menu_item_new_with_label (_("Stop All Wireless Devices"));
@@ -1130,7 +1430,6 @@ static void nmwa_context_menu_update (NMWirelessApplet *applet)
g_signal_connect (G_OBJECT (applet->stop_wireless_item), "activate", G_CALLBACK (nmwa_set_wireless_enabled_cb), applet);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (applet->stop_wireless_item), image);
gtk_menu_shell_insert (GTK_MENU_SHELL (applet->context_menu), applet->stop_wireless_item, 1);
- gtk_widget_set_sensitive (GTK_WIDGET (applet->stop_wireless_item), FALSE);
gtk_widget_show_all (applet->stop_wireless_item);
g_mutex_unlock (applet->data_mutex);
@@ -1148,26 +1447,49 @@ static GtkWidget *nmwa_context_menu_create (NMWirelessApplet *applet)
GtkWidget *menu;
GtkWidget *menu_item;
GtkWidget *image;
+ GtkWidget *scanning_subitem;
g_return_val_if_fail (applet != NULL, NULL);
menu = gtk_menu_new ();
- applet->pause_scanning_item = gtk_image_menu_item_new_with_label (_("Pause Wireless Scanning"));
- g_signal_connect (G_OBJECT (applet->pause_scanning_item), "activate", G_CALLBACK (nmwa_set_scanning_enabled_cb), applet);
- image = gtk_image_new_from_stock (GTK_STOCK_MEDIA_PAUSE, GTK_ICON_SIZE_MENU);
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (applet->pause_scanning_item), image);
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), applet->pause_scanning_item);
-
+ /* Construct the wireless scanning submenu */
+ applet->scan_method = nmwa_gconf_get_wireless_scan_method (applet);
+ applet->scanning_item = gtk_menu_item_new_with_label (_("Wireless Network Discovery"));
+ applet->scanning_menu = gtk_menu_new ();
+
+ scanning_subitem = GTK_WIDGET (gtk_check_menu_item_new_with_label (_("Always Search")));
+ g_object_set_data (G_OBJECT (scanning_subitem), "scan_method", GUINT_TO_POINTER (NM_SCAN_METHOD_ALWAYS));
+ if (applet->scan_method == NM_SCAN_METHOD_ALWAYS)
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (scanning_subitem), TRUE);
+ g_signal_connect (G_OBJECT (scanning_subitem), "activate", G_CALLBACK (nmwa_menu_scanning_item_activate), applet);
+ gtk_menu_shell_append (GTK_MENU_SHELL (applet->scanning_menu), GTK_WIDGET (scanning_subitem));
+
+ scanning_subitem = GTK_WIDGET (gtk_check_menu_item_new_with_label (_("Seach Only When Disconnected")));
+ g_object_set_data (G_OBJECT (scanning_subitem), "scan_method", GINT_TO_POINTER (NM_SCAN_METHOD_WHEN_UNASSOCIATED));
+ if (applet->scan_method == NM_SCAN_METHOD_WHEN_UNASSOCIATED)
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (scanning_subitem), TRUE);
+ g_signal_connect (G_OBJECT (scanning_subitem), "activate", G_CALLBACK (nmwa_menu_scanning_item_activate), applet);
+ gtk_menu_shell_append (GTK_MENU_SHELL (applet->scanning_menu), GTK_WIDGET (scanning_subitem));
+
+ scanning_subitem = GTK_WIDGET (gtk_check_menu_item_new_with_label (_("Never Search")));
+ g_object_set_data (G_OBJECT (scanning_subitem), "scan_method", GINT_TO_POINTER (NM_SCAN_METHOD_NEVER));
+ if (applet->scan_method == NM_SCAN_METHOD_NEVER)
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (scanning_subitem), TRUE);
+ g_signal_connect (G_OBJECT (scanning_subitem), "activate", G_CALLBACK (nmwa_menu_scanning_item_activate), applet);
+ gtk_menu_shell_append (GTK_MENU_SHELL (applet->scanning_menu), GTK_WIDGET (scanning_subitem));
+
+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (applet->scanning_item), applet->scanning_menu);
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), applet->scanning_item);
+
+ /* Stop All Wireless Devices item */
applet->stop_wireless_item = gtk_image_menu_item_new_with_label (_("Stop All Wireless Devices"));
g_signal_connect (G_OBJECT (applet->stop_wireless_item), "activate", G_CALLBACK (nmwa_set_wireless_enabled_cb), applet);
image = gtk_image_new_from_stock (GTK_STOCK_STOP, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (applet->stop_wireless_item), image);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), applet->stop_wireless_item);
- gtk_widget_set_sensitive (GTK_WIDGET (applet->stop_wireless_item), FALSE);
- menu_item = gtk_separator_menu_item_new ();
- gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
+ nmwa_menu_add_separator_item (menu);
menu_item = gtk_image_menu_item_new_with_label (_("Help"));
/* g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (nmwa_help_cb), applet); */
@@ -1270,6 +1592,14 @@ static void nmwa_setup_widgets (NMWirelessApplet *applet)
applet->context_menu = nmwa_context_menu_create (applet);
applet->encryption_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+ applet->glade_file = g_build_filename (GLADEDIR, "wireless-applet.glade", NULL);
+ if (!applet->glade_file || !g_file_test (applet->glade_file, G_FILE_TEST_IS_REGULAR))
+ {
+ show_warning_dialog (TRUE, _("The NetworkManager Applet could not find some required resources (the glade file was not found)."));
+ g_free (applet->glade_file);
+ applet->glade_file = NULL;
+ }
}
@@ -1303,6 +1633,8 @@ static void nmwa_destroy (NMWirelessApplet *applet, gpointer user_data)
nmwa_free_gui_data_model (applet);
nmwa_free_dbus_data_model (applet);
+
+ g_free (applet->glade_file);
}
@@ -1330,6 +1662,8 @@ static GtkWidget * nmwa_get_instance (NMWirelessApplet *applet)
applet->thread_context = NULL;
applet->thread_loop = NULL;
applet->thread_done = FALSE;
+ applet->scanning_menu = NULL;
+ applet->scanning_item = NULL;
/* Start our dbus thread */
if (!(applet->data_mutex = g_mutex_new ()))
@@ -1395,6 +1729,7 @@ nmwa_icons_free (NMWirelessApplet *applet)
gint i;
g_object_unref (applet->no_nm_icon);
+ g_object_unref (applet->no_connection_icon);
g_object_unref (applet->wired_icon);
g_object_unref (applet->adhoc_icon);
for (i = 0; i < NUM_WIRED_CONNECTING_FRAMES; i++)
@@ -1417,6 +1752,7 @@ nmwa_icons_load_from_disk (NMWirelessApplet *applet, GtkIconTheme *icon_theme)
gint icon_size = 22;
applet->no_nm_icon = gtk_icon_theme_load_icon (icon_theme, "nm-device-broken", icon_size, 0, NULL);
+ applet->no_connection_icon = gtk_icon_theme_load_icon (icon_theme, "nm-no-connection", icon_size, 0, NULL);
applet->wired_icon = gtk_icon_theme_load_icon (icon_theme, "nm-device-wired", icon_size, 0, NULL);
applet->adhoc_icon = gtk_icon_theme_load_icon (icon_theme, "nm-adhoc", icon_size, 0, NULL);
applet->wired_connecting_icons[0] = gtk_icon_theme_load_icon (icon_theme, "nm-connecting01", icon_size, 0, NULL);
diff --git a/panel-applet/NMWirelessApplet.h b/panel-applet/NMWirelessApplet.h
index f039bb96e4..8447215a67 100644
--- a/panel-applet/NMWirelessApplet.h
+++ b/panel-applet/NMWirelessApplet.h
@@ -32,6 +32,8 @@
#else
#include "eggtrayicon.h"
#endif
+#include <net/ethernet.h>
+#include "NetworkManager.h"
typedef enum
{
@@ -70,7 +72,8 @@ typedef struct
char *nm_device;
int type;
gboolean link;
- gboolean supports_carrier_detect;
+ guint32 driver_support_level;
+ char *addr;
char *nm_name;
char *hal_name;
char *udi;
@@ -78,8 +81,6 @@ typedef struct
GSList *networks;
} NetworkDevice;
-
-
#ifdef BUILD_NOTIFICATION_ICON
#define NM_TYPE_WIRELESS_APPLET (nmwa_get_type())
@@ -107,8 +108,10 @@ typedef struct
DBusConnection *connection;
GConfClient *gconf_client;
- GladeXML *ui_resources;
+ char *glade_file;
guint redraw_timeout_id;
+
+ /* dbus thread stuff */
GThread *dbus_thread;
GMainContext *thread_context;
GMainLoop *thread_loop;
@@ -118,7 +121,7 @@ typedef struct
GMutex *data_mutex;
AppletState applet_state;
gboolean is_adhoc;
- gboolean scanning_enabled;
+ NMWirelessScanMethod scan_method;
gboolean wireless_enabled;
GSList *gui_device_list;
@@ -130,6 +133,7 @@ typedef struct
char *dbus_nm_status;
GdkPixbuf *no_nm_icon;
+ GdkPixbuf *no_connection_icon;
GdkPixbuf *wired_icon;
GdkPixbuf *adhoc_icon;
#define NUM_WIRED_CONNECTING_FRAMES 11
@@ -157,16 +161,24 @@ typedef struct
GtkTooltips *tooltips;
GtkWidget *context_menu;
- GtkWidget *pause_scanning_item;
+ GtkWidget *scanning_item;
+ GtkWidget *scanning_menu;
GtkWidget *stop_wireless_item;
} NMWirelessApplet;
+typedef struct
+{
+ NMWirelessApplet *applet;
+ NetworkDevice *dev;
+ GladeXML *xml;
+} DriverNotifyCBData;
NetworkDevice *nmwa_get_device_for_nm_device (GSList *dev_list, const char *nm_dev);
WirelessNetwork *nmwa_get_net_for_nm_net (NetworkDevice *dev, const char *net_path);
WirelessNetwork *nmwa_get_net_by_essid (NetworkDevice *dev, const char *essid);
NMWirelessApplet *nmwa_new (void);
void show_warning_dialog (gboolean error, gchar *mesg, ...);
+gboolean nmwa_driver_notify (gpointer user_data);
#endif
diff --git a/panel-applet/NMWirelessAppletDbus.c b/panel-applet/NMWirelessAppletDbus.c
index 9ff1d56005..4e8879e80c 100644
--- a/panel-applet/NMWirelessAppletDbus.c
+++ b/panel-applet/NMWirelessAppletDbus.c
@@ -36,6 +36,24 @@
/* dbus doesn't define a DBUS_TYPE_STRING_ARRAY so we fake one here for consistency */
#define DBUS_TYPE_STRING_ARRAY ((int) '$')
+/*
+ * nm_null_safe_strcmp
+ *
+ * Doesn't freaking segfault if s1/s2 are NULL
+ *
+ */
+int nm_null_safe_strcmp (const char *s1, const char *s2)
+{
+ if (!s1 && !s2)
+ return 0;
+ if (!s1 && s2)
+ return -1;
+ if (s1 && !s2)
+ return 1;
+
+ return (strcmp (s1, s2));
+}
+
/*
* nmwa_dbus_call_nm_method
@@ -271,7 +289,7 @@ static gboolean nmwa_dbus_get_device_link_active (NMWirelessApplet *applet, char
break;
default:
- break;
+ break;
}
return (link);
@@ -279,17 +297,17 @@ static gboolean nmwa_dbus_get_device_link_active (NMWirelessApplet *applet, char
/*
- * nmwa_dbus_get_device_supports_carrier_detect
+ * nmwa_dbus_get_device_driver_support_level
*
* Returns whether or not the device supports carrier detection.
*
*/
-static gboolean nmwa_dbus_get_device_supports_carrier_detect (NMWirelessApplet *applet, char *net_path)
+static gboolean nmwa_dbus_get_device_driver_support_level (NMWirelessApplet *applet, char *net_path)
{
- gboolean supports_carrier_detect = FALSE;
+ guint32 driver_support_level = FALSE;
- switch (nmwa_dbus_call_nm_method (applet->connection, net_path, "getSupportsCarrierDetect",
- DBUS_TYPE_BOOLEAN, (void **)(&supports_carrier_detect), NULL))
+ switch (nmwa_dbus_call_nm_method (applet->connection, net_path, "getDriverSupportLevel",
+ DBUS_TYPE_UINT32, (void **)(&driver_support_level), NULL))
{
case (RETURN_NO_NM):
applet->applet_state = APPLET_STATE_NO_NM;
@@ -299,7 +317,31 @@ static gboolean nmwa_dbus_get_device_supports_carrier_detect (NMWirelessApplet *
break;
}
- return (supports_carrier_detect);
+ return (driver_support_level);
+}
+
+
+/*
+ * nmwa_dbus_get_hw_addr
+ *
+ * Return the hardware address of a given device
+ *
+ */
+static char * nmwa_dbus_get_hw_addr (NMWirelessApplet *applet, char *dev_path)
+{
+ char *addr = NULL;
+
+ switch (nmwa_dbus_call_nm_method (applet->connection, dev_path, "getHWAddress", DBUS_TYPE_STRING, (void **)(&addr), NULL))
+ {
+ case (RETURN_NO_NM):
+ applet->applet_state = APPLET_STATE_NO_NM;
+ break;
+
+ default:
+ break;
+ }
+
+ return (addr);
}
@@ -451,26 +493,6 @@ static gboolean nmwa_dbus_get_network_encrypted (NMWirelessApplet *applet, char
/*
- * nmwa_dbus_get_scanning_enabled
- */
-static gboolean nmwa_dbus_get_scanning_enabled (NMWirelessApplet *applet)
-{
- gboolean enabled = FALSE;
-
- switch (nmwa_dbus_call_nm_method (applet->connection, NM_DBUS_PATH, "getScanningEnabled", DBUS_TYPE_BOOLEAN, (void **)(&enabled), NULL))
- {
- case (RETURN_NO_NM):
- applet->applet_state = APPLET_STATE_NO_NM;
- break;
-
- default:
- break;
- }
-
- return (enabled);
-}
-
-/*
* nmwa_dbus_get_wireless_enabled
*/
static gboolean nmwa_dbus_get_wireless_enabled (NMWirelessApplet *applet)
@@ -704,28 +726,6 @@ void nmwa_dbus_create_network (DBusConnection *connection, const NetworkDevice *
/*
- * nmwa_dbus_enable_scanning
- *
- * Tell NetworkManager to start/stop scanning.
- *
- */
-void nmwa_dbus_enable_scanning (NMWirelessApplet *applet, gboolean enabled)
-{
- DBusMessage *message;
-
- g_return_if_fail (applet != NULL);
- g_return_if_fail (applet->connection != NULL);
-
- if ((message = dbus_message_new_method_call (NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, "setScanningEnabled")))
- {
- dbus_message_append_args (message, DBUS_TYPE_BOOLEAN, enabled, DBUS_TYPE_INVALID);
- dbus_connection_send (applet->connection, message, NULL);
- applet->scanning_enabled = nmwa_dbus_get_scanning_enabled (applet);
- }
-}
-
-
-/*
* nmwa_dbus_enable_wireless
*
* Tell NetworkManager to enabled or disable all wireless devices.
@@ -914,6 +914,7 @@ void network_device_unref (NetworkDevice *dev)
g_free (dev->nm_name);
g_free (dev->udi);
g_free (dev->hal_name);
+ g_free (dev->addr);
g_free (dev);
memset (dev, 0, sizeof (NetworkDevice));
}
@@ -959,7 +960,8 @@ NetworkDevice *network_device_copy (NetworkDevice *src)
dev->nm_device = g_strdup (src->nm_device);
dev->type = src->type;
dev->link = src->link;
- dev->supports_carrier_detect = src->supports_carrier_detect;
+ dev->addr = g_strdup (src->addr);
+ dev->driver_support_level = src->driver_support_level;
dev->nm_name = g_strdup (src->nm_name);
dev->hal_name = g_strdup (src->hal_name);
dev->udi = g_strdup (src->udi);
@@ -996,6 +998,36 @@ void network_device_add_wireless_network (NetworkDevice *dev, WirelessNetwork *n
}
+static int sort_networks_function (WirelessNetwork *a, WirelessNetwork *b)
+{
+ const char *name_a = a->essid;
+ const char *name_b = b->essid;
+
+ if (name_a && !name_b)
+ return -1;
+ else if (!name_a && name_b)
+ return 1;
+ else if (!name_a && !name_b)
+ return 0;
+ else
+ return strcasecmp (name_a, name_b);
+}
+
+/*
+ * network_device_sort_wireless_networks
+ *
+ * Alphabetize the wireless networks list
+ *
+ */
+void network_device_sort_wireless_networks (NetworkDevice *dev)
+{
+ g_return_if_fail (dev != NULL);
+ g_return_if_fail (dev->type == DEVICE_TYPE_WIRELESS_ETHERNET);
+
+ dev->networks = g_slist_sort (dev->networks, (GCompareFunc) sort_networks_function);
+}
+
+
/*
* nmwa_dbus_get_one_wireless_network
*
@@ -1157,9 +1189,12 @@ void nmwa_copy_data_model (NMWirelessApplet *applet)
for (elt = applet->dbus_device_list; elt; elt = g_slist_next (elt))
{
NetworkDevice *src = (NetworkDevice *)(elt->data);
- NetworkDevice *dst = network_device_copy (src);
+ NetworkDevice *dst = NULL;
+
+ if (src->type == DEVICE_TYPE_WIRELESS_ETHERNET)
+ network_device_sort_wireless_networks (src);
- if (dst)
+ if ((dst = network_device_copy (src)))
{
/* Transfer ownership of device to list, don't need to unref it */
applet->gui_device_list = g_slist_append (applet->gui_device_list, dst);
@@ -1192,6 +1227,10 @@ static gboolean nmwa_dbus_update_active_device_strength (gpointer user_data)
g_return_val_if_fail (user_data != NULL, FALSE);
applet = (NMWirelessApplet *)user_data;
+
+ if (applet->applet_state == APPLET_STATE_NO_NM)
+ return TRUE;
+
if (applet->gui_active_device && (applet->gui_active_device->type == DEVICE_TYPE_WIRELESS_ETHERNET))
{
guint8 strength = nmwa_dbus_get_object_strength (applet, applet->gui_active_device->nm_device);
@@ -1316,6 +1355,73 @@ static void nmwa_dbus_device_update_one_network (NMWirelessApplet *applet, DBusM
/*
+ * nmwa_dbus_schedule_driver_notification
+ *
+ * Schedule the driver notification routine to run in the main loop.
+ *
+ */
+void nmwa_dbus_schedule_driver_notification (NMWirelessApplet *applet, NetworkDevice *dev)
+{
+ DriverNotifyCBData *cb_data;
+
+ g_return_if_fail (applet != NULL);
+ g_return_if_fail (dev != NULL);
+
+ cb_data = g_malloc0 (sizeof (DriverNotifyCBData));
+ cb_data->applet = applet;
+ cb_data->dev = dev;
+
+ g_idle_add (nmwa_driver_notify, (gpointer)cb_data);
+}
+
+
+/*
+ * nmwa_dbus_check_drivers
+ *
+ * If a device got added, we notify the user if the device's driver
+ * has any problems (no carrier detect, no wireless scanning, etc).
+ *
+ */
+void nmwa_dbus_check_drivers (NMWirelessApplet *applet)
+{
+ GSList *elt;
+
+ g_return_if_fail (applet != NULL);
+
+ /* For every device that's in the dbus data model but not in
+ * the gui data model, signal the user.
+ */
+ for (elt = applet->dbus_device_list; elt; elt = g_slist_next (elt))
+ {
+ NetworkDevice *dbus_dev = (NetworkDevice *)(elt->data);
+ GSList *elt2;
+ gboolean found = FALSE;
+
+ for (elt2 = applet->gui_device_list; elt2; elt2 = g_slist_next (elt2))
+ {
+ NetworkDevice *gui_dev = (NetworkDevice *)(elt2->data);
+
+ if ( !nm_null_safe_strcmp (dbus_dev->nm_device, gui_dev->nm_device)
+ && !nm_null_safe_strcmp (dbus_dev->addr, gui_dev->addr)
+ && !nm_null_safe_strcmp (dbus_dev->udi, gui_dev->udi))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if ( !found
+ && ( (dbus_dev->driver_support_level == NM_DRIVER_NO_CARRIER_DETECT)
+ || (dbus_dev->driver_support_level == NM_DRIVER_NO_WIRELESS_SCAN)))
+ {
+ network_device_ref (dbus_dev);
+ nmwa_dbus_schedule_driver_notification (applet, dbus_dev);
+ }
+ }
+}
+
+
+/*
* sort_devices_function
*
* Sort the devices for display... Wired devices at the top.
@@ -1414,8 +1520,8 @@ static void nmwa_dbus_update_devices (NMWirelessApplet *applet)
{
dev->nm_device = g_strdup (devices[i]);
dev->type = nmwa_dbus_get_device_type (applet, devices[i], APPLET_STATE_NO_CONNECTION);
- if (dev->type == DEVICE_TYPE_WIRED_ETHERNET)
- dev->supports_carrier_detect = nmwa_dbus_get_device_supports_carrier_detect (applet, devices[i]);
+ dev->driver_support_level = nmwa_dbus_get_device_driver_support_level (applet, devices[i]);
+ dev->addr = nmwa_dbus_get_hw_addr (applet, devices[i]);
dev->link = nmwa_dbus_get_device_link_active (applet, devices[i]);
dev->nm_name = g_strdup (name);
dev->udi = nmwa_dbus_get_device_udi (applet, devices[i]);
@@ -1447,12 +1553,14 @@ static void nmwa_dbus_update_devices (NMWirelessApplet *applet)
/* Sort the devices for display */
applet->dbus_device_list = g_slist_sort (applet->dbus_device_list, sort_devices_function);
+ /* Notify user of issues with certain cards/drivers */
+ nmwa_dbus_check_drivers (applet);
+
/* Now copy the data over to the GUI side */
g_mutex_lock (applet->data_mutex);
nmwa_copy_data_model (applet);
applet->is_adhoc = adhoc;
- applet->scanning_enabled = nmwa_dbus_get_scanning_enabled (applet);
applet->wireless_enabled = nmwa_dbus_get_wireless_enabled (applet);
g_mutex_unlock (applet->data_mutex);
diff --git a/panel-applet/NMWirelessAppletOtherNetworkDialog.c b/panel-applet/NMWirelessAppletOtherNetworkDialog.c
index a6ebea9ed9..3b440c57e7 100644
--- a/panel-applet/NMWirelessAppletOtherNetworkDialog.c
+++ b/panel-applet/NMWirelessAppletOtherNetworkDialog.c
@@ -215,6 +215,9 @@ static GtkDialog *nmwa_other_network_dialog_init (GladeXML *xml, NMWirelessApple
/* Set up the dialog */
dialog = GTK_DIALOG (glade_xml_get_widget (xml, "custom_essid_dialog"));
+ if (!dialog)
+ return NULL;
+
essid_entry = glade_xml_get_widget (xml, "essid_entry");
button = glade_xml_get_widget (xml, "ok_button");
@@ -302,26 +305,17 @@ static GtkDialog *nmwa_other_network_dialog_init (GladeXML *xml, NMWirelessApple
void nmwa_other_network_dialog_run (NMWirelessApplet *applet, gboolean create_network)
{
gchar *glade_file;
- GtkDialog *dialog;
- GladeXML *xml;
- gint response;
+ GtkDialog *dialog;
+ gint response;
NetworkDevice *def_dev = NULL;
+ GladeXML *xml;
g_return_if_fail (applet != NULL);
+ g_return_if_fail (applet->glade_file != NULL);
- glade_file = g_build_filename (GLADEDIR, "essid.glade", NULL);
-
- if (!glade_file || !g_file_test (glade_file, G_FILE_TEST_IS_REGULAR))
- {
- show_warning_dialog (TRUE, _("The NetworkManager Applet could not find some required resources (the glade file was not found)."));
- return;
- }
-
- xml = glade_xml_new (glade_file, NULL, NULL);
- g_free (glade_file);
+ xml = glade_xml_new (applet->glade_file, NULL, NULL);
if (xml == NULL)
{
- /* Reuse the above string to make the translators less angry. */
show_warning_dialog (TRUE, _("The NetworkManager Applet could not find some required resources (the glade file was not found)."));
return;
}
diff --git a/panel-applet/gtkcellrendererprogress.c b/panel-applet/gtkcellrendererprogress.c
deleted file mode 100644
index 4933c23d4b..0000000000
--- a/panel-applet/gtkcellrendererprogress.c
+++ /dev/null
@@ -1,387 +0,0 @@
-/* gtkcellrendererprogress.c
- * Copyright (C) 2002 Naba Kumar <kh_naba@users.sourceforge.net>
- * heavily modified by Jörgen Scheibengruber <mfcn@gmx.de>
- * heavily modified by Marco Pesenti Gritti <marco@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-/*
- * Modified by the GTK+ Team and others 1997-2004. See the AUTHORS
- * file for a list of people on the GTK+ Team. See the ChangeLog
- * files for a list of changes. These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-/* GtkCellRendererProgress is public in GTK 2.6, but not in GTK 2.4.
- */
-
-#include <gtk/gtkversion.h>
-
-#if (GTK_MAJOR_VERSION <= 2 && GTK_MINOR_VERSION < 6)
-
-#include <stdlib.h>
-
-#include "gtkcellrendererprogress.h"
-#define _(x) (x)
-#define P_(x) (x)
-#define Q_(x) (x)
-#define N_(x) (x)
-
-#define GTK_CELL_RENDERER_PROGRESS_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), \
- GTK_TYPE_CELL_RENDERER_PROGRESS, \
- GtkCellRendererProgressPrivate))
-
-enum
-{
- PROP_0,
- PROP_VALUE,
- PROP_TEXT
-};
-
-struct _GtkCellRendererProgressPrivate
-{
- gint value;
- gchar *text;
- gchar *label;
- gint min_h;
- gint min_w;
-};
-
-static void gtk_cell_renderer_progress_finalize (GObject *object);
-static void gtk_cell_renderer_progress_get_property (GObject *object,
- guint param_id,
- GValue *value,
- GParamSpec *pspec);
-static void gtk_cell_renderer_progress_set_property (GObject *object,
- guint param_id,
- const GValue *value,
- GParamSpec *pspec);
-static void gtk_cell_renderer_progress_set_value (GtkCellRendererProgress *cellprogress,
- gint value);
-static void gtk_cell_renderer_progress_set_text (GtkCellRendererProgress *cellprogress,
- const gchar *text);
-static void compute_dimensions (GtkCellRenderer *cell,
- GtkWidget *widget,
- const gchar *text,
- gint *width,
- gint *height);
-static void gtk_cell_renderer_progress_get_size (GtkCellRenderer *cell,
- GtkWidget *widget,
- GdkRectangle *cell_area,
- gint *x_offset,
- gint *y_offset,
- gint *width,
- gint *height);
-static void gtk_cell_renderer_progress_render (GtkCellRenderer *cell,
- GdkWindow *window,
- GtkWidget *widget,
- GdkRectangle *background_area,
- GdkRectangle *cell_area,
- GdkRectangle *expose_area,
- guint flags);
-
-
-G_DEFINE_TYPE (GtkCellRendererProgress, gtk_cell_renderer_progress, GTK_TYPE_CELL_RENDERER);
-
-static void
-gtk_cell_renderer_progress_class_init (GtkCellRendererProgressClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
-
- object_class->finalize = gtk_cell_renderer_progress_finalize;
- object_class->get_property = gtk_cell_renderer_progress_get_property;
- object_class->set_property = gtk_cell_renderer_progress_set_property;
-
- cell_class->get_size = gtk_cell_renderer_progress_get_size;
- cell_class->render = gtk_cell_renderer_progress_render;
-
- /**
- * GtkCellRendererProgress:value:
- *
- * The "value" property determines the percentage to which the
- * progress bar will be "filled in".
- *
- * Since: 2.6
- **/
- g_object_class_install_property (object_class,
- PROP_VALUE,
- g_param_spec_int ("value",
- P_("Value"),
- P_("Value of the progress bar"),
- 0, 100, 0,
- G_PARAM_READWRITE));
-
- /**
- * GtkCellRendererProgress:text:
- *
- * The "text" property determines the label which will be drawn
- * over the progress bar. Setting this property to %NULL causes the default
- * label to be displayed. Setting this property to an empty string causes
- * no label to be displayed.
- *
- * Since: 2.6
- **/
- g_object_class_install_property (object_class,
- PROP_TEXT,
- g_param_spec_string ("text",
- P_("Text"),
- P_("Text on the progress bar"),
- NULL,
- G_PARAM_READWRITE));
-
- g_type_class_add_private (object_class,
- sizeof (GtkCellRendererProgressPrivate));
-}
-
-static void
-gtk_cell_renderer_progress_init (GtkCellRendererProgress *cellprogress)
-{
- cellprogress->priv = GTK_CELL_RENDERER_PROGRESS_GET_PRIVATE (cellprogress);
- cellprogress->priv->value = 0;
- cellprogress->priv->text = NULL;
- cellprogress->priv->label = NULL;
- cellprogress->priv->min_w = -1;
- cellprogress->priv->min_h = -1;
-}
-
-
-/**
- * gtk_cell_renderer_progress_new:
- *
- * Creates a new #GtkCellRendererProgress.
- *
- * Return value: the new cell renderer
- *
- * Since: 2.6
- **/
-GtkCellRenderer*
-gtk_cell_renderer_progress_new (void)
-{
- return GTK_CELL_RENDERER (g_object_new (GTK_TYPE_CELL_RENDERER_PROGRESS, NULL));
-}
-
-static void
-gtk_cell_renderer_progress_finalize (GObject *object)
-{
- GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
-
- g_free (cellprogress->priv->text);
- g_free (cellprogress->priv->label);
-
- G_OBJECT_CLASS (gtk_cell_renderer_progress_parent_class)->finalize (object);
-}
-
-static void
-gtk_cell_renderer_progress_get_property (GObject *object,
- guint param_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
-
- switch (param_id)
- {
- case PROP_VALUE:
- g_value_set_int (value, cellprogress->priv->value);
- break;
- case PROP_TEXT:
- g_value_set_string (value, cellprogress->priv->text);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
- }
-}
-
-static void
-gtk_cell_renderer_progress_set_property (GObject *object,
- guint param_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (object);
-
- switch (param_id)
- {
- case PROP_VALUE:
- gtk_cell_renderer_progress_set_value (cellprogress,
- g_value_get_int (value));
- break;
- case PROP_TEXT:
- gtk_cell_renderer_progress_set_text (cellprogress,
- g_value_get_string (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
- }
-}
-
-static void
-gtk_cell_renderer_progress_set_value (GtkCellRendererProgress *cellprogress,
- gint value)
-{
- gchar *text;
-
- cellprogress->priv->value = value;
-
- if (cellprogress->priv->text)
- text = g_strdup (cellprogress->priv->text);
- else
- text = g_strdup_printf (Q_("progress bar label|%d %%"),
- cellprogress->priv->value);
-
- g_free (cellprogress->priv->label);
- cellprogress->priv->label = text;
-}
-
-static void
-gtk_cell_renderer_progress_set_text (GtkCellRendererProgress *cellprogress,
- const gchar *text)
-{
- gchar *new_text;
-
- new_text = g_strdup (text);
- g_free (cellprogress->priv->text);
- cellprogress->priv->text = new_text;
-
- /* Update the label */
- gtk_cell_renderer_progress_set_value (cellprogress, cellprogress->priv->value);
-}
-
-static void
-compute_dimensions (GtkCellRenderer *cell,
- GtkWidget *widget,
- const gchar *text,
- gint *width,
- gint *height)
-{
- PangoRectangle logical_rect;
- PangoLayout *layout;
-
- layout = gtk_widget_create_pango_layout (widget, text);
- pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
-
- if (width)
- *width = logical_rect.width + cell->xpad * 2 + widget->style->xthickness * 2;
-
- if (height)
- *height = logical_rect.height + cell->ypad * 2 + widget->style->ythickness * 2;
-
- g_object_unref (G_OBJECT (layout));
-}
-
-static void
-gtk_cell_renderer_progress_get_size (GtkCellRenderer *cell,
- GtkWidget *widget,
- GdkRectangle *cell_area,
- gint *x_offset,
- gint *y_offset,
- gint *width,
- gint *height)
-{
- GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (cell);
- gint w, h;
- gchar *text;
-
- if (cellprogress->priv->min_w < 0)
- {
- text = g_strdup_printf (Q_("progress bar label|%d %%"), 100);
- compute_dimensions (cell, widget, text,
- &cellprogress->priv->min_w,
- &cellprogress->priv->min_h);
- g_free (text);
- }
-
- compute_dimensions (cell, widget, cellprogress->priv->label, &w, &h);
-
- if (width)
- *width = MAX (cellprogress->priv->min_w, w);
-
- if (height)
- *height = MIN (cellprogress->priv->min_h, h);
-}
-
-static void
-gtk_cell_renderer_progress_render (GtkCellRenderer *cell,
- GdkWindow *window,
- GtkWidget *widget,
- GdkRectangle *background_area,
- GdkRectangle *cell_area,
- GdkRectangle *expose_area,
- guint flags)
-{
- GtkCellRendererProgress *cellprogress = GTK_CELL_RENDERER_PROGRESS (cell);
- GdkGC *gc;
- PangoLayout *layout;
- PangoRectangle logical_rect;
- gint x, y, w, h, perc_w, pos;
- GdkRectangle clip;
- gboolean is_rtl;
-
- is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
-
- gc = gdk_gc_new (window);
-
- x = cell_area->x + cell->xpad;
- y = cell_area->y + cell->ypad;
-
- w = cell_area->width - cell->xpad * 2;
- h = cell_area->height - cell->ypad * 2;
-
- gdk_gc_set_rgb_fg_color (gc, &widget->style->fg[GTK_STATE_NORMAL]);
- gdk_draw_rectangle (window, gc, TRUE, x, y, w, h);
-
- x += widget->style->xthickness;
- y += widget->style->ythickness;
- w -= widget->style->xthickness * 2;
- h -= widget->style->ythickness * 2;
- gdk_gc_set_rgb_fg_color (gc, &widget->style->bg[GTK_STATE_NORMAL]);
- gdk_draw_rectangle (window, gc, TRUE, x, y, w, h);
-
- gdk_gc_set_rgb_fg_color (gc, &widget->style->bg[GTK_STATE_SELECTED]);
- perc_w = w * MAX (0, cellprogress->priv->value) / 100;
- gdk_draw_rectangle (window, gc, TRUE, is_rtl ? (x + w - perc_w) : x, y, perc_w, h);
-
- layout = gtk_widget_create_pango_layout (widget, cellprogress->priv->label);
- pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
-
- pos = (w - logical_rect.width)/2;
-
- clip.x = x;
- clip.y = y;
- clip.width = is_rtl ? w - perc_w : perc_w;
- clip.height = h;
-
- gtk_paint_layout (widget->style, window,
- is_rtl ? GTK_STATE_NORMAL : GTK_STATE_SELECTED,
- FALSE, &clip, widget, "progressbar",
- x + pos, y + (h - logical_rect.height)/2,
- layout);
-
- clip.x = clip.x + clip.width;
- clip.width = w - clip.width;
-
- gtk_paint_layout (widget->style, window,
- is_rtl ? GTK_STATE_SELECTED : GTK_STATE_NORMAL,
- FALSE, &clip, widget, "progressbar",
- x + pos, y + (h - logical_rect.height)/2,
- layout);
-
- g_object_unref (G_OBJECT (layout));
- g_object_unref (G_OBJECT (gc));
-}
-
-#endif /* GTK < 2.6 check */
diff --git a/panel-applet/gtkcellrendererprogress.h b/panel-applet/gtkcellrendererprogress.h
deleted file mode 100644
index ff47332823..0000000000
--- a/panel-applet/gtkcellrendererprogress.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* gtkcellrendererprogress.h
- * Copyright (C) 2002 Naba Kumar <kh_naba@users.sourceforge.net>
- * modified by Jörgen Scheibengruber <mfcn@gmx.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-/*
- * Modified by the GTK+ Team and others 1997-2004. See the AUTHORS
- * file for a list of people on the GTK+ Team. See the ChangeLog
- * files for a list of changes. These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
- */
-
-
-/* GtkCellRendererProgress is public in GTK 2.6, but not in GTK 2.4.
- */
-
-#include <gtk/gtkversion.h>
-
-#if (GTK_MAJOR_VERSION <= 2 && GTK_MINOR_VERSION < 6)
-
-#ifndef __GTK_CELL_RENDERER_PROGRESS_H__
-#define __GTK_CELL_RENDERER_PROGRESS_H__
-
-#include <gtk/gtkcellrenderer.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_CELL_RENDERER_PROGRESS (gtk_cell_renderer_progress_get_type ())
-#define GTK_CELL_RENDERER_PROGRESS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CELL_RENDERER_PROGRESS, GtkCellRendererProgress))
-#define GTK_CELL_RENDERER_PROGRESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_CELL_RENDERER_PROGRESS, GtkCellRendererProgressClass))
-#define GTK_IS_CELL_RENDERER_PROGRESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_CELL_RENDERER_PROGRESS))
-#define GTK_IS_CELL_RENDERER_PROGRESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CELL_RENDERER_PROGRESS))
-#define GTK_CELL_RENDERER_PROGRESS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CELL_RENDERER_PROGRESS, GtkCellRendererProgressClass))
-
-typedef struct _GtkCellRendererProgress GtkCellRendererProgress;
-typedef struct _GtkCellRendererProgressClass GtkCellRendererProgressClass;
-typedef struct _GtkCellRendererProgressPrivate GtkCellRendererProgressPrivate;
-
-struct _GtkCellRendererProgress
-{
- GtkCellRenderer parent_instance;
-
- /*< private >*/
- GtkCellRendererProgressPrivate *priv;
-};
-
-struct _GtkCellRendererProgressClass
-{
- GtkCellRendererClass parent_class;
-
- /* Padding for future expansion */
- void (*_gtk_reserved1) (void);
- void (*_gtk_reserved2) (void);
- void (*_gtk_reserved3) (void);
- void (*_gtk_reserved4) (void);
-};
-
-GType gtk_cell_renderer_progress_get_type (void);
-GtkCellRenderer* gtk_cell_renderer_progress_new (void);
-
-G_END_DECLS
-
-#endif /* __GTK_CELL_RENDERER_PROGRESS_H__ */
-
-#endif /* GTK < 2.6 check */
diff --git a/panel-applet/gtkcellview.c b/panel-applet/gtkcellview.c
deleted file mode 100644
index 15920fb9af..0000000000
--- a/panel-applet/gtkcellview.c
+++ /dev/null
@@ -1,1018 +0,0 @@
-/* gtkellview.c
- * Copyright (C) 2002, 2003 Kristian Rietveld <kris@gtk.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/* GtkCellView is public in GTK 2.6, but not in GTK 2.4. We can't include
- * this private copy of GtkCellView when using GTK 2.6 due to link-time errors.
- */
-
-#include <gtk/gtkversion.h>
-
-#if (GTK_MAJOR_VERSION <= 2 && GTK_MINOR_VERSION < 6)
-
-#include "gtkcellview.h"
-#include <gtk/gtksignal.h>
-#include <gtk/gtkcelllayout.h>
-#include <gtk/gtkcellrenderertext.h>
-#include <gtk/gtkcellrendererpixbuf.h>
-#include <gobject/gmarshal.h>
-#define _(x) (x)
-#define P_(x) (x)
-#define Q_(x) (x)
-#define N_(x) (x)
-
-typedef struct _GtkCellViewCellInfo GtkCellViewCellInfo;
-struct _GtkCellViewCellInfo
-{
- GtkCellRenderer *cell;
-
- gint requested_width;
- gint real_width;
- guint expand : 1;
- guint pack : 1;
-
- GSList *attributes;
-
- GtkCellLayoutDataFunc func;
- gpointer func_data;
- GDestroyNotify destroy;
-};
-
-struct _GtkCellViewPrivate
-{
- GtkTreeModel *model;
- GtkTreeRowReference *displayed_row;
- GList *cell_list;
- gint spacing;
-
- GdkColor background;
- gboolean background_set;
-};
-
-
-static void gtk_cell_view_class_init (GtkCellViewClass *klass);
-static void gtk_cell_view_cell_layout_init (GtkCellLayoutIface *iface);
-static void gtk_cell_view_get_property (GObject *object,
- guint param_id,
- GValue *value,
- GParamSpec *pspec);
-static void gtk_cell_view_set_property (GObject *object,
- guint param_id,
- const GValue *value,
- GParamSpec *pspec);
-static void gtk_cell_view_init (GtkCellView *cellview);
-static void gtk_cell_view_finalize (GObject *object);
-static void gtk_cell_view_style_set (GtkWidget *widget,
- GtkStyle *previous_style);
-static void gtk_cell_view_size_request (GtkWidget *widget,
- GtkRequisition *requisition);
-static void gtk_cell_view_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation);
-static gboolean gtk_cell_view_expose (GtkWidget *widget,
- GdkEventExpose *event);
-static void gtk_cell_view_set_valuesv (GtkCellView *cellview,
- GtkCellRenderer *renderer,
- va_list args);
-static GtkCellViewCellInfo *gtk_cell_view_get_cell_info (GtkCellView *cellview,
- GtkCellRenderer *renderer);
-
-
-static void gtk_cell_view_cell_layout_pack_start (GtkCellLayout *layout,
- GtkCellRenderer *renderer,
- gboolean expand);
-static void gtk_cell_view_cell_layout_pack_end (GtkCellLayout *layout,
- GtkCellRenderer *renderer,
- gboolean expand);
-static void gtk_cell_view_cell_layout_add_attribute (GtkCellLayout *layout,
- GtkCellRenderer *renderer,
- const gchar *attribute,
- gint column);
-static void gtk_cell_view_cell_layout_clear (GtkCellLayout *layout);
-static void gtk_cell_view_cell_layout_clear_attributes (GtkCellLayout *layout,
- GtkCellRenderer *renderer);
-static void gtk_cell_view_cell_layout_set_cell_data_func (GtkCellLayout *layout,
- GtkCellRenderer *cell,
- GtkCellLayoutDataFunc func,
- gpointer func_data,
- GDestroyNotify destroy);
-static void gtk_cell_view_cell_layout_reorder (GtkCellLayout *layout,
- GtkCellRenderer *cell,
- gint position);
-
-
-#define GTK_CELL_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_CELL_VIEW, GtkCellViewPrivate))
-
-enum
-{
- PROP_0,
- PROP_BACKGROUND,
- PROP_BACKGROUND_GDK,
- PROP_BACKGROUND_SET
-};
-
-static GtkObjectClass *parent_class = NULL;
-
-
-GType
-gtk_cell_view_get_type (void)
-{
- static GType cell_view_type = 0;
-
- if (!cell_view_type)
- {
- static const GTypeInfo cell_view_info =
- {
- sizeof (GtkCellViewClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) gtk_cell_view_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (GtkCellView),
- 0,
- (GInstanceInitFunc) gtk_cell_view_init
- };
-
- static const GInterfaceInfo cell_layout_info =
- {
- (GInterfaceInitFunc) gtk_cell_view_cell_layout_init,
- NULL,
- NULL
- };
-
- cell_view_type = g_type_register_static (GTK_TYPE_WIDGET, "GtkCellView",
- &cell_view_info, 0);
-
- g_type_add_interface_static (cell_view_type, GTK_TYPE_CELL_LAYOUT,
- &cell_layout_info);
- }
-
- return cell_view_type;
-}
-
-static void
-gtk_cell_view_class_init (GtkCellViewClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-
- parent_class = g_type_class_peek_parent (klass);
-
- gobject_class->get_property = gtk_cell_view_get_property;
- gobject_class->set_property = gtk_cell_view_set_property;
- gobject_class->finalize = gtk_cell_view_finalize;
-
- widget_class->expose_event = gtk_cell_view_expose;
- widget_class->size_allocate = gtk_cell_view_size_allocate;
- widget_class->size_request = gtk_cell_view_size_request;
- widget_class->style_set = gtk_cell_view_style_set;
-
- /* properties */
- g_object_class_install_property (gobject_class,
- PROP_BACKGROUND,
- g_param_spec_string ("background",
- P_("Background color name"),
- P_("Background color as a string"),
- NULL,
- G_PARAM_WRITABLE));
- g_object_class_install_property (gobject_class,
- PROP_BACKGROUND_GDK,
- g_param_spec_boxed ("background_gdk",
- P_("Background color"),
- P_("Background color as a GdkColor"),
- GDK_TYPE_COLOR,
- G_PARAM_READABLE | G_PARAM_WRITABLE));
-
-#define ADD_SET_PROP(propname, propval, nick, blurb) g_object_class_install_property (gobject_class, propval, g_param_spec_boolean (propname, nick, blurb, FALSE, G_PARAM_READABLE | G_PARAM_WRITABLE))
-
- ADD_SET_PROP ("background_set", PROP_BACKGROUND_SET,
- P_("Background set"),
- P_("Whether this tag affects the background color"));
-
- g_type_class_add_private (gobject_class, sizeof (GtkCellViewPrivate));
-}
-
-static void
-gtk_cell_view_cell_layout_init (GtkCellLayoutIface *iface)
-{
- iface->pack_start = gtk_cell_view_cell_layout_pack_start;
- iface->pack_end = gtk_cell_view_cell_layout_pack_end;
- iface->clear = gtk_cell_view_cell_layout_clear;
- iface->add_attribute = gtk_cell_view_cell_layout_add_attribute;
- iface->set_cell_data_func = gtk_cell_view_cell_layout_set_cell_data_func;
- iface->clear_attributes = gtk_cell_view_cell_layout_clear_attributes;
- iface->reorder = gtk_cell_view_cell_layout_reorder;
-}
-
-static void
-gtk_cell_view_get_property (GObject *object,
- guint param_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkCellView *view = GTK_CELL_VIEW (object);
-
- switch (param_id)
- {
- case PROP_BACKGROUND_GDK:
- {
- GdkColor color;
-
- color = view->priv->background;
-
- g_value_set_boxed (value, &color);
- }
- break;
- case PROP_BACKGROUND_SET:
- g_value_set_boolean (value, view->priv->background_set);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
- break;
- }
-}
-
-static void
-gtk_cell_view_set_property (GObject *object,
- guint param_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkCellView *view = GTK_CELL_VIEW (object);
-
- switch (param_id)
- {
- case PROP_BACKGROUND:
- {
- GdkColor color;
-
- if (!g_value_get_string (value))
- gtk_cell_view_set_background_color (view, NULL);
- else if (gdk_color_parse (g_value_get_string (value), &color))
- gtk_cell_view_set_background_color (view, &color);
- else
- g_warning ("Don't know color `%s'", g_value_get_string (value));
-
- g_object_notify (object, "background_gdk");
- }
- break;
- case PROP_BACKGROUND_GDK:
- gtk_cell_view_set_background_color (view, g_value_get_boxed (value));
- break;
- case PROP_BACKGROUND_SET:
- view->priv->background_set = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
- break;
- }
-}
-
-static void
-gtk_cell_view_init (GtkCellView *cellview)
-{
- GTK_WIDGET_SET_FLAGS (cellview, GTK_NO_WINDOW);
-
- cellview->priv = GTK_CELL_VIEW_GET_PRIVATE (cellview);
-}
-
-static void
-gtk_cell_view_style_set (GtkWidget *widget,
- GtkStyle *previous_style)
-{
- if (previous_style && GTK_WIDGET_REALIZED (widget))
- gdk_window_set_background (widget->window,
- &widget->style->base[GTK_WIDGET_STATE (widget)]);
-}
-
-static void
-gtk_cell_view_finalize (GObject *object)
-{
- GtkCellView *cellview = GTK_CELL_VIEW (object);
-
- gtk_cell_view_cell_layout_clear (GTK_CELL_LAYOUT (cellview));
-
- if (cellview->priv->model)
- g_object_unref (cellview->priv->model);
-
- if (cellview->priv->displayed_row)
- gtk_tree_row_reference_free (cellview->priv->displayed_row);
-
- (* G_OBJECT_CLASS (parent_class)->finalize) (object);
-}
-
-static void
-gtk_cell_view_size_request (GtkWidget *widget,
- GtkRequisition *requisition)
-{
- GList *i;
- gboolean first_cell = TRUE;
- GtkCellView *cellview;
-
- cellview = GTK_CELL_VIEW (widget);
-
- requisition->width = 0;
- requisition->height = 0;
-
- if (cellview->priv->displayed_row)
- gtk_cell_view_set_cell_data (cellview);
-
- for (i = cellview->priv->cell_list; i; i = i->next)
- {
- gint width, height;
- GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
-
- if (!info->cell->visible)
- continue;
-
- if (!first_cell)
- requisition->width += cellview->priv->spacing;
-
- gtk_cell_renderer_get_size (info->cell, widget, NULL, NULL, NULL,
- &width, &height);
-
- info->requested_width = width;
- requisition->width += width;
- requisition->height = MAX (requisition->height, height);
-
- first_cell = FALSE;
- }
-}
-
-static void
-gtk_cell_view_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
-{
- GList *i;
- gint expand_cell_count = 0;
- gint full_requested_width = 0;
- gint extra_space;
- GtkCellView *cellview;
-
- widget->allocation = *allocation;
-
- cellview = GTK_CELL_VIEW (widget);
-
- /* checking how much extra space we have */
- for (i = cellview->priv->cell_list; i; i = i->next)
- {
- GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
-
- if (!info->cell->visible)
- continue;
-
- if (info->expand)
- expand_cell_count++;
-
- full_requested_width += info->requested_width;
- }
-
- extra_space = widget->allocation.width - full_requested_width;
- if (extra_space < 0)
- extra_space = 0;
- else if (extra_space > 0 && expand_cell_count > 0)
- extra_space /= expand_cell_count;
-
- /* iterate list for PACK_START cells */
- for (i = cellview->priv->cell_list; i; i = i->next)
- {
- GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
-
- if (info->pack == GTK_PACK_END)
- continue;
-
- if (!info->cell->visible)
- continue;
-
- info->real_width = info->requested_width + (info->expand?extra_space:0);
- }
-
- /* iterate list for PACK_END cells */
- for (i = cellview->priv->cell_list; i; i = i->next)
- {
- GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
-
- if (info->pack == GTK_PACK_START)
- continue;
-
- if (!info->cell->visible)
- continue;
-
- info->real_width = info->requested_width + (info->expand?extra_space:0);
- }
-}
-
-static gboolean
-gtk_cell_view_expose (GtkWidget *widget,
- GdkEventExpose *event)
-{
- GList *i;
- GtkCellView *cellview;
- GdkRectangle area;
- GtkCellRendererState state;
- gboolean rtl = (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL);
-
- cellview = GTK_CELL_VIEW (widget);
-
- if (! GTK_WIDGET_DRAWABLE (widget))
- return FALSE;
-
- /* "blank" background */
- if (cellview->priv->background_set)
- {
- GdkGC *gc;
-
- gc = gdk_gc_new (GTK_WIDGET (cellview)->window);
- gdk_gc_set_rgb_fg_color (gc, &cellview->priv->background);
-
- gdk_draw_rectangle (GTK_WIDGET (cellview)->window,
- gc,
- TRUE,
- /*0, 0,*/
- widget->allocation.x,
- widget->allocation.y,
-
- widget->allocation.width,
- widget->allocation.height);
-
- g_object_unref (G_OBJECT (gc));
- }
-
- /* set cell data (if available) */
- if (cellview->priv->displayed_row)
- gtk_cell_view_set_cell_data (cellview);
- else if (cellview->priv->model)
- return FALSE;
-
- /* render cells */
- area = widget->allocation;
-
- /* we draw on our very own window, initialize x and y to zero */
- area.x = widget->allocation.x + (rtl ? widget->allocation.width : 0);
- area.y = widget->allocation.y;
-
- if (GTK_WIDGET_STATE (widget) == GTK_STATE_PRELIGHT)
- state = GTK_CELL_RENDERER_PRELIT;
- else
- state = 0;
-
- /* PACK_START */
- for (i = cellview->priv->cell_list; i; i = i->next)
- {
- GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
-
- if (info->pack == GTK_PACK_END)
- continue;
-
- if (!info->cell->visible)
- continue;
-
- area.width = info->real_width;
- if (rtl)
- area.x -= area.width;
-
- gtk_cell_renderer_render (info->cell,
- event->window,
- widget,
- /* FIXME! */
- &area, &area, &event->area, state);
-
- if (!rtl)
- area.x += info->real_width;
- }
-
- area.x = rtl ? widget->allocation.x : (widget->allocation.x + widget->allocation.width);
-
- /* PACK_END */
- for (i = cellview->priv->cell_list; i; i = i->next)
- {
- GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
-
- if (info->pack == GTK_PACK_START)
- continue;
-
- if (!info->cell->visible)
- continue;
-
- area.width = info->real_width;
- if (!rtl)
- area.x -= area.width;
-
- gtk_cell_renderer_render (info->cell,
- widget->window,
- widget,
- /* FIXME ! */
- &area, &area, &event->area, state);
- if (rtl)
- area.x += info->real_width;
- }
-
- return FALSE;
-}
-
-static GtkCellViewCellInfo *
-gtk_cell_view_get_cell_info (GtkCellView *cellview,
- GtkCellRenderer *renderer)
-{
- GList *i;
-
- for (i = cellview->priv->cell_list; i; i = i->next)
- {
- GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)i->data;
-
- if (info->cell == renderer)
- return info;
- }
-
- return NULL;
-}
-
-void
-gtk_cell_view_set_cell_data (GtkCellView *cellview)
-{
- GList *i;
- GtkTreeIter iter;
- GtkTreePath *path;
-
- g_return_if_fail (cellview->priv->displayed_row != NULL);
-
- path = gtk_tree_row_reference_get_path (cellview->priv->displayed_row);
- if (!path)
- return;
-
- gtk_tree_model_get_iter (cellview->priv->model, &iter, path);
- gtk_tree_path_free (path);
-
- for (i = cellview->priv->cell_list; i; i = i->next)
- {
- GSList *j;
- GtkCellViewCellInfo *info = i->data;
-
- g_object_freeze_notify (G_OBJECT (info->cell));
-
- for (j = info->attributes; j && j->next; j = j->next->next)
- {
- gchar *property = j->data;
- gint column = GPOINTER_TO_INT (j->next->data);
- GValue value = {0, };
-
- gtk_tree_model_get_value (cellview->priv->model, &iter,
- column, &value);
- g_object_set_property (G_OBJECT (info->cell),
- property, &value);
- g_value_unset (&value);
- }
-
- if (info->func)
- (* info->func) (GTK_CELL_LAYOUT (cellview),
- info->cell,
- cellview->priv->model,
- &iter,
- info->func_data);
-
- g_object_thaw_notify (G_OBJECT (info->cell));
- }
-}
-
-/* GtkCellLayout implementation */
-static void
-gtk_cell_view_cell_layout_pack_start (GtkCellLayout *layout,
- GtkCellRenderer *renderer,
- gboolean expand)
-{
- GtkCellViewCellInfo *info;
- GtkCellView *cellview = GTK_CELL_VIEW (layout);
-
- g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
- g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
- g_return_if_fail (!gtk_cell_view_get_cell_info (cellview, renderer));
-
- g_object_ref (G_OBJECT (renderer));
- gtk_object_sink (GTK_OBJECT (renderer));
-
- info = g_new0 (GtkCellViewCellInfo, 1);
- info->cell = renderer;
- info->expand = expand ? TRUE : FALSE;
- info->pack = GTK_PACK_START;
-
- cellview->priv->cell_list = g_list_append (cellview->priv->cell_list, info);
-}
-
-static void
-gtk_cell_view_cell_layout_pack_end (GtkCellLayout *layout,
- GtkCellRenderer *renderer,
- gboolean expand)
-{
- GtkCellViewCellInfo *info;
- GtkCellView *cellview = GTK_CELL_VIEW (layout);
-
- g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
- g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
- g_return_if_fail (!gtk_cell_view_get_cell_info (cellview, renderer));
-
- g_object_ref (G_OBJECT (renderer));
- gtk_object_sink (GTK_OBJECT (renderer));
-
- info = g_new0 (GtkCellViewCellInfo, 1);
- info->cell = renderer;
- info->expand = expand ? TRUE : FALSE;
- info->pack = GTK_PACK_END;
-
- cellview->priv->cell_list = g_list_append (cellview->priv->cell_list, info);
-}
-
-static void
-gtk_cell_view_cell_layout_add_attribute (GtkCellLayout *layout,
- GtkCellRenderer *renderer,
- const gchar *attribute,
- gint column)
-{
- GtkCellViewCellInfo *info;
- GtkCellView *cellview = GTK_CELL_VIEW (layout);
-
- g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
- info = gtk_cell_view_get_cell_info (cellview, renderer);
- g_return_if_fail (info != NULL);
-
- info->attributes = g_slist_prepend (info->attributes,
- GINT_TO_POINTER (column));
- info->attributes = g_slist_prepend (info->attributes,
- g_strdup (attribute));
-}
-
-static void
-gtk_cell_view_cell_layout_clear (GtkCellLayout *layout)
-{
- GtkCellView *cellview = GTK_CELL_VIEW (layout);
-
- g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
-
- while (cellview->priv->cell_list)
- {
- GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)cellview->priv->cell_list->data;
-
- gtk_cell_view_cell_layout_clear_attributes (layout, info->cell);
- g_object_unref (G_OBJECT (info->cell));
- g_free (info);
- cellview->priv->cell_list = g_list_delete_link (cellview->priv->cell_list,
- cellview->priv->cell_list);
- }
-}
-
-static void
-gtk_cell_view_cell_layout_set_cell_data_func (GtkCellLayout *layout,
- GtkCellRenderer *cell,
- GtkCellLayoutDataFunc func,
- gpointer func_data,
- GDestroyNotify destroy)
-{
- GtkCellView *cellview = GTK_CELL_VIEW (layout);
- GtkCellViewCellInfo *info;
-
- g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
-
- info = gtk_cell_view_get_cell_info (cellview, cell);
- g_return_if_fail (info != NULL);
-
- if (info->destroy)
- {
- GDestroyNotify d = info->destroy;
-
- info->destroy = NULL;
- d (info->func_data);
- }
-
- info->func = func;
- info->func_data = func_data;
- info->destroy = destroy;
-}
-
-static void
-gtk_cell_view_cell_layout_clear_attributes (GtkCellLayout *layout,
- GtkCellRenderer *renderer)
-{
- GtkCellViewCellInfo *info;
- GtkCellView *cellview = GTK_CELL_VIEW (layout);
- GSList *list;
-
- g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
- g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
-
- info = gtk_cell_view_get_cell_info (cellview, renderer);
- g_return_if_fail (info != NULL);
-
- list = info->attributes;
- while (list && list->next)
- {
- g_free (list->data);
- list = list->next->next;
- }
-
- g_slist_free (info->attributes);
- info->attributes = NULL;
-}
-
-static void
-gtk_cell_view_cell_layout_reorder (GtkCellLayout *layout,
- GtkCellRenderer *cell,
- gint position)
-{
- GList *link;
- GtkCellViewCellInfo *info;
- GtkCellView *cellview = GTK_CELL_VIEW (layout);
-
- g_return_if_fail (GTK_IS_CELL_VIEW (cellview));
- g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
-
- info = gtk_cell_view_get_cell_info (cellview, cell);
-
- g_return_if_fail (info != NULL);
- g_return_if_fail (position >= 0);
-
- link = g_list_find (cellview->priv->cell_list, info);
-
- g_return_if_fail (link != NULL);
-
- cellview->priv->cell_list = g_list_remove_link (cellview->priv->cell_list,
- link);
- cellview->priv->cell_list = g_list_insert (cellview->priv->cell_list,
- info, position);
-
- gtk_widget_queue_draw (GTK_WIDGET (cellview));
-}
-
-/* public API */
-GtkWidget *
-gtk_cell_view_new (void)
-{
- GtkCellView *cellview;
-
- cellview = GTK_CELL_VIEW (g_object_new (gtk_cell_view_get_type (), NULL));
-
- return GTK_WIDGET (cellview);
-}
-
-GtkWidget *
-gtk_cell_view_new_with_text (const gchar *text)
-{
- GtkCellView *cellview;
- GtkCellRenderer *renderer;
- GValue value = {0, };
-
- cellview = GTK_CELL_VIEW (gtk_cell_view_new ());
-
- renderer = gtk_cell_renderer_text_new ();
- gtk_cell_view_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview),
- renderer, TRUE);
-
- g_value_init (&value, G_TYPE_STRING);
- g_value_set_string (&value, text);
- gtk_cell_view_set_values (cellview, renderer, "text", &value, NULL);
- g_value_unset (&value);
-
- return GTK_WIDGET (cellview);
-}
-
-GtkWidget *
-gtk_cell_view_new_with_markup (const gchar *markup)
-{
- GtkCellView *cellview;
- GtkCellRenderer *renderer;
- GValue value = {0, };
-
- cellview = GTK_CELL_VIEW (gtk_cell_view_new ());
-
- renderer = gtk_cell_renderer_text_new ();
- gtk_cell_view_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview),
- renderer, TRUE);
-
- g_value_init (&value, G_TYPE_STRING);
- g_value_set_string (&value, markup);
- gtk_cell_view_set_values (cellview, renderer, "markup", &value, NULL);
- g_value_unset (&value);
-
- return GTK_WIDGET (cellview);
-}
-
-GtkWidget *
-gtk_cell_view_new_with_pixbuf (GdkPixbuf *pixbuf)
-{
- GtkCellView *cellview;
- GtkCellRenderer *renderer;
- GValue value = {0, };
-
- cellview = GTK_CELL_VIEW (gtk_cell_view_new ());
-
- renderer = gtk_cell_renderer_pixbuf_new ();
- gtk_cell_view_cell_layout_pack_start (GTK_CELL_LAYOUT (cellview),
- renderer, TRUE);
-
- g_value_init (&value, GDK_TYPE_PIXBUF);
- g_value_set_object (&value, pixbuf);
- gtk_cell_view_set_values (cellview, renderer, "pixbuf", &value, NULL);
- g_value_unset (&value);
-
- return GTK_WIDGET (cellview);
-}
-
-void
-gtk_cell_view_set_value (GtkCellView *cell_view,
- GtkCellRenderer *renderer,
- gchar *property,
- GValue *value)
-{
- g_return_if_fail (GTK_IS_CELL_VIEW (cell_view));
- g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
-
- g_object_set_property (G_OBJECT (renderer), property, value);
-
- /* force resize and redraw */
- gtk_widget_queue_resize (GTK_WIDGET (cell_view));
- gtk_widget_queue_draw (GTK_WIDGET (cell_view));
-}
-
-static void
-gtk_cell_view_set_valuesv (GtkCellView *cell_view,
- GtkCellRenderer *renderer,
- va_list args)
-{
- gchar *attribute;
- GValue *value;
-
- attribute = va_arg (args, gchar *);
-
- while (attribute)
- {
- value = va_arg (args, GValue *);
- gtk_cell_view_set_value (cell_view, renderer, attribute, value);
- attribute = va_arg (args, gchar *);
- }
-}
-
-void
-gtk_cell_view_set_values (GtkCellView *cell_view,
- GtkCellRenderer *renderer,
- ...)
-{
- va_list args;
-
- g_return_if_fail (GTK_IS_CELL_VIEW (cell_view));
- g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
- g_return_if_fail (gtk_cell_view_get_cell_info (cell_view, renderer));
-
- va_start (args, renderer);
- gtk_cell_view_set_valuesv (cell_view, renderer, args);
- va_end (args);
-}
-
-void
-gtk_cell_view_set_model (GtkCellView *cell_view,
- GtkTreeModel *model)
-{
- g_return_if_fail (GTK_IS_CELL_VIEW (cell_view));
- g_return_if_fail (GTK_IS_TREE_MODEL (model));
-
- if (cell_view->priv->model)
- {
- if (cell_view->priv->displayed_row)
- gtk_tree_row_reference_free (cell_view->priv->displayed_row);
- cell_view->priv->displayed_row = NULL;
-
- g_object_unref (G_OBJECT (cell_view->priv->model));
- cell_view->priv->model = NULL;
- }
-
- cell_view->priv->model = model;
-
- if (cell_view->priv->model)
- g_object_ref (G_OBJECT (cell_view->priv->model));
-}
-
-/**
- * gtk_cell_view_set_displayed_row:
- * @cell_view: a #GtkCellView
- * @path: a #GtkTreePath or %NULL to unset.
- *
- * Sets the row of the model that is currently displayed
- * by the #GtkCellView. If the path is unset, then the
- * contents of the cellview "stick" at their last value;
- * this is not normally a desired result, but may be
- * a needed intermediate state if say, the model for
- * the #GtkCellView becomes temporarily empty.
- **/
-void
-gtk_cell_view_set_displayed_row (GtkCellView *cell_view,
- GtkTreePath *path)
-{
- g_return_if_fail (GTK_IS_CELL_VIEW (cell_view));
- g_return_if_fail (GTK_IS_TREE_MODEL (cell_view->priv->model));
-
- if (cell_view->priv->displayed_row)
- gtk_tree_row_reference_free (cell_view->priv->displayed_row);
-
- if (path)
- {
- cell_view->priv->displayed_row =
- gtk_tree_row_reference_new (cell_view->priv->model, path);
- }
- else
- cell_view->priv->displayed_row = NULL;
-
- /* force resize and redraw */
- gtk_widget_queue_resize (GTK_WIDGET (cell_view));
- gtk_widget_queue_draw (GTK_WIDGET (cell_view));
-}
-
-GtkTreePath *
-gtk_cell_view_get_displayed_row (GtkCellView *cell_view)
-{
- g_return_val_if_fail (GTK_IS_CELL_VIEW (cell_view), NULL);
-
- if (!cell_view->priv->displayed_row)
- return NULL;
-
- return gtk_tree_row_reference_get_path (cell_view->priv->displayed_row);
-}
-
-gboolean
-gtk_cell_view_get_size_of_row (GtkCellView *cell_view,
- GtkTreePath *path,
- GtkRequisition *requisition)
-{
- GtkTreeRowReference *tmp;
-
- g_return_val_if_fail (GTK_IS_CELL_VIEW (cell_view), FALSE);
- g_return_val_if_fail (path != NULL, FALSE);
- g_return_val_if_fail (requisition != NULL, FALSE);
-
- tmp = cell_view->priv->displayed_row;
- cell_view->priv->displayed_row =
- gtk_tree_row_reference_new (cell_view->priv->model, path);
-
- gtk_cell_view_size_request (GTK_WIDGET (cell_view), requisition);
-
- gtk_tree_row_reference_free (cell_view->priv->displayed_row);
- cell_view->priv->displayed_row = tmp;
-
- return TRUE;
-}
-
-void
-gtk_cell_view_set_background_color (GtkCellView *view,
- const GdkColor *color)
-{
- g_return_if_fail (GTK_IS_CELL_VIEW (view));
-
- if (color)
- {
- if (!view->priv->background_set)
- {
- view->priv->background_set = TRUE;
- g_object_notify (G_OBJECT (view), "background_set");
- }
-
- view->priv->background = *color;
- }
- else
- {
- if (view->priv->background_set)
- {
- view->priv->background_set = FALSE;
- g_object_notify (G_OBJECT (view), "background_set");
- }
- }
-}
-
-GList *
-gtk_cell_view_get_cell_renderers (GtkCellView *cell_view)
-{
- GList *retval = NULL, *list;
-
- g_return_val_if_fail (cell_view != NULL, NULL);
-
- for (list = cell_view->priv->cell_list; list; list = list->next)
- {
- GtkCellViewCellInfo *info = (GtkCellViewCellInfo *)list->data;
-
- retval = g_list_prepend (retval, info->cell);
- }
-
- return g_list_reverse (retval);
-}
-
-#endif /* GTK < 2.6 check */
diff --git a/panel-applet/gtkcellview.h b/panel-applet/gtkcellview.h
deleted file mode 100644
index 6004013b77..0000000000
--- a/panel-applet/gtkcellview.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* gtkcellview.h
- * Copyright (C) 2002, 2003 Kristian Rietveld <kris@gtk.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/* GtkCellView is public in GTK 2.6, but not in GTK 2.4. We can't include
- * this private copy of GtkCellView when using GTK 2.6 due to link-time errors.
- */
-
-#include <gtk/gtkversion.h>
-
-#if (GTK_MAJOR_VERSION <= 2 && GTK_MINOR_VERSION < 6)
-
-#ifndef __GTK_CELL_VIEW_H__
-#define __GTK_CELL_VIEW_H__
-
-#include <gtk/gtkwidget.h>
-#include <gtk/gtkcellrenderer.h>
-#include <gtk/gtktreemodel.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_CELL_VIEW (gtk_cell_view_get_type ())
-#define GTK_CELL_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_CELL_VIEW, GtkCellView))
-#define GTK_CELL_VIEW_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), GTK_TYPE_CELL_VIEW, GtkCellViewClass))
-#define GTK_IS_CELL_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_CELL_VIEW))
-#define GTK_IS_CELL_VIEW_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), GTK_TYPE_CELL_VIEW))
-#define GTK_CELL_VIEW_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), GTK_TYPE_CELL_VIEW, GtkCellViewClass))
-
-typedef struct _GtkCellView GtkCellView;
-typedef struct _GtkCellViewClass GtkCellViewClass;
-typedef struct _GtkCellViewPrivate GtkCellViewPrivate;
-
-struct _GtkCellView
-{
- GtkWidget parent_instance;
-
- /*< private >*/
- GtkCellViewPrivate *priv;
-};
-
-struct _GtkCellViewClass
-{
- GtkWidgetClass parent_class;
-};
-
-GType gtk_cell_view_get_type (void);
-GtkWidget *gtk_cell_view_new (void);
-GtkWidget *gtk_cell_view_new_with_text (const gchar *text);
-GtkWidget *gtk_cell_view_new_with_markup (const gchar *markup);
-GtkWidget *gtk_cell_view_new_with_pixbuf (GdkPixbuf *pixbuf);
-
-
-void gtk_cell_view_set_value (GtkCellView *cell_view,
- GtkCellRenderer *renderer,
- gchar *property,
- GValue *value);
-void gtk_cell_view_set_values (GtkCellView *cell_view,
- GtkCellRenderer *renderer,
- ...);
-
-void gtk_cell_view_set_model (GtkCellView *cell_view,
- GtkTreeModel *model);
-void gtk_cell_view_set_displayed_row (GtkCellView *cell_view,
- GtkTreePath *path);
-GtkTreePath *gtk_cell_view_get_displayed_row (GtkCellView *cell_view);
-gboolean gtk_cell_view_get_size_of_row (GtkCellView *cell_view,
- GtkTreePath *path,
- GtkRequisition *requisition);
-
-void gtk_cell_view_set_background_color (GtkCellView *cell_view,
- const GdkColor *color);
-void gtk_cell_view_set_cell_data (GtkCellView *cellview);
-GList *gtk_cell_view_get_cell_renderers (GtkCellView *cellview);
-
-G_END_DECLS
-
-#endif /* __GTK_CELL_VIEW_H__ */
-
-
-#endif /* GTK < 2.6 check */
diff --git a/panel-applet/icons/Makefile.am b/panel-applet/icons/Makefile.am
index 160e7b1fd8..5fddd90db7 100644
--- a/panel-applet/icons/Makefile.am
+++ b/panel-applet/icons/Makefile.am
@@ -7,6 +7,7 @@ largeicon_DATA=\
smallicondir=${datadir}/icons/hicolor/22x22/apps
smallicon_DATA= \
+ nm-no-connection.png\
nm-device-wired.png \
nm-adhoc.png \
nm-connecting01.png \
diff --git a/panel-applet/icons/nm-no-connection.png b/panel-applet/icons/nm-no-connection.png
new file mode 100644
index 0000000000..f9cd02c4cb
--- /dev/null
+++ b/panel-applet/icons/nm-no-connection.png
Binary files differ
diff --git a/panel-applet/menu-info.c b/panel-applet/menu-info.c
index 81229b1768..281bd3beeb 100644
--- a/panel-applet/menu-info.c
+++ b/panel-applet/menu-info.c
@@ -33,13 +33,8 @@
#include <stdio.h>
#include <glib/gi18n.h>
#include <string.h>
-#include "menu-info.h"
-
-#if (GTK_MAJOR_VERSION <= 2 && GTK_MINOR_VERSION < 6)
-#include "gtkcellview.h"
-#include "gtkcellrendererprogress.h"
-#endif
+#include "menu-info.h"
#include "NMWirelessAppletDbus.h"
@@ -97,7 +92,7 @@ void wired_menu_item_update (NMWiredMenuItem *item, NetworkDevice *dev, const gi
/* Only dim the item if the device supports carrier detection AND
* we know it doesn't have a link.
*/
- if (dev->supports_carrier_detect == TRUE)
+ if (dev->driver_support_level != NM_DRIVER_NO_CARRIER_DETECT)
gtk_widget_set_sensitive (GTK_WIDGET (item->check_item), dev->link);
}
@@ -180,9 +175,8 @@ struct NMNetworkMenuItem
{
GtkCheckMenuItem *check_item;
GtkLabel *label;
- GtkWidget *cell_view;
+ GtkWidget *progress;
GtkWidget *security_image;
- GObject *progress_bar;
};
@@ -190,6 +184,11 @@ NMNetworkMenuItem *network_menu_item_new (GtkSizeGroup *encryption_size_group)
{
GtkWidget *hbox;
NMNetworkMenuItem *item = g_malloc0 (sizeof (NMNetworkMenuItem));
+ PangoFontDescription *fontdesc;
+ PangoFontMetrics *metrics;
+ PangoContext *context;
+ PangoLanguage *lang;
+ int ascent;
g_return_val_if_fail (item != NULL, NULL);
@@ -205,15 +204,25 @@ NMNetworkMenuItem *network_menu_item_new (GtkSizeGroup *encryption_size_group)
gtk_container_add (GTK_CONTAINER (item->check_item), hbox);
gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (item->label), TRUE, TRUE, 0);
- item->cell_view = gtk_cell_view_new ();
- item->progress_bar = g_object_new (GTK_TYPE_CELL_RENDERER_PROGRESS, "text", "", NULL);
- gtk_cell_renderer_set_fixed_size (GTK_CELL_RENDERER (item->progress_bar), 150, -1);
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (item->cell_view), GTK_CELL_RENDERER (item->progress_bar), TRUE);
- gtk_box_pack_start (GTK_BOX (hbox), item->cell_view, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (hbox), item->security_image, FALSE, FALSE, 0);
+ item->progress = gtk_progress_bar_new ();
+
+ /* get the font ascent for the current font and language */
+ context = gtk_widget_get_pango_context (item->progress);
+ fontdesc = pango_context_get_font_description (context);
+ lang = pango_context_get_language (context);
+ metrics = pango_context_get_metrics (context, fontdesc, lang);
+ ascent = pango_font_metrics_get_ascent (metrics) * 1.5 / PANGO_SCALE;
+ pango_font_metrics_unref (metrics);
+
+ /* size our progress bar to be five ascents long, one high */
+ gtk_widget_set_size_request (item->progress, ascent * 5, -1);
+
+ gtk_box_pack_end (GTK_BOX (hbox), item->progress, FALSE, TRUE, 0);
+
gtk_widget_show (GTK_WIDGET (item->label));
- gtk_widget_show (item->cell_view);
+ gtk_widget_show (item->progress);
gtk_widget_show (hbox);
return item;
@@ -232,6 +241,7 @@ GtkCheckMenuItem *network_menu_item_get_check_item (NMNetworkMenuItem *item)
void network_menu_item_update (NMNetworkMenuItem *item, WirelessNetwork *network, const gboolean is_encrypted)
{
char *display_essid;
+ gdouble percent;
g_return_if_fail (item != NULL);
g_return_if_fail (network != NULL);
@@ -240,7 +250,8 @@ void network_menu_item_update (NMNetworkMenuItem *item, WirelessNetwork *network
gtk_label_set_text (GTK_LABEL (item->label), display_essid);
g_free (display_essid);
- g_object_set (G_OBJECT (item->progress_bar), "value", CLAMP ((int) network->strength, 0, 100), NULL);
+ percent = (double) CLAMP (network->strength, 0, 100) / 100.0;
+ gtk_progress_set_percentage (GTK_PROGRESS (item->progress), percent);
/* Deal with the encrypted icon */
g_object_set (item->security_image, "visible", is_encrypted, NULL);
diff --git a/panel-applet/wireless-applet.glade b/panel-applet/wireless-applet.glade
index 43dbdead39..f06f482048 100644
--- a/panel-applet/wireless-applet.glade
+++ b/panel-applet/wireless-applet.glade
@@ -153,4 +153,518 @@ You have chosen log in to the wireless network '%s'. If you are sure this wirel
</child>
</widget>
+<widget class="GtkDialog" id="driver_sucks_dialog">
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes"> </property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_CENTER_ALWAYS</property>
+ <property name="modal">True</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="has_separator">False</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="vbox2">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="hbuttonbox1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+ <child>
+ <widget class="GtkButton" id="ok_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">_OK</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">-5</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox2">
+ <property name="border_width">6</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+
+ <child>
+ <widget class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="stock">gtk-dialog-warning</property>
+ <property name="icon_size">6</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox3">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+
+ <child>
+ <widget class="GtkLabel" id="driver_sucks_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;span weight=&quot;bold&quot; size=&quot;larger&quot;&gt;Reduced Network Functionality&lt;/span&gt;
+
+%s It will not be completely functional.</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">True</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="dont_remind_checkbox">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Don't remind me again</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkDialog" id="custom_essid_dialog">
+ <property name="border_width">6</property>
+ <property name="visible">True</property>
+ <property name="title" translatable="yes"></property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="default_width">488</property>
+ <property name="resizable">False</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="has_separator">False</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">4</property>
+
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+ <child>
+ <widget class="GtkButton" id="cancel_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-cancel</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">-6</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="ok_button">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">C_onnect</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">-5</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox1">
+ <property name="border_width">6</property>
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+
+ <child>
+ <widget class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="stock">gtk-dialog-question</property>
+ <property name="icon_size">6</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">12</property>
+
+ <child>
+ <widget class="GtkLabel" id="essid_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">True</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">True</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkTable" id="table1">
+ <property name="visible">True</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">2</property>
+ <property name="homogeneous">False</property>
+ <property name="row_spacing">12</property>
+ <property name="column_spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="wireless_adapter_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Wireless _adapter:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">wireless_adapter_combo</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkComboBox" id="wireless_adapter_combo">
+ <property name="visible">True</property>
+ <property name="items" translatable="yes"></property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Wireless _network:</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="mnemonic_widget">essid_entry</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="essid_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">3</property>
+ <property name="bottom_padding">6</property>
+ <property name="left_padding">6</property>
+ <property name="right_padding">6</property>
+
+ <child>
+ <widget class="GtkTable" id="table2">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">3</property>
+ <property name="homogeneous">False</property>
+ <property name="row_spacing">12</property>
+ <property name="column_spacing">6</property>
+
+ <child>
+ <widget class="GtkLabel" id="key_type_combo_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Key type:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="passphrase_entry_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Passphrase:</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkEntry" id="passphrase_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="editable">True</property>
+ <property name="visibility">True</property>
+ <property name="max_length">0</property>
+ <property name="text" translatable="yes"></property>
+ <property name="has_frame">True</property>
+ <property name="invisible_char" translatable="yes">*</property>
+ <property name="activates_default">False</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkComboBox" id="key_type_combo">
+ <property name="visible">True</property>
+ <property name="items" translatable="yes">128-bit passphrase (WEP)
+Ascii key (WEP)
+Hex key (WEP)</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">0</property>
+ <property name="bottom_attach">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options">fill</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkCheckButton" id="use_encryption_checkbox">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Connect with encryption enabled</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">fill</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
</glade-interface>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index eeb75de2f5..8aec20d7ae 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -9,3 +9,6 @@ panel-applet/NMWirelessAppletOtherNetworkDialog.c
panel-applet/essid.glade
panel-applet/menu-info.c
examples/python/systray/eggtrayicon.c
+panel-applet/NMWirelessApplet.xml
+panel-applet/eggtrayicon.c
+panel-applet/wireless-applet.glade
diff --git a/src/Makefile.am b/src/Makefile.am
index 2da17f00cd..47a311523b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -51,6 +51,7 @@ NetworkManager_CPPFLAGS = \
-DG_DISABLE_DEPRECATED \
-DBINDIR=\"$(bindir)\" \
-DDATADIR=\"$(datadir)\" \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
-DARP_DEBUG
if WITH_GCRYPT
NetworkManager_CPPFLAGS += $(LIBGCRYPT_CFLAGS)
diff --git a/src/NetworkManager.c b/src/NetworkManager.c
index 558c19eb6d..5fc89e4dec 100644
--- a/src/NetworkManager.c
+++ b/src/NetworkManager.c
@@ -182,14 +182,13 @@ void nm_remove_device_from_list (NMData *data, const char *udi)
nm_device_set_removed (dev, TRUE);
nm_device_deactivate (dev, FALSE);
nm_device_worker_thread_stop (dev);
+ nm_dbus_signal_device_status_change (data->dbus_connection, dev, DEVICE_LIST_CHANGE);
nm_device_unref (dev);
/* Remove the device entry from the device list and free its data */
data->dev_list = g_slist_remove_link (data->dev_list, elt);
- nm_device_unref (elt->data);
g_slist_free (elt);
nm_policy_schedule_state_update (data);
- nm_dbus_signal_device_status_change (data->dbus_connection, dev, DEVICE_LIST_CHANGE);
break;
}
}
@@ -413,6 +412,32 @@ void nm_schedule_status_signal_broadcast (NMData *data)
}
+void nm_wireless_link_state_handle (NMDevice *dev, NMData *data)
+{
+ g_return_if_fail (dev != NULL);
+ g_return_if_fail (data != NULL);
+
+ if (!nm_device_get_link_active (dev))
+ {
+ if ( nm_device_get_supports_wireless_scan (dev)
+ && !data->forcing_device
+ && data->state_modified_idle_id == 0)
+ {
+ nm_device_update_best_ap (dev);
+ }
+ else
+ {
+ /* If we loose a link to the access point, then
+ * look for another access point to connect to.
+ */
+ if ( !nm_device_is_activating (dev)
+ && !data->forcing_device
+ && data->state_modified_idle_id == 0)
+ nm_device_update_best_ap (dev);
+ }
+ }
+}
+
/*
* nm_link_state_monitor
*
@@ -423,52 +448,52 @@ void nm_schedule_status_signal_broadcast (NMData *data)
gboolean nm_link_state_monitor (gpointer user_data)
{
NMData *data = (NMData *)user_data;
+ GSList *elt;
g_return_val_if_fail (data != NULL, TRUE);
+ if ((data->wireless_enabled == FALSE) || (data->asleep == TRUE))
+ return (TRUE);
+
/* Attempt to acquire mutex for device list iteration.
* If the acquire fails, just ignore the device deletion entirely.
*/
- if (nm_try_acquire_mutex (data->dev_list_mutex, __FUNCTION__))
+ if (!nm_try_acquire_mutex (data->dev_list_mutex, __FUNCTION__))
{
- GSList *elt;
- for (elt = data->dev_list; elt; elt = g_slist_next (elt))
+ syslog(LOG_ERR, "nm_link_state_monitor() could not acquire device list mutex.");
+ return TRUE;
+ }
+
+ for (elt = data->dev_list; elt; elt = g_slist_next (elt))
+ {
+ NMDevice *dev = (NMDevice *)(elt->data);
+
+ if (dev)
{
- NMDevice *dev = (NMDevice *)(elt->data);
+ if (!nm_device_is_up (dev))
+ nm_device_bring_up (dev);
+ nm_device_update_link_active (dev);
- if (dev)
+ if (dev == data->active_device)
{
- if (!nm_device_is_up (dev))
- nm_device_bring_up (dev);
- nm_device_update_link_active (dev);
-
- if (dev == data->active_device)
- {
- if (nm_device_is_wireless (dev) && !nm_device_get_link_active (dev))
- {
- /* If we loose a link to the access point, then
- * look for another access point to connect to.
- */
- nm_device_update_best_ap (dev);
- }
- }
- else
- {
- /* Ensure that the device has no IP address or routes. This will
- * sometimes occur when a card gets inserted, and the system
- * initscripts will run to bring the card up, but they get around to
- * running _after_ we've been notified of insertion and cleared out
- * card info already.
- */
- nm_system_device_flush_routes (dev);
- if (nm_device_get_ip4_address (dev) != 0)
- nm_system_device_flush_addresses (dev);
- }
+ if (nm_device_is_wireless (dev))
+ nm_wireless_link_state_handle (dev, data);
+ }
+ else
+ {
+ /* Ensure that the device has no IP address or routes. This will
+ * sometimes occur when a card gets inserted, and the system
+ * initscripts will run to bring the card up, but they get around to
+ * running _after_ we've been notified of insertion and cleared out
+ * card info already.
+ */
+ nm_system_device_flush_routes (dev);
+ if (nm_device_get_ip4_address (dev) != 0)
+ nm_system_device_flush_addresses (dev);
}
}
-
- nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__);
- } else syslog( LOG_ERR, "nm_link_state_monitor() could not acquire device list mutex." );
+ }
+ nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__);
return (TRUE);
}
@@ -552,7 +577,7 @@ static NMData *nm_data_new (gboolean enable_test_devices)
data->enable_test_devices = enable_test_devices;
- data->scanning_enabled = TRUE;
+ data->scanning_method = NM_SCAN_METHOD_ALWAYS;
data->wireless_enabled = TRUE;
nm_policy_schedule_state_update (data);
@@ -585,14 +610,18 @@ static void nm_data_free (NMData *data)
g_main_loop_unref (data->main_loop);
g_main_context_unref (data->main_context);
+ g_io_channel_unref(data->sigterm_iochannel);
+
memset (data, 0, sizeof (NMData));
}
static void sigterm_handler (int signum)
{
+ int ignore;
+
syslog (LOG_NOTICE, "Caught SIGINT/SIGTERM");
- write (nm_data->sigterm_pipe[1], "X", 1);
+ ignore = write (nm_data->sigterm_pipe[1], "X", 1);
}
static gboolean sigterm_pipe_handler (GIOChannel *src, GIOCondition condition, gpointer user_data)
@@ -730,7 +759,10 @@ int main( int argc, char *argv[] )
/* If NMI is running, grab allowed wireless network lists from it ASAP */
if (nm_dbus_is_info_daemon_running (nm_data->dbus_connection))
+ {
nm_policy_schedule_allowed_ap_list_update (nm_data);
+ nm_dbus_update_wireless_scan_method (nm_data->dbus_connection, nm_data);
+ }
/* Right before we init hal, we have to make sure our mainloop integration function
* knows about our GMainContext. HAL doesn't give us any way to pass that into its
@@ -776,6 +808,8 @@ int main( int argc, char *argv[] )
/* Kill the watch functions */
g_source_remove (link_source_id);
+ nm_print_open_socks ();
+
/* Cleanup */
if (hal_shutdown (nm_data->hal_ctx) != 0)
syslog (LOG_NOTICE, "Error: libhal shutdown failed");
diff --git a/src/NetworkManagerAP.c b/src/NetworkManagerAP.c
index 0bb80b5fee..f679c68f72 100644
--- a/src/NetworkManagerAP.c
+++ b/src/NetworkManagerAP.c
@@ -279,7 +279,7 @@ void nm_ap_set_encrypted (NMAccessPoint *ap, gboolean encrypted)
* Return the encryption method the user specified for this access point.
*
*/
-const NMEncKeyType nm_ap_get_enc_type (const NMAccessPoint *ap)
+NMEncKeyType nm_ap_get_enc_type (const NMAccessPoint *ap)
{
g_return_val_if_fail (ap != NULL, TRUE);
diff --git a/src/NetworkManagerAP.h b/src/NetworkManagerAP.h
index 2d32aee436..d190deb611 100644
--- a/src/NetworkManagerAP.h
+++ b/src/NetworkManagerAP.h
@@ -43,7 +43,7 @@ void nm_ap_set_essid (NMAccessPoint *ap, const char *essid);
char * nm_ap_get_enc_key_source (const NMAccessPoint *ap);
char * nm_ap_get_enc_key_hashed (const NMAccessPoint *ap);
void nm_ap_set_enc_key_source (NMAccessPoint *ap, const char *key, NMEncKeyType type);
-const NMEncKeyType nm_ap_get_enc_type (const NMAccessPoint *ap);
+NMEncKeyType nm_ap_get_enc_type (const NMAccessPoint *ap);
NMDeviceAuthMethod nm_ap_get_auth_method (const NMAccessPoint *ap);
void nm_ap_set_auth_method (NMAccessPoint *ap, const NMDeviceAuthMethod auth_method);
diff --git a/src/NetworkManagerAPList.c b/src/NetworkManagerAPList.c
index f641eed6af..7c7c7d78c6 100644
--- a/src/NetworkManagerAPList.c
+++ b/src/NetworkManagerAPList.c
@@ -115,6 +115,7 @@ void nm_ap_list_unref (NMAccessPointList *list)
nm_unlock_mutex (list->mutex, __FUNCTION__);
g_mutex_free (list->mutex);
+ g_free(list);
}
}
@@ -171,7 +172,7 @@ void nm_ap_list_remove_ap (NMAccessPointList *list, NMAccessPoint *ap)
if (!nm_ap_list_lock (list))
{
- syslog( LOG_ERR, "nm_ap_list_append_ap() could not acquire AP list mutex." );
+ syslog( LOG_ERR, "nm_ap_list_remove_ap() could not acquire AP list mutex." );
return;
}
@@ -192,6 +193,115 @@ void nm_ap_list_remove_ap (NMAccessPointList *list, NMAccessPoint *ap)
/*
+ * nm_ap_list_remove_ap_by_essid
+ *
+ * Helper to remove an AP from an AP list by the AP's ESSID.
+ *
+ */
+void nm_ap_list_remove_ap_by_essid (NMAccessPointList *list, const char *network)
+{
+ GSList *elt = NULL;
+
+ g_return_if_fail (list != NULL);
+ g_return_if_fail (network != NULL);
+
+ if (!nm_ap_list_lock (list))
+ {
+ syslog (LOG_WARNING, "nm_ap_list_remove_ap_by_essid() could not acquire AP list mutex." );
+ return;
+ }
+
+ for (elt = list->ap_list; elt; elt = g_slist_next (elt))
+ {
+ NMAccessPoint *list_ap = (NMAccessPoint *)(elt->data);
+
+ if (nm_null_safe_strcmp (nm_ap_get_essid (list_ap), network) == 0)
+ {
+ list->ap_list = g_slist_remove_link (list->ap_list, elt);
+ nm_ap_unref (list_ap);
+ g_slist_free (elt);
+ break;
+ }
+ }
+ nm_ap_list_unlock (list);
+}
+
+/* nm_ap_list_remove_duplicate_essids
+ *
+ */
+void nm_ap_list_remove_duplicate_essids (NMAccessPointList *list)
+{
+ NMAccessPoint *removal_ap;
+ NMAccessPoint *list_ap_max;
+ GSList *elt_i = NULL;
+ GSList *elt_j = NULL;
+ GSList *elt_max = NULL;
+ GSList *removal_list = NULL;
+ GSList *elt;
+ gint8 max_strength = 0;
+ gint8 strengthj = 0;
+
+ g_return_if_fail (list != NULL);
+
+ if (!nm_ap_list_lock (list))
+ {
+ syslog (LOG_WARNING, "nm_ap_list_append_ap() could not acquire AP list mutex." );
+ return;
+ }
+
+ for (elt_i = list->ap_list; elt_i; elt_i = g_slist_next (elt_i))
+ {
+ NMAccessPoint *list_ap_i = (NMAccessPoint *)(elt_i->data);
+ gboolean found = FALSE;
+
+ for (elt_j = list->ap_list; elt_j < elt_i; elt_j = g_slist_next (elt_j))
+ {
+ NMAccessPoint *list_ap_j = (NMAccessPoint *)(elt_j->data);
+
+ if ((found = (nm_null_safe_strcmp (nm_ap_get_essid (list_ap_i), nm_ap_get_essid (list_ap_j)) == 0)))
+ break;
+ }
+
+ if (found)
+ continue;
+
+ elt_max = elt_i;
+ list_ap_max = (NMAccessPoint *)(elt_i->data);
+ max_strength = nm_ap_get_strength (list_ap_i);
+
+ for (elt_j = g_slist_next (elt_i); elt_j; elt_j = g_slist_next (elt_j))
+ {
+ NMAccessPoint *list_ap_j = (NMAccessPoint *)(elt_j->data);
+
+ strengthj = nm_ap_get_strength (list_ap_j);
+ if (nm_null_safe_strcmp (nm_ap_get_essid (list_ap_i), nm_ap_get_essid (list_ap_j)) == 0)
+ {
+ if (strengthj > max_strength)
+ {
+ removal_list = g_slist_append (removal_list, list_ap_max);
+ list_ap_max = list_ap_j;
+ max_strength = strengthj;
+ }
+ else
+ removal_list = g_slist_append (removal_list, list_ap_j);
+ }
+ }
+ }
+ nm_ap_list_unlock (list);
+
+ for (elt = removal_list; elt; elt = g_slist_next (elt))
+ {
+ if ((removal_ap = (NMAccessPoint *)(elt->data)))
+ {
+ nm_ap_list_remove_ap (list, removal_ap);
+ }
+ }
+ g_slist_free (removal_list);
+
+}
+
+
+/*
* nm_ap_list_get_ap_by_essid
*
* Search through an access point list and return the access point
@@ -380,49 +490,68 @@ void nm_ap_list_populate_from_nmi (NMAccessPointList *list, NMData *data)
gboolean nm_ap_list_merge_scanned_ap (NMAccessPointList *list, NMAccessPoint *merge_ap,
gboolean *new, gboolean *strength_changed)
{
- NMAccessPoint *list_ap;
- gboolean success = FALSE;
+ NMAccessPoint *list_ap_addr, *list_ap_essid;
g_return_val_if_fail (list != NULL, FALSE);
g_return_val_if_fail (merge_ap != NULL, FALSE);
g_return_val_if_fail (new != NULL, FALSE);
g_return_val_if_fail (strength_changed != NULL, FALSE);
- if (!(list_ap = nm_ap_list_get_ap_by_address (list, nm_ap_get_address (merge_ap))))
- list_ap = nm_ap_list_get_ap_by_essid (list, nm_ap_get_essid (merge_ap));
-
- if (list_ap)
+ if ((list_ap_addr = nm_ap_list_get_ap_by_address (list, nm_ap_get_address (merge_ap))))
{
- const GTimeVal *merge_ap_seen = nm_ap_get_last_seen (merge_ap);
- const GTimeVal *list_ap_seen = nm_ap_get_last_seen (list_ap);
-
- /* Merge some properties on the AP that are new from scan to scan. */
- nm_ap_set_encrypted (list_ap, nm_ap_get_encrypted (merge_ap));
- nm_ap_set_auth_method (list_ap, nm_ap_get_auth_method (merge_ap));
-
- /* Don't update the strength on the existing AP if the timestamp is
- * the same as the AP we're going to merge (which means that they were
- * found in the same scan, have the same ESSID, but are different APs)
- * and the existing AP's strength is greater than the one we're about
- * to merge. This helps keep the ESSID's reported strength that of the
- * strongest AP we can see.
- */
- if (!( (list_ap_seen->tv_sec == merge_ap_seen->tv_sec)
- && (nm_ap_get_strength (list_ap) > nm_ap_get_strength (merge_ap))))
+
+ /* First, we check for an address match. If the merge AP has the
+ * same address as a list AP, the merge AP and the list AP
+ * must be the same physical AP. The list AP properties must be from
+ * a previous scan so the time_last_seen's are not equal.
+ * Update encryption, authentication method,
+ * strength, and the time_last_seen. */
+
+ const GTimeVal *merge_ap_seen = nm_ap_get_last_seen (merge_ap);
+
+ nm_ap_set_encrypted (list_ap_addr, nm_ap_get_encrypted (merge_ap));
+ nm_ap_set_auth_method (list_ap_addr, nm_ap_get_auth_method (merge_ap));
+ if (nm_ap_get_strength (merge_ap) != nm_ap_get_strength (list_ap_addr))
{
- nm_ap_set_strength (list_ap, nm_ap_get_strength (merge_ap));
+ nm_ap_set_strength (list_ap_addr, nm_ap_get_strength (merge_ap));
*strength_changed = TRUE;
}
+ nm_ap_set_last_seen (list_ap_addr, merge_ap_seen);
+ }
+ else if ((list_ap_essid = nm_ap_list_get_ap_by_essid (list, nm_ap_get_essid (merge_ap))))
+ {
- nm_ap_set_last_seen (list_ap, merge_ap_seen);
+ /* Second, we check for an ESSID match. In this case,
+ * a list AP has the same non-NULL ESSID as the merge AP. Update the
+ * encryption and authentication method. Update the strength and address
+ * except when the time_last_seen of the list AP is the same as the
+ * time_last_seen of the merge AP and the strength of the list AP is greater
+ * than or equal to the strength of the merge AP. If the time_last_seen's are
+ * equal, the merge AP and the list AP come from the same scan.
+ * Update the time_last_seen. */
+
+ const GTimeVal *merge_ap_seen = nm_ap_get_last_seen (merge_ap);
+ const GTimeVal *list_ap_essid_seen = nm_ap_get_last_seen (list_ap_essid);
+
+ nm_ap_set_encrypted (list_ap_essid, nm_ap_get_encrypted (merge_ap));
+ nm_ap_set_auth_method (list_ap_essid, nm_ap_get_auth_method (merge_ap));
+
+ if (!((list_ap_essid_seen->tv_sec == merge_ap_seen->tv_sec)
+ && (nm_ap_get_strength (list_ap_essid) >= nm_ap_get_strength (merge_ap))))
+ {
+ nm_ap_set_strength (list_ap_essid, nm_ap_get_strength (merge_ap));
+ nm_ap_set_address (list_ap_essid, nm_ap_get_address (merge_ap));
+ *strength_changed = TRUE;
+ }
+ nm_ap_set_last_seen (list_ap_essid, merge_ap_seen);
}
else
{
- /* Add the whole AP, list takes ownership. */
+ /* Add the merge AP to the list. */
+
nm_ap_list_append_ap (list, merge_ap);
*new = TRUE;
}
-
return TRUE;
}
@@ -700,9 +829,16 @@ void nm_ap_list_print_members (NMAccessPointList *list, const char *name)
while ((ap = nm_ap_list_iter_next (iter)))
{
const GTimeVal *timestamp = nm_ap_get_timestamp (ap);
- syslog (LOG_ERR, "\t%d)\tobj=%p, essid='%s', timestamp=%ld, key='%s', enc=%d, addr=%p, strength=%d, %s=%f, rate=%d, inval=%d, mode=%d",
+ const struct ether_addr *addr;
+ char char_addr[20];
+
+ addr = nm_ap_get_address (ap);
+ memset (char_addr, 0, 20);
+ ether_ntoa_r (addr, &char_addr[0]);
+
+ syslog (LOG_ERR, "\t%d)\tobj=%p, essid='%s', timestamp=%ld, key='%s', enc=%d, addr='%s', strength=%d, %s=%f, rate=%d, inval=%d, mode=%d",
i, ap, nm_ap_get_essid (ap), timestamp->tv_sec, nm_ap_get_enc_key_source (ap), nm_ap_get_encrypted (ap),
- nm_ap_get_address (ap), nm_ap_get_strength (ap), (nm_ap_get_freq (ap) < 20) ? "channel" : "freq", nm_ap_get_freq (ap), nm_ap_get_rate (ap),
+ char_addr, nm_ap_get_strength (ap), (nm_ap_get_freq (ap) < 20) ? "channel" : "freq", nm_ap_get_freq (ap), nm_ap_get_rate (ap),
nm_ap_get_invalid (ap), nm_ap_get_mode (ap));
i++;
}
diff --git a/src/NetworkManagerAPList.h b/src/NetworkManagerAPList.h
index 2a8add99c8..fa68275ca0 100644
--- a/src/NetworkManagerAPList.h
+++ b/src/NetworkManagerAPList.h
@@ -38,6 +38,8 @@ gboolean nm_ap_list_is_empty (NMAccessPointList *list);
void nm_ap_list_append_ap (NMAccessPointList *list, NMAccessPoint *ap);
void nm_ap_list_remove_ap (NMAccessPointList *list, NMAccessPoint *ap);
+void nm_ap_list_remove_ap_by_essid (NMAccessPointList *list, const char *network);
+void nm_ap_list_remove_duplicate_essids (NMAccessPointList *list);
NMAccessPoint * nm_ap_list_get_ap_by_essid (NMAccessPointList *list, const char *network);
NMAccessPoint * nm_ap_list_get_ap_by_address (NMAccessPointList *list, const struct ether_addr *addr);
diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c
index 639086437c..fd58ae4ab8 100644
--- a/src/NetworkManagerDbus.c
+++ b/src/NetworkManagerDbus.c
@@ -325,6 +325,8 @@ char *nm_dbus_network_status_from_data (NMData *data)
g_return_val_if_fail (data != NULL, NULL);
+ if (data->asleep == TRUE)
+ status = g_strdup ("asleep");
if (data->forcing_device)
status = g_strdup ("scanning");
else if (data->active_device && nm_device_is_activating (data->active_device))
@@ -422,7 +424,6 @@ void nm_dbus_signal_wireless_network_change (DBusConnection *connection, NMDevic
DBusMessage *message;
char *dev_path;
char *ap_path;
- const char *signal;
g_return_if_fail (connection != NULL);
g_return_if_fail (dev != NULL);
@@ -648,6 +649,44 @@ out:
/*
+ * nm_dbus_update_wireless_scan_method
+ *
+ * Get the wireless scan method from NetworkManagerInfo
+ *
+ */
+void nm_dbus_update_wireless_scan_method (DBusConnection *connection, NMData *data)
+{
+ DBusMessage * message = NULL;
+ DBusMessage * reply = NULL;
+
+ g_return_if_fail (connection != NULL);
+ g_return_if_fail (data != NULL);
+
+ if (!(message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH, NMI_DBUS_INTERFACE, "getWirelessScanMethod")))
+ {
+ syslog (LOG_WARNING, "nm_dbus_update_wireless_scan_method(): Couldn't allocate the dbus message");
+ return;
+ }
+
+ if ((reply = dbus_connection_send_with_reply_and_block (connection, message, -1, NULL)))
+ {
+ NMWirelessScanMethod method;
+
+ if (dbus_message_get_args (reply, NULL, DBUS_TYPE_UINT32, &method, DBUS_TYPE_INVALID))
+ {
+ if ((method == NM_SCAN_METHOD_ALWAYS) || (method == NM_SCAN_METHOD_NEVER) || (method == NM_SCAN_METHOD_WHEN_UNASSOCIATED))
+ data->scanning_method = method;
+ }
+ dbus_message_unref (reply);
+ }
+ else
+ syslog (LOG_WARNING, "nm_dbus_update_wireless_scan_method(): could not send dbus message");
+
+ dbus_message_unref (message);
+}
+
+
+/*
* nm_dbus_update_network_auth_method
*
* Tell NetworkManagerInfo the updated auth_method of the AP
@@ -841,19 +880,23 @@ static DBusHandlerResult nm_dbus_nmi_filter (DBusConnection *connection, DBusMes
dbus_error_init (&error);
- if ( (strcmp (object_path, NMI_DBUS_PATH) == 0)
- && dbus_message_is_signal (message, NMI_DBUS_INTERFACE, "WirelessNetworkUpdate"))
+ if (strcmp (object_path, NMI_DBUS_PATH) == 0)
{
- char *network = NULL;
-
- if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &network, DBUS_TYPE_INVALID))
+ if (dbus_message_is_signal (message, NMI_DBUS_INTERFACE, "WirelessNetworkUpdate"))
{
- /* Update a single wireless network's data */
- syslog (LOG_DEBUG, "NetworkManagerInfo triggered update of wireless network '%s'", network);
- nm_ap_list_update_network_from_nmi (data->allowed_ap_list, network, data);
- dbus_free (network);
- handled = TRUE;
+ char * network = NULL;
+
+ if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &network, DBUS_TYPE_INVALID))
+ {
+ /* Update a single wireless network's data */
+ syslog (LOG_DEBUG, "NetworkManagerInfo triggered update of wireless network '%s'", network);
+ nm_ap_list_update_network_from_nmi (data->allowed_ap_list, network, data);
+ dbus_free (network);
+ handled = TRUE;
+ }
}
+ else if (dbus_message_is_signal (message, NMI_DBUS_INTERFACE, "WirelessScanMethodUpdate"))
+ nm_dbus_update_wireless_scan_method (connection, data);
}
#if (DBUS_VERSION_MAJOR == 0 && DBUS_VERSION_MINOR == 22)
else if (dbus_message_is_signal (message, DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, "ServiceCreated"))
@@ -889,7 +932,10 @@ static DBusHandlerResult nm_dbus_nmi_filter (DBusConnection *connection, DBusMes
* "ServiceCreated" signal in dbus <= 0.22
*/
if (!old_owner_good && new_owner_good)
+ {
nm_policy_schedule_allowed_ap_list_update (data);
+ nm_dbus_update_wireless_scan_method (connection, data);
+ }
}
}
#else
@@ -1051,7 +1097,6 @@ gboolean nm_dbus_is_info_daemon_running (DBusConnection *connection)
DBusConnection *nm_dbus_init (NMData *data)
{
DBusError error;
- dbus_bool_t success;
DBusConnection *connection;
DBusObjectPathVTable nm_vtable = {NULL, &nm_dbus_nm_message_handler, NULL, NULL, NULL, NULL};
DBusObjectPathVTable devices_vtable = {NULL, &nm_dbus_devices_message_handler, NULL, NULL, NULL, NULL};
diff --git a/src/NetworkManagerDbus.h b/src/NetworkManagerDbus.h
index 9d7805b569..c7b27f9878 100644
--- a/src/NetworkManagerDbus.h
+++ b/src/NetworkManagerDbus.h
@@ -60,6 +60,8 @@ void nm_dbus_get_user_key_for_network (DBusConnection *connection, NMDevice *
void nm_dbus_cancel_get_user_key_for_network (DBusConnection *connection);
+void nm_dbus_update_wireless_scan_method (DBusConnection *connection, NMData *data);
+
NMAccessPoint *nm_dbus_get_network_object (DBusConnection *connection, NMNetworkType type, const char *network);
gboolean nm_dbus_add_network_address (DBusConnection *connection, NMNetworkType type, const char *network, struct ether_addr *addr);
diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c
index b3d6f2576d..a2f202f061 100644
--- a/src/NetworkManagerDevice.c
+++ b/src/NetworkManagerDevice.c
@@ -46,6 +46,8 @@ static gboolean nm_device_activation_configure_ip (NMDevice *dev, gboolean do_on
static gboolean nm_device_wireless_scan (gpointer user_data);
static gboolean supports_mii_carrier_detect (NMDevice *dev);
static gboolean supports_ethtool_carrier_detect (NMDevice *dev);
+static gboolean nm_device_bring_up_wait (NMDevice *dev, gboolean cancelable);
+static gboolean nm_device_activation_handle_cancel (NMDevice *dev);
typedef struct
{
@@ -53,6 +55,11 @@ typedef struct
struct wireless_scan_head scan_head;
} NMWirelessScanResults;
+typedef struct
+{
+ NMDevice *dev;
+ gboolean reschedule;
+} NMWirelessScanCB;
/******************************************************/
@@ -67,10 +74,10 @@ typedef struct
*/
static gboolean nm_device_test_wireless_extensions (NMDevice *dev)
{
- int sk;
- int err;
- char ioctl_buf[64];
-
+ int err = -1;
+ char ioctl_buf[64];
+ NMSock *sk;
+
g_return_val_if_fail (dev != NULL, FALSE);
/* We obviously cannot probe test devices (since they don't
@@ -80,11 +87,13 @@ static gboolean nm_device_test_wireless_extensions (NMDevice *dev)
return (FALSE);
ioctl_buf[63] = 0;
- strncpy(ioctl_buf, nm_device_get_iface(dev), 63);
+ strncpy (ioctl_buf, nm_device_get_iface(dev), 63);
- sk = iw_sockets_open ();
- err = ioctl(sk, SIOCGIWNAME, ioctl_buf);
- close (sk);
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
+ {
+ err = ioctl (nm_dev_sock_get_fd (sk), SIOCGIWNAME, ioctl_buf);
+ nm_dev_sock_close (sk);
+ }
return (err == 0);
}
@@ -97,24 +106,26 @@ static gboolean nm_device_test_wireless_extensions (NMDevice *dev)
*/
static gboolean nm_device_supports_wireless_scan (NMDevice *dev)
{
- int sk;
- int err;
- gboolean can_scan = TRUE;
- wireless_scan_head scan_data;
-
+ NMSock *sk;
+ int err;
+ gboolean can_scan = TRUE;
+ wireless_scan_head scan_data;
+
g_return_val_if_fail (dev != NULL, FALSE);
g_return_val_if_fail (dev->type == DEVICE_TYPE_WIRELESS_ETHERNET, FALSE);
/* A test wireless device can always scan (we generate fake scan data for it) */
if (dev->test_device)
return (TRUE);
-
- sk = iw_sockets_open ();
- err = iw_scan (sk, (char *)nm_device_get_iface (dev), WIRELESS_EXT, &scan_data);
- nm_dispose_scan_results (scan_data.result);
- if ((err == -1) && (errno == EOPNOTSUPP))
- can_scan = FALSE;
- close (sk);
+
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
+ {
+ err = iw_scan (nm_dev_sock_get_fd (sk), (char *)nm_device_get_iface (dev), WIRELESS_EXT, &scan_data);
+ nm_dispose_scan_results (scan_data.result);
+ if ((err == -1) && (errno == EOPNOTSUPP))
+ can_scan = FALSE;
+ nm_dev_sock_close (sk);
+ }
return (can_scan);
}
@@ -189,6 +200,50 @@ NMDevice *nm_get_device_by_iface (NMData *data, const char *iface)
/* NMDevice object routines */
/*****************************************************************************/
+
+/*
+ * nm_device_copy_allowed_to_dev_list
+ *
+ * For devices that don't support wireless scanning, copy
+ * the allowed AP list to the device's ap list.
+ *
+ */
+void nm_device_copy_allowed_to_dev_list (NMDevice *dev, NMAccessPointList *allowed_list)
+{
+ NMAPListIter *iter;
+ NMAccessPoint *src_ap;
+ NMAccessPointList *dev_list;
+
+ g_return_if_fail (dev != NULL);
+
+ if (allowed_list == NULL)
+ return;
+
+ nm_device_ap_list_clear (dev);
+ dev->options.wireless.ap_list = nm_ap_list_new (NETWORK_TYPE_ALLOWED);
+
+ if (!(iter = nm_ap_list_iter_new (allowed_list)))
+ return;
+
+ dev_list = nm_device_ap_list_get (dev);
+ while ((src_ap = nm_ap_list_iter_next (iter)))
+ {
+ NMAccessPoint *dst_ap = nm_ap_new_from_ap (src_ap);
+
+ /* Assume that if the allowed list AP has a saved encryption
+ * key that the AP is encrypted.
+ */
+ if ( (nm_ap_get_auth_method (src_ap) == NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM)
+ || (nm_ap_get_auth_method (src_ap) == NM_DEVICE_AUTH_METHOD_SHARED_KEY))
+ nm_ap_set_encrypted (dst_ap, TRUE);
+
+ nm_ap_list_append_ap (dev_list, dst_ap);
+ nm_ap_unref (dst_ap);
+ }
+ nm_ap_list_iter_free (iter);
+}
+
+
/*
* nm_device_new
*
@@ -201,6 +256,8 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev,
{
NMDevice *dev;
GError *error = NULL;
+ char *msg;
+ nm_completion_args args;
g_return_val_if_fail (iface != NULL, NULL);
g_return_val_if_fail (strlen (iface) > 0, NULL);
@@ -250,14 +307,12 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev,
goto err;
/* Have to bring the device up before checking link status and other stuff */
- nm_device_bring_up (dev);
- g_usleep (G_USEC_PER_SEC);
- dev->driver_support_level = nm_get_driver_support_level (dev->app_data->hal_ctx, dev);
+ nm_device_bring_up_wait (dev, 0);
/* Initialize wireless-specific options */
if (nm_device_is_wireless (dev))
{
- int sk;
+ NMSock *sk;
NMDeviceWirelessOptions *opts = &(dev->options.wireless);
nm_device_set_mode (dev, NETWORK_MODE_INFRA);
@@ -275,10 +330,16 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev,
opts->supports_wireless_scan = nm_device_supports_wireless_scan (dev);
- if ((sk = iw_sockets_open ()) >= 0)
+ /* Non-scanning devices show the entire allowed AP list as their
+ * available networks.
+ */
+ if (opts->supports_wireless_scan == FALSE)
+ nm_device_copy_allowed_to_dev_list (dev, app_data->allowed_ap_list);
+
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
{
iwrange range;
- if (iw_get_range_info (sk, nm_device_get_iface (dev), &range) >= 0)
+ if (iw_get_range_info (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), &range) >= 0)
{
int i;
@@ -296,7 +357,7 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev,
for (i = 0; i < opts->num_freqs; i++)
opts->freqs[i] = iw_freq2float (&(range.freq[i]));
}
- close (sk);
+ nm_dev_sock_close (sk);
}
}
else if (nm_device_is_wired (dev))
@@ -305,6 +366,9 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev,
dev->options.wired.has_carrier_detect = TRUE;
}
+ /* Must be called after carrier detect or wireless scan detect. */
+ dev->driver_support_level = nm_get_driver_support_level (dev->app_data->hal_ctx, dev);
+
if (nm_device_get_driver_support_level (dev) != NM_DRIVER_UNSUPPORTED)
{
nm_device_update_link_active (dev);
@@ -316,7 +380,8 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev,
nm_system_device_update_config_info (dev);
}
- if (!g_thread_create (nm_device_worker, dev, FALSE, &error))
+ dev->worker = g_thread_create (nm_device_worker, dev, TRUE, &error);
+ if (!dev->worker)
{
syslog (LOG_CRIT, "nm_device_new (): could not create device worker thread. (glib said: '%s')", error->message);
g_error_free (error);
@@ -324,10 +389,15 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev,
}
/* Block until our device thread has actually had a chance to start. */
- syslog (LOG_ERR, "nm_device_new(): waiting for device's worker thread to start.\n");
- while (dev->worker_started == FALSE)
- g_usleep (G_USEC_PER_SEC / 2);
- syslog (LOG_ERR, "nm_device_new(): device's worker thread started, continuing.\n");
+ msg = g_strdup_printf ("%s: waiting for device's worker thread to start...", nm_device_get_iface (dev));
+ args[0] = &dev->worker_started;
+ args[1] = msg;
+ args[2] = (void *)LOG_INFO;
+ args[3] = 0;
+ nm_wait_for_completion (NM_COMPLETION_TRIES_INFINITY,
+ G_USEC_PER_SEC / 20, nm_completion_boolean_test, NULL, args);
+ g_free (msg);
+ syslog (LOG_ERR, "%s: device's worker thread started, continuing.\n", nm_device_get_iface (dev));
return (dev);
@@ -349,6 +419,7 @@ void nm_device_ref (NMDevice *dev)
dev->refcount++;
}
+
/*
* nm_device_unref
*
@@ -367,10 +438,8 @@ gboolean nm_device_unref (NMDevice *dev)
dev->refcount--;
if (dev->refcount <= 0)
{
- if (dev->loop)
- g_main_loop_quit (dev->loop);
- while (dev->worker_done == FALSE)
- g_usleep (300);
+ nm_device_worker_thread_stop (dev);
+ nm_device_bring_down (dev);
if (nm_device_is_wireless (dev))
{
@@ -418,19 +487,23 @@ static gpointer nm_device_worker (gpointer user_data)
exit (1);
}
- dev->worker_started = TRUE;
-
- /* Do an initial wireless scan */
- if (nm_device_is_wireless (dev))
+ /* Start the scanning timeout for devices that can do scanning */
+ if (nm_device_is_wireless (dev) && nm_device_get_supports_wireless_scan (dev))
{
- GSource *source = g_idle_source_new ();
- guint source_id = 0;
+ GSource *source = g_idle_source_new ();
+ guint source_id = 0;
+ NMWirelessScanCB *scan_cb;
+
+ scan_cb = g_malloc0 (sizeof (NMWirelessScanCB));
+ scan_cb->dev = dev;
+ scan_cb->reschedule = TRUE;
- g_source_set_callback (source, nm_device_wireless_scan, dev, NULL);
+ g_source_set_callback (source, nm_device_wireless_scan, scan_cb, NULL);
source_id = g_source_attach (source, dev->context);
g_source_unref (source);
}
+ dev->worker_started = TRUE;
g_main_loop_run (dev->loop);
/* Remove any DHCP timeouts that might have been running */
@@ -443,7 +516,6 @@ static gpointer nm_device_worker (gpointer user_data)
dev->loop = NULL;
dev->context = NULL;
- dev->worker_done = TRUE;
nm_device_unref (dev);
return NULL;
@@ -454,9 +526,10 @@ void nm_device_worker_thread_stop (NMDevice *dev)
{
g_return_if_fail (dev != NULL);
- g_main_loop_quit (dev->loop);
- while (dev->worker_done == FALSE)
- g_usleep (G_USEC_PER_SEC / 2);
+ if (dev->loop)
+ g_main_loop_quit (dev->loop);
+ g_thread_join(dev->worker);
+ dev->worker = NULL;
}
@@ -491,32 +564,6 @@ void nm_device_set_removed (NMDevice *dev, const gboolean removed)
/*
- * nm_device_open_sock
- *
- * Get a control socket for network operations.
- *
- */
-int nm_device_open_sock (void)
-{
- int fd;
-
- /* Try to grab a control socket */
- fd = socket(PF_INET, SOCK_DGRAM, 0);
- if (fd >= 0)
- return (fd);
- fd = socket(PF_PACKET, SOCK_DGRAM, 0);
- if (fd >= 0)
- return (fd);
- fd = socket(PF_INET6, SOCK_DGRAM, 0);
- if (fd >= 0)
- return (fd);
-
- syslog (LOG_ERR, "nm_device_open_sock () could not get network control socket.");
- return (-1);
-}
-
-
-/*
* Return the amount of time we should wait for the device
* to get a link, based on the # of frequencies it has to
* scan.
@@ -684,9 +731,9 @@ gboolean nm_device_get_supports_carrier_detect (NMDevice *dev)
*/
static gboolean nm_device_wireless_is_associated (NMDevice *dev)
{
- struct iwreq wrq;
- int sk;
- gboolean associated = FALSE;
+ struct iwreq wrq;
+ NMSock *sk;
+ gboolean associated = FALSE;
g_return_val_if_fail (dev != NULL, FALSE);
g_return_val_if_fail (dev->app_data != NULL, FALSE);
@@ -695,13 +742,13 @@ static gboolean nm_device_wireless_is_associated (NMDevice *dev)
if (dev->test_device)
return (nm_device_get_link_active (dev));
- if ((sk = iw_sockets_open ()) < 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)) == NULL)
return (FALSE);
/* Some cards, for example ipw2x00 cards, can short-circuit the MAC
* address check using this check on IWNAME. Its faster.
*/
- if (iw_get_ext (sk, nm_device_get_iface (dev), SIOCGIWNAME, &wrq) >= 0)
+ if (iw_get_ext (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), SIOCGIWNAME, &wrq) >= 0)
{
if (!strcmp(wrq.u.name, "unassociated"))
{
@@ -718,13 +765,13 @@ static gboolean nm_device_wireless_is_associated (NMDevice *dev)
* Is there a better way? Some cards don't work too well with this check, ie
* Lucent WaveLAN.
*/
- if (iw_get_ext (sk, nm_device_get_iface (dev), SIOCGIWAP, &wrq) >= 0)
+ if (iw_get_ext (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), SIOCGIWAP, &wrq) >= 0)
if (nm_ethernet_address_is_valid ((struct ether_addr *)(&(wrq.u.ap_addr.sa_data))))
associated = TRUE;
}
out:
- close (sk);
+ nm_dev_sock_close (sk);
return (associated);
}
@@ -850,8 +897,8 @@ void nm_device_update_link_active (NMDevice *dev)
*/
char * nm_device_get_essid (NMDevice *dev)
{
- int sk;
- int err;
+ NMSock *sk;
+ int err;
g_return_val_if_fail (dev != NULL, NULL);
g_return_val_if_fail (nm_device_is_wireless (dev), NULL);
@@ -873,12 +920,11 @@ char * nm_device_get_essid (NMDevice *dev)
return (essid);
}
- sk = iw_sockets_open ();
- if (sk >= 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
{
wireless_config info;
- err = iw_get_basic_config(sk, nm_device_get_iface (dev), &info);
+ err = iw_get_basic_config (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), &info);
if (err >= 0)
{
if (dev->options.wireless.cur_essid)
@@ -888,7 +934,7 @@ char * nm_device_get_essid (NMDevice *dev)
else
syslog (LOG_ERR, "nm_device_get_essid(): error getting ESSID for device %s. errno = %d", nm_device_get_iface (dev), errno);
- close (sk);
+ nm_dev_sock_close (sk);
}
return (dev->options.wireless.cur_essid);
@@ -902,10 +948,10 @@ char * nm_device_get_essid (NMDevice *dev)
*/
void nm_device_set_essid (NMDevice *dev, const char *essid)
{
- int sk;
- int err;
- struct iwreq wreq;
- unsigned char safe_essid[IW_ESSID_MAX_SIZE + 1] = "\0";
+ NMSock *sk;
+ int err;
+ struct iwreq wreq;
+ unsigned char safe_essid[IW_ESSID_MAX_SIZE + 1] = "\0";
g_return_if_fail (dev != NULL);
g_return_if_fail (nm_device_is_wireless (dev));
@@ -928,18 +974,24 @@ void nm_device_set_essid (NMDevice *dev, const char *essid)
safe_essid[IW_ESSID_MAX_SIZE] = '\0';
}
- sk = iw_sockets_open ();
- if (sk >= 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
{
wreq.u.essid.pointer = (caddr_t) safe_essid;
wreq.u.essid.length = strlen (safe_essid) + 1;
wreq.u.essid.flags = 1; /* Enable essid on card */
- err = iw_set_ext (sk, nm_device_get_iface (dev), SIOCSIWESSID, &wreq);
+ err = iw_set_ext (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), SIOCSIWESSID, &wreq);
if (err == -1)
syslog (LOG_ERR, "nm_device_set_essid(): error setting ESSID '%s' for device %s. errno = %d", safe_essid, nm_device_get_iface (dev), errno);
- close (sk);
+ nm_dev_sock_close (sk);
+
+ /* Orinoco cards seem to need extra time here to not screw
+ * up the firmware, which reboots when you set the ESSID.
+ * Unfortunately, there's no way to know when the card is back up
+ * again. Sigh...
+ */
+ sleep (2);
}
}
@@ -952,9 +1004,9 @@ void nm_device_set_essid (NMDevice *dev, const char *essid)
*/
double nm_device_get_frequency (NMDevice *dev)
{
- int sk;
- int err;
- double freq = 0;
+ NMSock *sk;
+ int err;
+ double freq = 0;
g_return_val_if_fail (dev != NULL, 0);
g_return_val_if_fail (nm_device_is_wireless (dev), 0);
@@ -963,18 +1015,17 @@ double nm_device_get_frequency (NMDevice *dev)
if (dev->test_device)
return 703000000;
- sk = iw_sockets_open ();
- if (sk >= 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
{
struct iwreq wrq;
- err = iw_set_ext (sk, nm_device_get_iface (dev), SIOCGIWFREQ, &wrq);
+ err = iw_get_ext (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), SIOCGIWFREQ, &wrq);
if (err >= 0)
freq = iw_freq2float (&wrq.u.freq);
if (err == -1)
syslog (LOG_ERR, "nm_device_get_frequency(): error getting frequency for device %s. errno = %d", nm_device_get_iface (dev), errno);
- close (sk);
+ nm_dev_sock_close (sk);
}
return (freq);
}
@@ -989,8 +1040,8 @@ double nm_device_get_frequency (NMDevice *dev)
*/
void nm_device_set_frequency (NMDevice *dev, const double freq)
{
- int sk;
- int err;
+ NMSock *sk;
+ int err;
/* HACK FOR NOW */
if (freq <= 0)
@@ -1006,8 +1057,7 @@ void nm_device_set_frequency (NMDevice *dev, const double freq)
if (nm_device_get_frequency (dev) == freq)
return;
- sk = iw_sockets_open ();
- if (sk >= 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
{
struct iwreq wrq;
@@ -1037,7 +1087,7 @@ void nm_device_set_frequency (NMDevice *dev, const double freq)
wrq.u.freq.flags = IW_FREQ_FIXED;
iw_float2freq (freq, &wrq.u.freq);
}
- err = iw_set_ext (sk, nm_device_get_iface (dev), SIOCSIWFREQ, &wrq);
+ err = iw_set_ext (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), SIOCSIWFREQ, &wrq);
if (err == -1)
{
gboolean success = FALSE;
@@ -1047,12 +1097,12 @@ void nm_device_set_frequency (NMDevice *dev, const double freq)
wrq.u.freq.m = -1;
wrq.u.freq.e = 0;
wrq.u.freq.flags = 0;
- if (iw_set_ext (sk, nm_device_get_iface (dev), SIOCSIWFREQ, &wrq) != -1)
+ if (iw_set_ext (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), SIOCSIWFREQ, &wrq) != -1)
success = TRUE;
}
}
- close (sk);
+ nm_dev_sock_close (sk);
}
}
@@ -1066,9 +1116,9 @@ void nm_device_set_frequency (NMDevice *dev, const double freq)
*/
int nm_device_get_bitrate (NMDevice *dev)
{
- int sk;
- int err = -1;
- struct iwreq wrq;
+ NMSock *sk;
+ int err = -1;
+ struct iwreq wrq;
g_return_val_if_fail (dev != NULL, 0);
g_return_val_if_fail (nm_device_is_wireless (dev), 0);
@@ -1077,11 +1127,10 @@ int nm_device_get_bitrate (NMDevice *dev)
if (dev->test_device)
return 11;
- sk = iw_sockets_open ();
- if (sk >= 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
{
- err = iw_set_ext (sk, nm_device_get_iface (dev), SIOCGIWRATE, &wrq);
- close (sk);
+ err = iw_get_ext (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), SIOCGIWRATE, &wrq);
+ nm_dev_sock_close (sk);
}
return ((err >= 0) ? wrq.u.bitrate.value / 1000 : 0);
@@ -1097,7 +1146,7 @@ int nm_device_get_bitrate (NMDevice *dev)
*/
void nm_device_set_bitrate (NMDevice *dev, const int Mbps)
{
- int sk;
+ NMSock *sk;
g_return_if_fail (dev != NULL);
g_return_if_fail (nm_device_is_wireless (dev));
@@ -1109,8 +1158,7 @@ void nm_device_set_bitrate (NMDevice *dev, const int Mbps)
if (nm_device_get_bitrate (dev) == Mbps)
return;
- sk = iw_sockets_open ();
- if (sk >= 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
{
struct iwreq wrq;
@@ -1126,9 +1174,9 @@ void nm_device_set_bitrate (NMDevice *dev, const int Mbps)
wrq.u.bitrate.fixed = 0;
}
/* Silently fail as not all drivers support setting bitrate yet (ipw2x00 for example) */
- iw_set_ext (sk, nm_device_get_iface (dev), SIOCSIWRATE, &wrq);
+ iw_set_ext (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), SIOCSIWRATE, &wrq);
- close (sk);
+ nm_dev_sock_close (sk);
}
}
@@ -1141,8 +1189,8 @@ void nm_device_set_bitrate (NMDevice *dev, const int Mbps)
*/
void nm_device_get_ap_address (NMDevice *dev, struct ether_addr *addr)
{
- int iwlib_socket;
- struct iwreq wrq;
+ NMSock *sk;
+ struct iwreq wrq;
g_return_if_fail (dev != NULL);
g_return_if_fail (addr != NULL);
@@ -1161,12 +1209,14 @@ void nm_device_get_ap_address (NMDevice *dev, struct ether_addr *addr)
return;
}
- iwlib_socket = iw_sockets_open ();
- if (iw_get_ext (iwlib_socket, nm_device_get_iface (dev), SIOCGIWAP, &wrq) >= 0)
- memcpy (addr, &(wrq.u.ap_addr.sa_data), sizeof (struct ether_addr));
- else
- memset (addr, 0, sizeof (struct ether_addr));
- close (iwlib_socket);
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
+ {
+ if (iw_get_ext (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), SIOCGIWAP, &wrq) >= 0)
+ memcpy (addr, &(wrq.u.ap_addr.sa_data), sizeof (struct ether_addr));
+ else
+ memset (addr, 0, sizeof (struct ether_addr));
+ nm_dev_sock_close (sk);
+ }
}
@@ -1181,8 +1231,7 @@ void nm_device_get_ap_address (NMDevice *dev, struct ether_addr *addr)
*/
void nm_device_set_enc_key (NMDevice *dev, const char *key, NMDeviceAuthMethod auth_method)
{
- int sk;
- int err;
+ NMSock *sk;
struct iwreq wreq;
int keylen;
unsigned char safe_key[IW_ENCODING_TOKEN_MAX + 1];
@@ -1204,8 +1253,7 @@ void nm_device_set_enc_key (NMDevice *dev, const char *key, NMDeviceAuthMethod a
safe_key[IW_ENCODING_TOKEN_MAX] = '\0';
}
- sk = iw_sockets_open ();
- if (sk >= 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
{
wreq.u.data.pointer = (caddr_t) NULL;
wreq.u.data.length = 0;
@@ -1226,7 +1274,7 @@ void nm_device_set_enc_key (NMDevice *dev, const char *key, NMDeviceAuthMethod a
{
unsigned char parsed_key[IW_ENCODING_TOKEN_MAX + 1];
- keylen = iw_in_key_full (sk, nm_device_get_iface (dev), safe_key, &parsed_key[0], &wreq.u.data.flags);
+ keylen = iw_in_key_full (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), safe_key, &parsed_key[0], &wreq.u.data.flags);
if (keylen > 0)
{
switch (auth_method)
@@ -1249,12 +1297,11 @@ void nm_device_set_enc_key (NMDevice *dev, const char *key, NMDeviceAuthMethod a
if (set_key)
{
- err = iw_set_ext (sk, nm_device_get_iface (dev), SIOCSIWENCODE, &wreq);
- if (err == -1)
+ if (iw_set_ext (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), SIOCSIWENCODE, &wreq) == -1)
syslog (LOG_ERR, "nm_device_set_enc_key(): error setting key for device %s. errno = %d", nm_device_get_iface (dev), errno);
}
- close (sk);
+ nm_dev_sock_close (sk);
} else syslog (LOG_ERR, "nm_device_set_enc_key(): could not get wireless control socket.");
}
@@ -1288,8 +1335,8 @@ gint8 nm_device_get_signal_strength (NMDevice *dev)
*/
void nm_device_update_signal_strength (NMDevice *dev)
{
- gboolean has_range;
- int sk;
+ gboolean has_range = FALSE;
+ NMSock *sk;
iwrange range;
iwstats stats;
int percent = -1;
@@ -1318,14 +1365,16 @@ void nm_device_update_signal_strength (NMDevice *dev)
goto out;
}
- sk = iw_sockets_open ();
- has_range = (iw_get_range_info (sk, nm_device_get_iface (dev), &range) >= 0);
- if (iw_get_stats (sk, nm_device_get_iface (dev), &stats, &range, has_range) == 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
{
- percent = nm_wireless_qual_to_percent (&stats.qual, (const iwqual *)(&dev->options.wireless.max_qual),
- (const iwqual *)(&dev->options.wireless.avg_qual));
+ has_range = (iw_get_range_info (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), &range) >= 0);
+ if (iw_get_stats (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), &stats, &range, has_range) == 0)
+ {
+ percent = nm_wireless_qual_to_percent (&stats.qual, (const iwqual *)(&dev->options.wireless.max_qual),
+ (const iwqual *)(&dev->options.wireless.avg_qual));
+ }
+ nm_dev_sock_close (sk);
}
- close (sk);
/* Try to smooth out the strength. Atmel cards, for example, will give no strength
* one second and normal strength the next.
@@ -1359,7 +1408,7 @@ void nm_device_update_ip4_address (NMDevice *dev)
{
guint32 new_address;
struct ifreq req;
- int sk;
+ NMSock *sk;
int err;
g_return_if_fail (dev != NULL);
@@ -1373,13 +1422,13 @@ void nm_device_update_ip4_address (NMDevice *dev)
return;
}
- if ((sk = nm_device_open_sock ()) < 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_GENERAL, __FUNCTION__, NULL)) == NULL)
return;
memset (&req, 0, sizeof (struct ifreq));
strncpy ((char *)(&req.ifr_name), nm_device_get_iface (dev), strlen (nm_device_get_iface (dev)));
- err = ioctl (sk, SIOCGIFADDR, &req);
- close (sk);
+ err = ioctl (nm_dev_sock_get_fd (sk), SIOCGIFADDR, &req);
+ nm_dev_sock_close (sk);
if (err != 0)
return;
@@ -1414,17 +1463,18 @@ void nm_device_get_ip6_address(NMDevice *dev)
* Get a device's hardware address
*
*/
-void nm_device_get_hw_address(NMDevice *dev, unsigned char hw_addr[ETH_ALEN])
+void nm_device_get_hw_address(NMDevice *dev, unsigned char *eth_addr)
{
+ g_return_if_fail (eth_addr != NULL);
g_return_if_fail (dev != NULL);
- memcpy (hw_addr, dev->hw_addr, ETH_ALEN);
+ memcpy (eth_addr, dev->hw_addr, ETH_ALEN);
}
void nm_device_update_hw_address (NMDevice *dev)
{
struct ifreq req;
- int sk;
+ NMSock *sk;
int err;
g_return_if_fail (dev != NULL);
@@ -1438,17 +1488,17 @@ void nm_device_update_hw_address (NMDevice *dev)
return;
}
- if ((sk = nm_device_open_sock ()) < 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_GENERAL, __FUNCTION__, NULL)) == NULL)
return;
memset (&req, 0, sizeof (struct ifreq));
strncpy ((char *)(&req.ifr_name), nm_device_get_iface (dev), strlen (nm_device_get_iface (dev)));
- err = ioctl (sk, SIOCGIFHWADDR, &req);
- close (sk);
+ err = ioctl (nm_dev_sock_get_fd (sk), SIOCGIFHWADDR, &req);
+ nm_dev_sock_close (sk);
if (err != 0)
return;
- memcpy (dev->hw_addr, req.ifr_hwaddr.sa_data, ETH_ALEN);
+ memcpy (dev->hw_addr, req.ifr_hwaddr.sa_data, ETH_ALEN);
}
@@ -1461,8 +1511,7 @@ void nm_device_update_hw_address (NMDevice *dev)
static void nm_device_set_up_down (NMDevice *dev, gboolean up)
{
struct ifreq ifr;
- int sk;
- int err;
+ NMSock *sk;
guint32 flags = up ? IFF_UP : ~IFF_UP;
g_return_if_fail (dev != NULL);
@@ -1474,17 +1523,12 @@ static void nm_device_set_up_down (NMDevice *dev, gboolean up)
return;
}
- if (nm_device_get_driver_support_level (dev) == NM_DRIVER_UNSUPPORTED)
- return;
-
- sk = nm_device_open_sock ();
- if (sk < 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_GENERAL, __FUNCTION__, NULL)) == NULL)
return;
/* Get flags already there */
strcpy (ifr.ifr_name, nm_device_get_iface (dev));
- err = ioctl (sk, SIOCGIFFLAGS, &ifr);
- if (!err)
+ if (ioctl (nm_dev_sock_get_fd (sk), SIOCGIFFLAGS, &ifr) != -1)
{
/* If the interface doesn't have those flags already,
* set them on it.
@@ -1493,7 +1537,7 @@ static void nm_device_set_up_down (NMDevice *dev, gboolean up)
{
ifr.ifr_flags &= ~IFF_UP;
ifr.ifr_flags |= IFF_UP & flags;
- if ((err = ioctl (sk, SIOCSIFFLAGS, &ifr)))
+ if (ioctl (nm_dev_sock_get_fd (sk), SIOCSIFFLAGS, &ifr) == -1)
syslog (LOG_ERR, "nm_device_set_up_down() could not bring device %s %s. errno = %d", nm_device_get_iface (dev), (up ? "up" : "down"), errno );
}
/* Make sure we have a valid MAC address, some cards reload firmware when they
@@ -1505,7 +1549,7 @@ static void nm_device_set_up_down (NMDevice *dev, gboolean up)
else
syslog (LOG_ERR, "nm_device_set_up_down() could not get flags for device %s. errno = %d", nm_device_get_iface (dev), errno );
- close (sk);
+ nm_dev_sock_close (sk);
}
@@ -1513,6 +1557,51 @@ static void nm_device_set_up_down (NMDevice *dev, gboolean up)
* Interface state functions: bring up, down, check
*
*/
+gboolean nm_device_is_up (NMDevice *dev)
+{
+ NMSock *sk;
+ struct ifreq ifr;
+ int err;
+
+ g_return_val_if_fail (dev != NULL, FALSE);
+
+ if (dev->test_device)
+ return (dev->test_device_up);
+
+ if ((sk = nm_dev_sock_open (dev, DEV_GENERAL, __FUNCTION__, NULL)) == NULL)
+ return (FALSE);
+
+ /* Get device's flags */
+ strcpy (ifr.ifr_name, nm_device_get_iface (dev));
+ err = ioctl (nm_dev_sock_get_fd (sk), SIOCGIFFLAGS, &ifr);
+ nm_dev_sock_close (sk);
+ if (!err)
+ return (!((ifr.ifr_flags^IFF_UP) & IFF_UP));
+
+ syslog (LOG_ERR, "nm_device_is_up() could not get flags for device %s. errno = %d", nm_device_get_iface (dev), errno );
+ return (FALSE);
+}
+
+gboolean nm_completion_device_is_up_test(int tries, nm_completion_args args)
+{
+ NMDevice *dev = args[0];
+ gboolean *err = args[1];
+ gboolean cancelable = (gboolean)args[2];
+
+ g_return_val_if_fail (dev != NULL, TRUE);
+ g_return_val_if_fail (err != NULL, TRUE);
+
+ *err = FALSE;
+ if (cancelable && nm_device_activation_handle_cancel (dev))
+ {
+ *err = TRUE;
+ return TRUE;
+ }
+ if (nm_device_is_up (dev))
+ return TRUE;
+ return FALSE;
+}
+
void nm_device_bring_up (NMDevice *dev)
{
g_return_if_fail (dev != NULL);
@@ -1520,6 +1609,25 @@ void nm_device_bring_up (NMDevice *dev)
nm_device_set_up_down (dev, TRUE);
}
+gboolean nm_device_bring_up_wait (NMDevice *dev, gboolean cancelable)
+{
+ gboolean err = FALSE;
+ nm_completion_args args;
+
+ g_return_val_if_fail (dev != NULL, TRUE);
+
+ nm_device_bring_up (dev);
+
+ args[0] = dev;
+ args[1] = &err;
+ args[2] = (void *)cancelable;
+ nm_wait_for_completion(400, G_USEC_PER_SEC / 200, NULL,
+ nm_completion_device_is_up_test, args);
+ if (err)
+ syslog (LOG_INFO, "failed to bring device up");
+ return err;
+}
+
void nm_device_bring_down (NMDevice *dev)
{
g_return_if_fail (dev != NULL);
@@ -1527,30 +1635,43 @@ void nm_device_bring_down (NMDevice *dev)
nm_device_set_up_down (dev, FALSE);
}
-gboolean nm_device_is_up (NMDevice *dev)
+gboolean nm_completion_device_is_down_test(int tries, nm_completion_args args)
{
- int sk;
- struct ifreq ifr;
- int err;
+ NMDevice *dev = args[0];
+ gboolean *err = args[1];
+ gboolean cancelable = (gboolean)args[2];
- g_return_val_if_fail (dev != NULL, FALSE);
+ g_return_val_if_fail (dev != NULL, TRUE);
+ g_return_val_if_fail (err != NULL, TRUE);
- if (dev->test_device)
- return (dev->test_device_up);
+ *err = FALSE;
+ if (cancelable && nm_device_activation_handle_cancel (dev))
+ {
+ *err = TRUE;
+ return TRUE;
+ }
+ if (!nm_device_is_up (dev))
+ return TRUE;
+ return FALSE;
+}
- sk = nm_device_open_sock ();
- if (sk < 0)
- return (FALSE);
+gboolean nm_device_bring_down_wait (NMDevice *dev, gboolean cancelable)
+{
+ gboolean err = FALSE;
+ nm_completion_args args;
- /* Get device's flags */
- strcpy (ifr.ifr_name, nm_device_get_iface (dev));
- err = ioctl (sk, SIOCGIFFLAGS, &ifr);
- close (sk);
- if (!err)
- return (!((ifr.ifr_flags^IFF_UP) & IFF_UP));
+ g_return_val_if_fail (dev != NULL, TRUE);
- syslog (LOG_ERR, "nm_device_is_up() could not get flags for device %s. errno = %d", nm_device_get_iface (dev), errno );
- return (FALSE);
+ nm_device_bring_down (dev);
+
+ args[0] = dev;
+ args[1] = &err;
+ args[2] = (void *)cancelable;
+ nm_wait_for_completion(400, G_USEC_PER_SEC / 200, NULL,
+ nm_completion_device_is_down_test, args);
+ if (err)
+ syslog (LOG_INFO, "failed to bring device down");
+ return err;
}
@@ -1562,21 +1683,18 @@ gboolean nm_device_is_up (NMDevice *dev)
*/
NMNetworkMode nm_device_get_mode (NMDevice *dev)
{
- int sk;
+ NMSock *sk;
NMNetworkMode mode = NETWORK_MODE_UNKNOWN;
g_return_val_if_fail (dev != NULL, NETWORK_MODE_UNKNOWN);
g_return_val_if_fail (nm_device_is_wireless (dev), NETWORK_MODE_UNKNOWN);
/* Force the card into Managed/Infrastructure mode */
- sk = iw_sockets_open ();
- if (sk >= 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
{
struct iwreq wrq;
- int err;
- err = iw_set_ext (sk, nm_device_get_iface (dev), SIOCGIWMODE, &wrq);
- if (err == 0)
+ if (iw_get_ext (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), SIOCGIWMODE, &wrq) == 0)
{
switch (wrq.u.mode)
{
@@ -1591,8 +1709,8 @@ NMNetworkMode nm_device_get_mode (NMDevice *dev)
}
}
else
- syslog (LOG_ERR, "nm_device_get_mode (%s): error setting card to Infrastructure mode. errno = %d", nm_device_get_iface (dev), errno);
- close (sk);
+ syslog (LOG_ERR, "nm_device_get_mode (%s): error getting card mode. errno = %d", nm_device_get_iface (dev), errno);
+ nm_dev_sock_close (sk);
}
return (mode);
@@ -1607,8 +1725,8 @@ NMNetworkMode nm_device_get_mode (NMDevice *dev)
*/
gboolean nm_device_set_mode (NMDevice *dev, const NMNetworkMode mode)
{
- int sk;
- gboolean success = FALSE;
+ NMSock *sk;
+ gboolean success = FALSE;
g_return_val_if_fail (dev != NULL, FALSE);
g_return_val_if_fail (nm_device_is_wireless (dev), FALSE);
@@ -1618,11 +1736,9 @@ gboolean nm_device_set_mode (NMDevice *dev, const NMNetworkMode mode)
return TRUE;
/* Force the card into Managed/Infrastructure mode */
- sk = iw_sockets_open ();
- if (sk >= 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
{
struct iwreq wreq;
- int err;
gboolean mode_good = FALSE;
switch (mode)
@@ -1641,13 +1757,15 @@ gboolean nm_device_set_mode (NMDevice *dev, const NMNetworkMode mode)
}
if (mode_good)
{
- err = iw_set_ext (sk, nm_device_get_iface (dev), SIOCSIWMODE, &wreq);
- if (err == 0)
+ if (iw_set_ext (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), SIOCSIWMODE, &wreq) == 0)
success = TRUE;
else
- syslog (LOG_ERR, "nm_device_set_mode (%s): error setting card to Infrastructure mode. errno = %d", nm_device_get_iface (dev), errno);
+ syslog (LOG_ERR, "nm_device_set_mode (%s): error setting card to %s mode. errno = %d",
+ nm_device_get_iface (dev),
+ mode == NETWORK_MODE_INFRA ? "Infrastructure" : (mode == NETWORK_MODE_ADHOC ? "adhoc" : "unknown"),
+ errno);
}
- close (sk);
+ nm_dev_sock_close (sk);
}
return (success);
@@ -1660,7 +1778,7 @@ gboolean nm_device_set_mode (NMDevice *dev, const NMNetworkMode mode)
* Schedule an idle routine in the main thread to finish the activation.
*
*/
-void nm_device_activation_schedule_finish (NMDevice *dev, DeviceStatus activation_result)
+void nm_device_activation_schedule_finish (NMDevice *dev, NMAccessPoint *failed_ap, DeviceStatus activation_result)
{
GSource *source = NULL;
NMActivationResult *result = NULL;
@@ -1671,6 +1789,7 @@ void nm_device_activation_schedule_finish (NMDevice *dev, DeviceStatus activatio
result = g_malloc0 (sizeof (NMActivationResult));
nm_device_ref (dev); /* Ref device for idle handler */
result->dev = dev;
+ result->failed_ap = failed_ap;
result->result = activation_result;
source = g_idle_source_new ();
@@ -1749,6 +1868,46 @@ static gboolean nm_device_activation_handle_cancel (NMDevice *dev)
return (FALSE);
}
+static gboolean nm_dwwfl_test (int tries, nm_completion_args args)
+{
+ NMDevice *dev = args[0];
+ guint *assoc_count = args[1];
+ double *last_freq = args[2];
+ char *essid = args[3];
+ int required = (int)args[4];
+
+ double cur_freq = nm_device_get_frequency (dev);
+ gboolean assoc = nm_device_wireless_is_associated (dev);
+ const char * cur_essid = nm_device_get_essid (dev);
+
+ /* If we've been cancelled, return that we should stop */
+ if (nm_device_activation_should_cancel (dev))
+ return TRUE;
+
+ /* If we're on the same frequency and essid, and we're associated,
+ * increment the count for how many iterations we've been associated;
+ * otherwise start over. */
+ /* XXX floating point comparison this way is dangerous, IIRC */
+ if ((cur_freq == *last_freq) && assoc && !strcmp (essid, cur_essid))
+ {
+ (*assoc_count)++;
+ }
+ else
+ {
+ *assoc_count = 0;
+ *last_freq = cur_freq;
+ }
+
+ /* If we're told to cancel, return that we're finished.
+ * If we've the frequency has been stable for more than the required
+ * interval, return that we're finished.
+ * Otherwise, we're not finished. */
+ if (nm_device_activation_should_cancel (dev) || *assoc_count >= required)
+ return TRUE;
+
+ return FALSE;
+}
+
/*
* nm_device_wireless_wait_for_link
@@ -1759,59 +1918,79 @@ static gboolean nm_device_activation_handle_cancel (NMDevice *dev)
*/
static gboolean nm_device_wireless_wait_for_link (NMDevice *dev, const char *essid)
{
- struct timeval end_time;
- struct timeval cur_time;
- gboolean link = FALSE;
+ guint assoc = 0;
double last_freq = 0;
- guint assoc_count = 0;
- gint pause_value;
+ struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 };
+ nm_completion_args args;
+
+ /* we want to sleep for a very short amount of time, to minimize
+ * hysteresis on the boundaries of our required time. But we
+ * also want the maximum to be based on what the card */
+ const guint delay = 30;
+ const guint required_tries = 10;
+ const guint min_delay = 2 * (required_tries / delay);
g_return_val_if_fail (dev != NULL, FALSE);
g_return_val_if_fail (time > 0, FALSE);
- pause_value = nm_device_get_association_pause_value (dev);
- if (pause_value < 1)
- return FALSE;
-
- gettimeofday (&end_time, NULL);
- end_time.tv_sec += pause_value;
-
- /* We more or less keep asking the driver for the frequency the card is on, and
- * when the frequency has stabilized (the driver has to scan channels to find the AP,
- * and when it finds the AP it stops scanning) and the MAC is valid, we think we
- * have a link.
- */
- gettimeofday (&cur_time, NULL);
- while (cur_time.tv_sec < end_time.tv_sec)
- {
- double cur_freq = nm_device_get_frequency (dev);
- gboolean assoc = nm_device_wireless_is_associated (dev);
- char *cur_essid = nm_device_get_essid (dev);
-
- if ((cur_freq == last_freq) && assoc && !strcmp (essid, cur_essid))
- assoc_count++;
- else
- assoc_count = 0;
- last_freq = cur_freq;
+ /* for cards which don't scan many frequencies, this will return
+ * 5 seconds, which we'll bump up to 6 seconds below. Oh well. */
+ timeout.tv_sec = (time_t)nm_device_get_association_pause_value (dev);
+
+ /* Refuse to to have a timeout that's _less_ than twice the total time
+ * required before calling a link valid */
+ if (timeout.tv_sec < min_delay)
+ timeout.tv_sec = min_delay;
+
+ /* We more or less keep asking the driver for the frequency the
+ * card is listening on until it connects to an AP. Once it's
+ * associated, the driver stops scanning. To detect that, we look
+ * for the essid and frequency to remain constant for 3 seconds.
+ * When it remains constant, we assume it's a real link. */
+ args[0] = dev;
+ args[1] = &assoc;
+ args[2] = &last_freq;
+ args[3] = (void *)essid;
+ args[4] = (void *)(required_tries * 2);
+ nm_wait_for_timeout (&timeout, G_USEC_PER_SEC / delay,
+ nm_dwwfl_test, nm_dwwfl_test, args);
- g_usleep (G_USEC_PER_SEC / 2);
- if (nm_device_activation_should_cancel (dev))
- break;
+ /* If we've had a reasonable association count, we say we have a link */
+ if (assoc > required_tries)
+ return TRUE;
+ return FALSE;
+}
- gettimeofday (&cur_time, NULL);
- if ((cur_time.tv_sec >= end_time.tv_sec) && (cur_time.tv_usec >= end_time.tv_usec))
- break;
+static gboolean nm_device_link_test(int tries, nm_completion_args args)
+{
+ NMDevice *dev = args[0];
+ gboolean *err = args[1];
- /* Assume that if we've been associated this long, we might as well just stop. */
- if (assoc_count >= 9)
- break;
+ g_return_val_if_fail(dev != NULL, TRUE);
+ g_return_val_if_fail(err != NULL, TRUE);
+
+ if (nm_device_wireless_is_associated (dev) && nm_device_get_essid (dev))
+ {
+ *err = FALSE;
+ return TRUE;
}
+ *err = TRUE;
+ return FALSE;
+}
- /* If we've had a reasonable association count, we say we have a link */
- if (assoc_count > 6)
- link = TRUE;
+static gboolean nm_device_is_up_and_associated_wait (NMDevice *dev, int timeout, int interval)
+{
+ gboolean err;
+ const gint delay = (G_USEC_PER_SEC * nm_device_get_association_pause_value (dev)) / interval;
+ const gint max_cycles = timeout * interval;
+ nm_completion_args args;
- return (link);
+ g_return_val_if_fail (dev != NULL, TRUE);
+
+ args[0] = dev;
+ args[1] = &err;
+ nm_wait_for_completion (max_cycles, delay, NULL, nm_device_link_test, args);
+ return !err;
}
@@ -1836,10 +2015,9 @@ static gboolean nm_device_set_wireless_config (NMDevice *dev, NMAccessPoint *ap)
g_return_val_if_fail (nm_ap_get_auth_method (ap) != NM_DEVICE_AUTH_METHOD_UNKNOWN, FALSE);
/* Force the card into Managed/Infrastructure mode */
- nm_device_bring_down (dev);
- g_usleep (G_USEC_PER_SEC * 2);
- nm_device_bring_up (dev);
- g_usleep (G_USEC_PER_SEC * 2);
+ nm_device_bring_down_wait (dev, 0);
+ nm_device_bring_up_wait (dev, 0);
+
nm_device_set_mode (dev, NETWORK_MODE_INFRA);
essid = nm_ap_get_essid (ap);
@@ -1877,8 +2055,11 @@ static gboolean nm_device_set_wireless_config (NMDevice *dev, NMAccessPoint *ap)
((auth == NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM) ? "Open System" :
((auth == NM_DEVICE_AUTH_METHOD_SHARED_KEY) ? "Shared Key" : "unknown")));
- /* Bring the device up and pause to allow card to associate. */
- g_usleep (G_USEC_PER_SEC * 2);
+ /* Bring the device up and pause to allow card to associate. After we set the ESSID
+ * on the card, the card has to scan all channels to find our requested AP (which can
+ * take a long time if it is an A/B/G chipset like the Atheros 5212, for example).
+ */
+ nm_device_is_up_and_associated_wait (dev, 2, 100);
/* Some cards don't really work well in ad-hoc mode unless you explicitly set the bitrate
* on them. (Netgear WG511T/Atheros 5212 with madwifi drivers). Until we can get rate information
@@ -1907,7 +2088,8 @@ static gboolean nm_device_activate_wireless_adhoc (NMDevice *dev, NMAccessPoint
int num_freqs = 0, i;
double freq_to_use = 0;
iwrange range;
- int sk;
+ NMSock *sk;
+ int err;
g_return_val_if_fail (dev != NULL, FALSE);
g_return_val_if_fail (ap != NULL, FALSE);
@@ -1936,15 +2118,13 @@ static gboolean nm_device_activate_wireless_adhoc (NMDevice *dev, NMAccessPoint
}
nm_ap_list_iter_free (iter);
- if ((sk = iw_sockets_open ()) < 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)) == NULL)
return FALSE;
- if (iw_get_range_info (sk, nm_device_get_iface (dev), &range) < 0)
- {
- close (sk);
+ err = iw_get_range_info (nm_dev_sock_get_fd (sk), nm_device_get_iface (dev), &range);
+ nm_dev_sock_close (sk);
+ if (err < 0)
return FALSE;
- }
- close (sk);
/* Ok, find the first non-zero freq in our table and use it.
* For now we only try to use a channel in the 802.11b channel
@@ -2070,6 +2250,82 @@ void invalidate_ap (NMDevice *dev, NMAccessPoint *ap)
}
+/* this gets called without the scan mutex held */
+static gboolean nm_wa_test (int tries, nm_completion_args args)
+{
+ NMDevice *dev = args[0];
+ NMAccessPoint **best_ap = args[1];
+ gboolean *err = args[2];
+
+ g_return_val_if_fail(dev != NULL, TRUE);
+ g_return_val_if_fail(best_ap != NULL, TRUE);
+ g_return_val_if_fail(err != NULL, TRUE);
+
+ *err = TRUE;
+ if (nm_device_activation_handle_cancel(dev))
+ return TRUE;
+
+ if (tries % 100 == 0)
+ syslog (LOG_INFO, "Activation (%s/wireless): waiting for access point. (attempt %d)", nm_device_get_iface(dev), tries);
+
+ *best_ap = nm_device_get_best_ap (dev);
+ if (*best_ap)
+ {
+ /* Set ESSID early so that when we send out the
+ * DeviceStatusChanged signal below, we are able to
+ * respond correctly to queries for "getActiveNetwork"
+ * against our device. nm_device_get_path_for_ap() uses
+ * the /card's/ AP, not the best_ap. */
+ nm_device_set_essid (dev, nm_ap_get_essid (*best_ap));
+ nm_device_set_now_scanning (dev, FALSE);
+ *err = FALSE;
+ return TRUE;
+ }
+ else
+ {
+ /* Since scanning runs in the device thread, we block scans
+ * during device activation. So we need to run a scan periodically
+ * during activation too.
+ */
+ GTimeVal cur_time;
+
+ /* If the last scan was done more than 15s before, do another one. */
+ g_get_current_time (&cur_time);
+ if (cur_time.tv_sec >= dev->options.wireless.last_scan + 15)
+ {
+ NMWirelessScanCB *scan_cb = g_malloc0 (sizeof (NMWirelessScanCB));
+
+ scan_cb->dev = dev;
+ scan_cb->reschedule = FALSE;
+ nm_device_wireless_scan (scan_cb);
+ }
+ }
+
+ return FALSE;
+}
+
+
+static gboolean nm_dukr_test (int tries, nm_completion_args args)
+{
+ NMDevice *dev = args[0];
+ gboolean *err = args[1];
+
+ g_return_val_if_fail (dev != NULL, TRUE);
+ g_return_val_if_fail (err != NULL, TRUE);
+
+ *err = TRUE;
+
+ if (nm_device_activation_handle_cancel (dev))
+ return TRUE;
+ if (dev->options.wireless.user_key_received)
+ {
+ *err = FALSE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
/*
* nm_device_activate_wireless
*
@@ -2080,12 +2336,13 @@ void invalidate_ap (NMDevice *dev, NMAccessPoint *ap)
*/
static gboolean nm_device_activate_wireless (NMDevice *dev)
{
- NMAccessPoint *best_ap;
+ NMAccessPoint *best_ap = NULL;
gboolean success = FALSE;
guint8 attempt = 1;
char last_essid [50] = "\0";
gboolean need_key = FALSE;
- gboolean found_ap = FALSE;
+ gboolean err = FALSE;
+ nm_completion_args args;
g_return_val_if_fail (dev != NULL, FALSE);
g_return_val_if_fail (dev->app_data != NULL, FALSE);
@@ -2095,9 +2352,7 @@ static gboolean nm_device_activate_wireless (NMDevice *dev)
*/
nm_lock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__);
- if (!nm_device_is_up (dev))
- nm_device_bring_up (dev);
- g_usleep (G_USEC_PER_SEC);
+ nm_device_bring_up_wait (dev, 1);
get_ap:
/* If we were told to quit activation, stop the thread and return */
@@ -2108,30 +2363,23 @@ get_ap:
* lock here because this might take a while.
*/
nm_unlock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__);
- while (!(best_ap = nm_device_get_best_ap (dev)))
- {
- nm_device_set_now_scanning (dev, TRUE);
- if (!found_ap)
- syslog (LOG_ERR, "Activation (%s/wireless): waiting for an access point.", nm_device_get_iface (dev));
- g_usleep (G_USEC_PER_SEC * 2);
- /* If we were told to quit activation, stop the thread and return */
- if (nm_device_activation_handle_cancel (dev))
- {
- /* Wierd as it may seem, we lock here to balance the unlock in "out:" */
- nm_lock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__);
- goto out;
- }
- found_ap = TRUE;
- }
- if (found_ap)
- syslog (LOG_ERR, "Activation (%s/wireless): found access point '%s' to use.", nm_device_get_iface (dev), nm_ap_get_essid (best_ap));
+ /* Get a valid "best" access point we should connect to. */
+ nm_device_set_now_scanning (dev, TRUE);
- /* Set ESSID early so that when we send out the DeviceStatusChanged signal below,
- * we are able to respond correctly to queries for "getActiveNetwork" against
- * our device. nm_device_get_path_for_ap() uses the /card's/ AP, not the best_ap.
- */
- nm_device_set_essid (dev, nm_ap_get_essid (best_ap));
+ /* Get an access point to connect to */
+ args[0] = dev;
+ args[1] = &best_ap;
+ args[2] = &err;
+ nm_wait_for_completion (NM_COMPLETION_TRIES_INFINITY, G_USEC_PER_SEC / 50,
+ nm_wa_test, NULL, args);
+ if (err)
+ {
+ /* Wierd as it may seem, we lock here to balance the unlock in "out:" */
+ nm_lock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__);
+ goto out;
+ }
+ syslog (LOG_ERR, "Activation (%s/wireless): found access point '%s' to use.", nm_device_get_iface (dev), nm_ap_get_essid (best_ap));
/* We grab the scan mutex so that scanning cannot screw up our link detection, since
* a scan can change most any attribute on the card for a period of time.
@@ -2155,6 +2403,8 @@ get_ap:
need_key = AP_NEED_KEY (dev, best_ap);
need_key:
+ if (nm_device_activation_handle_cancel (dev))
+ goto out;
if (need_key)
{
char *essid = nm_ap_get_essid (best_ap);
@@ -2173,9 +2423,11 @@ need_key:
/* Wait for the key to come back */
syslog (LOG_DEBUG, "Activation (%s/wireless): asking for user key.", nm_device_get_iface (dev));
- while (!dev->options.wireless.user_key_received && !dev->quit_activation)
- g_usleep (G_USEC_PER_SEC / 2);
+ args[0] = dev;
+ args[1] = &err;
+ nm_wait_for_completion (NM_COMPLETION_TRIES_INFINITY,
+ G_USEC_PER_SEC / 20, nm_dukr_test, nm_dukr_test, args);
syslog (LOG_DEBUG, "Activation (%s/wireless): user key received.", nm_device_get_iface (dev));
/* Done waiting, grab lock again */
@@ -2241,6 +2493,12 @@ try_connect:
nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)");
}
+ /* Don't try other APs for non-scanning devices.
+ * User must pick a new one manually.
+ */
+ if (!nm_device_get_supports_wireless_scan (dev))
+ goto out;
+
/* All applicable modes failed, invalidate current best_ap and get a new one */
invalidate_ap (dev, best_ap);
goto get_ap;
@@ -2250,8 +2508,15 @@ try_connect:
* and also for Open System mode (where you cannot know WEP key is wrong ever), we try to
* do DHCP and if that fails, fall back to next auth mode and try again.
*/
+ success = FALSE;
if ((success = nm_device_activation_configure_ip (dev, adhoc)))
{
+ if (nm_device_activation_handle_cancel (dev))
+ {
+ success = FALSE;
+ goto out;
+ }
+
/* Cache the last known good auth method in both NetworkManagerInfo and our allowed AP list */
nm_dbus_update_network_auth_method (dev->app_data->dbus_connection, nm_ap_get_essid (best_ap), nm_ap_get_auth_method (best_ap));
if ((tmp_ap = nm_ap_list_get_ap_by_essid (dev->app_data->allowed_ap_list, nm_ap_get_essid (best_ap))))
@@ -2259,7 +2524,6 @@ try_connect:
}
else
{
- /* If we were told to quit activation, stop the thread and return */
if (nm_device_activation_handle_cancel (dev))
goto out;
@@ -2281,6 +2545,12 @@ try_connect:
}
else
{
+ /* Don't try other APs for non-scanning devices.
+ * User must pick a new one manually.
+ */
+ if (!nm_device_get_supports_wireless_scan (dev))
+ goto out;
+
/* All applicable modes failed, invalidate current best_ap and get a new one */
invalidate_ap (dev, best_ap);
goto get_ap;
@@ -2291,7 +2561,10 @@ try_connect:
connect_done:
/* If we were told to quit activation, stop the thread and return */
if (nm_device_activation_handle_cancel (dev))
+ {
+ success = FALSE;
goto out;
+ }
if (success)
{
@@ -2350,7 +2623,10 @@ static gboolean nm_device_activation_configure_ip (NMDevice *dev, gboolean do_on
else
{
/* Manually set up the device */
+ nm_system_device_clear_ip4_nameservers (dev);
+ nm_system_device_clear_domain_searches (dev);
success = nm_system_device_setup_static_ip4_config (dev);
+ nm_device_update_ip4_address (dev);
}
if (success)
@@ -2375,6 +2651,7 @@ static gboolean nm_device_activate (gpointer user_data)
NMDevice *dev = (NMDevice *)user_data;
gboolean success = FALSE;
gboolean finished = FALSE;
+ NMAccessPoint *failed_best_ap = NULL;
g_return_val_if_fail (dev != NULL, FALSE);
g_return_val_if_fail (dev->app_data != NULL, FALSE);
@@ -2421,10 +2698,15 @@ static gboolean nm_device_activate (gpointer user_data)
out:
syslog (LOG_DEBUG, "Activation (%s) ended.\n", nm_device_get_iface (dev));
+ if (finished)
+ {
+ if (nm_device_is_wireless (dev) && !success)
+ failed_best_ap = nm_device_get_best_ap (dev);
+ }
dev->activating = FALSE;
dev->quit_activation = FALSE;
if (finished)
- nm_device_activation_schedule_finish (dev, success ? DEVICE_NOW_ACTIVE : DEVICE_ACTIVATION_FAILED);
+ nm_device_activation_schedule_finish (dev, failed_best_ap, success ? DEVICE_NOW_ACTIVE : DEVICE_ACTIVATION_FAILED);
return FALSE;
}
@@ -2458,6 +2740,35 @@ gboolean nm_device_activation_should_cancel (NMDevice *dev)
}
+static gboolean nm_ac_test (int tries, nm_completion_args args)
+{
+ NMDevice *dev = args[0];
+
+ g_return_val_if_fail (dev != NULL, TRUE);
+
+ if (tries == 0 && nm_device_get_dhcp_iface (dev))
+ nm_device_dhcp_cease (dev);
+
+ if (nm_device_is_activating(dev))
+ {
+ /* Nice race here between quit activation and dhcp. We may
+ * not have started DHCP when we're told to quit activation,
+ * so we need to keep signalling dhcp to quit, which it will
+ * pick up whenever it starts.
+ *
+ * This should really be taken care of a better way.
+ */
+ if (nm_device_get_dhcp_iface (dev))
+ nm_device_dhcp_cease (dev);
+ if (tries % 20 == 0)
+ syslog (LOG_DEBUG, "Activation (%s/wireless): waiting on dhcp to cease or device to finish activation", nm_device_get_iface(dev));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
/*
* nm_device_activation_cancel
*
@@ -2466,6 +2777,8 @@ gboolean nm_device_activation_should_cancel (NMDevice *dev)
*/
void nm_device_activation_cancel (NMDevice *dev)
{
+ nm_completion_args args;
+
g_return_if_fail (dev != NULL);
if (nm_device_is_activating (dev))
@@ -2477,18 +2790,9 @@ void nm_device_activation_cancel (NMDevice *dev)
* The other problem with waiting here is that we hold up dbus traffic
* that we should respond to.
*/
- while (nm_device_is_activating (dev))
- {
- /* Nice race here between quit activation and dhcp. We may not have
- * started DHCP when we're told to quit activation, so we need to keep
- * signalling dhcp to quit, which it will pick up whenever it starts.
- * This should really be taken care of a better way.
- */
- if (dev->dhcp_iface)
- nm_device_dhcp_cease (dev);
-
- g_usleep (G_USEC_PER_SEC / 2);
- }
+ args[0] = dev;
+ nm_wait_for_completion(NM_COMPLETION_TRIES_INFINITY,
+ G_USEC_PER_SEC / 20, nm_ac_test, NULL, args);
syslog (LOG_DEBUG, "nm_device_activation_cancel(%s): cancelled.", nm_device_get_iface (dev));
}
}
@@ -2854,6 +3158,22 @@ void nm_device_update_best_ap (NMDevice *dev)
g_return_if_fail (dev->app_data != NULL);
g_return_if_fail (nm_device_is_wireless (dev));
+ /* Devices that can't scan don't do anything automatic.
+ * The user must choose the access point from the menu.
+ */
+ if (!nm_device_get_supports_wireless_scan (dev))
+ {
+ /* If we lost a link to the AP, clear it out.
+ *
+ * FIXME: take samples over 5 seconds or so of the
+ * whether or not the link is active and only blow away
+ * the best_ap if its been down for 5 seconds or more.
+ */
+ if (!nm_device_get_link_active (dev))
+ nm_device_set_best_ap (dev, NULL);
+ return;
+ }
+
if (!(ap_list = nm_device_ap_list_get (dev)))
return;
@@ -2979,6 +3299,13 @@ static gboolean nm_device_wireless_force_use (NMDevice *dev, const char *essid,
nm_ap_list_append_ap (nm_device_ap_list_get (dev), ap);
nm_ap_unref (ap);
}
+ else
+ {
+ /* If the AP is in the ignore list, we have to remove it since
+ * the User Knows What's Best.
+ */
+ nm_ap_list_remove_ap_by_essid (dev->app_data->invalid_ap_list, nm_ap_get_essid (ap));
+ }
/* Now that this AP has an essid, copy over encryption keys and whatnot */
if ((tmp_ap = nm_ap_list_get_ap_by_essid (dev->app_data->allowed_ap_list, nm_ap_get_essid (ap))))
@@ -3031,9 +3358,11 @@ gboolean nm_device_force_use (gpointer user_data)
out:
/* Function that scheduled us must ref the device */
- nm_device_unref (cb_data->dev);
+ if (cb_data->dev)
+ nm_device_unref (cb_data->dev);
+ if (app_data)
+ app_data->forcing_device = FALSE;
- app_data->forcing_device = FALSE;
g_free (cb_data);
return FALSE;
}
@@ -3062,86 +3391,6 @@ void nm_device_schedule_force_use (NMDevice *dev, const char *network, const cha
/*
- * nm_device_do_pseudo_scan
- *
- * Brute-force the allowed access point list to find one that works, if any.
- *
- * FIXME
- * There's probably a better way to do the non-scanning access point discovery
- * than brute forcing it like this, but that makes the state machine here oh so
- * much more complicated.
- */
-static void nm_device_do_pseudo_scan (NMDevice *dev)
-{
- NMAPListIter *iter;
- NMAccessPoint *ap;
-
- g_return_if_fail (dev != NULL);
- g_return_if_fail (dev->app_data != NULL);
-
- /* Test devices shouldn't get here since we fake the AP list earlier */
- g_return_if_fail (!dev->test_device);
-
- nm_device_ref (dev);
-
- if (!(iter = nm_ap_list_iter_new (dev->app_data->allowed_ap_list)))
- return;
-
- nm_device_set_essid (dev, "");
- while ((ap = nm_ap_list_iter_next (iter)))
- {
- gboolean valid = FALSE;
- struct ether_addr save_ap_addr;
- struct ether_addr cur_ap_addr;
-
- if (!nm_device_is_up (dev));
- nm_device_bring_up (dev);
-
- /* Save the MAC address */
- nm_device_get_ap_address (dev, &save_ap_addr);
-
- if (nm_ap_get_enc_key_source (ap))
- {
- char *hashed_key = nm_ap_get_enc_key_hashed (ap);
- nm_device_set_enc_key (dev, hashed_key, NM_DEVICE_AUTH_METHOD_SHARED_KEY);
- g_free (hashed_key);
- }
- else
- nm_device_set_enc_key (dev, NULL, NM_DEVICE_AUTH_METHOD_NONE);
- nm_device_set_essid (dev, nm_ap_get_essid (ap));
-
- /* Wait a bit for association */
- g_usleep (G_USEC_PER_SEC * nm_device_get_association_pause_value (dev));
-
- /* Do we have a valid MAC address? */
- nm_device_get_ap_address (dev, &cur_ap_addr);
- valid = nm_ethernet_address_is_valid (&cur_ap_addr);
-
- /* If the ap address we had before, and the ap address we
- * have now, are the same, AP is invalid. Certain cards (orinoco)
- * will let the essid change, but the the card won't actually de-associate
- * from the previous access point if it can't associate with the new one
- * (ie signal too weak, etc).
- */
- if (valid && (memcmp (&save_ap_addr, &cur_ap_addr, sizeof (struct ether_addr)) == 0))
- valid = FALSE;
-
- if (valid)
- {
- syslog(LOG_INFO, "%s: setting AP '%s' best", nm_device_get_iface (dev), nm_ap_get_essid (ap));
-
- nm_device_set_best_ap (dev, ap);
- nm_policy_schedule_state_update (dev->app_data);
- break;
- }
- }
-
- nm_ap_list_iter_free (iter);
- nm_device_unref (dev);
-}
-
-
-/*
* nm_device_fake_ap_list
*
* Fake the access point list, used for test devices.
@@ -3211,14 +3460,19 @@ static void nm_device_fake_ap_list (NMDevice *dev)
*/
static void nm_device_wireless_schedule_scan (NMDevice *dev)
{
- GSource *wscan_source;
- guint wscan_source_id;
+ GSource *wscan_source;
+ guint wscan_source_id;
+ NMWirelessScanCB *scan_cb;
g_return_if_fail (dev != NULL);
g_return_if_fail (nm_device_is_wireless (dev));
+ scan_cb = g_malloc0 (sizeof (NMWirelessScanCB));
+ scan_cb->dev = dev;
+ scan_cb->reschedule = TRUE;
+
wscan_source = g_timeout_source_new (dev->options.wireless.scan_interval * 1000);
- g_source_set_callback (wscan_source, nm_device_wireless_scan, dev, NULL);
+ g_source_set_callback (wscan_source, nm_device_wireless_scan, scan_cb, NULL);
wscan_source_id = g_source_attach (wscan_source, dev->context);
g_source_unref (wscan_source);
}
@@ -3236,7 +3490,6 @@ static gboolean nm_device_wireless_process_scan_results (gpointer user_data)
NMWirelessScanResults *results = (NMWirelessScanResults *)user_data;
NMDevice *dev;
wireless_scan *tmp_ap;
- gboolean have_blank_essids = FALSE;
NMAPListIter *iter;
GTimeVal cur_time;
gboolean list_changed = FALSE;
@@ -3244,26 +3497,9 @@ static gboolean nm_device_wireless_process_scan_results (gpointer user_data)
g_return_val_if_fail (results != NULL, FALSE);
dev = results->dev;
-
if (!dev || !results->scan_head.result)
return FALSE;
- /* Test devices get their info faked */
- if (dev->test_device)
- {
- nm_device_fake_ap_list (dev);
- return FALSE;
- }
-
- /* Devices that don't support scanning have their pseudo-scanning done in
- * the main thread anyway.
- */
- if (!nm_device_get_supports_wireless_scan (dev))
- {
- nm_device_do_pseudo_scan (dev);
- return FALSE;
- }
-
g_get_current_time (&cur_time);
/* Translate iwlib scan results to NM access point list */
@@ -3346,7 +3582,7 @@ static gboolean nm_device_wireless_process_scan_results (gpointer user_data)
{
/* Handle dbus signals that we need to broadcast when the AP is added to the list or changes
* strength.
- */
+ */
if (new)
{
nm_dbus_signal_wireless_network_change (dev->app_data->dbus_connection, dev, nm_ap,
@@ -3419,6 +3655,56 @@ static gboolean nm_device_wireless_process_scan_results (gpointer user_data)
}
+static gboolean nm_completion_scan_has_results (int tries, nm_completion_args args)
+{
+ NMDevice *dev = args[0];
+ gboolean *err = args[1];
+ NMSock *sk = args[2];
+ NMWirelessScanResults *scan_results = args[3];
+ int rc;
+
+ g_return_val_if_fail (dev != NULL, TRUE);
+ g_return_val_if_fail (err != NULL, TRUE);
+ g_return_val_if_fail (scan_results != NULL, TRUE);
+
+ rc = iw_scan (nm_dev_sock_get_fd (sk), (char *)nm_device_get_iface (dev), WIRELESS_EXT, &(scan_results->scan_head));
+ *err = FALSE;
+ if (rc == -1 && errno == ETIME)
+ {
+ /* Scans take time. iw_scan's timeout is 15 seconds, so if the card hasn't returned
+ * scan results after two consecutive runs of iw_scan(), the card sucks.
+ */
+ if (tries >= 1)
+ {
+ syslog (LOG_DEBUG, "Warning: the wireless card (%s) requires too much time for scans. Its driver needs to be fixed.", nm_device_get_iface (dev));
+ scan_results->scan_head.result = NULL;
+ *err = TRUE;
+ return TRUE;
+ }
+ else
+ {
+ /* Give the card one more chance to return scan results */
+ scan_results->scan_head.result = NULL;
+ return FALSE;
+ }
+ }
+ if ((rc == -1 && errno == ENODATA) || (rc == 0 && scan_results->scan_head.result == NULL))
+ {
+ /* Card hasn't had time yet to compile full access point list.
+ * Give it some more time and scan again. If that doesn't
+ * work, we eventually give up. */
+ scan_results->scan_head.result = NULL;
+ return FALSE;
+ }
+ else if (rc == -1)
+ {
+ scan_results->scan_head.result = NULL;
+ return TRUE;
+ }
+ return TRUE;
+}
+
+
/*
* nm_device_wireless_scan
*
@@ -3427,39 +3713,71 @@ static gboolean nm_device_wireless_process_scan_results (gpointer user_data)
*/
static gboolean nm_device_wireless_scan (gpointer user_data)
{
- NMDevice *dev = (NMDevice *)(user_data);
- int sk;
+ NMWirelessScanCB *scan_cb = (NMWirelessScanCB *)(user_data);
+ NMDevice *dev = NULL;
NMWirelessScanResults *scan_results = NULL;
- g_return_val_if_fail (dev != NULL, FALSE);
- g_return_val_if_fail (dev->app_data != NULL, FALSE);
+ g_return_val_if_fail (scan_cb != NULL, FALSE);
- /* We don't scan on test devices or devices that don't have scanning support */
- if (dev->test_device || !nm_device_get_supports_wireless_scan (dev))
+ dev = scan_cb->dev;
+ if (!dev || !dev->app_data)
+ {
+ g_free (scan_cb);
return FALSE;
+ }
+
+ /* Reschedule if scanning is off, or if scanning is AUTO and we are
+ * associated to an access point.
+ */
+ if ( (dev->app_data->scanning_method == NM_SCAN_METHOD_NEVER)
+ || ( (dev->app_data->scanning_method == NM_SCAN_METHOD_WHEN_UNASSOCIATED)
+ && (dev->app_data->active_device == dev)
+ && nm_device_is_activating(dev)))
+ {
+ dev->options.wireless.scan_interval = 10;
+ goto reschedule;
+ }
- /* Just reschedule ourselves if scanning or all wireless is disabled */
- if ( (dev->app_data->scanning_enabled == FALSE)
- || (dev->app_data->wireless_enabled == FALSE))
+ /* Reschedule ourselves if all wireless is disabled, we're asleep,
+ * or we are currently activating.
+ */
+ if ( (dev->app_data->wireless_enabled == FALSE)
+ || (dev->app_data->asleep == TRUE))
{
dev->options.wireless.scan_interval = 10;
goto reschedule;
}
+ /* Test devices get a fake ap list */
+ if (dev->test_device)
+ {
+ nm_device_fake_ap_list (dev);
+ dev->options.wireless.scan_interval = 20;
+ goto reschedule;
+ }
+
/* Grab the scan mutex */
if (nm_try_acquire_mutex (dev->options.wireless.scan_mutex, __FUNCTION__))
{
+ NMSock *sk;
+ gboolean devup_err;
+
/* Device must be up before we can scan */
- if (!nm_device_is_up (dev))
- nm_device_bring_up (dev);
- g_usleep (G_USEC_PER_SEC);
+ devup_err = nm_device_bring_up_wait(dev, 1);
+ if (devup_err)
+ {
+ nm_unlock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__);
+ goto reschedule;
+ }
- if ((sk = iw_sockets_open ()) >= 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_WIRELESS, __FUNCTION__, NULL)))
{
- int err;
- NMNetworkMode orig_mode = NETWORK_MODE_INFRA;
- double orig_freq = 0;
- int orig_rate = 0;
+ int err;
+ NMNetworkMode orig_mode = NETWORK_MODE_INFRA;
+ double orig_freq = 0;
+ int orig_rate = 0;
+ const int max_wait = G_USEC_PER_SEC * nm_device_get_association_pause_value (dev) /2;
+ nm_completion_args args;
orig_mode = nm_device_get_mode (dev);
if (orig_mode == NETWORK_MODE_ADHOC)
@@ -3475,20 +3793,13 @@ static gboolean nm_device_wireless_scan (gpointer user_data)
nm_device_set_frequency (dev, 0);
scan_results = g_malloc0 (sizeof (NMWirelessScanResults));
- err = iw_scan (sk, (char *)nm_device_get_iface (dev), WIRELESS_EXT, &(scan_results->scan_head));
- if ((err == -1) && (errno == ENODATA))
- {
- /* Card hasn't had time yet to compile full access point list.
- * Give it some more time and scan again. If that doesn't work
- * give up.
- */
- g_usleep ((G_USEC_PER_SEC * nm_device_get_association_pause_value (dev)) / 2);
- err = iw_scan (sk, (char *)nm_device_get_iface (dev), WIRELESS_EXT, &(scan_results->scan_head));
- if (err == -1)
- scan_results->scan_head.result = NULL;
- }
- else if ((err == -1) && (errno == ETIME))
- syslog (LOG_ERR, "Warning: the wireless card (%s) requires too much time for scans. Its driver needs to be fixed.", nm_device_get_iface (dev));
+
+ args[0] = dev;
+ args[1] = &err;
+ args[2] = sk;
+ args[3] = scan_results;
+ nm_wait_for_completion(max_wait, max_wait/20,
+ nm_completion_scan_has_results, NULL, args);
nm_device_set_mode (dev, orig_mode);
/* Only set frequency if ad-hoc mode */
@@ -3498,7 +3809,13 @@ static gboolean nm_device_wireless_scan (gpointer user_data)
nm_device_set_bitrate (dev, orig_rate);
}
- close (sk);
+ nm_dev_sock_close (sk);
+
+ if (!scan_results->scan_head.result)
+ {
+ g_free (scan_results);
+ scan_results = NULL;
+ }
}
nm_unlock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__);
}
@@ -3511,17 +3828,23 @@ static gboolean nm_device_wireless_scan (gpointer user_data)
{
guint scan_process_source_id = 0;
GSource *scan_process_source = g_idle_source_new ();
+ GTimeVal cur_time;
scan_results->dev = dev;
g_source_set_callback (scan_process_source, nm_device_wireless_process_scan_results, scan_results, NULL);
scan_process_source_id = g_source_attach (scan_process_source, dev->app_data->main_context);
g_source_unref (scan_process_source);
+
+ g_get_current_time (&cur_time);
+ dev->options.wireless.last_scan = cur_time.tv_sec;
}
reschedule:
/* Make sure we reschedule ourselves so we keep scanning */
- nm_device_wireless_schedule_scan (dev);
+ if (scan_cb->reschedule)
+ nm_device_wireless_schedule_scan (dev);
+ g_free (scan_cb);
return FALSE;
}
@@ -3613,29 +3936,29 @@ typedef u_int64_t u64;
static gboolean supports_ethtool_carrier_detect (NMDevice *dev)
{
- int sk;
+ NMSock *sk;
struct ifreq ifr;
gboolean supports_ethtool = FALSE;
struct ethtool_cmd edata;
g_return_val_if_fail (dev != NULL, FALSE);
- if ((sk = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_GENERAL, __FUNCTION__, NULL)) == NULL)
{
- syslog (LOG_ERR, "cannot open socket on interface %s for MII detect; errno=%d", nm_device_get_iface (dev), errno);
+ syslog (LOG_ERR, "cannot open socket on interface %s for ethtool detect; errno=%d", nm_device_get_iface (dev), errno);
return (FALSE);
}
strncpy (ifr.ifr_name, nm_device_get_iface (dev), sizeof(ifr.ifr_name)-1);
edata.cmd = ETHTOOL_GLINK;
ifr.ifr_data = (char *) &edata;
- if (ioctl(sk, SIOCETHTOOL, &ifr) == -1)
+ if (ioctl (nm_dev_sock_get_fd (sk), SIOCETHTOOL, &ifr) == -1)
goto out;
supports_ethtool = TRUE;
out:
- close (sk);
+ nm_dev_sock_close (sk);
return (supports_ethtool);
}
@@ -3646,17 +3969,17 @@ out:
/**************************************/
#include <linux/mii.h>
-static int mdio_read (int sk, struct ifreq *ifr, int location)
+static int mdio_read (NMSock *sk, struct ifreq *ifr, int location)
{
struct mii_ioctl_data *mii;
- g_return_val_if_fail (sk < 0, -1);
+ g_return_val_if_fail (sk != NULL, -1);
g_return_val_if_fail (ifr != NULL, -1);
mii = (struct mii_ioctl_data *) &(ifr->ifr_data);
mii->reg_num = location;
- if (ioctl (sk, SIOCGMIIREG, &ifr) < 0)
+ if (ioctl (nm_dev_sock_get_fd (sk), SIOCGMIIREG, ifr) < 0)
return -1;
return (mii->val_out);
@@ -3664,29 +3987,29 @@ static int mdio_read (int sk, struct ifreq *ifr, int location)
static gboolean supports_mii_carrier_detect (NMDevice *dev)
{
- int sk;
+ NMSock *sk;
struct ifreq ifr;
int bmsr;
gboolean supports_mii = FALSE;
g_return_val_if_fail (dev != NULL, FALSE);
- if ((sk = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
+ if ((sk = nm_dev_sock_open (dev, DEV_GENERAL, __FUNCTION__, NULL)) == NULL)
{
syslog (LOG_ERR, "cannot open socket on interface %s for MII detect; errno=%d", nm_device_get_iface (dev), errno);
return (FALSE);
}
strncpy (ifr.ifr_name, nm_device_get_iface (dev), sizeof(ifr.ifr_name)-1);
- if (ioctl(sk, SIOCGMIIPHY, &ifr) < 0)
+ if (ioctl (nm_dev_sock_get_fd (sk), SIOCGMIIPHY, &ifr) < 0)
goto out;
/* If we can read the BMSR register, we assume that the card supports MII link detection */
- bmsr = mdio_read(sk, &ifr, MII_BMSR);
+ bmsr = mdio_read (sk, &ifr, MII_BMSR);
supports_mii = (bmsr != -1) ? TRUE : FALSE;
out:
- close (sk);
+ nm_dev_sock_close (sk);
return (supports_mii);
}
diff --git a/src/NetworkManagerDevice.h b/src/NetworkManagerDevice.h
index def2cc93fb..339290d9e7 100644
--- a/src/NetworkManagerDevice.h
+++ b/src/NetworkManagerDevice.h
@@ -70,7 +70,7 @@ NMNetworkMode nm_device_get_mode (NMDevice *dev);
guint32 nm_device_get_ip4_address (NMDevice *dev);
void nm_device_update_ip4_address (NMDevice *dev);
-void nm_device_get_hw_address (NMDevice *dev, unsigned char hw_addr[ETH_ALEN]);
+void nm_device_get_hw_address (NMDevice *dev, unsigned char *eth_addr);
void nm_device_update_hw_address (NMDevice *dev);
void nm_device_get_ip6_address (NMDevice *dev);
@@ -121,6 +121,7 @@ void nm_device_ap_list_clear (NMDevice *dev);
struct NMAccessPointList *nm_device_ap_list_get (NMDevice *dev);
NMAccessPoint *nm_device_ap_list_get_ap_by_essid (NMDevice *dev, const char *essid);
NMAccessPoint *nm_device_ap_list_get_ap_by_address(NMDevice *dev, const struct ether_addr *addr);
+void nm_device_copy_allowed_to_dev_list (NMDevice *dev, struct NMAccessPointList *allowed_list);
/* System config data accessors */
gboolean nm_device_config_get_use_dhcp (NMDevice *dev);
diff --git a/src/NetworkManagerDevicePrivate.h b/src/NetworkManagerDevicePrivate.h
index 16d6948c56..610bef4c7d 100644
--- a/src/NetworkManagerDevicePrivate.h
+++ b/src/NetworkManagerDevicePrivate.h
@@ -49,6 +49,7 @@ typedef struct NMDeviceWirelessOptions
GMutex *scan_mutex;
NMAccessPointList *ap_list;
guint8 scan_interval; /* seconds */
+ guint32 last_scan;
NMAccessPoint *best_ap;
GMutex *best_ap_mutex;
@@ -105,7 +106,7 @@ struct NMDevice
GMainContext *context;
GMainLoop *loop;
- gboolean worker_done;
+ GThread *worker;
gboolean worker_started;
guint renew_timeout;
guint rebind_timeout;
diff --git a/src/NetworkManagerMain.h b/src/NetworkManagerMain.h
index 18b424eb77..122fad232f 100644
--- a/src/NetworkManagerMain.h
+++ b/src/NetworkManagerMain.h
@@ -64,8 +64,9 @@ typedef struct NMData
gboolean forcing_device;
- gboolean scanning_enabled;
+ NMWirelessScanMethod scanning_method;
gboolean wireless_enabled;
+ gboolean asleep;
struct NMAccessPointList *allowed_ap_list;
struct NMAccessPointList *invalid_ap_list;
diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c
index 71910fdf68..a5b845c881 100644
--- a/src/NetworkManagerPolicy.c
+++ b/src/NetworkManagerPolicy.c
@@ -165,6 +165,12 @@ static NMDevice * nm_policy_get_best_device (NMDevice *switch_to_dev, NMData *da
if (should_lock_on_activate)
*should_lock_on_activate = FALSE;
+ if (data->asleep == TRUE)
+ {
+ data->active_device_locked = FALSE;
+ return NULL;
+ }
+
/* Prefer a device forced on us by the user */
if (switch_to_dev && !nm_device_get_removed (switch_to_dev))
{
@@ -227,6 +233,7 @@ gboolean nm_policy_activation_finish (gpointer user_data)
{
NMActivationResult *result = (NMActivationResult *)user_data;
NMDevice *dev = NULL;
+ NMAccessPoint *failed_ap = NULL;
NMData *data = NULL;
g_return_val_if_fail (result != NULL, FALSE);
@@ -234,6 +241,8 @@ gboolean nm_policy_activation_finish (gpointer user_data)
if (!(dev = result->dev))
goto out;
+ failed_ap = result->failed_ap;
+
if (!(data = nm_device_get_app_data (dev)))
goto out;
@@ -268,22 +277,29 @@ gboolean nm_policy_activation_finish (gpointer user_data)
nm_dbus_signal_device_status_change (data->dbus_connection, dev, result->result);
if (nm_device_is_wireless (dev))
{
- NMAccessPoint *ap = nm_device_get_best_ap (dev);
- if (ap)
+ if (failed_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_ap_list_append_ap (data->invalid_ap_list, failed_ap);
nm_device_update_best_ap (dev);
-
- /* Unref because nm_device_get_best_ap() refs it before returning. */
- nm_ap_unref (ap);
}
- syslog (LOG_INFO, "Activation (%s) failed for access point (%s)", nm_device_get_iface (dev), ap ? nm_ap_get_essid (ap) : "(none)");
+
+ syslog (LOG_INFO, "Activation (%s) failed for access point (%s)", nm_device_get_iface (dev),
+ failed_ap ? nm_ap_get_essid (failed_ap) : "(none)");
+
+ /* Failed AP got reffed by nm_device_get_best_ap() during activation,
+ * must unref it here.
+ */
+ if (failed_ap)
+ nm_ap_unref (failed_ap);
}
else
syslog (LOG_INFO, "Activation (%s) failed.", nm_device_get_iface (dev));
if (data->active_device == dev)
+ {
+ nm_device_unref (dev);
data->active_device = NULL;
+ }
nm_device_deactivate (dev, FALSE);
break;
@@ -468,7 +484,8 @@ void nm_policy_schedule_device_switch (NMDevice *switch_to_dev, NMData *app_data
*/
static gboolean nm_policy_allowed_ap_list_update (gpointer user_data)
{
- NMData *data = (NMData *)user_data;
+ NMData *data = (NMData *)user_data;
+ GSList *elt;
g_return_val_if_fail (data != NULL, FALSE);
@@ -481,6 +498,27 @@ static gboolean nm_policy_allowed_ap_list_update (gpointer user_data)
if (data->allowed_ap_list)
nm_ap_list_populate_from_nmi (data->allowed_ap_list, data);
+ for (elt = data->dev_list; elt != NULL; elt = g_slist_next (elt))
+ {
+ NMDevice *dev = (NMDevice *)(elt->data);
+ if (nm_device_is_wireless (dev))
+ {
+ if (nm_device_get_supports_wireless_scan (dev))
+ {
+ /* Once we have the list, copy in any relevant information from our Allowed list and fill
+ * in the ESSID of base stations that aren't broadcasting their ESSID, if we have their
+ * MAC address in our allowed list.
+ */
+ nm_ap_list_copy_essids_by_address (nm_device_ap_list_get (dev), data->allowed_ap_list);
+ nm_ap_list_copy_properties (nm_device_ap_list_get (dev), data->allowed_ap_list);
+ }
+ else
+ nm_device_copy_allowed_to_dev_list (dev, data->allowed_ap_list);
+
+ nm_ap_list_remove_duplicate_essids (nm_device_ap_list_get (dev));
+ }
+ }
+
/* If the active device doesn't have a best_ap already, make it update to
* get the new data.
*/
@@ -490,13 +528,6 @@ static gboolean nm_policy_allowed_ap_list_update (gpointer user_data)
{
NMAccessPoint *best_ap;
- /* Once we have the list, copy in any relevant information from our Allowed list and fill
- * in the ESSID of base stations that aren't broadcasting their ESSID, if we have their
- * MAC address in our allowed list.
- */
- nm_ap_list_copy_essids_by_address (nm_device_ap_list_get (data->active_device), data->allowed_ap_list);
- nm_ap_list_copy_properties (nm_device_ap_list_get (data->active_device), data->allowed_ap_list);
-
best_ap = nm_device_get_best_ap (data->active_device);
if (!best_ap)
nm_device_update_best_ap (data->active_device);
diff --git a/src/NetworkManagerPolicy.h b/src/NetworkManagerPolicy.h
index 3a6524118e..c347812935 100644
--- a/src/NetworkManagerPolicy.h
+++ b/src/NetworkManagerPolicy.h
@@ -29,6 +29,7 @@
typedef struct
{
NMDevice *dev;
+ NMAccessPoint *failed_ap;
DeviceStatus result;
} NMActivationResult;
diff --git a/src/NetworkManagerSystem.c b/src/NetworkManagerSystem.c
index cca0364e50..66445f8fb7 100644
--- a/src/NetworkManagerSystem.c
+++ b/src/NetworkManagerSystem.c
@@ -41,41 +41,28 @@
#include <glib.h>
#include "NetworkManagerSystem.h"
#include "NetworkManagerDevice.h"
-
-static int nm_system_open_sock (void)
-{
- int fd;
-
- /* Try to grab a control socket */
- fd = socket (AF_PACKET, SOCK_PACKET, htons (ETH_P_ALL));
- if (fd >= 0)
- return (fd);
-
- syslog (LOG_ERR, "nm_system_open_sock() could not get network control socket.");
- return (-1);
-}
-
+#include "NetworkManagerUtils.h"
gboolean nm_system_device_set_ip4_address (NMDevice *dev, int ip4_address)
{
struct ifreq ifr;
const char *iface;
- int sk;
+ NMSock *sk;
gboolean success = FALSE;
struct sockaddr_in *p = (struct sockaddr_in *)&(ifr.ifr_addr);
g_return_val_if_fail (dev != NULL, FALSE);
- iface = nm_device_get_iface (dev);
- sk = nm_system_open_sock ();
- if (sk < 0)
+ if ((sk = nm_dev_sock_open (dev, NETWORK_CONTROL, __FUNCTION__, NULL)) == NULL)
return FALSE;
memset (&ifr, 0, sizeof(struct ifreq));
+
+ iface = nm_device_get_iface (dev);
memcpy (ifr.ifr_name, iface, strlen (iface));
p->sin_family = AF_INET;
p->sin_addr.s_addr = ip4_address;
- if (ioctl (sk, SIOCSIFADDR, &ifr) == -1)
+ if (ioctl (nm_dev_sock_get_fd (sk), SIOCSIFADDR, &ifr) == -1)
syslog (LOG_ERR,"nm_system_device_set_ip4_address (%s): failed to set IPv4 address!", iface);
else
{
@@ -85,7 +72,7 @@ gboolean nm_system_device_set_ip4_address (NMDevice *dev, int ip4_address)
((unsigned char *)&ip4_address)[2], ((unsigned char *)&ip4_address)[3]);
}
- close (sk);
+ nm_dev_sock_close (sk);
return (success);
}
@@ -94,27 +81,27 @@ gboolean nm_system_device_set_ip4_netmask (NMDevice *dev, int ip4_netmask)
{
struct ifreq ifr;
const char *iface;
- int sk;
+ NMSock *sk;
gboolean success = FALSE;
struct sockaddr_in *p = (struct sockaddr_in *)&(ifr.ifr_addr);
g_return_val_if_fail (dev != NULL, FALSE);
- iface = nm_device_get_iface (dev);
- sk = nm_system_open_sock ();
- if (sk < 0)
+ if ((sk = nm_dev_sock_open (dev, NETWORK_CONTROL, __FUNCTION__, NULL)) == NULL)
return FALSE;
memset (&ifr, 0, sizeof(struct ifreq));
+
+ iface = nm_device_get_iface (dev);
memcpy (ifr.ifr_name, iface, strlen (iface));
p->sin_family = AF_INET;
p->sin_addr.s_addr = ip4_netmask;
- if (ioctl (sk, SIOCSIFNETMASK, &ifr) == -1)
+ if (ioctl (nm_dev_sock_get_fd (sk), SIOCSIFNETMASK, &ifr) == -1)
syslog (LOG_ERR,"nm_system_device_set_ip4_netmask (%s): failed to set IPv4 netmask! errno = %s", iface, strerror (errno));
else
success = TRUE;
- close (sk);
+ nm_dev_sock_close (sk);
return (success);
}
@@ -123,27 +110,26 @@ gboolean nm_system_device_set_ip4_broadcast (NMDevice *dev, int ip4_broadcast)
{
struct ifreq ifr;
const char *iface;
- int sk;
+ NMSock *sk;
gboolean success = FALSE;
struct sockaddr_in *p = (struct sockaddr_in *)&(ifr.ifr_addr);
g_return_val_if_fail (dev != NULL, FALSE);
- iface = nm_device_get_iface (dev);
- sk = nm_system_open_sock ();
- if (sk < 0)
+ if ((sk = nm_dev_sock_open (dev, NETWORK_CONTROL, __FUNCTION__, NULL)) == NULL)
return FALSE;
memset (&ifr, 0, sizeof(struct ifreq));
+ iface = nm_device_get_iface (dev);
memcpy (ifr.ifr_name, iface, strlen (iface));
p->sin_family = AF_INET;
p->sin_addr.s_addr = ip4_broadcast;
- if (ioctl (sk, SIOCSIFBRDADDR, &ifr) == -1)
- syslog (LOG_ERR,"nm_system_device_set_ip4_netmask (%s): failed to set IPv4 netmask!", iface);
+ if (ioctl (nm_dev_sock_get_fd (sk), SIOCSIFBRDADDR, &ifr) == -1)
+ syslog (LOG_ERR,"nm_system_device_set_ip4_netmask (%s): failed to set IPv4 broadcast address!", iface);
else
success = TRUE;
- close (sk);
+ nm_dev_sock_close (sk);
return (success);
}
@@ -151,18 +137,18 @@ gboolean nm_system_device_set_ip4_broadcast (NMDevice *dev, int ip4_broadcast)
gboolean nm_system_device_set_ip4_default_route (NMDevice *dev, int ip4_def_route)
{
const char *iface;
- int sk;
+ NMSock *sk;
gboolean success = FALSE;
struct rtentry rtent;
struct sockaddr_in *p;
g_return_val_if_fail (dev != NULL, FALSE);
- iface = nm_device_get_iface (dev);
- sk = nm_system_open_sock ();
- if (sk < 0)
+ if ((sk = nm_dev_sock_open (dev, NETWORK_CONTROL, __FUNCTION__, NULL)) == NULL)
return FALSE;
+ iface = nm_device_get_iface (dev);
+
memset (&rtent, 0, sizeof (struct rtentry));
p = (struct sockaddr_in *)&rtent.rt_dst;
p->sin_family = AF_INET;
@@ -178,7 +164,7 @@ gboolean nm_system_device_set_ip4_default_route (NMDevice *dev, int ip4_def_rout
rtent.rt_window = 0;
rtent.rt_flags = RTF_UP | RTF_GATEWAY | ( rtent.rt_window ? RTF_WINDOW : 0);
- if (ioctl (sk, SIOCADDRT, &rtent) == -1)
+ if (ioctl (nm_dev_sock_get_fd (sk), SIOCADDRT, &rtent) == -1)
{
if (errno == ENETUNREACH) /* possibly gateway is over the bridge */
{ /* try adding a route to gateway first */
@@ -197,9 +183,9 @@ gboolean nm_system_device_set_ip4_default_route (NMDevice *dev, int ip4_def_rout
rtent2.rt_metric = 0;
rtent2.rt_flags = RTF_UP | RTF_HOST;
- if ( ioctl (sk, SIOCADDRT, &rtent2) == 0 )
+ if (ioctl (nm_dev_sock_get_fd (sk), SIOCADDRT, &rtent2) == 0 )
{
- if ( ioctl (sk, SIOCADDRT, &rtent) == 0 )
+ if (ioctl (nm_dev_sock_get_fd (sk), SIOCADDRT, &rtent) == 0 )
success = TRUE;
else
syslog (LOG_ERR,"nm_system_device_set_ip4_default_route (%s): failed to set IPv4 default route! errno = %d", iface, errno);
@@ -211,7 +197,124 @@ gboolean nm_system_device_set_ip4_default_route (NMDevice *dev, int ip4_def_rout
else
success = TRUE;
- close (sk);
+ nm_dev_sock_close (sk);
return (success);
}
+
+gboolean nm_system_device_add_ip4_nameserver (NMDevice *dev, guint32 ip4_nameserver)
+{
+ gboolean success = FALSE;
+ char *nameserver;
+ GError *error = NULL;
+ NMData *data;
+ guint id;
+
+ g_return_val_if_fail (dev != NULL, FALSE);
+ data = nm_device_get_app_data (dev);
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ nameserver = g_strdup_printf ("%u.%u.%u.%u",
+ ((unsigned char *)&ip4_nameserver)[0],
+ ((unsigned char *)&ip4_nameserver)[1],
+ ((unsigned char *)&ip4_nameserver)[2],
+ ((unsigned char *)&ip4_nameserver)[3]);
+ syslog (LOG_WARNING, "Adding nameserver: %s", nameserver);
+
+ if ((id = nm_named_manager_add_nameserver_ipv4 (data->named, nameserver, &error)))
+ {
+ data->nameserver_ids = g_list_prepend (data->nameserver_ids, GUINT_TO_POINTER (id));
+ success = TRUE;
+ }
+ else
+ {
+ syslog (LOG_WARNING, "Couldn't add nameserver: %s\n", error->message);
+ g_clear_error (&error);
+ }
+ g_free (nameserver);
+
+ return success;
+}
+
+
+void nm_system_device_clear_ip4_nameservers (NMDevice *dev)
+{
+ GList *elt;
+ GError *error = NULL;
+ NMData *data;
+
+ g_return_if_fail (dev != NULL);
+ data = nm_device_get_app_data (dev);
+ g_return_if_fail (data != NULL);
+
+ /* Reset our nameserver list */
+ for (elt = data->nameserver_ids; elt; elt = elt->next)
+ {
+ if (!nm_named_manager_remove_nameserver_ipv4 (data->named,
+ GPOINTER_TO_UINT (elt->data),
+ &error))
+ {
+ syslog (LOG_WARNING, "Couldn't remove nameserver: %s", error->message);
+ g_clear_error (&error);
+ }
+ }
+ g_list_free (data->nameserver_ids);
+ data->nameserver_ids = NULL;
+
+}
+
+
+gboolean nm_system_device_add_domain_search (NMDevice *dev, const char *search)
+{
+ gboolean success = FALSE;
+ guint id;
+ GError *error = NULL;
+ NMData *data;
+
+ g_return_val_if_fail (dev != NULL, FALSE);
+ g_return_val_if_fail (search != NULL, FALSE);
+ g_return_val_if_fail (strlen (search) >= 0, FALSE);
+
+ data = nm_device_get_app_data (dev);
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ syslog (LOG_WARNING, "Adding domain search: %s\n", search);
+ if ((id = nm_named_manager_add_domain_search (data->named, search, &error)))
+ {
+ data->domain_search_ids = g_list_append (data->domain_search_ids, GUINT_TO_POINTER (id));
+ success = TRUE;
+ }
+ else
+ {
+ syslog (LOG_WARNING, "Couldn't add domain search '%s': %s\n", search, error->message);
+ g_clear_error (&error);
+ }
+
+ return success;
+}
+
+void nm_system_device_clear_domain_searches (NMDevice *dev)
+{
+ GError *error = NULL;
+ GList *elt;
+ NMData *data;
+
+ g_return_if_fail (dev != NULL);
+ data = nm_device_get_app_data (dev);
+ g_return_if_fail (data != NULL);
+
+ /* Reset our domain search list */
+ for (elt = data->domain_search_ids; elt; elt = elt->next)
+ {
+ if (!nm_named_manager_remove_domain_search (data->named,
+ GPOINTER_TO_UINT (elt->data),
+ &error))
+ {
+ syslog (LOG_WARNING, "Couldn't remove domain search: %s\n", error->message);
+ g_clear_error (&error);
+ }
+ }
+ g_list_free (data->domain_search_ids);
+ data->domain_search_ids = NULL;
+}
+
diff --git a/src/NetworkManagerSystem.h b/src/NetworkManagerSystem.h
index 560487146b..4f719031aa 100644
--- a/src/NetworkManagerSystem.h
+++ b/src/NetworkManagerSystem.h
@@ -52,6 +52,9 @@ gboolean nm_system_device_set_ip4_address (NMDevice *dev, int ip4_address);
gboolean nm_system_device_set_ip4_netmask (NMDevice *dev, int ip4_netmask);
gboolean nm_system_device_set_ip4_broadcast (NMDevice *dev, int ip4_broadcast);
gboolean nm_system_device_set_ip4_default_route (NMDevice *dev, int ip4_def_route);
-gboolean nm_system_device_update_resolv_conf (void *data, int len, const char *domain_name);
+gboolean nm_system_device_add_ip4_nameserver (NMDevice *dev, guint32 ip4_nameserver);
+void nm_system_device_clear_ip4_nameservers (NMDevice *dev);
+gboolean nm_system_device_add_domain_search (NMDevice *dev, const char *search);
+void nm_system_device_clear_domain_searches (NMDevice *dev);
#endif
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index 77b908c32a..4af75a5c27 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -25,11 +25,26 @@
#include <sys/socket.h>
#include <linux/sockios.h>
#include <syslog.h>
+#include <stdarg.h>
+#include <sys/time.h>
+#include <string.h>
+#include <iwlib.h>
#include "NetworkManager.h"
#include "NetworkManagerUtils.h"
+struct NMSock
+{
+ int fd;
+ char *func;
+ char *desc;
+ NMDevice *dev;
+};
+
+static GSList *sock_list = NULL;
+static GStaticMutex sock_list_mutex = G_STATIC_MUTEX_INIT;
+
typedef struct MutexDesc
{
GMutex *mutex;
@@ -151,6 +166,141 @@ void nm_unlock_mutex (GMutex *mutex, const char *func)
/*
+ * nm_dev_sock_open
+ *
+ * Open a socket to a network device and store some debug info about it.
+ *
+ */
+NMSock *nm_dev_sock_open (NMDevice *dev, SockType type, const char *func_name, const char *desc)
+{
+ NMSock *sock = NULL;
+
+ sock = g_malloc0 (sizeof (NMSock));
+
+ sock->fd = -1;
+
+ switch (type)
+ {
+ case DEV_WIRELESS:
+ sock->fd = iw_sockets_open ();
+ break;
+
+ case DEV_GENERAL:
+ if ((sock->fd = socket (PF_INET, SOCK_DGRAM, 0)) < 0)
+ if ((sock->fd = socket (PF_PACKET, SOCK_DGRAM, 0)) < 0)
+ sock->fd = socket (PF_INET6, SOCK_DGRAM, 0);
+ break;
+
+ case NETWORK_CONTROL:
+ sock->fd = socket (AF_PACKET, SOCK_PACKET, htons (ETH_P_ALL));
+ break;
+
+ default:
+ break;
+ }
+
+ if (sock->fd < 0)
+ {
+ g_free (sock);
+ syslog (LOG_ERR, "Could not open control socket for device '%s'.", dev ? nm_device_get_iface (dev) : "none");
+ return NULL;
+ }
+
+ sock->func = func_name ? g_strdup (func_name) : NULL;
+ sock->desc = desc ? g_strdup (desc) : NULL;
+ sock->dev = dev;
+ if (sock->dev)
+ nm_device_ref (sock->dev);
+
+ /* Add the sock to our global sock list for tracking */
+ g_static_mutex_lock (&sock_list_mutex);
+ sock_list = g_slist_append (sock_list, sock);
+ g_static_mutex_unlock (&sock_list_mutex);
+
+ return sock;
+}
+
+
+/*
+ * nm_dev_sock_close
+ *
+ * Close a socket and free its debug data.
+ *
+ */
+void nm_dev_sock_close (NMSock *sock)
+{
+ GSList *elt;
+
+ g_return_if_fail (sock != NULL);
+
+ close (sock->fd);
+ g_free (sock->func);
+ g_free (sock->desc);
+ if (sock->dev)
+ nm_device_unref (sock->dev);
+
+ memset (sock, 0, sizeof (NMSock));
+
+ g_static_mutex_lock (&sock_list_mutex);
+ for (elt = sock_list; elt; elt = g_slist_next (elt))
+ {
+ NMSock *temp_sock = (NMSock *)(elt->data);
+ if (temp_sock == sock)
+ {
+ sock_list = g_slist_remove_link (sock_list, elt);
+ g_slist_free (elt);
+ break;
+ }
+ }
+ g_static_mutex_unlock (&sock_list_mutex);
+
+ g_free (sock);
+}
+
+
+/*
+ * nm_dev_sock_get_fd
+ *
+ * Return the fd associated with an NMSock
+ *
+ */
+int nm_dev_sock_get_fd (NMSock *sock)
+{
+ g_return_val_if_fail (sock != NULL, -1);
+
+ return sock->fd;
+}
+
+
+/*
+ * nm_print_open_socks
+ *
+ * Print a list of currently open and registered NMSocks.
+ *
+ */
+void nm_print_open_socks (void)
+{
+ GSList *elt = NULL;
+ int i = 0;
+
+ syslog (LOG_DEBUG, "Open Sockets List:");
+ g_static_mutex_lock (&sock_list_mutex);
+ for (elt = sock_list; elt; elt = g_slist_next (elt))
+ {
+ NMSock *sock = (NMSock *)(elt->data);
+ if (sock)
+ {
+ i++;
+ syslog (LOG_DEBUG, " %d: %s fd:%d F:'%s' D:'%s'", i, sock->dev ? nm_device_get_iface (sock->dev) : "",
+ sock->fd, sock->func, sock->desc);
+ }
+ }
+ g_static_mutex_unlock (&sock_list_mutex);
+ syslog (LOG_DEBUG, "Open Sockets List Done.");
+}
+
+
+/*
* nm_null_safe_strcmp
*
* Doesn't freaking segfault if s1/s2 are NULL
@@ -169,7 +319,6 @@ int nm_null_safe_strcmp (const char *s1, const char *s2)
}
-
/*
* nm_ethernet_address_is_valid
*
@@ -331,6 +480,10 @@ NMDriverSupportLevel nm_get_wireless_driver_support_level (LibHalContext *ctx, N
g_free (driver_name);
}
+ /* Check for carrier detection support */
+ if ((level != NM_DRIVER_UNSUPPORTED) && !nm_device_get_supports_wireless_scan (dev))
+ level = NM_DRIVER_NO_WIRELESS_SCAN;
+
return (level);
}
@@ -381,6 +534,10 @@ NMDriverSupportLevel nm_get_wired_driver_support_level (LibHalContext *ctx, NMDe
level = NM_DRIVER_UNSUPPORTED;
}
+ /* Check for carrier detection support */
+ if ((level != NM_DRIVER_UNSUPPORTED) && !nm_device_get_supports_carrier_detect(dev))
+ level = NM_DRIVER_NO_CARRIER_DETECT;
+
return (level);
}
@@ -406,8 +563,13 @@ NMDriverSupportLevel nm_get_driver_support_level (LibHalContext *ctx, NMDevice *
switch (level)
{
- case NM_DRIVER_SEMI_SUPPORTED:
- syslog (LOG_INFO, "%s: Driver support level for '%s' is semi-supported",
+ case NM_DRIVER_NO_CARRIER_DETECT:
+ syslog (LOG_INFO, "%s: Driver '%s' does not support carrier detection.\n"
+ "\tYou must switch to it manually.", nm_device_get_iface (dev), driver);
+ break;
+ case NM_DRIVER_NO_WIRELESS_SCAN:
+ syslog (LOG_INFO, "%s: Driver '%s' does not support wireless scanning.\n"
+ "\tNetworkManager will not be able to fully use the card.",
nm_device_get_iface (dev), driver);
break;
case NM_DRIVER_FULLY_SUPPORTED:
@@ -423,3 +585,207 @@ NMDriverSupportLevel nm_get_driver_support_level (LibHalContext *ctx, NMDevice *
g_free (driver);
return (level);
}
+
+static inline int nm_timeval_cmp(const struct timeval *a,
+ const struct timeval *b)
+{
+ int x;
+ x = a->tv_sec - b->tv_sec;
+ x *= G_USEC_PER_SEC;
+ if (x)
+ return x;
+ x = a->tv_usec - b->tv_usec;
+ if (x)
+ return x;
+ return 0;
+}
+
+static inline int nm_timeval_has_passed(const struct timeval *a)
+{
+ struct timeval current;
+
+ gettimeofday(&current, NULL);
+
+ return (nm_timeval_cmp(&current, a) >= 0);
+}
+
+static inline void nm_timeval_add(struct timeval *a,
+ const struct timeval *b)
+{
+ struct timeval b1;
+
+ memmove(&b1, b, sizeof b1);
+
+ /* normalize a and b to be positive for everything */
+ while (a->tv_usec < 0)
+ {
+ a->tv_sec--;
+ a->tv_usec += G_USEC_PER_SEC;
+ }
+ while (b1.tv_usec < 0)
+ {
+ b1.tv_sec--;
+ b1.tv_usec += G_USEC_PER_SEC;
+ }
+
+ /* now add secs and usecs */
+ a->tv_sec += b1.tv_sec;
+ a->tv_usec += b1.tv_usec;
+
+ /* and handle our overflow */
+ if (a->tv_usec > G_USEC_PER_SEC)
+ {
+ a->tv_sec++;
+ a->tv_usec -= G_USEC_PER_SEC;
+ }
+}
+
+static void nm_v_wait_for_completion_or_timeout(
+ const int max_tries,
+ const struct timeval *max_time,
+ const guint interval_usecs,
+ nm_completion_func test_func,
+ nm_completion_func action_func,
+ nm_completion_args args)
+{
+ int try;
+ gboolean finished = FALSE;
+ struct timeval finish_time;
+
+ g_return_if_fail (test_func || action_func);
+
+ if (max_time) {
+ gettimeofday(&finish_time, NULL);
+ nm_timeval_add(&finish_time, max_time);
+ }
+
+ try = -1;
+ while (!finished &&
+ (max_tries == NM_COMPLETION_TRIES_INFINITY || try < max_tries))
+ {
+ if (max_time && nm_timeval_has_passed(&finish_time))
+ break;
+ try++;
+ if (test_func)
+ {
+ finished = (*test_func)(try, args);
+ if (finished)
+ break;
+ }
+
+#if 0
+#define NM_SLEEP_DEBUG
+#endif
+#ifdef NM_SLEEP_DEBUG
+ syslog (LOG_INFO, "sleeping or %d usecs", interval_usecs);
+#endif
+ g_usleep(interval_usecs);
+ if (action_func)
+ finished = (*action_func)(try, args);
+ }
+}
+
+/* these should probably be moved to NetworkManagerUtils.h as macros
+ * since they don't do varargs stuff any more */
+void nm_wait_for_completion_or_timeout(
+ const int max_tries,
+ const struct timeval *max_time,
+ const guint interval_usecs,
+ nm_completion_func test_func,
+ nm_completion_func action_func,
+ nm_completion_args args)
+{
+ nm_v_wait_for_completion_or_timeout(max_tries, max_time,
+ interval_usecs, test_func,
+ action_func, args);
+}
+
+void nm_wait_for_completion(
+ const int max_tries,
+ const guint interval_usecs,
+ nm_completion_func test_func,
+ nm_completion_func action_func,
+ nm_completion_args args)
+{
+ nm_v_wait_for_completion_or_timeout(max_tries, NULL,
+ interval_usecs, test_func,
+ action_func, args);
+}
+
+void nm_wait_for_timeout(
+ const struct timeval *max_time,
+ const guint interval_usecs,
+ nm_completion_func test_func,
+ nm_completion_func action_func,
+ nm_completion_args args)
+{
+ nm_v_wait_for_completion_or_timeout(-1, max_time, interval_usecs,
+ test_func, action_func, args);
+}
+
+/* you can use these, but they're really just examples */
+gboolean nm_completion_boolean_test(int tries, nm_completion_args args)
+{
+ gboolean *condition = (gboolean *)args[0];
+ char *message = (char *)args[1];
+ int log_level = (int)args[2];
+ int log_interval = (int)args[3];
+
+ g_return_val_if_fail (condition != NULL, TRUE);
+
+ if (message)
+ if ((log_interval == 0 && tries == 0) || (log_interval != 0 && tries % log_interval == 0))
+ syslog (log_level, message);
+
+ if (*condition)
+ return TRUE;
+ return FALSE;
+}
+
+gboolean nm_completion_boolean_function1_test(int tries,
+ nm_completion_args args)
+{
+ nm_completion_boolean_function_1 condition = args[0];
+ char *message = args[1];
+ int log_level = (int)args[2];
+ int log_interval = (int)args[3];
+ u_int64_t arg0;
+
+ memcpy(&arg0, &args[4], sizeof (arg0));
+
+ g_return_val_if_fail (condition, TRUE);
+
+ if (message)
+ if ((log_interval == 0 && tries == 0)
+ || (log_interval != 0 && tries % log_interval == 0))
+ syslog(log_level, message);
+
+ if (!(*condition)(arg0))
+ return TRUE;
+ return FALSE;
+}
+
+gboolean nm_completion_boolean_function2_test(int tries,
+ nm_completion_args args)
+{
+ nm_completion_boolean_function_2 condition = args[0];
+ char *message = args[1];
+ int log_level = (int)args[2];
+ int log_interval = (int)args[3];
+ u_int64_t arg0, arg1;
+
+ memcpy(&arg0, &args[4], sizeof (arg0));
+ memcpy(&arg1, &args[4]+sizeof (arg0), sizeof (arg1));
+
+ g_return_val_if_fail (condition, TRUE);
+
+ if (message)
+ if ((log_interval == 0 && tries == 0)
+ || (log_interval != 0 && tries % log_interval == 0))
+ syslog(log_level, message);
+
+ if (!(*condition)(arg0, arg1))
+ return TRUE;
+ return FALSE;
+}
+
diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h
index b46c89c318..6def8fe05c 100644
--- a/src/NetworkManagerUtils.h
+++ b/src/NetworkManagerUtils.h
@@ -27,17 +27,33 @@
#include <syslog.h>
#include <net/ethernet.h>
#include <iwlib.h>
+#include <sys/time.h>
+#include <stdarg.h>
#include "NetworkManager.h"
#include "NetworkManagerMain.h"
#include "NetworkManagerDevice.h"
+typedef enum SockType
+{
+ DEV_WIRELESS,
+ DEV_GENERAL,
+ NETWORK_CONTROL
+} SockType;
+
+typedef struct NMSock NMSock;
+
gboolean nm_try_acquire_mutex (GMutex *mutex, const char *func);
void nm_lock_mutex (GMutex *mutex, const char *func);
void nm_unlock_mutex (GMutex *mutex, const char *func);
void nm_register_mutex_desc (GMutex *mutex, char *string);
+NMSock * nm_dev_sock_open (NMDevice *dev, SockType type, const char *func_name, const char *desc);
+void nm_dev_sock_close (NMSock *sock);
+int nm_dev_sock_get_fd (NMSock *sock);
+void nm_print_open_socks (void);
+
int nm_null_safe_strcmp (const char *s1, const char *s2);
gboolean nm_ethernet_address_is_valid (struct ether_addr *test_addr);
@@ -48,4 +64,42 @@ int nm_spawn_process (char *args);
NMDriverSupportLevel nm_get_driver_support_level (LibHalContext *ctx, NMDevice *dev);
+#define NM_COMPLETION_TRIES_INFINITY -1
+
+typedef void * nm_completion_args[8];
+
+typedef gboolean (*nm_completion_func)(int tries, nm_completion_args args);
+typedef gboolean (*nm_completion_boolean_function_1)(u_int64_t arg);
+typedef gboolean (*nm_completion_boolean_function_2)(
+ u_int64_t arg0, u_int64_t arg1);
+
+void nm_wait_for_completion(
+ const int max_tries,
+ const guint interval_usecs,
+ nm_completion_func test_func,
+ nm_completion_func action_func,
+ nm_completion_args args);
+
+void nm_wait_for_completion_or_timeout(
+ const int max_tries,
+ const struct timeval *max_time,
+ const guint interval_usecs,
+ nm_completion_func test_func,
+ nm_completion_func action_func,
+ nm_completion_args args);
+
+void nm_wait_for_timeout(
+ const struct timeval *max_time,
+ const guint interval_usecs,
+ nm_completion_func test_func,
+ nm_completion_func action_func,
+ nm_completion_args args);
+
+gboolean nm_completion_boolean_test(int tries, nm_completion_args args);
+gboolean nm_completion_boolean_function1_test(int tries,
+ nm_completion_args args);
+gboolean nm_completion_boolean_function2_test(int tries,
+ nm_completion_args args);
+#define nm_completion_boolean_function_test nm_completion_boolean_function1_test
+
#endif
diff --git a/src/autoip.c b/src/autoip.c
index 92df4a369b..bbdfd0305c 100644
--- a/src/autoip.c
+++ b/src/autoip.c
@@ -33,6 +33,7 @@
#include "NetworkManager.h"
#include "NetworkManagerDevice.h"
#include "NetworkManagerMain.h"
+#include "NetworkManagerUtils.h"
// Times here are in seconds
#define LINKLOCAL_ADDR 0xa9fe0000
@@ -56,7 +57,7 @@ static struct ether_addr broadcast_addr = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}
/**
* Pick a random link local IP address.
*/
-static void pick(struct in_addr *ip)
+static void pick (struct in_addr *ip)
{
ip->s_addr = htonl (LINKLOCAL_ADDR | ((abs(random()) % 0xFD00) + (abs(random()) % 0x0100)));
@@ -174,7 +175,7 @@ gboolean get_autoip (NMDevice *dev, struct in_addr *out_ip)
arpMessage p;
struct ether_addr addr;
struct in_addr ip = {0};
- int fd;
+ NMSock *sk;
int nprobes = 0;
int nannounce = 0;
gboolean success = FALSE;
@@ -189,20 +190,20 @@ gboolean get_autoip (NMDevice *dev, struct in_addr *out_ip)
strncpy (saddr.sa_data, nm_device_get_iface (dev), sizeof (saddr.sa_data));
/* open an ARP socket */
- if ((fd = socket (PF_PACKET, SOCK_PACKET, htons (ETH_P_ARP))) < 0)
+ if ((sk = nm_dev_sock_open (dev, NETWORK_CONTROL, __FUNCTION__, NULL)) == NULL)
{
syslog (LOG_ERR, "%s: Couldn't open network control socket.", nm_device_get_iface (dev));
goto out;
}
/* bind to the ARP socket */
- if (bind (fd, &saddr, sizeof (saddr)) < 0)
+ if (bind (nm_dev_sock_get_fd (sk), &saddr, sizeof (saddr)) < 0)
{
syslog (LOG_ERR, "%s: Couldn't bind to the device.", nm_device_get_iface (dev));
goto out;
}
- nm_device_get_hw_address (dev, addr.ether_addr_octet);
+ nm_device_get_hw_address (dev, &(addr.ether_addr_octet[0]));
/* initialize pseudo random selection of IP addresses */
srandom ( (addr.ether_addr_octet[ETHER_ADDR_LEN-4] << 24) |
@@ -226,7 +227,7 @@ gboolean get_autoip (NMDevice *dev, struct in_addr *out_ip)
if (nprobes < PROBE_NUM)
{
syslog (LOG_INFO, "autoip: Sending probe #%d for IP address %s.", nprobes, inet_ntoa (ip));
- arp (fd, &saddr, ARPOP_REQUEST, &addr, null_ip, &null_addr, ip);
+ arp (nm_dev_sock_get_fd (sk), &saddr, ARPOP_REQUEST, &addr, null_ip, &null_addr, ip);
nprobes++;
gettimeofday (&timeout, NULL);
if (nprobes == PROBE_NUM)
@@ -246,7 +247,7 @@ gboolean get_autoip (NMDevice *dev, struct in_addr *out_ip)
else if (nannounce < ANNOUNCE_NUM)
{
syslog (LOG_INFO, "autoip: Sending announce #%d for IP address %s.", nannounce, inet_ntoa (ip));
- arp (fd, &saddr, ARPOP_REQUEST, &addr, ip, &addr, ip);
+ arp (nm_dev_sock_get_fd (sk), &saddr, ARPOP_REQUEST, &addr, ip, &addr, ip);
nannounce++;
gettimeofday (&timeout, NULL);
timeout.tv_sec += ANNOUNCE_INTERVAL;
@@ -261,7 +262,7 @@ gboolean get_autoip (NMDevice *dev, struct in_addr *out_ip)
}
syslog (LOG_INFO, "autoip: Waiting for reply...");
- err = peekfd (dev, fd, &timeout);
+ err = peekfd (dev, nm_dev_sock_get_fd (sk), &timeout);
if ((err == RET_DHCP_ERROR) || (err == RET_DHCP_CEASED))
goto out;
@@ -271,7 +272,7 @@ gboolean get_autoip (NMDevice *dev, struct in_addr *out_ip)
syslog (LOG_INFO, "autoip: Got some data to check for reply packet.");
/* read ARP packet */
- if (recv (fd, &p, sizeof (p), 0) < 0)
+ if (recv (nm_dev_sock_get_fd (sk), &p, sizeof (p), 0) < 0)
{
syslog (LOG_ERR, "autoip: packet receive failure, ignoring it.");
continue;
@@ -308,7 +309,6 @@ gboolean get_autoip (NMDevice *dev, struct in_addr *out_ip)
}
out:
- if (fd >= 0)
- close (fd);
+ nm_dev_sock_close (sk);
return (success);
}
diff --git a/src/backends/NetworkManagerDebian.c b/src/backends/NetworkManagerDebian.c
index b42653669f..51d234103d 100644
--- a/src/backends/NetworkManagerDebian.c
+++ b/src/backends/NetworkManagerDebian.c
@@ -334,9 +334,10 @@ void nm_system_restart_mdns_responder (void)
void nm_system_device_add_ip6_link_address (NMDevice *dev)
{
char *buf;
+ char *addr;
unsigned char eui[8];
- nm_device_get_hw_address(dev, eui);
+ nm_device_get_hw_address(dev, &eui[0]);
memmove(eui+5, eui+3, 3);
eui[3] = 0xff;
diff --git a/src/backends/NetworkManagerRedHat.c b/src/backends/NetworkManagerRedHat.c
index 21215c8684..899c7c710a 100644
--- a/src/backends/NetworkManagerRedHat.c
+++ b/src/backends/NetworkManagerRedHat.c
@@ -128,6 +128,102 @@ void nm_system_device_flush_addresses (NMDevice *dev)
/*
+ * get_current_profile_name
+ *
+ * Retrieve the current network profile, if any
+ *
+ */
+static char *get_current_profile_name (void)
+{
+ shvarFile * file;
+ char * buf;
+
+ if (!(file = svNewFile (SYSCONFDIR"/sysconfig/network")))
+ return NULL;
+
+ buf = svGetValue (file, "CURRENT_PROFILE");
+ if (!buf)
+ buf = strdup ("default");
+ svCloseFile (file);
+
+ return buf;
+}
+
+
+/*
+ * set_ip4_config_from_resolv_conf
+ *
+ * Add nameservers and search names from a resolv.conf format file.
+ *
+ */
+static void set_ip4_config_from_resolv_conf (NMDevice *dev, const char *filename)
+{
+ char * contents = NULL;
+ char ** split_contents = NULL;
+ char ** split_line = NULL;
+ int i, len;
+
+ g_return_if_fail (dev != NULL);
+ g_return_if_fail (filename != NULL);
+
+ if (!g_file_get_contents (filename, &contents, NULL, NULL) || (contents == NULL))
+ return;
+
+ if (!(split_contents = g_strsplit (contents, "\n", 0)))
+ goto out;
+
+ for (split_line = split_contents; *split_line; split_line++)
+ {
+ char *line = *split_line;
+
+ /* Ignore comments */
+ if (!line || (line[0] == ';'))
+ continue;
+
+ line = g_strstrip (line);
+ if ((strncmp (line, "search", 6) == 0) && (strlen (line) > 6))
+ {
+ char *searches = g_strdup (line + 7);
+ char **split_searches = NULL;
+
+ if (!searches || !strlen (searches))
+ continue;
+
+ /* Allow space-separated search domains */
+ if ((split_searches = g_strsplit (searches, " ", 0)))
+ {
+ char **item = NULL;
+ int m, srch_len;
+
+ for (item = split_searches; *item; item++)
+ nm_system_device_add_domain_search (dev, *item);
+ g_strfreev (split_searches);
+ }
+ else
+ {
+ /* Only 1 item, add the whole line */
+ nm_system_device_add_domain_search (dev, searches);
+ }
+
+ g_free (searches);
+ }
+ else if ((strncmp (line, "nameserver", 10) == 0) && (strlen (line) > 10))
+ {
+ guint32 addr = (guint32) (inet_addr (line + 11));
+
+ if (addr != (guint32) -1)
+ nm_system_device_add_ip4_nameserver (dev, addr);
+ }
+ }
+
+ g_strfreev (split_contents);
+
+out:
+ g_free (contents);
+}
+
+
+/*
* nm_system_device_setup_static_ip4_config
*
* Set up the device with a particular IPv4 address/netmask/gateway.
@@ -151,6 +247,7 @@ gboolean nm_system_device_setup_static_ip4_config (NMDevice *dev)
char *buf;
int err;
const char *iface;
+ char * cur_profile_name = get_current_profile_name ();
g_return_val_if_fail (dev != NULL, FALSE);
g_return_val_if_fail (!nm_device_config_get_use_dhcp (dev), FALSE);
@@ -207,6 +304,16 @@ gboolean nm_system_device_setup_static_ip4_config (NMDevice *dev)
goto error;
}
g_free (buf);
+
+ if (cur_profile_name)
+ {
+ char *filename = g_strdup_printf (SYSCONFDIR"/sysconfig/networking/profiles/%s/resolv.conf", cur_profile_name);
+
+ set_ip4_config_from_resolv_conf (dev, filename);
+ g_free (filename);
+ g_free (cur_profile_name);
+ }
+
return (TRUE);
error:
@@ -350,7 +457,7 @@ void nm_system_device_add_ip6_link_address (NMDevice *dev)
char *buf;
unsigned char eui[8];
- nm_device_get_hw_address(dev, eui);
+ nm_device_get_hw_address(dev, &eui[0]);
memmove(eui+5, eui+3, 3);
eui[3] = 0xff;
diff --git a/src/backends/shvar.c b/src/backends/shvar.c
index 765a77e7c5..01cf395a68 100644
--- a/src/backends/shvar.c
+++ b/src/backends/shvar.c
@@ -49,12 +49,18 @@ svOpenFile(const char *name, gboolean create)
s = g_malloc0(sizeof(shvarFile));
+#if 0
s->fd = open(name, O_RDWR); /* NOT O_CREAT */
if (s->fd == -1) {
/* try read-only */
s->fd = open(name, O_RDONLY); /* NOT O_CREAT */
if (s->fd != -1) closefd = 1;
}
+#else
+ /* try read-only */
+ s->fd = open(name, O_RDONLY); /* NOT O_CREAT */
+ if (s->fd != -1) closefd = 1;
+#endif
s->fileName = g_strdup(name);
if (s->fd != -1) {
diff --git a/src/nm-dbus-device.c b/src/nm-dbus-device.c
index fd7bfbca8b..74228dada2 100644
--- a/src/nm-dbus-device.c
+++ b/src/nm-dbus-device.c
@@ -25,6 +25,7 @@
#include <dbus/dbus-glib.h>
#include <stdarg.h>
#include <syslog.h>
+#include <netinet/ether.h>
#include "NetworkManagerDevice.h"
#include "NetworkManagerDbus.h"
@@ -88,6 +89,28 @@ static DBusMessage *nm_dbus_device_get_ip4_address (DBusConnection *connection,
return reply;
}
+static DBusMessage *nm_dbus_device_get_hw_address (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
+{
+ DBusMessage *reply = NULL;
+ NMDevice *dev;
+
+ g_return_val_if_fail (data && data->data && data->dev && connection && message, NULL);
+
+ dev = data->dev;
+ if ((reply = dbus_message_new_method_return (message)))
+ {
+ struct ether_addr addr;
+ char char_addr[20];
+
+ nm_device_get_hw_address (dev, (unsigned char *)&(addr.ether_addr_octet));
+ memset (char_addr, 0, 20);
+ ether_ntoa_r (&addr, &char_addr[0]);
+ dbus_message_append_args (reply, DBUS_TYPE_STRING, char_addr, DBUS_TYPE_INVALID);
+ }
+
+ return reply;
+}
+
static DBusMessage *nm_dbus_device_get_mode (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
{
DBusMessage *reply = NULL;
@@ -240,22 +263,16 @@ static DBusMessage *nm_dbus_device_get_networks (DBusConnection *connection, DBu
return reply;
}
-static DBusMessage *nm_dbus_device_get_supports_carrier_detect (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
+static DBusMessage *nm_dbus_device_get_driver_support_level (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
{
DBusMessage *reply = NULL;
NMDevice *dev;
g_return_val_if_fail (data && data->data && data->dev && connection && message, NULL);
- /* Wired devices only for now */
dev = data->dev;
- if (!nm_device_is_wired (dev))
- {
- reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotWired",
- "Carrier detection is only supported for wired devices.");
- }
- else if ((reply = dbus_message_new_method_return (message)))
- dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, nm_device_get_supports_carrier_detect (dev), DBUS_TYPE_INVALID);
+ if ((reply = dbus_message_new_method_return (message)))
+ dbus_message_append_args (reply, DBUS_TYPE_UINT32, nm_device_get_driver_support_level (dev), DBUS_TYPE_INVALID);
return reply;
}
@@ -301,17 +318,18 @@ NMDbusMethodList *nm_dbus_device_methods_setup (void)
{
NMDbusMethodList *list = nm_dbus_method_list_new (NULL);
- nm_dbus_method_list_add_method (list, "getName", nm_dbus_device_get_name);
- nm_dbus_method_list_add_method (list, "getType", nm_dbus_device_get_type);
- nm_dbus_method_list_add_method (list, "getHalUdi", nm_dbus_device_get_hal_udi);
- nm_dbus_method_list_add_method (list, "getIP4Address", nm_dbus_device_get_ip4_address);
- nm_dbus_method_list_add_method (list, "getMode", nm_dbus_device_get_mode);
- nm_dbus_method_list_add_method (list, "getStrength", nm_dbus_device_get_strength);
- nm_dbus_method_list_add_method (list, "getActiveNetwork", nm_dbus_device_get_active_network);
- nm_dbus_method_list_add_method (list, "getNetworks", nm_dbus_device_get_networks);
- nm_dbus_method_list_add_method (list, "getLinkActive", nm_dbus_device_get_link_active);
- nm_dbus_method_list_add_method (list, "setLinkActive", nm_dbus_device_set_link_active);
- nm_dbus_method_list_add_method (list, "getSupportsCarrierDetect", nm_dbus_device_get_supports_carrier_detect);
+ nm_dbus_method_list_add_method (list, "getName", nm_dbus_device_get_name);
+ nm_dbus_method_list_add_method (list, "getType", nm_dbus_device_get_type);
+ nm_dbus_method_list_add_method (list, "getHalUdi", nm_dbus_device_get_hal_udi);
+ nm_dbus_method_list_add_method (list, "getIP4Address", nm_dbus_device_get_ip4_address);
+ nm_dbus_method_list_add_method (list, "getHWAddress", nm_dbus_device_get_hw_address);
+ nm_dbus_method_list_add_method (list, "getMode", nm_dbus_device_get_mode);
+ nm_dbus_method_list_add_method (list, "getStrength", nm_dbus_device_get_strength);
+ nm_dbus_method_list_add_method (list, "getActiveNetwork", nm_dbus_device_get_active_network);
+ nm_dbus_method_list_add_method (list, "getNetworks", nm_dbus_device_get_networks);
+ nm_dbus_method_list_add_method (list, "getLinkActive", nm_dbus_device_get_link_active);
+ nm_dbus_method_list_add_method (list, "setLinkActive", nm_dbus_device_set_link_active);
+ nm_dbus_method_list_add_method (list, "getDriverSupportLevel", nm_dbus_device_get_driver_support_level);
return (list);
}
diff --git a/src/nm-dbus-nm.c b/src/nm-dbus-nm.c
index 55061cc305..fce172b645 100644
--- a/src/nm-dbus-nm.c
+++ b/src/nm-dbus-nm.c
@@ -123,7 +123,10 @@ static DBusMessage *nm_dbus_nm_get_devices (DBusConnection *connection, DBusMess
* (something which should never happen), die.
*/
if (!appended)
- g_assert ("Device list existed, but no devices were in it.");
+ {
+ syslog (LOG_ERR, "Device list existed, but no devices were in it.\n");
+ g_assert_not_reached ();
+ }
nm_unlock_mutex (data->data->dev_list_mutex, __FUNCTION__);
}
@@ -413,7 +416,19 @@ static DBusMessage * nm_dbus_nm_set_user_key_for_network (DBusConnection *connec
}
-static DBusMessage *nm_dbus_nm_set_scanning_enabled (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
+static DBusMessage *nm_dbus_nm_get_wireless_scan_method (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
+{
+ DBusMessage *reply = NULL;
+
+ g_return_val_if_fail (data && data->data && connection && message, NULL);
+
+ if ((reply = dbus_message_new_method_return (message)))
+ dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, data->data->scanning_method, DBUS_TYPE_INVALID);
+
+ return reply;
+}
+
+static DBusMessage *nm_dbus_nm_set_wireless_enabled (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
{
gboolean enabled = FALSE;
DBusError err;
@@ -422,50 +437,85 @@ static DBusMessage *nm_dbus_nm_set_scanning_enabled (DBusConnection *connection,
dbus_error_init (&err);
if (dbus_message_get_args (message, &err, DBUS_TYPE_BOOLEAN, &enabled, DBUS_TYPE_INVALID))
- data->data->scanning_enabled = enabled;
+ {
+ GSList *elt;
+ NMData *app_data;
+
+ app_data = data->data;
+ app_data->wireless_enabled = enabled;
+
+ /* Physically down all wireless devices */
+ nm_lock_mutex (app_data->dev_list_mutex, __FUNCTION__);
+ for (elt = app_data->dev_list; elt; elt = g_slist_next (elt))
+ {
+ NMDevice *dev = (NMDevice *)(elt->data);
+ if (nm_device_is_wireless (dev))
+ {
+ nm_device_deactivate (dev, FALSE);
+ nm_device_bring_down (dev);
+ }
+ }
+ nm_unlock_mutex (app_data->dev_list_mutex, __FUNCTION__);
+ nm_policy_schedule_state_update (app_data);
+ }
return NULL;
}
-static DBusMessage *nm_dbus_nm_get_scanning_enabled (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
+static DBusMessage *nm_dbus_nm_get_wireless_enabled (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
{
DBusMessage *reply = NULL;
g_return_val_if_fail (data && data->data && connection && message, NULL);
if ((reply = dbus_message_new_method_return (message)))
- dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, data->data->scanning_enabled, DBUS_TYPE_INVALID);
-
+ dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, data->data->wireless_enabled, DBUS_TYPE_INVALID);
+
return reply;
}
-static DBusMessage *nm_dbus_nm_set_wireless_enabled (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
+static DBusMessage *nm_dbus_nm_sleep (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
{
- gboolean enabled = FALSE;
- DBusError err;
+ GSList *elt;
+ NMData *app_data;
g_return_val_if_fail (data && data->data && connection && message, NULL);
- dbus_error_init (&err);
- if (dbus_message_get_args (message, &err, DBUS_TYPE_BOOLEAN, &enabled, DBUS_TYPE_INVALID))
+ app_data = data->data;
+ if (app_data->asleep == FALSE)
{
- data->data->wireless_enabled = enabled;
- nm_policy_schedule_state_update (data->data);
+ app_data->asleep = TRUE;
+
+ /* Physically down all devices */
+ nm_lock_mutex (app_data->dev_list_mutex, __FUNCTION__);
+ for (elt = app_data->dev_list; elt; elt = g_slist_next (elt))
+ {
+ NMDevice *dev = (NMDevice *)(elt->data);
+
+ nm_device_deactivate (dev, FALSE);
+ nm_device_bring_down (dev);
+ }
+ nm_unlock_mutex (app_data->dev_list_mutex, __FUNCTION__);
+ nm_policy_schedule_state_update (app_data);
}
return NULL;
}
-static DBusMessage *nm_dbus_nm_get_wireless_enabled (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
+static DBusMessage *nm_dbus_nm_wake (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
{
- DBusMessage *reply = NULL;
+ NMData *app_data;
g_return_val_if_fail (data && data->data && connection && message, NULL);
- if ((reply = dbus_message_new_method_return (message)))
- dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, data->data->wireless_enabled, DBUS_TYPE_INVALID);
+ app_data = data->data;
+ if (app_data->asleep == TRUE)
+ {
+ app_data->asleep = FALSE;
+ nm_policy_schedule_state_update (app_data);
+ }
- return reply;
+ return NULL;
}
static DBusMessage *nm_dbus_nm_get_status (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
@@ -499,10 +549,11 @@ NMDbusMethodList *nm_dbus_nm_methods_setup (void)
nm_dbus_method_list_add_method (list, "setActiveDevice", nm_dbus_nm_set_active_device);
nm_dbus_method_list_add_method (list, "createWirelessNetwork", nm_dbus_nm_create_wireless_network);
nm_dbus_method_list_add_method (list, "setKeyForNetwork", nm_dbus_nm_set_user_key_for_network);
- nm_dbus_method_list_add_method (list, "setScanningEnabled", nm_dbus_nm_set_scanning_enabled);
- nm_dbus_method_list_add_method (list, "getScanningEnabled", nm_dbus_nm_get_scanning_enabled);
+ nm_dbus_method_list_add_method (list, "getWirelessScanMethod", nm_dbus_nm_get_wireless_scan_method);
nm_dbus_method_list_add_method (list, "setWirelessEnabled", nm_dbus_nm_set_wireless_enabled);
nm_dbus_method_list_add_method (list, "getWirelessEnabled", nm_dbus_nm_get_wireless_enabled);
+ nm_dbus_method_list_add_method (list, "sleep", nm_dbus_nm_sleep);
+ nm_dbus_method_list_add_method (list, "wake", nm_dbus_nm_wake);
nm_dbus_method_list_add_method (list, "status", nm_dbus_nm_get_status);
nm_dbus_method_list_add_method (list, "createTestDevice", nm_dbus_nm_create_test_device);
nm_dbus_method_list_add_method (list, "removeTestDevice", nm_dbus_nm_remove_test_device);