patch-2.2.0-pre9 linux/net/ipv4/ip_output.c

Next file: linux/net/ipv4/tcp_input.c
Previous file: linux/mm/vmscan.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.0-pre8/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
@@ -35,6 +35,9 @@
  *		Andi Kleen	:	Split fast and slow ip_build_xmit path 
  *					for decreased register pressure on x86 
  *					and more readibility. 
+ *		Marc Boucher	:	When call_out_firewall returns FW_QUEUE,
+ *					silently abort send instead of failing
+ *					with -EPERM.
  */
 
 #include <asm/uaccess.h>
@@ -128,8 +131,10 @@
 
 	dev = rt->u.dst.dev;
 
+#ifdef CONFIG_FIREWALL
 	if (call_out_firewall(PF_INET, dev, iph, NULL, &skb) < FW_ACCEPT)
 		goto drop;
+#endif
 
 	ip_send_check(iph);
 
@@ -137,8 +142,10 @@
 	skb->dst->output(skb);
 	return;
 
+#ifdef CONFIG_FIREWALL
 drop:
 	kfree_skb(skb);
+#endif
 }
 
 int __ip_finish_output(struct sk_buff *skb)
@@ -284,8 +291,10 @@
 
 	dev = rt->u.dst.dev;
 
+#ifdef CONFIG_FIREWALL
 	if (call_out_firewall(PF_INET, dev, iph, NULL, &skb) < FW_ACCEPT) 
 		goto drop;
+#endif
 
 	/* This can happen when the transport layer has segments queued
 	 * with a cached route, and by the time we get here things are
@@ -546,9 +555,19 @@
 		 *	Account for the fragment.
 		 */
 
-		if(!err &&
-		   call_out_firewall(PF_INET, rt->u.dst.dev, skb->nh.iph, NULL, &skb) < FW_ACCEPT)
-			err = -EPERM;
+#ifdef CONFIG_FIREWALL
+		if(!err) {
+			int fw_res;
+
+			fw_res = call_out_firewall(PF_INET, rt->u.dst.dev, skb->nh.iph, NULL, &skb);
+			if(fw_res == FW_QUEUE) {
+				kfree_skb(skb);
+				skb = NULL;
+			} else if(fw_res < FW_ACCEPT) {
+				err = -EPERM;
+			}
+		}
+#endif
 
 		if (err) { 
 			ip_statistics.IpOutDiscards++;
@@ -564,7 +583,7 @@
 		nfrags++;
 
 		err = 0; 
-		if (rt->u.dst.output(skb)) {
+		if (skb && rt->u.dst.output(skb)) {
 			err = -ENETDOWN;
 			ip_statistics.IpOutDiscards++;	
 			break;
@@ -663,8 +682,20 @@
 	if (err) 
 		err = -EFAULT;
 
-	if(!err && call_out_firewall(PF_INET, rt->u.dst.dev, iph, NULL, &skb) < FW_ACCEPT) 
-		err = -EPERM;
+#ifdef CONFIG_FIREWALL
+	if(!err) {
+		int fw_res;
+
+		fw_res = call_out_firewall(PF_INET, rt->u.dst.dev, iph, NULL, &skb);
+		if(fw_res == FW_QUEUE) {
+			/* re-queued elsewhere; silently abort this send */
+			kfree_skb(skb);
+			return 0;
+		}
+		if(fw_res < FW_ACCEPT)
+			err = -EPERM;
+	}
+#endif
 
 	if (err) { 
 		kfree_skb(skb);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov