11use std:: {
22 collections:: HashMap ,
3+ ffi:: OsStr ,
34 net:: IpAddr ,
5+ os:: windows:: ffi:: OsStrExt ,
46 str:: FromStr ,
57 sync:: { LazyLock , Mutex } ,
68} ;
@@ -10,12 +12,17 @@ use thiserror::Error;
1012use windows:: {
1113 Win32 :: {
1214 Foundation :: { ERROR_BUFFER_OVERFLOW , NO_ERROR } ,
13- NetworkManagement :: IpHelper :: {
14- DNS_INTERFACE_SETTINGS , DNS_INTERFACE_SETTINGS_VERSION1 , DNS_SETTING_IPV6 ,
15- DNS_SETTING_NAMESERVER , GAA_FLAG_INCLUDE_PREFIX , GetAdaptersAddresses ,
16- IP_ADAPTER_ADDRESSES_LH , SetInterfaceDnsSettings ,
15+ NetworkManagement :: {
16+ IpHelper :: {
17+ ConvertInterfaceGuidToLuid , DNS_INTERFACE_SETTINGS ,
18+ DNS_INTERFACE_SETTINGS_VERSION1 , DNS_SETTING_IPV6 , DNS_SETTING_NAMESERVER ,
19+ GAA_FLAG_INCLUDE_PREFIX , GetAdaptersAddresses , GetIpInterfaceEntry ,
20+ IP_ADAPTER_ADDRESSES_LH , InitializeIpInterfaceEntry , MIB_IPINTERFACE_ROW ,
21+ SetInterfaceDnsSettings , SetIpInterfaceEntry ,
22+ } ,
23+ Ndis :: NET_LUID_LH ,
1724 } ,
18- Networking :: WinSock :: AF_UNSPEC ,
25+ Networking :: WinSock :: { ADDRESS_FAMILY , AF_INET , AF_INET6 , AF_UNSPEC } ,
1926 System :: Com :: CLSIDFromString ,
2027 } ,
2128 core:: { GUID , PCSTR , PCWSTR , PSTR } ,
@@ -136,6 +143,55 @@ fn get_adapter_guid(adapter_name: &str) -> Result<GUID, WindowsError> {
136143 guid. ok_or_else ( || WindowsError :: AdapterNotFound ( adapter_name. to_string ( ) ) )
137144}
138145
146+ /// Sets both IPv4 and IPv6 MTU on specified interface.
147+ fn set_interface_mtu ( interface_name : & str , mtu : u32 ) -> Result < ( ) , WindowsError > {
148+ debug ! ( "Setting interface {interface_name} MTU to {mtu}" ) ;
149+ let guid = get_adapter_guid ( interface_name) ?;
150+
151+ // Convert interface GUID to LUID.
152+ let mut luid = NET_LUID_LH :: default ( ) ;
153+ let res = unsafe { ConvertInterfaceGuidToLuid ( & guid, & mut luid) } ;
154+ if res. 0 != 0 {
155+ error ! (
156+ "ConvertInterfaceGuidToLuid call failed, error value: {}" ,
157+ res. 0
158+ ) ;
159+ return Err ( WindowsError :: NonZeroReturnValue ( res. 0 ) ) ;
160+ }
161+
162+ // Helper function, sets MTU for given IP family.
163+ fn set_mtu_for_family ( luid : NET_LUID_LH , family : u16 , mtu : u32 ) -> Result < ( ) , WindowsError > {
164+ // InitializeIpInterfaceEntry has to be called before get/set operations.
165+ let mut row = MIB_IPINTERFACE_ROW :: default ( ) ;
166+ unsafe { InitializeIpInterfaceEntry ( & mut row) } ;
167+
168+ // Load current configuration.
169+ row. InterfaceLuid = luid;
170+ row. Family = ADDRESS_FAMILY ( family) ;
171+ let res = unsafe { GetIpInterfaceEntry ( & mut row) } ;
172+ if res. 0 != 0 {
173+ error ! ( "GetIpInterfaceEntry call failed, error value: {}" , res. 0 ) ;
174+ return Err ( WindowsError :: NonZeroReturnValue ( res. 0 ) ) ;
175+ }
176+
177+ // Modify the configuration and apply.
178+ row. NlMtu = mtu;
179+ let res = unsafe { SetIpInterfaceEntry ( & mut row) } ;
180+ if res. 0 != 0 {
181+ error ! ( "SetIpInterfaceEntry call failed, error value: {}" , res. 0 ) ;
182+ return Err ( WindowsError :: NonZeroReturnValue ( res. 0 ) ) ;
183+ }
184+ Ok ( ( ) )
185+ }
186+
187+ // Set MTU for both IP addr families.
188+ set_mtu_for_family ( luid, AF_INET . 0 , mtu) ?;
189+ set_mtu_for_family ( luid, AF_INET6 . 0 , mtu) ?;
190+
191+ info ! ( "Set interface {interface_name} MTU to {mtu}" ) ;
192+ Ok ( ( ) )
193+ }
194+
139195impl From < wireguard_nt:: WireguardPeer > for Peer {
140196 fn from ( peer : wireguard_nt:: WireguardPeer ) -> Self {
141197 Self {
@@ -173,7 +229,7 @@ impl From<wireguard_nt::WireguardInterface> for Host {
173229
174230/// Converts an str to wide (u16), null-terminated
175231fn str_to_wide_null_terminated ( s : & str ) -> Vec < u16 > {
176- s . encode_utf16 ( ) . chain ( std :: iter :: once ( 0 ) ) . collect ( )
232+ OsStr :: new ( s ) . encode_wide ( ) . chain ( Some ( 0 ) ) . collect ( )
177233}
178234
179235/// Manages interfaces created with Windows kernel using https://git.zx2c4.com/wireguard-nt.
@@ -272,7 +328,14 @@ impl WireguardInterfaceApi for WGApi<Kernel> {
272328 . set_default_route ( & addresses, & interface)
273329 . map_err ( WindowsError :: from) ?;
274330
275- // Bring the adapter up
331+ // Set MTU
332+ if let Some ( mtu) = config. mtu {
333+ set_interface_mtu ( & self . ifname , mtu) ?;
334+ // Turn it off and on again.
335+ adapter. down ( ) . map_err ( WindowsError :: from) ?;
336+ }
337+
338+ // Bring the adapter up.
276339 debug ! ( "Bringing up adapter {}" , self . ifname) ;
277340 adapter. up ( ) . map_err ( WindowsError :: from) ?;
278341
0 commit comments