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