|
|
1.1 ! root 1: /* ! 2: * IP checksumming functions. ! 3: * (c) 2008 Gerd Hoffmann <[email protected]> ! 4: * ! 5: * This program is free software; you can redistribute it and/or modify ! 6: * it under the terms of the GNU General Public License as published by ! 7: * the Free Software Foundation; under version 2 of the License. ! 8: * ! 9: * This program is distributed in the hope that it will be useful, ! 10: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 12: * GNU General Public License for more details. ! 13: * ! 14: * You should have received a copy of the GNU General Public License ! 15: * along with this program; if not, see <http://www.gnu.org/licenses/>. ! 16: */ ! 17: ! 18: #include "net/checksum.h" ! 19: ! 20: #define PROTO_TCP 6 ! 21: #define PROTO_UDP 17 ! 22: ! 23: uint32_t net_checksum_add(int len, uint8_t *buf) ! 24: { ! 25: uint32_t sum = 0; ! 26: int i; ! 27: ! 28: for (i = 0; i < len; i++) { ! 29: if (i & 1) ! 30: sum += (uint32_t)buf[i]; ! 31: else ! 32: sum += (uint32_t)buf[i] << 8; ! 33: } ! 34: return sum; ! 35: } ! 36: ! 37: uint16_t net_checksum_finish(uint32_t sum) ! 38: { ! 39: while (sum>>16) ! 40: sum = (sum & 0xFFFF)+(sum >> 16); ! 41: return ~sum; ! 42: } ! 43: ! 44: uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto, ! 45: uint8_t *addrs, uint8_t *buf) ! 46: { ! 47: uint32_t sum = 0; ! 48: ! 49: sum += net_checksum_add(length, buf); // payload ! 50: sum += net_checksum_add(8, addrs); // src + dst address ! 51: sum += proto + length; // protocol & length ! 52: return net_checksum_finish(sum); ! 53: } ! 54: ! 55: void net_checksum_calculate(uint8_t *data, int length) ! 56: { ! 57: int hlen, plen, proto, csum_offset; ! 58: uint16_t csum; ! 59: ! 60: if ((data[14] & 0xf0) != 0x40) ! 61: return; /* not IPv4 */ ! 62: hlen = (data[14] & 0x0f) * 4; ! 63: plen = (data[16] << 8 | data[17]) - hlen; ! 64: proto = data[23]; ! 65: ! 66: switch (proto) { ! 67: case PROTO_TCP: ! 68: csum_offset = 16; ! 69: break; ! 70: case PROTO_UDP: ! 71: csum_offset = 6; ! 72: break; ! 73: default: ! 74: return; ! 75: } ! 76: ! 77: if (plen < csum_offset+2) ! 78: return; ! 79: ! 80: data[14+hlen+csum_offset] = 0; ! 81: data[14+hlen+csum_offset+1] = 0; ! 82: csum = net_checksum_tcpudp(plen, proto, data+14+12, data+14+hlen); ! 83: data[14+hlen+csum_offset] = csum >> 8; ! 84: data[14+hlen+csum_offset+1] = csum & 0xff; ! 85: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.