Manipulating the Networking Environment Using RTNETLINK

How to use RTNETLINK to develop applications that control networking.

RTNETLINK is a simple, yet versatile way of manipulating the networking environment of a Linux host. User-space network protocol handlers are ideal candidates for using RTNETLINK. The advanced IP routing command suite, referred to as IPROUTE2, is based on RTNETLINK. More information about the different operations and flags of RTNETLINK can be found at NETLINK(7) and RTNETLINK(7).

The sample code for this article is available at


I sincerely thank Professor Carmelita Goerg.

Asanga Udugama ( is a researcher/software developer for ComNets, University of Bremen, Germany. He currently works on implementing and improving the IETF standards for mobility-related network layer protocols. He has a few reference implementations to his credit. At the moment, he is awaiting the arrival of his dream wheelchair (Meyra X3 with Servomatic).



Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

wireless link

Pranab's picture

Is there any way to monitor the wireless link up and down using rtnetlink ? If yes, what all the parameters required to change ?

Getting default gateway

donX's picture

Is it possible to get the default gateway with out having to create a route? I am trying to get the default gateways ip with out having to add/delete to the routing table.

Please let me know.. and Thank You for this article it was great!

double event found on netlink socket

Anonymous's picture

hi All,

I M new for netlink socket programming. I am developing simple application which inform me when ever any Interface is make up/down using if/up/down/config or wire out from Link plug. now problem is i got two packet for every if/up/down or wire out event.

I am not able to solve problem and don't understand why this things happen.

I m using "nl_groups = RTNLGRP_LINK" only.


Route add does not work.

Nilesh's picture

Using this tutorial, i crated a function to add the route, I believe I am populating all the necessary elements of the data structures. However, the route is getting added wrongly. For any kind of route, the function only add route with mask and gateway It points to the correct interface that i specify in RTA_OIF.

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;
rta->rta_len = sizeof(struct rtattr) + 4;

printf("Copying prefix 0x%08x\n", prefix);

bcopy(&prefix,(char *)rta+rta->rta_len,4);

rtl += rta->rta_len;

rta = (struct rtattr *)(((char *)rta) + rta->rta_len);

rta->rta_type = RTA_OIF;
rta->rta_len = sizeof(struct rtattr) + 4;

printf("Copying OIF: %d\n", oif);
bcopy(&oif, (char *)rta+sizeof(struct rtattr), 4);

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
Destination Gateway Genmask Flags Metric Ref Use Iface U 0 0 0 eth1 U 0 0 0 eth0 U 0 0 0 eth3 U 0 0 0 lo UG 0 0 0 eth0

Here is the sample run of the test program that uses this function.

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
Destination Gateway Genmask Flags Metric Ref Use Iface UH 0 0 0 eth0 <<<<< U 0 0 0 eth1 U 0 0 0 eth0 U 0 0 0 eth3 U 0 0 0 lo UG 0 0 0 eth0
[root@iLinux-Nilesh route]#

Any idea what is wrong? Function in test program is invoked as below.

rc = rtm_add_v4(addr.s_addr,len,RT_TABLE_MAIN,oif,RTPROT_STATIC,RTN_UNICAST,NULL);

Never mind..found the

Nilesh's picture

Never mind..found the problem.

Hello Asanga... I am

Anonymous's picture

Hello Asanga...
I am newbie to Linux. As far as u have googled i found only your material for a sample.With my understanding on ur illustration I have made the below module to get the destination address and the gateway address when i give "route add -host gw"
I get the gateway address as from the module. but i expect the gateway to be

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

/* Read message from kernel */
recv(sock_fd,nlh,size, 0);
printf(" Received message payload: %s\n",

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

rtap =(struct rtattr*) RTM_RTA(rtp);
rtl = RTM_PAYLOAD(nlh);
for(;RTA_OK(rtap,rtl);rtap = RTA_NEXT(rtap,rtl))

printf("\n gateway address is %s",gws);

case RTA_DST:
printf("\n destination address is %s",dsts);

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


Getting the IPV6 Address of a Device via rtnetlink

saltorfer's picture

Hi, I currently have the problem that i want to get the IPV6 Address of a device via rtnetlink. Your article was already very helpful, but I still cannot find out, which fields of struct ifaddrmsg I have to fill out if I pass it with a request so that i get the IP that I am looking for. I set ifa_family to AF_INET6 and ifa_index to the device that I am looking at. Nevertheless when parsing the "answer" buffer so to speak I get NLMSG_ERROR and nothing else. Well and there is the problem that the programm never does more than one iteration in while(1) but it also never leaves it .. well that is a different problem I guess. Still, I would like to know why you put the second break condition in there, is it not always true? You didn't even set nl_groups in your programm ?
Sorry for my bad English but it has been a frustrating day full of debugging.

Greetings from Switzerland,

Re. Getting the IPV6 Address of a Device via rtnetlink

Asanga's picture


Here is the request init part of a sample RTNETLINK program that shows the IPv6 address info of interfaces.

bzero(&local, sizeof(local));
local.nl_family = AF_NETLINK;
local.nl_pid = getpid();
if(bind(fd, (struct sockaddr*) &local, sizeof(local)) < 0) {
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);

If you require the whole code, look in my home page.

Re. second break; Usually the end of a returned message is indicated by a NLMSG_DONE. But for monitoring of routing table changes, this will not work. Since the example code in this article was common, that second break is also part of the loop.

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.
I have a process that waits for any routing table changes. It is able to get updates when ever a new route is added or deleted. It gets arround 52 bytes of data.

When I add a new route entry I get 52 bytes but, it fails to enter
"for(;NLMSG_OK(nlp, nll);nlp=NLMSG_NEXT(nlp, nll))" loop of read_reply() as given in this document and more over when I try to print "nlp->nlmsg_type" its always RTM_NEWROUTE even though I deleted a route entry in my previous operation.

What I want is...
1) When ever a new entry gets added read_reply() function should print the new entry that got added.
2) When ever a entry is deleted from the route table, it should print the entry that got deleted as well as nlp->nlmsg_type shud be RTM_DELROUTE so that I know that the netlink message I got is because of delete operation.

Your help in this regard will be appreciated.

Thanks and regards,

Nagendra KS.

re: Getting route updates

Asanga's picture


I added the statement

printf("Type %d\n", nlp->nlmsg_type);

just after the statement

nlp = (struct nlmsghdr *) buf;

in the mon_routing_table.c file and I see 25 (RTM_DELROUTE) for a route delete and 24 (RTM_ADDROUTE) for a route add.

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


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

As far as I know, there isn't any RTNETLINK command to flush the routing cache. But after looking at the source code of the "ip" command suit I found that they write a -1 to
/proc/sys/net/ipv4/route/flush to flush the routing cache.

Kind regards,

How to specify a NIC?

CC's picture

this article helps me to understand the way to implement a protocol.
But some questions are still confusing me.

If an application just wants to send message through a specified NIC ( e.g. the node has more than one NIC, like LAN, WLAN etc), how can the application just set this selectivly ?
Is it able to set up more than one NIC for sending/receiving at the same time, or it should be done in different threads ?

Is there a Windows-Version of NETLINK & RTNETLINK ?

thanks in advance

Re: How to specify a NIC?

Asanga's picture


>If an application just wants to send message through a specified NIC ( e.g. the node has more than one NIC, like LAN, WLAN etc), how can the application just set this selectivly ?

I assume that you are asking about sending IP packets over an interface. If that is the case, you must use INET type sockets to do this.

> Is it able to set up more than one NIC for sending/receiving at the same time, or it should be done in different threads ?

What interface a packet takes, is usually decided by the routing table, depending on the destination address of the packet. But I think INET sockets also has a facility to send packets from a given interface (thru sendmsg())

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

As far as I know, no (atleast up to XP)


Via gateway

Miguel's picture

I'm having problems adding a route via a gateway, i tried to add it but it simply wont work.

This is the code i'm adding after the iface

rtap= (struct rtattr *) (((char *)rtap) + sizeof(struct rtattr));
rtap->rta_len = sizeof (struct rtattr) + 4;
inet_pton(AF_INET, gw, ((char *)rtap) + sizeof (struct rtattr));
rtl +=rtap->rta_len;


Re: Via gateway

Asanga's picture

Hello Miguel,

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

rtap = (struct rtattr *) (((char *)rtap)
+ rtap->rta_len);
rtap->rta_type = RTA_GATEWAY;
rtap->rta_len = sizeof(struct rtattr) + 4;
inet_pton(AF_INET, gw,
((char *)rtap) + sizeof(struct rtattr));
rtl += rtap->rta_len;

Your code piece is almost the same except for the rta_len addition. If there is no problem here, also check whether you can add the same route entry that you are trying to add programatically using ip route add command. A frequent problem of adding gateways to routes is that the gateway should be reachable.

Kind regards,