From e96c5c2967c482955365b0bb02afc5229b853c96 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 17 Dec 2004 17:16:22 +0000 Subject: [PATCH] 2004-12-17 Dan Williams * Ad Ad-Hoc networking mode support. In Ad-Hoc mode, we only try to get link-local addresses instead of doing DHCP. * In the panel applet, there's a new "Create new Wireless Network..." item * The panel applet also sticks around now even if NetworkManager dies, but it doesn't hide its icon when NM isn't around. Not hiding the icon is a bug, I'll fix that later. * We also don't use 'nscd' anymore in the RH backend, it was impeding name lookups after a switch rather than actually doing them. * Clean up some of those warnings in nm_ap_list_* functions * Delay between scans changed to 15s instead of 10s git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@342 4912f4e0-d625-0410-9fb7-b9a5a253dbdc --- ChangeLog | 18 + info-daemon/NetworkManagerInfoDbus.c | 79 +-- panel-applet/NMWirelessApplet.c | 31 +- panel-applet/NMWirelessAppletDbus.c | 33 + panel-applet/NMWirelessAppletDbus.h | 4 + .../NMWirelessAppletOtherNetworkDialog.c | 22 +- .../NMWirelessAppletOtherNetworkDialog.h | 2 +- src/NetworkManager.c | 2 +- src/NetworkManagerAP.c | 25 +- src/NetworkManagerAP.h | 3 + src/NetworkManagerAPList.c | 8 +- src/NetworkManagerDHCP.c | 68 +- src/NetworkManagerDHCP.h | 1 + src/NetworkManagerDbus.c | 96 +++ src/NetworkManagerDevice.c | 629 ++++++++++++++---- src/NetworkManagerDevicePrivate.h | 2 +- src/NetworkManagerPolicy.c | 4 +- src/NetworkManagerSystem.c | 4 +- src/NetworkManagerSystem.h | 3 + src/autoip.c | 20 +- src/backends/NetworkManagerDebian.c | 34 + src/backends/NetworkManagerGentoo.c | 34 + src/backends/NetworkManagerRedHat.c | 53 ++ src/backends/NetworkManagerSlackware.c | 34 + 24 files changed, 982 insertions(+), 227 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0fad9ca84..e75c0805c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2004-12-17 Dan Williams + + * Ad Ad-Hoc networking mode support. In Ad-Hoc mode, we only try to get + link-local addresses instead of doing DHCP. + + * In the panel applet, there's a new "Create new Wireless Network..." item + + * The panel applet also sticks around now even if NetworkManager dies, but + it doesn't hide its icon when NM isn't around. Not hiding the icon is + a bug, I'll fix that later. + + * We also don't use 'nscd' anymore in the RH backend, it was impeding name + lookups after a switch rather than actually doing them. + + * Clean up some of those warnings in nm_ap_list_* functions + + * Delay between scans changed to 15s instead of 10s + 2004-12-15 Dan Williams Patch from Tom Parker diff --git a/info-daemon/NetworkManagerInfoDbus.c b/info-daemon/NetworkManagerInfoDbus.c index d341c8f52..dace77a07 100644 --- a/info-daemon/NetworkManagerInfoDbus.c +++ b/info-daemon/NetworkManagerInfoDbus.c @@ -822,6 +822,35 @@ static DBusHandlerResult nmi_dbus_filter (DBusConnection *connection, DBusMessag appeared = TRUE; else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "WirelessNetworkDisappeared")) disappeared = TRUE; + else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceActivationFailed")) + { + char *dev = NULL; + char *net = NULL; + DBusError error; + + dbus_error_init (&error); + if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &dev, DBUS_TYPE_STRING, &net, DBUS_TYPE_INVALID)) + { + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + dbus_error_init (&error); + dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &dev, DBUS_TYPE_INVALID); + } + if (dbus_error_is_set (&error)) + dbus_error_free (&error); + if (dev && net) + { + char *string = g_strdup_printf ("Connection to the wireless network '%s' failed.\n", net); + nmi_show_warning_dialog (TRUE, string); + g_free (string); + } + else if (dev) + nmi_show_warning_dialog (TRUE, "Connection to the wired network failed.\n"); + + dbus_free (dev); + dbus_free (net); + } +#if 0 else if (dbus_message_is_signal (message, DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS, "ServiceDeleted")) { char *service; @@ -870,56 +899,8 @@ static DBusHandlerResult nmi_dbus_filter (DBusConnection *connection, DBusMessag if (dbus_error_is_set (&error)) dbus_error_free (&error); } - else if (dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceActivationFailed")) - { - char *dev = NULL; - char *net = NULL; - DBusError error; - - dbus_error_init (&error); - if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &dev, DBUS_TYPE_STRING, &net, DBUS_TYPE_INVALID)) - { - if (dbus_error_is_set (&error)) - dbus_error_free (&error); - dbus_error_init (&error); - dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &dev, DBUS_TYPE_INVALID); - } - if (dbus_error_is_set (&error)) - dbus_error_free (&error); - if (dev && net) - { - char *string = g_strdup_printf ("Connection to the wireless network '%s' failed.\n", net); - nmi_show_warning_dialog (TRUE, string); - g_free (string); - } - else if (dev) - nmi_show_warning_dialog (TRUE, "Connection to the wired network failed.\n"); - - dbus_free (dev); - dbus_free (net); - } - - if (appeared || disappeared) - { - dbus_error_init (&error); - if (dbus_message_get_args (message, &error, - DBUS_TYPE_STRING, &dev_path, - DBUS_TYPE_STRING, &ap_path, - DBUS_TYPE_INVALID)) - { -#if 0 - if (appeared) - nmi_new_networks_dialog_add_network (ap_path, info); - else if (disappeared) - nmi_new_networks_dialog_add_network (ap_path, info); #endif - dbus_free (dev_path); - dbus_free (ap_path); - handled = TRUE; - } - } - return (handled ? DBUS_HANDLER_RESULT_HANDLED : DBUS_HANDLER_RESULT_NOT_YET_HANDLED); } @@ -969,8 +950,10 @@ int nmi_dbus_service_init (DBusConnection *dbus_connection, NMIAppInfo *info) exit (0); } +#if 0 if (!nmi_dbus_nm_is_running (dbus_connection)) return (-1); +#endif if (!dbus_connection_register_object_path (dbus_connection, NMI_DBUS_PATH, &nmi_vtable, info)) { diff --git a/panel-applet/NMWirelessApplet.c b/panel-applet/NMWirelessApplet.c index e0a8fbb13..de4115aa2 100644 --- a/panel-applet/NMWirelessApplet.c +++ b/panel-applet/NMWirelessApplet.c @@ -640,14 +640,12 @@ static void nmwa_menu_add_device_item (GtkWidget *menu, NetworkDevice *device, g } -/* FIXME: We really should break this dialog into its own file. This function is too long. - */ -static void -custom_essid_item_selected (GtkWidget *menu_item, NMWirelessApplet *applet) +static void custom_essid_item_selected (GtkWidget *menu_item, NMWirelessApplet *applet) { - nmwa_other_network_dialog_run (applet); + nmwa_other_network_dialog_run (applet, FALSE); } + static void nmwa_menu_add_custom_essid_item (GtkWidget *menu, NMWirelessApplet *applet) { GtkWidget *menu_item; @@ -663,6 +661,26 @@ static void nmwa_menu_add_custom_essid_item (GtkWidget *menu, NMWirelessApplet * } +static void new_network_item_selected (GtkWidget *menu_item, NMWirelessApplet *applet) +{ + nmwa_other_network_dialog_run (applet, TRUE); +} + + +static void nmwa_menu_add_create_network_item (GtkWidget *menu, NMWirelessApplet *applet) +{ + GtkWidget *menu_item; + GtkWidget *label; + + menu_item = gtk_menu_item_new (); + label = gtk_label_new (_("Create new Wireless Network...")); + gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); + gtk_container_add (GTK_CONTAINER (menu_item), label); + gtk_widget_show_all (menu_item); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item); + g_signal_connect (menu_item, "activate", G_CALLBACK (new_network_item_selected), applet); +} + /* * nmwa_menu_device_add_networks * @@ -813,9 +831,10 @@ static void nmwa_menu_add_devices (GtkWidget *menu, NMWirelessApplet *applet) if (n_wireless_interfaces > 0) { - /* Add the 'Select a custom esssid entry */ + /* Add the "Other wireless network..." entry */ nmwa_menu_add_separator_item (menu); nmwa_menu_add_custom_essid_item (menu, applet); + nmwa_menu_add_create_network_item (menu, applet); } g_mutex_unlock (applet->data_mutex); diff --git a/panel-applet/NMWirelessAppletDbus.c b/panel-applet/NMWirelessAppletDbus.c index 17ef55bbf..8e37a7c0e 100644 --- a/panel-applet/NMWirelessAppletDbus.c +++ b/panel-applet/NMWirelessAppletDbus.c @@ -548,6 +548,39 @@ void nmwa_dbus_set_device (DBusConnection *connection, const NetworkDevice *dev, } +/* + * nmwa_dbus_create_network + * + * Tell NetworkManager to create an Ad-Hoc wireless network + * + */ +void nmwa_dbus_create_network (DBusConnection *connection, const NetworkDevice *dev, const WirelessNetwork *network, + NMEncKeyType key_type, const char *passphrase) +{ + DBusMessage *message; + + g_return_if_fail (connection != NULL); + g_return_if_fail (dev != NULL); + g_return_if_fail (dev->type == DEVICE_TYPE_WIRELESS_ETHERNET); + + if ((message = dbus_message_new_method_call (NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, "createWirelessNetwork"))) + { + if (network && network->essid) + { + fprintf (stderr, "Creating network '%s' %s passphrase on device '%s'.\n", network->essid, passphrase ? "with" : "without", dev->nm_device); + dbus_message_append_args (message, DBUS_TYPE_STRING, dev->nm_device, + DBUS_TYPE_STRING, network->essid, + DBUS_TYPE_STRING, (passphrase ? passphrase : ""), + DBUS_TYPE_INT32, key_type, + DBUS_TYPE_INVALID); + } + dbus_connection_send (connection, message, NULL); + } + else + fprintf (stderr, "nm_dbus_set_device(): Couldn't allocate the dbus message\n"); +} + + /* * wireless_network_ref * diff --git a/panel-applet/NMWirelessAppletDbus.h b/panel-applet/NMWirelessAppletDbus.h index 7d970b61a..22f7a7c83 100644 --- a/panel-applet/NMWirelessAppletDbus.h +++ b/panel-applet/NMWirelessAppletDbus.h @@ -42,6 +42,10 @@ void nmwa_dbus_set_device (DBusConnection *connection, const NetworkDevice const WirelessNetwork *network, NMEncKeyType key_type, const char *passphrase); +void nmwa_dbus_create_network (DBusConnection *connection, const NetworkDevice *dev, + const WirelessNetwork *network, NMEncKeyType key_type, + const char *passphrase); + WirelessNetwork * wireless_network_new_with_essid (const char *essid); void wireless_network_unref (WirelessNetwork *net); diff --git a/panel-applet/NMWirelessAppletOtherNetworkDialog.c b/panel-applet/NMWirelessAppletOtherNetworkDialog.c index c7519fdef..c8c3e9910 100644 --- a/panel-applet/NMWirelessAppletOtherNetworkDialog.c +++ b/panel-applet/NMWirelessAppletOtherNetworkDialog.c @@ -193,7 +193,7 @@ void nmwa_other_network_dialog_enc_check_toggled (GtkWidget *enc_check_button, g } -static GtkDialog *nmwa_other_network_dialog_init (GladeXML *xml, NMWirelessApplet *applet, NetworkDevice **def_dev) +static GtkDialog *nmwa_other_network_dialog_init (GladeXML *xml, NMWirelessApplet *applet, NetworkDevice **def_dev, gboolean create_network) { GtkDialog *dialog = NULL; GtkWidget *essid_entry; @@ -220,9 +220,18 @@ static GtkDialog *nmwa_other_network_dialog_init (GladeXML *xml, NMWirelessApple gtk_widget_set_sensitive (button, FALSE); g_signal_connect (essid_entry, "changed", G_CALLBACK (update_button_cb), xml); - label = g_strdup_printf ("%s\n\n%s", + if (create_network) + { + label = g_strdup_printf ("%s\n\n%s", + _("Create new wireless network"), + _("Enter the ESSID and security settings of the wireless network you wish to create.")); + } + else + { + label = g_strdup_printf ("%s\n\n%s", _("Custom wireless network"), _("Enter the ESSID of the wireless network to which you wish to connect.")); + } gtk_label_set_markup (GTK_LABEL (glade_xml_get_widget (xml, "essid_label")), label); /* Do we have multiple Network cards? */ @@ -287,7 +296,7 @@ static GtkDialog *nmwa_other_network_dialog_init (GladeXML *xml, NMWirelessApple } -void nmwa_other_network_dialog_run (NMWirelessApplet *applet) +void nmwa_other_network_dialog_run (NMWirelessApplet *applet, gboolean create_network) { gchar *glade_file; GtkDialog *dialog; @@ -315,7 +324,7 @@ void nmwa_other_network_dialog_run (NMWirelessApplet *applet) return; } - if (!(dialog = nmwa_other_network_dialog_init (xml, applet, &def_dev))) + if (!(dialog = nmwa_other_network_dialog_init (xml, applet, &def_dev, create_network))) return; /* Run the dialog */ @@ -375,7 +384,10 @@ void nmwa_other_network_dialog_run (NMWirelessApplet *applet) } applet->applet_state = APPLET_STATE_WIRELESS_CONNECTING; applet->forcing_device = TRUE; - nmwa_dbus_set_device (applet->connection, def_dev, net, nm_key_type, passphrase); + if (create_network) + nmwa_dbus_create_network (applet->connection, def_dev, net, nm_key_type, passphrase); + else + nmwa_dbus_set_device (applet->connection, def_dev, net, nm_key_type, passphrase); network_device_unref (def_dev); wireless_network_unref (net); } diff --git a/panel-applet/NMWirelessAppletOtherNetworkDialog.h b/panel-applet/NMWirelessAppletOtherNetworkDialog.h index 56fd8878c..7593b6fef 100644 --- a/panel-applet/NMWirelessAppletOtherNetworkDialog.h +++ b/panel-applet/NMWirelessAppletOtherNetworkDialog.h @@ -26,6 +26,6 @@ #ifndef NM_WIRELESS_APPLET_OTHER_NETWORK_DIALOG_H #define NM_WIRELESS_APPLET_OTHER_NETWORK_DIALOG_H -void nmwa_other_network_dialog_run (NMWirelessApplet *applet); +void nmwa_other_network_dialog_run (NMWirelessApplet *applet, gboolean create_network); #endif diff --git a/src/NetworkManager.c b/src/NetworkManager.c index f9e0d621f..f60940eb4 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -727,7 +727,7 @@ int main( int argc, char *argv[] ) policy_source_id = g_source_attach (policy_source, nm_data->main_context); /* Keep a current list of access points */ - wscan_source = g_timeout_source_new (10000); + wscan_source = g_timeout_source_new (15000); g_source_set_callback (wscan_source, nm_wireless_scan_monitor, nm_data, NULL); wscan_source_id = g_source_attach (wscan_source, nm_data->main_context); diff --git a/src/NetworkManagerAP.c b/src/NetworkManagerAP.c index 47cc1f262..b0f0cac8c 100644 --- a/src/NetworkManagerAP.c +++ b/src/NetworkManagerAP.c @@ -41,6 +41,7 @@ struct NMAccessPoint gboolean matched; /* used in ap list diffing */ gboolean trusted; gboolean artificial; /* Whether or not the AP is from a scan */ + gboolean user_created; /* Whether or not the AP was created by the user with "Create network..." */ /* Things from user prefs */ char *enc_key; @@ -104,7 +105,7 @@ NMAccessPoint * nm_ap_new_from_ap (NMAccessPoint *src_ap) memcpy (new_addr, src_ap->address, sizeof (struct ether_addr)); new_ap->address = new_addr; } - new_ap->mode = NETWORK_MODE_INFRA; + new_ap->mode = src_ap->mode; new_ap->strength = src_ap->strength; new_ap->freq = src_ap->freq; new_ap->rate = src_ap->rate; @@ -456,6 +457,28 @@ void nm_ap_set_artificial (NMAccessPoint *ap, gboolean artificial) } +/* + * Get/Set functions to indicate that an access point is + * user-created, ie whether or not its a network filled with + * information from the user and intended to create a new Ad-Hoc + * wireless network. + * + */ +gboolean nm_ap_get_user_created (NMAccessPoint *ap) +{ + g_return_val_if_fail (ap != NULL, FALSE); + + return (ap->user_created); +} + +void nm_ap_set_user_created (NMAccessPoint *ap, gboolean user_created) +{ + g_return_if_fail (ap != NULL); + + ap->user_created = user_created; +} + + /* * Return the encryption method the user specified for this access point. * diff --git a/src/NetworkManagerAP.h b/src/NetworkManagerAP.h index f78595431..d4db447f3 100644 --- a/src/NetworkManagerAP.h +++ b/src/NetworkManagerAP.h @@ -74,6 +74,9 @@ void nm_ap_set_trusted (NMAccessPoint *ap, gboolean trusted); gboolean nm_ap_get_artificial (NMAccessPoint *ap); void nm_ap_set_artificial (NMAccessPoint *ap, gboolean artificial); +gboolean nm_ap_get_user_created (NMAccessPoint *ap); +void nm_ap_set_user_created (NMAccessPoint *ap, gboolean user_created); + const NMEncKeyType nm_ap_get_enc_method (NMAccessPoint *ap); GSList * nm_ap_get_user_addresses (NMAccessPoint *ap); diff --git a/src/NetworkManagerAPList.c b/src/NetworkManagerAPList.c index ec87204b7..1a843d008 100644 --- a/src/NetworkManagerAPList.c +++ b/src/NetworkManagerAPList.c @@ -477,8 +477,8 @@ void nm_ap_list_copy_properties (NMAccessPointList *dest, NMAccessPointList *sou NMAPListIter *iter; NMAccessPoint *dest_ap; - g_return_if_fail (dest != NULL); - g_return_if_fail (source != NULL); + if (!dest || !source) + return; if ((iter = nm_ap_list_iter_new (dest))) { @@ -511,8 +511,8 @@ void nm_ap_list_copy_essids_by_address (NMAccessPointList *dest, NMAccessPointLi NMAPListIter *iter; NMAccessPoint *dest_ap; - g_return_if_fail (dest != NULL); - g_return_if_fail (source != NULL); + if (!dest || !source) + return; if ((iter = nm_ap_list_iter_new (dest))) { diff --git a/src/NetworkManagerDHCP.c b/src/NetworkManagerDHCP.c index 07d0970ab..b5f5a9cab 100644 --- a/src/NetworkManagerDHCP.c +++ b/src/NetworkManagerDHCP.c @@ -79,6 +79,39 @@ static void nm_device_dhcp_configure (NMDevice *dev) } +/* + * nm_device_do_autoip + * + * Get and assign a Link Local Address. + * + */ +gboolean nm_device_do_autoip (NMDevice *dev) +{ + struct in_addr ip; + gboolean success = FALSE; + + g_return_val_if_fail (dev != NULL, FALSE); + + if ((success = get_autoip (dev, &ip))) + { + #define LINKLOCAL_BCAST 0xa9feffff + int temp = ip.s_addr; + + nm_system_device_set_ip4_address (dev, temp); + temp = ntohl (0xFFFF0000); + nm_system_device_set_ip4_netmask (dev, temp); + temp = ntohl (LINKLOCAL_BCAST); + nm_system_device_set_ip4_broadcast (dev, temp); + + /* Set all traffic to go through the device */ + nm_system_flush_loopback_routes (); + nm_system_device_add_default_route_via_device (dev); + } + + return (success); +} + + /* * nm_device_dhcp_request * @@ -89,7 +122,6 @@ int nm_device_dhcp_request (NMDevice *dev) { dhcp_client_options opts; int err; - struct in_addr ip; g_return_val_if_fail (dev != NULL, RET_DHCP_ERROR); @@ -107,32 +139,16 @@ int nm_device_dhcp_request (NMDevice *dev) /* Start off in DHCP INIT state, get a completely new IP address * and settings. */ - err = dhcp_init (dev->dhcp_iface); - switch (err) + if ((err = dhcp_init (dev->dhcp_iface)) == RET_DHCP_BOUND) { - case RET_DHCP_BOUND: - nm_device_dhcp_configure (dev); - nm_device_update_ip4_address (dev); - nm_device_dhcp_setup_timeouts (dev); - break; - - default: - /* DHCP didn't work, so use Link Local addressing */ - dhcp_interface_free (dev->dhcp_iface); - dev->dhcp_iface = NULL; - if (get_autoip (dev, &ip)) - { - #define LINKLOCAL_BCAST 0xa9feffff - int temp = ip.s_addr; - - nm_system_device_set_ip4_address (dev, temp); - temp = ntohl (0xFFFF0000); - nm_system_device_set_ip4_netmask (dev, temp); - temp = ntohl (LINKLOCAL_BCAST); - nm_system_device_set_ip4_broadcast (dev, temp); - err = RET_DHCP_BOUND; - } - break; + nm_device_dhcp_configure (dev); + nm_device_update_ip4_address (dev); + nm_device_dhcp_setup_timeouts (dev); + } + else + { + dhcp_interface_free (dev->dhcp_iface); + dev->dhcp_iface = NULL; } return (err); diff --git a/src/NetworkManagerDHCP.h b/src/NetworkManagerDHCP.h index 57dc7779e..91ebb87db 100644 --- a/src/NetworkManagerDHCP.h +++ b/src/NetworkManagerDHCP.h @@ -29,5 +29,6 @@ void nm_device_dhcp_cease (NMDevice *dev); gboolean nm_device_dhcp_setup_timeouts (NMDevice *dev); gboolean nm_device_dhcp_renew (gpointer user_data); gboolean nm_device_dhcp_rebind (gpointer user_data); +gboolean nm_device_do_autoip (NMDevice *dev); #endif diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c index 65302823e..3042d9c80 100644 --- a/src/NetworkManagerDbus.c +++ b/src/NetworkManagerDbus.c @@ -298,7 +298,9 @@ static DBusMessage *nm_dbus_nm_set_active_device (DBusConnection *connection, DB /* If the user specificed a wireless network too, force that as well */ if (nm_device_is_wireless (dev) && !nm_device_find_and_use_essid (dev, network, key, key_type)) + { nm_dbus_send_network_not_found (data->dbus_connection, network); + } else { if (nm_try_acquire_mutex (data->user_device_mutex, __FUNCTION__)) @@ -326,6 +328,98 @@ out: } +/* + * nm_dbus_nm_create_wireless_network + * + * Create a new wireless network and + * + */ +static DBusMessage *nm_dbus_nm_create_wireless_network (DBusConnection *connection, DBusMessage *message, NMData *data) +{ + NMDevice *dev = NULL; + DBusMessage *reply_message = NULL; + char *dev_path = NULL; + char *network = NULL; + char *key = NULL; + int key_type = -1; + DBusError error; + + g_return_val_if_fail (connection != NULL, NULL); + g_return_val_if_fail (message != NULL, NULL); + g_return_val_if_fail (data != NULL, NULL); + + /* Try to grab both device _and_ network first, and if that fails then just the device. */ + dbus_error_init (&error); + if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &dev_path, + 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", + "NetworkManager::createWirelessNetwork called with invalid arguments."); + return (reply_message); + } else syslog (LOG_INFO, "Creating network '%s' on device '%s'.", network, dev_path); + + dev = nm_dbus_get_device_from_object_path (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", + "The requested network device does not exist."); + return (reply_message); + } + 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", + "NetworkManager::createWirelessNetwork called with invalid arguments."); + goto out; + } + + if (!(reply_message = dbus_message_new_method_return (message))) + goto out; + + /* If the user specificed a wireless network too, force that as well */ + if (nm_try_acquire_mutex (data->user_device_mutex, __FUNCTION__)) + { + NMAccessPoint *ap = nm_ap_new (); + + /* Fill in the description of the network to create */ + nm_ap_set_essid (ap, network); + if (key && strlen (key)) + { + nm_ap_set_encrypted (ap, TRUE); + nm_ap_set_enc_key_source (ap, key, key_type); + } + nm_ap_set_mode (ap, NETWORK_MODE_ADHOC); + nm_ap_set_user_created (ap, TRUE); + + nm_device_set_best_ap (dev, ap); + nm_device_freeze_best_ap (dev); + nm_device_activation_cancel (dev); + + if (data->user_device) + nm_device_unref (data->user_device); + data->user_device = dev; + nm_device_ref (data->user_device); + + nm_unlock_mutex (data->user_device_mutex, __FUNCTION__); + } + + /* Have to mark our state changed since we blew away our connection trying out + * the user-requested network. + */ + nm_data_mark_state_changed (data); + +out: + dbus_free (network); + dbus_free (key); + nm_device_unref (dev); + return (reply_message); +} + + /* * nm_dbus_nm_get_devices * @@ -1467,6 +1561,8 @@ static DBusHandlerResult nm_dbus_nm_message_handler (DBusConnection *connection, 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) diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c index 73df5a189..7e28b9911 100644 --- a/src/NetworkManagerDevice.c +++ b/src/NetworkManagerDevice.c @@ -42,7 +42,7 @@ /* Local static prototypes */ static gboolean mii_get_link (NMDevice *dev); static gpointer nm_device_activation_worker (gpointer user_data); -static gboolean nm_device_activation_configure_ip (NMDevice *dev); +static gboolean nm_device_activation_configure_ip (NMDevice *dev, gboolean do_only_autoip); /******************************************************/ @@ -276,11 +276,10 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev, nm_device_do_wireless_scan (dev); nm_device_update_best_ap (dev); - dev->options.wireless.num_freqs = 14; /* Default, fake something like 802.11b */ if ((sk = iw_sockets_open ()) >= 0) { - if (iw_get_range_info (sk, nm_device_get_iface (dev), &range) >= 0) - dev->options.wireless.num_freqs = range.num_frequency; + if (iw_get_range_info (sk, nm_device_get_iface (dev), &(dev->options.wireless.range_info)) == -1) + memset (&(dev->options.wireless.range_info), 0, sizeof (struct iw_range)); close (sk); } } @@ -387,7 +386,7 @@ int nm_device_get_association_pause_value (NMDevice *dev) * 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). */ - if (dev->options.wireless.num_freqs > 14) + if (dev->options.wireless.range_info.num_frequency > 14) return 10; else return 5; @@ -714,6 +713,150 @@ void nm_device_set_essid (NMDevice *dev, const char *essid) } +/* + * nm_device_get_frequency + * + * For wireless devices, get the frequency we broadcast/receive on. + * + */ +double nm_device_get_frequency (NMDevice *dev) +{ + int 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); + + /* Test devices don't really have a frequency, they always succeed */ + if (dev->test_device) + return 703000000; + + sk = iw_sockets_open (); + if (sk >= 0) + { + struct iwreq wrq; + + err = iw_set_ext (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); + } + return (freq); +} + + +/* + * nm_device_set_frequency + * + * For wireless devices, set the frequency to broadcast/receive on. + * + */ +void nm_device_set_frequency (NMDevice *dev, const double freq) +{ + int sk; + int err; + + g_return_if_fail (dev != NULL); + g_return_if_fail (nm_device_is_wireless (dev)); + + /* Test devices don't really have a frequency, they always succeed */ + if (dev->test_device) + return; + + sk = iw_sockets_open (); + if (sk >= 0) + { + struct iwreq wrq; + + 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); + if (err == -1) + syslog (LOG_ERR, "nm_device_set_frequency(): error setting frequency %f for device %s. errno = %d", freq, nm_device_get_iface (dev), errno); + + close (sk); + } +} + + +/* + * nm_device_get_bitrate + * + * For wireless devices, get the bitrate to broadcast/receive at. + * Returned value is rate in KHz. + * + */ +int nm_device_get_bitrate (NMDevice *dev) +{ + int 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); + + /* Test devices don't really have a frequency, they always succeed */ + if (dev->test_device) + return 11; + + sk = iw_sockets_open (); + if (sk >= 0) + { + err = iw_set_ext (sk, nm_device_get_iface (dev), SIOCGIWRATE, &wrq); + close (sk); + } + + return ((err >= 0) ? wrq.u.bitrate.value / 1000 : 0); +} + + +/* + * nm_device_set_bitrate + * + * For wireless devices, set the bitrate to broadcast/receive at. + * Rate argument should be in KHz, or 0 for automatic. + * + */ +void nm_device_set_bitrate (NMDevice *dev, const int KHz) +{ + int sk; + int err; + + g_return_if_fail (dev != NULL); + g_return_if_fail (nm_device_is_wireless (dev)); + + /* Test devices don't really have a frequency, they always succeed */ + if (dev->test_device) + return; + + sk = iw_sockets_open (); + if (sk >= 0) + { + struct iwreq wrq; + + if (KHz != 0) + { + wrq.u.bitrate.value = KHz * 1000; + wrq.u.bitrate.fixed = 1; + } + else + { + wrq.u.bitrate.value = -1; + wrq.u.bitrate.fixed = 0; + } + err = iw_set_ext (sk, nm_device_get_iface (dev), SIOCSIWRATE, &wrq); + if (err == -1) + syslog (LOG_ERR, "nm_device_set_bitrate(): error setting bitrate %d KHz for device %s. errno = %d", KHz, nm_device_get_iface (dev), errno); + + close (sk); + } +} + + /* * nm_device_get_ap_address * @@ -1187,6 +1330,51 @@ gboolean nm_device_is_up (NMDevice *dev) } +/* + * nm_device_get_mode + * + * Get managed/infrastructure/adhoc mode on a device (currently wireless only) + * + */ +NMNetworkMode nm_device_get_mode (NMDevice *dev) +{ + int 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) + { + struct iwreq wrq; + int err; + + err = iw_set_ext (sk, nm_device_get_iface (dev), SIOCGIWMODE, &wrq); + if (err == 0) + { + switch (wrq.u.mode) + { + case IW_MODE_INFRA: + mode = NETWORK_MODE_INFRA; + break; + case IW_MODE_ADHOC: + mode = NETWORK_MODE_ADHOC; + break; + default: + break; + } + } + 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); + } + + return (mode); +} + + /* * nm_device_set_mode * @@ -1230,7 +1418,7 @@ gboolean nm_device_set_mode (NMDevice *dev, const NMNetworkMode mode) if (err == 0) success = TRUE; else - syslog (LOG_ERR, "nm_device_set_mode_managed (%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 Infrastructure mode. errno = %d", nm_device_get_iface (dev), errno); } close (sk); } @@ -1362,6 +1550,11 @@ static gboolean nm_device_set_wireless_config (NMDevice *dev, NMAccessPoint *ap, */ essid = nm_ap_get_essid (ap); nm_device_set_mode (dev, nm_ap_get_mode (ap)); + nm_device_set_bitrate (dev, 0); + if (nm_ap_get_user_created (ap) || (nm_ap_get_freq (ap) && (nm_ap_get_mode (ap) == NETWORK_MODE_ADHOC))) + { + nm_device_set_frequency (dev, nm_ap_get_freq (ap)); + } nm_device_set_enc_key (dev, NULL, NM_DEVICE_AUTH_METHOD_NONE); if (nm_ap_get_encrypted (ap) && nm_ap_get_enc_key_source (ap)) { @@ -1383,6 +1576,13 @@ static gboolean nm_device_set_wireless_config (NMDevice *dev, NMAccessPoint *ap, */ g_usleep (G_USEC_PER_SEC * nm_device_get_association_pause_value (dev)); + /* 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 + * from scanned access points out of iwlib, clamp bitrate for these cards at 11Mbps. + */ + if ((nm_ap_get_mode (ap) == NETWORK_MODE_ADHOC) && (nm_device_get_bitrate (dev) <= 0)) + nm_device_set_bitrate (dev, 11000); /* In Kbps */ + nm_device_update_link_active (dev, FALSE); success = TRUE; @@ -1390,7 +1590,89 @@ static gboolean nm_device_set_wireless_config (NMDevice *dev, NMAccessPoint *ap, } -gboolean AP_NEED_KEY (NMAccessPoint *ap) +/* + * nm_device_activate_wireless_adhoc + * + * Create an ad-hoc network (rather than associating with one). + * + */ +static gboolean nm_device_activate_wireless_adhoc (NMDevice *dev, NMAccessPoint *ap) +{ + gboolean success = FALSE; + NMDeviceAuthMethod auth = NM_DEVICE_AUTH_METHOD_NONE; + NMAPListIter *iter; + NMAccessPoint *tmp_ap; + double card_freqs[IW_MAX_FREQUENCIES]; + int num_freqs = 0, i; + double freq_to_use = 0; + + g_return_val_if_fail (dev != NULL, FALSE); + g_return_val_if_fail (ap != NULL, FALSE); + + if (nm_ap_get_encrypted (ap)) + auth = NM_DEVICE_AUTH_METHOD_SHARED_KEY; + + /* Build our local list of frequencies to whittle down until we find a free one */ + memset (&card_freqs, 0, sizeof (card_freqs)); + num_freqs = MIN (dev->options.wireless.range_info.num_frequency, IW_MAX_FREQUENCIES); + for (i = 0; i < num_freqs; i++) + card_freqs[i] = iw_freq2float (&(dev->options.wireless.range_info.freq[i])); + + /* We need to find a clear wireless channel to use. We will + * only use 802.11b channels for now. + */ + iter = nm_ap_list_iter_new (nm_device_ap_list_get (dev)); + while ((tmp_ap = nm_ap_list_iter_next (iter))) + { + double ap_freq = nm_ap_get_freq (tmp_ap); + for (i = 0; i < num_freqs && ap_freq; i++) + { + if (card_freqs[i] == ap_freq) + card_freqs[i] = 0; + } + } + nm_ap_list_iter_free (iter); + + /* 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 + * space so that most everyone can see it. + */ + for (i = 0; i < num_freqs; i++) + { + int channel = iw_freq_to_channel (card_freqs[i], &(dev->options.wireless.range_info)); + if (card_freqs[i] && (channel > 0) && (channel < 15)) + { + freq_to_use = card_freqs[i]; + break; + } + } + + /* Hmm, no free channels in 802.11b space. Pick one more or less randomly */ + if (!freq_to_use) + { + double pfreq; + int channel = (int)(random () % 14); + int err; + + err = iw_channel_to_freq (channel, &pfreq, &(dev->options.wireless.range_info)); + if (err == channel) + freq_to_use = pfreq; + } + + if (freq_to_use) + { + nm_ap_set_freq (ap, freq_to_use); + + syslog (LOG_INFO, "Will create network '%s' with frequency %f.\n", nm_ap_get_essid (ap), nm_ap_get_freq (ap)); + if ((success = nm_device_set_wireless_config (dev, ap, auth))) + success = nm_device_activation_configure_ip (dev, TRUE); + } + + return (success); +} + + +static gboolean AP_NEED_KEY (NMAccessPoint *ap) { char *s; int len = 0; @@ -1407,7 +1689,7 @@ gboolean AP_NEED_KEY (NMAccessPoint *ap) return (FALSE); } -gboolean HAVE_LINK (NMDevice *dev) +static gboolean HAVE_LINK (NMDevice *dev) { g_return_val_if_fail (dev != NULL, FALSE); g_return_val_if_fail (nm_device_is_wireless (dev), FALSE); @@ -1462,7 +1744,7 @@ get_ap: /* If its unencrypted and we don't have a link, we can't use this AP. * If we can't get an IP address off this AP, we can't use it either. */ - if (!HAVE_LINK (dev) || !nm_device_activation_configure_ip (dev)) + if (!HAVE_LINK (dev) || !nm_device_activation_configure_ip (dev, FALSE)) { syslog (LOG_DEBUG, "nm_device_activate_wireless(%s): no link to '%s', or couldn't get configure interface for IP. Trying another access point.", nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); @@ -1524,42 +1806,56 @@ get_ap: goto out; nm_device_set_wireless_config (dev, best_ap, auth); - if (!HAVE_LINK (dev) && (auth == NM_DEVICE_AUTH_METHOD_SHARED_KEY)) + + /* Link checking and all this fallback doesn't really make sense in ad-hoc mode, + * so only do it for infrastructure mode. + */ + if (nm_ap_get_mode (best_ap) == NETWORK_MODE_ADHOC) { - syslog (LOG_DEBUG, "nm_device_activate_wireless(%s): no hardware link to '%s' in Shared Key mode, trying Open System.", - nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); - /* Back down to Open System mode */ - auth--; - continue; + /* Only do auto-ip on Ad-Hoc connections for now. We technically + * could do DHCP on them though. + */ + success = nm_device_activation_configure_ip (dev, TRUE); } - else if (!HAVE_LINK (dev)) + else if (nm_ap_get_mode (best_ap) == NETWORK_MODE_INFRA) { - /* Must be in Open System mode and it still didn't work, so - * we'll invalidate the current "best" ap and get another one */ - syslog (LOG_DEBUG, "nm_device_activate_wireless(%s): no hardware link to '%s' in Open System mode, trying another access point.", - nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); - nm_ap_set_invalid (best_ap, TRUE); - nm_ap_list_append_ap (dev->app_data->invalid_ap_list, best_ap); - nm_ap_unref (best_ap); - nm_device_update_best_ap (dev); - goto get_ap; - } - ip_success = nm_device_activation_configure_ip (dev); - if (!ip_success && (auth == NM_DEVICE_AUTH_METHOD_SHARED_KEY)) - { - /* Back down to Open System mode */ - syslog (LOG_DEBUG, "nm_device_activate_wireless(%s): could not get IP configuration info for '%s' in Shared Key mode, trying Open System.", - nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); - auth--; - continue; - } - else if (!ip_success) - { - /* Open System mode failed, we must have bad WEP key */ - syslog (LOG_DEBUG, "nm_device_activate_wireless(%s): could not get IP configuration info for '%s' in Open System mode, asking for new key.", - nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); - need_key = TRUE; - goto need_key; + if (!HAVE_LINK (dev) && (auth == NM_DEVICE_AUTH_METHOD_SHARED_KEY)) + { + syslog (LOG_DEBUG, "nm_device_activate_wireless(%s): no hardware link to '%s' in Shared Key mode, trying Open System.", + nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); + /* Back down to Open System mode */ + auth--; + continue; + } + else if (!HAVE_LINK (dev)) + { + /* Must be in Open System mode and it still didn't work, so + * we'll invalidate the current "best" ap and get another one */ + syslog (LOG_DEBUG, "nm_device_activate_wireless(%s): no hardware link to '%s' in Open System mode, trying another access point.", + nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); + nm_ap_set_invalid (best_ap, TRUE); + nm_ap_list_append_ap (dev->app_data->invalid_ap_list, best_ap); + nm_ap_unref (best_ap); + nm_device_update_best_ap (dev); + goto get_ap; + } + ip_success = nm_device_activation_configure_ip (dev, FALSE); + if (!ip_success && (auth == NM_DEVICE_AUTH_METHOD_SHARED_KEY)) + { + /* Back down to Open System mode */ + syslog (LOG_DEBUG, "nm_device_activate_wireless(%s): could not get IP configuration info for '%s' in Shared Key mode, trying Open System.", + nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); + auth--; + continue; + } + else if (!ip_success) + { + /* Open System mode failed, we must have bad WEP key */ + syslog (LOG_DEBUG, "nm_device_activate_wireless(%s): could not get IP configuration info for '%s' in Open System mode, asking for new key.", + nm_device_get_iface (dev), nm_ap_get_essid (best_ap) ? nm_ap_get_essid (best_ap) : "(none)"); + need_key = TRUE; + goto need_key; + } } /* OK, we have a link and we have IP address info, we're good */ @@ -1588,14 +1884,18 @@ out: * or manually setting up the IP address, gateway, and default route. * */ -static gboolean nm_device_activation_configure_ip (NMDevice *dev) +static gboolean nm_device_activation_configure_ip (NMDevice *dev, gboolean do_only_autoip) { gboolean success = FALSE; g_return_val_if_fail (dev != NULL, FALSE); nm_system_delete_default_route (); - if (nm_device_config_get_use_dhcp (dev)) + if (do_only_autoip) + { + success = nm_device_do_autoip (dev); + } + else if (nm_device_config_get_use_dhcp (dev)) { int err; @@ -1624,7 +1924,10 @@ static gboolean nm_device_activation_configure_ip (NMDevice *dev) } if (success) + { + nm_system_flush_arp_cache (); nm_system_restart_mdns_responder (); + } return (success); } @@ -1653,9 +1956,27 @@ static gpointer nm_device_activation_worker (gpointer user_data) nm_device_bring_up (dev); if (nm_device_is_wireless (dev)) - success = nm_device_activate_wireless (dev); + { + gboolean create_network = FALSE; + NMAccessPoint *best_ap = nm_device_get_best_ap (dev); + + if (best_ap) + { + if (nm_ap_get_user_created (best_ap)) + { + create_network = TRUE; + syslog (LOG_INFO, "Creating wireless network '%s'.\n", nm_ap_get_essid (best_ap)); + success = nm_device_activate_wireless_adhoc (dev, best_ap); + syslog (LOG_INFO, "Wireless network creation for '%s' was %s.\n", nm_ap_get_essid (best_ap), success ? "successful" : "unsuccessful"); + } + nm_ap_unref (best_ap); + } + + if (!create_network) + success = nm_device_activate_wireless (dev); + } else if (nm_device_is_wired (dev)) - success = nm_device_activation_configure_ip (dev); + success = nm_device_activation_configure_ip (dev, FALSE); syslog (LOG_DEBUG, "Activation (%s) IP configuration/DHCP returned = %d\n", nm_device_get_iface (dev), success); /* If we were told to quit activation, stop the thread and return */ @@ -1813,6 +2134,7 @@ void nm_device_activation_cancel (NMDevice *dev) */ while (nm_device_is_activating (dev)) g_usleep (G_USEC_PER_SEC / 2); + syslog (LOG_DEBUG, "nm_device_activation_cancel(%s): cancelled.", nm_device_get_iface (dev)); } } @@ -1849,6 +2171,7 @@ gboolean nm_device_deactivate (NMDevice *dev, gboolean just_added) { nm_device_set_essid (dev, ""); nm_device_set_enc_key (dev, NULL, NM_DEVICE_AUTH_METHOD_NONE); + nm_device_set_mode (dev, NETWORK_MODE_INFRA); } return (TRUE); @@ -2201,8 +2524,13 @@ void nm_device_update_best_ap (NMDevice *dev) if (best_ap) { char *essid = nm_ap_get_essid (best_ap); - if ( !nm_ap_list_get_ap_by_essid (dev->app_data->invalid_ap_list, essid) - && nm_device_ap_list_get_ap_by_essid (dev, essid)) + /* Two reasons to keep the current best_ap: + * 1) Its still valid and we see it in our scan data + * 2) Its an ad-hoc network that we've created (and therefore its not in our scan data) + */ + if ( ( !nm_ap_list_get_ap_by_essid (dev->app_data->invalid_ap_list, essid) + && nm_device_ap_list_get_ap_by_essid (dev, essid)) + || nm_ap_get_user_created (best_ap)) { nm_ap_unref (best_ap); g_mutex_unlock (dev->options.wireless.best_ap_mutex); @@ -2281,6 +2609,7 @@ gboolean nm_device_wireless_network_exists (NMDevice *dev, const char *network, NMAccessPoint *ap = NULL; NMDeviceAuthMethod auths[3] = { NM_DEVICE_AUTH_METHOD_SHARED_KEY, NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM, NM_DEVICE_AUTH_METHOD_NONE }; int i; + NMNetworkMode mode = NETWORK_MODE_INFRA; g_return_val_if_fail (dev != NULL, FALSE); g_return_val_if_fail (network != NULL, FALSE); @@ -2295,74 +2624,95 @@ gboolean nm_device_wireless_network_exists (NMDevice *dev, const char *network, nm_device_bring_up (dev); g_usleep (G_USEC_PER_SEC * 4); - /* Force the card into Managed/Infrastructure mode */ - nm_device_set_mode (dev, NETWORK_MODE_INFRA); - - if ((ap = nm_ap_list_get_ap_by_essid (nm_device_ap_list_get (dev), network)) && !nm_ap_get_encrypted (ap)) + if ((ap = nm_ap_list_get_ap_by_essid (nm_device_ap_list_get (dev), network))) { - auths[0] = NM_DEVICE_AUTH_METHOD_NONE; - auths[1] = NM_DEVICE_AUTH_METHOD_SHARED_KEY; - auths[2] = NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM; + mode = nm_ap_get_mode (ap); + + /* If the access point we're looking for is in our list and we know its + * not encrypted, short-cut our connection fallbacks here and don't even + * try enabling encryption to see if we can connect. + */ + if (!nm_ap_get_encrypted (ap)) + { + auths[0] = NM_DEVICE_AUTH_METHOD_NONE; + auths[1] = NM_DEVICE_AUTH_METHOD_SHARED_KEY; + auths[2] = NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM; + } } - /* Loop through the auth modes */ - for (i = 0; i < 3; i++) + /* Two cases here. Ad-Hoc networks don't have an access point that authenticates or + * that you associate with, we just have to see if we know about the network and then + * set up the card. So if we know about it, we can use it. I guess if you don't have + * the right WEP key, you're kind of screwed. + */ + if (mode == NETWORK_MODE_ADHOC) { - switch (auths[i]) - { - case NM_DEVICE_AUTH_METHOD_SHARED_KEY: - case NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM: - { - temp_enc = TRUE; - if ((key_type != NM_ENC_TYPE_UNKNOWN) && key) - { - char *hashed_key = NULL; - switch (key_type) - { - case (NM_ENC_TYPE_128_BIT_PASSPHRASE): - hashed_key = nm_wireless_128bit_key_from_passphrase (key); - break; - case (NM_ENC_TYPE_ASCII_KEY): - if (strlen (key) <= 5) - hashed_key = nm_wireless_64bit_ascii_to_hex (key); - else - hashed_key = nm_wireless_128bit_ascii_to_hex (key); - break; - case (NM_ENC_TYPE_HEX_KEY): - case (NM_ENC_TYPE_UNKNOWN): - hashed_key = g_strdup (key); - break; - default: - break; - } - nm_device_set_enc_key (dev, hashed_key, auths[i]); - g_free (hashed_key); - } - else - nm_device_set_enc_key (dev, "11111111111111111111111111", auths[i]); - break; - } - case NM_DEVICE_AUTH_METHOD_NONE: - default: - temp_enc = FALSE; - nm_device_set_enc_key (dev, NULL, auths[i]); - break; - } - - /* 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_set_essid (dev, network); - g_usleep (G_USEC_PER_SEC * nm_device_get_association_pause_value (dev)); - - nm_device_update_link_active (dev, FALSE); - nm_device_get_ap_address (dev, &addr); - if (nm_ethernet_address_is_valid (&addr) && nm_device_get_essid (dev)) - { - nm_device_get_ap_address (dev, ap_addr); + if (ap) success = TRUE; - *encrypted = temp_enc; + } + else if (mode == NETWORK_MODE_INFRA) + { + nm_device_set_mode (dev, mode); + + /* Loop through the auth modes */ + for (i = 0; i < 3; i++) + { + switch (auths[i]) + { + case NM_DEVICE_AUTH_METHOD_SHARED_KEY: + case NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM: + { + temp_enc = TRUE; + if ((key_type != NM_ENC_TYPE_UNKNOWN) && key) + { + char *hashed_key = NULL; + switch (key_type) + { + case (NM_ENC_TYPE_128_BIT_PASSPHRASE): + hashed_key = nm_wireless_128bit_key_from_passphrase (key); + break; + case (NM_ENC_TYPE_ASCII_KEY): + if (strlen (key) <= 5) + hashed_key = nm_wireless_64bit_ascii_to_hex (key); + else + hashed_key = nm_wireless_128bit_ascii_to_hex (key); + break; + case (NM_ENC_TYPE_HEX_KEY): + case (NM_ENC_TYPE_UNKNOWN): + hashed_key = g_strdup (key); + break; + default: + break; + } + nm_device_set_enc_key (dev, hashed_key, auths[i]); + g_free (hashed_key); + } + else + nm_device_set_enc_key (dev, "11111111111111111111111111", auths[i]); + break; + } + case NM_DEVICE_AUTH_METHOD_NONE: + default: + temp_enc = FALSE; + nm_device_set_enc_key (dev, NULL, auths[i]); + break; + } + + /* 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_set_essid (dev, network); + g_usleep (G_USEC_PER_SEC * nm_device_get_association_pause_value (dev)); + + nm_device_update_link_active (dev, FALSE); + nm_device_get_ap_address (dev, &addr); + if (nm_ethernet_address_is_valid (&addr) && nm_device_get_essid (dev)) + { + nm_device_get_ap_address (dev, ap_addr); + success = TRUE; + *encrypted = temp_enc; + } } } @@ -2467,8 +2817,8 @@ gboolean nm_device_find_and_use_essid (NMDevice *dev, const char *essid, const c */ static void nm_device_do_normal_scan (NMDevice *dev) { - int iwlib_socket; - NMData *data; + int iwlib_socket; + NMData *data; g_return_if_fail (dev != NULL); g_return_if_fail (dev->app_data != NULL); @@ -2495,6 +2845,14 @@ static void nm_device_do_normal_scan (NMDevice *dev) gboolean have_blank_essids = FALSE; NMAPListIter *iter; NMAccessPoint *artificial_ap; + NMNetworkMode orig_mode = NETWORK_MODE_INFRA; + double orig_freq; + int orig_rate; + + orig_mode = nm_device_get_mode (dev); + orig_freq = nm_device_get_frequency (dev); + orig_rate = nm_device_get_bitrate (dev); + nm_device_set_mode (dev, NETWORK_MODE_INFRA); err = iw_scan (iwlib_socket, (char *)nm_device_get_iface (dev), WIRELESS_EXT, &scan_results); if ((err == -1) && (errno == ENODATA)) @@ -2508,10 +2866,16 @@ static void nm_device_do_normal_scan (NMDevice *dev) err = iw_scan (iwlib_socket, (char *)nm_device_get_iface (dev), WIRELESS_EXT, &scan_results); if (err == -1) { + nm_device_set_mode (dev, orig_mode); + nm_device_set_frequency (dev, orig_freq); + nm_device_set_bitrate (dev, orig_rate); close (iwlib_socket); return; } } + nm_device_set_mode (dev, orig_mode); + nm_device_set_frequency (dev, orig_freq); + nm_device_set_bitrate (dev, orig_rate); /* New list for current scan data */ new_scan_list = nm_ap_list_new (NETWORK_TYPE_DEVICE); @@ -2810,6 +3174,9 @@ static void nm_device_fake_ap_list (NMDevice *dev) */ void nm_device_do_wireless_scan (NMDevice *dev) { + NMAccessPoint *best_ap = NULL; + gboolean do_scan = TRUE; + g_return_if_fail (dev != NULL); g_return_if_fail (dev->app_data != NULL); g_return_if_fail (nm_device_is_wireless (dev)); @@ -2825,23 +3192,31 @@ void nm_device_do_wireless_scan (NMDevice *dev) return; } - if (nm_device_get_supports_wireless_scan (dev)) - nm_device_do_normal_scan (dev); - else + if ((best_ap = nm_device_get_best_ap (dev))) { - struct ether_addr ap_addr; - - /* We can't pseudo-scan without switching APs, therefore - * if the card has a valid access point and its an allowed - * access point, don't pseudo-scan for others. - */ - nm_device_get_ap_address (dev, &ap_addr); - if ( !nm_ethernet_address_is_valid (&ap_addr) - || !nm_ap_list_get_ap_by_essid (dev->app_data->allowed_ap_list, nm_device_get_essid (dev)) - || !nm_device_get_best_ap (dev)) + /* Don't pseudo-scan when we already have a connection. */ + if (!nm_device_get_supports_wireless_scan (dev)) { + struct ether_addr ap_addr; + + /* We can't pseudo-scan without switching APs, therefore + * if the card has a valid access point and its an allowed + * access point, don't pseudo-scan for others. + */ + nm_device_get_ap_address (dev, &ap_addr); + if ( nm_ethernet_address_is_valid (&ap_addr) + && nm_ap_list_get_ap_by_essid (dev->app_data->allowed_ap_list, nm_device_get_essid (dev))) + do_scan = FALSE; + } + nm_ap_unref (best_ap); + } + + if (do_scan) + { + if (nm_device_get_supports_wireless_scan (dev)) + nm_device_do_normal_scan (dev); + else nm_device_do_pseudo_scan (dev); - } } nm_unlock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__); diff --git a/src/NetworkManagerDevicePrivate.h b/src/NetworkManagerDevicePrivate.h index c7288b88b..793677346 100644 --- a/src/NetworkManagerDevicePrivate.h +++ b/src/NetworkManagerDevicePrivate.h @@ -42,7 +42,7 @@ typedef struct NMDeviceWirelessOptions guint8 noise; gint8 strength; gint8 invalid_strength_counter; - gint8 num_freqs; + struct iw_range range_info; GMutex *scan_mutex; /* We keep a couple lists around since wireless cards diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index aa473cdb9..34525328b 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -293,12 +293,12 @@ gboolean nm_state_modification_monitor (gpointer user_data) { if (nm_device_is_wireless (best_dev) && !nm_device_is_activating (best_dev) && nm_device_need_ap_switch (best_dev)) { - syslog (LOG_INFO, " SWITCH: need to associate with new access point"); + syslog (LOG_INFO, " SWITCH: need to associate with new access point or create a wireless network."); do_switch = TRUE; } else if (!nm_device_is_activating (best_dev) && !nm_device_get_ip4_address (best_dev)) { - syslog (LOG_INFO, " SWITCH: need to get an IP address"); + syslog (LOG_INFO, " SWITCH: need to get an IP address."); do_switch = TRUE; } } diff --git a/src/NetworkManagerSystem.c b/src/NetworkManagerSystem.c index 5c94363ef..0e5a857ee 100644 --- a/src/NetworkManagerSystem.c +++ b/src/NetworkManagerSystem.c @@ -180,9 +180,9 @@ 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 (sk, SIOCADDRT, &rtent) == -1) { - if ( errno == ENETUNREACH ) /* possibly gateway is over the bridge */ + if (errno == ENETUNREACH) /* possibly gateway is over the bridge */ { /* try adding a route to gateway first */ struct rtentry rtent2; diff --git a/src/NetworkManagerSystem.h b/src/NetworkManagerSystem.h index 836139b28..c99748083 100644 --- a/src/NetworkManagerSystem.h +++ b/src/NetworkManagerSystem.h @@ -35,11 +35,14 @@ gboolean nm_system_device_run_dhcp (NMDevice *dev); void nm_system_device_stop_dhcp (NMDevice *dev); gboolean nm_system_device_has_active_routes (NMDevice *dev); void nm_system_device_flush_routes (NMDevice *dev); +void nm_system_device_add_default_route_via_device(NMDevice *dev); void nm_system_device_flush_addresses (NMDevice *dev); void nm_system_device_update_config_info (NMDevice *dev); gboolean nm_system_device_setup_static_ip4_config (NMDevice *dev); void nm_system_enable_loopback (void); +void nm_system_flush_loopback_routes (void); void nm_system_delete_default_route (void); +void nm_system_flush_arp_cache (void); void nm_system_kill_all_dhcp_daemons (void); void nm_system_update_dns (void); void nm_system_load_device_modules (void); diff --git a/src/autoip.c b/src/autoip.c index 983d99dd5..86e4ba43a 100644 --- a/src/autoip.c +++ b/src/autoip.c @@ -59,7 +59,14 @@ static struct ether_addr broadcast_addr = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}} */ static void pick(struct in_addr *ip) { - ip->s_addr = htonl (LINKLOCAL_ADDR | ((abs(random()) % 0xFD00) + 0x0100)); + ip->s_addr = htonl (LINKLOCAL_ADDR | ((abs(random()) % 0xFD00) + (abs(random()) % 0x0100))); + + /* Make sure we don't use 0xFF or 0x00 anywhere */ + while (((ip->s_addr & 0x0000FF00) == 0xFF00) || ((ip->s_addr & 0x0000FF00) == 0x0000)) + ip->s_addr = (ip->s_addr & 0xFFFF00FF) + (abs(random()) && 0xFFFF); + + while (((ip->s_addr & 0x000000FF) == 0xFF) || ((ip->s_addr & 0x000000FF) == 0x00)) + ip->s_addr = (ip->s_addr & 0xFFFFFF00) + (abs(random()) && 0xFF); } /** @@ -275,8 +282,15 @@ gboolean get_autoip (NMDevice *dev, struct in_addr *out_ip) #ifdef ARP_DEBUG syslog (LOG_ERR, "autoip: (%s) recv arp type=%d, op=%d, ", nm_device_get_iface (dev), ntohs(p.ethhdr.ether_type), ntohs(p.operation)); - syslog (LOG_ERR, "source=%s %s,", (char *)(p.sHaddr), p.sInaddr); - syslog (LOG_ERR, "target=%s %s\n", (char *)(p.tHaddr), p.tInaddr); + { + struct in_addr a; + memcpy (&(a.s_addr), &(p.sInaddr), sizeof (a.s_addr)); + syslog (LOG_ERR, " source = %s %02X:%02X:%02X:%02X:%02X:%02X, ", inet_ntoa (a), + p.sHaddr[0], p.sHaddr[1], p.sHaddr[2], p.sHaddr[3], p.sHaddr[4], p.sHaddr[5]); + memcpy (&(a.s_addr), &(p.tInaddr), sizeof (a.s_addr)); + syslog (LOG_ERR, " target = %s %02X:%02X:%02X:%02X:%02X:%02X\n", inet_ntoa (a), + p.tHaddr[0], p.tHaddr[1], p.tHaddr[2], p.tHaddr[3], p.tHaddr[4], p.tHaddr[5]); + } #endif if ( (ntohs (p.ethhdr.ether_type) == ETHERTYPE_ARP) diff --git a/src/backends/NetworkManagerDebian.c b/src/backends/NetworkManagerDebian.c index 4524b1bf3..d7911929d 100644 --- a/src/backends/NetworkManagerDebian.c +++ b/src/backends/NetworkManagerDebian.c @@ -453,3 +453,37 @@ void nm_system_load_device_modules (void) void nm_system_restart_mdns_responder (void) { } + +/* + * nm_system_device_add_default_route_via_device + * + * Flush all routes associated with a network device + * + */ +void nm_system_device_add_default_route_via_device (NMDevice *dev) +{ +} + + +/* + * nm_system_flush_loopback_routes + * + * Flush all routes associated with the loopback device, because it + * sometimes gets the first route for ZeroConf/Link-Local traffic. + * + */ +void nm_system_flush_loopback_routes (void) +{ +} + + +/* + * nm_system_flush_arp_cache + * + * Flush all entries in the arp cache. + * + */ +void nm_system_flush_arp_cache (void) +{ +} + diff --git a/src/backends/NetworkManagerGentoo.c b/src/backends/NetworkManagerGentoo.c index d0cf2ab55..1532c39a1 100644 --- a/src/backends/NetworkManagerGentoo.c +++ b/src/backends/NetworkManagerGentoo.c @@ -421,3 +421,37 @@ void nm_system_device_update_config_info (NMDevice *dev) nm_device_config_set_ip4_broadcast (dev, ip4_broadcast); } } + +/* + * nm_system_device_add_default_route_via_device + * + * Flush all routes associated with a network device + * + */ +void nm_system_device_add_default_route_via_device (NMDevice *dev) +{ +} + + +/* + * nm_system_flush_loopback_routes + * + * Flush all routes associated with the loopback device, because it + * sometimes gets the first route for ZeroConf/Link-Local traffic. + * + */ +void nm_system_flush_loopback_routes (void) +{ +} + + +/* + * nm_system_flush_arp_cache + * + * Flush all entries in the arp cache. + * + */ +void nm_system_flush_arp_cache (void) +{ +} + diff --git a/src/backends/NetworkManagerRedHat.c b/src/backends/NetworkManagerRedHat.c index 941469b4e..8c0a3421a 100644 --- a/src/backends/NetworkManagerRedHat.c +++ b/src/backends/NetworkManagerRedHat.c @@ -138,6 +138,29 @@ void nm_system_device_flush_routes (NMDevice *dev) } +/* + * nm_system_device_add_default_route_via_device + * + * Flush all routes associated with a network device + * + */ +void nm_system_device_add_default_route_via_device (NMDevice *dev) +{ + char *buf; + + g_return_if_fail (dev != NULL); + + /* Not really applicable for test devices */ + if (nm_device_is_test_device (dev)) + return; + + /* Remove routing table entries */ + buf = g_strdup_printf ("/sbin/ip route add default dev %s", nm_device_get_iface (dev)); + nm_spawn_process (buf); + g_free (buf); +} + + /* * nm_system_device_has_active_routes * @@ -277,6 +300,20 @@ void nm_system_enable_loopback (void) } +/* + * nm_system_flush_loopback_routes + * + * Flush all routes associated with the loopback device, because it + * sometimes gets the first route for ZeroConf/Link-Local traffic. + * + */ +void nm_system_flush_loopback_routes (void) +{ + /* Remove routing table entries for lo */ + nm_spawn_process ("/sbin/ip route flush dev lo"); +} + + /* * nm_system_delete_default_route * @@ -289,6 +326,18 @@ void nm_system_delete_default_route (void) } +/* + * nm_system_flush_arp_cache + * + * Flush all entries in the arp cache. + * + */ +void nm_system_flush_arp_cache (void) +{ + nm_spawn_process ("/sbin/ip neigh flush all"); +} + + /* * nm_system_kill_all_dhcp_daemons * @@ -310,8 +359,12 @@ void nm_system_kill_all_dhcp_daemons (void) */ void nm_system_update_dns (void) { +#if 0 +/* This doesn't acutally seem to work very well... */ if(nm_spawn_process ("/etc/init.d/nscd status")) nm_spawn_process ("nscd -i hosts"); +#endif + nm_spawn_process ("/usr/bin/killall -q nscd"); } diff --git a/src/backends/NetworkManagerSlackware.c b/src/backends/NetworkManagerSlackware.c index 6f16da87a..d30d8a53e 100644 --- a/src/backends/NetworkManagerSlackware.c +++ b/src/backends/NetworkManagerSlackware.c @@ -254,3 +254,37 @@ void nm_system_restart_mdns_responder (void) { } + +/* + * nm_system_device_add_default_route_via_device + * + * Flush all routes associated with a network device + * + */ +void nm_system_device_add_default_route_via_device (NMDevice *dev) +{ +} + + +/* + * nm_system_flush_loopback_routes + * + * Flush all routes associated with the loopback device, because it + * sometimes gets the first route for ZeroConf/Link-Local traffic. + * + */ +void nm_system_flush_loopback_routes (void) +{ +} + + +/* + * nm_system_flush_arp_cache + * + * Flush all entries in the arp cache. + * + */ +void nm_system_flush_arp_cache (void) +{ +} +