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