blob: a5724943aa2e9511cbdfc5ca6abf0b0ebe4274fc [file] [log] [blame]
Bruce Griffith3a2310e2014-07-16 11:25:21 -06001/*
2 * Copyright (c) 1998-2006 The TCPDUMP project
3 * 2014 Sage Electronic Engineering, LLC
4 * All Rights Reserved
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that: (1) source code
8 * distributions retain the above copyright notice and this paragraph
9 * in its entirety, and (2) distributions including binary code include
10 * the above copyright notice and this paragraph in its entirety in
11 * the documentation or other materials provided with the distribution.
12 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
13 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
14 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
15 * FOR A PARTICULAR PURPOSE.
16 *
17 * Original code by Hannes Gredler <hannes@juniper.net>
18 * Rewritten for Fletcher32 by Bruce Griffith <Bruce.Griffith@se-eng.com>
19 */
20
21#include <errno.h>
22#include <stdio.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25#include <unistd.h>
26#include <string.h>
27
28#define MAX_PSP_DIRECTORY_SIZE 512
29
30typedef unsigned int uint32_t;
31typedef unsigned char uint8_t;
32typedef unsigned short uint16_t;
33
34/*
35 * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
36 * The checksum field of the passed PDU does not need to be reset to zero.
37 *
38 * The "Fletcher Checksum" was proposed in a paper by John G. Fletcher of
39 * Lawrence Livermore Labs. The Fletcher Checksum was proposed as an
40 * alternative to cyclical redundancy checks because it provides error-
41 * detection properties similar to cyclical redundancy checks but at the
42 * cost of a simple summation technique. Its characteristics were first
43 * published in IEEE Transactions on Communications in January 1982. One
44 * version has been adopted by ISO for use in the class-4 transport layer
45 * of the network protocol.
46 *
47 * This program expects:
48 * stdin: The input file to compute a checksum for. The input file
49 * not be longer than 256 bytes.
50 * stdout: Copied from the input file with the Fletcher's Checksum
51 * inserted 8 bytes after the beginning of the file.
52 * stderr: Used to print out error messages.
53 */
54
55uint32_t fletcher32 (const uint16_t *pptr, int length)
56{
57
58 uint32_t c0;
59 uint32_t c1;
60 uint32_t checksum;
61 int index;
62
63 c0 = 0xFFFF;
64 c1 = 0xFFFF;
65
66 for (index = 0; index < length; index++) {
67 /*
68 * Ignore the contents of the checksum field.
69 */
70 c0 += *(pptr++);
71 c1 += c0;
72 if ((index % 360) == 0) {
73 c0 = (c0 & 0xFFFF) + (c0 >> 16); // Sum0 modulo 65535 + the overflow
74 c1 = (c1 & 0xFFFF) + (c1 >> 16); // Sum1 modulo 65535 + the overflow
75 }
76
77 }
78
79 c0 = (c0 & 0xFFFF) + (c0 >> 16); // Sum0 modulo 65535 + the overflow
80 c1 = (c1 & 0xFFFF) + (c1 >> 16); // Sum1 modulo 65535 + the overflow
81 checksum = (c1 << 16) | c0;
82
83 return checksum;
84}
85
86int main(int argc, char **argv)
87{
88 uint32_t checksum = 0xFFFFFFFF;
89 struct stat filestat = {};
90 int retcode = EINVAL;
91 size_t filesize = 0;
92 char debugoption[] = "--print";
93
94 uint16_t buffer[MAX_PSP_DIRECTORY_SIZE / sizeof(uint16_t)];
95
96 retcode = fstat(fileno(stdin), &filestat);
97 filesize = filestat.st_size;
98 if (retcode < 0) {
99 perror("FLETCHER32");
100 return errno;
101 } else if (!((12 < filesize) && (filesize <= sizeof(buffer)))) {
102 fprintf(stderr, "FLETCHER32: input file is not valid for this program.\n");
103 return EINVAL;
104 }
105 retcode = read(fileno(stdin), (void *)buffer, filesize);
106 if (retcode < 0) {
107 perror("FLETCHER32");
108 return errno;
109 }
110
111 checksum = fletcher32(&buffer[2], filesize/2 - 2);
112 *((uint32_t *)& buffer[2]) = checksum;
113#ifndef DEBUG
Patrick Georgi667c7a32014-09-29 10:12:29 +0200114 if ((argc == 2) && (strcmp(argv[1], debugoption) == 0)) {
Bruce Griffith3a2310e2014-07-16 11:25:21 -0600115#endif
116 fprintf(stderr, "Fletcher's Checksum: %x\n", checksum);
117#ifndef DEBUG
118 }
119#endif
120
121 retcode = write(fileno(stdout), buffer, filesize);
122 if (retcode < 0) {
123 perror("FLETCHER32");
124 return errno;
125 }
126
127 return 0;
128}