+
+/**
+ *
+ */
+Uint16 UDP_int_MakeChecksum(tInterface *Interface, const void *Dest, tUDPHeader *Hdr, size_t Len, const void *Data)
+{
+ size_t addrsize = IPStack_GetAddressSize(Interface->Type);
+ struct {
+ Uint8 Zeroes;
+ Uint8 Protocol;
+ Uint16 UDPLength;
+ } pheader;
+
+ pheader.Zeroes = 0;
+ switch(Interface->Type)
+ {
+ case 4: pheader.Protocol = IP4PROT_UDP; break;
+ //case 6: pheader.Protocol = IP6PROT_UDP; break;
+ default:
+ Log_Warning("UDP", "Unimplemented _MakeChecksum proto %i", Interface->Type);
+ return 0;
+ }
+ pheader.UDPLength = Hdr->Length;
+
+ Uint16 csum = 0;
+ csum = UDP_int_PartialChecksum(csum, addrsize, Interface->Address);
+ csum = UDP_int_PartialChecksum(csum, addrsize, Dest);
+ csum = UDP_int_PartialChecksum(csum, sizeof(pheader), &pheader);
+ csum = UDP_int_PartialChecksum(csum, sizeof(tUDPHeader), Hdr);
+ csum = UDP_int_PartialChecksum(csum, Len, Data);
+
+ return UDP_int_FinaliseChecksum(csum);
+}
+
+static inline Uint16 _add_ones_complement16(Uint16 a, Uint16 b)
+{
+ // One's complement arithmatic, overflows increment bottom bit
+ return a + b + (b > 0xFFFF - a ? 1 : 0);
+}
+
+Uint16 UDP_int_PartialChecksum(Uint16 Prev, size_t Len, const void *Data)
+{
+ Uint16 ret = Prev;
+ const Uint16 *data = Data;
+ for( int i = 0; i < Len/2; i ++ )
+ ret = _add_ones_complement16(ret, htons(*data++));
+ if( Len % 2 == 1 )
+ ret = _add_ones_complement16(ret, htons(*(const Uint8*)data));
+ return ret;
+}
+
+Uint16 UDP_int_FinaliseChecksum(Uint16 Value)
+{
+ Value = ~Value; // One's complement it
+ return (Value == 0 ? 0xFFFF : Value);
+}