diff --git a/ChangeLog b/ChangeLog index 0eb6f8b49f..af144eff34 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,48 @@ +2005-02-07 Dan Williams + + * panel-applet/NMWirelessApplet.[ch] + - Add a context menu that contains: + Pause/Resume Wireless Scanning + Stop/Start All Wireless Devices + About... + - Grab active device strength off active device, + not its network + + * panel-applet/NMWirelessAppletDbus.[ch] + - Add DBUS accessors for "getSupportsCarrierDetect", "setScanningEnabled", + "getScanningEnabled", "setWirelessEnabled", and "getWirelessEnabled" + - Update active device strength every 2 seconds, not every 1 second + + * panel-applet/menu-info.c + - Only disable wired devices in the menu when they support carrier detection, + and don't currently have a link. Non-carrier-detect devices will always + remain choosable + + * src/Makefile.am + src/NetworkManagerDbusUtils.[ch] + - Add new new dbus utils sources + + * src/NetworkManager.c + - Fixes for new link detection, we no longer need to call nm_device_update_link_active() + with the boolean parameter + - Set scanning_enabled & wireless_enabled to TRUE + + * src/NetworkManagerDbus.c + - Use new dbus util method dispatcher functions for org.freedesktop.NetworkManager methods + - Implement scanning & wireless enable/disable calls + - Remove the dbus vtable unregister handlers, weren't doing anything with them anyway + + * src/NetworkManagerDevice.c + - New link detection stuff again... + o Create device's mainloop earlier (but don't run it earlier) + o Hook up new carrier-detect support stuff + o Add in the ethtool & mii support detection code + - Don't scan if scanning is disabled + + * src/NetworkManagerPolicy.c + - Never automatically choose a device that doesn't support carrier detection + - Don't automatically choose a wireless device if wireless is disabled + 2005-02-07 Dan Williams * libnm_glib/libnm_glib.c diff --git a/panel-applet/NMWirelessApplet.c b/panel-applet/NMWirelessApplet.c index afc6bcffa8..ac89558627 100644 --- a/panel-applet/NMWirelessApplet.c +++ b/panel-applet/NMWirelessApplet.c @@ -22,7 +22,7 @@ * Eskil Heyn Olsen * Bastien Nocera (Gnome2 port) * - * (C) Copyright 2004 Red Hat, Inc. + * (C) Copyright 2004-2005 Red Hat, Inc. * (C) Copyright 2001, 2002 Free Software Foundation */ @@ -55,11 +55,13 @@ static GtkWidget * nmwa_populate_menu (NMWirelessApplet *applet); static void nmwa_dispose_menu_items (NMWirelessApplet *applet); -static gboolean do_not_eat_button_press (GtkWidget *widget, GdkEventButton *event); -static GObject * nmwa_constructor (GType type, guint n_props, GObjectConstructParam *construct_props); -static void setup_stock (void); -static void nmwa_icons_init (NMWirelessApplet *applet); -static gboolean nmwa_fill (NMWirelessApplet *applet); +static gboolean nmwa_toplevel_menu_button_press (GtkWidget *widget, GdkEventButton *event, gpointer user_data); +static GObject * nmwa_constructor (GType type, guint n_props, GObjectConstructParam *construct_props); +static void setup_stock (void); +static void nmwa_icons_init (NMWirelessApplet *applet); +static gboolean nmwa_fill (NMWirelessApplet *applet); +static void nmwa_about_cb (void); +static void nmwa_context_menu_update (NMWirelessApplet *applet); G_DEFINE_TYPE(NMWirelessApplet, nmwa, EGG_TYPE_TRAY_ICON) @@ -92,15 +94,43 @@ static GObject *nmwa_constructor (GType type, NMWirelessAppletClass *klass; klass = NM_WIRELESS_APPLET_CLASS (g_type_class_peek (type)); - obj = G_OBJECT_CLASS (nmwa_parent_class)->constructor (type, - n_props, - construct_props); + obj = G_OBJECT_CLASS (nmwa_parent_class)->constructor (type, n_props, construct_props); applet = NM_WIRELESS_APPLET (obj); return obj; } +void nmwa_about_cb (void) +{ + static const gchar *authors[] = + { + "\nThe Red Hat Desktop Team, including:\n", + "Dan Williams ", + "Jonathan Blandford ", + "John Palmieri ", + "Colin Walters ", + NULL + }; + + static const gchar *documenters[] = + { + NULL + }; + + gtk_show_about_dialog (NULL, + "name", _("NetworkManager Applet"), + "version", VERSION, + "copyright", _("\xC2\xA9 2004-2005 by Red Hat, Inc."), + "comments", _("A panel application for managing your network devices & connections."), + "authors", authors, + "documenters", documenters, + "translator-credits", _("translator-credits"), + "logo-icon-name", GTK_STOCK_NETWORK, + NULL); +} + + /* * nmwa_update_network_state * @@ -276,23 +306,7 @@ nmwa_update_state (NMWirelessApplet *applet) g_mutex_lock (applet->data_mutex); if ( applet->active_device && (applet->active_device->type == DEVICE_TYPE_WIRELESS_ETHERNET)) - { - GSList *list; - for (list = applet->active_device->networks; list; list = list->next) - { - WirelessNetwork *network = (WirelessNetwork *) list->data; - - if (network->active) - { - strength = CLAMP ((int) network->strength, 0, 100); - active_network = network; - } - } - - /* Fall back to old strength if current strength is invalid */ - if (strength <= 0) - strength = applet->active_device->strength; - } + strength = CLAMP ((int)applet->active_device->strength, 0, 100); #if 0 /* Only show icon if there's more than one device and at least one is wireless */ @@ -945,8 +959,127 @@ static GtkWidget * nmwa_populate_menu (NMWirelessApplet *applet) return (menu); } + +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); +} + + /* - * mnwa_setup_widgets + * nmwa_context_menu_update + * + */ +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")); + image = gtk_image_new_from_stock (GTK_STOCK_STOP, GTK_ICON_SIZE_MENU); + } + else + { + applet->stop_wireless_item = gtk_image_menu_item_new_with_label (_("Start All Wireless Devices")); + image = gtk_image_new_from_stock (GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU); + } + 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); +} + + +/* + * nmwa_context_menu_create + * + * Generate the contextual popup menu. + * + */ +static GtkWidget *nmwa_context_menu_create (NMWirelessApplet *applet) +{ + GtkWidget *menu; + GtkWidget *menu_item; + GtkWidget *image; + + 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); + + 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); + + menu_item = gtk_image_menu_item_new_with_label (_("Help")); +/* g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (nmwa_help_cb), applet); */ + image = gtk_image_new_from_stock (GTK_STOCK_HELP, GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), image); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); + gtk_widget_set_sensitive (GTK_WIDGET (menu_item), FALSE); + + menu_item = gtk_image_menu_item_new_with_label (_("About")); + g_signal_connect (G_OBJECT (menu_item), "activate", G_CALLBACK (nmwa_about_cb), applet); + image = gtk_image_new_from_stock (GTK_STOCK_ABOUT, GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menu_item), image); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); + + gtk_widget_show_all (menu); + + return menu; +} + + +/* + * nmwa_setup_widgets * * Intialize the applet's widgets and packing, create the initial * menu of networks. @@ -961,18 +1094,22 @@ static void nmwa_setup_widgets (NMWirelessApplet *applet) applet->pixmap = gtk_image_new (); applet->event_box = gtk_event_box_new (); gtk_container_set_border_width (GTK_CONTAINER (applet->event_box), 0); + menu_bar = gtk_menu_bar_new (); gtk_container_add (GTK_CONTAINER(applet->event_box), menu_bar); + applet->toplevel_menu = gtk_menu_item_new(); gtk_widget_set_name (applet->toplevel_menu, "ToplevelMenu"); gtk_container_set_border_width (GTK_CONTAINER (applet->toplevel_menu), 0); gtk_container_add (GTK_CONTAINER(applet->toplevel_menu), applet->pixmap); - gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), applet->toplevel_menu); - g_signal_connect(applet->toplevel_menu, "activate", G_CALLBACK(nmwa_toplevel_menu_activate), applet); + gtk_menu_shell_append (GTK_MENU_SHELL(menu_bar), applet->toplevel_menu); + g_signal_connect (applet->toplevel_menu, "activate", G_CALLBACK (nmwa_toplevel_menu_activate), applet); + + applet->context_menu = nmwa_context_menu_create (applet); + g_signal_connect (applet->toplevel_menu, "button_press_event", G_CALLBACK (nmwa_toplevel_menu_button_press), applet); applet->menu = gtk_menu_new(); gtk_menu_item_set_submenu (GTK_MENU_ITEM(applet->toplevel_menu), applet->menu); - g_signal_connect (menu_bar, "button_press_event", G_CALLBACK (do_not_eat_button_press), NULL); applet->encryption_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); @@ -982,19 +1119,27 @@ static void nmwa_setup_widgets (NMWirelessApplet *applet) } -static gboolean do_not_eat_button_press (GtkWidget *widget, GdkEventButton *event) +/* + * nmwa_toplevel_menu_button_press + * + * Handle right-clicks for the context popup menu + * + */ +static gboolean nmwa_toplevel_menu_button_press (GtkWidget *widget, GdkEventButton *event, gpointer user_data) { - /* Don't worry about this for now - We can use it if we need a contectual menu + NMWirelessApplet *applet = (NMWirelessApplet *)user_data; + + g_return_val_if_fail (applet != NULL, FALSE); if (event->button != 1) g_signal_stop_emission_by_name (widget, "button_press_event"); - if (event->button == 3) { - g_message ("3nd button pressed"); + if (event->button == 3) + { + nmwa_context_menu_update (applet); + gtk_menu_popup (GTK_MENU (applet->context_menu), NULL, NULL, NULL, applet, event->button, event->time); return (TRUE); } - */ return (FALSE); } @@ -1047,7 +1192,7 @@ static GtkWidget * nmwa_get_instance (NMWirelessApplet *applet) static gboolean nmwa_fill (NMWirelessApplet *applet) { - gtk_window_set_default_icon_from_file (ICONDIR"/NMWirelessApplet/wireless-applet.png", NULL); +/* gtk_window_set_default_icon_from_file (ICONDIR"/NMWirelessApplet/wireless-applet.png", NULL); */ glade_gnome_init (); gtk_widget_show (nmwa_get_instance (applet)); diff --git a/panel-applet/NMWirelessApplet.h b/panel-applet/NMWirelessApplet.h index b7c43f0090..fa8ef49fd3 100644 --- a/panel-applet/NMWirelessApplet.h +++ b/panel-applet/NMWirelessApplet.h @@ -70,6 +70,7 @@ typedef struct char *nm_device; int type; gboolean link; + gboolean supports_carrier_detect; char *nm_name; char *hal_name; char *udi; @@ -119,25 +120,27 @@ typedef struct NetworkDevice *active_device; char *nm_status; NetworkDevice *dbus_active_device; + gboolean scanning_enabled; + gboolean wireless_enabled; - GdkPixbuf *no_nm_icon; - GdkPixbuf *wired_icon; - GdkPixbuf *adhoc_icon; + GdkPixbuf *no_nm_icon; + GdkPixbuf *wired_icon; + GdkPixbuf *adhoc_icon; #define NUM_WIRED_CONNECTING_FRAMES 11 - GdkPixbuf *wired_connecting_icons[NUM_WIRED_CONNECTING_FRAMES]; - GdkPixbuf *wireless_00_icon; - GdkPixbuf *wireless_25_icon; - GdkPixbuf *wireless_50_icon; - GdkPixbuf *wireless_75_icon; - GdkPixbuf *wireless_100_icon; + GdkPixbuf *wired_connecting_icons[NUM_WIRED_CONNECTING_FRAMES]; + GdkPixbuf *wireless_00_icon; + GdkPixbuf *wireless_25_icon; + GdkPixbuf *wireless_50_icon; + GdkPixbuf *wireless_75_icon; + GdkPixbuf *wireless_100_icon; #define NUM_WIRELESS_CONNECTING_FRAMES 11 - GdkPixbuf *wireless_connecting_icons[NUM_WIRELESS_CONNECTING_FRAMES]; + GdkPixbuf *wireless_connecting_icons[NUM_WIRELESS_CONNECTING_FRAMES]; #define NUM_WIRELESS_SCANNING_FRAMES 16 - GdkPixbuf *wireless_scanning_icons[NUM_WIRELESS_SCANNING_FRAMES]; + GdkPixbuf *wireless_scanning_icons[NUM_WIRELESS_SCANNING_FRAMES]; /* Animation stuff */ - int animation_step; - guint animation_id; + int animation_step; + guint animation_id; /* Direct UI elements */ GtkWidget *pixmap; @@ -146,6 +149,11 @@ typedef struct GtkWidget *event_box; GtkSizeGroup *encryption_size_group; GtkTooltips *tooltips; + + GtkWidget *context_menu; + GtkWidget *pause_scanning_item; + GtkWidget *stop_wireless_item; + } NMWirelessApplet; diff --git a/panel-applet/NMWirelessAppletDbus.c b/panel-applet/NMWirelessAppletDbus.c index 9a93abf621..dbf4f3a475 100644 --- a/panel-applet/NMWirelessAppletDbus.c +++ b/panel-applet/NMWirelessAppletDbus.c @@ -280,6 +280,31 @@ static gboolean nmwa_dbus_get_device_link_active (NMWirelessApplet *applet, char } +/* + * nmwa_dbus_get_device_supports_carrier_detect + * + * Returns whether or not the device supports carrier detection. + * + */ +static gboolean nmwa_dbus_get_device_supports_carrier_detect (NMWirelessApplet *applet, char *net_path) +{ + gboolean supports_carrier_detect = FALSE; + + switch (nmwa_dbus_call_nm_method (applet->connection, net_path, "getSupportsCarrierDetect", + DBUS_TYPE_BOOLEAN, (void **)(&supports_carrier_detect), NULL)) + { + case (RETURN_NO_NM): + applet->applet_state = APPLET_STATE_NO_NM; + break; + + default: + break; + } + + return (supports_carrier_detect); +} + + /* * nmwa_dbus_get_object_strength * @@ -428,6 +453,47 @@ 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) +{ + gboolean enabled = FALSE; + + switch (nmwa_dbus_call_nm_method (applet->connection, NM_DBUS_PATH, "getWirelessEnabled", 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_device_networks * @@ -637,6 +703,50 @@ 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. + * + */ +void nmwa_dbus_enable_wireless (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, "setWirelessEnabled"))) + { + dbus_message_append_args (message, DBUS_TYPE_BOOLEAN, enabled, DBUS_TYPE_INVALID); + dbus_connection_send (applet->connection, message, NULL); + applet->wireless_enabled = nmwa_dbus_get_wireless_enabled (applet); + } +} + + /* * wireless_network_ref * @@ -955,7 +1065,6 @@ static void nmwa_dbus_update_devices (NMWirelessApplet *applet) int i; char *nm_act_dev = NULL; GSList *device_list = NULL; - NetworkDevice *active_device = NULL; char *nm_status = NULL; gboolean adhoc = FALSE; @@ -995,6 +1104,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->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]); @@ -1008,7 +1119,6 @@ static void nmwa_dbus_update_devices (NMWirelessApplet *applet) device_list = g_slist_append (device_list, dev); if (nm_act_dev && !strcmp (nm_act_dev, devices[i])) { - active_device = dev; network_device_ref (dev); applet->dbus_active_device = dev; network_device_ref (dev); @@ -1041,10 +1151,13 @@ static void nmwa_dbus_update_devices (NMWirelessApplet *applet) g_free (applet->nm_status); applet->device_list = device_list; - applet->active_device = active_device; + applet->active_device = applet->dbus_active_device; applet->nm_status = nm_status; 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); } @@ -1276,7 +1389,7 @@ gpointer nmwa_dbus_worker (gpointer user_data) g_source_set_callback (timeout_source, nmwa_dbus_timeout_worker, applet, NULL); timeout_id = g_source_attach (timeout_source, applet->thread_context); - strength_source = g_timeout_source_new (1000); + strength_source = g_timeout_source_new (2000); g_source_set_callback (strength_source, nmwa_dbus_update_active_device_strength, applet, NULL); strength_id = g_source_attach (strength_source, applet->thread_context); diff --git a/panel-applet/NMWirelessAppletDbus.h b/panel-applet/NMWirelessAppletDbus.h index 22f7a7c83c..dc29c2f027 100644 --- a/panel-applet/NMWirelessAppletDbus.h +++ b/panel-applet/NMWirelessAppletDbus.h @@ -46,6 +46,10 @@ void nmwa_dbus_create_network (DBusConnection *connection, const NetworkDev const WirelessNetwork *network, NMEncKeyType key_type, const char *passphrase); +void nmwa_dbus_enable_scanning (NMWirelessApplet *applet, gboolean enabled); + +void nmwa_dbus_enable_wireless (NMWirelessApplet *applet, gboolean enabled); + WirelessNetwork * wireless_network_new_with_essid (const char *essid); void wireless_network_unref (WirelessNetwork *net); diff --git a/panel-applet/menu-info.c b/panel-applet/menu-info.c index da7aa1b364..3bbc7770bb 100644 --- a/panel-applet/menu-info.c +++ b/panel-applet/menu-info.c @@ -95,23 +95,27 @@ nm_menu_wired_new (void) void nm_menu_wired_update (NMMenuWired *menu_wired, - NetworkDevice *network, + NetworkDevice *dev, gint n_devices) { gchar *text; - gchar *network_name; + gchar *dev_name; - g_assert (network->type == DEVICE_TYPE_WIRED_ETHERNET); + g_assert (dev->type == DEVICE_TYPE_WIRED_ETHERNET); - network_name = network->hal_name ? network->hal_name : network->nm_name; + dev_name = dev->hal_name ? dev->hal_name : dev->nm_name; if (n_devices > 1) - text = g_strdup_printf (_("Wired Network (%s)"), network_name); + text = g_strdup_printf (_("Wired Network (%s)"), dev_name); else text = g_strdup (_("Wired Network")); gtk_label_set_text (GTK_LABEL (menu_wired->label), text); - gtk_widget_set_sensitive (GTK_WIDGET (menu_wired), network->link); + /* 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) + gtk_widget_set_sensitive (GTK_WIDGET (menu_wired), dev->link); } diff --git a/src/Makefile.am b/src/Makefile.am index 53e9236b50..cbb00f7f7e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,6 +11,8 @@ NetworkManager_SOURCES = \ NetworkManagerAPList.h \ NetworkManagerDbus.c \ NetworkManagerDbus.h \ + NetworkManagerDbusUtils.c \ + NetworkManagerDbusUtils.h \ NetworkManagerDHCP.c \ NetworkManagerDHCP.h \ NetworkManagerDevice.c \ diff --git a/src/NetworkManager.c b/src/NetworkManager.c index 3c81b62720..9e30863660 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -305,10 +305,10 @@ static void nm_hal_device_property_modified (LibHalContext *ctx, const char *udi g_return_if_fail (udi != NULL); g_return_if_fail (key != NULL); - //syslog (LOG_DEBUG, "nm_hal_device_property_modified() called with udi = %s, key = %s, is_removed = %d, is_added = %d", udi, key, is_removed, is_added); + /*syslog (LOG_DEBUG, "nm_hal_device_property_modified() called with udi = %s, key = %s, is_removed = %d, is_added = %d", udi, key, is_removed, is_added);*/ /* Only accept wired ethernet link changes for now */ - if (is_removed || (strcmp (key, "net.80203.link"))) + if (is_removed || (strcmp (key, "net.80203.link") != 0)) return; if (!hal_device_property_exists (ctx, udi, "net.80203.link")) @@ -323,7 +323,7 @@ static void nm_hal_device_property_modified (LibHalContext *ctx, const char *udi if ((dev = nm_get_device_by_udi (data, udi)) && nm_device_is_wired (dev)) { syslog (LOG_DEBUG, "HAL signaled link state change for device %s.", nm_device_get_iface (dev)); - nm_device_update_link_active (dev, FALSE); + nm_device_update_link_active (dev); /* If the currently active device is locked and wireless, and the wired * device we just received this property change event for now has a link @@ -444,7 +444,7 @@ gboolean nm_link_state_monitor (gpointer user_data) { if (!nm_device_is_up (dev)) nm_device_bring_up (dev); - nm_device_update_link_active (dev, FALSE); + nm_device_update_link_active (dev); if (dev == data->active_device) { @@ -563,6 +563,9 @@ static NMData *nm_data_new (gboolean enable_test_devices) data->enable_test_devices = enable_test_devices; + data->scanning_enabled = TRUE; + data->wireless_enabled = TRUE; + nm_policy_schedule_state_update (data); return (data); diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c index bc0c81a22c..be4f1df78c 100644 --- a/src/NetworkManagerDbus.c +++ b/src/NetworkManagerDbus.c @@ -31,13 +31,12 @@ #include "NetworkManagerUtils.h" #include "NetworkManagerDevice.h" #include "NetworkManagerDbus.h" +#include "NetworkManagerDbusUtils.h" #include "NetworkManagerAP.h" #include "NetworkManagerAPList.h" #include "NetworkManagerPolicy.h" -static int test_dev_num = 0; - /* * nm_dbus_create_error_message * @@ -166,34 +165,35 @@ static NMAccessPoint *nm_dbus_get_ap_from_object_path (const char *path, NMDevic * Returns the object path of the currently active device * */ -static DBusMessage *nm_dbus_nm_get_active_device (DBusConnection *connection, DBusMessage *message, NMData *data) +static DBusMessage *nm_dbus_nm_get_active_device (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) { - DBusMessage *reply_message = NULL; + DBusMessage *reply = NULL; g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->data != NULL, NULL); g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (message != NULL, NULL); /* Construct object path of "active" device and return it */ - if (data->active_device) + if (data->data->active_device) { char *object_path; - reply_message = dbus_message_new_method_return (message); - if (!reply_message) + reply = dbus_message_new_method_return (message); + if (!reply) return (NULL); - object_path = g_strdup_printf ("%s/%s", NM_DBUS_PATH_DEVICES, nm_device_get_iface (data->active_device)); - dbus_message_append_args (reply_message, DBUS_TYPE_STRING, object_path, DBUS_TYPE_INVALID); + object_path = g_strdup_printf ("%s/%s", NM_DBUS_PATH_DEVICES, nm_device_get_iface (data->data->active_device)); + dbus_message_append_args (reply, DBUS_TYPE_STRING, object_path, DBUS_TYPE_INVALID); g_free (object_path); } else { - reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NoActiveDevice", + reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NoActiveDevice", "There is no currently active device."); } - return (reply_message); + return (reply); } @@ -266,10 +266,10 @@ void nm_dbus_schedule_network_not_found_signal (NMData *data, const char *networ * device. * */ -static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DBusMessage *message, NMData *data) +static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) { NMDevice *dev = NULL; - DBusMessage *reply_message = NULL; + DBusMessage *reply = NULL; char *dev_path = NULL; char *network = NULL; char *key = NULL; @@ -279,6 +279,7 @@ static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DB g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (message != NULL, NULL); g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->data != NULL, NULL); /* Try to grab both device _and_ network first, and if that fails then just the device. */ dbus_error_init (&error); @@ -300,7 +301,7 @@ static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DB if (dbus_error_is_set (&error)) dbus_error_free (&error); - reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "InvalidArguments", + reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "InvalidArguments", "NetworkManager::setActiveDevice called with invalid arguments."); goto out; } else syslog (LOG_INFO, "FORCE: device '%s'", dev_path); @@ -308,10 +309,10 @@ static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DB /* So by now we have a valid device and possibly a network as well */ - dev = nm_dbus_get_device_from_object_path (data, dev_path); + dev = nm_dbus_get_device_from_object_path (data->data, dev_path); if (!dev || (nm_device_get_driver_support_level (dev) == NM_DRIVER_UNSUPPORTED)) { - reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotFound", + reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotFound", "The requested network device does not exist."); goto out; } @@ -320,12 +321,12 @@ static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DB /* Make sure network is valid and device is wireless */ if (nm_device_is_wireless (dev) && !network) { - reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "InvalidArguments", + reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "InvalidArguments", "NetworkManager::setActiveDevice called with invalid arguments."); goto out; } - data->forcing_device = TRUE; + data->data->forcing_device = TRUE; nm_device_deactivate (dev, FALSE); nm_device_schedule_force_use (dev, network, key, key_type); @@ -333,7 +334,7 @@ out: dbus_free (dev_path); dbus_free (network); dbus_free (key); - return (reply_message); + return (reply); } @@ -343,10 +344,10 @@ out: * Create a new wireless network and * */ -static DBusMessage *nm_dbus_nm_create_wireless_network (DBusConnection *connection, DBusMessage *message, NMData *data) +static DBusMessage *nm_dbus_nm_create_wireless_network (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) { NMDevice *dev = NULL; - DBusMessage *reply_message = NULL; + DBusMessage *reply = NULL; char *dev_path = NULL; NMAccessPoint *new_ap = NULL; char *network = NULL; @@ -357,6 +358,7 @@ static DBusMessage *nm_dbus_nm_create_wireless_network (DBusConnection *connecti g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (message != NULL, NULL); g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->data != NULL, NULL); /* Try to grab both device _and_ network first, and if that fails then just the device. */ dbus_error_init (&error); @@ -364,33 +366,30 @@ static DBusMessage *nm_dbus_nm_create_wireless_network (DBusConnection *connecti DBUS_TYPE_STRING, &network, DBUS_TYPE_STRING, &key, DBUS_TYPE_INT32, &key_type, DBUS_TYPE_INVALID)) { - reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "InvalidArguments", + reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "InvalidArguments", "NetworkManager::createWirelessNetwork called with invalid arguments."); - return (reply_message); + return (reply); } else syslog (LOG_INFO, "Creating network '%s' on device '%s'.", network, dev_path); - dev = nm_dbus_get_device_from_object_path (data, dev_path); + dev = nm_dbus_get_device_from_object_path (data->data, dev_path); dbus_free (dev_path); if (!dev || (nm_device_get_driver_support_level (dev) == NM_DRIVER_UNSUPPORTED)) { - reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotFound", + reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotFound", "The requested network device does not exist."); - return (reply_message); + return (reply); } nm_device_ref (dev); /* Make sure network is valid and device is wireless */ if (!nm_device_is_wireless (dev) || !network) { - reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "InvalidArguments", + reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "InvalidArguments", "NetworkManager::createWirelessNetwork called with invalid arguments."); goto out; } - if (!(reply_message = dbus_message_new_method_return (message))) - goto out; - - data->forcing_device = TRUE; + data->data->forcing_device = TRUE; new_ap = nm_ap_new (); @@ -410,13 +409,13 @@ static DBusMessage *nm_dbus_nm_create_wireless_network (DBusConnection *connecti nm_device_activation_cancel (dev); /* Schedule this device to be used next. */ - nm_policy_schedule_device_switch (dev, data); + nm_policy_schedule_device_switch (dev, data->data); out: dbus_free (network); dbus_free (key); nm_device_unref (dev); - return (reply_message); + return (reply); } @@ -427,36 +426,37 @@ out: * devices in the device list. * */ -static DBusMessage *nm_dbus_nm_get_devices (DBusConnection *connection, DBusMessage *message, NMData *data) +static DBusMessage *nm_dbus_nm_get_devices (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) { - DBusMessage *reply_message = NULL; + DBusMessage *reply = NULL; DBusMessageIter iter; DBusMessageIter iter_array; g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->data != NULL, NULL); g_return_val_if_fail (connection != NULL, NULL); g_return_val_if_fail (message != NULL, NULL); /* Check for no devices */ - if (!data->dev_list) + if (!data->data->dev_list) return (nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NoDevices", "There are no available network devices.")); - if (!(reply_message = dbus_message_new_method_return (message))) - return (NULL); + if (!(reply = dbus_message_new_method_return (message))) + return NULL; - dbus_message_iter_init (reply_message, &iter); + dbus_message_iter_init (reply, &iter); dbus_message_iter_append_array (&iter, &iter_array, DBUS_TYPE_STRING); /* Iterate over device list and grab index of "active device" */ - if (nm_try_acquire_mutex (data->dev_list_mutex, __FUNCTION__)) + if (nm_try_acquire_mutex (data->data->dev_list_mutex, __FUNCTION__)) { - GSList *element = data->dev_list; + GSList *elt; gboolean appended = FALSE; - while (element) + for (elt = data->data->dev_list; elt; elt = g_slist_next (elt)) { - NMDevice *dev = (NMDevice *)(element->data); + NMDevice *dev = (NMDevice *)(elt->data); if (dev && (nm_device_get_driver_support_level (dev) != NM_DRIVER_UNSUPPORTED)) { @@ -465,7 +465,6 @@ static DBusMessage *nm_dbus_nm_get_devices (DBusConnection *connection, DBusMess g_free (object_path); appended = TRUE; } - element = g_slist_next (element); } /* If by some chance there is a device list, but it has no devices in it @@ -474,15 +473,15 @@ static DBusMessage *nm_dbus_nm_get_devices (DBusConnection *connection, DBusMess if (!appended) g_assert ("Device list existed, but no devices were in it."); - nm_unlock_mutex (data->dev_list_mutex, __FUNCTION__); + nm_unlock_mutex (data->data->dev_list_mutex, __FUNCTION__); } else { - reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "Retry", + reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "Retry", "NetworkManager could not lock device list, try again."); } - return (reply_message); + return (reply); } @@ -795,13 +794,13 @@ void nm_dbus_get_user_key_for_network (DBusConnection *connection, NMDevice *dev /* - * nm_dbus_set_user_key_for_network + * nm_dbus_nm_set_user_key_for_network * * In response to a NetworkManagerInfo message, sets the WEP key * for a particular wireless AP/network * */ -static void nm_dbus_set_user_key_for_network (DBusConnection *connection, DBusMessage *message, NMData *data) +static DBusMessage * nm_dbus_nm_set_user_key_for_network (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) { DBusError error; char *device; @@ -809,9 +808,10 @@ static void nm_dbus_set_user_key_for_network (DBusConnection *connection, DBusMe char *passphrase; NMEncKeyType key_type; - g_return_if_fail (data != NULL); - g_return_if_fail (connection != NULL); - g_return_if_fail (message != NULL); + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (data->data != NULL, NULL); + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); dbus_error_init (&error); if (dbus_message_get_args (message, &error, @@ -823,13 +823,15 @@ static void nm_dbus_set_user_key_for_network (DBusConnection *connection, DBusMe { NMDevice *dev; - if ((dev = nm_get_device_by_iface (data, device))) - nm_device_set_user_key_for_network (dev, data->invalid_ap_list, network, passphrase, key_type); + if ((dev = nm_get_device_by_iface (data->data, device))) + nm_device_set_user_key_for_network (dev, data->data->invalid_ap_list, network, passphrase, key_type); dbus_free (device); dbus_free (network); dbus_free (passphrase); } + + return (NULL); } /* @@ -1124,6 +1126,152 @@ char ** nm_dbus_get_networks (DBusConnection *connection, NMNetworkType type, in } +static DBusMessage *nm_dbus_nm_set_scanning_enabled (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + gboolean enabled = FALSE; + DBusError err; + + 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)) + { + data->data->scanning_enabled = enabled; +syslog (LOG_ERR, "Set scanning to %d\n", enabled); + } + + return NULL; +} + +static DBusMessage *nm_dbus_nm_get_scanning_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); + + return reply; +} + +static DBusMessage *nm_dbus_nm_set_wireless_enabled (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + gboolean enabled = FALSE; + DBusError err; + + 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)) + { + data->data->wireless_enabled = enabled; + nm_policy_schedule_state_update (data->data); + } + + return NULL; +} + +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->wireless_enabled, DBUS_TYPE_INVALID); + + return reply; +} + +static DBusMessage *nm_dbus_nm_get_status (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + DBusMessage *reply = NULL; + char *status; + + g_return_val_if_fail (data && data->data && connection && message, NULL); + + status = nm_dbus_network_status_from_data (data->data); + if (status && (reply = dbus_message_new_method_return (message))) + dbus_message_append_args (reply, DBUS_TYPE_STRING, status, DBUS_TYPE_INVALID); + g_free (status); + + return reply; +} + +static DBusMessage *nm_dbus_nm_create_test_device (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + DBusError err; + NMDeviceType type; + DBusMessage *reply = NULL; + static int test_dev_num = 0; + + g_return_val_if_fail (data && data->data && connection && message, NULL); + + dbus_error_init (&err); + if ( dbus_message_get_args (message, &err, DBUS_TYPE_INT32, &type, DBUS_TYPE_INVALID) + && ((type == DEVICE_TYPE_WIRED_ETHERNET) || (type == DEVICE_TYPE_WIRELESS_ETHERNET))) + { + char *interface = g_strdup_printf ("test%d", test_dev_num); + char *udi = g_strdup_printf ("/test-devices/%s", interface); + NMDevice *dev = NULL; + + dev = nm_create_device_and_add_to_list (data->data, udi, interface, TRUE, type); + test_dev_num++; + if ((reply = dbus_message_new_method_return (message))) + { + char *dev_path = g_strdup_printf ("%s/%s", NM_DBUS_PATH_DEVICES, nm_device_get_iface (dev)); + dbus_message_append_args (reply, DBUS_TYPE_STRING, dev_path, DBUS_TYPE_INVALID); + g_free (dev_path); + } + g_free (interface); + g_free (udi); + } + else + reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "BadType", "The test device type was invalid."); + + return (reply); +} + +static DBusMessage *nm_dbus_nm_remove_test_device (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data) +{ + DBusMessage *reply = NULL; + DBusError err; + char *dev_path; + + g_return_val_if_fail (data && data->data && connection && message, NULL); + + dbus_error_init (&err); + if (dbus_message_get_args (message, &err, DBUS_TYPE_STRING, &dev_path, DBUS_TYPE_INVALID)) + { + NMDevice *dev; + + if ((dev = nm_dbus_get_device_from_object_path (data->data, dev_path))) + { + if (nm_device_is_test_device (dev)) + nm_remove_device_from_list (data->data, nm_device_get_udi (dev)); + else + reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NotTestDevice", + "Only test devices can be removed via dbus calls."); + } + else + { + reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotFound", + "The requested network device does not exist."); + } + } + else + { + reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceBad", + "The device ID was bad."); + } + + if (dbus_error_is_set (&err)) + dbus_error_free (&err); + + return (reply); +} + /* * nm_dbus_nmi_is_running * @@ -1444,6 +1592,19 @@ static DBusMessage *nm_dbus_devices_handle_request (DBusConnection *connection, } else if (strcmp ("getLinkActive", request) == 0) dbus_message_append_args (reply_message, DBUS_TYPE_BOOLEAN, nm_device_get_link_active (dev), DBUS_TYPE_INVALID); + else if (strcmp ("getSupportsCarrierDetect", request) == 0) + { + /* Wired devices only for now */ + if (!nm_device_is_wired (dev)) + { + dbus_message_unref (reply_message); + reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotWired", + "Carrier detection is only supported for wired devices."); + return (reply_message); + } + + dbus_message_append_args (reply_message, DBUS_TYPE_BOOLEAN, nm_device_get_supports_carrier_detect (dev), DBUS_TYPE_INVALID); + } else if (strcmp ("setLinkActive", request) == 0) { /* Can only set link status for active devices */ @@ -1483,121 +1644,28 @@ static DBusMessage *nm_dbus_devices_handle_request (DBusConnection *connection, static DBusHandlerResult nm_dbus_nm_message_handler (DBusConnection *connection, DBusMessage *message, void *user_data) { NMData *data = (NMData *)user_data; - const char *method; - const char *path; - DBusMessage *reply_message = NULL; gboolean handled = TRUE; + DBusMessage *reply = NULL; + NMDbusCBData cb_data; g_return_val_if_fail (data != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); + g_return_val_if_fail (data->nm_methods != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); g_return_val_if_fail (connection != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - method = dbus_message_get_member (message); - path = dbus_message_get_path (message); - - /* syslog (LOG_DEBUG, "nm_dbus_nm_message_handler() got method %s for path %s", method, path); */ - - if (strcmp ("getActiveDevice", method) == 0) - reply_message = nm_dbus_nm_get_active_device (connection, message, data); - else if (strcmp ("getDevices", method) == 0) - reply_message = nm_dbus_nm_get_devices (connection, message, data); - else if (strcmp ("setActiveDevice", method) == 0) - nm_dbus_nm_set_active_device (connection, message, data); - else if (strcmp ("createWirelessNetwork", method) == 0) - nm_dbus_nm_create_wireless_network (connection, message, data); - else if (strcmp ("setKeyForNetwork", method) == 0) - nm_dbus_set_user_key_for_network (connection, message, data); - else if (strcmp ("status", method) == 0) + cb_data.data = data; + cb_data.dev = NULL; + handled = nm_dbus_method_dispatch (data->nm_methods, connection, message, &cb_data, &reply); + if (reply) { - char *status = nm_dbus_network_status_from_data (data); - - if (status && (reply_message = dbus_message_new_method_return (message))) - dbus_message_append_args (reply_message, DBUS_TYPE_STRING, status, DBUS_TYPE_INVALID); - g_free (status); - } - else if (strcmp ("createTestDevice", method) == 0) - { - DBusError error; - NMDeviceType type; - - dbus_error_init (&error); - if ( dbus_message_get_args (message, &error, DBUS_TYPE_INT32, &type, DBUS_TYPE_INVALID) - && ((type == DEVICE_TYPE_WIRED_ETHERNET) || (type == DEVICE_TYPE_WIRELESS_ETHERNET))) - { - char *interface = g_strdup_printf ("test%d", test_dev_num); - char *udi = g_strdup_printf ("/test-devices/%s", interface); - NMDevice *dev = NULL; - - dev = nm_create_device_and_add_to_list (data, udi, interface, TRUE, type); - test_dev_num++; - if ((reply_message = dbus_message_new_method_return (message))) - { - char *dev_path = g_strdup_printf ("%s/%s", NM_DBUS_PATH_DEVICES, nm_device_get_iface (dev)); - dbus_message_append_args (reply_message, DBUS_TYPE_STRING, dev_path, DBUS_TYPE_INVALID); - g_free (dev_path); - } - g_free (interface); - g_free (udi); - } - else - reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "BadType", - "The test device type was invalid."); - } - else if (strcmp ("removeTestDevice", method) == 0) - { - DBusError error; - char *dev_path; - - dbus_error_init (&error); - if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &dev_path, DBUS_TYPE_INVALID)) - { - NMDevice *dev; - - if ((dev = nm_dbus_get_device_from_object_path (data, dev_path))) - { - if (nm_device_is_test_device (dev)) - nm_remove_device_from_list (data, nm_device_get_udi (dev)); - else - reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NotTestDevice", - "Only test devices can be removed via dbus calls."); - } - else - { - reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotFound", - "The requested network device does not exist."); - } - } - else - { - reply_message = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceBad", - "The device ID was bad."); - } - } - else - handled = FALSE; - - if (reply_message) - { - dbus_connection_send (connection, reply_message, NULL); - dbus_message_unref (reply_message); + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); } return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED); } -/* - * nm_dbus_nm_unregister_handler - * - * Nothing happens here. - * - */ -void nm_dbus_nm_unregister_handler (DBusConnection *connection, void *user_data) -{ - /* do nothing */ -} - - /* * nm_dbus_devices_message_handler * @@ -1608,23 +1676,22 @@ static DBusHandlerResult nm_dbus_devices_message_handler (DBusConnection *connec { NMData *data = (NMData *)user_data; gboolean handled = FALSE; - const char *method; const char *path; - DBusMessage *reply_message = NULL; + const char *method; + DBusMessage *reply = NULL; g_return_val_if_fail (data != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); g_return_val_if_fail (connection != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); g_return_val_if_fail (message != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED); - method = dbus_message_get_member (message); path = dbus_message_get_path (message); + method = dbus_message_get_member (message); - /*syslog (LOG_DEBUG, "nm_dbus_devices_message_handler() got method %s for path %s", method, path);*/ - - if (method && path && (reply_message = nm_dbus_devices_handle_request (connection, data, message, path, method))) + reply = nm_dbus_devices_handle_request (connection, data, message, path, method); + if (reply) { - dbus_connection_send (connection, reply_message, NULL); - dbus_message_unref (reply_message); + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); handled = TRUE; } @@ -1632,18 +1699,6 @@ static DBusHandlerResult nm_dbus_devices_message_handler (DBusConnection *connec } -/* - * nm_dbus_devices_unregister_handler - * - * Nothing happens here. - * - */ -void nm_dbus_devices_unregister_handler (DBusConnection *connection, void *user_data) -{ - /* do nothing */ -} - - /* * nm_dbus_is_info_daemon_running * @@ -1665,6 +1720,27 @@ gboolean nm_dbus_is_info_daemon_running (DBusConnection *connection) } +NMDbusMethodList *nm_dbus_nm_methods_setup (void) +{ + NMDbusMethodList *list = nm_dbus_method_list_new (); + + nm_dbus_method_list_add_method (list, "getActiveDevice", nm_dbus_nm_get_active_device); + nm_dbus_method_list_add_method (list, "getDevices", nm_dbus_nm_get_devices); + 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, "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, "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); + + return (list); +} + + /* * nm_dbus_init * @@ -1676,8 +1752,8 @@ DBusConnection *nm_dbus_init (NMData *data) DBusError dbus_error; dbus_bool_t success; DBusConnection *connection; - DBusObjectPathVTable nm_vtable = { &nm_dbus_nm_unregister_handler, &nm_dbus_nm_message_handler, NULL, NULL, NULL, NULL }; - DBusObjectPathVTable devices_vtable = { &nm_dbus_devices_unregister_handler, &nm_dbus_devices_message_handler, NULL, NULL, NULL, NULL }; + 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}; dbus_connection_set_change_sigpipe (TRUE); @@ -1694,6 +1770,10 @@ DBusConnection *nm_dbus_init (NMData *data) dbus_connection_set_exit_on_disconnect (connection, FALSE); dbus_connection_setup_with_g_main (connection, data->main_context); + data->nm_methods = nm_dbus_nm_methods_setup (); +/* data->device_methods = nm_dbus_device_methods_setup (); + data->net_methods = nm_dbus_net_methods_setup (); +*/ success = dbus_connection_register_object_path (connection, NM_DBUS_PATH, &nm_vtable, data); if (!success) { diff --git a/src/NetworkManagerDbusUtils.c b/src/NetworkManagerDbusUtils.c new file mode 100644 index 0000000000..6d064c2efa --- /dev/null +++ b/src/NetworkManagerDbusUtils.c @@ -0,0 +1,92 @@ +/* NetworkManager -- Network link manager + * + * Dan Williams + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * (C) Copyright 2005 Red Hat, Inc. + */ + +#include +#include "NetworkManagerDevice.h" +#include "NetworkManagerDbusUtils.h" + + +struct NMDbusMethodList +{ + GHashTable *methods; +}; + + +NMDbusMethodList * nm_dbus_method_list_new (void) +{ + NMDbusMethodList *list = g_malloc0 (sizeof (NMDbusMethodList)); + + if (list) + list->methods = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + return list; +} + + +void nm_dbus_method_list_add_method (NMDbusMethodList *list, const char *method, NMDbusMethod callback) +{ + g_return_if_fail (list != NULL); + g_return_if_fail (list->methods != NULL); + g_return_if_fail (method != NULL); + g_return_if_fail (callback != NULL); + + g_hash_table_insert (list->methods, g_strdup (method), callback); +} + + +gboolean nm_dbus_method_dispatch (NMDbusMethodList *list, DBusConnection *connection, DBusMessage *message, gpointer user_data, DBusMessage **reply) +{ + NMDbusMethod callback = NULL; + const char *method; + DBusMessage *temp_reply = NULL; + + if (reply) + *reply = NULL; + + g_return_val_if_fail (list != NULL, FALSE); + g_return_val_if_fail (list->methods != NULL, FALSE); + g_return_val_if_fail (connection != NULL, FALSE); + g_return_val_if_fail (message != NULL, FALSE); + + if (!(method = dbus_message_get_member (message))) + return FALSE; + + if (!(callback = g_hash_table_lookup (list->methods, method))) + return FALSE; + +syslog (LOG_ERR, "DBUS calling method '%s'\n", method); + temp_reply = (*callback) (connection, message, (NMDbusCBData *)user_data); + + if (reply) + *reply = temp_reply; + + return (TRUE); +} + + +void nm_dbus_method_list_free (NMDbusMethodList *list) +{ + if (list) + { + g_hash_table_destroy (list->methods); + g_free (list); + } +} diff --git a/src/NetworkManagerDbusUtils.h b/src/NetworkManagerDbusUtils.h new file mode 100644 index 0000000000..d9ccb94f2b --- /dev/null +++ b/src/NetworkManagerDbusUtils.h @@ -0,0 +1,51 @@ +/* NetworkManager -- Network link manager + * + * Dan Williams + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * (C) Copyright 2005 Red Hat, Inc. + */ + +#ifndef NETWORK_MANAGER_DBUS_UTILS_H +#define NETWORK_MANAGER_DBUS_UTILS_H + +#include +#include +#include +#include + +#include "NetworkManagerMain.h" + +typedef struct NMDbusCBData +{ + NMData *data; + NMDevice *dev; +} NMDbusCBData; + +typedef DBusMessage* (*NMDbusMethod) (DBusConnection *, DBusMessage *, NMDbusCBData *); + + +NMDbusMethodList * nm_dbus_method_list_new (void); + +void nm_dbus_method_list_add_method (NMDbusMethodList *list, const char *method, NMDbusMethod callback); + +gboolean nm_dbus_method_dispatch (NMDbusMethodList *list, DBusConnection *connection, DBusMessage *message, + gpointer user_data, DBusMessage **reply); + +void nm_dbus_method_list_free (NMDbusMethodList *list); + + +#endif diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c index f015b9c3e2..6bb37597ca 100644 --- a/src/NetworkManagerDevice.c +++ b/src/NetworkManagerDevice.c @@ -40,11 +40,12 @@ #include "NetworkManagerDHCP.h" /* Local static prototypes */ -static gboolean mii_get_link (NMDevice *dev); static gpointer nm_device_worker (gpointer user_data); static gboolean nm_device_activate (gpointer user_data); static gboolean nm_device_activation_configure_ip (NMDevice *dev, gboolean do_only_autoip); 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); typedef struct { @@ -247,44 +248,39 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev, dev->type = nm_device_test_wireless_extensions (dev) ? DEVICE_TYPE_WIRELESS_ETHERNET : DEVICE_TYPE_WIRED_ETHERNET; + /* Device thread's main loop */ + dev->context = g_main_context_new (); + dev->loop = g_main_loop_new (dev->context, FALSE); + + if (!dev->context || !dev->loop) + 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); /* Initialize wireless-specific options */ if (nm_device_is_wireless (dev)) { - int sk; - - dev->options.wireless.scan_interval = 20; - - if (!(dev->options.wireless.scan_mutex = g_mutex_new ())) - { - g_free (dev->iface); - g_free (dev); - return (NULL); - } - nm_register_mutex_desc (dev->options.wireless.scan_mutex, "Scan Mutex"); - - if (!(dev->options.wireless.best_ap_mutex = g_mutex_new ())) - { - g_mutex_free (dev->options.wireless.scan_mutex); - g_free (dev->iface); - g_free (dev); - return (NULL); - } - nm_register_mutex_desc (dev->options.wireless.best_ap_mutex, "Best AP Mutex"); - - if (!(dev->options.wireless.ap_list = nm_ap_list_new (NETWORK_TYPE_DEVICE))) - { - g_free (dev->iface); - g_mutex_free (dev->options.wireless.best_ap_mutex); - g_free (dev); - return (NULL); - } - dev->options.wireless.supports_wireless_scan = nm_device_supports_wireless_scan (dev); + int sk; + NMDeviceWirelessOptions *opts = &(dev->options.wireless); nm_device_set_mode (dev, NETWORK_MODE_INFRA); + opts->scan_interval = 20; + + opts->scan_mutex = g_mutex_new (); + opts->best_ap_mutex = g_mutex_new (); + opts->ap_list = nm_ap_list_new (NETWORK_TYPE_DEVICE); + if (!opts->scan_mutex || !opts->best_ap_mutex || !opts->ap_list) + goto err; + + nm_register_mutex_desc (opts->scan_mutex, "Scan Mutex"); + nm_register_mutex_desc (opts->best_ap_mutex, "Best AP Mutex"); + + opts->supports_wireless_scan = nm_device_supports_wireless_scan (dev); + if ((sk = iw_sockets_open ()) >= 0) { iwrange range; @@ -292,29 +288,32 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev, { int i; - dev->options.wireless.max_qual.qual = range.max_qual.qual; - dev->options.wireless.max_qual.level = range.max_qual.level; - dev->options.wireless.max_qual.noise = range.max_qual.noise; - dev->options.wireless.max_qual.updated = range.max_qual.updated; + opts->max_qual.qual = range.max_qual.qual; + opts->max_qual.level = range.max_qual.level; + opts->max_qual.noise = range.max_qual.noise; + opts->max_qual.updated = range.max_qual.updated; - dev->options.wireless.avg_qual.qual = range.avg_qual.qual; - dev->options.wireless.avg_qual.level = range.avg_qual.level; - dev->options.wireless.avg_qual.noise = range.avg_qual.noise; - dev->options.wireless.avg_qual.updated = range.avg_qual.updated; + opts->avg_qual.qual = range.avg_qual.qual; + opts->avg_qual.level = range.avg_qual.level; + opts->avg_qual.noise = range.avg_qual.noise; + opts->avg_qual.updated = range.avg_qual.updated; - dev->options.wireless.num_freqs = MIN (range.num_frequency, IW_MAX_FREQUENCIES); - for (i = 0; i < dev->options.wireless.num_freqs; i++) - dev->options.wireless.freqs[i] = iw_freq2float (&(range.freq[i])); + opts->num_freqs = MIN (range.num_frequency, IW_MAX_FREQUENCIES); + for (i = 0; i < opts->num_freqs; i++) + opts->freqs[i] = iw_freq2float (&(range.freq[i])); } close (sk); } } - - dev->driver_support_level = nm_get_driver_support_level (dev->app_data->hal_ctx, dev); + else if (nm_device_is_wired (dev)) + { + if (supports_ethtool_carrier_detect (dev) || supports_mii_carrier_detect (dev)) + dev->options.wired.has_carrier_detect = TRUE; + } if (nm_device_get_driver_support_level (dev) != NM_DRIVER_UNSUPPORTED) { - nm_device_update_link_active (dev, TRUE); + nm_device_update_link_active (dev); nm_device_update_ip4_address (dev); nm_device_update_hw_address (dev); @@ -327,14 +326,7 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev, { syslog (LOG_CRIT, "nm_device_new (): could not create device worker thread. (glib said: '%s')", error->message); g_error_free (error); - - /* When we get here, we've got a refcount of 2, one because the - * device starts off with a refcount of 1, and a second ref because - * so that it sticks around for the worker thread. So we have to unref twice. - */ - nm_device_unref (dev); - nm_device_unref (dev); - dev = NULL; + goto err; } /* Block until our device thread has actually had a chance to start. */ @@ -344,6 +336,12 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev, syslog (LOG_ERR, "nm_device_new(): device's worker thread started, continuing.\n"); return (dev); + +err: + /* Initial refcount is 2 */ + nm_device_unref (dev); + nm_device_unref (dev); + return NULL; } @@ -419,9 +417,6 @@ static gpointer nm_device_worker (gpointer user_data) exit (1); } - dev->context = g_main_context_new (); - dev->loop = g_main_loop_new (dev->context, FALSE); - dev->worker_started = TRUE; /* Do an initial wireless scan */ @@ -521,7 +516,7 @@ int nm_device_open_sock (void) if (fd >= 0) return (fd); - syslog (LOG_ERR, "nm_get_network_control_socket() could not get network control socket."); + syslog (LOG_ERR, "nm_device_open_sock () could not get network control socket."); return (-1); } @@ -674,6 +669,19 @@ gboolean nm_device_get_supports_wireless_scan (NMDevice *dev) } +/* + * nm_device_get_supports_carrier_detect + */ +gboolean nm_device_get_supports_carrier_detect (NMDevice *dev) +{ + g_return_val_if_fail (dev != NULL, FALSE); + + if (!nm_device_is_wired (dev)) + return (FALSE); + + return (dev->options.wired.has_carrier_detect); +} + /* * nm_device_wireless_is_associated * @@ -764,28 +772,33 @@ static gboolean nm_device_wireless_link_active (NMDevice *dev) /* * nm_device_wired_link_active * - * Return the link state of a wired device. We usually just grab the HAL - * net.80203.link property, but on card insertion we need to check the MII - * registers of the card to get a more accurate response, since HAL may not - * have received a netlink socket link event for the device yet, and therefore - * will return FALSE when the device really does have a link. + * * */ -static gboolean nm_device_wired_link_active (NMDevice *dev, gboolean check_mii) +static gboolean nm_device_wired_link_active (NMDevice *dev) { gboolean link = FALSE; g_return_val_if_fail (dev != NULL, FALSE); + g_return_val_if_fail (nm_device_is_wired (dev) == TRUE, FALSE); g_return_val_if_fail (dev->app_data != NULL, FALSE); /* Test devices have their link state set through DBUS */ if (dev->test_device) return (nm_device_get_link_active (dev)); - if (check_mii) - link = mii_get_link (dev); - else if (hal_device_property_exists (dev->app_data->hal_ctx, nm_device_get_udi (dev), "net.80203.link")) - link = hal_device_get_property_bool (dev->app_data->hal_ctx, nm_device_get_udi (dev), "net.80203.link"); + /* We say that non-carrier-detect devices always have a link, because + * they never get auto-selected by NM. User has to force them on us, + * so we just hope the user knows whether or not the cable's plugged in. + */ + if (dev->options.wired.has_carrier_detect != TRUE) + link = TRUE; + else + { + /* Device has carrier detect, yay! */ + if (hal_device_property_exists (dev->app_data->hal_ctx, nm_device_get_udi (dev), "net.80203.link")) + link = hal_device_get_property_bool (dev->app_data->hal_ctx, nm_device_get_udi (dev), "net.80203.link"); + } return (link); } @@ -797,7 +810,7 @@ static gboolean nm_device_wired_link_active (NMDevice *dev, gboolean check_mii) * Updates the link state for a particular device. * */ -void nm_device_update_link_active (NMDevice *dev, gboolean check_mii) +void nm_device_update_link_active (NMDevice *dev) { gboolean link = FALSE; @@ -813,7 +826,7 @@ void nm_device_update_link_active (NMDevice *dev, gboolean check_mii) break; case DEVICE_TYPE_WIRED_ETHERNET: - link = nm_device_wired_link_active (dev, check_mii); + link = nm_device_wired_link_active (dev); break; default: @@ -3419,10 +3432,19 @@ static gboolean nm_device_wireless_scan (gpointer user_data) g_return_val_if_fail (dev != NULL, FALSE); g_return_val_if_fail (dev->app_data != NULL, FALSE); - /* We don't really scan on test devices or devices that don't have scanning support */ + /* We don't scan on test devices or devices that don't have scanning support */ if (dev->test_device || !nm_device_supports_wireless_scan (dev)) return FALSE; + /* Just reschedule ourselves if scanning or all wireless is disabled */ + if ( (dev->app_data->scanning_enabled == FALSE) + || (dev->app_data->wireless_enabled == FALSE)) + { + dev->options.wireless.scan_interval = 10; + goto reschedule; + } + +syslog (LOG_ERR, "ABOUT TO SCAN\n"); /* Grab the scan mutex */ if (nm_try_acquire_mutex (dev->options.wireless.scan_mutex, __FUNCTION__)) { @@ -3495,6 +3517,7 @@ static gboolean nm_device_wireless_scan (gpointer user_data) g_source_unref (scan_process_source); } +reschedule: /* Make sure we reschedule ourselves so we keep scanning */ nm_device_wireless_schedule_scan (dev); @@ -3574,85 +3597,90 @@ void nm_device_config_set_ip4_broadcast (NMDevice *dev, guint32 broadcast) } -/****************************************/ -/* Code ripped from HAL */ -/* minor modifications made for */ -/* integration with NLM */ -/****************************************/ +/**************************************/ +/* Ethtool capability detection */ +/**************************************/ +#include +#include +#include -/** Read a word from the MII transceiver management registers - * - * @param iface Which interface - * @param location Which register - * @return Word that is read - */ -static guint16 mdio_read (int sockfd, struct ifreq *ifr, int location, gboolean new_ioctl_nums) +static gboolean supports_ethtool_carrier_detect (NMDevice *dev) { - guint16 *data = (guint16 *) &(ifr->ifr_data); + int sk; + struct ifreq ifr; + gboolean supports_ethtool = FALSE; + struct ethtool_cmd edata; - data[1] = location; - if (ioctl (sockfd, new_ioctl_nums ? 0x8948 : SIOCDEVPRIVATE + 1, ifr) < 0) + g_return_val_if_fail (dev != NULL, FALSE); + + if ((sk = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { - syslog(LOG_ERR, "SIOCGMIIREG on %s failed: %s", ifr->ifr_name, strerror (errno)); - return -1; + syslog (LOG_ERR, "cannot open socket on interface %s for MII detect; errno=%d", nm_device_get_iface (dev), errno); + return (FALSE); } - return data[3]; + + 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) + goto out; + + supports_ethtool = TRUE; + +out: + close (sk); + return (supports_ethtool); } -static gboolean mii_get_link (NMDevice *dev) + + +/**************************************/ +/* MII capability detection */ +/**************************************/ +#include + +static int mdio_read (int sk, struct ifreq *ifr, int location) { - int sockfd; + struct mii_ioctl_data *mii; + + g_return_val_if_fail (sk < 0, -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) + return -1; + + return (mii->val_out); +} + +static gboolean supports_mii_carrier_detect (NMDevice *dev) +{ + int sk; struct ifreq ifr; - gboolean new_ioctl_nums; - guint16 status_word; - gboolean link_active = FALSE; + int bmsr; + gboolean supports_mii = FALSE; - sockfd = socket (AF_INET, SOCK_DGRAM, 0); - if (sockfd < 0) + g_return_val_if_fail (dev != NULL, FALSE); + + if ((sk = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { - syslog (LOG_ERR, "cannot open socket on interface %s; errno=%d", nm_device_get_iface (dev), errno); + syslog (LOG_ERR, "cannot open socket on interface %s for MII detect; errno=%d", nm_device_get_iface (dev), errno); return (FALSE); } - snprintf (ifr.ifr_name, IFNAMSIZ, nm_device_get_iface (dev)); - if (ioctl (sockfd, 0x8947, &ifr) >= 0) - new_ioctl_nums = TRUE; - else if (ioctl (sockfd, SIOCDEVPRIVATE, &ifr) >= 0) - new_ioctl_nums = FALSE; - else - { - syslog (LOG_ERR, "SIOCGMIIPHY on %s failed: %s", ifr.ifr_name, strerror (errno)); - close (sockfd); - return (FALSE); - } + strncpy (ifr.ifr_name, nm_device_get_iface (dev), sizeof(ifr.ifr_name)-1); + if (ioctl(sk, SIOCGMIIPHY, &ifr) < 0) + goto out; - /* Refer to http://www.scyld.com/diag/mii-status.html for - * the full explanation of the numbers - * - * 0x8000 Capable of 100baseT4. - * 0x7800 Capable of 10/100 HD/FD (most common). - * 0x0040 Preamble suppression permitted. - * 0x0020 Autonegotiation complete. - * 0x0010 Remote fault. - * 0x0008 Capable of Autonegotiation. - * 0x0004 Link established ("sticky"* on link failure) - * 0x0002 Jabber detected ("sticky"* on transmit jabber) - * 0x0001 Extended MII register exist. - * - */ + /* If we can read the BMSR register, we assume that the card supports MII link detection */ + bmsr = mdio_read(sk, &ifr, MII_BMSR); + supports_mii = (bmsr != -1) ? TRUE : FALSE; - /* We have to read it twice to clear any "sticky" bits */ - status_word = mdio_read (sockfd, &ifr, 1, new_ioctl_nums); - status_word = mdio_read (sockfd, &ifr, 1, new_ioctl_nums); - - if ((status_word & 0x0016) == 0x0004) - link_active = TRUE; - else - link_active = FALSE; - - close (sockfd); - - return (link_active); +out: + close (sk); + return (supports_mii); } /****************************************/ diff --git a/src/NetworkManagerDevice.h b/src/NetworkManagerDevice.h index b29b54e32e..371930b11e 100644 --- a/src/NetworkManagerDevice.h +++ b/src/NetworkManagerDevice.h @@ -58,7 +58,7 @@ void nm_device_set_removed (NMDevice *dev, const gboolean removed); gboolean nm_device_get_link_active (NMDevice *dev); void nm_device_set_link_active (NMDevice *dev, const gboolean active); -void nm_device_update_link_active (NMDevice *dev, gboolean check_mii); +void nm_device_update_link_active (NMDevice *dev); char * nm_device_get_essid (NMDevice *dev); void nm_device_set_essid (NMDevice *dev, const char *essid); @@ -76,8 +76,8 @@ void nm_device_update_hw_address (NMDevice *dev); void nm_device_get_ip6_address (NMDevice *dev); gboolean nm_device_get_supports_wireless_scan (NMDevice *dev); -gboolean nm_device_wireless_network_exists (NMDevice *dev, const char *network, const char *key, NMEncKeyType key_type, - struct ether_addr *addr, gboolean *encrypted); + +gboolean nm_device_get_supports_carrier_detect (NMDevice *dev); gboolean nm_device_set_mode (NMDevice *dev, const NMNetworkMode mode); diff --git a/src/NetworkManagerDevicePrivate.h b/src/NetworkManagerDevicePrivate.h index 7c9482fc98..0456e107bb 100644 --- a/src/NetworkManagerDevicePrivate.h +++ b/src/NetworkManagerDevicePrivate.h @@ -61,8 +61,7 @@ typedef struct NMDeviceWirelessOptions /* Wired device specific options */ typedef struct NMDeviceWiredOptions { - guint link_watch_id; - guint foo; + gboolean has_carrier_detect; } NMDeviceWiredOptions; typedef union NMDeviceOptions diff --git a/src/NetworkManagerMain.h b/src/NetworkManagerMain.h index 2f27e079a1..e7052e598b 100644 --- a/src/NetworkManagerMain.h +++ b/src/NetworkManagerMain.h @@ -30,6 +30,9 @@ #include "NetworkManagerAP.h" #include "nm-named-manager.h" +typedef struct NMDbusMethodList NMDbusMethodList; + + typedef struct NMData { GIOChannel *sigterm_iochannel; @@ -42,6 +45,10 @@ typedef struct NMData guint domain_search_id; DBusConnection *dbus_connection; + NMDbusMethodList *nm_methods; + NMDbusMethodList *device_methods; + NMDbusMethodList *net_methods; + GMainContext *main_context; GMainLoop *main_loop; gboolean enable_test_devices; @@ -56,6 +63,9 @@ typedef struct NMData gboolean forcing_device; + gboolean scanning_enabled; + gboolean wireless_enabled; + struct NMAccessPointList *allowed_ap_list; struct NMAccessPointList *invalid_ap_list; } NMData; diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index e08c53b7a0..ce19c366f5 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -1,4 +1,3 @@ - /* NetworkManager -- Network link manager * * Dan Williams @@ -45,7 +44,7 @@ */ static NMDevice * nm_policy_auto_get_best_device (NMData *data) { - GSList *element; + GSList *elt; NMDevice *best_wired_dev = NULL; guint best_wired_prio = 0; NMDevice *best_wireless_dev = NULL; @@ -53,27 +52,27 @@ static NMDevice * nm_policy_auto_get_best_device (NMData *data) NMDevice *highest_priority_dev = NULL; g_return_val_if_fail (data != NULL, NULL); - element = data->dev_list; - while (element) + for (elt = data->dev_list; elt != NULL; elt = g_slist_next (elt)) { guint dev_type; gboolean link_active; guint prio = 0; - NMDevice *dev = (NMDevice *)(element->data); + NMDevice *dev = (NMDevice *)(elt->data); /* Skip unsupported devices */ if (nm_device_get_driver_support_level (dev) == NM_DRIVER_UNSUPPORTED) - { - element = g_slist_next (element); continue; - } dev_type = nm_device_get_type (dev); link_active = nm_device_get_link_active (dev); if (dev_type == DEVICE_TYPE_WIRED_ETHERNET) { + /* We never automatically choose devices that don't support carrier detect */ + if (!nm_device_get_supports_carrier_detect (dev)) + continue; + if (link_active) prio += 1; @@ -88,7 +87,7 @@ static NMDevice * nm_policy_auto_get_best_device (NMData *data) best_wired_prio = prio; } } - else if (dev_type == DEVICE_TYPE_WIRELESS_ETHERNET) + else if ((dev_type == DEVICE_TYPE_WIRELESS_ETHERNET) && data->wireless_enabled) { NMAccessPoint *best_ap = nm_device_get_best_ap (dev); @@ -126,8 +125,6 @@ static NMDevice * nm_policy_auto_get_best_device (NMData *data) if (best_ap) nm_ap_unref (best_ap); } - - element = g_slist_next (element); } #if 0 @@ -182,20 +179,18 @@ static NMDevice * nm_policy_get_best_device (NMDevice *switch_to_dev, NMData *da { switch (nm_device_get_type (data->active_device)) { - /* If the active device was a wired device, and it no - * longer has a link, switch to auto mode. - */ + /* Wired devices get unlocked only if they have lost their link */ case (DEVICE_TYPE_WIRED_ETHERNET): if (nm_device_get_link_active (data->active_device)) best_dev = data->active_device; break; - /* For wireless devices, we only "unlock" them if they are - * removed from the system or a different device is "locked" - * by the user. + /* Wireless devices get unlocked if the user removes the card + * or turns wireless off. */ case (DEVICE_TYPE_WIRELESS_ETHERNET): - best_dev = data->active_device; + if (data->wireless_enabled == TRUE) + best_dev = data->active_device; break; default: