[BusyBox] udhcpc and some 3com adsl router dhcp-server

Cristian Ionescu-Idbohrn cristian.ionescu-idbohrn at axis.com
Mon May 16 12:48:20 MDT 2005


On Thu, 12 May 2005, Cristian Ionescu-Idbohrn wrote:

> The router is a 3Com OfficeConnect Remote 812 ADSL Router.
>
> Problem is the dhcp-server sends a larger offer packet (in a 618 bytes
> frame) than udhcpc has reserved space for reading it.  udhcpc just
> discards the offer (with a "Truncated packet" message from function
> get_raw_packet in clientpacket.c).  I really don't know why the
> dhcp-server needs to pad the packet with crappy 250+ NULL bytes, but it
> does :(
>
> Adding another member to the dhcpMessage struct (and thus providing the
> some extra 28 bytes of memory) resolves the problem.  That's the quick
> and dirty fix.
>
> I'd like to hear some other opinions on this matter.  Especially if
> there's any reason against increasing the size of dhcpMessage up to the
> border of a whole frame.

No comments :( But see attached patch.  Should apply cleanly to both the
1.0 release and the svn-reposirory version.
This workaround could probably now help some people to obtain leases from
some odd dhcp-servers.

By encapsulating the udp_dhcp_packet structure into a new one
(encapsulated_udp_dhcp_packet, which provides more space), the
get_raw_packet function can now read the dhcp-offer package and I can get
a lease.  The encapsulated_udp_dhcp_packet struct is only used by
get_raw_packet.  No visible changes on the wire, else than normal
behaviour.


Cheers,
Cristian
-------------- next part --------------
? clientpacket.c.test
Index: clientpacket.c
===================================================================
RCS file: /usr/local/cvs/linux/apps/busybox/networking/udhcp/clientpacket.c,v
retrieving revision 1.1.1.2
diff -u -b -B -p -r1.1.1.2 clientpacket.c
--- clientpacket.c	15 Oct 2004 09:19:25 -0000	1.1.1.2
+++ clientpacket.c	16 May 2005 14:18:56 -0000
@@ -178,12 +178,12 @@ int send_release(unsigned long server, u
 int get_raw_packet(struct dhcpMessage *payload, int fd)
 {
 	int bytes;
-	struct udp_dhcp_packet packet;
+	struct encapsulated_udp_dhcp_packet packet;
 	uint32_t source, dest;
 	uint16_t check;
 
-	memset(&packet, 0, sizeof(struct udp_dhcp_packet));
-	bytes = read(fd, &packet, sizeof(struct udp_dhcp_packet));
+	memset(&packet, 0, sizeof(struct encapsulated_udp_dhcp_packet));
+	bytes = read(fd, &packet, sizeof(struct encapsulated_udp_dhcp_packet));
 	if (bytes < 0) {
 		DEBUG(LOG_INFO, "couldn't read on raw listening socket -- ignoring");
 		usleep(500000); /* possible down interface, looping condition */
@@ -195,54 +195,54 @@ int get_raw_packet(struct dhcpMessage *p
 		return -2;
 	}
 
-	if (bytes < ntohs(packet.ip.tot_len)) {
+	if (bytes < ntohs(packet.encap.ip.tot_len)) {
 		DEBUG(LOG_INFO, "Truncated packet");
 		return -2;
 	}
 
 	/* ignore any extra garbage bytes */
-	bytes = ntohs(packet.ip.tot_len);
+	bytes = ntohs(packet.encap.ip.tot_len);
 
 	/* Make sure its the right packet for us, and that it passes sanity checks */
-	if (packet.ip.protocol != IPPROTO_UDP || packet.ip.version != IPVERSION ||
-	    packet.ip.ihl != sizeof(packet.ip) >> 2 || packet.udp.dest != htons(CLIENT_PORT) ||
-	    bytes > (int) sizeof(struct udp_dhcp_packet) ||
-	    ntohs(packet.udp.len) != (uint16_t) (bytes - sizeof(packet.ip))) {
+	if (packet.encap.ip.protocol != IPPROTO_UDP || packet.encap.ip.version != IPVERSION ||
+	    packet.encap.ip.ihl != sizeof(packet.encap.ip) >> 2 || packet.encap.udp.dest != htons(CLIENT_PORT) ||
+	    bytes > (int) sizeof(struct encapsulated_udp_dhcp_packet) ||
+	    ntohs(packet.encap.udp.len) != (uint16_t) (bytes - sizeof(packet.encap.ip))) {
 	    	DEBUG(LOG_INFO, "unrelated/bogus packet");
 	    	return -2;
 	}
 
 	/* check IP checksum */
-	check = packet.ip.check;
-	packet.ip.check = 0;
-	if (check != checksum(&(packet.ip), sizeof(packet.ip))) {
+	check = packet.encap.ip.check;
+	packet.encap.ip.check = 0;
+	if (check != checksum(&(packet.encap.ip), sizeof(packet.encap.ip))) {
 		DEBUG(LOG_INFO, "bad IP header checksum, ignoring");
 		return -1;
 	}
 
 	/* verify the UDP checksum by replacing the header with a psuedo header */
-	source = packet.ip.saddr;
-	dest = packet.ip.daddr;
-	check = packet.udp.check;
-	packet.udp.check = 0;
-	memset(&packet.ip, 0, sizeof(packet.ip));
-
-	packet.ip.protocol = IPPROTO_UDP;
-	packet.ip.saddr = source;
-	packet.ip.daddr = dest;
-	packet.ip.tot_len = packet.udp.len; /* cheat on the psuedo-header */
+	source = packet.encap.ip.saddr;
+	dest = packet.encap.ip.daddr;
+	check = packet.encap.udp.check;
+	packet.encap.udp.check = 0;
+	memset(&packet.encap.ip, 0, sizeof(packet.encap.ip));
+
+	packet.encap.ip.protocol = IPPROTO_UDP;
+	packet.encap.ip.saddr = source;
+	packet.encap.ip.daddr = dest;
+	packet.encap.ip.tot_len = packet.encap.udp.len; /* cheat on the psuedo-header */
 	if (check && check != checksum(&packet, bytes)) {
 		DEBUG(LOG_ERR, "packet with bad UDP checksum received, ignoring");
 		return -2;
 	}
 
-	memcpy(payload, &(packet.data), bytes - (sizeof(packet.ip) + sizeof(packet.udp)));
+	memcpy(payload, &(packet.encap.data), bytes - (sizeof(packet.encap.ip) + sizeof(packet.encap.udp)));
 
 	if (ntohl(payload->cookie) != DHCP_MAGIC) {
 		LOG(LOG_ERR, "received bogus message (bad magic) -- ignoring");
 		return -2;
 	}
 	DEBUG(LOG_INFO, "oooooh!!! got some!");
-	return bytes - (sizeof(packet.ip) + sizeof(packet.udp));
+	return bytes - (sizeof(packet.encap.ip) + sizeof(packet.encap.udp));
 
 }
Index: packet.h
===================================================================
RCS file: /usr/local/cvs/linux/apps/busybox/networking/udhcp/packet.h,v
retrieving revision 1.1.1.1
diff -u -b -B -p -r1.1.1.1 packet.h
--- packet.h	28 May 2004 11:38:17 -0000	1.1.1.1
+++ packet.h	16 May 2005 14:18:56 -0000
@@ -29,6 +29,15 @@ struct udp_dhcp_packet {
 	struct dhcpMessage data;
 };
 
+struct encapsulated_udp_dhcp_packet {
+	struct udp_dhcp_packet encap;
+	uint8_t crap1[28];  /* this is because of a certain server in a
+			       '3Com OfficeConnect Remote 812 ADSL Router'
+			       sends larger packets */
+	uint8_t crap2[896]; /* this (and previous crap1) will cover for a
+			       whole ethernet frame */
+};
+
 void init_header(struct dhcpMessage *packet, char type);
 int get_packet(struct dhcpMessage *packet, int fd);
 uint16_t checksum(void *addr, int count);


More information about the busybox mailing list