I want to find the route of a packet in user space. I have dst ip and I want to read the kernel tables, so it will give me the result according to current ip route cfg. any way of doing that in C?
Asked
Active
Viewed 368 times
1
-
Yes, there is a way to do that in C. If you show what you've tried, and what problems you have with it, someone is bound to show you how to address the problem. – ryyker Jan 20 '20 at 13:07
-
What exactly do you want as a result? The next-hop IP address, the outgoing interface, a destination MAC address? – Ctx Jan 20 '20 at 13:15
-
in fact I want all of them, but mostly I want the outgoing interface index – roni bar yanai Jan 20 '20 at 13:18
2 Answers
2
You can do the following to get the interface index:
First, create a UDP socket to your destination:
int fd = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in in;
in.sin_family = AF_INET;
in.sin_port = htons(1234);
in.sin_addr.s_addr = inet_addr("1.2.3.4");
connect(fd, (struct sockaddr *)&in, sizeof(struct sockaddr_in));
Then, call getsockname()
to determine the interface addr of the outgoing interface for this socket:
int inlen = sizeof(in);
getsockname(fd, (struct sockaddr *)&in, &inlen);
Now, get all system interface structures and look for the correct interface address:
struct ifaddrs *ifa, *ifap;
getifaddrs(&ifa);
ifap = ifa;
char *ifname = NULL;
while (ifa) {
if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr ==
in.sin_addr.s_addr) {
ifname = strdup(ifa->ifa_name);
break;
}
ifa = ifa->ifa_next;
}
freeifaddrs(ifap);
Finally, get the interface index for the interface name:
struct ifreq iface;
strncpy(iface.ifr_name, interface, IFNAMSIZ);
iface.ifr_name[IFNAMSIZ-1] = 0;
int len = sizeof(iface);
ioctl(fd, SIOCGIFINDEX, &iface, &len);
int ifindex = iface.ifr_ifindex;
Looks a bit complicated, but is independent from netlink (which isn't much easier either).

Ctx
- 18,090
- 24
- 36
- 51
1
Asking the kernel via nlmsg looks legit and worked for me in the past.
I started off from this answer back then:

lnksz
- 421
- 3
- 15