NetworkManager/src/NetworkManagerWireless.c
Dan Williams c9b41bb448 2005-01-18 Dan Williams <dcbw@redhat.com>
* dhcpcd/client.c
		- Remove some debug messages
		- Wrap others in #ifdef DEBUG/#endif

	* src/NetworkManager.c
		- Remove some debug messages
		- Clarify some debug messages
		- Remove code related to old single-thread wireless scanning

	* src/NetworkManagerAP.[ch]
		- New AP property "last_seen" to track how recently an AP was
			found in a scan
		- Start using 'const' more in function arguments

	* src/NetworkManagerAPList.[ch]
		- (nm_ap_list_merge_scanned_ap): new, selectively update attributes
			of an AP found in an AP list from a source AP, or if not found
			in the list add the source AP
		- (nm_ap_list_combine): remove, no longer needed

	* src/NetworkManagerDevice.c
		- Each device now has a "worker" thread from start to end of its life.
			Scanning for wireless devices now happens in that thread,
			not in a single "wireless scanning thread" for all devices as
			previously.  Activation consists of adding an idle handler to the
			thread's main loop/context, which gets run at the next available
			opportunity.
		- Wireless scanning is also simplified, there is now only one list of
			access points per wireless device, and APs older than 60s are
			removed from the list.  Previously, we kept results for the last
			3 scans and merged whole lists, which was complicated.
		- Cleaned up activation debug messages.
		- Wireless activation and access-point search routines now use Open System
			authentication before trying Shared Key.
		- Removed some code in nm_device_update_best_ap() that could cause cards
			to loose their link to the access point.
		- Scanning now uses a backoff algorithm, where the inverval becomes
			progressively longer between scans when the list of scanned access
			points doesn't change.  A change will revert to the shortest scan
			interval (20s).

	* src/NetworkManagerWireless.[ch]
		- Remove code related to old single-thread wireless scanning


git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@382 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-01-18 22:08:22 +00:00

193 lines
5 KiB
C

/* NetworkManager -- Network link manager
*
* Dan Williams <dcbw@redhat.com>
*
* 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 2004 Red Hat, Inc.
*/
#include <stdio.h>
#include <iwlib.h>
#include "config.h"
#ifdef HAVE_GCRYPT
#include <gcrypt.h>
#else
#include "gnome-keyring-md5.h"
#endif
#include "NetworkManager.h"
#include "NetworkManagerDevice.h"
#include "NetworkManagerWireless.h"
#include "NetworkManagerPolicy.h"
#include "NetworkManagerUtils.h"
/*
* nm_wireless_64bit_ascii_to_hex
*
* Convert an ASCII string into a suitable WEP key.
*
*/
char *nm_wireless_64bit_ascii_to_hex (const unsigned char *ascii)
{
static char hex_digits[] = "0123456789abcdef";
unsigned char *res;
int i;
res = g_malloc (33);
for (i = 0; i < 16; i++)
{
res[2*i] = hex_digits[(ascii[i] >> 4) & 0xf];
res[2*i+1] = hex_digits[ascii[i] & 0xf];
}
/* We chomp it at byte 10, since WEP keys only use 40 bits */
res[10] = 0;
return (res);
}
/*
* nm_wireless_128bit_ascii_to_hex
*
* Convert an ascii string into a suitable string for use
* as a WEP key.
*
* Code originally by Alex Larsson <alexl@redhat.com> and
* copyright Red Hat, Inc. under terms of the LGPL.
*
*/
char *nm_wireless_128bit_ascii_to_hex (const unsigned char *ascii)
{
static char hex_digits[] = "0123456789abcdef";
unsigned char *res;
int i;
res = g_malloc (33);
for (i = 0; i < 16; i++)
{
res[2*i] = hex_digits[(ascii[i] >> 4) & 0xf];
res[2*i+1] = hex_digits[ascii[i] & 0xf];
}
/* We chomp it at byte 26, since WEP keys only use 104 bits */
res[26] = 0;
return (res);
}
/*
* nm_wireless_128bit_key_from_passphrase
*
* From a passphrase, generate a standard 128-bit WEP key using
* MD5 algorithm.
*
*/
char *nm_wireless_128bit_key_from_passphrase (const char *passphrase)
{
char md5_data[65];
unsigned char digest[16];
int passphrase_len;
int i;
g_return_val_if_fail (passphrase != NULL, NULL);
passphrase_len = strlen (passphrase);
if (passphrase_len < 1)
return (NULL);
/* Get at least 64 bits */
for (i = 0; i < 64; i++)
md5_data [i] = passphrase [i % passphrase_len];
/* Null terminate md5 data-to-hash and hash it */
md5_data[64] = 0;
#ifdef HAVE_GCRYPT
gcry_md_hash_buffer (GCRY_MD_MD5, digest, md5_data, 64);
#else
gnome_keyring_md5_string (md5_data, digest);
#endif
return (nm_wireless_128bit_ascii_to_hex (digest));
}
/*
* nm_wireless_stats_to_percent
*
* Convert an iw_stats structure from a scan or the card into
* a magical signal strength percentage.
*
*/
int nm_wireless_qual_to_percent (NMDevice *dev, const struct iw_quality *qual)
{
int percent = -1;
g_return_val_if_fail (dev != NULL, -1);
g_return_val_if_fail (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))
{
/* Atmel driver seems to use qual->qual is the percentage value */
percent = qual->qual;
}
else if (qual->qual == (qual->level - qual->noise))
{
/* 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))
{
#define BEST_SIGNAL 85 /* In dBm, stuck card next to AP, this is what I got */
/* Values in dBm (absolute power measurement) */
if (qual->level > 0)
percent = (int)rint ((double)(((256 - qual->level) / (double)BEST_SIGNAL) * 100));
}
else
{
/* 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
}
}
return (percent);
}