]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
RFC 2131 is full of confusion regarding MTU it seems as the effective minimum MTU...
authorRoy Marples <roy@marples.name>
Fri, 2 Mar 2007 12:11:46 +0000 (12:11 +0000)
committerRoy Marples <roy@marples.name>
Fri, 2 Mar 2007 12:11:46 +0000 (12:11 +0000)
ChangeLog
Makefile
dhcp.c
dhcp.h
interface.c
interface.h

index 7dba477db706cf06fe5c0f88d38c6ee69585dc58..38a645e24e84ed7c2947ded8d014532da57ba20a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+dhcpcd-3.0.16
+RFC 2131 is full of confusion regarding MTU it seems as the effective minimum
+MTU is really 576 or DHCP requests stop working.
+
 dhcpcd-3.0.15
 Fix MTU length checking.
 We now request MTU from the DHCP server, and if given we set it.
index 3b48d27f7c413c4001291d0c8bedec038ab8c399..544e82598e77fd78aaadd0c6400378433c31b1eb 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 # Should work for both GNU make and BSD make
 
-VERSION = 3.0.15
+VERSION = 3.0.16
 
 CFLAGS ?= -O2 -pipe
 
diff --git a/dhcp.c b/dhcp.c
index a116ec1c4f016ad01712bbcc253c075968b25206..72b69deb46c89420936daf47d27441a00e87beae 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -123,7 +123,13 @@ size_t send_message (const interface_t *iface, const dhcp_t *dhcp,
     {
       *p++ = DHCP_MAXMESSAGESIZE;
       *p++ = 2;
-      sz = htons (sizeof (dhcpmessage_t));
+      sz = get_mtu (iface->name);
+      if (sz < MTU_MIN)
+       {
+         if (set_mtu (iface->name, MTU_MIN) == 0)
+           sz = MTU_MIN;
+       }
+      sz = htons (sz);
       memcpy (p, &sz, 2);
       p += 2;
     }
@@ -601,11 +607,12 @@ int parse_dhcpmessage (dhcp_t *dhcp, const dhcpmessage_t *message)
          break;
        case DHCP_MTU:
          GET_UINT16_H (dhcp->mtu);
-         /* Minimum legal mtu is 68 */
-         if (dhcp->mtu < 68)
+         /* Minimum legal mtu is 68 accoridng to RFC 2132.
+            In practise it's 576 (minimum maximum message size) */
+         if (dhcp->mtu < MTU_MIN)
            {
-             logger (LOG_ERR, "minimum legal MTU is 68");
-             dhcp->mtu = 68;
+             logger (LOG_ERR, "given MTU %d is too low, minium is %d", dhcp->mtu, MTU_MIN);
+             dhcp->mtu = MTU_MIN;
            }
          break;
 
diff --git a/dhcp.h b/dhcp.h
index 29a90b793055cbc2fb355ea1f56ed25d2dcfe17e..111b3ebaa6a5c8e9e31af96b37981f3e4d4fc857 100644 (file)
--- a/dhcp.h
+++ b/dhcp.h
@@ -33,6 +33,7 @@
 
 /* Max MTU - defines dhcp option length */
 #define MTU_MAX                        1500
+#define MTU_MIN                        576
 
 /* UDP port numbers for DHCP */
 #define DHCP_SERVER_PORT 67
@@ -163,7 +164,6 @@ typedef struct dhcp_t
 #define DHCP_OPTION_LEN                (MTU_MAX - DHCP_FIXED_LEN - DHCP_UDP_LEN \
                                 - DHCP_RESERVE_LEN)
 
-
 typedef struct dhcpmessage_t
 {
   unsigned char op;                            /* message type */
index 7b314a7d80c8f7f96351a3dce0f9bf544aafbecf..58c23156ef5d0a3ad447b337fcbb5c4625564a88 100644 (file)
@@ -55,6 +55,7 @@
 #include <unistd.h>
 
 #include "common.h"
+#include "dhcp.h"
 #include "interface.h"
 #include "logger.h"
 #include "pathnames.h"
@@ -230,6 +231,26 @@ interface_t *read_interface (const char *ifname, int metric)
     }
 #endif
 
+  strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+  if (ioctl(s, SIOCGIFMTU, &ifr) < 0)
+    {
+      logger (LOG_ERR, "ioctl SIOCGIFMTU: %s", strerror (errno));
+      close (s);
+      return NULL;
+    }
+  if (ifr.ifr_mtu < MTU_MIN)
+    {
+      logger (LOG_DEBUG, "MTU of %d is too low, setting to %d", ifr.ifr_mtu, MTU_MIN);
+      ifr.ifr_mtu = MTU_MIN;
+      strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+      if (ioctl(s, SIOCSIFMTU, &ifr) < 0)
+       {
+         logger (LOG_ERR, "ioctl SIOCSIFMTU,: %s", strerror (errno));
+         close (s);
+         return NULL;
+       }
+    }
+
   strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
   if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
     {
@@ -268,6 +289,32 @@ interface_t *read_interface (const char *ifname, int metric)
   return iface;
 }
 
+int get_mtu (const char *ifname)
+{
+  struct ifreq ifr;
+  int r;
+  int s;
+
+  if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
+    {
+      logger (LOG_ERR, "socket: %s", strerror (errno));
+      return (-1);
+    }
+
+  memset (&ifr, 0, sizeof (struct ifreq));
+  strcpy (ifr.ifr_name, ifname);
+  r = ioctl (s, SIOCGIFMTU, &ifr);
+  close (s);
+
+  if (r < 0)
+    {
+      logger (LOG_ERR, "ioctl SIOCGIFMTU: %s", strerror (errno));
+      return (-1);
+    }
+
+  return (ifr.ifr_mtu);
+}
+
 int set_mtu (const char *ifname, short int mtu)
 {
   struct ifreq ifr;
index 198c61d05fa0beefc044283f40f16d9d23841f2c..857eefbe56f73f421279dbb5f965821517dc86e3 100644 (file)
@@ -85,6 +85,7 @@ typedef struct interface_t
 void free_address (address_t *addresses);
 void free_route (route_t *routes);
 interface_t *read_interface (const char *ifname, int metric);
+int get_mtu (const char *ifname);
 int set_mtu (const char *ifname, short int mtu);
 
 int add_address (const char *ifname, struct in_addr address,