[PATCH] ipvs: support more FTP PASV responses

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


	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: Julian Anastasov <ja@xxxxxx>
---

	As this is not exactly a fix, it can be applied to
ipvs-next-2.6 after the merge window.

diff -urp v2.6.39/linux/net/netfilter/ipvs/ip_vs_ftp.c linux/net/netfilter/ipvs/ip_vs_ftp.c
--- v2.6.39/linux/net/netfilter/ipvs/ip_vs_ftp.c	2011-05-20 10:38:08.000000000 +0300
+++ linux/net/netfilter/ipvs/ip_vs_ftp.c	2011-05-29 11:51:50.630247073 +0300
@@ -44,8 +44,8 @@
 #include <net/ip_vs.h>
 
 
-#define SERVER_STRING "227 Entering Passive Mode ("
-#define CLIENT_STRING "PORT "
+#define SERVER_STRING "227 "
+#define CLIENT_STRING "PORT"
 
 
 /*
@@ -79,14 +79,17 @@ ip_vs_ftp_done_conn(struct ip_vs_app *ap
 
 /*
  * 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 *
 	if (strnicmp(data, pattern, plen) != 0) {
 		return 0;
 	}
-	*start = data + plen;
+	s = data + plen;
+	if (skip) {
+		int found = 0;
+
+		for (;; s++) {
+			if (s == data_limit)
+				return -1;
+			if (!found) {
+				if (*s == skip)
+					found = 1;
+			} else if (*s != skip) {
+				break;
+			}
+		}
+	}
 
-	for (data = *start; *data != term; data++) {
+	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,8 +146,9 @@ static int ip_vs_ftp_get_addrport(char *
 	if (i != 5)
 		return -1;
 
-	*addr = get_unaligned((__be32 *)p);
-	*port = get_unaligned((__be16 *)(p + 4));
+	*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_ap
 
 		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
 	 */
 	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;
 
--
To unsubscribe from this list: send the line "unsubscribe lvs-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]    [Yosemite Photos]    [Free Online Dating]     [Linux Kernel]     [Linux SCSI]     [XFree86]

Add to Google Powered by Linux