From fff145dba309df2a6ba2986ad2b690f7e0858cad Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Thu, 20 Dec 2007 21:11:38 +0000 Subject: udhcp: fix oversized packet sending (introduced by "slack for bad dhcp servers" options); slight optimizations and function renaming udhcp_send_raw_packet - 391 +391 udhcp_send_kernel_packet - 197 +197 udhcp_recv_packet - 134 +134 get_raw_packet 353 326 -27 udhcp_get_packet 134 - -134 udhcp_kernel_packet 197 - -197 udhcp_raw_packet 391 - -391 ------------------------------------------------------------------------------ (add/remove: 3/3 grow/shrink: 0/1 up/down: 722/-749) Total: -27 bytes --- networking/udhcp/packet.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) (limited to 'networking/udhcp/packet.c') diff --git a/networking/udhcp/packet.c b/networking/udhcp/packet.c index 0abe851a4..c3890229f 100644 --- a/networking/udhcp/packet.c +++ b/networking/udhcp/packet.c @@ -39,7 +39,7 @@ void udhcp_init_header(struct dhcpMessage *packet, char type) /* read a packet from socket fd, return -1 on read error, -2 on packet error */ -int udhcp_get_packet(struct dhcpMessage *packet, int fd) +int udhcp_recv_packet(struct dhcpMessage *packet, int fd) { #if 0 static const char broken_vendors[][8] = { @@ -111,7 +111,7 @@ uint16_t udhcp_checksum(void *addr, int count) /* Make sure that the left-over byte is added correctly both * with little and big endian hosts */ uint16_t tmp = 0; - *(uint8_t *) (&tmp) = * (uint8_t *) source; + *(uint8_t*)&tmp = *(uint8_t*)source; sum += tmp; } /* Fold 32-bit sum to 16 bits */ @@ -123,7 +123,7 @@ uint16_t udhcp_checksum(void *addr, int count) /* Construct a ip/udp header for a packet, and specify the source and dest hardware address */ -int udhcp_raw_packet(struct dhcpMessage *payload, +int udhcp_send_raw_packet(struct dhcpMessage *payload, uint32_t source_ip, int source_port, uint32_t dest_ip, int dest_port, const uint8_t *dest_arp, int ifindex) { @@ -132,6 +132,11 @@ int udhcp_raw_packet(struct dhcpMessage *payload, struct sockaddr_ll dest; struct udp_dhcp_packet packet; + enum { + IP_UPD_DHCP_SIZE = sizeof(struct udp_dhcp_packet) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS, + UPD_DHCP_SIZE = IP_UPD_DHCP_SIZE - offsetof(struct udp_dhcp_packet, udp), + }; + fd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); if (fd < 0) { bb_perror_msg("socket"); @@ -140,6 +145,7 @@ int udhcp_raw_packet(struct dhcpMessage *payload, memset(&dest, 0, sizeof(dest)); memset(&packet, 0, sizeof(packet)); + packet.data = *payload; /* struct copy */ dest.sll_family = AF_PACKET; dest.sll_protocol = htons(ETH_P_IP); @@ -157,19 +163,19 @@ int udhcp_raw_packet(struct dhcpMessage *payload, packet.ip.daddr = dest_ip; packet.udp.source = htons(source_port); packet.udp.dest = htons(dest_port); - packet.udp.len = htons(sizeof(packet.udp) + sizeof(struct dhcpMessage)); /* cheat on the psuedo-header */ + /* size, excluding IP header: */ + packet.udp.len = htons(UPD_DHCP_SIZE); + /* for UDP checksumming, ip.len is set to UDP packet len */ packet.ip.tot_len = packet.udp.len; - memcpy(&(packet.data), payload, sizeof(struct dhcpMessage)); - packet.udp.check = udhcp_checksum(&packet, sizeof(struct udp_dhcp_packet)); - - packet.ip.tot_len = htons(sizeof(struct udp_dhcp_packet)); + packet.udp.check = udhcp_checksum(&packet, IP_UPD_DHCP_SIZE); + /* but for sending, it is set to IP packet len */ + packet.ip.tot_len = htons(IP_UPD_DHCP_SIZE); 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)); + packet.ip.check = udhcp_checksum(&packet.ip, sizeof(packet.ip)); - result = sendto(fd, &packet, sizeof(struct udp_dhcp_packet), 0, - (struct sockaddr *) &dest, sizeof(dest)); + result = sendto(fd, &packet, IP_UPD_DHCP_SIZE, 0, (struct sockaddr *) &dest, sizeof(dest)); if (result <= 0) { bb_perror_msg("sendto"); } @@ -179,13 +185,17 @@ int udhcp_raw_packet(struct dhcpMessage *payload, /* Let the kernel do all the work for packet generation */ -int udhcp_kernel_packet(struct dhcpMessage *payload, +int udhcp_send_kernel_packet(struct dhcpMessage *payload, uint32_t source_ip, int source_port, uint32_t dest_ip, int dest_port) { int fd, result; struct sockaddr_in client; + enum { + DHCP_SIZE = sizeof(struct dhcpMessage) - CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS, + }; + fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (fd < 0) return -1; @@ -212,7 +222,7 @@ int udhcp_kernel_packet(struct dhcpMessage *payload, return -1; } - result = write(fd, payload, sizeof(struct dhcpMessage)); + result = write(fd, payload, DHCP_SIZE); close(fd); return result; } -- cgit v1.2.3