summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/Kconfig9
-rw-r--r--net/Makefile2
-rw-r--r--net/lwip/Makefile2
-rw-r--r--net/lwip/wget.c60
-rw-r--r--net/net-common.c14
-rw-r--r--net/net.c11
-rw-r--r--net/wget.c123
7 files changed, 174 insertions, 47 deletions
diff --git a/net/Kconfig b/net/Kconfig
index 76ab7d91eeb..b4bb68dd613 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -244,6 +244,15 @@ config NET_RANDOM_ETHADDR
generated. It will be saved to the appropriate environment variable,
too.
+config WGET
+ bool "Enable wget"
+ select PROT_TCP if NET
+ select PROT_TCP_LWIP if NET_LWIP
+ select PROT_DNS_LWIP if NET_LWIP
+ help
+ Selecting this will enable wget, an interface to send HTTP requests
+ via the network stack.
+
config TFTP_BLOCKSIZE
int "TFTP block size"
default 1468
diff --git a/net/Makefile b/net/Makefile
index 209377aeb26..7c917b318c0 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -29,7 +29,7 @@ obj-$(CONFIG_$(PHASE_)TCP_FUNCTION_FASTBOOT) += fastboot_tcp.o
obj-$(CONFIG_CMD_WOL) += wol.o
obj-$(CONFIG_PROT_UDP) += udp.o
obj-$(CONFIG_PROT_TCP) += tcp.o
-obj-$(CONFIG_CMD_WGET) += wget.o
+obj-$(CONFIG_WGET) += wget.o
# Disable this warning as it is triggered by:
# sprintf(buf, index ? "foo%d" : "foo", index)
diff --git a/net/lwip/Makefile b/net/lwip/Makefile
index f2558f8763a..79dd6b3fb50 100644
--- a/net/lwip/Makefile
+++ b/net/lwip/Makefile
@@ -5,4 +5,4 @@ obj-$(CONFIG_CMD_DHCP) += dhcp.o
obj-$(CONFIG_CMD_DNS) += dns.o
obj-$(CONFIG_CMD_PING) += ping.o
obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o
-obj-$(CONFIG_CMD_WGET) += wget.o
+obj-$(CONFIG_WGET) += wget.o
diff --git a/net/lwip/wget.c b/net/lwip/wget.c
index 5501ffdd004..b76f6c0f1d9 100644
--- a/net/lwip/wget.c
+++ b/net/lwip/wget.c
@@ -27,6 +27,8 @@ enum done_state {
};
struct wget_ctx {
+ char server_name[SERVER_NAME_SIZE];
+ u16 port;
char *path;
ulong daddr;
ulong saved_daddr;
@@ -36,6 +38,23 @@ struct wget_ctx {
enum done_state done;
};
+static void wget_lwip_fill_info(struct pbuf *hdr, u16_t hdr_len, u32_t hdr_cont_len)
+{
+ if (wget_info->headers) {
+ if (hdr_len < MAX_HTTP_HEADERS_SIZE)
+ pbuf_copy_partial(hdr, (void *)wget_info->headers, hdr_len, 0);
+ else
+ hdr_len = 0;
+ wget_info->headers[hdr_len] = 0;
+ }
+ wget_info->hdr_cont_len = (u32)hdr_cont_len;
+}
+
+static void wget_lwip_set_file_size(u32_t rx_content_len)
+{
+ wget_info->file_size = (ulong)rx_content_len;
+}
+
bool wget_validate_uri(char *uri);
int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len,
@@ -215,6 +234,13 @@ static void httpc_result_cb(void *arg, httpc_result_t httpc_result,
struct wget_ctx *ctx = arg;
ulong elapsed;
+ wget_info->status_code = (u32)srv_res;
+
+ if (err == ERR_BUF) {
+ ctx->done = FAILURE;
+ return;
+ }
+
if (httpc_result != HTTPC_RESULT_OK) {
log_err("\nHTTP client error %d\n", httpc_result);
ctx->done = FAILURE;
@@ -234,8 +260,10 @@ static void httpc_result_cb(void *arg, httpc_result_t httpc_result,
printf("%u bytes transferred in %lu ms (", rx_content_len, elapsed);
print_size(rx_content_len / elapsed * 1000, "/s)\n");
printf("Bytes transferred = %lu (%lx hex)\n", ctx->size, ctx->size);
- efi_set_bootdev("Net", "", ctx->path, map_sysmem(ctx->saved_daddr, 0),
- rx_content_len);
+ if (wget_info->set_bootdev)
+ efi_set_bootdev("Http", ctx->server_name, ctx->path, map_sysmem(ctx->saved_daddr, 0),
+ rx_content_len);
+ wget_lwip_set_file_size(rx_content_len);
if (env_set_hex("filesize", rx_content_len) ||
env_set_hex("fileaddr", ctx->saved_daddr)) {
log_err("Could not set filesize or fileaddr\n");
@@ -246,9 +274,19 @@ static void httpc_result_cb(void *arg, httpc_result_t httpc_result,
ctx->done = SUCCESS;
}
+static err_t httpc_headers_done_cb(httpc_state_t *connection, void *arg, struct pbuf *hdr,
+ u16_t hdr_len, u32_t content_len)
+{
+ wget_lwip_fill_info(hdr, hdr_len, content_len);
+
+ if (wget_info->check_buffer_size && (ulong)content_len > wget_info->buffer_size)
+ return ERR_BUF;
+
+ return ERR_OK;
+}
+
static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
{
- char server_name[SERVER_NAME_SIZE];
#if defined CONFIG_WGET_HTTPS
altcp_allocator_t tls_allocator;
#endif
@@ -257,7 +295,6 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
struct netif *netif;
struct wget_ctx ctx;
char *path;
- u16 port;
bool is_https;
ctx.daddr = dst_addr;
@@ -267,7 +304,7 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
ctx.prevsize = 0;
ctx.start_time = 0;
- if (parse_url(uri, server_name, &port, &path, &is_https))
+ if (parse_url(uri, ctx.server_name, &ctx.port, &path, &is_https))
return CMD_RET_USAGE;
netif = net_lwip_new_netif(udev);
@@ -279,7 +316,7 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
if (is_https) {
tls_allocator.alloc = &altcp_tls_alloc;
tls_allocator.arg =
- altcp_tls_create_config_client(NULL, 0, server_name);
+ altcp_tls_create_config_client(NULL, 0, ctx.server_name);
if (!tls_allocator.arg) {
log_err("error: Cannot create a TLS connection\n");
@@ -292,8 +329,9 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
#endif
conn.result_fn = httpc_result_cb;
+ conn.headers_done_fn = httpc_headers_done_cb;
ctx.path = path;
- if (httpc_get_file_dns(server_name, port, path, &conn, httpc_recv_cb,
+ if (httpc_get_file_dns(ctx.server_name, ctx.port, path, &conn, httpc_recv_cb,
&ctx, &state)) {
net_lwip_remove_netif(netif);
return CMD_RET_FAILURE;
@@ -314,10 +352,13 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri)
return -1;
}
-int wget_with_dns(ulong dst_addr, char *uri)
+int wget_do_request(ulong dst_addr, char *uri)
{
eth_set_current();
+ if (!wget_info)
+ wget_info = &default_wget_info;
+
return wget_loop(eth_get_dev(), dst_addr, uri);
}
@@ -344,7 +385,8 @@ int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[])
if (parse_legacy_arg(url, nurl, sizeof(nurl)))
return CMD_RET_FAILURE;
- if (wget_with_dns(dst_addr, nurl))
+ wget_info = &default_wget_info;
+ if (wget_do_request(dst_addr, nurl))
return CMD_RET_FAILURE;
return CMD_RET_SUCCESS;
diff --git a/net/net-common.c b/net/net-common.c
index a7f767d5e9c..e01b0da7d7b 100644
--- a/net/net-common.c
+++ b/net/net-common.c
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
+#include <net-common.h>
void copy_filename(char *dst, const char *src, int size)
{
@@ -11,3 +12,16 @@ void copy_filename(char *dst, const char *src, int size)
*dst++ = *src++;
*dst = '\0';
}
+
+struct wget_http_info default_wget_info = {
+ .method = WGET_HTTP_METHOD_GET,
+ .set_bootdev = true,
+};
+
+struct wget_http_info *wget_info;
+
+int wget_request(ulong dst_addr, char *uri, struct wget_http_info *info)
+{
+ wget_info = info ? info : &default_wget_info;
+ return wget_do_request(dst_addr, uri);
+}
diff --git a/net/net.c b/net/net.c
index f47e9fbe33a..ca35704f661 100644
--- a/net/net.c
+++ b/net/net.c
@@ -1723,17 +1723,6 @@ int net_parse_bootfile(struct in_addr *ipaddr, char *filename, int max_len)
return 1;
}
-void ip_to_string(struct in_addr x, char *s)
-{
- x.s_addr = ntohl(x.s_addr);
- sprintf(s, "%d.%d.%d.%d",
- (int) ((x.s_addr >> 24) & 0xff),
- (int) ((x.s_addr >> 16) & 0xff),
- (int) ((x.s_addr >> 8) & 0xff),
- (int) ((x.s_addr >> 0) & 0xff)
- );
-}
-
void vlan_to_string(ushort x, char *s)
{
x = ntohs(x);
diff --git a/net/wget.c b/net/wget.c
index 361817ace65..d338eaf4ef3 100644
--- a/net/wget.c
+++ b/net/wget.c
@@ -22,10 +22,11 @@ DECLARE_GLOBAL_DATA_PTR;
/* The default, change with environment variable 'httpdstp' */
#define SERVER_PORT 80
-static const char bootfile1[] = "GET ";
+static const char bootfileGET[] = "GET ";
+static const char bootfileHEAD[] = "HEAD ";
static const char bootfile3[] = " HTTP/1.0\r\n\r\n";
static const char http_eom[] = "\r\n\r\n";
-static const char http_ok[] = "200";
+static const char content_len[] = "Content-Length";
static const char linefeed[] = "\r\n";
static struct in_addr web_server_ip;
static int our_port;
@@ -45,6 +46,7 @@ struct pkt_qd {
#define PKTQ_SZ (PKTBUFSRX / 4)
static struct pkt_qd pkt_q[PKTQ_SZ];
static int pkt_q_idx;
+static unsigned long content_length;
static unsigned int packets;
static unsigned int initial_data_seq_num;
@@ -75,7 +77,7 @@ static inline int store_block(uchar *src, unsigned int offset, unsigned int len)
ulong newsize = offset + len;
uchar *ptr;
- if (CONFIG_IS_ENABLED(LMB)) {
+ if (CONFIG_IS_ENABLED(LMB) && wget_info->set_bootdev) {
if (store_addr < image_load_addr ||
lmb_read_check(store_addr, len)) {
printf("\nwget error: ");
@@ -130,8 +132,17 @@ static void wget_send_stored(void)
IP_TCP_HDR_SIZE + TCP_TSOPT_SIZE + 2;
offset = ptr;
- memcpy(offset, &bootfile1, strlen(bootfile1));
- offset += strlen(bootfile1);
+ switch (wget_info->method) {
+ case WGET_HTTP_METHOD_HEAD:
+ memcpy(offset, &bootfileHEAD, strlen(bootfileHEAD));
+ offset += strlen(bootfileHEAD);
+ break;
+ case WGET_HTTP_METHOD_GET:
+ default:
+ memcpy(offset, &bootfileGET, strlen(bootfileGET));
+ offset += strlen(bootfileGET);
+ break;
+ }
memcpy(offset, image_url, strlen(image_url));
offset += strlen(image_url);
@@ -191,6 +202,52 @@ static void wget_timeout_handler(void)
#define PKT_QUEUE_OFFSET 0x20000
#define PKT_QUEUE_PACKET_SIZE 0x800
+static void wget_fill_info(const uchar *pkt, int hlen)
+{
+ const char *first_space;
+ const char *second_space;
+ char *pos, *end;
+
+ if (wget_info->headers) {
+ if (hlen < MAX_HTTP_HEADERS_SIZE)
+ strncpy(wget_info->headers, pkt, hlen);
+ else
+ hlen = 0;
+ wget_info->headers[hlen] = 0;
+ }
+
+ //Get status code
+ first_space = strchr(pkt, ' ');
+ if (!first_space) {
+ wget_info->status_code = -1;
+ return;
+ }
+
+ second_space = strchr(first_space + 1, ' ');
+ if (!second_space) {
+ wget_info->status_code = -1;
+ return;
+ }
+
+ wget_info->status_code = (u32)simple_strtoul(first_space + 1, &end, 10);
+
+ if (second_space != end)
+ wget_info->status_code = -1;
+
+ pos = strstr((char *)pkt, content_len);
+
+ if (pos) {
+ pos += sizeof(content_len) + 1;
+ while (*pos == ' ')
+ pos++;
+ content_length = simple_strtoul(pos, &end, 10);
+ debug_cond(DEBUG_WGET,
+ "wget: Connected Len %lu\n",
+ content_length);
+ wget_info->hdr_cont_len = content_length;
+ }
+}
+
static void wget_connected(uchar *pkt, unsigned int tcp_seq_num,
u8 action, unsigned int tcp_ack_num, unsigned int len)
{
@@ -239,7 +296,11 @@ static void wget_connected(uchar *pkt, unsigned int tcp_seq_num,
initial_data_seq_num = tcp_seq_num + hlen;
next_data_seq_num = tcp_seq_num + len;
- if (strstr((char *)pkt, http_ok) == 0) {
+ wget_fill_info(pkt, hlen);
+ debug_cond(DEBUG_WGET,
+ "wget: HTTP Status Code %d\n", wget_info->status_code);
+
+ if (wget_info->status_code != 200) {
debug_cond(DEBUG_WGET,
"wget: Connected Bad Xfer\n");
wget_loop_state = NETLOOP_FAIL;
@@ -384,10 +445,13 @@ static void wget_handler(uchar *pkt, u16 dport,
case WGET_TRANSFERRED:
printf("Packets received %d, Transfer Successful\n", packets);
net_set_state(wget_loop_state);
- efi_set_bootdev("Net", "", image_url,
- map_sysmem(image_load_addr, 0),
- net_boot_file_size);
- env_set_hex("filesize", net_boot_file_size);
+ wget_info->file_size = net_boot_file_size;
+ if (wget_info->method == WGET_HTTP_METHOD_GET && wget_info->set_bootdev) {
+ efi_set_bootdev("Http", NULL, image_url,
+ map_sysmem(image_load_addr, 0),
+ net_boot_file_size);
+ env_set_hex("filesize", net_boot_file_size);
+ }
break;
}
}
@@ -412,6 +476,9 @@ static unsigned int random_port(void)
void wget_start(void)
{
+ if (!wget_info)
+ wget_info = &default_wget_info;
+
image_url = strchr(net_boot_file_name, ':');
if (image_url > 0) {
web_server_ip = string_to_ip(net_boot_file_name);
@@ -468,8 +535,7 @@ void wget_start(void)
wget_send(TCP_SYN, 0, 0, 0);
}
-#if (IS_ENABLED(CONFIG_CMD_DNS))
-int wget_with_dns(ulong dst_addr, char *uri)
+int wget_do_request(ulong dst_addr, char *uri)
{
int ret;
char *s, *host_name, *file_name, *str_copy;
@@ -488,24 +554,32 @@ int wget_with_dns(ulong dst_addr, char *uri)
s = str_copy + strlen("http://");
host_name = strsep(&s, "/");
if (!s) {
- log_err("Error: invalied uri, no file path\n");
ret = -EINVAL;
goto out;
}
file_name = s;
- /* TODO: If the given uri has ip address for the http server, skip dns */
- net_dns_resolve = host_name;
- net_dns_env_var = "httpserverip";
- if (net_loop(DNS) < 0) {
- log_err("Error: dns lookup of %s failed, check setup\n", net_dns_resolve);
- ret = -EINVAL;
- goto out;
- }
- s = env_get("httpserverip");
- if (!s) {
+ host_name = strsep(&host_name, ":");
+
+ if (string_to_ip(host_name).s_addr) {
+ s = host_name;
+ } else {
+#if IS_ENABLED(CONFIG_CMD_DNS)
+ net_dns_resolve = host_name;
+ net_dns_env_var = "httpserverip";
+ if (net_loop(DNS) < 0) {
+ ret = -EINVAL;
+ goto out;
+ }
+ s = env_get("httpserverip");
+ if (!s) {
+ ret = -EINVAL;
+ goto out;
+ }
+#else
ret = -EINVAL;
goto out;
+#endif
}
strlcpy(net_boot_file_name, s, sizeof(net_boot_file_name));
@@ -517,9 +591,8 @@ int wget_with_dns(ulong dst_addr, char *uri)
out:
free(str_copy);
- return ret;
+ return ret < 0 ? ret : 0;
}
-#endif
/**
* wget_validate_uri() - validate the uri for wget