From: Tristan Lelong <tristan.lel...@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.lel...@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 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot