7 struct thread_master
*master
;
20 static struct csum_vals ospfd_vals
, isisd_vals
;
22 typedef size_t testsz_t
;
23 typedef uint16_t testoff_t
;
25 /* Fletcher Checksum -- Refer to RFC1008. */
28 /* Accumulator phase of checksum */
31 accumulate (u_char
*buffer
, testsz_t len
, testoff_t off
)
35 int i
, init_len
, partial_len
;
38 csum
= (u_int16_t
*) (buffer
+ off
);
48 partial_len
= MIN(len
, MODX
);
50 for (i
= 0; i
< partial_len
; i
++)
52 ret
.c0
= ret
.c0
+ *(p
++);
56 ret
.c0
= ret
.c0
% 255;
57 ret
.c1
= ret
.c1
% 255;
64 /* The final reduction phase.
65 * This one should be the original ospfd version
68 reduce_ospfd (struct csum_vals
*vals
, testsz_t len
, testoff_t off
)
75 x
= ((len
- off
- 1) * c0
- c1
) % 255;
83 /* take care endian issue. */
84 return htons ((x
<< 8) + y
);
91 /* slightly different concatenation */
93 reduce_ospfd1 (struct csum_vals
*vals
, testsz_t len
, testoff_t off
)
100 x
= ((len
- off
- 1) * c0
- c1
) % 255;
107 /* take care endian issue. */
108 return htons ((x
<< 8) | (y
& 0xff));
115 /* original isisd version */
117 reduce_isisd (struct csum_vals
*vals
, testsz_t len
, testoff_t off
)
121 #define c0 vals->a.c0
122 #define c1 vals->a.c1
125 mul
= (len
- off
)*(c0
);
142 return htons ((x
<< 8) | (y
& 0xff));
150 /* Is the -1 in y wrong perhaps? */
152 reduce_isisd_yfix (struct csum_vals
*vals
, testsz_t len
, testoff_t off
)
156 #define c0 vals->a.c0
157 #define c1 vals->a.c1
160 mul
= (len
- off
)*(c0
);
177 return htons ((x
<< 8) | (y
& 0xff));
185 /* Move the mods yp */
187 reduce_isisd_mod (struct csum_vals
*vals
, testsz_t len
, testoff_t off
)
191 #define c0 vals->a.c0
192 #define c1 vals->a.c1
195 mul
= (len
- off
)*(c0
);
212 return htons ((x
<< 8) | (y
& 0xff));
220 /* Move the mods up + fix y */
222 reduce_isisd_mody (struct csum_vals
*vals
, testsz_t len
, testoff_t off
)
226 #define c0 vals->a.c0
227 #define c1 vals->a.c1
230 mul
= (len
- off
)*(c0
);
247 return htons ((x
<< 8) | (y
& 0xff));
255 struct reductions_t
{
257 u_int16_t (*f
) (struct csum_vals
*, testsz_t
, testoff_t
);
259 { .name
= "ospfd", .f
= reduce_ospfd
},
260 { .name
= "ospfd-1", .f
= reduce_ospfd1
},
261 { .name
= "isisd", .f
= reduce_isisd
},
262 { .name
= "isisd-yfix", .f
= reduce_isisd_yfix
},
263 { .name
= "isisd-mod", .f
= reduce_isisd_mod
},
264 { .name
= "isisd-mody", .f
= reduce_isisd_mody
},
268 /* The original ospfd checksum */
270 ospfd_checksum (u_char
*buffer
, testsz_t len
, testoff_t off
)
272 u_char
*sp
, *ep
, *p
, *q
;
275 u_int16_t checksum
, *csum
;
277 csum
= (u_int16_t
*) (buffer
+ off
);
282 for (ep
= sp
+ len
; sp
< ep
; sp
= q
)
287 for (p
= sp
; p
< q
; p
++)
296 ospfd_vals
.a
.c0
= c0
;
297 ospfd_vals
.a
.c1
= c1
;
299 //printf ("%s: len %u, off %u, c0 %d, c1 %d\n",
300 // __func__, len, off, c0, c1);
302 x
= ((int)(len
- off
- 1) * (int)c0
- (int)c1
) % 255;
316 /* take care endian issue. */
317 checksum
= htons ((x
<< 8) | (y
& 0xff));
322 /* the original, broken isisd checksum */
324 iso_csum_create (u_char
* buffer
, testsz_t len
, testoff_t off
)
333 u_int16_t checksum
, *csum
;
334 int i
, init_len
, partial_len
;
338 csum
= (u_int16_t
*) (buffer
+ off
);
348 partial_len
= MIN(len
, MODX
);
350 for (i
= 0; i
< partial_len
; i
++)
362 isisd_vals
.a
.c0
= c0
;
363 isisd_vals
.a
.c1
= c1
;
365 mul
= (init_len
- off
) * c0
;
386 checksum
= htons((x
<< 8) | (y
& 0xFF));
390 /* return the checksum for user usage */
395 verify (u_char
* buffer
, testsz_t len
)
411 partial_len
= MIN(len
, 5803);
413 for (i
= 0; i
< partial_len
; i
++)
424 if (c0
== 0 && c1
== 0)
430 int /* return checksum in low-order 16 bits */
431 in_cksum_optimized(void *parg
, int nbytes
)
434 register long sum
; /* assumes long == 32 bits */
435 register u_short answer
; /* assumes u_short == 16 bits */
438 * Our algorithm is simple, using a 32-bit accumulator (sum),
439 * we add sequential 16-bit words to it, and at the end, fold back
440 * all the carry bits from the top 16 bits into the lower 16 bits.
444 count
= nbytes
>> 1; /* div by 2 */
445 for(ptr
--; count
; --count
)
448 if (nbytes
& 1) /* Odd */
449 sum
+= *(u_char
*)(++ptr
); /* one byte only */
452 * Add back carry outs from top 16 bits to low 16 bits.
455 sum
= (sum
>> 16) + (sum
& 0xffff); /* add high-16 to low-16 */
456 sum
+= (sum
>> 16); /* add carry */
457 answer
= ~sum
; /* ones-complement, then truncate to 16 bits */
462 int /* return checksum in low-order 16 bits */
463 in_cksum_rfc(void *parg
, int count
)
466 u_short
*addr
= parg
;
467 /* Compute Internet Checksum for "count" bytes
468 * beginning at location "addr".
470 register long sum
= 0;
473 /* This is the inner loop */
477 /* Add left-over byte, if any */
479 sum
+= *(u_char
*)addr
;
482 /* Fold 32-bit sum to 16 bits */
484 sum
= (sum
& 0xffff) + (sum
>> 16);
490 main(int argc
, char **argv
)
492 /* 60017 65629 702179 */
493 #define MAXDATALEN 60017
494 #define BUFSIZE MAXDATALEN + sizeof(u_int16_t)
495 u_char buffer
[BUFSIZE
];
497 #define EXERCISESTEP 257
499 srandom (time (NULL
));
502 u_int16_t ospfd
, isisd
, lib
, in_csum
, in_csum_res
, in_csum_rfc
;
505 exercise
+= EXERCISESTEP
;
506 exercise
%= MAXDATALEN
;
508 for (i
= 0; i
< exercise
; i
+= sizeof (long int)) {
509 long int rand
= random ();
511 for (j
= sizeof (long int); j
> 0; j
--)
512 buffer
[i
+ (sizeof (long int) - j
)] = (rand
>> (j
* 8)) & 0xff;
515 in_csum
= in_cksum(buffer
, exercise
);
516 in_csum_res
= in_cksum_optimized(buffer
, exercise
);
517 in_csum_rfc
= in_cksum_rfc(buffer
, exercise
);
518 if (in_csum_res
!= in_csum
|| in_csum
!= in_csum_rfc
)
519 printf ("verify: in_chksum failed in_csum:%x, in_csum_res:%x,"
520 "in_csum_rfc %x, len:%d\n",
521 in_csum
, in_csum_res
, in_csum_rfc
, exercise
);
523 ospfd
= ospfd_checksum (buffer
, exercise
+ sizeof(u_int16_t
), exercise
);
524 if (verify (buffer
, exercise
+ sizeof(u_int16_t
)))
525 printf ("verify: ospfd failed\n");
526 isisd
= iso_csum_create (buffer
, exercise
+ sizeof(u_int16_t
), exercise
);
527 if (verify (buffer
, exercise
+ sizeof(u_int16_t
)))
528 printf ("verify: isisd failed\n");
529 lib
= fletcher_checksum (buffer
, exercise
+ sizeof(u_int16_t
), exercise
);
530 if (verify (buffer
, exercise
+ sizeof(u_int16_t
)))
531 printf ("verify: lib failed\n");
534 printf ("Mismatch in values at size %u\n"
535 "ospfd: 0x%04x\tc0: %d\tc1: %d\tx: %d\ty: %d\n"
536 "isisd: 0x%04x\tc0: %d\tc1: %d\tx: %d\ty: %d\n"
539 ospfd
, ospfd_vals
.a
.c0
, ospfd_vals
.a
.c1
, ospfd_vals
.x
, ospfd_vals
.y
,
540 isisd
, isisd_vals
.a
.c0
, isisd_vals
.a
.c1
, isisd_vals
.x
, isisd_vals
.y
,
544 /* Investigate reduction phase discrepencies */
545 if (ospfd_vals
.a
.c0
== isisd_vals
.a
.c0
546 && ospfd_vals
.a
.c1
== isisd_vals
.a
.c1
) {
548 for (i
= 0; reducts
[i
].name
!= NULL
; i
++) {
549 ospfd
= reducts
[i
].f (&ospfd_vals
,
550 exercise
+ sizeof (u_int16_t
),
552 printf ("%20s: x: %02x, y %02x, checksum 0x%04x\n",
553 reducts
[i
].name
, ospfd_vals
.x
& 0xff, ospfd_vals
.y
& 0xff, ospfd
);
557 printf ("\n u_char testdata [] = {\n ");
558 for (i
= 0; i
< exercise
; i
++) {
561 (i
+ 1) % 8 ? " " : "\n ");