summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/Kconfig29
-rw-r--r--net/Makefile3
-rw-r--r--net/dhcp.c47
-rw-r--r--net/dns.c16
-rw-r--r--net/eth.c294
-rw-r--r--net/fastboot.c589
-rw-r--r--net/ifup.c244
-rw-r--r--net/lib.c34
-rw-r--r--net/net.c288
-rw-r--r--net/netconsole.c22
-rw-r--r--net/nfs.c7
-rw-r--r--net/nfs.h74
-rw-r--r--net/ping.c2
-rw-r--r--net/rarp.h40
-rw-r--r--net/sntp.c13
15 files changed, 1347 insertions, 355 deletions
diff --git a/net/Kconfig b/net/Kconfig
index 12b6bdb56d..07e623670e 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -1,8 +1,28 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
menuconfig NET
bool "Networking Support"
+ select POLLER
if NET
+config NET_ETHADDR_FROM_MACHINE_ID
+ bool
+ prompt "generate stable Ethernet address"
+ depends on MACHINE_ID && HAVE_DIGEST_SHA256 && HAVE_DIGEST_HMAC
+ help
+ By default, barebox will generate random Ethernet addresses for
+ interfaces that had no explicit Ethernet address set via
+ either board code or NVMEM properties in device tree.
+
+ Say y here, to randomize Ethernet addresses only if no machine ID
+ is available. Should barebox have a machine ID, it will be used
+ alongside the hostname to generate MAC addresses that are unlikely
+ to change between subsequent runs of barebox.
+
+ This is not recommended for use in production as it may leak
+ information about the machine ID.
+
config NET_NFS
bool
prompt "nfs support"
@@ -31,4 +51,13 @@ config NET_SNTP
bool
prompt "sntp support"
+config NET_FASTBOOT
+ bool
+ select BANNER
+ select FASTBOOT_BASE
+ prompt "Android Fastboot support"
+ help
+ This option adds support for the UDP variant of the Fastboot
+ protocol.
+
endif
diff --git a/net/Makefile b/net/Makefile
index eb8d439150..c93d0772c3 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
obj-y += lib.o
obj-$(CONFIG_NET) += eth.o
obj-$(CONFIG_NET) += net.o
@@ -8,3 +10,4 @@ obj-$(CONFIG_CMD_PING) += ping.o
obj-$(CONFIG_NET_RESOLV)+= dns.o
obj-$(CONFIG_NET_NETCONSOLE) += netconsole.o
obj-$(CONFIG_NET_IFUP) += ifup.o
+obj-$(CONFIG_NET_FASTBOOT) += fastboot.o
diff --git a/net/dhcp.c b/net/dhcp.c
index 670a6a6422..e1025bf91b 100644
--- a/net/dhcp.c
+++ b/net/dhcp.c
@@ -1,11 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 1994, 1995, 2000 Neil Russell
+// SPDX-FileCopyrightText: 2000 Roland Borde
+// SPDX-FileCopyrightText: 2000 Paolo Scaffardi
+// SPDX-FileCopyrightText: 2000-2004 Wolfgang Denk, wd@denx.de
/*
- * Based on LiMon - BOOTP.
+ * dhcp.c - barebox dhcp support
*
- * Copyright 1994, 1995, 2000 Neil Russell.
- * (See License)
- * Copyright 2000 Roland Borde
- * Copyright 2000 Paolo Scaffardi
- * Copyright 2000-2004 Wolfgang Denk, wd@denx.de
+ * based on U-Boot (LiMon) code
*/
#include <common.h>
@@ -444,6 +445,7 @@ static char *global_dhcp_user_class;
static char *global_dhcp_vendor_id;
static char *global_dhcp_client_uuid;
static char *global_dhcp_client_id;
+static char *global_dhcp_hostname;
static char *global_dhcp_bootfile;
static char *global_dhcp_oftree_file;
static char *global_dhcp_rootpath;
@@ -482,6 +484,12 @@ int dhcp_request(struct eth_device *edev, const struct dhcp_req_param *param,
dhcp_param.client_uuid = global_dhcp_client_uuid;
if (!dhcp_param.client_id)
dhcp_param.client_id = global_dhcp_client_id;
+ if (!dhcp_param.hostname) {
+ if (global_dhcp_hostname && strlen(global_dhcp_hostname))
+ dhcp_param.hostname = global_dhcp_hostname;
+ else
+ dhcp_param.hostname = (char *)barebox_get_hostname();
+ }
if (!dhcp_param.option224)
dhcp_param.option224 = global_dhcp_option224;
if (!dhcp_param.retries)
@@ -609,6 +617,10 @@ int dhcp(struct eth_device *edev, const struct dhcp_req_param *param)
struct dhcp_result *res;
int ret;
+ ret = eth_open(edev);
+ if (ret)
+ return ret;
+
ret = dhcp_request(edev, param, &res);
if (ret)
return ret;
@@ -629,9 +641,12 @@ static int dhcp_global_init(void)
{
globalvar_add_simple_string("dhcp.bootfile", &global_dhcp_bootfile);
globalvar_add_simple_string("dhcp.rootpath", &global_dhcp_rootpath);
+
+ global_dhcp_vendor_id = strdup("barebox");
globalvar_add_simple_string("dhcp.vendor_id", &global_dhcp_vendor_id);
globalvar_add_simple_string("dhcp.client_uuid", &global_dhcp_client_uuid);
globalvar_add_simple_string("dhcp.client_id", &global_dhcp_client_id);
+ globalvar_add_simple_string("dhcp.hostname", &global_dhcp_hostname);
globalvar_add_simple_string("dhcp.user_class", &global_dhcp_user_class);
globalvar_add_simple_string("dhcp.oftree_file", &global_dhcp_oftree_file);
globalvar_add_simple_string("dhcp.tftp_server_name", &global_dhcp_tftp_server_name);
@@ -643,13 +658,13 @@ static int dhcp_global_init(void)
late_initcall(dhcp_global_init);
#endif
-BAREBOX_MAGICVAR_NAMED(global_dhcp_bootfile, global.dhcp.bootfile, "bootfile returned from DHCP request");
-BAREBOX_MAGICVAR_NAMED(global_dhcp_rootpath, global.dhcp.rootpath, "rootpath returned from DHCP request");
-BAREBOX_MAGICVAR_NAMED(global_dhcp_vendor_id, global.dhcp.vendor_id, "vendor id to send to the DHCP server");
-BAREBOX_MAGICVAR_NAMED(global_dhcp_client_uuid, global.dhcp.client_uuid, "client uuid to send to the DHCP server");
-BAREBOX_MAGICVAR_NAMED(global_dhcp_client_id, global.dhcp.client_id, "client id to send to the DHCP server");
-BAREBOX_MAGICVAR_NAMED(global_dhcp_user_class, global.dhcp.user_class, "user class to send to the DHCP server");
-BAREBOX_MAGICVAR_NAMED(global_dhcp_tftp_server_name, global.dhcp.tftp_server_name, "TFTP server Name returned from DHCP request");
-BAREBOX_MAGICVAR_NAMED(global_dhcp_oftree_file, global.dhcp.oftree_file, "OF tree returned from DHCP request (option 224)");
-BAREBOX_MAGICVAR_NAMED(global_dhcp_retries, global.dhcp.retries, "retry limit");
-BAREBOX_MAGICVAR_NAMED(global_dhcp_option224, global.dhcp.option224, "private data to send to the DHCP server (option 224)");
+BAREBOX_MAGICVAR(global.dhcp.bootfile, "bootfile returned from DHCP request");
+BAREBOX_MAGICVAR(global.dhcp.rootpath, "rootpath returned from DHCP request");
+BAREBOX_MAGICVAR(global.dhcp.vendor_id, "vendor id to send to the DHCP server");
+BAREBOX_MAGICVAR(global.dhcp.client_uuid, "client uuid to send to the DHCP server");
+BAREBOX_MAGICVAR(global.dhcp.client_id, "client id to send to the DHCP server");
+BAREBOX_MAGICVAR(global.dhcp.user_class, "user class to send to the DHCP server");
+BAREBOX_MAGICVAR(global.dhcp.tftp_server_name, "TFTP server Name returned from DHCP request");
+BAREBOX_MAGICVAR(global.dhcp.oftree_file, "OF tree returned from DHCP request (option 224)");
+BAREBOX_MAGICVAR(global.dhcp.retries, "retry limit");
+BAREBOX_MAGICVAR(global.dhcp.option224, "private data to send to the DHCP server (option 224)");
diff --git a/net/dns.c b/net/dns.c
index ffe98ef9e3..fdddb3f915 100644
--- a/net/dns.c
+++ b/net/dns.c
@@ -58,6 +58,7 @@ struct header {
static struct net_connection *dns_con;
static uint64_t dns_timer_start;
+static uint16_t dns_req_id;
static int dns_state;
static IPaddr_t dns_ip;
@@ -70,9 +71,12 @@ static int dns_send(const char *name)
unsigned char *p, *s, *fullname, *dotptr;
const unsigned char *domain;
+ /* generate "difficult" to predict transaction id */
+ dns_req_id = dns_timer_start + (dns_timer_start >> 16);
+
/* Prepare DNS packet header */
header = (struct header *)packet;
- header->tid = 1;
+ header->tid = htons(dns_req_id);
header->flags = htons(0x100); /* standard query */
header->nqueries = htons(1); /* Just one query */
header->nanswers = 0;
@@ -127,6 +131,12 @@ static void dns_recv(struct header *header, unsigned len)
pr_debug("%s\n", __func__);
+ /* Only accept responses with the expected request id */
+ if (ntohs(header->tid) != dns_req_id) {
+ pr_debug("DNS response with incorrect id\n");
+ return;
+ }
+
/* We sent 1 query. We want to see more that 1 answer. */
if (ntohs(header->nqueries) != 1)
return;
@@ -215,8 +225,8 @@ int resolv(const char *host, IPaddr_t *ip)
nameserver = net_get_nameserver();
if (!nameserver) {
- pr_err("no nameserver specified in $net.nameserver\n");
- return 0;
+ pr_err("no nameserver specified in $global.net.nameserver\n");
+ return -ENOENT;
}
pr_debug("resolving host %s via nameserver %pI4\n", host, &nameserver);
diff --git a/net/eth.c b/net/eth.c
index 53d24baa16..28961e868b 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -1,21 +1,5 @@
-/*
- * (C) Copyright 2001-2004
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * 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.
- *
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2001-2004 Wolfgang Denk <wd@denx.de>, DENX Software Engineering
#include <common.h>
#include <command.h>
@@ -25,7 +9,10 @@
#include <init.h>
#include <dhcp.h>
#include <net.h>
+#include <dma.h>
+#include <machine_id.h>
#include <of.h>
+#include <of_net.h>
#include <linux/phy.h>
#include <errno.h>
#include <malloc.h>
@@ -34,8 +21,6 @@
#include <linux/ctype.h>
#include <linux/stat.h>
-static uint64_t last_link_check;
-
LIST_HEAD(netdev_list);
struct eth_ethaddr {
@@ -47,6 +32,14 @@ struct eth_ethaddr {
static LIST_HEAD(ethaddr_list);
+int eth_set_promisc(struct eth_device *edev, bool enable)
+{
+ if (!edev->set_promisc)
+ return -EOPNOTSUPP;
+
+ return edev->set_promisc(edev, enable);
+}
+
int eth_set_ethaddr(struct eth_device *edev, const char *ethaddr)
{
int ret;
@@ -62,11 +55,8 @@ int eth_set_ethaddr(struct eth_device *edev, const char *ethaddr)
static void register_preset_mac_address(struct eth_device *edev, const char *ethaddr)
{
- unsigned char ethaddr_str[sizeof("xx:xx:xx:xx:xx:xx")];
-
if (is_valid_ether_addr(ethaddr)) {
- ethaddr_to_string(ethaddr, ethaddr_str);
- dev_info(&edev->dev, "got preset MAC address: %s\n", ethaddr_str);
+ dev_info(&edev->dev, "got preset MAC address: %pM\n", ethaddr);
eth_set_ethaddr(edev, ethaddr);
}
}
@@ -77,7 +67,7 @@ static int eth_get_registered_ethaddr(struct eth_device *edev, void *buf)
struct device_node *node = NULL;
if (edev->parent)
- node = edev->parent->device_node;
+ node = edev->parent->of_node;
list_for_each_entry(addr, &ethaddr_list, list) {
if ((node && node == addr->node) ||
@@ -129,9 +119,9 @@ static struct eth_device *eth_get_by_node(struct device_node *node)
for_each_netdev(edev) {
if (!edev->parent)
continue;
- if (!edev->parent->device_node)
+ if (!edev->parent->of_node)
continue;
- if (edev->parent->device_node == node)
+ if (edev->parent->of_node == node)
return edev;
}
return NULL;
@@ -184,10 +174,7 @@ int eth_complete(struct string_list *sl, char *instr)
}
#endif
-/*
- * Check for link if we haven't done so for longer.
- */
-static int eth_carrier_check(struct eth_device *edev, int force)
+int eth_carrier_poll_once(struct eth_device *edev)
{
int ret;
@@ -197,70 +184,119 @@ static int eth_carrier_check(struct eth_device *edev, int force)
if (!edev->phydev)
return 0;
- if (force)
- phy_wait_aneg_done(edev->phydev);
-
- if (force || is_timeout(last_link_check, 5 * SECOND) ||
- !edev->phydev->link) {
- ret = phy_update_status(edev->phydev);
- if (ret)
- return ret;
- last_link_check = get_time_ns();
- }
+ ret = phy_update_status(edev->phydev);
+ if (ret)
+ return ret;
+ edev->last_link_check = get_time_ns();
return edev->phydev->link ? 0 : -ENETDOWN;
}
/*
- * Check if we have a current ethernet device and
- * eventually open it if we have to.
+ * Check for link if we haven't done so for longer.
*/
-static int eth_check_open(struct eth_device *edev)
+static int eth_carrier_check(struct eth_device *edev, bool may_wait)
{
- int ret;
+ if (!IS_ENABLED(CONFIG_PHYLIB))
+ return 0;
- if (edev->active)
+ if (!edev->phydev)
return 0;
- ret = edev->open(edev);
- if (ret)
- return ret;
+ if (!edev->last_link_check ||
+ is_timeout(edev->last_link_check, 5 * SECOND))
+ eth_carrier_poll_once(edev);
+
+ if (may_wait && !edev->phydev->link) {
+ phy_wait_aneg_done(edev->phydev);
+ edev->last_link_check = get_time_ns();
+ }
+
+ return edev->phydev->link ? 0 : -ENETDOWN;
+}
+
+struct eth_q {
+ struct eth_device *edev;
+ int length;
+ struct list_head list;
+ void *data;
+};
+
+static int eth_queue(struct eth_device *edev, void *packet, int length)
+{
+ struct eth_q *q;
- edev->active = 1;
+ q = xzalloc(sizeof(*q));
+ if (!q)
+ return -ENOMEM;
- return eth_carrier_check(edev, 1);
+ q->data = dma_alloc(length);
+ if (!q->data) {
+ free(q);
+ return -ENOMEM;
+ }
+
+ q->length = length;
+ q->edev = edev;
+
+ memcpy(q->data, packet, length);
+ list_add_tail(&q->list, &edev->send_queue);
+
+ return 0;
}
int eth_send(struct eth_device *edev, void *packet, int length)
{
int ret;
- ret = eth_check_open(edev);
- if (ret)
- return ret;
+ if (!edev->active)
+ return -ENETDOWN;
- ret = eth_carrier_check(edev, 0);
+ if (slice_acquired(eth_device_slice(edev)))
+ return eth_queue(edev, packet, length);
+
+ ret = eth_carrier_check(edev, true);
if (ret)
return ret;
+ slice_acquire(eth_device_slice(edev));
+
led_trigger_network(LED_TRIGGER_NET_TX);
- return edev->send(edev, packet, length);
+ ret = eth_send_raw(edev, packet, length);
+
+ slice_release(eth_device_slice(edev));
+
+ return ret;
}
-static int __eth_rx(struct eth_device *edev)
+static void eth_do_work(struct eth_device *edev)
{
+ struct eth_q *q, *tmp;
int ret;
- ret = eth_check_open(edev);
- if (ret)
- return ret;
+ if (!phy_acquired(edev->phydev)) {
+ ret = eth_carrier_check(edev, false);
+ if (ret)
+ return;
+ }
- ret = eth_carrier_check(edev, 0);
- if (ret)
- return ret;
+ if (slice_acquired(eth_device_slice(edev)))
+ return;
- return edev->recv(edev);
+ slice_acquire(eth_device_slice(edev));
+
+ edev->recv(edev);
+
+ list_for_each_entry_safe(q, tmp, &edev->send_queue, list) {
+ led_trigger_network(LED_TRIGGER_NET_TX);
+ eth_send_raw(edev, q->data, q->length);
+ list_del(&q->list);
+ free(q->data);
+ free(q);
+ }
+
+ slice_release(eth_device_slice(edev));
}
int eth_rx(void)
@@ -269,7 +305,7 @@ int eth_rx(void)
for_each_netdev(edev) {
if (edev->active)
- __eth_rx(edev);
+ eth_do_work(edev);
}
return 0;
@@ -287,7 +323,8 @@ static void eth_of_fixup_node(struct device_node *root,
const char *node_path, int ethid,
const u8 ethaddr[ETH_ALEN])
{
- struct device_node *node;
+ struct device_node *bb_node, *fixup_node;
+ char *name;
int ret;
if (!is_valid_ether_addr(ethaddr)) {
@@ -297,22 +334,25 @@ static void eth_of_fixup_node(struct device_node *root,
}
if (node_path) {
- node = of_find_node_by_path_from(root, node_path);
+ bb_node = of_find_node_by_path_from(0, node_path);
+ name = of_get_reproducible_name(bb_node);
+ fixup_node = of_find_node_by_reproducible_name(root, name);
+ free(name);
} else {
char eth[12];
sprintf(eth, "ethernet%d", ethid);
- node = of_find_node_by_alias(root, eth);
+ fixup_node = of_find_node_by_alias(root, eth);
}
- if (!node) {
+ if (!fixup_node) {
pr_debug("%s: no node to fixup\n", __func__);
return;
}
- ret = of_set_property(node, "mac-address", ethaddr, ETH_ALEN, 1);
+ ret = of_set_property(fixup_node, "mac-address", ethaddr, ETH_ALEN, 1);
if (ret)
pr_err("Setting mac-address property of %s failed with: %s\n",
- node->full_name, strerror(-ret));
+ fixup_node->full_name, strerror(-ret));
}
static int eth_of_fixup(struct device_node *root, void *unused)
@@ -355,7 +395,7 @@ static const char * const eth_mode_names[] = {
int eth_register(struct eth_device *edev)
{
- struct device_d *dev = &edev->dev;
+ struct device *dev = &edev->dev;
unsigned char ethaddr[ETH_ALEN];
int ret, found = 0;
@@ -369,18 +409,23 @@ int eth_register(struct eth_device *edev)
if (edev->parent)
edev->dev.parent = edev->parent;
- if (edev->dev.parent && edev->dev.parent->device_node) {
- edev->dev.id = of_alias_get_id(edev->dev.parent->device_node, "ethernet");
+ if (edev->dev.parent && edev->dev.parent->of_node) {
+ edev->dev.id = of_alias_get_id(edev->dev.parent->of_node,
+ "ethernet");
if (edev->dev.id < 0)
edev->dev.id = DEVICE_ID_DYNAMIC;
} else {
edev->dev.id = DEVICE_ID_DYNAMIC;
}
+ INIT_LIST_HEAD(&edev->send_queue);
+
ret = register_device(&edev->dev);
if (ret)
return ret;
+ slice_init(&edev->slice, dev_name(dev));
+
edev->devname = xstrdup(dev_name(&edev->dev));
dev_add_param_ip(dev, "ipaddr", NULL, NULL, &edev->ipaddr, edev);
@@ -416,23 +461,61 @@ int eth_register(struct eth_device *edev)
register_preset_mac_address(edev, ethaddr);
if (IS_ENABLED(CONFIG_OFDEVICE) && edev->parent &&
- edev->parent->device_node)
- edev->nodepath = xstrdup(edev->parent->device_node->full_name);
+ edev->parent->of_node)
+ edev->nodepath = xstrdup(edev->parent->of_node->full_name);
return 0;
}
+int eth_open(struct eth_device *edev)
+{
+ int ret;
+
+ if (edev->active)
+ return 0;
+
+ edev->last_link_check = 0;
+
+ ret = edev->open(edev);
+ if (!ret)
+ edev->active = 1;
+
+ return ret;
+}
+
+void eth_close(struct eth_device *edev)
+{
+ if (!edev->active)
+ return;
+
+ edev->halt(edev);
+
+ edev->active = 0;
+}
+
void eth_unregister(struct eth_device *edev)
{
+ struct eth_q *q, *tmp;
+
if (edev->active)
edev->halt(edev);
+ list_for_each_entry_safe(q, tmp, &edev->send_queue, list) {
+ if (q->edev != edev)
+ continue;
+
+ list_del(&q->list);
+ free(q->data);
+ free(q);
+ }
+
if (IS_ENABLED(CONFIG_OFDEVICE))
free(edev->nodepath);
free(edev->devname);
unregister_device(&edev->dev);
+ slice_exit(&edev->slice);
list_del(&edev->list);
}
@@ -441,3 +524,62 @@ void led_trigger_network(enum led_trigger trigger)
led_trigger(trigger, TRIGGER_FLASH);
led_trigger(LED_TRIGGER_NET_TXRX, TRIGGER_FLASH);
}
+
+struct eth_device *of_find_eth_device_by_node(struct device_node *np)
+{
+ struct eth_device *edev;
+ int ret;
+
+ ret = of_device_ensure_probed(np);
+ if (ret)
+ return NULL;
+
+ list_for_each_entry(edev, &netdev_list, list)
+ if (edev->parent->of_node == np)
+ return edev;
+ return NULL;
+}
+EXPORT_SYMBOL(of_find_eth_device_by_node);
+
+void eth_open_all(void)
+{
+ struct eth_device *edev;
+
+ list_for_each_entry(edev, &netdev_list, list) {
+ if (edev->global_mode == ETH_MODE_DISABLED)
+ continue;
+ eth_open(edev);
+ }
+}
+
+static int populate_ethaddr(void)
+{
+ struct eth_device *edev;
+ bool generated = false;
+ int ret;
+
+ list_for_each_entry(edev, &netdev_list, list) {
+ if (!edev->parent || is_valid_ether_addr(edev->ethaddr))
+ continue;
+
+ ret = of_get_mac_addr_nvmem(edev->parent->of_node,
+ edev->ethaddr);
+ if (IS_ENABLED(CONFIG_NET_ETHADDR_FROM_MACHINE_ID) && ret) {
+ ret = generate_ether_addr(edev->ethaddr, edev->dev.id);
+ generated = true;
+ }
+ if (ret)
+ continue;
+
+ if (generated)
+ dev_notice(&edev->dev, "Generated MAC address from unique id: %pM\n",
+ edev->ethaddr);
+ else
+ dev_info(&edev->dev, "Got preset MAC address from NVMEM: %pM\n",
+ edev->ethaddr);
+ eth_set_ethaddr(edev, edev->ethaddr);
+ }
+
+ return 0;
+}
+postenvironment_initcall(populate_ethaddr);
diff --git a/net/fastboot.c b/net/fastboot.c
new file mode 100644
index 0000000000..932eb05c43
--- /dev/null
+++ b/net/fastboot.c
@@ -0,0 +1,589 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Copyright 2020 Edmund Henniges <eh@emlix.com>
+ * Copyright 2020 Daniel Glöckner <dg@emlix.com>
+ * Ported from U-Boot to Barebox
+ */
+
+#define pr_fmt(fmt) "net fastboot: " fmt
+
+#include <common.h>
+#include <net.h>
+#include <fastboot.h>
+#include <fastboot_net.h>
+#include <environment.h>
+#include <progress.h>
+#include <unistd.h>
+#include <init.h>
+#include <work.h>
+#include <globalvar.h>
+#include <magicvar.h>
+
+#define FASTBOOT_PORT 5554
+#define MAX_MTU 1500
+#define PACKET_SIZE (min(PKTSIZE, MAX_MTU + ETHER_HDR_SIZE) \
+ - (net_eth_to_udp_payload(0) - (char *)0))
+
+enum {
+ FASTBOOT_ERROR = 0,
+ FASTBOOT_QUERY = 1,
+ FASTBOOT_INIT = 2,
+ FASTBOOT_FASTBOOT = 3,
+};
+
+enum may_send {
+ MAY_NOT_SEND,
+ MAY_SEND_MESSAGE,
+ MAY_SEND_ACK,
+};
+
+struct __packed fastboot_header {
+ u8 id;
+ u8 flags;
+ u16 seq;
+};
+
+#define FASTBOOT_MAX_MSG_LEN 64
+
+struct fastboot_net {
+ struct fastboot fastboot;
+
+ struct net_connection *net_con;
+ struct fastboot_header response_header;
+ struct poller_struct poller;
+ struct work_queue wq;
+ u64 host_waits_since;
+ u64 last_download_pkt;
+ bool sequence_number_seen;
+ bool active_download;
+ bool reinit;
+ bool send_keep_alive;
+ enum may_send may_send;
+
+ IPaddr_t host_addr;
+ u16 host_port;
+ u8 host_mac[ETH_ALEN];
+ u16 sequence_number;
+ u16 last_payload_len;
+ void *last_payload;
+};
+
+static const ushort udp_version = 1;
+
+static bool is_current_connection(struct fastboot_net *fbn)
+{
+ return fbn->host_addr == net_read_ip(&fbn->net_con->ip->daddr) &&
+ fbn->host_port == fbn->net_con->udp->uh_dport;
+}
+
+static void fastboot_net_abort(struct fastboot_net *fbn)
+{
+ fbn->reinit = true;
+
+ fastboot_abort(&fbn->fastboot);
+
+ fbn->active_download = false;
+
+ poller_unregister(&fbn->poller);
+
+ /*
+ * If the host sends a data packet at a time when an empty packet was
+ * expected, fastboot_abort is called and an error message is sent.
+ * We don't want to execute the contents of the bad packet afterwards.
+ * Clearing command also tells our keep-alive poller to stop sending
+ * messages.
+ */
+ wq_cancel_work(&fbn->wq);
+
+ free(fbn->last_payload);
+ fbn->last_payload = NULL;
+}
+
+static void fastboot_net_save_payload(struct fastboot_net *fbn, void *packet,
+ int len)
+{
+ /* Save packet for retransmitting */
+
+ fbn->last_payload_len = len;
+ free(fbn->last_payload);
+ fbn->last_payload = memdup(packet, len);
+}
+
+static void fastboot_send(struct fastboot_net *fbn,
+ struct fastboot_header header,
+ const char *error_msg)
+{
+ short tmp;
+ uchar *packet = net_udp_get_payload(fbn->net_con);
+ uchar *packet_base = packet;
+ bool current_session = false;
+
+ if (fbn->sequence_number == ntohs(header.seq) &&
+ is_current_connection(fbn))
+ current_session = true;
+
+ if (error_msg)
+ header.id = FASTBOOT_ERROR;
+ else
+ error_msg = "no error";
+
+ /* send header */
+ memcpy(packet, &header, sizeof(header));
+ packet += sizeof(header);
+
+ switch (header.id) {
+ case FASTBOOT_QUERY:
+ /* send sequence number */
+ tmp = htons(fbn->sequence_number);
+ memcpy(packet, &tmp, sizeof(tmp));
+ packet += sizeof(tmp);
+ break;
+ case FASTBOOT_INIT:
+ /* send udp version and packet size */
+ tmp = htons(udp_version);
+ memcpy(packet, &tmp, sizeof(tmp));
+ packet += sizeof(tmp);
+ tmp = htons(PACKET_SIZE);
+ memcpy(packet, &tmp, sizeof(tmp));
+ packet += sizeof(tmp);
+ break;
+ case FASTBOOT_ERROR:
+ pr_err("%s\n", error_msg);
+
+ /* send error message */
+ tmp = strlen(error_msg);
+ memcpy(packet, error_msg, tmp);
+ packet += tmp;
+
+ if (current_session)
+ fastboot_net_abort(fbn);
+
+ break;
+ }
+
+ if (current_session && header.id != FASTBOOT_QUERY) {
+ fbn->sequence_number++;
+ fbn->sequence_number_seen = false;
+ fastboot_net_save_payload(fbn, packet_base, packet - packet_base);
+ }
+ net_udp_send(fbn->net_con, packet - packet_base);
+}
+
+static int fastboot_net_wait_may_send(struct fastboot_net *fbn)
+{
+ uint64_t start = get_time_ns();
+
+ while (!is_timeout(start, 2 * SECOND)) {
+ if (fbn->may_send != MAY_NOT_SEND)
+ return 0;
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int fastboot_write_net(struct fastboot *fb, const char *buf,
+ unsigned int n)
+{
+ struct fastboot_net *fbn = container_of(fb, struct fastboot_net,
+ fastboot);
+ struct fastboot_header response_header;
+ uchar *packet;
+ uchar *packet_base;
+ int ret;
+
+ if (fbn->reinit)
+ return 0;
+
+ /*
+ * This function is either called in command context, in which
+ * case we may wait, or from the keepalive poller which explicitly
+ * only calls us when we don't have to wait here.
+ */
+ ret = fastboot_net_wait_may_send(fbn);
+ if (ret) {
+ fastboot_net_abort(fbn);
+ return ret;
+ }
+
+ if (n && fbn->may_send == MAY_SEND_ACK) {
+ fastboot_send(fbn, fbn->response_header,
+ "Have message but only ACK allowed");
+ return -EPROTO;
+ } else if (!n && fbn->may_send == MAY_SEND_MESSAGE) {
+ fastboot_send(fbn, fbn->response_header,
+ "Want to send ACK but message expected");
+ return -EPROTO;
+ }
+
+ response_header = fbn->response_header;
+ response_header.flags = 0;
+ response_header.seq = htons(fbn->sequence_number);
+ ++fbn->sequence_number;
+ fbn->sequence_number_seen = false;
+
+ packet = net_udp_get_payload(fbn->net_con);
+ packet_base = packet;
+
+ /* Write headers */
+ memcpy(packet, &response_header, sizeof(response_header));
+ packet += sizeof(response_header);
+ /* Write response */
+ memcpy(packet, buf, n);
+ packet += n;
+
+ fastboot_net_save_payload(fbn, packet_base, packet - packet_base);
+
+ memcpy(fbn->net_con->et->et_dest, fbn->host_mac, ETH_ALEN);
+ net_write_ip(&fbn->net_con->ip->daddr, fbn->host_addr);
+ fbn->net_con->udp->uh_dport = fbn->host_port;
+
+ fbn->may_send = MAY_NOT_SEND;
+
+ net_udp_send(fbn->net_con, fbn->last_payload_len);
+
+ return 0;
+}
+
+static void fastboot_start_download_net(struct fastboot *fb)
+{
+ struct fastboot_net *fbn = container_of(fb, struct fastboot_net,
+ fastboot);
+
+ fastboot_start_download_generic(fb);
+ fbn->active_download = true;
+ fbn->last_download_pkt = get_time_ns();
+}
+
+/* must send exactly one packet on all code paths */
+static void fastboot_data_download(struct fastboot_net *fbn,
+ const void *fastboot_data,
+ unsigned int fastboot_data_len)
+{
+ int ret;
+
+ if (fastboot_data_len == 0 ||
+ (fbn->fastboot.download_bytes + fastboot_data_len) >
+ fbn->fastboot.download_size) {
+ fastboot_send(fbn, fbn->response_header,
+ "Received invalid data length");
+ return;
+ }
+
+ ret = fastboot_handle_download_data(&fbn->fastboot, fastboot_data,
+ fastboot_data_len);
+ if (ret < 0) {
+ fastboot_send(fbn, fbn->response_header, strerror(-ret));
+ return;
+ }
+
+ fastboot_tx_print(&fbn->fastboot, FASTBOOT_MSG_NONE, "");
+}
+
+struct fastboot_work {
+ struct work_struct work;
+ struct fastboot_net *fbn;
+ bool download_finished;
+ char command[FASTBOOT_MAX_CMD_LEN + 1];
+};
+
+static void fastboot_handle_type_fastboot(struct fastboot_net *fbn,
+ struct fastboot_header header,
+ char *fastboot_data,
+ unsigned int fastboot_data_len)
+{
+ struct fastboot_work *w;
+
+ fbn->response_header = header;
+ fbn->host_waits_since = get_time_ns();
+ fbn->may_send = fastboot_data_len ? MAY_SEND_ACK : MAY_SEND_MESSAGE;
+
+ if (fbn->active_download) {
+ fbn->last_download_pkt = get_time_ns();
+
+ if (!fastboot_data_len && fbn->fastboot.download_bytes
+ == fbn->fastboot.download_size) {
+
+ fbn->active_download = false;
+
+ w = xzalloc(sizeof(*w));
+ w->fbn = fbn;
+ w->download_finished = true;
+
+ wq_queue_work(&fbn->wq, &w->work);
+ } else {
+ fastboot_data_download(fbn, fastboot_data,
+ fastboot_data_len);
+ }
+ return;
+ }
+
+ if (fastboot_data_len > FASTBOOT_MAX_CMD_LEN) {
+ fastboot_send(fbn, header, "command too long");
+ return;
+ }
+
+ if (!list_empty(&fbn->wq.work))
+ return;
+
+ if (fastboot_data_len) {
+ w = xzalloc(sizeof(*w));
+ w->fbn = fbn;
+ memcpy(w->command, fastboot_data, fastboot_data_len);
+ w->command[fastboot_data_len] = 0;
+
+ wq_queue_work(&fbn->wq, &w->work);
+ }
+}
+
+static void fastboot_check_retransmit(struct fastboot_net *fbn,
+ struct fastboot_header header)
+{
+ if (ntohs(header.seq) == fbn->sequence_number - 1 &&
+ is_current_connection(fbn)) {
+ /* Retransmit last sent packet */
+ memcpy(net_udp_get_payload(fbn->net_con),
+ fbn->last_payload, fbn->last_payload_len);
+ net_udp_send(fbn->net_con, fbn->last_payload_len);
+ }
+}
+
+static void fastboot_handler(void *ctx, char *packet, unsigned int raw_len)
+{
+ unsigned int len = net_eth_to_udplen(packet);
+ struct ethernet *eth_header = (struct ethernet *)packet;
+ struct iphdr *ip_header = net_eth_to_iphdr(packet);
+ struct udphdr *udp_header = net_eth_to_udphdr(packet);
+ char *payload = net_eth_to_udp_payload(packet);
+ struct fastboot_net *fbn = ctx;
+ struct fastboot_header header;
+ char *fastboot_data = payload + sizeof(header);
+ u16 tot_len = ntohs(ip_header->tot_len);
+ int ret;
+
+ /* catch bogus tot_len values */
+ if ((char *)ip_header - packet + tot_len > raw_len)
+ return;
+
+ /* catch packets split into fragments that are too small to reply */
+ if (fastboot_data - (char *)ip_header > tot_len)
+ return;
+
+ /* catch packets too small to be valid */
+ if (len < sizeof(struct fastboot_header))
+ return;
+
+ memcpy(&header, payload, sizeof(header));
+ header.flags = 0;
+ len -= sizeof(header);
+
+ /* catch remaining fragmented packets */
+ if (fastboot_data - (char *)ip_header + len > tot_len) {
+ fastboot_send(fbn, header,
+ "can't reassemble fragmented frames");
+ return;
+ }
+ /* catch too large packets */
+ if (len > PACKET_SIZE) {
+ fastboot_send(fbn, header, "packet too large");
+ return;
+ }
+
+ memcpy(fbn->net_con->et->et_dest, eth_header->et_src, ETH_ALEN);
+ net_copy_ip(&fbn->net_con->ip->daddr, &ip_header->saddr);
+ fbn->net_con->udp->uh_dport = udp_header->uh_sport;
+
+ switch (header.id) {
+ case FASTBOOT_QUERY:
+ fastboot_send(fbn, header, NULL);
+ break;
+ case FASTBOOT_INIT:
+ if (ntohs(header.seq) != fbn->sequence_number) {
+ fastboot_check_retransmit(fbn, header);
+ break;
+ }
+ fbn->host_addr = net_read_ip(&ip_header->saddr);
+ fbn->host_port = udp_header->uh_sport;
+ memcpy(fbn->host_mac, eth_header->et_src, ETH_ALEN);
+ fastboot_net_abort(fbn);
+ /* poller just unregistered in fastboot_net_abort() */
+ ret = poller_register(&fbn->poller, "fastboot");
+ if (ret) {
+ pr_err("Cannot register poller: %s\n", strerror(-ret));
+ return;
+ }
+ fastboot_send(fbn, header, NULL);
+ break;
+ case FASTBOOT_FASTBOOT:
+ if (!is_current_connection(fbn))
+ break;
+ memcpy(fbn->host_mac, eth_header->et_src, ETH_ALEN);
+
+ if (ntohs(header.seq) != fbn->sequence_number) {
+ fastboot_check_retransmit(fbn, header);
+ } else if (!fbn->sequence_number_seen) {
+ fbn->sequence_number_seen = true;
+ fastboot_handle_type_fastboot(fbn, header,
+ fastboot_data, len);
+ }
+ break;
+ default:
+ fastboot_send(fbn, header, "unknown packet type");
+ break;
+ }
+}
+
+static void fastboot_do_work(struct work_struct *w)
+{
+ struct fastboot_work *fw = container_of(w, struct fastboot_work, work);
+ struct fastboot_net *fbn = fw->fbn;
+
+ if (fw->download_finished) {
+ fastboot_download_finished(&fbn->fastboot);
+ goto out;
+ }
+
+ fbn->reinit = false;
+ fastboot_tx_print(&fbn->fastboot, FASTBOOT_MSG_NONE, "");
+
+ fbn->send_keep_alive = true;
+
+ fastboot_exec_cmd(&fbn->fastboot, fw->command);
+ fbn->send_keep_alive = false;
+out:
+ free(fw);
+}
+
+static void fastboot_work_cancel(struct work_struct *w)
+{
+ struct fastboot_work *fw = container_of(w, struct fastboot_work, work);
+
+ free(fw);
+}
+
+static void fastboot_poll(struct poller_struct *poller)
+{
+ struct fastboot_net *fbn = container_of(poller, struct fastboot_net,
+ poller);
+
+ if (fbn->active_download) {
+ net_poll();
+ if (is_timeout(fbn->last_download_pkt, 5 * SECOND)) {
+ pr_err("No progress for 5s, aborting\n");
+ fastboot_net_abort(fbn);
+ return;
+ }
+ }
+
+ if (!fbn->send_keep_alive)
+ return;
+
+ if (!is_timeout(fbn->host_waits_since, 30ULL * SECOND))
+ return;
+
+ if (fbn->may_send != MAY_SEND_MESSAGE)
+ return;
+
+ fastboot_tx_print(&fbn->fastboot, FASTBOOT_MSG_INFO, "still busy");
+}
+
+void fastboot_net_free(struct fastboot_net *fbn)
+{
+ fastboot_generic_close(&fbn->fastboot);
+ net_unregister(fbn->net_con);
+ fastboot_generic_free(&fbn->fastboot);
+ wq_unregister(&fbn->wq);
+ free(fbn->last_payload);
+ free(fbn);
+}
+
+struct fastboot_net *fastboot_net_init(struct fastboot_opts *opts)
+{
+ struct fastboot_net *fbn;
+ bool bbu = get_fastboot_bbu();
+ int ret;
+
+ fbn = xzalloc(sizeof(*fbn));
+ fbn->fastboot.write = fastboot_write_net;
+ fbn->fastboot.start_download = fastboot_start_download_net;
+
+ if (opts) {
+ fbn->fastboot.files = opts->files;
+ fbn->fastboot.cmd_exec = opts->cmd_exec;
+ fbn->fastboot.cmd_flash = opts->cmd_flash;
+ ret = fastboot_generic_init(&fbn->fastboot, opts->export_bbu);
+ } else {
+ fbn->fastboot.files = get_fastboot_partitions() ?: file_list_parse("");
+ ret = fastboot_generic_init(&fbn->fastboot, bbu);
+ }
+ if (ret)
+ goto fail_generic_init;
+
+ fbn->net_con = net_udp_new(IP_BROADCAST, FASTBOOT_PORT,
+ fastboot_handler, fbn);
+ if (IS_ERR(fbn->net_con)) {
+ ret = PTR_ERR(fbn->net_con);
+ goto fail_net_con;
+ }
+ net_udp_bind(fbn->net_con, FASTBOOT_PORT);
+
+ eth_open(fbn->net_con->edev);
+
+ fbn->poller.func = fastboot_poll;
+
+ fbn->wq.fn = fastboot_do_work;
+ fbn->wq.cancel = fastboot_work_cancel;
+
+ wq_register(&fbn->wq);
+
+ return fbn;
+
+fail_net_con:
+ fastboot_generic_free(&fbn->fastboot);
+fail_generic_init:
+ free(fbn);
+ return ERR_PTR(ret);
+}
+
+static struct fastboot_net *fastboot_net_obj;
+static int fastboot_net_autostart;
+
+static int fastboot_net_autostart_set(struct param_d *p, void * priv)
+{
+ struct fastboot_net *fbn;
+ static bool started;
+
+ if (!fastboot_net_autostart || started)
+ return 0;
+
+ ifup_all(0);
+ fbn = fastboot_net_init(NULL);
+
+ if (IS_ERR(fbn))
+ return PTR_ERR(fbn);
+
+ fastboot_net_obj = fbn;
+ started = true;
+
+ return 0;
+}
+
+static int fastboot_net_init_globalvar(void)
+{
+ return globalvar_add_bool("fastboot.net.autostart",
+ fastboot_net_autostart_set,
+ &fastboot_net_autostart, NULL);
+}
+
+static void fastboot_net_exit(void)
+{
+ if (fastboot_net_obj)
+ fastboot_net_free(fastboot_net_obj);
+}
+
+postenvironment_initcall(fastboot_net_init_globalvar);
+predevshutdown_exitcall(fastboot_net_exit);
+
+BAREBOX_MAGICVAR(global.fastboot.net.autostart,
+ "If true, automatically start fastboot over UDP during startup");
diff --git a/net/ifup.c b/net/ifup.c
index d550f82530..5b92ee794d 100644
--- a/net/ifup.c
+++ b/net/ifup.c
@@ -1,26 +1,14 @@
-/*
- * ifup.c - bring up network interfaces
- *
- * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- *
- * 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 version 2
- * as published by the Free Software Foundation.
- *
- * 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 detaiifup.
- *
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+
+/* ifup.c - bring up network interfaces */
+
#define pr_fmt(fmt) "ifup: " fmt
#include <environment.h>
#include <command.h>
#include <common.h>
+#include <complete.h>
#include <getopt.h>
#include <dhcp.h>
#include <net.h>
@@ -29,7 +17,6 @@
#include <string.h>
#include <driver.h>
#include <init.h>
-#include <globalvar.h>
#include <magicvar.h>
#include <linux/stat.h>
@@ -98,7 +85,7 @@ static int source_env_network(struct eth_device *edev)
env_push_context();
for (i = 0; i < ARRAY_SIZE(vars); i++)
- setenv(vars[i], "");
+ unsetenv(vars[i]);
cmd = basprintf("source /env/network/%s", edev->devname);
ret = run_command(cmd);
@@ -171,8 +158,8 @@ out:
static void set_linux_bootarg(struct eth_device *edev)
{
+ char *bootarg;
if (edev->global_mode == ETH_MODE_STATIC) {
- char *bootarg;
IPaddr_t serverip;
IPaddr_t gateway;
@@ -188,10 +175,36 @@ static void set_linux_bootarg(struct eth_device *edev)
dev_set_param(&edev->dev, "linux.bootargs", bootarg);
free(bootarg);
} else if (edev->global_mode == ETH_MODE_DHCP) {
- dev_set_param(&edev->dev, "linux.bootargs", "ip=dhcp");
+ bootarg = basprintf("ip=::::%s:%s:dhcp",
+ barebox_get_hostname(),
+ edev->linuxdevname ? edev->linuxdevname : "");
+ dev_set_param(&edev->dev, "linux.bootargs", bootarg);
+ free(bootarg);
}
}
+static int ifup_edev_conf(struct eth_device *edev, unsigned flags)
+{
+ int ret;
+
+ if (edev->global_mode == ETH_MODE_DHCP) {
+ if (IS_ENABLED(CONFIG_NET_DHCP)) {
+ ret = dhcp(edev, NULL);
+ } else {
+ dev_err(&edev->dev, "DHCP support not available\n");
+ ret = -ENOSYS;
+ }
+ if (ret)
+ return ret;
+ }
+
+ set_linux_bootarg(edev);
+
+ edev->ifup = true;
+
+ return 0;
+}
+
int ifup_edev(struct eth_device *edev, unsigned flags)
{
int ret;
@@ -214,22 +227,20 @@ int ifup_edev(struct eth_device *edev, unsigned flags)
if (ret)
return ret;
- if (edev->global_mode == ETH_MODE_DHCP) {
- if (IS_ENABLED(CONFIG_NET_DHCP)) {
- ret = dhcp(edev, NULL);
- } else {
- dev_err(&edev->dev, "DHCP support not available\n");
- ret = -ENOSYS;
- }
- if (ret)
- return ret;
- }
+ ret = eth_open(edev);
+ if (ret)
+ return ret;
- set_linux_bootarg(edev);
+ if (flags & IFUP_FLAG_SKIP_CONF)
+ return 1;
- edev->ifup = true;
+ return ifup_edev_conf(edev, flags);
+}
- return 0;
+void ifdown_edev(struct eth_device *edev)
+{
+ eth_close(edev);
+ edev->ifup = false;
}
int ifup(const char *ethname, unsigned flags)
@@ -248,11 +259,86 @@ int ifup(const char *ethname, unsigned flags)
return ifup_edev(edev, flags);
}
+int ifdown(const char *ethname)
+{
+ struct eth_device *edev;
+
+ edev = eth_get_byname(ethname);
+ if (!edev)
+ return -ENODEV;
+
+ ifdown_edev(edev);
+
+ return 0;
+}
+
static int net_ifup_force_detect;
-int ifup_all(unsigned flags)
+static bool ifup_edev_need_conf(struct eth_device *edev)
+{
+ return edev->active && !edev->ifup &&
+ edev->global_mode != ETH_MODE_DISABLED;
+}
+
+static int __ifup_all_parallel(unsigned flags)
{
struct eth_device *edev;
+ unsigned netdev_count = 0;
+ u64 start;
+ int ret;
+
+ for_each_netdev(edev) {
+ ret = ifup_edev(edev, flags | IFUP_FLAG_SKIP_CONF);
+ if (ret == 1)
+ netdev_count++;
+ }
+
+ start = get_time_ns();
+ while (netdev_count && !is_timeout(start, PHY_AN_TIMEOUT * SECOND)) {
+ for_each_netdev(edev) {
+ if ((flags & IFUP_FLAG_UNTIL_NET_SERVER) && net_get_server())
+ return 0;
+
+ if (ctrlc())
+ return -EINTR;
+
+ if (!ifup_edev_need_conf(edev))
+ continue;
+
+ ret = eth_carrier_poll_once(edev);
+ if (ret)
+ continue;
+
+ ifup_edev_conf(edev, flags);
+ if (!edev->ifup)
+ continue;
+
+ netdev_count--;
+ }
+ }
+
+ return 0;
+}
+
+static int __ifup_all_sequence(unsigned flags)
+{
+ struct eth_device *edev;
+
+ for_each_netdev(edev) {
+ if ((flags & IFUP_FLAG_UNTIL_NET_SERVER) && net_get_server())
+ return 0;
+
+ if (ctrlc())
+ return -EINTR;
+
+ ifup_edev(edev, flags);
+ }
+
+ return 0;
+}
+
+int ifup_all(unsigned flags)
+{
DIR *dir;
struct dirent *d;
@@ -275,10 +361,28 @@ int ifup_all(unsigned flags)
list_empty(&netdev_list))
device_detect_all();
- for_each_netdev(edev)
- ifup_edev(edev, flags);
+ /*
+ * In the future, we may add an iproute -r option that tries to
+ * resolve $global.net.server using each interface. For now,
+ * we only support the special case of $global.net.server being
+ * empty, i.e. the first DHCP lease setting $global.net.server
+ * will be what we're going with.
+ */
+ if (net_get_server() && !net_get_gateway())
+ flags &= ~IFUP_FLAG_UNTIL_NET_SERVER;
+
+ if (flags & IFUP_FLAG_PARALLEL)
+ return __ifup_all_parallel(flags);
+ else
+ return __ifup_all_sequence(flags);
+}
- return 0;
+void ifdown_all(void)
+{
+ struct eth_device *edev;
+
+ for_each_netdev(edev)
+ ifdown_edev(edev);
}
static int ifup_all_init(void)
@@ -289,23 +393,28 @@ static int ifup_all_init(void)
}
late_initcall(ifup_all_init);
-BAREBOX_MAGICVAR_NAMED(global_net_ifup_force_detect,
- global.net.ifup_force_detect,
- "net: force detection of devices on ifup -a");
+BAREBOX_MAGICVAR(global.net.ifup_force_detect,
+ "net: force detection of devices on ifup -a");
#if IS_ENABLED(CONFIG_NET_CMD_IFUP)
static int do_ifup(int argc, char *argv[])
{
int opt;
- unsigned flags = 0;
+ unsigned flags = IFUP_FLAG_PARALLEL;
int all = 0;
- while ((opt = getopt(argc, argv, "af")) > 0) {
+ while ((opt = getopt(argc, argv, "asf1")) > 0) {
switch (opt) {
case 'f':
flags |= IFUP_FLAG_FORCE;
break;
+ case '1':
+ flags |= IFUP_FLAG_UNTIL_NET_SERVER;
+ break;
+ case 's':
+ flags &= ~IFUP_FLAG_PARALLEL;
+ break;
case 'a':
all = 1;
break;
@@ -329,15 +438,60 @@ BAREBOX_CMD_HELP_TEXT("/env/network/<intf> file. See Documentation/user/networki
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-a", "bring up all interfaces")
+BAREBOX_CMD_HELP_OPT ("-s", "bring up interfaces in sequence, not in parallel")
BAREBOX_CMD_HELP_OPT ("-f", "Force. Configure even if ip already set")
+BAREBOX_CMD_HELP_OPT ("-1", "Early exit if DHCP sets $global.net.server")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(ifup)
.cmd = do_ifup,
BAREBOX_CMD_DESC("bring a network interface up")
- BAREBOX_CMD_OPTS("[-af] [INTF]")
+ BAREBOX_CMD_OPTS("[-asf1] [INTF]")
BAREBOX_CMD_GROUP(CMD_GRP_NET)
+ BAREBOX_CMD_COMPLETE(eth_complete)
BAREBOX_CMD_HELP(cmd_ifup_help)
BAREBOX_CMD_END
+static int do_ifdown(int argc, char *argv[])
+{
+ int opt;
+ int all = 0;
+
+ while ((opt = getopt(argc, argv, "a")) > 0) {
+ switch (opt) {
+ case 'a':
+ all = 1;
+ break;
+ }
+ }
+
+ if (all) {
+ ifdown_all();
+ return 0;
+ }
+
+ if (argc == optind)
+ return COMMAND_ERROR_USAGE;
+
+ return ifdown(argv[optind]);
+}
+
+
+
+BAREBOX_CMD_HELP_START(ifdown)
+BAREBOX_CMD_HELP_TEXT("Disable a network interface")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-a", "disable all interfaces")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(ifdown)
+ .cmd = do_ifdown,
+ BAREBOX_CMD_DESC("disable a network interface")
+ BAREBOX_CMD_OPTS("[-a] [INTF]")
+ BAREBOX_CMD_GROUP(CMD_GRP_NET)
+ BAREBOX_CMD_COMPLETE(eth_complete)
+ BAREBOX_CMD_HELP(cmd_ifdown_help)
+BAREBOX_CMD_END
+
#endif
diff --git a/net/lib.c b/net/lib.c
index d2b33132d6..dc6e138f39 100644
--- a/net/lib.c
+++ b/net/lib.c
@@ -1,27 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2015 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+// SPDX-FileCopyrightText: 1994-2000 Neil Russell
+// SPDX-FileCopyrightText: 2000 Roland Borde
+// SPDX-FileCopyrightText: 2000 Paolo Scaffardi
+// SPDX-FileCopyrightText: 2000-2002 Wolfgang Denk <wd@denx.de>
+
/*
* net.c - barebox networking support
*
- * Copyright (c) 2015 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- *
* based on U-Boot (LiMon) code
- *
- * Copyright 1994 - 2000 Neil Russell.
- * Copyright 2000 Roland Borde
- * Copyright 2000 Paolo Scaffardi
- * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
- *
- * 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 version 2
- * as published by the Free Software Foundation.
- *
- * 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.
- *
*/
#include <common.h>
@@ -50,13 +37,6 @@ int string_to_ethaddr(const char *str, u8 enetaddr[ETH_ALEN])
return 0;
}
-void ethaddr_to_string(const u8 enetaddr[ETH_ALEN], char *str)
-{
- sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
- enetaddr[0], enetaddr[1], enetaddr[2], enetaddr[3],
- enetaddr[4], enetaddr[5]);
-}
-
int string_to_ip(const char *s, IPaddr_t *ip)
{
IPaddr_t addr = 0;
diff --git a/net/net.c b/net/net.c
index 0d889ddb52..a9d1306354 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1,27 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2010 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+// SPDX-FileCopyrightText: 1994-2000 Neil Russell
+// SPDX-FileCopyrightText: 2000 Roland Borde
+// SPDX-FileCopyrightText: 2000 Paolo Scaffardi
+// SPDX-FileCopyrightText: 2000-2002 Wolfgang Denk <wd@denx.de>
+
/*
* net.c - barebox networking support
*
- * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- *
* based on U-Boot (LiMon) code
- *
- * Copyright 1994 - 2000 Neil Russell.
- * Copyright 2000 Roland Borde
- * Copyright 2000 Paolo Scaffardi
- * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
- *
- * 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 version 2
- * as published by the Free Software Foundation.
- *
- * 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.
- *
*/
#define pr_fmt(fmt) "net: " fmt
@@ -38,10 +25,10 @@
#include <init.h>
#include <globalvar.h>
#include <magicvar.h>
+#include <machine_id.h>
#include <linux/ctype.h>
#include <linux/err.h>
-unsigned char *NetRxPackets[PKTBUFSRX]; /* Receive packets */
static unsigned int net_ip_id;
char *net_server;
@@ -254,8 +241,58 @@ static int arp_request(struct eth_device *edev, IPaddr_t dest, unsigned char *et
void net_poll(void)
{
+ static bool in_net_poll;
+
+ if (in_net_poll)
+ return;
+
+ in_net_poll = true;
+
eth_rx();
+
+ in_net_poll = false;
+}
+
+static void __net_poll(struct poller_struct *poller)
+{
+ static uint64_t last;
+
+ /*
+ * USB network controllers take a long time in the receive path,
+ * so limit the polling rate to once per 10ms. This is due to
+ * deficiencies in the barebox USB stack: We can't queue URBs and
+ * receive a callback when they are done. Instead, we always
+ * synchronously queue an URB and wait for its completion. In case
+ * of USB network adapters the only way to detect if packets have
+ * been received is to queue a RX URB and see if it completes (in
+ * which case we have received data) or if it timeouts (no data
+ * available). The timeout can't be arbitrarily small, 2ms is the
+ * smallest we can do with the 1ms USB frame size.
+ *
+ * Given that we do a mixture of polling-as-fast-as-possible when
+ * we are waiting for network traffic (tftp, nfs and other users
+ * actively calling net_poll()) and doing a low frequency polling
+ * here to still get packets when no user is actively waiting for
+ * incoming packets. This is used to receive incoming ping packets
+ * and to get fastboot over ethernet going.
+ */
+ if (!is_timeout(last, 10 * MSECOND))
+ return;
+
+ net_poll();
+
+ last = get_time_ns();
+}
+
+static struct poller_struct net_poller = {
+ .func = __net_poll,
+};
+
+static int init_net_poll(void)
+{
+ return poller_register(&net_poller, "net");
}
+device_initcall(init_net_poll);
static uint16_t net_udp_new_localport(void)
{
@@ -288,9 +325,14 @@ void net_set_serverip(IPaddr_t ip)
net_server = xasprintf("%pI4", &ip);
}
+const char *net_get_server(void)
+{
+ return net_server && *net_server ? net_server : NULL;
+}
+
void net_set_serverip_empty(IPaddr_t ip)
{
- if (net_server && *net_server)
+ if (net_get_server())
return;
net_set_serverip(ip);
@@ -323,6 +365,43 @@ IPaddr_t net_get_gateway(void)
static LIST_HEAD(connection_list);
+/**
+ * generate_ether_addr - Generates stable software assigned Ethernet address
+ * @addr: Pointer to a six-byte array to contain the Ethernet address
+ * @ethid: index of the Ethernet interface
+ *
+ * Derives an Ethernet address (MAC) from the machine ID, that's stable
+ * per board that is not multicast and has the local assigned bit set.
+ *
+ * Return 0 if an address could be generated or a negative error code otherwise.
+ */
+int generate_ether_addr(u8 *ethaddr, int ethid)
+{
+ const char *hostname;
+ uuid_t id;
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_NET_ETHADDR_FROM_MACHINE_ID))
+ return -ENOSYS;
+
+ hostname = barebox_get_hostname();
+ if (!hostname)
+ return -EINVAL;
+
+ ret = machine_id_get_app_specific(&id, ARRAY_AND_SIZE("barebox-macaddr:"),
+ hostname, strlen(hostname), NULL);
+ if (ret)
+ return ret;
+
+ memcpy(ethaddr, &id.b, ETH_ALEN);
+ eth_addr_add(ethaddr, ethid);
+
+ ethaddr[0] &= 0xfe; /* clear multicast bit */
+ ethaddr[0] |= 0x02; /* set local assignment bit (IEEE802) */
+
+ return 0;
+}
+
static struct net_connection *net_new(struct eth_device *edev, IPaddr_t dest,
rx_handler_f *handler, void *ctx)
{
@@ -338,10 +417,13 @@ static struct net_connection *net_new(struct eth_device *edev, IPaddr_t dest,
}
if (!is_valid_ether_addr(edev->ethaddr)) {
- char str[sizeof("xx:xx:xx:xx:xx:xx")];
- random_ether_addr(edev->ethaddr);
- ethaddr_to_string(edev->ethaddr, str);
- dev_warn(&edev->dev, "No MAC address set. Using random address %s\n", str);
+ ret = generate_ether_addr(edev->ethaddr, edev->dev.id);
+ if (ret)
+ random_ether_addr(edev->ethaddr);
+
+ dev_warn(&edev->dev, "No MAC address set. Using %s %pM\n",
+ ret == 1 ? "address computed from unique ID" : "random address",
+ edev->ethaddr);
eth_set_ethaddr(edev, edev->ethaddr);
}
@@ -383,7 +465,7 @@ static struct net_connection *net_new(struct eth_device *edev, IPaddr_t dest,
return con;
out:
- free(con->packet);
+ net_free_packet(con->packet);
free(con);
return ERR_PTR(ret);
}
@@ -428,7 +510,7 @@ struct net_connection *net_icmp_new(IPaddr_t dest, rx_handler_f *handler,
void net_unregister(struct net_connection *con)
{
list_del(&con->list);
- free(con->packet);
+ net_free_packet(con->packet);
free(con);
}
@@ -482,7 +564,7 @@ static int net_answer_arp(struct eth_device *edev, unsigned char *pkt, int len)
return 0;
memcpy(packet, pkt, ETHER_HDR_SIZE + ARP_HDR_SIZE);
ret = eth_send(edev, packet, ETHER_HDR_SIZE + ARP_HDR_SIZE);
- free(packet);
+ net_free_packet(packet);
return ret;
}
@@ -540,8 +622,6 @@ static int net_handle_arp(struct eth_device *edev, unsigned char *pkt, int len)
return -EINVAL;
}
- return 0;
-
bad:
net_bad_packet(pkt, len);
return -EINVAL;
@@ -565,12 +645,96 @@ static int net_handle_udp(unsigned char *pkt, int len)
return -EINVAL;
}
-static int net_handle_icmp(unsigned char *pkt, int len)
+static struct iphdr *ip_verify_size(unsigned char *pkt, int *total_len_nic)
+{
+ struct iphdr *ip = (struct iphdr *)(pkt + ETHER_HDR_SIZE);
+ int total_len_pkt;
+
+ total_len_pkt = ntohs(ip->tot_len) + ETHER_HDR_SIZE;
+
+ /* Only trust the packet's size if it's within bounds */
+ if (*total_len_nic < sizeof(struct ethernet) + sizeof(struct iphdr) ||
+ *total_len_nic < total_len_pkt) {
+ net_bad_packet(pkt, *total_len_nic);
+ return NULL;
+ }
+
+#ifdef DEBUG
+ /* Hitting this warning means we have trailing bytes after the IP
+ * payload that are not needed for padding.
+ *
+ * This may be an indication that the NIC driver is doing funny
+ * offloading stuff it shouldn't, but can also mean that some sender
+ * in the network likes to waste bit time for nought.
+ *
+ * We can't differentiate between the two, so we just print the
+ * warning when DEBUG is defined, so developers may investigate the
+ * reason without annoying users about something that might not even
+ * be barebox's fault.
+ */
+ if (WARN_ON_ONCE(*total_len_nic > total_len_pkt &&
+ *total_len_nic > 64)) {
+ net_bad_packet(pkt, *total_len_nic);
+ }
+#endif
+
+ *total_len_nic = total_len_pkt;
+ return ip;
+}
+
+static int ping_reply(struct eth_device *edev, unsigned char *pkt, int len)
+{
+ struct ethernet *et = (struct ethernet *)pkt;
+ struct icmphdr *icmp;
+ struct iphdr *ip;
+ unsigned char *packet;
+ int ret;
+
+ memcpy(et->et_dest, et->et_src, 6);
+ memcpy(et->et_src, edev->ethaddr, 6);
+ et->et_protlen = htons(PROT_IP);
+
+ icmp = net_eth_to_icmphdr(pkt);
+
+ ip = ip_verify_size(pkt, &len);
+ if (!ip)
+ return -EILSEQ;
+
+ icmp->type = ICMP_ECHO_REPLY;
+ icmp->checksum = 0;
+ icmp->checksum = ~net_checksum((unsigned char *)icmp,
+ len - sizeof(struct iphdr) - ETHER_HDR_SIZE);
+ ip->check = 0;
+ ip->frag_off = htons(0x4000);
+ ip->ttl = 255;
+ net_copy_ip((void *)&ip->daddr, &ip->saddr);
+ net_copy_ip((void *)&ip->saddr, &edev->ipaddr);
+ ip->check = ~net_checksum((unsigned char *)ip, sizeof(struct iphdr));
+
+ packet = net_alloc_packet();
+ if (!packet)
+ return 0;
+
+ memcpy(packet, pkt, len);
+
+ ret = eth_send(edev, packet, len);
+
+ net_free_packet(packet);
+
+ return ret;
+}
+
+static int net_handle_icmp(struct eth_device *edev, unsigned char *pkt, int len)
{
struct net_connection *con;
+ struct icmphdr *icmp;
pr_debug("%s\n", __func__);
+ icmp = net_eth_to_icmphdr(pkt);
+ if (icmp->type == ICMP_ECHO_REQUEST)
+ ping_reply(edev, pkt, len);
+
list_for_each_entry(con, &connection_list, list) {
if (con->proto == IPPROTO_ICMP) {
con->handler(con->priv, pkt, len);
@@ -587,16 +751,21 @@ static int net_handle_ip(struct eth_device *edev, unsigned char *pkt, int len)
pr_debug("%s\n", __func__);
- if (len < sizeof(struct ethernet) + sizeof(struct iphdr) ||
- len < ETHER_HDR_SIZE + ntohs(ip->tot_len)) {
+ ip = ip_verify_size(pkt, &len);
+ if (!ip) {
pr_debug("%s: bad len\n", __func__);
- goto bad;
+ return 0;
}
if ((ip->hl_v & 0xf0) != 0x40)
goto bad;
- if (ip->frag_off & htons(0x1fff)) /* Can't deal w/ fragments */
+ /* Can't deal w/ fragments.
+ * Either a fragment offset (13 bits), or
+ * MF (More Fragments) from fragment flags (3 bits).
+ * MF - because first fragment has fragment offset 0
+ */
+ if (ip->frag_off & htons(0x3fff))
goto bad;
if (!net_checksum_ok((unsigned char *)ip, sizeof(struct iphdr)))
goto bad;
@@ -607,7 +776,7 @@ static int net_handle_ip(struct eth_device *edev, unsigned char *pkt, int len)
switch (ip->protocol) {
case IPPROTO_ICMP:
- return net_handle_icmp(pkt, len);
+ return net_handle_icmp(edev, pkt, len);
case IPPROTO_UDP:
return net_handle_udp(pkt, len);
}
@@ -631,6 +800,20 @@ int net_receive(struct eth_device *edev, unsigned char *pkt, int len)
goto out;
}
+ if (edev->rx_monitor)
+ edev->rx_monitor(edev, pkt, len);
+
+ if (edev->rx_preprocessor) {
+ ret = edev->rx_preprocessor(edev, &pkt, &len);
+ if (ret == -ENOMSG)
+ return 0;
+ if (ret) {
+ pr_debug("%s: rx_preprocessor failed %pe\n", __func__,
+ ERR_PTR(ret));
+ return ret;
+ }
+ }
+
switch (et_protlen) {
case PROT_ARP:
ret = net_handle_arp(edev, pkt, len);
@@ -647,13 +830,32 @@ out:
return ret;
}
-static int net_init(void)
+void net_free_packets(void **packets, unsigned count)
+{
+ while (count-- > 0)
+ net_free_packet(packets[count]);
+}
+
+int net_alloc_packets(void **packets, int count)
{
+ void *packet;
int i;
- for (i = 0; i < PKTBUFSRX; i++)
- NetRxPackets[i] = net_alloc_packet();
+ for (i = 0; i < count; i++) {
+ packet = net_alloc_packet();
+ if (!packet)
+ goto free;
+ packets[i] = packet;
+ }
+
+ return 0;
+free:
+ net_free_packets(packets, i);
+ return -ENOMEM;
+}
+static int net_init(void)
+{
globalvar_add_simple_ip("net.nameserver", &net_nameserver);
globalvar_add_simple_string("net.domainname", &net_domainname);
globalvar_add_simple_string("net.server", &net_server);
@@ -664,6 +866,6 @@ static int net_init(void)
postcore_initcall(net_init);
-BAREBOX_MAGICVAR_NAMED(global_net_nameserver, global.net.nameserver, "The DNS server used for resolving host names");
-BAREBOX_MAGICVAR_NAMED(global_net_domainname, global.net.domainname, "Domain name used for DNS requests");
-BAREBOX_MAGICVAR_NAMED(global_net_server, global.net.server, "Standard server used for NFS/TFTP");
+BAREBOX_MAGICVAR(global.net.nameserver, "The DNS server used for resolving host names");
+BAREBOX_MAGICVAR(global.net.domainname, "Domain name used for DNS requests");
+BAREBOX_MAGICVAR(global.net.server, "Standard server used for NFS/TFTP");
diff --git a/net/netconsole.c b/net/netconsole.c
index ef8b1856b6..43f78997b8 100644
--- a/net/netconsole.c
+++ b/net/netconsole.c
@@ -1,21 +1,7 @@
-/*
- * netconsole.c - network console support
- *
- * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- *
- * 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 version 2
- * as published by the Free Software Foundation.
- *
- * 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.
- *
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2010 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+
+/* netconsole.c - network console support */
#define pr_fmt(fmt) "netconsole: " fmt
diff --git a/net/nfs.c b/net/nfs.c
index 63573098d7..df0840e4e7 100644
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
/*
* NFS support driver - based on etherboot and barebox's tftp.c
*
@@ -29,7 +31,6 @@
#include <malloc.h>
#include <libgen.h>
#include <fs.h>
-#include <libgen.h>
#include <fcntl.h>
#include <errno.h>
#include <progress.h>
@@ -533,7 +534,7 @@ static int nfs_readlink_reply(unsigned char *pkt, unsigned len)
static int nfs_read_reply(unsigned char *pkt, unsigned len)
{
- int rlen;
+ unsigned int rlen;
uint32_t *data;
int ret;
@@ -552,6 +553,8 @@ static int nfs_read_reply(unsigned char *pkt, unsigned len)
rlen = ntohl(net_read_uint32(data + 18));
+ rlen = max_t(unsigned int, rlen, len - 19);
+
ret = write(net_store_fd, (char *)(data + 19), rlen);
if (ret < 0) {
perror("write");
diff --git a/net/nfs.h b/net/nfs.h
deleted file mode 100644
index 7c7a648e46..0000000000
--- a/net/nfs.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * (C) Masami Komiya <mkomiya@sonare.it> 2004
- *
- * 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, or (at
- * your option) any later version.
- */
-
-#ifndef __NFS_H__
-#define __NFS_H__
-
-#define SUNRPC_PORT 111
-
-#define PROG_PORTMAP 100000
-#define PROG_NFS 100003
-#define PROG_MOUNT 100005
-
-#define MSG_CALL 0
-#define MSG_REPLY 1
-
-#define PORTMAP_GETPORT 3
-
-#define MOUNT_ADDENTRY 1
-#define MOUNT_UMOUNTALL 4
-
-#define NFS_LOOKUP 4
-#define NFS_READLINK 5
-#define NFS_READ 6
-
-#define NFS_FHSIZE 32
-
-#define NFSERR_PERM 1
-#define NFSERR_NOENT 2
-#define NFSERR_ACCES 13
-#define NFSERR_ISDIR 21
-#define NFSERR_INVAL 22
-
-/* Block size used for NFS read accesses. A RPC reply packet (including all
- * headers) must fit within a single Ethernet frame to avoid fragmentation.
- * Chosen to be a power of two, as most NFS servers are optimized for this. */
-#define NFS_READ_SIZE 1024
-
-#define NFS_MAXLINKDEPTH 16
-
-struct rpc_t {
- union {
- uint8_t data[2048];
- struct {
- uint32_t id;
- uint32_t type;
- uint32_t rpcvers;
- uint32_t prog;
- uint32_t vers;
- uint32_t proc;
- uint32_t data[1];
- } call;
- struct {
- uint32_t id;
- uint32_t type;
- uint32_t rstatus;
- uint32_t verifier;
- uint32_t v2;
- uint32_t astatus;
- uint32_t data[19];
- } reply;
- } u;
-};
-extern void NfsStart (char *); /* Begin NFS */
-
-
-/**********************************************************************/
-
-#endif /* __NFS_H__ */
diff --git a/net/ping.c b/net/ping.c
index a71f59a805..7b319e532e 100644
--- a/net/ping.c
+++ b/net/ping.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
#include <common.h>
#include <command.h>
#include <clock.h>
diff --git a/net/rarp.h b/net/rarp.h
deleted file mode 100644
index b5b222ee3e..0000000000
--- a/net/rarp.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * (C) Copyright 2000
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * 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.
- *
- */
-
-
-#ifndef __RARP_H__
-#define __RARP_H__
-
-#ifndef __NET_H__
-#include <net.h>
-#endif /* __NET_H__ */
-
-
-/**********************************************************************/
-/*
- * Global functions and variables.
- */
-
-extern int RarpTry;
-
-extern void RarpRequest (void); /* Send a RARP request */
-
-/**********************************************************************/
-
-#endif /* __RARP_H__ */
diff --git a/net/sntp.c b/net/sntp.c
index b4e6d6439c..08da012f36 100644
--- a/net/sntp.c
+++ b/net/sntp.c
@@ -1,18 +1,9 @@
-/*
- * 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; version 2.
- *
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0-only
#include <common.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#include <command.h>
#include <clock.h>
#include <net.h>