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 <common.h>
10 #include <command.h>
11 #include <dm.h>
12 #include <env.h>
13 #include <fdtdec.h>
14 #include <log.h>
15 #include <malloc.h>
16 #include <net.h>
17 #include <net/tcp.h>
18 #include <net/wget.h>
19 #include <asm/eth.h>
20 #include <dm/test.h>
21 #include <dm/device-internal.h>
22 #include <dm/uclass-internal.h>
23 #include <test/lib.h>
24 #include <test/test.h>
25 #include <test/ut.h>
26 
27 #define SHIFT_TO_TCPHDRLEN_FIELD(x) ((x) << 4)
28 #define LEN_B_TO_DW(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 	eth_send->et_protlen = htons(PROT_IP);
67 	tcp_send = (void *)eth_send + ETHER_HDR_SIZE;
68 	tcp_send->tcp_src = tcp->tcp_dst;
69 	tcp_send->tcp_dst = tcp->tcp_src;
70 	tcp_send->tcp_seq = htonl(0);
71 	tcp_send->tcp_ack = htonl(ntohl(tcp->tcp_seq) + 1);
72 	tcp_send->tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
73 	tcp_send->tcp_flags = TCP_SYN | TCP_ACK;
74 	tcp_send->tcp_win = htons(PKTBUFSRX * TCP_MSS >> TCP_SCALE);
75 	tcp_send->tcp_xsum = 0;
76 	tcp_send->tcp_ugr = 0;
77 	tcp_send->tcp_xsum = tcp_set_pseudo_header((uchar *)tcp_send,
78 						   tcp->ip_src,
79 						   tcp->ip_dst,
80 						   TCP_HDR_SIZE,
81 						   IP_TCP_HDR_SIZE);
82 	net_set_ip_header((uchar *)tcp_send,
83 			  tcp->ip_src,
84 			  tcp->ip_dst,
85 			  IP_TCP_HDR_SIZE,
86 			  IPPROTO_TCP);
87 
88 	priv->recv_packet_length[priv->recv_packets] =
89 		ETHER_HDR_SIZE + IP_TCP_HDR_SIZE;
90 	++priv->recv_packets;
91 
92 	return 0;
93 }
94 
sb_ack_handler(struct udevice * dev,void * packet,unsigned int len)95 static int sb_ack_handler(struct udevice *dev, void *packet,
96 			  unsigned int len)
97 {
98 	struct eth_sandbox_priv *priv = dev_get_priv(dev);
99 	struct ethernet_hdr *eth = packet;
100 	struct ip_tcp_hdr *tcp = packet + ETHER_HDR_SIZE;
101 	struct ethernet_hdr *eth_send;
102 	struct ip_tcp_hdr *tcp_send;
103 	void *data;
104 	int pkt_len;
105 	int payload_len = 0;
106 	const char *payload1 = "HTTP/1.1 200 OK\r\n"
107 		"Content-Length: 30\r\n\r\n\r\n"
108 		"<html><body>Hi</body></html>\r\n";
109 
110 	/* Don't allow the buffer to overrun */
111 	if (priv->recv_packets >= PKTBUFSRX)
112 		return 0;
113 
114 	eth_send = (void *)priv->recv_packet_buffer[priv->recv_packets];
115 	memcpy(eth_send->et_dest, eth->et_src, ARP_HLEN);
116 	memcpy(eth_send->et_src, priv->fake_host_hwaddr, ARP_HLEN);
117 	eth_send->et_protlen = htons(PROT_IP);
118 	tcp_send = (void *)eth_send + ETHER_HDR_SIZE;
119 	tcp_send->tcp_src = tcp->tcp_dst;
120 	tcp_send->tcp_dst = tcp->tcp_src;
121 	data = (void *)tcp_send + IP_TCP_HDR_SIZE;
122 
123 	if (ntohl(tcp->tcp_seq) == 1 && ntohl(tcp->tcp_ack) == 1) {
124 		tcp_send->tcp_seq = htonl(ntohl(tcp->tcp_ack));
125 		tcp_send->tcp_ack = htonl(ntohl(tcp->tcp_seq) + 1);
126 		payload_len = strlen(payload1);
127 		memcpy(data, payload1, payload_len);
128 		tcp_send->tcp_flags = TCP_ACK;
129 	} else if (ntohl(tcp->tcp_seq) == 2) {
130 		tcp_send->tcp_seq = htonl(ntohl(tcp->tcp_ack));
131 		tcp_send->tcp_ack = htonl(ntohl(tcp->tcp_seq) + 1);
132 		payload_len = 0;
133 		tcp_send->tcp_flags = TCP_ACK | TCP_FIN;
134 	}
135 
136 	tcp_send->tcp_hlen = SHIFT_TO_TCPHDRLEN_FIELD(LEN_B_TO_DW(TCP_HDR_SIZE));
137 	tcp_send->tcp_win = htons(PKTBUFSRX * TCP_MSS >> TCP_SCALE);
138 	tcp_send->tcp_xsum = 0;
139 	tcp_send->tcp_ugr = 0;
140 	pkt_len = IP_TCP_HDR_SIZE + payload_len;
141 	tcp_send->tcp_xsum = tcp_set_pseudo_header((uchar *)tcp_send,
142 						   tcp->ip_src,
143 						   tcp->ip_dst,
144 						   pkt_len - IP_HDR_SIZE,
145 						   pkt_len);
146 	net_set_ip_header((uchar *)tcp_send,
147 			  tcp->ip_src,
148 			  tcp->ip_dst,
149 			  pkt_len,
150 			  IPPROTO_TCP);
151 
152 	if (ntohl(tcp->tcp_seq) == 1 || ntohl(tcp->tcp_seq) == 2) {
153 		priv->recv_packet_length[priv->recv_packets] =
154 			ETHER_HDR_SIZE + IP_TCP_HDR_SIZE + payload_len;
155 		++priv->recv_packets;
156 	}
157 
158 	return 0;
159 }
160 
sb_http_handler(struct udevice * dev,void * packet,unsigned int len)161 static int sb_http_handler(struct udevice *dev, void *packet,
162 			   unsigned int len)
163 {
164 	struct ethernet_hdr *eth = packet;
165 	struct ip_hdr *ip;
166 	struct ip_tcp_hdr *tcp;
167 
168 	if (ntohs(eth->et_protlen) == PROT_ARP) {
169 		return sb_arp_handler(dev, packet, len);
170 	} else if (ntohs(eth->et_protlen) == PROT_IP) {
171 		ip = packet + ETHER_HDR_SIZE;
172 		if (ip->ip_p == IPPROTO_TCP) {
173 			tcp = packet + ETHER_HDR_SIZE;
174 			if (tcp->tcp_flags == TCP_SYN)
175 				return sb_syn_handler(dev, packet, len);
176 			else if (tcp->tcp_flags & TCP_ACK && !(tcp->tcp_flags & TCP_SYN))
177 				return sb_ack_handler(dev, packet, len);
178 			return 0;
179 		}
180 		return -EPROTONOSUPPORT;
181 	}
182 
183 	return -EPROTONOSUPPORT;
184 }
185 
net_test_wget(struct unit_test_state * uts)186 static int net_test_wget(struct unit_test_state *uts)
187 {
188 	sandbox_eth_set_tx_handler(0, sb_http_handler);
189 	sandbox_eth_set_priv(0, uts);
190 
191 	env_set("ethact", "eth@10002000");
192 	env_set("ethrotate", "no");
193 	env_set("loadaddr", "0x20000");
194 	ut_assertok(run_command("wget ${loadaddr} 1.1.2.2:/index.html", 0));
195 
196 	sandbox_eth_set_tx_handler(0, NULL);
197 
198 	ut_assertok(console_record_reset_enable());
199 	run_command("md5sum ${loadaddr} ${filesize}", 0);
200 	ut_assert_nextline("md5 for 00020000 ... 0002001f ==> 234af48e94b0085060249ecb5942ab57");
201 	ut_assertok(ut_check_console_end(uts));
202 
203 	return 0;
204 }
205 
206 LIB_TEST(net_test_wget, 0);
207