Commit 69d6da0b authored by Pavel Emelyanov's avatar Pavel Emelyanov Committed by David S. Miller

[IPv6] RAW: Compact the API for the kernel

Same as in the previous patch for ipv4, compact the
API and hide hash table and rwlock inside the raw.c
file.

Plus fix some "bad" places from checkpatch.pl point
of view (assignments inside if()).
Signed-off-by: default avatarPavel Emelyanov <xemul@openvz.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7bc54c90
...@@ -5,26 +5,13 @@ ...@@ -5,26 +5,13 @@
#include <net/protocol.h> #include <net/protocol.h>
#define RAWV6_HTABLE_SIZE MAX_INET_PROTOS void raw6_icmp_error(struct sk_buff *, int nexthdr,
extern struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE]; int type, int code, int inner_offset, __be32);
extern rwlock_t raw_v6_lock; int raw6_local_deliver(struct sk_buff *, int);
extern int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr);
extern struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num,
struct in6_addr *loc_addr, struct in6_addr *rmt_addr,
int dif);
extern int rawv6_rcv(struct sock *sk, extern int rawv6_rcv(struct sock *sk,
struct sk_buff *skb); struct sk_buff *skb);
extern void rawv6_err(struct sock *sk,
struct sk_buff *skb,
struct inet6_skb_parm *opt,
int type, int code,
int offset, __be32 info);
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
int rawv6_mh_filter_register(int (*filter)(struct sock *sock, int rawv6_mh_filter_register(int (*filter)(struct sock *sock,
struct sk_buff *skb)); struct sk_buff *skb));
......
...@@ -555,9 +555,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) ...@@ -555,9 +555,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info)
{ {
struct in6_addr *saddr, *daddr;
struct inet6_protocol *ipprot; struct inet6_protocol *ipprot;
struct sock *sk;
int inner_offset; int inner_offset;
int hash; int hash;
u8 nexthdr; u8 nexthdr;
...@@ -579,9 +577,6 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) ...@@ -579,9 +577,6 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info)
if (!pskb_may_pull(skb, inner_offset+8)) if (!pskb_may_pull(skb, inner_offset+8))
return; return;
saddr = &ipv6_hdr(skb)->saddr;
daddr = &ipv6_hdr(skb)->daddr;
/* BUGGG_FUTURE: we should try to parse exthdrs in this packet. /* BUGGG_FUTURE: we should try to parse exthdrs in this packet.
Without this we will not able f.e. to make source routed Without this we will not able f.e. to make source routed
pmtu discovery. pmtu discovery.
...@@ -597,15 +592,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info) ...@@ -597,15 +592,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, __be32 info)
ipprot->err_handler(skb, NULL, type, code, inner_offset, info); ipprot->err_handler(skb, NULL, type, code, inner_offset, info);
rcu_read_unlock(); rcu_read_unlock();
read_lock(&raw_v6_lock); raw6_icmp_error(skb, nexthdr, type, code, inner_offset, info);
if ((sk = sk_head(&raw_v6_htable[hash])) != NULL) {
while ((sk = __raw_v6_lookup(sk, nexthdr, saddr, daddr,
IP6CB(skb)->iif))) {
rawv6_err(sk, skb, NULL, type, code, inner_offset, info);
sk = sk_next(sk);
}
}
read_unlock(&raw_v6_lock);
} }
/* /*
......
...@@ -153,9 +153,8 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ...@@ -153,9 +153,8 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
static int ip6_input_finish(struct sk_buff *skb) static int ip6_input_finish(struct sk_buff *skb)
{ {
struct inet6_protocol *ipprot; struct inet6_protocol *ipprot;
struct sock *raw_sk;
unsigned int nhoff; unsigned int nhoff;
int nexthdr; int nexthdr, raw;
u8 hash; u8 hash;
struct inet6_dev *idev; struct inet6_dev *idev;
...@@ -171,9 +170,7 @@ static int ip6_input_finish(struct sk_buff *skb) ...@@ -171,9 +170,7 @@ static int ip6_input_finish(struct sk_buff *skb)
nhoff = IP6CB(skb)->nhoff; nhoff = IP6CB(skb)->nhoff;
nexthdr = skb_network_header(skb)[nhoff]; nexthdr = skb_network_header(skb)[nhoff];
raw_sk = sk_head(&raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]); raw = raw6_local_deliver(skb, nexthdr);
if (raw_sk && !ipv6_raw_deliver(skb, nexthdr))
raw_sk = NULL;
hash = nexthdr & (MAX_INET_PROTOS - 1); hash = nexthdr & (MAX_INET_PROTOS - 1);
if ((ipprot = rcu_dereference(inet6_protos[hash])) != NULL) { if ((ipprot = rcu_dereference(inet6_protos[hash])) != NULL) {
...@@ -206,7 +203,7 @@ static int ip6_input_finish(struct sk_buff *skb) ...@@ -206,7 +203,7 @@ static int ip6_input_finish(struct sk_buff *skb)
else if (ret == 0) else if (ret == 0)
IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDELIVERS); IP6_INC_STATS_BH(idev, IPSTATS_MIB_INDELIVERS);
} else { } else {
if (!raw_sk) { if (!raw) {
if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
IP6_INC_STATS_BH(idev, IPSTATS_MIB_INUNKNOWNPROTOS); IP6_INC_STATS_BH(idev, IPSTATS_MIB_INUNKNOWNPROTOS);
icmpv6_send(skb, ICMPV6_PARAMPROB, icmpv6_send(skb, ICMPV6_PARAMPROB,
......
...@@ -60,8 +60,10 @@ ...@@ -60,8 +60,10 @@
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE]; #define RAWV6_HTABLE_SIZE MAX_INET_PROTOS
DEFINE_RWLOCK(raw_v6_lock);
static struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE];
static DEFINE_RWLOCK(raw_v6_lock);
static void raw_v6_hash(struct sock *sk) static void raw_v6_hash(struct sock *sk)
{ {
...@@ -83,10 +85,8 @@ static void raw_v6_unhash(struct sock *sk) ...@@ -83,10 +85,8 @@ static void raw_v6_unhash(struct sock *sk)
} }
/* Grumble... icmp and ip_input want to get at this... */ static struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num,
struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num, struct in6_addr *loc_addr, struct in6_addr *rmt_addr, int dif)
struct in6_addr *loc_addr, struct in6_addr *rmt_addr,
int dif)
{ {
struct hlist_node *node; struct hlist_node *node;
int is_multicast = ipv6_addr_is_multicast(loc_addr); int is_multicast = ipv6_addr_is_multicast(loc_addr);
...@@ -167,7 +167,7 @@ EXPORT_SYMBOL(rawv6_mh_filter_unregister); ...@@ -167,7 +167,7 @@ EXPORT_SYMBOL(rawv6_mh_filter_unregister);
* *
* Caller owns SKB so we must make clones. * Caller owns SKB so we must make clones.
*/ */
int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
{ {
struct in6_addr *saddr; struct in6_addr *saddr;
struct in6_addr *daddr; struct in6_addr *daddr;
...@@ -242,6 +242,17 @@ int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) ...@@ -242,6 +242,17 @@ int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
return delivered; return delivered;
} }
int raw6_local_deliver(struct sk_buff *skb, int nexthdr)
{
struct sock *raw_sk;
raw_sk = sk_head(&raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]);
if (raw_sk && !ipv6_raw_deliver(skb, nexthdr))
raw_sk = NULL;
return raw_sk != NULL;
}
/* This cleans up af_inet6 a bit. -DaveM */ /* This cleans up af_inet6 a bit. -DaveM */
static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{ {
...@@ -316,7 +327,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -316,7 +327,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
return err; return err;
} }
void rawv6_err(struct sock *sk, struct sk_buff *skb, static void rawv6_err(struct sock *sk, struct sk_buff *skb,
struct inet6_skb_parm *opt, struct inet6_skb_parm *opt,
int type, int code, int offset, __be32 info) int type, int code, int offset, __be32 info)
{ {
...@@ -350,6 +361,31 @@ void rawv6_err(struct sock *sk, struct sk_buff *skb, ...@@ -350,6 +361,31 @@ void rawv6_err(struct sock *sk, struct sk_buff *skb,
} }
} }
void raw6_icmp_error(struct sk_buff *skb, int nexthdr,
int type, int code, int inner_offset, __be32 info)
{
struct sock *sk;
int hash;
struct in6_addr *saddr, *daddr;
hash = nexthdr & (RAWV6_HTABLE_SIZE - 1);
read_lock(&raw_v6_lock);
sk = sk_head(&raw_v6_htable[hash]);
if (sk != NULL) {
saddr = &ipv6_hdr(skb)->saddr;
daddr = &ipv6_hdr(skb)->daddr;
while ((sk = __raw_v6_lookup(sk, nexthdr, saddr, daddr,
IP6CB(skb)->iif))) {
rawv6_err(sk, skb, NULL, type, code,
inner_offset, info);
sk = sk_next(sk);
}
}
read_unlock(&raw_v6_lock);
}
static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb) static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb)
{ {
if ((raw6_sk(sk)->checksum || sk->sk_filter) && if ((raw6_sk(sk)->checksum || sk->sk_filter) &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment