Commit e80a07b2 authored by David S. Miller's avatar David S. Miller
Browse files


Pablo Neira Ayuso says:

====================
Netfilter/IPVS updates for net-next

The following patchset contains Netfilter updates for net-next:

1) Support for rejecting packets from the prerouting chain, from
   Laura Garcia Liebana.

2) Remove useless assignment in pipapo, from Stefano Brivio.

3) On demand hook registration in IPVS, from Julian Anastasov.

4) Expire IPVS connection from process context to not overload
   timers, also from Julian.

5) Fallback to conntrack TCP tracker to handle connection reuse
   in IPVS, from Julian Anastasov.

6) Several patches to support for chain bindings.

7) Expose enum nft_chain_flags through UAPI.

8) Reject unsupported chain flags from the netlink control plane.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3d07ae5f c1f79a2e
Loading
Loading
Loading
Loading
+9 −6
Original line number Diff line number Diff line
@@ -874,6 +874,7 @@ struct netns_ipvs {
	struct ip_vs_stats		tot_stats;  /* Statistics & est. */

	int			num_services;    /* no of virtual services */
	int			num_services6;   /* IPv6 virtual services */

	/* Trash for destinations */
	struct list_head	dest_trash;
@@ -960,6 +961,7 @@ struct netns_ipvs {
	 * are not supported when synchronization is enabled.
	 */
	unsigned int		mixed_address_family_dests;
	unsigned int		hooks_afmask;	/* &1=AF_INET, &2=AF_INET6 */
};

#define DEFAULT_SYNC_THRESHOLD	3
@@ -1624,18 +1626,16 @@ static inline void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp)
}
#endif /* CONFIG_IP_VS_NFCT */

/* Really using conntrack? */
static inline bool ip_vs_conn_uses_conntrack(struct ip_vs_conn *cp,
/* Using old conntrack that can not be redirected to another real server? */
static inline bool ip_vs_conn_uses_old_conntrack(struct ip_vs_conn *cp,
						 struct sk_buff *skb)
{
#ifdef CONFIG_IP_VS_NFCT
	enum ip_conntrack_info ctinfo;
	struct nf_conn *ct;

	if (!(cp->flags & IP_VS_CONN_F_NFCT))
		return false;
	ct = nf_ct_get(skb, &ctinfo);
	if (ct)
	if (ct && nf_ct_is_confirmed(ct))
		return true;
#endif
	return false;
@@ -1670,6 +1670,9 @@ static inline void ip_vs_unregister_conntrack(struct ip_vs_service *svc)
#endif
}

int ip_vs_register_hooks(struct netns_ipvs *ipvs, unsigned int af);
void ip_vs_unregister_hooks(struct netns_ipvs *ipvs, unsigned int af);

static inline int
ip_vs_dest_conn_overhead(struct ip_vs_dest *dest)
{
+16 −7
Original line number Diff line number Diff line
@@ -899,6 +899,8 @@ static inline struct nft_userdata *nft_userdata(const struct nft_rule *rule)
	return (void *)&rule->data[rule->dlen];
}

void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule);

static inline void nft_set_elem_update_expr(const struct nft_set_ext *ext,
					    struct nft_regs *regs,
					    const struct nft_pktinfo *pkt)
@@ -921,11 +923,6 @@ static inline void nft_set_elem_update_expr(const struct nft_set_ext *ext,
	     (expr) != (last); \
	     (expr) = nft_expr_next(expr))

enum nft_chain_flags {
	NFT_BASE_CHAIN			= 0x1,
	NFT_CHAIN_HW_OFFLOAD		= 0x2,
};

#define NFT_CHAIN_POLICY_UNSET		U8_MAX

/**
@@ -949,7 +946,8 @@ struct nft_chain {
	struct nft_table		*table;
	u64				handle;
	u32				use;
	u8				flags:6,
	u8				flags:5,
					bound:1,
					genmask:2;
	char				*name;

@@ -994,6 +992,14 @@ int nft_chain_validate_dependency(const struct nft_chain *chain,
int nft_chain_validate_hooks(const struct nft_chain *chain,
                             unsigned int hook_flags);

static inline bool nft_chain_is_bound(struct nft_chain *chain)
{
	return (chain->flags & NFT_CHAIN_BINDING) && chain->bound;
}

void nft_chain_del(struct nft_chain *chain);
void nf_tables_chain_destroy(struct nft_ctx *ctx);

struct nft_stats {
	u64			bytes;
	u64			pkts;
@@ -1036,7 +1042,7 @@ static inline struct nft_base_chain *nft_base_chain(const struct nft_chain *chai

static inline bool nft_is_base_chain(const struct nft_chain *chain)
{
	return chain->flags & NFT_BASE_CHAIN;
	return chain->flags & NFT_CHAIN_BASE;
}

int __nft_release_basechain(struct nft_ctx *ctx);
@@ -1433,6 +1439,7 @@ struct nft_trans_chain {
	char				*name;
	struct nft_stats __percpu	*stats;
	u8				policy;
	u32				chain_id;
};

#define nft_trans_chain_update(trans)	\
@@ -1443,6 +1450,8 @@ struct nft_trans_chain {
	(((struct nft_trans_chain *)trans->data)->stats)
#define nft_trans_chain_policy(trans)	\
	(((struct nft_trans_chain *)trans->data)->policy)
#define nft_trans_chain_id(trans)	\
	(((struct nft_trans_chain *)trans->data)->chain_id)

struct nft_trans_table {
	bool				update;
+14 −0
Original line number Diff line number Diff line
@@ -184,6 +184,15 @@ enum nft_table_attributes {
};
#define NFTA_TABLE_MAX		(__NFTA_TABLE_MAX - 1)

enum nft_chain_flags {
	NFT_CHAIN_BASE		= (1 << 0),
	NFT_CHAIN_HW_OFFLOAD	= (1 << 1),
	NFT_CHAIN_BINDING	= (1 << 2),
};
#define NFT_CHAIN_FLAGS		(NFT_CHAIN_BASE		| \
				 NFT_CHAIN_HW_OFFLOAD	| \
				 NFT_CHAIN_BINDING)

/**
 * enum nft_chain_attributes - nf_tables chain netlink attributes
 *
@@ -196,6 +205,7 @@ enum nft_table_attributes {
 * @NFTA_CHAIN_TYPE: type name of the string (NLA_NUL_STRING)
 * @NFTA_CHAIN_COUNTERS: counter specification of the chain (NLA_NESTED: nft_counter_attributes)
 * @NFTA_CHAIN_FLAGS: chain flags
 * @NFTA_CHAIN_ID: uniquely identifies a chain in a transaction (NLA_U32)
 */
enum nft_chain_attributes {
	NFTA_CHAIN_UNSPEC,
@@ -209,6 +219,7 @@ enum nft_chain_attributes {
	NFTA_CHAIN_COUNTERS,
	NFTA_CHAIN_PAD,
	NFTA_CHAIN_FLAGS,
	NFTA_CHAIN_ID,
	__NFTA_CHAIN_MAX
};
#define NFTA_CHAIN_MAX		(__NFTA_CHAIN_MAX - 1)
@@ -238,6 +249,7 @@ enum nft_rule_attributes {
	NFTA_RULE_PAD,
	NFTA_RULE_ID,
	NFTA_RULE_POSITION_ID,
	NFTA_RULE_CHAIN_ID,
	__NFTA_RULE_MAX
};
#define NFTA_RULE_MAX		(__NFTA_RULE_MAX - 1)
@@ -468,11 +480,13 @@ enum nft_data_attributes {
 *
 * @NFTA_VERDICT_CODE: nf_tables verdict (NLA_U32: enum nft_verdicts)
 * @NFTA_VERDICT_CHAIN: jump target chain name (NLA_STRING)
 * @NFTA_VERDICT_CHAIN_ID: jump target chain ID (NLA_U32)
 */
enum nft_verdict_attributes {
	NFTA_VERDICT_UNSPEC,
	NFTA_VERDICT_CODE,
	NFTA_VERDICT_CHAIN,
	NFTA_VERDICT_CHAIN_ID,
	__NFTA_VERDICT_MAX
};
#define NFTA_VERDICT_MAX	(__NFTA_VERDICT_MAX - 1)
+21 −0
Original line number Diff line number Diff line
@@ -96,6 +96,21 @@ void nf_reject_ip_tcphdr_put(struct sk_buff *nskb, const struct sk_buff *oldskb,
}
EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_put);

static int nf_reject_fill_skb_dst(struct sk_buff *skb_in)
{
	struct dst_entry *dst = NULL;
	struct flowi fl;

	memset(&fl, 0, sizeof(struct flowi));
	fl.u.ip4.daddr = ip_hdr(skb_in)->saddr;
	nf_ip_route(dev_net(skb_in->dev), &dst, &fl, false);
	if (!dst)
		return -1;

	skb_dst_set(skb_in, dst);
	return 0;
}

/* Send RST reply */
void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
{
@@ -109,6 +124,9 @@ void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
	if (!oth)
		return;

	if (hook == NF_INET_PRE_ROUTING && nf_reject_fill_skb_dst(oldskb))
		return;

	if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
		return;

@@ -175,6 +193,9 @@ void nf_send_unreach(struct sk_buff *skb_in, int code, int hook)
	if (iph->frag_off & htons(IP_OFFSET))
		return;

	if (hook == NF_INET_PRE_ROUTING && nf_reject_fill_skb_dst(skb_in))
		return;

	if (skb_csum_unnecessary(skb_in) || !nf_reject_verify_csum(proto)) {
		icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0);
		return;
+26 −0
Original line number Diff line number Diff line
@@ -126,6 +126,21 @@ void nf_reject_ip6_tcphdr_put(struct sk_buff *nskb,
}
EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_put);

static int nf_reject6_fill_skb_dst(struct sk_buff *skb_in)
{
	struct dst_entry *dst = NULL;
	struct flowi fl;

	memset(&fl, 0, sizeof(struct flowi));
	fl.u.ip6.daddr = ipv6_hdr(skb_in)->saddr;
	nf_ip6_route(dev_net(skb_in->dev), &dst, &fl, false);
	if (!dst)
		return -1;

	skb_dst_set(skb_in, dst);
	return 0;
}

void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
{
	struct net_device *br_indev __maybe_unused;
@@ -154,6 +169,14 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
	fl6.daddr = oip6h->saddr;
	fl6.fl6_sport = otcph->dest;
	fl6.fl6_dport = otcph->source;

	if (hook == NF_INET_PRE_ROUTING) {
		nf_ip6_route(net, &dst, flowi6_to_flowi(&fl6), false);
		if (!dst)
			return;
		skb_dst_set(oldskb, dst);
	}

	fl6.flowi6_oif = l3mdev_master_ifindex(skb_dst(oldskb)->dev);
	fl6.flowi6_mark = IP6_REPLY_MARK(net, oldskb->mark);
	security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
@@ -245,6 +268,9 @@ void nf_send_unreach6(struct net *net, struct sk_buff *skb_in,
	if (hooknum == NF_INET_LOCAL_OUT && skb_in->dev == NULL)
		skb_in->dev = net->loopback_dev;

	if (hooknum == NF_INET_PRE_ROUTING && nf_reject6_fill_skb_dst(skb_in))
		return;

	icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0);
}
EXPORT_SYMBOL_GPL(nf_send_unreach6);
Loading