platform: add support for address lifetimes

This commit is contained in:
Pavel Šimerda
2013-06-29 11:30:11 +02:00
parent aca9b9b570
commit f121995fad
8 changed files with 192 additions and 59 deletions

View File

@@ -719,8 +719,18 @@ ip6_address_get_all (NMPlatform *platform, int ifindex)
return addresses; return addresses;
} }
static guint32
get_time (void)
{
struct timespec tp;
clock_gettime (CLOCK_MONOTONIC, &tp);
return tp.tv_sec;
}
static gboolean static gboolean
ip4_address_add (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) ip4_address_add (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, guint32 lifetime, guint32 preferred)
{ {
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
NMPlatformIP4Address address; NMPlatformIP4Address address;
@@ -729,6 +739,9 @@ ip4_address_add (NMPlatform *platform, int ifindex, in_addr_t addr, int plen)
address.ifindex = ifindex; address.ifindex = ifindex;
address.address = addr; address.address = addr;
address.plen = plen; address.plen = plen;
address.timestamp = get_time ();
address.lifetime = lifetime;
address.preferred = preferred;
g_array_append_val (priv->ip4_addresses, address); g_array_append_val (priv->ip4_addresses, address);
@@ -738,7 +751,7 @@ ip4_address_add (NMPlatform *platform, int ifindex, in_addr_t addr, int plen)
} }
static gboolean static gboolean
ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen) ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen, guint32 lifetime, guint32 preferred)
{ {
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform); NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (platform);
NMPlatformIP6Address address; NMPlatformIP6Address address;
@@ -747,6 +760,9 @@ ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int pl
address.ifindex = ifindex; address.ifindex = ifindex;
address.address = addr; address.address = addr;
address.plen = plen; address.plen = plen;
address.timestamp = get_time ();
address.lifetime = lifetime;
address.preferred = preferred;
g_array_append_val (priv->ip6_addresses, address); g_array_append_val (priv->ip6_addresses, address);

View File

@@ -614,6 +614,9 @@ init_ip4_address (NMPlatformIP4Address *address, struct rtnl_addr *rtnladdr)
address->ifindex = rtnl_addr_get_ifindex (rtnladdr); address->ifindex = rtnl_addr_get_ifindex (rtnladdr);
address->plen = rtnl_addr_get_prefixlen (rtnladdr); address->plen = rtnl_addr_get_prefixlen (rtnladdr);
address->timestamp = rtnl_addr_get_create_time (rtnladdr);
address->lifetime = rtnl_addr_get_valid_lifetime (rtnladdr);
address->preferred = rtnl_addr_get_preferred_lifetime (rtnladdr);
g_assert (nl_addr_get_len (nladdr) == sizeof (address->address)); g_assert (nl_addr_get_len (nladdr) == sizeof (address->address));
memcpy (&address->address, nl_addr_get_binary_addr (nladdr), sizeof (address->address)); memcpy (&address->address, nl_addr_get_binary_addr (nladdr), sizeof (address->address));
} }
@@ -627,6 +630,9 @@ init_ip6_address (NMPlatformIP6Address *address, struct rtnl_addr *rtnladdr)
address->ifindex = rtnl_addr_get_ifindex (rtnladdr); address->ifindex = rtnl_addr_get_ifindex (rtnladdr);
address->plen = rtnl_addr_get_prefixlen (rtnladdr); address->plen = rtnl_addr_get_prefixlen (rtnladdr);
address->timestamp = rtnl_addr_get_create_time (rtnladdr);
address->lifetime = rtnl_addr_get_valid_lifetime (rtnladdr);
address->preferred = rtnl_addr_get_preferred_lifetime (rtnladdr);
g_assert (nl_addr_get_len (nladdr) == sizeof (address->address)); g_assert (nl_addr_get_len (nladdr) == sizeof (address->address));
memcpy (&address->address, nl_addr_get_binary_addr (nladdr), sizeof (address->address)); memcpy (&address->address, nl_addr_get_binary_addr (nladdr), sizeof (address->address));
} }
@@ -1985,7 +1991,7 @@ ip6_address_get_all (NMPlatform *platform, int ifindex)
} }
static struct nl_object * static struct nl_object *
build_rtnl_addr (int family, int ifindex, gconstpointer addr, int plen) build_rtnl_addr (int family, int ifindex, gconstpointer addr, int plen, guint32 lifetime, guint32 preferred)
{ {
struct rtnl_addr *rtnladdr = rtnl_addr_alloc (); struct rtnl_addr *rtnladdr = rtnl_addr_alloc ();
int addrlen = family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr); int addrlen = family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr);
@@ -1998,38 +2004,42 @@ build_rtnl_addr (int family, int ifindex, gconstpointer addr, int plen)
nle = rtnl_addr_set_local (rtnladdr, nladdr); nle = rtnl_addr_set_local (rtnladdr, nladdr);
g_assert (!nle); g_assert (!nle);
rtnl_addr_set_prefixlen (rtnladdr, plen); rtnl_addr_set_prefixlen (rtnladdr, plen);
if (lifetime) {
rtnl_addr_set_valid_lifetime (rtnladdr, lifetime);
rtnl_addr_set_preferred_lifetime (rtnladdr, preferred);
}
return (struct nl_object *) rtnladdr; return (struct nl_object *) rtnladdr;
} }
static gboolean static gboolean
ip4_address_add (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) ip4_address_add (NMPlatform *platform, int ifindex, in_addr_t addr, int plen, guint32 lifetime, guint32 preferred)
{ {
return add_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, plen)); return add_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, plen, lifetime, preferred));
} }
static gboolean static gboolean
ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen) ip6_address_add (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen, guint32 lifetime, guint32 preferred)
{ {
return add_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr, plen)); return add_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr, plen, lifetime, preferred));
} }
static gboolean static gboolean
ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen) ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, int plen)
{ {
return delete_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, plen)); return delete_object (platform, build_rtnl_addr (AF_INET, ifindex, &addr, plen, 0, 0));
} }
static gboolean static gboolean
ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen) ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, int plen)
{ {
return delete_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr, plen)); return delete_object (platform, build_rtnl_addr (AF_INET6, ifindex, &addr, plen, 0, 0));
} }
static gboolean static gboolean
ip_address_exists (NMPlatform *platform, int family, int ifindex, gconstpointer addr, int plen) ip_address_exists (NMPlatform *platform, int family, int ifindex, gconstpointer addr, int plen)
{ {
auto_nl_object struct nl_object *object = build_rtnl_addr (family, ifindex, addr, plen); auto_nl_object struct nl_object *object = build_rtnl_addr (family, ifindex, addr, plen, 0, 0);
auto_nl_object struct nl_object *cached_object = nl_cache_search (choose_cache (platform, object), object); auto_nl_object struct nl_object *cached_object = nl_cache_search (choose_cache (platform, object), object);
return !!cached_object; return !!cached_object;

View File

@@ -1064,12 +1064,14 @@ nm_platform_ip6_address_get_all (int ifindex)
} }
gboolean gboolean
nm_platform_ip4_address_add (int ifindex, in_addr_t address, int plen) nm_platform_ip4_address_add (int ifindex, in_addr_t address, int plen, guint32 lifetime, guint32 preferred)
{ {
reset_error (); reset_error ();
g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (plen > 0, FALSE); g_return_val_if_fail (plen > 0, FALSE);
g_return_val_if_fail (lifetime > 0, FALSE);
g_return_val_if_fail (preferred >= 0, FALSE);
g_return_val_if_fail (klass->ip4_address_add, FALSE); g_return_val_if_fail (klass->ip4_address_add, FALSE);
if (nm_platform_ip4_address_exists (ifindex, address, plen)) { if (nm_platform_ip4_address_exists (ifindex, address, plen)) {
@@ -1079,16 +1081,18 @@ nm_platform_ip4_address_add (int ifindex, in_addr_t address, int plen)
} }
debug ("address: adding IPv4 address"); debug ("address: adding IPv4 address");
return klass->ip4_address_add (platform, ifindex, address, plen); return klass->ip4_address_add (platform, ifindex, address, plen, lifetime, preferred);
} }
gboolean gboolean
nm_platform_ip6_address_add (int ifindex, struct in6_addr address, int plen) nm_platform_ip6_address_add (int ifindex, struct in6_addr address, int plen, guint32 lifetime, guint32 preferred)
{ {
reset_error (); reset_error ();
g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (plen > 0, FALSE); g_return_val_if_fail (plen > 0, FALSE);
g_return_val_if_fail (lifetime > 0, FALSE);
g_return_val_if_fail (preferred >= 0, FALSE);
g_return_val_if_fail (klass->ip6_address_add, FALSE); g_return_val_if_fail (klass->ip6_address_add, FALSE);
if (nm_platform_ip6_address_exists (ifindex, address, plen)) { if (nm_platform_ip6_address_exists (ifindex, address, plen)) {
@@ -1098,7 +1102,7 @@ nm_platform_ip6_address_add (int ifindex, struct in6_addr address, int plen)
} }
debug ("address: adding IPv6 address"); debug ("address: adding IPv6 address");
return klass->ip6_address_add (platform, ifindex, address, plen); return klass->ip6_address_add (platform, ifindex, address, plen, lifetime, preferred);
} }
gboolean gboolean
@@ -1187,6 +1191,26 @@ array_contains_ip6_address (const GArray *addresses, const NMPlatformIP6Address
return FALSE; return FALSE;
} }
static guint32
get_time (void)
{
struct timespec tp;
clock_gettime (CLOCK_MONOTONIC, &tp);
return tp.tv_sec;
}
/* Compute (a + b - c) in an overflow-safe manner. */
static guint32
addsubstract_guint32 (guint32 a, guint32 b, guint32 c)
{
a = a > c ? a - c : 0;
a = a < G_MAXUINT32 - b ? a + b : G_MAXUINT32;
return a;
}
/** /**
* nm_platform_ip4_address_sync: * nm_platform_ip4_address_sync:
* @ifindex: Interface index * @ifindex: Interface index
@@ -1204,6 +1228,7 @@ nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses)
GArray *addresses; GArray *addresses;
NMPlatformIP4Address *address; NMPlatformIP4Address *address;
const NMPlatformIP4Address *known_address; const NMPlatformIP4Address *known_address;
guint32 now = get_time ();
int i; int i;
/* Delete unknown addresses */ /* Delete unknown addresses */
@@ -1224,9 +1249,21 @@ nm_platform_ip4_address_sync (int ifindex, const GArray *known_addresses)
for (i = 0; i < known_addresses->len; i++) { for (i = 0; i < known_addresses->len; i++) {
known_address = &g_array_index (known_addresses, NMPlatformIP4Address, i); known_address = &g_array_index (known_addresses, NMPlatformIP4Address, i);
if (!nm_platform_ip4_address_exists (ifindex, known_address->address, known_address->plen)) if (!nm_platform_ip4_address_exists (ifindex, known_address->address, known_address->plen)) {
if (!nm_platform_ip4_address_add (ifindex, known_address->address, known_address->plen)) guint32 lifetime, preferred;
if (known_address->lifetime) {
guint32 shift = addsubstract_guint32 (now, 0, known_address->timestamp);
/* Pad the lifetime by 5 seconds to avoid potential races. */
lifetime = addsubstract_guint32 (known_address->lifetime, 5, shift);
preferred = addsubstract_guint32 (known_address->lifetime, 5, shift);
} else
lifetime = preferred = NM_PLATFORM_LIFETIME_PERMANENT;
if (!nm_platform_ip4_address_add (ifindex, known_address->address, known_address->plen, lifetime, preferred))
return FALSE; return FALSE;
}
} }
return TRUE; return TRUE;
@@ -1249,6 +1286,7 @@ nm_platform_ip6_address_sync (int ifindex, const GArray *known_addresses)
GArray *addresses; GArray *addresses;
NMPlatformIP6Address *address; NMPlatformIP6Address *address;
const NMPlatformIP6Address *known_address; const NMPlatformIP6Address *known_address;
guint32 now = get_time ();
int i; int i;
/* Delete unknown addresses */ /* Delete unknown addresses */
@@ -1273,9 +1311,21 @@ nm_platform_ip6_address_sync (int ifindex, const GArray *known_addresses)
for (i = 0; i < known_addresses->len; i++) { for (i = 0; i < known_addresses->len; i++) {
known_address = &g_array_index (known_addresses, NMPlatformIP6Address, i); known_address = &g_array_index (known_addresses, NMPlatformIP6Address, i);
if (!nm_platform_ip6_address_exists (ifindex, known_address->address, known_address->plen)) if (!nm_platform_ip6_address_exists (ifindex, known_address->address, known_address->plen)) {
if (!nm_platform_ip6_address_add (ifindex, known_address->address, known_address->plen)) guint32 lifetime, preferred;
if (known_address->lifetime) {
guint32 shift = addsubstract_guint32 (now, 0, known_address->timestamp);
/* Pad the lifetime by 5 seconds to avoid potential races. */
lifetime = addsubstract_guint32 (known_address->lifetime, 5, shift);
preferred = addsubstract_guint32 (known_address->lifetime, 5, shift);
} else
lifetime = preferred = NM_PLATFORM_LIFETIME_PERMANENT;
if (!nm_platform_ip6_address_add (ifindex, known_address->address, known_address->plen, lifetime, preferred))
return FALSE; return FALSE;
}
} }
return TRUE; return TRUE;

View File

@@ -103,16 +103,24 @@ typedef struct {
guint mtu; guint mtu;
} NMPlatformLink; } NMPlatformLink;
#define NM_PLATFORM_LIFETIME_PERMANENT G_MAXUINT32
typedef struct { typedef struct {
int ifindex; int ifindex;
in_addr_t address; in_addr_t address;
int plen; int plen;
guint32 timestamp;
guint32 lifetime;
guint32 preferred;
} NMPlatformIP4Address; } NMPlatformIP4Address;
typedef struct { typedef struct {
int ifindex; int ifindex;
struct in6_addr address; struct in6_addr address;
int plen; int plen;
guint32 timestamp;
guint32 lifetime;
guint32 preferred;
} NMPlatformIP6Address; } NMPlatformIP6Address;
typedef struct { typedef struct {
@@ -255,8 +263,10 @@ typedef struct {
GArray * (*ip4_address_get_all) (NMPlatform *, int ifindex); GArray * (*ip4_address_get_all) (NMPlatform *, int ifindex);
GArray * (*ip6_address_get_all) (NMPlatform *, int ifindex); GArray * (*ip6_address_get_all) (NMPlatform *, int ifindex);
gboolean (*ip4_address_add) (NMPlatform *, int ifindex, in_addr_t address, int plen); gboolean (*ip4_address_add) (NMPlatform *, int ifindex, in_addr_t address, int plen,
gboolean (*ip6_address_add) (NMPlatform *, int ifindex, struct in6_addr address, int plen); guint32 lifetime, guint32 preferred_lft);
gboolean (*ip6_address_add) (NMPlatform *, int ifindex, struct in6_addr address, int plen,
guint32 lifetime, guint32 preferred_lft);
gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, int plen); gboolean (*ip4_address_delete) (NMPlatform *, int ifindex, in_addr_t address, int plen);
gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, int plen); gboolean (*ip6_address_delete) (NMPlatform *, int ifindex, struct in6_addr address, int plen);
gboolean (*ip4_address_exists) (NMPlatform *, int ifindex, in_addr_t address, int plen); gboolean (*ip4_address_exists) (NMPlatform *, int ifindex, in_addr_t address, int plen);
@@ -372,8 +382,10 @@ gboolean nm_platform_gre_get_properties (int ifindex, NMPlatformGreProperties *p
GArray *nm_platform_ip4_address_get_all (int ifindex); GArray *nm_platform_ip4_address_get_all (int ifindex);
GArray *nm_platform_ip6_address_get_all (int ifindex); GArray *nm_platform_ip6_address_get_all (int ifindex);
gboolean nm_platform_ip4_address_add (int ifindex, in_addr_t address, int plen); gboolean nm_platform_ip4_address_add (int ifindex, in_addr_t address, int plen,
gboolean nm_platform_ip6_address_add (int ifindex, struct in6_addr address, int plen); guint32 lifetime, guint32 preferred_lft);
gboolean nm_platform_ip6_address_add (int ifindex, struct in6_addr address, int plen,
guint32 lifetime, guint32 preferred_lft);
gboolean nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen); gboolean nm_platform_ip4_address_delete (int ifindex, in_addr_t address, int plen);
gboolean nm_platform_ip6_address_delete (int ifindex, struct in6_addr address, int plen); gboolean nm_platform_ip6_address_delete (int ifindex, struct in6_addr address, int plen);
gboolean nm_platform_ip4_address_exists (int ifindex, in_addr_t address, int plen); gboolean nm_platform_ip4_address_exists (int ifindex, in_addr_t address, int plen);

View File

@@ -73,13 +73,13 @@ dump_interface (NMPlatformLink *link)
for (i = 0; i < ip4_addresses->len; i++) { for (i = 0; i < ip4_addresses->len; i++) {
ip4_address = &g_array_index (ip4_addresses, NMPlatformIP4Address, i); ip4_address = &g_array_index (ip4_addresses, NMPlatformIP4Address, i);
inet_ntop (AF_INET, &ip4_address->address, addrstr, sizeof (addrstr)); inet_ntop (AF_INET, &ip4_address->address, addrstr, sizeof (addrstr));
printf (" ip4-address %s/%d\n", addrstr, ip4_address->plen); printf (" ip4-address %s/%d lifetime %u preferred %u\n", addrstr, ip4_address->plen, ip4_address->lifetime, ip4_address->preferred);
} }
for (i = 0; i < ip6_addresses->len; i++) { for (i = 0; i < ip6_addresses->len; i++) {
ip6_address = &g_array_index (ip6_addresses, NMPlatformIP6Address, i); ip6_address = &g_array_index (ip6_addresses, NMPlatformIP6Address, i);
inet_ntop (AF_INET6, &ip6_address->address, addrstr, sizeof (addrstr)); inet_ntop (AF_INET6, &ip6_address->address, addrstr, sizeof (addrstr));
printf (" ip6-address %s/%d\n", addrstr, ip6_address->plen); printf (" ip6-address %s/%d lifetime %u preferred %u\n", addrstr, ip6_address->plen, ip6_address->lifetime, ip6_address->preferred);
} }
g_array_unref (ip4_addresses); g_array_unref (ip4_addresses);

View File

@@ -511,14 +511,48 @@ typedef struct in6_addr ip6_t;
#define parse_ip4_address(s, a, p) parse_ip_address (AF_INET, s, a, p) #define parse_ip4_address(s, a, p) parse_ip_address (AF_INET, s, a, p)
#define parse_ip6_address(s, a, p) parse_ip_address (AF_INET6, s, a, p) #define parse_ip6_address(s, a, p) parse_ip_address (AF_INET6, s, a, p)
static gboolean
do_ip4_address_add (char **argv)
{
int ifindex = parse_ifindex (*argv++);
ip4_t address;
int plen;
if (ifindex && parse_ip4_address (*argv++, &address, &plen)) {
guint32 lifetime = strtol (*argv++, NULL, 10);
guint32 preferred = strtol (*argv++, NULL, 10);
gboolean value = nm_platform_ip4_address_add (ifindex, address, plen, lifetime, preferred);
return value;
} else
return FALSE;
}
static gboolean
do_ip6_address_add (char **argv)
{
int ifindex = parse_ifindex (*argv++);
ip6_t address;
int plen;
if (ifindex && parse_ip6_address (*argv++, &address, &plen)) {
guint32 lifetime = strtol (*argv++, NULL, 10);
guint32 preferred = strtol (*argv++, NULL, 10);
gboolean value = nm_platform_ip6_address_add (ifindex, address, plen, lifetime, preferred);
return value;
} else
return FALSE;
}
#define ADDR_CMD_FULL(v, cmdname, print) \ #define ADDR_CMD_FULL(v, cmdname, print) \
static gboolean \ static gboolean \
do_##v##_address_##cmdname (char **argv) \ do_##v##_address_##cmdname (char **argv) \
{ \ { \
int ifindex = parse_ifindex (argv[0]); \ int ifindex = parse_ifindex (*argv++); \
v##_t address; \ v##_t address; \
int plen; \ int plen; \
if (ifindex && parse_##v##_address (argv[1], &address, &plen)) { \ if (ifindex && parse_##v##_address (*argv++, &address, &plen)) { \
gboolean value = nm_platform_##v##_address_##cmdname (ifindex, address, plen); \ gboolean value = nm_platform_##v##_address_##cmdname (ifindex, address, plen); \
if (print) { \ if (print) { \
print_boolean (value); \ print_boolean (value); \
@@ -531,7 +565,6 @@ typedef struct in6_addr ip6_t;
#define ADDR_CMD(cmdname) ADDR_CMD_FULL (ip4, cmdname, FALSE) ADDR_CMD_FULL (ip6, cmdname, FALSE) #define ADDR_CMD(cmdname) ADDR_CMD_FULL (ip4, cmdname, FALSE) ADDR_CMD_FULL (ip6, cmdname, FALSE)
#define ADDR_CMD_PRINT(cmdname) ADDR_CMD_FULL (ip4, cmdname, TRUE) ADDR_CMD_FULL (ip6, cmdname, TRUE) #define ADDR_CMD_PRINT(cmdname) ADDR_CMD_FULL (ip4, cmdname, TRUE) ADDR_CMD_FULL (ip6, cmdname, TRUE)
ADDR_CMD (add)
ADDR_CMD (delete) ADDR_CMD (delete)
ADDR_CMD_PRINT (exists) ADDR_CMD_PRINT (exists)
@@ -590,7 +623,7 @@ do_ip4_route_add (char **argv)
in_addr_t network, gateway; in_addr_t network, gateway;
int plen, metric, mss; int plen, metric, mss;
parse_ip4_address (*argv++, &network, &plen); parse_ip4_address (*argv++, &network, &plen);
parse_ip4_address (*argv++, &gateway, NULL); parse_ip4_address (*argv++, &gateway, NULL);
metric = strtol (*argv++, NULL, 10); metric = strtol (*argv++, NULL, 10);
mss = strtol (*argv++, NULL, 10); mss = strtol (*argv++, NULL, 10);
@@ -605,7 +638,7 @@ do_ip6_route_add (char **argv)
struct in6_addr network, gateway; struct in6_addr network, gateway;
int plen, metric, mss; int plen, metric, mss;
parse_ip6_address (*argv++, &network, &plen); parse_ip6_address (*argv++, &network, &plen);
parse_ip6_address (*argv++, &gateway, NULL); parse_ip6_address (*argv++, &gateway, NULL);
metric = strtol (*argv++, NULL, 10); metric = strtol (*argv++, NULL, 10);
mss = strtol (*argv++, NULL, 10); mss = strtol (*argv++, NULL, 10);
@@ -619,7 +652,7 @@ do_ip4_route_delete (char **argv)
in_addr_t network; in_addr_t network;
int plen, metric; int plen, metric;
parse_ip4_address (*argv++, &network, &plen); parse_ip4_address (*argv++, &network, &plen);
metric = strtol (*argv++, NULL, 10); metric = strtol (*argv++, NULL, 10);
return nm_platform_ip4_route_delete (ifindex, network, plen, metric); return nm_platform_ip4_route_delete (ifindex, network, plen, metric);
@@ -632,7 +665,7 @@ do_ip6_route_delete (char **argv)
struct in6_addr network; struct in6_addr network;
int plen, metric; int plen, metric;
parse_ip6_address (*argv++, &network, &plen); parse_ip6_address (*argv++, &network, &plen);
metric = strtol (*argv++, NULL, 10); metric = strtol (*argv++, NULL, 10);
return nm_platform_ip6_route_delete (ifindex, network, plen, metric); return nm_platform_ip6_route_delete (ifindex, network, plen, metric);
@@ -645,7 +678,7 @@ do_ip4_route_exists (char **argv)
in_addr_t network; in_addr_t network;
int plen, metric; int plen, metric;
parse_ip4_address (*argv++, &network, &plen); parse_ip4_address (*argv++, &network, &plen);
metric = strtol (*argv++, NULL, 10); metric = strtol (*argv++, NULL, 10);
print_boolean (nm_platform_ip4_route_exists (ifindex, network, plen, metric)); print_boolean (nm_platform_ip4_route_exists (ifindex, network, plen, metric));
@@ -659,7 +692,7 @@ do_ip6_route_exists (char **argv)
struct in6_addr network; struct in6_addr network;
int plen, metric; int plen, metric;
parse_ip6_address (*argv++, &network, &plen); parse_ip6_address (*argv++, &network, &plen);
metric = strtol (*argv++, NULL, 10); metric = strtol (*argv++, NULL, 10);
print_boolean (nm_platform_ip6_route_exists (ifindex, network, plen, metric)); print_boolean (nm_platform_ip6_route_exists (ifindex, network, plen, metric));
@@ -731,8 +764,8 @@ static const command_t commands[] = {
"<ifname/ifindex>" }, "<ifname/ifindex>" },
{ "ip4-address-get-all", "print all IPv4 addresses", do_ip4_address_get_all, 1, "<ifname/ifindex>" }, { "ip4-address-get-all", "print all IPv4 addresses", do_ip4_address_get_all, 1, "<ifname/ifindex>" },
{ "ip6-address-get-all", "print all IPv6 addresses", do_ip6_address_get_all, 1, "<ifname/ifindex>" }, { "ip6-address-get-all", "print all IPv6 addresses", do_ip6_address_get_all, 1, "<ifname/ifindex>" },
{ "ip4-address-add", "add IPv4 address", do_ip4_address_add, 2, "<ifname/ifindex> <address>/<plen>" }, { "ip4-address-add", "add IPv4 address", do_ip4_address_add, 4, "<ifname/ifindex> <address>/<plen> <lifetime> <>" },
{ "ip6-address-add", "add IPv6 address", do_ip6_address_add, 2, "<ifname/ifindex> <address>/<plen>" }, { "ip6-address-add", "add IPv6 address", do_ip6_address_add, 4, "<ifname/ifindex> <address>/<plen> <lifetime> <>" },
{ "ip4-address-delete", "delete IPv4 address", do_ip4_address_delete, 2, { "ip4-address-delete", "delete IPv4 address", do_ip4_address_delete, 2,
"<ifname/ifindex> <address>/<plen>" }, "<ifname/ifindex> <address>/<plen>" },
{ "ip6-address-delete", "delete IPv6 address", do_ip6_address_delete, 2, { "ip6-address-delete", "delete IPv6 address", do_ip6_address_delete, 2,

View File

@@ -49,34 +49,35 @@ test_ip4_address (void)
SignalData *address_removed = add_signal (NM_PLATFORM_IP4_ADDRESS_REMOVED, ip4_address_callback); SignalData *address_removed = add_signal (NM_PLATFORM_IP4_ADDRESS_REMOVED, ip4_address_callback);
int ifindex = nm_platform_link_get_ifindex (DEVICE_NAME); int ifindex = nm_platform_link_get_ifindex (DEVICE_NAME);
GArray *addresses; GArray *addresses;
NMPlatformIP4Address addrs[2]; NMPlatformIP4Address *address;
in_addr_t addr; in_addr_t addr;
guint32 lifetime = 2000;
guint32 preferred = 1000;
inet_pton (AF_INET, IP4_ADDRESS, &addr); inet_pton (AF_INET, IP4_ADDRESS, &addr);
/* Add address */ /* Add address */
g_assert (!nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN)); g_assert (!nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN));
no_error (); no_error ();
g_assert (nm_platform_ip4_address_add (ifindex, addr, IP4_PLEN)); g_assert (nm_platform_ip4_address_add (ifindex, addr, IP4_PLEN, lifetime, preferred));
no_error (); no_error ();
g_assert (nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN)); g_assert (nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN));
no_error (); no_error ();
accept_signal (address_added); accept_signal (address_added);
/* Add address again */ /* Add address again */
g_assert (!nm_platform_ip4_address_add (ifindex, addr, IP4_PLEN)); g_assert (!nm_platform_ip4_address_add (ifindex, addr, IP4_PLEN, lifetime, preferred));
error (NM_PLATFORM_ERROR_EXISTS); error (NM_PLATFORM_ERROR_EXISTS);
/* Test address listing */ /* Test address listing */
addresses = nm_platform_ip4_address_get_all (ifindex); addresses = nm_platform_ip4_address_get_all (ifindex);
g_assert (addresses); g_assert (addresses);
no_error (); no_error ();
memset (addrs, 0, sizeof (addrs));
addrs[0].ifindex = ifindex;
addrs[0].address = addr;
addrs[0].plen = IP4_PLEN;
g_assert_cmpint (addresses->len, ==, 1); g_assert_cmpint (addresses->len, ==, 1);
g_assert (!memcmp (addresses->data, addrs, sizeof (addrs))); address = &g_array_index (addresses, NMPlatformIP4Address, 0);
g_assert_cmpint (address->ifindex, ==, ifindex);
g_assert_cmphex (address->address, ==, addr);
g_assert_cmpint (address->plen, ==, IP4_PLEN);
g_array_unref (addresses); g_array_unref (addresses);
/* Remove address */ /* Remove address */
@@ -100,34 +101,35 @@ test_ip6_address (void)
SignalData *address_removed = add_signal (NM_PLATFORM_IP6_ADDRESS_REMOVED, ip6_address_callback); SignalData *address_removed = add_signal (NM_PLATFORM_IP6_ADDRESS_REMOVED, ip6_address_callback);
int ifindex = nm_platform_link_get_ifindex (DEVICE_NAME); int ifindex = nm_platform_link_get_ifindex (DEVICE_NAME);
GArray *addresses; GArray *addresses;
NMPlatformIP6Address addrs[2]; NMPlatformIP6Address *address;
struct in6_addr addr; struct in6_addr addr;
guint32 lifetime = 2000;
guint32 preferred = 1000;
inet_pton (AF_INET6, IP6_ADDRESS, &addr); inet_pton (AF_INET6, IP6_ADDRESS, &addr);
/* Add address */ /* Add address */
g_assert (!nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN)); g_assert (!nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN));
no_error (); no_error ();
g_assert (nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN)); g_assert (nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN, lifetime, preferred));
no_error (); no_error ();
g_assert (nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN)); g_assert (nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN));
no_error (); no_error ();
accept_signal (address_added); accept_signal (address_added);
/* Add address again */ /* Add address again */
g_assert (!nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN)); g_assert (!nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN, lifetime, preferred));
error (NM_PLATFORM_ERROR_EXISTS); error (NM_PLATFORM_ERROR_EXISTS);
/* Test address listing */ /* Test address listing */
addresses = nm_platform_ip6_address_get_all (ifindex); addresses = nm_platform_ip6_address_get_all (ifindex);
g_assert (addresses); g_assert (addresses);
no_error (); no_error ();
memset (addrs, 0, sizeof (addrs));
addrs[0].ifindex = ifindex;
addrs[0].address = addr;
addrs[0].plen = IP6_PLEN;
g_assert_cmpint (addresses->len, ==, 1); g_assert_cmpint (addresses->len, ==, 1);
g_assert (!memcmp (addresses->data, addrs, sizeof (addrs))); address = &g_array_index (addresses, NMPlatformIP6Address, 0);
g_assert_cmpint (address->ifindex, ==, ifindex);
g_assert (!memcmp (&address->address, &addr, sizeof (addr)));
g_assert_cmpint (address->plen, ==, IP6_PLEN);
g_array_unref (addresses); g_array_unref (addresses);
/* Remove address */ /* Remove address */
@@ -151,6 +153,8 @@ test_ip4_address_external (void)
SignalData *address_removed = add_signal (NM_PLATFORM_IP4_ADDRESS_REMOVED, ip4_address_callback); SignalData *address_removed = add_signal (NM_PLATFORM_IP4_ADDRESS_REMOVED, ip4_address_callback);
int ifindex = nm_platform_link_get_ifindex (DEVICE_NAME); int ifindex = nm_platform_link_get_ifindex (DEVICE_NAME);
in_addr_t addr; in_addr_t addr;
guint32 lifetime = 2000;
guint32 preferred = 1000;
inet_pton (AF_INET, IP4_ADDRESS, &addr); inet_pton (AF_INET, IP4_ADDRESS, &addr);
g_assert (ifindex > 0); g_assert (ifindex > 0);
@@ -161,7 +165,8 @@ test_ip4_address_external (void)
g_assert (nm_platform_link_set_up (nm_platform_link_get_ifindex (DEVICE_NAME))); g_assert (nm_platform_link_set_up (nm_platform_link_get_ifindex (DEVICE_NAME)));
/* Add/delete notification */ /* Add/delete notification */
run_command ("ip address add %s/%d dev %s", IP4_ADDRESS, IP4_PLEN, DEVICE_NAME); run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d",
IP4_ADDRESS, IP4_PLEN, DEVICE_NAME, lifetime, preferred);
wait_signal (address_added); wait_signal (address_added);
g_assert (nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN)); g_assert (nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN));
run_command ("ip address delete %s/%d dev %s", IP4_ADDRESS, IP4_PLEN, DEVICE_NAME); run_command ("ip address delete %s/%d dev %s", IP4_ADDRESS, IP4_PLEN, DEVICE_NAME);
@@ -169,8 +174,9 @@ test_ip4_address_external (void)
g_assert (!nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN)); g_assert (!nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN));
/* Add/delete conflict */ /* Add/delete conflict */
run_command ("ip address add %s/%d dev %s", IP4_ADDRESS, IP4_PLEN, DEVICE_NAME); run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d",
g_assert (nm_platform_ip4_address_add (ifindex, addr, IP4_PLEN)); IP4_ADDRESS, IP4_PLEN, DEVICE_NAME, lifetime, preferred);
g_assert (nm_platform_ip4_address_add (ifindex, addr, IP4_PLEN, lifetime, preferred));
no_error (); no_error ();
g_assert (nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN)); g_assert (nm_platform_ip4_address_exists (ifindex, addr, IP4_PLEN));
accept_signal (address_added); accept_signal (address_added);
@@ -191,11 +197,14 @@ test_ip6_address_external (void)
SignalData *address_removed = add_signal (NM_PLATFORM_IP6_ADDRESS_REMOVED, ip6_address_callback); SignalData *address_removed = add_signal (NM_PLATFORM_IP6_ADDRESS_REMOVED, ip6_address_callback);
int ifindex = nm_platform_link_get_ifindex (DEVICE_NAME); int ifindex = nm_platform_link_get_ifindex (DEVICE_NAME);
struct in6_addr addr; struct in6_addr addr;
guint32 lifetime = 2000;
guint32 preferred = 1000;
inet_pton (AF_INET6, IP6_ADDRESS, &addr); inet_pton (AF_INET6, IP6_ADDRESS, &addr);
/* Add/delete notification */ /* Add/delete notification */
run_command ("ip address add %s/%d dev %s", IP6_ADDRESS, IP6_PLEN, DEVICE_NAME); run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d",
IP6_ADDRESS, IP6_PLEN, DEVICE_NAME, lifetime, preferred);
wait_signal (address_added); wait_signal (address_added);
g_assert (nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN)); g_assert (nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN));
run_command ("ip address delete %s/%d dev %s", IP6_ADDRESS, IP6_PLEN, DEVICE_NAME); run_command ("ip address delete %s/%d dev %s", IP6_ADDRESS, IP6_PLEN, DEVICE_NAME);
@@ -203,8 +212,9 @@ test_ip6_address_external (void)
g_assert (!nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN)); g_assert (!nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN));
/* Add/delete conflict */ /* Add/delete conflict */
run_command ("ip address add %s/%d dev %s", IP6_ADDRESS, IP6_PLEN, DEVICE_NAME); run_command ("ip address add %s/%d dev %s valid_lft %d preferred_lft %d",
g_assert (nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN)); IP6_ADDRESS, IP6_PLEN, DEVICE_NAME, lifetime, preferred);
g_assert (nm_platform_ip6_address_add (ifindex, addr, IP6_PLEN, lifetime, preferred));
no_error (); no_error ();
g_assert (nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN)); g_assert (nm_platform_ip6_address_exists (ifindex, addr, IP6_PLEN));
accept_signal (address_added); accept_signal (address_added);

View File

@@ -19,6 +19,8 @@ test_cleanup_internal ()
struct in6_addr network6; struct in6_addr network6;
int plen6 = 64; int plen6 = 64;
struct in6_addr gateway6; struct in6_addr gateway6;
int lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
int preferred = NM_PLATFORM_LIFETIME_PERMANENT;
int metric = 20; int metric = 20;
int mss = 1000; int mss = 1000;
@@ -38,8 +40,8 @@ test_cleanup_internal ()
g_assert (ifindex > 0); g_assert (ifindex > 0);
/* Add routes and addresses */ /* Add routes and addresses */
g_assert (nm_platform_ip4_address_add (ifindex, addr4, plen4)); g_assert (nm_platform_ip4_address_add (ifindex, addr4, plen4, lifetime, preferred));
g_assert (nm_platform_ip6_address_add (ifindex, addr6, plen6)); g_assert (nm_platform_ip6_address_add (ifindex, addr6, plen6, lifetime, preferred));
g_assert (nm_platform_ip4_route_add (ifindex, gateway4, 32, INADDR_ANY, metric, mss)); g_assert (nm_platform_ip4_route_add (ifindex, gateway4, 32, INADDR_ANY, metric, mss));
g_assert (nm_platform_ip4_route_add (ifindex, network4, plen4, gateway4, metric, mss)); g_assert (nm_platform_ip4_route_add (ifindex, network4, plen4, gateway4, metric, mss));
g_assert (nm_platform_ip4_route_add (ifindex, 0, 0, gateway4, metric, mss)); g_assert (nm_platform_ip4_route_add (ifindex, 0, 0, gateway4, metric, mss));