xref: /freebsd/sys/netinet/libalias/alias_util.c (revision 46d28b4462cd716e288a57423224bd2fb27609de)
13b160b8bSBrian Somers /*
23b160b8bSBrian Somers     Alias_util.h contains general utilities used by other functions
33b160b8bSBrian Somers     in the packet aliasing module.  At the moment, there are functions
43b160b8bSBrian Somers     for computing IP header and TCP packet checksums.
53b160b8bSBrian Somers 
63b160b8bSBrian Somers     The checksum routines are based upon example code in a Unix networking
73b160b8bSBrian Somers     text written by Stevens (sorry, I can't remember the title -- but
83b160b8bSBrian Somers     at least this is a good author).
93b160b8bSBrian Somers 
103b160b8bSBrian Somers     Initial Version:  August, 1996  (cjm)
113b160b8bSBrian Somers 
123b160b8bSBrian Somers     Version 1.7:  January 9, 1997
133b160b8bSBrian Somers          Added differential checksum update function.
143b160b8bSBrian Somers */
153b160b8bSBrian Somers 
163b160b8bSBrian Somers /*
173b160b8bSBrian Somers Note: the checksum routines assume that the actual checksum word has
183b160b8bSBrian Somers been zeroed out.  If the checksum workd is filled with the proper value,
193b160b8bSBrian Somers then these routines will give a result of zero (useful for testing
203b160b8bSBrian Somers purposes);
213b160b8bSBrian Somers */
223b160b8bSBrian Somers 
233b160b8bSBrian Somers #include <sys/types.h>
243b160b8bSBrian Somers #include <netinet/in_systm.h>
253b160b8bSBrian Somers #include <netinet/in.h>
263b160b8bSBrian Somers #include <netinet/ip.h>
273b160b8bSBrian Somers #include <netinet/tcp.h>
283b160b8bSBrian Somers 
293efa11bbSBrian Somers #include "alias.h"
303b160b8bSBrian Somers #include "alias_local.h"
313b160b8bSBrian Somers 
323b160b8bSBrian Somers u_short
333efa11bbSBrian Somers PacketAliasInternetChecksum(u_short *ptr, int nbytes)
343b160b8bSBrian Somers {
353b160b8bSBrian Somers     int sum, oddbyte;
363b160b8bSBrian Somers 
373b160b8bSBrian Somers     sum = 0;
383b160b8bSBrian Somers     while (nbytes > 1)
393b160b8bSBrian Somers     {
403b160b8bSBrian Somers         sum += *ptr++;
413b160b8bSBrian Somers         nbytes -= 2;
423b160b8bSBrian Somers     }
433b160b8bSBrian Somers     if (nbytes == 1)
443b160b8bSBrian Somers     {
453b160b8bSBrian Somers         oddbyte = 0;
4646d28b44SLuoqi Chen         ((u_char *) &oddbyte)[0] = *(u_char *) ptr;
4746d28b44SLuoqi Chen         ((u_char *) &oddbyte)[1] = 0;
483b160b8bSBrian Somers         sum += oddbyte;
493b160b8bSBrian Somers     }
503b160b8bSBrian Somers     sum = (sum >> 16) + (sum & 0xffff);
513b160b8bSBrian Somers     sum += (sum >> 16);
523b160b8bSBrian Somers     return(~sum);
533b160b8bSBrian Somers }
543b160b8bSBrian Somers 
553b160b8bSBrian Somers u_short
563b160b8bSBrian Somers IpChecksum(struct ip *pip)
573b160b8bSBrian Somers {
583efa11bbSBrian Somers     return( PacketAliasInternetChecksum((u_short *) pip,
593efa11bbSBrian Somers             (pip->ip_hl << 2)) );
603b160b8bSBrian Somers 
613b160b8bSBrian Somers }
623b160b8bSBrian Somers 
633b160b8bSBrian Somers u_short
643b160b8bSBrian Somers TcpChecksum(struct ip *pip)
653b160b8bSBrian Somers {
663b160b8bSBrian Somers     u_short *ptr;
673b160b8bSBrian Somers     struct tcphdr *tc;
683b160b8bSBrian Somers     int nhdr, ntcp, nbytes;
693b160b8bSBrian Somers     int sum, oddbyte;
703b160b8bSBrian Somers 
713b160b8bSBrian Somers     nhdr = pip->ip_hl << 2;
723b160b8bSBrian Somers     ntcp = ntohs(pip->ip_len) - nhdr;
733b160b8bSBrian Somers 
743b160b8bSBrian Somers     tc = (struct tcphdr *) ((char *) pip + nhdr);
753b160b8bSBrian Somers     ptr = (u_short *) tc;
763b160b8bSBrian Somers 
773b160b8bSBrian Somers /* Add up TCP header and data */
783b160b8bSBrian Somers     nbytes = ntcp;
793b160b8bSBrian Somers     sum = 0;
803b160b8bSBrian Somers     while (nbytes > 1)
813b160b8bSBrian Somers     {
823b160b8bSBrian Somers         sum += *ptr++;
833b160b8bSBrian Somers         nbytes -= 2;
843b160b8bSBrian Somers     }
853b160b8bSBrian Somers     if (nbytes == 1)
863b160b8bSBrian Somers     {
873b160b8bSBrian Somers         oddbyte = 0;
8846d28b44SLuoqi Chen         ((u_char *) &oddbyte)[0] = *(u_char *) ptr;
8946d28b44SLuoqi Chen         ((u_char *) &oddbyte)[1] = 0;
903b160b8bSBrian Somers         sum += oddbyte;
913b160b8bSBrian Somers     }
923b160b8bSBrian Somers 
933b160b8bSBrian Somers /* "Pseudo-header" data */
943b160b8bSBrian Somers     ptr = (u_short *) &(pip->ip_dst);
953b160b8bSBrian Somers     sum += *ptr++;
963b160b8bSBrian Somers     sum += *ptr;
973b160b8bSBrian Somers     ptr = (u_short *) &(pip->ip_src);
983b160b8bSBrian Somers     sum += *ptr++;
993b160b8bSBrian Somers     sum += *ptr;
1003b160b8bSBrian Somers     sum += htons((u_short) ntcp);
1013b160b8bSBrian Somers     sum += htons((u_short) pip->ip_p);
1023b160b8bSBrian Somers 
1033b160b8bSBrian Somers /* Roll over carry bits */
1043b160b8bSBrian Somers     sum = (sum >> 16) + (sum & 0xffff);
1053b160b8bSBrian Somers     sum += (sum >> 16);
1063b160b8bSBrian Somers 
1073b160b8bSBrian Somers /* Return checksum */
1083b160b8bSBrian Somers     return((u_short) ~sum);
1093b160b8bSBrian Somers }
1103b160b8bSBrian Somers 
1113b160b8bSBrian Somers 
1123b160b8bSBrian Somers void
1133b160b8bSBrian Somers DifferentialChecksum(u_short *cksum, u_short *new, u_short *old, int n)
1143b160b8bSBrian Somers {
1153b160b8bSBrian Somers     int i;
1163b160b8bSBrian Somers     int accumulate;
1173b160b8bSBrian Somers 
1183b160b8bSBrian Somers     accumulate = *cksum;
1193b160b8bSBrian Somers     for (i=0; i<n; i++)
1203b160b8bSBrian Somers     {
1213b160b8bSBrian Somers         accumulate -= *new++;
1223b160b8bSBrian Somers         accumulate += *old++;
1233b160b8bSBrian Somers     }
1243b160b8bSBrian Somers 
1253b160b8bSBrian Somers     if (accumulate < 0)
1263b160b8bSBrian Somers     {
1273b160b8bSBrian Somers         accumulate = -accumulate;
1283b160b8bSBrian Somers         accumulate = (accumulate >> 16) + (accumulate & 0xffff);
1293b160b8bSBrian Somers         accumulate += accumulate >> 16;
1303b160b8bSBrian Somers         *cksum = (u_short) ~accumulate;
1313b160b8bSBrian Somers     }
1323b160b8bSBrian Somers     else
1333b160b8bSBrian Somers     {
1343b160b8bSBrian Somers         accumulate = (accumulate >> 16) + (accumulate & 0xffff);
1353b160b8bSBrian Somers         accumulate += accumulate >> 16;
1363b160b8bSBrian Somers         *cksum = (u_short) accumulate;
1373b160b8bSBrian Somers     }
1383b160b8bSBrian Somers }
1393b160b8bSBrian Somers 
140