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