netfilter: use nfnetlink_unicast()
Replace netlink_unicast() calls by nfnetlink_unicast() which already deals with translating EAGAIN to ENOBUFS as the nfnetlink core expects. nfnetlink_unicast() calls nlmsg_unicast() which returns zero in case of success, otherwise the netlink core function netlink_rcv_skb() turns err > 0 into an acknowlegment. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
02d8514267
commit
e0241ae6ac
@ -1685,8 +1685,8 @@ static const struct nla_policy ip_set_adt_policy[IPSET_ATTR_CMD_MAX + 1] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
|
call_ad(struct net *net, struct sock *ctnl, struct sk_buff *skb,
|
||||||
struct nlattr *tb[], enum ipset_adt adt,
|
struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt,
|
||||||
u32 flags, bool use_lineno)
|
u32 flags, bool use_lineno)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -1738,8 +1738,7 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
|
|||||||
|
|
||||||
*errline = lineno;
|
*errline = lineno;
|
||||||
|
|
||||||
netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid,
|
nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
|
||||||
MSG_DONTWAIT);
|
|
||||||
/* Signal netlink not to send its ACK/errmsg. */
|
/* Signal netlink not to send its ACK/errmsg. */
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
}
|
}
|
||||||
@ -1783,7 +1782,7 @@ static int ip_set_ad(struct net *net, struct sock *ctnl,
|
|||||||
attr[IPSET_ATTR_DATA],
|
attr[IPSET_ATTR_DATA],
|
||||||
set->type->adt_policy, NULL))
|
set->type->adt_policy, NULL))
|
||||||
return -IPSET_ERR_PROTOCOL;
|
return -IPSET_ERR_PROTOCOL;
|
||||||
ret = call_ad(ctnl, skb, set, tb, adt, flags,
|
ret = call_ad(net, ctnl, skb, set, tb, adt, flags,
|
||||||
use_lineno);
|
use_lineno);
|
||||||
} else {
|
} else {
|
||||||
int nla_rem;
|
int nla_rem;
|
||||||
@ -1794,7 +1793,7 @@ static int ip_set_ad(struct net *net, struct sock *ctnl,
|
|||||||
nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
|
nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
|
||||||
set->type->adt_policy, NULL))
|
set->type->adt_policy, NULL))
|
||||||
return -IPSET_ERR_PROTOCOL;
|
return -IPSET_ERR_PROTOCOL;
|
||||||
ret = call_ad(ctnl, skb, set, tb, adt,
|
ret = call_ad(net, ctnl, skb, set, tb, adt,
|
||||||
flags, use_lineno);
|
flags, use_lineno);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
@ -1859,7 +1858,6 @@ static int ip_set_header(struct sk_buff *skb, const struct nfnl_info *info,
|
|||||||
const struct ip_set *set;
|
const struct ip_set *set;
|
||||||
struct sk_buff *skb2;
|
struct sk_buff *skb2;
|
||||||
struct nlmsghdr *nlh2;
|
struct nlmsghdr *nlh2;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (unlikely(protocol_min_failed(attr) ||
|
if (unlikely(protocol_min_failed(attr) ||
|
||||||
!attr[IPSET_ATTR_SETNAME]))
|
!attr[IPSET_ATTR_SETNAME]))
|
||||||
@ -1885,12 +1883,7 @@ static int ip_set_header(struct sk_buff *skb, const struct nfnl_info *info,
|
|||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
nlmsg_end(skb2, nlh2);
|
nlmsg_end(skb2, nlh2);
|
||||||
|
|
||||||
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
|
return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
|
||||||
MSG_DONTWAIT);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
nlmsg_cancel(skb2, nlh2);
|
nlmsg_cancel(skb2, nlh2);
|
||||||
@ -1945,12 +1938,7 @@ static int ip_set_type(struct sk_buff *skb, const struct nfnl_info *info,
|
|||||||
nlmsg_end(skb2, nlh2);
|
nlmsg_end(skb2, nlh2);
|
||||||
|
|
||||||
pr_debug("Send TYPE, nlmsg_len: %u\n", nlh2->nlmsg_len);
|
pr_debug("Send TYPE, nlmsg_len: %u\n", nlh2->nlmsg_len);
|
||||||
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
|
return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
|
||||||
MSG_DONTWAIT);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
nlmsg_cancel(skb2, nlh2);
|
nlmsg_cancel(skb2, nlh2);
|
||||||
@ -1971,7 +1959,6 @@ static int ip_set_protocol(struct sk_buff *skb, const struct nfnl_info *info,
|
|||||||
{
|
{
|
||||||
struct sk_buff *skb2;
|
struct sk_buff *skb2;
|
||||||
struct nlmsghdr *nlh2;
|
struct nlmsghdr *nlh2;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (unlikely(!attr[IPSET_ATTR_PROTOCOL]))
|
if (unlikely(!attr[IPSET_ATTR_PROTOCOL]))
|
||||||
return -IPSET_ERR_PROTOCOL;
|
return -IPSET_ERR_PROTOCOL;
|
||||||
@ -1990,12 +1977,7 @@ static int ip_set_protocol(struct sk_buff *skb, const struct nfnl_info *info,
|
|||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
nlmsg_end(skb2, nlh2);
|
nlmsg_end(skb2, nlh2);
|
||||||
|
|
||||||
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
|
return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
|
||||||
MSG_DONTWAIT);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
nlmsg_cancel(skb2, nlh2);
|
nlmsg_cancel(skb2, nlh2);
|
||||||
@ -2014,7 +1996,6 @@ static int ip_set_byname(struct sk_buff *skb, const struct nfnl_info *info,
|
|||||||
struct nlmsghdr *nlh2;
|
struct nlmsghdr *nlh2;
|
||||||
ip_set_id_t id = IPSET_INVALID_ID;
|
ip_set_id_t id = IPSET_INVALID_ID;
|
||||||
const struct ip_set *set;
|
const struct ip_set *set;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (unlikely(protocol_failed(attr) ||
|
if (unlikely(protocol_failed(attr) ||
|
||||||
!attr[IPSET_ATTR_SETNAME]))
|
!attr[IPSET_ATTR_SETNAME]))
|
||||||
@ -2038,12 +2019,7 @@ static int ip_set_byname(struct sk_buff *skb, const struct nfnl_info *info,
|
|||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
nlmsg_end(skb2, nlh2);
|
nlmsg_end(skb2, nlh2);
|
||||||
|
|
||||||
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
|
return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
|
||||||
MSG_DONTWAIT);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
nlmsg_cancel(skb2, nlh2);
|
nlmsg_cancel(skb2, nlh2);
|
||||||
@ -2065,7 +2041,6 @@ static int ip_set_byindex(struct sk_buff *skb, const struct nfnl_info *info,
|
|||||||
struct nlmsghdr *nlh2;
|
struct nlmsghdr *nlh2;
|
||||||
ip_set_id_t id = IPSET_INVALID_ID;
|
ip_set_id_t id = IPSET_INVALID_ID;
|
||||||
const struct ip_set *set;
|
const struct ip_set *set;
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (unlikely(protocol_failed(attr) ||
|
if (unlikely(protocol_failed(attr) ||
|
||||||
!attr[IPSET_ATTR_INDEX]))
|
!attr[IPSET_ATTR_INDEX]))
|
||||||
@ -2091,12 +2066,7 @@ static int ip_set_byindex(struct sk_buff *skb, const struct nfnl_info *info,
|
|||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
nlmsg_end(skb2, nlh2);
|
nlmsg_end(skb2, nlh2);
|
||||||
|
|
||||||
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
|
return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
|
||||||
MSG_DONTWAIT);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
nla_put_failure:
|
nla_put_failure:
|
||||||
nlmsg_cancel(skb2, nlh2);
|
nlmsg_cancel(skb2, nlh2);
|
||||||
|
@ -1628,9 +1628,8 @@ static int ctnetlink_get_conntrack(struct sk_buff *skb,
|
|||||||
|
|
||||||
ct = nf_ct_tuplehash_to_ctrack(h);
|
ct = nf_ct_tuplehash_to_ctrack(h);
|
||||||
|
|
||||||
err = -ENOMEM;
|
|
||||||
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||||
if (skb2 == NULL) {
|
if (!skb2) {
|
||||||
nf_ct_put(ct);
|
nf_ct_put(ct);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
@ -1640,21 +1639,12 @@ static int ctnetlink_get_conntrack(struct sk_buff *skb,
|
|||||||
NFNL_MSG_TYPE(info->nlh->nlmsg_type), ct,
|
NFNL_MSG_TYPE(info->nlh->nlmsg_type), ct,
|
||||||
true, 0);
|
true, 0);
|
||||||
nf_ct_put(ct);
|
nf_ct_put(ct);
|
||||||
if (err <= 0)
|
if (err <= 0) {
|
||||||
goto free;
|
kfree_skb(skb2);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
err = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
|
return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
|
||||||
MSG_DONTWAIT);
|
|
||||||
if (err < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
free:
|
|
||||||
kfree_skb(skb2);
|
|
||||||
out:
|
|
||||||
/* this avoids a loop in nfnetlink. */
|
|
||||||
return err == -EAGAIN ? -ENOBUFS : err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ctnetlink_done_list(struct netlink_callback *cb)
|
static int ctnetlink_done_list(struct netlink_callback *cb)
|
||||||
@ -2590,21 +2580,12 @@ static int ctnetlink_stat_ct(struct sk_buff *skb, const struct nfnl_info *info,
|
|||||||
info->nlh->nlmsg_seq,
|
info->nlh->nlmsg_seq,
|
||||||
NFNL_MSG_TYPE(info->nlh->nlmsg_type),
|
NFNL_MSG_TYPE(info->nlh->nlmsg_type),
|
||||||
sock_net(skb->sk));
|
sock_net(skb->sk));
|
||||||
if (err <= 0)
|
if (err <= 0) {
|
||||||
goto free;
|
kfree_skb(skb2);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
err = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
|
return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
|
||||||
MSG_DONTWAIT);
|
|
||||||
if (err < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
free:
|
|
||||||
kfree_skb(skb2);
|
|
||||||
out:
|
|
||||||
/* this avoids a loop in nfnetlink. */
|
|
||||||
return err == -EAGAIN ? -ENOBUFS : err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
|
static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
|
||||||
@ -3329,11 +3310,10 @@ static int ctnetlink_get_expect(struct sk_buff *skb,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = -ENOMEM;
|
|
||||||
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||||
if (skb2 == NULL) {
|
if (!skb2) {
|
||||||
nf_ct_expect_put(exp);
|
nf_ct_expect_put(exp);
|
||||||
goto out;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
@ -3342,21 +3322,12 @@ static int ctnetlink_get_expect(struct sk_buff *skb,
|
|||||||
exp);
|
exp);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
nf_ct_expect_put(exp);
|
nf_ct_expect_put(exp);
|
||||||
if (err <= 0)
|
if (err <= 0) {
|
||||||
goto free;
|
kfree_skb(skb2);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
err = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
|
return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
|
||||||
MSG_DONTWAIT);
|
|
||||||
if (err < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
free:
|
|
||||||
kfree_skb(skb2);
|
|
||||||
out:
|
|
||||||
/* this avoids a loop in nfnetlink. */
|
|
||||||
return err == -EAGAIN ? -ENOBUFS : err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool expect_iter_name(struct nf_conntrack_expect *exp, void *data)
|
static bool expect_iter_name(struct nf_conntrack_expect *exp, void *data)
|
||||||
|
@ -314,14 +314,11 @@ static int nfnl_acct_get(struct sk_buff *skb, const struct nfnl_info *info,
|
|||||||
kfree_skb(skb2);
|
kfree_skb(skb2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
|
|
||||||
MSG_DONTWAIT);
|
|
||||||
if (ret > 0)
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
/* this avoids a loop in nfnetlink. */
|
ret = nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
|
||||||
return ret == -EAGAIN ? -ENOBUFS : ret;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,14 +663,10 @@ static int nfnl_cthelper_get(struct sk_buff *skb, const struct nfnl_info *info,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
|
ret = nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
|
||||||
MSG_DONTWAIT);
|
break;
|
||||||
if (ret > 0)
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
/* this avoids a loop in nfnetlink. */
|
|
||||||
return ret == -EAGAIN ? -ENOBUFS : ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,14 +287,11 @@ static int cttimeout_get_timeout(struct sk_buff *skb,
|
|||||||
kfree_skb(skb2);
|
kfree_skb(skb2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
|
|
||||||
MSG_DONTWAIT);
|
|
||||||
if (ret > 0)
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
/* this avoids a loop in nfnetlink. */
|
ret = nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
|
||||||
return ret == -EAGAIN ? -ENOBUFS : ret;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,9 +424,9 @@ static int cttimeout_default_get(struct sk_buff *skb,
|
|||||||
const struct nf_conntrack_l4proto *l4proto;
|
const struct nf_conntrack_l4proto *l4proto;
|
||||||
unsigned int *timeouts = NULL;
|
unsigned int *timeouts = NULL;
|
||||||
struct sk_buff *skb2;
|
struct sk_buff *skb2;
|
||||||
int ret, err;
|
|
||||||
__u16 l3num;
|
__u16 l3num;
|
||||||
__u8 l4num;
|
__u8 l4num;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!cda[CTA_TIMEOUT_L3PROTO] || !cda[CTA_TIMEOUT_L4PROTO])
|
if (!cda[CTA_TIMEOUT_L3PROTO] || !cda[CTA_TIMEOUT_L4PROTO])
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -438,9 +435,8 @@ static int cttimeout_default_get(struct sk_buff *skb,
|
|||||||
l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
|
l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
|
||||||
l4proto = nf_ct_l4proto_find(l4num);
|
l4proto = nf_ct_l4proto_find(l4num);
|
||||||
|
|
||||||
err = -EOPNOTSUPP;
|
|
||||||
if (l4proto->l4proto != l4num)
|
if (l4proto->l4proto != l4num)
|
||||||
goto err;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
switch (l4proto->l4proto) {
|
switch (l4proto->l4proto) {
|
||||||
case IPPROTO_ICMP:
|
case IPPROTO_ICMP:
|
||||||
@ -480,13 +476,11 @@ static int cttimeout_default_get(struct sk_buff *skb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!timeouts)
|
if (!timeouts)
|
||||||
goto err;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||||
if (skb2 == NULL) {
|
if (!skb2)
|
||||||
err = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = cttimeout_default_fill_info(info->net, skb2,
|
ret = cttimeout_default_fill_info(info->net, skb2,
|
||||||
NETLINK_CB(skb).portid,
|
NETLINK_CB(skb).portid,
|
||||||
@ -496,18 +490,10 @@ static int cttimeout_default_get(struct sk_buff *skb,
|
|||||||
l3num, l4proto, timeouts);
|
l3num, l4proto, timeouts);
|
||||||
if (ret <= 0) {
|
if (ret <= 0) {
|
||||||
kfree_skb(skb2);
|
kfree_skb(skb2);
|
||||||
err = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto err;
|
|
||||||
}
|
}
|
||||||
ret = netlink_unicast(info->sk, skb2, NETLINK_CB(skb).portid,
|
|
||||||
MSG_DONTWAIT);
|
|
||||||
if (ret > 0)
|
|
||||||
ret = 0;
|
|
||||||
|
|
||||||
/* this avoids a loop in nfnetlink. */
|
return nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
|
||||||
return ret == -EAGAIN ? -ENOBUFS : ret;
|
|
||||||
err:
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nf_ct_timeout *ctnl_timeout_find_get(struct net *net,
|
static struct nf_ct_timeout *ctnl_timeout_find_get(struct net *net,
|
||||||
|
Loading…
Reference in New Issue
Block a user