1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2022 Linaro
4  *
5  * (C) Copyright 2022
6  * Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>
7  */
8 
9 #include <command.h>
10 #include <dm.h>
11 #include <env.h>
12 #include <fdtdec.h>
13 #include <log.h>
14 #include <malloc.h>
15 #include <net.h>
16 #include <net/tcp.h>
17 #include <net/wget.h>
18 #include <asm/eth.h>
19 #include <dm/test.h>
20 #include <dm/device-internal.h>
21 #include <dm/uclass-internal.h>
22 #include <test/cmd.h>
23 #include <test/test.h>
24 #include <test/ut.h>
25 
26 #define SHIFT_TO_TCPHDRLEN_FIELD(x) ((x) << 4)
27 #define LEN_B_TO_DW(x) ((x) >> 2)
28 #define GET_TCP_HDR_LEN_IN_BYTES(x) ((x) >> 2)
29 
sb_arp_handler(struct udevice * dev,void * packet,unsigned int len)30 static int sb_arp_handler(struct udevice *dev, void *packet,
31 			  unsigned int len)
32 {
33 	struct eth_sandbox_priv *priv = dev_get_priv(dev);
34 	struct arp_hdr *arp = packet + ETHER_HDR_SIZE;
35 	int ret = 0;
36 
37 	if (ntohs(arp->ar_op) == ARPOP_REQUEST) {
38 		priv->fake_host_ipaddr = net_read_ip(&arp->ar_spa);
39 
40 		ret = sandbox_eth_recv_arp_req(dev);
41 		if (ret)
42 			return ret;
43 		ret = sandbox_eth_arp_req_to_reply(dev, packet, len);
44 		return ret;
45 	}
46 
47 	return -EPROTONOSUPPORT;
48 }
49 
sb_syn_handler(struct udevice * dev,void * packet,unsigned int len)50 static int sb_syn_handler(struct udevice *dev, void *packet,
51 			  unsigned int len)
52 {
53 	struct eth_sandbox_priv *priv = dev_get_priv(dev);
54 	struct ethernet_hdr *eth = packet;
55 	struct ip_tcp_hdr *tcp = packet + ETHER_HDR_SIZE;
56 	struct ethernet_hdr *eth_send;
57 	struct ip_tcp_hdr *tcp_send;
58 
59 	/* Don't allow the buffer to overrun */
60 	if (priv->recv_packets >= PKTBUFSRX)
61 		return 0;
62 
63 	eth_send = (void *)priv->recv_packet_buffer[priv->recv_packets];
64 	memcpy(eth_send->et_dest, eth->et_src, ARP_HLEN);
65 	memcpy(eth_send->et_src, priv->fake_host_hwaddr, ARP_HLEN);
66 	priv->irs = ntohl(tcp->tcp_seq);
67 	priv->iss = ~priv->irs; /* just to differ from irs */
68 	eth_send->et_protlen = htons(PROT_IP);
69 	tcp_send = (void *)eth_send + ETHER_HDR_SIZE;
70 	tcp_send->tcp_src = tcp->tcp_dst;
71 	tcp_send->tcp_dst = tcp->tcp_src;
72 	tcp_send->tcp_seq = htonl(priv->iss);
73 	tcp_send->tcp_ack = htonl(priv->irs + 1);
74 	tcp_send->tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
75 	tcp_send->tcp_flags = TCP_SYN | TCP_ACK;
76 	tcp_send->tcp_win = htons(PKTBUFSRX * TCP_MSS >> TCP_SCALE);
77 	tcp_send->tcp_xsum = 0;
78 	tcp_send->tcp_ugr = 0;
79 	tcp_send->tcp_xsum = tcp_set_pseudo_header((uchar *)tcp_send,
80 						   tcp->ip_src,
81 						   tcp->ip_dst,
82 						   TCP_HDR_SIZE,
83 						   IP_TCP_HDR_SIZE);
84 	net_set_ip_header((uchar *)tcp_send,
85 			  tcp->ip_src,
86 			  tcp->ip_dst,
87 			  IP_TCP_HDR_SIZE,
88 			  IPPROTO_TCP);
89 
90 	priv->recv_packet_length[priv->recv_packets] =
91 		ETHER_HDR_SIZE + IP_TCP_HDR_SIZE;
92 	++priv->recv_packets;
93 
94 	return 0;
95 }
96 
sb_ack_handler(struct udevice * dev,void * packet,unsigned int len)97 static int sb_ack_handler(struct udevice *dev, void *packet,
98 			  unsigned int len)
99 {
100 	struct eth_sandbox_priv *priv = dev_get_priv(dev);
101 	struct ethernet_hdr *eth = packet;
102 	struct ip_tcp_hdr *tcp = packet + ETHER_HDR_SIZE;
103 	struct ethernet_hdr *eth_send;
104 	struct ip_tcp_hdr *tcp_send;
105 	void *data;
106 	int pkt_len;
107 	int payload_len = 0;
108 	u32 tcp_seq, tcp_ack;
109 	int tcp_data_len;
110 	const char *payload1 =
111 		/* response status line */
112 		"HTTP/1.1 200 OK\r\n"
113 		/* response header fields */
114 		"Date: Mon, 23 Dec 2024 05:18:23 GMT\r\n"
115 		"Server: Apache/2.4.62 (Debian)\r\n"
116 		"Last-Modified: Mon, 23 Dec 2024 05:04:50 GMT\r\n"
117 		"ETag: \"1d-629e8efb09e7b\"\r\n"
118 		"Accept-Ranges: bytes\r\n"
119 		"Content-Length: 29\r\n"
120 		"Connection: close\r\n"
121 		"Content-Type: text/html\r\n"
122 		/* response header fields end marker */
123 		"\r\n"
124 		/* file data (for HTTP GET requests) */
125 		"<html><body>Hi</body></html>\n";
126 
127 	/* Don't allow the buffer to overrun */
128 	if (priv->recv_packets >= PKTBUFSRX)
129 		return 0;
130 
131 	eth_send = (void *)priv->recv_packet_buffer[priv->recv_packets];
132 	memcpy(eth_send->et_dest, eth->et_src, ARP_HLEN);
133 	memcpy(eth_send->et_src, priv->fake_host_hwaddr, ARP_HLEN);
134 	eth_send->et_protlen = htons(PROT_IP);
135 	tcp_send = (void *)eth_send + ETHER_HDR_SIZE;
136 	tcp_send->tcp_src = tcp->tcp_dst;
137 	tcp_send->tcp_dst = tcp->tcp_src;
138 	data = (void *)tcp_send + IP_TCP_HDR_SIZE;
139 
140 	tcp_seq = ntohl(tcp->tcp_seq) - priv->irs;
141 	tcp_ack = ntohl(tcp->tcp_ack) - priv->iss;
142 	tcp_data_len = len - ETHER_HDR_SIZE - IP_HDR_SIZE - GET_TCP_HDR_LEN_IN_BYTES(tcp->tcp_hlen);
143 
144 	if (tcp->tcp_flags & TCP_FIN)
145 		tcp_data_len++;
146 
147 	tcp_send->tcp_seq = htonl(ntohl(tcp->tcp_ack));
148 	tcp_send->tcp_ack = htonl(ntohl(tcp->tcp_seq) + tcp_data_len);
149 
150 	if (tcp_seq == 1 && tcp_ack == 1) {
151 		if (tcp_data_len == 0) {
152 			/* no data, wait for GET/HEAD request */
153 			return -1;
154 		}
155 
156 		/* reply to GET/HEAD request */
157 		payload_len = strlen(payload1);
158 		memcpy(data, payload1, payload_len);
159 		tcp_send->tcp_flags = TCP_ACK;
160 	} else if (tcp_ack == 1 + strlen(payload1)) {
161 		payload_len = 0;
162 		tcp_send->tcp_flags = TCP_ACK | TCP_FIN;
163 	} else if (tcp_ack == 2 + strlen(payload1)) {
164 		payload_len = 0;
165 		tcp_send->tcp_flags = TCP_ACK;
166 	}
167 
168 	tcp_send->tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
169 	tcp_send->tcp_win = htons(PKTBUFSRX * TCP_MSS >> TCP_SCALE);
170 	tcp_send->tcp_xsum = 0;
171 	tcp_send->tcp_ugr = 0;
172 	pkt_len = IP_TCP_HDR_SIZE + payload_len;
173 	tcp_send->tcp_xsum = tcp_set_pseudo_header((uchar *)tcp_send,
174 						   tcp->ip_src,
175 						   tcp->ip_dst,
176 						   pkt_len - IP_HDR_SIZE,
177 						   pkt_len);
178 	net_set_ip_header((uchar *)tcp_send,
179 			  tcp->ip_src,
180 			  tcp->ip_dst,
181 			  pkt_len,
182 			  IPPROTO_TCP);
183 
184 	priv->recv_packet_length[priv->recv_packets] =
185 		ETHER_HDR_SIZE + IP_TCP_HDR_SIZE + payload_len;
186 	++priv->recv_packets;
187 
188 	return 0;
189 }
190 
sb_http_handler(struct udevice * dev,void * packet,unsigned int len)191 static int sb_http_handler(struct udevice *dev, void *packet,
192 			   unsigned int len)
193 {
194 	struct ethernet_hdr *eth = packet;
195 	struct ip_hdr *ip;
196 	struct ip_tcp_hdr *tcp;
197 
198 	if (ntohs(eth->et_protlen) == PROT_ARP) {
199 		return sb_arp_handler(dev, packet, len);
200 	} else if (ntohs(eth->et_protlen) == PROT_IP) {
201 		ip = packet + ETHER_HDR_SIZE;
202 		if (ip->ip_p == IPPROTO_TCP) {
203 			tcp = packet + ETHER_HDR_SIZE;
204 			if (tcp->tcp_flags == TCP_SYN)
205 				return sb_syn_handler(dev, packet, len);
206 			else if (tcp->tcp_flags & TCP_ACK && !(tcp->tcp_flags & TCP_SYN))
207 				return sb_ack_handler(dev, packet, len);
208 			return 0;
209 		}
210 		return -EPROTONOSUPPORT;
211 	}
212 
213 	return -EPROTONOSUPPORT;
214 }
215 
net_test_wget(struct unit_test_state * uts)216 static int net_test_wget(struct unit_test_state *uts)
217 {
218 	char *prev_ethact = env_get("ethact");
219 	char *prev_ethrotate = env_get("ethrotate");
220 
221 	sandbox_eth_set_tx_handler(0, sb_http_handler);
222 	sandbox_eth_set_priv(0, uts);
223 
224 	env_set("ethact", "eth@10002000");
225 	env_set("ethrotate", "no");
226 	env_set("wgetaddr", "0x20000");
227 	ut_assertok(run_command("wget ${wgetaddr} 1.1.2.2:/index.html", 0));
228 	ut_assert_nextline_empty();
229 	ut_assert_nextline("Packets received 5, Transfer Successful");
230 	ut_assert_nextline("Bytes transferred = 29 (1d hex)");
231 
232 	sandbox_eth_set_tx_handler(0, NULL);
233 
234 	run_command("md5sum ${wgetaddr} ${filesize}", 0);
235 	ut_assert_nextline("md5 for 00020000 ... 0002001c ==> 847d5e7320a27462e90bc1ed75eb8cd8");
236 	ut_assert_console_end();
237 
238 	env_set("ethact", prev_ethact);
239 	env_set("ethrotate", prev_ethrotate);
240 
241 	return 0;
242 }
243 CMD_TEST(net_test_wget, UTF_CONSOLE);
244 
net_test_wget_uri_validate(struct unit_test_state * uts)245 static int net_test_wget_uri_validate(struct unit_test_state *uts)
246 {
247 	ut_asserteq(true, wget_validate_uri("http://foo.com/bar.html"));
248 	ut_asserteq(true, wget_validate_uri("http://1.1.2.3/bar.html"));
249 	ut_asserteq(false, wget_validate_uri("http://foo/ba r.html"));
250 	ut_asserteq(false, wget_validate_uri("http://"));
251 
252 	if (CONFIG_IS_ENABLED(WGET_HTTPS)) {
253 		ut_asserteq(true,
254 			    wget_validate_uri("https://foo.com/bar.html"));
255 		ut_asserteq(true,
256 			    wget_validate_uri("https://1.1.2.3/bar.html"));
257 		ut_asserteq(false, wget_validate_uri("https://foo/ba r.html"));
258 		ut_asserteq(false, wget_validate_uri("https://"));
259 	}
260 
261 	return 0;
262 }
263 CMD_TEST(net_test_wget_uri_validate, UTF_CONSOLE);
264