alias_util.c revision 84195
177701Sbrian/*- 277701Sbrian * Copyright (c) 2001 Charles Mott <cmott@scientech.com> 377701Sbrian * All rights reserved. 477701Sbrian * 577701Sbrian * Redistribution and use in source and binary forms, with or without 677701Sbrian * modification, are permitted provided that the following conditions 777701Sbrian * are met: 877701Sbrian * 1. Redistributions of source code must retain the above copyright 977701Sbrian * notice, this list of conditions and the following disclaimer. 1077701Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1177701Sbrian * notice, this list of conditions and the following disclaimer in the 1277701Sbrian * documentation and/or other materials provided with the distribution. 1377701Sbrian * 1477701Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1577701Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1677701Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1777701Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1877701Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1977701Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2077701Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2177701Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2277701Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2377701Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2477701Sbrian * SUCH DAMAGE. 2577701Sbrian */ 2677701Sbrian 2784195Sdillon#include <sys/cdefs.h> 2884195Sdillon__FBSDID("$FreeBSD: head/sys/netinet/libalias/alias_util.c 84195 2001-09-30 21:03:33Z dillon $"); 2984195Sdillon 3084195Sdillon 3126026Sbrian/* 3259031Sru Alias_util.c contains general utilities used by other functions 3326026Sbrian in the packet aliasing module. At the moment, there are functions 3426026Sbrian for computing IP header and TCP packet checksums. 3526026Sbrian 3626026Sbrian The checksum routines are based upon example code in a Unix networking 3726026Sbrian text written by Stevens (sorry, I can't remember the title -- but 3826026Sbrian at least this is a good author). 3926026Sbrian 4026026Sbrian Initial Version: August, 1996 (cjm) 4126026Sbrian 4226026Sbrian Version 1.7: January 9, 1997 4326026Sbrian Added differential checksum update function. 4426026Sbrian*/ 4526026Sbrian 4626026Sbrian/* 4726026SbrianNote: the checksum routines assume that the actual checksum word has 4859031Srubeen zeroed out. If the checksum word is filled with the proper value, 4926026Sbrianthen these routines will give a result of zero (useful for testing 5026026Sbrianpurposes); 5126026Sbrian*/ 5226026Sbrian 5326026Sbrian#include <sys/types.h> 5426026Sbrian#include <netinet/in_systm.h> 5526026Sbrian#include <netinet/in.h> 5626026Sbrian#include <netinet/ip.h> 5726026Sbrian#include <netinet/tcp.h> 5826026Sbrian 5927864Sbrian#include "alias.h" 6026026Sbrian#include "alias_local.h" 6126026Sbrian 6226026Sbrianu_short 6327864SbrianPacketAliasInternetChecksum(u_short *ptr, int nbytes) 6426026Sbrian{ 6526026Sbrian int sum, oddbyte; 6626026Sbrian 6726026Sbrian sum = 0; 6826026Sbrian while (nbytes > 1) 6926026Sbrian { 7026026Sbrian sum += *ptr++; 7126026Sbrian nbytes -= 2; 7226026Sbrian } 7326026Sbrian if (nbytes == 1) 7426026Sbrian { 7526026Sbrian oddbyte = 0; 7645926Sluoqi ((u_char *) &oddbyte)[0] = *(u_char *) ptr; 7745926Sluoqi ((u_char *) &oddbyte)[1] = 0; 7826026Sbrian sum += oddbyte; 7926026Sbrian } 8026026Sbrian sum = (sum >> 16) + (sum & 0xffff); 8126026Sbrian sum += (sum >> 16); 8226026Sbrian return(~sum); 8326026Sbrian} 8426026Sbrian 8526026Sbrianu_short 8626026SbrianIpChecksum(struct ip *pip) 8726026Sbrian{ 8827864Sbrian return( PacketAliasInternetChecksum((u_short *) pip, 8927864Sbrian (pip->ip_hl << 2)) ); 9026026Sbrian 9126026Sbrian} 9226026Sbrian 9326026Sbrianu_short 9426026SbrianTcpChecksum(struct ip *pip) 9526026Sbrian{ 9626026Sbrian u_short *ptr; 9726026Sbrian struct tcphdr *tc; 9826026Sbrian int nhdr, ntcp, nbytes; 9926026Sbrian int sum, oddbyte; 10026026Sbrian 10126026Sbrian nhdr = pip->ip_hl << 2; 10226026Sbrian ntcp = ntohs(pip->ip_len) - nhdr; 10326026Sbrian 10426026Sbrian tc = (struct tcphdr *) ((char *) pip + nhdr); 10526026Sbrian ptr = (u_short *) tc; 10626026Sbrian 10726026Sbrian/* Add up TCP header and data */ 10826026Sbrian nbytes = ntcp; 10926026Sbrian sum = 0; 11026026Sbrian while (nbytes > 1) 11126026Sbrian { 11226026Sbrian sum += *ptr++; 11326026Sbrian nbytes -= 2; 11426026Sbrian } 11526026Sbrian if (nbytes == 1) 11626026Sbrian { 11726026Sbrian oddbyte = 0; 11845926Sluoqi ((u_char *) &oddbyte)[0] = *(u_char *) ptr; 11945926Sluoqi ((u_char *) &oddbyte)[1] = 0; 12026026Sbrian sum += oddbyte; 12126026Sbrian } 12226026Sbrian 12326026Sbrian/* "Pseudo-header" data */ 12426026Sbrian ptr = (u_short *) &(pip->ip_dst); 12526026Sbrian sum += *ptr++; 12626026Sbrian sum += *ptr; 12726026Sbrian ptr = (u_short *) &(pip->ip_src); 12826026Sbrian sum += *ptr++; 12926026Sbrian sum += *ptr; 13026026Sbrian sum += htons((u_short) ntcp); 13126026Sbrian sum += htons((u_short) pip->ip_p); 13226026Sbrian 13326026Sbrian/* Roll over carry bits */ 13426026Sbrian sum = (sum >> 16) + (sum & 0xffff); 13526026Sbrian sum += (sum >> 16); 13626026Sbrian 13726026Sbrian/* Return checksum */ 13826026Sbrian return((u_short) ~sum); 13926026Sbrian} 14026026Sbrian 14126026Sbrian 14226026Sbrianvoid 14326026SbrianDifferentialChecksum(u_short *cksum, u_short *new, u_short *old, int n) 14426026Sbrian{ 14526026Sbrian int i; 14626026Sbrian int accumulate; 14726026Sbrian 14826026Sbrian accumulate = *cksum; 14926026Sbrian for (i=0; i<n; i++) 15026026Sbrian { 15126026Sbrian accumulate -= *new++; 15226026Sbrian accumulate += *old++; 15326026Sbrian } 15426026Sbrian 15526026Sbrian if (accumulate < 0) 15626026Sbrian { 15726026Sbrian accumulate = -accumulate; 15826026Sbrian accumulate = (accumulate >> 16) + (accumulate & 0xffff); 15926026Sbrian accumulate += accumulate >> 16; 16026026Sbrian *cksum = (u_short) ~accumulate; 16126026Sbrian } 16226026Sbrian else 16326026Sbrian { 16426026Sbrian accumulate = (accumulate >> 16) + (accumulate & 0xffff); 16526026Sbrian accumulate += accumulate >> 16; 16626026Sbrian *cksum = (u_short) accumulate; 16726026Sbrian } 16826026Sbrian} 16926026Sbrian 170