All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH xtables-addons 0/8] xt_ipp2p: support for non-linear packets
@ 2023-06-05 19:17 Jeremy Sowden
  2023-06-05 19:17 ` [PATCH xtables-addons 1/8] xt_ipp2p: fix an off-by-one error Jeremy Sowden
                   ` (7 more replies)
  0 siblings, 8 replies; 11+ messages in thread
From: Jeremy Sowden @ 2023-06-05 19:17 UTC (permalink / raw)
  To: Netfilter Devel

xt_ipp2p currently requires that skb's are linear.  This series adds
support for non-linear ones.

* Patches 1-2 fix bugs.
* Patches 3-5 perform some tidy-ups.
* Patch 6 introduces the kernel's textsearch API for doing substring
  matching.
* Patches 7-8 add support for non-linear skb's.

Jeremy Sowden (8):
  xt_ipp2p: fix an off-by-one error
  xt_ipp2p: fix Soulseek false-positive matches
  xt_ipp2p: change byte-orer conversion
  xt_ipp2p: add helper for matching "\r\n"
  xt_ipp2p: rearrange some conditionals and a couple of loops
  xt_ipp2p: use textsearch API for substring searching
  xt_ipp2p: use `skb_header_pointer` and `skb_find_text`
  xt_ipp2p: drop requirement that skb is linear

 extensions/xt_ipp2p.c | 937 ++++++++++++++++++++++++++++++------------
 extensions/xt_ipp2p.h |  10 +
 2 files changed, 689 insertions(+), 258 deletions(-)

-- 
2.39.2


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH xtables-addons 1/8] xt_ipp2p: fix an off-by-one error
  2023-06-05 19:17 [PATCH xtables-addons 0/8] xt_ipp2p: support for non-linear packets Jeremy Sowden
@ 2023-06-05 19:17 ` Jeremy Sowden
  2023-06-05 19:17 ` [PATCH xtables-addons 2/8] xt_ipp2p: fix Soulseek false-positive matches Jeremy Sowden
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Jeremy Sowden @ 2023-06-05 19:17 UTC (permalink / raw)
  To: Netfilter Devel

When checking for waste, we check that the packet is at least eight
bytes long and then examine the first nine bytes.  Fix the length check.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 extensions/xt_ipp2p.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/extensions/xt_ipp2p.c b/extensions/xt_ipp2p.c
index 2a9f3e4553b0..a90d1b3d57c8 100644
--- a/extensions/xt_ipp2p.c
+++ b/extensions/xt_ipp2p.c
@@ -793,7 +793,7 @@ search_xdcc(const unsigned char *payload, const unsigned int plen)
 static unsigned int
 search_waste(const unsigned char *payload, const unsigned int plen)
 {
-	if (plen >= 8 && memcmp(payload, "GET.sha1:", 9) == 0)
+	if (plen >= 9 && memcmp(payload, "GET.sha1:", 9) == 0)
 		return IPP2P_WASTE * 100 + 0;
 
 	return 0;
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH xtables-addons 2/8] xt_ipp2p: fix Soulseek false-positive matches
  2023-06-05 19:17 [PATCH xtables-addons 0/8] xt_ipp2p: support for non-linear packets Jeremy Sowden
  2023-06-05 19:17 ` [PATCH xtables-addons 1/8] xt_ipp2p: fix an off-by-one error Jeremy Sowden
@ 2023-06-05 19:17 ` Jeremy Sowden
  2023-06-05 19:17 ` [PATCH xtables-addons 3/8] xt_ipp2p: change byte-orer conversion Jeremy Sowden
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Jeremy Sowden @ 2023-06-05 19:17 UTC (permalink / raw)
  To: Netfilter Devel

According to the comment, the last match attempted is:

  14 00 00 00 01 yy 00 00 00 STRING(YY) 01 00 00 00 00 46|50 00 00 00 00

However, the conditional that inspects the last ten bytes is followed by
a semi-colon, so the printk and return statements are executed regard-
less of what the last ten bytes are.

Remove the semi-colon and only execute the printk and return if the
conditional expression is true.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 extensions/xt_ipp2p.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/extensions/xt_ipp2p.c b/extensions/xt_ipp2p.c
index a90d1b3d57c8..5f7d5f61b96e 100644
--- a/extensions/xt_ipp2p.c
+++ b/extensions/xt_ipp2p.c
@@ -448,13 +448,13 @@ search_soul(const unsigned char *payload, const unsigned int plen)
 			const unsigned char *w = payload + 9 + y;
 			if (get_u32(w, 0) == 0x01 &&
 			    (get_u16(w, 4) == 0x4600 ||
-			    get_u16(w, 4) == 0x5000) &&
-			    get_u32(w, 6) == 0x00)
-				;
+			     get_u16(w, 4) == 0x5000) &&
+			    get_u32(w, 6) == 0x00) {
 #ifdef IPP2P_DEBUG_SOUL
-	    		printk(KERN_DEBUG "Soulssek special client command recognized\n");
+				printk(KERN_DEBUG "Soulseek special client command recognized\n");
 #endif
-	    		return IPP2P_SOUL * 100 + 9;
+				return IPP2P_SOUL * 100 + 9;
+			}
 		}
 	}
 	return 0;
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH xtables-addons 3/8] xt_ipp2p: change byte-orer conversion
  2023-06-05 19:17 [PATCH xtables-addons 0/8] xt_ipp2p: support for non-linear packets Jeremy Sowden
  2023-06-05 19:17 ` [PATCH xtables-addons 1/8] xt_ipp2p: fix an off-by-one error Jeremy Sowden
  2023-06-05 19:17 ` [PATCH xtables-addons 2/8] xt_ipp2p: fix Soulseek false-positive matches Jeremy Sowden
@ 2023-06-05 19:17 ` Jeremy Sowden
  2023-06-05 19:17 ` [PATCH xtables-addons 4/8] xt_ipp2p: add helper for matching "\r\n" Jeremy Sowden
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Jeremy Sowden @ 2023-06-05 19:17 UTC (permalink / raw)
  To: Netfilter Devel

Instead of converting the packet bytes before comparing it to a constant,
convert the constant.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 extensions/xt_ipp2p.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/extensions/xt_ipp2p.c b/extensions/xt_ipp2p.c
index 5f7d5f61b96e..4790c2fca229 100644
--- a/extensions/xt_ipp2p.c
+++ b/extensions/xt_ipp2p.c
@@ -210,8 +210,8 @@ udp_search_bit(const unsigned char *haystack, const unsigned int packet_len)
 	switch (packet_len) {
 	case 16:
 		/* ^ 00 00 04 17 27 10 19 80 */
-		if (ntohl(get_u32(haystack, 0)) == 0x00000417 &&
-		    ntohl(get_u32(haystack, 4)) == 0x27101980)
+		if (get_u32(haystack, 0) == __constant_htonl(0x00000417) &&
+		    get_u32(haystack, 4) == __constant_htonl(0x27101980))
 			return IPP2P_BIT * 100 + 50;
 		break;
 	case 36:
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH xtables-addons 4/8] xt_ipp2p: add helper for matching "\r\n"
  2023-06-05 19:17 [PATCH xtables-addons 0/8] xt_ipp2p: support for non-linear packets Jeremy Sowden
                   ` (2 preceding siblings ...)
  2023-06-05 19:17 ` [PATCH xtables-addons 3/8] xt_ipp2p: change byte-orer conversion Jeremy Sowden
@ 2023-06-05 19:17 ` Jeremy Sowden
  2023-06-05 19:17 ` [PATCH xtables-addons 5/8] xt_ipp2p: rearrange some conditionals and a couple of loops Jeremy Sowden
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 11+ messages in thread
From: Jeremy Sowden @ 2023-06-05 19:17 UTC (permalink / raw)
  To: Netfilter Devel

There are repeated checks that:

  pkt[x] == 0x0d && pkt[x + 1] == 0x0a

Replace them with `iscrlf(&pkt[x])` function calls.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 extensions/xt_ipp2p.c | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/extensions/xt_ipp2p.c b/extensions/xt_ipp2p.c
index 4790c2fca229..de253c4f4cb4 100644
--- a/extensions/xt_ipp2p.c
+++ b/extensions/xt_ipp2p.c
@@ -39,6 +39,11 @@ struct ipp2p_result_printer {
 	void (*print)(const union nf_inet_addr *, short, const union nf_inet_addr *, short, bool, unsigned int);
 };
 
+static bool iscrlf(const unsigned char *str)
+{
+	return *str == '\r' && *(str + 1) == '\n';
+}
+
 static void
 print_result(const struct ipp2p_result_printer *rp, bool result,
              unsigned int hlen)
@@ -518,7 +523,7 @@ search_winmx(const unsigned char *payload, const unsigned int plen)
 static unsigned int
 search_apple(const unsigned char *payload, const unsigned int plen)
 {
-	if (plen > 7 && payload[6] == 0x0d && payload[7] == 0x0a &&
+	if (plen > 7 && iscrlf(&payload[6]) &&
 	    memcmp(payload, "ajprot", 6) == 0)
 		return IPP2P_APPLE * 100;
 
@@ -574,7 +579,7 @@ search_kazaa(const unsigned char *payload, const unsigned int plen)
 {
 	if (plen < 13)
 		return 0;
-	if (payload[plen-2] == 0x0d && payload[plen-1] == 0x0a &&
+	if (iscrlf(&payload[plen - 2]) &&
 	    memcmp(payload, "GET /.hash=", 11) == 0)
 		return IPP2P_DATA_KAZAA * 100;
 
@@ -587,7 +592,7 @@ search_gnu(const unsigned char *payload, const unsigned int plen)
 {
 	if (plen < 11)
 		return 0;
-	if (payload[plen-2] == 0x0d && payload[plen-1] == 0x0a) {
+	if (iscrlf(&payload[plen - 2])) {
 		if (memcmp(payload, "GET /get/", 9) == 0)
 			return IPP2P_DATA_GNU * 100 + 1;
 		if (plen >= 15 && memcmp(payload, "GET /uri-res/", 13) == 0)
@@ -602,7 +607,7 @@ search_all_gnu(const unsigned char *payload, const unsigned int plen)
 {
 	if (plen < 11)
 		return 0;
-	if (payload[plen-2] == 0x0d && payload[plen-1] == 0x0a) {
+	if (iscrlf(&payload[plen - 2])) {
 		if (plen >= 19 && memcmp(payload, "GNUTELLA CONNECT/", 17) == 0)
 			return IPP2P_GNU * 100 + 1;
 		if (memcmp(payload, "GNUTELLA/", 9) == 0)
@@ -614,8 +619,7 @@ search_all_gnu(const unsigned char *payload, const unsigned int plen)
 			unsigned int c;
 
 			for (c = 0; c < plen - 22; ++c)
-				if (payload[c] == 0x0d &&
-				    payload[c+1] == 0x0a &&
+				if (iscrlf(&payload[c]) &&
 				    (memcmp(&payload[c+2], "X-Gnutella-", 11) == 0 ||
 				    memcmp(&payload[c+2], "X-Queue:", 8) == 0))
 					return IPP2P_GNU * 100 + 3;
@@ -635,7 +639,7 @@ search_all_kazaa(const unsigned char *payload, const unsigned int plen)
 		/* too short for anything we test for - early bailout */
 		return 0;
 
-	if (payload[plen-2] != 0x0d || payload[plen-1] != 0x0a)
+	if (!iscrlf(&payload[plen - 2]))
 		return 0;
 
 	if (memcmp(payload, "GIVE ", 5) == 0)
@@ -651,9 +655,7 @@ search_all_kazaa(const unsigned char *payload, const unsigned int plen)
 	end = plen - 18;
 	rem = plen - 5;
 	for (c = 5; c < end; ++c, --rem) {
-		if (payload[c] != 0x0d)
-			continue;
-		if (payload[c+1] != 0x0a)
+		if (!iscrlf(&payload[c]))
 			continue;
 		if (rem >= 18 &&
 		    memcmp(&payload[c+2], "X-Kazaa-Username: ", 18) == 0)
@@ -769,8 +771,8 @@ static unsigned int
 search_xdcc(const unsigned char *payload, const unsigned int plen)
 {
 	/* search in small packets only */
-	if (plen > 20 && plen < 200 && payload[plen-1] == 0x0a &&
-	    payload[plen-2] == 0x0d && memcmp(payload, "PRIVMSG ", 8) == 0)
+	if (plen > 20 && plen < 200 && iscrlf(&payload[plen - 2]) &&
+	    memcmp(payload, "PRIVMSG ", 8) == 0)
 	{
 		uint16_t x = 10;
 		const uint16_t end = plen - 13;
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH xtables-addons 5/8] xt_ipp2p: rearrange some conditionals and a couple of loops
  2023-06-05 19:17 [PATCH xtables-addons 0/8] xt_ipp2p: support for non-linear packets Jeremy Sowden
                   ` (3 preceding siblings ...)
  2023-06-05 19:17 ` [PATCH xtables-addons 4/8] xt_ipp2p: add helper for matching "\r\n" Jeremy Sowden
@ 2023-06-05 19:17 ` Jeremy Sowden
  2023-06-05 20:36   ` Jan Engelhardt
  2023-06-05 19:17 ` [PATCH xtables-addons 6/8] xt_ipp2p: use textsearch API for substring searching Jeremy Sowden
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 11+ messages in thread
From: Jeremy Sowden @ 2023-06-05 19:17 UTC (permalink / raw)
  To: Netfilter Devel

Reduce indentation and improve the readability of the code.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 extensions/xt_ipp2p.c | 333 ++++++++++++++++++++++--------------------
 1 file changed, 172 insertions(+), 161 deletions(-)

diff --git a/extensions/xt_ipp2p.c b/extensions/xt_ipp2p.c
index de253c4f4cb4..ae9a3dd2a920 100644
--- a/extensions/xt_ipp2p.c
+++ b/extensions/xt_ipp2p.c
@@ -199,12 +199,14 @@ static unsigned int udp_search_directconnect(const unsigned char *t,
 {
 	if (packet_len < 5)
 		return 0;
-	if (t[0] == 0x24 && t[packet_len-1] == 0x7c) {
-		if (memcmp(&t[1], "SR ", 3) == 0)
-			return IPP2P_DC * 100 + 60;
-		if (packet_len >= 7 && memcmp(&t[1], "Ping ", 5) == 0)
-			return IPP2P_DC * 100 + 61;
-	}
+	if (t[0] != 0x24)
+		return 0;
+	if (t[packet_len-1] != 0x7c)
+		return 0;
+	if (memcmp(&t[1], "SR ", 3) == 0)
+		return IPP2P_DC * 100 + 60;
+	if (packet_len >= 7 && memcmp(&t[1], "Ping ", 5) == 0)
+		return IPP2P_DC * 100 + 61;
 	return 0;
 }
 
@@ -263,12 +265,14 @@ udp_search_bit(const unsigned char *haystack, const unsigned int packet_len)
 	}
 
 	/* some extra-bitcomet rules: "d1:" [a|r] "d2:id20:" */
-	if (packet_len > 22 && get_u8(haystack, 0) == 'd' &&
-	    get_u8(haystack, 1) == '1' && get_u8(haystack, 2) == ':')
-		if (get_u8(haystack, 3) == 'a' ||
-		    get_u8(haystack, 3) == 'r')
-			if (memcmp(haystack + 4, "d2:id20:", 8) == 0)
-				return IPP2P_BIT * 100 + 57;
+	if (packet_len > 22 &&
+	    get_u8(haystack, 0) == 'd' &&
+	    get_u8(haystack, 1) == '1' &&
+	    get_u8(haystack, 2) == ':' &&
+	    (get_u8(haystack, 3) == 'a' ||
+	     get_u8(haystack, 3) == 'r') &&
+	    memcmp(haystack + 4, "d2:id20:", 8) == 0)
+		return IPP2P_BIT * 100 + 57;
 
 #if 0
 	/* bitlord rules */
@@ -447,19 +451,22 @@ search_soul(const unsigned char *payload, const unsigned int plen)
 	/* without size at the beginning !!! */
 	if (get_u32(payload, 0) == 0x14 && get_u8(payload, 4) == 0x01) {
 		uint32_t y = get_u32(payload, 5);
+		const unsigned char *w;
 
 		/* we need 19 chars + string */
-		if (y + 19 <= plen) {
-			const unsigned char *w = payload + 9 + y;
-			if (get_u32(w, 0) == 0x01 &&
-			    (get_u16(w, 4) == 0x4600 ||
-			     get_u16(w, 4) == 0x5000) &&
-			    get_u32(w, 6) == 0x00) {
+		if (plen < y + 19)
+			return 0;
+
+		w = payload + 9 + y;
+
+		if (get_u32(w, 0) == 0x01 &&
+		    (get_u16(w, 4) == 0x4600 ||
+		     get_u16(w, 4) == 0x5000) &&
+		    get_u32(w, 6) == 0x00) {
 #ifdef IPP2P_DEBUG_SOUL
-				printk(KERN_DEBUG "Soulseek special client command recognized\n");
+			printk(KERN_DEBUG "Soulseek special client command recognized\n");
 #endif
-				return IPP2P_SOUL * 100 + 9;
-			}
+			return IPP2P_SOUL * 100 + 9;
 		}
 	}
 	return 0;
@@ -523,10 +530,10 @@ search_winmx(const unsigned char *payload, const unsigned int plen)
 static unsigned int
 search_apple(const unsigned char *payload, const unsigned int plen)
 {
-	if (plen > 7 && iscrlf(&payload[6]) &&
-	    memcmp(payload, "ajprot", 6) == 0)
+	if (plen < 8)
+		return 0;
+	if (memcmp(payload, "ajprot\r\n", 8) == 0)
 		return IPP2P_APPLE * 100;
-
 	return 0;
 }
 
@@ -534,41 +541,38 @@ search_apple(const unsigned char *payload, const unsigned int plen)
 static unsigned int
 search_bittorrent(const unsigned char *payload, const unsigned int plen)
 {
-	if (plen > 20) {
-		/* test for match 0x13+"BitTorrent protocol" */
-		if (payload[0] == 0x13)
-			if (memcmp(payload + 1, "BitTorrent protocol", 19) == 0)
-				return IPP2P_BIT * 100;
-		/*
-		 * Any tracker command starts with GET / then *may be* some file on web server
-		 * (e.g. announce.php or dupa.pl or whatever.cgi or NOTHING for tracker on root dir)
-		 * but *must have* one (or more) of strings listed below (true for scrape and announce)
-		 */
-		if (memcmp(payload, "GET /", 5) == 0) {
-			if (HX_memmem(payload, plen, "info_hash=", 10) != NULL)
-				return IPP2P_BIT * 100 + 1;
-			if (HX_memmem(payload, plen, "peer_id=", 8) != NULL)
-				return IPP2P_BIT * 100 + 2;
-			if (HX_memmem(payload, plen, "passkey=", 8) != NULL)
-				return IPP2P_BIT * 100 + 4;
-		}
-	} else {
-	    	/* bitcomet encryptes the first packet, so we have to detect another
-	    	 * one later in the flow */
-		/* first try failed, too many false positives */
-	    	/*
-		if (size == 5 && get_u32(t, 0) == __constant_htonl(1) &&
-		    t[4] < 3)
-			return IPP2P_BIT * 100 + 3;
-		*/
+	/*
+	 * bitcomet encrypts the first packet, so we have to detect another one
+	 * later in the flow.
+	 */
+	if (plen == 17 &&
+	    get_u32(payload, 0) == __constant_htonl(0x0d) &&
+	    payload[4] == 0x06 &&
+	    get_u32(payload,13) == __constant_htonl(0x4000))
+		return IPP2P_BIT * 100 + 3;
 
-	    	/* second try: block request packets */
-	    	if (plen == 17 &&
-		    get_u32(payload, 0) == __constant_htonl(0x0d) &&
-		    payload[4] == 0x06 &&
-		    get_u32(payload,13) == __constant_htonl(0x4000))
-			return IPP2P_BIT * 100 + 3;
-	}
+	if (plen <= 20)
+		return 0;
+
+	/* test for match 0x13+"BitTorrent protocol" */
+	if (payload[0] == 0x13)
+		if (memcmp(payload + 1, "BitTorrent protocol", 19) == 0)
+			return IPP2P_BIT * 100;
+
+	/*
+	 * Any tracker command starts with GET / then *may be* some file
+	 * on web server (e.g. announce.php or dupa.pl or whatever.cgi
+	 * or NOTHING for tracker on root dir) but *must have* one (or
+	 * more) of strings listed below (true for scrape and announce)
+	 */
+	if (memcmp(payload, "GET /", 5) != 0)
+		return 0;
+	if (HX_memmem(payload, plen, "info_hash=", 10) != NULL)
+		return IPP2P_BIT * 100 + 1;
+	if (HX_memmem(payload, plen, "peer_id=", 8) != NULL)
+		return IPP2P_BIT * 100 + 2;
+	if (HX_memmem(payload, plen, "passkey=", 8) != NULL)
+		return IPP2P_BIT * 100 + 4;
 
 	return 0;
 }
@@ -592,12 +596,12 @@ search_gnu(const unsigned char *payload, const unsigned int plen)
 {
 	if (plen < 11)
 		return 0;
-	if (iscrlf(&payload[plen - 2])) {
-		if (memcmp(payload, "GET /get/", 9) == 0)
-			return IPP2P_DATA_GNU * 100 + 1;
-		if (plen >= 15 && memcmp(payload, "GET /uri-res/", 13) == 0)
-			return IPP2P_DATA_GNU * 100 + 2;
-	}
+	if (!iscrlf(&payload[plen - 2]))
+		return 0;
+	if (memcmp(payload, "GET /get/", 9) == 0)
+		return IPP2P_DATA_GNU * 100 + 1;
+	if (plen >= 15 && memcmp(payload, "GET /uri-res/", 13) == 0)
+		return IPP2P_DATA_GNU * 100 + 2;
 	return 0;
 }
 
@@ -605,25 +609,33 @@ search_gnu(const unsigned char *payload, const unsigned int plen)
 static unsigned int
 search_all_gnu(const unsigned char *payload, const unsigned int plen)
 {
+	unsigned int c;
+
 	if (plen < 11)
 		return 0;
-	if (iscrlf(&payload[plen - 2])) {
-		if (plen >= 19 && memcmp(payload, "GNUTELLA CONNECT/", 17) == 0)
-			return IPP2P_GNU * 100 + 1;
-		if (memcmp(payload, "GNUTELLA/", 9) == 0)
-			return IPP2P_GNU * 100 + 2;
-
-		if (plen >= 22 && (memcmp(payload, "GET /get/", 9) == 0 ||
-		    memcmp(payload, "GET /uri-res/", 13) == 0))
-		{
-			unsigned int c;
+	if (!iscrlf(&payload[plen - 2]))
+		return 0;
+	if (plen >= 19 && memcmp(payload, "GNUTELLA CONNECT/", 17) == 0)
+		return IPP2P_GNU * 100 + 1;
+	if (memcmp(payload, "GNUTELLA/", 9) == 0)
+		return IPP2P_GNU * 100 + 2;
 
-			for (c = 0; c < plen - 22; ++c)
-				if (iscrlf(&payload[c]) &&
-				    (memcmp(&payload[c+2], "X-Gnutella-", 11) == 0 ||
-				    memcmp(&payload[c+2], "X-Queue:", 8) == 0))
-					return IPP2P_GNU * 100 + 3;
-		}
+	if (plen < 22)
+		return 0;
+
+	if (memcmp(payload, "GET /get/", 9) != 0 &&
+	    memcmp(payload, "GET /uri-res/", 13) != 0)
+		return 0;
+
+	for (c = 0; c < plen - 22; ++c) {
+		if (!iscrlf(&payload[c]))
+			continue;
+
+		if (memcmp(&payload[c+2], "X-Gnutella-", 11) == 0)
+			return IPP2P_GNU * 100 + 3;
+
+		if ( memcmp(&payload[c+2], "X-Queue:", 8) == 0)
+			return IPP2P_GNU * 100 + 3;
 	}
 	return 0;
 }
@@ -674,39 +686,37 @@ search_edk(const unsigned char *payload, const unsigned int plen)
 {
 	if (plen < 6)
 		return 0;
-	if (payload[0] != 0xe3) {
+	if (payload[0] != 0xe3)
 		return 0;
-	} else {
-		if (payload[5] == 0x47)
-			return IPP2P_DATA_EDK * 100;
-		else
-			return 0;
-	}
+	if (payload[5] == 0x47)
+		return IPP2P_DATA_EDK * 100;
+	return 0;
 }
 
 /* intensive but slower search for some edonkey packets including size-check */
 static unsigned int
 search_all_edk(const unsigned char *payload, const unsigned int plen)
 {
+	unsigned int cmd;
+
 	if (plen < 6)
 		return 0;
-	if (payload[0] != 0xe3) {
+	if (payload[0] != 0xe3)
 		return 0;
-	} else {
-		unsigned int cmd = get_u16(payload, 1);
 
-		if (cmd == plen - 5) {
-			switch (payload[5]) {
-			case 0x01:
-				/* Client: hello or Server:hello */
+	cmd = get_u16(payload, 1);
+
+	if (cmd == plen - 5) {
+		switch (payload[5]) {
+		case 0x01:
+			/* Client: hello or Server:hello */
 			return IPP2P_EDK * 100 + 1;
-				case 0x4c:
-				/* Client: Hello-Answer */
-				return IPP2P_EDK * 100 + 9;
-			}
+		case 0x4c:
+			/* Client: Hello-Answer */
+			return IPP2P_EDK * 100 + 9;
 		}
-		return 0;
 	}
+	return 0;
 }
 
 /* fast check for Direct Connect send command */
@@ -715,36 +725,41 @@ search_dc(const unsigned char *payload, const unsigned int plen)
 {
 	if (plen < 6)
 		return 0;
-	if (payload[0] != 0x24) {
+	if (payload[0] != 0x24)
 		return 0;
-	} else {
-		if (memcmp(&payload[1], "Send|", 5) == 0)
-			return IPP2P_DATA_DC * 100;
-		else
-			return 0;
-	}
+	if (memcmp(&payload[1], "Send|", 5) == 0)
+		return IPP2P_DATA_DC * 100;
+	return 0;
 }
 
 /* intensive but slower check for all direct connect packets */
 static unsigned int
 search_all_dc(const unsigned char *payload, const unsigned int plen)
 {
+	const unsigned char *t;
+
 	if (plen < 7)
 		return 0;
-	if (payload[0] == 0x24 && payload[plen-1] == 0x7c) {
-		const unsigned char *t = &payload[1];
 
-		/* Client-Hub-Protocol */
-		if (memcmp(t, "Lock ", 5) == 0)
-			return IPP2P_DC * 100 + 1;
+	if (payload[0] != 0x24)
+		return 0;
+
+	if (payload[plen-1] != 0x7c)
+		return 0;
+
+	t = &payload[1];
+
+	/* Client-Hub-Protocol */
+	if (memcmp(t, "Lock ", 5) == 0)
+		return IPP2P_DC * 100 + 1;
+
+	/*
+	 * Client-Client-Protocol, some are already recognized by client-hub
+	 * (like lock)
+	 */
+	if (plen >= 9 && memcmp(t, "MyNick ", 7) == 0)
+		return IPP2P_DC * 100 + 38;
 
-		/*
-		 * Client-Client-Protocol, some are already recognized by
-		 * client-hub (like lock)
-		 */
-		if (plen >= 9 && memcmp(t, "MyNick ", 7) == 0)
-			return IPP2P_DC * 100 + 38;
-	}
 	return 0;
 }
 
@@ -770,23 +785,25 @@ search_mute(const unsigned char *payload, const unsigned int plen)
 static unsigned int
 search_xdcc(const unsigned char *payload, const unsigned int plen)
 {
+	uint16_t x = 10;
+	const uint16_t end = plen - 13;
+
 	/* search in small packets only */
-	if (plen > 20 && plen < 200 && iscrlf(&payload[plen - 2]) &&
-	    memcmp(payload, "PRIVMSG ", 8) == 0)
-	{
-		uint16_t x = 10;
-		const uint16_t end = plen - 13;
+	if (plen <= 20 || plen >= 200)
+		return 0;
 
-		/*
-		 * is seems to be a irc private massage, chedck for
-		 * xdcc command
-		 */
-		while (x < end)	{
-			if (payload[x] == ':')
-				if (memcmp(&payload[x+1], "xdcc send #", 11) == 0)
-					return IPP2P_XDCC * 100 + 0;
-			x++;
-		}
+	if (memcmp(payload, "PRIVMSG ", 8) != 0 || !iscrlf(&payload[plen - 2]))
+		return 0;
+
+	/*
+	 * is seems to be a irc private massage, chedck for
+	 * xdcc command
+	 */
+	while (x < end)	{
+		if (payload[x] == ':' &&
+		    memcmp(&payload[x + 1], "xdcc send #", 11) == 0)
+			return IPP2P_XDCC * 100 + 0;
+		x++;
 	}
 	return 0;
 }
@@ -862,8 +879,7 @@ ipp2p_mt_tcp(const struct ipt_p2p_info *info, const struct tcphdr *tcph,
              const struct ipp2p_result_printer *rp)
 {
 	size_t tcph_len = tcph->doff * 4;
-	bool p2p_result = false;
-	int i = 0;
+	int i;
 
 	if (tcph->fin) return 0;  /* if FIN bit is set bail out */
 	if (tcph->syn) return 0;  /* if SYN bit is set bail out */
@@ -880,20 +896,18 @@ ipp2p_mt_tcp(const struct ipt_p2p_info *info, const struct tcphdr *tcph,
 	haystack += tcph_len;
 	hlen     -= tcph_len;
 
-	while (matchlist[i].command) {
-		if ((info->cmd & matchlist[i].command) == matchlist[i].command &&
-		    hlen > matchlist[i].packet_len)
-		{
-			p2p_result = matchlist[i].function_name(haystack, hlen);
-			if (p2p_result)	{
-				if (info->debug)
-					print_result(rp, p2p_result, hlen);
-				return p2p_result;
-			}
+	for (i = 0; matchlist[i].command; ++i) {
+		if ((info->cmd & matchlist[i].command) != matchlist[i].command)
+			continue;
+		if (hlen <= matchlist[i].packet_len)
+			continue;
+		if (matchlist[i].function_name(haystack, hlen))	{
+			if (info->debug)
+				print_result(rp, true, hlen);
+			return true;
 		}
-		i++;
 	}
-	return p2p_result;
+	return false;
 }
 
 static void
@@ -920,8 +934,7 @@ ipp2p_mt_udp(const struct ipt_p2p_info *info, const struct udphdr *udph,
              const struct ipp2p_result_printer *rp)
 {
 	size_t udph_len = sizeof(*udph);
-	bool p2p_result = false;
-	int i = 0;
+	int i;
 
 	if (hlen < udph_len) {
 		if (info->debug)
@@ -934,20 +947,18 @@ ipp2p_mt_udp(const struct ipt_p2p_info *info, const struct udphdr *udph,
 	haystack += udph_len;
 	hlen     -= udph_len;
 
-	while (udp_list[i].command) {
-		if ((info->cmd & udp_list[i].command) == udp_list[i].command &&
-		    hlen > udp_list[i].packet_len)
-		{
-			p2p_result = udp_list[i].function_name(haystack, hlen);
-			if (p2p_result) {
-				if (info->debug)
-					print_result(rp, p2p_result, hlen);
-				return p2p_result;
-			}
+	for (i = 0; udp_list[i].command; ++i) {
+		if ((info->cmd & udp_list[i].command) != udp_list[i].command)
+			continue;
+		if (hlen <= udp_list[i].packet_len)
+			continue;
+		if (udp_list[i].function_name(haystack, hlen)) {
+			if (info->debug)
+				print_result(rp, true, hlen);
+			return true;
 		}
-		i++;
 	}
-	return p2p_result;
+	return false;
 }
 
 static bool
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH xtables-addons 6/8] xt_ipp2p: use textsearch API for substring searching
  2023-06-05 19:17 [PATCH xtables-addons 0/8] xt_ipp2p: support for non-linear packets Jeremy Sowden
                   ` (4 preceding siblings ...)
  2023-06-05 19:17 ` [PATCH xtables-addons 5/8] xt_ipp2p: rearrange some conditionals and a couple of loops Jeremy Sowden
@ 2023-06-05 19:17 ` Jeremy Sowden
  2023-06-05 19:17 ` [PATCH xtables-addons 7/8] xt_ipp2p: use `skb_header_pointer` and `skb_find_text` Jeremy Sowden
  2023-06-05 19:17 ` [PATCH xtables-addons 8/8] xt_ipp2p: drop requirement that skb is linear Jeremy Sowden
  7 siblings, 0 replies; 11+ messages in thread
From: Jeremy Sowden @ 2023-06-05 19:17 UTC (permalink / raw)
  To: Netfilter Devel

Some of the matchers have hand-rolled substring search implementations.
Replace them with the kernel's textsearch API.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 extensions/xt_ipp2p.c | 312 +++++++++++++++++++++++++++++++-----------
 extensions/xt_ipp2p.h |  10 ++
 2 files changed, 245 insertions(+), 77 deletions(-)

diff --git a/extensions/xt_ipp2p.c b/extensions/xt_ipp2p.c
index ae9a3dd2a920..1378701605c3 100644
--- a/extensions/xt_ipp2p.c
+++ b/extensions/xt_ipp2p.c
@@ -1,4 +1,6 @@
+#include <linux/gfp.h>
 #include <linux/module.h>
+#include <linux/textsearch.h>
 #include <linux/version.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <net/tcp.h>
@@ -55,7 +57,8 @@ print_result(const struct ipp2p_result_printer *rp, bool result,
 
 /* Search for UDP eDonkey/eMule/Kad commands */
 static unsigned int
-udp_search_edk(const unsigned char *t, const unsigned int packet_len)
+udp_search_edk(const unsigned char *t, const unsigned int packet_len,
+	       const struct ipt_p2p_info *info)
 {
 	if (packet_len < 4)
 		return 0;
@@ -173,7 +176,8 @@ udp_search_edk(const unsigned char *t, const unsigned int packet_len)
 
 /* Search for UDP Gnutella commands */
 static unsigned int
-udp_search_gnu(const unsigned char *t, const unsigned int packet_len)
+udp_search_gnu(const unsigned char *t, const unsigned int packet_len,
+	       const struct ipt_p2p_info *info)
 {
 	if (packet_len >= 3 && memcmp(t, "GND", 3) == 0)
 		return IPP2P_GNU * 100 + 51;
@@ -184,7 +188,8 @@ udp_search_gnu(const unsigned char *t, const unsigned int packet_len)
 
 /* Search for UDP KaZaA commands */
 static unsigned int
-udp_search_kazaa(const unsigned char *t, const unsigned int packet_len)
+udp_search_kazaa(const unsigned char *t, const unsigned int packet_len,
+		 const struct ipt_p2p_info *info)
 {
 	if (packet_len < 6)
 		return 0;
@@ -194,8 +199,9 @@ udp_search_kazaa(const unsigned char *t, const unsigned int packet_len)
 }
 
 /* Search for UDP DirectConnect commands */
-static unsigned int udp_search_directconnect(const unsigned char *t,
-                                             const unsigned int packet_len)
+static unsigned int
+udp_search_directconnect(const unsigned char *t, const unsigned int packet_len,
+			 const struct ipt_p2p_info *info)
 {
 	if (packet_len < 5)
 		return 0;
@@ -212,7 +218,8 @@ static unsigned int udp_search_directconnect(const unsigned char *t,
 
 /* Search for UDP BitTorrent commands */
 static unsigned int
-udp_search_bit(const unsigned char *haystack, const unsigned int packet_len)
+udp_search_bit(const unsigned char *haystack, const unsigned int packet_len,
+	       const struct ipt_p2p_info *info)
 {
 	switch (packet_len) {
 	case 16:
@@ -298,7 +305,8 @@ udp_search_bit(const unsigned char *haystack, const unsigned int packet_len)
 
 /* Search for Ares commands */
 static unsigned int
-search_ares(const unsigned char *payload, const unsigned int plen)
+search_ares(const unsigned char *payload, const unsigned int plen,
+	    const struct ipt_p2p_info *info)
 {
 	if (plen < 3)
 		return 0;
@@ -350,7 +358,8 @@ search_ares(const unsigned char *payload, const unsigned int plen)
 
 /* Search for SoulSeek commands */
 static unsigned int
-search_soul(const unsigned char *payload, const unsigned int plen)
+search_soul(const unsigned char *payload, const unsigned int plen,
+	    const struct ipt_p2p_info *info)
 {
 	if (plen < 8)
 		return 0;
@@ -474,8 +483,11 @@ search_soul(const unsigned char *payload, const unsigned int plen)
 
 /* Search for WinMX commands */
 static unsigned int
-search_winmx(const unsigned char *payload, const unsigned int plen)
+search_winmx(const unsigned char *payload, const unsigned int plen,
+	     const struct ipt_p2p_info *info)
 {
+	uint16_t start;
+
 	if (plen == 4 && memcmp(payload, "SEND", 4) == 0)
 		return IPP2P_WINMX * 100 + 1;
 	if (plen == 3 && memcmp(payload, "GET", 3) == 0)
@@ -487,20 +499,33 @@ search_winmx(const unsigned char *payload, const unsigned int plen)
 	if (plen < 10)
 		return 0;
 
-	if (memcmp(payload, "SEND", 4) == 0 || memcmp(payload, "GET", 3) == 0) {
-		uint16_t c = 4;
-		const uint16_t end = plen - 2;
+	if (memcmp(payload, "SEND", 4) == 0)
+		start = 4;
+	else if (memcmp(payload, "GET", 3) == 0)
+		start = 3;
+	else
+		start = 0;
+
+	if (start) {
 		uint8_t count = 0;
 
-		while (c < end) {
-			if (payload[c] == 0x20 && payload[c+1] == 0x22) {
-				c++;
-				count++;
-				if (count >= 2)
-					return IPP2P_WINMX * 100 + 3;
-			}
-			c++;
-		}
+		do {
+			struct ts_state state;
+			unsigned int pos;
+
+			pos = textsearch_find_continuous(info->ts_conf_winmx,
+							 &state,
+							 &payload[start],
+							 plen - start);
+			if (pos == UINT_MAX)
+				break;
+
+			count++;
+			if (count >= 2)
+				return IPP2P_WINMX * 100 + 3;
+
+			start = pos + 2;
+		} while (start < plen);
 	}
 
 	if (plen == 149 && payload[0] == '8') {
@@ -528,7 +553,8 @@ search_winmx(const unsigned char *payload, const unsigned int plen)
 
 /* Search for appleJuice commands */
 static unsigned int
-search_apple(const unsigned char *payload, const unsigned int plen)
+search_apple(const unsigned char *payload, const unsigned int plen,
+	     const struct ipt_p2p_info *info)
 {
 	if (plen < 8)
 		return 0;
@@ -539,8 +565,12 @@ search_apple(const unsigned char *payload, const unsigned int plen)
 
 /* Search for BitTorrent commands */
 static unsigned int
-search_bittorrent(const unsigned char *payload, const unsigned int plen)
+search_bittorrent(const unsigned char *payload, const unsigned int plen,
+		  const struct ipt_p2p_info *info)
 {
+	struct ts_state state;
+	unsigned int pos;
+
 	/*
 	 * bitcomet encrypts the first packet, so we have to detect another one
 	 * later in the flow.
@@ -567,11 +597,20 @@ search_bittorrent(const unsigned char *payload, const unsigned int plen)
 	 */
 	if (memcmp(payload, "GET /", 5) != 0)
 		return 0;
-	if (HX_memmem(payload, plen, "info_hash=", 10) != NULL)
+
+	pos = textsearch_find_continuous(info->ts_conf_bt_info_hash,
+					 &state, &payload[5], plen - 5);
+	if (pos != UINT_MAX)
 		return IPP2P_BIT * 100 + 1;
-	if (HX_memmem(payload, plen, "peer_id=", 8) != NULL)
+
+	pos = textsearch_find_continuous(info->ts_conf_bt_peer_id,
+					 &state, &payload[5], plen - 5);
+	if (pos != UINT_MAX)
 		return IPP2P_BIT * 100 + 2;
-	if (HX_memmem(payload, plen, "passkey=", 8) != NULL)
+
+	pos = textsearch_find_continuous(info->ts_conf_bt_passkey,
+					 &state, &payload[5], plen - 5);
+	if (pos != UINT_MAX)
 		return IPP2P_BIT * 100 + 4;
 
 	return 0;
@@ -579,7 +618,8 @@ search_bittorrent(const unsigned char *payload, const unsigned int plen)
 
 /* check for Kazaa get command */
 static unsigned int
-search_kazaa(const unsigned char *payload, const unsigned int plen)
+search_kazaa(const unsigned char *payload, const unsigned int plen,
+	     const struct ipt_p2p_info *info)
 {
 	if (plen < 13)
 		return 0;
@@ -592,7 +632,8 @@ search_kazaa(const unsigned char *payload, const unsigned int plen)
 
 /* check for gnutella get command */
 static unsigned int
-search_gnu(const unsigned char *payload, const unsigned int plen)
+search_gnu(const unsigned char *payload, const unsigned int plen,
+	   const struct ipt_p2p_info *info)
 {
 	if (plen < 11)
 		return 0;
@@ -607,9 +648,11 @@ search_gnu(const unsigned char *payload, const unsigned int plen)
 
 /* check for gnutella get commands and other typical data */
 static unsigned int
-search_all_gnu(const unsigned char *payload, const unsigned int plen)
+search_all_gnu(const unsigned char *payload, const unsigned int plen,
+	       const struct ipt_p2p_info *info)
 {
-	unsigned int c;
+	struct ts_state state;
+	unsigned int c, pos;
 
 	if (plen < 11)
 		return 0;
@@ -623,29 +666,34 @@ search_all_gnu(const unsigned char *payload, const unsigned int plen)
 	if (plen < 22)
 		return 0;
 
-	if (memcmp(payload, "GET /get/", 9) != 0 &&
-	    memcmp(payload, "GET /uri-res/", 13) != 0)
+	if (memcmp(payload, "GET /get/", 9) == 0)
+		c = 9;
+	else if (memcmp(payload, "GET /uri-res/", 13) == 0)
+		c = 13;
+	else
 		return 0;
 
-	for (c = 0; c < plen - 22; ++c) {
-		if (!iscrlf(&payload[c]))
-			continue;
+	pos = textsearch_find_continuous(info->ts_conf_gnu_x_gnutella,
+					 &state, &payload[c], plen - c);
+	if (pos != UINT_MAX)
+		return IPP2P_GNU * 100 + 3;
 
-		if (memcmp(&payload[c+2], "X-Gnutella-", 11) == 0)
-			return IPP2P_GNU * 100 + 3;
+	pos = textsearch_find_continuous(info->ts_conf_gnu_x_queue,
+					 &state, &payload[c], plen - c);
+	if (pos != UINT_MAX)
+		return IPP2P_GNU * 100 + 3;
 
-		if ( memcmp(&payload[c+2], "X-Queue:", 8) == 0)
-			return IPP2P_GNU * 100 + 3;
-	}
 	return 0;
 }
 
 /* check for KaZaA download commands and other typical data */
 /* plen is guaranteed to be >= 5 (see @matchlist) */
 static unsigned int
-search_all_kazaa(const unsigned char *payload, const unsigned int plen)
+search_all_kazaa(const unsigned char *payload, const unsigned int plen,
+		 const struct ipt_p2p_info *info)
 {
-	uint16_t c, end, rem;
+	struct ts_state state;
+	unsigned int pos;
 
 	if (plen < 7)
 		/* too short for anything we test for - early bailout */
@@ -664,25 +712,23 @@ search_all_kazaa(const unsigned char *payload, const unsigned int plen)
 		/* The next tests would not succeed anyhow. */
 		return 0;
 
-	end = plen - 18;
-	rem = plen - 5;
-	for (c = 5; c < end; ++c, --rem) {
-		if (!iscrlf(&payload[c]))
-			continue;
-		if (rem >= 18 &&
-		    memcmp(&payload[c+2], "X-Kazaa-Username: ", 18) == 0)
-			return IPP2P_KAZAA * 100 + 2;
-		if (rem >= 24 &&
-		    memcmp(&payload[c+2], "User-Agent: PeerEnabler/", 24) == 0)
-			return IPP2P_KAZAA * 100 + 2;
-	}
+	pos = textsearch_find_continuous(info->ts_conf_kz_x_kazaa_username,
+					 &state, &payload[5], plen - 5);
+	if (pos != UINT_MAX)
+		return IPP2P_KAZAA * 100 + 2;
+
+	pos = textsearch_find_continuous(info->ts_conf_kz_user_agent,
+					 &state, &payload[5], plen - 5);
+	if (pos != UINT_MAX)
+		return IPP2P_KAZAA * 100 + 2;
 
 	return 0;
 }
 
 /* fast check for edonkey file segment transfer command */
 static unsigned int
-search_edk(const unsigned char *payload, const unsigned int plen)
+search_edk(const unsigned char *payload, const unsigned int plen,
+	   const struct ipt_p2p_info *info)
 {
 	if (plen < 6)
 		return 0;
@@ -695,7 +741,8 @@ search_edk(const unsigned char *payload, const unsigned int plen)
 
 /* intensive but slower search for some edonkey packets including size-check */
 static unsigned int
-search_all_edk(const unsigned char *payload, const unsigned int plen)
+search_all_edk(const unsigned char *payload, const unsigned int plen,
+	       const struct ipt_p2p_info *info)
 {
 	unsigned int cmd;
 
@@ -721,7 +768,8 @@ search_all_edk(const unsigned char *payload, const unsigned int plen)
 
 /* fast check for Direct Connect send command */
 static unsigned int
-search_dc(const unsigned char *payload, const unsigned int plen)
+search_dc(const unsigned char *payload, const unsigned int plen,
+	  const struct ipt_p2p_info *info)
 {
 	if (plen < 6)
 		return 0;
@@ -734,7 +782,8 @@ search_dc(const unsigned char *payload, const unsigned int plen)
 
 /* intensive but slower check for all direct connect packets */
 static unsigned int
-search_all_dc(const unsigned char *payload, const unsigned int plen)
+search_all_dc(const unsigned char *payload, const unsigned int plen,
+	      const struct ipt_p2p_info *info)
 {
 	const unsigned char *t;
 
@@ -765,7 +814,8 @@ search_all_dc(const unsigned char *payload, const unsigned int plen)
 
 /* check for mute */
 static unsigned int
-search_mute(const unsigned char *payload, const unsigned int plen)
+search_mute(const unsigned char *payload, const unsigned int plen,
+	    const struct ipt_p2p_info *info)
 {
 	if (plen == 209 || plen == 345 || plen == 473 || plen == 609 ||
 	    plen == 1121) {
@@ -783,10 +833,11 @@ search_mute(const unsigned char *payload, const unsigned int plen)
 
 /* check for xdcc */
 static unsigned int
-search_xdcc(const unsigned char *payload, const unsigned int plen)
+search_xdcc(const unsigned char *payload, const unsigned int plen,
+	    const struct ipt_p2p_info *info)
 {
-	uint16_t x = 10;
-	const uint16_t end = plen - 13;
+	struct ts_state state;
+	unsigned int pos;
 
 	/* search in small packets only */
 	if (plen <= 20 || plen >= 200)
@@ -795,22 +846,19 @@ search_xdcc(const unsigned char *payload, const unsigned int plen)
 	if (memcmp(payload, "PRIVMSG ", 8) != 0 || !iscrlf(&payload[plen - 2]))
 		return 0;
 
-	/*
-	 * is seems to be a irc private massage, chedck for
-	 * xdcc command
-	 */
-	while (x < end)	{
-		if (payload[x] == ':' &&
-		    memcmp(&payload[x + 1], "xdcc send #", 11) == 0)
-			return IPP2P_XDCC * 100 + 0;
-		x++;
-	}
+	/* seems to be a irc private massage, check for xdcc command */
+	pos = textsearch_find_continuous(info->ts_conf_xdcc,
+					 &state, &payload[8], plen - 8);
+	if (pos != UINT_MAX)
+		return IPP2P_XDCC * 100 + 0;
+
 	return 0;
 }
 
 /* search for waste */
 static unsigned int
-search_waste(const unsigned char *payload, const unsigned int plen)
+search_waste(const unsigned char *payload, const unsigned int plen,
+	     const struct ipt_p2p_info *info)
 {
 	if (plen >= 9 && memcmp(payload, "GET.sha1:", 9) == 0)
 		return IPP2P_WASTE * 100 + 0;
@@ -821,7 +869,8 @@ search_waste(const unsigned char *payload, const unsigned int plen)
 static const struct {
 	unsigned int command;
 	unsigned int packet_len;
-	unsigned int (*function_name)(const unsigned char *, const unsigned int);
+	unsigned int (*function_name)(const unsigned char *, const unsigned int,
+				      const struct ipt_p2p_info *);
 } matchlist[] = {
 	{IPP2P_EDK,         20, search_all_edk},
 	{IPP2P_DATA_KAZAA, 200, search_kazaa}, /* exp */
@@ -845,7 +894,8 @@ static const struct {
 static const struct {
 	unsigned int command;
 	unsigned int packet_len;
-	unsigned int (*function_name)(const unsigned char *, const unsigned int);
+	unsigned int (*function_name)(const unsigned char *, const unsigned int,
+				      const struct ipt_p2p_info *);
 } udp_list[] = {
 	{IPP2P_KAZAA, 14, udp_search_kazaa},
 	{IPP2P_BIT,   23, udp_search_bit},
@@ -901,7 +951,7 @@ ipp2p_mt_tcp(const struct ipt_p2p_info *info, const struct tcphdr *tcph,
 			continue;
 		if (hlen <= matchlist[i].packet_len)
 			continue;
-		if (matchlist[i].function_name(haystack, hlen))	{
+		if (matchlist[i].function_name(haystack, hlen, info)) {
 			if (info->debug)
 				print_result(rp, true, hlen);
 			return true;
@@ -952,7 +1002,7 @@ ipp2p_mt_udp(const struct ipt_p2p_info *info, const struct udphdr *udph,
 			continue;
 		if (hlen <= udp_list[i].packet_len)
 			continue;
-		if (udp_list[i].function_name(haystack, hlen)) {
+		if (udp_list[i].function_name(haystack, hlen, info)) {
 			if (info->debug)
 				print_result(rp, true, hlen);
 			return true;
@@ -1041,12 +1091,118 @@ ipp2p_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	}
 }
 
+static int ipp2p_mt_check(const struct xt_mtchk_param *par)
+{
+	struct ipt_p2p_info *info = par->matchinfo;
+	struct ts_config *ts_conf;
+
+	ts_conf = textsearch_prepare("bm", "\x20\x22", 2,
+				     GFP_KERNEL, TS_AUTOLOAD);
+	if (IS_ERR(ts_conf))
+		goto err_return;
+	info->ts_conf_winmx = ts_conf;
+
+	ts_conf = textsearch_prepare("bm", "info_hash=", 10,
+				     GFP_KERNEL, TS_AUTOLOAD);
+	if (IS_ERR(ts_conf))
+		goto err_ts_destroy_winmx;
+	info->ts_conf_bt_info_hash = ts_conf;
+
+	ts_conf = textsearch_prepare("bm", "peer_id=", 8,
+				     GFP_KERNEL, TS_AUTOLOAD);
+	if (IS_ERR(ts_conf))
+		goto err_ts_destroy_bt_info_hash;
+	info->ts_conf_bt_peer_id = ts_conf;
+
+	ts_conf = textsearch_prepare("bm", "passkey", 8,
+				     GFP_KERNEL, TS_AUTOLOAD);
+	if (IS_ERR(ts_conf))
+		goto err_ts_destroy_bt_peer_id;
+	info->ts_conf_bt_passkey = ts_conf;
+
+	ts_conf = textsearch_prepare("bm", "\r\nX-Gnutella-", 13,
+				     GFP_KERNEL, TS_AUTOLOAD);
+	if (IS_ERR(ts_conf))
+		goto err_ts_destroy_bt_passkey;
+	info->ts_conf_gnu_x_gnutella = ts_conf;
+
+	ts_conf = textsearch_prepare("bm", "\r\nX-Queue-", 10,
+				     GFP_KERNEL, TS_AUTOLOAD);
+	if (IS_ERR(ts_conf))
+		goto err_ts_destroy_gnu_x_gnutella;
+	info->ts_conf_gnu_x_queue = ts_conf;
+
+	ts_conf = textsearch_prepare("bm", "\r\nX-Kazaa-Username: ", 20,
+				     GFP_KERNEL, TS_AUTOLOAD);
+	if (IS_ERR(ts_conf))
+		goto err_ts_destroy_gnu_x_queue;
+	info->ts_conf_kz_x_kazaa_username = ts_conf;
+
+	ts_conf = textsearch_prepare("bm", "\r\nUser-Agent: PeerEnabler/", 26,
+				     GFP_KERNEL, TS_AUTOLOAD);
+	if (IS_ERR(ts_conf))
+		goto err_ts_destroy_kazaa_x_kazaa_username;
+	info->ts_conf_kz_user_agent = ts_conf;
+
+	ts_conf = textsearch_prepare("bm", ":xdcc send #", 12,
+				     GFP_KERNEL, TS_AUTOLOAD);
+	if (IS_ERR(ts_conf))
+		goto err_ts_destroy_kazaa_user_agent;
+	info->ts_conf_xdcc = ts_conf;
+
+	return 0;
+
+err_ts_destroy_kazaa_user_agent:
+	textsearch_destroy(info->ts_conf_kz_user_agent);
+
+err_ts_destroy_kazaa_x_kazaa_username:
+	textsearch_destroy(info->ts_conf_kz_x_kazaa_username);
+
+err_ts_destroy_gnu_x_queue:
+	textsearch_destroy(info->ts_conf_gnu_x_queue);
+
+err_ts_destroy_gnu_x_gnutella:
+	textsearch_destroy(info->ts_conf_gnu_x_gnutella);
+
+err_ts_destroy_bt_passkey:
+	textsearch_destroy(info->ts_conf_bt_passkey);
+
+err_ts_destroy_bt_peer_id:
+	textsearch_destroy(info->ts_conf_bt_peer_id);
+
+err_ts_destroy_bt_info_hash:
+	textsearch_destroy(info->ts_conf_bt_info_hash);
+
+err_ts_destroy_winmx:
+	textsearch_destroy(info->ts_conf_winmx);
+
+err_return:
+	return PTR_ERR(ts_conf);
+}
+
+static void ipp2p_mt_destroy(const struct xt_mtdtor_param *par)
+{
+	struct ipt_p2p_info *info = (struct ipt_p2p_info *) par->matchinfo;
+
+	textsearch_destroy(info->ts_conf_winmx);
+	textsearch_destroy(info->ts_conf_bt_info_hash);
+	textsearch_destroy(info->ts_conf_bt_peer_id);
+	textsearch_destroy(info->ts_conf_bt_passkey);
+	textsearch_destroy(info->ts_conf_gnu_x_gnutella);
+	textsearch_destroy(info->ts_conf_gnu_x_queue);
+	textsearch_destroy(info->ts_conf_kz_x_kazaa_username);
+	textsearch_destroy(info->ts_conf_kz_user_agent);
+	textsearch_destroy(info->ts_conf_xdcc);
+}
+
 static struct xt_match ipp2p_mt_reg[] __read_mostly = {
 	{
 		.name       = "ipp2p",
 		.revision   = 1,
 		.family     = NFPROTO_IPV4,
+		.checkentry = ipp2p_mt_check,
 		.match      = ipp2p_mt,
+		.destroy    = ipp2p_mt_destroy,
 		.matchsize  = sizeof(struct ipt_p2p_info),
 		.me         = THIS_MODULE,
 	},
@@ -1054,7 +1210,9 @@ static struct xt_match ipp2p_mt_reg[] __read_mostly = {
 		.name       = "ipp2p",
 		.revision   = 1,
 		.family     = NFPROTO_IPV6,
+		.checkentry = ipp2p_mt_check,
 		.match      = ipp2p_mt,
+		.destroy    = ipp2p_mt_destroy,
 		.matchsize  = sizeof(struct ipt_p2p_info),
 		.me         = THIS_MODULE,
 	},
diff --git a/extensions/xt_ipp2p.h b/extensions/xt_ipp2p.h
index f463f7f6e630..b821d75220b6 100644
--- a/extensions/xt_ipp2p.h
+++ b/extensions/xt_ipp2p.h
@@ -39,4 +39,14 @@ enum {
 
 struct ipt_p2p_info {
 	int32_t cmd, debug;
+
+	struct ts_config *ts_conf_winmx;
+	struct ts_config *ts_conf_bt_info_hash;
+	struct ts_config *ts_conf_bt_peer_id;
+	struct ts_config *ts_conf_bt_passkey;
+	struct ts_config *ts_conf_gnu_x_gnutella;
+	struct ts_config *ts_conf_gnu_x_queue;
+	struct ts_config *ts_conf_kz_x_kazaa_username;
+	struct ts_config *ts_conf_kz_user_agent;
+	struct ts_config *ts_conf_xdcc;
 };
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH xtables-addons 7/8] xt_ipp2p: use `skb_header_pointer` and `skb_find_text`
  2023-06-05 19:17 [PATCH xtables-addons 0/8] xt_ipp2p: support for non-linear packets Jeremy Sowden
                   ` (5 preceding siblings ...)
  2023-06-05 19:17 ` [PATCH xtables-addons 6/8] xt_ipp2p: use textsearch API for substring searching Jeremy Sowden
@ 2023-06-05 19:17 ` Jeremy Sowden
  2023-06-05 19:17 ` [PATCH xtables-addons 8/8] xt_ipp2p: drop requirement that skb is linear Jeremy Sowden
  7 siblings, 0 replies; 11+ messages in thread
From: Jeremy Sowden @ 2023-06-05 19:17 UTC (permalink / raw)
  To: Netfilter Devel

Use `skb_header_pointer` to copy byte-ranges for matching and
`skb_find_text` for substring searches.  Doing so allows the module to
work with non-linear skbs.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 extensions/xt_ipp2p.c | 487 ++++++++++++++++++++++++++++++++----------
 1 file changed, 372 insertions(+), 115 deletions(-)

diff --git a/extensions/xt_ipp2p.c b/extensions/xt_ipp2p.c
index 1378701605c3..def2d1ffc7bf 100644
--- a/extensions/xt_ipp2p.c
+++ b/extensions/xt_ipp2p.c
@@ -1,5 +1,6 @@
 #include <linux/gfp.h>
 #include <linux/module.h>
+#include <linux/skbuff.h>
 #include <linux/textsearch.h>
 #include <linux/version.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
@@ -38,7 +39,9 @@ ipv6_transport_len(const struct sk_buff *skb)
 struct ipp2p_result_printer {
 	const union nf_inet_addr *saddr, *daddr;
 	short sport, dport;
-	void (*print)(const union nf_inet_addr *, short, const union nf_inet_addr *, short, bool, unsigned int);
+	void (*print)(const union nf_inet_addr *, short,
+		      const union nf_inet_addr *, short,
+		      bool, unsigned int);
 };
 
 static bool iscrlf(const unsigned char *str)
@@ -57,12 +60,23 @@ print_result(const struct ipp2p_result_printer *rp, bool result,
 
 /* Search for UDP eDonkey/eMule/Kad commands */
 static unsigned int
-udp_search_edk(const unsigned char *t, const unsigned int packet_len,
+udp_search_edk(const struct sk_buff *skb,
+	       const unsigned int packet_off,
+	       const unsigned int packet_len,
 	       const struct ipt_p2p_info *info)
 {
+	unsigned char buf[36], *t;
+
 	if (packet_len < 4)
 		return 0;
 
+	t = skb_header_pointer(skb, packet_off,
+			       packet_len < sizeof(buf) ?
+			       packet_len : sizeof(buf),
+			       buf);
+	if (t == NULL)
+		return 0;
+
 	switch (t[0]) {
 	case 0xe3:
 		/* edonkey */
@@ -176,9 +190,20 @@ udp_search_edk(const unsigned char *t, const unsigned int packet_len,
 
 /* Search for UDP Gnutella commands */
 static unsigned int
-udp_search_gnu(const unsigned char *t, const unsigned int packet_len,
+udp_search_gnu(const struct sk_buff *skb,
+	       const unsigned int packet_off,
+	       const unsigned int packet_len,
 	       const struct ipt_p2p_info *info)
 {
+	unsigned char buf[9], *t;
+
+	t = skb_header_pointer(skb, packet_off,
+			       packet_len < sizeof(buf) ?
+			       packet_len : sizeof(buf),
+			       buf);
+	if (t == NULL)
+		return 0;
+
 	if (packet_len >= 3 && memcmp(t, "GND", 3) == 0)
 		return IPP2P_GNU * 100 + 51;
 	if (packet_len >= 9 && memcmp(t, "GNUTELLA ", 9) == 0)
@@ -188,39 +213,73 @@ udp_search_gnu(const unsigned char *t, const unsigned int packet_len,
 
 /* Search for UDP KaZaA commands */
 static unsigned int
-udp_search_kazaa(const unsigned char *t, const unsigned int packet_len,
+udp_search_kazaa(const struct sk_buff *skb,
+		 const unsigned int packet_off,
+		 const unsigned int packet_len,
 		 const struct ipt_p2p_info *info)
 {
+	unsigned char buf[6], *t;
+
 	if (packet_len < 6)
 		return 0;
-	if (memcmp(t + packet_len - 6, "KaZaA\x00", 6) == 0)
+
+	t = skb_header_pointer(skb, packet_off + packet_len - 6, 6, buf);
+	if (t == NULL)
+		return 0;
+
+	if (memcmp(t, "KaZaA\x00", 6) == 0)
 		return IPP2P_KAZAA * 100 + 50;
 	return 0;
 }
 
 /* Search for UDP DirectConnect commands */
 static unsigned int
-udp_search_directconnect(const unsigned char *t, const unsigned int packet_len,
+udp_search_directconnect(const struct sk_buff *skb,
+			 const unsigned int packet_off,
+			 const unsigned int packet_len,
 			 const struct ipt_p2p_info *info)
 {
+	unsigned char hbuf[6], *head, tbuf, *tail;
+
 	if (packet_len < 5)
 		return 0;
-	if (t[0] != 0x24)
+
+	head = skb_header_pointer(skb, packet_off, packet_len < 7 ? 4 : 6,
+				  hbuf);
+	if (head == NULL)
 		return 0;
-	if (t[packet_len-1] != 0x7c)
+
+	tail = skb_header_pointer(skb, packet_off + packet_len - 1, 1, &tbuf);
+	if (tail == NULL)
 		return 0;
-	if (memcmp(&t[1], "SR ", 3) == 0)
+
+	if (head[0] != 0x24)
+		return 0;
+	if (tail[0] != 0x7c)
+		return 0;
+	if (memcmp(&head[1], "SR ", 3) == 0)
 		return IPP2P_DC * 100 + 60;
-	if (packet_len >= 7 && memcmp(&t[1], "Ping ", 5) == 0)
+	if (packet_len >= 7 && memcmp(&head[1], "Ping ", 5) == 0)
 		return IPP2P_DC * 100 + 61;
 	return 0;
 }
 
 /* Search for UDP BitTorrent commands */
 static unsigned int
-udp_search_bit(const unsigned char *haystack, const unsigned int packet_len,
+udp_search_bit(const struct sk_buff *skb,
+	       const unsigned int packet_off,
+	       const unsigned int packet_len,
 	       const struct ipt_p2p_info *info)
 {
+	unsigned char buf[32], *haystack;
+
+	haystack = skb_header_pointer(skb, packet_off,
+				      packet_len < sizeof(buf) ?
+				      packet_len : sizeof(buf),
+				      buf);
+	if (haystack == NULL)
+		return 0;
+
 	switch (packet_len) {
 	case 16:
 		/* ^ 00 00 04 17 27 10 19 80 */
@@ -305,11 +364,22 @@ udp_search_bit(const unsigned char *haystack, const unsigned int packet_len,
 
 /* Search for Ares commands */
 static unsigned int
-search_ares(const unsigned char *payload, const unsigned int plen,
+search_ares(const struct sk_buff *skb,
+	    const unsigned int poff,
+	    const unsigned int plen,
 	    const struct ipt_p2p_info *info)
 {
+	unsigned char buf[60], *payload;
+
 	if (plen < 3)
 		return 0;
+
+	payload = skb_header_pointer(skb, poff,
+				     plen < sizeof(buf) ? plen : sizeof(buf),
+				     buf);
+	if (payload == NULL)
+		return 0;
+
 	/* all ares packets start with  */
 	if (payload[1] == 0 && plen - payload[0] == 3) {
 		switch (payload[2]) {
@@ -358,11 +428,22 @@ search_ares(const unsigned char *payload, const unsigned int plen,
 
 /* Search for SoulSeek commands */
 static unsigned int
-search_soul(const unsigned char *payload, const unsigned int plen,
+search_soul(const struct sk_buff *skb,
+	    const unsigned int poff,
+	    const unsigned int plen,
 	    const struct ipt_p2p_info *info)
 {
+	unsigned char buf[16], *payload;
+
 	if (plen < 8)
 		return 0;
+
+	payload = skb_header_pointer(skb, poff,
+				     plen < sizeof(buf) ? plen : sizeof(buf),
+				     buf);
+	if (payload == NULL)
+		return 0;
+
 	/* match: xx xx xx xx | xx = sizeof(payload) - 4 */
 	if (get_u32(payload, 0) == plen - 4) {
 		const uint32_t m = get_u32(payload, 4);
@@ -461,12 +542,20 @@ search_soul(const unsigned char *payload, const unsigned int plen,
 	if (get_u32(payload, 0) == 0x14 && get_u8(payload, 4) == 0x01) {
 		uint32_t y = get_u32(payload, 5);
 		const unsigned char *w;
+		unsigned int off, len;
 
 		/* we need 19 chars + string */
 		if (plen < y + 19)
 			return 0;
 
-		w = payload + 9 + y;
+		off = poff + y + 9;
+		len = plen - y + 9;
+
+		w = skb_header_pointer(skb, off,
+				       len < sizeof(buf) ? len : sizeof(buf),
+				       buf);
+		if (w == NULL)
+			return 0;
 
 		if (get_u32(w, 0) == 0x01 &&
 		    (get_u16(w, 4) == 0x4600 ||
@@ -483,10 +572,19 @@ search_soul(const unsigned char *payload, const unsigned int plen,
 
 /* Search for WinMX commands */
 static unsigned int
-search_winmx(const unsigned char *payload, const unsigned int plen,
+search_winmx(const struct sk_buff *skb,
+	     const unsigned int poff,
+	     const unsigned int plen,
 	     const struct ipt_p2p_info *info)
 {
-	uint16_t start;
+	unsigned char buf[149], *payload;
+	uint16_t start = poff;
+
+	payload = skb_header_pointer(skb, poff,
+				     plen < sizeof(buf) ? plen : sizeof(buf),
+				     buf);
+	if (payload == NULL)
+		return 0;
 
 	if (plen == 4 && memcmp(payload, "SEND", 4) == 0)
 		return IPP2P_WINMX * 100 + 1;
@@ -500,23 +598,18 @@ search_winmx(const unsigned char *payload, const unsigned int plen,
 		return 0;
 
 	if (memcmp(payload, "SEND", 4) == 0)
-		start = 4;
+		start += 4;
 	else if (memcmp(payload, "GET", 3) == 0)
-		start = 3;
-	else
-		start = 0;
+		start += 3;
 
-	if (start) {
+	if (start > poff) {
 		uint8_t count = 0;
 
 		do {
-			struct ts_state state;
 			unsigned int pos;
 
-			pos = textsearch_find_continuous(info->ts_conf_winmx,
-							 &state,
-							 &payload[start],
-							 plen - start);
+			pos = skb_find_text((struct sk_buff *)skb, start,
+					    skb->len, info->ts_conf_winmx);
 			if (pos == UINT_MAX)
 				break;
 
@@ -525,7 +618,7 @@ search_winmx(const unsigned char *payload, const unsigned int plen,
 				return IPP2P_WINMX * 100 + 3;
 
 			start = pos + 2;
-		} while (start < plen);
+		} while (start < skb->len);
 	}
 
 	if (plen == 149 && payload[0] == '8') {
@@ -553,11 +646,22 @@ search_winmx(const unsigned char *payload, const unsigned int plen,
 
 /* Search for appleJuice commands */
 static unsigned int
-search_apple(const unsigned char *payload, const unsigned int plen,
+search_apple(const struct sk_buff *skb,
+	     const unsigned int poff,
+	     const unsigned int plen,
 	     const struct ipt_p2p_info *info)
 {
+	unsigned char buf[8], *payload;
+
 	if (plen < 8)
 		return 0;
+
+	payload = skb_header_pointer(skb, poff,
+				     plen < sizeof(buf) ? plen : sizeof(buf),
+				     buf);
+	if (payload == NULL)
+		return 0;
+
 	if (memcmp(payload, "ajprot\r\n", 8) == 0)
 		return IPP2P_APPLE * 100;
 	return 0;
@@ -565,12 +669,20 @@ search_apple(const unsigned char *payload, const unsigned int plen,
 
 /* Search for BitTorrent commands */
 static unsigned int
-search_bittorrent(const unsigned char *payload, const unsigned int plen,
+search_bittorrent(const struct sk_buff *skb,
+		  const unsigned int poff,
+		  const unsigned int plen,
 		  const struct ipt_p2p_info *info)
 {
-	struct ts_state state;
+	unsigned char buf[20], *payload;
 	unsigned int pos;
 
+	payload = skb_header_pointer(skb, poff,
+				     plen < sizeof(buf) ? plen : sizeof(buf),
+				     buf);
+	if (payload == NULL)
+		return 0;
+
 	/*
 	 * bitcomet encrypts the first packet, so we have to detect another one
 	 * later in the flow.
@@ -598,18 +710,18 @@ search_bittorrent(const unsigned char *payload, const unsigned int plen,
 	if (memcmp(payload, "GET /", 5) != 0)
 		return 0;
 
-	pos = textsearch_find_continuous(info->ts_conf_bt_info_hash,
-					 &state, &payload[5], plen - 5);
+	pos = skb_find_text((struct sk_buff *)skb, poff + 5, skb->len,
+			    info->ts_conf_bt_info_hash);
 	if (pos != UINT_MAX)
 		return IPP2P_BIT * 100 + 1;
 
-	pos = textsearch_find_continuous(info->ts_conf_bt_peer_id,
-					 &state, &payload[5], plen - 5);
+	pos = skb_find_text((struct sk_buff *)skb, poff + 5, skb->len,
+			    info->ts_conf_bt_peer_id);
 	if (pos != UINT_MAX)
 		return IPP2P_BIT * 100 + 2;
 
-	pos = textsearch_find_continuous(info->ts_conf_bt_passkey,
-					 &state, &payload[5], plen - 5);
+	pos = skb_find_text((struct sk_buff *)skb, poff + 5, skb->len,
+			    info->ts_conf_bt_passkey);
 	if (pos != UINT_MAX)
 		return IPP2P_BIT * 100 + 4;
 
@@ -618,13 +730,25 @@ search_bittorrent(const unsigned char *payload, const unsigned int plen,
 
 /* check for Kazaa get command */
 static unsigned int
-search_kazaa(const unsigned char *payload, const unsigned int plen,
+search_kazaa(const struct sk_buff *skb,
+	     const unsigned int poff,
+	     const unsigned int plen,
 	     const struct ipt_p2p_info *info)
 {
+	unsigned char hbuf[11], *head, tbuf[2], *tail;
+
 	if (plen < 13)
 		return 0;
-	if (iscrlf(&payload[plen - 2]) &&
-	    memcmp(payload, "GET /.hash=", 11) == 0)
+
+	head = skb_header_pointer(skb, poff, 11, hbuf);
+	if (head == NULL)
+		return 0;
+
+	tail = skb_header_pointer(skb, poff + plen - 2, 2, tbuf);
+	if (tail == NULL)
+		return 0;
+
+	if (iscrlf(tail) && memcmp(head, "GET /.hash=", 11) == 0)
 		return IPP2P_DATA_KAZAA * 100;
 
 	return 0;
@@ -632,54 +756,87 @@ search_kazaa(const unsigned char *payload, const unsigned int plen,
 
 /* check for gnutella get command */
 static unsigned int
-search_gnu(const unsigned char *payload, const unsigned int plen,
+search_gnu(const struct sk_buff *skb,
+	   const unsigned int poff,
+	   const unsigned int plen,
 	   const struct ipt_p2p_info *info)
 {
+	unsigned char hbuf[15], *head, tbuf[2], *tail;
+
 	if (plen < 11)
 		return 0;
-	if (!iscrlf(&payload[plen - 2]))
+
+	head = skb_header_pointer(skb, poff,
+				  plen - 2 < sizeof(hbuf) ?
+				  plen - 2 : sizeof(hbuf),
+				  hbuf);
+	if (head == NULL)
+		return 0;
+
+	tail = skb_header_pointer(skb, poff + plen - 2, 2, tbuf);
+	if (tail == NULL)
+		return 0;
+
+	if (!iscrlf(tail))
 		return 0;
-	if (memcmp(payload, "GET /get/", 9) == 0)
+	if (memcmp(head, "GET /get/", 9) == 0)
 		return IPP2P_DATA_GNU * 100 + 1;
-	if (plen >= 15 && memcmp(payload, "GET /uri-res/", 13) == 0)
+	if (plen >= 15 && memcmp(head, "GET /uri-res/", 13) == 0)
 		return IPP2P_DATA_GNU * 100 + 2;
 	return 0;
 }
 
 /* check for gnutella get commands and other typical data */
 static unsigned int
-search_all_gnu(const unsigned char *payload, const unsigned int plen,
+search_all_gnu(const struct sk_buff *skb,
+	       const unsigned int poff,
+	       const unsigned int plen,
 	       const struct ipt_p2p_info *info)
 {
-	struct ts_state state;
-	unsigned int c, pos;
+	unsigned char hbuf[17], *head, tbuf[2], *tail;
+	unsigned int off, pos;
 
 	if (plen < 11)
 		return 0;
-	if (!iscrlf(&payload[plen - 2]))
+
+	head = skb_header_pointer(skb, poff,
+				  plen - 2 < sizeof(hbuf) ?
+				  plen - 2 : sizeof(hbuf),
+				  hbuf);
+	if (head == NULL)
+		return 0;
+
+	tail = skb_header_pointer(skb, poff + plen - 2, 2, tbuf);
+	if (tail == NULL)
 		return 0;
-	if (plen >= 19 && memcmp(payload, "GNUTELLA CONNECT/", 17) == 0)
+
+	if (!iscrlf(tail))
+		return 0;
+
+	if (plen >= 19 && memcmp(head, "GNUTELLA CONNECT/", 17) == 0)
 		return IPP2P_GNU * 100 + 1;
-	if (memcmp(payload, "GNUTELLA/", 9) == 0)
+
+	if (memcmp(head, "GNUTELLA/", 9) == 0)
 		return IPP2P_GNU * 100 + 2;
 
 	if (plen < 22)
 		return 0;
 
-	if (memcmp(payload, "GET /get/", 9) == 0)
-		c = 9;
-	else if (memcmp(payload, "GET /uri-res/", 13) == 0)
-		c = 13;
+	if (memcmp(head, "GET /get/", 9) == 0)
+		off = 9;
+	else if (memcmp(head, "GET /uri-res/", 13) == 0)
+		off = 13;
 	else
 		return 0;
 
-	pos = textsearch_find_continuous(info->ts_conf_gnu_x_gnutella,
-					 &state, &payload[c], plen - c);
+	pos = skb_find_text((struct sk_buff *)skb, poff + off, skb->len,
+			    info->ts_conf_gnu_x_gnutella);
 	if (pos != UINT_MAX)
 		return IPP2P_GNU * 100 + 3;
 
-	pos = textsearch_find_continuous(info->ts_conf_gnu_x_queue,
-					 &state, &payload[c], plen - c);
+	pos = skb_find_text((struct sk_buff *)skb, poff + off, skb->len,
+			    info->ts_conf_gnu_x_queue);
+
 	if (pos != UINT_MAX)
 		return IPP2P_GNU * 100 + 3;
 
@@ -689,36 +846,46 @@ search_all_gnu(const unsigned char *payload, const unsigned int plen,
 /* check for KaZaA download commands and other typical data */
 /* plen is guaranteed to be >= 5 (see @matchlist) */
 static unsigned int
-search_all_kazaa(const unsigned char *payload, const unsigned int plen,
+search_all_kazaa(const struct sk_buff *skb,
+		 const unsigned int poff,
+		 const unsigned int plen,
 		 const struct ipt_p2p_info *info)
 {
-	struct ts_state state;
+	unsigned char hbuf[5], *head, tbuf[2], *tail;
 	unsigned int pos;
 
 	if (plen < 7)
 		/* too short for anything we test for - early bailout */
 		return 0;
 
-	if (!iscrlf(&payload[plen - 2]))
+	head = skb_header_pointer(skb, poff, sizeof(hbuf), hbuf);
+	if (head == NULL)
+		return 0;
+
+	tail = skb_header_pointer(skb, poff + plen - 2, 2, tbuf);
+	if (tail == NULL)
 		return 0;
 
-	if (memcmp(payload, "GIVE ", 5) == 0)
+	if (!iscrlf(tail))
+		return 0;
+
+	if (memcmp(head, "GIVE ", 5) == 0)
 		return IPP2P_KAZAA * 100 + 1;
 
-	if (memcmp(payload, "GET /", 5) != 0)
+	if (memcmp(head, "GET /", 5) != 0)
 		return 0;
 
 	if (plen < 18)
 		/* The next tests would not succeed anyhow. */
 		return 0;
 
-	pos = textsearch_find_continuous(info->ts_conf_kz_x_kazaa_username,
-					 &state, &payload[5], plen - 5);
+	pos = skb_find_text((struct sk_buff *)skb, poff + 5, skb->len,
+			    info->ts_conf_kz_x_kazaa_username);
 	if (pos != UINT_MAX)
 		return IPP2P_KAZAA * 100 + 2;
 
-	pos = textsearch_find_continuous(info->ts_conf_kz_user_agent,
-					 &state, &payload[5], plen - 5);
+	pos = skb_find_text((struct sk_buff *)skb, poff + 5, skb->len,
+			    info->ts_conf_kz_user_agent);
 	if (pos != UINT_MAX)
 		return IPP2P_KAZAA * 100 + 2;
 
@@ -727,11 +894,20 @@ search_all_kazaa(const unsigned char *payload, const unsigned int plen,
 
 /* fast check for edonkey file segment transfer command */
 static unsigned int
-search_edk(const unsigned char *payload, const unsigned int plen,
+search_edk(const struct sk_buff *skb,
+	   const unsigned int poff,
+	   const unsigned int plen,
 	   const struct ipt_p2p_info *info)
 {
+	unsigned char buf[6], *payload;
+
 	if (plen < 6)
 		return 0;
+
+	payload = skb_header_pointer(skb, poff, sizeof(buf), buf);
+	if (payload == NULL)
+		return 0;
+
 	if (payload[0] != 0xe3)
 		return 0;
 	if (payload[5] == 0x47)
@@ -741,13 +917,21 @@ search_edk(const unsigned char *payload, const unsigned int plen,
 
 /* intensive but slower search for some edonkey packets including size-check */
 static unsigned int
-search_all_edk(const unsigned char *payload, const unsigned int plen,
+search_all_edk(const struct sk_buff *skb,
+	       const unsigned int poff,
+	       const unsigned int plen,
 	       const struct ipt_p2p_info *info)
 {
+	unsigned char buf[6], *payload;
 	unsigned int cmd;
 
 	if (plen < 6)
 		return 0;
+
+	payload = skb_header_pointer(skb, poff, sizeof(buf), buf);
+	if (payload == NULL)
+		return 0;
+
 	if (payload[0] != 0xe3)
 		return 0;
 
@@ -768,11 +952,20 @@ search_all_edk(const unsigned char *payload, const unsigned int plen,
 
 /* fast check for Direct Connect send command */
 static unsigned int
-search_dc(const unsigned char *payload, const unsigned int plen,
+search_dc(const struct sk_buff *skb,
+	  const unsigned int poff,
+	  const unsigned int plen,
 	  const struct ipt_p2p_info *info)
 {
+	unsigned char buf[6], *payload;
+
 	if (plen < 6)
 		return 0;
+
+	payload = skb_header_pointer(skb, poff, sizeof(buf), buf);
+	if (payload == NULL)
+		return 0;
+
 	if (payload[0] != 0x24)
 		return 0;
 	if (memcmp(&payload[1], "Send|", 5) == 0)
@@ -782,21 +975,35 @@ search_dc(const unsigned char *payload, const unsigned int plen,
 
 /* intensive but slower check for all direct connect packets */
 static unsigned int
-search_all_dc(const unsigned char *payload, const unsigned int plen,
+search_all_dc(const struct sk_buff *skb,
+	      const unsigned int poff,
+	      const unsigned int plen,
 	      const struct ipt_p2p_info *info)
 {
+	unsigned char hbuf[8], *head, tbuf, *tail;
 	const unsigned char *t;
 
 	if (plen < 7)
 		return 0;
 
-	if (payload[0] != 0x24)
+	head = skb_header_pointer(skb, poff,
+				  plen - 1 < sizeof(hbuf) ?
+				  plen - 1 : sizeof(hbuf),
+				  hbuf);
+	if (head == NULL)
 		return 0;
 
-	if (payload[plen-1] != 0x7c)
+	tail = skb_header_pointer(skb, poff + plen - 1, 1, &tbuf);
+	if (tail == NULL)
 		return 0;
 
-	t = &payload[1];
+	if (head[0] != 0x24)
+		return 0;
+
+	if (tail[0] != 0x7c)
+		return 0;
+
+	t = &head[1];
 
 	/* Client-Hub-Protocol */
 	if (memcmp(t, "Lock ", 5) == 0)
@@ -814,18 +1021,21 @@ search_all_dc(const unsigned char *payload, const unsigned int plen,
 
 /* check for mute */
 static unsigned int
-search_mute(const unsigned char *payload, const unsigned int plen,
+search_mute(const struct sk_buff *skb,
+	    const unsigned int poff,
+	    const unsigned int plen,
 	    const struct ipt_p2p_info *info)
 {
 	if (plen == 209 || plen == 345 || plen == 473 || plen == 609 ||
 	    plen == 1121) {
-		//printk(KERN_DEBUG "size hit: %u", size);
+		unsigned char buf[11], *payload;
+
+		payload = skb_header_pointer(skb, poff, sizeof(buf), buf);
+		if (payload == NULL)
+			return 0;
+
 		if (memcmp(payload,"PublicKey: ", 11) == 0) {
 			return IPP2P_MUTE * 100 + 0;
-			/*
-			if (memcmp(t + size - 14, "\x0aEndPublicKey\x0a", 14) == 0)
-				printk(KERN_DEBUG "end pubic key hit: %u", size);
-			*/
 		}
 	}
 	return 0;
@@ -833,22 +1043,35 @@ search_mute(const unsigned char *payload, const unsigned int plen,
 
 /* check for xdcc */
 static unsigned int
-search_xdcc(const unsigned char *payload, const unsigned int plen,
+search_xdcc(const struct sk_buff *skb,
+	    const unsigned int poff,
+	    const unsigned int plen,
 	    const struct ipt_p2p_info *info)
 {
-	struct ts_state state;
+	unsigned char hbuf[8], *head, tbuf[2], *tail;
 	unsigned int pos;
 
 	/* search in small packets only */
 	if (plen <= 20 || plen >= 200)
 		return 0;
 
-	if (memcmp(payload, "PRIVMSG ", 8) != 0 || !iscrlf(&payload[plen - 2]))
+	head = skb_header_pointer(skb, poff,
+				  plen - 2 < sizeof(hbuf) ?
+				  plen - 2 : sizeof(hbuf),
+				  hbuf);
+	if (head == NULL)
+		return 0;
+
+	tail = skb_header_pointer(skb, poff + plen - 2, 2, &tbuf);
+	if (tail == NULL)
+		return 0;
+
+	if (memcmp(head, "PRIVMSG ", 8) != 0 || !iscrlf(tail))
 		return 0;
 
 	/* seems to be a irc private massage, check for xdcc command */
-	pos = textsearch_find_continuous(info->ts_conf_xdcc,
-					 &state, &payload[8], plen - 8);
+	pos = skb_find_text((struct sk_buff *)skb, poff + 8, skb->len,
+			    info->ts_conf_xdcc);
 	if (pos != UINT_MAX)
 		return IPP2P_XDCC * 100 + 0;
 
@@ -857,10 +1080,23 @@ search_xdcc(const unsigned char *payload, const unsigned int plen,
 
 /* search for waste */
 static unsigned int
-search_waste(const unsigned char *payload, const unsigned int plen,
+search_waste(const struct sk_buff *skb,
+	     const unsigned int poff,
+	     const unsigned int plen,
 	     const struct ipt_p2p_info *info)
 {
-	if (plen >= 9 && memcmp(payload, "GET.sha1:", 9) == 0)
+	unsigned char buf[9], *payload;
+
+	if (plen < 9)
+		return 0;
+
+	payload = skb_header_pointer(skb, poff,
+				     plen < sizeof(buf) ? plen : sizeof(buf),
+				     buf);
+	if (payload == NULL)
+		return 0;
+
+	if (memcmp(payload, "GET.sha1:", 9) == 0)
 		return IPP2P_WASTE * 100 + 0;
 
 	return 0;
@@ -869,7 +1105,9 @@ search_waste(const unsigned char *payload, const unsigned int plen,
 static const struct {
 	unsigned int command;
 	unsigned int packet_len;
-	unsigned int (*function_name)(const unsigned char *, const unsigned int,
+	unsigned int (*function_name)(const struct sk_buff *,
+				      const unsigned int,
+				      const unsigned int,
 				      const struct ipt_p2p_info *);
 } matchlist[] = {
 	{IPP2P_EDK,         20, search_all_edk},
@@ -894,7 +1132,9 @@ static const struct {
 static const struct {
 	unsigned int command;
 	unsigned int packet_len;
-	unsigned int (*function_name)(const unsigned char *, const unsigned int,
+	unsigned int (*function_name)(const struct sk_buff *,
+				      const unsigned int,
+				      const unsigned int,
 				      const struct ipt_p2p_info *);
 } udp_list[] = {
 	{IPP2P_KAZAA, 14, udp_search_kazaa},
@@ -925,8 +1165,9 @@ ipp2p_print_result_tcp6(const union nf_inet_addr *saddr, short sport,
 
 static bool
 ipp2p_mt_tcp(const struct ipt_p2p_info *info, const struct tcphdr *tcph,
-             const unsigned char *haystack, unsigned int hlen,
-             const struct ipp2p_result_printer *rp)
+	     const struct sk_buff *skb, unsigned int packet_off,
+	     unsigned int packet_len,
+	     const struct ipp2p_result_printer *rp)
 {
 	size_t tcph_len = tcph->doff * 4;
 	int i;
@@ -935,25 +1176,26 @@ ipp2p_mt_tcp(const struct ipt_p2p_info *info, const struct tcphdr *tcph,
 	if (tcph->syn) return 0;  /* if SYN bit is set bail out */
 	if (tcph->rst) return 0;  /* if RST bit is set bail out */
 
-	if (hlen < tcph_len) {
+	if (packet_len < tcph_len) {
 		if (info->debug)
 			pr_info("TCP header indicated packet larger than it is\n");
 		return 0;
 	}
-	if (hlen == tcph_len)
+	if (packet_len == tcph_len)
 		return 0;
 
-	haystack += tcph_len;
-	hlen     -= tcph_len;
+	packet_off += tcph_len;
+	packet_len -= tcph_len;
 
 	for (i = 0; matchlist[i].command; ++i) {
 		if ((info->cmd & matchlist[i].command) != matchlist[i].command)
 			continue;
-		if (hlen <= matchlist[i].packet_len)
+		if (packet_len <= matchlist[i].packet_len)
 			continue;
-		if (matchlist[i].function_name(haystack, hlen, info)) {
+		if (matchlist[i].function_name(skb, packet_off, packet_len,
+					       info)) {
 			if (info->debug)
-				print_result(rp, true, hlen);
+				print_result(rp, true, packet_len);
 			return true;
 		}
 	}
@@ -980,31 +1222,33 @@ ipp2p_print_result_udp6(const union nf_inet_addr *saddr, short sport,
 
 static bool
 ipp2p_mt_udp(const struct ipt_p2p_info *info, const struct udphdr *udph,
-             const unsigned char *haystack, unsigned int hlen,
-             const struct ipp2p_result_printer *rp)
+	     const struct sk_buff *skb, unsigned int packet_off,
+	     unsigned int packet_len,
+	     const struct ipp2p_result_printer *rp)
 {
 	size_t udph_len = sizeof(*udph);
 	int i;
 
-	if (hlen < udph_len) {
+	if (packet_len < udph_len) {
 		if (info->debug)
 			pr_info("UDP header indicated packet larger than it is\n");
 		return 0;
 	}
-	if (hlen == udph_len)
+	if (packet_len == udph_len)
 		return 0;
 
-	haystack += udph_len;
-	hlen     -= udph_len;
+	packet_off += udph_len;
+	packet_len -= udph_len;
 
 	for (i = 0; udp_list[i].command; ++i) {
 		if ((info->cmd & udp_list[i].command) != udp_list[i].command)
 			continue;
-		if (hlen <= udp_list[i].packet_len)
+		if (packet_len <= udp_list[i].packet_len)
 			continue;
-		if (udp_list[i].function_name(haystack, hlen, info)) {
+		if (udp_list[i].function_name(skb, packet_off, packet_len,
+					      info)) {
 			if (info->debug)
-				print_result(rp, true, hlen);
+				print_result(rp, true, packet_len);
 			return true;
 		}
 	}
@@ -1017,9 +1261,8 @@ ipp2p_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	const struct ipt_p2p_info *info = par->matchinfo;
 	struct ipp2p_result_printer printer;
 	union nf_inet_addr saddr, daddr;
-	const unsigned char *haystack;  /* packet data */
-	unsigned int hlen;              /* packet data length */
 	uint8_t family = xt_family(par);
+	unsigned int packet_len;
 	int protocol;
 
 	/*
@@ -1044,10 +1287,11 @@ ipp2p_mt(const struct sk_buff *skb, struct xt_action_param *par)
 
 	if (family == NFPROTO_IPV4) {
 		const struct iphdr *ip = ip_hdr(skb);
+
 		saddr.ip = ip->saddr;
 		daddr.ip = ip->daddr;
 		protocol = ip->protocol;
-		hlen = ip_transport_len(skb);
+		packet_len = ip_transport_len(skb);
 	} else {
 		const struct ipv6hdr *ip = ipv6_hdr(skb);
 		int thoff = 0;
@@ -1057,34 +1301,47 @@ ipp2p_mt(const struct sk_buff *skb, struct xt_action_param *par)
 		protocol = ipv6_find_hdr(skb, &thoff, -1, NULL, NULL);
 		if (protocol < 0)
 			return 0;
-		hlen = ipv6_transport_len(skb);
+		packet_len = ipv6_transport_len(skb);
 	}
 
 	printer.saddr = &saddr;
 	printer.daddr = &daddr;
-	haystack = skb_transport_header(skb);
 
 	switch (protocol) {
 	case IPPROTO_TCP:	/* what to do with a TCP packet */
 	{
-		const struct tcphdr *tcph = tcp_hdr(skb);
+		const struct tcphdr *tcph;
+		struct tcphdr _tcph;
+
+		tcph = skb_header_pointer(skb, par->thoff, sizeof(_tcph), &_tcph);
+		if (tcph == NULL)
+			return 0;
 
 		printer.sport = ntohs(tcph->source);
 		printer.dport = ntohs(tcph->dest);
 		printer.print = family == NFPROTO_IPV6 ?
 		                ipp2p_print_result_tcp6 : ipp2p_print_result_tcp4;
-		return ipp2p_mt_tcp(info, tcph, haystack, hlen, &printer);
+
+		return ipp2p_mt_tcp(info, tcph, skb, par->thoff, packet_len,
+				    &printer);
 	}
 	case IPPROTO_UDP:	/* what to do with a UDP packet */
 	case IPPROTO_UDPLITE:
 	{
-		const struct udphdr *udph = udp_hdr(skb);
+		const struct udphdr *udph;
+		struct udphdr _udph;
+
+		udph = skb_header_pointer(skb, par->thoff, sizeof(_udph), &_udph);
+		if (udph == NULL)
+			return 0;
 
 		printer.sport = ntohs(udph->source);
 		printer.dport = ntohs(udph->dest);
 		printer.print = family == NFPROTO_IPV6 ?
 		                ipp2p_print_result_udp6 : ipp2p_print_result_udp4;
-		return ipp2p_mt_udp(info, udph, haystack, hlen, &printer);
+
+		return ipp2p_mt_udp(info, udph, skb, par->thoff, packet_len,
+				    &printer);
 	}
 	default:
 		return 0;
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH xtables-addons 8/8] xt_ipp2p: drop requirement that skb is linear
  2023-06-05 19:17 [PATCH xtables-addons 0/8] xt_ipp2p: support for non-linear packets Jeremy Sowden
                   ` (6 preceding siblings ...)
  2023-06-05 19:17 ` [PATCH xtables-addons 7/8] xt_ipp2p: use `skb_header_pointer` and `skb_find_text` Jeremy Sowden
@ 2023-06-05 19:17 ` Jeremy Sowden
  7 siblings, 0 replies; 11+ messages in thread
From: Jeremy Sowden @ 2023-06-05 19:17 UTC (permalink / raw)
  To: Netfilter Devel

It is no longer necessary.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 extensions/xt_ipp2p.c | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/extensions/xt_ipp2p.c b/extensions/xt_ipp2p.c
index def2d1ffc7bf..c7712660816d 100644
--- a/extensions/xt_ipp2p.c
+++ b/extensions/xt_ipp2p.c
@@ -1278,13 +1278,6 @@ ipp2p_mt(const struct sk_buff *skb, struct xt_action_param *par)
 		return 0;
 	}
 
-	/* make sure that skb is linear */
-	if (skb_is_nonlinear(skb)) {
-		if (info->debug)
-			printk("IPP2P.match: nonlinear skb found\n");
-		return 0;
-	}
-
 	if (family == NFPROTO_IPV4) {
 		const struct iphdr *ip = ip_hdr(skb);
 
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH xtables-addons 5/8] xt_ipp2p: rearrange some conditionals and a couple of loops
  2023-06-05 19:17 ` [PATCH xtables-addons 5/8] xt_ipp2p: rearrange some conditionals and a couple of loops Jeremy Sowden
@ 2023-06-05 20:36   ` Jan Engelhardt
  2023-06-05 21:40     ` Jeremy Sowden
  0 siblings, 1 reply; 11+ messages in thread
From: Jan Engelhardt @ 2023-06-05 20:36 UTC (permalink / raw)
  To: Jeremy Sowden; +Cc: Netfilter Devel

On Monday 2023-06-05 21:17, Jeremy Sowden wrote:

>Reduce indentation and improve the readability of the code.

Applying patch extensions/xt_ipp2p.c with 3 rejects...
Hunk #1 applied cleanly.
Hunk #2 applied cleanly.
Rejected hunk #3.
Hunk #4 applied cleanly.
Hunk #5 applied cleanly.
Hunk #6 applied cleanly.
Hunk #7 applied cleanly.
Rejected hunk #8.
Hunk #9 applied cleanly.
Rejected hunk #10.
Hunk #11 applied cleanly.
Hunk #12 applied cleanly.
Hunk #13 applied cleanly.
Hunk #14 applied cleanly.
Patch failed at 0001 xt_ipp2p: rearrange some conditionals and a couple of loops
hint: Use 'git am --show-current-patch=diff' to see the failed patch

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH xtables-addons 5/8] xt_ipp2p: rearrange some conditionals and a couple of loops
  2023-06-05 20:36   ` Jan Engelhardt
@ 2023-06-05 21:40     ` Jeremy Sowden
  0 siblings, 0 replies; 11+ messages in thread
From: Jeremy Sowden @ 2023-06-05 21:40 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: Netfilter Devel

[-- Attachment #1: Type: text/plain, Size: 859 bytes --]

On 2023-06-05, at 22:36:34 +0200, Jan Engelhardt wrote:
> On Monday 2023-06-05 21:17, Jeremy Sowden wrote:
> 
> >Reduce indentation and improve the readability of the code.
> 
> Applying patch extensions/xt_ipp2p.c with 3 rejects...
> Hunk #1 applied cleanly.
> Hunk #2 applied cleanly.
> Rejected hunk #3.
> Hunk #4 applied cleanly.
> Hunk #5 applied cleanly.
> Hunk #6 applied cleanly.
> Hunk #7 applied cleanly.
> Rejected hunk #8.
> Hunk #9 applied cleanly.
> Rejected hunk #10.
> Hunk #11 applied cleanly.
> Hunk #12 applied cleanly.
> Hunk #13 applied cleanly.
> Hunk #14 applied cleanly.
> Patch failed at 0001 xt_ipp2p: rearrange some conditionals and a couple of loops
> hint: Use 'git am --show-current-patch=diff' to see the failed patch

Mea culpa.  Was working from an out-of-date branch.  Will rebase and
send v2.

J.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2023-06-05 21:40 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-05 19:17 [PATCH xtables-addons 0/8] xt_ipp2p: support for non-linear packets Jeremy Sowden
2023-06-05 19:17 ` [PATCH xtables-addons 1/8] xt_ipp2p: fix an off-by-one error Jeremy Sowden
2023-06-05 19:17 ` [PATCH xtables-addons 2/8] xt_ipp2p: fix Soulseek false-positive matches Jeremy Sowden
2023-06-05 19:17 ` [PATCH xtables-addons 3/8] xt_ipp2p: change byte-orer conversion Jeremy Sowden
2023-06-05 19:17 ` [PATCH xtables-addons 4/8] xt_ipp2p: add helper for matching "\r\n" Jeremy Sowden
2023-06-05 19:17 ` [PATCH xtables-addons 5/8] xt_ipp2p: rearrange some conditionals and a couple of loops Jeremy Sowden
2023-06-05 20:36   ` Jan Engelhardt
2023-06-05 21:40     ` Jeremy Sowden
2023-06-05 19:17 ` [PATCH xtables-addons 6/8] xt_ipp2p: use textsearch API for substring searching Jeremy Sowden
2023-06-05 19:17 ` [PATCH xtables-addons 7/8] xt_ipp2p: use `skb_header_pointer` and `skb_find_text` Jeremy Sowden
2023-06-05 19:17 ` [PATCH xtables-addons 8/8] xt_ipp2p: drop requirement that skb is linear Jeremy Sowden

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.