Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Nov 2000 20:03:59 +0200
From:      Ruslan Ermilov <ru@FreeBSD.org>
To:        net@FreeBSD.org
Cc:        Charles Mott <cmott@scientech.com>, Ari Suutari <ari@suutari.iki.fi>
Subject:   libalias: Incremental Update of Internet Checksum
Message-ID:  <20001108200359.A38693@sunbay.com>

next in thread | raw e-mail | index | archive | help

--Dxnq1zWXvFF0Q93v
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi!

The DifferentialChecksum() function in libalias(3) is used
to efficiently recompute the checksum for altered packets.
Unfortunately, the implementation suffers from the problem
described in RFC 1624.  I have implemented the replacement
for it, using the final formula [4] from the RFC.

The attached C program demonstrates the problem as well as
the new implementation.

Comments?


-- 
Ruslan Ermilov		Oracle Developer/DBA,
ru@sunbay.com		Sunbay Software AG,
ru@FreeBSD.org		FreeBSD committer,
+380.652.512.251	Simferopol, Ukraine

http://www.FreeBSD.org	The Power To Serve
http://www.oracle.com	Enabling The Information Age

--Dxnq1zWXvFF0Q93v
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=Makefile

PROG=	inc_cksum
NOMAN=	YES
CFLAGS+=${BDECFLAGS}

.include <bsd.prog.mk>

--Dxnq1zWXvFF0Q93v
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="inc_cksum.c"

#include <sys/types.h>
#include <stdio.h>

void DifferentialChecksum(u_short *, u_short *, u_short *, int);
void DifferentialChecksum_RFC1624(u_short *, u_short *, u_short *, int);

void
DifferentialChecksum(u_short *cksum, u_short *new, u_short *old, int n)
{
    int i;
    int accumulate;

    accumulate = *cksum;
    for (i=0; i<n; i++)
    {
        accumulate -= *new++;
        accumulate += *old++;
    }

    if (accumulate < 0)
    {
        accumulate = -accumulate;
        accumulate = (accumulate >> 16) + (accumulate & 0xffff);
        accumulate += accumulate >> 16;
        *cksum = (u_short) ~accumulate;
    }
    else
    {
        accumulate = (accumulate >> 16) + (accumulate & 0xffff);
        accumulate += accumulate >> 16;
        *cksum = (u_short) accumulate;
    }
}

/*
 * Incremental Update of Internet Checksum with [Eqn. 4] from RFC 1624.
 */
void
DifferentialChecksum_RFC1624(u_short *cksum, u_short *new, u_short *old, int n)
{
	int i;
	int accumulate;			/* should be `signed' */

	accumulate = *cksum;
	for (i = 0; i < n; i++) {
		accumulate -= *new++;
		accumulate -= (u_short)~*old++;
	}

	accumulate = (accumulate >> 16) + (accumulate & 0xffff);
	accumulate += accumulate >> 16;
	*cksum = (u_short) accumulate;
}

int
main(void)
{
	u_short old, new, oldcksum, newcksum1, newcksum2;

        old = 0x5555;
	for (new = 0x0;; new++) {
		for (oldcksum = 0x0;; oldcksum++) {
			newcksum1 = newcksum2 = oldcksum;
			DifferentialChecksum(&newcksum1, &new, &old, 1);
			DifferentialChecksum_RFC1624(&newcksum2, &new, &old, 1);
			if (newcksum1 != newcksum2)
				printf("old=%#hx new=%#hx oldcksum=%#hx "
				       "newcksum1=%#hx newcksum2=%#hx\n",
				       old, new, oldcksum,
				       newcksum1, newcksum2);
			if (oldcksum == 0xffff)
				break;
		}
		if (new == 0xffff)
			break;
	}

	return (0);
}

--Dxnq1zWXvFF0Q93v--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001108200359.A38693>