1f987e1bdSBrian Somers /*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3fe267a55SPedro F. Giffuni * 4e83aaae3SBrian Somers * Copyright (c) 2001 Charles Mott <cm@linktel.net> 5f987e1bdSBrian Somers * All rights reserved. 6f987e1bdSBrian Somers * 7f987e1bdSBrian Somers * Redistribution and use in source and binary forms, with or without 8f987e1bdSBrian Somers * modification, are permitted provided that the following conditions 9f987e1bdSBrian Somers * are met: 10f987e1bdSBrian Somers * 1. Redistributions of source code must retain the above copyright 11f987e1bdSBrian Somers * notice, this list of conditions and the following disclaimer. 12f987e1bdSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright 13f987e1bdSBrian Somers * notice, this list of conditions and the following disclaimer in the 14f987e1bdSBrian Somers * documentation and/or other materials provided with the distribution. 15f987e1bdSBrian Somers * 16f987e1bdSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17f987e1bdSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18f987e1bdSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19f987e1bdSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20f987e1bdSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21f987e1bdSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22f987e1bdSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23f987e1bdSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24f987e1bdSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25f987e1bdSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26f987e1bdSBrian Somers * SUCH DAMAGE. 27f987e1bdSBrian Somers */ 28f987e1bdSBrian Somers 29e2505aa6SMatthew Dillon #include <sys/cdefs.h> 30e2505aa6SMatthew Dillon __FBSDID("$FreeBSD$"); 31e2505aa6SMatthew Dillon 323b160b8bSBrian Somers /* 3391cc2995SRuslan Ermilov Alias_util.c contains general utilities used by other functions 343b160b8bSBrian Somers in the packet aliasing module. At the moment, there are functions 353b160b8bSBrian Somers for computing IP header and TCP packet checksums. 363b160b8bSBrian Somers 373b160b8bSBrian Somers The checksum routines are based upon example code in a Unix networking 383b160b8bSBrian Somers text written by Stevens (sorry, I can't remember the title -- but 393b160b8bSBrian Somers at least this is a good author). 403b160b8bSBrian Somers 413b160b8bSBrian Somers Initial Version: August, 1996 (cjm) 423b160b8bSBrian Somers 433b160b8bSBrian Somers Version 1.7: January 9, 1997 443b160b8bSBrian Somers Added differential checksum update function. 453b160b8bSBrian Somers */ 463b160b8bSBrian Somers 47c649a2e0SGleb Smirnoff #ifdef _KERNEL 48c649a2e0SGleb Smirnoff #include <sys/param.h> 49be4f3cd0SPaolo Pisati #include <sys/proc.h> 50c649a2e0SGleb Smirnoff #else 513b160b8bSBrian Somers #include <sys/types.h> 52c649a2e0SGleb Smirnoff #include <stdio.h> 53c649a2e0SGleb Smirnoff #endif 54c649a2e0SGleb Smirnoff 553b160b8bSBrian Somers #include <netinet/in_systm.h> 563b160b8bSBrian Somers #include <netinet/in.h> 573b160b8bSBrian Somers #include <netinet/ip.h> 583b160b8bSBrian Somers #include <netinet/tcp.h> 593b160b8bSBrian Somers 60c649a2e0SGleb Smirnoff #ifdef _KERNEL 61c649a2e0SGleb Smirnoff #include <netinet/libalias/alias.h> 62c649a2e0SGleb Smirnoff #include <netinet/libalias/alias_local.h> 63c649a2e0SGleb Smirnoff #else 643efa11bbSBrian Somers #include "alias.h" 653b160b8bSBrian Somers #include "alias_local.h" 66c649a2e0SGleb Smirnoff #endif 673b160b8bSBrian Somers 6859dde15eSGleb Smirnoff /* 6959dde15eSGleb Smirnoff * Note: the checksum routines assume that the actual checksum word has 7059dde15eSGleb Smirnoff * been zeroed out. If the checksum word is filled with the proper value, 7159dde15eSGleb Smirnoff * then these routines will give a result of zero (useful for testing 7259dde15eSGleb Smirnoff * purposes); 7359dde15eSGleb Smirnoff */ 743b160b8bSBrian Somers u_short 7572f2d657SGleb Smirnoff LibAliasInternetChecksum(struct libalias *la __unused, u_short *ptr, 7672f2d657SGleb Smirnoff int nbytes) 773b160b8bSBrian Somers { 783b160b8bSBrian Somers int sum, oddbyte; 793b160b8bSBrian Somers 80ccd57eeaSPaolo Pisati LIBALIAS_LOCK(la); 813b160b8bSBrian Somers sum = 0; 82f0f93429SDag-Erling Smørgrav while (nbytes > 1) { 833b160b8bSBrian Somers sum += *ptr++; 843b160b8bSBrian Somers nbytes -= 2; 853b160b8bSBrian Somers } 86f0f93429SDag-Erling Smørgrav if (nbytes == 1) { 873b160b8bSBrian Somers oddbyte = 0; 8846d28b44SLuoqi Chen ((u_char *)&oddbyte)[0] = *(u_char *)ptr; 8946d28b44SLuoqi Chen ((u_char *)&oddbyte)[1] = 0; 903b160b8bSBrian Somers sum += oddbyte; 913b160b8bSBrian Somers } 923b160b8bSBrian Somers sum = (sum >> 16) + (sum & 0xffff); 933b160b8bSBrian Somers sum += (sum >> 16); 94ccd57eeaSPaolo Pisati LIBALIAS_UNLOCK(la); 953b160b8bSBrian Somers return (~sum); 963b160b8bSBrian Somers } 973b160b8bSBrian Somers 9859dde15eSGleb Smirnoff #ifndef _KERNEL 993b160b8bSBrian Somers u_short 1003b160b8bSBrian Somers IpChecksum(struct ip *pip) 1013b160b8bSBrian Somers { 10272f2d657SGleb Smirnoff return (LibAliasInternetChecksum(NULL, (u_short *)pip, 1033efa11bbSBrian Somers (pip->ip_hl << 2))); 1043b160b8bSBrian Somers 1053b160b8bSBrian Somers } 1063b160b8bSBrian Somers 1073b160b8bSBrian Somers u_short 1083b160b8bSBrian Somers TcpChecksum(struct ip *pip) 1093b160b8bSBrian Somers { 1103b160b8bSBrian Somers u_short *ptr; 1113b160b8bSBrian Somers struct tcphdr *tc; 1123b160b8bSBrian Somers int nhdr, ntcp, nbytes; 1133b160b8bSBrian Somers int sum, oddbyte; 1143b160b8bSBrian Somers 1153b160b8bSBrian Somers nhdr = pip->ip_hl << 2; 1163b160b8bSBrian Somers ntcp = ntohs(pip->ip_len) - nhdr; 1173b160b8bSBrian Somers 1189fa0fd26SDag-Erling Smørgrav tc = (struct tcphdr *)ip_next(pip); 1193b160b8bSBrian Somers ptr = (u_short *)tc; 1203b160b8bSBrian Somers 1213b160b8bSBrian Somers /* Add up TCP header and data */ 1223b160b8bSBrian Somers nbytes = ntcp; 1233b160b8bSBrian Somers sum = 0; 124f0f93429SDag-Erling Smørgrav while (nbytes > 1) { 1253b160b8bSBrian Somers sum += *ptr++; 1263b160b8bSBrian Somers nbytes -= 2; 1273b160b8bSBrian Somers } 128f0f93429SDag-Erling Smørgrav if (nbytes == 1) { 1293b160b8bSBrian Somers oddbyte = 0; 13046d28b44SLuoqi Chen ((u_char *)&oddbyte)[0] = *(u_char *)ptr; 13146d28b44SLuoqi Chen ((u_char *)&oddbyte)[1] = 0; 1323b160b8bSBrian Somers sum += oddbyte; 1333b160b8bSBrian Somers } 1343b160b8bSBrian Somers /* "Pseudo-header" data */ 1356c7faee2SDag-Erling Smørgrav ptr = (void *)&pip->ip_dst; 1363b160b8bSBrian Somers sum += *ptr++; 1373b160b8bSBrian Somers sum += *ptr; 1386c7faee2SDag-Erling Smørgrav ptr = (void *)&pip->ip_src; 1393b160b8bSBrian Somers sum += *ptr++; 1403b160b8bSBrian Somers sum += *ptr; 1413b160b8bSBrian Somers sum += htons((u_short)ntcp); 1423b160b8bSBrian Somers sum += htons((u_short)pip->ip_p); 1433b160b8bSBrian Somers 1443b160b8bSBrian Somers /* Roll over carry bits */ 1453b160b8bSBrian Somers sum = (sum >> 16) + (sum & 0xffff); 1463b160b8bSBrian Somers sum += (sum >> 16); 1473b160b8bSBrian Somers 1483b160b8bSBrian Somers /* Return checksum */ 1493b160b8bSBrian Somers return ((u_short)~sum); 1503b160b8bSBrian Somers } 15159dde15eSGleb Smirnoff #endif /* not _KERNEL */ 1523b160b8bSBrian Somers 1533b160b8bSBrian Somers void 1542871c501SDag-Erling Smørgrav DifferentialChecksum(u_short *cksum, void *newp, void *oldp, int n) 1553b160b8bSBrian Somers { 1563b160b8bSBrian Somers int i; 1573b160b8bSBrian Somers int accumulate; 1582871c501SDag-Erling Smørgrav u_short *new = newp; 1592871c501SDag-Erling Smørgrav u_short *old = oldp; 1603b160b8bSBrian Somers 1613b160b8bSBrian Somers accumulate = *cksum; 162f0f93429SDag-Erling Smørgrav for (i = 0; i < n; i++) { 1633b160b8bSBrian Somers accumulate -= *new++; 1643b160b8bSBrian Somers accumulate += *old++; 1653b160b8bSBrian Somers } 1663b160b8bSBrian Somers 167f0f93429SDag-Erling Smørgrav if (accumulate < 0) { 1683b160b8bSBrian Somers accumulate = -accumulate; 1693b160b8bSBrian Somers accumulate = (accumulate >> 16) + (accumulate & 0xffff); 1703b160b8bSBrian Somers accumulate += accumulate >> 16; 1713b160b8bSBrian Somers *cksum = (u_short)~accumulate; 172f0f93429SDag-Erling Smørgrav } else { 1733b160b8bSBrian Somers accumulate = (accumulate >> 16) + (accumulate & 0xffff); 1743b160b8bSBrian Somers accumulate += accumulate >> 16; 1753b160b8bSBrian Somers *cksum = (u_short)accumulate; 1763b160b8bSBrian Somers } 1773b160b8bSBrian Somers } 178