X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;ds=sidebyside;f=src%2Flibsystemd-network%2Fdhcp-packet.c;h=b012e63d1f498a3c534ee1503e3beeea1db2648e;hb=7739a40b45fcc00874f8760be3d26534ed76cd45;hp=0549f575ac66dced8da2b3428addca708956e682;hpb=3b7ca119fdc501e21f017695dc9b6f82fdbd1d93;p=elogind.git diff --git a/src/libsystemd-network/dhcp-packet.c b/src/libsystemd-network/dhcp-packet.c index 0549f575a..b012e63d1 100644 --- a/src/libsystemd-network/dhcp-packet.c +++ b/src/libsystemd-network/dhcp-packet.c @@ -59,21 +59,48 @@ int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, return 0; } -uint16_t dhcp_packet_checksum(void *buf, int len) { - uint32_t sum; - uint16_t *check; - int i; - uint8_t *odd; +uint16_t dhcp_packet_checksum(void *buf, size_t len) { + uint64_t *buf_64 = buf; + uint64_t *end_64 = (uint64_t*)buf + (len / sizeof(uint64_t)); + uint32_t *buf_32; + uint16_t *buf_16; + uint8_t *buf_8; + uint64_t sum = 0; + + while (buf_64 < end_64) { + sum += *buf_64; + if (sum < *buf_64) + sum++; + + buf_64 ++; + } + + buf_32 = (uint32_t*)buf_64; + + if (len & sizeof(uint32_t)) { + sum += *buf_32; + if (sum < *buf_32) + sum++; + + buf_32 ++; + } + + buf_16 = (uint16_t*)buf_32; + + if (len & sizeof(uint16_t)) { + sum += *buf_16; + if (sum < *buf_16) + sum ++; - sum = 0; - check = buf; + buf_16 ++; + } - for (i = 0; i < len / 2 ; i++) - sum += check[i]; + buf_8 = (uint8_t*)buf_16; - if (len & 0x01) { - odd = buf; - sum += odd[len - 1]; + if (len & sizeof(uint8_t)) { + sum += *buf_8; + if (sum < *buf_8) + sum++; } while (sum >> 16) @@ -113,63 +140,49 @@ int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum) { /* IP */ - if (len < DHCP_IP_SIZE) { - log_dhcp_client(client, "ignoring packet: packet (%zu bytes) " - " smaller than IP header (%u bytes)", len, - DHCP_IP_SIZE); - return -EINVAL; - } - if (packet->ip.version != IPVERSION) { - log_dhcp_client(client, "ignoring packet: not IPv4"); + log_debug("ignoring packet: not IPv4"); return -EINVAL; } if (packet->ip.ihl < 5) { - log_dhcp_client(client, "ignoring packet: IPv4 IHL (%u words) invalid", - packet->ip.ihl); + log_debug("ignoring packet: IPv4 IHL (%u words) invalid", + packet->ip.ihl); return -EINVAL; } hdrlen = packet->ip.ihl * 4; if (hdrlen < 20) { - log_dhcp_client(client, "ignoring packet: IPv4 IHL (%zu bytes) " - "smaller than minimum (20 bytes)", hdrlen); + log_debug("ignoring packet: IPv4 IHL (%zu bytes) " + "smaller than minimum (20 bytes)", hdrlen); return -EINVAL; } if (len < hdrlen) { - log_dhcp_client(client, "ignoring packet: packet (%zu bytes) " - "smaller than expected (%zu) by IP header", len, - hdrlen); + log_debug("ignoring packet: packet (%zu bytes) " + "smaller than expected (%zu) by IP header", len, + hdrlen); return -EINVAL; } /* UDP */ if (packet->ip.protocol != IPPROTO_UDP) { - log_dhcp_client(client, "ignoring packet: not UDP"); - return -EINVAL; - } - - if (len < DHCP_IP_UDP_SIZE) { - log_dhcp_client(client, "ignoring packet: packet (%zu bytes) " - " smaller than IP+UDP header (%u bytes)", len, - DHCP_IP_UDP_SIZE); + log_debug("ignoring packet: not UDP"); return -EINVAL; } if (len < hdrlen + be16toh(packet->udp.len)) { - log_dhcp_client(client, "ignoring packet: packet (%zu bytes) " - "smaller than expected (%zu) by UDP header", len, - hdrlen + be16toh(packet->udp.len)); + log_debug("ignoring packet: packet (%zu bytes) " + "smaller than expected (%zu) by UDP header", len, + hdrlen + be16toh(packet->udp.len)); return -EINVAL; } if (be16toh(packet->udp.dest) != DHCP_PORT_CLIENT) { - log_dhcp_client(client, "ignoring packet: to port %u, which " - "is not the DHCP client port (%u)", - be16toh(packet->udp.dest), DHCP_PORT_CLIENT); + log_debug("ignoring packet: to port %u, which " + "is not the DHCP client port (%u)", + be16toh(packet->udp.dest), DHCP_PORT_CLIENT); return -EINVAL; } @@ -178,7 +191,7 @@ int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum) { */ if (dhcp_packet_checksum(&packet->ip, hdrlen)) { - log_dhcp_client(client, "ignoring packet: invalid IP checksum"); + log_debug("ignoring packet: invalid IP checksum"); return -EINVAL; } @@ -188,7 +201,7 @@ int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum) { if (dhcp_packet_checksum(&packet->ip.ttl, be16toh(packet->udp.len) + 12)) { - log_dhcp_client(client, "ignoring packet: invalid UDP checksum"); + log_debug("ignoring packet: invalid UDP checksum"); return -EINVAL; } }