diff --git a/ChangeLog b/ChangeLog index c09e527b41..24a3cf62f2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2005-01-31 Dan Williams + + * info-daemon/NetworkManagerInfoDbus.c + - (nmi_dbus_nmi_message_handler): make sure 'dialog' exists before using it + + * src/NetworkManagerDevice.c + - (nm_device_new): Don't store the entire range struct, use only what we need + (which is currently avg_quality, max_quality, and frequencies). Also + zero device structure when we've free'd it to maybe expose errors down + the line. + - (nm_device_update_signal_strength): grab the scan mutex before getting + quality data from the card since quality will be useless during a scan. + Call updated wireless qual-to-percent function with values stored in + nm_device_new() earlier. + - Remove some unused functions (nm_device_get_max_quality(), nm_device_get_noise(), + nm_device_get_bad_crypt_packets()) + - (nm_device_activate_wireless_adhoc): use new frequency values we go in + nm_device_new() + - (get_initial_auth_method): always use the Auth method that's in the allowed + list if available. Problem was this: when the WEP key is wrong, NM will + try OS then SK modes, and then get stuck in SK mode after that. This + should reset it. + - (nm_device_wireless_process_scan_results): work with new qual-to-percent + function + + * src/NetworkManagerWireless.c + - (nm_wireless_qual_to_percent): try to make this function actually work and + mimic iwlib behavior. Use card's idea of quality divided by max_qual + if that's all present, otherwise fall back to signal-to-noise ratios. + 2005-01-29 Dan Williams * initscript/RedHat/NetworkManager diff --git a/info-daemon/NetworkManagerInfoDbus.c b/info-daemon/NetworkManagerInfoDbus.c index 6b8a919c25..fd6719d37c 100644 --- a/info-daemon/NetworkManagerInfoDbus.c +++ b/info-daemon/NetworkManagerInfoDbus.c @@ -665,13 +665,13 @@ static DBusHandlerResult nmi_dbus_nmi_message_handler (DBusConnection *connectio if (strcmp ("getKeyForNetwork", method) == 0) { GtkWidget *dialog = glade_xml_get_widget (info->passphrase_dialog, "passphrase_dialog"); - if (!GTK_WIDGET_VISIBLE (dialog)) + if (dialog && !GTK_WIDGET_VISIBLE (dialog)) nmi_dbus_get_key_for_network (info, message); } else if (strcmp ("cancelGetKeyForNetwork", method) == 0) { GtkWidget *dialog = glade_xml_get_widget (info->passphrase_dialog, "passphrase_dialog"); - if (GTK_WIDGET_VISIBLE (dialog)) + if (dialog && GTK_WIDGET_VISIBLE (dialog)) nmi_passphrase_dialog_cancel (info); } else if (strcmp ("getVPNUserPass", method) == 0) diff --git a/src/NetworkManager.c b/src/NetworkManager.c index 06ce3897df..6527943a4e 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -102,6 +102,7 @@ NMDevice * nm_create_device_and_add_to_list (NMData *data, const char *udi, cons g_return_val_if_fail (data != NULL, NULL); g_return_val_if_fail (udi != NULL, NULL); g_return_val_if_fail (iface != NULL, NULL); + g_return_val_if_fail (strlen (iface) > 0, NULL); /* If we are called to create a test devices, but test devices weren't enabled * on the command-line, don't create the device. diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c index 1a9b605dbe..64f3d86547 100644 --- a/src/NetworkManagerDevice.c +++ b/src/NetworkManagerDevice.c @@ -225,7 +225,7 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev, return (NULL); } - dev = g_new0 (NMDevice, 1); + dev = g_malloc0 (sizeof (NMDevice)); if (!dev) { syslog (LOG_ERR, "nm_device_new() could not allocate a new device... Not enough memory?"); @@ -253,7 +253,6 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev, /* Initialize wireless-specific options */ if (nm_device_is_wireless (dev)) { - iwrange range; int sk; dev->options.wireless.scan_interval = 20; @@ -286,8 +285,25 @@ NMDevice *nm_device_new (const char *iface, const char *udi, gboolean test_dev, if ((sk = iw_sockets_open ()) >= 0) { - 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)); + iwrange range; + if (iw_get_range_info (sk, nm_device_get_iface (dev), &range) >= 0) + { + 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; + + 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; + + 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])); + } close (sk); } } @@ -365,7 +381,6 @@ gboolean nm_device_unref (NMDevice *dev) if (nm_device_is_wireless (dev)) { nm_device_ap_list_clear (dev); - dev->options.wireless.ap_list = NULL; g_mutex_free (dev->options.wireless.scan_mutex); if (dev->options.wireless.ap_list) @@ -376,9 +391,8 @@ gboolean nm_device_unref (NMDevice *dev) } g_free (dev->udi); - dev->udi = NULL; g_free (dev->iface); - dev->iface = NULL; + memset (dev, 0, sizeof (NMDevice)); g_free (dev); deleted = TRUE; } @@ -525,7 +539,7 @@ gint 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.range_info.num_frequency > 14) + if (dev->options.wireless.num_freqs > 14) return 10; else return 5; @@ -1049,7 +1063,7 @@ int nm_device_get_bitrate (NMDevice *dev) 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 */ + /* Test devices don't really have a bitrate, they always succeed */ if (dev->test_device) return 11; @@ -1275,36 +1289,32 @@ void nm_device_update_signal_strength (NMDevice *dev) g_return_if_fail (nm_device_is_wireless (dev)); g_return_if_fail (dev->app_data != NULL); + /* Grab the scan lock since our strength is meaningless during a scan. */ + if (!nm_try_acquire_mutex (dev->options.wireless.scan_mutex, __FUNCTION__)) + return; + /* If we aren't the active device, we don't really have a signal strength * that would mean anything. */ if (dev != dev->app_data->active_device) { dev->options.wireless.strength = -1; - return; + goto out; } /* Fake a value for test devices */ if (dev->test_device) { dev->options.wireless.strength = 75; - return; + goto out; } sk = iw_sockets_open (); has_range = (iw_get_range_info (sk, nm_device_get_iface (dev), &range) >= 0); if (iw_get_stats (sk, nm_device_get_iface (dev), &stats, &range, has_range) == 0) { - /* Update our max quality while we're at it */ - dev->options.wireless.max_quality = range.max_qual.level; - dev->options.wireless.noise = stats.qual.noise; - percent = nm_wireless_qual_to_percent (dev, &(stats.qual)); - } - else - { - dev->options.wireless.max_quality = -1; - dev->options.wireless.noise = -1; - percent = -1; + percent = nm_wireless_qual_to_percent (&stats.qual, (const iwqual *)(&dev->options.wireless.max_qual), + (const iwqual *)(&dev->options.wireless.avg_qual)); } close (sk); @@ -1317,59 +1327,9 @@ void nm_device_update_signal_strength (NMDevice *dev) dev->options.wireless.invalid_strength_counter = 0; dev->options.wireless.strength = percent; -} - -/* - * nm_device_get_noise - * - * Get the current noise level of a wireless device. - * - */ -guint8 nm_device_get_noise (NMDevice *dev) -{ - g_return_val_if_fail (dev != NULL, 0); - g_return_val_if_fail (nm_device_is_wireless (dev), 0); - - return (dev->options.wireless.noise); -} - - -/* - * nm_device_get_max_quality - * - * Get the quality maximum of a wireless device. - * - */ -guint8 nm_device_get_max_quality (NMDevice *dev) -{ - g_return_val_if_fail (dev != NULL, 0); - g_return_val_if_fail (nm_device_is_wireless (dev), 0); - - return (dev->options.wireless.max_quality); -} - - -/* - * nm_device_get_bad_crypt_packets - * - * Return the number of packets the card has dropped because - * they could not be successfully decrypted. - * - */ -guint32 nm_device_get_bad_crypt_packets (NMDevice *dev) -{ - iwstats stats; - int sk; - int err; - - g_return_val_if_fail (dev != NULL, 0); - g_return_val_if_fail (nm_device_is_wireless (dev), 0); - - sk = iw_sockets_open (); - err = iw_get_stats (sk, nm_device_get_iface (dev), &stats, NULL, FALSE); - close (sk); - return (err == 0 ? stats.discard.code : 0); +out: + nm_unlock_mutex (dev->options.wireless.scan_mutex, __FUNCTION__); } @@ -1936,6 +1896,8 @@ static gboolean nm_device_activate_wireless_adhoc (NMDevice *dev, NMAccessPoint double card_freqs[IW_MAX_FREQUENCIES]; int num_freqs = 0, i; double freq_to_use = 0; + iwrange range; + int sk; g_return_val_if_fail (dev != NULL, FALSE); g_return_val_if_fail (ap != NULL, FALSE); @@ -1945,9 +1907,9 @@ static gboolean nm_device_activate_wireless_adhoc (NMDevice *dev, NMAccessPoint /* 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); + num_freqs = MIN (dev->options.wireless.num_freqs, IW_MAX_FREQUENCIES); for (i = 0; i < num_freqs; i++) - card_freqs[i] = iw_freq2float (&(dev->options.wireless.range_info.freq[i])); + card_freqs[i] = dev->options.wireless.freqs[i]; /* We need to find a clear wireless channel to use. We will * only use 802.11b channels for now. @@ -1964,13 +1926,23 @@ static gboolean nm_device_activate_wireless_adhoc (NMDevice *dev, NMAccessPoint } nm_ap_list_iter_free (iter); + if ((sk = iw_sockets_open ()) < 0) + return FALSE; + + if (iw_get_range_info (sk, nm_device_get_iface (dev), &range) < 0) + { + close (sk); + return FALSE; + } + close (sk); + /* Ok, find the first non-zero freq in our table and use it. * For now we only try to use a channel in the 802.11b channel * 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)); + int channel = iw_freq_to_channel (card_freqs[i], &range); if (card_freqs[i] && (channel > 0) && (channel < 15)) { freq_to_use = card_freqs[i]; @@ -1985,7 +1957,7 @@ static gboolean nm_device_activate_wireless_adhoc (NMDevice *dev, NMAccessPoint int channel = (int)(random () % 14); int err; - err = iw_channel_to_freq (channel, &pfreq, &(dev->options.wireless.range_info)); + err = iw_channel_to_freq (channel, &pfreq, &range); if (err == channel) freq_to_use = pfreq; } @@ -2039,20 +2011,26 @@ static gboolean AP_NEED_KEY (NMDevice *dev, NMAccessPoint *ap) /* * get_initial_auth_method * - * Ensure the auth method the AP reports is valid for its encryption mode. + * Update the auth method of the AP from the last-known-good one saved in the allowed list + * (which is found from NMI) and ensure that its valid with the encryption status of the AP. * */ -static NMDeviceAuthMethod get_initial_auth_method (NMAccessPoint *ap) +static NMDeviceAuthMethod get_initial_auth_method (NMAccessPoint *ap, NMAccessPointList *allowed_list) { g_return_val_if_fail (ap != NULL, NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM); if (nm_ap_get_encrypted (ap)) { - NMDeviceAuthMethod auth = nm_ap_get_auth_method (ap); + NMDeviceAuthMethod auth = nm_ap_get_auth_method (ap); + NMAccessPoint *allowed_ap = nm_ap_list_get_ap_by_essid (allowed_list, nm_ap_get_essid (ap)); + + /* Prefer default auth method if we found one for this AP in our allowed list. */ + if (allowed_ap) + auth = nm_ap_get_auth_method (allowed_ap); if ( (auth == NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM) || (auth == NM_DEVICE_AUTH_METHOD_SHARED_KEY)) - return (nm_ap_get_auth_method (ap)); + return (auth); else return (NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM); } @@ -2207,7 +2185,7 @@ need_key: try_connect: /* Initial authentication method */ - nm_ap_set_auth_method (best_ap, get_initial_auth_method (best_ap)); + nm_ap_set_auth_method (best_ap, get_initial_auth_method (best_ap, dev->app_data->allowed_ap_list)); while (success == FALSE) { @@ -3289,6 +3267,7 @@ static gboolean nm_device_wireless_process_scan_results (gpointer user_data) if (tmp_ap->b.has_essid || tmp_ap->has_ap_addr) { NMAccessPoint *nm_ap = nm_ap_new (); + int percent; /* Copy over info from scan to local structure */ @@ -3339,7 +3318,10 @@ static gboolean nm_device_wireless_process_scan_results (gpointer user_data) else nm_ap_set_mode (nm_ap, NETWORK_MODE_INFRA); - nm_ap_set_strength (nm_ap, nm_wireless_qual_to_percent (dev, &(tmp_ap->stats.qual))); + percent = nm_wireless_qual_to_percent (&(tmp_ap->stats.qual), + (const iwqual *)(&dev->options.wireless.max_qual), + (const iwqual *)(&dev->options.wireless.avg_qual)); + nm_ap_set_strength (nm_ap, percent); if (tmp_ap->b.has_freq) nm_ap_set_freq (nm_ap, tmp_ap->b.freq); diff --git a/src/NetworkManagerDevice.h b/src/NetworkManagerDevice.h index 0d648276e0..b29b54e32e 100644 --- a/src/NetworkManagerDevice.h +++ b/src/NetworkManagerDevice.h @@ -83,9 +83,6 @@ gboolean nm_device_set_mode (NMDevice *dev, const NMNetworkMode mode); gint8 nm_device_get_signal_strength (NMDevice *dev); void nm_device_update_signal_strength (NMDevice *dev); -guint8 nm_device_get_noise (NMDevice *dev); -guint8 nm_device_get_max_quality (NMDevice *dev); -guint32 nm_device_get_bad_crypt_packets (NMDevice *dev); NMAccessPoint *nm_device_get_best_ap (NMDevice *dev); void nm_device_set_best_ap (NMDevice *dev, NMAccessPoint *ap); diff --git a/src/NetworkManagerDevicePrivate.h b/src/NetworkManagerDevicePrivate.h index 1abec22770..7c9482fc98 100644 --- a/src/NetworkManagerDevicePrivate.h +++ b/src/NetworkManagerDevicePrivate.h @@ -36,13 +36,15 @@ /* Wireless device specific options */ typedef struct NMDeviceWirelessOptions { - char *cur_essid; + char *cur_essid; /* Mainly for test devices */ gboolean supports_wireless_scan; - guint8 max_quality; - guint8 noise; gint8 strength; gint8 invalid_strength_counter; - struct iw_range range_info; + iwqual max_qual; + iwqual avg_qual; + + gint8 num_freqs; + double freqs[IW_MAX_FREQUENCIES]; GMutex *scan_mutex; NMAccessPointList *ap_list; @@ -59,7 +61,8 @@ typedef struct NMDeviceWirelessOptions /* Wired device specific options */ typedef struct NMDeviceWiredOptions { - int foo; + guint link_watch_id; + guint foo; } NMDeviceWiredOptions; typedef union NMDeviceOptions diff --git a/src/NetworkManagerWireless.c b/src/NetworkManagerWireless.c index 7baa419978..c1b3bda254 100644 --- a/src/NetworkManagerWireless.c +++ b/src/NetworkManagerWireless.c @@ -130,64 +130,47 @@ char *nm_wireless_128bit_key_from_passphrase (const char *passphrase) * a magical signal strength percentage. * */ -int nm_wireless_qual_to_percent (NMDevice *dev, const struct iw_quality *qual) +int nm_wireless_qual_to_percent (const struct iw_quality *qual, const struct iw_quality *max_qual, const struct iw_quality *avg_qual) { int percent = -1; - g_return_val_if_fail (dev != NULL, -1); g_return_val_if_fail (qual != NULL, -1); + g_return_val_if_fail (max_qual != NULL, -1); + g_return_val_if_fail (avg_qual != NULL, -1); - /* Try using the card's idea of the signal quality first */ - if ((nm_device_get_max_quality (dev) == 100) && (qual->qual < 100)) + /* Try using the card's idea of the signal quality first as long as it tells us what the max quality is */ + if ((max_qual->qual != 0) && !(max_qual->updated & IW_QUAL_QUAL_INVALID) && !(qual->updated & IW_QUAL_QUAL_INVALID)) { - /* Atmel driver seems to use qual->qual is the percentage value */ - percent = qual->qual; + percent = (int)(100 * ((double)qual->qual / (double)max_qual->qual)); } - else if (qual->qual == (qual->level - qual->noise)) + else { - /* Ok, simple signal : noise ratio. Prism54 for example. */ -//fprintf (stderr, "20 * log (level / noise) = 20 * log (%d / %d) = %f\n", qual->level, qual->noise, log ((255-qual->level) / (255-qual->noise)) * 100); - percent = (int)rint ((log (qual->qual) / log (96)) * 100.0); - percent = CLAMP (percent, 0, 100); - } - else if (qual->qual >= 1) - { - /* Try it the Gnome Wireless Applet way */ - percent = (int)rint ((log (qual->qual) / log (94)) * 100.0); - percent = CLAMP (percent, 0, 100); - } - - /* If that failed, try to calculate the signal quality based on other - * values, like Signal-to-Noise ratio. - */ - if (((percent == -1) || (percent == 0))) - { - /* If the statistics are in dBm or relative */ - if(qual->level > nm_device_get_max_quality (dev)) + if((qual->level > max_qual->level) && (qual->noise != 0)) { - #define BEST_SIGNAL 85 /* In dBm, stuck card next to AP, this is what I got */ + int level = -1; + int noise = -1; - /* Values in dBm (absolute power measurement) */ - if (qual->level > 0) - percent = (int)rint ((double)(((256 - qual->level) / (double)BEST_SIGNAL) * 100)); + /* Signal level is in dBm (absolute power measurement) */ + if (!(qual->updated & IW_QUAL_LEVEL_INVALID)) + level = qual->level - 0x100; + + /* Deal with noise level in dBm (absolute power measurement) */ + if (!(qual->updated & IW_QUAL_NOISE_INVALID)) + noise = qual->noise - 0x100; + + /* Try a sort of signal-to-noise ratio */ + percent = abs((int)rint(10 * log ((double)level / ((double)level + (double)noise)))); } - else + else if (!(max_qual->level & IW_QUAL_LEVEL_INVALID) && (max_qual->level != 0)) { -/* FIXME - * Not quite sure what to do here... Above we have a "100% strength" number - * empirically derived, but I don't have any cards that trigger this code below... - */ -#if 0 - /* Relative values (0 -> max) */ - qual_rel = qual->level; - qual_max_rel = range->max_qual.level; - noise_rel = qual->noise; - noise_max_rel = range->max_qual.noise; -#else - percent = -1; -#endif + /* Signal level is relavtive (0 -> max) */ + if (!(qual->updated & IW_QUAL_LEVEL_INVALID)) + { + percent = (int)(100 * ((double)qual->level / (double)max_qual->level)); + } } } + percent = CLAMP (percent, 0, 100); return (percent); } diff --git a/src/NetworkManagerWireless.h b/src/NetworkManagerWireless.h index 9f416edc68..299f3b0f3d 100644 --- a/src/NetworkManagerWireless.h +++ b/src/NetworkManagerWireless.h @@ -32,6 +32,8 @@ char * nm_wireless_64bit_ascii_to_hex (const unsigned char *ascii); char * nm_wireless_128bit_ascii_to_hex (const unsigned char *ascii); char * nm_wireless_128bit_key_from_passphrase (const char *passphrase); -int nm_wireless_qual_to_percent (NMDevice *dev, const struct iw_quality *qual); +int nm_wireless_qual_to_percent (const struct iw_quality *qual, + const struct iw_quality *max_qual, + const struct iw_quality *avg_qual); #endif