History

netfilter: ipset: Add skbinfo extension support to SET target.

Anton Danilov committed 12 years ago

Commit 76cea411 parent cbee93d2 files · +165 −0Browse files

Unified · Split

2 files
  1. include/uapi/linux/netfilter/xt_set.h +10 −0
  2. net/netfilter/xt_set.c +155 −0
include/uapi/linux/netfilter/xt_set.h+10−0
@@ -71,4 +71,14 @@ struct xt_set_info_match_v3 { · 70 unmodified lines
7171 __u32 flags;
7272 };
7373
74+/* Revision 3 target */
75+
76+struct xt_set_info_target_v3 {
77+ struct xt_set_info add_set;
78+ struct xt_set_info del_set;
79+ struct xt_set_info map_set;
80+ __u32 flags;
81+ __u32 timeout;
82+};
83+
7484 #endif /*_XT_SET_H*/
net/netfilter/xt_set.c+155−0
@@ -366,6 +366,140 @@ set_target_v2(struct sk_buff *skb, const struct xt_action_param *par) · 365 unmodified lines
366366 #define set_target_v2_checkentry set_target_v1_checkentry
367367 #define set_target_v2_destroy set_target_v1_destroy
368368
369+/* Revision 3 target */
370+
371+static unsigned int
372+set_target_v3(struct sk_buff *skb, const struct xt_action_param *par)
373+{
374+ const struct xt_set_info_target_v3 *info = par->targinfo;
375+ ADT_OPT(add_opt, par->family, info->add_set.dim,
376+ info->add_set.flags, info->flags, info->timeout);
377+ ADT_OPT(del_opt, par->family, info->del_set.dim,
378+ info->del_set.flags, 0, UINT_MAX);
379+ ADT_OPT(map_opt, par->family, info->map_set.dim,
380+ info->map_set.flags, 0, UINT_MAX);
381+
382+ int ret;
383+
384+ /* Normalize to fit into jiffies */
385+ if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
386+ add_opt.ext.timeout > UINT_MAX/MSEC_PER_SEC)
387+ add_opt.ext.timeout = UINT_MAX/MSEC_PER_SEC;
388+ if (info->add_set.index != IPSET_INVALID_ID)
389+ ip_set_add(info->add_set.index, skb, par, &add_opt);
390+ if (info->del_set.index != IPSET_INVALID_ID)
391+ ip_set_del(info->del_set.index, skb, par, &del_opt);
392+ if (info->map_set.index != IPSET_INVALID_ID) {
393+ map_opt.cmdflags |= info->flags & (IPSET_FLAG_MAP_SKBMARK |
394+ IPSET_FLAG_MAP_SKBPRIO |
395+ IPSET_FLAG_MAP_SKBQUEUE);
396+ ret = match_set(info->map_set.index, skb, par, &map_opt,
397+ info->map_set.flags & IPSET_INV_MATCH);
398+ if (!ret)
399+ return XT_CONTINUE;
400+ if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBMARK)
401+ skb->mark = (skb->mark & ~(map_opt.ext.skbmarkmask))
402+ ^ (map_opt.ext.skbmark);
403+ if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBPRIO)
404+ skb->priority = map_opt.ext.skbprio;
405+ if ((map_opt.cmdflags & IPSET_FLAG_MAP_SKBQUEUE) &&
406+ skb->dev &&
407+ skb->dev->real_num_tx_queues > map_opt.ext.skbqueue)
408+ skb_set_queue_mapping(skb, map_opt.ext.skbqueue);
409+ }
410+ return XT_CONTINUE;
411+}
412+
413+
414+static int
415+set_target_v3_checkentry(const struct xt_tgchk_param *par)
416+{
417+ const struct xt_set_info_target_v3 *info = par->targinfo;
418+ ip_set_id_t index;
419+
420+ if (info->add_set.index != IPSET_INVALID_ID) {
421+ index = ip_set_nfnl_get_byindex(par->net,
422+ info->add_set.index);
423+ if (index == IPSET_INVALID_ID) {
424+ pr_warn("Cannot find add_set index %u as target\n",
425+ info->add_set.index);
426+ return -ENOENT;
427+ }
428+ }
429+
430+ if (info->del_set.index != IPSET_INVALID_ID) {
431+ index = ip_set_nfnl_get_byindex(par->net,
432+ info->del_set.index);
433+ if (index == IPSET_INVALID_ID) {
434+ pr_warn("Cannot find del_set index %u as target\n",
435+ info->del_set.index);
436+ if (info->add_set.index != IPSET_INVALID_ID)
437+ ip_set_nfnl_put(par->net,
438+ info->add_set.index);
439+ return -ENOENT;
440+ }
441+ }
442+
443+ if (info->map_set.index != IPSET_INVALID_ID) {
444+ if (strncmp(par->table, "mangle", 7)) {
445+ pr_warn("--map-set only usable from mangle table\n");
446+ return -EINVAL;
447+ }
448+ if (((info->flags & IPSET_FLAG_MAP_SKBPRIO) |
449+ (info->flags & IPSET_FLAG_MAP_SKBQUEUE)) &&
450+ !(par->hook_mask & (1 << NF_INET_FORWARD |
451+ 1 << NF_INET_LOCAL_OUT |
452+ 1 << NF_INET_POST_ROUTING))) {
453+ pr_warn("mapping of prio or/and queue is allowed only"
454+ "from OUTPUT/FORWARD/POSTROUTING chains\n");
455+ return -EINVAL;
456+ }
457+ index = ip_set_nfnl_get_byindex(par->net,
458+ info->map_set.index);
459+ if (index == IPSET_INVALID_ID) {
460+ pr_warn("Cannot find map_set index %u as target\n",
461+ info->map_set.index);
462+ if (info->add_set.index != IPSET_INVALID_ID)
463+ ip_set_nfnl_put(par->net,
464+ info->add_set.index);
465+ if (info->del_set.index != IPSET_INVALID_ID)
466+ ip_set_nfnl_put(par->net,
467+ info->del_set.index);
468+ return -ENOENT;
469+ }
470+ }
471+
472+ if (info->add_set.dim > IPSET_DIM_MAX ||
473+ info->del_set.dim > IPSET_DIM_MAX ||
474+ info->map_set.dim > IPSET_DIM_MAX) {
475+ pr_warn("Protocol error: SET target dimension "
476+ "is over the limit!\n");
477+ if (info->add_set.index != IPSET_INVALID_ID)
478+ ip_set_nfnl_put(par->net, info->add_set.index);
479+ if (info->del_set.index != IPSET_INVALID_ID)
480+ ip_set_nfnl_put(par->net, info->del_set.index);
481+ if (info->map_set.index != IPSET_INVALID_ID)
482+ ip_set_nfnl_put(par->net, info->map_set.index);
483+ return -ERANGE;
484+ }
485+
486+ return 0;
487+}
488+
489+static void
490+set_target_v3_destroy(const struct xt_tgdtor_param *par)
491+{
492+ const struct xt_set_info_target_v3 *info = par->targinfo;
493+
494+ if (info->add_set.index != IPSET_INVALID_ID)
495+ ip_set_nfnl_put(par->net, info->add_set.index);
496+ if (info->del_set.index != IPSET_INVALID_ID)
497+ ip_set_nfnl_put(par->net, info->del_set.index);
498+ if (info->map_set.index != IPSET_INVALID_ID)
499+ ip_set_nfnl_put(par->net, info->map_set.index);
500+}
501+
502+
369503 static struct xt_match set_matches[] __read_mostly = {
370504 {
371505 .name = "set",
@@ -493,6 +627,27 @@ static struct xt_target set_targets[] __read_mostly = { · 121 unmodified lines
493627 .destroy = set_target_v2_destroy,
494628 .me = THIS_MODULE
495629 },
630+ /* --map-set support */
631+ {
632+ .name = "SET",
633+ .revision = 3,
634+ .family = NFPROTO_IPV4,
635+ .target = set_target_v3,
636+ .targetsize = sizeof(struct xt_set_info_target_v3),
637+ .checkentry = set_target_v3_checkentry,
638+ .destroy = set_target_v3_destroy,
639+ .me = THIS_MODULE
640+ },
641+ {
642+ .name = "SET",
643+ .revision = 3,
644+ .family = NFPROTO_IPV6,
645+ .target = set_target_v3,
646+ .targetsize = sizeof(struct xt_set_info_target_v3),
647+ .checkentry = set_target_v3_checkentry,
648+ .destroy = set_target_v3_destroy,
649+ .me = THIS_MODULE
650+ },
496651 };
497652
498653 static int __init xt_set_init(void)