patch-2.4.20 linux-2.4.20/net/ipv4/netfilter/ip_nat_irc.c

Next file: linux-2.4.20/net/ipv4/netfilter/ip_nat_proto_tcp.c
Previous file: linux-2.4.20/net/ipv4/netfilter/ip_nat_helper.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.19/net/ipv4/netfilter/ip_nat_irc.c linux-2.4.20/net/ipv4/netfilter/ip_nat_irc.c
@@ -51,42 +51,29 @@
 
 /* FIXME: Time out? --RR */
 
-static int
+static unsigned int
 irc_nat_expected(struct sk_buff **pskb,
 		 unsigned int hooknum,
 		 struct ip_conntrack *ct,
-		 struct ip_nat_info *info,
-		 struct ip_conntrack *master,
-		 struct ip_nat_info *masterinfo, unsigned int *verdict)
+		 struct ip_nat_info *info)
 {
 	struct ip_nat_multi_range mr;
 	u_int32_t newdstip, newsrcip, newip;
-	struct ip_ct_irc *ircinfo;
+
+	struct ip_conntrack *master = master_ct(ct);
 
 	IP_NF_ASSERT(info);
 	IP_NF_ASSERT(master);
-	IP_NF_ASSERT(masterinfo);
 
 	IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
 
 	DEBUGP("nat_expected: We have a connection!\n");
 
-	/* Master must be an irc connection */
-	ircinfo = &master->help.ct_irc_info;
-	LOCK_BH(&ip_irc_lock);
-	if (ircinfo->is_irc != IP_CONNTR_IRC) {
-		UNLOCK_BH(&ip_irc_lock);
-		DEBUGP("nat_expected: master not irc\n");
-		return 0;
-	}
-
 	newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
 	newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
 	DEBUGP("nat_expected: DCC cmd. %u.%u.%u.%u->%u.%u.%u.%u\n",
 	       NIPQUAD(newsrcip), NIPQUAD(newdstip));
 
-	UNLOCK_BH(&ip_irc_lock);
-
 	if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
 		newip = newsrcip;
 	else
@@ -99,16 +86,14 @@
 	mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
 	mr.range[0].min_ip = mr.range[0].max_ip = newip;
 
-	*verdict = ip_nat_setup_info(ct, &mr, hooknum);
-
-	return 1;
+	return ip_nat_setup_info(ct, &mr, hooknum);
 }
 
-static int irc_data_fixup(const struct ip_ct_irc *ct_irc_info,
+static int irc_data_fixup(const struct ip_ct_irc_expect *ct_irc_info,
 			  struct ip_conntrack *ct,
-			  unsigned int datalen,
 			  struct sk_buff **pskb,
-			  enum ip_conntrack_info ctinfo)
+			  enum ip_conntrack_info ctinfo,
+			  struct ip_conntrack_expect *expect)
 {
 	u_int32_t newip;
 	struct ip_conntrack_tuple t;
@@ -121,9 +106,9 @@
 
 	MUST_BE_LOCKED(&ip_irc_lock);
 
-	DEBUGP("IRC_NAT: info (seq %u + %u) packet(seq %u + %u)\n",
-	       ct_irc_info->seq, ct_irc_info->len,
-	       ntohl(tcph->seq), datalen);
+	DEBUGP("IRC_NAT: info (seq %u + %u) in %u\n",
+	       expect->seq, ct_irc_info->len,
+	       ntohl(tcph->seq));
 
 	newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
 
@@ -133,13 +118,11 @@
 	   only set in ip_conntrack_irc, with ip_irc_lock held
 	   writable */
 
-	t = ct->expected.tuple;
+	t = expect->tuple;
 	t.dst.ip = newip;
 	for (port = ct_irc_info->port; port != 0; port++) {
 		t.dst.u.tcp.port = htons(port);
-		if (ip_conntrack_expect_related(ct, &t,
-						&ct->expected.mask,
-						NULL) == 0) {
+		if (ip_conntrack_change_expect(expect, &t) == 0) {
 			DEBUGP("using port %d", port);
 			break;
 		}
@@ -166,26 +149,28 @@
 	       buffer, NIPQUAD(newip), port);
 
 	return ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
-					ct_irc_info->seq - ntohl(tcph->seq),
+					expect->seq - ntohl(tcph->seq),
 					ct_irc_info->len, buffer, 
 					strlen(buffer));
 }
 
 static unsigned int help(struct ip_conntrack *ct,
+			 struct ip_conntrack_expect *exp,
 			 struct ip_nat_info *info,
 			 enum ip_conntrack_info ctinfo,
-			 unsigned int hooknum, struct sk_buff **pskb)
+			 unsigned int hooknum, 
+			 struct sk_buff **pskb)
 {
 	struct iphdr *iph = (*pskb)->nh.iph;
 	struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
 	unsigned int datalen;
 	int dir;
-	int score;
-	struct ip_ct_irc *ct_irc_info = &ct->help.ct_irc_info;
+	struct ip_ct_irc_expect *ct_irc_info;
 
-	/* Delete SACK_OK on initial TCP SYNs. */
-	if (tcph->syn && !tcph->ack)
-		ip_nat_delete_sack(*pskb, tcph);
+	if (!exp)
+		DEBUGP("ip_nat_irc: no exp!!");
+		
+	ct_irc_info = &exp->help.exp_irc_info;
 
 	/* Only mangle things once: original direction in POST_ROUTING
 	   and reply direction on PRE_ROUTING. */
@@ -202,55 +187,35 @@
 	DEBUGP("got beyond not touching\n");
 
 	datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
-	score = 0;
 	LOCK_BH(&ip_irc_lock);
-	if (ct_irc_info->len) {
-		DEBUGP("got beyond ct_irc_info->len\n");
-
-		/* If it's in the right range... */
-		score += between(ct_irc_info->seq, ntohl(tcph->seq),
-				 ntohl(tcph->seq) + datalen);
-		score += between(ct_irc_info->seq + ct_irc_info->len,
-				 ntohl(tcph->seq),
-				 ntohl(tcph->seq) + datalen);
-		if (score == 1) {
-			/* Half a match?  This means a partial retransmisison.
-			   It's a cracker being funky. */
-			if (net_ratelimit()) {
-				printk
-				    ("IRC_NAT: partial packet %u/%u in %u/%u\n",
-				     ct_irc_info->seq, ct_irc_info->len,
-				     ntohl(tcph->seq),
-				     ntohl(tcph->seq) + datalen);
-			}
+	/* Check wether the whole IP/address pattern is carried in the payload */
+	if (between(exp->seq + ct_irc_info->len,
+		    ntohl(tcph->seq),
+		    ntohl(tcph->seq) + datalen)) {
+		if (!irc_data_fixup(ct_irc_info, ct, pskb, ctinfo, exp)) {
 			UNLOCK_BH(&ip_irc_lock);
 			return NF_DROP;
-		} else if (score == 2) {
-			DEBUGP("IRC_NAT: score=2, calling fixup\n");
-			if (!irc_data_fixup(ct_irc_info, ct, datalen,
-					    pskb, ctinfo)) {
-				UNLOCK_BH(&ip_irc_lock);
-				return NF_DROP;
-			}
-			/* skb may have been reallocated */
-			iph = (*pskb)->nh.iph;
-			tcph = (void *) iph + iph->ihl * 4;
 		}
+	} else { 
+		/* Half a match?  This means a partial retransmisison.
+		   It's a cracker being funky. */
+		if (net_ratelimit()) {
+			printk
+			    ("IRC_NAT: partial packet %u/%u in %u/%u\n",
+			     exp->seq, ct_irc_info->len,
+			     ntohl(tcph->seq),
+			     ntohl(tcph->seq) + datalen);
+		}
+		UNLOCK_BH(&ip_irc_lock);
+		return NF_DROP;
 	}
-
 	UNLOCK_BH(&ip_irc_lock);
 
-	ip_nat_seq_adjust(*pskb, ct, ctinfo);
-
 	return NF_ACCEPT;
 }
 
 static struct ip_nat_helper ip_nat_irc_helpers[MAX_PORTS];
-static char ip_nih_names[MAX_PORTS][6];
-
-static struct ip_nat_expect irc_expect
-    = { {NULL, NULL}, irc_nat_expected };
-
+static char irc_names[MAX_PORTS][10];
 
 /* This function is intentionally _NOT_ defined as  __exit, because
  * it is needed by init() */
@@ -262,52 +227,54 @@
 		DEBUGP("ip_nat_irc: unregistering helper for port %d\n",
 		       ports[i]);
 		ip_nat_helper_unregister(&ip_nat_irc_helpers[i]);
-	}
-	ip_nat_expect_unregister(&irc_expect);
+	} 
 }
+
 static int __init init(void)
 {
-	int ret;
+	int ret = 0;
 	int i;
 	struct ip_nat_helper *hlpr;
 	char *tmpname;
 
-	ret = ip_nat_expect_register(&irc_expect);
-	if (ret == 0) {
-
-		if (ports[0] == 0) {
-			ports[0] = 6667;
-		}
+	if (ports[0] == 0) {
+		ports[0] = IRC_PORT;
+	}
 
-		for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++) {
-			hlpr = &ip_nat_irc_helpers[i];
-			memset(hlpr, 0,
-			       sizeof(struct ip_nat_helper));
-
-			hlpr->tuple.dst.protonum = IPPROTO_TCP;
-			hlpr->tuple.src.u.tcp.port = htons(ports[i]);
-			hlpr->mask.src.u.tcp.port = 0xFFFF;
-			hlpr->mask.dst.protonum = 0xFFFF;
-			hlpr->help = help;
-
-			tmpname = &ip_nih_names[i][0];
-			sprintf(tmpname, "irc%2.2d", i);
-
-			hlpr->name = tmpname;
-			DEBUGP
-			    ("ip_nat_irc: Trying to register helper for port %d: name %s\n",
-			     ports[i], hlpr->name);
-			ret = ip_nat_helper_register(hlpr);
-
-			if (ret) {
-				printk
-				    ("ip_nat_irc: error registering helper for port %d\n",
-				     ports[i]);
-				fini();
-				return 1;
-			}
-			ports_c++;
+	for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++) {
+		hlpr = &ip_nat_irc_helpers[i];
+		memset(hlpr, 0,
+		       sizeof(struct ip_nat_helper));
+
+		hlpr->tuple.dst.protonum = IPPROTO_TCP;
+		hlpr->tuple.src.u.tcp.port = htons(ports[i]);
+		hlpr->mask.src.u.tcp.port = 0xFFFF;
+		hlpr->mask.dst.protonum = 0xFFFF;
+		hlpr->help = help;
+		hlpr->flags = 0;
+		hlpr->me = THIS_MODULE;
+		hlpr->expect = irc_nat_expected;
+
+		tmpname = &irc_names[i][0];
+		if (ports[i] == IRC_PORT)
+			sprintf(tmpname, "irc");
+		else
+			sprintf(tmpname, "irc-%d", i);
+		hlpr->name = tmpname;
+
+		DEBUGP
+		    ("ip_nat_irc: Trying to register helper for port %d: name %s\n",
+		     ports[i], hlpr->name);
+		ret = ip_nat_helper_register(hlpr);
+
+		if (ret) {
+			printk
+			    ("ip_nat_irc: error registering helper for port %d\n",
+			     ports[i]);
+			fini();
+			return 1;
 		}
+		ports_c++;
 	}
 	return ret;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)