softwarecontainer  0.18.0-739e8d7 2017-05-04
softwarecontainer::Netlink Class Reference

Handles various network operations over netlink. More...

#include <netlink.h>

Public Types

typedef std::pair< rtattr, void * > AttributeInfo
 
typedef std::vector< AttributeInfo > AttributeList
 
typedef std::pair< ifinfomsg, AttributeList > LinkInfo
 
typedef std::pair< ifaddrmsg, AttributeList > AddressInfo
 
typedef std::pair< rtmsg, AttributeList > RouteInfo
 

Public Member Functions

 LOG_DECLARE_CLASS_CONTEXT ("NETL","Netlink")
 
 Netlink ()
 Construct a new Netlink object. More...
 
virtual ~Netlink ()
 release all resources held by the Netlink object More...
 
bool getKernelDump ()
 get a dump of all links, addresses and routes from the kernel. More...
 
virtual bool checkKernelDump ()
 check for a kernel dump, and if not present, try to get one More...
 
bool setDefaultGateway (const char *gatewayAddress)
 Sets an ip address as the default gateway. More...
 
bool linkUp (const int ifaceIndex)
 Bring the given interface up. More...
 
bool linkDown (const int ifaceIndex)
 Bring a given interface down. More...
 
bool setIP (const int ifaceIndex, const in_addr ip, const unsigned char netmask)
 Sets an IP address for a network link. More...
 
bool findLink (const char *ifaceName, LinkInfo &linkInfo)
 Check that the device given is a network bridge. More...
 
bool findAddresses (const unsigned int interfaceIndex, std::vector< AddressInfo > &result)
 Get all addresses associated with the given interface index. More...
 
bool hasAddress (const std::vector< AddressInfo > &haystack, const int addressFamily, const char *needle)
 checks if an address is present in the given list More...
 

Detailed Description

Handles various network operations over netlink.

Some of the code in this class is based on code shown here, written by Jean Lorchat http://iijean.blogspot.se/2010/03/howto-get-list-of-network-interfaces-in.html

Definition at line 37 of file netlink.h.

Constructor & Destructor Documentation

softwarecontainer::Netlink::Netlink ( )

Construct a new Netlink object.

This will do a setup of the sockets needed to talk netlink to the kernel, and will also call getKernelDump()

Definition at line 30 of file netlink.cpp.

References getKernelDump().

31 {
32  m_sequenceNumber = 1;
33  m_hasKernelDump = false;
34  m_netlinkInitialized = false;
35 
36  if (!setupNetlink()) {
37  fprintf(stderr, "Failed to setup netlink\n");
38  }
39 
40  if (!getKernelDump()) {
41  fprintf(stderr, "Failed to initialize cache\n");
42  }
43 }

Here is the call graph for this function:

softwarecontainer::Netlink::~Netlink ( )
virtual

release all resources held by the Netlink object

Since we allocate everything on the stack, except for the netlink attributes which we save as void pointers, we basically go through all data structures and free those pointers.

Also shuts down the communication with the kernel.

Definition at line 45 of file netlink.cpp.

46 {
47  if (m_netlinkInitialized) {
48  shutdown(m_fd, SHUT_RDWR);
49  close(m_fd);
50  }
51 
52  if (m_hasKernelDump) {
53  clearCache();
54  }
55 }

Member Function Documentation

bool softwarecontainer::Netlink::getKernelDump ( )

get a dump of all links, addresses and routes from the kernel.

To get a dump of all links/addresses/routes we only need to use the generic netlink family message type, and for that we only need to set family (AF_PACKET).

This is done by sending RTM_GETLINK, RTM_GETADDR and RTM_GETROUTE as a general message (rtgenmsg) to the kernel.

After running this successfully, there will be a local cache of these network objects, which is needed to run some of the other functions.

Returns
true on success, false otherwise
See also
clearCache()

Definition at line 458 of file netlink.cpp.

Referenced by checkKernelDump(), and Netlink().

459 {
460  m_hasKernelDump = false;
461 
462  netlink_request<rtgenmsg> link_msg = createMessage<rtgenmsg>(RTM_GETLINK, NLM_F_DUMP);
463  link_msg.pay.rtgen_family = AF_PACKET;
464  if (!sendMessage(link_msg)) {
465  std::cerr << "Could not send link message" << std::endl;
466  return false;
467  }
468 
469  netlink_request<rtgenmsg> addr_msg = createMessage<rtgenmsg>(RTM_GETADDR, NLM_F_DUMP);
470  addr_msg.pay.rtgen_family = AF_PACKET;
471  if (!sendMessage(addr_msg)) {
472  std::cerr << "Could not send address message" << std::endl;
473  return false;
474  }
475 
476  netlink_request<rtgenmsg> route_msg = createMessage<rtgenmsg>(RTM_GETROUTE, NLM_F_DUMP);
477  route_msg.pay.rtgen_family = AF_PACKET;
478  if (!sendMessage(route_msg)) {
479  std::cerr << "Could not send route message" << std::endl;
480  return false;
481  }
482 
483  m_hasKernelDump = true;
484  return true;
485 }

Here is the caller graph for this function:

bool softwarecontainer::Netlink::checkKernelDump ( )
virtual

check for a kernel dump, and if not present, try to get one

Returns
true if there a kernel dump was found or could be fetched
false otherwise

Definition at line 487 of file netlink.cpp.

References getKernelDump().

Referenced by findAddresses(), findLink(), and linkUp().

488 {
489  if (!m_hasKernelDump && !getKernelDump()) {
490  std::cerr << "Could not get cache dump from kernel" << std::endl;
491  return false;
492  }
493 
494  return true;
495 }

Here is the call graph for this function:

Here is the caller graph for this function:

bool softwarecontainer::Netlink::setDefaultGateway ( const char *  gatewayAddress)

Sets an ip address as the default gateway.

Parameters
gatewayAddressthe address to set
Returns
true on success
false otherwise

Definition at line 175 of file netlink.cpp.

Referenced by softwarecontainer::NetworkGateway::teardownGateway().

176 {
177  netlink_request<rtmsg> set_gw = createMessage<rtmsg>(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_REPLACE);
178  set_gw.pay.rtm_family = AF_INET;
179  set_gw.pay.rtm_table = RT_TABLE_MAIN;
180  set_gw.pay.rtm_protocol = RTPROT_STATIC;
181  set_gw.pay.rtm_scope = RT_SCOPE_UNIVERSE;
182  set_gw.pay.rtm_type = RTN_UNICAST;
183 
184  struct in_addr gw_addr;
185  if (inet_aton(gatewayAddress, &gw_addr) == 0) {
186  return false;
187  }
188  addAttribute(set_gw, RTA_GATEWAY, sizeof(gw_addr), &gw_addr);
189 
190  return sendMessage(set_gw);
191 }

Here is the caller graph for this function:

bool softwarecontainer::Netlink::linkUp ( const int  ifaceIndex)

Bring the given interface up.

Sets the UP flag for the given interface, if it exists.

Parameters
ifaceIndexthe index for the interface to bring up
Returns
true if the interface was found and brought up
false otherwise

Definition at line 194 of file netlink.cpp.

References checkKernelDump().

Referenced by softwarecontainer::NetworkGateway::teardownGateway().

195 {
196  if (!checkKernelDump()) {
197  return false;
198  }
199 
200  for (LinkInfo link : m_links) {
201  ifinfomsg ifinfo = link.first;
202  if (ifinfo.ifi_index != ifaceIndex) {
203  continue;
204  }
205 
206  // First, bring the link up
207  netlink_request<ifinfomsg> msg_up = createMessage<ifinfomsg>(RTM_NEWLINK, NLM_F_CREATE);
208  msg_up.pay.ifi_family = AF_UNSPEC;
209  msg_up.pay.ifi_flags = ifinfo.ifi_flags | IFF_UP;
210  msg_up.pay.ifi_change |= IFF_UP;
211  msg_up.pay.ifi_index = ifinfo.ifi_index;
212  if (!sendMessage(msg_up)) {
213  fprintf(stderr, "Failed to bring device %i up\n", ifinfo.ifi_index);
214  return false;
215  } else {
216  return true;
217  }
218  }
219 
220  return false;
221 }

Here is the call graph for this function:

Here is the caller graph for this function:

bool softwarecontainer::Netlink::linkDown ( const int  ifaceIndex)

Bring a given interface down.

Parameters
ifaceIndexthe index for the interface to bring down
Returns
true if interface was found and brought down
false otherwise

Definition at line 261 of file netlink.cpp.

Referenced by softwarecontainer::NetworkGateway::teardownGateway().

262 {
263  for (LinkInfo link : m_links) {
264  ifinfomsg ifinfo = link.first;
265  if (ifinfo.ifi_type == ARPHRD_LOOPBACK) {
266  continue; // This is the loopback device
267  }
268 
269  if (ifinfo.ifi_index != ifaceIndex) {
270  continue; // Only bring down the requested iface
271  }
272 
273  netlink_request<ifinfomsg> down_msg = createMessage<ifinfomsg>(RTM_NEWLINK, 0);
274  down_msg.pay.ifi_family = AF_UNSPEC;
275  down_msg.pay.ifi_index = ifinfo.ifi_index;
276  down_msg.pay.ifi_flags = ~IFF_UP;
277  down_msg.pay.ifi_change = IFF_UP;
278 
279  if (!sendMessage(down_msg)) {
280  return false;
281  } else {
282  return true;
283  }
284  }
285 
286  return false;
287 }

Here is the caller graph for this function:

bool softwarecontainer::Netlink::setIP ( const int  ifaceIndex,
const in_addr  ip,
const unsigned char  netmask 
)

Sets an IP address for a network link.

Parameters
ifaceIndexthe index for the interface to set ip for
ipthe ipv4 address to set
netmaskthe netmask in CIDR format (for example 24)
Returns
true if interface was found and IP was set
false otherwise

Definition at line 223 of file netlink.cpp.

Referenced by softwarecontainer::NetworkGateway::teardownGateway().

224 {
225  for (LinkInfo link : m_links) {
226  ifinfomsg ifinfo = link.first;
227  if (ifinfo.ifi_index != ifaceIndex) {
228  continue;
229  }
230 
231  // TODO: Support for ipv6
232  netlink_request<ifaddrmsg> msg_setip = createMessage<ifaddrmsg>(RTM_NEWADDR, NLM_F_CREATE | NLM_F_REPLACE);
233  msg_setip.pay.ifa_family = AF_INET; // ipv4
234  msg_setip.pay.ifa_prefixlen = netmask;
235  msg_setip.pay.ifa_scope = RT_SCOPE_UNIVERSE;
236  msg_setip.pay.ifa_index = ifinfo.ifi_index; // interface (link)
237 
238  // Calculate the broadcast address.
239  // Broadcast = IP | (~Netmask)
240  in_addr_t inet_netmask = (1 << netmask) -1;
241  in_addr_t inet_bcast = ip.s_addr | (~inet_netmask);
242  in_addr bcast_addr = { inet_bcast };
243 
244  addAttribute(msg_setip, IFA_LOCAL, sizeof(ip), &ip);
245  addAttribute(msg_setip, IFA_BROADCAST, sizeof(bcast_addr), &bcast_addr);
246 
247  // No matter what happens, we return since we found the link we've been looking for.
248  if (!sendMessage(msg_setip)) {
249  // TODO: pton to print ip number also.
250  fprintf(stderr, "Failed to set ip on link %i\n", ifinfo.ifi_index);
251  return false;
252  } else {
253  return true;
254  }
255  }
256 
257  // No link found, that's a failure.
258  return false;
259 }

Here is the caller graph for this function:

bool softwarecontainer::Netlink::findLink ( const char *  ifaceName,
LinkInfo &  linkInfo 
)

Check that the device given is a network bridge.

Parameters
ifaceNamethe name of the interface
ifaceIndexthe index of the interface (out parameter)
Returns
true if interface with matching name was found.
false otherwise.

Definition at line 289 of file netlink.cpp.

References checkKernelDump().

Referenced by softwarecontainer::NetworkGateway::teardownGateway().

290 {
291  if (!checkKernelDump()) {
292  return false;
293  }
294 
295  for (LinkInfo link : m_links) {
296  AttributeList attributes = link.second;
297  for (AttributeInfo attrinfo : attributes) {
298  rtattr attr = attrinfo.first;
299  void *data = attrinfo.second;
300 
301  if (attr.rta_type == IFLA_IFNAME) {
302  char *ifname = (char *) data;
303  if (strcmp(ifname, ifaceName) == 0) {
304  linkInfo = link;
305  return true;
306  }
307  }
308  }
309  }
310 
311  return false;
312 }

Here is the call graph for this function:

Here is the caller graph for this function:

bool softwarecontainer::Netlink::findAddresses ( const unsigned int  interfaceIndex,
std::vector< AddressInfo > &  result 
)

Get all addresses associated with the given interface index.

Parameters
interfaceIndexthe interface address to get addresses for
resultthe vector to place all addresses in (out parameter)
Returns
true on success
false otherwise

Definition at line 314 of file netlink.cpp.

References checkKernelDump().

Referenced by softwarecontainer::NetworkGateway::teardownGateway().

315 {
316  if (!checkKernelDump()) {
317  return false;
318  }
319 
320  for (AddressInfo addressInfo : m_addresses) {
321  ifaddrmsg addrmsg = addressInfo.first;
322  if (addrmsg.ifa_index == interfaceIndex) {
323  result.push_back(addressInfo);
324  }
325  }
326 
327  return true;
328 
329 }

Here is the call graph for this function:

Here is the caller graph for this function:

bool softwarecontainer::Netlink::hasAddress ( const std::vector< AddressInfo > &  haystack,
const int  addressFamily,
const char *  needle 
)

checks if an address is present in the given list

Parameters
haystackthe list to search in
addressFamilythe address family, AF_INET or AF_INET6
needlethe ip address to search for, in dotted notation
Returns
true if the address is in the haystack
false otherwise

Definition at line 331 of file netlink.cpp.

Referenced by softwarecontainer::NetworkGateway::teardownGateway().

334 {
335  for (AddressInfo addressInfo : haystack) {
336  AttributeList attributes = addressInfo.second;
337  for (AttributeInfo attrPair : attributes) {
338 
339  // Skip if this attribute is not an address attribute
340  rtattr attr = attrPair.first;
341  if (attr.rta_type != IFA_ADDRESS && attr.rta_type != IFA_LOCAL) {
342  continue;
343  }
344 
345  void *data = attrPair.second;
346  char out[INET6_ADDRSTRLEN];
347 
348  // It is ok here for inet_ntop to fail (data could be bad)
349  if (inet_ntop(addressFamily, data, out, sizeof(out)) && strcmp(out, needle) == 0) {
350  return true;
351  }
352  }
353  }
354 
355  std::cout << "Netlink does not have address" << std::endl;
356  return false;
357 }

Here is the caller graph for this function:


The documentation for this class was generated from the following files: