| 59 | } |
| 60 | |
| 61 | uint16_t UDPHeaderCalculateChecksum(const void *udp_packet, |
| 62 | const size_t udp_packet_length, |
| 63 | const in_addr_t source_addr, |
| 64 | const in_addr_t destination_addr) { |
| 65 | const uint16_t *udp_packet_words = udp_packet; |
| 66 | uint32_t checksum = 0; |
| 67 | size_t length = udp_packet_length; |
| 68 | |
| 69 | // Process UDP packet |
| 70 | while(length > 1) { |
| 71 | checksum += *udp_packet_words++; |
| 72 | if(checksum & 0x8000000) { |
| 73 | checksum = (checksum & 0xFFFF) + (checksum >> 16); |
| 74 | } |
| 75 | length -= 2; |
| 76 | } |
| 77 | |
| 78 | if(0 != length % 2) { |
| 79 | // Add padding if packet length is odd |
| 80 | checksum += *( (uint8_t *)udp_packet_words ); |
| 81 | } |
| 82 | |
| 83 | //Process IP pseudo header |
| 84 | uint16_t *source_addr_as_words = (void *)&source_addr; |
| 85 | checksum += *source_addr_as_words + *(source_addr_as_words + 1); |
| 86 | |
| 87 | uint16_t *destination_addr_as_words = (void *)&destination_addr; |
| 88 | checksum += *destination_addr_as_words + *(destination_addr_as_words + 1); |
| 89 | |
| 90 | checksum += htons(IPPROTO_UDP); |
| 91 | checksum += htons(udp_packet_length); |
| 92 | |
| 93 | //Add the carries |
| 94 | while(0 != checksum >> 16) { |
| 95 | checksum = (checksum & 0xFFFF) + (checksum >> 16); |
| 96 | } |
| 97 | |
| 98 | // Return one's complement |
| 99 | return (uint16_t)(~checksum); |
| 100 | } |