[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