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