summaryrefslogtreecommitdiffstats
path: root/net/ipv4/raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/raw.c')
-rw-r--r--net/ipv4/raw.c53
1 files changed, 48 insertions, 5 deletions
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index b80987d2fc55..8a506618b912 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -80,8 +80,10 @@
80#include <linux/netfilter.h> 80#include <linux/netfilter.h>
81#include <linux/netfilter_ipv4.h> 81#include <linux/netfilter_ipv4.h>
82 82
83struct hlist_head raw_v4_htable[RAWV4_HTABLE_SIZE]; 83#define RAWV4_HTABLE_SIZE MAX_INET_PROTOS
84DEFINE_RWLOCK(raw_v4_lock); 84
85static struct hlist_head raw_v4_htable[RAWV4_HTABLE_SIZE];
86static DEFINE_RWLOCK(raw_v4_lock);
85 87
86static void raw_v4_hash(struct sock *sk) 88static void raw_v4_hash(struct sock *sk)
87{ 89{
@@ -102,7 +104,7 @@ static void raw_v4_unhash(struct sock *sk)
102 write_unlock_bh(&raw_v4_lock); 104 write_unlock_bh(&raw_v4_lock);
103} 105}
104 106
105struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num, 107static struct sock *__raw_v4_lookup(struct sock *sk, unsigned short num,
106 __be32 raddr, __be32 laddr, 108 __be32 raddr, __be32 laddr,
107 int dif) 109 int dif)
108{ 110{
@@ -150,7 +152,7 @@ static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb)
150 * RFC 1122: SHOULD pass TOS value up to the transport layer. 152 * RFC 1122: SHOULD pass TOS value up to the transport layer.
151 * -> It does. And not only TOS, but all IP header. 153 * -> It does. And not only TOS, but all IP header.
152 */ 154 */
153int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash) 155static int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash)
154{ 156{
155 struct sock *sk; 157 struct sock *sk;
156 struct hlist_head *head; 158 struct hlist_head *head;
@@ -182,7 +184,25 @@ out:
182 return delivered; 184 return delivered;
183} 185}
184 186
185void raw_err (struct sock *sk, struct sk_buff *skb, u32 info) 187int raw_local_deliver(struct sk_buff *skb, int protocol)
188{
189 int hash;
190 struct sock *raw_sk;
191
192 hash = protocol & (RAWV4_HTABLE_SIZE - 1);
193 raw_sk = sk_head(&raw_v4_htable[hash]);
194
195 /* If there maybe a raw socket we must check - if not we
196 * don't care less
197 */
198 if (raw_sk && !raw_v4_input(skb, ip_hdr(skb), hash))
199 raw_sk = NULL;
200
201 return raw_sk != NULL;
202
203}
204
205static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info)
186{ 206{
187 struct inet_sock *inet = inet_sk(sk); 207 struct inet_sock *inet = inet_sk(sk);
188 const int type = icmp_hdr(skb)->type; 208 const int type = icmp_hdr(skb)->type;
@@ -236,6 +256,29 @@ void raw_err (struct sock *sk, struct sk_buff *skb, u32 info)
236 } 256 }
237} 257}
238 258
259void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info)
260{
261 int hash;
262 struct sock *raw_sk;
263 struct iphdr *iph;
264
265 hash = protocol & (RAWV4_HTABLE_SIZE - 1);
266
267 read_lock(&raw_v4_lock);
268 raw_sk = sk_head(&raw_v4_htable[hash]);
269 if (raw_sk != NULL) {
270 iph = (struct iphdr *)skb->data;
271 while ((raw_sk = __raw_v4_lookup(raw_sk, protocol, iph->daddr,
272 iph->saddr,
273 skb->dev->ifindex)) != NULL) {
274 raw_err(raw_sk, skb, info);
275 raw_sk = sk_next(raw_sk);
276 iph = (struct iphdr *)skb->data;
277 }
278 }
279 read_unlock(&raw_v4_lock);
280}
281
239static int raw_rcv_skb(struct sock * sk, struct sk_buff * skb) 282static int raw_rcv_skb(struct sock * sk, struct sk_buff * skb)
240{ 283{
241 /* Charge it to the socket. */ 284 /* Charge it to the socket. */