9

at the moment I do:

def get_inet_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.connect(('mysite.com', 80))
    return s.getsockname()[0]

This was based on: Finding local IP addresses using Python's stdlib

However, This looks a bit dubious. As far as I can tell, it opens a socket to mysite.com:80, and then returns the first address for that socket, assuming it to be an IPv4 address. This seems a bit dodgy... i dont think we can ever guaranteee that to be the case.

Thats my first question, is it safe? On an IPv6-enable server, could the IPv6 address ever be returned unexpectedly?

My second question, is how do I get the IPv6 address in a similar way. Im going to modify the function to take an optional ipv6 paramater.

Community
  • 1
  • 1
James Bennet
  • 213
  • 1
  • 4
  • 6

2 Answers2

7

The question is, do you just want to connect, or do you really want the address?

If you just want to connect, you can do

s = socket.create_connection(('mysite.com', 80))

and have the connection established.

However, if you are interested in the address, you can go one of these ways:

def get_ip_6(host, port=0):
    import socket
    # search only for the wanted v6 addresses
    result = socket.getaddrinfo(host, port, socket.AF_INET6)
    return result # or:
    return result[0][4][0] # just returns the first answer and only the address

or, to be closer to another, already presented solution:

def get_ip_6(host, port=0):
     # search for all addresses, but take only the v6 ones
     alladdr = socket.getaddrinfo(host,port)
     ip6 = filter(
         lambda x: x[0] == socket.AF_INET6, # means its ip6
         alladdr
     )
     # if you want just the sockaddr
     # return map(lambda x:x[4],ip6)
     return list(ip6)[0][4][0]
Community
  • 1
  • 1
glglgl
  • 89,107
  • 13
  • 149
  • 217
2

You should be using the function socket.getaddrinfo()

Example code to get IPv6

def get_ip_6(host,port=80):
    # discard the (family, socktype, proto, canonname) part of the tuple
    # and make sure the ips are unique
    alladdr = list(
        set(
            map(
                lambda x: x[4],
                socket.getaddrinfo(host,port)
            )
        )
    )
    ip6 = filter(
        lambda x: ':' in x[0], # means its ip6
        alladdr
    )
    return ip6
katharas
  • 401
  • 2
  • 6
  • I would find it better to filter for the address family field of the result, not for the textual represnetation of the returned address. See my answer. – glglgl Apr 29 '13 at 11:40
  • @glglgl Yes you're right, it was just a quick and dirty example. The point was mostly to redirect him to socket.getaddrinfo() documentation. – katharas May 14 '13 at 11:03