diff options
Diffstat (limited to 'net/netfilter/nfnetlink_queue_core.c')
-rw-r--r-- | net/netfilter/nfnetlink_queue_core.c | 50 |
1 files changed, 29 insertions, 21 deletions
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c index c0496a55ad0..e12d44e75b2 100644 --- a/net/netfilter/nfnetlink_queue_core.c +++ b/net/netfilter/nfnetlink_queue_core.c | |||
@@ -44,7 +44,7 @@ struct nfqnl_instance { | |||
44 | struct hlist_node hlist; /* global list of queues */ | 44 | struct hlist_node hlist; /* global list of queues */ |
45 | struct rcu_head rcu; | 45 | struct rcu_head rcu; |
46 | 46 | ||
47 | int peer_pid; | 47 | int peer_portid; |
48 | unsigned int queue_maxlen; | 48 | unsigned int queue_maxlen; |
49 | unsigned int copy_range; | 49 | unsigned int copy_range; |
50 | unsigned int queue_dropped; | 50 | unsigned int queue_dropped; |
@@ -92,7 +92,7 @@ instance_lookup(u_int16_t queue_num) | |||
92 | } | 92 | } |
93 | 93 | ||
94 | static struct nfqnl_instance * | 94 | static struct nfqnl_instance * |
95 | instance_create(u_int16_t queue_num, int pid) | 95 | instance_create(u_int16_t queue_num, int portid) |
96 | { | 96 | { |
97 | struct nfqnl_instance *inst; | 97 | struct nfqnl_instance *inst; |
98 | unsigned int h; | 98 | unsigned int h; |
@@ -111,7 +111,7 @@ instance_create(u_int16_t queue_num, int pid) | |||
111 | } | 111 | } |
112 | 112 | ||
113 | inst->queue_num = queue_num; | 113 | inst->queue_num = queue_num; |
114 | inst->peer_pid = pid; | 114 | inst->peer_portid = portid; |
115 | inst->queue_maxlen = NFQNL_QMAX_DEFAULT; | 115 | inst->queue_maxlen = NFQNL_QMAX_DEFAULT; |
116 | inst->copy_range = 0xfffff; | 116 | inst->copy_range = 0xfffff; |
117 | inst->copy_mode = NFQNL_COPY_NONE; | 117 | inst->copy_mode = NFQNL_COPY_NONE; |
@@ -225,7 +225,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, | |||
225 | { | 225 | { |
226 | sk_buff_data_t old_tail; | 226 | sk_buff_data_t old_tail; |
227 | size_t size; | 227 | size_t size; |
228 | size_t data_len = 0; | 228 | size_t data_len = 0, cap_len = 0; |
229 | struct sk_buff *skb; | 229 | struct sk_buff *skb; |
230 | struct nlattr *nla; | 230 | struct nlattr *nla; |
231 | struct nfqnl_msg_packet_hdr *pmsg; | 231 | struct nfqnl_msg_packet_hdr *pmsg; |
@@ -247,7 +247,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, | |||
247 | #endif | 247 | #endif |
248 | + nla_total_size(sizeof(u_int32_t)) /* mark */ | 248 | + nla_total_size(sizeof(u_int32_t)) /* mark */ |
249 | + nla_total_size(sizeof(struct nfqnl_msg_packet_hw)) | 249 | + nla_total_size(sizeof(struct nfqnl_msg_packet_hw)) |
250 | + nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)); | 250 | + nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp) |
251 | + nla_total_size(sizeof(u_int32_t))); /* cap_len */ | ||
251 | 252 | ||
252 | outdev = entry->outdev; | 253 | outdev = entry->outdev; |
253 | 254 | ||
@@ -266,6 +267,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, | |||
266 | data_len = entskb->len; | 267 | data_len = entskb->len; |
267 | 268 | ||
268 | size += nla_total_size(data_len); | 269 | size += nla_total_size(data_len); |
270 | cap_len = entskb->len; | ||
269 | break; | 271 | break; |
270 | } | 272 | } |
271 | 273 | ||
@@ -402,12 +404,14 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, | |||
402 | if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0) | 404 | if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0) |
403 | goto nla_put_failure; | 405 | goto nla_put_failure; |
404 | 406 | ||
407 | if (cap_len > 0 && nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len))) | ||
408 | goto nla_put_failure; | ||
409 | |||
405 | nlh->nlmsg_len = skb->tail - old_tail; | 410 | nlh->nlmsg_len = skb->tail - old_tail; |
406 | return skb; | 411 | return skb; |
407 | 412 | ||
408 | nla_put_failure: | 413 | nla_put_failure: |
409 | if (skb) | 414 | kfree_skb(skb); |
410 | kfree_skb(skb); | ||
411 | net_err_ratelimited("nf_queue: error creating packet message\n"); | 415 | net_err_ratelimited("nf_queue: error creating packet message\n"); |
412 | return NULL; | 416 | return NULL; |
413 | } | 417 | } |
@@ -440,7 +444,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) | |||
440 | } | 444 | } |
441 | spin_lock_bh(&queue->lock); | 445 | spin_lock_bh(&queue->lock); |
442 | 446 | ||
443 | if (!queue->peer_pid) { | 447 | if (!queue->peer_portid) { |
444 | err = -EINVAL; | 448 | err = -EINVAL; |
445 | goto err_out_free_nskb; | 449 | goto err_out_free_nskb; |
446 | } | 450 | } |
@@ -459,7 +463,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum) | |||
459 | *packet_id_ptr = htonl(entry->id); | 463 | *packet_id_ptr = htonl(entry->id); |
460 | 464 | ||
461 | /* nfnetlink_unicast will either free the nskb or add it to a socket */ | 465 | /* nfnetlink_unicast will either free the nskb or add it to a socket */ |
462 | err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT); | 466 | err = nfnetlink_unicast(nskb, &init_net, queue->peer_portid, MSG_DONTWAIT); |
463 | if (err < 0) { | 467 | if (err < 0) { |
464 | queue->queue_user_dropped++; | 468 | queue->queue_user_dropped++; |
465 | goto err_out_unlock; | 469 | goto err_out_unlock; |
@@ -527,9 +531,13 @@ nfqnl_set_mode(struct nfqnl_instance *queue, | |||
527 | 531 | ||
528 | case NFQNL_COPY_PACKET: | 532 | case NFQNL_COPY_PACKET: |
529 | queue->copy_mode = mode; | 533 | queue->copy_mode = mode; |
530 | /* we're using struct nlattr which has 16bit nla_len */ | 534 | /* We're using struct nlattr which has 16bit nla_len. Note that |
531 | if (range > 0xffff) | 535 | * nla_len includes the header length. Thus, the maximum packet |
532 | queue->copy_range = 0xffff; | 536 | * length that we support is 65531 bytes. We send truncated |
537 | * packets if the specified length is larger than that. | ||
538 | */ | ||
539 | if (range > 0xffff - NLA_HDRLEN) | ||
540 | queue->copy_range = 0xffff - NLA_HDRLEN; | ||
533 | else | 541 | else |
534 | queue->copy_range = range; | 542 | queue->copy_range = range; |
535 | break; | 543 | break; |
@@ -616,7 +624,7 @@ nfqnl_rcv_nl_event(struct notifier_block *this, | |||
616 | if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) { | 624 | if (event == NETLINK_URELEASE && n->protocol == NETLINK_NETFILTER) { |
617 | int i; | 625 | int i; |
618 | 626 | ||
619 | /* destroy all instances for this pid */ | 627 | /* destroy all instances for this portid */ |
620 | spin_lock(&instances_lock); | 628 | spin_lock(&instances_lock); |
621 | for (i = 0; i < INSTANCE_BUCKETS; i++) { | 629 | for (i = 0; i < INSTANCE_BUCKETS; i++) { |
622 | struct hlist_node *tmp, *t2; | 630 | struct hlist_node *tmp, *t2; |
@@ -625,7 +633,7 @@ nfqnl_rcv_nl_event(struct notifier_block *this, | |||
625 | 633 | ||
626 | hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) { | 634 | hlist_for_each_entry_safe(inst, tmp, t2, head, hlist) { |
627 | if ((n->net == &init_net) && | 635 | if ((n->net == &init_net) && |
628 | (n->pid == inst->peer_pid)) | 636 | (n->portid == inst->peer_portid)) |
629 | __instance_destroy(inst); | 637 | __instance_destroy(inst); |
630 | } | 638 | } |
631 | } | 639 | } |
@@ -650,7 +658,7 @@ static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = { | |||
650 | [NFQA_MARK] = { .type = NLA_U32 }, | 658 | [NFQA_MARK] = { .type = NLA_U32 }, |
651 | }; | 659 | }; |
652 | 660 | ||
653 | static struct nfqnl_instance *verdict_instance_lookup(u16 queue_num, int nlpid) | 661 | static struct nfqnl_instance *verdict_instance_lookup(u16 queue_num, int nlportid) |
654 | { | 662 | { |
655 | struct nfqnl_instance *queue; | 663 | struct nfqnl_instance *queue; |
656 | 664 | ||
@@ -658,7 +666,7 @@ static struct nfqnl_instance *verdict_instance_lookup(u16 queue_num, int nlpid) | |||
658 | if (!queue) | 666 | if (!queue) |
659 | return ERR_PTR(-ENODEV); | 667 | return ERR_PTR(-ENODEV); |
660 | 668 | ||
661 | if (queue->peer_pid != nlpid) | 669 | if (queue->peer_portid != nlportid) |
662 | return ERR_PTR(-EPERM); | 670 | return ERR_PTR(-EPERM); |
663 | 671 | ||
664 | return queue; | 672 | return queue; |
@@ -698,7 +706,7 @@ nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb, | |||
698 | LIST_HEAD(batch_list); | 706 | LIST_HEAD(batch_list); |
699 | u16 queue_num = ntohs(nfmsg->res_id); | 707 | u16 queue_num = ntohs(nfmsg->res_id); |
700 | 708 | ||
701 | queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid); | 709 | queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).portid); |
702 | if (IS_ERR(queue)) | 710 | if (IS_ERR(queue)) |
703 | return PTR_ERR(queue); | 711 | return PTR_ERR(queue); |
704 | 712 | ||
@@ -749,7 +757,7 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb, | |||
749 | queue = instance_lookup(queue_num); | 757 | queue = instance_lookup(queue_num); |
750 | if (!queue) | 758 | if (!queue) |
751 | 759 | ||
752 | queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid); | 760 | queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).portid); |
753 | if (IS_ERR(queue)) | 761 | if (IS_ERR(queue)) |
754 | return PTR_ERR(queue); | 762 | return PTR_ERR(queue); |
755 | 763 | ||
@@ -832,7 +840,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, | |||
832 | 840 | ||
833 | rcu_read_lock(); | 841 | rcu_read_lock(); |
834 | queue = instance_lookup(queue_num); | 842 | queue = instance_lookup(queue_num); |
835 | if (queue && queue->peer_pid != NETLINK_CB(skb).pid) { | 843 | if (queue && queue->peer_portid != NETLINK_CB(skb).portid) { |
836 | ret = -EPERM; | 844 | ret = -EPERM; |
837 | goto err_out_unlock; | 845 | goto err_out_unlock; |
838 | } | 846 | } |
@@ -844,7 +852,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, | |||
844 | ret = -EBUSY; | 852 | ret = -EBUSY; |
845 | goto err_out_unlock; | 853 | goto err_out_unlock; |
846 | } | 854 | } |
847 | queue = instance_create(queue_num, NETLINK_CB(skb).pid); | 855 | queue = instance_create(queue_num, NETLINK_CB(skb).portid); |
848 | if (IS_ERR(queue)) { | 856 | if (IS_ERR(queue)) { |
849 | ret = PTR_ERR(queue); | 857 | ret = PTR_ERR(queue); |
850 | goto err_out_unlock; | 858 | goto err_out_unlock; |
@@ -1016,7 +1024,7 @@ static int seq_show(struct seq_file *s, void *v) | |||
1016 | 1024 | ||
1017 | return seq_printf(s, "%5d %6d %5d %1d %5d %5d %5d %8d %2d\n", | 1025 | return seq_printf(s, "%5d %6d %5d %1d %5d %5d %5d %8d %2d\n", |
1018 | inst->queue_num, | 1026 | inst->queue_num, |
1019 | inst->peer_pid, inst->queue_total, | 1027 | inst->peer_portid, inst->queue_total, |
1020 | inst->copy_mode, inst->copy_range, | 1028 | inst->copy_mode, inst->copy_range, |
1021 | inst->queue_dropped, inst->queue_user_dropped, | 1029 | inst->queue_dropped, inst->queue_user_dropped, |
1022 | inst->id_sequence, 1); | 1030 | inst->id_sequence, 1); |