summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/Kconfig1
-rw-r--r--include/linux/string.h3
-rw-r--r--include/net-lwip.h1
-rw-r--r--lib/lwip/lwip/src/apps/tftp/tftp.c54
-rw-r--r--lib/lwip/u-boot/arch/cc.h2
-rw-r--r--lib/string.c51
-rw-r--r--net/lwip/dhcp.c2
-rw-r--r--net/lwip/dns.c2
-rw-r--r--net/lwip/net-lwip.c23
-rw-r--r--net/lwip/ping.c2
-rw-r--r--net/lwip/tftp.c2
-rw-r--r--net/lwip/wget.c13
-rw-r--r--test/lib/string.c40
13 files changed, 153 insertions, 43 deletions
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 1f9b26928c4..a04fcaa0e08 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2161,6 +2161,7 @@ config WGET_HTTPS
depends on CMD_WGET
depends on PROT_TCP_LWIP
depends on MBEDTLS_LIB
+ depends on DM_RNG
select SHA256
select RSA
select ASYMMETRIC_KEY_TYPE
diff --git a/include/linux/string.h b/include/linux/string.h
index 27b2beb9ddb..d943fcce690 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -72,6 +72,9 @@ extern char * strrchr(const char *,int);
#ifndef __HAVE_ARCH_STRSTR
extern char * strstr(const char *,const char *);
#endif
+#ifndef __HAVE_ARCH_STRNSTR
+extern char *strnstr(const char *, const char *, size_t);
+#endif
#ifndef __HAVE_ARCH_STRLEN
extern __kernel_size_t strlen(const char *);
#endif
diff --git a/include/net-lwip.h b/include/net-lwip.h
index 4d7f9387d1d..64e5c720560 100644
--- a/include/net-lwip.h
+++ b/include/net-lwip.h
@@ -10,6 +10,7 @@ enum proto_t {
TFTPGET
};
+void net_lwip_set_current(void);
struct netif *net_lwip_new_netif(struct udevice *udev);
struct netif *net_lwip_new_netif_noip(struct udevice *udev);
void net_lwip_remove_netif(struct netif *netif);
diff --git a/lib/lwip/lwip/src/apps/tftp/tftp.c b/lib/lwip/lwip/src/apps/tftp/tftp.c
index 56aeabc4d73..63b1e0e0e20 100644
--- a/lib/lwip/lwip/src/apps/tftp/tftp.c
+++ b/lib/lwip/lwip/src/apps/tftp/tftp.c
@@ -264,19 +264,55 @@ static u16_t payload_size(void)
return TFTP_DEFAULT_BLOCK_SIZE;
}
+/**
+ * find_option() - check if OACK message contains option
+ *
+ * @p: message buffer
+ * @option: option key
+ * Return: option value
+ */
static const char *
find_option(struct pbuf *p, const char *option)
{
- int i;
- u16_t optlen = strlen(option);
- const char *b = p->payload;
-
- for (i = 0; i + optlen + 1 < p->len; i++) {
- if (lwip_strnstr(b + i, option, optlen))
- return b + i + optlen + 2;
- }
+ const char *pos = p->payload;
+ int rem = p->len;
+
+ /*
+ * According to RFC 2347 the OACK packet has the following format:
+ *
+ * +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+
+ * | opc | opt1 | 0 | value1 | 0 | optN | 0 | valueN | 0 |
+ * +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+
+ */
+
+ /* Skip opc */
+ pos += 2;
+ rem -= 2;
+ if (rem <= 0)
+ return NULL;
+
+ for (;;) {
+ int len;
+ int diff;
+
+ len = strnlen(pos, rem) + 1;
+ if (rem < len)
+ break;
+ diff = strcmp(pos, option);
+ /* Skip option */
+ pos += len;
+ rem -= len;
+ len = strnlen(pos, rem) + 1;
+ if (rem < len)
+ break;
+ if (!diff)
+ return pos;
+ /* Skip value */
+ pos += len;
+ rem -= len;
+ }
- return NULL;
+ return NULL;
}
static void
diff --git a/lib/lwip/u-boot/arch/cc.h b/lib/lwip/u-boot/arch/cc.h
index de138846358..6104c296f6f 100644
--- a/lib/lwip/u-boot/arch/cc.h
+++ b/lib/lwip/u-boot/arch/cc.h
@@ -34,7 +34,7 @@
x, __LINE__, __FILE__); } while (0)
#define atoi(str) (int)dectoul(str, NULL)
-#define lwip_strnstr(a, b, c) strstr(a, b)
+#define lwip_strnstr(a, b, c) strnstr(a, b, c)
#define LWIP_ERR_T int
#define LWIP_CONST_CAST(target_type, val) ((target_type)((uintptr_t)val))
diff --git a/lib/string.c b/lib/string.c
index 0e0900de8bf..d56f88d4a84 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -15,13 +15,14 @@
* reentrant and should be faster). Use only strsep() in new code, please.
*/
+#include <asm/sections.h>
#include <config.h>
+#include <limits.h>
#include <linux/compiler.h>
-#include <linux/types.h>
-#include <linux/string.h>
#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/types.h>
#include <malloc.h>
-#include <asm/sections.h>
/**
* strncasecmp - Case insensitive, length-limited string comparison
@@ -679,30 +680,48 @@ char *memdup(const void *src, size_t len)
return p;
}
-#ifndef __HAVE_ARCH_STRSTR
+#ifndef __HAVE_ARCH_STRNSTR
/**
- * strstr - Find the first substring in a %NUL terminated string
- * @s1: The string to be searched
- * @s2: The string to search for
+ * strnstr() - find the first substring occurrence in a NUL terminated string
+ *
+ * @s1: string to be searched
+ * @s2: string to search for
+ * @len: maximum number of characters in s2 to consider
+ *
+ * Return: pointer to the first occurrence or NULL
*/
-char * strstr(const char * s1,const char * s2)
+char *strnstr(const char *s1, const char *s2, size_t len)
{
- int l1, l2;
+ size_t l1, l2;
+ l1 = strnlen(s1, len);
l2 = strlen(s2);
- if (!l2)
- return (char *) s1;
- l1 = strlen(s1);
- while (l1 >= l2) {
- l1--;
- if (!memcmp(s1,s2,l2))
+
+ for (; l1 >= l2; --l1, ++s1) {
+ if (!memcmp(s1, s2, l2))
return (char *) s1;
- s1++;
}
+
return NULL;
}
#endif
+#ifndef __HAVE_ARCH_STRSTR
+/**
+ * strstr() - find the first substring occurrence in a NUL terminated string
+ *
+ * @s1: string to be searched
+ * @s2: string to search for
+ * @len: maximum number of characters in s2 to consider
+ *
+ * Return: pointer to the first occurrence or NULL
+ */
+char *strstr(const char *s1, const char *s2)
+{
+ return strnstr(s1, s2, SIZE_MAX);
+}
+#endif
+
#ifndef __HAVE_ARCH_MEMCHR
/**
* memchr - Find a character in an area of memory.
diff --git a/net/lwip/dhcp.c b/net/lwip/dhcp.c
index e7d9147455c..3b7e4700c6e 100644
--- a/net/lwip/dhcp.c
+++ b/net/lwip/dhcp.c
@@ -115,7 +115,7 @@ int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
int ret;
struct udevice *dev;
- eth_set_current();
+ net_lwip_set_current();
dev = eth_get_dev();
if (!dev) {
diff --git a/net/lwip/dns.c b/net/lwip/dns.c
index 1de63c9998b..149bdb784dc 100644
--- a/net/lwip/dns.c
+++ b/net/lwip/dns.c
@@ -121,7 +121,7 @@ int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
if (argc == 3)
var = argv[2];
- eth_set_current();
+ net_lwip_set_current();
return dns_loop(eth_get_dev(), name, var);
}
diff --git a/net/lwip/net-lwip.c b/net/lwip/net-lwip.c
index b863047f598..cab1dd7d483 100644
--- a/net/lwip/net-lwip.c
+++ b/net/lwip/net-lwip.c
@@ -127,6 +127,20 @@ static int get_udev_ipv4_info(struct udevice *dev, ip4_addr_t *ip,
return 0;
}
+/* Initialize the lwIP stack and the ethernet devices and set current device */
+void net_lwip_set_current(void)
+{
+ static bool init_done;
+
+ if (!init_done) {
+ eth_init_rings();
+ eth_init();
+ lwip_init();
+ init_done = true;
+ }
+ eth_set_current();
+}
+
static struct netif *new_netif(struct udevice *udev, bool with_ip)
{
unsigned char enetaddr[ARP_HLEN];
@@ -134,19 +148,10 @@ static struct netif *new_netif(struct udevice *udev, bool with_ip)
ip4_addr_t ip, mask, gw;
struct netif *netif;
int ret = 0;
- static bool first_call = true;
if (!udev)
return NULL;
- if (first_call) {
- eth_init_rings();
- /* Pick a valid active device, if any */
- eth_init();
- lwip_init();
- first_call = false;
- }
-
if (eth_start_udev(udev) < 0) {
log_err("Could not start %s\n", udev->name);
return NULL;
diff --git a/net/lwip/ping.c b/net/lwip/ping.c
index aa617530749..200a702bbb5 100644
--- a/net/lwip/ping.c
+++ b/net/lwip/ping.c
@@ -168,7 +168,7 @@ int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
if (!ipaddr_aton(argv[1], &addr))
return CMD_RET_USAGE;
- eth_set_current();
+ net_lwip_set_current();
if (ping_loop(eth_get_dev(), &addr) < 0)
return CMD_RET_FAILURE;
diff --git a/net/lwip/tftp.c b/net/lwip/tftp.c
index fc4aff5f2ba..123d66b5dba 100644
--- a/net/lwip/tftp.c
+++ b/net/lwip/tftp.c
@@ -280,7 +280,7 @@ int do_tftpb(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
goto out;
}
- eth_set_current();
+ net_lwip_set_current();
if (tftp_loop(eth_get_dev(), laddr, fname, srvip, port) < 0)
ret = CMD_RET_FAILURE;
diff --git a/net/lwip/wget.c b/net/lwip/wget.c
index b76f6c0f1d9..14f27d42998 100644
--- a/net/lwip/wget.c
+++ b/net/lwip/wget.c
@@ -354,7 +354,7 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
int wget_do_request(ulong dst_addr, char *uri)
{
- eth_set_current();
+ net_lwip_set_current();
if (!wget_info)
wget_info = &default_wget_info;
@@ -433,10 +433,15 @@ bool wget_validate_uri(char *uri)
if (!strncmp(uri, "http://", strlen("http://"))) {
prefix_len = strlen("http://");
- } else if (!strncmp(uri, "https://", strlen("https://"))) {
- prefix_len = strlen("https://");
+ } else if (CONFIG_IS_ENABLED(WGET_HTTPS)) {
+ if (!strncmp(uri, "https://", strlen("https://"))) {
+ prefix_len = strlen("https://");
+ } else {
+ log_err("only http(s):// is supported\n");
+ return false;
+ }
} else {
- log_err("only http(s):// is supported\n");
+ log_err("only http:// is supported\n");
return false;
}
diff --git a/test/lib/string.c b/test/lib/string.c
index 8d22f3fd68f..31391a387b9 100644
--- a/test/lib/string.c
+++ b/test/lib/string.c
@@ -11,6 +11,7 @@
#include <command.h>
#include <log.h>
+#include <string.h>
#include <test/lib.h>
#include <test/test.h>
#include <test/ut.h>
@@ -221,3 +222,42 @@ static int lib_memdup(struct unit_test_state *uts)
return 0;
}
LIB_TEST(lib_memdup, 0);
+
+/** lib_strnstr() - unit test for strnstr() */
+static int lib_strnstr(struct unit_test_state *uts)
+{
+ const char *s1 = "Itsy Bitsy Teenie Weenie";
+ const char *s2 = "eenie";
+ const char *s3 = "eery";
+
+ ut_asserteq_ptr(&s1[12], strnstr(s1, s2, SIZE_MAX));
+ ut_asserteq_ptr(&s1[12], strnstr(s1, s2, 17));
+ ut_assertnull(strnstr(s1, s2, 16));
+ ut_assertnull(strnstr(s1, s2, 0));
+ ut_asserteq_ptr(&s1[13], strnstr(&s1[3], &s2[1], SIZE_MAX));
+ ut_asserteq_ptr(&s1[13], strnstr(&s1[3], &s2[1], 14));
+ ut_assertnull(strnstr(&s1[3], &s2[1], 13));
+ ut_assertnull(strnstr(&s1[3], &s2[1], 0));
+ ut_assertnull(strnstr(s1, s3, SIZE_MAX));
+ ut_assertnull(strnstr(s1, s3, 0));
+
+ return 0;
+}
+LIB_TEST(lib_strnstr, 0);
+
+/** lib_strstr() - unit test for strstr() */
+static int lib_strstr(struct unit_test_state *uts)
+{
+ const char *s1 = "Itsy Bitsy Teenie Weenie";
+ const char *s2 = "eenie";
+ const char *s3 = "easy";
+
+ ut_asserteq_ptr(&s1[12], strstr(s1, s2));
+ ut_asserteq_ptr(&s1[13], strstr(&s1[3], &s2[1]));
+ ut_assertnull(strstr(s1, s3));
+ ut_asserteq_ptr(&s1[2], strstr(s1, &s3[2]));
+ ut_asserteq_ptr(&s1[8], strstr(&s1[5], &s3[2]));
+
+ return 0;
+}
+LIB_TEST(lib_strstr, 0);