mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-30 18:05:48 +01:00 
			
		
		
		
	After some header file cleanups to add missing include files, remove common.h from all files in the lib directory. This primarily means just dropping the line but in a few cases we need to add in other header files now. Reviewed-by: Simon Glass <sjg@chromium.org> Signed-off-by: Tom Rini <trini@konsulko.com>
		
			
				
	
	
		
			217 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			217 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0+
 | |
| /*
 | |
|  * Generic network code. Moved from net.c
 | |
|  *
 | |
|  * Copyright 1994 - 2000 Neil Russell.
 | |
|  * Copyright 2000 Roland Borde
 | |
|  * Copyright 2000 Paolo Scaffardi
 | |
|  * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
 | |
|  * Copyright 2009 Dirk Behme, dirk.behme@googlemail.com
 | |
|  */
 | |
| 
 | |
| #include <net.h>
 | |
| #include <net6.h>
 | |
| #include <vsprintf.h>
 | |
| 
 | |
| struct in_addr string_to_ip(const char *s)
 | |
| {
 | |
| 	struct in_addr addr;
 | |
| 	char *e;
 | |
| 	int i;
 | |
| 
 | |
| 	addr.s_addr = 0;
 | |
| 	if (s == NULL)
 | |
| 		return addr;
 | |
| 
 | |
| 	for (addr.s_addr = 0, i = 0; i < 4; ++i) {
 | |
| 		ulong val = s ? dectoul(s, &e) : 0;
 | |
| 		if (val > 255) {
 | |
| 			addr.s_addr = 0;
 | |
| 			return addr;
 | |
| 		}
 | |
| 		if (i != 3 && *e != '.') {
 | |
| 			addr.s_addr = 0;
 | |
| 			return addr;
 | |
| 		}
 | |
| 		addr.s_addr <<= 8;
 | |
| 		addr.s_addr |= (val & 0xFF);
 | |
| 		if (s) {
 | |
| 			s = (*e) ? e+1 : e;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	addr.s_addr = htonl(addr.s_addr);
 | |
| 	return addr;
 | |
| }
 | |
| 
 | |
| #if IS_ENABLED(CONFIG_IPV6)
 | |
| int string_to_ip6(const char *str, size_t len, struct in6_addr *addr)
 | |
| {
 | |
| 	int colon_count = 0;
 | |
| 	int found_double_colon = 0;
 | |
| 	int xstart = 0;		/* first zero (double colon) */
 | |
| 	int section_num = 7;	/* num words the double colon represents */
 | |
| 	int i;
 | |
| 	const char *s = str;
 | |
| 	const char *const e = s + len;
 | |
| 	struct in_addr zero_ip = {.s_addr = 0};
 | |
| 
 | |
| 	if (!str)
 | |
| 		return -1;
 | |
| 
 | |
| 	/* First pass, verify the syntax and locate the double colon */
 | |
| 	while (s < e) {
 | |
| 		while (s < e && isxdigit((int)*s))
 | |
| 			s++;
 | |
| 		if (*s == '\0')
 | |
| 			break;
 | |
| 		if (*s != ':') {
 | |
| 			if (*s == '.' && section_num >= 2) {
 | |
| 				struct in_addr v4;
 | |
| 
 | |
| 				while (s != str && *(s - 1) != ':')
 | |
| 					--s;
 | |
| 				v4 = string_to_ip(s);
 | |
| 				if (memcmp(&zero_ip, &v4,
 | |
| 					   sizeof(struct in_addr)) != 0) {
 | |
| 					section_num -= 2;
 | |
| 					break;
 | |
| 				}
 | |
| 			}
 | |
| 			/* This could be a valid address */
 | |
| 			break;
 | |
| 		}
 | |
| 		if (s == str) {
 | |
| 			/* The address begins with a colon */
 | |
| 			if (*++s != ':')
 | |
| 				/* Must start with a double colon or a number */
 | |
| 				goto out_err;
 | |
| 		} else {
 | |
| 			s++;
 | |
| 			if (found_double_colon)
 | |
| 				section_num--;
 | |
| 			else
 | |
| 				xstart++;
 | |
| 		}
 | |
| 
 | |
| 		if (*s == ':') {
 | |
| 			if (found_double_colon)
 | |
| 				/* Two double colons are not allowed */
 | |
| 				goto out_err;
 | |
| 			found_double_colon = 1;
 | |
| 			section_num -= xstart;
 | |
| 			s++;
 | |
| 		}
 | |
| 
 | |
| 		if (++colon_count == 7)
 | |
| 			/* Found all colons */
 | |
| 			break;
 | |
| 		++s;
 | |
| 	}
 | |
| 
 | |
| 	if (colon_count == 0)
 | |
| 		goto out_err;
 | |
| 	if (*--s == ':')
 | |
| 		section_num++;
 | |
| 
 | |
| 	/* Second pass, read the address */
 | |
| 	s = str;
 | |
| 	for (i = 0; i < 8; i++) {
 | |
| 		int val = 0;
 | |
| 		char *end;
 | |
| 
 | |
| 		if (found_double_colon &&
 | |
| 		    i >= xstart && i < xstart + section_num) {
 | |
| 			addr->s6_addr16[i] = 0;
 | |
| 			continue;
 | |
| 		}
 | |
| 		while (*s == ':')
 | |
| 			s++;
 | |
| 
 | |
| 		if (i == 6 && isdigit((int)*s)) {
 | |
| 			struct in_addr v4 = string_to_ip(s);
 | |
| 
 | |
| 			if (memcmp(&zero_ip, &v4,
 | |
| 				   sizeof(struct in_addr)) != 0) {
 | |
| 				/* Ending with :IPv4-address */
 | |
| 				addr->s6_addr32[3] = v4.s_addr;
 | |
| 				break;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		val = simple_strtoul(s, &end, 16);
 | |
| 		if (end != e && *end != '\0' && *end != ':')
 | |
| 			goto out_err;
 | |
| 		addr->s6_addr16[i] = htons(val);
 | |
| 		s = end;
 | |
| 	}
 | |
| 	return 0;
 | |
| 
 | |
| out_err:
 | |
| 	return -1;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| void string_to_enetaddr(const char *addr, uint8_t *enetaddr)
 | |
| {
 | |
| 	char *end;
 | |
| 	int i;
 | |
| 
 | |
| 	if (!enetaddr)
 | |
| 		return;
 | |
| 
 | |
| 	for (i = 0; i < 6; ++i) {
 | |
| 		enetaddr[i] = addr ? hextoul(addr, &end) : 0;
 | |
| 		if (addr)
 | |
| 			addr = (*end) ? end + 1 : end;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| uint compute_ip_checksum(const void *vptr, uint nbytes)
 | |
| {
 | |
| 	int sum, oddbyte;
 | |
| 	const unsigned short *ptr = vptr;
 | |
| 
 | |
| 	sum = 0;
 | |
| 	while (nbytes > 1) {
 | |
| 		sum += *ptr++;
 | |
| 		nbytes -= 2;
 | |
| 	}
 | |
| 	if (nbytes == 1) {
 | |
| 		oddbyte = 0;
 | |
| 		((u8 *)&oddbyte)[0] = *(u8 *)ptr;
 | |
| 		((u8 *)&oddbyte)[1] = 0;
 | |
| 		sum += oddbyte;
 | |
| 	}
 | |
| 	sum = (sum >> 16) + (sum & 0xffff);
 | |
| 	sum += (sum >> 16);
 | |
| 	sum = ~sum & 0xffff;
 | |
| 
 | |
| 	return sum;
 | |
| }
 | |
| 
 | |
| uint add_ip_checksums(uint offset, uint sum, uint new)
 | |
| {
 | |
| 	ulong checksum;
 | |
| 
 | |
| 	sum = ~sum & 0xffff;
 | |
| 	new = ~new & 0xffff;
 | |
| 	if (offset & 1) {
 | |
| 		/*
 | |
| 		 * byte-swap the sum if it came from an odd offset; since the
 | |
| 		 * computation is endian-independent this works.
 | |
| 		 */
 | |
| 		new = ((new >> 8) & 0xff) | ((new << 8) & 0xff00);
 | |
| 	}
 | |
| 	checksum = sum + new;
 | |
| 	if (checksum > 0xffff)
 | |
| 		checksum -= 0xffff;
 | |
| 
 | |
| 	return (~checksum) & 0xffff;
 | |
| }
 | |
| 
 | |
| int ip_checksum_ok(const void *addr, uint nbytes)
 | |
| {
 | |
| 	return !(compute_ip_checksum(addr, nbytes) & 0xfffe);
 | |
| }
 |