diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-05-31 00:45:09 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-05-31 00:45:09 +0200 |
commit | b8b72f02f01017d0f9584666fa572221f2b58613 (patch) | |
tree | 544348ff496fbba3f0c4c49d131cdeff8bb217c9 | |
parent | e58c6e2e13030bea91f7cd41a62229b0f5927d51 (diff) | |
download | busybox-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.c | 32 |
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"); |