diff --git a/HACKING b/HACKING index df05ff5b7c..976055a086 100644 --- a/HACKING +++ b/HACKING @@ -49,3 +49,7 @@ Third-party Code and License Overview Source: LZMA SDK, http://sourceforge.net/projects/sevenzip/ Current version we use: LZMA SDK 4.40 (05/2006) +* lib/compute_ip_checksum.c, include/ip_checksum.h: GPLv2 + Source: kexec-tools, http://www.xmission.com/~ebiederm/files/kexec/ + Current version we use: kexec-tools 1.101 + diff --git a/include/ip_checksum.h b/include/ip_checksum.h index 485de2c371..b0dfbcd0a1 100644 --- a/include/ip_checksum.h +++ b/include/ip_checksum.h @@ -1,8 +1,29 @@ +/* + * This file is part of the LinuxBIOS project. + * + * It was taken from kexec-tools 1.101. + * + * Copyright (C) 2003,2004 Eric Biederman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + #ifndef IP_CHECKSUM_H #define IP_CHECKSUM_H unsigned long compute_ip_checksum(void *addr, unsigned long length); unsigned long add_ip_checksums(unsigned long offset, unsigned long sum, unsigned long new); +unsigned long negate_ip_checksum(unsigned long sum); #endif /* IP_CHECKSUM_H */ - diff --git a/lib/compute_ip_checksum.c b/lib/compute_ip_checksum.c index 0b8eb90f85..49bdf364bb 100644 --- a/lib/compute_ip_checksum.c +++ b/lib/compute_ip_checksum.c @@ -1,36 +1,78 @@ +/* + * This file is part of the LinuxBIOS project. + * + * It was taken from kexec-tools 1.101. + * + * Copyright (C) 2003,2004 Eric Biederman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + #include #include +#include unsigned long compute_ip_checksum(void *addr, unsigned long length) { - uint8_t *ptr; - volatile union { - uint8_t byte[2]; - uint16_t word; - } value; + uint16_t *ptr; unsigned long sum; - unsigned long i; - /* In the most straight forward way possible, - * compute an ip style checksum. - */ + unsigned long len; + unsigned long laddr; + /* compute an ip style checksum */ + laddr = (unsigned long )addr; sum = 0; - ptr = addr; - for(i = 0; i < length; i++) { - unsigned long value; - value = ptr[i]; - if (i & 1) { - value <<= 8; - } - /* Add the new value */ - sum += value; - /* Wrap around the carry */ - if (sum > 0xFFFF) { - sum = (sum + (sum >> 16)) & 0xFFFF; - } + if (laddr & 1) { + uint16_t buffer; + unsigned char *ptr; + /* copy the first byte into a 2 byte buffer. + * This way automatically handles the endian question + * of which byte (low or high) the last byte goes in. + */ + buffer = 0; + ptr = addr; + memcpy(&buffer, ptr, 1); + sum += buffer; + if (sum > 0xFFFF) + sum -= 0xFFFF; + length -= 1; + addr = ptr +1; + } - value.byte[0] = sum & 0xff; - value.byte[1] = (sum >> 8) & 0xff; - return (~value.word) & 0xFFFF; + len = length >> 1; + ptr = addr; + while (len--) { + sum += *(ptr++); + if (sum > 0xFFFF) + sum -= 0xFFFF; + } + addr = ptr; + if (length & 1) { + uint16_t buffer; + unsigned char *ptr; + /* copy the last byte into a 2 byte buffer. + * This way automatically handles the endian question + * of which byte (low or high) the last byte goes in. + */ + buffer = 0; + ptr = addr; + memcpy(&buffer, ptr, 1); + sum += buffer; + if (sum > 0xFFFF) + sum -= 0xFFFF; + } + return (~sum) & 0xFFFF; + } unsigned long add_ip_checksums(unsigned long offset, unsigned long sum, unsigned long new) @@ -51,3 +93,12 @@ unsigned long add_ip_checksums(unsigned long offset, unsigned long sum, unsigned } return (~checksum) & 0xFFFF; } + +unsigned long negate_ip_checksum(unsigned long sum) +{ + sum = ~sum & 0xFFFF; + + sum = 0xFFFF - sum; + + return ~sum & 0xFFFF; +}