$NetBSD: patch-af,v 1.1 2006/03/30 13:51:29 salo Exp $ --- ars.c.orig 2003-07-28 11:00:54.000000000 +0200 +++ ars.c 2005-11-05 21:35:00.000000000 +0100 @@ -372,7 +372,7 @@ } 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 @@ } /* 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 @@ 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;