1 // SPDX-License-Identifier: GPL-2.0+
3 * Generic network code. Moved from net.c
5 * Copyright 1994 - 2000 Neil Russell.
6 * Copyright 2000 Roland Borde
7 * Copyright 2000 Paolo Scaffardi
16 struct in_addr string_to_ip(const char *s)
26 for (addr.s_addr = 0, i = 0; i < 4; ++i) {
27 ulong val = s ? dectoul(s, &e) : 0;
32 if (i != 3 && *e != '.') {
37 addr.s_addr |= (val & 0xFF);
43 addr.s_addr = htonl(addr.s_addr);
47 #if IS_ENABLED(CONFIG_IPV6)
48 int string_to_ip6(const char *str, size_t len, struct in6_addr *addr)
51 int found_double_colon = 0;
52 int xstart = 0; /* first zero (double colon) */
53 int section_num = 7; /* num words the double colon represents */
56 const char *const e = s + len;
57 struct in_addr zero_ip = {.s_addr = 0};
62 /* First pass, verify the syntax and locate the double colon */
64 while (s < e && isxdigit((int)*s))
69 if (*s == '.' && section_num >= 2) {
72 while (s != str && *(s - 1) != ':')
75 if (memcmp(&zero_ip, &v4,
76 sizeof(struct in_addr)) != 0) {
81 /* This could be a valid address */
85 /* The address begins with a colon */
87 /* Must start with a double colon or a number */
91 if (found_double_colon)
98 if (found_double_colon)
99 /* Two double colons are not allowed */
101 found_double_colon = 1;
102 section_num -= xstart;
106 if (++colon_count == 7)
107 /* Found all colons */
112 if (colon_count == 0)
117 /* Second pass, read the address */
119 for (i = 0; i < 8; i++) {
123 if (found_double_colon &&
124 i >= xstart && i < xstart + section_num) {
125 addr->s6_addr16[i] = 0;
131 if (i == 6 && isdigit((int)*s)) {
132 struct in_addr v4 = string_to_ip(s);
134 if (memcmp(&zero_ip, &v4,
135 sizeof(struct in_addr)) != 0) {
136 /* Ending with :IPv4-address */
137 addr->s6_addr32[3] = v4.s_addr;
142 val = simple_strtoul(s, &end, 16);
143 if (end != e && *end != '\0' && *end != ':')
145 addr->s6_addr16[i] = htons(val);
155 void ip_to_string(struct in_addr x, char *s)
157 x.s_addr = ntohl(x.s_addr);
158 sprintf(s, "%d.%d.%d.%d",
159 (int) ((x.s_addr >> 24) & 0xff),
160 (int) ((x.s_addr >> 16) & 0xff),
161 (int) ((x.s_addr >> 8) & 0xff),
162 (int) ((x.s_addr >> 0) & 0xff)
166 void string_to_enetaddr(const char *addr, uint8_t *enetaddr)
174 for (i = 0; i < 6; ++i) {
175 enetaddr[i] = addr ? hextoul(addr, &end) : 0;
177 addr = (*end) ? end + 1 : end;
181 uint compute_ip_checksum(const void *vptr, uint nbytes)
184 const unsigned short *ptr = vptr;
193 ((u8 *)&oddbyte)[0] = *(u8 *)ptr;
194 ((u8 *)&oddbyte)[1] = 0;
197 sum = (sum >> 16) + (sum & 0xffff);
204 uint add_ip_checksums(uint offset, uint sum, uint new)
212 * byte-swap the sum if it came from an odd offset; since the
213 * computation is endian-independent this works.
215 new = ((new >> 8) & 0xff) | ((new << 8) & 0xff00);
217 checksum = sum + new;
218 if (checksum > 0xffff)
221 return (~checksum) & 0xffff;
224 int ip_checksum_ok(const void *addr, uint nbytes)
226 return !(compute_ip_checksum(addr, nbytes) & 0xfffe);