bat-serjo / PyIface

Python module to control network interfaces.
GNU General Public License v3.0
21 stars 10 forks source link

Can't read out IP address #5

Closed Frostlock closed 7 years ago

Frostlock commented 7 years ago

I can read out the interfaces but if I want to get the addr property I get an error message. Here is a minimal example in the python console:

>>> import pyiface
>>> pyiface.getIfaces()[0].addr
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/pyiface/iface.py", line 291, in addr
    ifr = self.__newIfreqWithName()
  File "/usr/local/lib/python2.7/dist-packages/pyiface/iface.py", line 181, in __newIfreqWithName
    ifr.ifr_name = self._name
TypeError: expected c_ubyte_Array_16 instance, got str

Any thoughts on what is going on? :) Thanks!

petri commented 7 years ago

I can confirm this on Debian stable, Python 2.7.

petri commented 7 years ago

Easy fix. Just replace the:

 ifr.ifr_name = self._name

with:

ifr.ifr_name = (c_ubyte*IFNAMSIZ) (*bytearray(self._name))

That's how it's done elsewhere in the same module, anyway. For what it's worth, it might actually be better to use:

ifr.ifr_name = (c_ubyte*IFNAMSIZ).from_buffer_copy(self._name)

(assuming the interface name is always a regular string rather than unicode - I don't know if it always is)

For reasoning, see http://stackoverflow.com/questions/21483482/efficient-way-to-convert-string-to-ctypes-c-ubyte-array-in-python, especially the chosen answer by eryksun.

EDIT: the above second alternative does not work, the name has to be padded thus:

ifr.ifr_name = (c_ubyte*IFNAMSIZ).from_buffer_copy(self._name + (IFNAMSIZ-len(self._name))*'\0')

Which probably eats any performance benefits of the approach. Of course, we don't need to worry about performance here anyway, though.

petri commented 7 years ago

A PR submitted; @bat-serjo, think you can merge and make a release?