Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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


Pablo Neira Ayuso says:

====================
Netfilter updates for net-next

The following patchset contains the first batch of Netfilter updates for
your net-next tree.

1) Define pr_fmt() in nf_conntrack, from Weongyo Jeong.

2) Define and register netfilter's afinfo for the bridge family,
   this comes in preparation for native nfqueue's bridge for nft,
   from Stephane Bryant.

3) Add new attributes to store layer 2 and VLAN headers to nfqueue,
   also from Stephane Bryant.

4) Parse new NFQA_VLAN and NFQA_L2HDR nfqueue netlink attributes
   coming from userspace, from Stephane Bryant.

5) Use net->ipv6.devconf_all->hop_limit instead of hardcoded hop_limit
   in IPv6 SYNPROXY, from Liping Zhang.

6) Remove unnecessary check for dst == NULL in nf_reject_ipv6,
   from Haishuang Yan.

7) Deinline ctnetlink event report functions, from Florian Westphal.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 69fb7812 ecdfb48c
Loading
Loading
Loading
Loading
+15 −93
Original line number Diff line number Diff line
@@ -73,6 +73,8 @@ void nf_conntrack_unregister_notifier(struct net *net,
				      struct nf_ct_event_notifier *nb);

void nf_ct_deliver_cached_events(struct nf_conn *ct);
int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct,
				  u32 portid, int report);

static inline void
nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
@@ -90,70 +92,26 @@ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
	set_bit(event, &e->cache);
}

static inline int
nf_conntrack_eventmask_report(unsigned int eventmask,
			      struct nf_conn *ct,
			      u32 portid,
			      int report)
{
	int ret = 0;
	struct net *net = nf_ct_net(ct);
	struct nf_ct_event_notifier *notify;
	struct nf_conntrack_ecache *e;

	rcu_read_lock();
	notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
	if (notify == NULL)
		goto out_unlock;

	e = nf_ct_ecache_find(ct);
	if (e == NULL)
		goto out_unlock;

	if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) {
		struct nf_ct_event item = {
			.ct 	= ct,
			.portid	= e->portid ? e->portid : portid,
			.report = report
		};
		/* This is a resent of a destroy event? If so, skip missed */
		unsigned long missed = e->portid ? 0 : e->missed;

		if (!((eventmask | missed) & e->ctmask))
			goto out_unlock;

		ret = notify->fcn(eventmask | missed, &item);
		if (unlikely(ret < 0 || missed)) {
			spin_lock_bh(&ct->lock);
			if (ret < 0) {
				/* This is a destroy event that has been
				 * triggered by a process, we store the PORTID
				 * to include it in the retransmission. */
				if (eventmask & (1 << IPCT_DESTROY) &&
				    e->portid == 0 && portid != 0)
					e->portid = portid;
				else
					e->missed |= eventmask;
			} else
				e->missed &= ~missed;
			spin_unlock_bh(&ct->lock);
		}
	}
out_unlock:
	rcu_read_unlock();
	return ret;
}

static inline int
nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct,
			  u32 portid, int report)
{
	const struct net *net = nf_ct_net(ct);

	if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
		return 0;

	return nf_conntrack_eventmask_report(1 << event, ct, portid, report);
}

static inline int
nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
{
	const struct net *net = nf_ct_net(ct);

	if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
		return 0;

	return nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
}

@@ -172,43 +130,9 @@ int nf_ct_expect_register_notifier(struct net *net,
void nf_ct_expect_unregister_notifier(struct net *net,
				      struct nf_exp_event_notifier *nb);

static inline void
nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
void nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
			       struct nf_conntrack_expect *exp,
			  u32 portid,
			  int report)
{
	struct net *net = nf_ct_exp_net(exp);
	struct nf_exp_event_notifier *notify;
	struct nf_conntrack_ecache *e;

	rcu_read_lock();
	notify = rcu_dereference(net->ct.nf_expect_event_cb);
	if (notify == NULL)
		goto out_unlock;

	e = nf_ct_ecache_find(exp->master);
	if (e == NULL)
		goto out_unlock;

	if (e->expmask & (1 << event)) {
		struct nf_exp_event item = {
			.exp	= exp,
			.portid	= portid,
			.report = report
		};
		notify->fcn(1 << event, &item);
	}
out_unlock:
	rcu_read_unlock();
}

static inline void
nf_ct_expect_event(enum ip_conntrack_expect_events event,
		   struct nf_conntrack_expect *exp)
{
	nf_ct_expect_event_report(event, exp, 0, 0);
}
			       u32 portid, int report);

int nf_conntrack_ecache_pernet_init(struct net *net);
void nf_conntrack_ecache_pernet_fini(struct net *net);
@@ -245,8 +169,6 @@ static inline int nf_conntrack_event_report(enum ip_conntrack_events event,
					    u32 portid,
					    int report) { return 0; }
static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {}
static inline void nf_ct_expect_event(enum ip_conntrack_expect_events event,
				      struct nf_conntrack_expect *exp) {}
static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e,
					     struct nf_conntrack_expect *exp,
 					     u32 portid,
+10 −0
Original line number Diff line number Diff line
@@ -30,6 +30,14 @@ struct nfqnl_msg_packet_timestamp {
	__aligned_be64	usec;
};

enum nfqnl_vlan_attr {
	NFQA_VLAN_UNSPEC,
	NFQA_VLAN_PROTO,		/* __be16 skb vlan_proto */
	NFQA_VLAN_TCI,			/* __be16 skb htons(vlan_tci) */
	__NFQA_VLAN_MAX,
};
#define NFQA_VLAN_MAX (__NFQA_VLAN_MAX + 1)

enum nfqnl_attr_type {
	NFQA_UNSPEC,
	NFQA_PACKET_HDR,
@@ -50,6 +58,8 @@ enum nfqnl_attr_type {
	NFQA_UID,			/* __u32 sk uid */
	NFQA_GID,			/* __u32 sk gid */
	NFQA_SECCTX,			/* security context string */
	NFQA_VLAN,			/* nested attribute: packet vlan info */
	NFQA_L2HDR,			/* full L2 header */

	__NFQA_MAX
};
+45 −2
Original line number Diff line number Diff line
@@ -162,15 +162,57 @@ static const struct nf_chain_type filter_bridge = {
			  (1 << NF_BR_POST_ROUTING),
};

static void nf_br_saveroute(const struct sk_buff *skb,
			    struct nf_queue_entry *entry)
{
}

static int nf_br_reroute(struct net *net, struct sk_buff *skb,
			 const struct nf_queue_entry *entry)
{
	return 0;
}

static __sum16 nf_br_checksum(struct sk_buff *skb, unsigned int hook,
			      unsigned int dataoff, u_int8_t protocol)
{
	return 0;
}

static __sum16 nf_br_checksum_partial(struct sk_buff *skb, unsigned int hook,
				      unsigned int dataoff, unsigned int len,
				      u_int8_t protocol)
{
	return 0;
}

static int nf_br_route(struct net *net, struct dst_entry **dst,
		       struct flowi *fl, bool strict __always_unused)
{
	return 0;
}

static const struct nf_afinfo nf_br_afinfo = {
	.family                 = AF_BRIDGE,
	.checksum               = nf_br_checksum,
	.checksum_partial       = nf_br_checksum_partial,
	.route                  = nf_br_route,
	.saveroute              = nf_br_saveroute,
	.reroute                = nf_br_reroute,
	.route_key_size         = 0,
};

static int __init nf_tables_bridge_init(void)
{
	int ret;

	nf_register_afinfo(&nf_br_afinfo);
	nft_register_chain_type(&filter_bridge);
	ret = register_pernet_subsys(&nf_tables_bridge_net_ops);
	if (ret < 0)
	if (ret < 0) {
		nft_unregister_chain_type(&filter_bridge);

		nf_unregister_afinfo(&nf_br_afinfo);
	}
	return ret;
}

@@ -178,6 +220,7 @@ static void __exit nf_tables_bridge_exit(void)
{
	unregister_pernet_subsys(&nf_tables_bridge_net_ops);
	nft_unregister_chain_type(&filter_bridge);
	nf_unregister_afinfo(&nf_br_afinfo);
}

module_init(nf_tables_bridge_init);
+30 −26
Original line number Diff line number Diff line
@@ -20,7 +20,8 @@
#include <net/netfilter/nf_conntrack_synproxy.h>

static struct ipv6hdr *
synproxy_build_ip(struct sk_buff *skb, const struct in6_addr *saddr,
synproxy_build_ip(struct net *net, struct sk_buff *skb,
		  const struct in6_addr *saddr,
		  const struct in6_addr *daddr)
{
	struct ipv6hdr *iph;
@@ -28,7 +29,7 @@ synproxy_build_ip(struct sk_buff *skb, const struct in6_addr *saddr,
	skb_reset_network_header(skb);
	iph = (struct ipv6hdr *)skb_put(skb, sizeof(*iph));
	ip6_flow_hdr(iph, 0, 0);
	iph->hop_limit	= 64;	//XXX
	iph->hop_limit	= net->ipv6.devconf_all->hop_limit;
	iph->nexthdr	= IPPROTO_TCP;
	iph->saddr	= *saddr;
	iph->daddr	= *daddr;
@@ -37,13 +38,12 @@ synproxy_build_ip(struct sk_buff *skb, const struct in6_addr *saddr,
}

static void
synproxy_send_tcp(const struct synproxy_net *snet,
synproxy_send_tcp(struct net *net,
		  const struct sk_buff *skb, struct sk_buff *nskb,
		  struct nf_conntrack *nfct, enum ip_conntrack_info ctinfo,
		  struct ipv6hdr *niph, struct tcphdr *nth,
		  unsigned int tcp_hdr_size)
{
	struct net *net = nf_ct_net(snet->tmpl);
	struct dst_entry *dst;
	struct flowi6 fl6;

@@ -84,7 +84,7 @@ synproxy_send_tcp(const struct synproxy_net *snet,
}

static void
synproxy_send_client_synack(const struct synproxy_net *snet,
synproxy_send_client_synack(struct net *net,
			    const struct sk_buff *skb, const struct tcphdr *th,
			    const struct synproxy_options *opts)
{
@@ -103,7 +103,7 @@ synproxy_send_client_synack(const struct synproxy_net *snet,
		return;
	skb_reserve(nskb, MAX_TCP_HEADER);

	niph = synproxy_build_ip(nskb, &iph->daddr, &iph->saddr);
	niph = synproxy_build_ip(net, nskb, &iph->daddr, &iph->saddr);

	skb_reset_transport_header(nskb);
	nth = (struct tcphdr *)skb_put(nskb, tcp_hdr_size);
@@ -121,15 +121,16 @@ synproxy_send_client_synack(const struct synproxy_net *snet,

	synproxy_build_options(nth, opts);

	synproxy_send_tcp(snet, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
	synproxy_send_tcp(net, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
			  niph, nth, tcp_hdr_size);
}

static void
synproxy_send_server_syn(const struct synproxy_net *snet,
synproxy_send_server_syn(struct net *net,
			 const struct sk_buff *skb, const struct tcphdr *th,
			 const struct synproxy_options *opts, u32 recv_seq)
{
	struct synproxy_net *snet = synproxy_pernet(net);
	struct sk_buff *nskb;
	struct ipv6hdr *iph, *niph;
	struct tcphdr *nth;
@@ -144,7 +145,7 @@ synproxy_send_server_syn(const struct synproxy_net *snet,
		return;
	skb_reserve(nskb, MAX_TCP_HEADER);

	niph = synproxy_build_ip(nskb, &iph->saddr, &iph->daddr);
	niph = synproxy_build_ip(net, nskb, &iph->saddr, &iph->daddr);

	skb_reset_transport_header(nskb);
	nth = (struct tcphdr *)skb_put(nskb, tcp_hdr_size);
@@ -165,12 +166,12 @@ synproxy_send_server_syn(const struct synproxy_net *snet,

	synproxy_build_options(nth, opts);

	synproxy_send_tcp(snet, skb, nskb, &snet->tmpl->ct_general, IP_CT_NEW,
	synproxy_send_tcp(net, skb, nskb, &snet->tmpl->ct_general, IP_CT_NEW,
			  niph, nth, tcp_hdr_size);
}

static void
synproxy_send_server_ack(const struct synproxy_net *snet,
synproxy_send_server_ack(struct net *net,
			 const struct ip_ct_tcp *state,
			 const struct sk_buff *skb, const struct tcphdr *th,
			 const struct synproxy_options *opts)
@@ -189,7 +190,7 @@ synproxy_send_server_ack(const struct synproxy_net *snet,
		return;
	skb_reserve(nskb, MAX_TCP_HEADER);

	niph = synproxy_build_ip(nskb, &iph->daddr, &iph->saddr);
	niph = synproxy_build_ip(net, nskb, &iph->daddr, &iph->saddr);

	skb_reset_transport_header(nskb);
	nth = (struct tcphdr *)skb_put(nskb, tcp_hdr_size);
@@ -205,11 +206,11 @@ synproxy_send_server_ack(const struct synproxy_net *snet,

	synproxy_build_options(nth, opts);

	synproxy_send_tcp(snet, skb, nskb, NULL, 0, niph, nth, tcp_hdr_size);
	synproxy_send_tcp(net, skb, nskb, NULL, 0, niph, nth, tcp_hdr_size);
}

static void
synproxy_send_client_ack(const struct synproxy_net *snet,
synproxy_send_client_ack(struct net *net,
			 const struct sk_buff *skb, const struct tcphdr *th,
			 const struct synproxy_options *opts)
{
@@ -227,7 +228,7 @@ synproxy_send_client_ack(const struct synproxy_net *snet,
		return;
	skb_reserve(nskb, MAX_TCP_HEADER);

	niph = synproxy_build_ip(nskb, &iph->saddr, &iph->daddr);
	niph = synproxy_build_ip(net, nskb, &iph->saddr, &iph->daddr);

	skb_reset_transport_header(nskb);
	nth = (struct tcphdr *)skb_put(nskb, tcp_hdr_size);
@@ -243,15 +244,16 @@ synproxy_send_client_ack(const struct synproxy_net *snet,

	synproxy_build_options(nth, opts);

	synproxy_send_tcp(snet, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
	synproxy_send_tcp(net, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
			  niph, nth, tcp_hdr_size);
}

static bool
synproxy_recv_client_ack(const struct synproxy_net *snet,
synproxy_recv_client_ack(struct net *net,
			 const struct sk_buff *skb, const struct tcphdr *th,
			 struct synproxy_options *opts, u32 recv_seq)
{
	struct synproxy_net *snet = synproxy_pernet(net);
	int mss;

	mss = __cookie_v6_check(ipv6_hdr(skb), th, ntohl(th->ack_seq) - 1);
@@ -267,7 +269,7 @@ synproxy_recv_client_ack(const struct synproxy_net *snet,
	if (opts->options & XT_SYNPROXY_OPT_TIMESTAMP)
		synproxy_check_timestamp_cookie(opts);

	synproxy_send_server_syn(snet, skb, th, opts, recv_seq);
	synproxy_send_server_syn(net, skb, th, opts, recv_seq);
	return true;
}

@@ -275,7 +277,8 @@ static unsigned int
synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par)
{
	const struct xt_synproxy_info *info = par->targinfo;
	struct synproxy_net *snet = synproxy_pernet(par->net);
	struct net *net = par->net;
	struct synproxy_net *snet = synproxy_pernet(net);
	struct synproxy_options opts = {};
	struct tcphdr *th, _th;

@@ -304,12 +307,12 @@ synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par)
					  XT_SYNPROXY_OPT_SACK_PERM |
					  XT_SYNPROXY_OPT_ECN);

		synproxy_send_client_synack(snet, skb, th, &opts);
		synproxy_send_client_synack(net, skb, th, &opts);
		return NF_DROP;

	} else if (th->ack && !(th->fin || th->rst || th->syn)) {
		/* ACK from client */
		synproxy_recv_client_ack(snet, skb, th, &opts, ntohl(th->seq));
		synproxy_recv_client_ack(net, skb, th, &opts, ntohl(th->seq));
		return NF_DROP;
	}

@@ -320,7 +323,8 @@ static unsigned int ipv6_synproxy_hook(void *priv,
				       struct sk_buff *skb,
				       const struct nf_hook_state *nhs)
{
	struct synproxy_net *snet = synproxy_pernet(nhs->net);
	struct net *net = nhs->net;
	struct synproxy_net *snet = synproxy_pernet(net);
	enum ip_conntrack_info ctinfo;
	struct nf_conn *ct;
	struct nf_conn_synproxy *synproxy;
@@ -384,7 +388,7 @@ static unsigned int ipv6_synproxy_hook(void *priv,
			 * therefore we need to add 1 to make the SYN sequence
			 * number match the one of first SYN.
			 */
			if (synproxy_recv_client_ack(snet, skb, th, &opts,
			if (synproxy_recv_client_ack(net, skb, th, &opts,
						     ntohl(th->seq) + 1))
				this_cpu_inc(snet->stats->cookie_retrans);

@@ -410,12 +414,12 @@ static unsigned int ipv6_synproxy_hook(void *priv,
				  XT_SYNPROXY_OPT_SACK_PERM);

		swap(opts.tsval, opts.tsecr);
		synproxy_send_server_ack(snet, state, skb, th, &opts);
		synproxy_send_server_ack(net, state, skb, th, &opts);

		nf_ct_seqadj_init(ct, ctinfo, synproxy->isn - ntohl(th->seq));

		swap(opts.tsval, opts.tsecr);
		synproxy_send_client_ack(snet, skb, th, &opts);
		synproxy_send_client_ack(net, skb, th, &opts);

		consume_skb(skb);
		return NF_STOLEN;
+1 −1
Original line number Diff line number Diff line
@@ -158,7 +158,7 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
	fl6.fl6_dport = otcph->source;
	security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
	dst = ip6_route_output(net, NULL, &fl6);
	if (dst == NULL || dst->error) {
	if (dst->error) {
		dst_release(dst);
		return;
	}
Loading