alias_util.c revision 26026
1/*
2    Alias_util.h contains general utilities used by other functions
3    in the packet aliasing module.  At the moment, there are functions
4    for computing IP header and TCP packet checksums.
5
6    The checksum routines are based upon example code in a Unix networking
7    text written by Stevens (sorry, I can't remember the title -- but
8    at least this is a good author).
9
10    Initial Version:  August, 1996  (cjm)
11
12    Version 1.7:  January 9, 1997
13         Added differential checksum update function.
14*/
15
16/*
17Note: the checksum routines assume that the actual checksum word has
18been zeroed out.  If the checksum workd is filled with the proper value,
19then these routines will give a result of zero (useful for testing
20purposes);
21*/
22
23#include <sys/types.h>
24#include <netinet/in_systm.h>
25#include <netinet/in.h>
26#include <netinet/ip.h>
27#include <netinet/tcp.h>
28
29#include "alias_local.h"
30
31u_short
32InternetChecksum(u_short *ptr, int nbytes)
33{
34    int sum, oddbyte;
35
36    sum = 0;
37    while (nbytes > 1)
38    {
39        sum += *ptr++;
40        nbytes -= 2;
41    }
42    if (nbytes == 1)
43    {
44        oddbyte = 0;
45        *((u_char *) &oddbyte) = *(u_char *) ptr;
46        sum += oddbyte;
47    }
48    sum = (sum >> 16) + (sum & 0xffff);
49    sum += (sum >> 16);
50    return(~sum);
51}
52
53u_short
54IpChecksum(struct ip *pip)
55{
56    return( InternetChecksum((u_short *) pip, (pip->ip_hl << 2)) );
57
58}
59
60u_short
61TcpChecksum(struct ip *pip)
62{
63    u_short *ptr;
64    struct tcphdr *tc;
65    int nhdr, ntcp, nbytes;
66    int sum, oddbyte;
67
68    nhdr = pip->ip_hl << 2;
69    ntcp = ntohs(pip->ip_len) - nhdr;
70
71    tc = (struct tcphdr *) ((char *) pip + nhdr);
72    ptr = (u_short *) tc;
73
74/* Add up TCP header and data */
75    nbytes = ntcp;
76    sum = 0;
77    while (nbytes > 1)
78    {
79        sum += *ptr++;
80        nbytes -= 2;
81    }
82    if (nbytes == 1)
83    {
84        oddbyte = 0;
85        *((u_char *) &oddbyte) = *(u_char *) ptr;
86        sum += oddbyte;
87    }
88
89/* "Pseudo-header" data */
90    ptr = (u_short *) &(pip->ip_dst);
91    sum += *ptr++;
92    sum += *ptr;
93    ptr = (u_short *) &(pip->ip_src);
94    sum += *ptr++;
95    sum += *ptr;
96    sum += htons((u_short) ntcp);
97    sum += htons((u_short) pip->ip_p);
98
99/* Roll over carry bits */
100    sum = (sum >> 16) + (sum & 0xffff);
101    sum += (sum >> 16);
102
103/* Return checksum */
104    return((u_short) ~sum);
105}
106
107
108void
109DifferentialChecksum(u_short *cksum, u_short *new, u_short *old, int n)
110{
111    int i;
112    int accumulate;
113
114    accumulate = *cksum;
115    for (i=0; i<n; i++)
116    {
117        accumulate -= *new++;
118        accumulate += *old++;
119    }
120
121    if (accumulate < 0)
122    {
123        accumulate = -accumulate;
124        accumulate = (accumulate >> 16) + (accumulate & 0xffff);
125        accumulate += accumulate >> 16;
126        *cksum = (u_short) ~accumulate;
127    }
128    else
129    {
130        accumulate = (accumulate >> 16) + (accumulate & 0xffff);
131        accumulate += accumulate >> 16;
132        *cksum = (u_short) accumulate;
133    }
134}
135
136