platform: link address setting

This commit is contained in:
Pavel Šimerda
2013-03-27 22:53:55 +01:00
parent a28a880214
commit 6c55e5a1c6
7 changed files with 200 additions and 0 deletions

View File

@@ -40,6 +40,7 @@ typedef struct {
typedef struct {
NMPlatformLink link;
GBytes *address;
int vlan_parent;
int vlan_id;
} NMFakePlatformLink;
@@ -123,6 +124,7 @@ link_init (NMFakePlatformLink *device, int ifindex, int type, const char *name)
default:
device->link.arp = TRUE;
}
device->address = NULL;
}
static NMFakePlatformLink *
@@ -354,6 +356,35 @@ link_uses_arp (NMPlatform *platform, int ifindex)
return device ? device->link.arp : FALSE;
}
static gboolean
link_set_address (NMPlatform *platform, int ifindex, gconstpointer addr, size_t len)
{
NMFakePlatformLink *device = link_get (platform, ifindex);
if (device->address)
g_bytes_unref (device->address);
device->address = g_bytes_new (addr, len);
link_changed (platform, link_get (platform, ifindex));
return TRUE;
}
static gconstpointer
link_get_address (NMPlatform *platform, int ifindex, size_t *length)
{
NMFakePlatformLink *device = link_get (platform, ifindex);
if (!device || !device->address) {
if (length)
*length = 0;
return NULL;
}
return g_bytes_get_data (device->address, length);
}
static gboolean
link_supports_carrier_detect (NMPlatform *platform, int ifindex)
{
@@ -896,8 +927,14 @@ static void
nm_fake_platform_finalize (GObject *object)
{
NMFakePlatformPrivate *priv = NM_FAKE_PLATFORM_GET_PRIVATE (object);
int i;
g_hash_table_unref (priv->options);
for (i = 0; i < priv->links->len; i++) {
NMFakePlatformLink *device = &g_array_index (priv->links, NMFakePlatformLink, i);
g_bytes_unref (device->address);
}
g_array_unref (priv->links);
g_array_unref (priv->ip4_addresses);
g_array_unref (priv->ip6_addresses);
@@ -939,6 +976,9 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass)
platform_class->link_is_connected = link_is_connected;
platform_class->link_uses_arp = link_uses_arp;
platform_class->link_set_address = link_set_address;
platform_class->link_get_address = link_get_address;
platform_class->link_supports_carrier_detect = link_supports_carrier_detect;
platform_class->link_supports_vlans = link_supports_vlans;

View File

@@ -1108,6 +1108,37 @@ link_supports_vlans (NMPlatform *platform, int ifindex)
return !(features->features[block].active & (1 << bit));
}
static gboolean
link_set_address (NMPlatform *platform, int ifindex, gconstpointer address, size_t length)
{
auto_nl_object struct rtnl_link *change = NULL;
auto_nl_addr struct nl_addr *nladdr = NULL;
change = rtnl_link_alloc ();
g_return_val_if_fail (change, FALSE);
nladdr = nl_addr_build (AF_LLC, address, length);
g_return_val_if_fail (nladdr, FALSE);
rtnl_link_set_addr (change, nladdr);
return link_change (platform, ifindex, change);
}
static gconstpointer
link_get_address (NMPlatform *platform, int ifindex, size_t *length)
{
auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex);
struct nl_addr *nladdr;
nladdr = rtnllink ? rtnl_link_get_addr (rtnllink) : NULL;
if (length)
*length = nladdr ? nl_addr_get_len (nladdr) : 0;
return nladdr ? nl_addr_get_binary_addr (nladdr) : NULL;
}
static int
vlan_add (NMPlatform *platform, const char *name, int parent, int vlan_id, guint32 vlan_flags)
{
@@ -1740,6 +1771,9 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->link_is_connected = link_is_connected;
platform_class->link_uses_arp = link_uses_arp;
platform_class->link_get_address = link_get_address;
platform_class->link_set_address = link_set_address;
platform_class->link_supports_carrier_detect = link_supports_carrier_detect;
platform_class->link_supports_vlans = link_supports_vlans;

View File

@@ -493,6 +493,48 @@ nm_platform_link_uses_arp (int ifindex)
return klass->link_uses_arp (platform, ifindex);
}
/**
* 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);
}
gboolean
nm_platform_link_supports_carrier_detect (int ifindex)
{

View File

@@ -159,6 +159,9 @@ typedef struct {
gboolean (*link_is_connected) (NMPlatform *, int ifindex);
gboolean (*link_uses_arp) (NMPlatform *, int ifindex);
gconstpointer (*link_get_address) (NMPlatform *, int ifindex, size_t *length);
gboolean (*link_set_address) (NMPlatform *, int ifindex, gconstpointer address, size_t length);
gboolean (*link_supports_carrier_detect) (NMPlatform *, int ifindex);
gboolean (*link_supports_vlans) (NMPlatform *, int ifindex);
@@ -261,6 +264,9 @@ gboolean nm_platform_link_is_up (int ifindex);
gboolean nm_platform_link_is_connected (int ifindex);
gboolean nm_platform_link_uses_arp (int ifindex);
gconstpointer nm_platform_link_get_address (int ifindex, size_t *length);
gboolean nm_platform_link_set_address (int ifindex, const void *address, size_t length);
gboolean nm_platform_link_supports_carrier_detect (int ifindex);
gboolean nm_platform_link_supports_vlans (int ifindex);

View File

@@ -21,6 +21,8 @@ dump_interface (NMPlatformLink *link)
char networkstr[INET6_ADDRSTRLEN];
char gatewaystr[INET6_ADDRSTRLEN];
int vlan_id, vlan_parent;
const char *address;
size_t addrlen;
int i;
g_assert (link->up || !link->connected);
@@ -44,6 +46,14 @@ dump_interface (NMPlatformLink *link)
if (nm_platform_link_supports_vlans (link->ifindex))
printf (" feature vlans\n");
address = nm_platform_link_get_address (link->ifindex, &addrlen);
if (address) {
printf (" link-address ");
for (i = 0; i < addrlen; i++)
printf ("%s%02hhx", i ? ":" : "", address[i]);
printf ("\n");
}
ip4_addresses = nm_platform_ip4_address_get_all (link->ifindex);
ip6_addresses = nm_platform_ip6_address_get_all (link->ifindex);

View File

@@ -184,6 +184,52 @@ LINK_CMD_GET (is_up, boolean)
LINK_CMD_GET (is_connected, boolean)
LINK_CMD_GET (uses_arp, boolean)
static gboolean
do_link_set_address (char **argv)
{
int ifindex = parse_ifindex (*argv++);
char *hex = *argv++;
int hexlen = strlen (hex);
char address[hexlen/2];
char *endptr;
int i;
g_assert (!(hexlen % 2));
for (i = 0; i < sizeof (address); i++) {
char digit[3];
digit[0] = hex[2*i];
digit[1] = hex[2*i+1];
digit[2] = '\0';
address[i] = strtoul (digit, &endptr, 16);
g_assert (!*endptr);
}
return nm_platform_link_set_address (ifindex, address, sizeof (address));
}
static gboolean
do_link_get_address (char **argv)
{
int ifindex = parse_ifindex (*argv++);
const char *address;
size_t length;
int i;
address = nm_platform_link_get_address (ifindex, &length);
if (!address || length <= 0)
return FALSE;
for (i = 0; i < length; i++)
printf ("%02x", address[i]);
printf ("\n");
return TRUE;
}
LINK_CMD_GET (supports_carrier_detect, boolean)
LINK_CMD_GET (supports_vlans, boolean)
@@ -546,6 +592,8 @@ static const command_t commands[] = {
{ "link-is-up", "check if interface is up", do_link_is_up, 1, "<ifname/ifindex>" },
{ "link-is-connected", "check interface carrier", do_link_is_connected, 1, "<ifname/ifindex>" },
{ "link-uses-arp", "check whether interface uses arp", do_link_uses_arp, 1, "<ifname/ifindex>" },
{ "link-get-address", "print link address", do_link_get_address, 1, "<ifname/ifindex>" },
{ "link-set-address", "set link address", do_link_set_address, 2, "<ifname/ifindex> <hex>" },
{ "link-supports-carrier-detect", "check whether interface supports carrier detect",
do_link_supports_carrier_detect, 1, "<ifname/ifindex>" },
{ "link-supports-vlans", "check whether interface supports VLANs",

View File

@@ -58,6 +58,8 @@ link_callback (NMPlatform *platform, int ifindex, NMPlatformLink *received, Sign
static void
test_bogus(void)
{
size_t addrlen;
g_assert (!nm_platform_link_exists (BOGUS_NAME));
no_error ();
g_assert (!nm_platform_link_delete (BOGUS_IFINDEX));
@@ -88,6 +90,12 @@ test_bogus(void)
g_assert (!nm_platform_link_uses_arp (BOGUS_IFINDEX));
error (NM_PLATFORM_ERROR_NOT_FOUND);
g_assert (!nm_platform_link_get_address (BOGUS_IFINDEX, &addrlen));
g_assert (!addrlen);
error (NM_PLATFORM_ERROR_NOT_FOUND);
g_assert (!nm_platform_link_get_address (BOGUS_IFINDEX, NULL));
error (NM_PLATFORM_ERROR_NOT_FOUND);
g_assert (!nm_platform_link_supports_carrier_detect (BOGUS_IFINDEX));
error (NM_PLATFORM_ERROR_NOT_FOUND);
g_assert (!nm_platform_link_supports_vlans (BOGUS_IFINDEX));
@@ -382,6 +390,9 @@ test_internal (void)
SignalData *link_added = add_signal (NM_PLATFORM_LINK_ADDED, link_callback);
SignalData *link_changed = add_signal (NM_PLATFORM_LINK_CHANGED, link_callback);
SignalData *link_removed = add_signal (NM_PLATFORM_LINK_REMOVED, link_callback);
const char mac[6] = { 0x00, 0xff, 0x11, 0xee, 0x22, 0xdd };
const char *address;
size_t addrlen;
int ifindex;
/* Check the functions for non-existent devices */
@@ -430,6 +441,15 @@ test_internal (void)
g_assert (!nm_platform_link_supports_carrier_detect (ifindex));
g_assert (nm_platform_link_supports_vlans (ifindex));
/* Set MAC address */
g_assert (nm_platform_link_set_address (ifindex, mac, sizeof (mac)));
address = nm_platform_link_get_address (ifindex, &addrlen);
g_assert (addrlen == sizeof(mac));
g_assert (!memcmp (address, mac, addrlen));
address = nm_platform_link_get_address (ifindex, NULL);
g_assert (!memcmp (address, mac, addrlen));
accept_signal (link_changed);
/* Delete device */
g_assert (nm_platform_link_delete (ifindex));
no_error ();