xref: /freebsd/sys/netinet/libalias/alias_util.c (revision 380a989b3223d455375b4fae70fd0b9bdd43bafb)
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 /*
17 Note: the checksum routines assume that the actual checksum word has
18 been zeroed out.  If the checksum workd is filled with the proper value,
19 then these routines will give a result of zero (useful for testing
20 purposes);
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 
32 u_short
33 PacketAliasInternetChecksum(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 
54 u_short
55 IpChecksum(struct ip *pip)
56 {
57     return( PacketAliasInternetChecksum((u_short *) pip,
58             (pip->ip_hl << 2)) );
59 
60 }
61 
62 u_short
63 TcpChecksum(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 
110 void
111 DifferentialChecksum(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