X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=net%2Fnetfilter%2Fnfnetlink_queue.c;h=10522c04ed248fe3c8998661ca61393a3f5db970;hb=a49072bb367a94a9af6c6a6dcbaa1dc5617d7fa0;hp=370f0af50f487338a91e385fce307843bda7c785;hpb=cd21f0ac43f8d7f23573a01ada7fb2c96e686ff8;p=~andy%2Flinux diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 370f0af50f4..10522c04ed2 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -89,16 +89,21 @@ instance_lookup(u_int16_t queue_num) static struct nfqnl_instance * instance_create(u_int16_t queue_num, int pid) { - struct nfqnl_instance *inst = NULL; + struct nfqnl_instance *inst; unsigned int h; + int err; spin_lock(&instances_lock); - if (instance_lookup(queue_num)) + if (instance_lookup(queue_num)) { + err = -EEXIST; goto out_unlock; + } inst = kzalloc(sizeof(*inst), GFP_ATOMIC); - if (!inst) + if (!inst) { + err = -ENOMEM; goto out_unlock; + } inst->queue_num = queue_num; inst->peer_pid = pid; @@ -109,8 +114,10 @@ instance_create(u_int16_t queue_num, int pid) INIT_LIST_HEAD(&inst->queue_list); INIT_RCU_HEAD(&inst->rcu); - if (!try_module_get(THIS_MODULE)) + if (!try_module_get(THIS_MODULE)) { + err = -EAGAIN; goto out_free; + } h = instance_hashfn(queue_num); hlist_add_head_rcu(&inst->hlist, &instance_table[h]); @@ -123,7 +130,7 @@ out_free: kfree(inst); out_unlock: spin_unlock(&instances_lock); - return NULL; + return ERR_PTR(err); } static void nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, @@ -217,7 +224,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, struct net_device *indev; struct net_device *outdev; - size = NLMSG_ALIGN(sizeof(struct nfgenmsg)) + size = NLMSG_SPACE(sizeof(struct nfgenmsg)) + nla_total_size(sizeof(struct nfqnl_msg_packet_hdr)) + nla_total_size(sizeof(u_int32_t)) /* ifindex */ + nla_total_size(sizeof(u_int32_t)) /* ifindex */ @@ -353,7 +360,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, if (data_len) { struct nlattr *nla; - int size = nla_attr_size(data_len); + int sz = nla_attr_size(data_len); if (skb_tailroom(skb) < nla_total_size(data_len)) { printk(KERN_WARNING "nf_queue: no tailroom!\n"); @@ -362,7 +369,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, nla = (struct nlattr *)skb_put(skb, nla_total_size(data_len)); nla->nla_type = NFQA_PAYLOAD; - nla->nla_len = size; + nla->nla_len = sz; if (skb_copy_bits(entskb, 0, nla_data(nla), data_len)) BUG(); @@ -436,8 +443,8 @@ err_out: static int nfqnl_mangle(void *data, int data_len, struct nf_queue_entry *e) { + struct sk_buff *nskb; int diff; - int err; diff = data_len - e->skb->len; if (diff < 0) { @@ -447,14 +454,16 @@ nfqnl_mangle(void *data, int data_len, struct nf_queue_entry *e) if (data_len > 0xFFFF) return -EINVAL; if (diff > skb_tailroom(e->skb)) { - err = pskb_expand_head(e->skb, 0, + nskb = skb_copy_expand(e->skb, 0, diff - skb_tailroom(e->skb), GFP_ATOMIC); - if (err) { + if (!nskb) { printk(KERN_WARNING "nf_queue: OOM " "in mangle, dropping packet\n"); - return err; + return -ENOMEM; } + kfree_skb(e->skb); + e->skb = nskb; } skb_put(e->skb, diff); } @@ -694,19 +703,12 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, /* Commands without queue context - might sleep */ switch (cmd->command) { case NFQNL_CFG_CMD_PF_BIND: - ret = nf_register_queue_handler(ntohs(cmd->pf), - &nfqh); - break; + return nf_register_queue_handler(ntohs(cmd->pf), + &nfqh); case NFQNL_CFG_CMD_PF_UNBIND: - ret = nf_unregister_queue_handler(ntohs(cmd->pf), - &nfqh); - break; - default: - break; + return nf_unregister_queue_handler(ntohs(cmd->pf), + &nfqh); } - - if (ret < 0) - return ret; } rcu_read_lock(); @@ -724,8 +726,8 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, goto err_out_unlock; } queue = instance_create(queue_num, NETLINK_CB(skb).pid); - if (!queue) { - ret = -EINVAL; + if (IS_ERR(queue)) { + ret = PTR_ERR(queue); goto err_out_unlock; } break; @@ -838,6 +840,7 @@ static struct hlist_node *get_idx(struct seq_file *seq, loff_t pos) } static void *seq_start(struct seq_file *seq, loff_t *pos) + __acquires(instances_lock) { spin_lock(&instances_lock); return get_idx(seq, *pos); @@ -850,6 +853,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) { spin_unlock(&instances_lock); } @@ -892,9 +896,6 @@ static const struct file_operations nfqnl_file_ops = { static int __init nfnetlink_queue_init(void) { int i, status = -ENOMEM; -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *proc_nfqueue; -#endif for (i = 0; i < INSTANCE_BUCKETS; i++) INIT_HLIST_HEAD(&instance_table[i]); @@ -907,11 +908,9 @@ static int __init nfnetlink_queue_init(void) } #ifdef CONFIG_PROC_FS - proc_nfqueue = create_proc_entry("nfnetlink_queue", 0440, - proc_net_netfilter); - if (!proc_nfqueue) + if (!proc_create("nfnetlink_queue", 0440, + proc_net_netfilter, &nfqnl_file_ops)) goto cleanup_subsys; - proc_nfqueue->proc_fops = &nfqnl_file_ops; #endif register_netdevice_notifier(&nfqnl_dev_notifier);