2

There may be several network interfaces on a server, e.g., lo, eth0, eth1

From the route table, I know that eth0 is connected to the default gateway. The address of the default gateway, for example, is 192.168.1.1. And the address of eth0 is, for example, 192.168.1.100.

How can I get the address "192.168.1.100"? Any approach is ok: Python, Shell, UNIX C API...

Currently I can only think of one way:

  1. Execute command "route" and get last line (default 192.168.1.1 0.0.0.0 ...)
  2. Execute command "ifconfig" and get the address list (127.0.0.1, 192.168.1.100, ...)
  3. Find the address which is in the same subnet with default gateway (192.168.1.1)
  4. Then we get address 192.168.1.100

Are there some better solutions?

PS: It has been suggested that we can call connect() on a udp socket, and then call getsockname() to get local address. However, it works only on part of the servers.

@EEAA

So this is my script:

route -n | awk '$1 == "0.0.0.0" { print $2 }' > gateway.tmp
ip -4 addr show | grep inet | awk '{ print $2 }' > addrs.tmp

The first line prints the default gateway:

10.1.40.1

The second line prints a list of interface addresses (in cidr notation):

127.0.0.1/8
10.1.46.122/21

Then I have to decide which network 10.1.40.1 belongs to. So I write a Python script:

import sys

def ip_to_binary(ip):
    bytes = ip.split(".")
    a = int(bytes[0])
    b = int(bytes[1])
    c = int(bytes[2])
    d = int(bytes[3])
    return "{0:08b}{1:08b}{2:08b}{3:08b}".format(a, b, c, d)

def mask_to_binary(bits):
    return "1" * bits + "0" * (32 - bits)

def binary_and(a, b):
    if len(a) == len(b):
        result = ""
        for i in range(0, len(a)):
            if a[i] == "1" and b[i] == "1":
                result += "1"
            else:
                result += "0"
        return result
    return None

def ip_in_net(ip, net_cidr_notation):
    net_addr, bits = net_cidr_notation.split("/")
    bin_mask = mask_to_binary(int(bits))
    bin_net = ip_to_binary(net_addr)
    bin_ip = ip_to_binary(ip)

    if binary_and(bin_ip, bin_mask) == binary_and(bin_net, bin_mask):
        return True
    return False

# usage: python autoaddr.py gateway_file addrs_file
gateway = open(sys.argv[1]).readline().strip()
addrs = open(sys.argv[2]).readlines()

for addr in addrs:
    if ip_in_net(gateway, addr):
        print addr.split("/")[0]

To avoid extra dependencies, I didnot use libraries like netaddr and ipaddress. Finally, I have to add the Python script to Shell script:

python autoaddr.py gateway.tmp addrs.tmp > auto.tmp
rm -f gateway.tmp
rm -f addrs.tmp

Now I have a file auto.tmp containing the automatically generated address:

10.1.46.122
1

Why not something like this:

$ ip -4 addr show eth0 | grep inet | awk '{ print $2 }'
192.168.1.100/24

FYI, ifconfig is deprecated. You should start using the various ip commands in place of what you used ifconfig for previously.

  • This is something similar to what I want, but not exactly. – F32 Jul 30 '15 at 4:28
  • There may be multiple interfaces, eth1, eth2, ... and I have to also query the routing table – F32 Jul 30 '15 at 4:29
  • So write yourself a bash script to collect the info you want. We're not a script writing service. I've given you a start, so now take and run with it. – EEAA Jul 30 '15 at 4:30
  • If you're looking for more than the IP, you need to re-write your question. As it stands, that's the only thing you say you're looking for. – EEAA Jul 30 '15 at 4:32
  • I have added my full script. It works, but is rather dirty, isn't it? Are there some better solutions? – F32 Jul 30 '15 at 6:48

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.