diff options
| author | Pablo Neira Ayuso <pablo@netfilter.org> | 2013-12-26 10:49:03 -0500 |
|---|---|---|
| committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-01-03 18:23:11 -0500 |
| commit | c9c8e485978a308c8a359140da187d55120f8fee (patch) | |
| tree | 084673372c2f76b1cd2378985e750ab95b1b1055 /net | |
| parent | 720e0dfa3a86de3482d82fc1d37090eba1c460eb (diff) | |
netfilter: nf_tables: dump sets in all existing families
This patch allows you to dump all sets available in all of
the registered families. This allows you to use NFPROTO_UNSPEC
to dump all existing sets, similarly to other existing table,
chain and rule operations.
This patch is based on original patch from Arturo Borrero
González.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
| -rw-r--r-- | net/netfilter/nf_tables_api.c | 87 |
1 files changed, 78 insertions, 9 deletions
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 37f0e6988ec4..0d4b42df3350 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
| @@ -1904,12 +1904,14 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, | |||
| 1904 | { | 1904 | { |
| 1905 | struct net *net = sock_net(skb->sk); | 1905 | struct net *net = sock_net(skb->sk); |
| 1906 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | 1906 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); |
| 1907 | const struct nft_af_info *afi; | 1907 | const struct nft_af_info *afi = NULL; |
| 1908 | const struct nft_table *table = NULL; | 1908 | const struct nft_table *table = NULL; |
| 1909 | 1909 | ||
| 1910 | afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false); | 1910 | if (nfmsg->nfgen_family != NFPROTO_UNSPEC) { |
| 1911 | if (IS_ERR(afi)) | 1911 | afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false); |
| 1912 | return PTR_ERR(afi); | 1912 | if (IS_ERR(afi)) |
| 1913 | return PTR_ERR(afi); | ||
| 1914 | } | ||
| 1913 | 1915 | ||
| 1914 | if (nla[NFTA_SET_TABLE] != NULL) { | 1916 | if (nla[NFTA_SET_TABLE] != NULL) { |
| 1915 | table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]); | 1917 | table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]); |
| @@ -2078,8 +2080,8 @@ done: | |||
| 2078 | return skb->len; | 2080 | return skb->len; |
| 2079 | } | 2081 | } |
| 2080 | 2082 | ||
| 2081 | static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb, | 2083 | static int nf_tables_dump_sets_family(struct nft_ctx *ctx, struct sk_buff *skb, |
| 2082 | struct netlink_callback *cb) | 2084 | struct netlink_callback *cb) |
| 2083 | { | 2085 | { |
| 2084 | const struct nft_set *set; | 2086 | const struct nft_set *set; |
| 2085 | unsigned int idx = 0, s_idx = cb->args[0]; | 2087 | unsigned int idx = 0, s_idx = cb->args[0]; |
| @@ -2111,6 +2113,61 @@ done: | |||
| 2111 | return skb->len; | 2113 | return skb->len; |
| 2112 | } | 2114 | } |
| 2113 | 2115 | ||
| 2116 | static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb, | ||
| 2117 | struct netlink_callback *cb) | ||
| 2118 | { | ||
| 2119 | const struct nft_set *set; | ||
| 2120 | unsigned int idx, s_idx = cb->args[0]; | ||
| 2121 | const struct nft_af_info *afi; | ||
| 2122 | struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2]; | ||
| 2123 | struct net *net = sock_net(skb->sk); | ||
| 2124 | int cur_family = cb->args[3]; | ||
| 2125 | |||
| 2126 | if (cb->args[1]) | ||
| 2127 | return skb->len; | ||
| 2128 | |||
| 2129 | list_for_each_entry(afi, &net->nft.af_info, list) { | ||
| 2130 | if (cur_family) { | ||
| 2131 | if (afi->family != cur_family) | ||
| 2132 | continue; | ||
| 2133 | |||
| 2134 | cur_family = 0; | ||
| 2135 | } | ||
| 2136 | |||
| 2137 | list_for_each_entry(table, &afi->tables, list) { | ||
| 2138 | if (cur_table) { | ||
| 2139 | if (cur_table != table) | ||
| 2140 | continue; | ||
| 2141 | |||
| 2142 | cur_table = NULL; | ||
| 2143 | } | ||
| 2144 | |||
| 2145 | ctx->table = table; | ||
| 2146 | ctx->afi = afi; | ||
| 2147 | idx = 0; | ||
| 2148 | list_for_each_entry(set, &ctx->table->sets, list) { | ||
| 2149 | if (idx < s_idx) | ||
| 2150 | goto cont; | ||
| 2151 | if (nf_tables_fill_set(skb, ctx, set, | ||
| 2152 | NFT_MSG_NEWSET, | ||
| 2153 | NLM_F_MULTI) < 0) { | ||
| 2154 | cb->args[0] = idx; | ||
| 2155 | cb->args[2] = (unsigned long) table; | ||
| 2156 | cb->args[3] = afi->family; | ||
| 2157 | goto done; | ||
| 2158 | } | ||
| 2159 | cont: | ||
| 2160 | idx++; | ||
| 2161 | } | ||
| 2162 | if (s_idx) | ||
| 2163 | s_idx = 0; | ||
| 2164 | } | ||
| 2165 | } | ||
| 2166 | cb->args[1] = 1; | ||
| 2167 | done: | ||
| 2168 | return skb->len; | ||
| 2169 | } | ||
| 2170 | |||
| 2114 | static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb) | 2171 | static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb) |
| 2115 | { | 2172 | { |
| 2116 | const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); | 2173 | const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); |
| @@ -2127,9 +2184,12 @@ static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 2127 | if (err < 0) | 2184 | if (err < 0) |
| 2128 | return err; | 2185 | return err; |
| 2129 | 2186 | ||
| 2130 | if (ctx.table == NULL) | 2187 | if (ctx.table == NULL) { |
| 2131 | ret = nf_tables_dump_sets_all(&ctx, skb, cb); | 2188 | if (ctx.afi == NULL) |
| 2132 | else | 2189 | ret = nf_tables_dump_sets_all(&ctx, skb, cb); |
| 2190 | else | ||
| 2191 | ret = nf_tables_dump_sets_family(&ctx, skb, cb); | ||
| 2192 | } else | ||
| 2133 | ret = nf_tables_dump_sets_table(&ctx, skb, cb); | 2193 | ret = nf_tables_dump_sets_table(&ctx, skb, cb); |
| 2134 | 2194 | ||
| 2135 | return ret; | 2195 | return ret; |
| @@ -2142,6 +2202,7 @@ static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb, | |||
| 2142 | const struct nft_set *set; | 2202 | const struct nft_set *set; |
| 2143 | struct nft_ctx ctx; | 2203 | struct nft_ctx ctx; |
| 2144 | struct sk_buff *skb2; | 2204 | struct sk_buff *skb2; |
| 2205 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | ||
| 2145 | int err; | 2206 | int err; |
| 2146 | 2207 | ||
| 2147 | /* Verify existance before starting dump */ | 2208 | /* Verify existance before starting dump */ |
| @@ -2156,6 +2217,10 @@ static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb, | |||
| 2156 | return netlink_dump_start(nlsk, skb, nlh, &c); | 2217 | return netlink_dump_start(nlsk, skb, nlh, &c); |
| 2157 | } | 2218 | } |
| 2158 | 2219 | ||
| 2220 | /* Only accept unspec with dump */ | ||
| 2221 | if (nfmsg->nfgen_family == NFPROTO_UNSPEC) | ||
| 2222 | return -EAFNOSUPPORT; | ||
| 2223 | |||
| 2159 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]); | 2224 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]); |
| 2160 | if (IS_ERR(set)) | 2225 | if (IS_ERR(set)) |
| 2161 | return PTR_ERR(set); | 2226 | return PTR_ERR(set); |
| @@ -2325,6 +2390,7 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb, | |||
| 2325 | const struct nlmsghdr *nlh, | 2390 | const struct nlmsghdr *nlh, |
| 2326 | const struct nlattr * const nla[]) | 2391 | const struct nlattr * const nla[]) |
| 2327 | { | 2392 | { |
| 2393 | const struct nfgenmsg *nfmsg = nlmsg_data(nlh); | ||
| 2328 | struct nft_set *set; | 2394 | struct nft_set *set; |
| 2329 | struct nft_ctx ctx; | 2395 | struct nft_ctx ctx; |
| 2330 | int err; | 2396 | int err; |
| @@ -2336,6 +2402,9 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb, | |||
| 2336 | if (err < 0) | 2402 | if (err < 0) |
| 2337 | return err; | 2403 | return err; |
| 2338 | 2404 | ||
| 2405 | if (nfmsg->nfgen_family == NFPROTO_UNSPEC) | ||
| 2406 | return -EAFNOSUPPORT; | ||
| 2407 | |||
| 2339 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]); | 2408 | set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]); |
| 2340 | if (IS_ERR(set)) | 2409 | if (IS_ERR(set)) |
| 2341 | return PTR_ERR(set); | 2410 | return PTR_ERR(set); |
