1 /* $OpenBSD: in_cksum.c,v 1.1 2014/06/20 04:01:42 lteo Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 32 */ 33 34 #include <sys/types.h> 35 36 #include "interface.h" 37 38 /* 39 * Given the host-byte-order value of the checksum field in a packet 40 * header, and the network-byte-order computed checksum of the data 41 * that the checksum covers (including the checksum itself), compute 42 * what the checksum field *should* have been. 43 */ 44 u_int16_t 45 in_cksum_shouldbe(u_int16_t sum, u_int16_t computed_sum) 46 { 47 u_int32_t shouldbe; 48 49 /* 50 * The value that should have gone into the checksum field 51 * is the negative of the value gotten by summing up everything 52 * *but* the checksum field. 53 * 54 * We can compute that by subtracting the value of the checksum 55 * field from the sum of all the data in the packet, and then 56 * computing the negative of that value. 57 * 58 * "sum" is the value of the checksum field, and "computed_sum" 59 * is the negative of the sum of all the data in the packets, 60 * so that's -(-computed_sum - sum), or (sum + computed_sum). 61 * 62 * All the arithmetic in question is one's complement, so the 63 * addition must include an end-around carry; we do this by 64 * doing the arithmetic in 32 bits (with no sign-extension), 65 * and then adding the upper 16 bits of the sum, which contain 66 * the carry, to the lower 16 bits of the sum, and then do it 67 * again in case *that* sum produced a carry. 68 * 69 * As RFC 1071 notes, the checksum can be computed without 70 * byte-swapping the 16-bit words; summing 16-bit words 71 * on a big-endian machine gives a big-endian checksum, which 72 * can be directly stuffed into the big-endian checksum fields 73 * in protocol headers, and summing words on a little-endian 74 * machine gives a little-endian checksum, which must be 75 * byte-swapped before being stuffed into a big-endian checksum 76 * field. 77 * 78 * "computed_sum" is a network-byte-order value, so we must put 79 * it in host byte order before subtracting it from the 80 * host-byte-order value from the header; the adjusted checksum 81 * will be in host byte order, which is what we'll return. 82 */ 83 shouldbe = sum; 84 shouldbe += ntohs(computed_sum); 85 shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16); 86 shouldbe = (shouldbe & 0xFFFF) + (shouldbe >> 16); 87 return shouldbe; 88 } 89