Blame view
net/sched/em_ipset.c
3.09 KB
6d4fa852a net: sched: add i... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/* * net/sched/em_ipset.c ipset ematch * * Copyright (c) 2012 Florian Westphal <fw@strlen.de> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. */ #include <linux/gfp.h> #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/skbuff.h> #include <linux/netfilter/xt_set.h> #include <linux/ipv6.h> #include <net/ip.h> #include <net/pkt_cls.h> |
82a470f11 net: sched: remov... |
21 |
static int em_ipset_change(struct net *net, void *data, int data_len, |
6d4fa852a net: sched: add i... |
22 23 24 25 26 27 28 |
struct tcf_ematch *em) { struct xt_set_info *set = data; ip_set_id_t index; if (data_len != sizeof(*set)) return -EINVAL; |
1785e8f47 netfiler: ipset: ... |
29 |
index = ip_set_nfnl_get_byindex(net, set->index); |
6d4fa852a net: sched: add i... |
30 31 32 33 34 35 36 |
if (index == IPSET_INVALID_ID) return -ENOENT; em->datalen = sizeof(*set); em->data = (unsigned long)kmemdup(data, em->datalen, GFP_KERNEL); if (em->data) return 0; |
1785e8f47 netfiler: ipset: ... |
37 |
ip_set_nfnl_put(net, index); |
6d4fa852a net: sched: add i... |
38 39 |
return -ENOMEM; } |
82a470f11 net: sched: remov... |
40 |
static void em_ipset_destroy(struct tcf_ematch *em) |
6d4fa852a net: sched: add i... |
41 42 43 |
{ const struct xt_set_info *set = (const void *) em->data; if (set) { |
82a470f11 net: sched: remov... |
44 |
ip_set_nfnl_put(em->net, set->index); |
6d4fa852a net: sched: add i... |
45 46 47 48 49 50 51 52 53 54 55 |
kfree((void *) em->data); } } static int em_ipset_match(struct sk_buff *skb, struct tcf_ematch *em, struct tcf_pkt_info *info) { struct ip_set_adt_opt opt; struct xt_action_param acpar; const struct xt_set_info *set = (const void *) em->data; struct net_device *dev, *indev = NULL; |
613dbd957 netfilter: x_tabl... |
56 57 58 |
struct nf_hook_state state = { .net = em->net, }; |
6d4fa852a net: sched: add i... |
59 |
int ret, network_offset; |
d8b9605d2 net: sched: fix s... |
60 |
switch (tc_skb_protocol(skb)) { |
6d4fa852a net: sched: add i... |
61 |
case htons(ETH_P_IP): |
613dbd957 netfilter: x_tabl... |
62 |
state.pf = NFPROTO_IPV4; |
6d4fa852a net: sched: add i... |
63 64 65 66 67 |
if (!pskb_network_may_pull(skb, sizeof(struct iphdr))) return 0; acpar.thoff = ip_hdrlen(skb); break; case htons(ETH_P_IPV6): |
613dbd957 netfilter: x_tabl... |
68 |
state.pf = NFPROTO_IPV6; |
6d4fa852a net: sched: add i... |
69 70 71 72 73 74 75 76 |
if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr))) return 0; /* doesn't call ipv6_find_hdr() because ipset doesn't use thoff, yet */ acpar.thoff = sizeof(struct ipv6hdr); break; default: return 0; } |
613dbd957 netfilter: x_tabl... |
77 |
opt.family = state.pf; |
6d4fa852a net: sched: add i... |
78 79 80 |
opt.dim = set->dim; opt.flags = set->flags; opt.cmdflags = 0; |
075e64c04 netfilter: ipset:... |
81 |
opt.ext.timeout = ~0u; |
6d4fa852a net: sched: add i... |
82 83 84 85 86 87 88 |
network_offset = skb_network_offset(skb); skb_pull(skb, network_offset); dev = skb->dev; rcu_read_lock(); |
17cebfd09 net: sched: Simpl... |
89 90 |
if (skb->skb_iif) indev = dev_get_by_index_rcu(em->net, skb->skb_iif); |
6d4fa852a net: sched: add i... |
91 |
|
613dbd957 netfilter: x_tabl... |
92 93 94 |
state.in = indev ? indev : dev; state.out = dev; acpar.state = &state; |
6d4fa852a net: sched: add i... |
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
ret = ip_set_test(set->index, skb, &acpar, &opt); rcu_read_unlock(); skb_push(skb, network_offset); return ret; } static struct tcf_ematch_ops em_ipset_ops = { .kind = TCF_EM_IPSET, .change = em_ipset_change, .destroy = em_ipset_destroy, .match = em_ipset_match, .owner = THIS_MODULE, .link = LIST_HEAD_INIT(em_ipset_ops.link) }; static int __init init_em_ipset(void) { return tcf_em_register(&em_ipset_ops); } static void __exit exit_em_ipset(void) { tcf_em_unregister(&em_ipset_ops); } MODULE_LICENSE("GPL"); MODULE_AUTHOR("Florian Westphal <fw@strlen.de>"); MODULE_DESCRIPTION("TC extended match for IP sets"); module_init(init_em_ipset); module_exit(exit_em_ipset); MODULE_ALIAS_TCF_EMATCH(TCF_EM_IPSET); |