aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-05-31 00:45:09 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2010-05-31 00:45:09 +0200
commitb8b72f02f01017d0f9584666fa572221f2b58613 (patch)
tree544348ff496fbba3f0c4c49d131cdeff8bb217c9
parente58c6e2e13030bea91f7cd41a62229b0f5927d51 (diff)
downloadbusybox-w32-b8b72f02f01017d0f9584666fa572221f2b58613.tar.gz
busybox-w32-b8b72f02f01017d0f9584666fa572221f2b58613.tar.bz2
busybox-w32-b8b72f02f01017d0f9584666fa572221f2b58613.zip
dhcp: truncate packets instead of padding them to 574 bytes. closes bug 1849
function old new delta udhcp_send_raw_packet 411 456 +45 udhcp_send_kernel_packet 259 271 +12 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/udhcp/packet.c32
1 files changed, 20 insertions, 12 deletions
diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c
index c01fb7d7c..4badc9cbc 100644
--- a/networking/udhcp/packet.c
+++ b/networking/udhcp/packet.c
@@ -173,6 +173,7 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt,
173{ 173{
174 struct sockaddr_ll dest_sll; 174 struct sockaddr_ll dest_sll;
175 struct ip_udp_dhcp_packet packet; 175 struct ip_udp_dhcp_packet packet;
176 unsigned padding;
176 int fd; 177 int fd;
177 int result = -1; 178 int result = -1;
178 const char *msg; 179 const char *msg;
@@ -198,34 +199,40 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt,
198 goto ret_close; 199 goto ret_close;
199 } 200 }
200 201
202 /* We were sending full-sized DHCP packets (zero padded),
203 * but some badly configured servers were seen dropping them.
204 * Apparently they drop all DHCP packets >576 *ethernet* octets big,
205 * whereas they may only drop packets >576 *IP* octets big
206 * (which for typical Ethernet II means 590 octets: 6+6+2 + 576).
207 *
208 * In order to work with those buggy servers,
209 * we truncate packets after end option byte.
210 */
211 padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(packet.data.options);
212
201 packet.ip.protocol = IPPROTO_UDP; 213 packet.ip.protocol = IPPROTO_UDP;
202 packet.ip.saddr = source_nip; 214 packet.ip.saddr = source_nip;
203 packet.ip.daddr = dest_nip; 215 packet.ip.daddr = dest_nip;
204 packet.udp.source = htons(source_port); 216 packet.udp.source = htons(source_port);
205 packet.udp.dest = htons(dest_port); 217 packet.udp.dest = htons(dest_port);
206 /* size, excluding IP header: */ 218 /* size, excluding IP header: */
207 packet.udp.len = htons(UPD_DHCP_SIZE); 219 packet.udp.len = htons(UPD_DHCP_SIZE - padding);
208 /* for UDP checksumming, ip.len is set to UDP packet len */ 220 /* for UDP checksumming, ip.len is set to UDP packet len */
209 packet.ip.tot_len = packet.udp.len; 221 packet.ip.tot_len = packet.udp.len;
210 packet.udp.check = udhcp_checksum(&packet, IP_UPD_DHCP_SIZE); 222 packet.udp.check = udhcp_checksum(&packet, IP_UPD_DHCP_SIZE - padding);
211 /* but for sending, it is set to IP packet len */ 223 /* but for sending, it is set to IP packet len */
212 packet.ip.tot_len = htons(IP_UPD_DHCP_SIZE); 224 packet.ip.tot_len = htons(IP_UPD_DHCP_SIZE - padding);
213 packet.ip.ihl = sizeof(packet.ip) >> 2; 225 packet.ip.ihl = sizeof(packet.ip) >> 2;
214 packet.ip.version = IPVERSION; 226 packet.ip.version = IPVERSION;
215 packet.ip.ttl = IPDEFTTL; 227 packet.ip.ttl = IPDEFTTL;
216 packet.ip.check = udhcp_checksum(&packet.ip, sizeof(packet.ip)); 228 packet.ip.check = udhcp_checksum(&packet.ip, sizeof(packet.ip));
217 229
218 /* Currently we send full-sized DHCP packets (zero padded).
219 * If you need to change this: last byte of the packet is
220 * packet.data.options[udhcp_end_option(packet.data.options)]
221 */
222 udhcp_dump_packet(dhcp_pkt); 230 udhcp_dump_packet(dhcp_pkt);
223 result = sendto(fd, &packet, IP_UPD_DHCP_SIZE, 0, 231 result = sendto(fd, &packet, IP_UPD_DHCP_SIZE - padding, /*flags:*/ 0,
224 (struct sockaddr *) &dest_sll, sizeof(dest_sll)); 232 (struct sockaddr *) &dest_sll, sizeof(dest_sll));
225 msg = "sendto"; 233 msg = "sendto";
226 ret_close: 234 ret_close:
227 close(fd); 235 close(fd);
228 /* FIXME: and if result >= 0 but != IP_UPD_DHCP_SIZE? */
229 if (result < 0) { 236 if (result < 0) {
230 ret_msg: 237 ret_msg:
231 bb_perror_msg(msg, "PACKET"); 238 bb_perror_msg(msg, "PACKET");
@@ -239,6 +246,7 @@ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt,
239 uint32_t dest_nip, int dest_port) 246 uint32_t dest_nip, int dest_port)
240{ 247{
241 struct sockaddr_in client; 248 struct sockaddr_in client;
249 unsigned padding;
242 int fd; 250 int fd;
243 int result = -1; 251 int result = -1;
244 const char *msg; 252 const char *msg;
@@ -268,13 +276,13 @@ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt,
268 goto ret_close; 276 goto ret_close;
269 } 277 }
270 278
271 /* Currently we send full-sized DHCP packets (see above) */
272 udhcp_dump_packet(dhcp_pkt); 279 udhcp_dump_packet(dhcp_pkt);
273 result = safe_write(fd, dhcp_pkt, DHCP_SIZE); 280
281 padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(dhcp_pkt->options);
282 result = safe_write(fd, dhcp_pkt, DHCP_SIZE - padding);
274 msg = "write"; 283 msg = "write";
275 ret_close: 284 ret_close:
276 close(fd); 285 close(fd);
277 /* FIXME: and if result >= 0 but != DHCP_SIZE? */
278 if (result < 0) { 286 if (result < 0) {
279 ret_msg: 287 ret_msg:
280 bb_perror_msg(msg, "UDP"); 288 bb_perror_msg(msg, "UDP");