Merge branch '2021-08-02-numeric-input-cleanups'
[platform/kernel/u-boot.git] / lib / net_utils.c
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
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 ? dectoul(s, &e) : 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
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 ? hextoul(addr, &end) : 0;
56                 if (addr)
57                         addr = (*end) ? end + 1 : end;
58         }
59 }
60
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
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
104 int ip_checksum_ok(const void *addr, uint nbytes)
105 {
106         return !(compute_ip_checksum(addr, nbytes) & 0xfffe);
107 }