[PATCH] net/netcat: add netcat over tcp support

This patch adds downloading/uploading of data with netcat utility. Client/server modes are supported both.
This patch is also an example of using new tcp api for legacy stack.
How to test: ============ netcat-openbsd=1.219-1 from debian were used for a tests
a) Load data from remote host. * U-Boot listen on tcp port 3456 * PC connects
u-boot: netcat load ${loadaddr} 3456 PC: netcat -q1 ${UBOOT_IP} 3456 < image.itb
b) Load data from remote host. * PC listen on tcp port 3456 * U-Boot connects
PC: netcat -q1 -l -p 3456 < image.itb u-boot: netcat load ${loadaddr} ${PC_IP}:3456
c) Save data to remote host * U-Boot listen on tcp port 3456 * PC connects
u-boot: netcat save ${loadaddr} ${data_size_in_hex} 3456 PC: netcat -w1 ${UBOOT_IP} 3456 >image.itb
d) Save data to remote host * PC listen on tcp port 3456 * U-Boot connects
PC: netcat -w1 -l -p 3456 >image.itb u-boot: netcat save ${loadaddr} ${data_size_in_hex} ${PC_IP}:3456
Signed-off-by: Mikhail Kshevetskiy mikhail.kshevetskiy@iopsys.eu Reviewed-by: Simon Glass sjg@chromium.org --- cmd/Kconfig | 10 +++ cmd/net.c | 35 ++++++-- include/net-legacy.h | 2 +- include/net/netcat.h | 20 +++++ net/Makefile | 1 + net/net.c | 9 ++ net/netcat.c | 194 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 265 insertions(+), 6 deletions(-) create mode 100644 include/net/netcat.h create mode 100644 net/netcat.c
diff --git a/cmd/Kconfig b/cmd/Kconfig index 93efeaec6f4..e37e50a18b5 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -2091,6 +2091,16 @@ config CMD_DNS help Lookup the IP of a hostname
+config CMD_NETCAT + bool "netcat" + select PROT_TCP + help + netcat is a simple command to load/store kernel, or other files, + using well-known netcat (nc) utility. Unlike classic netcat utility + this command supports TCP-based data transfer only, thus no data + will be lost or reordered. Any netcat implementation should work, + but openbsd one was tested only. + config CMD_MII bool "mii" imply CMD_MDIO diff --git a/cmd/net.c b/cmd/net.c index 79525f73a51..d7a5025f940 100644 --- a/cmd/net.c +++ b/cmd/net.c @@ -208,6 +208,29 @@ U_BOOT_CMD( ); #endif
+#if defined(CONFIG_CMD_NETCAT) +static int do_netcat_load(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + return netboot_common(NETCAT_LOAD, cmdtp, argc, argv); +} + +static int do_netcat_save(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + return netboot_common(NETCAT_SAVE, cmdtp, argc, argv); +} + +U_BOOT_LONGHELP(netcat, + "load [loadAddress] [[hostIPaddr:]port]\n" + "save Address Size [[hostIPaddr:]port]"); + +U_BOOT_CMD_WITH_SUBCMDS(netcat, + "load/store data over plain TCP via netcat utility", netcat_help_text, + U_BOOT_SUBCMD_MKENT(load, 3, 0, do_netcat_load), + U_BOOT_SUBCMD_MKENT(save, 4, 0, do_netcat_save)); +#endif + static void netboot_update_env(void) { char tmp[46]; @@ -325,16 +348,17 @@ static int parse_args(enum proto_t proto, int argc, char *const argv[])
switch (argc) { case 1: - if (IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) + if ((IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) || + (IS_ENABLED(CONFIG_CMD_NETCAT) && proto == NETCAT_SAVE)) return 1; - /* refresh bootfile name from env */ copy_filename(net_boot_file_name, env_get("bootfile"), sizeof(net_boot_file_name)); break;
case 2: - if (IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) + if ((IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) || + (IS_ENABLED(CONFIG_CMD_NETCAT) && proto == NETCAT_SAVE)) return 1; /* * Only one arg - accept two forms: @@ -356,7 +380,8 @@ static int parse_args(enum proto_t proto, int argc, char *const argv[]) break;
case 3: - if (IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) { + if ((IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) || + (IS_ENABLED(CONFIG_CMD_NETCAT) && proto == NETCAT_SAVE)) { if (parse_addr_size(argv)) return 1; } else { @@ -367,7 +392,7 @@ static int parse_args(enum proto_t proto, int argc, char *const argv[]) } break;
-#ifdef CONFIG_CMD_TFTPPUT +#if defined(CONFIG_CMD_TFTPPUT) || defined(CONFIG_CMD_NETCAT) case 4: if (parse_addr_size(argv)) return 1; diff --git a/include/net-legacy.h b/include/net-legacy.h index bc0f0cde9fe..84a4beb9ec1 100644 --- a/include/net-legacy.h +++ b/include/net-legacy.h @@ -305,7 +305,7 @@ extern int net_restart_wrap; /* Tried all network devices */ enum proto_t { BOOTP, RARP, ARP, TFTPGET, DHCP, DHCP6, PING, PING6, DNS, NFS, CDP, NETCONS, SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT_UDP, FASTBOOT_TCP, - WOL, UDP, NCSI, WGET, RS + WOL, UDP, NCSI, WGET, NETCAT_LOAD, NETCAT_SAVE, RS };
/* Indicates whether the file name was specified on the command line */ diff --git a/include/net/netcat.h b/include/net/netcat.h new file mode 100644 index 00000000000..d8e09aaaa55 --- /dev/null +++ b/include/net/netcat.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-2-Clause + * + * netcat include file + * Copyright (C) 2024 IOPSYS Software Solutions AB + * Author: Mikhail Kshevetskiy mikhail.kshevetskiy@iopsys.eu + */ +#ifndef __NET_NETCAT_TCP_H__ +#define __NET_NETCAT_TCP_H__ + +/** + * netcat_load_start() - begin netcat in loading mode + */ +void netcat_load_start(void); + +/** + * netcat_save_start() - begin netcat in data saving mode + */ +void netcat_save_start(void); + +#endif /* __NET_NETCAT_TCP_H__ */ diff --git a/net/Makefile b/net/Makefile index 7c917b318c0..bc5f2f123be 100644 --- a/net/Makefile +++ b/net/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_CMD_WOL) += wol.o obj-$(CONFIG_PROT_UDP) += udp.o obj-$(CONFIG_PROT_TCP) += tcp.o obj-$(CONFIG_WGET) += wget.o +obj-$(CONFIG_CMD_NETCAT) += netcat.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 1828f1cca36..595bffdc532 100644 --- a/net/net.c +++ b/net/net.c @@ -103,6 +103,7 @@ #include <net/fastboot_udp.h> #include <net/fastboot_tcp.h> #include <net/ncsi.h> +#include <net/netcat.h> #if defined(CONFIG_CMD_PCAP) #include <net/pcap.h> #endif @@ -572,6 +573,14 @@ restart: wget_start(); break; #endif +#if defined(CONFIG_CMD_NETCAT) + case NETCAT_LOAD: + netcat_load_start(); + break; + case NETCAT_SAVE: + netcat_save_start(); + break; +#endif #if defined(CONFIG_CMD_CDP) case CDP: cdp_start(); diff --git a/net/netcat.c b/net/netcat.c new file mode 100644 index 00000000000..47dbebe5ae2 --- /dev/null +++ b/net/netcat.c @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * netcat support driver + * Copyright (C) 2024 IOPSYS Software Solutions AB + * Author: Mikhail Kshevetskiy mikhail.kshevetskiy@iopsys.eu + */ + +#include <command.h> +#include <display_options.h> +#include <env.h> +#include <image.h> +#include <mapmem.h> +#include <net.h> +#include <net/tcp.h> +#include <net/netcat.h> + +#define HASHES_PER_LINE 65 +#define MARKER_STEP 10 + +static struct in_addr server_ip; +static u16 server_port; +static u16 local_port; +static int listen; +static int reading; +static int marker, marks_in_line; +static enum net_loop_state netcat_loop_state; + +static void show_block_marker(int packets) +{ + for (; marker + MARKER_STEP <= packets; marker += MARKER_STEP) { + marks_in_line++; + putc('#'); + if (marks_in_line == HASHES_PER_LINE) { + marks_in_line = 0; + puts("\n"); + } + } +} + +static void tcp_stream_on_closed(struct tcp_stream *tcp) +{ + if (tcp->status != TCP_ERR_OK) + netcat_loop_state = NETLOOP_FAIL; + + /* + * The status line will be shown after the download/upload + * progress (see show_block_marker() function). This progress + * generally have no final "\n", so jump to new line before + * output the status + */ + if (netcat_loop_state != NETLOOP_SUCCESS) { + net_boot_file_size = 0; + printf("\nnetcat: Transfer Fail, TCP status - %d\n", tcp->status); + } else { + env_set_hex("filesize", net_boot_file_size); + printf("\nPackets %s %d, Transfer Successful\n", + reading ? "received" : "transmitted", + reading ? tcp->rx_packets : tcp->tx_packets); + } + net_set_state(netcat_loop_state); +} + +static void tcp_stream_on_rcv_nxt_update(struct tcp_stream *tcp, u32 rx_bytes) +{ + net_boot_file_size = rx_bytes; + show_block_marker(tcp->rx_packets); +} + +static void tcp_stream_on_snd_una_update(struct tcp_stream *tcp, u32 tx_bytes) +{ + show_block_marker(tcp->tx_packets); + if (tx_bytes == image_save_size) + tcp_stream_close(tcp); +} + +static void tcp_stream_on_established(struct tcp_stream *tcp) +{ + netcat_loop_state = NETLOOP_SUCCESS; +} + +static int tcp_stream_rx(struct tcp_stream *tcp, u32 rx_offs, void *buf, int len) +{ + void *ptr; + + ptr = map_sysmem(image_load_addr + rx_offs, len); + memcpy(ptr, buf, len); + unmap_sysmem(ptr); + + return len; +} + +static int tcp_stream_tx(struct tcp_stream *tcp, u32 tx_offs, void *buf, int maxlen) +{ + void *ptr; + + if (tx_offs + maxlen > image_save_size) + maxlen = image_save_size - tx_offs; + if (!maxlen) + return 0; + + ptr = map_sysmem(image_save_addr + tx_offs, maxlen); + memcpy(buf, ptr, maxlen); + unmap_sysmem(ptr); + + return maxlen; +} + +/* + * This function will be called on new connections (incoming or outgoing) + * It MUST: + * -- setup required tcp_stream callbacks (if connection will be accepted) + * -- return a connection verdict: + * 0: discard connection + * 1: accept connection + */ +static int tcp_stream_on_create(struct tcp_stream *tcp) +{ + if (listen) { + /* + * We are listening for incoming connections. + * Accept connections to netcat listen port only. + */ + if (tcp->lport != local_port) + return 0; + } else { + /* + * We are connecting to remote host. + * Check remote IP:port to make sure that this is our connection + */ + if (tcp->rhost.s_addr != server_ip.s_addr || + tcp->rport != server_port) + return 0; + } + + netcat_loop_state = NETLOOP_FAIL; + net_boot_file_size = 0; + marker = 0; + marks_in_line = 0; + + tcp->on_closed = tcp_stream_on_closed; + tcp->on_established = tcp_stream_on_established; + if (reading) { + tcp->on_rcv_nxt_update = tcp_stream_on_rcv_nxt_update; + tcp->rx = tcp_stream_rx; + } else { + tcp->on_snd_una_update = tcp_stream_on_snd_una_update; + tcp->tx = tcp_stream_tx; + } + + return 1; +} + +static void netcat_start(void) +{ + struct tcp_stream *tcp; + + memset(net_server_ethaddr, 0, 6); + tcp_stream_set_on_create_handler(tcp_stream_on_create); + + if (!strchr(net_boot_file_name, ':')) { + listen = 1; + printf("Listening on port %s...\n", net_boot_file_name); + + local_port = dectoul(net_boot_file_name, NULL); + } else { + listen = 0; + printf("Connecting to %s...\n", net_boot_file_name); + + server_ip = string_to_ip(net_boot_file_name); + server_port = dectoul(strchr(net_boot_file_name, ':') + 1, NULL); + + tcp = tcp_stream_connect(server_ip, server_port); + if (!tcp) { + printf("No free tcp streams\n"); + net_set_state(NETLOOP_FAIL); + return; + } + tcp_stream_put(tcp); + } +} + +void netcat_load_start(void) +{ + reading = 1; + + return netcat_start(); +} + +void netcat_save_start(void) +{ + reading = 0; + + return netcat_start(); +}

On 1/1/25 04:33, Mikhail Kshevetskiy wrote:
This patch adds downloading/uploading of data with netcat utility. Client/server modes are supported both.
This patch is also an example of using new tcp api for legacy stack.
How to test:
netcat-openbsd=1.219-1 from debian were used for a tests
a) Load data from remote host. * U-Boot listen on tcp port 3456 * PC connects
u-boot: netcat load ${loadaddr} 3456 PC: netcat -q1 ${UBOOT_IP} 3456 < image.itb
b) Load data from remote host. * PC listen on tcp port 3456 * U-Boot connects
PC: netcat -q1 -l -p 3456 < image.itb u-boot: netcat load ${loadaddr} ${PC_IP}:3456
c) Save data to remote host * U-Boot listen on tcp port 3456 * PC connects
u-boot: netcat save ${loadaddr} ${data_size_in_hex} 3456 PC: netcat -w1 ${UBOOT_IP} 3456 >image.itb
d) Save data to remote host * PC listen on tcp port 3456 * U-Boot connects
PC: netcat -w1 -l -p 3456 >image.itb u-boot: netcat save ${loadaddr} ${data_size_in_hex} ${PC_IP}:3456
Signed-off-by: Mikhail Kshevetskiy mikhail.kshevetskiy@iopsys.eu Reviewed-by: Simon Glass sjg@chromium.org
cmd/Kconfig | 10 +++ cmd/net.c | 35 ++++++-- include/net-legacy.h | 2 +- include/net/netcat.h | 20 +++++ net/Makefile | 1 + net/net.c | 9 ++ net/netcat.c | 194 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 265 insertions(+), 6 deletions(-) create mode 100644 include/net/netcat.h create mode 100644 net/netcat.c
diff --git a/cmd/Kconfig b/cmd/Kconfig index 93efeaec6f4..e37e50a18b5 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -2091,6 +2091,16 @@ config CMD_DNS help Lookup the IP of a hostname
+config CMD_NETCAT
- bool "netcat"
- select PROT_TCP
Thank you for your patch which looks like a useful addition to U-Boot.
Here you make the netcat command depend on CMD_NET. This dependency seems unnecessary at least for the lwIP case.
- help
netcat is a simple command to load/store kernel, or other files,
using well-known netcat (nc) utility. Unlike classic netcat utility
this command supports TCP-based data transfer only, thus no data
will be lost or reordered. Any netcat implementation should work,
but openbsd one was tested only.
- config CMD_MII bool "mii" imply CMD_MDIO
diff --git a/cmd/net.c b/cmd/net.c index 79525f73a51..d7a5025f940 100644 --- a/cmd/net.c +++ b/cmd/net.c @@ -208,6 +208,29 @@ U_BOOT_CMD( ); #endif
+#if defined(CONFIG_CMD_NETCAT) +static int do_netcat_load(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
- return netboot_common(NETCAT_LOAD, cmdtp, argc, argv);
+}
+static int do_netcat_save(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
+{
- return netboot_common(NETCAT_SAVE, cmdtp, argc, argv);
+}
+U_BOOT_LONGHELP(netcat,
- "load [loadAddress] [[hostIPaddr:]port]\n"
- "save Address Size [[hostIPaddr:]port]");
+U_BOOT_CMD_WITH_SUBCMDS(netcat,
- "load/store data over plain TCP via netcat utility", netcat_help_text,
- U_BOOT_SUBCMD_MKENT(load, 3, 0, do_netcat_load),
- U_BOOT_SUBCMD_MKENT(save, 4, 0, do_netcat_save));
+#endif
- static void netboot_update_env(void) { char tmp[46];
@@ -325,16 +348,17 @@ static int parse_args(enum proto_t proto, int argc, char *const argv[])
switch (argc) { case 1:
if (IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT)
if ((IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) ||
(IS_ENABLED(CONFIG_CMD_NETCAT) && proto == NETCAT_SAVE)) return 1;
/* refresh bootfile name from env */ copy_filename(net_boot_file_name, env_get("bootfile"), sizeof(net_boot_file_name)); break;
case 2:
if (IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT)
if ((IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) ||
/*(IS_ENABLED(CONFIG_CMD_NETCAT) && proto == NETCAT_SAVE)) return 1;
- Only one arg - accept two forms:
@@ -356,7 +380,8 @@ static int parse_args(enum proto_t proto, int argc, char *const argv[]) break;
case 3:
if (IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) {
if ((IS_ENABLED(CONFIG_CMD_TFTPPUT) && proto == TFTPPUT) ||
} else {(IS_ENABLED(CONFIG_CMD_NETCAT) && proto == NETCAT_SAVE)) { if (parse_addr_size(argv)) return 1;
@@ -367,7 +392,7 @@ static int parse_args(enum proto_t proto, int argc, char *const argv[]) } break;
-#ifdef CONFIG_CMD_TFTPPUT +#if defined(CONFIG_CMD_TFTPPUT) || defined(CONFIG_CMD_NETCAT) case 4: if (parse_addr_size(argv)) return 1; diff --git a/include/net-legacy.h b/include/net-legacy.h index bc0f0cde9fe..84a4beb9ec1 100644 --- a/include/net-legacy.h +++ b/include/net-legacy.h @@ -305,7 +305,7 @@ extern int net_restart_wrap; /* Tried all network devices */ enum proto_t { BOOTP, RARP, ARP, TFTPGET, DHCP, DHCP6, PING, PING6, DNS, NFS, CDP, NETCONS, SNTP, TFTPSRV, TFTPPUT, LINKLOCAL, FASTBOOT_UDP, FASTBOOT_TCP,
- WOL, UDP, NCSI, WGET, RS
WOL, UDP, NCSI, WGET, NETCAT_LOAD, NETCAT_SAVE, RS };
/* Indicates whether the file name was specified on the command line */
diff --git a/include/net/netcat.h b/include/net/netcat.h new file mode 100644 index 00000000000..d8e09aaaa55 --- /dev/null +++ b/include/net/netcat.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-2-Clause
According to doc/develop/sending_patches.rst all new code should use the GPL-2.0-or-later license.
- netcat include file
- Copyright (C) 2024 IOPSYS Software Solutions AB
- Author: Mikhail Kshevetskiy mikhail.kshevetskiy@iopsys.eu
- */
+#ifndef __NET_NETCAT_TCP_H__ +#define __NET_NETCAT_TCP_H__
+/**
- netcat_load_start() - begin netcat in loading mode
- */
+void netcat_load_start(void);
+/**
- netcat_save_start() - begin netcat in data saving mode
- */
+void netcat_save_start(void);
+#endif /* __NET_NETCAT_TCP_H__ */ diff --git a/net/Makefile b/net/Makefile index 7c917b318c0..bc5f2f123be 100644 --- a/net/Makefile +++ b/net/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_CMD_WOL) += wol.o obj-$(CONFIG_PROT_UDP) += udp.o obj-$(CONFIG_PROT_TCP) += tcp.o obj-$(CONFIG_WGET) += wget.o +obj-$(CONFIG_CMD_NETCAT) += netcat.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 1828f1cca36..595bffdc532 100644 --- a/net/net.c +++ b/net/net.c @@ -103,6 +103,7 @@ #include <net/fastboot_udp.h> #include <net/fastboot_tcp.h> #include <net/ncsi.h> +#include <net/netcat.h> #if defined(CONFIG_CMD_PCAP) #include <net/pcap.h> #endif @@ -572,6 +573,14 @@ restart: wget_start(); break; #endif +#if defined(CONFIG_CMD_NETCAT)
case NETCAT_LOAD:
netcat_load_start();
break;
case NETCAT_SAVE:
netcat_save_start();
break;
+#endif #if defined(CONFIG_CMD_CDP) case CDP: cdp_start(); diff --git a/net/netcat.c b/net/netcat.c new file mode 100644 index 00000000000..47dbebe5ae2 --- /dev/null +++ b/net/netcat.c @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0
According to doc/develop/sending_patches.rst all new code should use the GPL-2.0-or-later license.
+/*
- netcat support driver
- Copyright (C) 2024 IOPSYS Software Solutions AB
- Author: Mikhail Kshevetskiy mikhail.kshevetskiy@iopsys.eu
- */
+#include <command.h> +#include <display_options.h> +#include <env.h> +#include <image.h> +#include <mapmem.h> +#include <net.h> +#include <net/tcp.h> +#include <net/netcat.h>
+#define HASHES_PER_LINE 65 +#define MARKER_STEP 10
+static struct in_addr server_ip; +static u16 server_port; +static u16 local_port; +static int listen; +static int reading; +static int marker, marks_in_line; +static enum net_loop_state netcat_loop_state;
Please, describe all functions in Sphinx style. Cf. https://docs.kernel.org/doc-guide/kernel-doc.html#function-documentation
+static void show_block_marker(int packets) +{
- for (; marker + MARKER_STEP <= packets; marker += MARKER_STEP) {
marks_in_line++;
putc('#');
if (marks_in_line == HASHES_PER_LINE) {
marks_in_line = 0;
puts("\n");
}
- }
+}
+static void tcp_stream_on_closed(struct tcp_stream *tcp) +{
- if (tcp->status != TCP_ERR_OK)
netcat_loop_state = NETLOOP_FAIL;
- /*
* The status line will be shown after the download/upload
* progress (see show_block_marker() function). This progress
* generally have no final "\n", so jump to new line before
* output the status
*/
- if (netcat_loop_state != NETLOOP_SUCCESS) {
net_boot_file_size = 0;
printf("\nnetcat: Transfer Fail, TCP status - %d\n", tcp->status);
- } else {
env_set_hex("filesize", net_boot_file_size);
printf("\nPackets %s %d, Transfer Successful\n",
reading ? "received" : "transmitted",
reading ? tcp->rx_packets : tcp->tx_packets);
- }
- net_set_state(netcat_loop_state);
+}
+static void tcp_stream_on_rcv_nxt_update(struct tcp_stream *tcp, u32 rx_bytes) +{
- net_boot_file_size = rx_bytes;
- show_block_marker(tcp->rx_packets);
+}
+static void tcp_stream_on_snd_una_update(struct tcp_stream *tcp, u32 tx_bytes) +{
- show_block_marker(tcp->tx_packets);
- if (tx_bytes == image_save_size)
tcp_stream_close(tcp);
+}
+static void tcp_stream_on_established(struct tcp_stream *tcp) +{
- netcat_loop_state = NETLOOP_SUCCESS;
+}
+static int tcp_stream_rx(struct tcp_stream *tcp, u32 rx_offs, void *buf, int len) +{
- void *ptr;
- ptr = map_sysmem(image_load_addr + rx_offs, len);
- memcpy(ptr, buf, len);
- unmap_sysmem(ptr);
- return len;
+}
+static int tcp_stream_tx(struct tcp_stream *tcp, u32 tx_offs, void *buf, int maxlen) +{
- void *ptr;
- if (tx_offs + maxlen > image_save_size)
maxlen = image_save_size - tx_offs;
- if (!maxlen)
return 0;
- ptr = map_sysmem(image_save_addr + tx_offs, maxlen);
- memcpy(buf, ptr, maxlen);
- unmap_sysmem(ptr);
- return maxlen;
+}
+/*
- This function will be called on new connections (incoming or outgoing)
- It MUST:
- -- setup required tcp_stream callbacks (if connection will be accepted)
- -- return a connection verdict:
0: discard connection
1: accept connection
Please, use a Sphinx style function description.
Best regards
Heinrich
- */
+static int tcp_stream_on_create(struct tcp_stream *tcp) +{
- if (listen) {
/*
* We are listening for incoming connections.
* Accept connections to netcat listen port only.
*/
if (tcp->lport != local_port)
return 0;
- } else {
/*
* We are connecting to remote host.
* Check remote IP:port to make sure that this is our connection
*/
if (tcp->rhost.s_addr != server_ip.s_addr ||
tcp->rport != server_port)
return 0;
- }
- netcat_loop_state = NETLOOP_FAIL;
- net_boot_file_size = 0;
- marker = 0;
- marks_in_line = 0;
- tcp->on_closed = tcp_stream_on_closed;
- tcp->on_established = tcp_stream_on_established;
- if (reading) {
tcp->on_rcv_nxt_update = tcp_stream_on_rcv_nxt_update;
tcp->rx = tcp_stream_rx;
- } else {
tcp->on_snd_una_update = tcp_stream_on_snd_una_update;
tcp->tx = tcp_stream_tx;
- }
- return 1;
+}
+static void netcat_start(void) +{
- struct tcp_stream *tcp;
- memset(net_server_ethaddr, 0, 6);
- tcp_stream_set_on_create_handler(tcp_stream_on_create);
- if (!strchr(net_boot_file_name, ':')) {
listen = 1;
printf("Listening on port %s...\n", net_boot_file_name);
local_port = dectoul(net_boot_file_name, NULL);
- } else {
listen = 0;
printf("Connecting to %s...\n", net_boot_file_name);
server_ip = string_to_ip(net_boot_file_name);
server_port = dectoul(strchr(net_boot_file_name, ':') + 1, NULL);
tcp = tcp_stream_connect(server_ip, server_port);
if (!tcp) {
printf("No free tcp streams\n");
net_set_state(NETLOOP_FAIL);
return;
}
tcp_stream_put(tcp);
- }
+}
+void netcat_load_start(void) +{
- reading = 1;
- return netcat_start();
+}
+void netcat_save_start(void) +{
- reading = 0;
- return netcat_start();
+}
participants (2)
-
Heinrich Schuchardt
-
Mikhail Kshevetskiy