
There can be multiple default routes for an interface with different metrics. Grab the gateway of the default route with the lowest metric as the overall gateway of the IP config. Otherwise the rest could get left in the config and applied at random times.
1727 lines
46 KiB
C
1727 lines
46 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
|
/* NetworkManager
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* 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) 2005 - 2013 Red Hat, Inc.
|
|
* Copyright (C) 2006 - 2008 Novell, Inc.
|
|
*/
|
|
|
|
#include <string.h>
|
|
|
|
#include "nm-ip4-config.h"
|
|
|
|
#include "libgsystem.h"
|
|
#include "nm-platform.h"
|
|
#include "nm-utils.h"
|
|
#include "nm-dbus-manager.h"
|
|
#include "nm-dbus-glib-types.h"
|
|
#include "nm-ip4-config-glue.h"
|
|
#include "NetworkManagerUtils.h"
|
|
|
|
|
|
G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, G_TYPE_OBJECT)
|
|
|
|
#define NM_IP4_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IP4_CONFIG, NMIP4ConfigPrivate))
|
|
|
|
typedef struct {
|
|
char *path;
|
|
|
|
gboolean never_default;
|
|
guint32 gateway;
|
|
GArray *addresses;
|
|
GArray *routes;
|
|
GArray *nameservers;
|
|
GPtrArray *domains;
|
|
GPtrArray *searches;
|
|
guint32 mss;
|
|
guint32 ptp_address;
|
|
GArray *nis;
|
|
char *nis_domain;
|
|
GArray *wins;
|
|
guint32 mtu;
|
|
} NMIP4ConfigPrivate;
|
|
|
|
/* internal guint32 are assigned to gobject properties of type uint. Ensure, that uint is large enough */
|
|
G_STATIC_ASSERT (sizeof (uint) >= sizeof (guint32));
|
|
G_STATIC_ASSERT (G_MAXUINT >= 0xFFFFFFFF);
|
|
|
|
enum {
|
|
PROP_0,
|
|
PROP_GATEWAY,
|
|
PROP_ADDRESSES,
|
|
PROP_ROUTES,
|
|
PROP_NAMESERVERS,
|
|
PROP_DOMAINS,
|
|
PROP_SEARCHES,
|
|
PROP_WINS_SERVERS,
|
|
|
|
LAST_PROP
|
|
};
|
|
static GParamSpec *obj_properties[LAST_PROP] = { NULL, };
|
|
#define _NOTIFY(config, prop) G_STMT_START { g_object_notify_by_pspec (G_OBJECT (config), obj_properties[prop]); } G_STMT_END
|
|
|
|
|
|
NMIP4Config *
|
|
nm_ip4_config_new (void)
|
|
{
|
|
return (NMIP4Config *) g_object_new (NM_TYPE_IP4_CONFIG, NULL);
|
|
}
|
|
|
|
|
|
void
|
|
nm_ip4_config_export (NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
static guint32 counter = 0;
|
|
|
|
if (!priv->path) {
|
|
priv->path = g_strdup_printf (NM_DBUS_PATH "/IP4Config/%d", counter++);
|
|
nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->path, config);
|
|
}
|
|
}
|
|
|
|
const char *
|
|
nm_ip4_config_get_dbus_path (const NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return priv->path;
|
|
}
|
|
|
|
static gboolean
|
|
same_prefix (guint32 address1, guint32 address2, int plen)
|
|
{
|
|
guint32 masked1 = ntohl (address1) >> (32 - plen);
|
|
guint32 masked2 = ntohl (address2) >> (32 - plen);
|
|
|
|
return masked1 == masked2;
|
|
}
|
|
|
|
/******************************************************************/
|
|
|
|
/**
|
|
* nm_ip4_config_capture_resolv_conf():
|
|
* @nameservers: array of guint32
|
|
* @rc_contents: the contents of a resolv.conf or %NULL to read /etc/resolv.conf
|
|
*
|
|
* Reads all resolv.conf IPv6 nameservers and adds them to @nameservers.
|
|
*
|
|
* Returns: %TRUE if nameservers were added, %FALSE if @nameservers is unchanged
|
|
*/
|
|
gboolean
|
|
nm_ip4_config_capture_resolv_conf (GArray *nameservers,
|
|
const char *rc_contents)
|
|
{
|
|
GPtrArray *read_ns;
|
|
guint i, j;
|
|
gboolean changed = FALSE;
|
|
|
|
g_return_val_if_fail (nameservers != NULL, FALSE);
|
|
|
|
read_ns = nm_utils_read_resolv_conf_nameservers (rc_contents);
|
|
if (!read_ns)
|
|
return FALSE;
|
|
|
|
for (i = 0; i < read_ns->len; i++) {
|
|
const char *s = g_ptr_array_index (read_ns, i);
|
|
guint32 ns = 0;
|
|
|
|
if (!inet_pton (AF_INET, s, (void *) &ns) || !ns)
|
|
continue;
|
|
|
|
/* Ignore duplicates */
|
|
for (j = 0; j < nameservers->len; j++) {
|
|
if (g_array_index (nameservers, guint32, j) == ns)
|
|
break;
|
|
}
|
|
|
|
if (j == nameservers->len) {
|
|
g_array_append_val (nameservers, ns);
|
|
changed = TRUE;
|
|
}
|
|
}
|
|
|
|
g_ptr_array_unref (read_ns);
|
|
return changed;
|
|
}
|
|
|
|
static gboolean
|
|
addresses_are_duplicate (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b, gboolean consider_plen)
|
|
{
|
|
return a->address == b->address && (!consider_plen || a->plen == b->plen);
|
|
}
|
|
|
|
static gboolean
|
|
routes_are_duplicate (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, gboolean consider_gateway_and_metric)
|
|
{
|
|
return a->network == b->network && a->plen == b->plen &&
|
|
(!consider_gateway_and_metric || (a->gateway == b->gateway && a->metric == b->metric));
|
|
}
|
|
|
|
NMIP4Config *
|
|
nm_ip4_config_capture (int ifindex, gboolean capture_resolv_conf)
|
|
{
|
|
NMIP4Config *config;
|
|
NMIP4ConfigPrivate *priv;
|
|
guint i;
|
|
guint lowest_metric = G_MAXUINT;
|
|
guint32 old_gateway = 0;
|
|
gboolean has_gateway = FALSE;
|
|
|
|
/* Slaves have no IP configuration */
|
|
if (nm_platform_link_get_master (ifindex) > 0)
|
|
return NULL;
|
|
|
|
config = nm_ip4_config_new ();
|
|
priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
g_array_unref (priv->addresses);
|
|
g_array_unref (priv->routes);
|
|
|
|
priv->addresses = nm_platform_ip4_address_get_all (ifindex);
|
|
priv->routes = nm_platform_ip4_route_get_all (ifindex, TRUE);
|
|
|
|
/* Extract gateway from default route */
|
|
old_gateway = priv->gateway;
|
|
for (i = 0; i < priv->routes->len; i++) {
|
|
const NMPlatformIP4Route *route = &g_array_index (priv->routes, NMPlatformIP4Route, i);
|
|
|
|
if (route->network == 0) {
|
|
if (route->metric < lowest_metric) {
|
|
priv->gateway = route->gateway;
|
|
lowest_metric = route->metric;
|
|
}
|
|
has_gateway = TRUE;
|
|
/* Remove the default route from the list */
|
|
g_array_remove_index (priv->routes, i);
|
|
i--;
|
|
}
|
|
}
|
|
|
|
/* If the interface has the default route, and has IPv4 addresses, capture
|
|
* nameservers from /etc/resolv.conf.
|
|
*/
|
|
if (priv->addresses->len && has_gateway && capture_resolv_conf) {
|
|
if (nm_ip4_config_capture_resolv_conf (priv->nameservers, NULL))
|
|
_NOTIFY (config, PROP_NAMESERVERS);
|
|
}
|
|
|
|
/* actually, nobody should be connected to the signal, just to be sure, notify */
|
|
_NOTIFY (config, PROP_ADDRESSES);
|
|
_NOTIFY (config, PROP_ROUTES);
|
|
if (priv->gateway != old_gateway)
|
|
_NOTIFY (config, PROP_GATEWAY);
|
|
|
|
return config;
|
|
}
|
|
|
|
gboolean
|
|
nm_ip4_config_commit (const NMIP4Config *config, int ifindex, int priority)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
int mtu = nm_ip4_config_get_mtu (config);
|
|
int i;
|
|
|
|
g_return_val_if_fail (ifindex > 0, FALSE);
|
|
g_return_val_if_fail (config != NULL, FALSE);
|
|
|
|
/* Addresses */
|
|
nm_platform_ip4_address_sync (ifindex, priv->addresses);
|
|
|
|
/* Routes */
|
|
{
|
|
int count = nm_ip4_config_get_num_routes (config);
|
|
GArray *routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP4Route), count);
|
|
NMPlatformIP4Route route;
|
|
gboolean success;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
memcpy (&route, nm_ip4_config_get_route (config, i), sizeof (route));
|
|
route.metric = priority;
|
|
|
|
/* Don't add the route if it's more specific than one of the subnets
|
|
* the device already has an IP address on.
|
|
*/
|
|
if (nm_ip4_config_destination_is_direct (config, route.network, route.plen))
|
|
continue;
|
|
|
|
/* Don't add the default route when and the connection
|
|
* is never supposed to be the default connection.
|
|
*/
|
|
if (nm_ip4_config_get_never_default (config) && route.network == 0)
|
|
continue;
|
|
|
|
g_array_append_val (routes, route);
|
|
}
|
|
|
|
success = nm_platform_ip4_route_sync (ifindex, routes);
|
|
g_array_unref (routes);
|
|
if (!success)
|
|
return FALSE;
|
|
}
|
|
|
|
/* MTU */
|
|
if (mtu && mtu != nm_platform_link_get_mtu (ifindex))
|
|
nm_platform_link_set_mtu (ifindex, mtu);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_merge_setting (NMIP4Config *config, NMSettingIP4Config *setting)
|
|
{
|
|
guint naddresses, nroutes, nnameservers, nsearches;
|
|
int i;
|
|
|
|
if (!setting)
|
|
return;
|
|
|
|
g_object_freeze_notify (G_OBJECT (config));
|
|
|
|
naddresses = nm_setting_ip4_config_get_num_addresses (setting);
|
|
nroutes = nm_setting_ip4_config_get_num_routes (setting);
|
|
nnameservers = nm_setting_ip4_config_get_num_dns (setting);
|
|
nsearches = nm_setting_ip4_config_get_num_dns_searches (setting);
|
|
|
|
/* Gateway */
|
|
if (nm_setting_ip4_config_get_never_default (setting))
|
|
nm_ip4_config_set_never_default (config, TRUE);
|
|
else if (nm_setting_ip4_config_get_ignore_auto_routes (setting))
|
|
nm_ip4_config_set_never_default (config, FALSE);
|
|
for (i = 0; i < naddresses; i++) {
|
|
guint32 gateway = nm_ip4_address_get_gateway (nm_setting_ip4_config_get_address (setting, i));
|
|
|
|
if (gateway) {
|
|
nm_ip4_config_set_gateway (config, gateway);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Addresses */
|
|
for (i = 0; i < naddresses; i++) {
|
|
NMIP4Address *s_addr = nm_setting_ip4_config_get_address (setting, i);
|
|
NMPlatformIP4Address address;
|
|
|
|
memset (&address, 0, sizeof (address));
|
|
address.address = nm_ip4_address_get_address (s_addr);
|
|
address.plen = nm_ip4_address_get_prefix (s_addr);
|
|
address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
|
|
address.preferred = NM_PLATFORM_LIFETIME_PERMANENT;
|
|
|
|
nm_ip4_config_add_address (config, &address);
|
|
}
|
|
|
|
/* Routes */
|
|
if (nm_setting_ip4_config_get_ignore_auto_routes (setting))
|
|
nm_ip4_config_reset_routes (config);
|
|
for (i = 0; i < nroutes; i++) {
|
|
NMIP4Route *s_route = nm_setting_ip4_config_get_route (setting, i);
|
|
NMPlatformIP4Route route;
|
|
|
|
memset (&route, 0, sizeof (route));
|
|
route.network = nm_ip4_route_get_dest (s_route);
|
|
route.plen = nm_ip4_route_get_prefix (s_route);
|
|
route.gateway = nm_ip4_route_get_next_hop (s_route);
|
|
route.metric = nm_ip4_route_get_metric (s_route);
|
|
|
|
nm_ip4_config_add_route (config, &route);
|
|
}
|
|
|
|
/* DNS */
|
|
if (nm_setting_ip4_config_get_ignore_auto_dns (setting)) {
|
|
nm_ip4_config_reset_nameservers (config);
|
|
nm_ip4_config_reset_domains (config);
|
|
nm_ip4_config_reset_searches (config);
|
|
}
|
|
for (i = 0; i < nnameservers; i++)
|
|
nm_ip4_config_add_nameserver (config, nm_setting_ip4_config_get_dns (setting, i));
|
|
for (i = 0; i < nsearches; i++)
|
|
nm_ip4_config_add_search (config, nm_setting_ip4_config_get_dns_search (setting, i));
|
|
|
|
g_object_thaw_notify (G_OBJECT (config));
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_update_setting (const NMIP4Config *config, NMSettingIP4Config *setting)
|
|
{
|
|
guint32 gateway;
|
|
guint naddresses, nroutes, nnameservers, nsearches;
|
|
const char *method = NULL;
|
|
int i;
|
|
|
|
if (!config)
|
|
return;
|
|
|
|
gateway = nm_ip4_config_get_gateway (config);
|
|
naddresses = nm_ip4_config_get_num_addresses (config);
|
|
nroutes = nm_ip4_config_get_num_routes (config);
|
|
nnameservers = nm_ip4_config_get_num_nameservers (config);
|
|
nsearches = nm_ip4_config_get_num_searches (config);
|
|
|
|
/* Addresses */
|
|
for (i = 0; i < naddresses; i++) {
|
|
const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i);
|
|
NMIP4Address *s_addr;
|
|
|
|
/* Detect dynamic address */
|
|
if (address->lifetime != NM_PLATFORM_LIFETIME_PERMANENT) {
|
|
method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
|
|
continue;
|
|
}
|
|
|
|
/* Static address found. */
|
|
if (!method)
|
|
method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
|
|
|
|
s_addr = nm_ip4_address_new ();
|
|
|
|
nm_ip4_address_set_address (s_addr, address->address);
|
|
nm_ip4_address_set_prefix (s_addr, address->plen);
|
|
/* For backwards compatibility, attach the gateway to an address if it's
|
|
* in the same subnet.
|
|
*/
|
|
if (same_prefix (address->address, gateway, address->plen))
|
|
nm_ip4_address_set_gateway (s_addr, gateway);
|
|
|
|
nm_setting_ip4_config_add_address (setting, s_addr);
|
|
nm_ip4_address_unref (s_addr);
|
|
}
|
|
|
|
/* Only use 'disabled' if the method wasn't previously set */
|
|
if (!method && !nm_setting_ip4_config_get_method (setting))
|
|
method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
|
|
if (method)
|
|
g_object_set (setting, NM_SETTING_IP4_CONFIG_METHOD, method, NULL);
|
|
|
|
/* Routes */
|
|
for (i = 0; i < nroutes; i++) {
|
|
const NMPlatformIP4Route *route = nm_ip4_config_get_route (config, i);
|
|
NMIP4Route *s_route;
|
|
|
|
/* Ignore default route. */
|
|
if (!route->plen)
|
|
continue;
|
|
|
|
s_route = nm_ip4_route_new ();
|
|
nm_ip4_route_set_dest (s_route, route->network);
|
|
nm_ip4_route_set_prefix (s_route, route->plen);
|
|
nm_ip4_route_set_next_hop (s_route, route->gateway);
|
|
nm_ip4_route_set_metric (s_route, route->metric);
|
|
|
|
nm_setting_ip4_config_add_route (setting, s_route);
|
|
nm_ip4_route_unref (s_route);
|
|
}
|
|
|
|
/* DNS */
|
|
for (i = 0; i < nnameservers; i++) {
|
|
guint32 nameserver = nm_ip4_config_get_nameserver (config, i);
|
|
|
|
nm_setting_ip4_config_add_dns (setting, nameserver);
|
|
}
|
|
for (i = 0; i < nsearches; i++) {
|
|
const char *search = nm_ip4_config_get_search (config, i);
|
|
|
|
nm_setting_ip4_config_add_dns_search (setting, search);
|
|
}
|
|
}
|
|
|
|
/******************************************************************/
|
|
|
|
void
|
|
nm_ip4_config_merge (NMIP4Config *dst, const NMIP4Config *src)
|
|
{
|
|
guint32 i;
|
|
|
|
g_return_if_fail (src != NULL);
|
|
g_return_if_fail (dst != NULL);
|
|
|
|
g_object_freeze_notify (G_OBJECT (dst));
|
|
|
|
/* addresses */
|
|
for (i = 0; i < nm_ip4_config_get_num_addresses (src); i++)
|
|
nm_ip4_config_add_address (dst, nm_ip4_config_get_address (src, i));
|
|
|
|
/* ptp address; only replace if src doesn't have one */
|
|
if (!nm_ip4_config_get_ptp_address (dst))
|
|
nm_ip4_config_set_ptp_address (dst, nm_ip4_config_get_ptp_address (src));
|
|
|
|
/* nameservers */
|
|
for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++)
|
|
nm_ip4_config_add_nameserver (dst, nm_ip4_config_get_nameserver (src, i));
|
|
|
|
/* default gateway */
|
|
if (!nm_ip4_config_get_gateway (dst))
|
|
nm_ip4_config_set_gateway (dst, nm_ip4_config_get_gateway (src));
|
|
|
|
/* routes */
|
|
for (i = 0; i < nm_ip4_config_get_num_routes (src); i++)
|
|
nm_ip4_config_add_route (dst, nm_ip4_config_get_route (src, i));
|
|
|
|
/* domains */
|
|
for (i = 0; i < nm_ip4_config_get_num_domains (src); i++)
|
|
nm_ip4_config_add_domain (dst, nm_ip4_config_get_domain (src, i));
|
|
|
|
/* dns searches */
|
|
for (i = 0; i < nm_ip4_config_get_num_searches (src); i++)
|
|
nm_ip4_config_add_search (dst, nm_ip4_config_get_search (src, i));
|
|
|
|
if (!nm_ip4_config_get_mss (dst))
|
|
nm_ip4_config_set_mss (dst, nm_ip4_config_get_mss (src));
|
|
|
|
/* NIS */
|
|
for (i = 0; i < nm_ip4_config_get_num_nis_servers (src); i++)
|
|
nm_ip4_config_add_nis_server (dst, nm_ip4_config_get_nis_server (src, i));
|
|
|
|
if (nm_ip4_config_get_nis_domain (src))
|
|
nm_ip4_config_set_nis_domain (dst, nm_ip4_config_get_nis_domain (src));
|
|
|
|
/* WINS */
|
|
for (i = 0; i < nm_ip4_config_get_num_wins (src); i++)
|
|
nm_ip4_config_add_wins (dst, nm_ip4_config_get_wins (src, i));
|
|
|
|
g_object_thaw_notify (G_OBJECT (dst));
|
|
}
|
|
|
|
/**
|
|
* nm_ip4_config_subtract:
|
|
* @dst: config from which to remove everything in @src
|
|
* @src: config to remove from @dst
|
|
*
|
|
* Removes everything in @src from @dst.
|
|
*/
|
|
void
|
|
nm_ip4_config_subtract (NMIP4Config *dst, const NMIP4Config *src)
|
|
{
|
|
guint32 i, j;
|
|
|
|
g_return_if_fail (src != NULL);
|
|
g_return_if_fail (dst != NULL);
|
|
|
|
g_object_freeze_notify (G_OBJECT (dst));
|
|
|
|
/* addresses */
|
|
for (i = 0; i < nm_ip4_config_get_num_addresses (src); i++) {
|
|
const NMPlatformIP4Address *src_addr = nm_ip4_config_get_address (src, i);
|
|
|
|
for (j = 0; j < nm_ip4_config_get_num_addresses (dst); j++) {
|
|
const NMPlatformIP4Address *dst_addr = nm_ip4_config_get_address (dst, j);
|
|
|
|
if (src_addr->address == dst_addr->address &&
|
|
src_addr->plen == dst_addr->plen) {
|
|
nm_ip4_config_del_address (dst, j);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ptp address */
|
|
if (nm_ip4_config_get_ptp_address (src) == nm_ip4_config_get_ptp_address (dst))
|
|
nm_ip4_config_set_ptp_address (dst, 0);
|
|
|
|
/* nameservers */
|
|
for (i = 0; i < nm_ip4_config_get_num_nameservers (src); i++) {
|
|
guint32 src_ns = nm_ip4_config_get_nameserver (src, i);
|
|
|
|
for (j = 0; j < nm_ip4_config_get_num_nameservers (dst); j++) {
|
|
guint32 dst_ns = nm_ip4_config_get_nameserver (dst, j);
|
|
|
|
if (dst_ns == src_ns) {
|
|
nm_ip4_config_del_nameserver (dst, j);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* default gateway */
|
|
if (nm_ip4_config_get_gateway (src) == nm_ip4_config_get_gateway (dst))
|
|
nm_ip4_config_set_gateway (dst, 0);
|
|
|
|
/* routes */
|
|
for (i = 0; i < nm_ip4_config_get_num_routes (src); i++) {
|
|
const NMPlatformIP4Route *src_route = nm_ip4_config_get_route (src, i);
|
|
|
|
for (j = 0; j < nm_ip4_config_get_num_routes (dst); j++) {
|
|
const NMPlatformIP4Route *dst_route = nm_ip4_config_get_route (dst, j);
|
|
|
|
if (src_route->network == dst_route->network && src_route->plen == dst_route->plen) {
|
|
nm_ip4_config_del_route (dst, j);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* domains */
|
|
for (i = 0; i < nm_ip4_config_get_num_domains (src); i++) {
|
|
const char *src_domain = nm_ip4_config_get_domain (src, i);
|
|
|
|
for (j = 0; j < nm_ip4_config_get_num_domains (dst); j++) {
|
|
const char *dst_domain = nm_ip4_config_get_domain (dst, j);
|
|
|
|
if (g_strcmp0 (src_domain, dst_domain) == 0) {
|
|
nm_ip4_config_del_domain (dst, j);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* dns searches */
|
|
for (i = 0; i < nm_ip4_config_get_num_searches (src); i++) {
|
|
const char *src_search = nm_ip4_config_get_search (src, i);
|
|
|
|
for (j = 0; j < nm_ip4_config_get_num_searches (dst); j++) {
|
|
const char *dst_search = nm_ip4_config_get_search (dst, j);
|
|
|
|
if (g_strcmp0 (src_search, dst_search) == 0) {
|
|
nm_ip4_config_del_search (dst, j);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nm_ip4_config_get_mss (src) == nm_ip4_config_get_mss (dst))
|
|
nm_ip4_config_set_mss (dst, 0);
|
|
|
|
/* NIS */
|
|
for (i = 0; i < nm_ip4_config_get_num_nis_servers (src); i++) {
|
|
guint32 src_nis = nm_ip4_config_get_nis_server (src, i);
|
|
|
|
for (j = 0; j < nm_ip4_config_get_num_nis_servers (dst); j++) {
|
|
guint32 dst_nis = nm_ip4_config_get_nis_server (dst, j);
|
|
|
|
if (dst_nis == src_nis) {
|
|
nm_ip4_config_del_nis_server (dst, j);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (g_strcmp0 (nm_ip4_config_get_nis_domain (src), nm_ip4_config_get_nis_domain (dst)) == 0)
|
|
nm_ip4_config_set_nis_domain (dst, NULL);
|
|
|
|
/* WINS */
|
|
for (i = 0; i < nm_ip4_config_get_num_wins (src); i++) {
|
|
guint32 src_wins = nm_ip4_config_get_wins (src, i);
|
|
|
|
for (j = 0; j < nm_ip4_config_get_num_wins (dst); j++) {
|
|
guint32 dst_wins = nm_ip4_config_get_wins (dst, j);
|
|
|
|
if (dst_wins == src_wins) {
|
|
nm_ip4_config_del_wins (dst, j);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
g_object_thaw_notify (G_OBJECT (dst));
|
|
}
|
|
|
|
|
|
/**
|
|
* nm_ip4_config_replace:
|
|
* @dst: config from which to remove everything in @src
|
|
* @src: config to remove from @dst
|
|
* @relevant_changes: return whether there are changes to the
|
|
* destination object that are relevant. This is equal to
|
|
* nm_ip4_config_equal() showing any difference.
|
|
*
|
|
* Replaces everything in @dst with @src so that the two configurations
|
|
* contain the same content -- with the exception of the dbus path.
|
|
*
|
|
* Returns: whether the @dst instance changed in any way (including minor changes,
|
|
* that are not signaled by the output parameter @relevant_changes).
|
|
*/
|
|
gboolean
|
|
nm_ip4_config_replace (NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes)
|
|
{
|
|
#ifndef G_DISABLE_ASSERT
|
|
gboolean config_equal;
|
|
#endif
|
|
gboolean has_minor_changes = FALSE, has_relevant_changes = FALSE, are_equal;
|
|
guint i, num;
|
|
NMIP4ConfigPrivate *dst_priv, *src_priv;
|
|
const NMPlatformIP4Address *dst_addr, *src_addr;
|
|
const NMPlatformIP4Route *dst_route, *src_route;
|
|
|
|
g_return_val_if_fail (src != NULL, FALSE);
|
|
g_return_val_if_fail (dst != NULL, FALSE);
|
|
g_return_val_if_fail (src != dst, FALSE);
|
|
|
|
#ifndef G_DISABLE_ASSERT
|
|
config_equal = nm_ip4_config_equal (dst, src);
|
|
#endif
|
|
|
|
dst_priv = NM_IP4_CONFIG_GET_PRIVATE (dst);
|
|
src_priv = NM_IP4_CONFIG_GET_PRIVATE (src);
|
|
|
|
g_object_freeze_notify (G_OBJECT (dst));
|
|
|
|
/* never_default */
|
|
if (src_priv->never_default != dst_priv->never_default) {
|
|
dst_priv->never_default = src_priv->never_default;
|
|
has_minor_changes = TRUE;
|
|
}
|
|
|
|
/* default gateway */
|
|
if (src_priv->gateway != dst_priv->gateway) {
|
|
nm_ip4_config_set_gateway (dst, src_priv->gateway);
|
|
has_relevant_changes = TRUE;
|
|
}
|
|
|
|
/* addresses */
|
|
num = nm_ip4_config_get_num_addresses (src);
|
|
are_equal = num == nm_ip4_config_get_num_addresses (dst);
|
|
if (are_equal) {
|
|
for (i = 0; i < num; i++ ) {
|
|
if (nm_platform_ip4_address_cmp (src_addr = nm_ip4_config_get_address (src, i),
|
|
dst_addr = nm_ip4_config_get_address (dst, i))) {
|
|
are_equal = FALSE;
|
|
if (!addresses_are_duplicate (src_addr, dst_addr, TRUE)) {
|
|
has_relevant_changes = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else
|
|
has_relevant_changes = TRUE;
|
|
if (!are_equal) {
|
|
nm_ip4_config_reset_addresses (dst);
|
|
for (i = 0; i < num; i++)
|
|
nm_ip4_config_add_address (dst, nm_ip4_config_get_address (src, i));
|
|
has_minor_changes = TRUE;
|
|
}
|
|
|
|
/* routes */
|
|
num = nm_ip4_config_get_num_routes (src);
|
|
are_equal = num == nm_ip4_config_get_num_routes (dst);
|
|
if (are_equal) {
|
|
for (i = 0; i < num; i++ ) {
|
|
if (nm_platform_ip4_route_cmp (src_route = nm_ip4_config_get_route (src, i),
|
|
dst_route = nm_ip4_config_get_route (dst, i))) {
|
|
are_equal = FALSE;
|
|
if (!routes_are_duplicate (src_route, dst_route, TRUE)) {
|
|
has_relevant_changes = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else
|
|
has_relevant_changes = TRUE;
|
|
if (!are_equal) {
|
|
nm_ip4_config_reset_routes (dst);
|
|
for (i = 0; i < num; i++)
|
|
nm_ip4_config_add_route (dst, nm_ip4_config_get_route (src, i));
|
|
has_minor_changes = TRUE;
|
|
}
|
|
|
|
/* nameservers */
|
|
num = nm_ip4_config_get_num_nameservers (src);
|
|
are_equal = num == nm_ip4_config_get_num_nameservers (dst);
|
|
if (are_equal) {
|
|
for (i = 0; i < num; i++ ) {
|
|
if (nm_ip4_config_get_nameserver (src, i) != nm_ip4_config_get_nameserver (dst, i)) {
|
|
are_equal = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!are_equal) {
|
|
nm_ip4_config_reset_nameservers (dst);
|
|
for (i = 0; i < num; i++)
|
|
nm_ip4_config_add_nameserver (dst, nm_ip4_config_get_nameserver (src, i));
|
|
has_relevant_changes = TRUE;
|
|
}
|
|
|
|
/* domains */
|
|
num = nm_ip4_config_get_num_domains (src);
|
|
are_equal = num == nm_ip4_config_get_num_domains (dst);
|
|
if (are_equal) {
|
|
for (i = 0; i < num; i++ ) {
|
|
if (g_strcmp0 (nm_ip4_config_get_domain (src, i),
|
|
nm_ip4_config_get_domain (dst, i))) {
|
|
are_equal = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!are_equal) {
|
|
nm_ip4_config_reset_domains (dst);
|
|
for (i = 0; i < num; i++)
|
|
nm_ip4_config_add_domain (dst, nm_ip4_config_get_domain (src, i));
|
|
has_relevant_changes = TRUE;
|
|
}
|
|
|
|
/* dns searches */
|
|
num = nm_ip4_config_get_num_searches (src);
|
|
are_equal = num == nm_ip4_config_get_num_searches (dst);
|
|
if (are_equal) {
|
|
for (i = 0; i < num; i++ ) {
|
|
if (g_strcmp0 (nm_ip4_config_get_search (src, i),
|
|
nm_ip4_config_get_search (dst, i))) {
|
|
are_equal = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!are_equal) {
|
|
nm_ip4_config_reset_searches (dst);
|
|
for (i = 0; i < num; i++)
|
|
nm_ip4_config_add_search (dst, nm_ip4_config_get_search (src, i));
|
|
has_relevant_changes = TRUE;
|
|
}
|
|
|
|
/* mss */
|
|
if (src_priv->mss != dst_priv->mss) {
|
|
nm_ip4_config_set_mss (dst, src_priv->mss);
|
|
has_minor_changes = TRUE;
|
|
}
|
|
|
|
/* ptp address */
|
|
if (src_priv->ptp_address != dst_priv->ptp_address) {
|
|
dst_priv->ptp_address = src_priv->ptp_address;
|
|
has_relevant_changes = TRUE;
|
|
}
|
|
|
|
/* nis */
|
|
num = nm_ip4_config_get_num_nis_servers (src);
|
|
are_equal = num == nm_ip4_config_get_num_nis_servers (dst);
|
|
if (are_equal) {
|
|
for (i = 0; i < num; i++ ) {
|
|
if (nm_ip4_config_get_nis_server (src, i) != nm_ip4_config_get_nis_server (dst, i)) {
|
|
are_equal = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!are_equal) {
|
|
nm_ip4_config_reset_nis_servers (dst);
|
|
for (i = 0; i < num; i++)
|
|
nm_ip4_config_add_nis_server (dst, nm_ip4_config_get_nis_server (src, i));
|
|
has_relevant_changes = TRUE;
|
|
}
|
|
|
|
/* nis_domain */
|
|
if (g_strcmp0 (src_priv->nis_domain, dst_priv->nis_domain)) {
|
|
nm_ip4_config_set_nis_domain (dst, src_priv->nis_domain);
|
|
has_relevant_changes = TRUE;
|
|
}
|
|
|
|
/* wins */
|
|
num = nm_ip4_config_get_num_wins (src);
|
|
are_equal = num == nm_ip4_config_get_num_wins (dst);
|
|
if (are_equal) {
|
|
for (i = 0; i < num; i++ ) {
|
|
if (nm_ip4_config_get_wins (src, i) != nm_ip4_config_get_wins (dst, i)) {
|
|
are_equal = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!are_equal) {
|
|
nm_ip4_config_reset_wins (dst);
|
|
for (i = 0; i < num; i++)
|
|
nm_ip4_config_add_wins (dst, nm_ip4_config_get_wins (src, i));
|
|
has_relevant_changes = TRUE;
|
|
}
|
|
|
|
/* mtu */
|
|
if (src_priv->mtu != dst_priv->mtu) {
|
|
nm_ip4_config_set_mtu (dst, src_priv->mtu);
|
|
has_minor_changes = TRUE;
|
|
}
|
|
|
|
/* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes
|
|
* regardless of config_equal. But config_equal must correspond to has_relevant_changes. */
|
|
g_assert (config_equal == !has_relevant_changes);
|
|
|
|
g_object_thaw_notify (G_OBJECT (dst));
|
|
|
|
if (relevant_changes)
|
|
*relevant_changes = has_relevant_changes;
|
|
|
|
return has_relevant_changes || has_minor_changes;
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_dump (const NMIP4Config *config, const char *detail)
|
|
{
|
|
guint32 i, tmp;
|
|
const char *str;
|
|
char buf[INET_ADDRSTRLEN];
|
|
|
|
g_return_if_fail (config != NULL);
|
|
|
|
g_message ("--------- NMIP4Config %p (%s)", config, detail);
|
|
|
|
str = nm_ip4_config_get_dbus_path (config);
|
|
if (str)
|
|
g_message (" path: %s", str);
|
|
|
|
/* addresses */
|
|
for (i = 0; i < nm_ip4_config_get_num_addresses (config); i++)
|
|
g_message (" a: %s", nm_platform_ip4_address_to_string (nm_ip4_config_get_address (config, i)));
|
|
|
|
/* ptp address */
|
|
tmp = nm_ip4_config_get_ptp_address (config);
|
|
if (inet_ntop (AF_INET, (void *) &tmp, buf, sizeof (buf)))
|
|
g_message (" ptp: %s", buf);
|
|
|
|
/* default gateway */
|
|
tmp = nm_ip4_config_get_gateway (config);
|
|
if (inet_ntop (AF_INET, (void *) &tmp, buf, sizeof (buf)))
|
|
g_message (" gw: %s", buf);
|
|
|
|
/* nameservers */
|
|
for (i = 0; i < nm_ip4_config_get_num_nameservers (config); i++) {
|
|
tmp = nm_ip4_config_get_nameserver (config, i);
|
|
if (inet_ntop (AF_INET, (void *) &tmp, buf, sizeof (buf)))
|
|
g_message (" ns: %s", buf);
|
|
}
|
|
|
|
/* routes */
|
|
for (i = 0; i < nm_ip4_config_get_num_routes (config); i++)
|
|
g_message (" rt: %s", nm_platform_ip4_route_to_string (nm_ip4_config_get_route (config, i)));
|
|
|
|
/* domains */
|
|
for (i = 0; i < nm_ip4_config_get_num_domains (config); i++)
|
|
g_message (" domain: %s", nm_ip4_config_get_domain (config, i));
|
|
|
|
/* dns searches */
|
|
for (i = 0; i < nm_ip4_config_get_num_searches (config); i++)
|
|
g_message (" search: %s", nm_ip4_config_get_search (config, i));
|
|
|
|
g_message (" mss: %u", nm_ip4_config_get_mss (config));
|
|
g_message (" mtu: %u", nm_ip4_config_get_mtu (config));
|
|
|
|
/* NIS */
|
|
for (i = 0; i < nm_ip4_config_get_num_nis_servers (config); i++) {
|
|
guint32 nis = nm_ip4_config_get_nis_server (config, i);
|
|
|
|
if (inet_ntop (AF_INET, (void *) &nis, buf, sizeof (buf)))
|
|
g_message (" nis: %s", buf);
|
|
}
|
|
|
|
g_message (" nisdmn: %s", nm_ip4_config_get_nis_domain (config));
|
|
|
|
/* WINS */
|
|
for (i = 0; i < nm_ip4_config_get_num_wins (config); i++) {
|
|
guint32 wins = nm_ip4_config_get_wins (config, i);
|
|
|
|
if (inet_ntop (AF_INET, (void *) &wins, buf, sizeof (buf)))
|
|
g_message (" wins: %s", buf);
|
|
}
|
|
|
|
g_message (" n-dflt: %d", nm_ip4_config_get_never_default (config));
|
|
}
|
|
|
|
gboolean
|
|
nm_ip4_config_destination_is_direct (const NMIP4Config *config, guint32 network, int plen)
|
|
{
|
|
guint naddresses = nm_ip4_config_get_num_addresses (config);
|
|
int i;
|
|
|
|
for (i = 0; i < naddresses; i++) {
|
|
const NMPlatformIP4Address *item = nm_ip4_config_get_address (config, i);
|
|
|
|
if (item->plen <= plen && same_prefix (item->address, network, item->plen))
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/******************************************************************/
|
|
|
|
void
|
|
nm_ip4_config_set_never_default (NMIP4Config *config, gboolean never_default)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
priv->never_default = !!never_default;
|
|
}
|
|
|
|
gboolean
|
|
nm_ip4_config_get_never_default (const NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return priv->never_default;
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_set_gateway (NMIP4Config *config, guint32 gateway)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
if (priv->gateway != gateway) {
|
|
priv->gateway = gateway;
|
|
_NOTIFY (config, PROP_GATEWAY);
|
|
}
|
|
}
|
|
|
|
guint32
|
|
nm_ip4_config_get_gateway (const NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return priv->gateway;
|
|
}
|
|
|
|
/******************************************************************/
|
|
|
|
void
|
|
nm_ip4_config_reset_addresses (NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
if (priv->addresses->len != 0) {
|
|
g_array_set_size (priv->addresses, 0);
|
|
_NOTIFY (config, PROP_ADDRESSES);
|
|
}
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_add_address (NMIP4Config *config, const NMPlatformIP4Address *new)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
int i;
|
|
|
|
g_return_if_fail (new != NULL);
|
|
|
|
for (i = 0; i < priv->addresses->len; i++ ) {
|
|
NMPlatformIP4Address *item = &g_array_index (priv->addresses, NMPlatformIP4Address, i);
|
|
|
|
if (addresses_are_duplicate (item, new, FALSE)) {
|
|
if (nm_platform_ip4_address_cmp (item, new) == 0)
|
|
return;
|
|
memcpy (item, new, sizeof (*item));
|
|
goto NOTIFY;
|
|
}
|
|
}
|
|
|
|
g_array_append_val (priv->addresses, *new);
|
|
NOTIFY:
|
|
_NOTIFY (config, PROP_ADDRESSES);
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_del_address (NMIP4Config *config, guint i)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
g_return_if_fail (i < priv->addresses->len);
|
|
|
|
g_array_remove_index (priv->addresses, i);
|
|
_NOTIFY (config, PROP_ADDRESSES);
|
|
}
|
|
|
|
guint
|
|
nm_ip4_config_get_num_addresses (const NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return priv->addresses->len;
|
|
}
|
|
|
|
const NMPlatformIP4Address *
|
|
nm_ip4_config_get_address (const NMIP4Config *config, guint i)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return &g_array_index (priv->addresses, NMPlatformIP4Address, i);
|
|
}
|
|
|
|
gboolean
|
|
nm_ip4_config_address_exists (const NMIP4Config *config,
|
|
const NMPlatformIP4Address *needle)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
guint i;
|
|
|
|
for (i = 0; i < priv->addresses->len; i++) {
|
|
const NMPlatformIP4Address *haystack = &g_array_index (priv->addresses, NMPlatformIP4Address, i);
|
|
|
|
if (needle->address == haystack->address && needle->plen == haystack->plen)
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/******************************************************************/
|
|
|
|
void
|
|
nm_ip4_config_reset_routes (NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
if (priv->routes->len != 0) {
|
|
g_array_set_size (priv->routes, 0);
|
|
_NOTIFY (config, PROP_ROUTES);
|
|
}
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_add_route (NMIP4Config *config, const NMPlatformIP4Route *new)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
int i;
|
|
|
|
g_return_if_fail (new != NULL);
|
|
|
|
for (i = 0; i < priv->routes->len; i++ ) {
|
|
NMPlatformIP4Route *item = &g_array_index (priv->routes, NMPlatformIP4Route, i);
|
|
|
|
if (routes_are_duplicate (item, new, FALSE)) {
|
|
if (nm_platform_ip4_route_cmp (item, new) == 0)
|
|
return;
|
|
memcpy (item, new, sizeof (*item));
|
|
goto NOTIFY;
|
|
}
|
|
}
|
|
|
|
g_array_append_val (priv->routes, *new);
|
|
NOTIFY:
|
|
_NOTIFY (config, PROP_ROUTES);
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_del_route (NMIP4Config *config, guint i)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
g_return_if_fail (i < priv->routes->len);
|
|
|
|
g_array_remove_index (priv->routes, i);
|
|
_NOTIFY (config, PROP_ROUTES);
|
|
}
|
|
|
|
guint
|
|
nm_ip4_config_get_num_routes (const NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return priv->routes->len;
|
|
}
|
|
|
|
const NMPlatformIP4Route *
|
|
nm_ip4_config_get_route (const NMIP4Config *config, guint i)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return &g_array_index (priv->routes, NMPlatformIP4Route, i);
|
|
}
|
|
|
|
/******************************************************************/
|
|
|
|
void
|
|
nm_ip4_config_reset_nameservers (NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
if (priv->nameservers->len != 0) {
|
|
g_array_set_size (priv->nameservers, 0);
|
|
_NOTIFY (config, PROP_NAMESERVERS);
|
|
}
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_add_nameserver (NMIP4Config *config, guint32 new)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
int i;
|
|
|
|
g_return_if_fail (new != 0);
|
|
|
|
for (i = 0; i < priv->nameservers->len; i++)
|
|
if (new == g_array_index (priv->nameservers, guint32, i))
|
|
return;
|
|
|
|
g_array_append_val (priv->nameservers, new);
|
|
_NOTIFY (config, PROP_NAMESERVERS);
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_del_nameserver (NMIP4Config *config, guint i)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
g_return_if_fail (i < priv->nameservers->len);
|
|
|
|
g_array_remove_index (priv->nameservers, i);
|
|
_NOTIFY (config, PROP_NAMESERVERS);
|
|
}
|
|
|
|
guint32
|
|
nm_ip4_config_get_num_nameservers (const NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return priv->nameservers->len;
|
|
}
|
|
|
|
guint32
|
|
nm_ip4_config_get_nameserver (const NMIP4Config *config, guint i)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return g_array_index (priv->nameservers, guint32, i);
|
|
}
|
|
|
|
/******************************************************************/
|
|
|
|
void
|
|
nm_ip4_config_reset_domains (NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
if (priv->domains->len != 0) {
|
|
g_ptr_array_set_size (priv->domains, 0);
|
|
_NOTIFY (config, PROP_DOMAINS);
|
|
}
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_add_domain (NMIP4Config *config, const char *domain)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
int i;
|
|
|
|
g_return_if_fail (domain != NULL);
|
|
g_return_if_fail (domain[0] != '\0');
|
|
|
|
for (i = 0; i < priv->domains->len; i++)
|
|
if (!g_strcmp0 (g_ptr_array_index (priv->domains, i), domain))
|
|
return;
|
|
|
|
g_ptr_array_add (priv->domains, g_strdup (domain));
|
|
_NOTIFY (config, PROP_DOMAINS);
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_del_domain (NMIP4Config *config, guint i)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
g_return_if_fail (i < priv->domains->len);
|
|
|
|
g_ptr_array_remove_index (priv->domains, i);
|
|
_NOTIFY (config, PROP_DOMAINS);
|
|
}
|
|
|
|
guint32
|
|
nm_ip4_config_get_num_domains (const NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return priv->domains->len;
|
|
}
|
|
|
|
const char *
|
|
nm_ip4_config_get_domain (const NMIP4Config *config, guint i)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return g_ptr_array_index (priv->domains, i);
|
|
}
|
|
|
|
/******************************************************************/
|
|
|
|
void
|
|
nm_ip4_config_reset_searches (NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
if (priv->searches->len != 0) {
|
|
g_ptr_array_set_size (priv->searches, 0);
|
|
_NOTIFY (config, PROP_SEARCHES);
|
|
}
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_add_search (NMIP4Config *config, const char *new)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
int i;
|
|
|
|
g_return_if_fail (new != NULL);
|
|
g_return_if_fail (new[0] != '\0');
|
|
|
|
for (i = 0; i < priv->searches->len; i++)
|
|
if (!g_strcmp0 (g_ptr_array_index (priv->searches, i), new))
|
|
return;
|
|
|
|
g_ptr_array_add (priv->searches, g_strdup (new));
|
|
_NOTIFY (config, PROP_SEARCHES);
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_del_search (NMIP4Config *config, guint i)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
g_return_if_fail (i < priv->searches->len);
|
|
|
|
g_ptr_array_remove_index (priv->searches, i);
|
|
_NOTIFY (config, PROP_SEARCHES);
|
|
}
|
|
|
|
guint32
|
|
nm_ip4_config_get_num_searches (const NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return priv->searches->len;
|
|
}
|
|
|
|
const char *
|
|
nm_ip4_config_get_search (const NMIP4Config *config, guint i)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return g_ptr_array_index (priv->searches, i);
|
|
}
|
|
|
|
/******************************************************************/
|
|
|
|
void
|
|
nm_ip4_config_set_mss (NMIP4Config *config, guint32 mss)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
priv->mss = mss;
|
|
}
|
|
|
|
guint32
|
|
nm_ip4_config_get_mss (const NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return priv->mss;
|
|
}
|
|
|
|
/******************************************************************/
|
|
|
|
void
|
|
nm_ip4_config_set_ptp_address (NMIP4Config *config, guint32 ptp_addr)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
priv->ptp_address = ptp_addr;
|
|
}
|
|
|
|
guint32
|
|
nm_ip4_config_get_ptp_address (const NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return priv->ptp_address;
|
|
}
|
|
|
|
/******************************************************************/
|
|
|
|
void
|
|
nm_ip4_config_reset_nis_servers (NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
g_array_set_size (priv->nis, 0);
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_add_nis_server (NMIP4Config *config, guint32 nis)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
int i;
|
|
|
|
for (i = 0; i < priv->nis->len; i++)
|
|
if (nis == g_array_index (priv->nis, guint32, i))
|
|
return;
|
|
|
|
g_array_append_val (priv->nis, nis);
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_del_nis_server (NMIP4Config *config, guint i)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
g_return_if_fail (i < priv->nis->len);
|
|
|
|
g_array_remove_index (priv->nis, i);
|
|
}
|
|
|
|
guint32
|
|
nm_ip4_config_get_num_nis_servers (const NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return priv->nis->len;
|
|
}
|
|
|
|
guint32
|
|
nm_ip4_config_get_nis_server (const NMIP4Config *config, guint i)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return g_array_index (priv->nis, guint32, i);
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_set_nis_domain (NMIP4Config *config, const char *domain)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
g_free (priv->nis_domain);
|
|
priv->nis_domain = g_strdup (domain);
|
|
}
|
|
|
|
const char *
|
|
nm_ip4_config_get_nis_domain (const NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return priv->nis_domain;
|
|
}
|
|
|
|
/******************************************************************/
|
|
|
|
void
|
|
nm_ip4_config_reset_wins (NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
if (priv->wins->len != 0) {
|
|
g_array_set_size (priv->wins, 0);
|
|
_NOTIFY (config, PROP_WINS_SERVERS);
|
|
}
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_add_wins (NMIP4Config *config, guint32 wins)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
int i;
|
|
|
|
g_return_if_fail (wins != 0);
|
|
|
|
for (i = 0; i < priv->wins->len; i++)
|
|
if (wins == g_array_index (priv->wins, guint32, i))
|
|
return;
|
|
|
|
g_array_append_val (priv->wins, wins);
|
|
_NOTIFY (config, PROP_WINS_SERVERS);
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_del_wins (NMIP4Config *config, guint i)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
g_return_if_fail (i < priv->wins->len);
|
|
|
|
g_array_remove_index (priv->wins, i);
|
|
_NOTIFY (config, PROP_WINS_SERVERS);
|
|
}
|
|
|
|
guint32
|
|
nm_ip4_config_get_num_wins (const NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return priv->wins->len;
|
|
}
|
|
|
|
guint32
|
|
nm_ip4_config_get_wins (const NMIP4Config *config, guint i)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return g_array_index (priv->wins, guint32, i);
|
|
}
|
|
|
|
/******************************************************************/
|
|
|
|
void
|
|
nm_ip4_config_set_mtu (NMIP4Config *config, guint32 mtu)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
priv->mtu = mtu;
|
|
}
|
|
|
|
guint32
|
|
nm_ip4_config_get_mtu (const NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
return priv->mtu;
|
|
}
|
|
|
|
/******************************************************************/
|
|
|
|
static inline void
|
|
hash_u32 (GChecksum *sum, guint32 n)
|
|
{
|
|
g_checksum_update (sum, (const guint8 *) &n, sizeof (n));
|
|
}
|
|
|
|
void
|
|
nm_ip4_config_hash (const NMIP4Config *config, GChecksum *sum, gboolean dns_only)
|
|
{
|
|
guint32 i, n;
|
|
const char *s;
|
|
|
|
g_return_if_fail (config);
|
|
g_return_if_fail (sum);
|
|
|
|
if (!dns_only) {
|
|
hash_u32 (sum, nm_ip4_config_get_gateway (config));
|
|
|
|
for (i = 0; i < nm_ip4_config_get_num_addresses (config); i++) {
|
|
const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i);
|
|
hash_u32 (sum, address->address);
|
|
hash_u32 (sum, address->plen);
|
|
}
|
|
|
|
for (i = 0; i < nm_ip4_config_get_num_routes (config); i++) {
|
|
const NMPlatformIP4Route *route = nm_ip4_config_get_route (config, i);
|
|
|
|
hash_u32 (sum, route->network);
|
|
hash_u32 (sum, route->plen);
|
|
hash_u32 (sum, route->gateway);
|
|
hash_u32 (sum, route->metric);
|
|
}
|
|
|
|
n = nm_ip4_config_get_ptp_address (config);
|
|
if (n)
|
|
hash_u32 (sum, n);
|
|
|
|
for (i = 0; i < nm_ip4_config_get_num_nis_servers (config); i++)
|
|
hash_u32 (sum, nm_ip4_config_get_nis_server (config, i));
|
|
|
|
s = nm_ip4_config_get_nis_domain (config);
|
|
if (s)
|
|
g_checksum_update (sum, (const guint8 *) s, strlen (s));
|
|
}
|
|
|
|
for (i = 0; i < nm_ip4_config_get_num_nameservers (config); i++)
|
|
hash_u32 (sum, nm_ip4_config_get_nameserver (config, i));
|
|
|
|
for (i = 0; i < nm_ip4_config_get_num_wins (config); i++)
|
|
hash_u32 (sum, nm_ip4_config_get_wins (config, i));
|
|
|
|
for (i = 0; i < nm_ip4_config_get_num_domains (config); i++) {
|
|
s = nm_ip4_config_get_domain (config, i);
|
|
g_checksum_update (sum, (const guint8 *) s, strlen (s));
|
|
}
|
|
|
|
for (i = 0; i < nm_ip4_config_get_num_searches (config); i++) {
|
|
s = nm_ip4_config_get_search (config, i);
|
|
g_checksum_update (sum, (const guint8 *) s, strlen (s));
|
|
}
|
|
}
|
|
|
|
gboolean
|
|
nm_ip4_config_equal (const NMIP4Config *a, const NMIP4Config *b)
|
|
{
|
|
GChecksum *a_checksum = g_checksum_new (G_CHECKSUM_SHA1);
|
|
GChecksum *b_checksum = g_checksum_new (G_CHECKSUM_SHA1);
|
|
gsize a_len = g_checksum_type_get_length (G_CHECKSUM_SHA1);
|
|
gsize b_len = g_checksum_type_get_length (G_CHECKSUM_SHA1);
|
|
guchar a_data[a_len], b_data[b_len];
|
|
gboolean equal;
|
|
|
|
if (a)
|
|
nm_ip4_config_hash (a, a_checksum, FALSE);
|
|
if (b)
|
|
nm_ip4_config_hash (b, b_checksum, FALSE);
|
|
|
|
g_checksum_get_digest (a_checksum, a_data, &a_len);
|
|
g_checksum_get_digest (b_checksum, b_data, &b_len);
|
|
|
|
g_assert (a_len == b_len);
|
|
equal = !memcmp (a_data, b_data, a_len);
|
|
|
|
g_checksum_free (a_checksum);
|
|
g_checksum_free (b_checksum);
|
|
|
|
return equal;
|
|
}
|
|
|
|
/******************************************************************/
|
|
|
|
static void
|
|
nm_ip4_config_init (NMIP4Config *config)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (config);
|
|
|
|
priv->addresses = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Address));
|
|
priv->routes = g_array_new (FALSE, FALSE, sizeof (NMPlatformIP4Route));
|
|
priv->nameservers = g_array_new (FALSE, FALSE, sizeof (guint32));
|
|
priv->domains = g_ptr_array_new_with_free_func (g_free);
|
|
priv->searches = g_ptr_array_new_with_free_func (g_free);
|
|
priv->nis = g_array_new (FALSE, TRUE, sizeof (guint32));
|
|
priv->wins = g_array_new (FALSE, TRUE, sizeof (guint32));
|
|
}
|
|
|
|
static void
|
|
finalize (GObject *object)
|
|
{
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object);
|
|
|
|
g_array_unref (priv->addresses);
|
|
g_array_unref (priv->routes);
|
|
g_array_unref (priv->nameservers);
|
|
g_ptr_array_unref (priv->domains);
|
|
g_ptr_array_unref (priv->searches);
|
|
g_array_unref (priv->nis);
|
|
g_free (priv->nis_domain);
|
|
g_array_unref (priv->wins);
|
|
|
|
G_OBJECT_CLASS (nm_ip4_config_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
get_property (GObject *object, guint prop_id,
|
|
GValue *value, GParamSpec *pspec)
|
|
{
|
|
NMIP4Config *config = NM_IP4_CONFIG (object);
|
|
NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE (object);
|
|
|
|
switch (prop_id) {
|
|
case PROP_GATEWAY:
|
|
if (priv->gateway) {
|
|
char addr_buf[INET_ADDRSTRLEN];
|
|
g_value_set_string (value, inet_ntop (AF_INET, &priv->gateway, addr_buf, sizeof (addr_buf)));
|
|
} else
|
|
g_value_set_string (value, NULL);
|
|
break;
|
|
case PROP_ADDRESSES:
|
|
{
|
|
GPtrArray *addresses = g_ptr_array_new ();
|
|
int naddr = nm_ip4_config_get_num_addresses (config);
|
|
int i;
|
|
|
|
for (i = 0; i < naddr; i++) {
|
|
const NMPlatformIP4Address *address = nm_ip4_config_get_address (config, i);
|
|
GArray *array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3);
|
|
|
|
g_array_append_val (array, address->address);
|
|
g_array_append_val (array, address->plen);
|
|
g_array_append_val (array, priv->gateway);
|
|
|
|
g_ptr_array_add (addresses, array);
|
|
}
|
|
|
|
g_value_take_boxed (value, addresses);
|
|
}
|
|
break;
|
|
case PROP_ROUTES:
|
|
{
|
|
GPtrArray *routes = g_ptr_array_new ();
|
|
guint nroutes = nm_ip4_config_get_num_routes (config);
|
|
int i;
|
|
|
|
for (i = 0; i < nroutes; i++) {
|
|
const NMPlatformIP4Route *route = nm_ip4_config_get_route (config, i);
|
|
GArray *array = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 4);
|
|
|
|
g_array_append_val (array, route->network);
|
|
g_array_append_val (array, route->plen);
|
|
g_array_append_val (array, route->gateway);
|
|
g_array_append_val (array, route->metric);
|
|
|
|
g_ptr_array_add (routes, array);
|
|
}
|
|
|
|
g_value_take_boxed (value, routes);
|
|
}
|
|
break;
|
|
case PROP_NAMESERVERS:
|
|
g_value_set_boxed (value, priv->nameservers);
|
|
break;
|
|
case PROP_DOMAINS:
|
|
g_value_set_boxed (value, priv->domains);
|
|
break;
|
|
case PROP_SEARCHES:
|
|
g_value_set_boxed (value, priv->searches);
|
|
break;
|
|
case PROP_WINS_SERVERS:
|
|
g_value_set_boxed (value, priv->wins);
|
|
break;
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
nm_ip4_config_class_init (NMIP4ConfigClass *config_class)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (config_class);
|
|
|
|
g_type_class_add_private (config_class, sizeof (NMIP4ConfigPrivate));
|
|
|
|
object_class->get_property = get_property;
|
|
object_class->finalize = finalize;
|
|
|
|
obj_properties[PROP_GATEWAY] =
|
|
g_param_spec_string (NM_IP4_CONFIG_GATEWAY,
|
|
"Gateway",
|
|
"IP4 gateway",
|
|
NULL,
|
|
G_PARAM_READABLE);
|
|
obj_properties[PROP_ADDRESSES] =
|
|
g_param_spec_boxed (NM_IP4_CONFIG_ADDRESSES,
|
|
"Addresses",
|
|
"IP4 addresses",
|
|
DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
|
|
G_PARAM_READABLE);
|
|
obj_properties[PROP_ROUTES] =
|
|
g_param_spec_boxed (NM_IP4_CONFIG_ROUTES,
|
|
"Routes",
|
|
"Routes",
|
|
DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT,
|
|
G_PARAM_READABLE);
|
|
obj_properties[PROP_NAMESERVERS] =
|
|
g_param_spec_boxed (NM_IP4_CONFIG_NAMESERVERS,
|
|
"Nameservers",
|
|
"DNS list",
|
|
DBUS_TYPE_G_UINT_ARRAY,
|
|
G_PARAM_READABLE);
|
|
obj_properties[PROP_DOMAINS] =
|
|
g_param_spec_boxed (NM_IP4_CONFIG_DOMAINS,
|
|
"Domains",
|
|
"Domains",
|
|
DBUS_TYPE_G_ARRAY_OF_STRING,
|
|
G_PARAM_READABLE);
|
|
obj_properties[PROP_SEARCHES] =
|
|
g_param_spec_boxed (NM_IP4_CONFIG_SEARCHES,
|
|
"Searches",
|
|
"Searches",
|
|
DBUS_TYPE_G_ARRAY_OF_STRING,
|
|
G_PARAM_READABLE);
|
|
obj_properties[PROP_WINS_SERVERS] =
|
|
g_param_spec_boxed (NM_IP4_CONFIG_WINS_SERVERS,
|
|
"WinsServers",
|
|
"WINS server list",
|
|
DBUS_TYPE_G_UINT_ARRAY,
|
|
G_PARAM_READABLE);
|
|
|
|
g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
|
|
|
|
dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (config_class), &dbus_glib_nm_ip4_config_object_info);
|
|
}
|