xref: /freebsd/sys/netinet/libalias/alias_util.c (revision 9fa0fd268273d90e765d9ebfe0be87ea4d64e138)
1f987e1bdSBrian Somers /*-
2e83aaae3SBrian Somers  * Copyright (c) 2001 Charles Mott <cm@linktel.net>
3f987e1bdSBrian Somers  * All rights reserved.
4f987e1bdSBrian Somers  *
5f987e1bdSBrian Somers  * Redistribution and use in source and binary forms, with or without
6f987e1bdSBrian Somers  * modification, are permitted provided that the following conditions
7f987e1bdSBrian Somers  * are met:
8f987e1bdSBrian Somers  * 1. Redistributions of source code must retain the above copyright
9f987e1bdSBrian Somers  *    notice, this list of conditions and the following disclaimer.
10f987e1bdSBrian Somers  * 2. Redistributions in binary form must reproduce the above copyright
11f987e1bdSBrian Somers  *    notice, this list of conditions and the following disclaimer in the
12f987e1bdSBrian Somers  *    documentation and/or other materials provided with the distribution.
13f987e1bdSBrian Somers  *
14f987e1bdSBrian Somers  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15f987e1bdSBrian Somers  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16f987e1bdSBrian Somers  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17f987e1bdSBrian Somers  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18f987e1bdSBrian Somers  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19f987e1bdSBrian Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20f987e1bdSBrian Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21f987e1bdSBrian Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22f987e1bdSBrian Somers  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23f987e1bdSBrian Somers  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24f987e1bdSBrian Somers  * SUCH DAMAGE.
25f987e1bdSBrian Somers  */
26f987e1bdSBrian Somers 
27e2505aa6SMatthew Dillon #include <sys/cdefs.h>
28e2505aa6SMatthew Dillon __FBSDID("$FreeBSD$");
29e2505aa6SMatthew Dillon 
30e2505aa6SMatthew Dillon 
313b160b8bSBrian Somers /*
3291cc2995SRuslan Ermilov     Alias_util.c contains general utilities used by other functions
333b160b8bSBrian Somers     in the packet aliasing module.  At the moment, there are functions
343b160b8bSBrian Somers     for computing IP header and TCP packet checksums.
353b160b8bSBrian Somers 
363b160b8bSBrian Somers     The checksum routines are based upon example code in a Unix networking
373b160b8bSBrian Somers     text written by Stevens (sorry, I can't remember the title -- but
383b160b8bSBrian Somers     at least this is a good author).
393b160b8bSBrian Somers 
403b160b8bSBrian Somers     Initial Version:  August, 1996  (cjm)
413b160b8bSBrian Somers 
423b160b8bSBrian Somers     Version 1.7:  January 9, 1997
433b160b8bSBrian Somers 	 Added differential checksum update function.
443b160b8bSBrian Somers */
453b160b8bSBrian Somers 
463b160b8bSBrian Somers /*
473b160b8bSBrian Somers Note: the checksum routines assume that the actual checksum word has
4891cc2995SRuslan Ermilov been zeroed out.  If the checksum word is filled with the proper value,
493b160b8bSBrian Somers then these routines will give a result of zero (useful for testing
503b160b8bSBrian Somers purposes);
513b160b8bSBrian Somers */
523b160b8bSBrian Somers 
535e289f9eSPoul-Henning Kamp #include <stdio.h>
543b160b8bSBrian Somers #include <sys/types.h>
553b160b8bSBrian Somers #include <netinet/in_systm.h>
563b160b8bSBrian Somers #include <netinet/in.h>
573b160b8bSBrian Somers #include <netinet/ip.h>
583b160b8bSBrian Somers #include <netinet/tcp.h>
593b160b8bSBrian Somers 
603efa11bbSBrian Somers #include "alias.h"
613b160b8bSBrian Somers #include "alias_local.h"
623b160b8bSBrian Somers 
633b160b8bSBrian Somers u_short
645e289f9eSPoul-Henning Kamp LibAliasInternetChecksum(struct libalias *la, u_short * ptr, int nbytes)
653b160b8bSBrian Somers {
663b160b8bSBrian Somers 	int sum, oddbyte;
673b160b8bSBrian Somers 
68ed01a582SDag-Erling Smørgrav 	(void)la;
69ed01a582SDag-Erling Smørgrav 
703b160b8bSBrian Somers 	sum = 0;
71f0f93429SDag-Erling Smørgrav 	while (nbytes > 1) {
723b160b8bSBrian Somers 		sum += *ptr++;
733b160b8bSBrian Somers 		nbytes -= 2;
743b160b8bSBrian Somers 	}
75f0f93429SDag-Erling Smørgrav 	if (nbytes == 1) {
763b160b8bSBrian Somers 		oddbyte = 0;
7746d28b44SLuoqi Chen 		((u_char *) & oddbyte)[0] = *(u_char *) ptr;
7846d28b44SLuoqi Chen 		((u_char *) & oddbyte)[1] = 0;
793b160b8bSBrian Somers 		sum += oddbyte;
803b160b8bSBrian Somers 	}
813b160b8bSBrian Somers 	sum = (sum >> 16) + (sum & 0xffff);
823b160b8bSBrian Somers 	sum += (sum >> 16);
833b160b8bSBrian Somers 	return (~sum);
843b160b8bSBrian Somers }
853b160b8bSBrian Somers 
863b160b8bSBrian Somers u_short
873b160b8bSBrian Somers IpChecksum(struct ip *pip)
883b160b8bSBrian Somers {
893efa11bbSBrian Somers 	return (PacketAliasInternetChecksum((u_short *) pip,
903efa11bbSBrian Somers 	    (pip->ip_hl << 2)));
913b160b8bSBrian Somers 
923b160b8bSBrian Somers }
933b160b8bSBrian Somers 
943b160b8bSBrian Somers u_short
953b160b8bSBrian Somers TcpChecksum(struct ip *pip)
963b160b8bSBrian Somers {
973b160b8bSBrian Somers 	u_short *ptr;
983b160b8bSBrian Somers 	struct tcphdr *tc;
993b160b8bSBrian Somers 	int nhdr, ntcp, nbytes;
1003b160b8bSBrian Somers 	int sum, oddbyte;
1013b160b8bSBrian Somers 
1023b160b8bSBrian Somers 	nhdr = pip->ip_hl << 2;
1033b160b8bSBrian Somers 	ntcp = ntohs(pip->ip_len) - nhdr;
1043b160b8bSBrian Somers 
1059fa0fd26SDag-Erling Smørgrav 	tc = (struct tcphdr *)ip_next(pip);
1063b160b8bSBrian Somers 	ptr = (u_short *) tc;
1073b160b8bSBrian Somers 
1083b160b8bSBrian Somers /* Add up TCP header and data */
1093b160b8bSBrian Somers 	nbytes = ntcp;
1103b160b8bSBrian Somers 	sum = 0;
111f0f93429SDag-Erling Smørgrav 	while (nbytes > 1) {
1123b160b8bSBrian Somers 		sum += *ptr++;
1133b160b8bSBrian Somers 		nbytes -= 2;
1143b160b8bSBrian Somers 	}
115f0f93429SDag-Erling Smørgrav 	if (nbytes == 1) {
1163b160b8bSBrian Somers 		oddbyte = 0;
11746d28b44SLuoqi Chen 		((u_char *) & oddbyte)[0] = *(u_char *) ptr;
11846d28b44SLuoqi Chen 		((u_char *) & oddbyte)[1] = 0;
1193b160b8bSBrian Somers 		sum += oddbyte;
1203b160b8bSBrian Somers 	}
1213b160b8bSBrian Somers /* "Pseudo-header" data */
1223b160b8bSBrian Somers 	ptr = (u_short *) & (pip->ip_dst);
1233b160b8bSBrian Somers 	sum += *ptr++;
1243b160b8bSBrian Somers 	sum += *ptr;
1253b160b8bSBrian Somers 	ptr = (u_short *) & (pip->ip_src);
1263b160b8bSBrian Somers 	sum += *ptr++;
1273b160b8bSBrian Somers 	sum += *ptr;
1283b160b8bSBrian Somers 	sum += htons((u_short) ntcp);
1293b160b8bSBrian Somers 	sum += htons((u_short) pip->ip_p);
1303b160b8bSBrian Somers 
1313b160b8bSBrian Somers /* Roll over carry bits */
1323b160b8bSBrian Somers 	sum = (sum >> 16) + (sum & 0xffff);
1333b160b8bSBrian Somers 	sum += (sum >> 16);
1343b160b8bSBrian Somers 
1353b160b8bSBrian Somers /* Return checksum */
1363b160b8bSBrian Somers 	return ((u_short) ~ sum);
1373b160b8bSBrian Somers }
1383b160b8bSBrian Somers 
1393b160b8bSBrian Somers 
1403b160b8bSBrian Somers void
1412871c501SDag-Erling Smørgrav DifferentialChecksum(u_short * cksum, void *newp, void *oldp, int n)
1423b160b8bSBrian Somers {
1433b160b8bSBrian Somers 	int i;
1443b160b8bSBrian Somers 	int accumulate;
1452871c501SDag-Erling Smørgrav 	u_short *new = newp;
1462871c501SDag-Erling Smørgrav 	u_short *old = oldp;
1473b160b8bSBrian Somers 
1483b160b8bSBrian Somers 	accumulate = *cksum;
149f0f93429SDag-Erling Smørgrav 	for (i = 0; i < n; i++) {
1503b160b8bSBrian Somers 		accumulate -= *new++;
1513b160b8bSBrian Somers 		accumulate += *old++;
1523b160b8bSBrian Somers 	}
1533b160b8bSBrian Somers 
154f0f93429SDag-Erling Smørgrav 	if (accumulate < 0) {
1553b160b8bSBrian Somers 		accumulate = -accumulate;
1563b160b8bSBrian Somers 		accumulate = (accumulate >> 16) + (accumulate & 0xffff);
1573b160b8bSBrian Somers 		accumulate += accumulate >> 16;
1583b160b8bSBrian Somers 		*cksum = (u_short) ~ accumulate;
159f0f93429SDag-Erling Smørgrav 	} else {
1603b160b8bSBrian Somers 		accumulate = (accumulate >> 16) + (accumulate & 0xffff);
1613b160b8bSBrian Somers 		accumulate += accumulate >> 16;
1623b160b8bSBrian Somers 		*cksum = (u_short) accumulate;
1633b160b8bSBrian Somers 	}
1643b160b8bSBrian Somers }
165