Fastest way to check IP address version - python

I have a large set of strings which I already know it holds an IP address and I want to determine if it's IPv4 or IPv6. Currently I'm checking whether the string contains a colon:
version = 4
if ':' in ip_string:
version = 6
Is there a faster way to determine the IP version, given that we already know it's an IP address. Is there any possibility that the above simple check can return the wrong result (for example is it possible to have an IPv6 address without a colon)?

Use ipaddress in python to check the version.
Below is the example-
import ipaddress
#str1='10.10.10.2/24'
str1 = '2b11::327a:7b00/120'
[address, netmask] = str1.split('/')
ip_ver = ipaddress.ip_address(str(address))
if ip_ver.version == 4:
print('IPv4')
else:
print('IPv6')
Output:
IPv6
Note: Tested in Python 3.7.2

Related

How to remove/exclude unwanted objects from a list in python

Hi I am trying to get the IP of every interface on my machine using netifaces in python. I am still new to python and working my way through some concepts but it seems like I can query every NIC at once and then put the results into a list the problem is my end goal is to ask the user which network to work on and I want to exclude everything that returns 'No IP addr'.
I have already tried a few different methods including removing strings from the list and that didnt work or only adding IP addresses objects but im pretty sure im not doing it properly since it still errors out. Any help is appreciated.
import os
import socket
from netifaces import interfaces, ifaddresses, AF_INET
def get_self_IP():
for ifaceName in interfaces():
addresses = []
possibilities = [i['addr'] for i in ifaddresses(ifaceName).setdefault(AF_INET, [{'addr':'No IP addr'}] )]
print(' '.join(possibilities))
for i in possibilities:
if isinstance(i, ifaddress.ipaddress): # if i is an IP address
addresses.append(i)
print(addresses)
Also I have two lists now because ive changed it a few times to troubleshoot but if I can keep it as one list and only .append the IPs to it while its gathering IPs rather than have to do an entire separate list with a separate for or if loop it would be ideal but I do not know another way unfortunately.
Not sure if this is what you want, but:
I changed the function to:
def get_self_IP():
addresses = []
for ifaceName in interfaces():
ifaddresses_list = ifaddresses(ifaceName)
possibilities = [i['addr'] for i in ifaddresses_list.setdefault(AF_INET, [{'addr': 'No IP addr'}])]
for i in possibilities:
if ifaddresses_list[2][0]['addr'] != "No IP addr":
addresses.append(i)
print(addresses)
The ifaddresses(ifaceName) returns a dictionary which apparently the key 2 contains the IP address in the index 0 with the key 'addr', which in case the IP doesn't exist the value is No IP addr. In that the if checks if that is not the case and then adds the IP address to the addresses list.
If I didn't understand what you want clearly, please answer with more details :)

Trying to replace last 2 octets of ip address

I have the following ip address "192.168.2.65"
Is there a way to convert the last 2 octets to 0.
I found the following, but it only lets me replace the last one, i need to replace the last 2.
ip = 192.168.2.65
output='.'.join(ip.split('.')[:-1]+["0"])
print(output)
which gives me 192.168.2.0 and i would like to be 192.168.0.0
Index -1 means the last index. If you want to change two, change your index to -2.
output='.'.join(ip.split('.')[:-2]+["0", "0"])
You could also use a regex based approach here:
ip = "192.168.2.65"
output = re.sub(r'\.\d+\.\d+$', '.0.0', ip)
print(output) # prints 192.168.0.0
Dependant on the logic you are trying to apply.. if you are simply wanting to modify a string, the other answers are correct.
However, if you are looking to get the network address for the subnet an address resides in, you should handle the addresses correctly and use the ipaddress module.
This will assist in calculating the correct network & broadcast addresses, and allow you to check inclusions in networks etc.
import ipaddress
interface = IPv4Interface('192.168.2.35/255.255.0.0')
print(interface.network)
#192.168.0.0/16
print(interface.network.network_address)
#192.168.0.0
print(interface.network.broadcast_address)
#192.168.255.255

How to check an IP address is within a predefined list in python

Providing that I have this list which contains a number IP addresses:
IpAddresses = ["192.168.0.1","192.168.0.2","192.168.0.3","192.168.0.4"]
Then after receiving a packet I want to check if its source address is included in the predefined list IpAddresses
data, address = rxsocket.recvfrom(4096)
I have tried two alternatives, but both didn't work:
First:
if (address in IpAddresses):
do something
Then, I tried to convert address into string before making the comparison:
str_address = str(address)
if (str_address in IpAddresses):
do something
I am not familiar with python syntax, so please could you show me how to do this.
if address[0] in IpAddresses:
since the address object appears as a tuple only the 0th index appears in your list so you should check for its existence (also you can usually skip the parenthesis on an if statement unless it makes the if statement less readable)

CIDR subnet calculation and python ipcalc

I am questioning the results of the ipcalc module (ipcalc) for Python (it seems that netaddr may be a better choice).
Let's take 192.168.1.25/30 as an example. In binary, the last octet is 00011001 AND 11111100 = 00011000, so I get 192.168.1.24 as the Network ID and the range 192.168.1.24 - 192.168.1.27.
Using ipcalc, when I specify
subnet = ipcalc.Network('192.168.1.25/30')
for x in subnet: print x
The output is
192.168.1.25
192.168.1.26
192.168.1.27
192.168.1.28
I am not understanding the inconsistency. When using CIDR notation, it seems that specifying both 192.168.1.24/30 and 192.168.1.25/30 (or .26/30 or .27/30) refer to the same subnet.
Is that correct? Is this just a bug in the ipcalc module?
There is an open bug for this at the moment: No way to resolve IP + Netmask to Network Object
And an earlier bug report that discuss the matter: Strange subnet calculations
But they have also added a function called network to get the network address from an IP. From the manual:
>>> localnet = Network('127.128.99.3/8')
>>> print localnet.network()
127.0.0.0
The manual specifically says that the constructor Network should take a network address as its first argument, not any IP in the network. Rather confusing if you ask me (especially since the above code block breaks that condition). I would at least read the code for the module before using it.
It's correct the subnet is 192.168.1.24/30 so the ips 192.168.1.24 to 192.168.1.27 make part of this network.

Python IP Check

Given the range xxx.xxx.xxx.(195-223)
Is that correct to write it in xxx.xxx.xxx.196/29 and check whether an IP is in the given network by doing
from ipaddr import IP, CIDR
#if IP('xxx.xxx.xxx.xxx') in IP('xxx.xxx.xxx.196/29') or
#if IP('xxx.xxx.xxx.xxx') in CIDR('xxx.xxx.xxx.196/29')
I didn't see IP in ipaddr, only IPAddress.
May be like this?
from ipaddr import IPAdddress, IPNetwork
if IPAddress('10.0.0.195') in IPNetwork('10.0.0.196/29'):
pass
I haven't used the ipaddr module, but note that /29 means that your network mask is 255.255.255.248 and that you only have the latest 3 bits to address 2^3 = 8 different hosts in your network ranging from xxx.xxx.xxx.248 to xxx.xxx.xxx.255. That's outside of the range you want to check.
For more information, please have a look at the subnetwork wikipedia page.

Categories