1 /*
2  * Copyright (c) 2014 Chris Anderson
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 
9 #include "minip-internal.h"
10 
11 /* XXX alternate implementation, merge */
ones_sum16(uint32_t sum,const void * _buf,int len)12 uint16_t ones_sum16(uint32_t sum, const void *_buf, int len) {
13     const uint16_t *buf = _buf;
14 
15     while (len >= 2) {
16         sum += *buf++;
17         if (sum & 0x80000000)
18             sum = (sum & 0xffff) + (sum >> 16);
19         len -= 2;
20     }
21 
22     if (len) {
23         uint16_t temp = htons((*(uint8_t *)buf) << 8);
24         sum += temp;
25     }
26 
27     while (sum >> 16)
28         sum = (sum & 0xffff) + (sum >> 16);
29 
30     return sum;
31 }
32 
rfc1701_chksum(const uint8_t * buf,size_t len)33 uint16_t rfc1701_chksum(const uint8_t *buf, size_t len) {
34     uint32_t total = 0;
35     uint16_t chksum = 0;
36     const uint16_t *p = (const uint16_t *) buf;
37 
38     // Length is in bytes
39     for (size_t i = 0; i < len / 2; i++ ) {
40         total += p[i];
41     }
42 
43     chksum = (total & 0xFFFF) + (total >> 16);
44     chksum = ~chksum;
45 
46     return chksum;
47 }
48 
49 #if MINIP_USE_UDP_CHECKSUM
rfc768_chksum(struct ipv4_hdr * ipv4,struct udp_hdr * udp)50 uint16_t rfc768_chksum(struct ipv4_hdr *ipv4, struct udp_hdr *udp) {
51     uint32_t total = 0;
52     uint16_t chksum = 0;
53     size_t len = ntohs(udp->len);
54     uint16_t *p;
55 
56     p = (uint16_t *)ipv4->src_addr;
57     total += htons(p[0]);
58     total += htons(p[1]);
59 
60     p = (uint16_t *)ipv4->dst_addr;
61     total += htons(p[0]);
62     total += htons(p[1]);
63 
64     p = (const uint16_t *)udp->data;
65     for (size_t i = 0; i < len / 2; i++ ) {
66         total += p[i];
67     }
68 
69     total += IP_PROTO_UDP;
70     total += udp->len;
71     total += udp->src_port;
72     total += udp->dst_port;
73     total += ipv4->len;
74 
75     chksum = (total & 0xFFFF) + (total >> 16);
76     chksum = ~chksum;
77 
78     return chksum;
79 }
80 #endif
81