File: checksum.c

package info (click to toggle)
pcaputils 0.8-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 372 kB
  • sloc: ansic: 2,945; sh: 44; makefile: 38
file content (72 lines) | stat: -rw-r--r-- 1,565 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include "checksum.h"
#include "net.h"
#include "uint.h"
#include "util.h"

/*
 *  This is a version of ip_compute_csum() optimized for IP headers,
 *  which always checksum on 4 octet boundaries.
 *
 *  By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
 *  Arnt Gulbrandsen.
 */

/**
 * ip_fast_csum - Compute the IPv4 header checksum efficiently.
 * iph: ipv4 header
 * ihl: length of header / 4
 */

#if defined(__i386__) || defined(__amd64__)
__inline u16 checksum_ip(const void *iph, unsigned ihl)
{
	unsigned sum;

	asm(	"  movl (%1), %0\n"
		"  subl $4, %2\n"
		"  jbe 2f\n"
		"  addl 4(%1), %0\n"
		"  adcl 8(%1), %0\n"
		"  adcl 12(%1), %0\n"
		"1: adcl 16(%1), %0\n"
		"  lea 4(%1), %1\n"
		"  decl %2\n"
		"  jne  1b\n"
		"  adcl $0, %0\n"
		"  movl %0, %2\n"
		"  shrl $16, %0\n"
		"  addw %w2, %w0\n"
		"  adcl $0, %0\n"
		"  notl %0\n"
		"2:"
	/* Since the input registers which are loaded with iph and ihl
	   are modified, we must also specify them as outputs, or gcc
	   will assume they contain their original values. */
	: "=r" (sum), "=r" (iph), "=r" (ihl)
	: "1" (iph), "2" (ihl)
	: "memory");
	return (u16) sum;
}
#else
__inline u16 checksum_ip(const void *iph, unsigned ihl)
{
	return checksum_net(iph, 4 * ihl);
}
#endif

__inline u16 checksum_net(const void *p, unsigned len)
{
	unsigned sum = 0;
	u16 *ip = (u16 *) p;
	while(len > 1){
		sum += *ip++;
		len -= 2;
	}
	while(sum >> 16)
		sum = (sum & 0xffff) + (sum >> 16);
#if __BYTE_ORDER == __LITTLE_ENDIAN	
	return (u16) (~sum);
#else
	return bswap16((u16) (~sum));
#endif
}