alias_util.c revision 45926
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.h"
30#include "alias_local.h"
31
32u_short
33PacketAliasInternetChecksum(u_short *ptr, int nbytes)
34{
35    int sum, oddbyte;
36
37    sum = 0;
38    while (nbytes > 1)
39    {
40        sum += *ptr++;
41        nbytes -= 2;
42    }
43    if (nbytes == 1)
44    {
45        oddbyte = 0;
46        ((u_char *) &oddbyte)[0] = *(u_char *) ptr;
47        ((u_char *) &oddbyte)[1] = 0;
48        sum += oddbyte;
49    }
50    sum = (sum >> 16) + (sum & 0xffff);
51    sum += (sum >> 16);
52    return(~sum);
53}
54
55u_short
56IpChecksum(struct ip *pip)
57{
58    return( PacketAliasInternetChecksum((u_short *) pip,
59            (pip->ip_hl << 2)) );
60
61}
62
63u_short
64TcpChecksum(struct ip *pip)
65{
66    u_short *ptr;
67    struct tcphdr *tc;
68    int nhdr, ntcp, nbytes;
69    int sum, oddbyte;
70
71    nhdr = pip->ip_hl << 2;
72    ntcp = ntohs(pip->ip_len) - nhdr;
73
74    tc = (struct tcphdr *) ((char *) pip + nhdr);
75    ptr = (u_short *) tc;
76
77/* Add up TCP header and data */
78    nbytes = ntcp;
79    sum = 0;
80    while (nbytes > 1)
81    {
82        sum += *ptr++;
83        nbytes -= 2;
84    }
85    if (nbytes == 1)
86    {
87        oddbyte = 0;
88        ((u_char *) &oddbyte)[0] = *(u_char *) ptr;
89        ((u_char *) &oddbyte)[1] = 0;
90        sum += oddbyte;
91    }
92
93/* "Pseudo-header" data */
94    ptr = (u_short *) &(pip->ip_dst);
95    sum += *ptr++;
96    sum += *ptr;
97    ptr = (u_short *) &(pip->ip_src);
98    sum += *ptr++;
99    sum += *ptr;
100    sum += htons((u_short) ntcp);
101    sum += htons((u_short) pip->ip_p);
102
103/* Roll over carry bits */
104    sum = (sum >> 16) + (sum & 0xffff);
105    sum += (sum >> 16);
106
107/* Return checksum */
108    return((u_short) ~sum);
109}
110
111
112void
113DifferentialChecksum(u_short *cksum, u_short *new, u_short *old, int n)
114{
115    int i;
116    int accumulate;
117
118    accumulate = *cksum;
119    for (i=0; i<n; i++)
120    {
121        accumulate -= *new++;
122        accumulate += *old++;
123    }
124
125    if (accumulate < 0)
126    {
127        accumulate = -accumulate;
128        accumulate = (accumulate >> 16) + (accumulate & 0xffff);
129        accumulate += accumulate >> 16;
130        *cksum = (u_short) ~accumulate;
131    }
132    else
133    {
134        accumulate = (accumulate >> 16) + (accumulate & 0xffff);
135        accumulate += accumulate >> 16;
136        *cksum = (u_short) accumulate;
137    }
138}
139
140