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()
Related
Unsure how to phrase this, as I am new to Python.
Basically, I have this method in Python (below) that is scanning for devices available on my network. The Python code returns only 6 devices, and not the one I am searching for (Roku)
def scanner(self):
"""
Method that scans the network for available IP addresses.
"""
if len(self.ip) == 0:
network = '192.168.1.0/24'
else:
network = self.ip + '/24'
print("Scanning please wait...")
nm = nmap.PortScanner()
nm.scan(hosts=network, arguments='-sn')
host_list = [(x, nm[x]['status']['state']) for x in nm.all_hosts()]
for item in nm.all_hosts():
print(item)
for host, status in host_list:
self.ip_addresses.append(host)
self.choose_address()
When I use sudo nmap -sn 192.168.1.0/24 in my terminal, I get back 9 devices, including the Roku. Does anyone have any insight into why this doesn't want to work for me?
I've been working on hid omnikey 5325 cl and trying to get the ATR value. I'm using pcscd and pyscard library on Ubuntu. System automatically gets the ATR using T0 protocol but I need RAW return. On windows using helloprox or omnikey's official software I can get what I need, but on ubuntu even though I've change the protocol but ATR does not change.
here is the code I use:
class PrintObserver(CardObserver):
"""A simple card observer that is notified
when cards are inserted/removed from the system and
prints the list of cards
"""
def update(self, observable, actions):
(addedcards, removedcards) = actions
for card in addedcards:
card.connection=card.createConnection()
card.connection.connect(protocol=CardConnection.RAW_protocol)
binary_atr=bin(int(toHexString(card.connection.getATR()).replace(" ",""), 16))
binary_atr=binary_atr[len(binary_atr)-24:len(binary_atr)-1]
print int(binary_atr,2)
for card in removedcards:
print "-Removed: ", toHexString(card.atr)
if __name__ == '__main__':
cardmonitor = CardMonitor()
cardobserver = PrintObserver()
cardmonitor.addObserver(cardobserver)
#Get Ports
config=ConfigParser.ConfigParser()
config.read('../config.ini')
Read_Port=int(config.get('CardReaderSocketPorts','Read',0))
Write_Port=int(config.get('CardReaderSocketPorts','Write',0))
# Initialise socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_address = ('localhost', Read_Port)
return_address = ('localhost', Write_Port)
sock.bind(server_address)
while 1:
message, address = sock.recvfrom(4096)
if message:
parsed_json=json.loads(message)
#Single Line
if parsed_json['set'].upper()=="Stop":
sock.sendto('{"success":"True"}',return_address)
break
# don't forget to remove observer, or the
# monitor will poll forever...
cardmonitor.deleteObserver(cardobserver)
Some considerations, which may be helpful, even if they don't add to a full answer:
You are working with contactless cards or tags
These tags have no ATR, but depending on the protocol something like ATQB or ATS, which is completely differently structured.
PCSC is a dated software concept, which strictly requires an ATR
So contactless reader manufacturers have to invent an ATR, based on the information they get from the card
What your software receives as "ATR" is the result of this invention.
Omnikey apparently uses the Windows registry to control the invention process, which is obviously a non-portable approach.
So my advice would be, to contact the Omnikey support, how to proceed from Linux. According to my experience they are cooperative.
After contacting the Omnikey support, the problem is solved.
As in developer guide I was looking for the config file "/etc/cmrfid.ini" to change the prox format. The file name was changed into "/etc/Omnikey.ini"
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.
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
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.