Browse code

Set the correct mtu on windows based systems

Signed-off-by: Christopher Schenk <cschenk@mail.uni-paderborn.de>
Acked-by: Selva Nair <selva.nair@gmail.com>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20200421154612.14140-1-cschenk@mail.uni-paderborn.de>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg19803.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>

Christopher Schenk authored on 2020/04/22 00:46:12
Showing 3 changed files
... ...
@@ -39,7 +39,8 @@ typedef enum {
39 39
     msg_del_block_dns,
40 40
     msg_register_dns,
41 41
     msg_enable_dhcp,
42
-    msg_register_ring_buffers
42
+    msg_register_ring_buffers,
43
+    msg_set_mtu
43 44
 } message_type_t;
44 45
 
45 46
 typedef struct {
... ...
@@ -127,4 +128,11 @@ typedef struct {
127 127
     HANDLE receive_tail_moved;
128 128
 } register_ring_buffers_message_t;
129 129
 
130
+typedef struct {
131
+    message_header_t header;
132
+    interface_t iface;
133
+    short family;
134
+    int mtu;
135
+} set_mtu_message_t;
136
+
130 137
 #endif /* ifndef OPENVPN_MSG_H_ */
... ...
@@ -73,6 +73,10 @@ static void netsh_ifconfig(const struct tuntap_options *to,
73 73
                            const in_addr_t netmask,
74 74
                            const unsigned int flags);
75 75
 
76
+static void windows_set_mtu(const int iface_index,
77
+                            const short family,
78
+                            const int mtu);
79
+
76 80
 static void netsh_set_dns6_servers(const struct in6_addr *addr_list,
77 81
                                    const int addr_len,
78 82
                                    const char *flex_name);
... ...
@@ -214,6 +218,47 @@ out:
214 214
     return ret;
215 215
 }
216 216
 
217
+static bool
218
+do_set_mtu_service(const struct tuntap *tt, const short family, const int mtu)
219
+{
220
+    DWORD len;
221
+    bool ret = false;
222
+    ack_message_t ack;
223
+    struct gc_arena gc = gc_new();
224
+    HANDLE pipe = tt->options.msg_channel;
225
+    const char *family_name = (family == AF_INET6) ? "IPv6" : "IPv4";
226
+    set_mtu_message_t mtu_msg = {
227
+        .header = {
228
+            msg_set_mtu,
229
+            sizeof(set_mtu_message_t),
230
+            0
231
+        },
232
+        .iface = {.index = tt->adapter_index,.name = tt->actual_name },
233
+        .mtu = mtu,
234
+        .family = family
235
+    };
236
+
237
+    if (!send_msg_iservice(pipe, &mtu_msg, sizeof(mtu_msg), &ack, "Set_mtu"))
238
+    {
239
+        goto out;
240
+    }
241
+
242
+    if (ack.error_number != NO_ERROR)
243
+    {
244
+        msg(M_NONFATAL, "TUN: setting %s mtu using service failed: %s [status=%u if_index=%d]",
245
+            family_name, strerror_win32(ack.error_number, &gc), ack.error_number, mtu_msg.iface.index);
246
+    }
247
+    else
248
+    {
249
+        msg(M_INFO, "%s MTU set to %d on interface %d using service", family_name, mtu, mtu_msg.iface.index);
250
+        ret = true;
251
+    }
252
+
253
+out:
254
+    gc_free(&gc);
255
+    return ret;
256
+}
257
+
217 258
 #endif /* ifdef _WIN32 */
218 259
 
219 260
 #ifdef TARGET_SOLARIS
... ...
@@ -1018,6 +1063,7 @@ do_ifconfig_ipv6(struct tuntap *tt, const char *ifname, int tun_mtu,
1018 1018
         do_address_service(true, AF_INET6, tt);
1019 1019
         add_route_connected_v6_net(tt, es);
1020 1020
         do_dns_service(true, AF_INET6, tt);
1021
+        do_set_mtu_service(tt, AF_INET6, tun_mtu);
1021 1022
     }
1022 1023
     else
1023 1024
     {
... ...
@@ -1035,6 +1081,7 @@ do_ifconfig_ipv6(struct tuntap *tt, const char *ifname, int tun_mtu,
1035 1035
         add_route_connected_v6_net(tt, es);
1036 1036
         /* set ipv6 dns servers if any are specified */
1037 1037
         netsh_set_dns6_servers(tt->options.dns6, tt->options.dns6_len, ifname);
1038
+        windows_set_mtu(tt->adapter_index, AF_INET6, tun_mtu);
1038 1039
     }
1039 1040
 #else /* platforms we have no IPv6 code for */
1040 1041
     msg(M_FATAL, "Sorry, but I don't know how to do IPv6 'ifconfig' commands on this operating system.  You should ifconfig your TUN/TAP device manually or use an --up script.");
... ...
@@ -1404,6 +1451,14 @@ do_ifconfig_ipv4(struct tuntap *tt, const char *ifname, int tun_mtu,
1404 1404
         netsh_ifconfig(&tt->options, ifname, tt->local,
1405 1405
                        tt->adapter_netmask, NI_IP_NETMASK|NI_OPTIONS);
1406 1406
     }
1407
+    if (tt->options.msg_channel)
1408
+    {
1409
+        do_set_mtu_service(tt, AF_INET, tun_mtu);
1410
+    }
1411
+    else
1412
+    {
1413
+        windows_set_mtu(tt->adapter_index, AF_INET, tun_mtu);
1414
+    }
1407 1415
 #else  /* if defined(TARGET_LINUX) */
1408 1416
     msg(M_FATAL, "Sorry, but I don't know how to do 'ifconfig' commands on this operating system.  You should ifconfig your TUN/TAP device manually or use an --up script.");
1409 1417
 #endif /* if defined(TARGET_LINUX) */
... ...
@@ -5432,6 +5487,40 @@ out:
5432 5432
     return ret;
5433 5433
 }
5434 5434
 
5435
+static void
5436
+windows_set_mtu(const int iface_index, const short family,
5437
+                const int mtu)
5438
+{
5439
+    DWORD err = 0;
5440
+    struct gc_arena gc = gc_new();
5441
+    MIB_IPINTERFACE_ROW ipiface;
5442
+    InitializeIpInterfaceEntry(&ipiface);
5443
+    const char *family_name = (family == AF_INET6) ? "IPv6" : "IPv4";
5444
+    ipiface.Family = family;
5445
+    ipiface.InterfaceIndex = iface_index;
5446
+    err = GetIpInterfaceEntry(&ipiface);
5447
+    if (err == NO_ERROR)
5448
+    {
5449
+        if (family == AF_INET)
5450
+        {
5451
+            ipiface.SitePrefixLength = 0;
5452
+        }
5453
+        ipiface.NlMtu = mtu;
5454
+        err = SetIpInterfaceEntry(&ipiface);
5455
+    }
5456
+
5457
+    if (err != NO_ERROR)
5458
+    {
5459
+        msg(M_WARN, "TUN: Setting %s mtu failed: %s [status=%u if_index=%d]",
5460
+            family_name, strerror_win32(err, &gc), err, iface_index);
5461
+    }
5462
+    else
5463
+    {
5464
+        msg(M_INFO, "Successfully set %s mtu on interface %d", family_name, iface_index);
5465
+    }
5466
+}
5467
+
5468
+
5435 5469
 /*
5436 5470
  * Return a TAP name for netsh commands.
5437 5471
  */
... ...
@@ -1286,6 +1286,29 @@ HandleRegisterRingBuffers(const register_ring_buffers_message_t *rrb, HANDLE ovp
1286 1286
     return err;
1287 1287
 }
1288 1288
 
1289
+static DWORD
1290
+HandleMTUMessage(const set_mtu_message_t *mtu)
1291
+{
1292
+    DWORD err = 0;
1293
+    MIB_IPINTERFACE_ROW ipiface;
1294
+    InitializeIpInterfaceEntry(&ipiface);
1295
+    ipiface.Family = mtu->family;
1296
+    ipiface.InterfaceIndex = mtu->iface.index;
1297
+    err = GetIpInterfaceEntry(&ipiface);
1298
+    if (err != NO_ERROR)
1299
+    {
1300
+        return err;
1301
+    }
1302
+    if (mtu->family == AF_INET)
1303
+    {
1304
+        ipiface.SitePrefixLength = 0;
1305
+    }
1306
+    ipiface.NlMtu = mtu->mtu;
1307
+
1308
+    err = SetIpInterfaceEntry(&ipiface);
1309
+    return err;
1310
+}
1311
+
1289 1312
 static VOID
1290 1313
 HandleMessage(HANDLE pipe, HANDLE ovpn_proc, ring_buffer_handles_t *ring_buffer_handles,
1291 1314
               DWORD bytes, DWORD count, LPHANDLE events, undo_lists_t *lists)
... ...
@@ -1300,6 +1323,7 @@ HandleMessage(HANDLE pipe, HANDLE ovpn_proc, ring_buffer_handles_t *ring_buffer_
1300 1300
         dns_cfg_message_t dns;
1301 1301
         enable_dhcp_message_t dhcp;
1302 1302
         register_ring_buffers_message_t rrb;
1303
+        set_mtu_message_t mtu;
1303 1304
     } msg;
1304 1305
     ack_message_t ack = {
1305 1306
         .header = {
... ...
@@ -1374,6 +1398,13 @@ HandleMessage(HANDLE pipe, HANDLE ovpn_proc, ring_buffer_handles_t *ring_buffer_
1374 1374
             }
1375 1375
             break;
1376 1376
 
1377
+        case msg_set_mtu:
1378
+            if (msg.header.size == sizeof(msg.mtu))
1379
+            {
1380
+                ack.error_number = HandleMTUMessage(&msg.mtu);
1381
+            }
1382
+            break;
1383
+
1377 1384
         default:
1378 1385
             ack.error_number = ERROR_MESSAGE_TYPE;
1379 1386
             MsgToEventLog(MSG_FLAGS_ERROR, TEXT("Unknown message type %d"), msg.header.type);