patch-pre2.0.13 linux/net/ipv4/ip_output.c

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

diff -u --recursive --new-file pre2.0.12/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
@@ -320,6 +320,44 @@
 	iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
 }
 
+
+/*
+ *	If a sender wishes the packet to remain unfreed
+ *	we add it to his send queue. This arguably belongs
+ *	in the TCP level since nobody else uses it. BUT
+ *	remember IPng might change all the rules.
+ */
+static inline void add_to_send_queue(struct sock * sk, struct sk_buff * skb)
+{
+	unsigned long flags;
+
+	/* The socket now has more outstanding blocks */
+	sk->packets_out++;
+
+	/* Protect the list for a moment */
+	save_flags(flags);
+	cli();
+
+	if (skb->link3 != NULL)
+	{
+		NETDEBUG(printk("ip.c: link3 != NULL\n"));
+		skb->link3 = NULL;
+	}
+	if (sk->send_head == NULL)
+	{
+		sk->send_tail = skb;
+		sk->send_head = skb;
+		sk->send_next = skb;
+	}
+	else
+	{
+		sk->send_tail->link3 = skb;
+		sk->send_tail = skb;
+	}
+	restore_flags(flags);
+}
+
+
 /*
  * Queues a packet to be sent, and starts the transmitter
  * if necessary.  if free = 1 then we free the block after
@@ -332,15 +370,8 @@
 void ip_queue_xmit(struct sock *sk, struct device *dev,
 	      struct sk_buff *skb, int free)
 {
+	unsigned int tot_len;
 	struct iphdr *iph;
-/*	unsigned char *ptr;*/
-
-	/* Sanity check */
-	if (dev == NULL)
-	{
-		NETDEBUG(printk("IP: ip_queue_xmit dev = NULL\n"));
-		return;
-	}
 
 	IS_SKB(skb);
 
@@ -348,7 +379,7 @@
 	 *	Do some book-keeping in the packet for later
 	 */
 
-
+	skb->sk = sk;
 	skb->dev = dev;
 	skb->when = jiffies;
 
@@ -361,32 +392,30 @@
 	 */
 
 	iph = skb->ip_hdr;
-	iph->tot_len = htons(skb->len-(((unsigned char *)iph)-skb->data));
-
-	/*
-	 *	No reassigning numbers to fragments...
-	 */
-
-	if(free!=2)
-		iph->id      = htons(ip_id_count++);
-	else
-		free=1;
+	tot_len = skb->len - (((unsigned char *)iph) - skb->data);
+	iph->tot_len = htons(tot_len);
 
-	/* All buffers without an owner socket get freed */
-	if (sk == NULL)
-		free = 1;
+	switch (free) {
+		/* No reassigning numbers to fragments... */
+		default:
+			free = 1;
+			break;
+		case 0:
+			add_to_send_queue(sk, skb);
+			/* fall through */
+		case 1:
+			iph->id = htons(ip_id_count++);
+	}
 
 	skb->free = free;
 
+	/* Sanity check */
+	if (dev == NULL)
+		goto no_device;
+
 #ifdef CONFIG_FIREWALL
-	if(call_out_firewall(PF_INET, skb->dev, iph, NULL) < FW_ACCEPT) {
-		/* just don't send this packet */
-		/* and free socket buffers ;) <[email protected]> */
-		if (free)
-		  skb->sk = sk;		/* I am not sure *this* really need, */
-		kfree_skb(skb, FREE_WRITE);	/* but *this* must be here */
-		return;
-	}
+	if (call_out_firewall(PF_INET, skb->dev, iph, NULL) < FW_ACCEPT)
+		goto out;
 #endif	
 
 	/*
@@ -395,13 +424,8 @@
 	 *	bits of it.
 	 */
 
-	if(ntohs(iph->tot_len)> dev->mtu)
-	{
-		ip_fragment(sk,skb,dev,0);
-		IS_SKB(skb);
-		kfree_skb(skb,FREE_WRITE);
-		return;
-	}
+	if (tot_len > dev->mtu)
+		goto fragment;
 
 	/*
 	 *	Add an IP checksum
@@ -410,10 +434,6 @@
 	ip_send_check(iph);
 
 	/*
-	 *	Print the frame when debugging
-	 */
-
-	/*
 	 *	More debugging. You cannot queue a packet already on a list
 	 *	Spot this and moan loudly.
 	 */
@@ -424,57 +444,14 @@
 	}
 
 	/*
-	 *	If a sender wishes the packet to remain unfreed
-	 *	we add it to his send queue. This arguably belongs
-	 *	in the TCP level since nobody else uses it. BUT
-	 *	remember IPng might change all the rules.
-	 */
-
-	if (!free)
-	{
-		unsigned long flags;
-		/* The socket now has more outstanding blocks */
-
-		sk->packets_out++;
-
-		/* Protect the list for a moment */
-		save_flags(flags);
-		cli();
-
-		if (skb->link3 != NULL)
-		{
-			NETDEBUG(printk("ip.c: link3 != NULL\n"));
-			skb->link3 = NULL;
-		}
-		if (sk->send_head == NULL)
-		{
-			sk->send_tail = skb;
-			sk->send_head = skb;
-			sk->send_next = skb;
-		}
-		else
-		{
-			sk->send_tail->link3 = skb;
-			sk->send_tail = skb;
-		}
-		/* skb->link3 is NULL */
-
-		/* Interrupt restore */
-		restore_flags(flags);
-	}
-	else
-		/* Remember who owns the buffer */
-		skb->sk = sk;
-
-	/*
 	 *	If the indicated interface is up and running, send the packet.
 	 */
 	 
 	ip_statistics.IpOutRequests++;
 #ifdef CONFIG_IP_ACCT
-	ip_fw_chk(iph,dev,NULL,ip_acct_chain,IP_FW_F_ACCEPT,IP_FW_MODE_ACCT_OUT);
+	ip_fw_chk(iph,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT);
 #endif	
-	
+
 #ifdef CONFIG_IP_MULTICAST	
 
 	/*
@@ -505,14 +482,12 @@
 		}
 		/* Multicasts with ttl 0 must not go beyond the host */
 		
-		if(skb->ip_hdr->ttl==0)
-		{
-			kfree_skb(skb, FREE_READ);
-			return;
-		}
+		if (iph->ttl==0)
+			goto out;
 	}
 #endif
-	if((dev->flags&IFF_BROADCAST) && (iph->daddr==dev->pa_brdaddr||iph->daddr==0xFFFFFFFF) && !(dev->flags&IFF_LOOPBACK))
+	if ((dev->flags & IFF_BROADCAST) && !(dev->flags & IFF_LOOPBACK)
+	    && (iph->daddr==dev->pa_brdaddr || iph->daddr==0xFFFFFFFF))
 		ip_loopback(dev,skb);
 		
 	if (dev->flags & IFF_UP)
@@ -521,24 +496,28 @@
 		 *	If we have an owner use its priority setting,
 		 *	otherwise use NORMAL
 		 */
+		int priority = SOPRI_NORMAL;
+		if (sk)
+			priority = sk->priority;
 
-		if (sk != NULL)
-		{
-			dev_queue_xmit(skb, dev, sk->priority);
-		}
-		else
-		{
-			dev_queue_xmit(skb, dev, SOPRI_NORMAL);
-		}
-	}
-	else
-	{
-		if(sk)
-			sk->err = ENETDOWN;
-		ip_statistics.IpOutDiscards++;
-		if (free)
-			kfree_skb(skb, FREE_WRITE);
+		dev_queue_xmit(skb, dev, priority);
+		return;
 	}
+	if(sk)
+		sk->err = ENETDOWN;
+	ip_statistics.IpOutDiscards++;
+out:
+	if (free)
+		kfree_skb(skb, FREE_WRITE);
+	return;
+
+no_device:
+	NETDEBUG(printk("IP: ip_queue_xmit dev = NULL\n"));
+	goto out;
+
+fragment:
+	ip_fragment(sk,skb,dev,0);
+	goto out;
 }
 
 
@@ -720,7 +699,7 @@
 		}
 #endif
 #ifdef CONFIG_IP_ACCT
-		ip_fw_chk(iph,dev,NULL,ip_acct_chain, IP_FW_F_ACCEPT,IP_FW_MODE_ACCT_OUT);
+		ip_fw_chk(iph,dev,NULL,ip_acct_chain,0,IP_FW_MODE_ACCT_OUT);
 #endif		
 		if(dev->flags&IFF_UP)
 			dev_queue_xmit(skb,dev,sk->priority);
@@ -926,7 +905,7 @@
 #endif		
 #ifdef CONFIG_IP_ACCT
 		if(!offset)
-			ip_fw_chk(iph, dev, NULL, ip_acct_chain, IP_FW_F_ACCEPT, IP_FW_MODE_ACCT_OUT);
+			ip_fw_chk(iph, dev, NULL, ip_acct_chain, 0, IP_FW_MODE_ACCT_OUT);
 #endif	
 		offset -= (maxfraglen-fragheaderlen);
 		fraglen = maxfraglen;

FUNET's LINUX-ADM group, [email protected]
TCL-scripts by Sam Shen, [email protected] with Sam's (original) version
of this