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"
|
2015-02-22 11:54:03 +01:00
|
|
|
#include "nm-core-internal.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
|
|
|
|
2015-02-22 11:55:31 +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);
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-22 16:41:15 +01:00
|
|
|
/**
|
|
|
|
|
* nm_platform_link_get_unmanaged:
|
|
|
|
|
* @ifindex: Interface index.
|
|
|
|
|
* @managed: Management status in case %TRUE is returned
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE if platform overrides whether the device ought
|
|
|
|
|
* to be managed by default. %FALSE with @managed unmodified
|
|
|
|
|
* otherwise.
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_get_unmanaged (int ifindex, gboolean *managed)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (klass->link_get_unmanaged, FALSE);
|
|
|
|
|
|
|
|
|
|
return klass->link_get_unmanaged (platform, ifindex, managed);
|
|
|
|
|
}
|
|
|
|
|
|
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-09-27 09:03:56 +02:00
|
|
|
/**
|
|
|
|
|
* nm_platform_link_get_ipv6_token:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
* @iid: Tokenized interface identifier
|
|
|
|
|
*
|
|
|
|
|
* Returns IPv6 tokenized interface identifier. If the platform or OS doesn't
|
|
|
|
|
* support IPv6 tokenized interface identifiers, or the token is not set
|
|
|
|
|
* this call will fail and return %FALSE.
|
|
|
|
|
*
|
|
|
|
|
* Returns: %TRUE a tokenized identifier was available
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
nm_platform_link_get_ipv6_token (int ifindex, NMUtilsIPv6IfaceId *iid)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (ifindex >= 0, FALSE);
|
|
|
|
|
g_return_val_if_fail (iid, FALSE);
|
|
|
|
|
|
|
|
|
|
if (klass->link_get_ipv6_token)
|
|
|
|
|
return klass->link_get_ipv6_token (platform, ifindex, iid);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
/**
|
2015-03-24 12:18:48 -05:00
|
|
|
* nm_platform_link_get_physical_port_id:
|
2013-10-11 14:59:26 -04:00
|
|
|
* @ifindex: Interface index
|
|
|
|
|
*
|
2015-03-24 12:18:48 -05:00
|
|
|
* The physical port ID, if present, indicates some unique identifier of
|
|
|
|
|
* the parent interface (eg, the physical port of which this link is a child).
|
|
|
|
|
* Two links that report the same physical port ID can be assumed to be
|
|
|
|
|
* children of the same physical port and may share resources that limit
|
|
|
|
|
* their abilities.
|
|
|
|
|
*
|
2013-10-11 14:59:26 -04:00
|
|
|
* 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);
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-23 14:19:59 -04:00
|
|
|
static void
|
|
|
|
|
wifi_set_powersave (NMPlatform *p, int ifindex, guint32 powersave)
|
|
|
|
|
{
|
|
|
|
|
/* empty */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_platform_wifi_set_powersave (int ifindex, guint32 powersave)
|
|
|
|
|
{
|
|
|
|
|
reset_error ();
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (ifindex > 0);
|
|
|
|
|
|
|
|
|
|
klass->wifi_set_powersave (platform, ifindex, powersave);
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-04 14:27:03 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
2014-11-26 00:10:04 +01:00
|
|
|
gboolean
|
|
|
|
|
nm_platform_ip4_check_reinstall_device_route (int ifindex, const NMPlatformIP4Address *address, guint32 device_route_metric)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (address, FALSE);
|
|
|
|
|
|
|
|
|
|
if ( ifindex <= 0
|
|
|
|
|
|| address->plen <= 0
|
|
|
|
|
|| address->plen >= 32)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (device_route_metric == NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE) {
|
|
|
|
|
/* The automatically added route would be already our desired priority.
|
|
|
|
|
* Nothing to do. */
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return klass->ip4_check_reinstall_device_route (platform, ifindex, address, device_route_metric);
|
|
|
|
|
}
|
|
|
|
|
|
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;
|
2014-11-26 00:10:04 +01:00
|
|
|
gboolean reinstall_device_route = FALSE;
|
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-11-26 00:10:04 +01:00
|
|
|
if (nm_platform_ip4_check_reinstall_device_route (ifindex, known_address, device_route_metric))
|
|
|
|
|
reinstall_device_route = TRUE;
|
|
|
|
|
|
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
|
|
|
|
2014-11-26 00:10:04 +01:00
|
|
|
if (reinstall_device_route) {
|
|
|
|
|
/* 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, would replace the other. This is avoided
|
|
|
|
|
* by the above nm_platform_ip4_check_reinstall_device_route() check.
|
|
|
|
|
*/
|
|
|
|
|
network = nm_utils_ip4_address_clear_host_address (known_address->address, known_address->plen);
|
|
|
|
|
(void) nm_platform_ip4_route_add (ifindex, NM_IP_CONFIG_SOURCE_KERNEL, network, known_address->plen,
|
|
|
|
|
0, known_address->address, device_route_metric, 0);
|
|
|
|
|
(void) nm_platform_ip4_route_delete (ifindex, network, known_address->plen,
|
|
|
|
|
NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE);
|
2014-11-11 14:55:07 +01:00
|
|
|
}
|
2013-04-16 14:24:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* nm_platform_ip6_address_sync:
|
|
|
|
|
* @ifindex: Interface index
|
|
|
|
|
* @known_addresses: List of addresses
|
2015-01-28 12:00:00 +01:00
|
|
|
* @keep_link_local: Don't remove link-local address
|
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
|
2015-01-28 12:00:00 +01:00
|
|
|
nm_platform_ip6_address_sync (int ifindex, const GArray *known_addresses, gboolean keep_link_local)
|
2013-04-16 14:24:46 +02:00
|
|
|
{
|
|
|
|
|
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 */
|
2015-01-28 12:00:00 +01:00
|
|
|
if (keep_link_local && IN6_IS_ADDR_LINKLOCAL (&address->address))
|
2013-04-16 14:24:46 +02:00
|
|
|
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)
|
2015-01-28 12:00:00 +01:00
|
|
|
&& nm_platform_ip6_address_sync (ifindex, NULL, FALSE);
|
2013-04-16 14:24:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/******************************************************************/
|
|
|
|
|
|
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-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);
|
|
|
|
|
|
2014-10-23 14:19:59 -04:00
|
|
|
platform_class->wifi_set_powersave = wifi_set_powersave;
|
|
|
|
|
|
2013-03-27 22:23:24 +01:00
|
|
|
/* 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
|
|
|
}
|