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