alias_util.c revision 124621
1/*-
2 * Copyright (c) 2001 Charles Mott <cm@linktel.net>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/netinet/libalias/alias_util.c 124621 2004-01-17 10:52:21Z phk $");
29
30
31/*
32    Alias_util.c contains general utilities used by other functions
33    in the packet aliasing module.  At the moment, there are functions
34    for computing IP header and TCP packet checksums.
35
36    The checksum routines are based upon example code in a Unix networking
37    text written by Stevens (sorry, I can't remember the title -- but
38    at least this is a good author).
39
40    Initial Version:  August, 1996  (cjm)
41
42    Version 1.7:  January 9, 1997
43         Added differential checksum update function.
44*/
45
46/*
47Note: the checksum routines assume that the actual checksum word has
48been zeroed out.  If the checksum word is filled with the proper value,
49then these routines will give a result of zero (useful for testing
50purposes);
51*/
52
53#include <stdio.h>
54#include <sys/types.h>
55#include <netinet/in_systm.h>
56#include <netinet/in.h>
57#include <netinet/ip.h>
58#include <netinet/tcp.h>
59
60#include "alias.h"
61#include "alias_local.h"
62
63u_short
64LibAliasInternetChecksum(struct libalias *la, u_short *ptr, int nbytes)
65{
66    int sum, oddbyte;
67
68    sum = 0;
69    while (nbytes > 1)
70    {
71        sum += *ptr++;
72        nbytes -= 2;
73    }
74    if (nbytes == 1)
75    {
76        oddbyte = 0;
77        ((u_char *) &oddbyte)[0] = *(u_char *) ptr;
78        ((u_char *) &oddbyte)[1] = 0;
79        sum += oddbyte;
80    }
81    sum = (sum >> 16) + (sum & 0xffff);
82    sum += (sum >> 16);
83    return(~sum);
84}
85
86u_short
87IpChecksum(struct ip *pip)
88{
89    return( PacketAliasInternetChecksum((u_short *) pip,
90            (pip->ip_hl << 2)) );
91
92}
93
94u_short
95TcpChecksum(struct ip *pip)
96{
97    u_short *ptr;
98    struct tcphdr *tc;
99    int nhdr, ntcp, nbytes;
100    int sum, oddbyte;
101
102    nhdr = pip->ip_hl << 2;
103    ntcp = ntohs(pip->ip_len) - nhdr;
104
105    tc = (struct tcphdr *) ((char *) pip + nhdr);
106    ptr = (u_short *) tc;
107
108/* Add up TCP header and data */
109    nbytes = ntcp;
110    sum = 0;
111    while (nbytes > 1)
112    {
113        sum += *ptr++;
114        nbytes -= 2;
115    }
116    if (nbytes == 1)
117    {
118        oddbyte = 0;
119        ((u_char *) &oddbyte)[0] = *(u_char *) ptr;
120        ((u_char *) &oddbyte)[1] = 0;
121        sum += oddbyte;
122    }
123
124/* "Pseudo-header" data */
125    ptr = (u_short *) &(pip->ip_dst);
126    sum += *ptr++;
127    sum += *ptr;
128    ptr = (u_short *) &(pip->ip_src);
129    sum += *ptr++;
130    sum += *ptr;
131    sum += htons((u_short) ntcp);
132    sum += htons((u_short) pip->ip_p);
133
134/* Roll over carry bits */
135    sum = (sum >> 16) + (sum & 0xffff);
136    sum += (sum >> 16);
137
138/* Return checksum */
139    return((u_short) ~sum);
140}
141
142
143void
144DifferentialChecksum(u_short *cksum, u_short *new, u_short *old, int n)
145{
146    int i;
147    int accumulate;
148
149    accumulate = *cksum;
150    for (i=0; i<n; i++)
151    {
152        accumulate -= *new++;
153        accumulate += *old++;
154    }
155
156    if (accumulate < 0)
157    {
158        accumulate = -accumulate;
159        accumulate = (accumulate >> 16) + (accumulate & 0xffff);
160        accumulate += accumulate >> 16;
161        *cksum = (u_short) ~accumulate;
162    }
163    else
164    {
165        accumulate = (accumulate >> 16) + (accumulate & 0xffff);
166        accumulate += accumulate >> 16;
167        *cksum = (u_short) accumulate;
168    }
169}
170
171