Search code examples
pythonsocketsioctlnetwork-interfacefcntl

Sending IOCTL Call to Network Driver using Python


I would like to send an IOCTL call from a Python application to a fake network interface I have running in Ubuntu 12.04. I know that I can open a socket and bind it to the network that the fake network interface is governing, and then use fcntl.ioctl(socket, IOC_COMMAND_NUM, some_struct) to send an IOCTL call. But, this seems to use a different network interface than I need it to. So, my question is, how can I ensure that a specific network interface is used? And, it seems like a lot of trouble to open a socket just to send an IOCTL call, so is there anyway to bypass that step? Below is some sample Python code that behaves as mentioned above.

>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> sock.bind(("192.168.0.1",0))
>>> fcntl.ioctl(sock,IOC_COMMAND_NUM,some_struct)
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
IOError: [Errno 25] Inappropriate ioctl for device

# This proves that it is sending the IOCTL to a different interface because my
# interface automatically returns success for any IOCTL call. 

Below is the output of ifconfig myDummyNetInter.

myDummyNetInter0 Link encap:Ethernet  HWaddr e2:44:46:d5:79:3e  
      inet addr:192.168.0.1  Bcast:192.168.0.255  Mask:255.255.255.0
      inet6 addr: fe80::e044:46ff:fed5:793e/64 Scope:Link
      UP BROADCAST RUNNING NOARP  MTU:1500  Metric:1
      RX packets:0 errors:0 dropped:0 overruns:0 frame:0
      TX packets:24 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:0 
      RX bytes:0 (0.0 B)  TX bytes:2682 (2.6 KB)

If it helps, I do have another application written in C++ using this network interface without any problems. (Including IOCTL calls.)

Thanks, I appreciate any and all help.


Solution

  • While this doesn't necessarily answer all of my questions, I was able to find a solution. The IOCTL call is a bit different than I had expected. The first thing I needed to fix was using the correct IOCTL number. Unlike character drivers, network drivers can only use a certain range (starting at 0x89F0) for custom IOCTLs. The other thing I had to do was to put an ifreq struct as the third argument of the IOCTL call. The ifreq struct has an ifr_name member that is used to select the specific network interface to interact with. These two fixes allowed me to communicate with my driver flawlessly.