Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Pull networking fixes from David Miller:
1) Use netif_rx_ni() when necessary in batman-adv stack, from Jussi
Kivilinna.
2) Fix loss of RTT samples in rxrpc, from David Howells.
3) Memory leak in hns_nic_dev_probe(), from Dignhao Liu.
4) ravb module cannot be unloaded, fix from Yuusuke Ashizuka.
5) We disable BH for too lokng in sctp_get_port_local(), add a
cond_resched() here as well, from Xin Long.
6) Fix memory leak in st95hf_in_send_cmd, from Dinghao Liu.
7) Out of bound access in bpf_raw_tp_link_fill_link_info(), from
Yonghong Song.
8) Missing of_node_put() in mt7530 DSA driver, from Sumera
Priyadarsini.
9) Fix crash in bnxt_fw_reset_task(), from Michael Chan.
10) Fix geneve tunnel checksumming bug in hns3, from Yi Li.
11) Memory leak in rxkad_verify_response, from Dinghao Liu.
12) In tipc, don't use smp_processor_id() in preemptible context. From
Tuong Lien.
13) Fix signedness issue in mlx4 memory allocation, from Shung-Hsi Yu.
14) Missing clk_disable_prepare() in gemini driver, from Dan Carpenter.
15) Fix ABI mismatch between driver and firmware in nfp, from Louis
Peens.
* git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net: (110 commits)
net/smc: fix sock refcounting in case of termination
net/smc: reset sndbuf_desc if freed
net/smc: set rx_off for SMCR explicitly
net/smc: fix toleration of fake add_link messages
tg3: Fix soft lockup when tg3_reset_task() fails.
doc: net: dsa: Fix typo in config code sample
net: dp83867: Fix WoL SecureOn password
nfp: flower: fix ABI mismatch between driver and firmware
tipc: fix shutdown() of connectionless socket
ipv6: Fix sysctl max for fib_multipath_hash_policy
drivers/net/wan/hdlc: Change the default of hard_header_len to 0
net: gemini: Fix another missing clk_disable_unprepare() in probe
net: bcmgenet: fix mask check in bcmgenet_validate_flow()
amd-xgbe: Add support for new port mode
net: usb: dm9601: Add USB ID of Keenetic Plus DSL
vhost: fix typo in error message
net: ethernet: mlx4: Fix memory allocation in mlx4_buddy_init()
pktgen: fix error message with wrong function name
net: ethernet: ti: am65-cpsw: fix rmii 100Mbit link mode
cxgb4: fix thermal zone device registration
...
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Connection tracking support for PPTP (Point to Point Tunneling Protocol).
|
||||
* PPTP is a a protocol for creating virtual private networks.
|
||||
* PPTP is a protocol for creating virtual private networks.
|
||||
* It is a specification defined by Microsoft and some vendors
|
||||
* working with Microsoft. PPTP is built on top of a modified
|
||||
* version of the Internet Generic Routing Encapsulation Protocol.
|
||||
|
||||
@@ -62,6 +62,8 @@ static const unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX] = {
|
||||
[SCTP_CONNTRACK_HEARTBEAT_ACKED] = 210 SECS,
|
||||
};
|
||||
|
||||
#define SCTP_FLAG_HEARTBEAT_VTAG_FAILED 1
|
||||
|
||||
#define sNO SCTP_CONNTRACK_NONE
|
||||
#define sCL SCTP_CONNTRACK_CLOSED
|
||||
#define sCW SCTP_CONNTRACK_COOKIE_WAIT
|
||||
@@ -369,6 +371,7 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct,
|
||||
u_int32_t offset, count;
|
||||
unsigned int *timeouts;
|
||||
unsigned long map[256 / sizeof(unsigned long)] = { 0 };
|
||||
bool ignore = false;
|
||||
|
||||
if (sctp_error(skb, dataoff, state))
|
||||
return -NF_ACCEPT;
|
||||
@@ -427,15 +430,39 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct,
|
||||
/* Sec 8.5.1 (D) */
|
||||
if (sh->vtag != ct->proto.sctp.vtag[dir])
|
||||
goto out_unlock;
|
||||
} else if (sch->type == SCTP_CID_HEARTBEAT ||
|
||||
sch->type == SCTP_CID_HEARTBEAT_ACK) {
|
||||
} else if (sch->type == SCTP_CID_HEARTBEAT) {
|
||||
if (ct->proto.sctp.vtag[dir] == 0) {
|
||||
pr_debug("Setting %d vtag %x for dir %d\n", sch->type, sh->vtag, dir);
|
||||
ct->proto.sctp.vtag[dir] = sh->vtag;
|
||||
} else if (sh->vtag != ct->proto.sctp.vtag[dir]) {
|
||||
if (test_bit(SCTP_CID_DATA, map) || ignore)
|
||||
goto out_unlock;
|
||||
|
||||
ct->proto.sctp.flags |= SCTP_FLAG_HEARTBEAT_VTAG_FAILED;
|
||||
ct->proto.sctp.last_dir = dir;
|
||||
ignore = true;
|
||||
continue;
|
||||
} else if (ct->proto.sctp.flags & SCTP_FLAG_HEARTBEAT_VTAG_FAILED) {
|
||||
ct->proto.sctp.flags &= ~SCTP_FLAG_HEARTBEAT_VTAG_FAILED;
|
||||
}
|
||||
} else if (sch->type == SCTP_CID_HEARTBEAT_ACK) {
|
||||
if (ct->proto.sctp.vtag[dir] == 0) {
|
||||
pr_debug("Setting vtag %x for dir %d\n",
|
||||
sh->vtag, dir);
|
||||
ct->proto.sctp.vtag[dir] = sh->vtag;
|
||||
} else if (sh->vtag != ct->proto.sctp.vtag[dir]) {
|
||||
pr_debug("Verification tag check failed\n");
|
||||
goto out_unlock;
|
||||
if (test_bit(SCTP_CID_DATA, map) || ignore)
|
||||
goto out_unlock;
|
||||
|
||||
if ((ct->proto.sctp.flags & SCTP_FLAG_HEARTBEAT_VTAG_FAILED) == 0 ||
|
||||
ct->proto.sctp.last_dir == dir)
|
||||
goto out_unlock;
|
||||
|
||||
ct->proto.sctp.flags &= ~SCTP_FLAG_HEARTBEAT_VTAG_FAILED;
|
||||
ct->proto.sctp.vtag[dir] = sh->vtag;
|
||||
ct->proto.sctp.vtag[!dir] = 0;
|
||||
} else if (ct->proto.sctp.flags & SCTP_FLAG_HEARTBEAT_VTAG_FAILED) {
|
||||
ct->proto.sctp.flags &= ~SCTP_FLAG_HEARTBEAT_VTAG_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -470,6 +497,10 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct,
|
||||
}
|
||||
spin_unlock_bh(&ct->lock);
|
||||
|
||||
/* allow but do not refresh timeout */
|
||||
if (ignore)
|
||||
return NF_ACCEPT;
|
||||
|
||||
timeouts = nf_ct_timeout_lookup(ct);
|
||||
if (!timeouts)
|
||||
timeouts = nf_sctp_pernet(nf_ct_net(ct))->timeouts;
|
||||
|
||||
@@ -1152,7 +1152,7 @@ int nf_conntrack_tcp_packet(struct nf_conn *ct,
|
||||
&& (old_state == TCP_CONNTRACK_SYN_RECV
|
||||
|| old_state == TCP_CONNTRACK_ESTABLISHED)
|
||||
&& new_state == TCP_CONNTRACK_ESTABLISHED) {
|
||||
/* Set ASSURED if we see see valid ack in ESTABLISHED
|
||||
/* Set ASSURED if we see valid ack in ESTABLISHED
|
||||
after SYN_RECV or a valid answer for a picked up
|
||||
connection. */
|
||||
set_bit(IPS_ASSURED_BIT, &ct->status);
|
||||
|
||||
@@ -81,18 +81,6 @@ static bool udp_error(struct sk_buff *skb,
|
||||
return false;
|
||||
}
|
||||
|
||||
static void nf_conntrack_udp_refresh_unreplied(struct nf_conn *ct,
|
||||
struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
u32 extra_jiffies)
|
||||
{
|
||||
if (unlikely(ctinfo == IP_CT_ESTABLISHED_REPLY &&
|
||||
ct->status & IPS_NAT_CLASH))
|
||||
nf_ct_kill(ct);
|
||||
else
|
||||
nf_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies);
|
||||
}
|
||||
|
||||
/* Returns verdict for packet, and may modify conntracktype */
|
||||
int nf_conntrack_udp_packet(struct nf_conn *ct,
|
||||
struct sk_buff *skb,
|
||||
@@ -124,12 +112,15 @@ int nf_conntrack_udp_packet(struct nf_conn *ct,
|
||||
|
||||
nf_ct_refresh_acct(ct, ctinfo, skb, extra);
|
||||
|
||||
/* never set ASSURED for IPS_NAT_CLASH, they time out soon */
|
||||
if (unlikely((ct->status & IPS_NAT_CLASH)))
|
||||
return NF_ACCEPT;
|
||||
|
||||
/* Also, more likely to be important, and not a probe */
|
||||
if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
|
||||
nf_conntrack_event_cache(IPCT_ASSURED, ct);
|
||||
} else {
|
||||
nf_conntrack_udp_refresh_unreplied(ct, skb, ctinfo,
|
||||
timeouts[UDP_CT_UNREPLIED]);
|
||||
nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[UDP_CT_UNREPLIED]);
|
||||
}
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
@@ -206,12 +197,15 @@ int nf_conntrack_udplite_packet(struct nf_conn *ct,
|
||||
if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
|
||||
nf_ct_refresh_acct(ct, ctinfo, skb,
|
||||
timeouts[UDP_CT_REPLIED]);
|
||||
|
||||
if (unlikely((ct->status & IPS_NAT_CLASH)))
|
||||
return NF_ACCEPT;
|
||||
|
||||
/* Also, more likely to be important, and not a probe */
|
||||
if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
|
||||
nf_conntrack_event_cache(IPCT_ASSURED, ct);
|
||||
} else {
|
||||
nf_conntrack_udp_refresh_unreplied(ct, skb, ctinfo,
|
||||
timeouts[UDP_CT_UNREPLIED]);
|
||||
nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[UDP_CT_UNREPLIED]);
|
||||
}
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
@@ -815,11 +815,11 @@ static int nf_tables_gettable(struct net *net, struct sock *nlsk,
|
||||
nlh->nlmsg_seq, NFT_MSG_NEWTABLE, 0,
|
||||
family, table);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
goto err_fill_table_info;
|
||||
|
||||
return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
|
||||
return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
|
||||
|
||||
err:
|
||||
err_fill_table_info:
|
||||
kfree_skb(skb2);
|
||||
return err;
|
||||
}
|
||||
@@ -1563,11 +1563,11 @@ static int nf_tables_getchain(struct net *net, struct sock *nlsk,
|
||||
nlh->nlmsg_seq, NFT_MSG_NEWCHAIN, 0,
|
||||
family, table, chain);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
goto err_fill_chain_info;
|
||||
|
||||
return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
|
||||
return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
|
||||
|
||||
err:
|
||||
err_fill_chain_info:
|
||||
kfree_skb(skb2);
|
||||
return err;
|
||||
}
|
||||
@@ -3008,11 +3008,11 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk,
|
||||
nlh->nlmsg_seq, NFT_MSG_NEWRULE, 0,
|
||||
family, table, chain, rule, NULL);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
goto err_fill_rule_info;
|
||||
|
||||
return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
|
||||
return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
|
||||
|
||||
err:
|
||||
err_fill_rule_info:
|
||||
kfree_skb(skb2);
|
||||
return err;
|
||||
}
|
||||
@@ -3770,7 +3770,8 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
if (nla_put(skb, NFTA_SET_USERDATA, set->udlen, set->udata))
|
||||
if (set->udata &&
|
||||
nla_put(skb, NFTA_SET_USERDATA, set->udlen, set->udata))
|
||||
goto nla_put_failure;
|
||||
|
||||
nest = nla_nest_start_noflag(skb, NFTA_SET_DESC);
|
||||
@@ -3967,11 +3968,11 @@ static int nf_tables_getset(struct net *net, struct sock *nlsk,
|
||||
|
||||
err = nf_tables_fill_set(skb2, &ctx, set, NFT_MSG_NEWSET, 0);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
goto err_fill_set_info;
|
||||
|
||||
return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
|
||||
return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
|
||||
|
||||
err:
|
||||
err_fill_set_info:
|
||||
kfree_skb(skb2);
|
||||
return err;
|
||||
}
|
||||
@@ -4859,24 +4860,18 @@ static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,
|
||||
err = -ENOMEM;
|
||||
skb = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
|
||||
if (skb == NULL)
|
||||
goto err1;
|
||||
return err;
|
||||
|
||||
err = nf_tables_fill_setelem_info(skb, ctx, ctx->seq, ctx->portid,
|
||||
NFT_MSG_NEWSETELEM, 0, set, &elem);
|
||||
if (err < 0)
|
||||
goto err2;
|
||||
goto err_fill_setelem;
|
||||
|
||||
err = nfnetlink_unicast(skb, ctx->net, ctx->portid, MSG_DONTWAIT);
|
||||
/* This avoids a loop in nfnetlink. */
|
||||
if (err < 0)
|
||||
goto err1;
|
||||
return nfnetlink_unicast(skb, ctx->net, ctx->portid);
|
||||
|
||||
return 0;
|
||||
err2:
|
||||
err_fill_setelem:
|
||||
kfree_skb(skb);
|
||||
err1:
|
||||
/* this avoids a loop in nfnetlink. */
|
||||
return err == -EAGAIN ? -ENOBUFS : err;
|
||||
return err;
|
||||
}
|
||||
|
||||
/* called with rcu_read_lock held */
|
||||
@@ -6181,10 +6176,11 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk,
|
||||
nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0,
|
||||
family, table, obj, reset);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
goto err_fill_obj_info;
|
||||
|
||||
return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
|
||||
err:
|
||||
return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
|
||||
|
||||
err_fill_obj_info:
|
||||
kfree_skb(skb2);
|
||||
return err;
|
||||
}
|
||||
@@ -7044,10 +7040,11 @@ static int nf_tables_getflowtable(struct net *net, struct sock *nlsk,
|
||||
NFT_MSG_NEWFLOWTABLE, 0, family,
|
||||
flowtable, &flowtable->hook_list);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
goto err_fill_flowtable_info;
|
||||
|
||||
return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
|
||||
err:
|
||||
return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
|
||||
|
||||
err_fill_flowtable_info:
|
||||
kfree_skb(skb2);
|
||||
return err;
|
||||
}
|
||||
@@ -7233,10 +7230,11 @@ static int nf_tables_getgen(struct net *net, struct sock *nlsk,
|
||||
err = nf_tables_fill_gen_info(skb2, net, NETLINK_CB(skb).portid,
|
||||
nlh->nlmsg_seq);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
goto err_fill_gen_info;
|
||||
|
||||
return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
|
||||
err:
|
||||
return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
|
||||
|
||||
err_fill_gen_info:
|
||||
kfree_skb(skb2);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -149,10 +149,15 @@ int nfnetlink_set_err(struct net *net, u32 portid, u32 group, int error)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfnetlink_set_err);
|
||||
|
||||
int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u32 portid,
|
||||
int flags)
|
||||
int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u32 portid)
|
||||
{
|
||||
return netlink_unicast(net->nfnl, skb, portid, flags);
|
||||
int err;
|
||||
|
||||
err = nlmsg_unicast(net->nfnl, skb, portid);
|
||||
if (err == -EAGAIN)
|
||||
err = -ENOBUFS;
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfnetlink_unicast);
|
||||
|
||||
|
||||
@@ -356,8 +356,7 @@ __nfulnl_send(struct nfulnl_instance *inst)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid,
|
||||
MSG_DONTWAIT);
|
||||
nfnetlink_unicast(inst->skb, inst->net, inst->peer_portid);
|
||||
out:
|
||||
inst->qlen = 0;
|
||||
inst->skb = NULL;
|
||||
|
||||
@@ -681,7 +681,7 @@ __nfqnl_enqueue_packet(struct net *net, struct nfqnl_instance *queue,
|
||||
*packet_id_ptr = htonl(entry->id);
|
||||
|
||||
/* nfnetlink_unicast will either free the nskb or add it to a socket */
|
||||
err = nfnetlink_unicast(nskb, net, queue->peer_portid, MSG_DONTWAIT);
|
||||
err = nfnetlink_unicast(nskb, net, queue->peer_portid);
|
||||
if (err < 0) {
|
||||
if (queue->flags & NFQA_CFG_F_FAIL_OPEN) {
|
||||
failopen = 1;
|
||||
|
||||
@@ -102,7 +102,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
|
||||
}
|
||||
|
||||
if (nf_ct_ext_exist(ct, NF_CT_EXT_HELPER) ||
|
||||
ct->status & IPS_SEQ_ADJUST)
|
||||
ct->status & (IPS_SEQ_ADJUST | IPS_NAT_CLASH))
|
||||
goto out;
|
||||
|
||||
if (!nf_ct_is_confirmed(ct))
|
||||
|
||||
@@ -87,7 +87,9 @@ void nft_payload_eval(const struct nft_expr *expr,
|
||||
u32 *dest = ®s->data[priv->dreg];
|
||||
int offset;
|
||||
|
||||
dest[priv->len / NFT_REG32_SIZE] = 0;
|
||||
if (priv->len % NFT_REG32_SIZE)
|
||||
dest[priv->len / NFT_REG32_SIZE] = 0;
|
||||
|
||||
switch (priv->base) {
|
||||
case NFT_PAYLOAD_LL_HEADER:
|
||||
if (!skb_mac_header_was_set(skb))
|
||||
|
||||
@@ -218,11 +218,11 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
|
||||
struct nft_rbtree_elem *new,
|
||||
struct nft_set_ext **ext)
|
||||
{
|
||||
bool overlap = false, dup_end_left = false, dup_end_right = false;
|
||||
struct nft_rbtree *priv = nft_set_priv(set);
|
||||
u8 genmask = nft_genmask_next(net);
|
||||
struct nft_rbtree_elem *rbe;
|
||||
struct rb_node *parent, **p;
|
||||
bool overlap = false;
|
||||
int d;
|
||||
|
||||
/* Detect overlaps as we descend the tree. Set the flag in these cases:
|
||||
@@ -238,24 +238,44 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
|
||||
*
|
||||
* b1. _ _ __>| !_ _ __| (insert end before existing start)
|
||||
* b2. _ _ ___| !_ _ _>| (insert end after existing start)
|
||||
* b3. _ _ ___! >|_ _ __| (insert start after existing end)
|
||||
* b3. _ _ ___! >|_ _ __| (insert start after existing end, as a leaf)
|
||||
* '--' no nodes falling in this range
|
||||
* b4. >|_ _ ! (insert start before existing start)
|
||||
*
|
||||
* Case a3. resolves to b3.:
|
||||
* - if the inserted start element is the leftmost, because the '0'
|
||||
* element in the tree serves as end element
|
||||
* - otherwise, if an existing end is found. Note that end elements are
|
||||
* always inserted after corresponding start elements.
|
||||
* - otherwise, if an existing end is found immediately to the left. If
|
||||
* there are existing nodes in between, we need to further descend the
|
||||
* tree before we can conclude the new start isn't causing an overlap
|
||||
*
|
||||
* or to b4., which, preceded by a3., means we already traversed one or
|
||||
* more existing intervals entirely, from the right.
|
||||
*
|
||||
* For a new, rightmost pair of elements, we'll hit cases b3. and b2.,
|
||||
* in that order.
|
||||
*
|
||||
* The flag is also cleared in two special cases:
|
||||
*
|
||||
* b4. |__ _ _!|<_ _ _ (insert start right before existing end)
|
||||
* b5. |__ _ >|!__ _ _ (insert end right after existing start)
|
||||
* b5. |__ _ _!|<_ _ _ (insert start right before existing end)
|
||||
* b6. |__ _ >|!__ _ _ (insert end right after existing start)
|
||||
*
|
||||
* which always happen as last step and imply that no further
|
||||
* overlapping is possible.
|
||||
*
|
||||
* Another special case comes from the fact that start elements matching
|
||||
* an already existing start element are allowed: insertion is not
|
||||
* performed but we return -EEXIST in that case, and the error will be
|
||||
* cleared by the caller if NLM_F_EXCL is not present in the request.
|
||||
* This way, request for insertion of an exact overlap isn't reported as
|
||||
* error to userspace if not desired.
|
||||
*
|
||||
* However, if the existing start matches a pre-existing start, but the
|
||||
* end element doesn't match the corresponding pre-existing end element,
|
||||
* we need to report a partial overlap. This is a local condition that
|
||||
* can be noticed without need for a tracking flag, by checking for a
|
||||
* local duplicated end for a corresponding start, from left and right,
|
||||
* separately.
|
||||
*/
|
||||
|
||||
parent = NULL;
|
||||
@@ -272,26 +292,41 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
|
||||
if (nft_rbtree_interval_start(new)) {
|
||||
if (nft_rbtree_interval_end(rbe) &&
|
||||
nft_set_elem_active(&rbe->ext, genmask) &&
|
||||
!nft_set_elem_expired(&rbe->ext))
|
||||
!nft_set_elem_expired(&rbe->ext) && !*p)
|
||||
overlap = false;
|
||||
} else {
|
||||
if (dup_end_left && !*p)
|
||||
return -ENOTEMPTY;
|
||||
|
||||
overlap = nft_rbtree_interval_end(rbe) &&
|
||||
nft_set_elem_active(&rbe->ext,
|
||||
genmask) &&
|
||||
!nft_set_elem_expired(&rbe->ext);
|
||||
|
||||
if (overlap) {
|
||||
dup_end_right = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else if (d > 0) {
|
||||
p = &parent->rb_right;
|
||||
|
||||
if (nft_rbtree_interval_end(new)) {
|
||||
if (dup_end_right && !*p)
|
||||
return -ENOTEMPTY;
|
||||
|
||||
overlap = nft_rbtree_interval_end(rbe) &&
|
||||
nft_set_elem_active(&rbe->ext,
|
||||
genmask) &&
|
||||
!nft_set_elem_expired(&rbe->ext);
|
||||
} else if (nft_rbtree_interval_end(rbe) &&
|
||||
nft_set_elem_active(&rbe->ext, genmask) &&
|
||||
|
||||
if (overlap) {
|
||||
dup_end_left = true;
|
||||
continue;
|
||||
}
|
||||
} else if (nft_set_elem_active(&rbe->ext, genmask) &&
|
||||
!nft_set_elem_expired(&rbe->ext)) {
|
||||
overlap = true;
|
||||
overlap = nft_rbtree_interval_end(rbe);
|
||||
}
|
||||
} else {
|
||||
if (nft_rbtree_interval_end(rbe) &&
|
||||
@@ -316,6 +351,8 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
|
||||
p = &parent->rb_left;
|
||||
}
|
||||
}
|
||||
|
||||
dup_end_left = dup_end_right = false;
|
||||
}
|
||||
|
||||
if (overlap)
|
||||
|
||||
@@ -640,7 +640,7 @@ static void __net_exit recent_proc_net_exit(struct net *net)
|
||||
struct recent_table *t;
|
||||
|
||||
/* recent_net_exit() is called before recent_mt_destroy(). Make sure
|
||||
* that the parent xt_recent proc entry is is empty before trying to
|
||||
* that the parent xt_recent proc entry is empty before trying to
|
||||
* remove it.
|
||||
*/
|
||||
spin_lock_bh(&recent_lock);
|
||||
|
||||
Reference in New Issue
Block a user