alias_util.c revision 50597
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    $FreeBSD: head/sys/netinet/libalias/alias_util.c 50597 1999-08-29 23:17:04Z billf $
16*/
17
18/*
19Note: the checksum routines assume that the actual checksum word has
20been zeroed out.  If the checksum workd is filled with the proper value,
21then these routines will give a result of zero (useful for testing
22purposes);
23*/
24
25#include <sys/types.h>
26#include <netinet/in_systm.h>
27#include <netinet/in.h>
28#include <netinet/ip.h>
29#include <netinet/tcp.h>
30
31#include "alias.h"
32#include "alias_local.h"
33
34u_short
35PacketAliasInternetChecksum(u_short *ptr, int nbytes)
36{
37    int sum, oddbyte;
38
39    sum = 0;
40    while (nbytes > 1)
41    {
42        sum += *ptr++;
43        nbytes -= 2;
44    }
45    if (nbytes == 1)
46    {
47        oddbyte = 0;
48        ((u_char *) &oddbyte)[0] = *(u_char *) ptr;
49        ((u_char *) &oddbyte)[1] = 0;
50        sum += oddbyte;
51    }
52    sum = (sum >> 16) + (sum & 0xffff);
53    sum += (sum >> 16);
54    return(~sum);
55}
56
57u_short
58IpChecksum(struct ip *pip)
59{
60    return( PacketAliasInternetChecksum((u_short *) pip,
61            (pip->ip_hl << 2)) );
62
63}
64
65u_short
66TcpChecksum(struct ip *pip)
67{
68    u_short *ptr;
69    struct tcphdr *tc;
70    int nhdr, ntcp, nbytes;
71    int sum, oddbyte;
72
73    nhdr = pip->ip_hl << 2;
74    ntcp = ntohs(pip->ip_len) - nhdr;
75
76    tc = (struct tcphdr *) ((char *) pip + nhdr);
77    ptr = (u_short *) tc;
78
79/* Add up TCP header and data */
80    nbytes = ntcp;
81    sum = 0;
82    while (nbytes > 1)
83    {
84        sum += *ptr++;
85        nbytes -= 2;
86    }
87    if (nbytes == 1)
88    {
89        oddbyte = 0;
90        ((u_char *) &oddbyte)[0] = *(u_char *) ptr;
91        ((u_char *) &oddbyte)[1] = 0;
92        sum += oddbyte;
93    }
94
95/* "Pseudo-header" data */
96    ptr = (u_short *) &(pip->ip_dst);
97    sum += *ptr++;
98    sum += *ptr;
99    ptr = (u_short *) &(pip->ip_src);
100    sum += *ptr++;
101    sum += *ptr;
102    sum += htons((u_short) ntcp);
103    sum += htons((u_short) pip->ip_p);
104
105/* Roll over carry bits */
106    sum = (sum >> 16) + (sum & 0xffff);
107    sum += (sum >> 16);
108
109/* Return checksum */
110    return((u_short) ~sum);
111}
112
113
114void
115DifferentialChecksum(u_short *cksum, u_short *new, u_short *old, int n)
116{
117    int i;
118    int accumulate;
119
120    accumulate = *cksum;
121    for (i=0; i<n; i++)
122    {
123        accumulate -= *new++;
124        accumulate += *old++;
125    }
126
127    if (accumulate < 0)
128    {
129        accumulate = -accumulate;
130        accumulate = (accumulate >> 16) + (accumulate & 0xffff);
131        accumulate += accumulate >> 16;
132        *cksum = (u_short) ~accumulate;
133    }
134    else
135    {
136        accumulate = (accumulate >> 16) + (accumulate & 0xffff);
137        accumulate += accumulate >> 16;
138        *cksum = (u_short) accumulate;
139    }
140}
141
142