You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'iov_iter' into for-next
This commit is contained in:
@@ -659,7 +659,7 @@ ip_set_nfnl_get_byindex(struct net *net, ip_set_id_t index)
|
||||
struct ip_set *set;
|
||||
struct ip_set_net *inst = ip_set_pernet(net);
|
||||
|
||||
if (index > inst->ip_set_max)
|
||||
if (index >= inst->ip_set_max)
|
||||
return IPSET_INVALID_ID;
|
||||
|
||||
nfnl_lock(NFNL_SUBSYS_IPSET);
|
||||
@@ -1863,6 +1863,12 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
|
||||
if (*op < IP_SET_OP_VERSION) {
|
||||
/* Check the version at the beginning of operations */
|
||||
struct ip_set_req_version *req_version = data;
|
||||
|
||||
if (*len < sizeof(struct ip_set_req_version)) {
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (req_version->version != IPSET_PROTOCOL) {
|
||||
ret = -EPROTO;
|
||||
goto done;
|
||||
|
||||
@@ -316,7 +316,7 @@ __ip_vs_get_out_rt(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
|
||||
if (unlikely(crosses_local_route_boundary(skb_af, skb, rt_mode,
|
||||
local))) {
|
||||
IP_VS_DBG_RL("We are crossing local and non-local addresses"
|
||||
" daddr=%pI4\n", &dest->addr.ip);
|
||||
" daddr=%pI4\n", &daddr);
|
||||
goto err_put;
|
||||
}
|
||||
|
||||
@@ -458,7 +458,7 @@ __ip_vs_get_out_rt_v6(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
|
||||
if (unlikely(crosses_local_route_boundary(skb_af, skb, rt_mode,
|
||||
local))) {
|
||||
IP_VS_DBG_RL("We are crossing local and non-local addresses"
|
||||
" daddr=%pI6\n", &dest->addr.in6);
|
||||
" daddr=%pI6\n", daddr);
|
||||
goto err_put;
|
||||
}
|
||||
|
||||
@@ -846,6 +846,8 @@ ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int skb_af,
|
||||
new_skb = skb_realloc_headroom(skb, max_headroom);
|
||||
if (!new_skb)
|
||||
goto error;
|
||||
if (skb->sk)
|
||||
skb_set_owner_w(new_skb, skb->sk);
|
||||
consume_skb(skb);
|
||||
skb = new_skb;
|
||||
}
|
||||
|
||||
@@ -611,12 +611,16 @@ __nf_conntrack_confirm(struct sk_buff *skb)
|
||||
*/
|
||||
NF_CT_ASSERT(!nf_ct_is_confirmed(ct));
|
||||
pr_debug("Confirming conntrack %p\n", ct);
|
||||
/* We have to check the DYING flag inside the lock to prevent
|
||||
a race against nf_ct_get_next_corpse() possibly called from
|
||||
user context, else we insert an already 'dead' hash, blocking
|
||||
further use of that particular connection -JM */
|
||||
|
||||
/* We have to check the DYING flag after unlink to prevent
|
||||
* a race against nf_ct_get_next_corpse() possibly called from
|
||||
* user context, else we insert an already 'dead' hash, blocking
|
||||
* further use of that particular connection -JM.
|
||||
*/
|
||||
nf_ct_del_from_dying_or_unconfirmed_list(ct);
|
||||
|
||||
if (unlikely(nf_ct_is_dying(ct))) {
|
||||
nf_ct_add_to_dying_list(ct);
|
||||
nf_conntrack_double_unlock(hash, reply_hash);
|
||||
local_bh_enable();
|
||||
return NF_ACCEPT;
|
||||
@@ -636,8 +640,6 @@ __nf_conntrack_confirm(struct sk_buff *skb)
|
||||
zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)))
|
||||
goto out;
|
||||
|
||||
nf_ct_del_from_dying_or_unconfirmed_list(ct);
|
||||
|
||||
/* Timer relative to confirmation time, not original
|
||||
setting time, otherwise we'd get timer wrap in
|
||||
weird delay cases. */
|
||||
|
||||
@@ -213,7 +213,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
|
||||
{
|
||||
/* REPLY */
|
||||
/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */
|
||||
/*syn*/ { sIV, sS2, sIV, sIV, sIV, sIV, sIV, sIV, sIV, sS2 },
|
||||
/*syn*/ { sIV, sS2, sIV, sIV, sIV, sIV, sIV, sSS, sIV, sS2 },
|
||||
/*
|
||||
* sNO -> sIV Never reached.
|
||||
* sSS -> sS2 Simultaneous open
|
||||
@@ -223,7 +223,7 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
|
||||
* sFW -> sIV
|
||||
* sCW -> sIV
|
||||
* sLA -> sIV
|
||||
* sTW -> sIV Reopened connection, but server may not do it.
|
||||
* sTW -> sSS Reopened connection, but server may have switched role
|
||||
* sCL -> sIV
|
||||
*/
|
||||
/* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */
|
||||
|
||||
@@ -1328,10 +1328,10 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
|
||||
basechain->stats = stats;
|
||||
} else {
|
||||
stats = netdev_alloc_pcpu_stats(struct nft_stats);
|
||||
if (IS_ERR(stats)) {
|
||||
if (stats == NULL) {
|
||||
module_put(type->owner);
|
||||
kfree(basechain);
|
||||
return PTR_ERR(stats);
|
||||
return -ENOMEM;
|
||||
}
|
||||
rcu_assign_pointer(basechain->stats, stats);
|
||||
}
|
||||
@@ -3484,13 +3484,8 @@ static void nft_chain_commit_update(struct nft_trans *trans)
|
||||
}
|
||||
}
|
||||
|
||||
/* Schedule objects for release via rcu to make sure no packets are accesing
|
||||
* removed rules.
|
||||
*/
|
||||
static void nf_tables_commit_release_rcu(struct rcu_head *rt)
|
||||
static void nf_tables_commit_release(struct nft_trans *trans)
|
||||
{
|
||||
struct nft_trans *trans = container_of(rt, struct nft_trans, rcu_head);
|
||||
|
||||
switch (trans->msg_type) {
|
||||
case NFT_MSG_DELTABLE:
|
||||
nf_tables_table_destroy(&trans->ctx);
|
||||
@@ -3612,10 +3607,11 @@ static int nf_tables_commit(struct sk_buff *skb)
|
||||
}
|
||||
}
|
||||
|
||||
synchronize_rcu();
|
||||
|
||||
list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
|
||||
list_del(&trans->list);
|
||||
trans->ctx.nla = NULL;
|
||||
call_rcu(&trans->rcu_head, nf_tables_commit_release_rcu);
|
||||
nf_tables_commit_release(trans);
|
||||
}
|
||||
|
||||
nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN);
|
||||
@@ -3623,13 +3619,8 @@ static int nf_tables_commit(struct sk_buff *skb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Schedule objects for release via rcu to make sure no packets are accesing
|
||||
* aborted rules.
|
||||
*/
|
||||
static void nf_tables_abort_release_rcu(struct rcu_head *rt)
|
||||
static void nf_tables_abort_release(struct nft_trans *trans)
|
||||
{
|
||||
struct nft_trans *trans = container_of(rt, struct nft_trans, rcu_head);
|
||||
|
||||
switch (trans->msg_type) {
|
||||
case NFT_MSG_NEWTABLE:
|
||||
nf_tables_table_destroy(&trans->ctx);
|
||||
@@ -3725,11 +3716,12 @@ static int nf_tables_abort(struct sk_buff *skb)
|
||||
}
|
||||
}
|
||||
|
||||
synchronize_rcu();
|
||||
|
||||
list_for_each_entry_safe_reverse(trans, next,
|
||||
&net->nft.commit_list, list) {
|
||||
list_del(&trans->list);
|
||||
trans->ctx.nla = NULL;
|
||||
call_rcu(&trans->rcu_head, nf_tables_abort_release_rcu);
|
||||
nf_tables_abort_release(trans);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -3744,6 +3736,20 @@ static const struct nfnetlink_subsystem nf_tables_subsys = {
|
||||
.abort = nf_tables_abort,
|
||||
};
|
||||
|
||||
int nft_chain_validate_dependency(const struct nft_chain *chain,
|
||||
enum nft_chain_type type)
|
||||
{
|
||||
const struct nft_base_chain *basechain;
|
||||
|
||||
if (chain->flags & NFT_BASE_CHAIN) {
|
||||
basechain = nft_base_chain(chain);
|
||||
if (basechain->type->type != type)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_chain_validate_dependency);
|
||||
|
||||
/*
|
||||
* Loop detection - walk through the ruleset beginning at the destination chain
|
||||
* of a new jump until either the source chain is reached (loop) or all
|
||||
|
||||
@@ -47,6 +47,8 @@ static const int nfnl_group2type[NFNLGRP_MAX+1] = {
|
||||
[NFNLGRP_CONNTRACK_EXP_NEW] = NFNL_SUBSYS_CTNETLINK_EXP,
|
||||
[NFNLGRP_CONNTRACK_EXP_UPDATE] = NFNL_SUBSYS_CTNETLINK_EXP,
|
||||
[NFNLGRP_CONNTRACK_EXP_DESTROY] = NFNL_SUBSYS_CTNETLINK_EXP,
|
||||
[NFNLGRP_NFTABLES] = NFNL_SUBSYS_NFTABLES,
|
||||
[NFNLGRP_ACCT_QUOTA] = NFNL_SUBSYS_ACCT,
|
||||
};
|
||||
|
||||
void nfnl_lock(__u8 subsys_id)
|
||||
@@ -464,7 +466,12 @@ static void nfnetlink_rcv(struct sk_buff *skb)
|
||||
static int nfnetlink_bind(int group)
|
||||
{
|
||||
const struct nfnetlink_subsystem *ss;
|
||||
int type = nfnl_group2type[group];
|
||||
int type;
|
||||
|
||||
if (group <= NFNLGRP_NONE || group > NFNLGRP_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
type = nfnl_group2type[group];
|
||||
|
||||
rcu_read_lock();
|
||||
ss = nfnetlink_get_subsys(type);
|
||||
@@ -514,6 +521,9 @@ static int __init nfnetlink_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = NFNLGRP_NONE + 1; i <= NFNLGRP_MAX; i++)
|
||||
BUG_ON(nfnl_group2type[i] == NFNL_SUBSYS_NONE);
|
||||
|
||||
for (i=0; i<NFNL_SUBSYS_COUNT; i++)
|
||||
mutex_init(&table[i].mutex);
|
||||
|
||||
|
||||
@@ -43,7 +43,8 @@
|
||||
#define NFULNL_NLBUFSIZ_DEFAULT NLMSG_GOODSIZE
|
||||
#define NFULNL_TIMEOUT_DEFAULT 100 /* every second */
|
||||
#define NFULNL_QTHRESH_DEFAULT 100 /* 100 packets */
|
||||
#define NFULNL_COPY_RANGE_MAX 0xFFFF /* max packet size is limited by 16-bit struct nfattr nfa_len field */
|
||||
/* max packet size is limited by 16-bit struct nfattr nfa_len field */
|
||||
#define NFULNL_COPY_RANGE_MAX (0xFFFF - NLA_HDRLEN)
|
||||
|
||||
#define PRINTR(x, args...) do { if (net_ratelimit()) \
|
||||
printk(x, ## args); } while (0);
|
||||
@@ -252,6 +253,8 @@ nfulnl_set_mode(struct nfulnl_instance *inst, u_int8_t mode,
|
||||
|
||||
case NFULNL_COPY_PACKET:
|
||||
inst->copy_mode = mode;
|
||||
if (range == 0)
|
||||
range = NFULNL_COPY_RANGE_MAX;
|
||||
inst->copy_range = min_t(unsigned int,
|
||||
range, NFULNL_COPY_RANGE_MAX);
|
||||
break;
|
||||
@@ -343,26 +346,25 @@ nfulnl_alloc_skb(struct net *net, u32 peer_portid, unsigned int inst_size,
|
||||
return skb;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
__nfulnl_send(struct nfulnl_instance *inst)
|
||||
{
|
||||
int status = -1;
|
||||
|
||||
if (inst->qlen > 1) {
|
||||
struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0,
|
||||
NLMSG_DONE,
|
||||
sizeof(struct nfgenmsg),
|
||||
0);
|
||||
if (!nlh)
|
||||
if (WARN_ONCE(!nlh, "bad nlskb size: %u, tailroom %d\n",
|
||||
inst->skb->len, skb_tailroom(inst->skb))) {
|
||||
kfree_skb(inst->skb);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
status = nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid,
|
||||
MSG_DONTWAIT);
|
||||
|
||||
nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid,
|
||||
MSG_DONTWAIT);
|
||||
out:
|
||||
inst->qlen = 0;
|
||||
inst->skb = NULL;
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -649,7 +651,8 @@ nfulnl_log_packet(struct net *net,
|
||||
+ nla_total_size(sizeof(u_int32_t)) /* gid */
|
||||
+ nla_total_size(plen) /* prefix */
|
||||
+ nla_total_size(sizeof(struct nfulnl_msg_packet_hw))
|
||||
+ nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp));
|
||||
+ nla_total_size(sizeof(struct nfulnl_msg_packet_timestamp))
|
||||
+ nla_total_size(sizeof(struct nfgenmsg)); /* NLMSG_DONE */
|
||||
|
||||
if (in && skb_mac_header_was_set(skb)) {
|
||||
size += nla_total_size(skb->dev->hard_header_len)
|
||||
@@ -678,8 +681,7 @@ nfulnl_log_packet(struct net *net,
|
||||
break;
|
||||
|
||||
case NFULNL_COPY_PACKET:
|
||||
if (inst->copy_range == 0
|
||||
|| inst->copy_range > skb->len)
|
||||
if (inst->copy_range > skb->len)
|
||||
data_len = skb->len;
|
||||
else
|
||||
data_len = inst->copy_range;
|
||||
@@ -692,8 +694,7 @@ nfulnl_log_packet(struct net *net,
|
||||
goto unlock_and_release;
|
||||
}
|
||||
|
||||
if (inst->skb &&
|
||||
size > skb_tailroom(inst->skb) - sizeof(struct nfgenmsg)) {
|
||||
if (inst->skb && size > skb_tailroom(inst->skb)) {
|
||||
/* either the queue len is too high or we don't have
|
||||
* enough room in the skb left. flush to userspace. */
|
||||
__nfulnl_flush(inst);
|
||||
|
||||
@@ -665,7 +665,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
|
||||
* returned by nf_queue. For instance, callers rely on -ECANCELED to
|
||||
* mean 'ignore this hook'.
|
||||
*/
|
||||
if (IS_ERR(segs))
|
||||
if (IS_ERR_OR_NULL(segs))
|
||||
goto out_err;
|
||||
queued = 0;
|
||||
err = 0;
|
||||
|
||||
+45
-12
@@ -19,9 +19,24 @@
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <asm/uaccess.h> /* for set_fs */
|
||||
#include <net/netfilter/nf_tables.h>
|
||||
|
||||
static int nft_compat_chain_validate_dependency(const char *tablename,
|
||||
const struct nft_chain *chain)
|
||||
{
|
||||
const struct nft_base_chain *basechain;
|
||||
|
||||
if (!tablename || !(chain->flags & NFT_BASE_CHAIN))
|
||||
return 0;
|
||||
|
||||
basechain = nft_base_chain(chain);
|
||||
if (strcmp(tablename, "nat") == 0 &&
|
||||
basechain->type->type != NFT_CHAIN_T_NAT)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
union nft_entry {
|
||||
struct ipt_entry e4;
|
||||
struct ip6t_entry e6;
|
||||
@@ -74,7 +89,7 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
|
||||
struct xt_target *target, void *info,
|
||||
union nft_entry *entry, u8 proto, bool inv)
|
||||
{
|
||||
par->net = &init_net;
|
||||
par->net = ctx->net;
|
||||
par->table = ctx->table->name;
|
||||
switch (ctx->afi->family) {
|
||||
case AF_INET:
|
||||
@@ -95,6 +110,8 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
|
||||
const struct nf_hook_ops *ops = &basechain->ops[0];
|
||||
|
||||
par->hook_mask = 1 << ops->hooknum;
|
||||
} else {
|
||||
par->hook_mask = 0;
|
||||
}
|
||||
par->family = ctx->afi->family;
|
||||
}
|
||||
@@ -151,6 +168,10 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
union nft_entry e = {};
|
||||
int ret;
|
||||
|
||||
ret = nft_compat_chain_validate_dependency(target->table, ctx->chain);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
target_compat_from_user(target, nla_data(tb[NFTA_TARGET_INFO]), info);
|
||||
|
||||
if (ctx->nla[NFTA_RULE_COMPAT]) {
|
||||
@@ -216,6 +237,7 @@ static int nft_target_validate(const struct nft_ctx *ctx,
|
||||
{
|
||||
struct xt_target *target = expr->ops->data;
|
||||
unsigned int hook_mask = 0;
|
||||
int ret;
|
||||
|
||||
if (ctx->chain->flags & NFT_BASE_CHAIN) {
|
||||
const struct nft_base_chain *basechain =
|
||||
@@ -223,11 +245,13 @@ static int nft_target_validate(const struct nft_ctx *ctx,
|
||||
const struct nf_hook_ops *ops = &basechain->ops[0];
|
||||
|
||||
hook_mask = 1 << ops->hooknum;
|
||||
if (hook_mask & target->hooks)
|
||||
return 0;
|
||||
if (!(hook_mask & target->hooks))
|
||||
return -EINVAL;
|
||||
|
||||
/* This target is being called from an invalid chain */
|
||||
return -EINVAL;
|
||||
ret = nft_compat_chain_validate_dependency(target->table,
|
||||
ctx->chain);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -272,7 +296,7 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
|
||||
struct xt_match *match, void *info,
|
||||
union nft_entry *entry, u8 proto, bool inv)
|
||||
{
|
||||
par->net = &init_net;
|
||||
par->net = ctx->net;
|
||||
par->table = ctx->table->name;
|
||||
switch (ctx->afi->family) {
|
||||
case AF_INET:
|
||||
@@ -293,6 +317,8 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
|
||||
const struct nf_hook_ops *ops = &basechain->ops[0];
|
||||
|
||||
par->hook_mask = 1 << ops->hooknum;
|
||||
} else {
|
||||
par->hook_mask = 0;
|
||||
}
|
||||
par->family = ctx->afi->family;
|
||||
}
|
||||
@@ -320,6 +346,10 @@ nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
union nft_entry e = {};
|
||||
int ret;
|
||||
|
||||
ret = nft_compat_chain_validate_dependency(match->table, ctx->chain);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
match_compat_from_user(match, nla_data(tb[NFTA_MATCH_INFO]), info);
|
||||
|
||||
if (ctx->nla[NFTA_RULE_COMPAT]) {
|
||||
@@ -379,6 +409,7 @@ static int nft_match_validate(const struct nft_ctx *ctx,
|
||||
{
|
||||
struct xt_match *match = expr->ops->data;
|
||||
unsigned int hook_mask = 0;
|
||||
int ret;
|
||||
|
||||
if (ctx->chain->flags & NFT_BASE_CHAIN) {
|
||||
const struct nft_base_chain *basechain =
|
||||
@@ -386,11 +417,13 @@ static int nft_match_validate(const struct nft_ctx *ctx,
|
||||
const struct nf_hook_ops *ops = &basechain->ops[0];
|
||||
|
||||
hook_mask = 1 << ops->hooknum;
|
||||
if (hook_mask & match->hooks)
|
||||
return 0;
|
||||
if (!(hook_mask & match->hooks))
|
||||
return -EINVAL;
|
||||
|
||||
/* This match is being called from an invalid chain */
|
||||
return -EINVAL;
|
||||
ret = nft_compat_chain_validate_dependency(match->table,
|
||||
ctx->chain);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -611,7 +644,7 @@ nft_target_select_ops(const struct nft_ctx *ctx,
|
||||
family = ctx->afi->family;
|
||||
|
||||
/* Re-use the existing target if it's already loaded. */
|
||||
list_for_each_entry(nft_target, &nft_match_list, head) {
|
||||
list_for_each_entry(nft_target, &nft_target_list, head) {
|
||||
struct xt_target *target = nft_target->ops.data;
|
||||
|
||||
if (strcmp(target->name, tg_name) == 0 &&
|
||||
|
||||
@@ -26,6 +26,11 @@ int nft_masq_init(const struct nft_ctx *ctx,
|
||||
const struct nlattr * const tb[])
|
||||
{
|
||||
struct nft_masq *priv = nft_expr_priv(expr);
|
||||
int err;
|
||||
|
||||
err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[NFTA_MASQ_FLAGS] == NULL)
|
||||
return 0;
|
||||
@@ -55,5 +60,12 @@ nla_put_failure:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_masq_dump);
|
||||
|
||||
int nft_masq_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
const struct nft_data **data)
|
||||
{
|
||||
return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_masq_validate);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>");
|
||||
|
||||
+54
-32
@@ -95,7 +95,13 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
u32 family;
|
||||
int err;
|
||||
|
||||
if (tb[NFTA_NAT_TYPE] == NULL)
|
||||
err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[NFTA_NAT_TYPE] == NULL ||
|
||||
(tb[NFTA_NAT_REG_ADDR_MIN] == NULL &&
|
||||
tb[NFTA_NAT_REG_PROTO_MIN] == NULL))
|
||||
return -EINVAL;
|
||||
|
||||
switch (ntohl(nla_get_be32(tb[NFTA_NAT_TYPE]))) {
|
||||
@@ -120,38 +126,44 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
priv->family = family;
|
||||
|
||||
if (tb[NFTA_NAT_REG_ADDR_MIN]) {
|
||||
priv->sreg_addr_min = ntohl(nla_get_be32(
|
||||
tb[NFTA_NAT_REG_ADDR_MIN]));
|
||||
priv->sreg_addr_min =
|
||||
ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MIN]));
|
||||
|
||||
err = nft_validate_input_register(priv->sreg_addr_min);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[NFTA_NAT_REG_ADDR_MAX]) {
|
||||
priv->sreg_addr_max =
|
||||
ntohl(nla_get_be32(tb[NFTA_NAT_REG_ADDR_MAX]));
|
||||
|
||||
err = nft_validate_input_register(priv->sreg_addr_max);
|
||||
if (err < 0)
|
||||
return err;
|
||||
} else {
|
||||
priv->sreg_addr_max = priv->sreg_addr_min;
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[NFTA_NAT_REG_ADDR_MAX]) {
|
||||
priv->sreg_addr_max = ntohl(nla_get_be32(
|
||||
tb[NFTA_NAT_REG_ADDR_MAX]));
|
||||
err = nft_validate_input_register(priv->sreg_addr_max);
|
||||
if (err < 0)
|
||||
return err;
|
||||
} else
|
||||
priv->sreg_addr_max = priv->sreg_addr_min;
|
||||
|
||||
if (tb[NFTA_NAT_REG_PROTO_MIN]) {
|
||||
priv->sreg_proto_min = ntohl(nla_get_be32(
|
||||
tb[NFTA_NAT_REG_PROTO_MIN]));
|
||||
priv->sreg_proto_min =
|
||||
ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MIN]));
|
||||
|
||||
err = nft_validate_input_register(priv->sreg_proto_min);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (tb[NFTA_NAT_REG_PROTO_MAX]) {
|
||||
priv->sreg_proto_max = ntohl(nla_get_be32(
|
||||
tb[NFTA_NAT_REG_PROTO_MAX]));
|
||||
err = nft_validate_input_register(priv->sreg_proto_max);
|
||||
if (err < 0)
|
||||
return err;
|
||||
} else
|
||||
priv->sreg_proto_max = priv->sreg_proto_min;
|
||||
if (tb[NFTA_NAT_REG_PROTO_MAX]) {
|
||||
priv->sreg_proto_max =
|
||||
ntohl(nla_get_be32(tb[NFTA_NAT_REG_PROTO_MAX]));
|
||||
|
||||
err = nft_validate_input_register(priv->sreg_proto_max);
|
||||
if (err < 0)
|
||||
return err;
|
||||
} else {
|
||||
priv->sreg_proto_max = priv->sreg_proto_min;
|
||||
}
|
||||
}
|
||||
|
||||
if (tb[NFTA_NAT_FLAGS]) {
|
||||
priv->flags = ntohl(nla_get_be32(tb[NFTA_NAT_FLAGS]));
|
||||
@@ -179,17 +191,19 @@ static int nft_nat_dump(struct sk_buff *skb, const struct nft_expr *expr)
|
||||
|
||||
if (nla_put_be32(skb, NFTA_NAT_FAMILY, htonl(priv->family)))
|
||||
goto nla_put_failure;
|
||||
if (nla_put_be32(skb,
|
||||
NFTA_NAT_REG_ADDR_MIN, htonl(priv->sreg_addr_min)))
|
||||
goto nla_put_failure;
|
||||
if (nla_put_be32(skb,
|
||||
NFTA_NAT_REG_ADDR_MAX, htonl(priv->sreg_addr_max)))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (priv->sreg_addr_min) {
|
||||
if (nla_put_be32(skb, NFTA_NAT_REG_ADDR_MIN,
|
||||
htonl(priv->sreg_addr_min)) ||
|
||||
nla_put_be32(skb, NFTA_NAT_REG_ADDR_MAX,
|
||||
htonl(priv->sreg_addr_max)))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
if (priv->sreg_proto_min) {
|
||||
if (nla_put_be32(skb, NFTA_NAT_REG_PROTO_MIN,
|
||||
htonl(priv->sreg_proto_min)))
|
||||
goto nla_put_failure;
|
||||
if (nla_put_be32(skb, NFTA_NAT_REG_PROTO_MAX,
|
||||
htonl(priv->sreg_proto_min)) ||
|
||||
nla_put_be32(skb, NFTA_NAT_REG_PROTO_MAX,
|
||||
htonl(priv->sreg_proto_max)))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
@@ -205,6 +219,13 @@ nla_put_failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int nft_nat_validate(const struct nft_ctx *ctx,
|
||||
const struct nft_expr *expr,
|
||||
const struct nft_data **data)
|
||||
{
|
||||
return nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT);
|
||||
}
|
||||
|
||||
static struct nft_expr_type nft_nat_type;
|
||||
static const struct nft_expr_ops nft_nat_ops = {
|
||||
.type = &nft_nat_type,
|
||||
@@ -212,6 +233,7 @@ static const struct nft_expr_ops nft_nat_ops = {
|
||||
.eval = nft_nat_eval,
|
||||
.init = nft_nat_init,
|
||||
.dump = nft_nat_dump,
|
||||
.validate = nft_nat_validate,
|
||||
};
|
||||
|
||||
static struct nft_expr_type nft_nat_type __read_mostly = {
|
||||
|
||||
Reference in New Issue
Block a user