I was working on a mini module to have low level network interface access for my university assignmets (not that this is an actual assignment, just to clarify) in python. The actual assignment was done in C, but after that I decided to get some practice with ctypes and started the lib, targeting Linux and Python 2.7.
I already know that Python 3.3 exposes a lot of the functionality I've tried to cover, and that it already has a fcntl.ioctl module since arround version 2.3 or so (it does not really matter the exact version, just that it is present in 2.7), but this task was meant for learning.
The issue I ran into is very simple. I've got the following classes defined, based on the layout of the C counterparts( for the sake of clarity, bear with the long snippet ):
class struct_ifmap(Structure):
_fields_ = [
('mem_start', c_ulong),
('mem_end', c_ulong),
('base_addr', c_ushort),
('irq', c_ubyte),
('dma', c_ubyte),
('port', c_ubyte),]
class union_ifreq_anon(Union):
_fields_ = [
('ifr_addr', struct_sockaddr),
('ifr_dstaddr', struct_sockaddr),
('ifr_broadaddr', struct_sockaddr),
('ifr_netmask', struct_sockaddr),
('ifr_hwaddr', struct_sockaddr),
('ifr_flags', c_short),
('ifr_ifindex', c_int),
('ifr_metric', c_int),
('ifr_mtu', c_int),
('ifr_map', struct_ifmap),
('ifr_slave', c_char),
('ifr_newname', c_char),
('ifr_data', c_char_p),
('raw', c_short * 15),]
class struct_ifreq(Structure):
__IFNAMSIZ = 16
_anonymous_ = [
('u'),]
_fields_ = [
('ifr_name', c_char * __IFNAMSIZ),
('u', union_ifreq_anon),]
And the following function:
def _getfahwdraddr(name):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
socket.IPPROTO_IP)
ifr = struct_ifreq()
ifr.ifr_name = name
result = _libc.ioctl(sock.fileno(), 0x8927, pointer(ifr))
if result != 0:
raise OSError(get_errno())
return ''.join(['%02x:' % pair for pair in \
ifr.ifr_hwaddr.sa_data[0:6]])[:-1]
The output that this gives is -6c:39:-1b:XX:XX:XX, wich does not correspond with the real MAC, that is 94:39:e5:XX:XX:XX. One clue may be that some elements are correct, but as you can see, the output is just wrong. I can not figure why.
Surprisingly, I found a similar question in SO that aims to do almost the same, but uses packed structures, and python's own ioctl. It just works: Getting MAC Address. Still, my problem is how to correctly represent and use ctype Structures.