Coverage Report

Created: 2026-03-11 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/u-boot/lib/net_utils.c
Line
Count
Source
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 <net.h>
13
#include <net6.h>
14
#include <vsprintf.h>
15
16
struct in_addr string_to_ip(const char *s)
17
0
{
18
0
  struct in_addr addr;
19
0
  char *e;
20
0
  int i;
21
22
0
  addr.s_addr = 0;
23
0
  if (s == NULL)
24
0
    return addr;
25
26
0
  for (addr.s_addr = 0, i = 0; i < 4; ++i) {
27
0
    ulong val = s ? dectoul(s, &e) : 0;
28
0
    if (val > 255) {
29
0
      addr.s_addr = 0;
30
0
      return addr;
31
0
    }
32
0
    if (i != 3 && *e != '.') {
33
0
      addr.s_addr = 0;
34
0
      return addr;
35
0
    }
36
0
    addr.s_addr <<= 8;
37
0
    addr.s_addr |= (val & 0xFF);
38
0
    if (s) {
39
0
      s = (*e) ? e+1 : e;
40
0
    }
41
0
  }
42
43
0
  addr.s_addr = htonl(addr.s_addr);
44
0
  return addr;
45
0
}
46
47
#if IS_ENABLED(CONFIG_IPV6)
48
int string_to_ip6(const char *str, size_t len, struct in6_addr *addr)
49
0
{
50
0
  int colon_count = 0;
51
0
  int found_double_colon = 0;
52
0
  int xstart = 0;   /* first zero (double colon) */
53
0
  int section_num = 7;  /* num words the double colon represents */
54
0
  int i;
55
0
  const char *s = str;
56
0
  const char *const e = s + len;
57
0
  struct in_addr zero_ip = {.s_addr = 0};
58
59
0
  if (!str)
60
0
    return -1;
61
62
  /* First pass, verify the syntax and locate the double colon */
63
0
  while (s < e) {
64
0
    while (s < e && isxdigit((int)*s))
65
0
      s++;
66
0
    if (*s == '\0')
67
0
      break;
68
0
    if (*s != ':') {
69
0
      if (*s == '.' && section_num >= 2) {
70
0
        struct in_addr v4;
71
72
0
        while (s != str && *(s - 1) != ':')
73
0
          --s;
74
0
        v4 = string_to_ip(s);
75
0
        if (memcmp(&zero_ip, &v4,
76
0
             sizeof(struct in_addr)) != 0) {
77
0
          section_num -= 2;
78
0
          break;
79
0
        }
80
0
      }
81
      /* This could be a valid address */
82
0
      break;
83
0
    }
84
0
    if (s == str) {
85
      /* The address begins with a colon */
86
0
      if (*++s != ':')
87
        /* Must start with a double colon or a number */
88
0
        goto out_err;
89
0
    } else {
90
0
      s++;
91
0
      if (found_double_colon)
92
0
        section_num--;
93
0
      else
94
0
        xstart++;
95
0
    }
96
97
0
    if (*s == ':') {
98
0
      if (found_double_colon)
99
        /* Two double colons are not allowed */
100
0
        goto out_err;
101
0
      found_double_colon = 1;
102
0
      section_num -= xstart;
103
0
      s++;
104
0
    }
105
106
0
    if (++colon_count == 7)
107
      /* Found all colons */
108
0
      break;
109
0
    ++s;
110
0
  }
111
112
0
  if (colon_count == 0)
113
0
    goto out_err;
114
0
  if (*--s == ':')
115
0
    section_num++;
116
117
  /* Second pass, read the address */
118
0
  s = str;
119
0
  for (i = 0; i < 8; i++) {
120
0
    int val = 0;
121
0
    char *end;
122
123
0
    if (found_double_colon &&
124
0
        i >= xstart && i < xstart + section_num) {
125
0
      addr->s6_addr16[i] = 0;
126
0
      continue;
127
0
    }
128
0
    while (*s == ':')
129
0
      s++;
130
131
0
    if (i == 6 && isdigit((int)*s)) {
132
0
      struct in_addr v4 = string_to_ip(s);
133
134
0
      if (memcmp(&zero_ip, &v4,
135
0
           sizeof(struct in_addr)) != 0) {
136
        /* Ending with :IPv4-address */
137
0
        addr->s6_addr32[3] = v4.s_addr;
138
0
        break;
139
0
      }
140
0
    }
141
142
0
    val = simple_strtoul(s, &end, 16);
143
0
    if (end != e && *end != '\0' && *end != ':')
144
0
      goto out_err;
145
0
    addr->s6_addr16[i] = htons(val);
146
0
    s = end;
147
0
  }
148
0
  return 0;
149
150
0
out_err:
151
0
  return -1;
152
0
}
153
#endif
154
155
void ip_to_string(struct in_addr x, char *s)
156
0
{
157
0
  x.s_addr = ntohl(x.s_addr);
158
0
  sprintf(s, "%d.%d.%d.%d",
159
0
    (int) ((x.s_addr >> 24) & 0xff),
160
0
    (int) ((x.s_addr >> 16) & 0xff),
161
0
    (int) ((x.s_addr >> 8) & 0xff),
162
0
    (int) ((x.s_addr >> 0) & 0xff)
163
0
  );
164
0
}
165
166
void string_to_enetaddr(const char *addr, uint8_t *enetaddr)
167
0
{
168
0
  char *end;
169
0
  int i;
170
171
0
  if (!enetaddr)
172
0
    return;
173
174
0
  for (i = 0; i < 6; ++i) {
175
0
    enetaddr[i] = addr ? hextoul(addr, &end) : 0;
176
0
    if (addr)
177
0
      addr = (*end) ? end + 1 : end;
178
0
  }
179
0
}
180
181
uint compute_ip_checksum(const void *vptr, uint nbytes)
182
0
{
183
0
  int sum, oddbyte;
184
0
  const unsigned short *ptr = vptr;
185
186
0
  sum = 0;
187
0
  while (nbytes > 1) {
188
0
    sum += *ptr++;
189
0
    nbytes -= 2;
190
0
  }
191
0
  if (nbytes == 1) {
192
0
    oddbyte = 0;
193
0
    ((u8 *)&oddbyte)[0] = *(u8 *)ptr;
194
0
    ((u8 *)&oddbyte)[1] = 0;
195
0
    sum += oddbyte;
196
0
  }
197
0
  sum = (sum >> 16) + (sum & 0xffff);
198
0
  sum += (sum >> 16);
199
0
  sum = ~sum & 0xffff;
200
201
0
  return sum;
202
0
}
203
204
uint add_ip_checksums(uint offset, uint sum, uint new)
205
0
{
206
0
  ulong checksum;
207
208
0
  sum = ~sum & 0xffff;
209
0
  new = ~new & 0xffff;
210
0
  if (offset & 1) {
211
    /*
212
     * byte-swap the sum if it came from an odd offset; since the
213
     * computation is endian-independent this works.
214
     */
215
0
    new = ((new >> 8) & 0xff) | ((new << 8) & 0xff00);
216
0
  }
217
0
  checksum = sum + new;
218
0
  if (checksum > 0xffff)
219
0
    checksum -= 0xffff;
220
221
0
  return (~checksum) & 0xffff;
222
0
}
223
224
int ip_checksum_ok(const void *addr, uint nbytes)
225
0
{
226
0
  return !(compute_ip_checksum(addr, nbytes) & 0xfffe);
227
0
}