]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/netfilter/nfnetlink_log.c
r8169: Tx performance tweak helper
[linux-2.6-omap-h63xx.git] / net / netfilter / nfnetlink_log.c
index c12e1d1bd00e1a8874db401a27f89eabf38beb56..9a35b57ab76d9ea4bc43b4a37401c9c21bd50ee7 100644 (file)
@@ -128,19 +128,23 @@ static struct nfulnl_instance *
 instance_create(u_int16_t group_num, int pid)
 {
        struct nfulnl_instance *inst;
+       int err;
 
        write_lock_bh(&instances_lock);
        if (__instance_lookup(group_num)) {
-               inst = NULL;
+               err = -EEXIST;
                goto out_unlock;
        }
 
        inst = kzalloc(sizeof(*inst), GFP_ATOMIC);
-       if (!inst)
+       if (!inst) {
+               err = -ENOMEM;
                goto out_unlock;
+       }
 
        if (!try_module_get(THIS_MODULE)) {
                kfree(inst);
+               err = -EAGAIN;
                goto out_unlock;
        }
 
@@ -169,7 +173,7 @@ instance_create(u_int16_t group_num, int pid)
 
 out_unlock:
        write_unlock_bh(&instances_lock);
-       return NULL;
+       return ERR_PTR(err);
 }
 
 static void __nfulnl_flush(struct nfulnl_instance *inst);
@@ -385,32 +389,27 @@ __build_packet_message(struct nfulnl_instance *inst,
                NLA_PUT(inst->skb, NFULA_PREFIX, plen, prefix);
 
        if (indev) {
-               tmp_uint = htonl(indev->ifindex);
 #ifndef CONFIG_BRIDGE_NETFILTER
-               NLA_PUT(inst->skb, NFULA_IFINDEX_INDEV, sizeof(tmp_uint),
-                       &tmp_uint);
+               NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV,
+                            htonl(indev->ifindex));
 #else
                if (pf == PF_BRIDGE) {
                        /* Case 1: outdev is physical input device, we need to
                         * look for bridge group (when called from
                         * netfilter_bridge) */
-                       NLA_PUT(inst->skb, NFULA_IFINDEX_PHYSINDEV,
-                               sizeof(tmp_uint), &tmp_uint);
+                       NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
+                                    htonl(indev->ifindex));
                        /* this is the bridge group "brX" */
-                       tmp_uint = htonl(indev->br_port->br->dev->ifindex);
-                       NLA_PUT(inst->skb, NFULA_IFINDEX_INDEV,
-                               sizeof(tmp_uint), &tmp_uint);
+                       NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV,
+                                    htonl(indev->br_port->br->dev->ifindex));
                } else {
                        /* Case 2: indev is bridge group, we need to look for
                         * physical device (when called from ipv4) */
-                       NLA_PUT(inst->skb, NFULA_IFINDEX_INDEV,
-                               sizeof(tmp_uint), &tmp_uint);
-                       if (skb->nf_bridge && skb->nf_bridge->physindev) {
-                               tmp_uint =
-                                   htonl(skb->nf_bridge->physindev->ifindex);
-                               NLA_PUT(inst->skb, NFULA_IFINDEX_PHYSINDEV,
-                                       sizeof(tmp_uint), &tmp_uint);
-                       }
+                       NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV,
+                                    htonl(indev->ifindex));
+                       if (skb->nf_bridge && skb->nf_bridge->physindev)
+                               NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSINDEV,
+                                            htonl(skb->nf_bridge->physindev->ifindex));
                }
 #endif
        }
@@ -418,38 +417,32 @@ __build_packet_message(struct nfulnl_instance *inst,
        if (outdev) {
                tmp_uint = htonl(outdev->ifindex);
 #ifndef CONFIG_BRIDGE_NETFILTER
-               NLA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV, sizeof(tmp_uint),
-                       &tmp_uint);
+               NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV,
+                            htonl(outdev->ifindex));
 #else
                if (pf == PF_BRIDGE) {
                        /* Case 1: outdev is physical output device, we need to
                         * look for bridge group (when called from
                         * netfilter_bridge) */
-                       NLA_PUT(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
-                               sizeof(tmp_uint), &tmp_uint);
+                       NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
+                                    htonl(outdev->ifindex));
                        /* this is the bridge group "brX" */
-                       tmp_uint = htonl(outdev->br_port->br->dev->ifindex);
-                       NLA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV,
-                               sizeof(tmp_uint), &tmp_uint);
+                       NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV,
+                                    htonl(outdev->br_port->br->dev->ifindex));
                } else {
                        /* Case 2: indev is a bridge group, we need to look
                         * for physical device (when called from ipv4) */
-                       NLA_PUT(inst->skb, NFULA_IFINDEX_OUTDEV,
-                               sizeof(tmp_uint), &tmp_uint);
-                       if (skb->nf_bridge && skb->nf_bridge->physoutdev) {
-                               tmp_uint =
-                                   htonl(skb->nf_bridge->physoutdev->ifindex);
-                               NLA_PUT(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
-                                       sizeof(tmp_uint), &tmp_uint);
-                       }
+                       NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV,
+                                    htonl(outdev->ifindex));
+                       if (skb->nf_bridge && skb->nf_bridge->physoutdev)
+                               NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV,
+                                            htonl(skb->nf_bridge->physoutdev->ifindex));
                }
 #endif
        }
 
-       if (skb->mark) {
-               tmp_uint = htonl(skb->mark);
-               NLA_PUT(inst->skb, NFULA_MARK, sizeof(tmp_uint), &tmp_uint);
-       }
+       if (skb->mark)
+               NLA_PUT_BE32(inst->skb, NFULA_MARK, htonl(skb->mark));
 
        if (indev && skb->dev) {
                struct nfulnl_msg_packet_hw phw;
@@ -460,6 +453,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);
@@ -474,23 +475,23 @@ __build_packet_message(struct nfulnl_instance *inst,
                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 = htonl(skb->sk->sk_socket->file->f_gid);
                        /* need to unlock here since NLA_PUT may goto */
                        read_unlock_bh(&skb->sk->sk_callback_lock);
-                       NLA_PUT(inst->skb, NFULA_UID, sizeof(uid), &uid);
+                       NLA_PUT_BE32(inst->skb, NFULA_UID, uid);
+                       NLA_PUT_BE32(inst->skb, NFULA_GID, gid);
                } else
                        read_unlock_bh(&skb->sk->sk_callback_lock);
        }
 
        /* local sequence number */
-       if (inst->flags & NFULNL_CFG_F_SEQ) {
-               tmp_uint = htonl(inst->seq++);
-               NLA_PUT(inst->skb, NFULA_SEQ, sizeof(tmp_uint), &tmp_uint);
-       }
+       if (inst->flags & NFULNL_CFG_F_SEQ)
+               NLA_PUT_BE32(inst->skb, NFULA_SEQ, htonl(inst->seq++));
+
        /* global sequence number */
-       if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) {
-               tmp_uint = htonl(atomic_inc_return(&global_seq));
-               NLA_PUT(inst->skb, NFULA_SEQ_GLOBAL, sizeof(tmp_uint), &tmp_uint);
-       }
+       if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL)
+               NLA_PUT_BE32(inst->skb, NFULA_SEQ_GLOBAL,
+                            htonl(atomic_inc_return(&global_seq)));
 
        if (data_len) {
                struct nlattr *nla;
@@ -563,7 +564,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 */
@@ -573,6 +574,7 @@ nfulnl_log_packet(unsigned int pf,
 #endif
                + nla_total_size(sizeof(u_int32_t))     /* mark */
                + nla_total_size(sizeof(u_int32_t))     /* uid */
+               + nla_total_size(sizeof(u_int32_t))     /* gid */
                + nla_total_size(plen)                  /* prefix */
                + nla_total_size(sizeof(struct nfulnl_msg_packet_hw))
                + nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp));
@@ -708,20 +710,30 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
        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_register(pf, &nfulnl_logger);
+               case NFULNL_CFG_CMD_PF_UNBIND:
+                       nf_log_unregister_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) {
@@ -731,8 +743,8 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
 
                        inst = instance_create(group_num,
                                               NETLINK_CB(skb).pid);
-                       if (!inst) {
-                               ret = -EINVAL;
+                       if (IS_ERR(inst)) {
+                               ret = PTR_ERR(inst);
                                goto out;
                        }
                        break;
@@ -744,14 +756,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;
@@ -771,8 +775,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
        }
 
        if (nfula[NFULA_CFG_TIMEOUT]) {
-               __be32 timeout =
-                       *(__be32 *)nla_data(nfula[NFULA_CFG_TIMEOUT]);
+               __be32 timeout = nla_get_be32(nfula[NFULA_CFG_TIMEOUT]);
 
                if (!inst) {
                        ret = -ENODEV;
@@ -782,8 +785,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
        }
 
        if (nfula[NFULA_CFG_NLBUFSIZ]) {
-               __be32 nlbufsiz =
-                       *(__be32 *)nla_data(nfula[NFULA_CFG_NLBUFSIZ]);
+               __be32 nlbufsiz = nla_get_be32(nfula[NFULA_CFG_NLBUFSIZ]);
 
                if (!inst) {
                        ret = -ENODEV;
@@ -793,8 +795,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
        }
 
        if (nfula[NFULA_CFG_QTHRESH]) {
-               __be32 qthresh =
-                       *(__be32 *)nla_data(nfula[NFULA_CFG_QTHRESH]);
+               __be32 qthresh = nla_get_be32(nfula[NFULA_CFG_QTHRESH]);
 
                if (!inst) {
                        ret = -ENODEV;
@@ -804,8 +805,7 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
        }
 
        if (nfula[NFULA_CFG_FLAGS]) {
-               __be16 flags =
-                       *(__be16 *)nla_data(nfula[NFULA_CFG_FLAGS]);
+               __be16 flags = nla_get_be16(nfula[NFULA_CFG_FLAGS]);
 
                if (!inst) {
                        ret = -ENODEV;
@@ -876,6 +876,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);
@@ -888,6 +889,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);
 }
@@ -929,9 +931,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]);
@@ -949,11 +948,9 @@ static int __init nfnetlink_log_init(void)
        }
 
 #ifdef CONFIG_PROC_FS
-       proc_nful = create_proc_entry("nfnetlink_log", 0440,
-                                     proc_net_netfilter);
-       if (!proc_nful)
+       if (!proc_create("nfnetlink_log", 0440,
+                        proc_net_netfilter, &nful_file_ops))
                goto cleanup_subsys;
-       proc_nful->proc_fops = &nful_file_ops;
 #endif
        return status;