[U-Boot] [PATCH 2/3] Add sendnbc tool to broadcast NBC magic packet
tristan.lelong at blunderer.org
tristan.lelong at blunderer.org
Tue Nov 16 19:04:32 CET 2010
From: Tristan Lelong <tristan.lelong at blunderer.org>
This tool send NBC packet filled with data provided on command line
It can be used in combination with netconsole by calling:
BOARD_IP=192.168.0.2 ./sendnbc -i $BOARD_IP && ./netconsole $BOARD_IP
Signed-off-by: Tristan Lelong <tristan.lelong at blunderer.org>
---
tools/Makefile | 6 ++
tools/sendnbc.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 225 insertions(+), 0 deletions(-)
create mode 100644 tools/sendnbc.c
diff --git a/tools/Makefile b/tools/Makefile
index 619c9f2..e1719fc 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -45,6 +45,7 @@ CONFIG_CMD_LOADS = y
CONFIG_CMD_NET = y
CONFIG_INCA_IP = y
CONFIG_NETCONSOLE = y
+CONFIG_CMD_NBC = y
CONFIG_SHA1_CHECK_UB_IMG = y
endif
@@ -64,6 +65,7 @@ BIN_FILES-$(CONFIG_CMD_LOADS) += img2srec$(SFX)
BIN_FILES-$(CONFIG_INCA_IP) += inca-swap-bytes$(SFX)
BIN_FILES-y += mkimage$(SFX)
BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX)
+BIN_FILES-$(CONFIG_CMD_NBC) += sendnbc$(SFX)
BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX)
# Source files which exist outside the tools directory
@@ -86,6 +88,7 @@ NOPED_OBJ_FILES-y += kwbimage.o
NOPED_OBJ_FILES-y += imximage.o
NOPED_OBJ_FILES-y += mkimage.o
OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o
+OBJ_FILES-$(CONFIG_CMD_NBC) += sendnbc.o
NOPED_OBJ_FILES-y += os_support.o
OBJ_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1.o
@@ -197,6 +200,9 @@ $(obj)ncb$(SFX): $(obj)ncb.o
$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
$(HOSTSTRIP) $@
+$(obj)sendnbc$(SFX): $(obj)sendnbc.o
+ $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
+
$(obj)ubsha1$(SFX): $(obj)os_support.o $(obj)sha1.o $(obj)ubsha1.o
$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
diff --git a/tools/sendnbc.c b/tools/sendnbc.c
new file mode 100644
index 0000000..03bf5af
--- /dev/null
+++ b/tools/sendnbc.c
@@ -0,0 +1,219 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/ether.h>
+
+static void usage (char *argv0)
+{
+ printf
+ ("SENDNBC: sends a magic packet to u-boot board to interrupt the autoboot\n");
+ printf (" and reconfigure u-boot in netconsole mode.\n");
+ printf
+ (" Use in combination with netconsole to connect and control\n");
+ printf (" your u-boot device\n");
+ printf
+ (" Ex: BOARD_IP=192.168.0.2 ./sendnbc -i $BOARD_IP -d eth0 && ./netconsole $BOARD_IP\n");
+ printf ("\nusage: %s [options]\n", argv0);
+ printf (" -i <ip addr>: the ip addr to assign to u-boot board\n");
+ printf (" -m <mac addr>: the targeted board mac addr \n");
+ printf (" -n <hostname>: the targeted board hostname \n");
+ printf
+ (" -d <device>: the net interface to use for broadcasting (ex: eth0). Must be root to use this option\n");
+ printf (" -h: display this help\n");
+}
+
+static int build_nbc_pkt (char *buf, int buf_len, char *ip, char *mac,
+ char *hostname)
+{
+ int offset = 0;
+ char *size = NULL;
+ char *ip_size = NULL;
+ char *mac_size = NULL;
+ char *hostname_size = NULL;
+
+ struct in_addr binip;
+ struct ether_addr binmac;
+
+ memset (buf, 0, buf_len);
+
+ buf[0] = (char)0xD3; /* magic number */
+ offset += 1;
+
+ strcpy (buf + offset, "NBC"); /* packet header */
+ offset += 3;
+
+ size = (char *)(buf + offset); /* msg total size */
+ offset += 1;
+
+ strcpy (buf + offset, "IP"); /* IP chunk header */
+ offset += 4;
+
+ ip_size = (char *)(buf + offset); /* IP chunk size */
+ offset += 1;
+
+ inet_pton (AF_INET, ip, &binip);
+ memcpy (buf + offset, &binip, sizeof (struct in_addr)); /* IP chunk data */
+ offset += sizeof (struct in_addr);
+ *ip_size = sizeof (struct in_addr);
+
+ if (mac) {
+ strcpy (buf + offset, "MAC"); /* MAC chunk header */
+ offset += 4;
+
+ mac_size = (char *)(buf + offset); /* MAC chunk size */
+ offset += 1;
+
+ ether_aton_r (mac, &binmac);
+ memcpy (buf + offset, &binmac, sizeof (struct ether_addr)); /* MAC chunk data */
+ offset += sizeof (struct ether_addr);
+ *mac_size = sizeof (struct ether_addr);
+ }
+
+ if (hostname) {
+ strcpy (buf + offset, "HOST"); /* HOST chunk header */
+ offset += 4;
+
+ hostname_size = (char *)(buf + offset); /* HOST chunk size */
+ offset += 1;
+
+ strcpy (buf + offset, hostname); /* HOST chunk data */
+ offset += strlen (hostname);
+ *hostname_size = strlen (hostname);
+ }
+
+ *size = offset;
+
+ return offset;
+}
+
+int main (int argc, char *argv[])
+{
+ char buf[255];
+ int s, len, o, nbcport = 4446, netconsoleport = 6666;
+ int buf_len = sizeof (buf);
+ char option;
+ char *ip = NULL;
+ char *mac = NULL;
+ char *device = NULL;
+ char *hostname = NULL;
+ struct sockaddr_in addr;
+ struct sockaddr_in broadcast_addr;
+ socklen_t addr_len = sizeof (addr);
+ socklen_t broadcast_addr_len = sizeof (broadcast_addr);
+
+ s = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (s < 0) {
+ perror ("Error with socket creation");
+ return 1;
+ }
+ while ((option = getopt (argc, argv, "hn:m:i:d:")) >= 0) {
+ switch (option) {
+ case 'h':
+ usage (argv[0]);
+ exit (0);
+ case 'd':
+ device = optarg;
+ break;
+ case 'n':
+ hostname = optarg;
+ break;
+ case 'm':
+ mac = optarg;
+ break;
+ case 'i':
+ ip = optarg;
+ break;
+ default:
+ usage (argv[0]);
+ exit (0);
+ }
+ }
+
+ if (!ip) {
+ usage (argv[0]);
+ exit (0);
+ }
+
+ /* set sockoptions */
+ o = 1;
+ len = 4;
+ setsockopt (3, SOL_SOCKET, SO_REUSEADDR, &o, len);
+ o = 1;
+ len = 4;
+ setsockopt (3, SOL_SOCKET, SO_BROADCAST, &o, len);
+ if (device) {
+ len = strlen (device);
+ setsockopt (3, SOL_SOCKET, SO_BINDTODEVICE, device, len);
+ }
+
+ /* configure socket */
+ memset (&addr, 0, sizeof (struct sockaddr_in));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons (netconsoleport);
+ addr.sin_addr.s_addr = INADDR_ANY;
+
+ memset (&broadcast_addr, 0, sizeof (struct sockaddr_in));
+ broadcast_addr.sin_family = AF_INET;
+ broadcast_addr.sin_port = htons (nbcport);
+ broadcast_addr.sin_addr.s_addr = INADDR_BROADCAST;
+
+ if (bind (s, (struct sockaddr *)&addr, sizeof (addr)) < 0) {
+ perror ("error with bind");
+ close (s);
+ }
+
+ /* build packets */
+ buf_len = build_nbc_pkt (buf, sizeof (buf), ip, mac, hostname);
+
+ for (;;) {
+ char recv_buf = '\n';
+ struct in_addr binip;
+ struct sockaddr_in board_addr;
+ socklen_t board_addr_len = sizeof (struct sockaddr_in);
+
+ memset (&addr, 0, sizeof (struct sockaddr_in));
+ inet_pton (AF_INET, ip, &binip);
+ board_addr.sin_family = AF_INET;
+ board_addr.sin_port = htons (netconsoleport);
+ memcpy (&board_addr.sin_addr.s_addr, &binip,
+ sizeof (struct in_addr));
+
+ /* send the magic packet */
+ len =
+ sendto (s, buf, buf_len, 0,
+ (struct sockaddr *)&broadcast_addr,
+ broadcast_addr_len);
+ if (len < 0) {
+ perror ("error in send");
+ break;
+ }
+
+ usleep (100000);
+
+ /* check for u-boot in netconsole mode */
+ len =
+ sendto (s, &recv_buf, 1, 0, (struct sockaddr *)&board_addr,
+ board_addr_len);
+ len = recv (s, &recv_buf, 1, MSG_PEEK | MSG_DONTWAIT);
+ if (len < 0) {
+ if (errno != EAGAIN) {
+ perror ("error in recv");
+ break;
+ }
+ } else if (len > 0) {
+ break;
+ }
+ }
+ if (len < 0) {
+ return 1;
+ }
+
+ close (s);
+
+ return 0;
+}
--
1.7.2.3
More information about the U-Boot
mailing list