Merge tag 'u-boot-imx-20200623' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx
[oweals/u-boot.git] / lib / net_utils.c
index b425a68d9138fcef3854912c308c71221453c519..0a8a557319cf69aa096518e6fdab9a7e18011bf6 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Generic network code. Moved from net.c
  *
  * Copyright 2000 Paolo Scaffardi
  * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
  * Copyright 2009 Dirk Behme, dirk.behme@googlemail.com
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
  */
 
 #include <common.h>
+#include <net.h>
 
-IPaddr_t string_to_ip(const char *s)
+struct in_addr string_to_ip(const char *s)
 {
-       IPaddr_t addr;
+       struct in_addr addr;
        char *e;
        int i;
 
+       addr.s_addr = 0;
        if (s == NULL)
-               return(0);
+               return addr;
 
-       for (addr=0, i=0; i<4; ++i) {
+       for (addr.s_addr = 0, i = 0; i < 4; ++i) {
                ulong val = s ? simple_strtoul(s, &e, 10) : 0;
-               addr <<= 8;
-               addr |= (val & 0xFF);
+               if (val > 255) {
+                       addr.s_addr = 0;
+                       return addr;
+               }
+               if (i != 3 && *e != '.') {
+                       addr.s_addr = 0;
+                       return addr;
+               }
+               addr.s_addr <<= 8;
+               addr.s_addr |= (val & 0xFF);
                if (s) {
                        s = (*e) ? e+1 : e;
                }
        }
 
-       return (htonl(addr));
+       addr.s_addr = htonl(addr.s_addr);
+       return addr;
+}
+
+void string_to_enetaddr(const char *addr, uint8_t *enetaddr)
+{
+       char *end;
+       int i;
+
+       if (!enetaddr)
+               return;
+
+       for (i = 0; i < 6; ++i) {
+               enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0;
+               if (addr)
+                       addr = (*end) ? end + 1 : end;
+       }
+}
+
+uint compute_ip_checksum(const void *vptr, uint nbytes)
+{
+       int sum, oddbyte;
+       const unsigned short *ptr = vptr;
+
+       sum = 0;
+       while (nbytes > 1) {
+               sum += *ptr++;
+               nbytes -= 2;
+       }
+       if (nbytes == 1) {
+               oddbyte = 0;
+               ((u8 *)&oddbyte)[0] = *(u8 *)ptr;
+               ((u8 *)&oddbyte)[1] = 0;
+               sum += oddbyte;
+       }
+       sum = (sum >> 16) + (sum & 0xffff);
+       sum += (sum >> 16);
+       sum = ~sum & 0xffff;
+
+       return sum;
+}
+
+uint add_ip_checksums(uint offset, uint sum, uint new)
+{
+       ulong checksum;
+
+       sum = ~sum & 0xffff;
+       new = ~new & 0xffff;
+       if (offset & 1) {
+               /*
+                * byte-swap the sum if it came from an odd offset; since the
+                * computation is endian-independent this works.
+                */
+               new = ((new >> 8) & 0xff) | ((new << 8) & 0xff00);
+       }
+       checksum = sum + new;
+       if (checksum > 0xffff)
+               checksum -= 0xffff;
+
+       return (~checksum) & 0xffff;
+}
+
+int ip_checksum_ok(const void *addr, uint nbytes)
+{
+       return !(compute_ip_checksum(addr, nbytes) & 0xfffe);
 }