From 0073d4dd5591393708ef7faff5bd017acfa6b17d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 6 Jul 2004 04:45:00 +0000 Subject: [PATCH] 2004-07-06 Dan Williams * src/NetworkManager.c - Add IPv4 address update for active device during link state check - Don't allow wireless cards to be powered up when they are not the active device * src/NetworkManagerDbus.c src/NetworkManagerDbus.h - Add DBUS IPv4 address change signal - Add DBUS IPv4 address get method for devices * src/NetworkManagerDevice.c - Make setting the WEP key actually work - Move IP address get/set/update stuff here, per-device - Power down/bring down wireless device when deactivated - For scanning wireless devices, if first scan returned ENODATA, try again * src/NetworkManagerPolicy.c - Only set the WEP key for an allowed access point if there is one. We were setting it to be blank if one wasn't specified. * src/NetworkManagerUtils.h src/NetworkManagerUtils.c - Move the IP address stuff to NetworkManagerDevice.c * dispatcher-daemon/NetworkManagerDispatcher.c - Add device IPv4 address change notification stuff git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@13 4912f4e0-d625-0410-9fb7-b9a5a253dbdc --- ChangeLog | 29 +++++++ dispatcher-daemon/NetworkManagerDispatcher.c | 88 ++++++++++++++++++-- src/NetworkManager.c | 31 ++++--- src/NetworkManagerDbus.c | 31 +++++++ src/NetworkManagerDbus.h | 2 + src/NetworkManagerDevice.c | 72 +++++++++++++--- src/NetworkManagerPolicy.c | 3 +- src/NetworkManagerUtils.c | 39 --------- src/NetworkManagerUtils.h | 3 - 9 files changed, 224 insertions(+), 74 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7ff858bc8..e4a0545c5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2004-07-06 Dan Williams + + * src/NetworkManager.c + - Add IPv4 address update for active device during link state check + - Don't allow wireless cards to be powered up when they are not the + active device + + * src/NetworkManagerDbus.c + src/NetworkManagerDbus.h + - Add DBUS IPv4 address change signal + - Add DBUS IPv4 address get method for devices + + * src/NetworkManagerDevice.c + - Make setting the WEP key actually work + - Move IP address get/set/update stuff here, per-device + - Power down/bring down wireless device when deactivated + - For scanning wireless devices, if first scan returned ENODATA, try again + + * src/NetworkManagerPolicy.c + - Only set the WEP key for an allowed access point if there is one. + We were setting it to be blank if one wasn't specified. + + * src/NetworkManagerUtils.h + src/NetworkManagerUtils.c + - Move the IP address stuff to NetworkManagerDevice.c + + * dispatcher-daemon/NetworkManagerDispatcher.c + - Add device IPv4 address change notification stuff + 2004-07-05 Dan Williams * dispatcher-daemon/NetworkManagerDispatcher.c diff --git a/dispatcher-daemon/NetworkManagerDispatcher.c b/dispatcher-daemon/NetworkManagerDispatcher.c index 46141db52..c18e61a10 100644 --- a/dispatcher-daemon/NetworkManagerDispatcher.c +++ b/dispatcher-daemon/NetworkManagerDispatcher.c @@ -36,10 +36,15 @@ enum NMDAction { NMD_DEVICE_DONT_KNOW, NMD_DEVICE_NOW_INACTIVE, - NMD_DEVICE_NOW_ACTIVE + NMD_DEVICE_NOW_ACTIVE, + NMD_DEVICE_IP4_ADDRESS_CHANGE }; typedef enum NMDAction NMDAction; +#define NIPQUAD(addr) ((unsigned char)(addr)), \ + ((unsigned char)(addr>>8)), \ + ((unsigned char)(addr>>16)), \ + ((unsigned char)(addr>>24)) /* * nmd_execute_scripts @@ -47,7 +52,7 @@ typedef enum NMDAction NMDAction; * Call scripts in /etc/NetworkManager.d when devices go down or up * */ -void nmd_execute_scripts (NMDAction action, char *iface_name) +void nmd_execute_scripts (NMDAction action, char *iface_name, guint32 new_ip4_address) { DIR *dir = opendir ("/etc/NetworkManager.d"); struct dirent *ent; @@ -77,9 +82,16 @@ void nmd_execute_scripts (NMDAction action, char *iface_name) { char cmd[500]; - snprintf (cmd, 499, "%s %s %s", path, iface_name, - (action == NMD_DEVICE_NOW_INACTIVE ? "down" : - (action == NMD_DEVICE_NOW_ACTIVE ? "up" : "error"))); + if ((action == NMD_DEVICE_NOW_INACTIVE) || (action == NMD_DEVICE_NOW_ACTIVE)) + { + snprintf (cmd, 499, "%s %s %s", path, iface_name, + (action == NMD_DEVICE_NOW_INACTIVE ? "down" : + (action == NMD_DEVICE_NOW_ACTIVE ? "up" : "error"))); + } + else if (action == NMD_DEVICE_IP4_ADDRESS_CHANGE) + { + snprintf (cmd, 499, "%s %s %u.%u.%u.%u", path, iface_name, NIPQUAD (new_ip4_address)); + } system (cmd); } } @@ -145,6 +157,55 @@ char * nmd_get_device_name (DBusConnection *connection, char *path) } +/* + * nmd_get_device_ip4_address + * + * Queries NetworkManager for the IPv4 address of a device, specified by a device path + */ +guint32 nmd_get_device_ip4_address (DBusConnection *connection, char *path) +{ + DBusMessage *message; + DBusMessage *reply; + DBusMessageIter iter; + DBusError error; + guint32 ret_address; + + message = dbus_message_new_method_call ("org.freedesktop.NetworkManager", + path, + "org.freedesktop.NetworkManager", + "getIP4Address"); + if (message == NULL) + { + fprintf (stderr, "Couldn't allocate the dbus message\n"); + return (0); + } + + dbus_error_init (&error); + reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error); + if (dbus_error_is_set (&error)) + { + fprintf (stderr, "%s raised:\n %s\n\n", error.name, error.message); + dbus_message_unref (message); + return (0); + } + + if (reply == NULL) + { + fprintf( stderr, "dbus reply message was NULL\n" ); + dbus_message_unref (message); + return (0); + } + + /* now analyze reply */ + dbus_message_iter_init (reply, &iter); + ret_address = dbus_message_iter_get_uint32 (&iter); + dbus_message_unref (reply); + dbus_message_unref (message); + + return (ret_address); +} + + /* * nmd_dbus_filter * @@ -161,7 +222,9 @@ static DBusHandlerResult nmd_dbus_filter (DBusConnection *connection, DBusMessag dbus_error_init (&error); object_path = dbus_message_get_path (message); - if (dbus_message_is_signal (message, "org.freedesktop.NetworkManager", "DeviceNoLongerActive")) + if (dbus_message_is_signal (message, "org.freedesktop.NetworkManager", "DeviceIP4AddressChange")) + action = NMD_DEVICE_IP4_ADDRESS_CHANGE; + else if (dbus_message_is_signal (message, "org.freedesktop.NetworkManager", "DeviceNoLongerActive")) action = NMD_DEVICE_NOW_INACTIVE; else if (dbus_message_is_signal (message, "org.freedesktop.NetworkManager", "DeviceNowActive")) action = NMD_DEVICE_NOW_ACTIVE; @@ -171,12 +234,21 @@ static DBusHandlerResult nmd_dbus_filter (DBusConnection *connection, DBusMessag if (dbus_message_get_args (message, &error, DBUS_TYPE_STRING, &dev_object_path, DBUS_TYPE_INVALID)) { char *dev_iface_name = nmd_get_device_name (connection, dev_object_path); + guint32 dev_ip4_address = nmd_get_device_ip4_address (connection, dev_object_path); - fprintf (stderr, "Device %s (%s) is now %s.\n", dev_object_path, dev_iface_name, + if (action == NMD_DEVICE_NOW_ACTIVE || action == NMD_DEVICE_NOW_INACTIVE) + { + fprintf (stderr, "Device %s (%s) is now %s.\n", dev_object_path, dev_iface_name, (action == NMD_DEVICE_NOW_INACTIVE ? "down" : (action == NMD_DEVICE_NOW_ACTIVE ? "up" : "error"))); + } + else if (action == NMD_DEVICE_IP4_ADDRESS_CHANGE) + { + fprintf (stderr, "Device %s (%s) now has address %u.%u.%u.%u\n", dev_object_path, dev_iface_name, + NIPQUAD(dev_ip4_address)); + } - nmd_execute_scripts (action, dev_iface_name); + nmd_execute_scripts (action, dev_iface_name, dev_ip4_address); free (dev_iface_name); dbus_free (dev_object_path); diff --git a/src/NetworkManager.c b/src/NetworkManager.c index 6ff73d05f..ac0963b17 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -100,11 +100,10 @@ NMDevice * nm_create_device_and_add_to_list (NMData *data, const char *udi) /* Initialize and bring up all new devices */ if (nm_device_get_iface_type (dev) == NM_IFACE_TYPE_WIRELESS_ETHERNET) { - /* Disable WEP */ + /* Disable WEP, take device down */ nm_device_bring_down (dev); nm_device_set_wep_key (dev, NULL); nm_device_set_essid (dev, NULL); - nm_device_bring_up (dev); } else { @@ -334,19 +333,31 @@ gboolean nm_link_state_monitor (gpointer user_data) if (dev) { - /* Make sure the device is up first. It doesn't have to have - * an IP address or anything, but most devices cannot do link - * detection when they are down. - */ - if (!nm_device_is_up (dev)) - nm_device_bring_up (dev); + if ( dev != data->active_device + && (nm_device_get_iface_type (dev) == NM_IFACE_TYPE_WIRELESS_ETHERNET)) + { + /* If its a wireless card, make sure its down. Saves power. */ + if (nm_device_is_up (dev)) + nm_device_bring_down (dev); + } - nm_device_update_link_active (dev, FALSE); + if ((nm_device_get_iface_type (dev) == NM_IFACE_TYPE_WIRED_ETHERNET)) + { + /* Make sure the device is up first. It doesn't have to have + * an IP address or anything, but most wired devices cannot do link + * detection when they are down. + */ + if (!nm_device_is_up (dev)) + nm_device_bring_up (dev); + + nm_device_update_link_active (dev, FALSE); + } /* Check if the device's IP address has changed * (ie dhcp lease renew/address change) */ - /* Implement me */ + if (dev == data->active_device) + nm_device_update_ip4_address (dev); } element = g_slist_next (element); diff --git a/src/NetworkManagerDbus.c b/src/NetworkManagerDbus.c index 073c3a38f..5d2e71074 100644 --- a/src/NetworkManagerDbus.c +++ b/src/NetworkManagerDbus.c @@ -413,6 +413,35 @@ void nm_dbus_signal_device_now_active (DBusConnection *connection, NMDevice *dev } +/* + * nm_dbus_signal_device_ip4_address_change + * + * Notifies the bus that a particular device's IPv4 address changed. + * + */ +void nm_dbus_signal_device_ip4_address_change (DBusConnection *connection, NMDevice *dev) +{ + DBusMessage *message; + unsigned char *object_path = g_new0 (unsigned char, 100); + + message = dbus_message_new_signal (NM_DBUS_NM_OBJECT_PATH_PREFIX, NM_DBUS_NM_NAMESPACE, "DeviceIP4AddressChange"); + if (!message) + { + NM_DEBUG_PRINT ("nm_dbus_signal_device_ip4_address_change(): Not enough memory for new dbus message!\n"); + return; + } + + nm_dbus_get_object_path_from_device (dev, object_path, 100, FALSE); + dbus_message_append_args (message, DBUS_TYPE_STRING, object_path, DBUS_TYPE_INVALID); + g_free (object_path); + + if (!dbus_connection_send (connection, message, NULL)) + NM_DEBUG_PRINT ("nm_dbus_signal_device_ip4_address_change(): Could not raise the IP4AddressChange signal!\n"); + + dbus_message_unref (message); +} + + /* * nm_dbus_devices_handle_networks_request * @@ -502,6 +531,8 @@ static DBusMessage *nm_dbus_devices_handle_request (DBusConnection *connection, dbus_message_iter_append_string (&iter, nm_device_get_iface (dev)); else if (strcmp ("getType", request) == 0) dbus_message_iter_append_int32 (&iter, nm_device_get_iface_type (dev)); + else if (strcmp ("getIP4Address", request) == 0) + dbus_message_iter_append_uint32 (&iter, nm_device_get_ip4_address (dev)); else if (strcmp ("getActiveNetwork", request) == 0) { NMAccessPoint *ap = NULL; diff --git a/src/NetworkManagerDbus.h b/src/NetworkManagerDbus.h index 17efa44a3..7ad8dc406 100644 --- a/src/NetworkManagerDbus.h +++ b/src/NetworkManagerDbus.h @@ -38,4 +38,6 @@ void nm_dbus_signal_device_no_longer_active (DBusConnection *connection, NMDe void nm_dbus_signal_device_now_active (DBusConnection *connection, NMDevice *dev); +void nm_dbus_signal_device_ip4_address_change(DBusConnection *connection, NMDevice *dev); + #endif diff --git a/src/NetworkManagerDevice.c b/src/NetworkManagerDevice.c index f37f1f7a5..716d87c78 100644 --- a/src/NetworkManagerDevice.c +++ b/src/NetworkManagerDevice.c @@ -187,7 +187,7 @@ struct NMDevice gchar *iface; NMIfaceType iface_type; gboolean link_active; - guint32 ip_address; + guint32 ip4_address; /* FIXME: ipv6 address too */ NMDeviceOptions dev_options; }; @@ -373,7 +373,7 @@ void nm_device_update_link_active (NMDevice *dev, gboolean check_mii) iwlib_socket = iw_sockets_open (); if (iw_get_ext (iwlib_socket, nm_device_get_iface (dev), SIOCGIWAP, &wrq) >= 0) - link_active = nm_ethernet_address_is_valid (&(wrq.u.ap_addr.sa_data)); + link_active = nm_ethernet_address_is_valid ((struct ether_addr *)(&(wrq.u.ap_addr.sa_data))); close (iwlib_socket); break; } @@ -521,7 +521,7 @@ void nm_device_set_wep_key (NMDevice *dev, const char *wep_key) int err; struct iwreq wreq; int keylen; - unsigned char safe_key[IW_ENCODING_TOKEN_MAX]; + unsigned char safe_key[IW_ENCODING_TOKEN_MAX + 1]; gboolean set_key = FALSE; char *it = NULL; @@ -552,10 +552,12 @@ void nm_device_set_wep_key (NMDevice *dev, const char *wep_key) } else { - keylen = iw_in_key_full(iwlib_socket, nm_device_get_iface (dev), "", safe_key, &wreq.u.data.flags); + unsigned char parsed_key[IW_ENCODING_TOKEN_MAX + 1]; + + keylen = iw_in_key_full(iwlib_socket, nm_device_get_iface (dev), safe_key, &parsed_key[0], &wreq.u.data.flags); if (keylen > 0) { - wreq.u.data.pointer = (caddr_t) safe_key; + wreq.u.data.pointer = (caddr_t) &parsed_key; wreq.u.data.length = keylen; set_key = TRUE; } @@ -569,7 +571,7 @@ void nm_device_set_wep_key (NMDevice *dev, const char *wep_key) } close (iwlib_socket); - } + } else NM_DEBUG_PRINT ("nm_device_set_wep_key(): could not get wireless control socket.\n"); } @@ -585,17 +587,37 @@ guint32 nm_device_get_ip4_address(NMDevice *dev) int socket; g_return_val_if_fail (dev != NULL, 0); - g_return_val_if_fail (nm_device_get_iface (dev) != NULL, 0); + + return (dev->ip4_address); +} + +void nm_device_update_ip4_address (NMDevice *dev) +{ + NMData *data = nm_get_global_data (); + guint32 new_address; + struct ifreq req; + int socket; + + g_return_if_fail (data != NULL); + g_return_if_fail (dev != NULL); + g_return_if_fail (nm_device_get_iface (dev) != NULL); socket = nm_get_network_control_socket (); if (socket < 0) - return (0); + return; strncpy ((char *)(&req.ifr_name), nm_device_get_iface (dev), 16); // 16 == IF_NAMESIZE if (ioctl (socket, SIOCGIFADDR, &req) != 0) - return (0); + return; - return (((struct sockaddr_in *)(&req.ifr_addr))->sin_addr.s_addr); + new_address = ((struct sockaddr_in *)(&req.ifr_addr))->sin_addr.s_addr; + + /* If the new address is different, send an IP4AddressChanged signal on the bus */ + if (new_address != nm_device_get_ip4_address (dev)) + { + nm_dbus_signal_device_ip4_address_change (data->dbus_connection, dev); + dev->ip4_address = new_address; + } } @@ -734,7 +756,7 @@ gboolean nm_device_activate (NMDevice *dev) } /* If there is a desired AP to connect to, use that essid and possible WEP key */ - if (nm_ap_get_essid (ap) != NULL) + if (ap && nm_ap_get_essid (ap) != NULL) { nm_device_bring_down (dev); @@ -744,7 +766,8 @@ gboolean nm_device_activate (NMDevice *dev) nm_device_set_wep_key (dev, NULL); if (nm_ap_get_wep_key (ap)) nm_device_set_wep_key (dev, nm_ap_get_wep_key (ap)); - } + } else NM_DEBUG_PRINT_1 ("nm_device_activate(%s) could not get best ap even after scan\n", nm_device_get_iface (dev)); + NM_DEBUG_PRINT_2 ("nm_device_activate(%s) using essid '%s'\n", nm_device_get_iface (dev), nm_ap_get_essid (ap)); } @@ -848,6 +871,15 @@ gboolean nm_device_deactivate (NMDevice *dev) nm_dbus_signal_device_no_longer_active (data->dbus_connection, dev); + /* Clean up stuff, don't leave the card associated or up */ + if (nm_device_get_iface_type (dev) == NM_IFACE_TYPE_WIRELESS_ETHERNET) + { + nm_device_set_essid (dev, ""); + nm_device_set_wep_key (dev, NULL); + + nm_device_bring_down (dev); + } + return (success); } @@ -1007,6 +1039,20 @@ static void nm_device_do_normal_scan (NMDevice *dev) nm_device_ap_list_clear (dev); err = iw_scan (iwlib_socket, nm_device_get_iface (dev), WIRELESS_EXT, &scan_results); + if ((err == -1) && (errno == ENODATA)) + { + /* Card hasn't had time yet to compile full access point list. + * Give it some more time and scan again. If that doesn't work + * give up. + */ + g_usleep (G_USEC_PER_SEC / 2); + err = iw_scan (iwlib_socket, nm_device_get_iface (dev), WIRELESS_EXT, &scan_results); + if (err == -1) + { + close (iwlib_socket); + return; + } + } /* Iterate over scan results and pick a "most" preferred access point. */ tmp_ap = scan_results.result; @@ -1128,7 +1174,7 @@ fprintf( stderr, "Looking at AP %s\n", nm_ap_get_essid (ap) ); nm_device_set_wep_key (dev, NULL); /* Wait a bit for association */ - g_usleep (G_USEC_PER_SEC * 2); + g_usleep (G_USEC_PER_SEC); /* Do we have a valid MAC address? */ nm_device_get_ap_address (dev, &cur_ap_addr); diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index 2edf509f8..c669ae834 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -324,7 +324,8 @@ void nm_policy_update_allowed_access_points (NMData *data) ap = nm_ap_new (); nm_ap_set_priority (ap, prio_num); nm_ap_set_essid (ap, essid); - nm_ap_set_wep_key (ap, wep_key); + if (strlen (wep_key) > 0) + nm_ap_set_wep_key (ap, wep_key); data->allowed_ap_list = g_slist_append (data->allowed_ap_list, ap); /* diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index bcd3d62b3..555363838 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -171,42 +171,3 @@ void nm_dispose_scan_results (wireless_scan *result_list) } } - -/* - * nm_get_ip4_address_for_device - * - * Get a device's IPv4 address - * - */ -guint32 nm_get_ip4_address_for_device(NMDevice *dev) -{ - struct ifreq req; - int socket; - - g_return_val_if_fail (dev != NULL, 0); - g_return_val_if_fail (nm_device_get_iface (dev) != NULL, 0); - - socket = nm_get_network_control_socket (); - if (socket < 0) - return (0); - - strncpy ((char *)(&req.ifr_name), nm_device_get_iface (dev), 16); // 16 == IF_NAMESIZE - if (ioctl (socket, SIOCGIFADDR, &req) != 0) - return (0); - - return (((struct sockaddr_in *)(&req.ifr_addr))->sin_addr.s_addr); -} - - -/* - * nm_get_ip6_address_for_device - * - * Get a device's IPv6 address - * - */ -void nm_get_ip6_address_for_device(NMDevice *dev) -{ - /* FIXME - * Implement - */ -} diff --git a/src/NetworkManagerUtils.h b/src/NetworkManagerUtils.h index 1fe55d3e2..360f1f3f8 100644 --- a/src/NetworkManagerUtils.h +++ b/src/NetworkManagerUtils.h @@ -48,7 +48,4 @@ gboolean nm_ethernet_address_is_valid (struct ether_addr *test_addr); void nm_dispose_scan_results (wireless_scan *result_list); -guint32 nm_get_ipv4_address_for_device (NMDevice *dev); -void nm_get_ipv6_address_for_device (NMDevice *dev); - #endif