Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c3aa1bd3 authored by Julian Anastasov's avatar Julian Anastasov Committed by Simon Horman
Browse files

ipvs: support more FTP PASV responses



	Change the parsing of FTP commands and responses to
support skip character. It allows to detect variations in
the 227 PASV response.

Signed-off-by: default avatarJulian Anastasov <ja@ssi.bg>
Signed-off-by: default avatarSimon Horman <horms@verge.net.au>
parent 8f0ea0fe
Loading
Loading
Loading
Loading
+38 −14
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@
#include <net/ip_vs.h>


#define SERVER_STRING "227 Entering Passive Mode ("
#define SERVER_STRING "227 "
#define CLIENT_STRING "PORT"


@@ -79,14 +79,17 @@ ip_vs_ftp_done_conn(struct ip_vs_app *app, struct ip_vs_conn *cp)

/*
 * Get <addr,port> from the string "xxx.xxx.xxx.xxx,ppp,ppp", started
 * with the "pattern" and terminated with the "term" character.
 * with the "pattern", ignoring before "skip" and terminated with
 * the "term" character.
 * <addr,port> is in network order.
 */
static int ip_vs_ftp_get_addrport(char *data, char *data_limit,
				  const char *pattern, size_t plen, char term,
				  const char *pattern, size_t plen,
				  char skip, char term,
				  __be32 *addr, __be16 *port,
				  char **start, char **end)
{
	char *s, c;
	unsigned char p[6];
	int i = 0;

@@ -101,19 +104,38 @@ static int ip_vs_ftp_get_addrport(char *data, char *data_limit,
	if (strnicmp(data, pattern, plen) != 0) {
		return 0;
	}
	*start = data + plen;
	s = data + plen;
	if (skip) {
		int found = 0;

	for (data = *start; *data != term; data++) {
		for (;; s++) {
			if (s == data_limit)
				return -1;
			if (!found) {
				if (*s == skip)
					found = 1;
			} else if (*s != skip) {
				break;
			}
		}
	}

	for (data = s; ; data++) {
		if (data == data_limit)
			return -1;
		if (*data == term)
			break;
	}
	*end = data;

	memset(p, 0, sizeof(p));
	for (data = *start; data != *end; data++) {
		if (*data >= '0' && *data <= '9') {
			p[i] = p[i]*10 + *data - '0';
		} else if (*data == ',' && i < 5) {
	for (data = s; ; data++) {
		c = *data;
		if (c == term)
			break;
		if (c >= '0' && c <= '9') {
			p[i] = p[i]*10 + c - '0';
		} else if (c == ',' && i < 5) {
			i++;
		} else {
			/* unexpected character */
@@ -124,6 +146,7 @@ static int ip_vs_ftp_get_addrport(char *data, char *data_limit,
	if (i != 5)
		return -1;

	*start = s;
	*addr = get_unaligned((__be32 *) p);
	*port = get_unaligned((__be16 *) (p + 4));
	return 1;
@@ -185,7 +208,8 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,

		if (ip_vs_ftp_get_addrport(data, data_limit,
					   SERVER_STRING,
					   sizeof(SERVER_STRING)-1, ')',
					   sizeof(SERVER_STRING)-1,
					   '(', ')',
					   &from.ip, &port,
					   &start, &end) != 1)
			return 1;
@@ -345,7 +369,7 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
	 */
	if (ip_vs_ftp_get_addrport(data_start, data_limit,
				   CLIENT_STRING, sizeof(CLIENT_STRING)-1,
				   '\r', &to.ip, &port,
				   ' ', '\r', &to.ip, &port,
				   &start, &end) != 1)
		return 1;