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