IPv6: Delete redundant counter of IPSTATS_MIB_REASMFAILS
[safe/jmp/linux-2.6] / net / netfilter / nfnetlink_log.c
index 5013cb9..9de0470 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/random.h>
 #include <net/sock.h>
 #include <net/netfilter/nf_log.h>
+#include <net/netfilter/nfnetlink_log.h>
 
 #include <asm/atomic.h>
 
@@ -38,7 +39,7 @@
 #endif
 
 #define NFULNL_NLBUFSIZ_DEFAULT        NLMSG_GOODSIZE
-#define NFULNL_TIMEOUT_DEFAULT         HZ      /* every second */
+#define NFULNL_TIMEOUT_DEFAULT         100     /* every second */
 #define NFULNL_QTHRESH_DEFAULT         100     /* 100 packets */
 #define NFULNL_COPY_RANGE_MAX  0xFFFF  /* max packet size is limited by 16-bit struct nfattr nfa_len field */
 
@@ -359,7 +360,7 @@ static inline int
 __build_packet_message(struct nfulnl_instance *inst,
                        const struct sk_buff *skb,
                        unsigned int data_len,
-                       unsigned int pf,
+                       u_int8_t pf,
                        unsigned int hooknum,
                        const struct net_device *indev,
                        const struct net_device *outdev,
@@ -453,6 +454,14 @@ __build_packet_message(struct nfulnl_instance *inst,
                }
        }
 
+       if (indev && skb_mac_header_was_set(skb)) {
+               NLA_PUT_BE16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type));
+               NLA_PUT_BE16(inst->skb, NFULA_HWLEN,
+                            htons(skb->dev->hard_header_len));
+               NLA_PUT(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len,
+                       skb_mac_header(skb));
+       }
+
        if (skb->tstamp.tv64) {
                struct nfulnl_msg_packet_timestamp ts;
                struct timeval tv = ktime_to_timeval(skb->tstamp);
@@ -466,8 +475,9 @@ __build_packet_message(struct nfulnl_instance *inst,
        if (skb->sk) {
                read_lock_bh(&skb->sk->sk_callback_lock);
                if (skb->sk->sk_socket && skb->sk->sk_socket->file) {
-                       __be32 uid = htonl(skb->sk->sk_socket->file->f_uid);
-                       __be32 gid = htons(skb->sk->sk_socket->file->f_gid);
+                       struct file *file = skb->sk->sk_socket->file;
+                       __be32 uid = htonl(file->f_cred->fsuid);
+                       __be32 gid = htonl(file->f_cred->fsgid);
                        /* need to unlock here since NLA_PUT may goto */
                        read_unlock_bh(&skb->sk->sk_callback_lock);
                        NLA_PUT_BE32(inst->skb, NFULA_UID, uid);
@@ -525,8 +535,8 @@ static struct nf_loginfo default_loginfo = {
 };
 
 /* log handler for internal netfilter logging api */
-static void
-nfulnl_log_packet(unsigned int pf,
+void
+nfulnl_log_packet(u_int8_t pf,
                  unsigned int hooknum,
                  const struct sk_buff *skb,
                  const struct net_device *in,
@@ -556,7 +566,7 @@ nfulnl_log_packet(unsigned int pf,
        /* FIXME: do we want to make the size calculation conditional based on
         * what is actually present?  way more branches and checks, but more
         * memory efficient... */
-       size =    NLMSG_ALIGN(sizeof(struct nfgenmsg))
+       size =    NLMSG_SPACE(sizeof(struct nfgenmsg))
                + nla_total_size(sizeof(struct nfulnl_msg_packet_hdr))
                + nla_total_size(sizeof(u_int32_t))     /* ifindex */
                + nla_total_size(sizeof(u_int32_t))     /* ifindex */
@@ -571,6 +581,12 @@ nfulnl_log_packet(unsigned int pf,
                + nla_total_size(sizeof(struct nfulnl_msg_packet_hw))
                + nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp));
 
+       if (in && skb_mac_header_was_set(skb)) {
+               size +=   nla_total_size(skb->dev->hard_header_len)
+                       + nla_total_size(sizeof(u_int16_t))     /* hwtype */
+                       + nla_total_size(sizeof(u_int16_t));    /* hwlen */
+       }
+
        spin_lock_bh(&inst->lock);
 
        if (inst->flags & NFULNL_CFG_F_SEQ)
@@ -580,8 +596,10 @@ nfulnl_log_packet(unsigned int pf,
 
        qthreshold = inst->qthreshold;
        /* per-rule qthreshold overrides per-instance */
-       if (qthreshold > li->u.ulog.qthreshold)
-               qthreshold = li->u.ulog.qthreshold;
+       if (li->u.ulog.qthreshold)
+               if (qthreshold > li->u.ulog.qthreshold)
+                       qthreshold = li->u.ulog.qthreshold;
+
 
        switch (inst->copy_mode) {
        case NFULNL_COPY_META:
@@ -640,6 +658,7 @@ alloc_failure:
        /* FIXME: statistics */
        goto unlock_and_release;
 }
+EXPORT_SYMBOL_GPL(nfulnl_log_packet);
 
 static int
 nfulnl_rcv_nl_event(struct notifier_block *this,
@@ -647,8 +666,7 @@ nfulnl_rcv_nl_event(struct notifier_block *this,
 {
        struct netlink_notify *n = ptr;
 
-       if (event == NETLINK_URELEASE &&
-           n->protocol == NETLINK_NETFILTER && n->pid) {
+       if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) {
                int i;
 
                /* destroy all instances for this pid */
@@ -659,7 +677,7 @@ nfulnl_rcv_nl_event(struct notifier_block *this,
                        struct hlist_head *head = &instance_table[i];
 
                        hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) {
-                               if ((n->net == &init_net) &&
+                               if ((net_eq(n->net, &init_net)) &&
                                    (n->pid == inst->peer_pid))
                                        __instance_destroy(inst);
                        }
@@ -675,12 +693,13 @@ static struct notifier_block nfulnl_rtnl_notifier = {
 
 static int
 nfulnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb,
-                 struct nlmsghdr *nlh, struct nlattr *nfqa[])
+                  const struct nlmsghdr *nlh,
+                  const struct nlattr * const nfqa[])
 {
        return -ENOTSUPP;
 }
 
-static const struct nf_logger nfulnl_logger = {
+static struct nf_logger nfulnl_logger __read_mostly = {
        .name   = "nfnetlink_log",
        .logfn  = &nfulnl_log_packet,
        .me     = THIS_MODULE,
@@ -697,25 +716,36 @@ static const struct nla_policy nfula_cfg_policy[NFULA_CFG_MAX+1] = {
 
 static int
 nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
-                  struct nlmsghdr *nlh, struct nlattr *nfula[])
+                  const struct nlmsghdr *nlh,
+                  const struct nlattr * const nfula[])
 {
        struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
        u_int16_t group_num = ntohs(nfmsg->res_id);
        struct nfulnl_instance *inst;
+       struct nfulnl_msg_config_cmd *cmd = NULL;
        int ret = 0;
 
+       if (nfula[NFULA_CFG_CMD]) {
+               u_int8_t pf = nfmsg->nfgen_family;
+               cmd = nla_data(nfula[NFULA_CFG_CMD]);
+
+               /* Commands without queue context */
+               switch (cmd->command) {
+               case NFULNL_CFG_CMD_PF_BIND:
+                       return nf_log_bind_pf(pf, &nfulnl_logger);
+               case NFULNL_CFG_CMD_PF_UNBIND:
+                       nf_log_unbind_pf(pf);
+                       return 0;
+               }
+       }
+
        inst = instance_lookup_get(group_num);
        if (inst && inst->peer_pid != NETLINK_CB(skb).pid) {
                ret = -EPERM;
                goto out_put;
        }
 
-       if (nfula[NFULA_CFG_CMD]) {
-               u_int8_t pf = nfmsg->nfgen_family;
-               struct nfulnl_msg_config_cmd *cmd;
-
-               cmd = nla_data(nfula[NFULA_CFG_CMD]);
-
+       if (cmd != NULL) {
                switch (cmd->command) {
                case NFULNL_CFG_CMD_BIND:
                        if (inst) {
@@ -738,14 +768,6 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
 
                        instance_destroy(inst);
                        goto out;
-               case NFULNL_CFG_CMD_PF_BIND:
-                       ret = nf_log_register(pf, &nfulnl_logger);
-                       break;
-               case NFULNL_CFG_CMD_PF_UNBIND:
-                       /* This is a bug and a feature.  We cannot unregister
-                        * other handlers, like nfnetlink_inst can */
-                       nf_log_unregister_pf(pf);
-                       break;
                default:
                        ret = -ENOTSUPP;
                        break;
@@ -866,6 +888,7 @@ static struct hlist_node *get_idx(struct iter_state *st, loff_t pos)
 }
 
 static void *seq_start(struct seq_file *seq, loff_t *pos)
+       __acquires(instances_lock)
 {
        read_lock_bh(&instances_lock);
        return get_idx(seq->private, *pos);
@@ -878,6 +901,7 @@ static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
 }
 
 static void seq_stop(struct seq_file *s, void *v)
+       __releases(instances_lock)
 {
        read_unlock_bh(&instances_lock);
 }
@@ -919,9 +943,6 @@ static const struct file_operations nful_file_ops = {
 static int __init nfnetlink_log_init(void)
 {
        int i, status = -ENOMEM;
-#ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *proc_nful;
-#endif
 
        for (i = 0; i < INSTANCE_BUCKETS; i++)
                INIT_HLIST_HEAD(&instance_table[i]);
@@ -938,19 +959,25 @@ static int __init nfnetlink_log_init(void)
                goto cleanup_netlink_notifier;
        }
 
-#ifdef CONFIG_PROC_FS
-       proc_nful = create_proc_entry("nfnetlink_log", 0440,
-                                     proc_net_netfilter);
-       if (!proc_nful)
+       status = nf_log_register(NFPROTO_UNSPEC, &nfulnl_logger);
+       if (status < 0) {
+               printk(KERN_ERR "log: failed to register logger\n");
                goto cleanup_subsys;
-       proc_nful->proc_fops = &nful_file_ops;
+       }
+
+#ifdef CONFIG_PROC_FS
+       if (!proc_create("nfnetlink_log", 0440,
+                        proc_net_netfilter, &nful_file_ops))
+               goto cleanup_logger;
 #endif
        return status;
 
 #ifdef CONFIG_PROC_FS
+cleanup_logger:
+       nf_log_unregister(&nfulnl_logger);
+#endif
 cleanup_subsys:
        nfnetlink_subsys_unregister(&nfulnl_subsys);
-#endif
 cleanup_netlink_notifier:
        netlink_unregister_notifier(&nfulnl_rtnl_notifier);
        return status;