Commits
Joakim Tjernlund authored and Paul Jakma committed 439c52f1900
420 420 | |
421 421 | len -= partial_len; |
422 422 | } |
423 423 | |
424 424 | if (c0 == 0 && c1 == 0) |
425 425 | return 0; |
426 426 | |
427 427 | return 1; |
428 428 | } |
429 429 | |
430 + | int /* return checksum in low-order 16 bits */ |
431 + | in_cksum_optimized(void *parg, int nbytes) |
432 + | { |
433 + | u_short *ptr = parg; |
434 + | register long sum; /* assumes long == 32 bits */ |
435 + | register u_short answer; /* assumes u_short == 16 bits */ |
436 + | register int count; |
437 + | /* |
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. |
441 + | */ |
442 + | |
443 + | sum = 0; |
444 + | count = nbytes >> 1; /* div by 2 */ |
445 + | for(ptr--; count; --count) |
446 + | sum += *++ptr; |
447 + | |
448 + | if (nbytes & 1) /* Odd */ |
449 + | sum += *(u_char *)(++ptr); /* one byte only */ |
450 + | |
451 + | /* |
452 + | * Add back carry outs from top 16 bits to low 16 bits. |
453 + | */ |
454 + | |
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 */ |
458 + | return(answer); |
459 + | } |
460 + | |
461 + | |
462 + | int /* return checksum in low-order 16 bits */ |
463 + | in_cksum_rfc(void *parg, int count) |
464 + | /* from RFC 1071 */ |
465 + | { |
466 + | u_short *addr = parg; |
467 + | /* Compute Internet Checksum for "count" bytes |
468 + | * beginning at location "addr". |
469 + | */ |
470 + | register long sum = 0; |
471 + | |
472 + | while (count > 1) { |
473 + | /* This is the inner loop */ |
474 + | sum += *addr++; |
475 + | count -= 2; |
476 + | } |
477 + | /* Add left-over byte, if any */ |
478 + | if (count > 0) { |
479 + | sum += *(u_char *)addr; |
480 + | } |
481 + | |
482 + | /* Fold 32-bit sum to 16 bits */ |
483 + | while (sum>>16) |
484 + | sum = (sum & 0xffff) + (sum >> 16); |
485 + | return ~sum; |
486 + | } |
487 + | |
488 + | |
430 489 | int |
431 490 | main(int argc, char **argv) |
432 491 | { |
433 492 | /* 60017 65629 702179 */ |
434 493 | |
435 494 | |
436 495 | u_char buffer[BUFSIZE]; |
437 496 | int exercise = 0; |
438 497 | |
439 498 | |
440 499 | srandom (time (NULL)); |
441 500 | |
442 501 | while (1) { |
443 - | u_int16_t ospfd, isisd, lib; |
444 - | |
502 + | u_int16_t ospfd, isisd, lib, in_csum, in_csum_res, in_csum_rfc; |
503 + | int i,j; |
504 + | |
445 505 | exercise += EXERCISESTEP; |
446 506 | exercise %= MAXDATALEN; |
447 507 | |
448 - | for (int i = 0; i < exercise; i += sizeof (long int)) { |
508 + | for (i = 0; i < exercise; i += sizeof (long int)) { |
449 509 | long int rand = random (); |
450 510 | |
451 - | for (int j = sizeof (long int); j > 0; j--) |
511 + | for (j = sizeof (long int); j > 0; j--) |
452 512 | buffer[i + (sizeof (long int) - j)] = (rand >> (j * 8)) & 0xff; |
453 513 | } |
454 514 | |
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); |
522 + | |
455 523 | ospfd = ospfd_checksum (buffer, exercise + sizeof(u_int16_t), exercise); |
456 524 | if (verify (buffer, exercise + sizeof(u_int16_t))) |
457 525 | printf ("verify: ospfd failed\n"); |
458 526 | isisd = iso_csum_create (buffer, exercise + sizeof(u_int16_t), exercise); |
459 527 | if (verify (buffer, exercise + sizeof(u_int16_t))) |
460 528 | printf ("verify: isisd failed\n"); |
461 529 | lib = fletcher_checksum (buffer, exercise + sizeof(u_int16_t), exercise); |
462 530 | if (verify (buffer, exercise + sizeof(u_int16_t))) |
463 531 | printf ("verify: lib failed\n"); |
464 532 | |
470 538 | exercise, |
471 539 | ospfd, ospfd_vals.a.c0, ospfd_vals.a.c1, ospfd_vals.x, ospfd_vals.y, |
472 540 | isisd, isisd_vals.a.c0, isisd_vals.a.c1, isisd_vals.x, isisd_vals.y, |
473 541 | lib |
474 542 | ); |
475 543 | |
476 544 | /* Investigate reduction phase discrepencies */ |
477 545 | if (ospfd_vals.a.c0 == isisd_vals.a.c0 |
478 546 | && ospfd_vals.a.c1 == isisd_vals.a.c1) { |
479 547 | printf ("\n"); |
480 - | for (int i = 0; reducts[i].name != NULL; i++) { |
548 + | for (i = 0; reducts[i].name != NULL; i++) { |
481 549 | ospfd = reducts[i].f (&ospfd_vals, |
482 550 | exercise + sizeof (u_int16_t), |
483 551 | exercise); |
484 552 | printf ("%20s: x: %02x, y %02x, checksum 0x%04x\n", |
485 553 | reducts[i].name, ospfd_vals.x & 0xff, ospfd_vals.y & 0xff, ospfd); |
486 554 | } |
487 555 | } |
488 556 | |
489 557 | printf ("\n u_char testdata [] = {\n "); |
490 - | for (int i = 0; i < exercise; i++) { |
558 + | for (i = 0; i < exercise; i++) { |
491 559 | printf ("0x%02x,%s", |
492 560 | buffer[i], |
493 561 | (i + 1) % 8 ? " " : "\n "); |
494 562 | } |
495 563 | printf ("\n}\n"); |
496 564 | exit (1); |
497 565 | } |
498 566 | } |
499 567 | } |