aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2007-11-20 01:35:07 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:54:28 -0500
commit7bc54c90307b4bc3d7fb2ffd6ad8fbda0671a45e (patch)
tree74e2030d9603c41ce5dc3699862804a69300b7dc /net/ipv4
parente372c41401993b45c721c4d92730e7e0a79f7c1b (diff)
[IPv4] RAW: Compact the API for the kernel
The raw sockets functions are explicitly used from inside the kernel in two places: 1. in ip_local_deliver_finish to intercept skb-s 2. in icmp_error For this purposes many functions and even data structures, that are naturally internal for raw protocol, are exported. Compact the API to two functions and hide all the other (including hash table and rwlock) inside the net/ipv4/raw.c Signed-off-by: Pavel Emelyanov <xemul@openvz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/icmp.c15
-rw-r--r--net/ipv4/ip_input.c16
-rw-r--r--net/ipv4/raw.c53
3 files changed, 53 insertions, 31 deletions
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 82baea026484..13d74598d3e4 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -603,7 +603,6 @@ static void icmp_unreach(struct sk_buff *skb)
603 struct icmphdr *icmph; 603 struct icmphdr *icmph;
604 int hash, protocol; 604 int hash, protocol;
605 struct net_protocol *ipprot; 605 struct net_protocol *ipprot;
606 struct sock *raw_sk;
607 u32 info = 0; 606 u32 info = 0;
608 607
609 /* 608 /*
@@ -697,21 +696,9 @@ static void icmp_unreach(struct sk_buff *skb)
697 /* 696 /*
698 * Deliver ICMP message to raw sockets. Pretty useless feature? 697 * Deliver ICMP message to raw sockets. Pretty useless feature?
699 */ 698 */
699 raw_icmp_error(skb, protocol, info);
700 700
701 /* Note: See raw.c and net/raw.h, RAWV4_HTABLE_SIZE==MAX_INET_PROTOS */
702 hash = protocol & (MAX_INET_PROTOS - 1); 701 hash = protocol & (MAX_INET_PROTOS - 1);
703 read_lock(&raw_v4_lock);
704 if ((raw_sk = sk_head(&raw_v4_htable[hash])) != NULL) {
705 while ((raw_sk = __raw_v4_lookup(raw_sk, protocol, iph->daddr,
706 iph->saddr,
707 skb->dev->ifindex)) != NULL) {
708 raw_err(raw_sk, skb, info);
709 raw_sk = sk_next(raw_sk);
710 iph = (struct iphdr *)skb->data;
711 }
712 }
713 read_unlock(&raw_v4_lock);
714
715 rcu_read_lock(); 702 rcu_read_lock();
716 ipprot = rcu_dereference(inet_protos[hash]); 703 ipprot = rcu_dereference(inet_protos[hash]);
717 if (ipprot && ipprot->err_handler) 704 if (ipprot && ipprot->err_handler)
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 4068e178d747..65631391d479 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -204,22 +204,14 @@ static int ip_local_deliver_finish(struct sk_buff *skb)
204 204
205 rcu_read_lock(); 205 rcu_read_lock();
206 { 206 {
207 /* Note: See raw.c and net/raw.h, RAWV4_HTABLE_SIZE==MAX_INET_PROTOS */
208 int protocol = ip_hdr(skb)->protocol; 207 int protocol = ip_hdr(skb)->protocol;
209 int hash; 208 int hash, raw;
210 struct sock *raw_sk;
211 struct net_protocol *ipprot; 209 struct net_protocol *ipprot;
212 210
213 resubmit: 211 resubmit:
214 hash = protocol & (MAX_INET_PROTOS - 1); 212 raw = raw_local_deliver(skb, protocol);
215 raw_sk = sk_head(&raw_v4_htable[hash]);
216
217 /* If there maybe a raw socket we must check - if not we
218 * don't care less
219 */
220 if (raw_sk && !raw_v4_input(skb, ip_hdr(skb), hash))
221 raw_sk = NULL;
222 213
214 hash = protocol & (MAX_INET_PROTOS - 1);
223 if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) { 215 if ((ipprot = rcu_dereference(inet_protos[hash])) != NULL) {
224 int ret; 216 int ret;
225 217
@@ -237,7 +229,7 @@ static int ip_local_deliver_finish(struct sk_buff *skb)
237 } 229 }
238 IP_INC_STATS_BH(IPSTATS_MIB_INDELIVERS); 230 IP_INC_STATS_BH(IPSTATS_MIB_INDELIVERS);
239 } else { 231 } else {
240 if (!raw_sk) { 232 if (!raw) {
241 if (xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) { 233 if (xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
242 IP_INC_STATS_BH(IPSTATS_MIB_INUNKNOWNPROTOS); 234 IP_INC_STATS_BH(IPSTATS_MIB_INUNKNOWNPROTOS);
243 icmp_send(skb, ICMP_DEST_UNREACH, 235 icmp_send(skb, ICMP_DEST_UNREACH,
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. */