alias_util.c revision 173874
11590Srgrimes/*- 21590Srgrimes * Copyright (c) 2001 Charles Mott <cm@linktel.net> 31590Srgrimes * All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 141590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 151590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 181590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241590Srgrimes * SUCH DAMAGE. 251590Srgrimes */ 261590Srgrimes 271590Srgrimes#include <sys/cdefs.h> 281590Srgrimes__FBSDID("$FreeBSD: head/sys/netinet/libalias/alias_util.c 173874 2007-11-23 23:56:03Z jb $"); 291590Srgrimes 301590Srgrimes 311590Srgrimes/* 321590Srgrimes Alias_util.c contains general utilities used by other functions 331590Srgrimes in the packet aliasing module. At the moment, there are functions 341590Srgrimes for computing IP header and TCP packet checksums. 3527752Scharnier 361590Srgrimes The checksum routines are based upon example code in a Unix networking 371590Srgrimes text written by Stevens (sorry, I can't remember the title -- but 381590Srgrimes at least this is a good author). 391590Srgrimes 401590Srgrimes Initial Version: August, 1996 (cjm) 4127752Scharnier 4223693Speter Version 1.7: January 9, 1997 4327752Scharnier Added differential checksum update function. 4427752Scharnier*/ 4546928Smjacob 461590Srgrimes#ifdef _KERNEL 471590Srgrimes#include <sys/param.h> 481590Srgrimes#include <sys/proc.h> 491590Srgrimes#else 501590Srgrimes#include <sys/types.h> 511590Srgrimes#include <stdio.h> 521590Srgrimes#endif 531590Srgrimes 541590Srgrimes#include <netinet/in_systm.h> 5523693Speter#include <netinet/in.h> 5623693Speter#include <netinet/ip.h> 5727752Scharnier#include <netinet/tcp.h> 581590Srgrimes 5923693Speter#ifdef _KERNEL 601590Srgrimes#include <netinet/libalias/alias.h> 611590Srgrimes#include <netinet/libalias/alias_local.h> 6223693Speter#else 631590Srgrimes#include "alias.h" 647913Sjoerg#include "alias_local.h" 657913Sjoerg#endif 667913Sjoerg 677913Sjoerg/* 687929Sjoerg * Note: the checksum routines assume that the actual checksum word has 697929Sjoerg * been zeroed out. If the checksum word is filled with the proper value, 709541Sjoerg * then these routines will give a result of zero (useful for testing 7139260Sgibbs * purposes); 727913Sjoerg */ 737913Sjoergu_short 7439260SgibbsLibAliasInternetChecksum(struct libalias *la __unused, u_short * ptr, 7539260Sgibbs int nbytes) 7639260Sgibbs{ 7739260Sgibbs int sum, oddbyte; 7839260Sgibbs 7939260Sgibbs LIBALIAS_LOCK(la); 8039260Sgibbs sum = 0; 811590Srgrimes while (nbytes > 1) { 821590Srgrimes sum += *ptr++; 831590Srgrimes nbytes -= 2; 841590Srgrimes } 857913Sjoerg if (nbytes == 1) { 867913Sjoerg oddbyte = 0; 877913Sjoerg ((u_char *) & oddbyte)[0] = *(u_char *) ptr; 881590Srgrimes ((u_char *) & oddbyte)[1] = 0; 891590Srgrimes sum += oddbyte; 901590Srgrimes } 919541Sjoerg sum = (sum >> 16) + (sum & 0xffff); 929541Sjoerg sum += (sum >> 16); 939541Sjoerg LIBALIAS_UNLOCK(la); 949541Sjoerg return (~sum); 959541Sjoerg} 969541Sjoerg 979541Sjoerg#ifndef _KERNEL 981590Srgrimesu_short 991590SrgrimesIpChecksum(struct ip *pip) 1001590Srgrimes{ 1011590Srgrimes return (LibAliasInternetChecksum(NULL, (u_short *) pip, 1021590Srgrimes (pip->ip_hl << 2))); 1031590Srgrimes 10441913Smjacob} 10541913Smjacob 10641913Smjacobu_short 1071590SrgrimesTcpChecksum(struct ip *pip) 10841913Smjacob{ 1097913Sjoerg u_short *ptr; 11039260Sgibbs struct tcphdr *tc; 1117913Sjoerg int nhdr, ntcp, nbytes; 1127929Sjoerg int sum, oddbyte; 1137913Sjoerg void *v; 11428492Sjoerg 11542010Smjacob nhdr = pip->ip_hl << 2; 11642010Smjacob ntcp = ntohs(pip->ip_len) - nhdr; 11742010Smjacob 11842010Smjacob tc = (struct tcphdr *)ip_next(pip); 11939260Sgibbs ptr = (u_short *) tc; 12013401Sjoerg 12141913Smjacob/* Add up TCP header and data */ 12241913Smjacob nbytes = ntcp; 12341913Smjacob sum = 0; 12441913Smjacob while (nbytes > 1) { 12541945Smjacob sum += *ptr++; 12646928Smjacob nbytes -= 2; 12746928Smjacob } 12846928Smjacob if (nbytes == 1) { 12946928Smjacob oddbyte = 0; 1307913Sjoerg ((u_char *) & oddbyte)[0] = *(u_char *) ptr; 1311590Srgrimes ((u_char *) & oddbyte)[1] = 0; 1321590Srgrimes sum += oddbyte; 1331590Srgrimes } 1341590Srgrimes/* "Pseudo-header" data */ 1351590Srgrimes v = &pip->ip_dst; 1361590Srgrimes ptr = v; 1377913Sjoerg sum += *ptr++; 1387913Sjoerg sum += *ptr; 1397929Sjoerg v = &pip->ip_src; 1407929Sjoerg ptr = v; 14139260Sgibbs sum += *ptr++; 14239260Sgibbs sum += *ptr; 14339260Sgibbs sum += htons((u_short) ntcp); 1449541Sjoerg sum += htons((u_short) pip->ip_p); 1457913Sjoerg 1461590Srgrimes/* Roll over carry bits */ 1471590Srgrimes sum = (sum >> 16) + (sum & 0xffff); 1481590Srgrimes sum += (sum >> 16); 1491590Srgrimes 1501590Srgrimes/* Return checksum */ 1511590Srgrimes return ((u_short) ~ sum); 1521590Srgrimes} 1531590Srgrimes#endif /* not _KERNEL */ 1541590Srgrimes 1551590Srgrimesvoid 1561590SrgrimesDifferentialChecksum(u_short * cksum, void *newp, void *oldp, int n) 1571590Srgrimes{ 1581590Srgrimes int i; 1591590Srgrimes int accumulate; 1601590Srgrimes u_short *new = newp; 16124360Simp u_short *old = oldp; 1621590Srgrimes 1631590Srgrimes accumulate = *cksum; 1641590Srgrimes for (i = 0; i < n; i++) { 1651590Srgrimes accumulate -= *new++; 1661590Srgrimes accumulate += *old++; 1671590Srgrimes } 1681590Srgrimes 1691590Srgrimes if (accumulate < 0) { 1701590Srgrimes accumulate = -accumulate; 1711590Srgrimes accumulate = (accumulate >> 16) + (accumulate & 0xffff); 1721590Srgrimes accumulate += accumulate >> 16; 1731590Srgrimes *cksum = (u_short) ~ accumulate; 1741590Srgrimes } else { 1751590Srgrimes accumulate = (accumulate >> 16) + (accumulate & 0xffff); 1761590Srgrimes accumulate += accumulate >> 16; 1771590Srgrimes *cksum = (u_short) accumulate; 1781590Srgrimes } 1791590Srgrimes} 18027752Scharnier