$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;