Get all IP addresses associated with a host - python

I'm trying to write some code that can get all the IP addresses associated with a given hostname.
This is what I have so far:
def getips(hostname):
try:
result = socket.getaddrinfo(hostname, None, socket.AF_INET,\
socket.SOCK_DGRAM, socket.IPPROTO_IP, socket.AI_CANONNAME)
list = [x[4][0] for x in result]
return list
except Exception, err:
print "error"
return ""
ips = getips('bbc.co.uk')
print ips
The problem is, sometimes it returns all 4 IPs associated with the specific host in this example, sometimes it returns just one. Is there any way to do this in Python so it consistently returns all the IPs associated with a host?

getaddrinfo() calls the resolver library on your host to lookup IP addresses for any given host. There is no special magic in python that can force it to get a different set of results than what the resolver shows.
For e.g if you run strace on your python script, you will notice that the resolver is invoked:
open("/lib/x86_64-linux-gnu/libresolv.so.2", O_RDONLY|O_CLOEXEC) = 3

Related

Check if IP is in network on Python3

I am trying to run a routine on two lists, sourced from MySQL queries - one contains CIDR networks and the other contains IP addresses. I am trying to compare entries in the IP list to see whether they are in the networks described by the CIDR list, and act on those that are not.
I am trying to use the netaddr module but this doesn't appear to be implemented on Python3 yet?
I have also tried to use ipaddress but I can't seem to get them to compare correctly. Using ipaddress I have the following code:
networks = (('1.1.6.0/20',), ('2.8.2.0/19',), ('7.2.2.0/19',), ('2.2.0.0/19',))
ips = ((8888, 'customer', b'2.8.4.64', '8888*200'),(8888, 'customer', b'1.1.6.3', '8888*201'), (8888, 'customer', b'122.223.159.3', '8888*202'))
straglers = list()
for ip in ips:
exclude = 0
for network in networks:
subnet = ip_network(network[0])
if ip_address(ip[2]) in subnet:
exclude = 1
if exclude == 0:
straglers.append([ip[3],ip[2],ip[1]]) # extension, customer_ip, company
As things stand the code gives a value error as follows: ValueError: b'82.148.47.64' does not appear to be an IPv4 or IPv6 address
I have tried converting ip[2] to an utf-8 string but this makes no difference.
What you are describing as a list is actually a tuple.
First, when I ran your code I did not receive the error you are getting
ValueError: b'82.148.47.64' does not appear to be an IPv4 or IPv6 address
Instead I received the following
raise ValueError('%s has host bits set' % self)
ValueError: 1.1.6.0/20 has host bits set
Is this the error your are actually receiving? If so, this is how to properly correct it.
Referenced from ipaddress module Defining Networks:
By default, attempting to create a network object with host bits set will result in ValueError being raised. To request that the additional bits instead be coerced to zero, the flag strict=False can be passed to the constructor:
This is because the host bits are set and will need to be coerced to zero, as the documentation states above. Pass the following flag strict=False to the constructor.
For example.
subnet = ip_network(network[0], strict=False)
Also, in your ips contained in your tuple need only to be formatted to a string.
For example.
ips = ((8888, 'customer', '2.8.4.64', '8888*200')
OR the following will be presented to you.
'ValueError: b'2.8.4.64' does not appear to be an IPv4 or IPv6 address'
The full working code.
from ipaddress import ip_network, ip_address
networks = (('1.1.6.0/20',), ('2.8.2.0/19',), ('7.2.2.0/19',), ('2.2.0.0/19',))
ips = ((8888, 'customer', b'2.8.4.64', '8888*200'),(8888, 'customer', b'1.1.6.3', '8888*201'), (8888, 'customer', b'122.223.159.3', '8888*202'))
straglers = list()
for ip in ips:
exclude = 0
for network in networks:
subnet = ip_network(network[0], strict=False)
print(ip_address(ip[2].decode('utf-8')))
print(subnet)
if ip_address(ip[2].decode('utf-8')) in subnet:
exclude = 1
if exclude == 0:
straglers.append([ip[3],ip[2],ip[1]]) # extension, customer_ip, company
print(straglers)

Finding all the websites which are on a particular hostname

I did find this function on stackoverflow which extract hostname, aliaslist, and ipaddrlist,
but how can I make a function which take a hostname and search all the websites associated with it (hosted by it)?
>>> import socket
>>> def get_ips_for_host(host):
try:
ips = socket.gethostbyname_ex(host)
except socket.gaierror:
ips=[]
return ips
>>> ips = get_ips_for_host('www.slowtravelmagazine.com')
>>> print(repr(ips))
('ext-cust.squarespace.com', ['www.slowtravelmagazine.com'],
['198.185.159.144', '198.185.159.145', '198.49.23.144',
'198.49.23.145'])
You can't. At least not with a built in function. You would need a datasource that contains all websites with their associated IP addresses.
There are probably some providers out there that have an API for this.

Getting IP address of the beagleboard using python

SIOCGIFADDR = 0x8915
def getIpAddr(iface = 'eth0'):
ifreq = struct.pack('16sH14s', iface, socket.AF_INET, '\x00'*14)
try:
res = fcntl.ioctl(sock, SIOCGIFADDR, ifreq)
except:
return None
ip = struct.unpack('16sH2x4s8x', res)[2]
return socket.inet_ntoa(ip)
At each step what are the return values of the functions?
And, what is SIOCGIFADDR?
Also, why [2] has been used following the unpack() function?
SIOCGIFADDR : is stands for get internet interface address means 'eth0'.
This is CPU macro which is written at address 0x8915.
You cant take access of that cpu address so you have to go through pack and unpack function using parameters
"16sH2x4s8x"
IP address which u want from machine it have 4 fields like "192.168.5.20"
so that (4*4) 16 is required likewise search more fields of pack unpack functions.

Fabric Assign Hosts Using a List Variable

I know I can assign hosts with fabric by doing this:
env.hosts = ['host1', 'host2']
But can I do this?
myList = ['host1', 'host2']
env.hosts = myList
I am getting a list of 'public_dns_name's using Boto (from Amazon AWS) and then want to run commands on those servers. The server list can be dynamic so I need to be able to assign the hosts environment variable rather than statically. Can anyone suggest a solution?
myHosts = []
for i in myInstances:
publicDnsAddress = i.public_dns_name
myHosts.append(i.public_dns_name)
print ("public dns address: " + publicDnsAddress)
print ("myHosts = " + str(myHosts))
env.hosts=myHosts
env.user='myUser'
run("/scripts/remote_script.py")
I get this error:
No hosts found. Please specify (single) host string for connection:
If the host names were bad I would expect at least a connection error rather than a message saying it could find no hosts. Granted I may be calling this thing wrong but then again, that is why I am asking for help.
When dynamically setting hosts within the code, I've needed to use this with settings pattern:
user = 'root'
hosts = ['server1', 'server2']
for host in hosts:
with settings(user=user, host_string=host):
run(whatever_my_command_is)

Determine IP address of CONNECTED interface (linux) in python

On my linux machine, 1 of 3 network interfaces may be actually connected to the internet. I need to get the IP address of the currently connected interface, keeping in mind that my other 2 interfaces may be assigned IP addresses, just not be connected.
I can just ping a website through each of my interfaces to determine which one has connectivity, but I'd like to get this faster than waiting for a ping time out. And I'd like to not have to rely on an external website being up.
Update:
All my interfaces may have ip addresses and gateways. This is for an embedded device. So we allow the user to choose between say eth0 and eth1. But if there's no connection on the interface that the user tells us to use, we fall back to say eth2 which (in theory) will always work.
So what I need to do is first check if the user's selection is connected and if so return that IP. Otherwise I need to get the ip of eth2. I can get the IPs of the interfaces just fine, it's just determining which one is actually connected.
If the default gateway for the system is reliable, then grab that from the output from route -n the line that contains " UG " (note the spaces) will also contain the IP of the gateway and interface name of the active interface.
the solution is here : http://code.activestate.com/recipes/439093-get-names-of-all-up-network-interfaces-linux-only/
import fcntl
import array
import struct
import socket
import platform
"""
global constants. If you don't like 'em here,
move 'em inside the function definition.
"""
SIOCGIFCONF = 0x8912
MAXBYTES = 8096
def localifs():
"""
Used to get a list of the up interfaces and associated IP addresses
on this machine (linux only).
Returns:
List of interface tuples. Each tuple consists of
(interface name, interface IP)
"""
global SIOCGIFCONF
global MAXBYTES
arch = platform.architecture()[0]
# I really don't know what to call these right now
var1 = -1
var2 = -1
if arch == '32bit':
var1 = 32
var2 = 32
elif arch == '64bit':
var1 = 16
var2 = 40
else:
raise OSError("Unknown architecture: %s" % arch)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
names = array.array('B', '\0' * MAXBYTES)
outbytes = struct.unpack('iL', fcntl.ioctl(
sock.fileno(),
SIOCGIFCONF,
struct.pack('iL', MAXBYTES, names.buffer_info()[0])
))[0]
namestr = names.tostring()
return [(namestr[i:i+var1].split('\0', 1)[0], socket.inet_ntoa(namestr[i+20:i+24])) \
for i in xrange(0, outbytes, var2)]
print localifs()

Categories

Resources