summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorLothar Felten <lothar.felten@gmail.com>2018-06-22 22:29:54 +0200
committerJoe Hershberger <joe.hershberger@ni.com>2018-07-02 14:14:20 -0500
commitd8970dae276377a0beff1c3e9d8b6f805ecf5cd5 (patch)
treeeb3fdb9ef7d734fbca0d0a92ddd30915c52ba44a /net
parent318b5d76b6661dcaf6934b0a925bbcfdf0469069 (diff)
net: Add new wol command - Wake on LAN
Add a new command 'wol': Wait for an incoming Wake-on-LAN packet or time out if no WoL packed is received. If the WoL packet contains a password, it is saved in the environment variable 'wolpassword' using the etherwake format (dot or colon separated decimals). Intended use case: a networked device should boot an alternate image. It's attached to a network on a client site, modifying the DHCP server configuration or setup of a tftp server is not allowed. After power on the device waits a few seconds for a WoL packet. If a packet is received, the device boots the alternate image. Otherwise it boots the default image. This method is a simple way to interact with a system via network even if only the MAC address is known. Tools to send WoL packets are available on all common platforms. Some Ethernet drivers seem to pad the incoming packet. The additional padding bytes might be recognized as Wake-on-LAN password bytes. By default enabled in pengwyn_defconfig. Signed-off-by: Lothar Felten <lothar.felten@gmail.com> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
Diffstat (limited to 'net')
-rw-r--r--net/Makefile1
-rw-r--r--net/net.c19
-rw-r--r--net/wol.c96
-rw-r--r--net/wol.h65
4 files changed, 181 insertions, 0 deletions
diff --git a/net/Makefile b/net/Makefile
index 07466879f5..ce36362168 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_CMD_RARP) += rarp.o
obj-$(CONFIG_CMD_SNTP) += sntp.o
obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
obj-$(CONFIG_UDP_FUNCTION_FASTBOOT) += fastboot.o
+obj-$(CONFIG_CMD_WOL) += wol.o
# Disable this warning as it is triggered by:
# sprintf(buf, index ? "foo%d" : "foo", index)
diff --git a/net/net.c b/net/net.c
index b4563a4cab..084269e31e 100644
--- a/net/net.c
+++ b/net/net.c
@@ -78,6 +78,12 @@
* - own IP address
* We want: - network time
* Next step: none
+ *
+ * WOL:
+ *
+ * Prerequisites: - own ethernet address
+ * We want: - magic packet or timeout
+ * Next step: none
*/
@@ -108,6 +114,9 @@
#if defined(CONFIG_CMD_SNTP)
#include "sntp.h"
#endif
+#if defined(CONFIG_CMD_WOL)
+#include "wol.h"
+#endif
/** BOOTP EXTENTIONS **/
@@ -515,6 +524,11 @@ restart:
link_local_start();
break;
#endif
+#if defined(CONFIG_CMD_WOL)
+ case WOL:
+ wol_start();
+ break;
+#endif
default:
break;
}
@@ -1281,6 +1295,11 @@ void net_process_received_packet(uchar *in_packet, int len)
ntohs(ip->udp_src),
ntohs(ip->udp_len) - UDP_HDR_SIZE);
break;
+#ifdef CONFIG_CMD_WOL
+ case PROT_WOL:
+ wol_receive(ip, len);
+ break;
+#endif
}
}
diff --git a/net/wol.c b/net/wol.c
new file mode 100644
index 0000000000..946bd91b47
--- /dev/null
+++ b/net/wol.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 Lothar Felten, lothar.felten@gmail.com
+ */
+
+#include <common.h>
+#include <command.h>
+#include <net.h>
+#include <environment.h>
+#include "wol.h"
+
+static ulong wol_timeout = WOL_DEFAULT_TIMEOUT;
+
+/*
+ * Check incoming Wake-on-LAN packet for:
+ * - sync bytes
+ * - sixteen copies of the target MAC address
+ *
+ * @param wol Wake-on-LAN packet
+ * @param len Packet length
+ */
+static int wol_check_magic(struct wol_hdr *wol, unsigned int len)
+{
+ int i;
+
+ if (len < sizeof(struct wol_hdr))
+ return 0;
+
+ for (i = 0; i < WOL_SYNC_COUNT; i++)
+ if (wol->wol_sync[i] != WOL_SYNC_BYTE)
+ return 0;
+
+ for (i = 0; i < WOL_MAC_REPETITIONS; i++)
+ if (memcmp(&wol->wol_dest[i * ARP_HLEN],
+ net_ethaddr, ARP_HLEN) != 0)
+ return 0;
+
+ return 1;
+}
+
+void wol_receive(struct ip_udp_hdr *ip, unsigned int len)
+{
+ struct wol_hdr *wol;
+
+ wol = (struct wol_hdr *)ip;
+
+ if (!wol_check_magic(wol, len))
+ return;
+
+ /* save the optional password using the ether-wake formats */
+ /* don't check for exact length, the packet might have padding */
+ if (len >= (sizeof(struct wol_hdr) + WOL_PASSWORD_6B)) {
+ eth_env_set_enetaddr("wolpassword", wol->wol_passwd);
+ } else if (len >= (sizeof(struct wol_hdr) + WOL_PASSWORD_4B)) {
+ char buffer[16];
+ struct in_addr *ip = (struct in_addr *)(wol->wol_passwd);
+
+ ip_to_string(*ip, buffer);
+ env_set("wolpassword", buffer);
+ }
+ net_set_state(NETLOOP_SUCCESS);
+}
+
+static void wol_udp_handler(uchar *pkt, unsigned int dest, struct in_addr sip,
+ unsigned int src, unsigned int len)
+{
+ struct wol_hdr *wol;
+
+ wol = (struct wol_hdr *)pkt;
+
+ /* UDP destination port must be 0, 7 or 9 */
+ if (dest != 0 && dest != 7 && dest != 9)
+ return;
+
+ if (!wol_check_magic(wol, len))
+ return;
+
+ net_set_state(NETLOOP_SUCCESS);
+}
+
+void wol_set_timeout(ulong timeout)
+{
+ wol_timeout = timeout;
+}
+
+static void wol_timeout_handler(void)
+{
+ eth_halt();
+ net_set_state(NETLOOP_FAIL);
+}
+
+void wol_start(void)
+{
+ net_set_timeout_handler(wol_timeout, wol_timeout_handler);
+ net_set_udp_handler(wol_udp_handler);
+}
diff --git a/net/wol.h b/net/wol.h
new file mode 100644
index 0000000000..ebc81f24b6
--- /dev/null
+++ b/net/wol.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * wol - Wake-on-LAN
+ *
+ * Supports both Wake-on-LAN packet types:
+ * - EtherType 0x0842 packets
+ * - UDP packets on ports 0, 7 and 9.
+ *
+ * Copyright 2018 Lothar Felten, lothar.felten@gmail.com
+ */
+
+#if defined(CONFIG_CMD_WOL)
+
+#ifndef __WOL_H__
+#define __WOL_H__
+
+#include <net.h>
+
+/**********************************************************************/
+
+#define WOL_SYNC_BYTE 0xFF
+#define WOL_SYNC_COUNT 6
+#define WOL_MAC_REPETITIONS 16
+#define WOL_DEFAULT_TIMEOUT 5000
+#define WOL_PASSWORD_4B 4
+#define WOL_PASSWORD_6B 6
+
+/*
+ * Wake-on-LAN header
+ */
+struct wol_hdr {
+ u8 wol_sync[WOL_SYNC_COUNT]; /* sync bytes */
+ u8 wol_dest[WOL_MAC_REPETITIONS * ARP_HLEN]; /* 16x MAC */
+ u8 wol_passwd[0]; /* optional */
+};
+
+/*
+ * Initialize wol (beginning of netloop)
+ */
+void wol_start(void);
+
+/*
+ * Check incoming Wake-on-LAN packet for:
+ * - sync bytes
+ * - sixteen copies of the target MAC address
+ *
+ * Optionally store the four or six byte password in the environment
+ * variable "wolpassword"
+ *
+ * @param ip IP header in the packet
+ * @param len Packet length
+ */
+void wol_receive(struct ip_udp_hdr *ip, unsigned int len);
+
+/*
+ * Set the timeout for the reception of a Wake-on-LAN packet
+ *
+ * @param timeout in milliseconds
+ */
+void wol_set_timeout(ulong timeout);
+
+/**********************************************************************/
+
+#endif /* __WOL_H__ */
+#endif