xref: /freebsd/sys/netinet/libalias/alias_util.c (revision f987e1bd0feafc76ea8571b9b3191c026a4d6508)
1f987e1bdSBrian Somers /*-
2f987e1bdSBrian Somers  * Copyright (c) 2001 Charles Mott <cmott@scientech.com>
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  * $FreeBSD$
27f987e1bdSBrian Somers  */
28f987e1bdSBrian Somers 
293b160b8bSBrian Somers /*
3091cc2995SRuslan Ermilov     Alias_util.c contains general utilities used by other functions
313b160b8bSBrian Somers     in the packet aliasing module.  At the moment, there are functions
323b160b8bSBrian Somers     for computing IP header and TCP packet checksums.
333b160b8bSBrian Somers 
343b160b8bSBrian Somers     The checksum routines are based upon example code in a Unix networking
353b160b8bSBrian Somers     text written by Stevens (sorry, I can't remember the title -- but
363b160b8bSBrian Somers     at least this is a good author).
373b160b8bSBrian Somers 
383b160b8bSBrian Somers     Initial Version:  August, 1996  (cjm)
393b160b8bSBrian Somers 
403b160b8bSBrian Somers     Version 1.7:  January 9, 1997
413b160b8bSBrian Somers          Added differential checksum update function.
423b160b8bSBrian Somers */
433b160b8bSBrian Somers 
443b160b8bSBrian Somers /*
453b160b8bSBrian Somers Note: the checksum routines assume that the actual checksum word has
4691cc2995SRuslan Ermilov been zeroed out.  If the checksum word is filled with the proper value,
473b160b8bSBrian Somers then these routines will give a result of zero (useful for testing
483b160b8bSBrian Somers purposes);
493b160b8bSBrian Somers */
503b160b8bSBrian Somers 
513b160b8bSBrian Somers #include <sys/types.h>
523b160b8bSBrian Somers #include <netinet/in_systm.h>
533b160b8bSBrian Somers #include <netinet/in.h>
543b160b8bSBrian Somers #include <netinet/ip.h>
553b160b8bSBrian Somers #include <netinet/tcp.h>
563b160b8bSBrian Somers 
573efa11bbSBrian Somers #include "alias.h"
583b160b8bSBrian Somers #include "alias_local.h"
593b160b8bSBrian Somers 
603b160b8bSBrian Somers u_short
613efa11bbSBrian Somers PacketAliasInternetChecksum(u_short *ptr, int nbytes)
623b160b8bSBrian Somers {
633b160b8bSBrian Somers     int sum, oddbyte;
643b160b8bSBrian Somers 
653b160b8bSBrian Somers     sum = 0;
663b160b8bSBrian Somers     while (nbytes > 1)
673b160b8bSBrian Somers     {
683b160b8bSBrian Somers         sum += *ptr++;
693b160b8bSBrian Somers         nbytes -= 2;
703b160b8bSBrian Somers     }
713b160b8bSBrian Somers     if (nbytes == 1)
723b160b8bSBrian Somers     {
733b160b8bSBrian Somers         oddbyte = 0;
7446d28b44SLuoqi Chen         ((u_char *) &oddbyte)[0] = *(u_char *) ptr;
7546d28b44SLuoqi Chen         ((u_char *) &oddbyte)[1] = 0;
763b160b8bSBrian Somers         sum += oddbyte;
773b160b8bSBrian Somers     }
783b160b8bSBrian Somers     sum = (sum >> 16) + (sum & 0xffff);
793b160b8bSBrian Somers     sum += (sum >> 16);
803b160b8bSBrian Somers     return(~sum);
813b160b8bSBrian Somers }
823b160b8bSBrian Somers 
833b160b8bSBrian Somers u_short
843b160b8bSBrian Somers IpChecksum(struct ip *pip)
853b160b8bSBrian Somers {
863efa11bbSBrian Somers     return( PacketAliasInternetChecksum((u_short *) pip,
873efa11bbSBrian Somers             (pip->ip_hl << 2)) );
883b160b8bSBrian Somers 
893b160b8bSBrian Somers }
903b160b8bSBrian Somers 
913b160b8bSBrian Somers u_short
923b160b8bSBrian Somers TcpChecksum(struct ip *pip)
933b160b8bSBrian Somers {
943b160b8bSBrian Somers     u_short *ptr;
953b160b8bSBrian Somers     struct tcphdr *tc;
963b160b8bSBrian Somers     int nhdr, ntcp, nbytes;
973b160b8bSBrian Somers     int sum, oddbyte;
983b160b8bSBrian Somers 
993b160b8bSBrian Somers     nhdr = pip->ip_hl << 2;
1003b160b8bSBrian Somers     ntcp = ntohs(pip->ip_len) - nhdr;
1013b160b8bSBrian Somers 
1023b160b8bSBrian Somers     tc = (struct tcphdr *) ((char *) pip + nhdr);
1033b160b8bSBrian Somers     ptr = (u_short *) tc;
1043b160b8bSBrian Somers 
1053b160b8bSBrian Somers /* Add up TCP header and data */
1063b160b8bSBrian Somers     nbytes = ntcp;
1073b160b8bSBrian Somers     sum = 0;
1083b160b8bSBrian Somers     while (nbytes > 1)
1093b160b8bSBrian Somers     {
1103b160b8bSBrian Somers         sum += *ptr++;
1113b160b8bSBrian Somers         nbytes -= 2;
1123b160b8bSBrian Somers     }
1133b160b8bSBrian Somers     if (nbytes == 1)
1143b160b8bSBrian Somers     {
1153b160b8bSBrian Somers         oddbyte = 0;
11646d28b44SLuoqi Chen         ((u_char *) &oddbyte)[0] = *(u_char *) ptr;
11746d28b44SLuoqi Chen         ((u_char *) &oddbyte)[1] = 0;
1183b160b8bSBrian Somers         sum += oddbyte;
1193b160b8bSBrian Somers     }
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
1413b160b8bSBrian Somers DifferentialChecksum(u_short *cksum, u_short *new, u_short *old, int n)
1423b160b8bSBrian Somers {
1433b160b8bSBrian Somers     int i;
1443b160b8bSBrian Somers     int accumulate;
1453b160b8bSBrian Somers 
1463b160b8bSBrian Somers     accumulate = *cksum;
1473b160b8bSBrian Somers     for (i=0; i<n; i++)
1483b160b8bSBrian Somers     {
1493b160b8bSBrian Somers         accumulate -= *new++;
1503b160b8bSBrian Somers         accumulate += *old++;
1513b160b8bSBrian Somers     }
1523b160b8bSBrian Somers 
1533b160b8bSBrian Somers     if (accumulate < 0)
1543b160b8bSBrian Somers     {
1553b160b8bSBrian Somers         accumulate = -accumulate;
1563b160b8bSBrian Somers         accumulate = (accumulate >> 16) + (accumulate & 0xffff);
1573b160b8bSBrian Somers         accumulate += accumulate >> 16;
1583b160b8bSBrian Somers         *cksum = (u_short) ~accumulate;
1593b160b8bSBrian Somers     }
1603b160b8bSBrian Somers     else
1613b160b8bSBrian Somers     {
1623b160b8bSBrian Somers         accumulate = (accumulate >> 16) + (accumulate & 0xffff);
1633b160b8bSBrian Somers         accumulate += accumulate >> 16;
1643b160b8bSBrian Somers         *cksum = (u_short) accumulate;
1653b160b8bSBrian Somers     }
1663b160b8bSBrian Somers }
1673b160b8bSBrian Somers 
168