Frederic Blase
Frederic Blase

Reputation: 530

How to get network link L2 address via netlink?

I'm using netlink to get interfaces, its names, types etc. but I can't get L2 address (ugly_data is nlmsghdr*):

struct ifinfomsg *iface;
struct rtattr *attribute;
int len;

iface = (struct ifinfomsg *) NLMSG_DATA(ugly_data);
len = ugly_data->nlmsg_len - NLMSG_LENGTH(sizeof(*iface));

for (attribute = IFLA_RTA(iface);
     RTA_OK(attribute, len);
     attribute = RTA_NEXT(attribute, len))
{
  id_ = iface->ifi_index;

  // get type
  switch (iface->ifi_type)
  {
  case ARPHRD_ETHER:
    type_ = "Ethernet";
    break;
  case ...
  }

  // get attributes
  switch (attribute->rta_type)
  {
  case IFLA_IFNAME:
    name_ = (char *) RTA_DATA(attribute);
    break;
  case IFLA_ADDRESS:
    address_ = (char *) RTA_DATA(attribute);
    break;
   ...
  }
}

type_, id_ and name_ contain right values, same as I got from ifconfig, but address_ is always empty. What am I doing wrong and how to get addresses?

Upvotes: 0

Views: 2543

Answers (2)

AAAfarmclub
AAAfarmclub

Reputation: 2390

Here's a Python (Linux) 'solution' (might help somebody):
This is from the first example in the Python Netlink library:
see: https://pypi.python.org/pypi/pyroute2/0.2.16
Really simple installation:

$ sudo pip install pyroute2  

Stick this in a file (I called it netlink1.py) and make it executable:

#!/usr/bin/env python
from pyroute2 import IPRoute

# get access to the netlink socket
ip = IPRoute()

# print interfaces
print ip.get_links()

# stop working with netlink and release all sockets
# ip.release() (deprecated)
ip.close()

This prints out all on one line, then:

$ ./netlink1.py | sed 's/\], /\n/g' | grep IFLA_ADD

Upvotes: 0

Pavel Davydov
Pavel Davydov

Reputation: 3579

Maybe the porblem is that hardware address here is not a string. Try getting address_ like this:

case IFLA_ADDRESS:
  char buffer[64];
  unsigned char* ptr = (unsigned char*)RTA_DATA(attribute);
  snprintf(buffer, 64, " %02x:%02x:%02x:%02x:%02x:%02x", 
      ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5]);
  std::cout << "address : " << buffer << std::endl;

this works for me.

Upvotes: 4

Related Questions