This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Cannot write to a tun interface file
Type: Stage:
Components: IO Versions: Python 3.5
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Rémy Léone, neologix, pitrou
Priority: normal Keywords:

Created on 2017-05-22 12:34 by Rémy Léone, last changed 2022-04-11 14:58 by admin.

Files
File name Uploaded Description Edit
simple_incorrect.py Rémy Léone, 2017-05-22 12:34
simple_incorrect.py Rémy Léone, 2017-05-22 15:36
Messages (7)
msg294143 - (view) Author: Rémy Léone (Rémy Léone) Date: 2017-05-22 12:34
I cannot write certain bytes object to a tun interface file. I've added a working and unworking example in the attached file.
I'm running on Ubuntu16.04 with Python 3.5.2
msg294151 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2017-05-22 15:01
Would you care to post the detailed error and traceback here?  Not everyone wants to set up a TUN interface to try to reproduce :-)
msg294152 - (view) Author: Rémy Léone (Rémy Léone) Date: 2017-05-22 15:06
Traceback (most recent call last):
  File "simple_incorrect.py", line 31, in <module>
    tun.write(incorrect_frame)
OSError: [Errno 22] Invalid argument
msg294154 - (view) Author: Rémy Léone (Rémy Léone) Date: 2017-05-22 15:11
The question I'm the most interested about is why depending on what the bytes object contains I get a different result. In one case the bytes are written fine to the TUN interface file descriptor and in the other case I get an Errno22. My assumption is that the bytes to write are completely opaque for Python.

My current workaround is mainly to start the bytes I want to send to my tun interface with a non-0 byte.
Something strange that I have also noticed using strace python simple_incorrect.py is that I get EINVAL errors in the second case while I didn't change the mode with which I open the tun.
msg294155 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2017-05-22 15:12
So basically the write() system call seems to be returning EINVAL.  Can I suggest the following steps:

1. try to reproduce using os.open() and os.write() instead of open() and write() (just to make sure something doesn't get in the way)

2. if it still fails, try to reproduce using an equivalent C snippet

If 2 fails as well, then this is a system issue and not a Python issue.  Otherwise, we'll have to find out how Python differs from C.
msg294156 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2017-05-22 15:19
I know nothing about TUN but you may simply be hitting this code path:
https://github.com/spotify/linux/blob/master/drivers/net/tun.c#L601-L614

Since:
>>> ('e'.encode()[0] & 0xf0) in (0x40, 0x60)
True
>>> ('é'.encode()[0] & 0xf0) in (0x40, 0x60)
False

writing 'é'.encode() will hit the EINVAL-returning path.  The bottom line is that TUN devices don't seem to support free-form data, but expect a certain format.
msg294158 - (view) Author: Rémy Léone (Rémy Léone) Date: 2017-05-22 15:36
I've tackle the 1. by replacing write/open with os.write/os.open. I still get :
$ python3 simple_incorrect.py
b'\xc3\xa9'
Traceback (most recent call last):
  File "simple_incorrect.py", line 32, in <module>
    os.write(tun, incorrect_frame)
OSError: [Errno 22] Invalid argument

I'm going to study more in depth the point you raised about tun.c
History
Date User Action Args
2022-04-11 14:58:46adminsetgithub: 74615
2017-05-22 15:36:01Rémy Léonesetfiles: + simple_incorrect.py

messages: + msg294158
2017-05-22 15:19:59pitrousetnosy: + neologix
messages: + msg294156
2017-05-22 15:12:40pitrousetmessages: + msg294155
2017-05-22 15:11:54Rémy Léonesetmessages: + msg294154
2017-05-22 15:06:04Rémy Léonesetmessages: + msg294152
2017-05-22 15:01:23pitrousetnosy: + pitrou
messages: + msg294151
2017-05-22 12:34:41Rémy Léonecreate