2008-11-03 04:13:42 +00:00
|
|
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
2004-06-24 14:18:37 +00:00
|
|
|
/* NetworkManager -- Network link manager
|
|
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
2008-06-26 18:31:52 +00:00
|
|
|
* 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.,
|
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2004-06-24 14:18:37 +00:00
|
|
|
*
|
2012-05-21 14:10:05 +02:00
|
|
|
* Copyright (C) 2004 - 2012 Red Hat, Inc.
|
2008-11-03 04:13:42 +00:00
|
|
|
* Copyright (C) 2005 - 2008 Novell, Inc.
|
2004-06-24 14:18:37 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <glib.h>
|
2009-07-29 12:12:41 -04:00
|
|
|
#include <errno.h>
|
|
|
|
|
#include <fcntl.h>
|
2005-03-26 03:42:05 +00:00
|
|
|
#include <string.h>
|
2009-07-29 12:12:41 -04:00
|
|
|
#include <unistd.h>
|
2011-07-22 12:50:54 -05:00
|
|
|
#include <stdlib.h>
|
2013-11-19 22:28:36 -06:00
|
|
|
#include <resolv.h>
|
2004-06-24 14:18:37 +00:00
|
|
|
|
|
|
|
|
#include "NetworkManagerUtils.h"
|
2005-03-14 Ray Strode <rstrode@redhat.com>
Fourth (probably working) cut at porting to
dbus 0.30 api and new hal. This cut adds
some new logging macros to make debugging
easier.
* dispatcher-daemon/NetworkManagerDispatcher.c:
* info-daemon/NetworkmanagerInfo.c:
* info-daemon/NetworkManagerInfoPassphraseDialog.c:
* info-daemon/NetworkManagerInfoVPN.c:
* src/NetworkManager.c:
* src/NetworkManagerAP.c:
* src/NetworkManagerAPList.c:
* src/NetworkManagerDHCP.c:
* src/NetworkManagerDbus.c:
* src/NetworkManagerDevice.c:
* src/NetworkManagerPolicy.c:
* src/NetworkManagerSystem.c:
* src/NetworkManagerUtils.c:
* src/NetworkManagerWireless.c:
* src/autoip.c:
* src/nm-dbus-nm.c:
* src/backends/NetworkManagerDebian.c:
* src/backends/NetworkManagerGentoo.c:
* src/backends/NetworkManagerRedHat.c:
* src/backends/NetworkManagerSlackware.c:
use new logging macros.
* dispatcher-daemon/NetworkManagerDispatcher.c:
(nmd_dbus_filter): s/dbus_free/g_free/
* info-daemon/Makefile.am: link in utils library.
* info-daemon/NetworkmanagerInfo.c: use new logging
macros.
(nmi_dbus_get_network): don't assume enumerations
are 32-bit.
(nmi_dbus_nmi_message_handler): don't free what
doesn't belong to us.
* libnm_glib/libnm_glib.c:
(libnm_glib_get_nm_status):
(libnm_glib_init): don't free what doesn't
belong to us.
(libnm_glib_dbus): strdup result, so it doesn't get
lost when message is unref'd.
* panel-applet/NMWirelessAppletDbus.c:
(nmwa_dbus_update_devices): s/dbus_free/g_free/
* src/NetworkManager.c:
(nm_monitor_wired_link_state): request initial status
dump of all cards when we start up, instead of relying
on /sys/.../carrier.
(nm_info_handler), (nm_set_up_log_handlers):
log handlers to specify what syslog priorites
the logging macros default to.
* src/NetworkManagerAPList.c:
(nm_ap_list_populate_from_nmi):
s/dbus_free_string_array/g_strfreev/
* src/NetworkManagerDbus.c:
(nm_dbus_get_network_object):
validate d-bus message argument types.
Advance message iterator after reading argument,
prepend instead of append to GSList.
* src/NetworkManagerDevice.c:
(nm_device_probe_wired_link_status):
remove redundant /sys in /sys path. remove wrong
contents == NULL means has carrier assumption.
* src/nm-netlink-monitor.c
(nm_netlink_monitor_request_status): implement
function to ask kernel to dump interface link
status over netlink socket.
* test/*.c: s/dbus_free/g_free/
* utils/nm-utils.h:
(nm_print_backtrace): new macro to print backtrace.
(nm_get_timestamp): new macro to get sub-second precise
unix timestamp.
(nm_info), (nm_debug), (nm_warning), (nm_error):
new logging functions. nm_info just prints,
nm_debug includes timestamp and function,
nm_warning includes function, nm_error includes
backtrace and sigtrap.
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@497 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2005-03-15 05:30:15 +00:00
|
|
|
#include "nm-utils.h"
|
2010-04-07 12:28:57 -07:00
|
|
|
#include "nm-logging.h"
|
2005-12-31 08:21:24 +00:00
|
|
|
#include "nm-device.h"
|
2011-01-13 13:28:52 -06:00
|
|
|
#include "nm-setting-connection.h"
|
|
|
|
|
#include "nm-setting-ip4-config.h"
|
|
|
|
|
#include "nm-setting-ip6-config.h"
|
2011-07-01 14:56:07 -05:00
|
|
|
#include "nm-setting-wireless.h"
|
|
|
|
|
#include "nm-setting-wireless-security.h"
|
|
|
|
|
#include "nm-manager-auth.h"
|
2012-05-21 14:10:05 +02:00
|
|
|
#include "nm-posix-signals.h"
|
2004-06-24 14:18:37 +00:00
|
|
|
|
2004-07-06 01:34:10 +00:00
|
|
|
/*
|
|
|
|
|
* nm_ethernet_address_is_valid
|
|
|
|
|
*
|
2006-05-17 15:02:57 +00:00
|
|
|
* Compares an Ethernet address against known invalid addresses.
|
2004-07-06 01:34:10 +00:00
|
|
|
*
|
|
|
|
|
*/
|
2007-11-15 18:33:17 +00:00
|
|
|
gboolean
|
|
|
|
|
nm_ethernet_address_is_valid (const struct ether_addr *test_addr)
|
2004-07-06 01:34:10 +00:00
|
|
|
{
|
2007-11-15 18:33:17 +00:00
|
|
|
guint8 invalid_addr1[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
|
|
|
|
guint8 invalid_addr2[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
|
guint8 invalid_addr3[ETH_ALEN] = {0x44, 0x44, 0x44, 0x44, 0x44, 0x44};
|
|
|
|
|
guint8 invalid_addr4[ETH_ALEN] = {0x00, 0x30, 0xb4, 0x00, 0x00, 0x00}; /* prism54 dummy MAC */
|
2004-07-06 01:34:10 +00:00
|
|
|
|
2004-07-15 Dan Williams <dcbw@redhat.com>
* src/Makefile.am
- Turn on warnings
* src/NetworkManager.c
- nm_create_device_and_add_to_list(): call nm_device_deactivate() rather
that doing the deactivation ourselves
- Cancel an pending actions on a device if its being removed
- Break up link state checking a bit, make non-active wireless cards
deactivated to save power
- Remove unused variables
* src/NetworkManager.h
- Add support for "pending" device
* src/NetworkManagerAP.h
src/NetworkManagerAP.c
- Add support for determining whether and AP has encryption enabled or not
- AP address is now "struct ether_addr" rather than a string
* src/NetworkManagerDbus.h
src/NetworkManagerDbus.c
- Add signal NeedKeyForNetwork, method SetKeyForNetwork (testing only)
- Changes for AP address from struct ether_addr->string
* src/NetworkManagerDevice.h
src/NetworkManagerDevice.c
- Remove unused variables, fix warnings
- Add support for Pending Actions (things that block a device from being "active"
until they are completed).
- First pending action: Get a WEP key from the user
- Add nm_device_is_wire[d|less](), rename nm_device_is_wireless()
- Clean up explicit testing of dev->iface_type to use nm_device_is_wireless()
- Update wireless link checking to try to determine if the AP we are associated
with is correct, but the WEP key we are using is just wrong. If its wrong,
trigger the GetUserKey pending action on the device
- If dhclient can't get an IP address, it brings the device down. Bring it back
up in that case, otherwise we can't scan or link-check on it
- Add IP address change notifications at appropriate points (still needs some work)
- Add nm_device_need_ap_switch(), checks whether we need to switch access points or not
* src/NetworkManagerPolicy.h
src/NetworkManagerPolicy.c
- Split out "best" access point determiniation into separate function
- Make device activation 2-stage: first the device is pending, then
in the next iteration through it becomes "active" unless it has
pending actions
* src/NetworkManagerUtils.h
src/NetworkManagerUtils.c
- Clean up unused variables and warnings
- Wrap our debug macros in {} to prevent possible confusion
* src/NetworkManagerWireless.c
- Forgot to return current best priority, which lead to last available AP always
being chosen no matter what its priority was. Corrected.
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@15 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2004-07-15 16:51:48 +00:00
|
|
|
g_return_val_if_fail (test_addr != NULL, FALSE);
|
2004-07-06 01:34:10 +00:00
|
|
|
|
|
|
|
|
/* Compare the AP address the card has with invalid ethernet MAC addresses. */
|
2007-11-15 20:33:08 +00:00
|
|
|
if (!memcmp (test_addr->ether_addr_octet, &invalid_addr1, ETH_ALEN))
|
2007-11-15 18:33:17 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
2007-11-15 20:33:08 +00:00
|
|
|
if (!memcmp (test_addr->ether_addr_octet, &invalid_addr2, ETH_ALEN))
|
2007-11-15 18:33:17 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
2007-11-15 20:33:08 +00:00
|
|
|
if (!memcmp (test_addr->ether_addr_octet, &invalid_addr3, ETH_ALEN))
|
2007-11-15 18:33:17 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
2007-11-15 20:33:08 +00:00
|
|
|
if (!memcmp (test_addr->ether_addr_octet, &invalid_addr4, ETH_ALEN))
|
2007-11-15 18:33:17 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (test_addr->ether_addr_octet[0] & 1) /* Multicast addresses */
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
2004-07-06 01:34:10 +00:00
|
|
|
}
|
|
|
|
|
|
2004-06-24 14:18:37 +00:00
|
|
|
|
2008-04-27 12:23:17 +00:00
|
|
|
int
|
|
|
|
|
nm_spawn_process (const char *args)
|
2004-08-12 Dan Williams <dcbw@redhat.com>
* info-daemon/passphrase.glade
- Set window title to " "
* panel-applet/Makefile.am
panel-applet/keyring.png
- Deliver to correct place
* panel-applet/NMWirelessApplet.[ch]
- Add comments
- Remove applet->have_active_device as its no longer used
- (nmwa_load_theme): load keyring.png too
- (error_dialog): remove
- (show_warning_dialog): subsume functionality of error dialog too
- (nmwa_destroy, nmwa_new): create and dispose of an application-wide GConfClient
- (nmwa_handle_network_choice): add to deal with user clicking on an item from
the networks menu
- (nmwa_menu_item_activated): GtkMenuItem "activate" signal handler
- (nmwa_button_clicked, nmwa_setup_widgets): create and populate the menu on startup
and when we get broadcasts of changed wireless access points only, not when the
user clicks on the button to display the menu (too long of a wait)
- (nmwa_add_menu_item): Make active network bold, and place a keyring icon beside
networks that are encrypted
- (nmwa_dispose_menu, nmwa_menu_item_data_free): dispose of the data we place on each
menu item with g_object_set_data()
* panel-applet/NMWirelessAppletDbus.[ch]
- (nmwa_dbus_get_bool): add method to return boolean value from dbus message
- (nmwa_dbus_get_active_network): add (nmwa_dbus_get_string() wrapper to get active network)
- (nmwa_dbus_add_networks_to_menu): clean up, only show one instance of each ESSID in the menu
- (nmwa_dbus_set_network): force NetworkManager to use a particular network for wireless cards
- (nmwa_dbus_init, nmwa_dbus_filter): Trap network appear/disappear and device
activation/deactivation signals and rebuild the menu when they happen
* src/NetworkManager.c
- (main): use new nm_spawn_process() rather than system()
* src/NetworkManagerDbus.c
- (nm_dbus_devices_handle_request): don't compare AP structure addresses directly, but essids
instead. Since we can now force best_aps to stick around, the AP structure to which
dev->options.wireless.best_ap points to won't necessarily be in the device's device list
if a scan has happened since the best_ap was frozen. Also add "setNetwork" method
to freeze the best_ap.
* src/NetworkManagerDevice.[ch]
- (nm_device_activation_worker): Use new nm_spawn_process() call rather than system()
- (nm_device_*_best_ap): add freeze/unfreeze/get_frozen functions, and don't really update
the best_ap in nm_device_update_best_ap() if the best_ap is frozen AND in the device's
ap list
* src/NetworkManagerUtils.[ch]
- (nm_spawn_process): add replacement for system() usage
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@48 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2004-08-12 19:58:01 +00:00
|
|
|
{
|
2008-04-27 12:23:17 +00:00
|
|
|
gint num_args;
|
|
|
|
|
char **argv = NULL;
|
|
|
|
|
int status = -1;
|
|
|
|
|
GError *error = NULL;
|
2004-10-28 19:49:55 +00:00
|
|
|
|
2004-08-12 Dan Williams <dcbw@redhat.com>
* info-daemon/passphrase.glade
- Set window title to " "
* panel-applet/Makefile.am
panel-applet/keyring.png
- Deliver to correct place
* panel-applet/NMWirelessApplet.[ch]
- Add comments
- Remove applet->have_active_device as its no longer used
- (nmwa_load_theme): load keyring.png too
- (error_dialog): remove
- (show_warning_dialog): subsume functionality of error dialog too
- (nmwa_destroy, nmwa_new): create and dispose of an application-wide GConfClient
- (nmwa_handle_network_choice): add to deal with user clicking on an item from
the networks menu
- (nmwa_menu_item_activated): GtkMenuItem "activate" signal handler
- (nmwa_button_clicked, nmwa_setup_widgets): create and populate the menu on startup
and when we get broadcasts of changed wireless access points only, not when the
user clicks on the button to display the menu (too long of a wait)
- (nmwa_add_menu_item): Make active network bold, and place a keyring icon beside
networks that are encrypted
- (nmwa_dispose_menu, nmwa_menu_item_data_free): dispose of the data we place on each
menu item with g_object_set_data()
* panel-applet/NMWirelessAppletDbus.[ch]
- (nmwa_dbus_get_bool): add method to return boolean value from dbus message
- (nmwa_dbus_get_active_network): add (nmwa_dbus_get_string() wrapper to get active network)
- (nmwa_dbus_add_networks_to_menu): clean up, only show one instance of each ESSID in the menu
- (nmwa_dbus_set_network): force NetworkManager to use a particular network for wireless cards
- (nmwa_dbus_init, nmwa_dbus_filter): Trap network appear/disappear and device
activation/deactivation signals and rebuild the menu when they happen
* src/NetworkManager.c
- (main): use new nm_spawn_process() rather than system()
* src/NetworkManagerDbus.c
- (nm_dbus_devices_handle_request): don't compare AP structure addresses directly, but essids
instead. Since we can now force best_aps to stick around, the AP structure to which
dev->options.wireless.best_ap points to won't necessarily be in the device's device list
if a scan has happened since the best_ap was frozen. Also add "setNetwork" method
to freeze the best_ap.
* src/NetworkManagerDevice.[ch]
- (nm_device_activation_worker): Use new nm_spawn_process() call rather than system()
- (nm_device_*_best_ap): add freeze/unfreeze/get_frozen functions, and don't really update
the best_ap in nm_device_update_best_ap() if the best_ap is frozen AND in the device's
ap list
* src/NetworkManagerUtils.[ch]
- (nm_spawn_process): add replacement for system() usage
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@48 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2004-08-12 19:58:01 +00:00
|
|
|
g_return_val_if_fail (args != NULL, -1);
|
|
|
|
|
|
2008-04-27 12:23:17 +00:00
|
|
|
if (!g_shell_parse_argv (args, &num_args, &argv, &error)) {
|
2010-04-07 12:28:57 -07:00
|
|
|
nm_log_warn (LOGD_CORE, "could not parse arguments for '%s': %s", args, error->message);
|
2008-04-27 12:23:17 +00:00
|
|
|
g_error_free (error);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2004-10-28 19:49:55 +00:00
|
|
|
|
2012-05-21 14:10:05 +02:00
|
|
|
if (!g_spawn_sync ("/", argv, NULL, 0, nm_unblock_posix_signals, NULL, NULL, NULL, &status, &error)) {
|
2010-04-07 12:28:57 -07:00
|
|
|
nm_log_warn (LOGD_CORE, "could not spawn process '%s': %s", args, error->message);
|
2008-04-27 12:23:17 +00:00
|
|
|
g_error_free (error);
|
|
|
|
|
}
|
2004-10-28 19:49:55 +00:00
|
|
|
|
2008-04-27 12:23:17 +00:00
|
|
|
g_strfreev (argv);
|
|
|
|
|
return status;
|
2004-08-12 Dan Williams <dcbw@redhat.com>
* info-daemon/passphrase.glade
- Set window title to " "
* panel-applet/Makefile.am
panel-applet/keyring.png
- Deliver to correct place
* panel-applet/NMWirelessApplet.[ch]
- Add comments
- Remove applet->have_active_device as its no longer used
- (nmwa_load_theme): load keyring.png too
- (error_dialog): remove
- (show_warning_dialog): subsume functionality of error dialog too
- (nmwa_destroy, nmwa_new): create and dispose of an application-wide GConfClient
- (nmwa_handle_network_choice): add to deal with user clicking on an item from
the networks menu
- (nmwa_menu_item_activated): GtkMenuItem "activate" signal handler
- (nmwa_button_clicked, nmwa_setup_widgets): create and populate the menu on startup
and when we get broadcasts of changed wireless access points only, not when the
user clicks on the button to display the menu (too long of a wait)
- (nmwa_add_menu_item): Make active network bold, and place a keyring icon beside
networks that are encrypted
- (nmwa_dispose_menu, nmwa_menu_item_data_free): dispose of the data we place on each
menu item with g_object_set_data()
* panel-applet/NMWirelessAppletDbus.[ch]
- (nmwa_dbus_get_bool): add method to return boolean value from dbus message
- (nmwa_dbus_get_active_network): add (nmwa_dbus_get_string() wrapper to get active network)
- (nmwa_dbus_add_networks_to_menu): clean up, only show one instance of each ESSID in the menu
- (nmwa_dbus_set_network): force NetworkManager to use a particular network for wireless cards
- (nmwa_dbus_init, nmwa_dbus_filter): Trap network appear/disappear and device
activation/deactivation signals and rebuild the menu when they happen
* src/NetworkManager.c
- (main): use new nm_spawn_process() rather than system()
* src/NetworkManagerDbus.c
- (nm_dbus_devices_handle_request): don't compare AP structure addresses directly, but essids
instead. Since we can now force best_aps to stick around, the AP structure to which
dev->options.wireless.best_ap points to won't necessarily be in the device's device list
if a scan has happened since the best_ap was frozen. Also add "setNetwork" method
to freeze the best_ap.
* src/NetworkManagerDevice.[ch]
- (nm_device_activation_worker): Use new nm_spawn_process() call rather than system()
- (nm_device_*_best_ap): add freeze/unfreeze/get_frozen functions, and don't really update
the best_ap in nm_device_update_best_ap() if the best_ap is frozen AND in the device's
ap list
* src/NetworkManagerUtils.[ch]
- (nm_spawn_process): add replacement for system() usage
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@48 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2004-08-12 19:58:01 +00:00
|
|
|
}
|
2004-08-16 19:46:43 +00:00
|
|
|
|
2013-07-04 20:20:27 +02:00
|
|
|
gboolean
|
|
|
|
|
nm_match_spec_string (const GSList *specs, const char *match)
|
|
|
|
|
{
|
|
|
|
|
const GSList *iter;
|
|
|
|
|
|
|
|
|
|
for (iter = specs; iter; iter = g_slist_next (iter)) {
|
|
|
|
|
if (!g_ascii_strcasecmp ((const char *) iter->data, match))
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2009-06-11 00:39:12 -04:00
|
|
|
gboolean
|
|
|
|
|
nm_match_spec_hwaddr (const GSList *specs, const char *hwaddr)
|
|
|
|
|
{
|
2013-06-11 11:21:17 -03:00
|
|
|
char *hwaddr_match;
|
2013-02-12 18:00:48 -05:00
|
|
|
gboolean matched;
|
2009-06-11 00:39:12 -04:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (hwaddr != NULL, FALSE);
|
|
|
|
|
|
2013-06-11 11:21:17 -03:00
|
|
|
hwaddr_match = g_strdup_printf ("mac:%s", hwaddr);
|
2013-02-12 18:00:48 -05:00
|
|
|
matched = nm_match_spec_string (specs, hwaddr_match);
|
2009-06-11 00:39:12 -04:00
|
|
|
g_free (hwaddr_match);
|
2013-02-12 18:00:48 -05:00
|
|
|
return matched;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_match_spec_interface_name (const GSList *specs, const char *interface_name)
|
|
|
|
|
{
|
|
|
|
|
char *iface_match;
|
|
|
|
|
gboolean matched;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (interface_name != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
iface_match = g_strdup_printf ("interface-name:%s", interface_name);
|
|
|
|
|
matched = nm_match_spec_string (specs, iface_match);
|
|
|
|
|
g_free (iface_match);
|
|
|
|
|
return matched;
|
2009-06-11 00:39:12 -04:00
|
|
|
}
|
|
|
|
|
|
2010-05-26 16:28:51 -07:00
|
|
|
#define BUFSIZE 10
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
parse_subchannels (const char *subchannels, guint32 *a, guint32 *b, guint32 *c)
|
|
|
|
|
{
|
|
|
|
|
long unsigned int tmp;
|
|
|
|
|
char buf[BUFSIZE + 1];
|
|
|
|
|
const char *p = subchannels;
|
|
|
|
|
int i = 0;
|
|
|
|
|
char *pa = NULL, *pb = NULL, *pc = NULL;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (subchannels != NULL, FALSE);
|
|
|
|
|
g_return_val_if_fail (a != NULL, FALSE);
|
|
|
|
|
g_return_val_if_fail (*a == 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (b != NULL, FALSE);
|
|
|
|
|
g_return_val_if_fail (*b == 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (c != NULL, FALSE);
|
|
|
|
|
g_return_val_if_fail (*c == 0, FALSE);
|
|
|
|
|
|
|
|
|
|
/* sanity check */
|
2012-09-25 10:44:23 -04:00
|
|
|
if (!g_ascii_isxdigit (subchannels[0]))
|
2010-05-26 16:28:51 -07:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/* Get the first channel */
|
|
|
|
|
while (*p && (*p != ',')) {
|
2012-09-25 10:44:23 -04:00
|
|
|
if (!g_ascii_isxdigit (*p) && (*p != '.'))
|
2010-05-26 16:28:51 -07:00
|
|
|
return FALSE; /* Invalid chars */
|
|
|
|
|
if (i >= BUFSIZE)
|
|
|
|
|
return FALSE; /* Too long to be a subchannel */
|
|
|
|
|
buf[i++] = *p++;
|
|
|
|
|
}
|
|
|
|
|
buf[i] = '\0';
|
|
|
|
|
|
|
|
|
|
/* and grab each of its elements, there should be 3 */
|
|
|
|
|
pa = &buf[0];
|
|
|
|
|
pb = strchr (buf, '.');
|
|
|
|
|
if (pb)
|
|
|
|
|
pc = strchr (pb + 1, '.');
|
|
|
|
|
if (!pa || !pb || !pc)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/* Split the string */
|
|
|
|
|
*pb++ = '\0';
|
|
|
|
|
*pc++ = '\0';
|
|
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
|
tmp = strtoul (pa, NULL, 16);
|
|
|
|
|
if (errno)
|
|
|
|
|
return FALSE;
|
|
|
|
|
*a = (guint32) tmp;
|
|
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
|
tmp = strtoul (pb, NULL, 16);
|
|
|
|
|
if (errno)
|
|
|
|
|
return FALSE;
|
|
|
|
|
*b = (guint32) tmp;
|
|
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
|
tmp = strtoul (pc, NULL, 16);
|
|
|
|
|
if (errno)
|
|
|
|
|
return FALSE;
|
|
|
|
|
*c = (guint32) tmp;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-17 21:24:14 -07:00
|
|
|
#define SUBCHAN_TAG "s390-subchannels:"
|
2010-05-26 16:28:51 -07:00
|
|
|
|
|
|
|
|
gboolean
|
2010-06-17 21:24:14 -07:00
|
|
|
nm_match_spec_s390_subchannels (const GSList *specs, const char *subchannels)
|
2010-05-26 16:28:51 -07:00
|
|
|
{
|
|
|
|
|
const GSList *iter;
|
|
|
|
|
guint32 a = 0, b = 0, c = 0;
|
|
|
|
|
guint32 spec_a = 0, spec_b = 0, spec_c = 0;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (subchannels != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
if (!parse_subchannels (subchannels, &a, &b, &c))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
for (iter = specs; iter; iter = g_slist_next (iter)) {
|
|
|
|
|
const char *spec = iter->data;
|
|
|
|
|
|
|
|
|
|
if (!strncmp (spec, SUBCHAN_TAG, strlen (SUBCHAN_TAG))) {
|
|
|
|
|
spec += strlen (SUBCHAN_TAG);
|
|
|
|
|
if (parse_subchannels (spec, &spec_a, &spec_b, &spec_c)) {
|
|
|
|
|
if (a == spec_a && b == spec_b && c == spec_c)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-01 14:56:07 -05:00
|
|
|
const char *
|
|
|
|
|
nm_utils_get_shared_wifi_permission (NMConnection *connection)
|
|
|
|
|
{
|
|
|
|
|
NMSettingWireless *s_wifi;
|
|
|
|
|
NMSettingWirelessSecurity *s_wsec;
|
|
|
|
|
const char *method = NULL;
|
|
|
|
|
|
core: don't have IP4 and IP6 configs on slaves
Although it's convenient in some places to have IP configs on all
connections, it makes more sense in other places to not have IP
configs on slaves. (eg, it's confusing for nmcli, etc, to report a
full NMSettingIP4Config on a slave device). So revert parts of the
earlier patch. However, it's still safe to assume that s_ip4 != NULL
if method != DISABLED, so some of the earlier simplifications can
stay.
Also, add nm_utils_get_ip_config_method(), which returns the correct
IP config method for a connection, whether the connection has IP4 and
IP6 settings objects or not, and use that to keep some more of the
simplifications from the earlier patch.
2013-10-14 10:38:56 -04:00
|
|
|
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG);
|
2013-09-26 17:34:23 -04:00
|
|
|
if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) != 0)
|
2011-07-01 14:56:07 -05:00
|
|
|
return NULL; /* Not shared */
|
|
|
|
|
|
|
|
|
|
s_wifi = nm_connection_get_setting_wireless (connection);
|
|
|
|
|
if (s_wifi) {
|
|
|
|
|
s_wsec = nm_connection_get_setting_wireless_security (connection);
|
2013-08-27 13:13:23 +01:00
|
|
|
if (s_wsec)
|
2011-07-01 14:56:07 -05:00
|
|
|
return NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED;
|
|
|
|
|
else
|
|
|
|
|
return NM_AUTH_PERMISSION_WIFI_SHARE_OPEN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2009-01-22 12:35:04 +02:00
|
|
|
/*********************************/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_gvalue_destroy (gpointer data)
|
|
|
|
|
{
|
|
|
|
|
GValue *value = (GValue *) data;
|
|
|
|
|
|
|
|
|
|
g_value_unset (value);
|
|
|
|
|
g_slice_free (GValue, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GHashTable *
|
|
|
|
|
value_hash_create (void)
|
|
|
|
|
{
|
|
|
|
|
return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, nm_gvalue_destroy);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
value_hash_add (GHashTable *hash,
|
|
|
|
|
const char *key,
|
|
|
|
|
GValue *value)
|
|
|
|
|
{
|
|
|
|
|
g_hash_table_insert (hash, g_strdup (key), value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
value_hash_add_str (GHashTable *hash,
|
|
|
|
|
const char *key,
|
|
|
|
|
const char *str)
|
|
|
|
|
{
|
|
|
|
|
GValue *value;
|
|
|
|
|
|
|
|
|
|
value = g_slice_new0 (GValue);
|
|
|
|
|
g_value_init (value, G_TYPE_STRING);
|
|
|
|
|
g_value_set_string (value, str);
|
|
|
|
|
|
|
|
|
|
value_hash_add (hash, key, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
value_hash_add_object_path (GHashTable *hash,
|
|
|
|
|
const char *key,
|
|
|
|
|
const char *op)
|
|
|
|
|
{
|
|
|
|
|
GValue *value;
|
|
|
|
|
|
|
|
|
|
value = g_slice_new0 (GValue);
|
|
|
|
|
g_value_init (value, DBUS_TYPE_G_OBJECT_PATH);
|
|
|
|
|
g_value_set_boxed (value, op);
|
|
|
|
|
|
|
|
|
|
value_hash_add (hash, key, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
value_hash_add_uint (GHashTable *hash,
|
|
|
|
|
const char *key,
|
|
|
|
|
guint32 val)
|
|
|
|
|
{
|
|
|
|
|
GValue *value;
|
|
|
|
|
|
|
|
|
|
value = g_slice_new0 (GValue);
|
|
|
|
|
g_value_init (value, G_TYPE_UINT);
|
|
|
|
|
g_value_set_uint (value, val);
|
|
|
|
|
|
|
|
|
|
value_hash_add (hash, key, value);
|
|
|
|
|
}
|
2009-06-11 00:39:12 -04:00
|
|
|
|
2010-03-16 23:51:55 -07:00
|
|
|
void
|
|
|
|
|
value_hash_add_bool (GHashTable *hash,
|
|
|
|
|
const char *key,
|
|
|
|
|
gboolean val)
|
|
|
|
|
{
|
|
|
|
|
GValue *value;
|
|
|
|
|
|
|
|
|
|
value = g_slice_new0 (GValue);
|
|
|
|
|
g_value_init (value, G_TYPE_BOOLEAN);
|
|
|
|
|
g_value_set_boolean (value, val);
|
|
|
|
|
|
|
|
|
|
value_hash_add (hash, key, value);
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-02 22:38:51 -05:00
|
|
|
void
|
|
|
|
|
value_hash_add_object_property (GHashTable *hash,
|
|
|
|
|
const char *key,
|
|
|
|
|
GObject *object,
|
|
|
|
|
const char *prop,
|
|
|
|
|
GType val_type)
|
|
|
|
|
{
|
|
|
|
|
GValue *value;
|
|
|
|
|
|
|
|
|
|
value = g_slice_new0 (GValue);
|
|
|
|
|
g_value_init (value, val_type);
|
|
|
|
|
g_object_get_property (object, prop, value);
|
|
|
|
|
value_hash_add (hash, key, value);
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-12 09:08:04 +02:00
|
|
|
|
2011-01-13 13:28:52 -06:00
|
|
|
static char *
|
|
|
|
|
get_new_connection_name (const GSList *existing,
|
|
|
|
|
const char *format,
|
|
|
|
|
const char *preferred)
|
|
|
|
|
{
|
|
|
|
|
GSList *names = NULL;
|
|
|
|
|
const GSList *iter;
|
|
|
|
|
char *cname = NULL;
|
|
|
|
|
int i = 0;
|
|
|
|
|
gboolean preferred_found = FALSE;
|
|
|
|
|
|
|
|
|
|
for (iter = existing; iter; iter = g_slist_next (iter)) {
|
|
|
|
|
NMConnection *candidate = NM_CONNECTION (iter->data);
|
|
|
|
|
const char *id;
|
|
|
|
|
|
2011-03-08 13:41:28 +01:00
|
|
|
id = nm_connection_get_id (candidate);
|
2011-01-13 13:28:52 -06:00
|
|
|
g_assert (id);
|
|
|
|
|
names = g_slist_append (names, (gpointer) id);
|
|
|
|
|
|
|
|
|
|
if (preferred && !preferred_found && (strcmp (preferred, id) == 0))
|
|
|
|
|
preferred_found = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return the preferred name if it was unique */
|
|
|
|
|
if (preferred && !preferred_found) {
|
|
|
|
|
g_slist_free (names);
|
|
|
|
|
return g_strdup (preferred);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Otherwise find the next available unique connection name using the given
|
|
|
|
|
* connection name template.
|
|
|
|
|
*/
|
|
|
|
|
while (!cname && (i++ < 10000)) {
|
|
|
|
|
char *temp;
|
|
|
|
|
gboolean found = FALSE;
|
|
|
|
|
|
|
|
|
|
temp = g_strdup_printf (format, i);
|
|
|
|
|
for (iter = names; iter; iter = g_slist_next (iter)) {
|
|
|
|
|
if (!strcmp (iter->data, temp)) {
|
|
|
|
|
found = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!found)
|
|
|
|
|
cname = temp;
|
|
|
|
|
else
|
|
|
|
|
g_free (temp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_slist_free (names);
|
|
|
|
|
return cname;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-26 17:34:23 -04:00
|
|
|
void
|
|
|
|
|
nm_utils_normalize_connection (NMConnection *connection,
|
|
|
|
|
gboolean default_enable_ipv6)
|
|
|
|
|
{
|
|
|
|
|
NMSettingConnection *s_con = nm_connection_get_setting_connection (connection);
|
|
|
|
|
const char *default_ip4_method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
|
|
|
|
|
const char *default_ip6_method =
|
|
|
|
|
default_enable_ipv6 ? NM_SETTING_IP6_CONFIG_METHOD_AUTO : NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
|
|
|
|
|
NMSettingIP4Config *s_ip4;
|
|
|
|
|
NMSettingIP6Config *s_ip6;
|
|
|
|
|
NMSetting *setting;
|
|
|
|
|
const char *method;
|
|
|
|
|
|
|
|
|
|
s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
|
|
|
|
s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
|
|
|
|
|
|
|
|
|
if (nm_setting_connection_get_master (s_con)) {
|
core: don't have IP4 and IP6 configs on slaves
Although it's convenient in some places to have IP configs on all
connections, it makes more sense in other places to not have IP
configs on slaves. (eg, it's confusing for nmcli, etc, to report a
full NMSettingIP4Config on a slave device). So revert parts of the
earlier patch. However, it's still safe to assume that s_ip4 != NULL
if method != DISABLED, so some of the earlier simplifications can
stay.
Also, add nm_utils_get_ip_config_method(), which returns the correct
IP config method for a connection, whether the connection has IP4 and
IP6 settings objects or not, and use that to keep some more of the
simplifications from the earlier patch.
2013-10-14 10:38:56 -04:00
|
|
|
/* Slave connections don't have IP configuration. */
|
2013-09-26 17:34:23 -04:00
|
|
|
|
|
|
|
|
if (s_ip4) {
|
|
|
|
|
method = nm_setting_ip4_config_get_method (s_ip4);
|
|
|
|
|
if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED) != 0) {
|
|
|
|
|
nm_log_warn (LOGD_SETTINGS, "ignoring IP4 config on slave '%s'",
|
|
|
|
|
nm_connection_get_id (connection));
|
|
|
|
|
}
|
core: don't have IP4 and IP6 configs on slaves
Although it's convenient in some places to have IP configs on all
connections, it makes more sense in other places to not have IP
configs on slaves. (eg, it's confusing for nmcli, etc, to report a
full NMSettingIP4Config on a slave device). So revert parts of the
earlier patch. However, it's still safe to assume that s_ip4 != NULL
if method != DISABLED, so some of the earlier simplifications can
stay.
Also, add nm_utils_get_ip_config_method(), which returns the correct
IP config method for a connection, whether the connection has IP4 and
IP6 settings objects or not, and use that to keep some more of the
simplifications from the earlier patch.
2013-10-14 10:38:56 -04:00
|
|
|
nm_connection_remove_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
|
|
|
|
|
s_ip4 = NULL;
|
2013-09-26 17:34:23 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (s_ip6) {
|
|
|
|
|
method = nm_setting_ip6_config_get_method (s_ip6);
|
|
|
|
|
if (g_strcmp0 (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE) != 0) {
|
|
|
|
|
nm_log_warn (LOGD_SETTINGS, "ignoring IP6 config on slave '%s'",
|
|
|
|
|
nm_connection_get_id (connection));
|
|
|
|
|
}
|
core: don't have IP4 and IP6 configs on slaves
Although it's convenient in some places to have IP configs on all
connections, it makes more sense in other places to not have IP
configs on slaves. (eg, it's confusing for nmcli, etc, to report a
full NMSettingIP4Config on a slave device). So revert parts of the
earlier patch. However, it's still safe to assume that s_ip4 != NULL
if method != DISABLED, so some of the earlier simplifications can
stay.
Also, add nm_utils_get_ip_config_method(), which returns the correct
IP config method for a connection, whether the connection has IP4 and
IP6 settings objects or not, and use that to keep some more of the
simplifications from the earlier patch.
2013-10-14 10:38:56 -04:00
|
|
|
nm_connection_remove_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
|
|
|
|
s_ip6 = NULL;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* Ensure all non-slave connections have IP4 and IP6 settings objects. If no
|
|
|
|
|
* IP6 setting was specified, then assume that means IP6 config is allowed
|
|
|
|
|
* to fail. But if no IP4 setting was specified, assume the caller was just
|
|
|
|
|
* being lazy.
|
|
|
|
|
*/
|
|
|
|
|
if (!s_ip4) {
|
|
|
|
|
setting = nm_setting_ip4_config_new ();
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
g_object_set (setting,
|
|
|
|
|
NM_SETTING_IP4_CONFIG_METHOD, default_ip4_method,
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
|
|
|
|
if (!s_ip6) {
|
|
|
|
|
setting = nm_setting_ip6_config_new ();
|
|
|
|
|
nm_connection_add_setting (connection, setting);
|
|
|
|
|
|
|
|
|
|
g_object_set (setting,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_METHOD, default_ip6_method,
|
|
|
|
|
NM_SETTING_IP6_CONFIG_MAY_FAIL, TRUE,
|
|
|
|
|
NULL);
|
2013-09-26 17:34:23 -04:00
|
|
|
}
|
|
|
|
|
}
|
core: don't have IP4 and IP6 configs on slaves
Although it's convenient in some places to have IP configs on all
connections, it makes more sense in other places to not have IP
configs on slaves. (eg, it's confusing for nmcli, etc, to report a
full NMSettingIP4Config on a slave device). So revert parts of the
earlier patch. However, it's still safe to assume that s_ip4 != NULL
if method != DISABLED, so some of the earlier simplifications can
stay.
Also, add nm_utils_get_ip_config_method(), which returns the correct
IP config method for a connection, whether the connection has IP4 and
IP6 settings objects or not, and use that to keep some more of the
simplifications from the earlier patch.
2013-10-14 10:38:56 -04:00
|
|
|
}
|
2013-09-26 17:34:23 -04:00
|
|
|
|
core: don't have IP4 and IP6 configs on slaves
Although it's convenient in some places to have IP configs on all
connections, it makes more sense in other places to not have IP
configs on slaves. (eg, it's confusing for nmcli, etc, to report a
full NMSettingIP4Config on a slave device). So revert parts of the
earlier patch. However, it's still safe to assume that s_ip4 != NULL
if method != DISABLED, so some of the earlier simplifications can
stay.
Also, add nm_utils_get_ip_config_method(), which returns the correct
IP config method for a connection, whether the connection has IP4 and
IP6 settings objects or not, and use that to keep some more of the
simplifications from the earlier patch.
2013-10-14 10:38:56 -04:00
|
|
|
const char *
|
|
|
|
|
nm_utils_get_ip_config_method (NMConnection *connection,
|
|
|
|
|
GType ip_setting_type)
|
|
|
|
|
{
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
NMSettingIP4Config *s_ip4;
|
|
|
|
|
NMSettingIP6Config *s_ip6;
|
|
|
|
|
const char *method;
|
2013-09-26 17:34:23 -04:00
|
|
|
|
core: don't have IP4 and IP6 configs on slaves
Although it's convenient in some places to have IP configs on all
connections, it makes more sense in other places to not have IP
configs on slaves. (eg, it's confusing for nmcli, etc, to report a
full NMSettingIP4Config on a slave device). So revert parts of the
earlier patch. However, it's still safe to assume that s_ip4 != NULL
if method != DISABLED, so some of the earlier simplifications can
stay.
Also, add nm_utils_get_ip_config_method(), which returns the correct
IP config method for a connection, whether the connection has IP4 and
IP6 settings objects or not, and use that to keep some more of the
simplifications from the earlier patch.
2013-10-14 10:38:56 -04:00
|
|
|
s_con = nm_connection_get_setting_connection (connection);
|
|
|
|
|
|
|
|
|
|
if (ip_setting_type == NM_TYPE_SETTING_IP4_CONFIG) {
|
|
|
|
|
g_return_val_if_fail (s_con != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
|
|
|
|
|
|
|
|
|
|
if (nm_setting_connection_get_master (s_con))
|
|
|
|
|
return NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
|
|
|
|
|
else {
|
|
|
|
|
s_ip4 = nm_connection_get_setting_ip4_config (connection);
|
|
|
|
|
g_return_val_if_fail (s_ip4 != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
|
|
|
|
|
method = nm_setting_ip4_config_get_method (s_ip4);
|
|
|
|
|
g_return_val_if_fail (method != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
|
|
|
|
|
|
|
|
|
|
return method;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else if (ip_setting_type == NM_TYPE_SETTING_IP6_CONFIG) {
|
|
|
|
|
g_return_val_if_fail (s_con != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
|
|
|
|
|
|
|
|
|
|
if (nm_setting_connection_get_master (s_con))
|
|
|
|
|
return NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
|
|
|
|
|
else {
|
|
|
|
|
s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
|
|
|
|
g_return_val_if_fail (s_ip6 != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
|
|
|
|
|
method = nm_setting_ip6_config_get_method (s_ip6);
|
|
|
|
|
g_return_val_if_fail (method != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO);
|
|
|
|
|
|
|
|
|
|
return method;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else
|
|
|
|
|
g_assert_not_reached ();
|
2013-09-26 17:34:23 -04:00
|
|
|
}
|
|
|
|
|
|
2011-01-13 13:28:52 -06:00
|
|
|
void
|
|
|
|
|
nm_utils_complete_generic (NMConnection *connection,
|
|
|
|
|
const char *ctype,
|
|
|
|
|
const GSList *existing,
|
|
|
|
|
const char *format,
|
2011-02-25 11:58:16 -06:00
|
|
|
const char *preferred,
|
|
|
|
|
gboolean default_enable_ipv6)
|
2011-01-13 13:28:52 -06:00
|
|
|
{
|
|
|
|
|
NMSettingConnection *s_con;
|
|
|
|
|
char *id, *uuid;
|
|
|
|
|
|
2011-12-05 12:27:47 +01:00
|
|
|
s_con = nm_connection_get_setting_connection (connection);
|
2011-01-13 13:28:52 -06:00
|
|
|
if (!s_con) {
|
|
|
|
|
s_con = (NMSettingConnection *) nm_setting_connection_new ();
|
|
|
|
|
nm_connection_add_setting (connection, NM_SETTING (s_con));
|
|
|
|
|
}
|
|
|
|
|
g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_TYPE, ctype, NULL);
|
|
|
|
|
|
|
|
|
|
if (!nm_setting_connection_get_uuid (s_con)) {
|
|
|
|
|
uuid = nm_utils_uuid_generate ();
|
|
|
|
|
g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_UUID, uuid, NULL);
|
|
|
|
|
g_free (uuid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Add a connection ID if absent */
|
|
|
|
|
if (!nm_setting_connection_get_id (s_con)) {
|
|
|
|
|
id = get_new_connection_name (existing, format, preferred);
|
|
|
|
|
g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_ID, id, NULL);
|
|
|
|
|
g_free (id);
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-26 17:34:23 -04:00
|
|
|
/* Normalize */
|
|
|
|
|
nm_utils_normalize_connection (connection, default_enable_ipv6);
|
2011-01-13 13:28:52 -06:00
|
|
|
}
|
|
|
|
|
|
2012-02-12 14:48:44 -06:00
|
|
|
char *
|
2012-02-22 23:40:18 -06:00
|
|
|
nm_utils_new_vlan_name (const char *parent_iface, guint32 vlan_id)
|
2012-02-12 14:48:44 -06:00
|
|
|
{
|
2012-08-06 13:05:05 -05:00
|
|
|
/* Basically VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD */
|
2012-02-22 23:40:18 -06:00
|
|
|
return g_strdup_printf ("%s.%d", parent_iface, vlan_id);
|
2012-02-12 14:48:44 -06:00
|
|
|
}
|
|
|
|
|
|
2013-11-19 22:28:36 -06:00
|
|
|
/**
|
|
|
|
|
* nm_utils_read_resolv_conf_nameservers():
|
|
|
|
|
* @rc_contents: contents of a resolv.conf; or %NULL to read /etc/resolv.conf
|
|
|
|
|
*
|
|
|
|
|
* Reads all nameservers out of @rc_contents or /etc/resolv.conf and returns
|
|
|
|
|
* them.
|
|
|
|
|
*
|
|
|
|
|
* Returns: a #GPtrArray of 'char *' elements of each nameserver line from
|
|
|
|
|
* @contents or resolv.conf
|
|
|
|
|
*/
|
|
|
|
|
GPtrArray *
|
|
|
|
|
nm_utils_read_resolv_conf_nameservers (const char *rc_contents)
|
|
|
|
|
{
|
|
|
|
|
GPtrArray *nameservers = NULL;
|
|
|
|
|
char *contents = NULL;
|
|
|
|
|
char **lines, **iter;
|
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
|
|
if (rc_contents)
|
|
|
|
|
contents = g_strdup (rc_contents);
|
|
|
|
|
else {
|
|
|
|
|
if (!g_file_get_contents (_PATH_RESCONF, &contents, NULL, NULL))
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nameservers = g_ptr_array_new_full (3, g_free);
|
|
|
|
|
|
|
|
|
|
lines = g_strsplit_set (contents, "\r\n", -1);
|
|
|
|
|
for (iter = lines; *iter; iter++) {
|
|
|
|
|
if (!g_str_has_prefix (*iter, "nameserver"))
|
|
|
|
|
continue;
|
|
|
|
|
p = *iter + strlen ("nameserver");
|
|
|
|
|
if (!g_ascii_isspace (*p++))
|
|
|
|
|
continue;
|
|
|
|
|
/* Skip intermediate whitespace */
|
|
|
|
|
while (g_ascii_isspace (*p))
|
|
|
|
|
p++;
|
|
|
|
|
g_strchomp (p);
|
|
|
|
|
|
|
|
|
|
g_ptr_array_add (nameservers, g_strdup (p));
|
|
|
|
|
}
|
|
|
|
|
g_strfreev (lines);
|
|
|
|
|
g_free (contents);
|
|
|
|
|
|
|
|
|
|
return nameservers;
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-15 13:09:12 -06:00
|
|
|
static NMConnection *
|
|
|
|
|
check_possible_match (NMConnection *orig,
|
|
|
|
|
NMConnection *candidate,
|
|
|
|
|
GHashTable *settings)
|
|
|
|
|
{
|
|
|
|
|
GHashTable *props;
|
|
|
|
|
const char *orig_ip6_method, *candidate_ip6_method;
|
|
|
|
|
NMSettingIP6Config *candidate_ip6;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (settings != NULL, NULL);
|
|
|
|
|
|
|
|
|
|
props = g_hash_table_lookup (settings, NM_SETTING_IP6_CONFIG_SETTING_NAME);
|
|
|
|
|
if ( !props
|
|
|
|
|
|| (g_hash_table_size (props) != 1)
|
|
|
|
|
|| !g_hash_table_lookup (props, NM_SETTING_IP6_CONFIG_METHOD)) {
|
|
|
|
|
/* For now 'method' is the only difference we handle here */
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If the original connection is 'link-local' and the candidate is both 'auto'
|
|
|
|
|
* and may-fail=TRUE, then the candidate is OK to use. may-fail is included
|
|
|
|
|
* in the decision because if the candidate is 'auto' but may-fail=FALSE, then
|
|
|
|
|
* the connection could not possibly have been previously activated on the
|
|
|
|
|
* device if the device has no non-link-local IPv6 address.
|
|
|
|
|
*/
|
|
|
|
|
orig_ip6_method = nm_utils_get_ip_config_method (orig, NM_TYPE_SETTING_IP6_CONFIG);
|
|
|
|
|
candidate_ip6_method = nm_utils_get_ip_config_method (candidate, NM_TYPE_SETTING_IP6_CONFIG);
|
|
|
|
|
candidate_ip6 = nm_connection_get_setting_ip6_config (candidate);
|
|
|
|
|
|
|
|
|
|
if ( strcmp (orig_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0
|
|
|
|
|
&& strcmp (candidate_ip6_method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0
|
|
|
|
|
&& (!candidate_ip6 || nm_setting_ip6_config_get_may_fail (candidate_ip6))) {
|
|
|
|
|
return candidate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_utils_match_connection:
|
|
|
|
|
* @connections: a (optionally pre-sorted) list of connections from which to
|
|
|
|
|
* find a matching connection to @original based on "inferrable" properties
|
|
|
|
|
* @original: the #NMConnection to find a match for from @connections
|
|
|
|
|
* @match_filter_func: a function to check whether each connection from @connections
|
|
|
|
|
* should be considered for matching. This function should return %TRUE if the
|
|
|
|
|
* connection should be considered, %FALSE if the connection should be ignored
|
|
|
|
|
* @match_compat_data: data pointer passed to @match_filter_func
|
|
|
|
|
*
|
|
|
|
|
* Checks each connection from @connections until a matching connection is found
|
|
|
|
|
* considering only setting properties marked with %NM_SETTING_PARAM_INFERRABLE
|
|
|
|
|
* and checking a few other characteristics like IPv6 method. If the caller
|
|
|
|
|
* desires some priority order of the connections, @connections should be
|
|
|
|
|
* sorted before calling this function.
|
|
|
|
|
*
|
|
|
|
|
* Returns: the best #NMConnection matching @original, or %NULL if no connection
|
|
|
|
|
* matches well enough.
|
|
|
|
|
*/
|
|
|
|
|
NMConnection *
|
|
|
|
|
nm_utils_match_connection (GSList *connections,
|
|
|
|
|
NMConnection *original,
|
|
|
|
|
NMUtilsMatchFilterFunc match_filter_func,
|
|
|
|
|
gpointer match_filter_data)
|
|
|
|
|
{
|
|
|
|
|
NMConnection *best_match = NULL;
|
|
|
|
|
GSList *iter;
|
|
|
|
|
|
|
|
|
|
for (iter = connections; iter; iter = iter->next) {
|
|
|
|
|
NMConnection *candidate = NM_CONNECTION (iter->data);
|
|
|
|
|
GHashTable *diffs = NULL;
|
|
|
|
|
|
|
|
|
|
if (match_filter_func) {
|
|
|
|
|
if (!match_filter_func (candidate, match_filter_data))
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!nm_connection_diff (original, candidate, NM_SETTING_COMPARE_FLAG_INFERRABLE, &diffs)) {
|
|
|
|
|
if (!best_match)
|
|
|
|
|
best_match = check_possible_match (original, candidate, diffs);
|
|
|
|
|
g_hash_table_unref (diffs);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Exact match */
|
|
|
|
|
return candidate;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Best match (if any) */
|
|
|
|
|
return best_match;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-21 13:07:06 +01:00
|
|
|
/* nm_utils_ascii_str_to_int64:
|
|
|
|
|
*
|
|
|
|
|
* A wrapper for g_ascii_strtoll, that checks whether the whole string
|
|
|
|
|
* can be successfully converted to a number and is within a given
|
|
|
|
|
* range. On any error, @fallback will be returned and @errno will be set
|
|
|
|
|
* to a non-zero value. Check @errno for errors. Any trailing or leading
|
|
|
|
|
* (ascii) white space is ignored and the functions is locale independent.
|
|
|
|
|
*
|
|
|
|
|
* The function is guaranteed to return a value between @min and @max
|
|
|
|
|
* (included) or @fallback. Also, the parsing is rather strict, it does
|
|
|
|
|
* not allow for any unrecognized characters, except leading and trailing
|
|
|
|
|
* white space.
|
|
|
|
|
**/
|
|
|
|
|
gint64
|
|
|
|
|
nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback)
|
|
|
|
|
{
|
|
|
|
|
gint64 v;
|
|
|
|
|
char *end;
|
|
|
|
|
char *str_free = NULL;
|
|
|
|
|
|
|
|
|
|
if (str) {
|
|
|
|
|
while (str[0] && g_ascii_isspace (str[0]))
|
|
|
|
|
str++;
|
|
|
|
|
}
|
|
|
|
|
if (!str || !str[0]) {
|
|
|
|
|
errno = EINVAL;
|
|
|
|
|
return fallback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (g_ascii_isspace (str[strlen (str) - 1])) {
|
|
|
|
|
str_free = g_strdup (str);
|
|
|
|
|
g_strstrip (str_free);
|
|
|
|
|
str = str_free;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
|
v = g_ascii_strtoll (str, &end, base);
|
|
|
|
|
|
|
|
|
|
if (errno != 0) {
|
|
|
|
|
g_free (str_free);
|
|
|
|
|
return fallback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (end[0] != 0) {
|
|
|
|
|
g_free (str_free);
|
|
|
|
|
errno = EINVAL;
|
|
|
|
|
return fallback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_free (str_free);
|
|
|
|
|
if (v > max || v < min) {
|
|
|
|
|
errno = ERANGE;
|
|
|
|
|
return fallback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return v;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2013-12-10 13:16:08 +01:00
|
|
|
static gint64 monotonic_timestamp_offset_sec;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
monotonic_timestamp_get (struct timespec *tp)
|
|
|
|
|
{
|
|
|
|
|
static gboolean initialized = FALSE;
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
err = clock_gettime (CLOCK_BOOTTIME, tp);
|
|
|
|
|
|
|
|
|
|
g_assert (err == 0); (void)err;
|
|
|
|
|
g_assert (tp->tv_nsec >= 0 && tp->tv_nsec < NM_UTILS_NS_PER_SECOND);
|
|
|
|
|
|
|
|
|
|
if (G_LIKELY (initialized))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Calculate an offset for the time stamp.
|
|
|
|
|
*
|
|
|
|
|
* We always want positive values, because then we can initialize
|
|
|
|
|
* a timestamp with 0 and be sure, that it will be less then any
|
|
|
|
|
* value nm_utils_get_monotonic_timestamp_*() might return.
|
|
|
|
|
* For this to be true also for nm_utils_get_monotonic_timestamp_s() at
|
|
|
|
|
* early boot, we have to shift the timestamp to start counting at
|
|
|
|
|
* least from 1 second onward.
|
|
|
|
|
*
|
|
|
|
|
* Another advantage of shifting is, that this way we make use of the whole 31 bit
|
|
|
|
|
* range of signed int, before the time stamp for nm_utils_get_monotonic_timestamp_s()
|
|
|
|
|
* wraps (~68 years).
|
|
|
|
|
**/
|
|
|
|
|
monotonic_timestamp_offset_sec = (- ((gint64) tp->tv_sec)) + 1;
|
|
|
|
|
initialized = TRUE;
|
|
|
|
|
|
|
|
|
|
if (nm_logging_enabled (LOGL_DEBUG, LOGD_CORE)) {
|
|
|
|
|
time_t now = time (NULL);
|
|
|
|
|
struct tm tm;
|
|
|
|
|
char s[255];
|
|
|
|
|
|
|
|
|
|
strftime (s, sizeof (s), "%Y-%m-%d %H:%M:%S", localtime_r (&now, &tm));
|
2014-01-31 13:25:04 +01:00
|
|
|
nm_log_dbg (LOGD_CORE, "monotonic timestamp started counting 1.%09ld seconds ago with "
|
|
|
|
|
"an offset of %lld.0 seconds to CLOCK_BOOTTIME (local time is %s)",
|
|
|
|
|
tp->tv_nsec, (long long) -monotonic_timestamp_offset_sec, s);
|
2013-12-10 13:16:08 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-11 11:17:40 +01:00
|
|
|
/**
|
|
|
|
|
* nm_utils_get_monotonic_timestamp_us:
|
|
|
|
|
*
|
|
|
|
|
* Returns: a monotonically increasing time stamp in microseconds,
|
|
|
|
|
* starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
|
|
|
|
|
*
|
|
|
|
|
* The returned value will start counting at an undefined point
|
|
|
|
|
* in the past and will always be positive.
|
|
|
|
|
**/
|
|
|
|
|
gint64
|
|
|
|
|
nm_utils_get_monotonic_timestamp_us (void)
|
|
|
|
|
{
|
|
|
|
|
struct timespec tp;
|
|
|
|
|
|
|
|
|
|
monotonic_timestamp_get (&tp);
|
|
|
|
|
|
|
|
|
|
/* Although the result will always be positive, we return a signed
|
|
|
|
|
* integer, which makes it easier to calculate time differences (when
|
|
|
|
|
* you want to subtract signed values).
|
|
|
|
|
**/
|
|
|
|
|
return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec) * ((gint64) G_USEC_PER_SEC) +
|
|
|
|
|
(tp.tv_nsec / (NM_UTILS_NS_PER_SECOND/G_USEC_PER_SEC));
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-10 13:16:08 +01:00
|
|
|
/**
|
|
|
|
|
* nm_utils_get_monotonic_timestamp_ms:
|
|
|
|
|
*
|
|
|
|
|
* Returns: a monotonically increasing time stamp in milliseconds,
|
|
|
|
|
* starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
|
|
|
|
|
*
|
|
|
|
|
* The returned value will start counting at an undefined point
|
|
|
|
|
* in the past and will always be positive.
|
|
|
|
|
**/
|
|
|
|
|
gint64
|
|
|
|
|
nm_utils_get_monotonic_timestamp_ms (void)
|
|
|
|
|
{
|
|
|
|
|
struct timespec tp;
|
|
|
|
|
|
|
|
|
|
monotonic_timestamp_get (&tp);
|
|
|
|
|
|
|
|
|
|
/* Although the result will always be positive, we return a signed
|
|
|
|
|
* integer, which makes it easier to calculate time differences (when
|
|
|
|
|
* you want to subtract signed values).
|
|
|
|
|
**/
|
|
|
|
|
return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec) * ((gint64) 1000) +
|
|
|
|
|
(tp.tv_nsec / (NM_UTILS_NS_PER_SECOND/1000));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_utils_get_monotonic_timestamp_s:
|
|
|
|
|
*
|
|
|
|
|
* Returns: nm_utils_get_monotonic_timestamp_ms() in seconds (throwing
|
|
|
|
|
* away sub second parts). The returned value will always be positive.
|
|
|
|
|
*
|
|
|
|
|
* This value wraps after roughly 68 years which should be fine for any
|
|
|
|
|
* practical purpose.
|
|
|
|
|
**/
|
|
|
|
|
gint32
|
|
|
|
|
nm_utils_get_monotonic_timestamp_s (void)
|
|
|
|
|
{
|
|
|
|
|
struct timespec tp;
|
|
|
|
|
|
|
|
|
|
monotonic_timestamp_get (&tp);
|
|
|
|
|
return (((gint64) tp.tv_sec) + monotonic_timestamp_offset_sec);
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-21 13:07:06 +01:00
|
|
|
|