alias_util.c revision 124621
177701Sbrian/*- 285964Sbrian * Copyright (c) 2001 Charles Mott <cm@linktel.net> 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 124621 2004-01-17 10:52:21Z phk $"); 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*/ 5299207Sbrian 53124621Sphk#include <stdio.h> 5426026Sbrian#include <sys/types.h> 5526026Sbrian#include <netinet/in_systm.h> 5626026Sbrian#include <netinet/in.h> 5726026Sbrian#include <netinet/ip.h> 5826026Sbrian#include <netinet/tcp.h> 5926026Sbrian 6027864Sbrian#include "alias.h" 6126026Sbrian#include "alias_local.h" 6226026Sbrian 6326026Sbrianu_short 64124621SphkLibAliasInternetChecksum(struct libalias *la, u_short *ptr, int nbytes) 6526026Sbrian{ 6626026Sbrian int sum, oddbyte; 6726026Sbrian 6826026Sbrian sum = 0; 6926026Sbrian while (nbytes > 1) 7026026Sbrian { 7126026Sbrian sum += *ptr++; 7226026Sbrian nbytes -= 2; 7326026Sbrian } 7426026Sbrian if (nbytes == 1) 7526026Sbrian { 7626026Sbrian oddbyte = 0; 7745926Sluoqi ((u_char *) &oddbyte)[0] = *(u_char *) ptr; 7845926Sluoqi ((u_char *) &oddbyte)[1] = 0; 7926026Sbrian sum += oddbyte; 8026026Sbrian } 8126026Sbrian sum = (sum >> 16) + (sum & 0xffff); 8226026Sbrian sum += (sum >> 16); 8326026Sbrian return(~sum); 8426026Sbrian} 8526026Sbrian 8626026Sbrianu_short 8726026SbrianIpChecksum(struct ip *pip) 8826026Sbrian{ 8927864Sbrian return( PacketAliasInternetChecksum((u_short *) pip, 9027864Sbrian (pip->ip_hl << 2)) ); 9126026Sbrian 9226026Sbrian} 9326026Sbrian 9499207Sbrianu_short 9526026SbrianTcpChecksum(struct ip *pip) 9626026Sbrian{ 9726026Sbrian u_short *ptr; 9826026Sbrian struct tcphdr *tc; 9926026Sbrian int nhdr, ntcp, nbytes; 10026026Sbrian int sum, oddbyte; 10126026Sbrian 10226026Sbrian nhdr = pip->ip_hl << 2; 10326026Sbrian ntcp = ntohs(pip->ip_len) - nhdr; 10426026Sbrian 10526026Sbrian tc = (struct tcphdr *) ((char *) pip + nhdr); 10626026Sbrian ptr = (u_short *) tc; 10799207Sbrian 10826026Sbrian/* Add up TCP header and data */ 10926026Sbrian nbytes = ntcp; 11026026Sbrian sum = 0; 11126026Sbrian while (nbytes > 1) 11226026Sbrian { 11326026Sbrian sum += *ptr++; 11426026Sbrian nbytes -= 2; 11526026Sbrian } 11626026Sbrian if (nbytes == 1) 11726026Sbrian { 11826026Sbrian oddbyte = 0; 11945926Sluoqi ((u_char *) &oddbyte)[0] = *(u_char *) ptr; 12045926Sluoqi ((u_char *) &oddbyte)[1] = 0; 12126026Sbrian sum += oddbyte; 12226026Sbrian } 12326026Sbrian 12426026Sbrian/* "Pseudo-header" data */ 12526026Sbrian ptr = (u_short *) &(pip->ip_dst); 12626026Sbrian sum += *ptr++; 12726026Sbrian sum += *ptr; 12826026Sbrian ptr = (u_short *) &(pip->ip_src); 12926026Sbrian sum += *ptr++; 13026026Sbrian sum += *ptr; 13126026Sbrian sum += htons((u_short) ntcp); 13226026Sbrian sum += htons((u_short) pip->ip_p); 13326026Sbrian 13426026Sbrian/* Roll over carry bits */ 13526026Sbrian sum = (sum >> 16) + (sum & 0xffff); 13626026Sbrian sum += (sum >> 16); 13726026Sbrian 13826026Sbrian/* Return checksum */ 13926026Sbrian return((u_short) ~sum); 14026026Sbrian} 14126026Sbrian 14226026Sbrian 14326026Sbrianvoid 14426026SbrianDifferentialChecksum(u_short *cksum, u_short *new, u_short *old, int n) 14526026Sbrian{ 14626026Sbrian int i; 14726026Sbrian int accumulate; 14826026Sbrian 14926026Sbrian accumulate = *cksum; 15026026Sbrian for (i=0; i<n; i++) 15126026Sbrian { 15226026Sbrian accumulate -= *new++; 15326026Sbrian accumulate += *old++; 15426026Sbrian } 15526026Sbrian 15626026Sbrian if (accumulate < 0) 15726026Sbrian { 15826026Sbrian accumulate = -accumulate; 15926026Sbrian accumulate = (accumulate >> 16) + (accumulate & 0xffff); 16026026Sbrian accumulate += accumulate >> 16; 16126026Sbrian *cksum = (u_short) ~accumulate; 16226026Sbrian } 16326026Sbrian else 16426026Sbrian { 16526026Sbrian accumulate = (accumulate >> 16) + (accumulate & 0xffff); 16626026Sbrian accumulate += accumulate >> 16; 16726026Sbrian *cksum = (u_short) accumulate; 16826026Sbrian } 16926026Sbrian} 17026026Sbrian 171