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

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

Merge branch 'nf-hook-compress'



netfilter: Compress hook function signatures.

Currently netfilter hooks have a function signature that is huge and
has many arguments.  This propagates from the hook entry points down
into the individual hook implementations themselves.

This means that if, for example, we want to change the type of one of
these arguments then we have to touch hundreds of locations.

The main initial motivation behind this is that we'd like to change
the signature of "okfn" so that a socket pointer can be passed in (and
reference counted properly) for the sake of using the proper socket
context in the case of tunnels whilst not releasing the top level user
socket from skb->sk (and thus releasing it's socket memory quota
usage) in order to accomodate this.

This also makes it clear who actually uses 'okfn', nf_queue().  It is
absolutely critical to make this obvious because any user of 'okfn'
down in these hook chains have the be strictly audited for
escapability.  Specifically, escapability of references to objects
outside of the packet processing path.  And that's exactly what
nf_queue() does via it's packet reinjection framework.

In fact this points out a bug in Jiri's original attempt to push the
socket pointer down through netfilter's okfn.  It didn't grab and drop
a reference to the socket in net/netfilter/nf_queue.c as needed.

Furthermore, so many code paths are simplified, and should in fact be
more efficient because we aren't passing in arguments that often are
simply not used by the netfilter hook at all.

Further simplifications are probably possible, but this series takes
care of the main cases.

Unfortunately I couldn't convert ebt_do_table() because ebtables is
complete and utter crap and uses ebt_do_table() outside of the hook
call chains.  But that should not be news to anyone.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Acked-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parents b81b7be6 b85c3dc9
Loading
Loading
Loading
Loading
+24 −8
Original line number Diff line number Diff line
@@ -44,11 +44,19 @@ int netfilter_init(void);
struct sk_buff;

struct nf_hook_ops;

struct nf_hook_state {
	unsigned int hook;
	int thresh;
	u_int8_t pf;
	struct net_device *in;
	struct net_device *out;
	int (*okfn)(struct sk_buff *);
};

typedef unsigned int nf_hookfn(const struct nf_hook_ops *ops,
			       struct sk_buff *skb,
			       const struct net_device *in,
			       const struct net_device *out,
			       int (*okfn)(struct sk_buff *));
			       const struct nf_hook_state *state);

struct nf_hook_ops {
	struct list_head list;
@@ -118,9 +126,7 @@ static inline bool nf_hooks_active(u_int8_t pf, unsigned int hook)
}
#endif

int nf_hook_slow(u_int8_t pf, unsigned int hook, struct sk_buff *skb,
		 struct net_device *indev, struct net_device *outdev,
		 int (*okfn)(struct sk_buff *), int thresh);
int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state);

/**
 *	nf_hook_thresh - call a netfilter hook
@@ -135,8 +141,18 @@ static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,
				 struct net_device *outdev,
				 int (*okfn)(struct sk_buff *), int thresh)
{
	if (nf_hooks_active(pf, hook))
		return nf_hook_slow(pf, hook, skb, indev, outdev, okfn, thresh);
	if (nf_hooks_active(pf, hook)) {
		struct nf_hook_state state = {
			.hook = hook,
			.thresh = thresh,
			.pf = pf,
			.in = indev,
			.out = outdev,
			.okfn = okfn
		};

		return nf_hook_slow(skb, &state);
	}
	return 1;
}

+1 −2
Original line number Diff line number Diff line
@@ -54,8 +54,7 @@ extern struct xt_table *arpt_register_table(struct net *net,
extern void arpt_unregister_table(struct xt_table *table);
extern unsigned int arpt_do_table(struct sk_buff *skb,
				  unsigned int hook,
				  const struct net_device *in,
				  const struct net_device *out,
				  const struct nf_hook_state *state,
				  struct xt_table *table);

#ifdef CONFIG_COMPAT
+1 −2
Original line number Diff line number Diff line
@@ -65,8 +65,7 @@ struct ipt_error {
extern void *ipt_alloc_initial_table(const struct xt_table *);
extern unsigned int ipt_do_table(struct sk_buff *skb,
				 unsigned int hook,
				 const struct net_device *in,
				 const struct net_device *out,
				 const struct nf_hook_state *state,
				 struct xt_table *table);

#ifdef CONFIG_COMPAT
+1 −2
Original line number Diff line number Diff line
@@ -31,8 +31,7 @@ extern struct xt_table *ip6t_register_table(struct net *net,
extern void ip6t_unregister_table(struct net *net, struct xt_table *table);
extern unsigned int ip6t_do_table(struct sk_buff *skb,
				  unsigned int hook,
				  const struct net_device *in,
				  const struct net_device *out,
				  const struct nf_hook_state *state,
				  struct xt_table *table);

/* Check for an extension */
+16 −32
Original line number Diff line number Diff line
@@ -44,40 +44,32 @@ int nf_nat_icmp_reply_translation(struct sk_buff *skb, struct nf_conn *ct,
				  unsigned int hooknum);

unsigned int nf_nat_ipv4_in(const struct nf_hook_ops *ops, struct sk_buff *skb,
			    const struct net_device *in,
			    const struct net_device *out,
			    const struct nf_hook_state *state,
			    unsigned int (*do_chain)(const struct nf_hook_ops *ops,
						     struct sk_buff *skb,
						     const struct net_device *in,
						     const struct net_device *out,
						     const struct nf_hook_state *state,
						     struct nf_conn *ct));

unsigned int nf_nat_ipv4_out(const struct nf_hook_ops *ops, struct sk_buff *skb,
			     const struct net_device *in,
			     const struct net_device *out,
			     const struct nf_hook_state *state,
			     unsigned int (*do_chain)(const struct nf_hook_ops *ops,
						      struct sk_buff *skb,
						      const struct net_device *in,
						      const struct net_device *out,
						      const struct nf_hook_state *state,
						      struct nf_conn *ct));

unsigned int nf_nat_ipv4_local_fn(const struct nf_hook_ops *ops,
				  struct sk_buff *skb,
				  const struct net_device *in,
				  const struct net_device *out,
				  const struct nf_hook_state *state,
				  unsigned int (*do_chain)(const struct nf_hook_ops *ops,
							   struct sk_buff *skb,
							   const struct net_device *in,
							   const struct net_device *out,
							   const struct nf_hook_state *state,
							   struct nf_conn *ct));

unsigned int nf_nat_ipv4_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
			    const struct net_device *in,
			    const struct net_device *out,
			    const struct nf_hook_state *state,
			    unsigned int (*do_chain)(const struct nf_hook_ops *ops,
						     struct sk_buff *skb,
						     const struct net_device *in,
						     const struct net_device *out,
						     const struct nf_hook_state *state,
						     struct nf_conn *ct));

int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, struct nf_conn *ct,
@@ -85,40 +77,32 @@ int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, struct nf_conn *ct,
				    unsigned int hooknum, unsigned int hdrlen);

unsigned int nf_nat_ipv6_in(const struct nf_hook_ops *ops, struct sk_buff *skb,
			    const struct net_device *in,
			    const struct net_device *out,
			    const struct nf_hook_state *state,
			    unsigned int (*do_chain)(const struct nf_hook_ops *ops,
						     struct sk_buff *skb,
						     const struct net_device *in,
						     const struct net_device *out,
						     const struct nf_hook_state *state,
						     struct nf_conn *ct));

unsigned int nf_nat_ipv6_out(const struct nf_hook_ops *ops, struct sk_buff *skb,
			     const struct net_device *in,
			     const struct net_device *out,
			     const struct nf_hook_state *state,
			     unsigned int (*do_chain)(const struct nf_hook_ops *ops,
						      struct sk_buff *skb,
						      const struct net_device *in,
						      const struct net_device *out,
						      const struct nf_hook_state *state,
						      struct nf_conn *ct));

unsigned int nf_nat_ipv6_local_fn(const struct nf_hook_ops *ops,
				  struct sk_buff *skb,
				  const struct net_device *in,
				  const struct net_device *out,
				  const struct nf_hook_state *state,
				  unsigned int (*do_chain)(const struct nf_hook_ops *ops,
							   struct sk_buff *skb,
							   const struct net_device *in,
							   const struct net_device *out,
							   const struct nf_hook_state *state,
							   struct nf_conn *ct));

unsigned int nf_nat_ipv6_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
			    const struct net_device *in,
			    const struct net_device *out,
			    const struct nf_hook_state *state,
			    unsigned int (*do_chain)(const struct nf_hook_ops *ops,
						     struct sk_buff *skb,
						     const struct net_device *in,
						     const struct net_device *out,
						     const struct nf_hook_state *state,
						     struct nf_conn *ct));

#endif /* _NF_NAT_L3PROTO_H */
Loading