Ejemplo n.º 1
0
int main(int argc, char *argv[])
{
	int ret;
	struct cavan_tcp_repeater *repeater;
	struct cavan_dynamic_service *service;

	service = cavan_dynamic_service_create(sizeof(struct cavan_tcp_repeater));
	if (service == NULL) {
		pr_red_info("cavan_dynamic_service_create");
		return -ENOMEM;
	}

	service->min = 20;
	service->max = 1000;

	repeater = cavan_dynamic_service_get_data(service);
	network_url_init(&repeater->url, "tcp", "any", CAVAN_TCP_REPEATER_PORT, network_get_socket_pathname());

	ret = network_url_parse_cmdline(&repeater->url, service, argc, argv);
	if (ret < 0) {
		goto out_cavan_dynamic_service_destroy;
	}

	ret = cavan_tcp_repeater_run(service);

out_cavan_dynamic_service_destroy:
	cavan_dynamic_service_destroy(service);
	return ret;
}
Ejemplo n.º 2
0
static int ftp_data_service_open(struct network_service *service, struct network_client *client, char *buff, size_t size)
{
	u8 *ip;
	int ret;
	u16 port;
	struct in_addr addr;
	struct network_url url;

	network_url_init(&url, "tcp", "any", 0, NULL);

	ret = network_service_open(service, &url, 0);
	if (ret < 0)
	{
		pr_red_info("network_service_open");
		return ret;
	}

	ret = network_service_get_local_port(service);
	if (ret < 0)
	{
		pr_error_info("network_service_get_local_port");
		goto out_network_service_close;
	}

	port = ret;

	ret = network_client_get_local_ip(client, &addr);
	if (ret < 0)
	{
		pr_error_info("network_client_getsockname");
		goto out_network_service_close;
	}

	ip = (u8 *) &addr;

	return snprintf(buff, size, "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d).\r\n", ip[0], ip[1], ip[2], ip[3], port & 0xFF, (port >> 8) & 0xFF);

out_network_service_close:
	network_service_close(service);
	return ret;
}
Ejemplo n.º 3
0
static int ftp_service_cmdline(struct cavan_ftp_service *service, struct network_client *client)
{
	int fd;
	int ret;
	u32 command;
	char file_type;
	const char *reply;
	char rep_pasv[64];
	struct pollfd pfds[2];
	enum cavan_ftp_state state;
	struct network_url data_url;
	ssize_t wrlen, rdlen, replen;
	struct network_client data_link;
	struct network_service data_service;
	char abs_path[1024], curr_path[1024];
	char cmd_buff[1024], rep_buff[1024], *cmd_arg, *cmd_end;

	file_type = 0;
	data_link.sockfd = -1;
	data_service.sockfd = -1;
	network_url_init(&data_url, "tcp", NULL, 0, NULL);

	replen = 0;
	reply = "220 Cavan ftp server ready.\r\n";

	state = FTP_STATE_READY;
	text_copy(curr_path, service->home);

	pfds[0].fd = -1;
	pfds[1].fd = client->sockfd;
	pfds[0].events = pfds[1].events = POLLIN;

	while (1)
	{
		if (replen == 0)
		{
			replen = strlen(reply);
		}

#if FTP_DEBUG
		println("reply = %s", reply);
#endif

		wrlen = client->send(client, reply, replen);
		if (wrlen < 0)
		{
			pr_red_info("inet_send_text");
			goto out_close_data_link;
		}

		replen = 0;
		reply = rep_buff;

label_poll:
		ret = poll(pfds, NELEM(pfds), FTP_TIMEOUT_MS);
		if (ret < 1)
		{
			if (ret < 0)
			{
				pr_error_info("poll");
				goto out_close_data_link;
			}

			goto label_poll;
		}

		if (pfds[0].revents == POLLIN)
		{
			if (data_link.sockfd >= 0)
			{
				network_client_close(&data_link);
			}

			ret = network_service_accept(&data_service, &data_link);
			if (ret < 0)
			{
				pr_red_info("network_service_accept");
				goto out_network_service_close;
			}

			if (pfds[1].revents != POLLIN)
			{
				goto label_poll;
			}
		}

		rdlen = client->recv(client, cmd_buff, sizeof(cmd_buff) - 1);
		if (rdlen < 3)
		{
			goto out_close_data_link;
		}

		for (cmd_end = cmd_buff + rdlen - 1; cmd_end > cmd_buff && byte_is_lf(*cmd_end); cmd_end--);

		*++cmd_end = 0;

		for (cmd_arg = cmd_buff; cmd_arg < cmd_end && !byte_is_space(*cmd_arg); cmd_arg++);

		while ( cmd_arg < cmd_end && byte_is_space(*cmd_arg))
		{
			*cmd_arg++ = 0;
		}

#if FTP_DEBUG
		println("command = `%s', args = `%s'", cmd_buff, cmd_arg);
#endif

		command = *(u32 *) cmd_buff;

		switch (command)
		{
		case FTP_BUILD_CMD('q', 'u', 'i', 't'):
		case FTP_BUILD_CMD('Q', 'U', 'I', 'T'):
			network_client_send_text(client, "221 Goodbye.\r\n");
			return 0;

		case FTP_BUILD_CMD('u', 's', 'e', 'r'):
		case FTP_BUILD_CMD('U', 'S', 'E', 'R'):
			if (state < FTP_STATE_USER_RECVED)
			{
				state = FTP_STATE_USER_RECVED;
				reply = "331 Please input password.\r\n";
			}
			else
			{
				reply = "331 Any password will do.\r\n";
			}

			break;

		case FTP_BUILD_CMD('p', 'a', 's', 's'):
		case FTP_BUILD_CMD('P', 'A', 'S', 'S'):
			if (state < FTP_STATE_USER_RECVED)
			{
				reply = "530 Please input username.\r\n";
			}
			else if (state < FTP_STATE_LOGINED)
			{
				state = FTP_STATE_LOGINED;
				reply = "230 User login successfull.\r\n";
			}
			else
			{
				reply = "230 Alreay logged in.\r\n";
			}

			break;

		default:
			if (state < FTP_STATE_LOGINED)
			{
				if (state < FTP_STATE_USER_RECVED)
				{
					reply = "530 Please login with USER and PASS.\r\n";
				}
				else
				{
					reply = "530 Please login with PASS.\r\n";
				}

				break;
			}

			switch (command)
			{
			case FTP_BUILD_CMD('p', 'o', 'r', 't'):
			case FTP_BUILD_CMD('P', 'O', 'R', 'T'):
			{
				int temp[6];

				ret = sscanf(cmd_arg, "%d,%d,%d,%d,%d,%d", temp, temp + 1, temp + 2, temp + 3, temp + 4, temp + 5);
				if (ret == 6)
				{
					snprintf(data_url.memory, sizeof(data_url.memory), "%d.%d.%d.%d", temp[0], temp[1], temp[2], temp[3]);
					data_url.hostname = data_url.memory;
					data_url.port = temp[4] << 8 | temp[5];
					reply = "200 PORT command complete.\r\n";
				}
				else
				{
					reply = "501 Argument error.\r\n";
				}

				break;
			}

			case FTP_BUILD_CMD('o', 'p', 't', 's'):
			case FTP_BUILD_CMD('O', 'P', 'T', 'S'):
				reply = "200 OPTS command complete.\r\n";
				break;

			case FTP_BUILD_CMD('p', 'w', 'd', 0):
			case FTP_BUILD_CMD('P', 'W', 'D', 0):
			case FTP_BUILD_CMD('x', 'p', 'w', 'd'):
			case FTP_BUILD_CMD('X', 'P', 'W', 'D'):
				replen = snprintf(rep_buff, sizeof(rep_buff), "257 \"%s\"\r\n", curr_path);
				break;

			case FTP_BUILD_CMD('t', 'y', 'p', 'e'):
			case FTP_BUILD_CMD('T', 'Y', 'P', 'E'):
				reply = "200 TYPE commnd complete.\r\n";
				file_type = cmd_buff[5];
				break;

			case FTP_BUILD_CMD('s', 'y', 's', 't'):
			case FTP_BUILD_CMD('S', 'Y', 'S', 'T'):
				reply = "215 UNIX Type L8.\r\n";
				break;

			case FTP_BUILD_CMD('c', 'w', 'd', 0):
			case FTP_BUILD_CMD('C', 'W', 'D', 0):
			case FTP_BUILD_CMD('x', 'c', 'w', 'd'):
			case FTP_BUILD_CMD('X', 'C', 'W', 'D'):
				if (*cmd_arg)
				{
					ftp_get_abs_path(curr_path, cmd_arg, abs_path, sizeof(abs_path));
					if (access(abs_path, F_OK) < 0)
					{
						reply = "550 Failed to change directory.\r\n";
						break;
					}

					prettify_pathname_base(abs_path, curr_path, sizeof(curr_path));
				}
				else
				{
					text_copy(curr_path, service->home);
				}

				reply = "250 CWD commnd complete.\r\n";
				break;

			case FTP_BUILD_CMD('l', 'i', 's', 't'):
			case FTP_BUILD_CMD('L', 'I', 'S', 'T'):
				if (data_link.sockfd < 0 && data_url.port == 0)
				{
					reply = "550 Please run PORT or PASV first.\r\n";
					break;
				}

				fd = ftp_list_directory1(curr_path, file_type == 'I' ? "\n" : "\r\n");
				if (fd < 0)
				{
					replen = snprintf(rep_buff, sizeof(rep_buff), "550 List directory failed: %s.\r\n", strerror(errno));
					break;
				}

				wrlen = network_client_send_text(client, "150 List directory complete.\r\n");
				if (wrlen < 0)
				{
					pr_red_info("ftp_send_text");
					close(fd);
					goto out_close_data_link;
				}

				ret = ftp_server_send_file1(&data_link, &data_url, fd);
				close(fd);

				if (ret < 0)
				{
					replen = snprintf(rep_buff, sizeof(rep_buff), "550 Send list failed: %s.\r\n", strerror(errno));
				}
				else
				{
					reply = "226 List send complete.\r\n";
				}

				break;

			case FTP_BUILD_CMD('s', 'i', 'z', 'e'):
			case FTP_BUILD_CMD('S', 'I', 'Z', 'E'):
			{
				struct stat st;

				if (*cmd_arg == 0 || stat(ftp_get_abs_path(curr_path, cmd_arg, abs_path, sizeof(abs_path)), &st))
				{
					replen = snprintf(rep_buff, sizeof(rep_buff), "550 get file size failed: %s.\r\n", strerror(errno));
				}
				else
				{
					replen = snprintf(rep_buff, sizeof(rep_buff), "213 %" PRINT_FORMAT_OFF "\r\n", st.st_size);
				}

				break;
			}

			case FTP_BUILD_CMD('r', 'e', 't', 'r'):
			case FTP_BUILD_CMD('R', 'E', 'T', 'R'):
				fd = open(ftp_get_abs_path(curr_path, cmd_arg, abs_path, sizeof(abs_path)), O_RDONLY);
				if (fd < 0)
				{
					reply = "550 Open file failed.\r\n";
					break;
				}

				wrlen = network_client_send_text(client, "125 Starting transfer\r\n");
				if (wrlen < 0)
				{
					pr_red_info("network_client_send_text");
					close(fd);
					goto out_close_data_link;
				}

				ret = ftp_server_send_file1(&data_link, &data_url, fd);
				close(fd);

				if (ret < 0)
				{
					reply = "550 Send file failed.\r\n";
				}
				else
				{
					reply = "226 Transfer complete.\r\n";
				}

				break;

			case FTP_BUILD_CMD('s', 't', 'o', 'r'):
			case FTP_BUILD_CMD('S', 'T', 'O', 'R'):
				fd = open(ftp_get_abs_path(curr_path, cmd_arg, abs_path, sizeof(abs_path)), O_WRONLY | O_CREAT, 0777);
				if (fd < 0)
				{
					reply = "550 Open file failed.\r\n";
					break;
				}

				wrlen = network_client_send_text(client, "125 Starting transfer\r\n");
				if (wrlen < 0)
				{
					pr_error_info("ftp_send_text");
					close(fd);
					goto out_close_data_link;
				}

				ret = ftp_server_receive_file1(&data_link, &data_url, fd);
				close(fd);

				if (ret < 0)
				{
					reply = "550 Receive file failed.\r\n";
				}
				else
				{
					reply = "226 Transfer complete.\r\n";
				}

				break;

			case FTP_BUILD_CMD('p', 'a', 's', 'v'):
			case FTP_BUILD_CMD('P', 'A', 'S', 'V'):
				if (data_service.sockfd < 0)
				{
					ret = ftp_data_service_open(&data_service, client, rep_pasv, sizeof(rep_pasv));
					if (ret < 0)
					{
						pr_red_info("ftp_data_service_open");
						return ret;
					}

					replen = ret;
					pfds[0].fd = data_service.sockfd;
				}

				reply = rep_pasv;
				break;

			case FTP_BUILD_CMD('d', 'e', 'l', 'e'):
			case FTP_BUILD_CMD('D', 'E', 'L', 'E'):
				ret = remove(ftp_get_abs_path(curr_path, cmd_arg, abs_path, sizeof(abs_path)));
				if (ret < 0)
				{
					replen = snprintf(rep_buff, sizeof(rep_buff), "550 remove %s failed: %s.\r\n", cmd_arg, strerror(errno));
				}
				else
				{
					reply = "200 DELE command complete.\r\n";
				}

				break;

			case FTP_BUILD_CMD('r', 'm', 'd', 0):
			case FTP_BUILD_CMD('R', 'M', 'D', 0):
				ret = rmdir(ftp_get_abs_path(curr_path, cmd_arg, abs_path, sizeof(abs_path)));
				if (ret < 0)
				{
					replen = snprintf(rep_buff, sizeof(rep_buff), "550 remove %s failed: %s.\r\n", cmd_arg, strerror(errno));
				}
				else
				{
					reply = "200 DELE command complete.\r\n";
				}

				break;

			case FTP_BUILD_CMD('m', 'k', 'd', 0):
			case FTP_BUILD_CMD('M', 'K', 'D', 0):
				ret = mkdir(ftp_get_abs_path(curr_path, cmd_arg, abs_path, sizeof(abs_path)), 0777);
				if (ret < 0)
				{
					replen = snprintf(rep_buff, sizeof(rep_buff), "550 create directory %s failed: %s.\r\n", cmd_arg, strerror(errno));
				}
				else
				{
					reply = "200 MKD command complete.\r\n";
				}

				break;

			case FTP_BUILD_CMD('m', 'd', 't', 'm'):
			case FTP_BUILD_CMD('M', 'D', 'T', 'M'):
			{
				struct stat st;

				ret = stat(ftp_get_abs_path(curr_path, cmd_arg, abs_path, sizeof(abs_path)), &st);
				if (ret < 0)
				{
					replen = snprintf(rep_buff, sizeof(rep_buff), "550 get file stat failed: %s.\r\n", strerror(errno));
				}
				else
				{
					struct tm ti;

					if (localtime_r((time_t *) &st.st_atime, &ti) == NULL)
					{
						replen = snprintf(rep_buff, sizeof(rep_buff), "550 get localtime failed: %s.\r\n", strerror(errno));
					}
					else
					{
						replen = snprintf(rep_buff, sizeof(rep_buff), "213 %04d%02d%02d%02d%02d%02d\r\n", \
							ti.tm_year + 1900, ti.tm_mon + 1, ti.tm_mday, ti.tm_hour, ti.tm_min, ti.tm_sec);
					}
				}

				break;
			}

			case FTP_BUILD_CMD('n', 'o', 'o', 'p'):
			case FTP_BUILD_CMD('N', 'O', 'O', 'P'):
				reply = "200 NOOP commnd complete.\r\n";
				break;

			case FTP_BUILD_CMD('r', 'n', 'f', 'r'):
			case FTP_BUILD_CMD('R', 'N', 'F', 'R'):
			{
				char rnfr_path[1024];

				ftp_get_abs_path(curr_path, cmd_arg, rnfr_path, sizeof(rnfr_path));
				reply = "350 RNFR command complete.\r\n";
				break;
			}

			case FTP_BUILD_CMD('r', 'n', 't', 'o'):
			case FTP_BUILD_CMD('R', 'N', 'T', 'O'):
			{
				char rnfr_path[1024];

				ftp_get_abs_path(curr_path, cmd_arg, abs_path, sizeof(abs_path));
				ret = rename(rnfr_path, abs_path);
				if (ret < 0)
				{
					replen = snprintf(rep_buff, sizeof(rep_buff), "550 Rename %s to %s failed[%s].\r\n", rnfr_path, abs_path, strerror(errno));
				}
				else
				{
					replen = snprintf(rep_buff, sizeof(rep_buff), "250 Rename %s to %s successfully.\r\n", rnfr_path, abs_path);
				}

				break;
			}

			case FTP_BUILD_CMD('s', 'i', 't', 'e'):
			case FTP_BUILD_CMD('S', 'I', 'T', 'E'):
				command = *(u32 *) cmd_arg;
				switch (command)
				{
				case FTP_BUILD_CMD('h', 'e', 'l', 'p'):
				case FTP_BUILD_CMD('H', 'E', 'L', 'P'):
					reply = "214 UNMASK HELP\r\n";
					break;

				default:
					goto label_unsupport_command;
				}

				break;

			case FTP_BUILD_CMD('f', 'e', 'a', 't'):
			case FTP_BUILD_CMD('F', 'E', 'A', 'T'):
				reply = "211 MDTM SIZE PASV PORT RNTO MKD RMD DELE RETR STOR\r\n";
				break;

			default:
label_unsupport_command:
				pr_red_info("unsupport command: `%s'", cmd_buff);
				reply = "500 Unknown command.\r\n";
			}
		}
	}

out_close_data_link:
	if (data_link.sockfd >= 0)
	{
		network_client_close(&data_link);
	}
out_network_service_close:
	if (data_service.sockfd >= 0)
	{
		network_service_close(&data_service);
	}
	return 0;
}