parlib: Fix the use-after-func issue
[akaros.git] / user / iplib / ptclbsum.c
1 /*
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9 #include <stdlib.h>
10
11 #include <iplib/iplib.h>
12 #include <parlib/parlib.h>
13 #include <signal.h>
14 #include <stdio.h>
15 #include <unistd.h>
16
17 static short endian = 1;
18 static uint8_t *aendian = (uint8_t *)&endian;
19 #define LITTLE *aendian
20
21 /* "Returns the one's complement checksum used in IP protocols."  That's from
22  * Plan 9's man page.  This is not a usable, as is - you want to call
23  * ip_calc_xsum(). */
24 uint16_t ptclbsum(uint8_t *addr, int len)
25 {
26         uint32_t losum, hisum, mdsum, x;
27         uint32_t t1, t2;
28
29         losum = 0;
30         hisum = 0;
31         mdsum = 0;
32
33         x = 0;
34         if ((uintptr_t)addr & 1) {
35                 if (len) {
36                         hisum += addr[0];
37                         len--;
38                         addr++;
39                 }
40                 x = 1;
41         }
42         while(len >= 16) {
43                 t1 = *(uint16_t*)(addr + 0);
44                 t2 = *(uint16_t*)(addr + 2);    mdsum += t1;
45                 t1 = *(uint16_t*)(addr + 4);    mdsum += t2;
46                 t2 = *(uint16_t*)(addr + 6);    mdsum += t1;
47                 t1 = *(uint16_t*)(addr + 8);    mdsum += t2;
48                 t2 = *(uint16_t*)(addr + 10);   mdsum += t1;
49                 t1 = *(uint16_t*)(addr + 12);   mdsum += t2;
50                 t2 = *(uint16_t*)(addr + 14);   mdsum += t1;
51                 mdsum += t2;
52                 len -= 16;
53                 addr += 16;
54         }
55         while (len >= 2) {
56                 mdsum += *(uint16_t *)addr;
57                 len -= 2;
58                 addr += 2;
59         }
60         if (x) {
61                 if (len)
62                         losum += addr[0];
63                 if (LITTLE)
64                         losum += mdsum;
65                 else
66                         hisum += mdsum;
67         } else {
68                 if (len)
69                         hisum += addr[0];
70                 if (LITTLE)
71                         hisum += mdsum;
72                 else
73                         losum += mdsum;
74         }
75
76         losum += hisum >> 8;
77         losum += (hisum & 0xff) << 8;
78         while (hisum = losum >> 16)
79                 losum = hisum + (losum & 0xffff);
80
81         return losum & 0xffff;
82 }
83
84 /* Calculates an IP checksum for [addr, addr + len), returning the xsum in host
85  * endian. */
86 uint16_t ip_calc_xsum(uint8_t *addr, size_t len)
87 {
88         return ~ptclbsum(addr, len) & 0xffff;
89 }