2013-03-27 22:23:24 +01:00
|
|
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
|
|
|
|
/* nm-platform.c - Handle runtime kernel networking configuration
|
|
|
|
|
*
|
|
|
|
|
* 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, 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.,
|
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
|
*
|
|
|
|
|
* Copyright (C) 2012 Red Hat, Inc.
|
|
|
|
|
*/
|
|
|
|
|
|
2014-11-13 10:07:02 -05:00
|
|
|
#include "config.h"
|
|
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#include <netinet/in.h>
|
2013-03-27 22:23:24 +01:00
|
|
|
#include <arpa/inet.h>
|
2013-04-03 16:10:38 +02:00
|
|
|
#include <string.h>
|
2013-10-15 20:44:59 +02:00
|
|
|
#include <netlink/route/addr.h>
|
2013-03-27 22:23:24 +01:00
|
|
|
|
2014-10-29 17:23:46 +01:00
|
|
|
#include "gsystem-local-alloc.h"
|
2013-12-10 19:04:22 +01:00
|
|
|
#include "NetworkManagerUtils.h"
|
2014-01-30 20:31:29 +01:00
|
|
|
#include "nm-utils.h"
|
2013-03-27 22:23:24 +01:00
|
|
|
#include "nm-platform.h"
|
2014-01-06 19:59:17 +01:00
|
|
|
#include "NetworkManagerUtils.h"
|
2013-03-27 22:23:24 +01:00
|
|
|
#include "nm-logging.h"
|
2013-08-02 18:51:06 +02:00
|
|
|
#include "nm-enum-types.h"
|
2013-03-27 22:23:24 +01:00
|
|
|
|
|
|
|
|
#define debug(...) nm_log_dbg (LOGD_PLATFORM, __VA_ARGS__)
|
|
|
|
|
|
|
|
|
|
#define NM_PLATFORM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_PLATFORM, NMPlatformPrivate))
|
|
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (NMPlatform, nm_platform, G_TYPE_OBJECT)
|
|
|
|
|
|
|
|
|
|
/* NMPlatform signals */
|
|
|
|
|
enum {
|
2014-03-07 19:04:38 +01:00
|
|
|
SIGNAL_LINK_CHANGED,
|
|
|
|
|
SIGNAL_IP4_ADDRESS_CHANGED,
|
|
|
|
|
SIGNAL_IP6_ADDRESS_CHANGED,
|
|
|
|
|
SIGNAL_IP4_ROUTE_CHANGED,
|
|
|
|
|
SIGNAL_IP6_ROUTE_CHANGED,
|
2013-03-27 22:23:24 +01:00
|
|
|
LAST_SIGNAL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static guint signals[LAST_SIGNAL] = { 0 };
|
|
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
|
|
|
|
|
|
|
|
/* Singleton NMPlatform subclass instance and cached class object */
|
|
|
|
|
static NMPlatform *platform = NULL;
|
|
|
|
|
static NMPlatformClass *klass = NULL;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_setup:
|
|
|
|
|
* @type: The #GType for a subclass of #NMPlatform
|
|
|
|
|
*
|
|
|
|
|
* Do not use this function directly, it is intended to be called by
|
|
|
|
|
* NMPlatform subclasses. For the linux platform initialization use
|
|
|
|
|
* nm_linux_platform_setup() instead.
|
|
|
|
|
*
|
|
|
|
|
* Failing to set up #NMPlatform singleton results in a fatal error,
|
|
|
|
|
* as well as trying to initialize it multiple times without freeing
|
|
|
|
|
* it.
|
|
|
|
|
*
|
|
|
|
|
* NetworkManager will typically use only one platform object during
|
|
|
|
|
* its run. Test programs might want to switch platform implementations,
|
|
|
|
|
* though. This is done with a combination of nm_platform_free() and
|
|
|
|
|
* nm_*_platform_setup().
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_platform_setup (GType type)
|
|
|
|
|
{
|
|
|
|
|
gboolean status;
|
|
|
|
|
|
|
|
|
|
g_assert (platform == NULL);
|
|
|
|
|
|
|
|
|
|
platform = g_object_new (type, NULL);
|
|
|
|
|
g_assert (NM_IS_PLATFORM (platform));
|
|
|
|
|
|
|
|
|
|
klass = NM_PLATFORM_GET_CLASS (platform);
|
|
|
|
|
g_assert (klass->setup);
|
|
|
|
|
|
|
|
|
|
status = klass->setup (platform);
|
|
|
|
|
g_assert (status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_free:
|
|
|
|
|
*
|
|
|
|
|
* Free #NMPlatform singleton created by nm_*_platform_setup().
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_platform_free (void)
|
|
|
|
|
{
|
|
|
|
|
g_assert (platform);
|
|
|
|
|
|
|
|
|
|
g_object_unref (platform);
|
|
|
|
|
platform = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_get:
|
|
|
|
|
*
|
|
|
|
|
* Retrieve #NMPlatform singleton. Use this whenever you want to connect to
|
|
|
|
|
* #NMPlatform signals. It is an error to call it before nm_*_platform_setup()
|
|
|
|
|
* or after nm_platform_free().
|
|
|
|
|
*
|
|
|
|
|
* Returns: (transfer none): The #NMPlatform singleton reference.
|
|
|
|
|
*/
|
|
|
|
|
NMPlatform *
|
|
|
|
|
nm_platform_get (void)
|
|
|
|
|
{
|
|
|
|
|
g_assert (platform);
|
|
|
|
|
|
|
|
|
|
return platform;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
|
|
|
|
2013-04-29 13:57:58 +02:00
|
|
|
/**
|
|
|
|
|
* nm_platform_set_error:
|
|
|
|
|
* @error: The error code
|
|
|
|
|
*
|
|
|
|
|
* Convenience function to falsify platform->error. It can be used for example
|
|
|
|
|
* by functions that want to save the error, execute some operations and
|
|
|
|
|
* restore it.
|
|
|
|
|
*/
|
|
|
|
|
void nm_platform_set_error (NMPlatformError error)
|
|
|
|
|
{
|
|
|
|
|
platform->error = error;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
/**
|
|
|
|
|
* nm_platform_get_error:
|
|
|
|
|
*
|
|
|
|
|
* Convenience function to quickly retrieve the error code of the last
|
|
|
|
|
* operation.
|
|
|
|
|
*
|
|
|
|
|
* Returns: Integer error code.
|
|
|
|
|
*/
|
2013-04-29 13:57:58 +02:00
|
|
|
NMPlatformError
|
2013-03-27 22:23:24 +01:00
|
|
|
nm_platform_get_error (void)
|
|
|
|
|
{
|
|
|
|
|
g_assert (platform);
|
|
|
|
|
|
|
|
|
|
return platform->error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_get_error_message:
|
|
|
|
|
*
|
|
|
|
|
* Returns: Static human-readable string for the error. Don't free.
|
|
|
|
|
*/
|
|
|
|
|
const char *
|
|
|
|
|
nm_platform_get_error_msg (void)
|
|
|
|
|
{
|
|
|
|
|
g_assert (platform);
|
|
|
|
|
|
|
|
|
|
switch (platform->error) {
|
|
|
|
|
case NM_PLATFORM_ERROR_NONE:
|
|
|
|
|
return "unknown error";
|
|
|
|
|
case NM_PLATFORM_ERROR_NOT_FOUND:
|
|
|
|
|
return "object not found";
|
|
|
|
|
case NM_PLATFORM_ERROR_EXISTS:
|
|
|
|
|
return "object already exists";
|
2013-06-10 16:21:08 -03:00
|
|
|
case NM_PLATFORM_ERROR_WRONG_TYPE:
|
|
|
|
|
return "object is wrong type";
|
2013-05-24 00:29:57 +02:00
|
|
|
case NM_PLATFORM_ERROR_NOT_SLAVE:
|
|
|
|
|
return "link not a slave";
|
2013-05-24 00:29:21 +02:00
|
|
|
case NM_PLATFORM_ERROR_NO_FIRMWARE:
|
|
|
|
|
return "firmware not found";
|
2013-03-27 22:23:24 +01:00
|
|
|
default:
|
|
|
|
|
return "invalid error number";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
reset_error (void)
|
|
|
|
|
{
|
|
|
|
|
g_assert (platform);
|
|
|
|
|
platform->error = NM_PLATFORM_ERROR_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-03 16:07:36 +01:00
|
|
|
#define IFA_F_MANAGETEMPADDR_STR "mngtmpaddr"
|
|
|
|
|
#define IFA_F_NOPREFIXROUTE_STR "noprefixroute"
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_check_support_libnl_extended_ifa_flags ()
|
|
|
|
|
{
|
|
|
|
|
static int supported = -1;
|
|
|
|
|
|
|
|
|
|
/* support for extended ifa-flags was added together
|
|
|
|
|
* with the IFA_F_MANAGETEMPADDR flag. So, check if libnl
|
|
|
|
|
* is able to parse this flag. */
|
|
|
|
|
if (supported == -1)
|
|
|
|
|
supported = rtnl_addr_str2flags (IFA_F_MANAGETEMPADDR_STR) == IFA_F_MANAGETEMPADDR;
|
|
|
|
|
|
|
|
|
|
return supported;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-07 17:21:12 +01:00
|
|
|
gboolean
|
|
|
|
|
nm_platform_check_support_kernel_extended_ifa_flags ()
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_PLATFORM (platform), FALSE);
|
|
|
|
|
|
|
|
|
|
if (!klass->check_support_kernel_extended_ifa_flags)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
return klass->check_support_kernel_extended_ifa_flags (platform);
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 15:57:08 -05:00
|
|
|
gboolean
|
|
|
|
|
nm_platform_check_support_user_ipv6ll (void)
|
|
|
|
|
{
|
|
|
|
|
static int supported = -1;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_PLATFORM (platform), FALSE);
|
|
|
|
|
|
|
|
|
|
if (!klass->check_support_user_ipv6ll)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (supported < 0)
|
|
|
|
|
supported = klass->check_support_user_ipv6ll (platform) ? 1 : 0;
|
|
|
|
|
return !!supported;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
/******************************************************************/
|
|
|
|
|
|
2013-04-03 16:10:38 +02:00
|
|
|
/**
|
|
|
|
|
* nm_platform_sysctl_set:
|
|
|
|
|
* @path: Absolute option path
|
|
|
|
|
* @value: Value to write
|
|
|
|
|
*
|
|
|
|
|
* This function is intended to be used for writing values to sysctl-style
|
|
|
|
|
* virtual runtime configuration files. This includes not only /proc/sys
|
|
|
|
|
* but also for example /sys/class.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE on success.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_sysctl_set (const char *path, const char *value)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (path, FALSE);
|
|
|
|
|
g_return_val_if_fail (value, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->sysctl_set, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->sysctl_set (platform, path, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_sysctl_get:
|
|
|
|
|
* @path: Absolute path to sysctl
|
|
|
|
|
*
|
|
|
|
|
* Returns: (transfer full): Contents of the virtual sysctl file.
|
|
|
|
|
*/
|
|
|
|
|
char *
|
2014-02-25 13:23:07 -05:00
|
|
|
nm_platform_sysctl_get (const char *path)
|
2013-04-03 16:10:38 +02:00
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (path, NULL);
|
|
|
|
|
g_return_val_if_fail (klass->sysctl_get, NULL);
|
|
|
|
|
|
2014-02-25 13:23:07 -05:00
|
|
|
return klass->sysctl_get (platform, path);
|
2013-04-03 16:10:38 +02:00
|
|
|
}
|
|
|
|
|
|
2013-11-08 08:49:06 -05:00
|
|
|
/**
|
2014-01-06 19:59:17 +01:00
|
|
|
* nm_platform_sysctl_get_int32:
|
2013-11-08 08:49:06 -05:00
|
|
|
* @path: Absolute path to sysctl
|
2014-01-06 19:59:17 +01:00
|
|
|
* @fallback: default value, if the content of path could not be read
|
|
|
|
|
* as decimal integer.
|
2013-11-08 08:49:06 -05:00
|
|
|
*
|
2014-01-06 19:59:17 +01:00
|
|
|
* Returns: contents of the sysctl file parsed as s32 integer, or
|
2014-03-23 14:57:39 +01:00
|
|
|
* @fallback on error. On error, %errno will be set to a non-zero
|
|
|
|
|
* value, on success %errno will be set to zero.
|
2013-11-08 08:49:06 -05:00
|
|
|
*/
|
2014-01-06 19:59:17 +01:00
|
|
|
gint32
|
|
|
|
|
nm_platform_sysctl_get_int32 (const char *path, gint32 fallback)
|
2014-03-12 12:27:58 +01:00
|
|
|
{
|
|
|
|
|
return nm_platform_sysctl_get_int_checked (path, 10, G_MININT32, G_MAXINT32, fallback);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_sysctl_get_int_checked:
|
|
|
|
|
* @path: Absolute path to sysctl
|
|
|
|
|
* @base: base of numeric conversion
|
|
|
|
|
* @min: minimal value that is still valid
|
|
|
|
|
* @max: maximal value that is still valid
|
|
|
|
|
* @fallback: default value, if the content of path could not be read
|
|
|
|
|
* as valid integer.
|
|
|
|
|
*
|
|
|
|
|
* Returns: contents of the sysctl file parsed as s64 integer, or
|
|
|
|
|
* @fallback on error. On error, %errno will be set to a non-zero
|
|
|
|
|
* value. On success, %errno will be set to zero. The returned value
|
|
|
|
|
* will always be in the range between @min and @max
|
|
|
|
|
* (inclusive) or @fallback.
|
|
|
|
|
*/
|
|
|
|
|
gint64
|
|
|
|
|
nm_platform_sysctl_get_int_checked (const char *path, guint base, gint64 min, gint64 max, gint64 fallback)
|
2013-11-08 08:49:06 -05:00
|
|
|
{
|
2014-01-06 19:59:17 +01:00
|
|
|
char *value = NULL;
|
|
|
|
|
gint32 ret;
|
2013-11-08 08:49:06 -05:00
|
|
|
|
2014-01-06 19:59:17 +01:00
|
|
|
g_return_val_if_fail (path, fallback);
|
2013-11-08 08:49:06 -05:00
|
|
|
|
2014-01-06 19:59:17 +01:00
|
|
|
if (path)
|
2014-02-25 13:23:07 -05:00
|
|
|
value = nm_platform_sysctl_get (path);
|
2014-01-06 19:59:17 +01:00
|
|
|
|
|
|
|
|
if (!value) {
|
|
|
|
|
errno = EINVAL;
|
|
|
|
|
return fallback;
|
|
|
|
|
}
|
2013-11-08 08:49:06 -05:00
|
|
|
|
2014-03-12 12:27:58 +01:00
|
|
|
ret = nm_utils_ascii_str_to_int64 (value, base, min, max, fallback);
|
2014-01-06 19:59:17 +01:00
|
|
|
g_free (value);
|
2013-11-08 08:49:06 -05:00
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-03 16:10:38 +02:00
|
|
|
/******************************************************************/
|
|
|
|
|
|
2013-05-29 12:00:50 -03:00
|
|
|
/**
|
|
|
|
|
* nm_platform_query_devices:
|
|
|
|
|
*
|
2014-04-17 14:57:55 +02:00
|
|
|
* Emit #NMPlatform:link-changed ADDED signals for all currently-known links.
|
2013-05-29 12:00:50 -03:00
|
|
|
* Should only be called at startup.
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_platform_query_devices (void)
|
|
|
|
|
{
|
|
|
|
|
GArray *links_array;
|
|
|
|
|
NMPlatformLink *links;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
links_array = nm_platform_link_get_all ();
|
|
|
|
|
links = (NMPlatformLink *) links_array->data;
|
2013-08-05 17:03:14 -04:00
|
|
|
for (i = 0; i < links_array->len; i++) {
|
2014-03-07 19:04:38 +01:00
|
|
|
g_signal_emit (platform, signals[SIGNAL_LINK_CHANGED], 0,
|
|
|
|
|
links[i].ifindex, &links[i], NM_PLATFORM_SIGNAL_ADDED,
|
|
|
|
|
NM_PLATFORM_REASON_INTERNAL);
|
2013-08-05 17:03:14 -04:00
|
|
|
}
|
2013-05-29 12:00:50 -03:00
|
|
|
g_array_unref (links_array);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
/**
|
|
|
|
|
* nm_platform_link_get_all:
|
|
|
|
|
*
|
|
|
|
|
* Retrieve a snapshot of configuration for all links at once. The result is
|
|
|
|
|
* owned by the caller and should be freed with g_array_unref().
|
|
|
|
|
*/
|
|
|
|
|
GArray *
|
2013-05-29 12:00:50 -03:00
|
|
|
nm_platform_link_get_all (void)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
2013-11-06 22:15:03 -06:00
|
|
|
GArray *links, *result;
|
|
|
|
|
guint i, j, nresult;
|
|
|
|
|
GHashTable *unseen;
|
|
|
|
|
NMPlatformLink *item;
|
2013-06-03 11:49:55 -03:00
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (klass->link_get_all, NULL);
|
|
|
|
|
|
2013-06-03 11:49:55 -03:00
|
|
|
links = klass->link_get_all (platform);
|
2013-11-06 22:15:03 -06:00
|
|
|
|
|
|
|
|
if (!links || links->len == 0)
|
|
|
|
|
return links;
|
|
|
|
|
|
|
|
|
|
unseen = g_hash_table_new (g_direct_hash, g_direct_equal);
|
|
|
|
|
for (i = 0; i < links->len; i++) {
|
|
|
|
|
item = &g_array_index (links, NMPlatformLink, i);
|
|
|
|
|
|
|
|
|
|
if (item->ifindex <= 0 || g_hash_table_contains (unseen, GINT_TO_POINTER (item->ifindex))) {
|
|
|
|
|
g_warn_if_reached ();
|
|
|
|
|
item->ifindex = 0;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
g_hash_table_insert (unseen, GINT_TO_POINTER (item->ifindex), NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef G_DISABLE_ASSERT
|
|
|
|
|
/* Ensure that link_get_all returns a consistent and valid result. */
|
|
|
|
|
for (i = 0; i < links->len; i++) {
|
|
|
|
|
item = &g_array_index (links, NMPlatformLink, i);
|
|
|
|
|
|
|
|
|
|
if (!item->ifindex)
|
|
|
|
|
continue;
|
|
|
|
|
if (item->master != 0) {
|
|
|
|
|
g_warn_if_fail (item->master > 0);
|
|
|
|
|
g_warn_if_fail (item->master != item->ifindex);
|
|
|
|
|
g_warn_if_fail (g_hash_table_contains (unseen, GINT_TO_POINTER (item->master)));
|
|
|
|
|
}
|
|
|
|
|
if (item->parent != 0) {
|
|
|
|
|
g_warn_if_fail (item->parent > 0);
|
|
|
|
|
g_warn_if_fail (item->parent != item->ifindex);
|
|
|
|
|
g_warn_if_fail (g_hash_table_contains (unseen, GINT_TO_POINTER (item->parent)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Re-order the links list such that children/slaves come after all ancestors */
|
|
|
|
|
nresult = g_hash_table_size (unseen);
|
|
|
|
|
result = g_array_sized_new (TRUE, TRUE, sizeof (NMPlatformLink), nresult);
|
|
|
|
|
g_array_set_size (result, nresult);
|
|
|
|
|
|
|
|
|
|
j = 0;
|
|
|
|
|
do {
|
|
|
|
|
gboolean found_something = FALSE;
|
|
|
|
|
guint first_idx = G_MAXUINT;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < links->len; i++) {
|
|
|
|
|
item = &g_array_index (links, NMPlatformLink, i);
|
|
|
|
|
|
|
|
|
|
if (!item->ifindex)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (first_idx == G_MAXUINT)
|
|
|
|
|
first_idx = i;
|
|
|
|
|
|
|
|
|
|
g_assert (g_hash_table_contains (unseen, GINT_TO_POINTER (item->ifindex)));
|
|
|
|
|
|
|
|
|
|
if (item->master > 0 && g_hash_table_contains (unseen, GINT_TO_POINTER (item->master)))
|
|
|
|
|
continue;
|
|
|
|
|
if (item->parent > 0 && g_hash_table_contains (unseen, GINT_TO_POINTER (item->parent)))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
g_hash_table_remove (unseen, GINT_TO_POINTER (item->ifindex));
|
|
|
|
|
g_array_index (result, NMPlatformLink, j++) = *item;
|
|
|
|
|
item->ifindex = 0;
|
|
|
|
|
found_something = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!found_something) {
|
|
|
|
|
/* there is a circle, pop the first (remaining) element from the list */
|
|
|
|
|
g_warn_if_reached ();
|
|
|
|
|
item = &g_array_index (links, NMPlatformLink, first_idx);
|
|
|
|
|
|
|
|
|
|
g_hash_table_remove (unseen, GINT_TO_POINTER (item->ifindex));
|
|
|
|
|
g_array_index (result, NMPlatformLink, j++) = *item;
|
|
|
|
|
item->ifindex = 0;
|
|
|
|
|
}
|
|
|
|
|
} while (j < nresult);
|
|
|
|
|
|
|
|
|
|
g_hash_table_destroy (unseen);
|
|
|
|
|
g_array_free (links, TRUE);
|
|
|
|
|
|
|
|
|
|
return result;
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
2014-04-22 16:02:15 +02:00
|
|
|
/**
|
|
|
|
|
* nm_platform_link_get:
|
|
|
|
|
* @ifindex: ifindex of the link
|
|
|
|
|
* @link: (out): output NMPlatformLink structure.
|
|
|
|
|
*
|
|
|
|
|
* If a link with given @ifindex exists, fill the given NMPlatformLink
|
|
|
|
|
* structure.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE, if such a link exists, %FALSE otherwise.
|
|
|
|
|
* If the link does not exist, the content of @link is undefined.
|
|
|
|
|
**/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_get (int ifindex, NMPlatformLink *link)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (link, FALSE);
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (klass->link_get, FALSE);
|
|
|
|
|
return !!klass->link_get (platform, ifindex, link);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
/**
|
|
|
|
|
* nm_platform_link_add:
|
|
|
|
|
* @name: Interface name
|
|
|
|
|
* @type: Interface type
|
2014-05-13 18:13:52 +02:00
|
|
|
* @address: (allow-none): set the mac address of the link
|
|
|
|
|
* @address_len: the length of the @address
|
2013-03-27 22:23:24 +01:00
|
|
|
*
|
|
|
|
|
* Add a software interface. Sets platform->error to NM_PLATFORM_ERROR_EXISTS
|
2014-04-17 14:57:55 +02:00
|
|
|
* if interface is already already exists. Any link-changed ADDED signal will be
|
|
|
|
|
* emitted directly, before this function finishes.
|
2013-03-27 22:23:24 +01:00
|
|
|
*/
|
|
|
|
|
static gboolean
|
2014-05-13 18:13:52 +02:00
|
|
|
nm_platform_link_add (const char *name, NMLinkType type, const void *address, size_t address_len)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (name, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->link_add, FALSE);
|
2014-05-13 18:13:52 +02:00
|
|
|
g_return_val_if_fail ( (address != NULL) ^ (address_len == 0) , FALSE);
|
2013-03-27 22:23:24 +01:00
|
|
|
|
|
|
|
|
if (nm_platform_link_exists (name)) {
|
|
|
|
|
debug ("link: already exists");
|
|
|
|
|
platform->error = NM_PLATFORM_ERROR_EXISTS;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-13 18:13:52 +02:00
|
|
|
return klass->link_add (platform, name, type, address, address_len);
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_dummy_add:
|
|
|
|
|
* @name: New interface name
|
|
|
|
|
*
|
|
|
|
|
* Create a software ethernet-like interface
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_dummy_add (const char *name)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (name, FALSE);
|
|
|
|
|
|
|
|
|
|
debug ("link: adding dummy '%s'", name);
|
2014-05-13 18:13:52 +02:00
|
|
|
return nm_platform_link_add (name, NM_LINK_TYPE_DUMMY, NULL, 0);
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_link_exists:
|
|
|
|
|
* @name: Interface name
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if an interface of this name exists, %FALSE otherwise.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_exists (const char *name)
|
|
|
|
|
{
|
|
|
|
|
int ifindex = nm_platform_link_get_ifindex (name);
|
|
|
|
|
|
|
|
|
|
reset_error();
|
|
|
|
|
return ifindex > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_link_delete:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
*
|
|
|
|
|
* Delete a software interface. Sets platform->error to
|
|
|
|
|
* NM_PLATFORM_ERROR_NOT_FOUND if ifindex not available.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_delete (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (klass->link_delete, FALSE);
|
|
|
|
|
|
|
|
|
|
name = nm_platform_link_get_name (ifindex);
|
|
|
|
|
|
|
|
|
|
if (!name)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
debug ("link: deleting '%s' (%d)", name, ifindex);
|
|
|
|
|
return klass->link_delete (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_link_get_index:
|
|
|
|
|
* @name: Interface name
|
|
|
|
|
*
|
|
|
|
|
* Returns: The interface index corresponding to the given interface name
|
|
|
|
|
* or 0. Inteface name is owned by #NMPlatform, don't free it.
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
nm_platform_link_get_ifindex (const char *name)
|
|
|
|
|
{
|
|
|
|
|
int ifindex;
|
|
|
|
|
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (name, 0);
|
|
|
|
|
g_return_val_if_fail (klass->link_get_ifindex, 0);
|
|
|
|
|
|
|
|
|
|
ifindex = klass->link_get_ifindex (platform, name);
|
|
|
|
|
|
|
|
|
|
if (!ifindex) {
|
|
|
|
|
debug ("link not found: %s", name);
|
|
|
|
|
platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ifindex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_link_get_name:
|
|
|
|
|
* @name: Interface name
|
|
|
|
|
*
|
|
|
|
|
* Returns: The interface name corresponding to the given interface index
|
2013-04-19 15:48:01 +02:00
|
|
|
* or %NULL.
|
2013-03-27 22:23:24 +01:00
|
|
|
*/
|
|
|
|
|
const char *
|
|
|
|
|
nm_platform_link_get_name (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (klass->link_get_name, NULL);
|
|
|
|
|
|
|
|
|
|
name = klass->link_get_name (platform, ifindex);
|
|
|
|
|
|
|
|
|
|
if (!name) {
|
|
|
|
|
debug ("link not found: %d", ifindex);
|
|
|
|
|
platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_link_get_type:
|
|
|
|
|
* @ifindex: Interface index.
|
|
|
|
|
*
|
|
|
|
|
* Returns: Link type constant as defined in nm-platform.h. On error,
|
|
|
|
|
* NM_LINK_TYPE_NONE is returned.
|
|
|
|
|
*/
|
|
|
|
|
NMLinkType
|
|
|
|
|
nm_platform_link_get_type (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (klass->link_get_type, NM_LINK_TYPE_NONE);
|
|
|
|
|
|
|
|
|
|
return klass->link_get_type (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-26 11:43:08 -04:00
|
|
|
/**
|
|
|
|
|
* nm_platform_link_get_type_name:
|
|
|
|
|
* @ifindex: Interface index.
|
|
|
|
|
*
|
|
|
|
|
* Returns: A string describing the type of link. In some cases this
|
|
|
|
|
* may be more specific than nm_platform_link_get_type(), but in
|
|
|
|
|
* other cases it may not. On error, %NULL is returned.
|
|
|
|
|
*/
|
|
|
|
|
const char *
|
|
|
|
|
nm_platform_link_get_type_name (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (klass->link_get_type_name, NULL);
|
|
|
|
|
|
|
|
|
|
return klass->link_get_type_name (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-20 12:48:44 +02:00
|
|
|
/**
|
|
|
|
|
* nm_platform_link_is_software:
|
|
|
|
|
* @ifindex: Interface index.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if ifindex belongs to a software interface, not backed by
|
|
|
|
|
* a physical device.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_is_software (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
return (nm_platform_link_get_type (ifindex) & 0x10000);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_link_supports_slaves:
|
|
|
|
|
* @ifindex: Interface index.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if ifindex belongs to an interface capable of enslaving
|
|
|
|
|
* other interfaces.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_supports_slaves (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
return (nm_platform_link_get_type (ifindex) & 0x20000);
|
|
|
|
|
}
|
2013-04-26 11:43:08 -04:00
|
|
|
|
2014-02-11 13:58:00 +01:00
|
|
|
/**
|
|
|
|
|
* nm_platform_link_refresh:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
*
|
|
|
|
|
* Reload the cache for ifindex synchronously.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_refresh (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
|
|
|
|
|
if (klass->link_refresh)
|
|
|
|
|
return klass->link_refresh (platform, ifindex);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
/**
|
|
|
|
|
* nm_platform_link_is_up:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
*
|
|
|
|
|
* Check if the interface is up.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_is_up (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex >= 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->link_is_up, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->link_is_up (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_link_is_connected:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
*
|
|
|
|
|
* Check if the interface is connected.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_is_connected (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex >= 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->link_is_connected, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->link_is_connected (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_link_uses_arp:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
*
|
|
|
|
|
* Check if the interface is configured to use ARP.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_uses_arp (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex >= 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->link_uses_arp, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->link_uses_arp (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-24 15:57:08 -05:00
|
|
|
/**
|
|
|
|
|
* nm_platform_link_get_user_ip6vll_enabled:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
*
|
|
|
|
|
* Check whether NM handles IPv6LL address creation for the link. If the
|
|
|
|
|
* platform or OS doesn't support changing the IPv6LL address mode, this call
|
|
|
|
|
* will fail and return %FALSE.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if NM handles the IPv6LL address for @ifindex
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_get_user_ipv6ll_enabled (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex >= 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->check_support_user_ipv6ll, FALSE);
|
|
|
|
|
|
|
|
|
|
if (klass->link_get_user_ipv6ll_enabled)
|
|
|
|
|
return klass->link_get_user_ipv6ll_enabled (platform, ifindex);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_link_set_user_ip6vll_enabled:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
*
|
|
|
|
|
* Set whether NM handles IPv6LL address creation for the link. If the
|
|
|
|
|
* platform or OS doesn't support changing the IPv6LL address mode, this call
|
|
|
|
|
* will fail and return %FALSE.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if the operation was successful, %FALSE if it failed.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_set_user_ipv6ll_enabled (int ifindex, gboolean enabled)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex >= 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->check_support_user_ipv6ll, FALSE);
|
|
|
|
|
|
|
|
|
|
if (klass->link_set_user_ipv6ll_enabled)
|
|
|
|
|
return klass->link_set_user_ipv6ll_enabled (platform, ifindex, enabled);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-27 22:53:55 +01:00
|
|
|
/**
|
|
|
|
|
* nm_platform_link_set_address:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
* @address: The new MAC address
|
|
|
|
|
*
|
|
|
|
|
* Set interface MAC address.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_set_address (int ifindex, gconstpointer address, size_t length)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (address, FALSE);
|
|
|
|
|
g_return_val_if_fail (length > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->link_set_address, FALSE);
|
|
|
|
|
|
|
|
|
|
debug ("link: setting '%s' (%d) hardware address", nm_platform_link_get_name (ifindex), ifindex);
|
|
|
|
|
return klass->link_set_address (platform, ifindex, address, length);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_link_get_address:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
* @length: Pointer to a variable to store address length
|
|
|
|
|
*
|
|
|
|
|
* Saves interface hardware address to @address.
|
|
|
|
|
*/
|
|
|
|
|
gconstpointer
|
|
|
|
|
nm_platform_link_get_address (int ifindex, size_t *length)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
if (length)
|
|
|
|
|
*length = 0;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, NULL);
|
|
|
|
|
g_return_val_if_fail (klass->link_get_address, NULL);
|
|
|
|
|
|
|
|
|
|
return klass->link_get_address (platform, ifindex, length);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-27 22:53:55 +01:00
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_supports_carrier_detect (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (ifindex >= 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->link_supports_carrier_detect, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->link_supports_carrier_detect (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_supports_vlans (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (ifindex >= 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->link_supports_vlans, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->link_supports_vlans (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
/**
|
|
|
|
|
* nm_platform_link_set_up:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
*
|
|
|
|
|
* Bring the interface up.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_set_up (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->link_set_up, FALSE);
|
|
|
|
|
|
|
|
|
|
debug ("link: setting up '%s' (%d)", nm_platform_link_get_name (ifindex), ifindex);
|
|
|
|
|
return klass->link_set_up (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_link_set_down:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
*
|
|
|
|
|
* Take the interface down.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_set_down (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->link_set_down, FALSE);
|
|
|
|
|
|
|
|
|
|
debug ("link: setting down '%s' (%d)", nm_platform_link_get_name (ifindex), ifindex);
|
|
|
|
|
return klass->link_set_down (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_link_set_arp:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
*
|
|
|
|
|
* Enable ARP on the interface.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_set_arp (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex >= 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->link_set_arp, FALSE);
|
|
|
|
|
|
|
|
|
|
debug ("link: setting arp '%s' (%d)", nm_platform_link_get_name (ifindex), ifindex);
|
|
|
|
|
return klass->link_set_arp (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_link_set_noarp:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
*
|
|
|
|
|
* Disable ARP on the interface.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_set_noarp (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex >= 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->link_set_noarp, FALSE);
|
|
|
|
|
|
|
|
|
|
debug ("link: setting noarp '%s' (%d)", nm_platform_link_get_name (ifindex), ifindex);
|
|
|
|
|
return klass->link_set_noarp (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-15 21:48:12 +02:00
|
|
|
/**
|
|
|
|
|
* nm_platform_link_set_mtu:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
* @mtu: The new MTU value
|
|
|
|
|
*
|
|
|
|
|
* Set interface MTU.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_set_mtu (int ifindex, guint32 mtu)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex >= 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (mtu > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->link_set_mtu, FALSE);
|
|
|
|
|
|
2014-10-09 13:12:00 +02:00
|
|
|
debug ("link: setting '%s' (%d) mtu %"G_GUINT32_FORMAT, nm_platform_link_get_name (ifindex), ifindex, mtu);
|
2013-04-15 21:48:12 +02:00
|
|
|
return klass->link_set_mtu (platform, ifindex, mtu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_link_get_mtu:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
*
|
|
|
|
|
* Returns: MTU value for the interface or 0 on error.
|
|
|
|
|
*/
|
|
|
|
|
guint32
|
|
|
|
|
nm_platform_link_get_mtu (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex >= 0, 0);
|
|
|
|
|
g_return_val_if_fail (klass->link_get_mtu, 0);
|
|
|
|
|
|
|
|
|
|
return klass->link_get_mtu (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-11 14:59:26 -04:00
|
|
|
/**
|
|
|
|
|
* nm_platform_link_get_mtu:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
*
|
|
|
|
|
* Returns: physical port ID for the interface, or %NULL on error
|
|
|
|
|
* or if the interface has no physical port ID.
|
|
|
|
|
*/
|
|
|
|
|
char *
|
|
|
|
|
nm_platform_link_get_physical_port_id (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex >= 0, NULL);
|
|
|
|
|
g_return_val_if_fail (klass->link_get_physical_port_id, NULL);
|
|
|
|
|
|
|
|
|
|
return klass->link_get_physical_port_id (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-05 11:56:44 +01:00
|
|
|
/**
|
|
|
|
|
* nm_platform_link_get_wake_onlan:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
*
|
|
|
|
|
* Returns: the "Wake-on-LAN" status for @ifindex.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_get_wake_on_lan (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex >= 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->link_get_wake_on_lan, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->link_get_wake_on_lan (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-27 22:53:55 +01:00
|
|
|
/**
|
|
|
|
|
* nm_platform_link_enslave:
|
|
|
|
|
* @master: Interface index of the master
|
|
|
|
|
* @slave: Interface index of the slave
|
|
|
|
|
*
|
|
|
|
|
* Enslave @slave to @master.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_enslave (int master, int slave)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_assert (platform);
|
|
|
|
|
g_return_val_if_fail (master > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (slave> 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->link_enslave, FALSE);
|
|
|
|
|
|
|
|
|
|
debug ("link: enslaving '%s' (%d) to master '%s' (%d)",
|
|
|
|
|
nm_platform_link_get_name (slave), slave,
|
|
|
|
|
nm_platform_link_get_name (master), master);
|
|
|
|
|
return klass->link_enslave (platform, master, slave);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_link_release:
|
|
|
|
|
* @master: Interface index of the master
|
|
|
|
|
* @slave: Interface index of the slave
|
|
|
|
|
*
|
|
|
|
|
* Release @slave from @master.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_release (int master, int slave)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_assert (platform);
|
|
|
|
|
g_return_val_if_fail (master > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (slave > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->link_release, FALSE);
|
|
|
|
|
|
|
|
|
|
if (nm_platform_link_get_master (slave) != master) {
|
|
|
|
|
platform->error = NM_PLATFORM_ERROR_NOT_SLAVE;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
debug ("link: releasing '%s' (%d) from master '%s' (%d)",
|
|
|
|
|
nm_platform_link_get_name (slave), slave,
|
|
|
|
|
nm_platform_link_get_name (master), master);
|
|
|
|
|
return klass->link_release (platform, master, slave);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_link_get_master:
|
|
|
|
|
* @slave: Interface index of the slave.
|
|
|
|
|
*
|
|
|
|
|
* Returns: Interfase index of the slave's master.
|
|
|
|
|
*/
|
|
|
|
|
int
|
|
|
|
|
nm_platform_link_get_master (int slave)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_assert (platform);
|
|
|
|
|
g_return_val_if_fail (slave >= 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->link_get_master, FALSE);
|
|
|
|
|
|
|
|
|
|
if (!nm_platform_link_get_name (slave)) {
|
|
|
|
|
platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return klass->link_get_master (platform, slave);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_bridge_add:
|
|
|
|
|
* @name: New interface name
|
2014-05-13 18:13:52 +02:00
|
|
|
* @address: (allow-none): set the mac address of the new bridge
|
|
|
|
|
* @address_len: the length of the @address
|
2013-03-27 22:53:55 +01:00
|
|
|
*
|
2013-06-26 21:23:25 +02:00
|
|
|
* Create a software bridge.
|
2013-03-27 22:53:55 +01:00
|
|
|
*/
|
|
|
|
|
gboolean
|
2014-05-13 18:13:52 +02:00
|
|
|
nm_platform_bridge_add (const char *name, const void *address, size_t address_len)
|
2013-03-27 22:53:55 +01:00
|
|
|
{
|
|
|
|
|
debug ("link: adding bridge '%s'", name);
|
2014-05-13 18:13:52 +02:00
|
|
|
return nm_platform_link_add (name, NM_LINK_TYPE_BRIDGE, address, address_len);
|
2013-03-27 22:53:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_bond_add:
|
|
|
|
|
* @name: New interface name
|
|
|
|
|
*
|
2013-06-26 21:23:25 +02:00
|
|
|
* Create a software bonding device.
|
2013-03-27 22:53:55 +01:00
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_bond_add (const char *name)
|
|
|
|
|
{
|
|
|
|
|
debug ("link: adding bond '%s'", name);
|
2014-05-13 18:13:52 +02:00
|
|
|
return nm_platform_link_add (name, NM_LINK_TYPE_BOND, NULL, 0);
|
2013-03-27 22:53:55 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_team_add:
|
|
|
|
|
* @name: New interface name
|
|
|
|
|
*
|
2013-06-26 21:23:25 +02:00
|
|
|
* Create a software teaming device.
|
2013-03-27 22:53:55 +01:00
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_team_add (const char *name)
|
|
|
|
|
{
|
|
|
|
|
debug ("link: adding team '%s'", name);
|
2014-05-13 18:13:52 +02:00
|
|
|
return nm_platform_link_add (name, NM_LINK_TYPE_TEAM, NULL, 0);
|
2013-03-27 22:53:55 +01:00
|
|
|
}
|
|
|
|
|
|
2013-03-27 22:53:55 +01:00
|
|
|
/**
|
|
|
|
|
* nm_platform_vlan_add:
|
|
|
|
|
* @name: New interface name
|
|
|
|
|
* @vlanid: VLAN identifier
|
2014-05-19 13:44:02 -04:00
|
|
|
* @vlanflags: VLAN flags from libnm
|
2013-03-27 22:53:55 +01:00
|
|
|
*
|
|
|
|
|
* Create a software VLAN device.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_vlan_add (const char *name, int parent, int vlanid, guint32 vlanflags)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_assert (platform);
|
|
|
|
|
g_return_val_if_fail (parent >= 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (vlanid >= 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (name, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->vlan_add, FALSE);
|
|
|
|
|
|
|
|
|
|
if (nm_platform_link_exists (name)) {
|
|
|
|
|
debug ("link already exists: %s", name);
|
|
|
|
|
platform->error = NM_PLATFORM_ERROR_EXISTS;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
debug ("link: adding vlan '%s' parent %d vlanid %d vlanflags %x",
|
|
|
|
|
name, parent, vlanid, vlanflags);
|
|
|
|
|
return klass->vlan_add (platform, name, parent, vlanid, vlanflags);
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-04 17:07:47 +02:00
|
|
|
gboolean
|
|
|
|
|
nm_platform_master_set_option (int ifindex, const char *option, const char *value)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (option, FALSE);
|
|
|
|
|
g_return_val_if_fail (value, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->master_set_option, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->master_set_option (platform, ifindex, option, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
|
nm_platform_master_get_option (int ifindex, const char *option)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (option, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->master_set_option, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->master_get_option (platform, ifindex, option);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_slave_set_option (int ifindex, const char *option, const char *value)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (option, FALSE);
|
|
|
|
|
g_return_val_if_fail (value, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->slave_set_option, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->slave_set_option (platform, ifindex, option, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
|
nm_platform_slave_get_option (int ifindex, const char *option)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (option, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->slave_set_option, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->slave_get_option (platform, ifindex, option);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-27 22:53:55 +01:00
|
|
|
gboolean
|
|
|
|
|
nm_platform_vlan_get_info (int ifindex, int *parent, int *vlanid)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_assert (platform);
|
|
|
|
|
g_return_val_if_fail (klass->vlan_get_info, FALSE);
|
|
|
|
|
|
|
|
|
|
if (parent)
|
|
|
|
|
*parent = 0;
|
|
|
|
|
if (vlanid)
|
|
|
|
|
*vlanid = 0;
|
|
|
|
|
|
|
|
|
|
if (nm_platform_link_get_type (ifindex) != NM_LINK_TYPE_VLAN)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
return klass->vlan_get_info (platform, ifindex, parent, vlanid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_vlan_set_ingress_map (int ifindex, int from, int to)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_assert (platform);
|
|
|
|
|
g_return_val_if_fail (klass->vlan_set_ingress_map, FALSE);
|
|
|
|
|
|
|
|
|
|
debug ("link: setting vlan ingress map for %d from %d to %d", ifindex, from, to);
|
|
|
|
|
return klass->vlan_set_ingress_map (platform, ifindex, from, to);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_vlan_set_egress_map (int ifindex, int from, int to)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_assert (platform);
|
|
|
|
|
g_return_val_if_fail (klass->vlan_set_egress_map, FALSE);
|
|
|
|
|
|
|
|
|
|
debug ("link: setting vlan egress map for %d from %d to %d", ifindex, from, to);
|
|
|
|
|
return klass->vlan_set_egress_map (platform, ifindex, from, to);
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-10 16:21:08 -03:00
|
|
|
gboolean
|
|
|
|
|
nm_platform_infiniband_partition_add (int parent, int p_key)
|
|
|
|
|
{
|
|
|
|
|
const char *parent_name;
|
|
|
|
|
char *name;
|
|
|
|
|
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (parent >= 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (p_key >= 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->infiniband_partition_add, FALSE);
|
|
|
|
|
|
|
|
|
|
if (nm_platform_link_get_type (parent) != NM_LINK_TYPE_INFINIBAND) {
|
|
|
|
|
platform->error = NM_PLATFORM_ERROR_WRONG_TYPE;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parent_name = nm_platform_link_get_name (parent);
|
|
|
|
|
name = g_strdup_printf ("%s.%04x", parent_name, p_key);
|
|
|
|
|
if (nm_platform_link_exists (name)) {
|
|
|
|
|
debug ("infiniband: already exists");
|
|
|
|
|
platform->error = NM_PLATFORM_ERROR_EXISTS;
|
|
|
|
|
g_free (name);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
g_free (name);
|
|
|
|
|
|
|
|
|
|
return klass->infiniband_partition_add (platform, parent, p_key);
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-03 13:55:51 -04:00
|
|
|
gboolean
|
|
|
|
|
nm_platform_veth_get_properties (int ifindex, NMPlatformVethProperties *props)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (props != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->veth_get_properties (platform, ifindex, props);
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-25 15:46:39 -04:00
|
|
|
gboolean
|
|
|
|
|
nm_platform_tun_get_properties (int ifindex, NMPlatformTunProperties *props)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (props != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->tun_get_properties (platform, ifindex, props);
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-06 09:16:17 -04:00
|
|
|
gboolean
|
|
|
|
|
nm_platform_macvlan_get_properties (int ifindex, NMPlatformMacvlanProperties *props)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (props != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->macvlan_get_properties (platform, ifindex, props);
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-04 10:31:22 -03:00
|
|
|
gboolean
|
|
|
|
|
nm_platform_vxlan_get_properties (int ifindex, NMPlatformVxlanProperties *props)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (props != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->vxlan_get_properties (platform, ifindex, props);
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-21 12:49:24 -03:00
|
|
|
gboolean
|
|
|
|
|
nm_platform_gre_get_properties (int ifindex, NMPlatformGreProperties *props)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (props != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->gre_get_properties (platform, ifindex, props);
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-04 14:27:03 +01:00
|
|
|
gboolean
|
|
|
|
|
nm_platform_wifi_get_capabilities (int ifindex, NMDeviceWifiCapabilities *caps)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->wifi_get_capabilities (platform, ifindex, caps);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2014-07-07 12:04:14 -04:00
|
|
|
nm_platform_wifi_get_bssid (int ifindex, guint8 *bssid)
|
2014-02-04 14:27:03 +01:00
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->wifi_get_bssid (platform, ifindex, bssid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GByteArray *
|
|
|
|
|
nm_platform_wifi_get_ssid (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, NULL);
|
|
|
|
|
|
|
|
|
|
return klass->wifi_get_ssid (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
guint32
|
|
|
|
|
nm_platform_wifi_get_frequency (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, 0);
|
|
|
|
|
|
|
|
|
|
return klass->wifi_get_frequency (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
nm_platform_wifi_get_quality (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, 0);
|
|
|
|
|
|
|
|
|
|
return klass->wifi_get_quality (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
guint32
|
|
|
|
|
nm_platform_wifi_get_rate (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, 0);
|
|
|
|
|
|
|
|
|
|
return klass->wifi_get_rate (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NM80211Mode
|
|
|
|
|
nm_platform_wifi_get_mode (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, NM_802_11_MODE_UNKNOWN);
|
|
|
|
|
|
|
|
|
|
return klass->wifi_get_mode (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_platform_wifi_set_mode (int ifindex, NM80211Mode mode)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (ifindex > 0);
|
|
|
|
|
|
|
|
|
|
klass->wifi_set_mode (platform, ifindex, mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
guint32
|
|
|
|
|
nm_platform_wifi_find_frequency (int ifindex, const guint32 *freqs)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, 0);
|
|
|
|
|
g_return_val_if_fail (freqs != NULL, 0);
|
|
|
|
|
|
|
|
|
|
return klass->wifi_find_frequency (platform, ifindex, freqs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_platform_wifi_indicate_addressing_running (int ifindex, gboolean running)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (ifindex > 0);
|
|
|
|
|
|
|
|
|
|
klass->wifi_indicate_addressing_running (platform, ifindex, running);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
guint32
|
|
|
|
|
nm_platform_mesh_get_channel (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, 0);
|
|
|
|
|
|
|
|
|
|
return klass->mesh_get_channel (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_mesh_set_channel (int ifindex, guint32 channel)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->mesh_set_channel (platform, ifindex, channel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2014-06-26 10:42:11 -04:00
|
|
|
nm_platform_mesh_set_ssid (int ifindex, const guint8 *ssid, gsize len)
|
2014-02-04 14:27:03 +01:00
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (ssid != NULL, FALSE);
|
|
|
|
|
|
2014-06-26 10:42:11 -04:00
|
|
|
return klass->mesh_set_ssid (platform, ifindex, ssid, len);
|
2014-02-04 14:27:03 +01:00
|
|
|
}
|
|
|
|
|
|
2014-08-11 21:32:47 +02:00
|
|
|
#define TO_STRING_DEV_BUF_SIZE (5+15+1)
|
2014-08-11 21:40:52 +02:00
|
|
|
static const char *
|
2014-08-11 21:32:47 +02:00
|
|
|
_to_string_dev (int ifindex, char *buf, size_t size)
|
|
|
|
|
{
|
|
|
|
|
g_assert (buf && size >= TO_STRING_DEV_BUF_SIZE);
|
|
|
|
|
|
|
|
|
|
if (ifindex) {
|
|
|
|
|
const char *name = ifindex > 0 ? nm_platform_link_get_name (ifindex) : NULL;
|
2014-08-11 21:40:52 +02:00
|
|
|
char *buf2;
|
2014-08-11 21:32:47 +02:00
|
|
|
|
|
|
|
|
strcpy (buf, " dev ");
|
2014-08-11 21:40:52 +02:00
|
|
|
buf2 = buf + 5;
|
2014-08-11 21:32:47 +02:00
|
|
|
size -= 5;
|
|
|
|
|
|
|
|
|
|
if (name)
|
2014-08-11 21:40:52 +02:00
|
|
|
g_strlcpy (buf2, name, size);
|
2014-08-11 21:32:47 +02:00
|
|
|
else
|
2014-08-11 21:40:52 +02:00
|
|
|
g_snprintf (buf2, size, "%d", ifindex);
|
2014-08-11 21:32:47 +02:00
|
|
|
} else
|
|
|
|
|
buf[0] = 0;
|
2014-08-11 21:40:52 +02:00
|
|
|
|
|
|
|
|
return buf;
|
2014-08-11 21:32:47 +02:00
|
|
|
}
|
|
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
/******************************************************************/
|
|
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
GArray *
|
|
|
|
|
nm_platform_ip4_address_get_all (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, NULL);
|
|
|
|
|
g_return_val_if_fail (klass->ip4_address_get_all, NULL);
|
|
|
|
|
|
|
|
|
|
return klass->ip4_address_get_all (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GArray *
|
|
|
|
|
nm_platform_ip6_address_get_all (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, NULL);
|
|
|
|
|
g_return_val_if_fail (klass->ip6_address_get_all, NULL);
|
|
|
|
|
|
|
|
|
|
return klass->ip6_address_get_all (platform, ifindex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2013-12-02 10:20:26 -05:00
|
|
|
nm_platform_ip4_address_add (int ifindex,
|
|
|
|
|
in_addr_t address,
|
|
|
|
|
in_addr_t peer_address,
|
|
|
|
|
int plen,
|
|
|
|
|
guint32 lifetime,
|
2014-02-19 16:10:59 -05:00
|
|
|
guint32 preferred,
|
|
|
|
|
const char *label)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (plen > 0, FALSE);
|
2013-06-29 11:30:11 +02:00
|
|
|
g_return_val_if_fail (lifetime > 0, FALSE);
|
2014-04-01 22:46:46 +02:00
|
|
|
g_return_val_if_fail (preferred <= lifetime, FALSE);
|
2013-03-27 22:23:24 +01:00
|
|
|
g_return_val_if_fail (klass->ip4_address_add, FALSE);
|
2014-02-19 16:10:59 -05:00
|
|
|
g_return_val_if_fail (!label || strlen (label) < sizeof (((NMPlatformIP4Address *) NULL)->label), FALSE);
|
2013-03-27 22:23:24 +01:00
|
|
|
|
2014-01-30 20:31:29 +01:00
|
|
|
if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) {
|
|
|
|
|
NMPlatformIP4Address addr = { 0 };
|
|
|
|
|
|
|
|
|
|
addr.ifindex = ifindex;
|
|
|
|
|
addr.address = address;
|
|
|
|
|
addr.peer_address = peer_address;
|
|
|
|
|
addr.plen = plen;
|
2014-06-09 10:03:01 +02:00
|
|
|
addr.timestamp = 0; /* set it at zero, which to_string will treat as *now* */
|
2014-01-30 20:31:29 +01:00
|
|
|
addr.lifetime = lifetime;
|
|
|
|
|
addr.preferred = preferred;
|
2014-02-19 16:10:59 -05:00
|
|
|
if (label)
|
|
|
|
|
g_strlcpy (addr.label, label, sizeof (addr.label));
|
2014-01-30 20:31:29 +01:00
|
|
|
|
|
|
|
|
debug ("address: adding or updating IPv4 address: %s", nm_platform_ip4_address_to_string (&addr));
|
|
|
|
|
}
|
2014-02-19 16:10:59 -05:00
|
|
|
return klass->ip4_address_add (platform, ifindex, address, peer_address, plen, lifetime, preferred, label);
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2013-12-02 10:20:26 -05:00
|
|
|
nm_platform_ip6_address_add (int ifindex,
|
|
|
|
|
struct in6_addr address,
|
|
|
|
|
struct in6_addr peer_address,
|
|
|
|
|
int plen,
|
|
|
|
|
guint32 lifetime,
|
|
|
|
|
guint32 preferred,
|
|
|
|
|
guint flags)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (plen > 0, FALSE);
|
2013-06-29 11:30:11 +02:00
|
|
|
g_return_val_if_fail (lifetime > 0, FALSE);
|
2014-04-01 22:46:46 +02:00
|
|
|
g_return_val_if_fail (preferred <= lifetime, FALSE);
|
2013-03-27 22:23:24 +01:00
|
|
|
g_return_val_if_fail (klass->ip6_address_add, FALSE);
|
|
|
|
|
|
2014-01-30 20:31:29 +01:00
|
|
|
if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) {
|
|
|
|
|
NMPlatformIP6Address addr = { 0 };
|
|
|
|
|
|
|
|
|
|
addr.ifindex = ifindex;
|
|
|
|
|
addr.address = address;
|
|
|
|
|
addr.peer_address = peer_address;
|
|
|
|
|
addr.plen = plen;
|
2014-06-09 10:03:01 +02:00
|
|
|
addr.timestamp = 0; /* set it to zero, which to_string will treat as *now* */
|
2014-01-30 20:31:29 +01:00
|
|
|
addr.lifetime = lifetime;
|
|
|
|
|
addr.preferred = preferred;
|
|
|
|
|
addr.flags = flags;
|
|
|
|
|
|
|
|
|
|
debug ("address: adding or updating IPv6 address: %s", nm_platform_ip6_address_to_string (&addr));
|
|
|
|
|
}
|
2013-12-02 10:20:26 -05:00
|
|
|
return klass->ip6_address_add (platform, ifindex, address, peer_address, plen, lifetime, preferred, flags);
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2014-08-12 01:31:00 +02:00
|
|
|
nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen, in_addr_t peer_address)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
2014-08-11 21:40:52 +02:00
|
|
|
char str_dev[TO_STRING_DEV_BUF_SIZE];
|
2014-08-12 01:31:00 +02:00
|
|
|
char str_peer[NM_UTILS_INET_ADDRSTRLEN];
|
2014-08-11 21:40:52 +02:00
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (plen > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->ip4_address_delete, FALSE);
|
|
|
|
|
|
2014-08-12 01:31:00 +02:00
|
|
|
debug ("address: deleting IPv4 address %s/%d, %s%s%sifindex %d%s",
|
|
|
|
|
nm_utils_inet4_ntop (address, NULL), plen,
|
|
|
|
|
peer_address ? "peer " : "",
|
|
|
|
|
peer_address ? nm_utils_inet4_ntop (peer_address, str_peer) : "",
|
|
|
|
|
peer_address ? ", " : "",
|
|
|
|
|
ifindex,
|
2014-08-11 21:40:52 +02:00
|
|
|
_to_string_dev (ifindex, str_dev, sizeof (str_dev)));
|
2014-08-12 01:31:00 +02:00
|
|
|
return klass->ip4_address_delete (platform, ifindex, address, plen, peer_address);
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_ip6_address_delete (int ifindex, struct in6_addr address, int plen)
|
|
|
|
|
{
|
2014-08-11 21:40:52 +02:00
|
|
|
char str_dev[TO_STRING_DEV_BUF_SIZE];
|
|
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (plen > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->ip6_address_delete, FALSE);
|
|
|
|
|
|
2014-08-11 21:40:52 +02:00
|
|
|
debug ("address: deleting IPv6 address %s/%d, ifindex %d%s",
|
|
|
|
|
nm_utils_inet6_ntop (&address, NULL), plen, ifindex,
|
|
|
|
|
_to_string_dev (ifindex, str_dev, sizeof (str_dev)));
|
2013-03-27 22:23:24 +01:00
|
|
|
return klass->ip6_address_delete (platform, ifindex, address, plen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_ip4_address_exists (int ifindex, in_addr_t address, int plen)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (plen > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->ip4_address_exists, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->ip4_address_exists (platform, ifindex, address, plen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_ip6_address_exists (int ifindex, struct in6_addr address, int plen)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (plen > 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->ip6_address_exists, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->ip6_address_exists (platform, ifindex, address, plen);
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-16 14:24:46 +02:00
|
|
|
static gboolean
|
|
|
|
|
array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address *address)
|
|
|
|
|
{
|
2013-07-29 23:00:44 +02:00
|
|
|
guint len = addresses ? addresses->len : 0;
|
|
|
|
|
guint i;
|
2013-04-16 14:24:46 +02:00
|
|
|
|
2013-07-29 23:00:44 +02:00
|
|
|
for (i = 0; i < len; i++) {
|
2013-07-29 14:54:25 -05:00
|
|
|
NMPlatformIP4Address *candidate = &g_array_index (addresses, NMPlatformIP4Address, i);
|
|
|
|
|
|
2013-07-29 23:32:58 +02:00
|
|
|
if (candidate->address == address->address && candidate->plen == address->plen)
|
2013-04-16 14:24:46 +02:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
array_contains_ip6_address (const GArray *addresses, const NMPlatformIP6Address *address)
|
|
|
|
|
{
|
2013-07-29 23:00:44 +02:00
|
|
|
guint len = addresses ? addresses->len : 0;
|
|
|
|
|
guint i;
|
2013-04-16 14:24:46 +02:00
|
|
|
|
2013-07-29 23:00:44 +02:00
|
|
|
for (i = 0; i < len; i++) {
|
2013-07-29 14:54:25 -05:00
|
|
|
NMPlatformIP6Address *candidate = &g_array_index (addresses, NMPlatformIP6Address, i);
|
|
|
|
|
|
2013-07-29 23:32:58 +02:00
|
|
|
if (IN6_ARE_ADDR_EQUAL (&candidate->address, &address->address) && candidate->plen == address->plen)
|
2013-04-16 14:24:46 +02:00
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-31 11:19:45 +02:00
|
|
|
/**
|
|
|
|
|
* Takes a pair @timestamp and @duration, and returns the remaining duration based
|
|
|
|
|
* on the new timestamp @now.
|
|
|
|
|
*/
|
2013-06-29 11:30:11 +02:00
|
|
|
static guint32
|
2014-06-07 11:32:40 +02:00
|
|
|
_rebase_relative_time_on_now (guint32 timestamp, guint32 duration, guint32 now, guint32 padding)
|
2013-06-29 11:30:11 +02:00
|
|
|
{
|
2014-03-31 11:19:45 +02:00
|
|
|
gint64 t;
|
|
|
|
|
|
|
|
|
|
if (duration == NM_PLATFORM_LIFETIME_PERMANENT)
|
|
|
|
|
return NM_PLATFORM_LIFETIME_PERMANENT;
|
2013-06-29 11:30:11 +02:00
|
|
|
|
2014-06-09 10:03:01 +02:00
|
|
|
if (timestamp == 0) {
|
|
|
|
|
/* if the @timestamp is zero, assume it was just left unset and that the relative
|
|
|
|
|
* @duration starts counting from @now. This is convenient to construct an address
|
|
|
|
|
* and print it in nm_platform_ip4_address_to_string().
|
|
|
|
|
*
|
|
|
|
|
* In general it does not make sense to set the @duration without anchoring at
|
|
|
|
|
* @timestamp because you don't know the absolute expiration time when looking
|
|
|
|
|
* at the address at a later moment. */
|
|
|
|
|
timestamp = now;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-07 11:32:40 +02:00
|
|
|
/* For timestamp > now, just accept it and calculate the expected(?) result. */
|
2014-03-31 11:19:45 +02:00
|
|
|
t = (gint64) timestamp + (gint64) duration - (gint64) now;
|
|
|
|
|
|
2014-06-07 11:32:40 +02:00
|
|
|
/* Optional padding to avoid potential races. */
|
|
|
|
|
t += (gint64) padding;
|
2014-03-31 11:19:45 +02:00
|
|
|
|
|
|
|
|
if (t <= 0)
|
|
|
|
|
return 0;
|
|
|
|
|
if (t >= NM_PLATFORM_LIFETIME_PERMANENT)
|
|
|
|
|
return NM_PLATFORM_LIFETIME_PERMANENT - 1;
|
|
|
|
|
return t;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
2014-06-07 11:32:40 +02:00
|
|
|
_address_get_lifetime (const NMPlatformIPAddress *address, guint32 now, guint32 padding, guint32 *out_lifetime, guint32 *out_preferred)
|
2014-03-31 11:19:45 +02:00
|
|
|
{
|
2014-11-05 12:37:37 -06:00
|
|
|
guint32 lifetime, preferred;
|
2014-03-31 11:19:45 +02:00
|
|
|
|
|
|
|
|
if (address->lifetime == 0) {
|
|
|
|
|
*out_lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
|
|
|
|
|
*out_preferred = NM_PLATFORM_LIFETIME_PERMANENT;
|
2014-11-12 13:37:30 +01:00
|
|
|
|
|
|
|
|
/* We treat lifetime==0 as permanent addresses to allow easy creation of such addresses
|
|
|
|
|
* (without requiring to set the lifetime fields to NM_PLATFORM_LIFETIME_PERMANENT).
|
|
|
|
|
* In that case we also expect that the other fields (timestamp and preferred) are left unset. */
|
|
|
|
|
g_return_val_if_fail (address->timestamp == 0 && address->preferred == 0, TRUE);
|
2014-03-31 11:19:45 +02:00
|
|
|
} else {
|
2014-06-07 11:32:40 +02:00
|
|
|
lifetime = _rebase_relative_time_on_now (address->timestamp, address->lifetime, now, padding);
|
2014-03-31 11:19:45 +02:00
|
|
|
if (!lifetime)
|
|
|
|
|
return FALSE;
|
2014-06-07 11:32:40 +02:00
|
|
|
preferred = _rebase_relative_time_on_now (address->timestamp, address->preferred, now, padding);
|
2014-03-31 11:19:45 +02:00
|
|
|
|
|
|
|
|
*out_lifetime = lifetime;
|
2014-06-09 10:03:01 +02:00
|
|
|
*out_preferred = MIN (preferred, lifetime);
|
|
|
|
|
|
|
|
|
|
/* Assert that non-permanent addresses have a (positive) @timestamp. _rebase_relative_time_on_now()
|
|
|
|
|
* treats addresses with timestamp 0 as *now*. Addresses passed to _address_get_lifetime() always
|
|
|
|
|
* should have a valid @timestamp, otherwise on every re-sync, their lifetime will be extended anew.
|
|
|
|
|
*/
|
|
|
|
|
g_return_val_if_fail ( address->timestamp != 0
|
|
|
|
|
|| ( address->lifetime == NM_PLATFORM_LIFETIME_PERMANENT
|
|
|
|
|
&& address->preferred == NM_PLATFORM_LIFETIME_PERMANENT), TRUE);
|
|
|
|
|
g_return_val_if_fail (preferred <= lifetime, TRUE);
|
2014-03-31 11:19:45 +02:00
|
|
|
}
|
|
|
|
|
return TRUE;
|
2013-06-29 11:30:11 +02:00
|
|
|
}
|
|
|
|
|
|
2013-04-16 14:24:46 +02:00
|
|
|
/**
|
|
|
|
|
* nm_platform_ip4_address_sync:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
* @known_addresses: List of addresses
|
2014-11-11 14:55:07 +01:00
|
|
|
* @device_route_metric: the route metric for adding subnet routes (replaces
|
|
|
|
|
* the kernel added routes).
|
2013-04-16 14:24:46 +02:00
|
|
|
*
|
|
|
|
|
* A convenience function to synchronize addresses for a specific interface
|
|
|
|
|
* with the least possible disturbance. It simply removes addresses that are
|
|
|
|
|
* not listed and adds addresses that are.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE on success.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
2014-11-11 14:55:07 +01:00
|
|
|
nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses, guint32 device_route_metric)
|
2013-04-16 14:24:46 +02:00
|
|
|
{
|
|
|
|
|
GArray *addresses;
|
|
|
|
|
NMPlatformIP4Address *address;
|
2013-12-10 19:04:22 +01:00
|
|
|
guint32 now = nm_utils_get_monotonic_timestamp_s ();
|
2013-04-16 14:24:46 +02:00
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* Delete unknown addresses */
|
|
|
|
|
addresses = nm_platform_ip4_address_get_all (ifindex);
|
|
|
|
|
for (i = 0; i < addresses->len; i++) {
|
|
|
|
|
address = &g_array_index (addresses, NMPlatformIP4Address, i);
|
|
|
|
|
|
2013-07-29 23:00:44 +02:00
|
|
|
if (!array_contains_ip4_address (known_addresses, address))
|
2014-08-12 01:31:00 +02:00
|
|
|
nm_platform_ip4_address_delete (ifindex, address->address, address->plen, address->peer_address);
|
2013-04-16 14:24:46 +02:00
|
|
|
}
|
|
|
|
|
g_array_free (addresses, TRUE);
|
|
|
|
|
|
|
|
|
|
if (!known_addresses)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
/* Add missing addresses */
|
|
|
|
|
for (i = 0; i < known_addresses->len; i++) {
|
2013-07-30 00:03:48 +02:00
|
|
|
const NMPlatformIP4Address *known_address = &g_array_index (known_addresses, NMPlatformIP4Address, i);
|
|
|
|
|
guint32 lifetime, preferred;
|
2014-11-11 14:55:07 +01:00
|
|
|
guint32 network;
|
2013-04-16 14:24:46 +02:00
|
|
|
|
2014-06-07 11:32:40 +02:00
|
|
|
/* add a padding of 5 seconds to avoid potential races. */
|
|
|
|
|
if (!_address_get_lifetime ((NMPlatformIPAddress *) known_address, now, 5, &lifetime, &preferred))
|
2014-03-31 11:19:45 +02:00
|
|
|
continue;
|
2013-06-29 11:30:11 +02:00
|
|
|
|
2014-02-19 16:10:59 -05:00
|
|
|
if (!nm_platform_ip4_address_add (ifindex, known_address->address, known_address->peer_address, known_address->plen, lifetime, preferred, known_address->label))
|
2013-07-30 00:03:48 +02:00
|
|
|
return FALSE;
|
2014-11-11 14:55:07 +01:00
|
|
|
|
|
|
|
|
if (known_address->plen == 0 || known_address->plen == 32)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (device_route_metric == NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE) {
|
|
|
|
|
/* Kernel already adds routes for us with this metric. */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Kernel automatically adds a device route for us with metric 0. That is not what we want.
|
|
|
|
|
* Remove it, and re-add it.
|
|
|
|
|
*
|
|
|
|
|
* In face of having the same subnets on two different interfaces with the same metric,
|
|
|
|
|
* this is a problem. Surprisingly, kernel is able to add two routes for the same subnet/prefix,metric
|
|
|
|
|
* to different interfaces. We cannot. Adding one, will replace the other. Indeed we will
|
|
|
|
|
* toggle the routes between the interfaces.
|
|
|
|
|
*
|
|
|
|
|
* Indeed we have that problem for all our routes, that if another interface wants the same route
|
|
|
|
|
* we don't coordinate them. See bug 740064.
|
|
|
|
|
*
|
|
|
|
|
* The workaround is to configure different device priorities via ipv4.route-metric. */
|
|
|
|
|
|
|
|
|
|
network = nm_utils_ip4_address_clear_host_address (known_address->address, known_address->plen);
|
|
|
|
|
nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_KERNEL, network, known_address->plen, 0, known_address->address, device_route_metric, 0);
|
|
|
|
|
nm_platform_ip4_route_delete (ifindex, network, known_address->plen, NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE);
|
2013-04-16 14:24:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_ip6_address_sync:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
* @known_addresses: List of addresses
|
|
|
|
|
*
|
|
|
|
|
* A convenience function to synchronize addresses for a specific interface
|
|
|
|
|
* with the least possible disturbance. It simply removes addresses that are
|
|
|
|
|
* not listed and adds addresses that are.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE on success.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_ip6_address_sync (int ifindex, const GArray *known_addresses)
|
|
|
|
|
{
|
|
|
|
|
GArray *addresses;
|
|
|
|
|
NMPlatformIP6Address *address;
|
2013-12-10 19:04:22 +01:00
|
|
|
guint32 now = nm_utils_get_monotonic_timestamp_s ();
|
2013-04-16 14:24:46 +02:00
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* Delete unknown addresses */
|
|
|
|
|
addresses = nm_platform_ip6_address_get_all (ifindex);
|
|
|
|
|
for (i = 0; i < addresses->len; i++) {
|
|
|
|
|
address = &g_array_index (addresses, NMPlatformIP6Address, i);
|
|
|
|
|
|
|
|
|
|
/* Leave link local address management to the kernel */
|
|
|
|
|
if (IN6_IS_ADDR_LINKLOCAL (&address->address))
|
|
|
|
|
continue;
|
|
|
|
|
|
2013-07-29 23:00:44 +02:00
|
|
|
if (!array_contains_ip6_address (known_addresses, address))
|
2013-04-16 14:24:46 +02:00
|
|
|
nm_platform_ip6_address_delete (ifindex, address->address, address->plen);
|
|
|
|
|
}
|
|
|
|
|
g_array_free (addresses, TRUE);
|
|
|
|
|
|
|
|
|
|
if (!known_addresses)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
/* Add missing addresses */
|
|
|
|
|
for (i = 0; i < known_addresses->len; i++) {
|
2013-07-30 00:03:48 +02:00
|
|
|
const NMPlatformIP6Address *known_address = &g_array_index (known_addresses, NMPlatformIP6Address, i);
|
|
|
|
|
guint32 lifetime, preferred;
|
2013-06-29 11:30:11 +02:00
|
|
|
|
2014-06-07 11:32:40 +02:00
|
|
|
/* add a padding of 5 seconds to avoid potential races. */
|
|
|
|
|
if (!_address_get_lifetime ((NMPlatformIPAddress *) known_address, now, 5, &lifetime, &preferred))
|
2014-03-31 11:19:45 +02:00
|
|
|
continue;
|
2013-06-29 11:30:11 +02:00
|
|
|
|
2013-12-02 10:20:26 -05:00
|
|
|
if (!nm_platform_ip6_address_add (ifindex, known_address->address,
|
|
|
|
|
known_address->peer_address, known_address->plen,
|
2013-10-15 20:44:59 +02:00
|
|
|
lifetime, preferred, known_address->flags))
|
2013-07-30 00:03:48 +02:00
|
|
|
return FALSE;
|
2013-04-16 14:24:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_address_flush (int ifindex)
|
|
|
|
|
{
|
2014-11-11 14:55:07 +01:00
|
|
|
return nm_platform_ip4_address_sync (ifindex, NULL, 0)
|
2013-04-16 14:24:46 +02:00
|
|
|
&& nm_platform_ip6_address_sync (ifindex, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
GArray *
|
2014-10-14 19:02:50 +02:00
|
|
|
nm_platform_ip4_route_get_all (int ifindex, NMPlatformGetRouteMode mode)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
2014-11-07 10:56:21 +01:00
|
|
|
g_return_val_if_fail (ifindex >= 0, NULL);
|
2013-03-27 22:23:24 +01:00
|
|
|
g_return_val_if_fail (klass->ip4_route_get_all, NULL);
|
|
|
|
|
|
2014-10-14 19:02:50 +02:00
|
|
|
return klass->ip4_route_get_all (platform, ifindex, mode);
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GArray *
|
2014-10-14 19:02:50 +02:00
|
|
|
nm_platform_ip6_route_get_all (int ifindex, NMPlatformGetRouteMode mode)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
2014-11-07 10:56:21 +01:00
|
|
|
g_return_val_if_fail (ifindex >= 0, NULL);
|
2013-03-27 22:23:24 +01:00
|
|
|
g_return_val_if_fail (klass->ip6_route_get_all, NULL);
|
|
|
|
|
|
2014-10-14 19:02:50 +02:00
|
|
|
return klass->ip6_route_get_all (platform, ifindex, mode);
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2014-10-13 11:52:29 +02:00
|
|
|
nm_platform_ip4_route_add (int ifindex, NMIPConfigSource source,
|
2014-05-15 15:19:59 -04:00
|
|
|
in_addr_t network, int plen,
|
2014-11-11 14:19:12 +01:00
|
|
|
in_addr_t gateway, guint32 pref_src,
|
|
|
|
|
guint32 metric, guint32 mss)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (platform, FALSE);
|
|
|
|
|
g_return_val_if_fail (0 <= plen && plen <= 32, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->ip4_route_add, FALSE);
|
|
|
|
|
|
2014-02-13 14:42:26 +01:00
|
|
|
if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) {
|
|
|
|
|
NMPlatformIP4Route route = { 0 };
|
2014-11-11 14:19:12 +01:00
|
|
|
char pref_src_buf[NM_UTILS_INET_ADDRSTRLEN];
|
2014-02-13 14:42:26 +01:00
|
|
|
|
|
|
|
|
route.ifindex = ifindex;
|
2014-05-08 14:50:02 -04:00
|
|
|
route.source = source;
|
2014-02-13 14:42:26 +01:00
|
|
|
route.network = network;
|
|
|
|
|
route.plen = plen;
|
|
|
|
|
route.gateway = gateway;
|
|
|
|
|
route.metric = metric;
|
|
|
|
|
route.mss = mss;
|
|
|
|
|
|
2014-11-11 14:19:12 +01:00
|
|
|
debug ("route: adding or updating IPv4 route: %s%s%s%s", nm_platform_ip4_route_to_string (&route),
|
|
|
|
|
pref_src ? " (src: " : "",
|
|
|
|
|
pref_src ? nm_utils_inet4_ntop (pref_src, pref_src_buf) : "",
|
|
|
|
|
pref_src ? ")" : "");
|
2014-02-13 14:42:26 +01:00
|
|
|
}
|
2014-11-11 14:19:12 +01:00
|
|
|
return klass->ip4_route_add (platform, ifindex, source, network, plen, gateway, pref_src, metric, mss);
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2014-10-13 11:52:29 +02:00
|
|
|
nm_platform_ip6_route_add (int ifindex, NMIPConfigSource source,
|
2014-05-15 15:19:59 -04:00
|
|
|
struct in6_addr network, int plen, struct in6_addr gateway,
|
2014-08-28 17:25:36 +02:00
|
|
|
guint32 metric, guint32 mss)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (platform, FALSE);
|
|
|
|
|
g_return_val_if_fail (0 <= plen && plen <= 128, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->ip6_route_add, FALSE);
|
|
|
|
|
|
2014-02-13 14:42:26 +01:00
|
|
|
if (nm_logging_enabled (LOGL_DEBUG, LOGD_PLATFORM)) {
|
|
|
|
|
NMPlatformIP6Route route = { 0 };
|
|
|
|
|
|
|
|
|
|
route.ifindex = ifindex;
|
2014-05-08 14:50:02 -04:00
|
|
|
route.source = source;
|
2014-02-13 14:42:26 +01:00
|
|
|
route.network = network;
|
|
|
|
|
route.plen = plen;
|
|
|
|
|
route.gateway = gateway;
|
|
|
|
|
route.metric = metric;
|
|
|
|
|
route.mss = mss;
|
|
|
|
|
|
|
|
|
|
debug ("route: adding or updating IPv6 route: %s", nm_platform_ip6_route_to_string (&route));
|
|
|
|
|
}
|
2014-05-08 14:50:02 -04:00
|
|
|
return klass->ip6_route_add (platform, ifindex, source, network, plen, gateway, metric, mss);
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2014-08-28 17:25:36 +02:00
|
|
|
nm_platform_ip4_route_delete (int ifindex, in_addr_t network, int plen, guint32 metric)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
2014-08-11 21:40:52 +02:00
|
|
|
char str_dev[TO_STRING_DEV_BUF_SIZE];
|
|
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (platform, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->ip4_route_delete, FALSE);
|
|
|
|
|
|
2014-08-28 17:25:36 +02:00
|
|
|
debug ("route: deleting IPv4 route %s/%d, metric=%"G_GUINT32_FORMAT", ifindex %d%s",
|
2014-08-11 21:40:52 +02:00
|
|
|
nm_utils_inet4_ntop (network, NULL), plen, metric, ifindex,
|
|
|
|
|
_to_string_dev (ifindex, str_dev, sizeof (str_dev)));
|
2013-05-02 08:06:08 +02:00
|
|
|
return klass->ip4_route_delete (platform, ifindex, network, plen, metric);
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2014-08-28 17:25:36 +02:00
|
|
|
nm_platform_ip6_route_delete (int ifindex, struct in6_addr network, int plen, guint32 metric)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
2014-08-11 21:40:52 +02:00
|
|
|
char str_dev[TO_STRING_DEV_BUF_SIZE];
|
|
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (platform, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->ip6_route_delete, FALSE);
|
|
|
|
|
|
2014-08-28 17:25:36 +02:00
|
|
|
debug ("route: deleting IPv6 route %s/%d, metric=%"G_GUINT32_FORMAT", ifindex %d%s",
|
2014-08-11 21:40:52 +02:00
|
|
|
nm_utils_inet6_ntop (&network, NULL), plen, metric, ifindex,
|
|
|
|
|
_to_string_dev (ifindex, str_dev, sizeof (str_dev)));
|
2013-05-02 08:06:08 +02:00
|
|
|
return klass->ip6_route_delete (platform, ifindex, network, plen, metric);
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2014-08-28 17:25:36 +02:00
|
|
|
nm_platform_ip4_route_exists (int ifindex, in_addr_t network, int plen, guint32 metric)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (platform, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->ip4_route_exists, FALSE);
|
|
|
|
|
|
2013-05-02 08:06:08 +02:00
|
|
|
return klass->ip4_route_exists (platform,ifindex, network, plen, metric);
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2014-08-28 17:25:36 +02:00
|
|
|
nm_platform_ip6_route_exists (int ifindex, struct in6_addr network, int plen, guint32 metric)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (platform, FALSE);
|
|
|
|
|
g_return_val_if_fail (klass->ip6_route_exists, FALSE);
|
|
|
|
|
|
2013-05-02 08:06:08 +02:00
|
|
|
return klass->ip6_route_exists (platform, ifindex, network, plen, metric);
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
2013-05-02 08:02:44 +02:00
|
|
|
static gboolean
|
|
|
|
|
array_contains_ip4_route (const GArray *routes, const NMPlatformIP4Route *route)
|
|
|
|
|
{
|
2013-07-29 23:00:44 +02:00
|
|
|
guint len = routes ? routes->len : 0;
|
|
|
|
|
guint i;
|
2013-05-02 08:02:44 +02:00
|
|
|
|
2014-01-06 14:14:14 -06:00
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
NMPlatformIP4Route *c = &g_array_index (routes, NMPlatformIP4Route, i);
|
|
|
|
|
|
|
|
|
|
if (route->network == c->network &&
|
|
|
|
|
route->plen == c->plen &&
|
|
|
|
|
route->gateway == c->gateway &&
|
|
|
|
|
route->metric == c->metric)
|
2013-05-02 08:02:44 +02:00
|
|
|
return TRUE;
|
2014-01-06 14:14:14 -06:00
|
|
|
}
|
2013-05-02 08:02:44 +02:00
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
array_contains_ip6_route (const GArray *routes, const NMPlatformIP6Route *route)
|
|
|
|
|
{
|
2013-07-29 23:00:44 +02:00
|
|
|
guint len = routes ? routes->len : 0;
|
|
|
|
|
guint i;
|
2013-05-02 08:02:44 +02:00
|
|
|
|
2014-01-06 14:14:14 -06:00
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
NMPlatformIP6Route *c = &g_array_index (routes, NMPlatformIP6Route, i);
|
|
|
|
|
|
|
|
|
|
if (IN6_ARE_ADDR_EQUAL (&route->network, &c->network) &&
|
|
|
|
|
route->plen == c->plen &&
|
|
|
|
|
IN6_ARE_ADDR_EQUAL (&route->gateway, &c->gateway) &&
|
|
|
|
|
route->metric == c->metric)
|
2013-05-02 08:02:44 +02:00
|
|
|
return TRUE;
|
2014-01-06 14:14:14 -06:00
|
|
|
}
|
2013-05-02 08:02:44 +02:00
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_ip4_route_sync:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
* @known_routes: List of routes
|
|
|
|
|
*
|
|
|
|
|
* A convenience function to synchronize routes for a specific interface
|
|
|
|
|
* with the least possible disturbance. It simply removes routes that are
|
|
|
|
|
* not listed and adds routes that are.
|
2014-10-19 00:35:24 +02:00
|
|
|
* Default routes are ignored (both in @known_routes and those already
|
|
|
|
|
* configured on the device).
|
2014-10-24 13:48:46 -04:00
|
|
|
*
|
2013-05-02 08:02:44 +02:00
|
|
|
* Returns: %TRUE on success.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes)
|
|
|
|
|
{
|
|
|
|
|
GArray *routes;
|
|
|
|
|
NMPlatformIP4Route *route;
|
|
|
|
|
const NMPlatformIP4Route *known_route;
|
platform: don't replace routes that already exist
If a route already exists that matches the network, prefix, gateway,
and metric of a route NM would like to add, don't try to overwrite
the route.
Unlike IP addresses, the kernel doesn't update the details, it
appears to completely replace that route, which might screw up
external tools that added the route originally.
One example of this is IPSec via openswan/libreswan. They add the
routes to the kernel upon connection, and if NM replaces those routes,
IPSec no longer works. While this may be due to kernel bugs or
bad handling of route replacement, there's no reason for NM to touch
routes that it wouldn't materially change anyway.
(yes, we could perhaps use NLM_F_REPLACE in add_kernel_object() only
when we really wanted to replace something, but why ask the kernel
to do the work when it's not required anyway?)
2014-01-06 15:24:07 -06:00
|
|
|
gboolean success;
|
2014-01-23 09:11:19 +01:00
|
|
|
int i, i_type;
|
2013-05-02 08:02:44 +02:00
|
|
|
|
|
|
|
|
/* Delete unknown routes */
|
2014-10-14 19:02:50 +02:00
|
|
|
routes = nm_platform_ip4_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT);
|
2013-05-02 08:02:44 +02:00
|
|
|
for (i = 0; i < routes->len; i++) {
|
|
|
|
|
route = &g_array_index (routes, NMPlatformIP4Route, i);
|
|
|
|
|
|
2013-07-29 23:00:44 +02:00
|
|
|
if (!array_contains_ip4_route (known_routes, route))
|
2013-05-02 08:02:44 +02:00
|
|
|
nm_platform_ip4_route_delete (ifindex, route->network, route->plen, route->metric);
|
|
|
|
|
}
|
|
|
|
|
|
platform: don't replace routes that already exist
If a route already exists that matches the network, prefix, gateway,
and metric of a route NM would like to add, don't try to overwrite
the route.
Unlike IP addresses, the kernel doesn't update the details, it
appears to completely replace that route, which might screw up
external tools that added the route originally.
One example of this is IPSec via openswan/libreswan. They add the
routes to the kernel upon connection, and if NM replaces those routes,
IPSec no longer works. While this may be due to kernel bugs or
bad handling of route replacement, there's no reason for NM to touch
routes that it wouldn't materially change anyway.
(yes, we could perhaps use NLM_F_REPLACE in add_kernel_object() only
when we really wanted to replace something, but why ask the kernel
to do the work when it's not required anyway?)
2014-01-06 15:24:07 -06:00
|
|
|
if (!known_routes) {
|
|
|
|
|
g_array_free (routes, TRUE);
|
2013-05-02 08:02:44 +02:00
|
|
|
return TRUE;
|
platform: don't replace routes that already exist
If a route already exists that matches the network, prefix, gateway,
and metric of a route NM would like to add, don't try to overwrite
the route.
Unlike IP addresses, the kernel doesn't update the details, it
appears to completely replace that route, which might screw up
external tools that added the route originally.
One example of this is IPSec via openswan/libreswan. They add the
routes to the kernel upon connection, and if NM replaces those routes,
IPSec no longer works. While this may be due to kernel bugs or
bad handling of route replacement, there's no reason for NM to touch
routes that it wouldn't materially change anyway.
(yes, we could perhaps use NLM_F_REPLACE in add_kernel_object() only
when we really wanted to replace something, but why ask the kernel
to do the work when it's not required anyway?)
2014-01-06 15:24:07 -06:00
|
|
|
}
|
2013-05-02 08:02:44 +02:00
|
|
|
|
|
|
|
|
/* Add missing routes */
|
2014-01-23 09:11:19 +01:00
|
|
|
for (i_type = 0, success = TRUE; i_type < 2 && success; i_type++) {
|
|
|
|
|
for (i = 0; i < known_routes->len && success; i++) {
|
|
|
|
|
known_route = &g_array_index (known_routes, NMPlatformIP4Route, i);
|
|
|
|
|
|
2014-10-24 13:48:46 -04:00
|
|
|
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (known_route))
|
|
|
|
|
continue;
|
|
|
|
|
|
2014-01-23 09:11:19 +01:00
|
|
|
if ((known_route->gateway == 0) ^ (i_type != 0)) {
|
|
|
|
|
/* Make two runs over the list of routes. On the first, only add
|
|
|
|
|
* device routes, on the second the others (gateway routes). */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Ignore routes that already exist */
|
|
|
|
|
if (!array_contains_ip4_route (routes, known_route)) {
|
|
|
|
|
success = nm_platform_ip4_route_add (ifindex,
|
2014-05-08 14:50:02 -04:00
|
|
|
known_route->source,
|
2014-01-23 09:11:19 +01:00
|
|
|
known_route->network,
|
|
|
|
|
known_route->plen,
|
|
|
|
|
known_route->gateway,
|
2014-11-11 14:19:12 +01:00
|
|
|
0,
|
2014-01-23 09:11:19 +01:00
|
|
|
known_route->metric,
|
|
|
|
|
known_route->mss);
|
2014-10-13 11:52:29 +02:00
|
|
|
if (!success && known_route->source < NM_IP_CONFIG_SOURCE_USER) {
|
2014-01-23 09:11:19 +01:00
|
|
|
nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv4 route to kernel: %s",
|
|
|
|
|
nm_platform_ip4_route_to_string (known_route));
|
|
|
|
|
success = TRUE;
|
|
|
|
|
}
|
2014-01-15 20:28:43 +01:00
|
|
|
}
|
platform: don't replace routes that already exist
If a route already exists that matches the network, prefix, gateway,
and metric of a route NM would like to add, don't try to overwrite
the route.
Unlike IP addresses, the kernel doesn't update the details, it
appears to completely replace that route, which might screw up
external tools that added the route originally.
One example of this is IPSec via openswan/libreswan. They add the
routes to the kernel upon connection, and if NM replaces those routes,
IPSec no longer works. While this may be due to kernel bugs or
bad handling of route replacement, there's no reason for NM to touch
routes that it wouldn't materially change anyway.
(yes, we could perhaps use NLM_F_REPLACE in add_kernel_object() only
when we really wanted to replace something, but why ask the kernel
to do the work when it's not required anyway?)
2014-01-06 15:24:07 -06:00
|
|
|
}
|
2013-05-02 08:02:44 +02:00
|
|
|
}
|
|
|
|
|
|
platform: don't replace routes that already exist
If a route already exists that matches the network, prefix, gateway,
and metric of a route NM would like to add, don't try to overwrite
the route.
Unlike IP addresses, the kernel doesn't update the details, it
appears to completely replace that route, which might screw up
external tools that added the route originally.
One example of this is IPSec via openswan/libreswan. They add the
routes to the kernel upon connection, and if NM replaces those routes,
IPSec no longer works. While this may be due to kernel bugs or
bad handling of route replacement, there's no reason for NM to touch
routes that it wouldn't materially change anyway.
(yes, we could perhaps use NLM_F_REPLACE in add_kernel_object() only
when we really wanted to replace something, but why ask the kernel
to do the work when it's not required anyway?)
2014-01-06 15:24:07 -06:00
|
|
|
g_array_free (routes, TRUE);
|
|
|
|
|
return success;
|
2013-05-02 08:02:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_ip6_route_sync:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
* @known_routes: List of routes
|
|
|
|
|
*
|
|
|
|
|
* A convenience function to synchronize routes for a specific interface
|
|
|
|
|
* with the least possible disturbance. It simply removes routes that are
|
|
|
|
|
* not listed and adds routes that are.
|
2014-10-19 00:35:24 +02:00
|
|
|
* Default routes are ignored (both in @known_routes and those already
|
|
|
|
|
* configured on the device).
|
2014-10-24 13:48:46 -04:00
|
|
|
*
|
2013-05-02 08:02:44 +02:00
|
|
|
* Returns: %TRUE on success.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes)
|
|
|
|
|
{
|
|
|
|
|
GArray *routes;
|
|
|
|
|
NMPlatformIP6Route *route;
|
|
|
|
|
const NMPlatformIP6Route *known_route;
|
platform: don't replace routes that already exist
If a route already exists that matches the network, prefix, gateway,
and metric of a route NM would like to add, don't try to overwrite
the route.
Unlike IP addresses, the kernel doesn't update the details, it
appears to completely replace that route, which might screw up
external tools that added the route originally.
One example of this is IPSec via openswan/libreswan. They add the
routes to the kernel upon connection, and if NM replaces those routes,
IPSec no longer works. While this may be due to kernel bugs or
bad handling of route replacement, there's no reason for NM to touch
routes that it wouldn't materially change anyway.
(yes, we could perhaps use NLM_F_REPLACE in add_kernel_object() only
when we really wanted to replace something, but why ask the kernel
to do the work when it's not required anyway?)
2014-01-06 15:24:07 -06:00
|
|
|
gboolean success;
|
2014-01-23 09:11:19 +01:00
|
|
|
int i, i_type;
|
2013-05-02 08:02:44 +02:00
|
|
|
|
|
|
|
|
/* Delete unknown routes */
|
2014-10-14 19:02:50 +02:00
|
|
|
routes = nm_platform_ip6_route_get_all (ifindex, NM_PLATFORM_GET_ROUTE_MODE_NO_DEFAULT);
|
2013-05-02 08:02:44 +02:00
|
|
|
for (i = 0; i < routes->len; i++) {
|
|
|
|
|
route = &g_array_index (routes, NMPlatformIP6Route, i);
|
|
|
|
|
route->ifindex = 0;
|
|
|
|
|
|
2013-07-29 23:00:44 +02:00
|
|
|
if (!array_contains_ip6_route (known_routes, route))
|
2013-05-02 08:02:44 +02:00
|
|
|
nm_platform_ip6_route_delete (ifindex, route->network, route->plen, route->metric);
|
|
|
|
|
}
|
|
|
|
|
|
platform: don't replace routes that already exist
If a route already exists that matches the network, prefix, gateway,
and metric of a route NM would like to add, don't try to overwrite
the route.
Unlike IP addresses, the kernel doesn't update the details, it
appears to completely replace that route, which might screw up
external tools that added the route originally.
One example of this is IPSec via openswan/libreswan. They add the
routes to the kernel upon connection, and if NM replaces those routes,
IPSec no longer works. While this may be due to kernel bugs or
bad handling of route replacement, there's no reason for NM to touch
routes that it wouldn't materially change anyway.
(yes, we could perhaps use NLM_F_REPLACE in add_kernel_object() only
when we really wanted to replace something, but why ask the kernel
to do the work when it's not required anyway?)
2014-01-06 15:24:07 -06:00
|
|
|
if (!known_routes) {
|
|
|
|
|
g_array_free (routes, TRUE);
|
2013-05-02 08:02:44 +02:00
|
|
|
return TRUE;
|
platform: don't replace routes that already exist
If a route already exists that matches the network, prefix, gateway,
and metric of a route NM would like to add, don't try to overwrite
the route.
Unlike IP addresses, the kernel doesn't update the details, it
appears to completely replace that route, which might screw up
external tools that added the route originally.
One example of this is IPSec via openswan/libreswan. They add the
routes to the kernel upon connection, and if NM replaces those routes,
IPSec no longer works. While this may be due to kernel bugs or
bad handling of route replacement, there's no reason for NM to touch
routes that it wouldn't materially change anyway.
(yes, we could perhaps use NLM_F_REPLACE in add_kernel_object() only
when we really wanted to replace something, but why ask the kernel
to do the work when it's not required anyway?)
2014-01-06 15:24:07 -06:00
|
|
|
}
|
2013-05-02 08:02:44 +02:00
|
|
|
|
|
|
|
|
/* Add missing routes */
|
2014-01-23 09:11:19 +01:00
|
|
|
for (i_type = 0, success = TRUE; i_type < 2 && success; i_type++) {
|
|
|
|
|
for (i = 0; i < known_routes->len && success; i++) {
|
|
|
|
|
known_route = &g_array_index (known_routes, NMPlatformIP6Route, i);
|
|
|
|
|
|
2014-10-24 13:48:46 -04:00
|
|
|
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT (known_route))
|
|
|
|
|
continue;
|
|
|
|
|
|
2014-01-23 09:11:19 +01:00
|
|
|
if (IN6_IS_ADDR_UNSPECIFIED (&known_route->gateway) ^ (i_type != 0)) {
|
|
|
|
|
/* Make two runs over the list of routes. On the first, only add
|
|
|
|
|
* device routes, on the second the others (gateway routes). */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Ignore routes that already exist */
|
|
|
|
|
if (!array_contains_ip6_route (routes, known_route)) {
|
|
|
|
|
success = nm_platform_ip6_route_add (ifindex,
|
2014-05-08 14:50:02 -04:00
|
|
|
known_route->source,
|
2014-01-23 09:11:19 +01:00
|
|
|
known_route->network,
|
|
|
|
|
known_route->plen,
|
|
|
|
|
known_route->gateway,
|
|
|
|
|
known_route->metric,
|
|
|
|
|
known_route->mss);
|
2014-10-13 11:52:29 +02:00
|
|
|
if (!success && known_route->source < NM_IP_CONFIG_SOURCE_USER) {
|
2014-01-23 09:11:19 +01:00
|
|
|
nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv6 route to kernel: %s",
|
|
|
|
|
nm_platform_ip6_route_to_string (known_route));
|
|
|
|
|
success = TRUE;
|
|
|
|
|
}
|
2014-01-15 20:28:43 +01:00
|
|
|
}
|
platform: don't replace routes that already exist
If a route already exists that matches the network, prefix, gateway,
and metric of a route NM would like to add, don't try to overwrite
the route.
Unlike IP addresses, the kernel doesn't update the details, it
appears to completely replace that route, which might screw up
external tools that added the route originally.
One example of this is IPSec via openswan/libreswan. They add the
routes to the kernel upon connection, and if NM replaces those routes,
IPSec no longer works. While this may be due to kernel bugs or
bad handling of route replacement, there's no reason for NM to touch
routes that it wouldn't materially change anyway.
(yes, we could perhaps use NLM_F_REPLACE in add_kernel_object() only
when we really wanted to replace something, but why ask the kernel
to do the work when it's not required anyway?)
2014-01-06 15:24:07 -06:00
|
|
|
}
|
2013-05-02 08:02:44 +02:00
|
|
|
}
|
|
|
|
|
|
platform: don't replace routes that already exist
If a route already exists that matches the network, prefix, gateway,
and metric of a route NM would like to add, don't try to overwrite
the route.
Unlike IP addresses, the kernel doesn't update the details, it
appears to completely replace that route, which might screw up
external tools that added the route originally.
One example of this is IPSec via openswan/libreswan. They add the
routes to the kernel upon connection, and if NM replaces those routes,
IPSec no longer works. While this may be due to kernel bugs or
bad handling of route replacement, there's no reason for NM to touch
routes that it wouldn't materially change anyway.
(yes, we could perhaps use NLM_F_REPLACE in add_kernel_object() only
when we really wanted to replace something, but why ask the kernel
to do the work when it's not required anyway?)
2014-01-06 15:24:07 -06:00
|
|
|
g_array_free (routes, TRUE);
|
|
|
|
|
return success;
|
2013-05-02 08:02:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_route_flush (int ifindex)
|
|
|
|
|
{
|
|
|
|
|
return nm_platform_ip4_route_sync (ifindex, NULL)
|
|
|
|
|
&& nm_platform_ip6_route_sync (ifindex, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
/******************************************************************/
|
|
|
|
|
|
2014-01-06 14:14:14 -06:00
|
|
|
static const char *
|
2014-10-13 11:52:29 +02:00
|
|
|
source_to_string (NMIPConfigSource source)
|
2014-01-06 14:14:14 -06:00
|
|
|
{
|
|
|
|
|
switch (source) {
|
2014-10-13 11:52:29 +02:00
|
|
|
case NM_IP_CONFIG_SOURCE_KERNEL:
|
2014-01-06 14:14:14 -06:00
|
|
|
return "kernel";
|
2014-10-13 11:52:29 +02:00
|
|
|
case NM_IP_CONFIG_SOURCE_SHARED:
|
2014-01-06 14:14:14 -06:00
|
|
|
return "shared";
|
2014-10-13 11:52:29 +02:00
|
|
|
case NM_IP_CONFIG_SOURCE_IP4LL:
|
2014-01-06 14:14:14 -06:00
|
|
|
return "ipv4ll";
|
2014-10-13 11:52:29 +02:00
|
|
|
case NM_IP_CONFIG_SOURCE_PPP:
|
2014-01-06 14:14:14 -06:00
|
|
|
return "ppp";
|
2014-10-13 11:52:29 +02:00
|
|
|
case NM_IP_CONFIG_SOURCE_WWAN:
|
2014-01-06 14:14:14 -06:00
|
|
|
return "wwan";
|
2014-10-13 11:52:29 +02:00
|
|
|
case NM_IP_CONFIG_SOURCE_VPN:
|
2014-01-06 14:14:14 -06:00
|
|
|
return "vpn";
|
2014-10-13 11:52:29 +02:00
|
|
|
case NM_IP_CONFIG_SOURCE_DHCP:
|
2014-01-06 14:14:14 -06:00
|
|
|
return "dhcp";
|
2014-10-13 11:52:29 +02:00
|
|
|
case NM_IP_CONFIG_SOURCE_RDISC:
|
2014-01-06 14:14:14 -06:00
|
|
|
return "rdisc";
|
2014-10-13 11:52:29 +02:00
|
|
|
case NM_IP_CONFIG_SOURCE_USER:
|
2014-01-06 14:14:14 -06:00
|
|
|
return "user";
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return "unknown";
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-02 14:31:12 +02:00
|
|
|
static const char *
|
|
|
|
|
_lifetime_to_string (guint32 timestamp, guint32 lifetime, gint32 now, char *buf, size_t buf_size)
|
|
|
|
|
{
|
|
|
|
|
if (lifetime == NM_PLATFORM_LIFETIME_PERMANENT)
|
|
|
|
|
return "forever";
|
|
|
|
|
|
2014-06-06 20:05:08 +02:00
|
|
|
g_snprintf (buf, buf_size, "%usec",
|
2014-06-07 11:32:40 +02:00
|
|
|
_rebase_relative_time_on_now (timestamp, lifetime, now, 0));
|
2014-04-02 14:31:12 +02:00
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
|
_lifetime_summary_to_string (gint32 now, guint32 timestamp, guint32 preferred, guint32 lifetime, char *buf, size_t buf_size)
|
|
|
|
|
{
|
|
|
|
|
g_snprintf (buf, buf_size, " lifetime %d-%u[%u,%u]",
|
|
|
|
|
(signed) now, (unsigned) timestamp, (unsigned) preferred, (unsigned) lifetime);
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-17 13:06:13 +01:00
|
|
|
static char to_string_buffer[256];
|
|
|
|
|
|
2014-02-17 14:08:32 +01:00
|
|
|
const char *
|
|
|
|
|
nm_platform_link_to_string (const NMPlatformLink *link)
|
|
|
|
|
{
|
|
|
|
|
char master[20];
|
|
|
|
|
char parent[20];
|
|
|
|
|
char *driver, *udi, *type;
|
|
|
|
|
GString *str;
|
|
|
|
|
|
|
|
|
|
if (!link)
|
|
|
|
|
return "(unknown link)";
|
|
|
|
|
|
|
|
|
|
str = g_string_new (NULL);
|
|
|
|
|
if (!link->arp)
|
|
|
|
|
g_string_append (str, "NOARP,");
|
|
|
|
|
if (link->up)
|
|
|
|
|
g_string_append (str, "UP");
|
|
|
|
|
else
|
|
|
|
|
g_string_append (str, "DOWN");
|
|
|
|
|
if (link->connected)
|
|
|
|
|
g_string_append (str, ",LOWER_UP");
|
|
|
|
|
|
|
|
|
|
if (link->master)
|
|
|
|
|
g_snprintf (master, sizeof (master), " master %d", link->master);
|
|
|
|
|
else
|
|
|
|
|
master[0] = 0;
|
|
|
|
|
|
|
|
|
|
if (link->parent)
|
|
|
|
|
g_snprintf (parent, sizeof (master), "@%d", link->parent);
|
|
|
|
|
else
|
|
|
|
|
parent[0] = 0;
|
|
|
|
|
|
|
|
|
|
driver = link->driver ? g_strdup_printf (" driver '%s'", link->driver) : NULL;
|
|
|
|
|
udi = link->udi ? g_strdup_printf (" udi '%s'", link->udi) : NULL;
|
|
|
|
|
type = link->type_name ? NULL : g_strdup_printf ("(%d)", link->type);
|
|
|
|
|
|
|
|
|
|
g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%d: %s%s <%s> mtu %d%s %s%s%s",
|
|
|
|
|
link->ifindex, link->name, parent, str->str,
|
|
|
|
|
link->mtu, master, link->type_name ? link->type_name : type,
|
|
|
|
|
driver ? driver : "", udi ? udi : "");
|
|
|
|
|
g_string_free (str, TRUE);
|
|
|
|
|
g_free (driver);
|
|
|
|
|
g_free (udi);
|
|
|
|
|
g_free (type);
|
|
|
|
|
return to_string_buffer;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-29 20:07:34 +02:00
|
|
|
/**
|
|
|
|
|
* nm_platform_ip4_address_to_string:
|
|
|
|
|
* @route: pointer to NMPlatformIP4Address address structure
|
|
|
|
|
*
|
|
|
|
|
* A method for converting an address struct into a string representation.
|
|
|
|
|
*
|
|
|
|
|
* Example output: ""
|
|
|
|
|
*
|
|
|
|
|
* Returns: a string representation of the address. The returned string
|
|
|
|
|
* is an internal buffer, so do not keep or free the returned string.
|
|
|
|
|
* Also, this function is not thread safe.
|
|
|
|
|
*/
|
|
|
|
|
const char *
|
|
|
|
|
nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address)
|
|
|
|
|
{
|
|
|
|
|
char s_address[INET_ADDRSTRLEN];
|
2013-12-02 21:12:05 +01:00
|
|
|
char s_peer[INET_ADDRSTRLEN];
|
2014-02-18 12:52:16 +01:00
|
|
|
char str_dev[TO_STRING_DEV_BUF_SIZE];
|
2014-02-19 16:10:59 -05:00
|
|
|
char str_label[32];
|
2014-04-02 14:31:12 +02:00
|
|
|
char str_lft[30], str_pref[30], str_time[50];
|
2013-12-02 21:12:05 +01:00
|
|
|
char *str_peer = NULL;
|
2014-04-02 14:31:12 +02:00
|
|
|
const char *str_lft_p, *str_pref_p, *str_time_p;
|
|
|
|
|
gint32 now = nm_utils_get_monotonic_timestamp_s ();
|
2013-08-29 20:07:34 +02:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (address, "(unknown)");
|
|
|
|
|
|
|
|
|
|
inet_ntop (AF_INET, &address->address, s_address, sizeof (s_address));
|
2013-10-21 14:36:59 +02:00
|
|
|
|
2013-12-02 21:12:05 +01:00
|
|
|
if (address->peer_address) {
|
|
|
|
|
inet_ntop (AF_INET, &address->peer_address, s_peer, sizeof (s_peer));
|
|
|
|
|
str_peer = g_strconcat (" ptp ", s_peer, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-18 12:52:16 +01:00
|
|
|
_to_string_dev (address->ifindex, str_dev, sizeof (str_dev));
|
2013-08-29 20:07:34 +02:00
|
|
|
|
2014-02-19 16:10:59 -05:00
|
|
|
if (*address->label)
|
|
|
|
|
g_snprintf (str_label, sizeof (str_label), " label %s", address->label);
|
|
|
|
|
else
|
|
|
|
|
str_label[0] = 0;
|
|
|
|
|
|
2014-04-02 14:31:12 +02:00
|
|
|
str_lft_p = _lifetime_to_string (address->timestamp,
|
|
|
|
|
address->lifetime ? address->lifetime : NM_PLATFORM_LIFETIME_PERMANENT,
|
|
|
|
|
now, str_lft, sizeof (str_lft)),
|
|
|
|
|
str_pref_p = (address->lifetime == address->preferred)
|
|
|
|
|
? str_lft_p
|
|
|
|
|
: ( _lifetime_to_string (address->timestamp,
|
|
|
|
|
address->lifetime ? MIN (address->preferred, address->lifetime) : NM_PLATFORM_LIFETIME_PERMANENT,
|
|
|
|
|
now, str_pref, sizeof (str_pref)) );
|
|
|
|
|
str_time_p = _lifetime_summary_to_string (now, address->timestamp, address->preferred, address->lifetime, str_time, sizeof (str_time));
|
|
|
|
|
|
|
|
|
|
g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d lft %s pref %s%s%s%s%s src %s",
|
|
|
|
|
s_address, address->plen, str_lft_p, str_pref_p, str_time_p,
|
2013-12-02 21:12:05 +01:00
|
|
|
str_peer ? str_peer : "",
|
2014-02-18 12:52:16 +01:00
|
|
|
str_dev,
|
2014-02-19 16:10:59 -05:00
|
|
|
str_label,
|
2014-01-06 14:14:14 -06:00
|
|
|
source_to_string (address->source));
|
2013-12-02 21:12:05 +01:00
|
|
|
g_free (str_peer);
|
2014-02-17 13:06:13 +01:00
|
|
|
return to_string_buffer;
|
2013-08-29 20:07:34 +02:00
|
|
|
}
|
|
|
|
|
|
2014-03-04 22:00:24 +01:00
|
|
|
/**
|
|
|
|
|
* nm_platform_addr_flags2str: wrapper for rtnl_addr_flags2str(),
|
|
|
|
|
* which might not yet support some recent address flags.
|
|
|
|
|
**/
|
|
|
|
|
void
|
|
|
|
|
nm_platform_addr_flags2str (int flags, char *buf, size_t size)
|
|
|
|
|
{
|
|
|
|
|
rtnl_addr_flags2str(flags, buf, size);
|
|
|
|
|
|
|
|
|
|
/* There are two recent flags IFA_F_MANAGETEMPADDR and IFA_F_NOPREFIXROUTE.
|
|
|
|
|
* If libnl does not yet support them, add them by hand.
|
|
|
|
|
* These two flags were introduced together with the extended ifa_flags,
|
|
|
|
|
* so, check for that.
|
|
|
|
|
*/
|
|
|
|
|
if ((flags & IFA_F_MANAGETEMPADDR) && !nm_platform_check_support_libnl_extended_ifa_flags ()) {
|
|
|
|
|
strncat (buf, buf[0] ? "," IFA_F_MANAGETEMPADDR_STR : IFA_F_MANAGETEMPADDR_STR,
|
|
|
|
|
size - strlen (buf) - 1);
|
|
|
|
|
}
|
|
|
|
|
if ((flags & IFA_F_NOPREFIXROUTE) && !nm_platform_check_support_libnl_extended_ifa_flags ()) {
|
|
|
|
|
strncat (buf, buf[0] ? "," IFA_F_NOPREFIXROUTE_STR : IFA_F_NOPREFIXROUTE_STR,
|
|
|
|
|
size - strlen (buf) - 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-29 20:07:34 +02:00
|
|
|
/**
|
|
|
|
|
* nm_platform_ip6_address_to_string:
|
|
|
|
|
* @route: pointer to NMPlatformIP6Address address structure
|
|
|
|
|
*
|
|
|
|
|
* A method for converting an address struct into a string representation.
|
|
|
|
|
*
|
|
|
|
|
* Example output: "2001:db8:0:f101::1/64 lft 4294967295 pref 4294967295 time 16922666 on dev em1"
|
|
|
|
|
*
|
|
|
|
|
* Returns: a string representation of the address. The returned string
|
|
|
|
|
* is an internal buffer, so do not keep or free the returned string.
|
|
|
|
|
* Also, this function is not thread safe.
|
|
|
|
|
*/
|
|
|
|
|
const char *
|
|
|
|
|
nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address)
|
|
|
|
|
{
|
2013-10-15 20:44:59 +02:00
|
|
|
char s_flags[256];
|
2013-08-29 20:07:34 +02:00
|
|
|
char s_address[INET6_ADDRSTRLEN];
|
2013-12-02 21:12:05 +01:00
|
|
|
char s_peer[INET6_ADDRSTRLEN];
|
2014-04-02 14:31:12 +02:00
|
|
|
char str_lft[30], str_pref[30], str_time[50];
|
2014-02-18 12:52:16 +01:00
|
|
|
char str_dev[TO_STRING_DEV_BUF_SIZE];
|
2014-04-02 14:31:12 +02:00
|
|
|
char *str_flags;
|
2013-12-02 21:12:05 +01:00
|
|
|
char *str_peer = NULL;
|
2014-04-02 14:31:12 +02:00
|
|
|
const char *str_lft_p, *str_pref_p, *str_time_p;
|
|
|
|
|
gint32 now = nm_utils_get_monotonic_timestamp_s ();
|
2013-08-29 20:07:34 +02:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (address, "(unknown)");
|
|
|
|
|
|
|
|
|
|
inet_ntop (AF_INET6, &address->address, s_address, sizeof (s_address));
|
2013-10-21 14:36:59 +02:00
|
|
|
|
2013-12-02 21:12:05 +01:00
|
|
|
if (!IN6_IS_ADDR_UNSPECIFIED (&address->peer_address)) {
|
|
|
|
|
inet_ntop (AF_INET6, &address->peer_address, s_peer, sizeof (s_peer));
|
|
|
|
|
str_peer = g_strconcat (" ptp ", s_peer, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-18 12:52:16 +01:00
|
|
|
_to_string_dev (address->ifindex, str_dev, sizeof (str_dev));
|
2013-08-29 20:07:34 +02:00
|
|
|
|
2014-03-04 22:00:24 +01:00
|
|
|
nm_platform_addr_flags2str (address->flags, s_flags, sizeof (s_flags));
|
2014-01-03 16:07:36 +01:00
|
|
|
|
2013-10-15 20:44:59 +02:00
|
|
|
str_flags = s_flags[0] ? g_strconcat (" flags ", s_flags, NULL) : NULL;
|
|
|
|
|
|
2014-04-02 14:31:12 +02:00
|
|
|
str_lft_p = _lifetime_to_string (address->timestamp,
|
|
|
|
|
address->lifetime ? address->lifetime : NM_PLATFORM_LIFETIME_PERMANENT,
|
|
|
|
|
now, str_lft, sizeof (str_lft)),
|
|
|
|
|
str_pref_p = (address->lifetime == address->preferred)
|
|
|
|
|
? str_lft_p
|
|
|
|
|
: ( _lifetime_to_string (address->timestamp,
|
|
|
|
|
address->lifetime ? MIN (address->preferred, address->lifetime) : NM_PLATFORM_LIFETIME_PERMANENT,
|
|
|
|
|
now, str_pref, sizeof (str_pref)) );
|
|
|
|
|
str_time_p = _lifetime_summary_to_string (now, address->timestamp, address->preferred, address->lifetime, str_time, sizeof (str_time));
|
|
|
|
|
|
|
|
|
|
g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d lft %s pref %s%s%s%s%s src %s",
|
|
|
|
|
s_address, address->plen, str_lft_p, str_pref_p, str_time_p,
|
2013-12-02 21:12:05 +01:00
|
|
|
str_peer ? str_peer : "",
|
2014-02-18 12:52:16 +01:00
|
|
|
str_dev,
|
2014-01-06 14:14:14 -06:00
|
|
|
str_flags ? str_flags : "",
|
|
|
|
|
source_to_string (address->source));
|
2013-10-15 20:44:59 +02:00
|
|
|
g_free (str_flags);
|
2013-12-02 21:12:05 +01:00
|
|
|
g_free (str_peer);
|
2014-02-17 13:06:13 +01:00
|
|
|
return to_string_buffer;
|
2013-08-29 20:07:34 +02:00
|
|
|
}
|
|
|
|
|
|
2013-08-26 22:10:11 +02:00
|
|
|
/**
|
|
|
|
|
* nm_platform_ip4_route_to_string:
|
|
|
|
|
* @route: pointer to NMPlatformIP4Route route structure
|
|
|
|
|
*
|
|
|
|
|
* A method for converting a route struct into a string representation.
|
|
|
|
|
*
|
2013-08-29 20:07:34 +02:00
|
|
|
* Example output: "192.168.1.0/24 via 0.0.0.0 dev em1 metric 0 mss 0"
|
|
|
|
|
*
|
|
|
|
|
* Returns: a string representation of the route. The returned string
|
|
|
|
|
* is an internal buffer, so do not keep or free the returned string.
|
|
|
|
|
* Also, this function is not thread safe.
|
2013-08-26 22:10:11 +02:00
|
|
|
*/
|
2013-08-29 20:07:34 +02:00
|
|
|
const char *
|
2013-08-26 22:10:11 +02:00
|
|
|
nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route)
|
|
|
|
|
{
|
2013-08-29 20:07:34 +02:00
|
|
|
char s_network[INET_ADDRSTRLEN], s_gateway[INET_ADDRSTRLEN];
|
2014-02-18 12:52:16 +01:00
|
|
|
char str_dev[TO_STRING_DEV_BUF_SIZE];
|
2013-08-29 20:07:34 +02:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (route, "(unknown)");
|
|
|
|
|
|
2013-08-26 22:10:11 +02:00
|
|
|
inet_ntop (AF_INET, &route->network, s_network, sizeof(s_network));
|
|
|
|
|
inet_ntop (AF_INET, &route->gateway, s_gateway, sizeof(s_gateway));
|
2013-10-21 14:36:59 +02:00
|
|
|
|
2014-02-18 12:52:16 +01:00
|
|
|
_to_string_dev (route->ifindex, str_dev, sizeof (str_dev));
|
2013-08-29 20:07:34 +02:00
|
|
|
|
2014-08-28 17:25:36 +02:00
|
|
|
g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d via %s%s metric %"G_GUINT32_FORMAT" mss %"G_GUINT32_FORMAT" src %s",
|
2013-10-21 14:36:59 +02:00
|
|
|
s_network, route->plen, s_gateway,
|
2014-02-18 12:52:16 +01:00
|
|
|
str_dev,
|
2014-01-06 14:14:14 -06:00
|
|
|
route->metric, route->mss,
|
|
|
|
|
source_to_string (route->source));
|
2014-02-17 13:06:13 +01:00
|
|
|
return to_string_buffer;
|
2013-08-29 20:07:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_ip6_route_to_string:
|
|
|
|
|
* @route: pointer to NMPlatformIP6Route route structure
|
|
|
|
|
*
|
|
|
|
|
* A method for converting a route struct into a string representation.
|
|
|
|
|
*
|
|
|
|
|
* Example output: "ff02::fb/128 via :: dev em1 metric 0"
|
|
|
|
|
*
|
|
|
|
|
* Returns: a string representation of the route. The returned string
|
|
|
|
|
* is an internal buffer, so do not keep or free the returned string.
|
|
|
|
|
* Also, this function is not thread safe.
|
|
|
|
|
*/
|
|
|
|
|
const char *
|
|
|
|
|
nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route)
|
|
|
|
|
{
|
|
|
|
|
char s_network[INET6_ADDRSTRLEN], s_gateway[INET6_ADDRSTRLEN];
|
2014-02-18 12:52:16 +01:00
|
|
|
char str_dev[TO_STRING_DEV_BUF_SIZE];
|
2013-08-29 20:07:34 +02:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (route, "(unknown)");
|
|
|
|
|
|
|
|
|
|
inet_ntop (AF_INET6, &route->network, s_network, sizeof(s_network));
|
|
|
|
|
inet_ntop (AF_INET6, &route->gateway, s_gateway, sizeof(s_gateway));
|
2013-10-21 14:36:59 +02:00
|
|
|
|
2014-02-18 12:52:16 +01:00
|
|
|
_to_string_dev (route->ifindex, str_dev, sizeof (str_dev));
|
2013-08-29 20:07:34 +02:00
|
|
|
|
2014-08-28 17:25:36 +02:00
|
|
|
g_snprintf (to_string_buffer, sizeof (to_string_buffer), "%s/%d via %s%s metric %"G_GUINT32_FORMAT" mss %"G_GUINT32_FORMAT" src %s",
|
2013-10-21 14:36:59 +02:00
|
|
|
s_network, route->plen, s_gateway,
|
2014-02-18 12:52:16 +01:00
|
|
|
str_dev,
|
2014-01-06 14:14:14 -06:00
|
|
|
route->metric, route->mss,
|
|
|
|
|
source_to_string (route->source));
|
2014-02-17 13:06:13 +01:00
|
|
|
return to_string_buffer;
|
2013-08-26 22:10:11 +02:00
|
|
|
}
|
|
|
|
|
|
2013-09-06 09:58:55 +02:00
|
|
|
#define _CMP_POINTER(a, b) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
if ((a) == (b)) \
|
|
|
|
|
return 0; \
|
|
|
|
|
if (!(a)) \
|
|
|
|
|
return -1; \
|
|
|
|
|
if (!(b)) \
|
|
|
|
|
return 1; \
|
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
|
|
|
|
#define _CMP_FIELD(a, b, field) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
if (((a)->field) != ((b)->field)) \
|
|
|
|
|
return (((a)->field) < ((b)->field)) ? -1 : 1; \
|
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
2014-02-19 16:10:59 -05:00
|
|
|
#define _CMP_FIELD_STR(a, b, field) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
int c = strcmp ((a)->field, (b)->field); \
|
|
|
|
|
if (c != 0) \
|
|
|
|
|
return c < 0 ? -1 : 1; \
|
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
2014-04-05 18:35:20 +02:00
|
|
|
#define _CMP_FIELD_STR0(a, b, field) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
int c = g_strcmp0 ((a)->field, (b)->field); \
|
|
|
|
|
if (c != 0) \
|
|
|
|
|
return c < 0 ? -1 : 1; \
|
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
2013-09-06 09:58:55 +02:00
|
|
|
#define _CMP_FIELD_MEMCMP(a, b, field) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
int c = memcmp (&((a)->field), &((b)->field), \
|
|
|
|
|
sizeof ((a)->field)); \
|
|
|
|
|
if (c != 0) \
|
|
|
|
|
return c < 0 ? -1 : 1; \
|
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
2014-04-05 18:35:20 +02:00
|
|
|
int
|
|
|
|
|
nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b)
|
|
|
|
|
{
|
|
|
|
|
_CMP_POINTER (a, b);
|
|
|
|
|
_CMP_FIELD (a, b, type);
|
|
|
|
|
_CMP_FIELD_STR (a, b, name);
|
|
|
|
|
_CMP_FIELD (a, b, master);
|
|
|
|
|
_CMP_FIELD (a, b, parent);
|
|
|
|
|
_CMP_FIELD (a, b, up);
|
|
|
|
|
_CMP_FIELD (a, b, connected);
|
|
|
|
|
_CMP_FIELD (a, b, arp);
|
|
|
|
|
_CMP_FIELD (a, b, mtu);
|
|
|
|
|
_CMP_FIELD_STR0 (a, b, type_name);
|
|
|
|
|
_CMP_FIELD_STR0 (a, b, udi);
|
|
|
|
|
_CMP_FIELD_STR0 (a, b, driver);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-06 09:58:55 +02:00
|
|
|
int
|
|
|
|
|
nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b)
|
|
|
|
|
{
|
|
|
|
|
_CMP_POINTER (a, b);
|
2014-01-06 14:14:14 -06:00
|
|
|
_CMP_FIELD (a, b, ifindex);
|
|
|
|
|
_CMP_FIELD (a, b, source);
|
2014-01-15 20:09:57 +01:00
|
|
|
_CMP_FIELD (a, b, address);
|
|
|
|
|
_CMP_FIELD (a, b, peer_address);
|
2013-09-06 09:58:55 +02:00
|
|
|
_CMP_FIELD (a, b, plen);
|
|
|
|
|
_CMP_FIELD (a, b, timestamp);
|
|
|
|
|
_CMP_FIELD (a, b, lifetime);
|
|
|
|
|
_CMP_FIELD (a, b, preferred);
|
2014-02-19 16:10:59 -05:00
|
|
|
_CMP_FIELD_STR (a, b, label);
|
2013-09-06 09:58:55 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6Address *b)
|
|
|
|
|
{
|
|
|
|
|
_CMP_POINTER (a, b);
|
|
|
|
|
_CMP_FIELD (a, b, ifindex);
|
2014-01-06 14:14:14 -06:00
|
|
|
_CMP_FIELD (a, b, source);
|
2013-09-06 09:58:55 +02:00
|
|
|
_CMP_FIELD_MEMCMP (a, b, address);
|
2013-12-02 10:20:26 -05:00
|
|
|
_CMP_FIELD_MEMCMP (a, b, peer_address);
|
2013-09-06 09:58:55 +02:00
|
|
|
_CMP_FIELD (a, b, plen);
|
|
|
|
|
_CMP_FIELD (a, b, timestamp);
|
|
|
|
|
_CMP_FIELD (a, b, lifetime);
|
|
|
|
|
_CMP_FIELD (a, b, preferred);
|
2013-10-15 20:44:59 +02:00
|
|
|
_CMP_FIELD (a, b, flags);
|
2013-09-06 09:58:55 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b)
|
|
|
|
|
{
|
|
|
|
|
_CMP_POINTER (a, b);
|
|
|
|
|
_CMP_FIELD (a, b, ifindex);
|
2014-01-06 14:14:14 -06:00
|
|
|
_CMP_FIELD (a, b, source);
|
2014-01-15 20:09:57 +01:00
|
|
|
_CMP_FIELD (a, b, network);
|
2013-09-06 09:58:55 +02:00
|
|
|
_CMP_FIELD (a, b, plen);
|
2014-01-15 20:09:57 +01:00
|
|
|
_CMP_FIELD (a, b, gateway);
|
2013-09-06 09:58:55 +02:00
|
|
|
_CMP_FIELD (a, b, metric);
|
|
|
|
|
_CMP_FIELD (a, b, mss);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b)
|
|
|
|
|
{
|
|
|
|
|
_CMP_POINTER (a, b);
|
|
|
|
|
_CMP_FIELD (a, b, ifindex);
|
2014-01-06 14:14:14 -06:00
|
|
|
_CMP_FIELD (a, b, source);
|
2013-09-06 09:58:55 +02:00
|
|
|
_CMP_FIELD_MEMCMP (a, b, network);
|
|
|
|
|
_CMP_FIELD (a, b, plen);
|
|
|
|
|
_CMP_FIELD_MEMCMP (a, b, gateway);
|
|
|
|
|
_CMP_FIELD (a, b, metric);
|
|
|
|
|
_CMP_FIELD (a, b, mss);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#undef _CMP_FIELD
|
|
|
|
|
#undef _CMP_FIELD_MEMCMP
|
|
|
|
|
|
2014-04-03 11:42:00 +02:00
|
|
|
/**
|
|
|
|
|
* nm_platform_ip_address_cmp_expiry:
|
|
|
|
|
* @a: a NMPlatformIPAddress to compare
|
|
|
|
|
* @b: the other NMPlatformIPAddress to compare
|
|
|
|
|
*
|
|
|
|
|
* Compares two addresses and returns which one has a longer remaining lifetime.
|
|
|
|
|
* If both addresses have the same lifetime, look at the remaining preferred time.
|
|
|
|
|
*
|
|
|
|
|
* For comparison, only the timestamp, lifetime and preferred fields are considered.
|
|
|
|
|
* If they compare equal (== 0), their other fields were not considered.
|
|
|
|
|
*
|
|
|
|
|
* Returns: -1, 0, or 1 according to the comparison
|
|
|
|
|
**/
|
|
|
|
|
int
|
|
|
|
|
nm_platform_ip_address_cmp_expiry (const NMPlatformIPAddress *a, const NMPlatformIPAddress *b)
|
|
|
|
|
{
|
2014-06-09 10:28:55 +02:00
|
|
|
gint64 ta = 0, tb = 0;
|
2014-04-03 11:42:00 +02:00
|
|
|
|
|
|
|
|
_CMP_POINTER (a, b);
|
|
|
|
|
|
|
|
|
|
if (a->lifetime == NM_PLATFORM_LIFETIME_PERMANENT || a->lifetime == 0)
|
|
|
|
|
ta = G_MAXINT64;
|
2014-06-09 10:28:55 +02:00
|
|
|
else if (a->timestamp)
|
2014-04-03 11:42:00 +02:00
|
|
|
ta = ((gint64) a->timestamp) + a->lifetime;
|
|
|
|
|
|
|
|
|
|
if (b->lifetime == NM_PLATFORM_LIFETIME_PERMANENT || b->lifetime == 0)
|
|
|
|
|
tb = G_MAXINT64;
|
2014-06-09 10:28:55 +02:00
|
|
|
else if (b->timestamp)
|
2014-04-03 11:42:00 +02:00
|
|
|
tb = ((gint64) b->timestamp) + b->lifetime;
|
|
|
|
|
|
|
|
|
|
if (ta == tb) {
|
|
|
|
|
/* if the lifetime is equal, compare the preferred time. */
|
2014-06-09 10:28:55 +02:00
|
|
|
ta = tb = 0;
|
2014-04-03 11:42:00 +02:00
|
|
|
|
|
|
|
|
if (a->preferred == NM_PLATFORM_LIFETIME_PERMANENT || a->lifetime == 0 /* liftime==0 means permanent! */)
|
|
|
|
|
ta = G_MAXINT64;
|
2014-06-09 10:28:55 +02:00
|
|
|
else if (a->timestamp)
|
2014-04-03 11:42:00 +02:00
|
|
|
ta = ((gint64) a->timestamp) + a->preferred;
|
|
|
|
|
|
|
|
|
|
if (b->preferred == NM_PLATFORM_LIFETIME_PERMANENT|| b->lifetime == 0)
|
|
|
|
|
tb = G_MAXINT64;
|
2014-06-09 10:28:55 +02:00
|
|
|
else if (b->timestamp)
|
2014-04-03 11:42:00 +02:00
|
|
|
tb = ((gint64) b->timestamp) + b->preferred;
|
|
|
|
|
|
|
|
|
|
if (ta == tb)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ta < tb ? -1 : 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#undef _CMP_POINTER
|
2013-09-06 09:58:55 +02:00
|
|
|
|
2014-03-07 19:04:38 +01:00
|
|
|
static const char *
|
|
|
|
|
_change_type_to_string (NMPlatformSignalChangeType change_type)
|
|
|
|
|
{
|
|
|
|
|
switch (change_type) {
|
|
|
|
|
case NM_PLATFORM_SIGNAL_ADDED:
|
|
|
|
|
return "added";
|
|
|
|
|
case NM_PLATFORM_SIGNAL_CHANGED:
|
|
|
|
|
return "changed";
|
|
|
|
|
case NM_PLATFORM_SIGNAL_REMOVED:
|
|
|
|
|
return "removed";
|
|
|
|
|
default:
|
|
|
|
|
g_return_val_if_reached ("UNKNOWN");
|
|
|
|
|
}
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-03-07 19:04:38 +01:00
|
|
|
log_link (NMPlatform *p, int ifindex, NMPlatformLink *device, NMPlatformSignalChangeType change_type, gpointer user_data)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
|
|
|
|
|
2014-03-07 19:04:38 +01:00
|
|
|
debug ("signal: link %7s: %s", _change_type_to_string (change_type), nm_platform_link_to_string (device));
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-03-07 19:04:38 +01:00
|
|
|
log_ip4_address (NMPlatform *p, int ifindex, NMPlatformIP4Address *address, NMPlatformSignalChangeType change_type, gpointer user_data)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
2014-03-07 19:04:38 +01:00
|
|
|
debug ("signal: address 4 %7s: %s", _change_type_to_string (change_type), nm_platform_ip4_address_to_string (address));
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-03-07 19:04:38 +01:00
|
|
|
log_ip6_address (NMPlatform *p, int ifindex, NMPlatformIP6Address *address, NMPlatformSignalChangeType change_type, gpointer user_data)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
2014-03-07 19:04:38 +01:00
|
|
|
debug ("signal: address 6 %7s: %s", _change_type_to_string (change_type), nm_platform_ip6_address_to_string (address));
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-03-07 19:04:38 +01:00
|
|
|
log_ip4_route (NMPlatform *p, int ifindex, NMPlatformIP4Route *route, NMPlatformSignalChangeType change_type, gpointer user_data)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
2014-03-07 19:04:38 +01:00
|
|
|
debug ("signal: route 4 %7s: %s", _change_type_to_string (change_type), nm_platform_ip4_route_to_string (route));
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2014-03-07 19:04:38 +01:00
|
|
|
log_ip6_route (NMPlatform *p, int ifindex, NMPlatformIP6Route *route, NMPlatformSignalChangeType change_type, gpointer user_data)
|
2013-03-27 22:23:24 +01:00
|
|
|
{
|
2014-03-07 19:04:38 +01:00
|
|
|
debug ("signal: route 6 %7s: %s", _change_type_to_string (change_type), nm_platform_ip6_route_to_string (route));
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|
|
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
/******************************************************************/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_platform_init (NMPlatform *object)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define SIGNAL(signal_id, method) signals[signal_id] = \
|
|
|
|
|
g_signal_new_class_handler (NM_PLATFORM_ ## signal_id, \
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class), \
|
|
|
|
|
G_SIGNAL_RUN_FIRST, \
|
|
|
|
|
G_CALLBACK (method), \
|
2013-05-06 13:37:25 -04:00
|
|
|
NULL, NULL, NULL, \
|
2014-03-07 19:04:38 +01:00
|
|
|
G_TYPE_NONE, 4, G_TYPE_INT, G_TYPE_POINTER, NM_TYPE_PLATFORM_SIGNAL_CHANGE_TYPE, NM_TYPE_PLATFORM_REASON);
|
2013-03-27 22:23:24 +01:00
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_platform_class_init (NMPlatformClass *platform_class)
|
|
|
|
|
{
|
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (platform_class);
|
|
|
|
|
|
|
|
|
|
/* Signals */
|
2014-03-07 19:04:38 +01:00
|
|
|
SIGNAL (SIGNAL_LINK_CHANGED, log_link)
|
|
|
|
|
SIGNAL (SIGNAL_IP4_ADDRESS_CHANGED, log_ip4_address)
|
|
|
|
|
SIGNAL (SIGNAL_IP6_ADDRESS_CHANGED, log_ip6_address)
|
|
|
|
|
SIGNAL (SIGNAL_IP4_ROUTE_CHANGED, log_ip4_route)
|
|
|
|
|
SIGNAL (SIGNAL_IP6_ROUTE_CHANGED, log_ip6_route)
|
2013-03-27 22:23:24 +01:00
|
|
|
}
|