[GSoC 2023] VPN Support Project Update #4

Blog post by Pairisto on Thu, 2023-07-27 22:13

The Weekly Problem

So we are just past the midway point for GSoC and last update I told you guys that I had a working (albeit somewhat buggy) TUN Driver working. I had gotten great feedback from Pulkomandy, Axel, and Korli to help with a more efficient driver and to make it more human-readable because it made no sense the way I had written it. I have very good news to bring to everyone in that all of the 3 main problems that I talked about last time are all solved! I think most of them got solved after I fully understood creating semaphores and imposed execution order by adding a write semaphore. While this new code made the driver much more efficient and less error-prone, there were two new errors that popped up during testing:

  1. If one or the other side was up (not both) and said side was then sending data, it would say that something was sent and not received (taking ping for example) and deadlock due to how now the write semaphore needs to be acquired instead of being able to freely write to it for the first time.
  2. If sending and receiving were happening and then the side receiving crashed, the other side accessing the driver would be stuck at receiving when it came time to and if you started the other side again by receiving or writing the driver would be deadlocked.

Now it took me a second to remember something about the first problem when it came to TUN driver behavior (at least it’s like this on Linux) being that when a TUN/TAP interface comes up, you cannot send data across if there is no other end. You just get an error back. You can see on my patchset 14 I use a “busy waiting” solution which is never truly a great solution but it still worked before I remembered the right behavior to implement which kind of happens in patchset 15. I say kind of because here I switched up the synchronization method from a semaphore to a condition variable since I realized that using semaphores here to impose execution order caused a lot of confusion when reading the code. Knowing there were 2 semaphores per open instance that had to be kept track of looked really confusing. This new synchronization method also solved the second problem which, as I was trying to solve while using semaphores, was starting to get messy so this just looked like a simpler solution that still passed all the tests that I have. Thanks to x512 over on the IRC for all the help!

Looking Forward

Since I believe the driver is in a much better state than it was a week ago, I have started to look onward from it and go into OpenVPN. I already started on a fork of the source code here where I have made some changes to how the program should run ifconfig and currently working on how the program should handle the route command. However, that is one of the low-priority problems that I am running into with OpenVPN as at the moment most tests pass but one of the last ones ./openvpn --remote 64.233.160.0 --verb 9 --ping 1 --dev tun which started to show signs of trouble as it would write to the driver and then hang. Normally if you run the command like this: ./openvpn --remote 64.233.160.0 --verb 9 --ping 1 --dev null it will run fine as it will keep sending pings. I a not sure if this is a driver issue, an interface issue, or an OpenVPN issue as I am still debugging the problem but I have reached out to the OpenVPN community (haven’t heard back from them in a bit) for learning more about that specific command and checking anything that might be wrong on the OpenVPN side while I focus more on anything wrong with the driver though it is turning into focusing on both. One path I think might be an issue is called with IOCTL being involved to set up the driver’s netmask, hardware address, etc. which is not implemented into the driver since the interface and driver are 2 separate things. Looking more forward, given that I have OpenVPN done, then I want to start possibly converging the interface into the driver like how it’s done in most other Unix-based OSs. That change would follow the relatively loose standard of how a TUN driver should be made since there is always more functionality to add.

Thank you for reading my post!