Home | History | Annotate | Download | only in net
      1 // SPDX-License-Identifier: BSD-2-Clause
      2 /*
      3  * This file was originally taken from the FreeBSD project.
      4  *
      5  * Copyright (c) 2001 Charles Mott <cm (at) linktel.net>
      6  * Copyright (c) 2008 coresystems GmbH
      7  * All rights reserved.
      8  */
      9 
     10 #include <common.h>
     11 #include <net.h>
     12 
     13 unsigned compute_ip_checksum(const void *vptr, unsigned nbytes)
     14 {
     15 	int sum, oddbyte;
     16 	const unsigned short *ptr = vptr;
     17 
     18 	sum = 0;
     19 	while (nbytes > 1) {
     20 		sum += *ptr++;
     21 		nbytes -= 2;
     22 	}
     23 	if (nbytes == 1) {
     24 		oddbyte = 0;
     25 		((u8 *)&oddbyte)[0] = *(u8 *)ptr;
     26 		((u8 *)&oddbyte)[1] = 0;
     27 		sum += oddbyte;
     28 	}
     29 	sum = (sum >> 16) + (sum & 0xffff);
     30 	sum += (sum >> 16);
     31 	sum = ~sum & 0xffff;
     32 
     33 	return sum;
     34 }
     35 
     36 unsigned add_ip_checksums(unsigned offset, unsigned sum, unsigned new)
     37 {
     38 	unsigned long checksum;
     39 
     40 	sum = ~sum & 0xffff;
     41 	new = ~new & 0xffff;
     42 	if (offset & 1) {
     43 		/*
     44 		 * byte-swap the sum if it came from an odd offset; since the
     45 		 * computation is endian independant this works.
     46 		 */
     47 		new = ((new >> 8) & 0xff) | ((new << 8) & 0xff00);
     48 	}
     49 	checksum = sum + new;
     50 	if (checksum > 0xffff)
     51 		checksum -= 0xffff;
     52 
     53 	return (~checksum) & 0xffff;
     54 }
     55 
     56 int ip_checksum_ok(const void *addr, unsigned nbytes)
     57 {
     58 	return !(compute_ip_checksum(addr, nbytes) & 0xfffe);
     59 }
     60