From patchwork Fri Dec 2 09:18:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Vyacheslav V. Mitrofanov" X-Patchwork-Id: 1711316 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=yadro.com header.i=@yadro.com header.a=rsa-sha256 header.s=mta-01 header.b=XDsUa9hn; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4NNnVT28c1z23nC for ; Fri, 2 Dec 2022 20:20:49 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 1B6808545A; Fri, 2 Dec 2022 10:19:31 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=yadro.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=yadro.com header.i=@yadro.com header.b="XDsUa9hn"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9431A853D1; Fri, 2 Dec 2022 10:19:12 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mta-01.yadro.com (mta-02.yadro.com [89.207.88.252]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 879D985221 for ; Fri, 2 Dec 2022 10:18:57 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=yadro.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=v.v.mitrofanov@yadro.com Received: from localhost (unknown [127.0.0.1]) by mta-01.yadro.com (Postfix) with ESMTP id 32A394014D; Fri, 2 Dec 2022 09:18:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=yadro.com; h= content-type:content-type:content-transfer-encoding:mime-version :references:in-reply-to:x-mailer:message-id:date:date:subject :subject:from:from:received:received:received:received; s= mta-01; t=1669972735; x=1671787136; bh=EfPY34axddgOvqPxeOdHspO4+ ZPIVGXH9KGbuVsBihs=; b=XDsUa9hn6402EPXHN59Q4E3LHhQyy8gWaFiIGchng FFglRvSPXpGv/wvdecjBkV/UxZbziuKo9PMIYVJcrlvWvPiX73o80Ph06W5ws7+8 oESS2LmV3TqLjPonKTAXKagHc+6MYsfZhLkLttebuu0gTy9syBP3b2jBLM/MqqAQ O8= Received: from mta-01.yadro.com ([127.0.0.1]) by localhost (mta-01.yadro.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id YJ53d2XK0Jji; Fri, 2 Dec 2022 12:18:55 +0300 (MSK) Received: from T-EXCH-02.corp.yadro.com (T-EXCH-02.corp.yadro.com [172.17.10.102]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by mta-01.yadro.com (Postfix) with ESMTPS id 9AFC140889; Fri, 2 Dec 2022 12:18:55 +0300 (MSK) Received: from T-Exch-05.corp.yadro.com (172.17.10.109) by T-EXCH-02.corp.yadro.com (172.17.10.102) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.669.32; Fri, 2 Dec 2022 12:18:55 +0300 Received: from v.yadro.com (10.178.114.10) by T-Exch-05.corp.yadro.com (172.17.10.109) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.2.1118.9; Fri, 2 Dec 2022 12:18:54 +0300 From: Viacheslav Mitrofanov To: CC: , , , , , , Subject: [PATCH v5 10/19] net: tftp: Add IPv6 support for tftpboot Date: Fri, 2 Dec 2022 12:18:07 +0300 Message-ID: <20221202091818.2382748-11-v.v.mitrofanov@yadro.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20221202091818.2382748-1-v.v.mitrofanov@yadro.com> References: <20221202091818.2382748-1-v.v.mitrofanov@yadro.com> MIME-Version: 1.0 X-Originating-IP: [10.178.114.10] X-ClientProxiedBy: T-EXCH-01.corp.yadro.com (172.17.10.101) To T-Exch-05.corp.yadro.com (172.17.10.109) X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.6 at phobos.denx.de X-Virus-Status: Clean The command tftpboot uses IPv4 by default. Add the possibility to use IPv6 instead. If an address in the command is an IPv6 address it will use IPv6 to boot or if there is a suffix -ipv6 in the end of the command it also force using IPv6. All other tftpboot features and parameters are left the same. Signed-off-by: Viacheslav Mitrofanov Reviewed-by: Ramon Fried Reviewed-by: Simon Glass --- cmd/net.c | 35 ++++++++++++++++++++++++++++++++ net/net.c | 17 ++++++++++++++-- net/tftp.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 103 insertions(+), 7 deletions(-) diff --git a/cmd/net.c b/cmd/net.c index f6d9f5ea3a..221b3525ca 100644 --- a/cmd/net.c +++ b/cmd/net.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -45,12 +46,22 @@ int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) return ret; } +#if IS_ENABLED(CONFIG_IPV6) +U_BOOT_CMD( + tftpboot, 4, 1, do_tftpb, + "boot image via network using TFTP protocol\n" + "To use IPv6 add -ipv6 parameter or use IPv6 hostIPaddr framed " + "with [] brackets", + "[loadAddress] [[hostIPaddr:]bootfilename] [" USE_IP6_CMD_PARAM "]" +); +#else U_BOOT_CMD( tftpboot, 3, 1, do_tftpb, "load file via network using TFTP protocol", "[loadAddress] [[hostIPaddr:]bootfilename]" ); #endif +#endif #ifdef CONFIG_CMD_TFTPPUT static int do_tftpput(struct cmd_tbl *cmdtp, int flag, int argc, @@ -306,6 +317,17 @@ static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc, if (s != NULL) image_load_addr = hextoul(s, NULL); + if (IS_ENABLED(CONFIG_IPV6)) { + use_ip6 = false; + + /* IPv6 parameter has to be always *last* */ + if (!strcmp(argv[argc - 1], USE_IP6_CMD_PARAM)) { + use_ip6 = true; + /* It is a hack not to break switch/case code */ + --argc; + } + } + if (parse_args(proto, argc, argv)) { bootstage_error(BOOTSTAGE_ID_NET_START); return CMD_RET_USAGE; @@ -313,6 +335,19 @@ static int netboot_common(enum proto_t proto, struct cmd_tbl *cmdtp, int argc, bootstage_mark(BOOTSTAGE_ID_NET_START); + if (IS_ENABLED(CONFIG_IPV6) && !use_ip6) { + char *s, *e; + size_t len; + + s = strchr(net_boot_file_name, '['); + e = strchr(net_boot_file_name, ']'); + if (s && e) { + len = e - s; + if (!string_to_ip6(s + 1, len - 1, &net_server_ip6)) + use_ip6 = true; + } + } + size = net_loop(proto); if (size < 0) { bootstage_error(BOOTSTAGE_ID_NET_NETLOOP_OK); diff --git a/net/net.c b/net/net.c index 63bf962b53..28c8dfdef2 100644 --- a/net/net.c +++ b/net/net.c @@ -1455,7 +1455,14 @@ static int net_check_prereq(enum proto_t protocol) /* Fall through */ case TFTPGET: case TFTPPUT: - if (net_server_ip.s_addr == 0 && !is_serverip_in_cmd()) { + if (IS_ENABLED(CONFIG_IPV6) && use_ip6) { + if (!memcmp(&net_server_ip6, &net_null_addr_ip6, + sizeof(struct in6_addr)) && + !strchr(net_boot_file_name, '[')) { + puts("*** ERROR: `serverip6' not set\n"); + return 1; + } + } else if (net_server_ip.s_addr == 0 && !is_serverip_in_cmd()) { puts("*** ERROR: `serverip' not set\n"); return 1; } @@ -1468,7 +1475,13 @@ common: case NETCONS: case FASTBOOT: case TFTPSRV: - if (net_ip.s_addr == 0) { + if (IS_ENABLED(CONFIG_IPV6) && use_ip6) { + if (!memcmp(&net_link_local_ip6, &net_null_addr_ip6, + sizeof(struct in6_addr))) { + puts("*** ERROR: `ip6addr` not set\n"); + return 1; + } + } else if (net_ip.s_addr == 0) { puts("*** ERROR: `ipaddr' not set\n"); return 1; } diff --git a/net/tftp.c b/net/tftp.c index 39421f8daa..c780c33f37 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include "bootp.h" @@ -41,6 +42,7 @@ DECLARE_GLOBAL_DATA_PTR; static ulong timeout_ms = TIMEOUT; static int timeout_count_max = (CONFIG_NET_RETRY_COUNT * 2); static ulong time_start; /* Record time we started tftp */ +static struct in6_addr tftp_remote_ip6; /* * These globals govern the timeout behavior when attempting a connection to a @@ -116,6 +118,7 @@ static int tftp_put_final_block_sent; /* default TFTP block size */ #define TFTP_BLOCK_SIZE 512 +#define TFTP_MTU_BLOCKSIZE6 (CONFIG_TFTP_BLOCKSIZE - 20) /* sequence number is 16 bit */ #define TFTP_SEQUENCE_SIZE ((ulong)(1<<16)) @@ -320,7 +323,11 @@ static void tftp_send(void) * We will always be sending some sort of packet, so * cobble together the packet headers now. */ - pkt = net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE; + if (IS_ENABLED(CONFIG_IPV6) && use_ip6) + pkt = net_tx_packet + net_eth_hdr_size() + + IP6_HDR_SIZE + UDP_HDR_SIZE; + else + pkt = net_tx_packet + net_eth_hdr_size() + IP_UDP_HDR_SIZE; switch (tftp_state) { case STATE_SEND_RRQ: @@ -422,8 +429,14 @@ static void tftp_send(void) break; } - net_send_udp_packet(net_server_ethaddr, tftp_remote_ip, - tftp_remote_port, tftp_our_port, len); + if (IS_ENABLED(CONFIG_IPV6) && use_ip6) + net_send_udp_packet6(net_server_ethaddr, + &tftp_remote_ip6, + tftp_remote_port, + tftp_our_port, len); + else + net_send_udp_packet(net_server_ethaddr, tftp_remote_ip, + tftp_remote_port, tftp_our_port, len); if (err_pkt) net_set_state(NETLOOP_FAIL); @@ -797,6 +810,9 @@ void tftp_start(enum proto_t protocol) debug("TFTP blocksize = %i, TFTP windowsize = %d timeout = %ld ms\n", tftp_block_size_option, tftp_window_size_option, timeout_ms); + if (IS_ENABLED(CONFIG_IPV6)) + tftp_remote_ip6 = net_server_ip6; + tftp_remote_ip = net_server_ip; if (!net_parse_bootfile(&tftp_remote_ip, tftp_filename, MAX_LEN)) { sprintf(default_filename, "%02X%02X%02X%02X.img", @@ -812,17 +828,49 @@ void tftp_start(enum proto_t protocol) tftp_filename); } + if (IS_ENABLED(CONFIG_IPV6)) { + if (use_ip6) { + char *s, *e; + size_t len; + + s = strchr(net_boot_file_name, '['); + e = strchr(net_boot_file_name, ']'); + len = e - s; + if (s && e) { + string_to_ip6(s + 1, len, &tftp_remote_ip6); + strlcpy(tftp_filename, e + 2, MAX_LEN); + } else { + strlcpy(tftp_filename, net_boot_file_name, MAX_LEN); + tftp_filename[MAX_LEN - 1] = 0; + } + } + } + printf("Using %s device\n", eth_get_name()); - printf("TFTP %s server %pI4; our IP address is %pI4", + + if (IS_ENABLED(CONFIG_IPV6) && use_ip6) { + printf("TFTP from server %pI6c; our IP address is %pI6c", + &tftp_remote_ip6, &net_ip6); + + if (tftp_block_size_option > TFTP_MTU_BLOCKSIZE6) + tftp_block_size_option = TFTP_MTU_BLOCKSIZE6; + } else { + printf("TFTP %s server %pI4; our IP address is %pI4", #ifdef CONFIG_CMD_TFTPPUT protocol == TFTPPUT ? "to" : "from", #else "from", #endif &tftp_remote_ip, &net_ip); + } /* Check if we need to send across this subnet */ - if (net_gateway.s_addr && net_netmask.s_addr) { + if (IS_ENABLED(CONFIG_IPV6) && use_ip6) { + if (!ip6_addr_in_subnet(&net_ip6, &tftp_remote_ip6, + net_prefix_length)) + printf("; sending through gateway %pI6c", + &net_gateway6); + } else if (net_gateway.s_addr && net_netmask.s_addr) { struct in_addr our_net; struct in_addr remote_net;