1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Generic network code. Moved from net.c
4 *
5 * Copyright 1994 - 2000 Neil Russell.
6 * Copyright 2000 Roland Borde
7 * Copyright 2000 Paolo Scaffardi
8 * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
9 * Copyright 2009 Dirk Behme, dirk.behme@googlemail.com
10 */
11
12 #include <common.h>
13 #include <net.h>
14
string_to_ip(const char * s)15 struct in_addr string_to_ip(const char *s)
16 {
17 struct in_addr addr;
18 char *e;
19 int i;
20
21 addr.s_addr = 0;
22 if (s == NULL)
23 return addr;
24
25 for (addr.s_addr = 0, i = 0; i < 4; ++i) {
26 ulong val = s ? simple_strtoul(s, &e, 10) : 0;
27 if (val > 255) {
28 addr.s_addr = 0;
29 return addr;
30 }
31 if (i != 3 && *e != '.') {
32 addr.s_addr = 0;
33 return addr;
34 }
35 addr.s_addr <<= 8;
36 addr.s_addr |= (val & 0xFF);
37 if (s) {
38 s = (*e) ? e+1 : e;
39 }
40 }
41
42 addr.s_addr = htonl(addr.s_addr);
43 return addr;
44 }
45
string_to_enetaddr(const char * addr,uint8_t * enetaddr)46 void string_to_enetaddr(const char *addr, uint8_t *enetaddr)
47 {
48 char *end;
49 int i;
50
51 if (!enetaddr)
52 return;
53
54 for (i = 0; i < 6; ++i) {
55 enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0;
56 if (addr)
57 addr = (*end) ? end + 1 : end;
58 }
59 }
60
compute_ip_checksum(const void * vptr,uint nbytes)61 uint compute_ip_checksum(const void *vptr, uint nbytes)
62 {
63 int sum, oddbyte;
64 const unsigned short *ptr = vptr;
65
66 sum = 0;
67 while (nbytes > 1) {
68 sum += *ptr++;
69 nbytes -= 2;
70 }
71 if (nbytes == 1) {
72 oddbyte = 0;
73 ((u8 *)&oddbyte)[0] = *(u8 *)ptr;
74 ((u8 *)&oddbyte)[1] = 0;
75 sum += oddbyte;
76 }
77 sum = (sum >> 16) + (sum & 0xffff);
78 sum += (sum >> 16);
79 sum = ~sum & 0xffff;
80
81 return sum;
82 }
83
add_ip_checksums(uint offset,uint sum,uint new)84 uint add_ip_checksums(uint offset, uint sum, uint new)
85 {
86 ulong checksum;
87
88 sum = ~sum & 0xffff;
89 new = ~new & 0xffff;
90 if (offset & 1) {
91 /*
92 * byte-swap the sum if it came from an odd offset; since the
93 * computation is endian-independent this works.
94 */
95 new = ((new >> 8) & 0xff) | ((new << 8) & 0xff00);
96 }
97 checksum = sum + new;
98 if (checksum > 0xffff)
99 checksum -= 0xffff;
100
101 return (~checksum) & 0xffff;
102 }
103
ip_checksum_ok(const void * addr,uint nbytes)104 int ip_checksum_ok(const void *addr, uint nbytes)
105 {
106 return !(compute_ip_checksum(addr, nbytes) & 0xfffe);
107 }
108