From: Roy Marples Date: Fri, 2 Mar 2007 12:11:46 +0000 (+0000) Subject: RFC 2131 is full of confusion regarding MTU it seems as the effective minimum MTU... X-Git-Tag: v3.2.3~301 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=70689e9f9f9f8393a6b7e64cfe3007ea9e01769f;p=thirdparty%2Fdhcpcd.git RFC 2131 is full of confusion regarding MTU it seems as the effective minimum MTU is really 576 or DHCP requests stop working. --- diff --git a/ChangeLog b/ChangeLog index 7dba477d..38a645e2 100644 --- 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. diff --git a/Makefile b/Makefile index 3b48d27f..544e8259 100644 --- 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 a116ec1c..72b69deb 100644 --- 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 29a90b79..111b3eba 100644 --- 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 */ diff --git a/interface.c b/interface.c index 7b314a7d..58c23156 100644 --- a/interface.c +++ b/interface.c @@ -55,6 +55,7 @@ #include #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; diff --git a/interface.h b/interface.h index 198c61d0..857eefbe 100644 --- a/interface.h +++ b/interface.h @@ -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,