1f987e1bdSBrian Somers /*- 2f987e1bdSBrian Somers * Copyright (c) 2001 Charles Mott <cmott@scientech.com> 3f987e1bdSBrian Somers * All rights reserved. 4f987e1bdSBrian Somers * 5f987e1bdSBrian Somers * Redistribution and use in source and binary forms, with or without 6f987e1bdSBrian Somers * modification, are permitted provided that the following conditions 7f987e1bdSBrian Somers * are met: 8f987e1bdSBrian Somers * 1. Redistributions of source code must retain the above copyright 9f987e1bdSBrian Somers * notice, this list of conditions and the following disclaimer. 10f987e1bdSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright 11f987e1bdSBrian Somers * notice, this list of conditions and the following disclaimer in the 12f987e1bdSBrian Somers * documentation and/or other materials provided with the distribution. 13f987e1bdSBrian Somers * 14f987e1bdSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15f987e1bdSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16f987e1bdSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17f987e1bdSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18f987e1bdSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19f987e1bdSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20f987e1bdSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21f987e1bdSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22f987e1bdSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23f987e1bdSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24f987e1bdSBrian Somers * SUCH DAMAGE. 25f987e1bdSBrian Somers * 26f987e1bdSBrian Somers * $FreeBSD$ 27f987e1bdSBrian Somers */ 28f987e1bdSBrian Somers 293b160b8bSBrian Somers /* 3091cc2995SRuslan Ermilov Alias_util.c contains general utilities used by other functions 313b160b8bSBrian Somers in the packet aliasing module. At the moment, there are functions 323b160b8bSBrian Somers for computing IP header and TCP packet checksums. 333b160b8bSBrian Somers 343b160b8bSBrian Somers The checksum routines are based upon example code in a Unix networking 353b160b8bSBrian Somers text written by Stevens (sorry, I can't remember the title -- but 363b160b8bSBrian Somers at least this is a good author). 373b160b8bSBrian Somers 383b160b8bSBrian Somers Initial Version: August, 1996 (cjm) 393b160b8bSBrian Somers 403b160b8bSBrian Somers Version 1.7: January 9, 1997 413b160b8bSBrian Somers Added differential checksum update function. 423b160b8bSBrian Somers */ 433b160b8bSBrian Somers 443b160b8bSBrian Somers /* 453b160b8bSBrian Somers Note: the checksum routines assume that the actual checksum word has 4691cc2995SRuslan Ermilov been zeroed out. If the checksum word is filled with the proper value, 473b160b8bSBrian Somers then these routines will give a result of zero (useful for testing 483b160b8bSBrian Somers purposes); 493b160b8bSBrian Somers */ 503b160b8bSBrian Somers 513b160b8bSBrian Somers #include <sys/types.h> 523b160b8bSBrian Somers #include <netinet/in_systm.h> 533b160b8bSBrian Somers #include <netinet/in.h> 543b160b8bSBrian Somers #include <netinet/ip.h> 553b160b8bSBrian Somers #include <netinet/tcp.h> 563b160b8bSBrian Somers 573efa11bbSBrian Somers #include "alias.h" 583b160b8bSBrian Somers #include "alias_local.h" 593b160b8bSBrian Somers 603b160b8bSBrian Somers u_short 613efa11bbSBrian Somers PacketAliasInternetChecksum(u_short *ptr, int nbytes) 623b160b8bSBrian Somers { 633b160b8bSBrian Somers int sum, oddbyte; 643b160b8bSBrian Somers 653b160b8bSBrian Somers sum = 0; 663b160b8bSBrian Somers while (nbytes > 1) 673b160b8bSBrian Somers { 683b160b8bSBrian Somers sum += *ptr++; 693b160b8bSBrian Somers nbytes -= 2; 703b160b8bSBrian Somers } 713b160b8bSBrian Somers if (nbytes == 1) 723b160b8bSBrian Somers { 733b160b8bSBrian Somers oddbyte = 0; 7446d28b44SLuoqi Chen ((u_char *) &oddbyte)[0] = *(u_char *) ptr; 7546d28b44SLuoqi Chen ((u_char *) &oddbyte)[1] = 0; 763b160b8bSBrian Somers sum += oddbyte; 773b160b8bSBrian Somers } 783b160b8bSBrian Somers sum = (sum >> 16) + (sum & 0xffff); 793b160b8bSBrian Somers sum += (sum >> 16); 803b160b8bSBrian Somers return(~sum); 813b160b8bSBrian Somers } 823b160b8bSBrian Somers 833b160b8bSBrian Somers u_short 843b160b8bSBrian Somers IpChecksum(struct ip *pip) 853b160b8bSBrian Somers { 863efa11bbSBrian Somers return( PacketAliasInternetChecksum((u_short *) pip, 873efa11bbSBrian Somers (pip->ip_hl << 2)) ); 883b160b8bSBrian Somers 893b160b8bSBrian Somers } 903b160b8bSBrian Somers 913b160b8bSBrian Somers u_short 923b160b8bSBrian Somers TcpChecksum(struct ip *pip) 933b160b8bSBrian Somers { 943b160b8bSBrian Somers u_short *ptr; 953b160b8bSBrian Somers struct tcphdr *tc; 963b160b8bSBrian Somers int nhdr, ntcp, nbytes; 973b160b8bSBrian Somers int sum, oddbyte; 983b160b8bSBrian Somers 993b160b8bSBrian Somers nhdr = pip->ip_hl << 2; 1003b160b8bSBrian Somers ntcp = ntohs(pip->ip_len) - nhdr; 1013b160b8bSBrian Somers 1023b160b8bSBrian Somers tc = (struct tcphdr *) ((char *) pip + nhdr); 1033b160b8bSBrian Somers ptr = (u_short *) tc; 1043b160b8bSBrian Somers 1053b160b8bSBrian Somers /* Add up TCP header and data */ 1063b160b8bSBrian Somers nbytes = ntcp; 1073b160b8bSBrian Somers sum = 0; 1083b160b8bSBrian Somers while (nbytes > 1) 1093b160b8bSBrian Somers { 1103b160b8bSBrian Somers sum += *ptr++; 1113b160b8bSBrian Somers nbytes -= 2; 1123b160b8bSBrian Somers } 1133b160b8bSBrian Somers if (nbytes == 1) 1143b160b8bSBrian Somers { 1153b160b8bSBrian Somers oddbyte = 0; 11646d28b44SLuoqi Chen ((u_char *) &oddbyte)[0] = *(u_char *) ptr; 11746d28b44SLuoqi Chen ((u_char *) &oddbyte)[1] = 0; 1183b160b8bSBrian Somers sum += oddbyte; 1193b160b8bSBrian Somers } 1203b160b8bSBrian Somers 1213b160b8bSBrian Somers /* "Pseudo-header" data */ 1223b160b8bSBrian Somers ptr = (u_short *) &(pip->ip_dst); 1233b160b8bSBrian Somers sum += *ptr++; 1243b160b8bSBrian Somers sum += *ptr; 1253b160b8bSBrian Somers ptr = (u_short *) &(pip->ip_src); 1263b160b8bSBrian Somers sum += *ptr++; 1273b160b8bSBrian Somers sum += *ptr; 1283b160b8bSBrian Somers sum += htons((u_short) ntcp); 1293b160b8bSBrian Somers sum += htons((u_short) pip->ip_p); 1303b160b8bSBrian Somers 1313b160b8bSBrian Somers /* Roll over carry bits */ 1323b160b8bSBrian Somers sum = (sum >> 16) + (sum & 0xffff); 1333b160b8bSBrian Somers sum += (sum >> 16); 1343b160b8bSBrian Somers 1353b160b8bSBrian Somers /* Return checksum */ 1363b160b8bSBrian Somers return((u_short) ~sum); 1373b160b8bSBrian Somers } 1383b160b8bSBrian Somers 1393b160b8bSBrian Somers 1403b160b8bSBrian Somers void 1413b160b8bSBrian Somers DifferentialChecksum(u_short *cksum, u_short *new, u_short *old, int n) 1423b160b8bSBrian Somers { 1433b160b8bSBrian Somers int i; 1443b160b8bSBrian Somers int accumulate; 1453b160b8bSBrian Somers 1463b160b8bSBrian Somers accumulate = *cksum; 1473b160b8bSBrian Somers for (i=0; i<n; i++) 1483b160b8bSBrian Somers { 1493b160b8bSBrian Somers accumulate -= *new++; 1503b160b8bSBrian Somers accumulate += *old++; 1513b160b8bSBrian Somers } 1523b160b8bSBrian Somers 1533b160b8bSBrian Somers if (accumulate < 0) 1543b160b8bSBrian Somers { 1553b160b8bSBrian Somers accumulate = -accumulate; 1563b160b8bSBrian Somers accumulate = (accumulate >> 16) + (accumulate & 0xffff); 1573b160b8bSBrian Somers accumulate += accumulate >> 16; 1583b160b8bSBrian Somers *cksum = (u_short) ~accumulate; 1593b160b8bSBrian Somers } 1603b160b8bSBrian Somers else 1613b160b8bSBrian Somers { 1623b160b8bSBrian Somers accumulate = (accumulate >> 16) + (accumulate & 0xffff); 1633b160b8bSBrian Somers accumulate += accumulate >> 16; 1643b160b8bSBrian Somers *cksum = (u_short) accumulate; 1653b160b8bSBrian Somers } 1663b160b8bSBrian Somers } 1673b160b8bSBrian Somers 168