alias_util.c revision 50597
1/* 2 Alias_util.h contains general utilities used by other functions 3 in the packet aliasing module. At the moment, there are functions 4 for computing IP header and TCP packet checksums. 5 6 The checksum routines are based upon example code in a Unix networking 7 text written by Stevens (sorry, I can't remember the title -- but 8 at least this is a good author). 9 10 Initial Version: August, 1996 (cjm) 11 12 Version 1.7: January 9, 1997 13 Added differential checksum update function. 14 15 $FreeBSD: head/sys/netinet/libalias/alias_util.c 50597 1999-08-29 23:17:04Z billf $ 16*/ 17 18/* 19Note: the checksum routines assume that the actual checksum word has 20been zeroed out. If the checksum workd is filled with the proper value, 21then these routines will give a result of zero (useful for testing 22purposes); 23*/ 24 25#include <sys/types.h> 26#include <netinet/in_systm.h> 27#include <netinet/in.h> 28#include <netinet/ip.h> 29#include <netinet/tcp.h> 30 31#include "alias.h" 32#include "alias_local.h" 33 34u_short 35PacketAliasInternetChecksum(u_short *ptr, int nbytes) 36{ 37 int sum, oddbyte; 38 39 sum = 0; 40 while (nbytes > 1) 41 { 42 sum += *ptr++; 43 nbytes -= 2; 44 } 45 if (nbytes == 1) 46 { 47 oddbyte = 0; 48 ((u_char *) &oddbyte)[0] = *(u_char *) ptr; 49 ((u_char *) &oddbyte)[1] = 0; 50 sum += oddbyte; 51 } 52 sum = (sum >> 16) + (sum & 0xffff); 53 sum += (sum >> 16); 54 return(~sum); 55} 56 57u_short 58IpChecksum(struct ip *pip) 59{ 60 return( PacketAliasInternetChecksum((u_short *) pip, 61 (pip->ip_hl << 2)) ); 62 63} 64 65u_short 66TcpChecksum(struct ip *pip) 67{ 68 u_short *ptr; 69 struct tcphdr *tc; 70 int nhdr, ntcp, nbytes; 71 int sum, oddbyte; 72 73 nhdr = pip->ip_hl << 2; 74 ntcp = ntohs(pip->ip_len) - nhdr; 75 76 tc = (struct tcphdr *) ((char *) pip + nhdr); 77 ptr = (u_short *) tc; 78 79/* Add up TCP header and data */ 80 nbytes = ntcp; 81 sum = 0; 82 while (nbytes > 1) 83 { 84 sum += *ptr++; 85 nbytes -= 2; 86 } 87 if (nbytes == 1) 88 { 89 oddbyte = 0; 90 ((u_char *) &oddbyte)[0] = *(u_char *) ptr; 91 ((u_char *) &oddbyte)[1] = 0; 92 sum += oddbyte; 93 } 94 95/* "Pseudo-header" data */ 96 ptr = (u_short *) &(pip->ip_dst); 97 sum += *ptr++; 98 sum += *ptr; 99 ptr = (u_short *) &(pip->ip_src); 100 sum += *ptr++; 101 sum += *ptr; 102 sum += htons((u_short) ntcp); 103 sum += htons((u_short) pip->ip_p); 104 105/* Roll over carry bits */ 106 sum = (sum >> 16) + (sum & 0xffff); 107 sum += (sum >> 16); 108 109/* Return checksum */ 110 return((u_short) ~sum); 111} 112 113 114void 115DifferentialChecksum(u_short *cksum, u_short *new, u_short *old, int n) 116{ 117 int i; 118 int accumulate; 119 120 accumulate = *cksum; 121 for (i=0; i<n; i++) 122 { 123 accumulate -= *new++; 124 accumulate += *old++; 125 } 126 127 if (accumulate < 0) 128 { 129 accumulate = -accumulate; 130 accumulate = (accumulate >> 16) + (accumulate & 0xffff); 131 accumulate += accumulate >> 16; 132 *cksum = (u_short) ~accumulate; 133 } 134 else 135 { 136 accumulate = (accumulate >> 16) + (accumulate & 0xffff); 137 accumulate += accumulate >> 16; 138 *cksum = (u_short) accumulate; 139 } 140} 141 142