]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv6/raw.c
[NETFILTER]: x_tables: struct xt_table_info diet
[linux-2.6-omap-h63xx.git] / net / ipv6 / raw.c
index 807260d03586dd596314dc29614e33b3162861f0..b34631e1b015c080553cec4ea3f16224c781d30f 100644 (file)
 #include <net/mip6.h>
 #endif
 
+#include <net/raw.h>
 #include <net/rawv6.h>
 #include <net/xfrm.h>
 
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 
-struct hlist_head raw_v6_htable[RAWV6_HTABLE_SIZE];
-DEFINE_RWLOCK(raw_v6_lock);
+static struct raw_hashinfo raw_v6_hashinfo = {
+       .lock = __RW_LOCK_UNLOCKED(),
+};
 
 static void raw_v6_hash(struct sock *sk)
 {
-       struct hlist_head *list = &raw_v6_htable[inet_sk(sk)->num &
-                                                (RAWV6_HTABLE_SIZE - 1)];
-
-       write_lock_bh(&raw_v6_lock);
-       sk_add_node(sk, list);
-       sock_prot_inc_use(sk->sk_prot);
-       write_unlock_bh(&raw_v6_lock);
+       raw_hash_sk(sk, &raw_v6_hashinfo);
 }
 
 static void raw_v6_unhash(struct sock *sk)
 {
-       write_lock_bh(&raw_v6_lock);
-       if (sk_del_node_init(sk))
-               sock_prot_dec_use(sk->sk_prot);
-       write_unlock_bh(&raw_v6_lock);
+       raw_unhash_sk(sk, &raw_v6_hashinfo);
 }
 
 
-/* Grumble... icmp and ip_input want to get at this... */
-struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num,
-                            struct in6_addr *loc_addr, struct in6_addr *rmt_addr,
-                            int dif)
+static struct sock *__raw_v6_lookup(struct sock *sk, unsigned short num,
+               struct in6_addr *loc_addr, struct in6_addr *rmt_addr, int dif)
 {
        struct hlist_node *node;
        int is_multicast = ipv6_addr_is_multicast(loc_addr);
@@ -167,7 +158,7 @@ EXPORT_SYMBOL(rawv6_mh_filter_unregister);
  *
  *     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 *daddr;
@@ -180,8 +171,8 @@ int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
 
        hash = nexthdr & (MAX_INET_PROTOS - 1);
 
-       read_lock(&raw_v6_lock);
-       sk = sk_head(&raw_v6_htable[hash]);
+       read_lock(&raw_v6_hashinfo.lock);
+       sk = sk_head(&raw_v6_hashinfo.ht[hash]);
 
        /*
         *      The first socket found will be delivered after
@@ -238,10 +229,21 @@ int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
                                     IP6CB(skb)->iif);
        }
 out:
-       read_unlock(&raw_v6_lock);
+       read_unlock(&raw_v6_hashinfo.lock);
        return delivered;
 }
 
+int raw6_local_deliver(struct sk_buff *skb, int nexthdr)
+{
+       struct sock *raw_sk;
+
+       raw_sk = sk_head(&raw_v6_hashinfo.ht[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 */
 static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 {
@@ -316,7 +318,7 @@ out:
        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,
               int type, int code, int offset, __be32 info)
 {
@@ -350,18 +352,43 @@ 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 & (RAW_HTABLE_SIZE - 1);
+
+       read_lock(&raw_v6_hashinfo.lock);
+       sk = sk_head(&raw_v6_hashinfo.ht[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_hashinfo.lock);
+}
+
 static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb)
 {
        if ((raw6_sk(sk)->checksum || sk->sk_filter) &&
            skb_checksum_complete(skb)) {
-               /* FIXME: increment a raw6 drops counter here */
+               atomic_inc(&sk->sk_drops);
                kfree_skb(skb);
                return 0;
        }
 
        /* Charge it to the socket. */
        if (sock_queue_rcv_skb(sk,skb)<0) {
-               /* FIXME: increment a raw6 drops counter here */
+               atomic_inc(&sk->sk_drops);
                kfree_skb(skb);
                return 0;
        }
@@ -382,6 +409,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
        struct raw6_sock *rp = raw6_sk(sk);
 
        if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) {
+               atomic_inc(&sk->sk_drops);
                kfree_skb(skb);
                return NET_RX_DROP;
        }
@@ -405,7 +433,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
 
        if (inet->hdrincl) {
                if (skb_checksum_complete(skb)) {
-                       /* FIXME: increment a raw6 drops counter here */
+                       atomic_inc(&sk->sk_drops);
                        kfree_skb(skb);
                        return 0;
                }
@@ -496,7 +524,7 @@ csum_copy_err:
           as some normal condition.
         */
        err = (flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH;
-       /* FIXME: increment a raw6 drops counter here */
+       atomic_inc(&sk->sk_drops);
        goto out;
 }
 
@@ -618,7 +646,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
                goto error_fault;
 
        IP6_INC_STATS(rt->rt6i_idev, IPSTATS_MIB_OUTREQUESTS);
-       err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
+       err = NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
                      dst_output);
        if (err > 0)
                err = np->recverr ? net_xmit_errno(err) : 0;
@@ -1172,76 +1200,6 @@ struct proto rawv6_prot = {
 };
 
 #ifdef CONFIG_PROC_FS
-struct raw6_iter_state {
-       int bucket;
-};
-
-#define raw6_seq_private(seq) ((struct raw6_iter_state *)(seq)->private)
-
-static struct sock *raw6_get_first(struct seq_file *seq)
-{
-       struct sock *sk;
-       struct hlist_node *node;
-       struct raw6_iter_state* state = raw6_seq_private(seq);
-
-       for (state->bucket = 0; state->bucket < RAWV6_HTABLE_SIZE; ++state->bucket)
-               sk_for_each(sk, node, &raw_v6_htable[state->bucket])
-                       if (sk->sk_family == PF_INET6)
-                               goto out;
-       sk = NULL;
-out:
-       return sk;
-}
-
-static struct sock *raw6_get_next(struct seq_file *seq, struct sock *sk)
-{
-       struct raw6_iter_state* state = raw6_seq_private(seq);
-
-       do {
-               sk = sk_next(sk);
-try_again:
-               ;
-       } while (sk && sk->sk_family != PF_INET6);
-
-       if (!sk && ++state->bucket < RAWV6_HTABLE_SIZE) {
-               sk = sk_head(&raw_v6_htable[state->bucket]);
-               goto try_again;
-       }
-       return sk;
-}
-
-static struct sock *raw6_get_idx(struct seq_file *seq, loff_t pos)
-{
-       struct sock *sk = raw6_get_first(seq);
-       if (sk)
-               while (pos && (sk = raw6_get_next(seq, sk)) != NULL)
-                       --pos;
-       return pos ? NULL : sk;
-}
-
-static void *raw6_seq_start(struct seq_file *seq, loff_t *pos)
-{
-       read_lock(&raw_v6_lock);
-       return *pos ? raw6_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
-}
-
-static void *raw6_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-       struct sock *sk;
-
-       if (v == SEQ_START_TOKEN)
-               sk = raw6_get_first(seq);
-       else
-               sk = raw6_get_next(seq, v);
-       ++*pos;
-       return sk;
-}
-
-static void raw6_seq_stop(struct seq_file *seq, void *v)
-{
-       read_unlock(&raw_v6_lock);
-}
-
 static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i)
 {
        struct ipv6_pinfo *np = inet6_sk(sp);
@@ -1254,7 +1212,7 @@ static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i)
        srcp  = inet_sk(sp)->num;
        seq_printf(seq,
                   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
-                  "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p\n",
+                  "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d\n",
                   i,
                   src->s6_addr32[0], src->s6_addr32[1],
                   src->s6_addr32[2], src->s6_addr32[3], srcp,
@@ -1266,7 +1224,7 @@ static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i)
                   0, 0L, 0,
                   sock_i_uid(sp), 0,
                   sock_i_ino(sp),
-                  atomic_read(&sp->sk_refcnt), sp);
+                  atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops));
 }
 
 static int raw6_seq_show(struct seq_file *seq, void *v)
@@ -1277,23 +1235,22 @@ static int raw6_seq_show(struct seq_file *seq, void *v)
                           "local_address                         "
                           "remote_address                        "
                           "st tx_queue rx_queue tr tm->when retrnsmt"
-                          "   uid  timeout inode\n");
+                          "   uid  timeout inode  drops\n");
        else
-               raw6_sock_seq_show(seq, v, raw6_seq_private(seq)->bucket);
+               raw6_sock_seq_show(seq, v, raw_seq_private(seq)->bucket);
        return 0;
 }
 
 static const struct seq_operations raw6_seq_ops = {
-       .start =        raw6_seq_start,
-       .next =         raw6_seq_next,
-       .stop =         raw6_seq_stop,
+       .start =        raw_seq_start,
+       .next =         raw_seq_next,
+       .stop =         raw_seq_stop,
        .show =         raw6_seq_show,
 };
 
 static int raw6_seq_open(struct inode *inode, struct file *file)
 {
-       return seq_open_private(file, &raw6_seq_ops,
-                       sizeof(struct raw6_iter_state));
+       return raw_seq_open(file, &raw_v6_hashinfo, PF_INET6);
 }
 
 static const struct file_operations raw6_seq_fops = {