Subject: Explicitly set DHCP_MAX_SIZE (option 57) for request packets, like for discover.

function                                             old     new   delta
init_packet                                          276     368     +92
udhcp_read_interface                                 428     500     +72
udhcpc_main                                         3808    3848     +40
.rodata                                            83794   83806     +12
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/0 up/down: 216/0)             Total: 216 bytes

Signed-off-by: Vladislav Grishenko <themiron@mail.ru>

--- busybox.orig/networking/udhcp/common.h	2010-10-13 00:00:00.000000000 +0000
+++ busybox/networking/udhcp/common.h	2010-10-13 19:10:29.684347002 +0000
@@ -63,14 +63,14 @@ struct udp_dhcp_packet {
 } PACKED;
 
 enum {
-	IP_UPD_DHCP_SIZE = sizeof(struct ip_udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS,
+	IP_UDP_DHCP_SIZE = sizeof(struct ip_udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS,
 	UPD_DHCP_SIZE    = sizeof(struct udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS,
 	DHCP_SIZE        = sizeof(struct dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS,
 };
 
 /* Let's see whether compiler understood us right */
 struct BUG_bad_sizeof_struct_ip_udp_dhcp_packet {
-	char c[IP_UPD_DHCP_SIZE == 576 ? 1 : -1];
+	char c[IP_UDP_DHCP_SIZE == 576 ? 1 : -1];
 };
 
 
@@ -294,7 +294,7 @@ void udhcp_sp_setup(void) FAST_FUNC;
 int udhcp_sp_fd_set(fd_set *rfds, int extra_fd) FAST_FUNC;
 int udhcp_sp_read(const fd_set *rfds) FAST_FUNC;
 
-int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC;
+int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac, uint16_t *mtu) FAST_FUNC;
 
 int udhcp_listen_socket(/*uint32_t ip,*/ int port, const char *inf) FAST_FUNC;
 
--- busybox.orig/networking/udhcp/dhcpc.c	2010-10-13 19:03:43.534347002 +0000
+++ busybox/networking/udhcp/dhcpc.c	2010-10-13 19:52:03.864347002 +0000
@@ -343,6 +343,8 @@ static ALWAYS_INLINE uint32_t random_xid
 /* Initialize the packet with the proper defaults */
 static void init_packet(struct dhcp_packet *packet, char type)
 {
+	int max_packet = sizeof(struct ip_udp_dhcp_packet);
+
 	udhcp_init_header(packet, type);
 	memcpy(packet->chaddr, client_config.client_mac, 6);
 	if (client_config.clientid)
@@ -357,6 +359,16 @@ static void init_packet(struct dhcp_pack
 	) {
 		udhcp_add_binary_option(packet, client_config.vendorclass);
 	}
+	switch (type) {
+	case DHCPDISCOVER:
+		/* Explicitly saying that we want RFC-compliant packets helps
+		 * some buggy DHCP servers to NOT send bigger packets */
+		max_packet = IP_UDP_DHCP_SIZE;
+		/* Fall through */
+	case DHCPREQUEST:
+		if (max_packet < client_config.client_mtu)
+			udhcp_add_simple_option(packet, DHCP_MAX_SIZE, htons(max_packet));
+	}
 }
 
 static void add_client_options(struct dhcp_packet *packet)
@@ -433,9 +445,6 @@ static int send_discover(uint32_t xid, u
 	packet.xid = xid;
 	if (requested)
 		udhcp_add_simple_option(&packet, DHCP_REQUESTED_IP, requested);
-	/* Explicitly saying that we want RFC-compliant packets helps
-	 * some buggy DHCP servers to NOT send bigger packets */
-	udhcp_add_simple_option(&packet, DHCP_MAX_SIZE, htons(576));
 	add_client_options(&packet);
 
 	bb_info_msg("Sending discover...");
@@ -923,7 +932,8 @@ int udhcpc_main(int argc UNUSED_PARAM, c
 	if (udhcp_read_interface(client_config.interface,
 			&client_config.ifindex,
 			NULL,
-			client_config.client_mac)
+			client_config.client_mac,
+			&client_config.client_mtu)
 	) {
 		return 1;
 	}
@@ -978,6 +988,16 @@ int udhcpc_main(int argc UNUSED_PARAM, c
 		/* silence "uninitialized!" warning */
 		unsigned timestamp_before_wait = timestamp_before_wait;
 
+		/* When running on a bridge, the ifindex may have changed (e.g. if
+		 * member interfaces were added/removed or if the status of the
+		 * bridge changed). Interface mtu may have changed also.
+		 * Workaround: refresh it here before processing the next packet */
+		udhcp_read_interface(client_config.interface,
+				&client_config.ifindex,
+				NULL,
+				client_config.client_mac,
+				&client_config.client_mtu);
+
 		//bb_error_msg("sockfd:%d, listen_mode:%d", sockfd, listen_mode);
 
 		/* Was opening raw or udp socket here
--- busybox.orig/networking/udhcp/dhcpc.h	2010-10-09 19:57:14.000000000 +0000
+++ busybox/networking/udhcp/dhcpc.h	2010-10-13 18:20:36.324347002 +0000
@@ -9,6 +9,7 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDD
 
 struct client_config_t {
 	uint8_t client_mac[6];          /* Our mac address */
+	uint16_t client_mtu;		/* Our mtu */
 	char no_default_options;        /* Do not include default options in request */
 	IF_FEATURE_UDHCP_PORT(uint16_t port;)
 	int ifindex;                    /* Index number of the interface to use */
--- busybox.orig/networking/udhcp/dhcpd.c	2010-09-16 23:05:35.000000000 +0000
+++ busybox/networking/udhcp/dhcpd.c	2010-10-13 18:19:07.024347002 +0000
@@ -357,7 +357,8 @@ int udhcpd_main(int argc UNUSED_PARAM, c
 	if (udhcp_read_interface(server_config.interface,
 			&server_config.ifindex,
 			&server_config.server_nip,
-			server_config.server_mac)
+			server_config.server_mac,
+			NULL)
 	) {
 		retval = 1;
 		goto ret;
--- busybox.orig/networking/udhcp/dhcprelay.c	2010-10-09 19:57:14.000000000 +0000
+++ busybox/networking/udhcp/dhcprelay.c	2010-10-13 18:19:07.024347002 +0000
@@ -267,7 +267,7 @@ int dhcprelay_main(int argc, char **argv
 	max_socket = init_sockets(client_ifaces, num_sockets, argv[2], fds);
 
 	/* Get our IP on server_iface */
-	if (udhcp_read_interface(argv[2], NULL, &our_nip, NULL))
+	if (udhcp_read_interface(argv[2], NULL, &our_nip, NULL, NULL))
 		return 1;
 
 	/* Main loop */
@@ -304,7 +304,7 @@ int dhcprelay_main(int argc, char **argv
 
 				/* Get our IP on corresponding client_iface */
 //why? what if server can't route such IP?
-				if (udhcp_read_interface(client_ifaces[i-1], NULL, &dhcp_msg.gateway_nip, NULL)) {
+				if (udhcp_read_interface(client_ifaces[i-1], NULL, &dhcp_msg.gateway_nip, NULL, NULL)) {
 					/* Fall back to our server_iface's IP */
 //this makes more sense!
 					dhcp_msg.gateway_nip = our_nip;
--- busybox.orig/networking/udhcp/packet.c	2010-07-25 19:15:32.000000000 +0000
+++ busybox/networking/udhcp/packet.c	2010-10-13 19:11:15.334347002 +0000
@@ -225,16 +225,16 @@ int FAST_FUNC udhcp_send_raw_packet(stru
 	packet.udp.len = htons(UPD_DHCP_SIZE - padding);
 	/* for UDP checksumming, ip.len is set to UDP packet len */
 	packet.ip.tot_len = packet.udp.len;
-	packet.udp.check = udhcp_checksum(&packet, IP_UPD_DHCP_SIZE - padding);
+	packet.udp.check = udhcp_checksum(&packet, IP_UDP_DHCP_SIZE - padding);
 	/* but for sending, it is set to IP packet len */
-	packet.ip.tot_len = htons(IP_UPD_DHCP_SIZE - padding);
+	packet.ip.tot_len = htons(IP_UDP_DHCP_SIZE - padding);
 	packet.ip.ihl = sizeof(packet.ip) >> 2;
 	packet.ip.version = IPVERSION;
 	packet.ip.ttl = IPDEFTTL;
 	packet.ip.check = udhcp_checksum(&packet.ip, sizeof(packet.ip));
 
 	udhcp_dump_packet(dhcp_pkt);
-	result = sendto(fd, &packet, IP_UPD_DHCP_SIZE - padding, /*flags:*/ 0,
+	result = sendto(fd, &packet, IP_UDP_DHCP_SIZE - padding, /*flags:*/ 0,
 			(struct sockaddr *) &dest_sll, sizeof(dest_sll));
 	msg = "sendto";
  ret_close:
--- busybox.orig/networking/udhcp/socket.c	2010-09-16 23:05:35.000000000 +0000
+++ busybox/networking/udhcp/socket.c	2010-10-13 18:19:07.024347002 +0000
@@ -34,7 +34,7 @@
 
 #include "common.h"
 
-int FAST_FUNC udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac)
+int FAST_FUNC udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac, uint16_t *mtu)
 {
 	int fd;
 	struct ifreq ifr;
@@ -76,6 +76,15 @@ int FAST_FUNC udhcp_read_interface(const
 			mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
 	}
 
+	if (mtu) {
+		if (ioctl_or_warn(fd, SIOCGIFMTU, &ifr) != 0) {
+			close(fd);
+			return -1;
+		}
+		log1("Adapter mtu %d", ifr.ifr_mtu);
+		*mtu = ifr.ifr_mtu;
+	}
+
 	close(fd);
 	return 0;
 }
