X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd-network%2Fdhcp-packet.c;h=b012e63d1f498a3c534ee1503e3beeea1db2648e;hb=998d8047029fb922ec42e55c9ed0c8926d1d9223;hp=102ed096aff666be3668813973587ab725f5efbc;hpb=0c79c68d93d721d37ba088fb50dbf07bb0d447e5;p=elogind.git diff --git a/src/libsystemd-network/dhcp-packet.c b/src/libsystemd-network/dhcp-packet.c index 102ed096a..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; - sum = 0; - check = buf; + if (len & sizeof(uint16_t)) { + sum += *buf_16; + if (sum < *buf_16) + sum ++; + + 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) @@ -114,48 +141,48 @@ int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum) { /* IP */ 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"); + 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; } @@ -164,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; } @@ -174,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; } }