Commit 498d3f87 authored by Dan Williams's avatar Dan Williams
Browse files

2004-11-17 Dan Williams <dcbw@redhat.com>

	* Cache access point MAC addresses in NetworkManagerInfo after you've explicitly
		connected to them.  Then, after a scan, match up non-ESSID-broadcasting access
		points with any cached MAC addresses from NetworkManagerInfo.  Allows us to
		show known access points that don't broadcast their ESSID in the menus without
		any user intervention whatsoever.

	* info-daemon/NetworkManagerInfoDbus.c
		- (nmi_dbus_get_network_addresses, nmi_dbus_add_network_address): new functions
			for dbus method calls "getNetworkAddresses" and "addNetworkAddress"

	* src/NetworkManagerAP.[ch]
		- Add a "user_addresses" data member to the NMAccessPoint structure
		- (nm_ap_get_user_addresses, nm_ap_set_user_addresses): new functions for accessing
			the user_addresses data member

	* src/NetworkManagerAPList.c
		- (nm_ap_list_get_ap_by_address): check user_addresses list too, instead of just
			the AP's reported address
		- (nm_ap_list_update_network): grab the user_addresses list from NetworkManagerInfo

	* src/NetworkManagerDHCP.c
		- Increase DHCP timeout from 25s -> 30s

	* src/NetworkManagerDbus.[ch]
		- (nm_dbus_get_network_addresses, nm_dbus_add_network_address): have NMI get/set
			user addresses

	* src/NetworkManagerDevice.c
		- (nm_device_set_wireless_config): bring down the interface, wait 4s, bring it up,
			wait 2s, then configure it.  Sometimes Prism54 cards will freeze up with
			"mgnt tx queue full", seemingly in response to NM controlling the card too much.
			So, we take the card down to clear it out.
		- (nm_device_do_normal_scan): Copy over AP ESSIDs from the allowed access point list
			too, since that's where the user_addresses are

	* src/NetworkManagerPolicy.c
		- (nm_state_modification_monitor): Tell NMI to add an AP's hardware address to
			that wireless networks' user_addresses list upon successful activation


git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@319 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
parent 5a62cdb8
2004-11-17 Dan Williams <dcbw@redhat.com>
* Cache access point MAC addresses in NetworkManagerInfo after you've explicitly
connected to them. Then, after a scan, match up non-ESSID-broadcasting access
points with any cached MAC addresses from NetworkManagerInfo. Allows us to
show known access points that don't broadcast their ESSID in the menus without
any user intervention whatsoever.
* info-daemon/NetworkManagerInfoDbus.c
- (nmi_dbus_get_network_addresses, nmi_dbus_add_network_address): new functions
for dbus method calls "getNetworkAddresses" and "addNetworkAddress"
* src/NetworkManagerAP.[ch]
- Add a "user_addresses" data member to the NMAccessPoint structure
- (nm_ap_get_user_addresses, nm_ap_set_user_addresses): new functions for accessing
the user_addresses data member
* src/NetworkManagerAPList.c
- (nm_ap_list_get_ap_by_address): check user_addresses list too, instead of just
the AP's reported address
- (nm_ap_list_update_network): grab the user_addresses list from NetworkManagerInfo
* src/NetworkManagerDHCP.c
- Increase DHCP timeout from 25s -> 30s
* src/NetworkManagerDbus.[ch]
- (nm_dbus_get_network_addresses, nm_dbus_add_network_address): have NMI get/set
user addresses
* src/NetworkManagerDevice.c
- (nm_device_set_wireless_config): bring down the interface, wait 4s, bring it up,
wait 2s, then configure it. Sometimes Prism54 cards will freeze up with
"mgnt tx queue full", seemingly in response to NM controlling the card too much.
So, we take the card down to clear it out.
- (nm_device_do_normal_scan): Copy over AP ESSIDs from the allowed access point list
too, since that's where the user_addresses are
* src/NetworkManagerPolicy.c
- (nm_state_modification_monitor): Tell NMI to add an AP's hardware address to
that wireless networks' user_addresses list upon successful activation
2004-11-16 Dan Williams <dcbw@redhat.com>
* src/NetworkManagerDevice.[ch]
......
......@@ -211,20 +211,14 @@ static DBusMessage *nmi_dbus_get_networks (NMIAppInfo *info, DBusMessage *messag
g_return_val_if_fail (message != NULL, NULL);
dbus_error_init (&error);
if (!dbus_message_get_args (message, &error, DBUS_TYPE_INT32, &type, DBUS_TYPE_INVALID))
if ( !dbus_message_get_args (message, &error, DBUS_TYPE_INT32, &type, DBUS_TYPE_INVALID)
|| !nmi_network_type_valid (type))
{
reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "InvalidArguments",
"NetworkManagerInfo::getNetworks called with invalid arguments.");
return (reply_message);
}
if (!nmi_network_type_valid (type))
{
reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "InvalidArguments",
"NetworkManagerInfo::getNetworks called with an invalid network type %d.", type);
return (reply_message);
}
/* List all allowed access points that gconf knows about */
element = dir_list = gconf_client_all_dirs (info->gconf_client, NMI_GCONF_WIRELESS_NETWORKS_PATH, NULL);
if (!dir_list)
......@@ -262,7 +256,6 @@ static DBusMessage *nmi_dbus_get_networks (NMIAppInfo *info, DBusMessage *messag
}
g_slist_free (dir_list);
/* Make sure that there's at least one array element if all the gconf calls failed */
if (!value_added)
{
dbus_message_unref (reply_message);
......@@ -495,6 +488,158 @@ static DBusMessage *nmi_dbus_get_network_trusted (NMIAppInfo *info, DBusMessage
}
/*
* nmi_dbus_get_network_addresses
*
* If the specified network exists, grabs a list of AP MAC addresses
* from gconf and pass it back.
*
*/
static DBusMessage *nmi_dbus_get_network_addresses (NMIAppInfo *info, DBusMessage *message)
{
DBusMessage *reply_message = NULL;
char *network = NULL;
NMNetworkType type;
char *key;
GConfValue *value;
DBusError error;
char *escaped_network;
gboolean success = FALSE;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (message != NULL, NULL);
dbus_error_init (&error);
if ( !dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &network, DBUS_TYPE_INT32, &type, DBUS_TYPE_INVALID)
|| !nmi_network_type_valid (type)
|| (strlen (network) <= 0))
{
reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "InvalidArguments",
"NetworkManagerInfo::getNetworkAddresses called with invalid arguments.");
return (reply_message);
}
/* Grab user-key key for our access point from GConf */
escaped_network = gconf_escape_key (network, strlen (network));
key = g_strdup_printf ("%s/%s/addresses", NMI_GCONF_WIRELESS_NETWORKS_PATH, escaped_network);
g_free (escaped_network);
value = gconf_client_get (info->gconf_client, key, NULL);
g_free (key);
/* We don't error out if no key was found in gconf, we return blank key */
reply_message = dbus_message_new_method_return (message);
if (value && (value->type == GCONF_VALUE_LIST) && (gconf_value_get_list_type (value) == GCONF_VALUE_STRING))
{
DBusMessageIter iter;
DBusMessageIter iter_array;
GSList *list = gconf_value_get_list (value);
GSList *elem = list;
dbus_message_iter_init (reply_message, &iter);
dbus_message_iter_append_array (&iter, &iter_array, DBUS_TYPE_STRING);
while (elem != NULL)
{
const char *string = gconf_value_get_string ((GConfValue *)elem->data);
if (string)
{
dbus_message_iter_append_string (&iter_array, string);
success = TRUE;
}
elem = g_slist_next (elem);
}
}
gconf_value_free (value);
if (!success)
{
dbus_message_unref (reply_message);
reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "NoAddresses",
"There were no stored addresses for this wireless network.");
}
return (reply_message);
}
/*
* nmi_dbus_add_network_address
*
* Add an AP's MAC address to a wireless network entry in gconf
*
*/
static DBusMessage *nmi_dbus_add_network_address (NMIAppInfo *info, DBusMessage *message)
{
DBusMessage *reply_message = NULL;
char *network = NULL;
NMNetworkType type;
char *addr;
char *key;
GConfValue *value;
DBusError error;
char *escaped_network;
GSList *new_mac_list = NULL;
gboolean found = FALSE;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (message != NULL, NULL);
dbus_error_init (&error);
if ( !dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &network, DBUS_TYPE_INT32, &type, DBUS_TYPE_STRING, &addr, DBUS_TYPE_INVALID)
|| !nmi_network_type_valid (type)
|| (strlen (network) <= 0)
|| !addr
|| (strlen (addr) < 11))
{
reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "InvalidArguments",
"NetworkManagerInfo::addNetworkAddress called with invalid arguments.");
return (reply_message);
}
/* Grab user-key key for our access point from GConf */
escaped_network = gconf_escape_key (network, strlen (network));
key = g_strdup_printf ("%s/%s/addresses", NMI_GCONF_WIRELESS_NETWORKS_PATH, escaped_network);
g_free (escaped_network);
value = gconf_client_get (info->gconf_client, key, NULL);
if (value && (value->type == GCONF_VALUE_LIST) && (gconf_value_get_list_type (value) == GCONF_VALUE_STRING))
{
GSList *elem;
new_mac_list = gconf_client_get_list (info->gconf_client, key, GCONF_VALUE_STRING, NULL);
gconf_value_free (value);
/* Ensure that the MAC isn't already in the list */
elem = new_mac_list;
while (elem)
{
if (elem->data && !strcmp (addr, elem->data))
{
found = TRUE;
break;
}
elem = g_slist_next (elem);
}
}
/* Add the new MAC address to the end of the list */
if (!found)
{
new_mac_list = g_slist_append (new_mac_list, g_strdup (addr));
gconf_client_set_list (info->gconf_client, key, GCONF_VALUE_STRING, new_mac_list, NULL);
}
/* Free the list, since gconf_client_set_list deep-copies it */
g_slist_foreach (new_mac_list, (GFunc)g_free, NULL);
g_slist_free (new_mac_list);
dbus_free (addr);
g_free (key);
return (NULL);
}
/*
* nmi_dbus_nmi_message_handler
*
......@@ -558,6 +703,10 @@ static DBusHandlerResult nmi_dbus_nmi_message_handler (DBusConnection *connectio
reply_message = nmi_dbus_get_network_key (info, message);
else if (strcmp ("getNetworkTrusted", method) == 0)
reply_message = nmi_dbus_get_network_trusted (info, message);
else if (strcmp ("getNetworkAddresses", method) == 0)
reply_message = nmi_dbus_get_network_addresses (info, message);
else if (strcmp ("addNetworkAddress", method) == 0)
nmi_dbus_add_network_address (info, message);
else
{
reply_message = nmi_dbus_create_error_message (message, NMI_DBUS_INTERFACE, "UnknownMethod",
......
......@@ -45,6 +45,7 @@ struct NMAccessPoint
char *enc_key;
NMEncKeyType enc_method;
GTimeVal timestamp;
GSList *user_addresses;
};
......@@ -133,6 +134,8 @@ void nm_ap_unref (NMAccessPoint *ap)
g_free (ap->essid);
g_free (ap->address);
g_free (ap->enc_key);
g_slist_foreach (ap->user_addresses, (GFunc)g_free, NULL);
g_slist_free (ap->user_addresses);
ap->essid = NULL;
ap->enc_key = NULL;
......@@ -441,3 +444,61 @@ const NMEncKeyType nm_ap_get_enc_method (NMAccessPoint *ap)
return (ap->enc_method);
}
/*
* Get/Set functions for user address list
*
* The internal address list is always "owned" by the AP and
* the list returned by nm_ap_get_user_addresses() is a deep copy.
* Likewise, when setting the list, a deep copy is made for the
* ap's actual list.
*
*/
GSList *nm_ap_get_user_addresses (NMAccessPoint *ap)
{
GSList *new = NULL;
GSList *elem = NULL;
g_return_val_if_fail (ap != NULL, NULL);
elem = ap->user_addresses;
while (elem)
{
if (elem->data)
new = g_slist_append (new, g_strdup (elem->data));
elem = g_slist_next (elem);
}
/* Return a _deep__copy_ of the address list */
return (new);
}
void nm_ap_set_user_addresses (NMAccessPoint *ap, GSList *list)
{
GSList *elem = NULL;
GSList *new = NULL;
g_return_if_fail (ap != NULL);
/* Free existing list */
elem = ap->user_addresses;
while (elem)
{
if (elem->data)
g_free (elem->data);
elem = g_slist_next (elem);
}
/* Copy new list and set as our own */
elem = list;
while (elem)
{
if (elem->data)
new = g_slist_append (new, g_strdup (elem->data));
elem = g_slist_next (elem);
}
ap->user_addresses = new;
}
......@@ -73,4 +73,7 @@ void nm_ap_set_artificial (NMAccessPoint *ap, gboolean artificial);
const NMEncKeyType nm_ap_get_enc_method (NMAccessPoint *ap);
GSList * nm_ap_get_user_addresses (NMAccessPoint *ap);
void nm_ap_set_user_addresses (NMAccessPoint *ap, GSList *list);
#endif
......@@ -21,6 +21,7 @@
#include <glib.h>
#include <dbus/dbus-glib.h>
#include <netinet/ether.h>
#include "NetworkManagerAP.h"
#include "NetworkManagerAPList.h"
#include "NetworkManagerUtils.h"
......@@ -250,7 +251,34 @@ NMAccessPoint *nm_ap_list_get_ap_by_address (NMAccessPointList *list, const stru
while ((ap = nm_ap_list_iter_next (iter)))
{
GSList *user_addrs;
gboolean success = FALSE;
if (nm_ap_get_address (ap) && (memcmp (addr, nm_ap_get_address (ap), sizeof (struct ether_addr)) == 0))
success = TRUE;
if (!success && (user_addrs = nm_ap_get_user_addresses (ap)))
{
char char_addr[20];
GSList *elem = user_addrs;
memset (&char_addr[0], 0, 20);
ether_ntoa_r (addr, &char_addr[0]);
while (elem)
{
if (elem->data && !strcmp (elem->data, &char_addr[0]))
{
success = TRUE;
break;
}
elem = g_slist_next (elem);
}
g_slist_foreach (user_addrs, (GFunc)g_free, NULL);
g_slist_free (user_addrs);
}
if (success)
{
found_ap = ap;
break;
......@@ -284,6 +312,8 @@ void nm_ap_list_update_network (NMAccessPointList *list, const char *network, NM
char *key = nm_dbus_get_network_key (data->dbus_connection, list->type, network, &enc_method);
GTimeVal *timestamp = nm_dbus_get_network_timestamp (data->dbus_connection, list->type, network);
gboolean trusted = nm_dbus_get_network_trusted (data->dbus_connection, list->type, network);
int num_addrs;
char **addrs = nm_dbus_get_network_addresses (data->dbus_connection, list->type, network, &num_addrs);
if (timestamp != NULL)
{
......@@ -304,6 +334,24 @@ void nm_ap_list_update_network (NMAccessPointList *list, const char *network, NM
else
nm_ap_set_enc_key_source (ap, NULL, NM_ENC_TYPE_UNKNOWN);
/* Get user addresses, form into a GSList, and stuff into the AP */
{
GSList *addr_list = NULL;
int i;
if (!addrs)
num_addrs = 0;
for (i = 0; i < num_addrs; i++)
{
if (addrs[i] && (strlen (addrs[i]) >= 11))
addr_list = g_slist_append (addr_list, g_strdup (addrs[i]));
}
nm_ap_set_user_addresses (ap, addr_list);
g_slist_foreach (addr_list, (GFunc)g_free, NULL);
g_slist_free (addr_list);
}
if (new)
{
nm_ap_list_append_ap (list, ap);
......@@ -311,6 +359,7 @@ void nm_ap_list_update_network (NMAccessPointList *list, const char *network, NM
}
}
dbus_free_string_array (addrs);
g_free (timestamp);
g_free (essid);
g_free (key);
......
......@@ -51,7 +51,7 @@ int nm_device_dhcp_run (NMDevice *dev)
g_return_val_if_fail (dev != NULL, RET_DHCP_ERROR);
memset (&opts, 0, sizeof (dhcp_client_options));
opts.base_timeout = 25;
opts.base_timeout = 30;
iface = nm_device_get_iface (dev);
if (!(dhcp_iface = dhcp_interface_init (iface, &opts)))
......
......@@ -25,7 +25,7 @@
#include <dbus/dbus-glib.h>
#include <stdarg.h>
#include <iwlib.h>
#include <netinet/ether.h>
#include "NetworkManager.h"
#include "NetworkManagerUtils.h"
......@@ -956,6 +956,124 @@ gboolean nm_dbus_get_network_trusted (DBusConnection *connection, NMNetworkType
}
/*
* nm_dbus_get_network_addresses
*
* Query NetworkManagerInfo for known MAC address of a wireless network
*
* Returns: NULL on error of if no MAC address exists for that network
* char array of addresses on success, num_addr = # items
*
*/
char **nm_dbus_get_network_addresses (DBusConnection *connection, NMNetworkType type, const char *network, int *num_addr)
{
DBusMessage *message;
DBusError error;
DBusMessage *reply;
gboolean success = FALSE;
char **list = NULL;
g_return_val_if_fail (connection != NULL, FALSE);
g_return_val_if_fail (network != NULL, FALSE);
g_return_val_if_fail (type != NETWORK_TYPE_UNKNOWN, FALSE);
g_return_val_if_fail (num_addr != NULL, FALSE);
*num_addr = 0;
message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH,
NMI_DBUS_INTERFACE, "getNetworkAddresses");
if (!message)
{
syslog (LOG_ERR, "nm_dbus_get_network_ap_mac_address(): Couldn't allocate the dbus message");
return (FALSE);
}
dbus_message_append_args (message, DBUS_TYPE_STRING, network,
DBUS_TYPE_INT32, (int)type,
DBUS_TYPE_INVALID);
/* Send message and get trusted status back from NetworkManagerInfo */
dbus_error_init (&error);
reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error);
if (dbus_error_is_set (&error))
{
/* Ignore the "NoAddresses" error */
if (strcmp (error.name, "org.freedesktop.NetworkManagerInfo.NoAddresses"))
syslog (LOG_ERR, "nm_dbus_get_network_addresses(): %s raised %s", error.name, error.message);
dbus_error_free (&error);
}
else if (!reply)
syslog (LOG_NOTICE, "nm_dbus_get_network_addresses(): reply was NULL.");
else
{
DBusMessageIter iter;
dbus_message_iter_init (reply, &iter);
dbus_message_iter_get_string_array (&iter, &list, num_addr);
if (*num_addr > 0)
success = TRUE;
}
dbus_message_unref (message);
if (reply)
dbus_message_unref (reply);
return (list);
}
/*
* nm_dbus_add_network_address
*
* Tell NetworkManagerInfo the MAC address of an AP
*
* Returns: FALSE on error
* TRUE on success
*
*/
gboolean nm_dbus_add_network_address (DBusConnection *connection, NMNetworkType type, const char *network, struct ether_addr *addr)
{
DBusMessage *message;
DBusError error;
gboolean success = FALSE;
char char_addr[20];
g_return_val_if_fail (connection != NULL, FALSE);
g_return_val_if_fail (network != NULL, FALSE);
g_return_val_if_fail (type != NETWORK_TYPE_UNKNOWN, FALSE);
g_return_val_if_fail (addr != NULL, FALSE);
message = dbus_message_new_method_call (NMI_DBUS_SERVICE, NMI_DBUS_PATH,
NMI_DBUS_INTERFACE, "addNetworkAddress");
if (!message)
{
syslog (LOG_ERR, "nm_dbus_add_network_ap_mac_address(): Couldn't allocate the dbus message");
return (FALSE);
}
memset (char_addr, 0, 20);
ether_ntoa_r (addr, &char_addr[0]);
dbus_message_append_args (message, DBUS_TYPE_STRING, network,
DBUS_TYPE_INT32, (int)type,
DBUS_TYPE_STRING, &char_addr,
DBUS_TYPE_INVALID);
/* Send message and get trusted status back from NetworkManagerInfo */
dbus_error_init (&error);
if (!dbus_connection_send (connection, message, NULL))
{
syslog (LOG_ERR, "nm_dbus_add_network_ap_mac_address(): failed to send dbus message.");
dbus_error_free (&error);
}
else
success = TRUE;
dbus_message_unref (message);
return (success);
}
/*
* nm_dbus_get_networks
*
......
......@@ -58,12 +58,11 @@ void nm_dbus_get_user_key_for_network (DBusConnection *connection, NMDevice *
void nm_dbus_cancel_get_user_key_for_network (DBusConnection *connection);
char * nm_dbus_get_network_essid (DBusConnection *connection, NMNetworkType type, const char *network);
char * nm_dbus_get_network_key (DBusConnection *connection, NMNetworkType type, const char *network, NMEncKeyType *enc_method);
GTimeVal * nm_dbus_get_network_timestamp (DBusConnection *connection, NMNetworkType type, const char *network);
gboolean nm_dbus_get_network_trusted (DBusConnection *connection, NMNetworkType type, const char *network);
char ** nm_dbus_get_network_addresses (DBusConnection *connection, NMNetworkType type, const char *network, int *num_addr);
gboolean nm_dbus_add_network_address (DBusConnection *connection, NMNetworkType type, const char *network, struct ether_addr *addr);
char ** nm_dbus_get_networks (DBusConnection *connection, NMNetworkType type, int *num_networks);
......
......@@ -1399,6 +1399,10 @@ static gboolean nm_device_set_wireless_config (NMDevice *dev, NMAccessPoint *ap,
g_return_val_if_fail (nm_ap_get_essid (ap) != NULL, FALSE);
/* Force the card into Managed/Infrastructure mode */
nm_device_bring_down (dev);
g_usleep (G_USEC_PER_SEC * 4);
nm_device_bring_up (dev);
g_usleep (G_USEC_PER_SEC * 2);
nm_device_set_mode_managed (dev);
nm_device_set_essid (dev, " ");
......@@ -1422,7 +1426,6 @@ static gboolean nm_device_set_wireless_config (NMDevice *dev, NMAccessPoint *ap,
((auth == NM_DEVICE_AUTH_METHOD_SHARED_KEY) ? "Shared Key" : "unknown")));
/* Bring the device up and pause to allow card to associate */
nm_device_bring_up (dev);
g_usleep (G_USEC_PER_SEC * 5);
nm_device_update_link_active (dev, FALSE);
......@@ -2550,11 +2553,9 @@ static void nm_device_do_normal_scan (NMDevice *dev)
/* Compose the current access point list for the card based on the past two scans. This
* is to achieve some stability in the list, since cards don't necessarily return the same
* access point list each scan even if you are standing in the same place.
* Once we have the list, copy in any relevant information from our Allowed list.
*/
old_ap_list = nm_device_ap_list_get (dev);
dev->options.wireless.ap_list = nm_ap_list_combine (dev->options.wireless.cached_ap_list1, dev->options.wireless.cached_ap_list2);
nm_ap_list_copy_properties (nm_device_ap_list_get (dev), dev->app_data->allowed_ap_list);
/* If any blank ESSID networks were detected in the current scan, try to match their
* AP MAC address with existing ones in previous scans, and if we get a match, copy the
......@@ -2563,7 +2564,13 @@ static void nm_device_do_normal_scan (NMDevice *dev)
* its job when the user wanted us to connect to a non-broadcasting network.
*/
if (have_blank_essids)
{
nm_ap_list_copy_essids_by_address (nm_device_ap_list_get (dev), old_ap_list);
nm_ap_list_copy_essids_by_address (nm_device_ap_list_get (dev), dev->app_data->allowed_ap_list);
}
/* Once we have the list, copy in any relevant information from our Allowed list. */
nm_ap_list_copy_properties (nm_device_ap_list_get (dev), dev->app_data->allowed_ap_list);