how can one check if variable contains DNS name or IP address in python ?
This will work.
import socket
host = "localhost"
if socket.gethostbyname(host) == host:
print "It's an IP"
else:
print "It's a host name"
You can use re module of Python to check if the contents of the variable is a ip address.
Example for the ip address :
import re
my_ip = "192.168.1.1"
is_valid = re.match("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", my_ip)
if is_valid:
print "%s is a valid ip address" % my_ip
Example for a hostname :
import re
my_hostname = "testhostname"
is_valid = re.match("^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$", my_hostname)
if is_valid:
print "%s is a valid hostname" % my_hostname
I'd check out the answer for this SO question:
Regular expression to match DNS hostname or IP Address?
The main point is to take those two regexs and OR them together to get the desired result.
print 'ip' if s.split('.')[-1].isdigit() else 'domain name'
This does not verify if either one is well-formed.
Related
I have the following code:
while True:
try:
HOST = input(float(('Enter host IP'))
except ValueError:
print('Error. That is not a valid IP address.')
continue
I require the user to input an IP address. I wanted to set an error so that if he uses a letter he gets an error. How can I do that and why isn't my code working?
Try something like this
while True:
try:
HOST = input('Enter host IP: ')
if len(HOST.split(".")) != 4:
raise ValueError
for char in HOST:
if char not in "0123456789.":
raise ValueError
except ValueError:
print('Error. That is not a valid IP address.')
continue
else:
break
There is no need for the try/except. You just need an IP validation. This code should be working.
import re
while True:
HOST = input("Enter IP adress: ")
if re.match(
r"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$",
HOST,
):
print(f"{inp} is valid IP adress")
break
else:
print("Enter valid IP adress")
I will begin by pointing out a few problems with your submitted code. First of all, your code will never exit the while loop, since you have provided no break out. Secondly, a valid IP address takes the form of something along the lines of 192.168.2.10 for IPV4 or "2001:0db8:0a0b:12f0:0000:0000:0000:0001" for IPV6, and which can never be interpreted as a float, so you will always generate a value error response. In order to validate an IP addfress correctly checkout the following check if a string matches an IP address pattern in python?.
import ipaddress
Host = None
while True:
try:
Host = ipaddress.ip_address(input('Enter host IP'))
break
except:
print('Error. That is not a valid IP address.')
continue
Do you know if there is any pattern/logic that could be used to distinguish between an IP address and an FQDN in python? I have a script that process user input which could be ip or fqdn and i would like to to ip validation checks if ip, and no validation check in case it is fqdn.
addy = "1.2.3.4"
a = addy.split('.')
match = re.search('^(([0-9]|[0-9][0-9]|[0-9][0-9][0-9]))$', a[0])
if match is not None:
if is_valid_ipv4(addy) == True:
# code continues
what is case addy is fqdn? I wish to call is_valid_ipv4 if input string is only an IP address. Do I need a pattern for FQDN? How to distinguish between IP and FQDN?
Python knows about IP addresses. Meanwhile, this answer gives a pretty good regexp for validating FQDNs.
import ipaddress
import re
addy = "192.0.2.1"
fqdn_re = re.compile('(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{1,63}(?<!-)\.)+[a-zA-Z]{2,63}\.?$)')
try:
ip_addy = ipaddress.ip_address(addy)
if ip_addy.version == 4:
print("IPv4 address")
elif ip_addy.version == 6:
print("IPv6 address")
except ValueError:
if fqdn_re.search(addy):
print("FQDN address")
else:
print("Invalid address")
Personally, I'd use regex. In Python you can use the re package.
Write a pattern for each (IP and FQDN) and see which gets a match (re.match()).
Here are some useful links:
Bulding a regex for an IP address
Test your regex patterns
I am trying to get the ip address and broadcast address of my machine and after a lot of research netifaces works fine but the problem is ip address prints properly but when i wanted the broadcast address it gives the docker broadcast address as well as the 'lo' broadcast address but i wanted only 'lo' broadcast address and i am not sure how to get only the broadcast address associated with 'lo'. Please help me with some ideas. Also i am not sure that i have mentioned that wanted only 'lo' broadcast address but it also gives me dockers broadcast address as well.
Code:
import netifaces
interfaces=netifaces.interfaces()
for i in interfaces:
if i=='lo':
continue
iface= netifaces.ifaddresses(i).get(netifaces.AF_INET)
if iface != None:
for j in iface:
bd=(j['broadcast'])
print(bd)
Output:
192.169.x.x('lo'-broadcast)
175.17.x.x ('docker'-broadcast)
Why are you trying to get lo? That is typically local loopback and will always have 127.0.0.1. I just made this in a CentOS environment. If you are using Windows, just tweek the "ifconfig adapter-name" string... probably use "ipconfig /all" or something.
#! /usr/bin/python
import os
import re
def get_ip_data(ether_adapter):
ip_list = []
ip_data = os.popen("ifconfig " + ether_adapter)
for line in ip_data:
match1 = re.search(r'inet\s+(\d+.\d+.\d+.\d+)', line)
match2 = re.search(r'broadcast\s+(\d+.\d+.\d+.\d+)', line)
if match1:
ip = match1.group(1)
ip_list.append(ip)
if match2:
bcast = match2.group(1)
ip_list.append(bcast)
return ip_list
if __name__ == "__main__":
ethernet_card = "virbr0"
inet_list = get_ip_data(ethernet_card)
for element in inet_list:
print(element)
[root#server Desktop]# ./ip.py
192.168.122.1
192.168.122.255
In the client "virbr0" is the name of my wifi card. Just replace that with your wifi card or ethernet card name as a string.
I'm doing some simple experiments using Python socket, where I've a HOSTNAME which resolves with two IP addresses but when I use, socket.gethostbyname('demo.sample.com') I'm getting only one IP address. Why is it showing that way? Is there any other way I can get multiple IP addresses?
EDIT - 1
I got it guys, instead of gethostbyname('demo.sample.com') I tried gethostbyname_ex('demo.sample.com') It gives the result as I expected.
From the documentation it is visible that:
gethostbyname returns only a single IPv4 address. And to cite: See gethostbyname_ex() for a more complete interface.
gethostbyname_ex will return multiple IPv4 address, but check out the usage. And to cite: gethostbyname_ex() does not support IPv6 name resolution, and getaddrinfo() should be used instead for IPv4/v6 dual stack support.
getaddrinfo will return all IPv4 and IPv6 addresses, but check out the usage.
I found a solution here, which returns the internal network IP:
import socket
def ip_addr(hostIP=None):
if hostIP is None or hostIP == 'auto':
hostIP = 'ip'
if hostIP == 'dns':
hostIP = socket.getfqdn()
elif hostIP == 'ip':
from socket import gaierror
try:
hostIP = socket.gethostbyname(socket.getfqdn())
except gaierror:
logger.warn('gethostbyname(socket.getfqdn()) failed... trying on hostname()')
hostIP = socket.gethostbyname(socket.gethostname())
if hostIP.startswith("127."):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# doesn't have to be reachable
s.connect(('10.255.255.255', 1))
hostIP = s.getsockname()[0]
return hostIP
if __name__ == '__main__':
print('%s' % ip_addr())
Are there any existing libraries to parse a string as an ipv4 or ipv6 address, or at least identify whether a string is an IP address (of either sort)?
Yes, there is ipaddr module, that can you help to check if a string is a IPv4/IPv6 address, and to detect its version.
import ipaddr
import sys
try:
ip = ipaddr.IPAddress(sys.argv[1])
print '%s is a correct IP%s address.' % (ip, ip.version)
except ValueError:
print 'address/netmask is invalid: %s' % sys.argv[1]
except:
print 'Usage : %s ip' % sys.argv[0]
But this is not a standard module, so it is not always possible to use it.
You also try using the standard socket module:
import socket
try:
socket.inet_aton(addr)
print "ipv4 address"
except socket.error:
print "not ipv4 address"
For IPv6 addresses you must use socket.inet_pton(socket.AF_INET6, address).
I also want to note, that inet_aton will try to convert (and really convert it) addresses like 10, 127 and so on, which do not look like IP addresses.
For IPv4, you can use
socket.inet_aton(some_string)
If it throws an exception, some_string is not a valid ip address
For IPv6, you can use:
socket.inet_pton(socket.AF_INET6, some_string)
Again, it throws an exception, if some_string is not a valid address.
IPv4 + IPv6 solution relying only on standard library. Returns 4 or 6 or raises ValueError.
try:
# Python 3.3+
import ipaddress
def ip_kind(addr):
return ipaddress.ip_address(addr).version
except ImportError:
# Fallback
import socket
def ip_kind(addr):
try:
socket.inet_aton(addr)
return 4
except socket.error: pass
try:
socket.inet_pton(socket.AF_INET6, addr)
return 6
except socket.error: pass
raise ValueError(addr)
You can use the netaddr library. It has valid_ipv4/valid_ipv6 methods:
import netaddr
if netaddr.valid_ipv4(str_ip) is True:
print("IP is IPv4")
else:
if netaddr.valid_ipv6(str_ip) is True:
print("IP is IPv6")
Try
apt-get install python-ipaddr
or get the source code from here
I prefer ip_interface because it handles situations both with and without prefix mask, for example, both "10.1.1.1/24" as well as simply "10.1.1.1". Needless to say, works for both v4 as well as v6
from ipaddress import ip_interface
ip_interface("10.1.1.1/24").ip
ip_interface("10.1.1.1/24").ip.version
ip_interface("10.1.1.1").ip
ip_interface("10.1.1.1").ip.version
ipaddr -- Google's IP address manipulation package.
Note that a proposal to include a revised version of the package in the Python standard library has recently been accepted (see PEP 3144).
If you know for sure that the address is valid and only trying to decide whether it is ipv4 or ipv6, wouldn't it be sufficient to do just:
if ":" in address:
print("Ipv6")
else:
print("Ipv4")