Manipulating the Networking Environment Using RTNETLINK

How to use RTNETLINK to develop applications that control networking.
RTNETLINK Functionality

A programmer who develops applications that use RTNETLINK must include the following #include files at a minimum:

#include <bits/sockaddr.h>
#include <asm/types.h>
#include <linux/rtnetlink.h>
#include <sys/socket.h>

These files contain the different definitions, such as data types and structures, required to make RTNETLINK calls. Here is a short explanation of what is defined in these files relevant to RTNETLINK:

  • bits/sockaddr.h: provides the definitions for the addresses used by socket functions.

  • asm/types.h: provides the definitions of the data types used in the header files related to NETLINK and RTNETLINK.

  • linux/rtnetlink.h: provides the macros and data structures that are used in RTNETLINK. Because RTNETLINK is based on NETLINK, this also includes the linux/netlink.h. netlink.h defines the general macros and structures that are used in all the NETLINK-based capabilities.

  • sys/socket.h: provides the function prototypes and the different data structures related to the socket implementation.

The operations that can be invoked using RTNETLINK are defined in the rtnetlink.h file. Each of the operations provides three possibilities of manipulation: add/update, delete or query. These three possibilities are identified by NEW, DEL and GET. Following are the manipulation operations allowed by RTNETLINK.

General networking environment manipulation services:

  • Link layer interface settings: identified by RTM_NEWLINK, RTM_DELLINK and RTM_GETLINK.

  • Network layer (IP) interface settings: RTM_NEWADDR, RTM_DELADDR and RTM_GETADDR.

  • Network layer routing tables: RTM_NEWROUTE, RTM_DELROUTE and RTM_GETROUTE.

  • Neighbor cache that associates network layer and link layer addressing: RTM_NEWNEIGH, RTM_DELNEIGH and RTM_GETNEIGH.

Traffic shaping (management) services:

  • Routing rules to direct network layer packets: RTM_NEWRULE, RTM_DELRULE and RTM_GETRULE.

  • Queuing discipline settings associated with network interfaces: RTM_NEWQDISC, RTM_DELQDISC and RTM_GETQDISC.

  • Traffic classes used together with queues: RTM_NEWTCLASS, RTM_DELTCLASS and RTM_GETTCLASS.

  • Traffic filters associated with a queuing: RTM_NEWTFILTER, RTM_DELTFILTER and RTM_GETTFILTER.

Forming and Reading RTNETLINK Messages

RTNETLINK employs a request-response mechanism to send and receive information to manipulate the networking environment. A request or a response of RTNETLINK consists of a stream of message structures. These structures are filled by the caller, in the case of a request, or filled by the kernel, in the case of a response. To place information into these structures or to retrieve information, RTNETLINK provides a set of macros (using #define statements). Every request must contain the following structure at the beginning:

struct nlmsghdr
  __u32  nlmsg_len;   //Length of msg incl. hdr
  __u16  nlmsg_type;  //Message content
  __u16  nlmsg_flags; //Additional flags
  __u32  nlmsg_seq;   //Sequence number
  __u32  nlmsg_pid;   //Sending process PID

This structure provides information about what type of RTNETLINK message is specified in the rest of the request. It is also called the NETLINK header. Here is a brief explanation of these fields:

  • nlmsg_len: should contain the length of the whole RTNETLINK message, including the length of the nlmsghdr structure. This field can be filled using the macro NLMSG_ALIGN(len), where len is the length of the message that follows this structure.

  • nlmsg_type: a 16-bit flag to indicate what is contained in the message, such as RTM_NEWROUTE.

  • nlmsg_flags: another 16-bit flag that further clarifies the operation specified in nlmsg_type, such as NLM_F_REQUEST.

  • nlmsg_seq and nlmsg_pid: these two fields are used to identify an RTNETLINK request uniquely. The caller can place the process ID and a sequence number in these fields.

Following the nlmsghdr structure are the structures relevant to the operation being requested. Depending on the type of RTNETLINK operation, the caller must include one or more of the following structures. These are called the RTNETLINK operation headers:

  • struct rtmsg: retrieving or modifying entries of the routing table requires the use of this structure.

  • struct rtnexthop: a next hop in a routing entry is the next host to consider on the way to the destination. A single routing entry can have multiple next hops. Each next hop entry has many types of attributes, such as the network interface in addition to the next hop IP address.

  • struct rta_cacheinfo: each route entry consists of status information that the kernel updates regularly, mainly usage information. Using this structure, a user can retrieve this information.

  • struct ifaddrmsg: retrieving or modifying network layer attributes associated with a network interface requires the use of this structure.

  • struct ifa_cacheinfo: similar to a route entry, a network interface also consists of information about its status, which is updated by the kernel. This structure is used to retrieve this information.

  • struct ndmsg: retrieving or modifying the association information between link layer addressing and network layer addressing of neighbors, referred to as neighbor discovery, is specified through this structure.

  • struct nda_cacheinfo: holds the kernel updated information related to each neighbor discovery entry.

  • struct ifinfomsg: retrieving or modifying the link layer attributes related to a network interface requires the use of this structure.

  • struct tcmsg: retrieving or modifying traffic shaping attributes is supplied using this structure.

Following the RTNETLINK operation header are the attributes related to the operation, such as an interface number and IP address. These attributes are specified using the struct rtattr. There is one structure for each attribute. This structure has the following format:

struct rtattr
  unsigned short  rta_len;
  unsigned short  rta_type;

Immediately following this structure is the value of the attribute. An attribute such as an IP version 4 address will occupy a 4-byte area. The variable rta_len should contain the size of this structure plus the size of the attribute. rta_type should contain the value identifying the attribute, which are given in the enumerations defined in rtnetlink.h. enum rtattr_type_t and other enumerations provide the attribute identifiers, such as IFA_ADDRESS and NDA_DST, to be used in this field. The maximum number of attributes that you can attach is up to only the macro RTATTR_MAX. An example of attaching an attribute is as follows:

rtap->rta_type = RTA_DST;
inet_pton(AF_INET, dsts,

Information that is received from an RTNETLINK socket is again a stream of structures. A programmer has to identify and extract information by moving a pointer along this byte stream. To simplify this process, RTNETLINK provides a set of macros to make the buffer positioning easier:

  • NLMSG_NEXT(nlh, len): returns the pointer to the next NETLINK header. nlh is the header returned previously, and len is the total length of the message. This will be called in a loop to read every message.

  • NLMSG_DATA(nlh): returns the pointer to the RTNETLINK header related to the requested operation given the NETLINK header. If a route entry is being manipulated, this will return a pointer to a struct rtmsg.

  • RTM_RTA(r), IFA_RTA(r), NDA_RTA(r), IFLA_RTA(r) and TCA_RTA(r): return a pointer to the start of the attributes of the respective RTNETLINK operation given the header of the RTNETLINK message (r).

  • RTM_PAYLOAD(n), IFA_PAYLOAD(n), NDA_PAYLOAD(n), IFLA_PAYLOAD(n) and TCA_PAYLOAD(n): return the total length of the attributes that follow the RTNETLINK operation header given the pointer to the NETLINK header (n).

  • RTA_NEXT(rta, attrlen): returns a pointer to the start of the next attribute given the last returned attribute (rta) and the remaining size (attrlen) of the attributes.

Considering a simple example where an RTNETLINK request to retrieve the routing table was sent, the reply is processed in the following manner:

char *buf; // ptr to RTNETLINK data
int nll; // byte length of all data
struct nlmsghdr *nlp;
struct rtmsg *rtp;
int rtl;
struct rtattr *rtap;

nlp = (struct nlmsghdr *) buf;

  // get RTNETLINK message header
  rtp = (struct rtmsg *) NLMSG_DATA(nlp);

  // get start of attributes
  rtap = (struct rtattr *) RTM_RTA(rtp);

  // get length of attributes
  rtl = RTM_PAYLOAD(nlp);

  // loop & get every attribute

    // check and process every attribute




Comment viewing options


wireless link

Pranab's picture


Getting default gateway

donX's picture



double event found on netlink socket

Anonymous's picture

hi All,



I m using "nl_groups = RTNLGRP_LINK" only.


Route add does not work.

Nilesh's picture


Here is the function.

unsigned int rtm_add_v4 (unsigned int prefix,
unsigned char len, u_char tbl_index,
unsigned int oif,
u_char proto,
u_char rt_type,
struct rtnexthop *rtnh)
struct sockaddr_nl ra;
struct msghdr msg;
struct iovec iov;
char buf[8192];
int rtn;

struct nlmsghdr *nlm;
int nlml;
struct rtmsg *rt;
int rtl;
struct rtattr *rta;
rtsock_req_t rreq;


bzero(&rreq, sizeof(rreq));

rtl = sizeof(struct rtmsg);

rta = (struct rtattr *)rreq.buf;

rta->rta_type = RTA_DST;



rtl += rta->rta_len;


rta->rta_type = RTA_OIF;


rtl += rta->rta_len;


/* Setup operation header */

rreq.rt.rtm_family = AF_INET;
rreq.rt.rtm_dst_len = len;
rreq.rt.rtm_table = tbl_index;
rreq.rt.rtm_protocol = proto;
rreq.rt.rtm_scope = RT_SCOPE_UNIVERSE;
rreq.rt.rtm_type = rt_type;

bzero(&ra, sizeof(ra));
ra.nl_family = AF_NETLINK;

bzero(&msg, sizeof(msg));

msg.msg_name = (void *)&ra;
msg.msg_namelen = sizeof(ra);

iov.iov_base = (void *)&;
iov.iov_len =;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;

rtn = sendmsg(rtsock,&msg, 0);

if (rtn < 0)
printf("%s :", __FUNCTION__);
return 0;
} else {
return 1;

return 0;


Here is the routing table before route add

[root@iLinux-Nilesh route]# route -n
Kernel IP routing table


Enter the route to be added:
Addr: 0xac150101
Enter prefix len: 32
len: 32
Enter the oif: 2
Copying prefix 0xac150101
Copying OIF: 2
[root@iLinux-Nilesh route]#

Routing table after route add program.

[root@iLinux-Nilesh route]# route -n
Kernel IP routing table
[root@iLinux-Nilesh route]#



Never mind..found the

Nilesh's picture

Never mind..found the problem.

Hello Asanga... I am

Anonymous's picture

Hello Asanga...

Please help me on this regard.
Thanks in advance...

/* Read message from kernel */
recv(sock_fd,nlh,size, 0);

rtp = (struct rtmsg*)NLMSG_DATA(nlh);

rtap =(struct rtattr*) RTM_RTA(rtp);
rtl = RTM_PAYLOAD(nlh);


case RTA_DST:

case RTA_SRC:
printf("\n received source address");


Getting the IPV6 Address of a Device via rtnetlink

saltorfer's picture


Greetings from Switzerland,

Re. Getting the IPV6 Address of a Device via rtnetlink

Asanga's picture



bzero(&local, sizeof(local));
local.nl_family = AF_NETLINK;
local.nl_pid = getpid();
printf("Error in sock bind\n");

bzero(&peer, sizeof(peer));
peer.nl_family = AF_NETLINK;

bzero(&msg_info, sizeof(msg_info));
msg_info.msg_name = (void *) &peer;
msg_info.msg_namelen = sizeof(peer);

bzero(&netlink_req, sizeof(netlink_req));

netlink_req.nlmsg_info.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
netlink_req.nlmsg_info.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
netlink_req.nlmsg_info.nlmsg_type = RTM_GETADDR;
netlink_req.nlmsg_info.nlmsg_pid = getpid();

netlink_req.ifaddrmsg_info.ifa_family = AF_INET6;

iov_info.iov_base = (void *) &netlink_req.nlmsg_info;
iov_info.iov_len = netlink_req.nlmsg_info.nlmsg_len;
msg_info.msg_iov = &iov_info;
msg_info.msg_iovlen = 1;

rtn = sendmsg(fd, &msg_info, 0);



Kind regards,

Getting route updates

Nagendra's picture


This document was really helpfull. Thanks a lot.

I have a question regarding receiving route updates from the kernel.


What I want is...

Your help in this regard will be appreciated.

Thanks and regards,

Nagendra KS.

re: Getting route updates

Asanga's picture


I added the statement


just after the statement

nlp = (struct nlmsghdr *) buf;


Kind regards,

Flush Cache

Mike CC's picture

It is possible to flush the route cache via rtnetlink sockets?

re: Flush Cache

Asanga's picture




Kind regards,

How to specify a NIC?

CC's picture

But some questions are still confusing me.


Is there a Windows-Version of NETLINK & RTNETLINK ?

thanks in advance

Re: How to specify a NIC?

Asanga's picture






> Is there a Windows-Version of NETLINK & RTNETLINK ?



Via gateway

Miguel's picture


This is the code i'm adding after the iface

rtl +=rtap->rta_len;


Re: Via gateway

Asanga's picture

Hello Miguel,

Here is the code to add the gateway to a route,

+ rtap->rta_len);
rtap->rta_type = RTA_GATEWAY;
inet_pton(AF_INET, gw,
rtl += rtap->rta_len;


Kind regards,



Learn More

Sponsored by Bit9

Linux Backup and Recovery Webinar



Learn More

Sponsored by Storix