1 /*
2  * Copyright (c) 2020 InnBlue
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(tftp_client, CONFIG_TFTP_LOG_LEVEL);
9 
10 #include <stddef.h>
11 #include <zephyr/net/tftp.h>
12 #include "tftp_client.h"
13 
14 #define ADDRLEN(sa) \
15 	(sa.sa_family == AF_INET ? \
16 		sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6))
17 
18 /*
19  * Prepare a request as required by RFC1350. This packet can be sent
20  * out directly to the TFTP server.
21  */
make_request(uint8_t * buf,int request,const char * remote_file,const char * mode)22 static size_t make_request(uint8_t *buf, int request,
23 			   const char *remote_file, const char *mode)
24 {
25 	char *ptr = (char *)buf;
26 	const char def_mode[] = "octet";
27 
28 	/* Fill in the Request Type. */
29 	sys_put_be16(request, ptr);
30 	ptr += 2;
31 
32 	/* Copy the name of the remote file. */
33 	strncpy(ptr, remote_file, TFTP_MAX_FILENAME_SIZE);
34 	ptr += strlen(remote_file);
35 	*ptr++ = '\0';
36 
37 	/* Default to "Octet" if mode not specified. */
38 	if (mode == NULL) {
39 		mode = def_mode;
40 	}
41 
42 	/* Copy the mode of operation. */
43 	strncpy(ptr, mode, TFTP_MAX_MODE_SIZE);
44 	ptr += strlen(mode);
45 	*ptr++ = '\0';
46 
47 	return ptr - (char *)buf;
48 }
49 
50 /*
51  * Send Data message to the TFTP Server and receive ACK message from it.
52  */
send_data(int sock,struct tftpc * client,uint32_t block_no,const uint8_t * data_buffer,size_t data_size)53 static int send_data(int sock, struct tftpc *client, uint32_t block_no, const uint8_t *data_buffer,
54 		     size_t data_size)
55 {
56 	int ret;
57 	int send_count = 0, ack_count = 0;
58 	struct zsock_pollfd fds = {
59 		.fd     = sock,
60 		.events = ZSOCK_POLLIN,
61 	};
62 
63 	LOG_DBG("Client send data: block no %u, size %u", block_no, data_size + TFTP_HEADER_SIZE);
64 
65 	do {
66 		if (send_count > TFTP_REQ_RETX) {
67 			LOG_ERR("No more retransmits. Exiting");
68 			return TFTPC_RETRIES_EXHAUSTED;
69 		}
70 
71 		/* Prepare DATA packet, send it out then poll for ACK response */
72 		sys_put_be16(DATA_OPCODE, client->tftp_buf);
73 		sys_put_be16(block_no, client->tftp_buf + 2);
74 		memcpy(client->tftp_buf + TFTP_HEADER_SIZE, data_buffer, data_size);
75 
76 		ret = zsock_send(sock, client->tftp_buf, data_size + TFTP_HEADER_SIZE, 0);
77 		if (ret < 0) {
78 			LOG_ERR("send() error: %d", -errno);
79 			return -errno;
80 		}
81 
82 		do {
83 			if (ack_count > TFTP_REQ_RETX) {
84 				LOG_WRN("No more waiting for ACK");
85 				break;
86 			}
87 
88 			ret = zsock_poll(&fds, 1, CONFIG_TFTPC_REQUEST_TIMEOUT);
89 			if (ret < 0) {
90 				LOG_ERR("recv() error: %d", -errno);
91 				return -errno;  /* IO error */
92 			} else if (ret == 0) {
93 				break;		/* no response, re-send data */
94 			}
95 
96 			ret = zsock_recv(sock, client->tftp_buf, TFTPC_MAX_BUF_SIZE, 0);
97 			if (ret < 0) {
98 				LOG_ERR("recv() error: %d", -errno);
99 				return -errno;
100 			}
101 
102 			if (ret != TFTP_HEADER_SIZE) {
103 				break; /* wrong response, re-send data */
104 			}
105 
106 			uint16_t opcode = sys_get_be16(client->tftp_buf);
107 			uint16_t blockno = sys_get_be16(client->tftp_buf + 2);
108 
109 			LOG_DBG("Receive: opcode %u, block no %u, size %d",
110 				opcode, blockno, ret);
111 
112 			if (opcode == ACK_OPCODE && blockno == block_no) {
113 				return TFTPC_SUCCESS;
114 			} else if (opcode == ACK_OPCODE && blockno < block_no) {
115 				LOG_WRN("Server responded with obsolete block number.");
116 				ack_count++;
117 				continue; /* duplicated ACK */
118 			} else if (opcode == ERROR_OPCODE) {
119 				if (client->callback) {
120 					struct tftp_evt evt = {
121 						.type = TFTP_EVT_ERROR
122 					};
123 
124 					evt.param.error.msg = client->tftp_buf + TFTP_HEADER_SIZE;
125 					evt.param.error.code = block_no;
126 					client->callback(&evt);
127 				}
128 				LOG_WRN("Server responded with obsolete block number.");
129 				break;
130 			} else {
131 				LOG_ERR("Server responded with invalid opcode or block number.");
132 				break; /* wrong response, re-send data */
133 			}
134 		} while (true);
135 
136 		send_count++;
137 	} while (true);
138 
139 	return TFTPC_REMOTE_ERROR;
140 }
141 
142 /*
143  * Send an Error Message to the TFTP Server.
144  */
send_err(int sock,struct tftpc * client,int err_code,char * err_msg)145 static inline int send_err(int sock, struct tftpc *client, int err_code, char *err_msg)
146 {
147 	uint32_t req_size;
148 
149 	LOG_DBG("Client sending error code: %d", err_code);
150 
151 	/* Fill in the "Err" Opcode and the actual error code. */
152 	sys_put_be16(ERROR_OPCODE, client->tftp_buf);
153 	sys_put_be16(err_code, client->tftp_buf + 2);
154 	req_size = 4;
155 
156 	/* Copy the Error String. */
157 	if (err_msg != NULL) {
158 		size_t copy_len = strlen(err_msg);
159 
160 		if (copy_len > sizeof(client->tftp_buf) - req_size) {
161 			copy_len = sizeof(client->tftp_buf) - req_size;
162 		}
163 
164 		memcpy(client->tftp_buf + req_size, err_msg, copy_len);
165 		req_size += copy_len;
166 	}
167 
168 	/* Send Error to server. */
169 	return zsock_send(sock, client->tftp_buf, req_size, 0);
170 }
171 
172 /*
173  * Send an Ack Message to the TFTP Server.
174  */
send_ack(int sock,struct tftphdr_ack * ackhdr)175 static inline int send_ack(int sock, struct tftphdr_ack *ackhdr)
176 {
177 	LOG_DBG("Client acking block number: %d", ntohs(ackhdr->block));
178 
179 	return zsock_send(sock, ackhdr, sizeof(struct tftphdr_ack), 0);
180 }
181 
send_request(int sock,struct tftpc * client,int request,const char * remote_file,const char * mode)182 static int send_request(int sock, struct tftpc *client,
183 			int request, const char *remote_file, const char *mode)
184 {
185 	int tx_count = 0;
186 	size_t req_size;
187 	int ret;
188 
189 	/* Create TFTP Request. */
190 	req_size = make_request(client->tftp_buf, request, remote_file, mode);
191 
192 	do {
193 		tx_count++;
194 
195 		LOG_DBG("Sending TFTP request %d file %s", request,
196 			remote_file);
197 
198 		/* Send the request to the server */
199 		ret = zsock_sendto(sock, client->tftp_buf, req_size, 0, &client->server,
200 				   ADDRLEN(client->server));
201 		if (ret < 0) {
202 			break;
203 		}
204 
205 		/* Poll for the response */
206 		struct zsock_pollfd fds = {
207 			.fd     = sock,
208 			.events = ZSOCK_POLLIN,
209 		};
210 
211 		ret = zsock_poll(&fds, 1, CONFIG_TFTPC_REQUEST_TIMEOUT);
212 		if (ret <= 0) {
213 			LOG_DBG("Failed to get data from the TFTP Server"
214 				", req. no. %d", tx_count);
215 			continue;
216 		}
217 
218 		/* Receive data from the TFTP Server. */
219 		struct sockaddr from_addr;
220 		socklen_t from_addr_len = sizeof(from_addr);
221 
222 		ret = zsock_recvfrom(sock, client->tftp_buf, TFTPC_MAX_BUF_SIZE, 0,
223 				     &from_addr, &from_addr_len);
224 		if (ret < TFTP_HEADER_SIZE) {
225 			req_size = make_request(client->tftp_buf, request,
226 						remote_file, mode);
227 			continue;
228 		}
229 
230 		/* Limit communication to the specific address:port */
231 		if (zsock_connect(sock, &from_addr, from_addr_len) < 0) {
232 			ret = -errno;
233 			LOG_ERR("connect failed, err %d", ret);
234 			break;
235 		}
236 
237 		break;
238 
239 	} while (tx_count <= TFTP_REQ_RETX);
240 
241 	return ret;
242 }
243 
tftp_get(struct tftpc * client,const char * remote_file,const char * mode)244 int tftp_get(struct tftpc *client, const char *remote_file, const char *mode)
245 {
246 	int sock;
247 	uint32_t tftpc_block_no = 1;
248 	uint32_t tftpc_index = 0;
249 	int tx_count = 0;
250 	struct tftphdr_ack ackhdr = {
251 		.opcode = htons(ACK_OPCODE),
252 		.block = htons(1)
253 	};
254 	int rcv_size;
255 	int ret;
256 
257 	if (client == NULL) {
258 		return -EINVAL;
259 	}
260 
261 	sock = zsock_socket(client->server.sa_family, SOCK_DGRAM, IPPROTO_UDP);
262 	if (sock < 0) {
263 		LOG_ERR("Failed to create UDP socket: %d", errno);
264 		return -errno;
265 	}
266 
267 	/* Send out the READ request to the TFTP Server. */
268 	ret = send_request(sock, client, READ_REQUEST, remote_file, mode);
269 	rcv_size = ret;
270 
271 	while (rcv_size >= TFTP_HEADER_SIZE && rcv_size <= TFTPC_MAX_BUF_SIZE) {
272 		/* Process server response. */
273 		uint16_t opcode = sys_get_be16(client->tftp_buf);
274 		uint16_t block_no = sys_get_be16(client->tftp_buf + 2);
275 
276 		LOG_DBG("Received data: opcode %u, block no %u, size %d",
277 			opcode, block_no, rcv_size);
278 
279 		if (opcode == ERROR_OPCODE) {
280 			if (client->callback) {
281 				struct tftp_evt evt = {
282 					.type = TFTP_EVT_ERROR
283 				};
284 
285 				evt.param.error.msg = client->tftp_buf + TFTP_HEADER_SIZE;
286 				evt.param.error.code = block_no;
287 				client->callback(&evt);
288 			}
289 			ret = TFTPC_REMOTE_ERROR;
290 			break;
291 		} else if (opcode != DATA_OPCODE) {
292 			LOG_ERR("Server responded with invalid opcode.");
293 			ret = TFTPC_REMOTE_ERROR;
294 			break;
295 		}
296 
297 		if (block_no == tftpc_block_no) {
298 			uint32_t data_size = rcv_size - TFTP_HEADER_SIZE;
299 
300 			tftpc_block_no++;
301 			ackhdr.block = htons(block_no);
302 			tx_count = 0;
303 
304 			if (client->callback == NULL) {
305 				LOG_ERR("No callback defined.");
306 				if (send_err(sock, client, TFTP_ERROR_DISK_FULL, NULL) < 0) {
307 					LOG_ERR("Failed to send error response, err: %d",
308 						-errno);
309 				}
310 				ret = TFTPC_BUFFER_OVERFLOW;
311 				goto get_end;
312 			}
313 
314 			/* Send received data to client */
315 			struct tftp_evt evt = {
316 				.type = TFTP_EVT_DATA
317 			};
318 
319 			evt.param.data.data_ptr = client->tftp_buf + TFTP_HEADER_SIZE;
320 			evt.param.data.len      = data_size;
321 			client->callback(&evt);
322 
323 			/* Update the index. */
324 			tftpc_index += data_size;
325 
326 			/* Per RFC1350, the end of a transfer is marked
327 			 * by datagram size < TFTPC_MAX_BUF_SIZE.
328 			 */
329 			if (rcv_size < TFTPC_MAX_BUF_SIZE) {
330 				(void)send_ack(sock, &ackhdr);
331 				ret = tftpc_index;
332 				LOG_DBG("%d bytes received.", tftpc_index);
333 				/* RFC1350: The host acknowledging the final DATA packet may
334 				 * terminate its side of the connection on sending the final ACK.
335 				 */
336 				break;
337 			}
338 		}
339 
340 		/* Poll for the response */
341 		struct zsock_pollfd fds = {
342 			.fd     = sock,
343 			.events = ZSOCK_POLLIN,
344 		};
345 
346 		do {
347 			if (tx_count > TFTP_REQ_RETX) {
348 				LOG_ERR("No more retransmits. Exiting");
349 				ret = TFTPC_RETRIES_EXHAUSTED;
350 				goto get_end;
351 			}
352 
353 			/* Send ACK to the TFTP Server */
354 			(void)send_ack(sock, &ackhdr);
355 			tx_count++;
356 		} while (zsock_poll(&fds, 1, CONFIG_TFTPC_REQUEST_TIMEOUT) <= 0);
357 
358 		/* Receive data from the TFTP Server. */
359 		ret = zsock_recv(sock, client->tftp_buf, TFTPC_MAX_BUF_SIZE, 0);
360 		rcv_size = ret;
361 	}
362 
363 	if (!(rcv_size >= TFTP_HEADER_SIZE && rcv_size <= TFTPC_MAX_BUF_SIZE)) {
364 		ret = TFTPC_REMOTE_ERROR;
365 	}
366 
367 get_end:
368 	zsock_close(sock);
369 	return ret;
370 }
371 
tftp_put(struct tftpc * client,const char * remote_file,const char * mode,const uint8_t * user_buf,uint32_t user_buf_size)372 int tftp_put(struct tftpc *client, const char *remote_file, const char *mode,
373 	     const uint8_t *user_buf, uint32_t user_buf_size)
374 {
375 	int sock;
376 	uint32_t tftpc_block_no = 1;
377 	uint32_t tftpc_index = 0;
378 	uint32_t send_size;
379 	uint8_t *send_buffer;
380 	int ret;
381 
382 	if (client == NULL || user_buf == NULL || user_buf_size == 0) {
383 		return -EINVAL;
384 	}
385 
386 	sock = zsock_socket(client->server.sa_family, SOCK_DGRAM, IPPROTO_UDP);
387 	if (sock < 0) {
388 		LOG_ERR("Failed to create UDP socket: %d", errno);
389 		return -errno;
390 	}
391 
392 	/* Send out the WRITE request to the TFTP Server. */
393 	ret = send_request(sock, client, WRITE_REQUEST, remote_file, mode);
394 
395 	/* Check connection initiation result */
396 	if (ret >= TFTP_HEADER_SIZE) {
397 		uint16_t opcode = sys_get_be16(client->tftp_buf);
398 		uint16_t block_no = sys_get_be16(client->tftp_buf + 2);
399 
400 		LOG_DBG("Receive: opcode %u, block no %u, size %d", opcode, block_no, ret);
401 
402 		if (opcode == ERROR_OPCODE) {
403 			if (client->callback) {
404 				struct tftp_evt evt = {
405 					.type = TFTP_EVT_ERROR
406 				};
407 
408 				evt.param.error.msg = client->tftp_buf + TFTP_HEADER_SIZE;
409 				evt.param.error.code = block_no;
410 				client->callback(&evt);
411 			}
412 			LOG_ERR("Server responded with service reject.");
413 			ret = TFTPC_REMOTE_ERROR;
414 			goto put_end;
415 		} else if (opcode != ACK_OPCODE || block_no != 0) {
416 			LOG_ERR("Server responded with invalid opcode or block number.");
417 			ret = TFTPC_REMOTE_ERROR;
418 			goto put_end;
419 		}
420 	} else {
421 		ret = TFTPC_REMOTE_ERROR;
422 		goto put_end;
423 	}
424 
425 	/* Send out data by chunks */
426 	do {
427 		send_size = user_buf_size - tftpc_index;
428 		if (send_size > TFTP_BLOCK_SIZE) {
429 			send_size = TFTP_BLOCK_SIZE;
430 		}
431 		send_buffer = (uint8_t *)(user_buf + tftpc_index);
432 
433 		ret = send_data(sock, client, tftpc_block_no, send_buffer, send_size);
434 		if (ret != TFTPC_SUCCESS) {
435 			goto put_end;
436 		} else {
437 			tftpc_index += send_size;
438 			tftpc_block_no++;
439 		}
440 
441 		/* Per RFC1350, the end of a transfer is marked
442 		 * by datagram size < TFTPC_MAX_BUF_SIZE.
443 		 */
444 		if (send_size < TFTP_BLOCK_SIZE) {
445 			LOG_DBG("%d bytes sent.", tftpc_index);
446 			ret = tftpc_index;
447 			break;
448 		}
449 	} while (true);
450 
451 put_end:
452 	zsock_close(sock);
453 	return ret;
454 }
455