ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync/*-
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * Copyright (c) 2001 Charles Mott <cm@linktel.net>
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * All rights reserved.
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync *
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * Redistribution and use in source and binary forms, with or without
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * modification, are permitted provided that the following conditions
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * are met:
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * 1. Redistributions of source code must retain the above copyright
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * notice, this list of conditions and the following disclaimer.
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * 2. Redistributions in binary form must reproduce the above copyright
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * notice, this list of conditions and the following disclaimer in the
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * documentation and/or other materials provided with the distribution.
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync *
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * SUCH DAMAGE.
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync */
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#ifndef VBOX
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#include <sys/cdefs.h>
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync__FBSDID("$FreeBSD: src/sys/netinet/libalias/alias_util.c,v 1.20.8.1 2009/04/15 03:14:26 kensmith Exp $");
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync/*
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync Alias_util.c contains general utilities used by other functions
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync in the packet aliasing module. At the moment, there are functions
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync for computing IP header and TCP packet checksums.
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync The checksum routines are based upon example code in a Unix networking
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync text written by Stevens (sorry, I can't remember the title -- but
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync at least this is a good author).
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync Initial Version: August, 1996 (cjm)
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync Version 1.7: January 9, 1997
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync Added differential checksum update function.
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync*/
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#ifdef _KERNEL
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#include <sys/param.h>
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#include <sys/proc.h>
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#else
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#include <sys/types.h>
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#include <stdio.h>
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#endif
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#include <netinet/in_systm.h>
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#include <netinet/in.h>
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#include <netinet/ip.h>
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#include <netinet/tcp.h>
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#ifdef _KERNEL
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#include <netinet/libalias/alias.h>
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#include <netinet/libalias/alias_local.h>
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#else
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#include "alias.h"
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#include "alias_local.h"
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#endif
4dd5020158b69719fd7942ff7b996df2d4535bb4vboxsync#else /* VBOX */
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync# include <slirp.h>
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync# include "alias.h"
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync# include "alias_local.h"
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#endif /* VBOX */
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync/*
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * Note: the checksum routines assume that the actual checksum word has
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * been zeroed out. If the checksum word is filled with the proper value,
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * then these routines will give a result of zero (useful for testing
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync * purposes);
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync */
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsyncu_short
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsyncLibAliasInternetChecksum(struct libalias *la __unused, u_short * ptr,
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync int nbytes)
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync{
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync int sum, oddbyte;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync LIBALIAS_LOCK(la);
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync sum = 0;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync while (nbytes > 1) {
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync sum += *ptr++;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync nbytes -= 2;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync }
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync if (nbytes == 1) {
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync oddbyte = 0;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync ((u_char *) & oddbyte)[0] = *(u_char *) ptr;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync ((u_char *) & oddbyte)[1] = 0;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync sum += oddbyte;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync }
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync sum = (sum >> 16) + (sum & 0xffff);
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync sum += (sum >> 16);
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync LIBALIAS_UNLOCK(la);
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync return (~sum);
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync}
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#ifndef _KERNEL
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsyncu_short
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsyncIpChecksum(struct ip *pip)
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync{
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync return (LibAliasInternetChecksum(NULL, (u_short *) pip,
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync (pip->ip_hl << 2)));
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync}
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsyncu_short
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsyncTcpChecksum(struct ip *pip)
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync{
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync u_short *ptr;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync struct tcphdr *tc;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync int nhdr, ntcp, nbytes;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync int sum, oddbyte;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync nhdr = pip->ip_hl << 2;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync ntcp = ntohs(pip->ip_len) - nhdr;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync tc = (struct tcphdr *)ip_next(pip);
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync ptr = (u_short *) tc;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync/* Add up TCP header and data */
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync nbytes = ntcp;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync sum = 0;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync while (nbytes > 1) {
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync sum += *ptr++;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync nbytes -= 2;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync }
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync if (nbytes == 1) {
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync oddbyte = 0;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync ((u_char *) & oddbyte)[0] = *(u_char *) ptr;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync ((u_char *) & oddbyte)[1] = 0;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync sum += oddbyte;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync }
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync/* "Pseudo-header" data */
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync ptr = (u_short *) & (pip->ip_dst);
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync sum += *ptr++;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync sum += *ptr;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync ptr = (u_short *) & (pip->ip_src);
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync sum += *ptr++;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync sum += *ptr;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync sum += htons((u_short) ntcp);
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync sum += htons((u_short) pip->ip_p);
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync/* Roll over carry bits */
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync sum = (sum >> 16) + (sum & 0xffff);
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync sum += (sum >> 16);
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync/* Return checksum */
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync return ((u_short) ~ sum);
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync}
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync#endif /* not _KERNEL */
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsyncvoid
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsyncDifferentialChecksum(u_short * cksum, void *newp, void *oldp, int n)
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync{
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync int i;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync int accumulate;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync u_short *new = newp;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync u_short *old = oldp;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync accumulate = *cksum;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync for (i = 0; i < n; i++) {
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync accumulate -= *new++;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync accumulate += *old++;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync }
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync if (accumulate < 0) {
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync accumulate = -accumulate;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync accumulate = (accumulate >> 16) + (accumulate & 0xffff);
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync accumulate += accumulate >> 16;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync *cksum = (u_short) ~ accumulate;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync } else {
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync accumulate = (accumulate >> 16) + (accumulate & 0xffff);
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync accumulate += accumulate >> 16;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync *cksum = (u_short) accumulate;
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync }
ae9ed83297460a052aeae98394d473e83aeafd1fvboxsync}