3

How to get interface name from IPv4 ip address using only filesystem like /proc, /dev, /sys and bash? Is this possible without using the commands (such as ip, ifconfig, etc.)? I am also not able to use any packages or install any tools.

Edit: The reason for this is I am trying to get host's interface names and ip addresses from within a Docker container. The container is mounted with host's root and has access to host's filesystem. However, since the container is in a separate namespace, ip commands (and other similar command such as ifconfig) will only return the container's network. Hence, I believe the only way of getting the host's interface names and ip addresses is through the host's root (/hostroot/proc, /hostroot/sys, etc.). Note that I cannot have the --net=host flag when starting the container (which tells the container to use the host's net namespace).

I tried finding all my network interface IP addresses (IPv4) from the /proc/net/fib_trie file. I read at https://regexit.com/3-ways-to-get-your-ip-on-a-linux-system/ which basically says that I can do cat /proc/net/fib_trie | grep -B 1 "32 host LOCAL" to find the IP addresses. I also see in https://stackoverflow.com/a/42082822 , that we can filter the fib_trie by pattern matching the string "32 host" to get the local network interface addresses. After getting the IP addresses from the above method (using the /proc/net/fib_trie), I try to match those IP address with the "destination" IP address in /proc/net/route to get the network interface name. However, my /proc/net/route contains multiple entry for some interfaces (such as enp0s3). For example, there are two enp0s3 entries with different IP addresss ("Destination column). Moreover, the network interfaces in route file does have ip close to what is indicated by the ip command but not exactly.

Is there a better way of getting the network interface name after getting the IP address from fib_trie?

Output I need will be all the host's network interface name and corresponding IPv4 IP addresses.

Community
  • 1
  • 1

1 Answers1

2

I think you have sufficient information there. The /proc/net/route file doesn't really list addresses. It's supposed to tell you how to route packets. But you can glean information about the interfaces from it. On my system (ubuntu 14 so different interface name format but otherwise should be similar), it shows this:

Iface   Destination Gateway     Flags   RefCnt  Use Metric  Mask        MTU Window  IRTT
eth0    00000000    0100A8C0    0003    0   0   0   00000000    0   0   0
eth0    0000A8C0    00000000    0001    0   0   1   00FFFFFF    0   0   0
eth1    0028A8C0    00000000    0001    0   0   1   00FFFFFF    0   0   0

The destination and mask fields are in hexadecimal -- and byte-reversed on little-endian machine -- and give you the range of the network. Interpretation is:

  • Anything destined for the 192.168.0.0/24 network (0000A8C0 + 00FFFFFF) goes to eth0 with no gateway needed (in other words, it's on the same subnet as this machine).
  • Anything destined for 192.168.40.0/24 (0028A8C0 + 00FFFFFF) goes to eth1 with no gateway needed.
  • Packets destined for any other address (00000000 + 00000000) go to the default gateway 192.168.0.1.
    (Not sure; it's possible that the extra flag bit or the "metric" value in this line marks this as a default gateway. But in any case, if it doesn't have a non-zero mask or is in the 0.0.0.0 address range, it's not going to be useful for routing in the real world.)

From this I can infer that my system has IP addresses in the 192.168.0.0/24 and 192.168.40.0/24 networks. The output from the grep command on /proc/net/fib_trie shows on my system:

           |-- 127.0.0.1
              /32 host LOCAL
           |-- 192.168.0.104
              /32 host LOCAL
           |-- 192.168.40.129
              /32 host LOCAL

So that makes it clear that my local IP addresses are 192.168.0.104 (eth0) and 192.168.40.129 (eth1). (We can ignore 127.0.0.1; it's always the loopback interface.)

Gil Hamilton
  • 11,973
  • 28
  • 51
  • I did some more researching and came up with something very close to what you mentioned. First, we can grep for the pair of addresses in fib_trie for both "/32 link" and "/32 host" under the same branch. Second, match the address of "/32 link" to the 'destination' address in /proc/net/route. Lastly, the interface name in /proc/net/route of the matched row from step 2 is the interface name of the "/32 host" address from step 1. Is this procedure, especially matching the "/32 link" to the 'destination' address in /proc/net/route, for getting the network interface name correct? – Maytas Monsereenusorn Mar 31 '17 at 07:33
  • I don't really see what additional info you are getting from the `/32 link` lines. The netmask info from `/proc/net/route` (`00FFFFFF` in my example) tells you the netmask is 255.255.255.0 (== /24). And the destination field gives you the "base network address" (in this case, all but the final tuple of the address). Combining that with the `/32 host` address from `/proc/net/fib_trie` already gives you a unique answer to which interface each address serves as well as its subnet range. – Gil Hamilton Mar 31 '17 at 16:02
  • What I found (I am not sure if this will always hold true) but from the `/proc/net/fib_trie` for example one of my branch has 10.0.2.0 for /32 link and corresponding 10.0.2.15 for /32 host. I then see in my `/proc/net/route` I have a row with Iface=enp0s3 and Destination=0002000A (10.0.2.0). I see that 10.0.2.15 for /32 host gotten above actually does not match with any of my Ifaces's destination. However, 10.0.2.0 for /32 link matches with enp0s3's destination (10.0.2.0). Thus, I can conclude that the pair of IP from fib_trie belongs to enp0s3. (enp0s3 has IP 10.0.2.15/24 from ip addr show) – Maytas Monsereenusorn Mar 31 '17 at 19:02
  • The route table already tells you about the subnets on your box (Destination + Mask); each is associated with an interface. The fib_trie "/32 Host" entries tell you your IP addresses. You then just need to figure out *which* subnet each IP address falls into to find the interface. For each subnet entry from the route table, test to see if the IP fits within the subnet: In other words, does IP_Address & Mask == Destination (where `&` is bitwise-and). If so, you've found the matching interface. 10.0.2.15 in hex (byte-flipped) is 0F02000A. (0F02000A & 00FFFFFF) == 0002000A => matches enp0s3 – Gil Hamilton Mar 31 '17 at 20:00
  • In case it's not clear, I'm not saying you can't use the /32 Link entries. I just don't see that they add any information you don't already have from the route entries. – Gil Hamilton Mar 31 '17 at 20:02
  • Ahhh...I see. That's better since we do less parsing of the `/proc/net/fib_trie` Just making sure, when we find the list of IP from the `/proc/net/fib_trie` such as 10.0.2.15 where in hex (byte-flipped) is 0F02000A. We can find the corresponding interface name by using the subnet mask (00FFFFFF) and Destination (0002000A) as you mentioned. And both subnet mask and Destination is from the `/proc/net/route` correct? – Maytas Monsereenusorn Mar 31 '17 at 21:12
  • Yes. The mask and destination are from the route file. You'll have to convert those into binary (with `scanf(%x)` or whatever your language uses) and the IP address into binary (say, with `inet_pton`). – Gil Hamilton Mar 31 '17 at 23:08
  • Btw. is it possible to also get the "scope" of the IPv4 addresses? This can normally be retrieved from "ip -o addr show" after the word "scope". The values are "global", "link", "site", "compat", "host", and "unknown". As mentioned earlier, I only have access to filesystem (/proc and /sys, etc.) and bash in Linux. – Maytas Monsereenusorn Apr 07 '17 at 19:07
  • I think that can be determined from the address itself. See https://en.wikipedia.org/wiki/IPv4#Addressing and https://en.wikipedia.org/wiki/IPv6_address#Address_scopes and the answers to this question: http://stackoverflow.com/q/11632284/1076479 – Gil Hamilton Apr 07 '17 at 22:30