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