/* * Copyright (c) 1998-2006 The TCPDUMP project * 2014 Sage Electronic Engineering, LLC * All Rights Reserved * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code * distributions retain the above copyright notice and this paragraph * in its entirety, and (2) distributions including binary code include * the above copyright notice and this paragraph in its entirety in * the documentation or other materials provided with the distribution. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE. * * Original code by Hannes Gredler <hannes@juniper.net> * Rewritten for Fletcher32 by Bruce Griffith <Bruce.Griffith@se-eng.com> */ #include <errno.h> #include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> #include <string.h> #define MAX_PSP_DIRECTORY_SIZE 512 typedef unsigned int uint32_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; /* * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3. * The checksum field of the passed PDU does not need to be reset to zero. * * The "Fletcher Checksum" was proposed in a paper by John G. Fletcher of * Lawrence Livermore Labs. The Fletcher Checksum was proposed as an * alternative to cyclical redundancy checks because it provides error- * detection properties similar to cyclical redundancy checks but at the * cost of a simple summation technique. Its characteristics were first * published in IEEE Transactions on Communications in January 1982. One * version has been adopted by ISO for use in the class-4 transport layer * of the network protocol. * * This program expects: * stdin: The input file to compute a checksum for. The input file * not be longer than 256 bytes. * stdout: Copied from the input file with the Fletcher's Checksum * inserted 8 bytes after the beginning of the file. * stderr: Used to print out error messages. */ uint32_t fletcher32 (const uint16_t *pptr, int length) { uint32_t c0; uint32_t c1; uint32_t checksum; int index; c0 = 0xFFFF; c1 = 0xFFFF; for (index = 0; index < length; index++) { /* * Ignore the contents of the checksum field. */ c0 += *(pptr++); c1 += c0; if ((index % 360) == 0) { c0 = (c0 & 0xFFFF) + (c0 >> 16); // Sum0 modulo 65535 + the overflow c1 = (c1 & 0xFFFF) + (c1 >> 16); // Sum1 modulo 65535 + the overflow } } c0 = (c0 & 0xFFFF) + (c0 >> 16); // Sum0 modulo 65535 + the overflow c1 = (c1 & 0xFFFF) + (c1 >> 16); // Sum1 modulo 65535 + the overflow checksum = (c1 << 16) | c0; return checksum; } int main(int argc, char **argv) { uint32_t checksum = 0xFFFFFFFF; struct stat filestat = {}; int retcode = EINVAL; size_t filesize = 0; char debugoption[] = "--print"; uint16_t buffer[MAX_PSP_DIRECTORY_SIZE / sizeof(uint16_t)]; retcode = fstat(fileno(stdin), &filestat); filesize = filestat.st_size; if (retcode < 0) { perror("FLETCHER32"); return errno; } else if (!((12 < filesize) && (filesize <= sizeof(buffer)))) { fprintf(stderr, "FLETCHER32: input file is not valid for this program.\n"); return EINVAL; } retcode = read(fileno(stdin), (void *)buffer, filesize); if (retcode < 0) { perror("FLETCHER32"); return errno; } checksum = fletcher32(&buffer[2], filesize/2 - 2); *((uint32_t *)& buffer[2]) = checksum; #ifndef DEBUG if ((argc == 2) && (strcmp(argv[1], debugoption) == 0)) { #endif fprintf(stderr, "Fletcher's Checksum: %x\n", checksum); #ifndef DEBUG } #endif retcode = write(fileno(stdout), buffer, filesize); if (retcode < 0) { perror("FLETCHER32"); return errno; } return 0; }