blob: 0a8a557319cf69aa096518e6fdab9a7e18011bf6 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Dirk Behme6a45e382010-01-03 08:33:58 +01002/*
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
Dirk Behme6a45e382010-01-03 08:33:58 +010010 */
11
12#include <common.h>
Simon Glass90526e92020-05-10 11:39:56 -060013#include <net.h>
Dirk Behme6a45e382010-01-03 08:33:58 +010014
Joe Hershberger049a95a2015-04-08 01:41:01 -050015struct in_addr string_to_ip(const char *s)
Dirk Behme6a45e382010-01-03 08:33:58 +010016{
Joe Hershberger049a95a2015-04-08 01:41:01 -050017 struct in_addr addr;
Dirk Behme6a45e382010-01-03 08:33:58 +010018 char *e;
19 int i;
20
Joe Hershberger049a95a2015-04-08 01:41:01 -050021 addr.s_addr = 0;
Dirk Behme6a45e382010-01-03 08:33:58 +010022 if (s == NULL)
Joe Hershberger049a95a2015-04-08 01:41:01 -050023 return addr;
Dirk Behme6a45e382010-01-03 08:33:58 +010024
Joe Hershberger049a95a2015-04-08 01:41:01 -050025 for (addr.s_addr = 0, i = 0; i < 4; ++i) {
Dirk Behme6a45e382010-01-03 08:33:58 +010026 ulong val = s ? simple_strtoul(s, &e, 10) : 0;
Chris Packhamd921ed92017-01-04 13:36:25 +130027 if (val > 255) {
28 addr.s_addr = 0;
29 return addr;
30 }
Chris Packhamf267e402017-01-04 13:36:26 +130031 if (i != 3 && *e != '.') {
32 addr.s_addr = 0;
33 return addr;
34 }
Joe Hershberger049a95a2015-04-08 01:41:01 -050035 addr.s_addr <<= 8;
36 addr.s_addr |= (val & 0xFF);
Dirk Behme6a45e382010-01-03 08:33:58 +010037 if (s) {
38 s = (*e) ? e+1 : e;
39 }
40 }
41
Joe Hershberger049a95a2015-04-08 01:41:01 -050042 addr.s_addr = htonl(addr.s_addr);
43 return addr;
Dirk Behme6a45e382010-01-03 08:33:58 +010044}
Joe Hershbergerfb8977c2019-09-13 19:21:16 -050045
46void 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}
Simon Glassd7210012019-12-06 21:41:39 -070060
61uint 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
84uint 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
104int ip_checksum_ok(const void *addr, uint nbytes)
105{
106 return !(compute_ip_checksum(addr, nbytes) & 0xfffe);
107}