GamePad64 / tunio

MIT License
29 stars 7 forks source link

Unable to set MTU size in Windows 10 #68

Open PotatoCider opened 1 year ago

PotatoCider commented 1 year ago

Version: v0.3.0

MTU size stays at 65535 bytes even after setting MTU size via iface.handle().set_mtu(1024).unwrap();.

GamePad64 commented 1 year ago

What platform are you running?

PotatoCider commented 1 year ago

built for x86_64-pc-windows-gnu have not tested using x86_64-pc-windows-msvc

same issue on both Windows 10 & 11 wintun v0.14.1

teschmitt commented 1 year ago

This is probably not a problem of tunio or netconfig (where the employed set_mtu method resides). I've narrowed this problem down to a system call that presumably fails but returns an ok here.

I found that in my case, windows::Win32::NetworkManagement::IpHelper::SetIpInterfaceEntry returns an NTSTATUS(0x00000057). This should indicate that the call failed because of invalid parameters. The documentation on the underlying SetIpInterfaceEntry specifies when parameters are invalid:

An invalid parameter was passed to the function. This error is returned if a NULL pointer is passed in the Row parameter, the Family member of the MIB_IPINTERFACE_ROW pointed to by the Row parameter was not specified as AF_INET or AF_INET6, or both the InterfaceLuid or InterfaceIndex members of the MIB_IPINTERFACE_ROW pointed to by the Row parameter were unspecified.

My parameters are correct though. How do I know this? The exact same SetIpInterfaceEntry call during the second iteration of the for loop with the same arguments sets the MTU of the IPv6 interface successfully to the proper value. In this case although, the above call returns an NTSTATUS(0x00000000) so the behavior here is correct.

EDIT 2023-07-10: Although my conclusion is true – this is not a problem of tunio – my rationale was false. In the set_mtu method, the first GetIpInterfaceEntry call (for the IPv4 interface) fills the row struct with the currently observed configuration. With it, a SitePrefixLength of 64 is returned. This is an invalid value, since for an IPv4 interface, the SitePrefixLength can only be 32 max. The NlMtu field is then set to the user value and the altered row settings are supposed to get persisted back through the SetIpInterfaceEntry call. But this call fails exactly because the SitePrefixLength parameter has an illegal value. For the second call (for the IPv6 interface), the value is not a problem, since the max value here is 128.

This is a problem that has been already been addressed here and seems to be a bug in the Windows API. Other libraries have resorted to simply patching the returned value. This is probably also the only way to quickly fix this issue for tunio as well.