aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2005-08-09 22:45:02 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 18:37:22 -0400
commitd13964f4490157b8a290903362bfbc54f750a6bc (patch)
tree377297846b513224a30185fb279afd6640e361f5
parent0bd1b59b15e4057101c89d4db15a3683c0d897f7 (diff)
[IPV4/6]: Check if packet was actually delivered to a raw socket to decide whether to send an ICMP unreachable
Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/raw.h2
-rw-r--r--include/net/rawv6.h2
-rw-r--r--net/ipv4/ip_input.c4
-rw-r--r--net/ipv4/raw.c5
-rw-r--r--net/ipv6/ip6_input.c4
-rw-r--r--net/ipv6/raw.c5
6 files changed, 14 insertions, 8 deletions
diff --git a/include/net/raw.h b/include/net/raw.h
index 1c411c45587a..1c4bc3e6809f 100644
--- a/include/net/raw.h
+++ b/include/net/raw.h
@@ -37,6 +37,6 @@ extern struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
37 unsigned long raddr, unsigned long laddr, 37 unsigned long raddr, unsigned long laddr,
38 int dif); 38 int dif);
39 39
40extern void raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash); 40extern int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash);
41 41
42#endif /* _RAW_H */ 42#endif /* _RAW_H */
diff --git a/include/net/rawv6.h b/include/net/rawv6.h
index 887009aa1f88..14476a71725e 100644
--- a/include/net/rawv6.h
+++ b/include/net/rawv6.h
@@ -7,7 +7,7 @@
7extern struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE]; 7extern struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE];
8extern rwlock_t raw_v6_lock; 8extern rwlock_t raw_v6_lock;
9 9
10extern void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr); 10extern int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr);
11 11
12extern struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num, 12extern struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num,
13 struct in6_addr *loc_addr, struct in6_addr *rmt_addr, 13 struct in6_addr *loc_addr, struct in6_addr *rmt_addr,
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index d603247bdfe9..81e18023dc19 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -225,8 +225,8 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb)
225 /* If there maybe a raw socket we must check - if not we 225 /* If there maybe a raw socket we must check - if not we
226 * don't care less 226 * don't care less
227 */ 227 */
228 if (raw_sk) 228 if (raw_sk && !raw_v4_input(skb, skb->nh.iph, hash))
229 raw_v4_input(skb, skb->nh.iph, hash); 229 raw_sk = NULL;
230 230
231 if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) { 231 if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) {
232 int ret; 232 int ret;
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index d1835b1bc8c4..e222c5c26b32 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -150,10 +150,11 @@ static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb)
150 * RFC 1122: SHOULD pass TOS value up to the transport layer. 150 * RFC 1122: SHOULD pass TOS value up to the transport layer.
151 * -> It does. And not only TOS, but all IP header. 151 * -> It does. And not only TOS, but all IP header.
152 */ 152 */
153void raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash) 153int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
154{ 154{
155 struct sock *sk; 155 struct sock *sk;
156 struct hlist_head *head; 156 struct hlist_head *head;
157 int delivered = 0;
157 158
158 read_lock(&raw_v4_lock); 159 read_lock(&raw_v4_lock);
159 head = &raw_v4_htable[hash]; 160 head = &raw_v4_htable[hash];
@@ -164,6 +165,7 @@ void raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
164 skb->dev->ifindex); 165 skb->dev->ifindex);
165 166
166 while (sk) { 167 while (sk) {
168 delivered = 1;
167 if (iph->protocol != IPPROTO_ICMP || !icmp_filter(sk, skb)) { 169 if (iph->protocol != IPPROTO_ICMP || !icmp_filter(sk, skb)) {
168 struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); 170 struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
169 171
@@ -177,6 +179,7 @@ void raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
177 } 179 }
178out: 180out:
179 read_unlock(&raw_v4_lock); 181 read_unlock(&raw_v4_lock);
182 return delivered;
180} 183}
181 184
182void raw_err (struct sock *sk, struct sk_buff *skb, u32 info) 185void raw_err (struct sock *sk, struct sk_buff *skb, u32 info)
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index ab51c0369e15..6e3480426939 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -166,8 +166,8 @@ resubmit:
166 nexthdr = skb->nh.raw[nhoff]; 166 nexthdr = skb->nh.raw[nhoff];
167 167
168 raw_sk = sk_head(&raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]); 168 raw_sk = sk_head(&raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]);
169 if (raw_sk) 169 if (raw_sk && !ipv6_raw_deliver(skb, nexthdr))
170 ipv6_raw_deliver(skb, nexthdr); 170 raw_sk = NULL;
171 171
172 hash = nexthdr & (MAX_INET_PROTOS - 1); 172 hash = nexthdr & (MAX_INET_PROTOS - 1);
173 if ((ipprot = rcu_dereference(inet6_protos[hash])) != NULL) { 173 if ((ipprot = rcu_dereference(inet6_protos[hash])) != NULL) {
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 9db0de81f074..a082646e6f16 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -141,11 +141,12 @@ static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb)
141 * 141 *
142 * Caller owns SKB so we must make clones. 142 * Caller owns SKB so we must make clones.
143 */ 143 */
144void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) 144int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
145{ 145{
146 struct in6_addr *saddr; 146 struct in6_addr *saddr;
147 struct in6_addr *daddr; 147 struct in6_addr *daddr;
148 struct sock *sk; 148 struct sock *sk;
149 int delivered = 0;
149 __u8 hash; 150 __u8 hash;
150 151
151 saddr = &skb->nh.ipv6h->saddr; 152 saddr = &skb->nh.ipv6h->saddr;
@@ -167,6 +168,7 @@ void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
167 sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, skb->dev->ifindex); 168 sk = __raw_v6_lookup(sk, nexthdr, daddr, saddr, skb->dev->ifindex);
168 169
169 while (sk) { 170 while (sk) {
171 delivered = 1;
170 if (nexthdr != IPPROTO_ICMPV6 || !icmpv6_filter(sk, skb)) { 172 if (nexthdr != IPPROTO_ICMPV6 || !icmpv6_filter(sk, skb)) {
171 struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); 173 struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC);
172 174
@@ -179,6 +181,7 @@ void ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
179 } 181 }
180out: 182out:
181 read_unlock(&raw_v6_lock); 183 read_unlock(&raw_v6_lock);
184 return delivered;
182} 185}
183 186
184/* This cleans up af_inet6 a bit. -DaveM */ 187/* This cleans up af_inet6 a bit. -DaveM */