summaryrefslogtreecommitdiff
path: root/net/hping/patches/patch-af
blob: 3436725087a29c495069548b59a8277c2dc49bf7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
$NetBSD: patch-af,v 1.2 2009/02/11 08:06:17 obache Exp $

--- ars.c.orig	2003-07-28 09:00:54.000000000 +0000
+++ ars.c
@@ -372,7 +372,7 @@ u_int16_t ars_cksum(void *vbuf, size_t n
 	}
 	if (nbytes == 1) {
 		oddbyte = 0;
-		*((u_int16_t *) &oddbyte) = *(u_int8_t *) buf;
+		*((u_int8_t *) &oddbyte) = *((u_int8_t *) buf);
 		sum += oddbyte;
 	}
 	sum = (sum >> 16) + (sum & 0xffff);
@@ -381,6 +381,13 @@ u_int16_t ars_cksum(void *vbuf, size_t n
 }
 
 /* Multiple buffers checksum facility */
+/*
+ * Important facts about the checksum (sum = ~cksum, Ai are bytes):
+ * 1. sum(A0...A2i-1,A2i...A2n-1) = sum(A0...A2i-1) + sum(A2i...B2n-1),
+ * 2. sum(A0...A2i,A2i+1...A2n-1) = sum(A0...A2i,0) + sum(0,A2i+1...A2n-1)
+ * 3. sum(A0...A2n-1,A2n) = sum(A0...A2n-1,A2n,0)  (ex definitiones)
+ * 4. sum(0,A0...Ak) = swap_bytes(sum(A0...Ak))
+ */
 u_int16_t ars_multi_cksum(struct mc_context *c, int op, void *vbuf,
 							size_t nbytes)
 {
@@ -394,38 +401,27 @@ u_int16_t ars_multi_cksum(struct mc_cont
 		c->old = 0;
 		return -ARS_OK;
 	} else if (op == ARS_MC_UPDATE) {
-		if (c->oddbyte_flag) {
-			u_int8_t *x = (u_int8_t*)&oddbyte;
-			oddbyte = 0;
-			*((u_int16_t *) &oddbyte) = c->oddbyte << 8;
-			*((u_int16_t *) &oddbyte) |= *(u_int8_t *) buf;
-			oddbyte = (x[0] << 8) | x[1]; /* fix endianess */
-			c->old += oddbyte;
-			nbytes--;
-			c->oddbyte_flag = 0;
-			/* We need to stay aligned -- bad slowdown, fix? */
-			tmp = alloca(nbytes);
-			memcpy(tmp, vbuf+1, nbytes);
-			buf = tmp;
-		}
-		sum = c->old;
+		sum = 0;
 		while (nbytes > 1) {
 			sum += *buf++;
 			nbytes -= 2;
 		}
-		c->old = sum;
 		if (nbytes == 1) {
-			c->oddbyte = *(u_int8_t*) buf;
-			c->oddbyte_flag++;
+			oddbyte = 0;
+			*((u_int8_t *) &oddbyte) = *((u_int8_t *) buf);
+			sum += oddbyte;
+		}
+		if (c->oddbyte_flag) {
+			/* reverse checksum endianness */
+			sum = (sum >> 16) + (sum & 0xffff);
+			sum += (sum >> 16);
+			sum = ((sum & 0xff00) >> 8) | ((sum & 0xff) << 8);
 		}
+		c->old += sum;
+		c->oddbyte_flag ^= (nbytes == 1 ? 1 : 0);
 		return -ARS_OK;
 	} else if (op == ARS_MC_FINAL) {
 		sum = c->old;
-		if (c->oddbyte_flag == 1) {
-			oddbyte = 0;
-			*((u_int16_t *) &oddbyte) = c->oddbyte;
-			sum += oddbyte;
-		}
 		sum = (sum >> 16) + (sum & 0xffff);
 		sum += (sum >> 16);
 		return (u_int16_t) ~sum;