Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2785

kernel-2.6.18-238.el5.src.rpm

From: Thomas Graf <tgraf@redhat.com>
Date: Thu, 7 Feb 2008 17:47:21 +0100
Subject: [net] ipv6: fixes to meet DoD requirements
Message-id: 20080207164721.GA11531@deb
O-Subject: [PATCH RHEL5.2] BZ431718: IPv6 bugfixes to meet DoD requirements
Bugzilla: 431718

This patch combines a series of IPv6 bugfixes required to meet the
DoD requirements. They've all been accepted upstream already.

The patches are:

5b4d383a1a562de6955cacd72e20809064ee137f
[ICMP]: ICMP_MIB_OUTMSGS increment duplicated

c964ff4ffbef4586ec63dbeb008563078114e6dc
[IPV6]: ICMP6_MIB_OUTMSGS increment duplicated

fa95c28322a312a798a688c655458ab2079b72eb
[IPV6]: RFC 2011 compatibility broken

d647b36a69bf0a630ebf981bde3c0651e2779e5e
[SNMP]: Fix SNMP counters with PREEMPT

cb75994ec311b2cd50e5205efdcc0696abd6675d
[UDP]: Defer InDataGrams increment until recvmsg() does checksum

1ac4f008857487bf45b709248d71c5b3f4cae7b5
[IPV6]: IPV6_MULTICAST_IF setting is ignored on link-local connect()

Please ACK.

diff --git a/include/net/snmp.h b/include/net/snmp.h
index 63f37f8..52f49a7 100644
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -23,6 +23,7 @@
 
 #include <linux/cache.h>
 #include <linux/snmp.h>
+#include <linux/smp.h>
 
 /*
  * Mibs are stored in array of unsigned long.
@@ -143,14 +144,26 @@ struct linux_mib {
 #define SNMP_INC_STATS_OFFSET_BH(mib, field, offset)	\
 	(per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field + (offset)]++)
 #define SNMP_INC_STATS_USER(mib, field) \
-	(per_cpu_ptr(mib[1], raw_smp_processor_id())->mibs[field]++)
+	do { \
+		per_cpu_ptr(mib[1], get_cpu())->mibs[field]++; \
+		put_cpu(); \
+	} while (0)
 #define SNMP_INC_STATS(mib, field) 	\
-	(per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id())->mibs[field]++)
+	do { \
+		per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]++; \
+		put_cpu(); \
+	} while (0)
 #define SNMP_DEC_STATS(mib, field) 	\
-	(per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id())->mibs[field]--)
+	do { \
+		per_cpu_ptr(mib[!in_softirq()], get_cpu())->mibs[field]--; \
+		put_cpu(); \
+	} while (0)
 #define SNMP_ADD_STATS_BH(mib, field, addend) 	\
 	(per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field] += addend)
 #define SNMP_ADD_STATS_USER(mib, field, addend) 	\
-	(per_cpu_ptr(mib[1], raw_smp_processor_id())->mibs[field] += addend)
+	do { \
+		per_cpu_ptr(mib[1], get_cpu())->mibs[field] += addend; \
+		put_cpu(); \
+	} while (0)
 
 #endif
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index f8d0789..83ff7c0 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -534,7 +534,6 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
 	icmp_param.data.icmph.checksum	 = 0;
 	icmp_param.skb	  = skb_in;
 	icmp_param.offset = skb_in->nh.raw - skb_in->data;
-	icmp_out_count(icmp_param.data.icmph.type);
 	inet_sk(icmp_socket->sk)->tos = tos;
 	ipc.addr = iph->saddr;
 	ipc.opt = &icmp_param.replyopts;
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index e443cff..8223397 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -837,6 +837,8 @@ try_again:
 	if (err)
 		goto out_free;
 
+	UDP_INC_STATS_USER(UDP_MIB_INDATAGRAMS);
+
 	sock_recv_timestamp(msg, sk, skb);
 
 	/* Copy the address. */
@@ -1031,7 +1033,6 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
 		if (ret < 0) {
 			/* process the ESP packet */
 			ret = xfrm4_rcv_encap(skb, up->encap_type);
-			UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS);
 			return -ret;
 		}
 		/* FALLTHROUGH -- it's a UDP Packet */
@@ -1051,7 +1052,6 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
 		kfree_skb(skb);
 		return -1;
 	}
-	UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS);
 	return 0;
 }
 
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 99bae51..621e8c8 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -124,11 +124,11 @@ ipv4_connected:
 				goto out;
 			}
 			sk->sk_bound_dev_if = usin->sin6_scope_id;
-			if (!sk->sk_bound_dev_if &&
-			    (addr_type & IPV6_ADDR_MULTICAST))
-				fl.oif = np->mcast_oif;
 		}
 
+		if (!sk->sk_bound_dev_if && (addr_type & IPV6_ADDR_MULTICAST))
+			sk->sk_bound_dev_if = np->mcast_oif;
+
 		/* Connect to link-local address requires an interface */
 		if (!sk->sk_bound_dev_if) {
 			err = -EINVAL;
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index a3d2aa9..bfad9b8 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -468,8 +468,6 @@ route_done:
 	}
 	err = icmpv6_push_pending_frames(sk, &fl, &tmp_hdr, len + sizeof(struct icmp6hdr));
 
-	ICMP6_INC_STATS_BH(idev, ICMP6_MIB_OUTMSGS);
-
 out_put:
 	if (likely(idev != NULL))
 		in6_dev_put(idev);
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index 7394590..cc34bba 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -98,7 +98,7 @@ static char *icmp6type2name[256] = {
 	[ICMPV6_PKT_TOOBIG] = "PktTooBigs",
 	[ICMPV6_TIME_EXCEED] = "TimeExcds",
 	[ICMPV6_PARAMPROB] = "ParmProblems",
-	[ICMPV6_ECHO_REQUEST] = "EchoRequest",
+	[ICMPV6_ECHO_REQUEST] = "Echos",
 	[ICMPV6_ECHO_REPLY] = "EchoReplies",
 	[ICMPV6_MGM_QUERY] = "GroupMembQueries",
 	[ICMPV6_MGM_REPORT] = "GroupMembResponses",
@@ -108,7 +108,7 @@ static char *icmp6type2name[256] = {
 	[NDISC_ROUTER_SOLICITATION] = "RouterSolicits",
 	[NDISC_NEIGHBOUR_ADVERTISEMENT] = "NeighborAdvertisements",
 	[NDISC_NEIGHBOUR_SOLICITATION] = "NeighborSolicits",
-	[NDISC_REDIRECT] = "NeighborRedirects",
+	[NDISC_REDIRECT] = "Redirects",
 };
  
  
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 1d3047c..56a69b4 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -258,6 +258,8 @@ try_again:
 	if (err)
 		goto out_free;
 
+	UDP6_INC_STATS_USER(UDP_MIB_INDATAGRAMS);
+
 	sock_recv_timestamp(msg, sk, skb);
 
 	/* Copy the address. */
@@ -363,7 +365,6 @@ static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
 		kfree_skb(skb);
 		return 0;
 	}
-	UDP6_INC_STATS_BH(UDP_MIB_INDATAGRAMS);
 	return 0;
 }