Files
Arquivotheca.SunOS-4.1.4/sys/sun/in_cksum.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

143 lines
3.0 KiB
C

#ifndef lint
static char sccsid[] = "@(#)in_cksum.c 1.1 94/10/31 Copyr 1983 Sun Micro";
#endif
/*
* Copyright (c) 1983 by Sun Microsystems, Inc.
*/
#include <sys/types.h>
#include <sys/mbuf.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
/*
* Checksum routine for Internet Protocol family headers.
* This routine is very heavily used in the network
* code and should be modified for each CPU to be as fast as possible.
*/
in_cksum(m, len)
register struct mbuf *m;
register int len;
{
register u_short *w;
register int sum;
register int mlen;
extern void swab();
if (len <= m->m_len && (len & 1) == 0) {
return (0xFFFF & ~ocsum(mtod(m, u_short *), len >> 1));
}
sum = 0;
mlen = 0;
for (; ;) {
/*
* Each trip around loop adds in
* word from one mbuf segment.
*/
w = mtod(m, u_short *);
if (mlen == -1) {
/*
* There is a byte left from the last segment;
* add it into the checksum. Don't have to worry
* about a carry-out here because we make sure
* that high part of (32 bit) sum is small below.
*/
#ifdef i386
sum += *(u_char *)w << 8;
#else
sum += *(u_char *)w;
#endif
w = (u_short *)((char *)w + 1);
mlen = m->m_len - 1;
len--;
} else
mlen = m->m_len;
m = m->m_next;
if (len < mlen)
mlen = len;
len -= mlen;
if (mlen > 0) {
if (((int)w & 1) == 0) {
sum += ocsum(w, mlen>>1);
w += mlen>>1;
/*
* If we had an odd number of bytes,
* then the last byte goes in the high
* part of the sum, and we take the
* first byte to the low part of the sum
* the next time around the loop.
*/
if (mlen & 1) {
#ifdef i386
sum += *(u_char *)w;
#else
sum += *(u_char *)w << 8;
#endif
mlen = -1;
}
} else {
u_short swsum;
#ifdef i386
sum += *(u_char *)w;
#else
sum += *(u_char *)w << 8;
#endif
mlen--;
w = (u_short *)(1 + (int)w);
swsum = ocsum(w, mlen>>1);
swab((char *)&swsum, (char *)&swsum,
sizeof (swsum));
sum += swsum;
w += mlen>>1;
/*
* If we had an even number of bytes,
* then the last byte goes in the low
* part of the sum. Otherwise we had an
* odd number of bytes and we take the first
* byte to the low part of the sum the
* next time around the loop.
*/
if (mlen & 1)
#ifdef i386
sum += *(u_char *)w << 8;
#else
sum += *(u_char *)w;
#endif
else
mlen = -1;
}
}
if (len == 0)
break;
/*
* Locate the next block with some data.
* If there is a word split across a boundary we
* will wrap to the top with mlen == -1 and
* then add it in shifted appropriately.
*/
for (; ;) {
if (m == 0) {
printf("cksum: out of data\n");
goto done;
}
if (m->m_len)
break;
m = m->m_next;
}
}
done:
/*
* Add together high and low parts of sum
* and carry to get cksum.
* Have to be careful to not drop the last
* carry here.
*/
sum = (sum & 0xFFFF) + (sum >> 16);
sum = (sum & 0xFFFF) + (sum >> 16);
sum = (~sum) & 0xFFFF;
return (sum);
}