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.
Related
I've decided to try to request an IP using scapy. I am able to send out a discover and receive an offer in the variable ansD. Unfortunately I'm having trouble accessing the field that contains the offered IP address which should be ansD[BOOTP].yiaddr . It tells me that the field does not exist. I have looked around and have seen similar issues but cannot seem to understand why I can access normal packet fields, but fail to do so with BOOTP fields.
receivedIP = 0
conf.checkIPaddr = False
fam,hw = get_if_raw_hwaddr(conf.iface)
dhcp_discover = Ether(dst="ff:ff:ff:ff:ff:ff")/IP(src="0.0.0.0",dst="255.255.255.255")/UDP(sport=68,dport=67)/BOOTP(chaddr=hw)/DHCP(options=[("message-type","discover"),"end"])
ansD,unans = srp(dhcp_discover, multi=True)
if True:
dhcp_request=Ether(dst="ff:ff:ff:ff:ff:ff")/IP(src="0.0.0.0",dst="255.255.255.255")/UDP(sport=68,dport=67)/BOOTP(chaddr=hw,yiaddr=ansD[BOOTP].yiaddr)/DHCP(options=[("message-type","request"),"end"])
ansR, unans = srp(dhcp_request,multi=True)
Object Error 'list' object has no attribute 'yiaddr'
I figured it out not two seconds after posting but hopefully this helps others in the future.
I used srp() instead of srp1(), the former returns multiple packets so I would need to index the specific packet I wanted to look at ansD[0][BOOTP].yiaddr . I have since changed my code to use srp1 instead since this is a DHCP request expecting only one specific "Offer" reply from the DHCP server.
Fixed code below
import sys
from scapy.all import *
receivedIP = 0
conf.checkIPaddr = False
fam,hw = get_if_raw_hwaddr(conf.iface)
dhcp_discover=Ether(dst="ff:ff:ff:ff:ff:ff")/IP(src="0.0.0.0",dst="255.255.255.255")/UDP(sport=68,dport=67)/BOOTP(chaddr=hw)/DHCP(options=[("message-type","discover"),"end"])
ansD = srp1(dhcp_discover, multi=True)
if True:
//Request using the IP the server offered us in ansD[BOOTP].yiaddr
dhcp_request = Ether(dst="ff:ff:ff:ff:ff:ff")/IP(src="0.0.0.0",dst="255.255.255.255")/UDP(sport=68,dport=67)/BOOTP(chaddr=hw,yiaddr=ansD[BOOTP].yiaddr)/DHCP(options=[("message-type","request"),"end"])
ansR, unans = srp(dhcp_request,multi=True)
ansR.summary()
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)
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
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()
I have my web page in python, I am able to get the IP address of the user, who will be accessing our web page, we want to get the mac address of the user's PC, is it possible in python, we are using Linux PC, we want to get it on Linux.
I have a small, signed Java Applet, which requires Java 6 runtime on the remote computer to do this. It uses the getHardwareAddress() method on NetworkInterface to obtain the MAC address. I use javascript to access a method in the applet that calls this and returns a JSON object containing the address. This gets stuffed into a hidden field in the form and posted with the rest of the fields.
from Active code
#!/usr/bin/env python
import ctypes
import socket
import struct
def get_macaddress(host):
""" Returns the MAC address of a network host, requires >= WIN2K. """
# Check for api availability
try:
SendARP = ctypes.windll.Iphlpapi.SendARP
except:
raise NotImplementedError('Usage only on Windows 2000 and above')
# Doesn't work with loopbacks, but let's try and help.
if host == '127.0.0.1' or host.lower() == 'localhost':
host = socket.gethostname()
# gethostbyname blocks, so use it wisely.
try:
inetaddr = ctypes.windll.wsock32.inet_addr(host)
if inetaddr in (0, -1):
raise Exception
except:
hostip = socket.gethostbyname(host)
inetaddr = ctypes.windll.wsock32.inet_addr(hostip)
buffer = ctypes.c_buffer(6)
addlen = ctypes.c_ulong(ctypes.sizeof(buffer))
if SendARP(inetaddr, 0, ctypes.byref(buffer), ctypes.byref(addlen)) != 0:
raise WindowsError('Retreival of mac address(%s) - failed' % host)
# Convert binary data into a string.
macaddr = ''
for intval in struct.unpack('BBBBBB', buffer):
if intval > 15:
replacestr = '0x'
else:
replacestr = 'x'
macaddr = ''.join([macaddr, hex(intval).replace(replacestr, '')])
return macaddr.upper()
if __name__ == '__main__':
print 'Your mac address is %s' % get_macaddress('localhost')
All you can access is what the user sends to you.
MAC address is not part of that data.
The dpkt package was already mentioned on SO. It allows for parsing TCP/IP packets. I have not yet used it for your case, though.