Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says:

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

The following patchset contains Netfilter/IPVS updates for your net-next tree
in this 4.4 development cycle, they are:

1) Schedule ICMP traffic to IPVS instances, this introduces a new schedule_icmp
   proc knob to enable/disable it. By default is off to retain the old
   behaviour. Patchset from Alex Gartrell.

I'm also including what Alex originally said for the record:

"The configuration of ipvs at Facebook is relatively straightforward.  All
ipvs instances bgp advertise a set of VIPs and the network prefers the
nearest one or uses ECMP in the event of a tie.  For the uninitiated, ECMP
deterministically and statelessly load balances by hashing the packet
(usually a 5-tuple of protocol, saddr, daddr, sport, and dport) and using
that number as an index (basic hash table type logic).

The problem is that ICMP packets (which contain really important
information like whether or not an MTU has been exceeded) will get a
different hash value and may end up at a different ipvs instance.  With no
information about where to route these packets, they are dropped, creating
ICMP black holes and breaking Path MTU discovery.  Suddenly, my mom's
pictures can't load and I'm fielding midday calls that I want nothing to do
with.

To address this, this patch set introduces the ability to schedule icmp
packets which is gated by a sysctl net.ipv4.vs.schedule_icmp.  If set to 0,
the old behavior is maintained -- otherwise ICMP packets are scheduled."

2) Add another proc entry to ignore tunneled packets to avoid routing loops
   from IPVS, also from Alex.

3) Fifteen patches from Eric Biederman to:

* Stop passing nf_hook_ops as parameter to the hook and use the state hook
  object instead all around the netfilter code, so only the private data
  pointer is passed to the registered hook function.

* Now that we've got state->net, propagate the netns pointer to netfilter hook
  clients to avoid its computation over and over again. A good example of how
  this has been simplified is the former TEE target (now nf_dup infrastructure)
  since it has killed the ugly pick_net() function.

There's another round of netns updates from Eric Biederman making the line. To
avoid the patchbomb again to almost all the networking mailing list (that is 84
patches) I'd suggest we send you a pull request with no patches or let me know
if you prefer a better way.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2015-09-22 13:11:43 -07:00
commit 99cb99aa05
120 changed files with 816 additions and 653 deletions

View File

@ -157,6 +157,16 @@ expire_quiescent_template - BOOLEAN
persistence template if it is to be used to schedule a new
connection and the destination server is quiescent.
ignore_tunneled - BOOLEAN
0 - disabled (default)
not 0 - enabled
If set, ipvs will set the ipvs_property on all packets which are of
unrecognized protocols. This prevents us from routing tunneled
protocols like ipip, which is useful to prevent rescheduling
packets that have been tunneled to the ipvs host (i.e. to prevent
ipvs routing loops when ipvs is also acting as a real server).
nat_icmp_send - BOOLEAN
0 - disabled (default)
not 0 - enabled

View File

@ -80,7 +80,7 @@ static inline void nf_hook_state_init(struct nf_hook_state *p,
p->okfn = okfn;
}
typedef unsigned int nf_hookfn(const struct nf_hook_ops *ops,
typedef unsigned int nf_hookfn(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state);

View File

@ -13,6 +13,7 @@
* @target: the target extension
* @matchinfo: per-match data
* @targetinfo: per-target data
* @net network namespace through which the action was invoked
* @in: input netdevice
* @out: output netdevice
* @fragoff: packet is a fragment, this is the data offset
@ -24,7 +25,6 @@
* Fields written to by extensions:
*
* @hotdrop: drop packet if we had inspection problems
* Network namespace obtainable using dev_net(in/out)
*/
struct xt_action_param {
union {
@ -34,6 +34,7 @@ struct xt_action_param {
union {
const void *matchinfo, *targinfo;
};
struct net *net;
const struct net_device *in, *out;
int fragoff;
unsigned int thoff;

View File

@ -53,7 +53,6 @@ extern struct xt_table *arpt_register_table(struct net *net,
const struct arpt_replace *repl);
extern void arpt_unregister_table(struct xt_table *table);
extern unsigned int arpt_do_table(struct sk_buff *skb,
unsigned int hook,
const struct nf_hook_state *state,
struct xt_table *table);

View File

@ -111,9 +111,9 @@ struct ebt_table {
extern struct ebt_table *ebt_register_table(struct net *net,
const struct ebt_table *table);
extern void ebt_unregister_table(struct net *net, struct ebt_table *table);
extern unsigned int ebt_do_table(unsigned int hook, struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
struct ebt_table *table);
extern unsigned int ebt_do_table(struct sk_buff *skb,
const struct nf_hook_state *state,
struct ebt_table *table);
/* Used in the kernel match() functions */
#define FWINV(bool,invflg) ((bool) ^ !!(info->invflags & invflg))

View File

@ -64,7 +64,6 @@ 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 nf_hook_state *state,
struct xt_table *table);

View File

@ -30,7 +30,6 @@ extern struct xt_table *ip6t_register_table(struct net *net,
const struct ip6t_replace *repl);
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 nf_hook_state *state,
struct xt_table *table);

View File

@ -29,6 +29,9 @@
#endif
#include <net/net_namespace.h> /* Netw namespace */
#define IP_VS_HDR_INVERSE 1
#define IP_VS_HDR_ICMP 2
/* Generic access of ipvs struct */
static inline struct netns_ipvs *net_ipvs(struct net* net)
{
@ -104,6 +107,8 @@ static inline struct net *seq_file_single_net(struct seq_file *seq)
extern int ip_vs_conn_tab_size;
struct ip_vs_iphdr {
int hdr_flags; /* ipvs flags */
__u32 off; /* Where IP or IPv4 header starts */
__u32 len; /* IPv4 simply where L4 starts
* IPv6 where L4 Transport Header starts */
__u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/
@ -120,48 +125,89 @@ static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
return skb_header_pointer(skb, offset, len, buffer);
}
static inline void
ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr)
{
const struct iphdr *iph = nh;
iphdr->len = iph->ihl * 4;
iphdr->fragoffs = 0;
iphdr->protocol = iph->protocol;
iphdr->saddr.ip = iph->saddr;
iphdr->daddr.ip = iph->daddr;
}
/* This function handles filling *ip_vs_iphdr, both for IPv4 and IPv6.
* IPv6 requires some extra work, as finding proper header position,
* depend on the IPv6 extension headers.
*/
static inline void
ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr)
static inline int
ip_vs_fill_iph_skb_off(int af, const struct sk_buff *skb, int offset,
int hdr_flags, struct ip_vs_iphdr *iphdr)
{
iphdr->hdr_flags = hdr_flags;
iphdr->off = offset;
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6) {
const struct ipv6hdr *iph =
(struct ipv6hdr *)skb_network_header(skb);
struct ipv6hdr _iph;
const struct ipv6hdr *iph = skb_header_pointer(
skb, offset, sizeof(_iph), &_iph);
if (!iph)
return 0;
iphdr->saddr.in6 = iph->saddr;
iphdr->daddr.in6 = iph->daddr;
/* ipv6_find_hdr() updates len, flags */
iphdr->len = 0;
iphdr->len = offset;
iphdr->flags = 0;
iphdr->protocol = ipv6_find_hdr(skb, &iphdr->len, -1,
&iphdr->fragoffs,
&iphdr->flags);
if (iphdr->protocol < 0)
return 0;
} else
#endif
{
const struct iphdr *iph =
(struct iphdr *)skb_network_header(skb);
iphdr->len = iph->ihl * 4;
struct iphdr _iph;
const struct iphdr *iph = skb_header_pointer(
skb, offset, sizeof(_iph), &_iph);
if (!iph)
return 0;
iphdr->len = offset + iph->ihl * 4;
iphdr->fragoffs = 0;
iphdr->protocol = iph->protocol;
iphdr->saddr.ip = iph->saddr;
iphdr->daddr.ip = iph->daddr;
}
return 1;
}
static inline int
ip_vs_fill_iph_skb_icmp(int af, const struct sk_buff *skb, int offset,
bool inverse, struct ip_vs_iphdr *iphdr)
{
int hdr_flags = IP_VS_HDR_ICMP;
if (inverse)
hdr_flags |= IP_VS_HDR_INVERSE;
return ip_vs_fill_iph_skb_off(af, skb, offset, hdr_flags, iphdr);
}
static inline int
ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, bool inverse,
struct ip_vs_iphdr *iphdr)
{
int hdr_flags = 0;
if (inverse)
hdr_flags |= IP_VS_HDR_INVERSE;
return ip_vs_fill_iph_skb_off(af, skb, skb_network_offset(skb),
hdr_flags, iphdr);
}
static inline bool
ip_vs_iph_inverse(const struct ip_vs_iphdr *iph)
{
return !!(iph->hdr_flags & IP_VS_HDR_INVERSE);
}
static inline bool
ip_vs_iph_icmp(const struct ip_vs_iphdr *iph)
{
return !!(iph->hdr_flags & IP_VS_HDR_ICMP);
}
static inline void ip_vs_addr_copy(int af, union nf_inet_addr *dst,
@ -449,14 +495,12 @@ struct ip_vs_protocol {
struct ip_vs_conn *
(*conn_in_get)(int af,
const struct sk_buff *skb,
const struct ip_vs_iphdr *iph,
int inverse);
const struct ip_vs_iphdr *iph);
struct ip_vs_conn *
(*conn_out_get)(int af,
const struct sk_buff *skb,
const struct ip_vs_iphdr *iph,
int inverse);
const struct ip_vs_iphdr *iph);
int (*snat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp,
struct ip_vs_conn *cp, struct ip_vs_iphdr *iph);
@ -953,6 +997,8 @@ struct netns_ipvs {
int sysctl_pmtu_disc;
int sysctl_backup_only;
int sysctl_conn_reuse_mode;
int sysctl_schedule_icmp;
int sysctl_ignore_tunneled;
/* ip_vs_lblc */
int sysctl_lblc_expiration;
@ -1071,6 +1117,16 @@ static inline int sysctl_conn_reuse_mode(struct netns_ipvs *ipvs)
return ipvs->sysctl_conn_reuse_mode;
}
static inline int sysctl_schedule_icmp(struct netns_ipvs *ipvs)
{
return ipvs->sysctl_schedule_icmp;
}
static inline int sysctl_ignore_tunneled(struct netns_ipvs *ipvs)
{
return ipvs->sysctl_ignore_tunneled;
}
#else
static inline int sysctl_sync_threshold(struct netns_ipvs *ipvs)
@ -1143,6 +1199,16 @@ static inline int sysctl_conn_reuse_mode(struct netns_ipvs *ipvs)
return 1;
}
static inline int sysctl_schedule_icmp(struct netns_ipvs *ipvs)
{
return 0;
}
static inline int sysctl_ignore_tunneled(struct netns_ipvs *ipvs)
{
return 0;
}
#endif
/* IPVS core functions
@ -1186,14 +1252,12 @@ struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p);
struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p);
struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
const struct ip_vs_iphdr *iph,
int inverse);
const struct ip_vs_iphdr *iph);
struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p);
struct ip_vs_conn * ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
const struct ip_vs_iphdr *iph,
int inverse);
const struct ip_vs_iphdr *iph);
/* Get reference to gain full access to conn.
* By default, RCU read-side critical sections have access only to

View File

@ -46,7 +46,7 @@ void br_netfilter_enable(void);
#if IS_ENABLED(CONFIG_IPV6)
int br_validate_ipv6(struct sk_buff *skb);
unsigned int br_nf_pre_routing_ipv6(const struct nf_hook_ops *ops,
unsigned int br_nf_pre_routing_ipv6(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state);
#else

View File

@ -1,7 +1,7 @@
#ifndef _NF_DUP_IPV4_H_
#define _NF_DUP_IPV4_H_
void nf_dup_ipv4(struct sk_buff *skb, unsigned int hooknum,
void nf_dup_ipv4(struct net *net, struct sk_buff *skb, unsigned int hooknum,
const struct in_addr *gw, int oif);
#endif /* _NF_DUP_IPV4_H_ */

View File

@ -1,7 +1,7 @@
#ifndef _NF_DUP_IPV6_H_
#define _NF_DUP_IPV6_H_
void nf_dup_ipv6(struct sk_buff *skb, unsigned int hooknum,
void nf_dup_ipv6(struct net *net, struct sk_buff *skb, unsigned int hooknum,
const struct in6_addr *gw, int oif);
#endif /* _NF_DUP_IPV6_H_ */

View File

@ -191,7 +191,8 @@ int nf_conntrack_hash_check_insert(struct nf_conn *ct);
bool nf_ct_delete(struct nf_conn *ct, u32 pid, int report);
bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff,
u_int16_t l3num, struct nf_conntrack_tuple *tuple);
u_int16_t l3num, struct net *net,
struct nf_conntrack_tuple *tuple);
bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig);

View File

@ -41,6 +41,7 @@ void nf_conntrack_cleanup_end(void);
bool nf_ct_get_tuple(const struct sk_buff *skb, unsigned int nhoff,
unsigned int dataoff, u_int16_t l3num, u_int8_t protonum,
struct net *net,
struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_l3proto *l3proto,
const struct nf_conntrack_l4proto *l4proto);

View File

@ -26,7 +26,7 @@ struct nf_conntrack_l4proto {
/* Try to fill in the third arg: dataoff is offset past network protocol
hdr. Return true if possible. */
bool (*pkt_to_tuple)(const struct sk_buff *skb, unsigned int dataoff,
struct nf_conntrack_tuple *tuple);
struct net *net, struct nf_conntrack_tuple *tuple);
/* Invert the per-proto part of the tuple: ie. turn xmit into reply.
* Some packets can't be inverted: return 0 in that case.

View File

@ -10,7 +10,7 @@
unsigned int nf_nat_packet(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
unsigned int hooknum, struct sk_buff *skb);
int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family);
int nf_xfrm_me_harder(struct net *net, struct sk_buff *skb, unsigned int family);
static inline int nf_nat_initialized(struct nf_conn *ct,
enum nf_nat_manip_type manip)

View File

@ -43,31 +43,31 @@ int nf_nat_icmp_reply_translation(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int hooknum);
unsigned int nf_nat_ipv4_in(const struct nf_hook_ops *ops, struct sk_buff *skb,
unsigned int nf_nat_ipv4_in(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state,
unsigned int (*do_chain)(const struct nf_hook_ops *ops,
unsigned int (*do_chain)(void *priv,
struct sk_buff *skb,
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,
unsigned int nf_nat_ipv4_out(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state,
unsigned int (*do_chain)(const struct nf_hook_ops *ops,
unsigned int (*do_chain)(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
struct nf_conn *ct));
unsigned int nf_nat_ipv4_local_fn(const struct nf_hook_ops *ops,
unsigned int nf_nat_ipv4_local_fn(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
unsigned int (*do_chain)(const struct nf_hook_ops *ops,
unsigned int (*do_chain)(void *priv,
struct sk_buff *skb,
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,
unsigned int nf_nat_ipv4_fn(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state,
unsigned int (*do_chain)(const struct nf_hook_ops *ops,
unsigned int (*do_chain)(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
struct nf_conn *ct));
@ -76,31 +76,31 @@ int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int hooknum, unsigned int hdrlen);
unsigned int nf_nat_ipv6_in(const struct nf_hook_ops *ops, struct sk_buff *skb,
unsigned int nf_nat_ipv6_in(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state,
unsigned int (*do_chain)(const struct nf_hook_ops *ops,
unsigned int (*do_chain)(void *priv,
struct sk_buff *skb,
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,
unsigned int nf_nat_ipv6_out(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state,
unsigned int (*do_chain)(const struct nf_hook_ops *ops,
unsigned int (*do_chain)(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
struct nf_conn *ct));
unsigned int nf_nat_ipv6_local_fn(const struct nf_hook_ops *ops,
unsigned int nf_nat_ipv6_local_fn(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
unsigned int (*do_chain)(const struct nf_hook_ops *ops,
unsigned int (*do_chain)(void *priv,
struct sk_buff *skb,
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,
unsigned int nf_nat_ipv6_fn(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state,
unsigned int (*do_chain)(const struct nf_hook_ops *ops,
unsigned int (*do_chain)(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
struct nf_conn *ct));

View File

@ -14,9 +14,11 @@
struct nft_pktinfo {
struct sk_buff *skb;
struct net *net;
const struct net_device *in;
const struct net_device *out;
const struct nf_hook_ops *ops;
u8 pf;
u8 hook;
u8 nhoff;
u8 thoff;
u8 tprot;
@ -25,16 +27,15 @@ struct nft_pktinfo {
};
static inline void nft_set_pktinfo(struct nft_pktinfo *pkt,
const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
pkt->skb = skb;
pkt->net = pkt->xt.net = state->net;
pkt->in = pkt->xt.in = state->in;
pkt->out = pkt->xt.out = state->out;
pkt->ops = ops;
pkt->xt.hooknum = ops->hooknum;
pkt->xt.family = ops->pf;
pkt->hook = pkt->xt.hooknum = state->hook;
pkt->pf = pkt->xt.family = state->pf;
}
/**
@ -815,8 +816,7 @@ int nft_register_basechain(struct nft_base_chain *basechain,
void nft_unregister_basechain(struct nft_base_chain *basechain,
unsigned int hook_nops);
unsigned int nft_do_chain(struct nft_pktinfo *pkt,
const struct nf_hook_ops *ops);
unsigned int nft_do_chain(struct nft_pktinfo *pkt, void *priv);
/**
* struct nft_table - nf_tables table

View File

@ -6,13 +6,12 @@
static inline void
nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
struct iphdr *ip;
nft_set_pktinfo(pkt, ops, skb, state);
nft_set_pktinfo(pkt, skb, state);
ip = ip_hdr(pkt->skb);
pkt->tprot = ip->protocol;

View File

@ -6,14 +6,13 @@
static inline int
nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
int protohdr, thoff = 0;
unsigned short frag_off;
nft_set_pktinfo(pkt, ops, skb, state);
nft_set_pktinfo(pkt, skb, state);
protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, NULL);
/* If malformed, drop it */

View File

@ -5,6 +5,7 @@
struct tcf_connmark_info {
struct tcf_common common;
struct net *net;
u16 zone;
};

View File

@ -464,7 +464,7 @@ struct net_device *setup_pre_routing(struct sk_buff *skb)
* receiving device) to make netfilter happy, the REDIRECT
* target in particular. Save the original destination IP
* address to be able to detect DNAT afterwards. */
static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops,
static unsigned int br_nf_pre_routing(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -486,7 +486,7 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops,
return NF_ACCEPT;
nf_bridge_pull_encap_header_rcsum(skb);
return br_nf_pre_routing_ipv6(ops, skb, state);
return br_nf_pre_routing_ipv6(priv, skb, state);
}
if (!brnf_call_iptables && !br->nf_call_iptables)
@ -526,7 +526,7 @@ static unsigned int br_nf_pre_routing(const struct nf_hook_ops *ops,
* took place when the packet entered the bridge), but we
* register an IPv4 PRE_ROUTING 'sabotage' hook that will
* prevent this from happening. */
static unsigned int br_nf_local_in(const struct nf_hook_ops *ops,
static unsigned int br_nf_local_in(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -570,7 +570,7 @@ static int br_nf_forward_finish(struct net *net, struct sock *sk, struct sk_buff
* but we are still able to filter on the 'real' indev/outdev
* because of the physdev module. For ARP, indev and outdev are the
* bridge ports. */
static unsigned int br_nf_forward_ip(const struct nf_hook_ops *ops,
static unsigned int br_nf_forward_ip(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -633,7 +633,7 @@ static unsigned int br_nf_forward_ip(const struct nf_hook_ops *ops,
return NF_STOLEN;
}
static unsigned int br_nf_forward_arp(const struct nf_hook_ops *ops,
static unsigned int br_nf_forward_arp(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -801,7 +801,7 @@ static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff
}
/* PF_BRIDGE/POST_ROUTING ********************************************/
static unsigned int br_nf_post_routing(const struct nf_hook_ops *ops,
static unsigned int br_nf_post_routing(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -850,7 +850,7 @@ static unsigned int br_nf_post_routing(const struct nf_hook_ops *ops,
/* IP/SABOTAGE *****************************************************/
/* Don't hand locally destined packets to PF_INET(6)/PRE_ROUTING
* for the second time. */
static unsigned int ip_sabotage_in(const struct nf_hook_ops *ops,
static unsigned int ip_sabotage_in(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{

View File

@ -218,7 +218,7 @@ static int br_nf_pre_routing_finish_ipv6(struct net *net, struct sock *sk, struc
/* Replicate the checks that IPv6 does on packet reception and pass the packet
* to ip6tables.
*/
unsigned int br_nf_pre_routing_ipv6(const struct nf_hook_ops *ops,
unsigned int br_nf_pre_routing_ipv6(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{

View File

@ -180,7 +180,7 @@ ebt_log_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct ebt_log_info *info = par->targinfo;
struct nf_loginfo li;
struct net *net = dev_net(par->in ? par->in : par->out);
struct net *net = par->net;
li.type = NF_LOG_TYPE_LOG;
li.u.log.level = info->loglevel;

View File

@ -24,7 +24,7 @@ ebt_nflog_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct ebt_nflog_info *info = par->targinfo;
struct nf_loginfo li;
struct net *net = dev_net(par->in ? par->in : par->out);
struct net *net = par->net;
li.type = NF_LOG_TYPE_ULOG;
li.u.ulog.copy_len = info->len;

View File

@ -50,10 +50,14 @@ static const struct ebt_table broute_table = {
static int ebt_broute(struct sk_buff *skb)
{
struct nf_hook_state state;
int ret;
ret = ebt_do_table(NF_BR_BROUTING, skb, skb->dev, NULL,
dev_net(skb->dev)->xt.broute_table);
nf_hook_state_init(&state, NULL, NF_BR_BROUTING, INT_MIN,
NFPROTO_BRIDGE, skb->dev, NULL, NULL,
dev_net(skb->dev), NULL);
ret = ebt_do_table(skb, &state, state.net->xt.broute_table);
if (ret == NF_DROP)
return 1; /* route it */
return 0; /* bridge it */

View File

@ -57,19 +57,17 @@ static const struct ebt_table frame_filter = {
};
static unsigned int
ebt_in_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
ebt_in_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
return ebt_do_table(ops->hooknum, skb, state->in, state->out,
state->net->xt.frame_filter);
return ebt_do_table(skb, state, state->net->xt.frame_filter);
}
static unsigned int
ebt_out_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
ebt_out_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
return ebt_do_table(ops->hooknum, skb, state->in, state->out,
state->net->xt.frame_filter);
return ebt_do_table(skb, state, state->net->xt.frame_filter);
}
static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {

View File

@ -57,19 +57,17 @@ static struct ebt_table frame_nat = {
};
static unsigned int
ebt_nat_in(const struct nf_hook_ops *ops, struct sk_buff *skb,
ebt_nat_in(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
return ebt_do_table(ops->hooknum, skb, state->in, state->out,
state->net->xt.frame_nat);
return ebt_do_table(skb, state, state->net->xt.frame_nat);
}
static unsigned int
ebt_nat_out(const struct nf_hook_ops *ops, struct sk_buff *skb,
ebt_nat_out(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
return ebt_do_table(ops->hooknum, skb, state->in, state->out,
state->net->xt.frame_nat);
return ebt_do_table(skb, state, state->net->xt.frame_nat);
}
static struct nf_hook_ops ebt_ops_nat[] __read_mostly = {

View File

@ -183,10 +183,11 @@ struct ebt_entry *ebt_next_entry(const struct ebt_entry *entry)
}
/* Do some firewalling */
unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
struct ebt_table *table)
unsigned int ebt_do_table(struct sk_buff *skb,
const struct nf_hook_state *state,
struct ebt_table *table)
{
unsigned int hook = state->hook;
int i, nentries;
struct ebt_entry *point;
struct ebt_counter *counter_base, *cb_base;
@ -199,8 +200,9 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
struct xt_action_param acpar;
acpar.family = NFPROTO_BRIDGE;
acpar.in = in;
acpar.out = out;
acpar.net = state->net;
acpar.in = state->in;
acpar.out = state->out;
acpar.hotdrop = false;
acpar.hooknum = hook;
@ -220,7 +222,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
base = private->entries;
i = 0;
while (i < nentries) {
if (ebt_basic_match(point, skb, in, out))
if (ebt_basic_match(point, skb, state->in, state->out))
goto letscontinue;
if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &acpar) != 0)

View File

@ -65,31 +65,29 @@ int nft_bridge_ip6hdr_validate(struct sk_buff *skb)
EXPORT_SYMBOL_GPL(nft_bridge_ip6hdr_validate);
static inline void nft_bridge_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
if (nft_bridge_iphdr_validate(skb))
nft_set_pktinfo_ipv4(pkt, ops, skb, state);
nft_set_pktinfo_ipv4(pkt, skb, state);
else
nft_set_pktinfo(pkt, ops, skb, state);
nft_set_pktinfo(pkt, skb, state);
}
static inline void nft_bridge_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
#if IS_ENABLED(CONFIG_IPV6)
if (nft_bridge_ip6hdr_validate(skb) &&
nft_set_pktinfo_ipv6(pkt, ops, skb, state) == 0)
nft_set_pktinfo_ipv6(pkt, skb, state) == 0)
return;
#endif
nft_set_pktinfo(pkt, ops, skb, state);
nft_set_pktinfo(pkt, skb, state);
}
static unsigned int
nft_do_chain_bridge(const struct nf_hook_ops *ops,
nft_do_chain_bridge(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -97,17 +95,17 @@ nft_do_chain_bridge(const struct nf_hook_ops *ops,
switch (eth_hdr(skb)->h_proto) {
case htons(ETH_P_IP):
nft_bridge_set_pktinfo_ipv4(&pkt, ops, skb, state);
nft_bridge_set_pktinfo_ipv4(&pkt, skb, state);
break;
case htons(ETH_P_IPV6):
nft_bridge_set_pktinfo_ipv6(&pkt, ops, skb, state);
nft_bridge_set_pktinfo_ipv6(&pkt, skb, state);
break;
default:
nft_set_pktinfo(&pkt, ops, skb, state);
nft_set_pktinfo(&pkt, skb, state);
break;
}
return nft_do_chain(&pkt, ops);
return nft_do_chain(&pkt, priv);
}
static struct nft_af_info nft_af_bridge __read_mostly = {

View File

@ -261,7 +261,6 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr,
const struct nft_pktinfo *pkt)
{
struct nft_reject *priv = nft_expr_priv(expr);
struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out);
const unsigned char *dest = eth_hdr(pkt->skb)->h_dest;
if (is_broadcast_ether_addr(dest) ||
@ -273,16 +272,16 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr,
switch (priv->type) {
case NFT_REJECT_ICMP_UNREACH:
nft_reject_br_send_v4_unreach(pkt->skb, pkt->in,
pkt->ops->hooknum,
pkt->hook,
priv->icmp_code);
break;
case NFT_REJECT_TCP_RST:
nft_reject_br_send_v4_tcp_reset(pkt->skb, pkt->in,
pkt->ops->hooknum);
pkt->hook);
break;
case NFT_REJECT_ICMPX_UNREACH:
nft_reject_br_send_v4_unreach(pkt->skb, pkt->in,
pkt->ops->hooknum,
pkt->hook,
nft_reject_icmp_code(priv->icmp_code));
break;
}
@ -290,17 +289,17 @@ static void nft_reject_bridge_eval(const struct nft_expr *expr,
case htons(ETH_P_IPV6):
switch (priv->type) {
case NFT_REJECT_ICMP_UNREACH:
nft_reject_br_send_v6_unreach(net, pkt->skb, pkt->in,
pkt->ops->hooknum,
nft_reject_br_send_v6_unreach(pkt->net, pkt->skb,
pkt->in, pkt->hook,
priv->icmp_code);
break;
case NFT_REJECT_TCP_RST:
nft_reject_br_send_v6_tcp_reset(net, pkt->skb, pkt->in,
pkt->ops->hooknum);
nft_reject_br_send_v6_tcp_reset(pkt->net, pkt->skb,
pkt->in, pkt->hook);
break;
case NFT_REJECT_ICMPX_UNREACH:
nft_reject_br_send_v6_unreach(net, pkt->skb, pkt->in,
pkt->ops->hooknum,
nft_reject_br_send_v6_unreach(pkt->net, pkt->skb,
pkt->in, pkt->hook,
nft_reject_icmpv6_code(priv->icmp_code));
break;
}

View File

@ -87,7 +87,7 @@ static void dnrmg_send_peer(struct sk_buff *skb)
}
static unsigned int dnrmg_hook(const struct nf_hook_ops *ops,
static unsigned int dnrmg_hook(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{

View File

@ -247,10 +247,10 @@ struct arpt_entry *arpt_next_entry(const struct arpt_entry *entry)
}
unsigned int arpt_do_table(struct sk_buff *skb,
unsigned int hook,
const struct nf_hook_state *state,
struct xt_table *table)
{
unsigned int hook = state->hook;
static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
unsigned int verdict = NF_DROP;
const struct arphdr *arp;
@ -285,6 +285,7 @@ unsigned int arpt_do_table(struct sk_buff *skb,
*/
e = get_entry(table_base, private->hook_entry[hook]);
acpar.net = state->net;
acpar.in = state->in;
acpar.out = state->out;
acpar.hooknum = hook;

View File

@ -27,11 +27,10 @@ static const struct xt_table packet_filter = {
/* The work comes in here from netfilter.c */
static unsigned int
arptable_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
arptable_filter_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
return arpt_do_table(skb, ops->hooknum, state,
state->net->ipv4.arptable_filter);
return arpt_do_table(skb, state, state->net->ipv4.arptable_filter);
}
static struct nf_hook_ops *arpfilter_ops __read_mostly;

View File

@ -285,10 +285,10 @@ struct ipt_entry *ipt_next_entry(const struct ipt_entry *entry)
/* Returns one of the generic firewall policies, like NF_ACCEPT. */
unsigned int
ipt_do_table(struct sk_buff *skb,
unsigned int hook,
const struct nf_hook_state *state,
struct xt_table *table)
{
unsigned int hook = state->hook;
static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
const struct iphdr *ip;
/* Initializing verdict to NF_DROP keeps gcc happy. */
@ -315,6 +315,7 @@ ipt_do_table(struct sk_buff *skb,
acpar.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
acpar.thoff = ip_hdrlen(skb);
acpar.hotdrop = false;
acpar.net = state->net;
acpar.in = state->in;
acpar.out = state->out;
acpar.family = NFPROTO_IPV4;

View File

@ -507,7 +507,7 @@ static void arp_print(struct arp_payload *payload)
#endif
static unsigned int
arp_mangle(const struct nf_hook_ops *ops,
arp_mangle(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{

View File

@ -258,7 +258,7 @@ static unsigned int
synproxy_tg4(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct xt_synproxy_info *info = par->targinfo;
struct synproxy_net *snet = synproxy_pernet(dev_net(par->in));
struct synproxy_net *snet = synproxy_pernet(par->net);
struct synproxy_options opts = {};
struct tcphdr *th, _th;
@ -299,7 +299,7 @@ synproxy_tg4(struct sk_buff *skb, const struct xt_action_param *par)
return XT_CONTINUE;
}
static unsigned int ipv4_synproxy_hook(const struct nf_hook_ops *ops,
static unsigned int ipv4_synproxy_hook(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *nhs)
{

View File

@ -32,12 +32,11 @@ static __be32 rpfilter_get_saddr(__be32 addr)
return addr;
}
static bool rpfilter_lookup_reverse(struct flowi4 *fl4,
static bool rpfilter_lookup_reverse(struct net *net, struct flowi4 *fl4,
const struct net_device *dev, u8 flags)
{
struct fib_result res;
bool dev_match;
struct net *net = dev_net(dev);
int ret __maybe_unused;
if (fib_lookup(net, fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE))
@ -98,7 +97,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
flow.flowi4_tos = RT_TOS(iph->tos);
flow.flowi4_scope = RT_SCOPE_UNIVERSE;
return rpfilter_lookup_reverse(&flow, par->in, info->flags) ^ invert;
return rpfilter_lookup_reverse(par->net, &flow, par->in, info->flags) ^ invert;
}
static int rpfilter_check(const struct xt_mtchk_param *par)

View File

@ -33,17 +33,16 @@ static const struct xt_table packet_filter = {
};
static unsigned int
iptable_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
iptable_filter_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
if (ops->hooknum == NF_INET_LOCAL_OUT &&
if (state->hook == NF_INET_LOCAL_OUT &&
(skb->len < sizeof(struct iphdr) ||
ip_hdrlen(skb) < sizeof(struct iphdr)))
/* root is playing with raw sockets. */
return NF_ACCEPT;
return ipt_do_table(skb, ops->hooknum, state,
state->net->ipv4.iptable_filter);
return ipt_do_table(skb, state, state->net->ipv4.iptable_filter);
}
static struct nf_hook_ops *filter_ops __read_mostly;

View File

@ -58,8 +58,7 @@ ipt_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state)
daddr = iph->daddr;
tos = iph->tos;
ret = ipt_do_table(skb, NF_INET_LOCAL_OUT, state,
state->net->ipv4.iptable_mangle);
ret = ipt_do_table(skb, state, state->net->ipv4.iptable_mangle);
/* Reroute for ANY change. */
if (ret != NF_DROP && ret != NF_STOLEN) {
iph = ip_hdr(skb);
@ -79,18 +78,17 @@ ipt_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state)
/* The work comes in here from netfilter.c. */
static unsigned int
iptable_mangle_hook(const struct nf_hook_ops *ops,
iptable_mangle_hook(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
if (ops->hooknum == NF_INET_LOCAL_OUT)
if (state->hook == NF_INET_LOCAL_OUT)
return ipt_mangle_out(skb, state);
if (ops->hooknum == NF_INET_POST_ROUTING)
return ipt_do_table(skb, ops->hooknum, state,
if (state->hook == NF_INET_POST_ROUTING)
return ipt_do_table(skb, state,
state->net->ipv4.iptable_mangle);
/* PREROUTING/INPUT/FORWARD: */
return ipt_do_table(skb, ops->hooknum, state,
state->net->ipv4.iptable_mangle);
return ipt_do_table(skb, state, state->net->ipv4.iptable_mangle);
}
static struct nf_hook_ops *mangle_ops __read_mostly;

View File

@ -28,41 +28,40 @@ static const struct xt_table nf_nat_ipv4_table = {
.af = NFPROTO_IPV4,
};
static unsigned int iptable_nat_do_chain(const struct nf_hook_ops *ops,
static unsigned int iptable_nat_do_chain(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
struct nf_conn *ct)
{
return ipt_do_table(skb, ops->hooknum, state,
state->net->ipv4.nat_table);
return ipt_do_table(skb, state, state->net->ipv4.nat_table);
}
static unsigned int iptable_nat_ipv4_fn(const struct nf_hook_ops *ops,
static unsigned int iptable_nat_ipv4_fn(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_nat_ipv4_fn(ops, skb, state, iptable_nat_do_chain);
return nf_nat_ipv4_fn(priv, skb, state, iptable_nat_do_chain);
}
static unsigned int iptable_nat_ipv4_in(const struct nf_hook_ops *ops,
static unsigned int iptable_nat_ipv4_in(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_nat_ipv4_in(ops, skb, state, iptable_nat_do_chain);
return nf_nat_ipv4_in(priv, skb, state, iptable_nat_do_chain);
}
static unsigned int iptable_nat_ipv4_out(const struct nf_hook_ops *ops,
static unsigned int iptable_nat_ipv4_out(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_nat_ipv4_out(ops, skb, state, iptable_nat_do_chain);
return nf_nat_ipv4_out(priv, skb, state, iptable_nat_do_chain);
}
static unsigned int iptable_nat_ipv4_local_fn(const struct nf_hook_ops *ops,
static unsigned int iptable_nat_ipv4_local_fn(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_nat_ipv4_local_fn(ops, skb, state, iptable_nat_do_chain);
return nf_nat_ipv4_local_fn(priv, skb, state, iptable_nat_do_chain);
}
static struct nf_hook_ops nf_nat_ipv4_ops[] __read_mostly = {

View File

@ -20,17 +20,16 @@ static const struct xt_table packet_raw = {
/* The work comes in here from netfilter.c. */
static unsigned int
iptable_raw_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
iptable_raw_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
if (ops->hooknum == NF_INET_LOCAL_OUT &&
if (state->hook == NF_INET_LOCAL_OUT &&
(skb->len < sizeof(struct iphdr) ||
ip_hdrlen(skb) < sizeof(struct iphdr)))
/* root is playing with raw sockets. */
return NF_ACCEPT;
return ipt_do_table(skb, ops->hooknum, state,
state->net->ipv4.iptable_raw);
return ipt_do_table(skb, state, state->net->ipv4.iptable_raw);
}
static struct nf_hook_ops *rawtable_ops __read_mostly;

View File

@ -37,17 +37,16 @@ static const struct xt_table security_table = {
};
static unsigned int
iptable_security_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
iptable_security_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
if (ops->hooknum == NF_INET_LOCAL_OUT &&
if (state->hook == NF_INET_LOCAL_OUT &&
(skb->len < sizeof(struct iphdr) ||
ip_hdrlen(skb) < sizeof(struct iphdr)))
/* Somebody is playing with raw sockets. */
return NF_ACCEPT;
return ipt_do_table(skb, ops->hooknum, state,
state->net->ipv4.iptable_security);
return ipt_do_table(skb, state, state->net->ipv4.iptable_security);
}
static struct nf_hook_ops *sectbl_ops __read_mostly;

View File

@ -92,7 +92,7 @@ static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
return NF_ACCEPT;
}
static unsigned int ipv4_helper(const struct nf_hook_ops *ops,
static unsigned int ipv4_helper(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -119,7 +119,7 @@ static unsigned int ipv4_helper(const struct nf_hook_ops *ops,
ct, ctinfo);
}
static unsigned int ipv4_confirm(const struct nf_hook_ops *ops,
static unsigned int ipv4_confirm(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -143,14 +143,14 @@ out:
return nf_conntrack_confirm(skb);
}
static unsigned int ipv4_conntrack_in(const struct nf_hook_ops *ops,
static unsigned int ipv4_conntrack_in(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_conntrack_in(state->net, PF_INET, ops->hooknum, skb);
return nf_conntrack_in(state->net, PF_INET, state->hook, skb);
}
static unsigned int ipv4_conntrack_local(const struct nf_hook_ops *ops,
static unsigned int ipv4_conntrack_local(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -158,7 +158,7 @@ static unsigned int ipv4_conntrack_local(const struct nf_hook_ops *ops,
if (skb->len < sizeof(struct iphdr) ||
ip_hdrlen(skb) < sizeof(struct iphdr))
return NF_ACCEPT;
return nf_conntrack_in(state->net, PF_INET, ops->hooknum, skb);
return nf_conntrack_in(state->net, PF_INET, state->hook, skb);
}
/* Connection tracking may drop packets, but never alters them, so

View File

@ -30,7 +30,7 @@ static inline struct nf_icmp_net *icmp_pernet(struct net *net)
}
static bool icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
struct nf_conntrack_tuple *tuple)
struct net *net, struct nf_conntrack_tuple *tuple)
{
const struct icmphdr *hp;
struct icmphdr _hdr;
@ -144,7 +144,7 @@ icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
if (!nf_ct_get_tuplepr(skb,
skb_network_offset(skb) + ip_hdrlen(skb)
+ sizeof(struct icmphdr),
PF_INET, &origtuple)) {
PF_INET, net, &origtuple)) {
pr_debug("icmp_error_message: failed to get tuple\n");
return -NF_ACCEPT;
}

View File

@ -61,7 +61,7 @@ static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum,
return IP_DEFRAG_CONNTRACK_OUT + zone_id;
}
static unsigned int ipv4_conntrack_defrag(const struct nf_hook_ops *ops,
static unsigned int ipv4_conntrack_defrag(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -83,7 +83,7 @@ static unsigned int ipv4_conntrack_defrag(const struct nf_hook_ops *ops,
/* Gather fragments. */
if (ip_is_fragment(ip_hdr(skb))) {
enum ip_defrag_users user =
nf_ct_defrag_user(ops->hooknum, skb);
nf_ct_defrag_user(state->hook, skb);
if (nf_ct_ipv4_gather_frags(skb, user))
return NF_STOLEN;

View File

@ -23,25 +23,10 @@
#include <net/netfilter/nf_conntrack.h>
#endif
static struct net *pick_net(struct sk_buff *skb)
{
#ifdef CONFIG_NET_NS
const struct dst_entry *dst;
if (skb->dev != NULL)
return dev_net(skb->dev);
dst = skb_dst(skb);
if (dst != NULL && dst->dev != NULL)
return dev_net(dst->dev);
#endif
return &init_net;
}
static bool nf_dup_ipv4_route(struct sk_buff *skb, const struct in_addr *gw,
int oif)
static bool nf_dup_ipv4_route(struct net *net, struct sk_buff *skb,
const struct in_addr *gw, int oif)
{
const struct iphdr *iph = ip_hdr(skb);
struct net *net = pick_net(skb);
struct rtable *rt;
struct flowi4 fl4;
@ -65,7 +50,7 @@ static bool nf_dup_ipv4_route(struct sk_buff *skb, const struct in_addr *gw,
return true;
}
void nf_dup_ipv4(struct sk_buff *skb, unsigned int hooknum,
void nf_dup_ipv4(struct net *net, struct sk_buff *skb, unsigned int hooknum,
const struct in_addr *gw, int oif)
{
struct iphdr *iph;
@ -105,7 +90,7 @@ void nf_dup_ipv4(struct sk_buff *skb, unsigned int hooknum,
--iph->ttl;
ip_send_check(iph);
if (nf_dup_ipv4_route(skb, gw, oif)) {
if (nf_dup_ipv4_route(net, skb, gw, oif)) {
__this_cpu_write(nf_skb_duplicated, true);
ip_local_out(skb);
__this_cpu_write(nf_skb_duplicated, false);

View File

@ -255,9 +255,9 @@ int nf_nat_icmp_reply_translation(struct sk_buff *skb,
EXPORT_SYMBOL_GPL(nf_nat_icmp_reply_translation);
unsigned int
nf_nat_ipv4_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
nf_nat_ipv4_fn(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state,
unsigned int (*do_chain)(const struct nf_hook_ops *ops,
unsigned int (*do_chain)(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
struct nf_conn *ct))
@ -266,7 +266,7 @@ nf_nat_ipv4_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
enum ip_conntrack_info ctinfo;
struct nf_conn_nat *nat;
/* maniptype == SRC for postrouting. */
enum nf_nat_manip_type maniptype = HOOK2MANIP(ops->hooknum);
enum nf_nat_manip_type maniptype = HOOK2MANIP(state->hook);
/* We never see fragments: conntrack defrags on pre-routing
* and local-out, and nf_nat_out protects post-routing.
@ -295,7 +295,7 @@ nf_nat_ipv4_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
case IP_CT_RELATED_REPLY:
if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo,
ops->hooknum))
state->hook))
return NF_DROP;
else
return NF_ACCEPT;
@ -308,21 +308,21 @@ nf_nat_ipv4_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
if (!nf_nat_initialized(ct, maniptype)) {
unsigned int ret;
ret = do_chain(ops, skb, state, ct);
ret = do_chain(priv, skb, state, ct);
if (ret != NF_ACCEPT)
return ret;
if (nf_nat_initialized(ct, HOOK2MANIP(ops->hooknum)))
if (nf_nat_initialized(ct, HOOK2MANIP(state->hook)))
break;
ret = nf_nat_alloc_null_binding(ct, ops->hooknum);
ret = nf_nat_alloc_null_binding(ct, state->hook);
if (ret != NF_ACCEPT)
return ret;
} else {
pr_debug("Already setup manip %s for ct %p\n",
maniptype == NF_NAT_MANIP_SRC ? "SRC" : "DST",
ct);
if (nf_nat_oif_changed(ops->hooknum, ctinfo, nat,
if (nf_nat_oif_changed(state->hook, ctinfo, nat,
state->out))
goto oif_changed;
}
@ -332,11 +332,11 @@ nf_nat_ipv4_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
/* ESTABLISHED */
NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
ctinfo == IP_CT_ESTABLISHED_REPLY);
if (nf_nat_oif_changed(ops->hooknum, ctinfo, nat, state->out))
if (nf_nat_oif_changed(state->hook, ctinfo, nat, state->out))
goto oif_changed;
}
return nf_nat_packet(ct, ctinfo, ops->hooknum, skb);
return nf_nat_packet(ct, ctinfo, state->hook, skb);
oif_changed:
nf_ct_kill_acct(ct, ctinfo, skb);
@ -345,9 +345,9 @@ oif_changed:
EXPORT_SYMBOL_GPL(nf_nat_ipv4_fn);
unsigned int
nf_nat_ipv4_in(const struct nf_hook_ops *ops, struct sk_buff *skb,
nf_nat_ipv4_in(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state,
unsigned int (*do_chain)(const struct nf_hook_ops *ops,
unsigned int (*do_chain)(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
struct nf_conn *ct))
@ -355,7 +355,7 @@ nf_nat_ipv4_in(const struct nf_hook_ops *ops, struct sk_buff *skb,
unsigned int ret;
__be32 daddr = ip_hdr(skb)->daddr;
ret = nf_nat_ipv4_fn(ops, skb, state, do_chain);
ret = nf_nat_ipv4_fn(priv, skb, state, do_chain);
if (ret != NF_DROP && ret != NF_STOLEN &&
daddr != ip_hdr(skb)->daddr)
skb_dst_drop(skb);
@ -365,9 +365,9 @@ nf_nat_ipv4_in(const struct nf_hook_ops *ops, struct sk_buff *skb,
EXPORT_SYMBOL_GPL(nf_nat_ipv4_in);
unsigned int
nf_nat_ipv4_out(const struct nf_hook_ops *ops, struct sk_buff *skb,
nf_nat_ipv4_out(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state,
unsigned int (*do_chain)(const struct nf_hook_ops *ops,
unsigned int (*do_chain)(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
struct nf_conn *ct))
@ -384,7 +384,7 @@ nf_nat_ipv4_out(const struct nf_hook_ops *ops, struct sk_buff *skb,
ip_hdrlen(skb) < sizeof(struct iphdr))
return NF_ACCEPT;
ret = nf_nat_ipv4_fn(ops, skb, state, do_chain);
ret = nf_nat_ipv4_fn(priv, skb, state, do_chain);
#ifdef CONFIG_XFRM
if (ret != NF_DROP && ret != NF_STOLEN &&
!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
@ -396,7 +396,7 @@ nf_nat_ipv4_out(const struct nf_hook_ops *ops, struct sk_buff *skb,
(ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
ct->tuplehash[dir].tuple.src.u.all !=
ct->tuplehash[!dir].tuple.dst.u.all)) {
err = nf_xfrm_me_harder(skb, AF_INET);
err = nf_xfrm_me_harder(state->net, skb, AF_INET);
if (err < 0)
ret = NF_DROP_ERR(err);
}
@ -407,9 +407,9 @@ nf_nat_ipv4_out(const struct nf_hook_ops *ops, struct sk_buff *skb,
EXPORT_SYMBOL_GPL(nf_nat_ipv4_out);
unsigned int
nf_nat_ipv4_local_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state,
unsigned int (*do_chain)(const struct nf_hook_ops *ops,
unsigned int (*do_chain)(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
struct nf_conn *ct))
@ -424,7 +424,7 @@ nf_nat_ipv4_local_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
ip_hdrlen(skb) < sizeof(struct iphdr))
return NF_ACCEPT;
ret = nf_nat_ipv4_fn(ops, skb, state, do_chain);
ret = nf_nat_ipv4_fn(priv, skb, state, do_chain);
if (ret != NF_DROP && ret != NF_STOLEN &&
(ct = nf_ct_get(skb, &ctinfo)) != NULL) {
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
@ -440,7 +440,7 @@ nf_nat_ipv4_local_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
ct->tuplehash[dir].tuple.dst.u.all !=
ct->tuplehash[!dir].tuple.src.u.all) {
err = nf_xfrm_me_harder(skb, AF_INET);
err = nf_xfrm_me_harder(state->net, skb, AF_INET);
if (err < 0)
ret = NF_DROP_ERR(err);
}

View File

@ -15,15 +15,15 @@
#include <net/netfilter/nf_tables.h>
static unsigned int
nft_do_chain_arp(const struct nf_hook_ops *ops,
nft_do_chain_arp(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
struct nft_pktinfo pkt;
nft_set_pktinfo(&pkt, ops, skb, state);
nft_set_pktinfo(&pkt, skb, state);
return nft_do_chain(&pkt, ops);
return nft_do_chain(&pkt, priv);
}
static struct nft_af_info nft_af_arp __read_mostly = {

View File

@ -18,18 +18,18 @@
#include <net/ip.h>
#include <net/netfilter/nf_tables_ipv4.h>
static unsigned int nft_do_chain_ipv4(const struct nf_hook_ops *ops,
static unsigned int nft_do_chain_ipv4(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
struct nft_pktinfo pkt;
nft_set_pktinfo_ipv4(&pkt, ops, skb, state);
nft_set_pktinfo_ipv4(&pkt, skb, state);
return nft_do_chain(&pkt, ops);
return nft_do_chain(&pkt, priv);
}
static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops,
static unsigned int nft_ipv4_output(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -41,7 +41,7 @@ static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops,
return NF_ACCEPT;
}
return nft_do_chain_ipv4(ops, skb, state);
return nft_do_chain_ipv4(priv, skb, state);
}
struct nft_af_info nft_af_ipv4 __read_mostly = {

View File

@ -26,44 +26,44 @@
#include <net/netfilter/nf_nat_l3proto.h>
#include <net/ip.h>
static unsigned int nft_nat_do_chain(const struct nf_hook_ops *ops,
static unsigned int nft_nat_do_chain(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
struct nf_conn *ct)
{
struct nft_pktinfo pkt;
nft_set_pktinfo_ipv4(&pkt, ops, skb, state);
nft_set_pktinfo_ipv4(&pkt, skb, state);
return nft_do_chain(&pkt, ops);
return nft_do_chain(&pkt, priv);
}
static unsigned int nft_nat_ipv4_fn(const struct nf_hook_ops *ops,
static unsigned int nft_nat_ipv4_fn(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_nat_ipv4_fn(ops, skb, state, nft_nat_do_chain);
return nf_nat_ipv4_fn(priv, skb, state, nft_nat_do_chain);
}
static unsigned int nft_nat_ipv4_in(const struct nf_hook_ops *ops,
static unsigned int nft_nat_ipv4_in(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_nat_ipv4_in(ops, skb, state, nft_nat_do_chain);
return nf_nat_ipv4_in(priv, skb, state, nft_nat_do_chain);
}
static unsigned int nft_nat_ipv4_out(const struct nf_hook_ops *ops,
static unsigned int nft_nat_ipv4_out(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_nat_ipv4_out(ops, skb, state, nft_nat_do_chain);
return nf_nat_ipv4_out(priv, skb, state, nft_nat_do_chain);
}
static unsigned int nft_nat_ipv4_local_fn(const struct nf_hook_ops *ops,
static unsigned int nft_nat_ipv4_local_fn(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_nat_ipv4_local_fn(ops, skb, state, nft_nat_do_chain);
return nf_nat_ipv4_local_fn(priv, skb, state, nft_nat_do_chain);
}
static const struct nf_chain_type nft_chain_nat_ipv4 = {

View File

@ -21,7 +21,7 @@
#include <net/route.h>
#include <net/ip.h>
static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops,
static unsigned int nf_route_table_hook(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -37,7 +37,7 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops,
ip_hdrlen(skb) < sizeof(struct iphdr))
return NF_ACCEPT;
nft_set_pktinfo_ipv4(&pkt, ops, skb, state);
nft_set_pktinfo_ipv4(&pkt, skb, state);
mark = skb->mark;
iph = ip_hdr(skb);
@ -45,7 +45,7 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops,
daddr = iph->daddr;
tos = iph->tos;
ret = nft_do_chain(&pkt, ops);
ret = nft_do_chain(&pkt, priv);
if (ret != NF_DROP && ret != NF_QUEUE) {
iph = ip_hdr(skb);

View File

@ -30,7 +30,7 @@ static void nft_dup_ipv4_eval(const struct nft_expr *expr,
};
int oif = regs->data[priv->sreg_dev];
nf_dup_ipv4(pkt->skb, pkt->ops->hooknum, &gw, oif);
nf_dup_ipv4(pkt->net, pkt->skb, pkt->hook, &gw, oif);
}
static int nft_dup_ipv4_init(const struct nft_ctx *ctx,

View File

@ -26,7 +26,7 @@ static void nft_masq_ipv4_eval(const struct nft_expr *expr,
memset(&range, 0, sizeof(range));
range.flags = priv->flags;
regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, pkt->ops->hooknum,
regs->verdict.code = nf_nat_masquerade_ipv4(pkt->skb, pkt->hook,
&range, pkt->out);
}

View File

@ -36,7 +36,7 @@ static void nft_redir_ipv4_eval(const struct nft_expr *expr,
mr.range[0].flags |= priv->flags;
regs->verdict.code = nf_nat_redirect_ipv4(pkt->skb, &mr,
pkt->ops->hooknum);
pkt->hook);
}
static struct nft_expr_type nft_redir_ipv4_type;

View File

@ -27,11 +27,10 @@ static void nft_reject_ipv4_eval(const struct nft_expr *expr,
switch (priv->type) {
case NFT_REJECT_ICMP_UNREACH:
nf_send_unreach(pkt->skb, priv->icmp_code,
pkt->ops->hooknum);
nf_send_unreach(pkt->skb, priv->icmp_code, pkt->hook);
break;
case NFT_REJECT_TCP_RST:
nf_send_reset(pkt->skb, pkt->ops->hooknum);
nf_send_reset(pkt->skb, pkt->hook);
break;
default:
break;

View File

@ -314,10 +314,10 @@ ip6t_next_entry(const struct ip6t_entry *entry)
/* Returns one of the generic firewall policies, like NF_ACCEPT. */
unsigned int
ip6t_do_table(struct sk_buff *skb,
unsigned int hook,
const struct nf_hook_state *state,
struct xt_table *table)
{
unsigned int hook = state->hook;
static const char nulldevname[IFNAMSIZ] __attribute__((aligned(sizeof(long))));
/* Initializing verdict to NF_DROP keeps gcc happy. */
unsigned int verdict = NF_DROP;
@ -340,6 +340,7 @@ ip6t_do_table(struct sk_buff *skb,
* rule is also a fragment-specific rule, non-fragments won't
* match it. */
acpar.hotdrop = false;
acpar.net = state->net;
acpar.in = state->in;
acpar.out = state->out;
acpar.family = NFPROTO_IPV6;

View File

@ -39,7 +39,7 @@ static unsigned int
reject_tg6(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct ip6t_reject_info *reject = par->targinfo;
struct net *net = dev_net((par->in != NULL) ? par->in : par->out);
struct net *net = par->net;
switch (reject->with) {
case IP6T_ICMP6_NO_ROUTE:

View File

@ -275,7 +275,7 @@ 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(dev_net(par->in));
struct synproxy_net *snet = synproxy_pernet(par->net);
struct synproxy_options opts = {};
struct tcphdr *th, _th;
@ -316,7 +316,7 @@ synproxy_tg6(struct sk_buff *skb, const struct xt_action_param *par)
return XT_CONTINUE;
}
static unsigned int ipv6_synproxy_hook(const struct nf_hook_ops *ops,
static unsigned int ipv6_synproxy_hook(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *nhs)
{

View File

@ -26,7 +26,7 @@ static bool rpfilter_addr_unicast(const struct in6_addr *addr)
return addr_type & IPV6_ADDR_UNICAST;
}
static bool rpfilter_lookup_reverse6(const struct sk_buff *skb,
static bool rpfilter_lookup_reverse6(struct net *net, const struct sk_buff *skb,
const struct net_device *dev, u8 flags)
{
struct rt6_info *rt;
@ -53,7 +53,7 @@ static bool rpfilter_lookup_reverse6(const struct sk_buff *skb,
lookup_flags |= RT6_LOOKUP_F_IFACE;
}
rt = (void *) ip6_route_lookup(dev_net(dev), &fl6, lookup_flags);
rt = (void *) ip6_route_lookup(net, &fl6, lookup_flags);
if (rt->dst.error)
goto out;
@ -93,7 +93,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
if (unlikely(saddrtype == IPV6_ADDR_ANY))
return true ^ invert; /* not routable: forward path will drop it */
return rpfilter_lookup_reverse6(skb, par->in, info->flags) ^ invert;
return rpfilter_lookup_reverse6(par->net, skb, par->in, info->flags) ^ invert;
}
static int rpfilter_check(const struct xt_mtchk_param *par)

View File

@ -32,11 +32,10 @@ static const struct xt_table packet_filter = {
/* The work comes in here from netfilter.c. */
static unsigned int
ip6table_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
ip6table_filter_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
return ip6t_do_table(skb, ops->hooknum, state,
state->net->ipv6.ip6table_filter);
return ip6t_do_table(skb, state, state->net->ipv6.ip6table_filter);
}
static struct nf_hook_ops *filter_ops __read_mostly;

View File

@ -57,8 +57,7 @@ ip6t_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state)
/* flowlabel and prio (includes version, which shouldn't change either */
flowlabel = *((u_int32_t *)ipv6_hdr(skb));
ret = ip6t_do_table(skb, NF_INET_LOCAL_OUT, state,
state->net->ipv6.ip6table_mangle);
ret = ip6t_do_table(skb, state, state->net->ipv6.ip6table_mangle);
if (ret != NF_DROP && ret != NF_STOLEN &&
(!ipv6_addr_equal(&ipv6_hdr(skb)->saddr, &saddr) ||
@ -76,17 +75,16 @@ ip6t_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state)
/* The work comes in here from netfilter.c. */
static unsigned int
ip6table_mangle_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
ip6table_mangle_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
if (ops->hooknum == NF_INET_LOCAL_OUT)
if (state->hook == NF_INET_LOCAL_OUT)
return ip6t_mangle_out(skb, state);
if (ops->hooknum == NF_INET_POST_ROUTING)
return ip6t_do_table(skb, ops->hooknum, state,
if (state->hook == NF_INET_POST_ROUTING)
return ip6t_do_table(skb, state,
state->net->ipv6.ip6table_mangle);
/* INPUT/FORWARD */
return ip6t_do_table(skb, ops->hooknum, state,
state->net->ipv6.ip6table_mangle);
return ip6t_do_table(skb, state, state->net->ipv6.ip6table_mangle);
}
static struct nf_hook_ops *mangle_ops __read_mostly;

View File

@ -30,41 +30,40 @@ static const struct xt_table nf_nat_ipv6_table = {
.af = NFPROTO_IPV6,
};
static unsigned int ip6table_nat_do_chain(const struct nf_hook_ops *ops,
static unsigned int ip6table_nat_do_chain(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
struct nf_conn *ct)
{
return ip6t_do_table(skb, ops->hooknum, state,
state->net->ipv6.ip6table_nat);
return ip6t_do_table(skb, state, state->net->ipv6.ip6table_nat);
}
static unsigned int ip6table_nat_fn(const struct nf_hook_ops *ops,
static unsigned int ip6table_nat_fn(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_nat_ipv6_fn(ops, skb, state, ip6table_nat_do_chain);
return nf_nat_ipv6_fn(priv, skb, state, ip6table_nat_do_chain);
}
static unsigned int ip6table_nat_in(const struct nf_hook_ops *ops,
static unsigned int ip6table_nat_in(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_nat_ipv6_in(ops, skb, state, ip6table_nat_do_chain);
return nf_nat_ipv6_in(priv, skb, state, ip6table_nat_do_chain);
}
static unsigned int ip6table_nat_out(const struct nf_hook_ops *ops,
static unsigned int ip6table_nat_out(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_nat_ipv6_out(ops, skb, state, ip6table_nat_do_chain);
return nf_nat_ipv6_out(priv, skb, state, ip6table_nat_do_chain);
}
static unsigned int ip6table_nat_local_fn(const struct nf_hook_ops *ops,
static unsigned int ip6table_nat_local_fn(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_nat_ipv6_local_fn(ops, skb, state, ip6table_nat_do_chain);
return nf_nat_ipv6_local_fn(priv, skb, state, ip6table_nat_do_chain);
}
static struct nf_hook_ops nf_nat_ipv6_ops[] __read_mostly = {

View File

@ -19,11 +19,10 @@ static const struct xt_table packet_raw = {
/* The work comes in here from netfilter.c. */
static unsigned int
ip6table_raw_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
ip6table_raw_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
return ip6t_do_table(skb, ops->hooknum, state,
state->net->ipv6.ip6table_raw);
return ip6t_do_table(skb, state, state->net->ipv6.ip6table_raw);
}
static struct nf_hook_ops *rawtable_ops __read_mostly;

View File

@ -36,11 +36,10 @@ static const struct xt_table security_table = {
};
static unsigned int
ip6table_security_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
ip6table_security_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
return ip6t_do_table(skb, ops->hooknum, state,
state->net->ipv6.ip6table_security);
return ip6t_do_table(skb, state, state->net->ipv6.ip6table_security);
}
static struct nf_hook_ops *sectbl_ops __read_mostly;

View File

@ -95,7 +95,7 @@ static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
return NF_ACCEPT;
}
static unsigned int ipv6_helper(const struct nf_hook_ops *ops,
static unsigned int ipv6_helper(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -131,7 +131,7 @@ static unsigned int ipv6_helper(const struct nf_hook_ops *ops,
return helper->help(skb, protoff, ct, ctinfo);
}
static unsigned int ipv6_confirm(const struct nf_hook_ops *ops,
static unsigned int ipv6_confirm(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -165,14 +165,14 @@ out:
return nf_conntrack_confirm(skb);
}
static unsigned int ipv6_conntrack_in(const struct nf_hook_ops *ops,
static unsigned int ipv6_conntrack_in(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_conntrack_in(state->net, PF_INET6, ops->hooknum, skb);
return nf_conntrack_in(state->net, PF_INET6, state->hook, skb);
}
static unsigned int ipv6_conntrack_local(const struct nf_hook_ops *ops,
static unsigned int ipv6_conntrack_local(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -181,7 +181,7 @@ static unsigned int ipv6_conntrack_local(const struct nf_hook_ops *ops,
net_notice_ratelimited("ipv6_conntrack_local: packet too short\n");
return NF_ACCEPT;
}
return nf_conntrack_in(state->net, PF_INET6, ops->hooknum, skb);
return nf_conntrack_in(state->net, PF_INET6, state->hook, skb);
}
static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {

View File

@ -36,6 +36,7 @@ static inline struct nf_icmp_net *icmpv6_pernet(struct net *net)
static bool icmpv6_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
struct net *net,
struct nf_conntrack_tuple *tuple)
{
const struct icmp6hdr *hp;
@ -159,7 +160,7 @@ icmpv6_error_message(struct net *net, struct nf_conn *tmpl,
skb_network_offset(skb)
+ sizeof(struct ipv6hdr)
+ sizeof(struct icmp6hdr),
PF_INET6, &origtuple)) {
PF_INET6, net, &origtuple)) {
pr_debug("icmpv6_error: Can't get tuple\n");
return -NF_ACCEPT;
}

View File

@ -51,7 +51,7 @@ static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
return IP6_DEFRAG_CONNTRACK_OUT + zone_id;
}
static unsigned int ipv6_defrag(const struct nf_hook_ops *ops,
static unsigned int ipv6_defrag(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -63,7 +63,7 @@ static unsigned int ipv6_defrag(const struct nf_hook_ops *ops,
return NF_ACCEPT;
#endif
reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(ops->hooknum, skb));
reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(state->hook, skb));
/* queued */
if (reasm == NULL)
return NF_STOLEN;
@ -74,7 +74,7 @@ static unsigned int ipv6_defrag(const struct nf_hook_ops *ops,
nf_ct_frag6_consume_orig(reasm);
NF_HOOK_THRESH(NFPROTO_IPV6, ops->hooknum, state->net, state->sk, reasm,
NF_HOOK_THRESH(NFPROTO_IPV6, state->hook, state->net, state->sk, reasm,
state->in, state->out,
state->okfn, NF_IP6_PRI_CONNTRACK_DEFRAG + 1);

View File

@ -19,25 +19,10 @@
#include <net/netfilter/nf_conntrack.h>
#endif
static struct net *pick_net(struct sk_buff *skb)
{
#ifdef CONFIG_NET_NS
const struct dst_entry *dst;
if (skb->dev != NULL)
return dev_net(skb->dev);
dst = skb_dst(skb);
if (dst != NULL && dst->dev != NULL)
return dev_net(dst->dev);
#endif
return &init_net;
}
static bool nf_dup_ipv6_route(struct sk_buff *skb, const struct in6_addr *gw,
int oif)
static bool nf_dup_ipv6_route(struct net *net, struct sk_buff *skb,
const struct in6_addr *gw, int oif)
{
const struct ipv6hdr *iph = ipv6_hdr(skb);
struct net *net = pick_net(skb);
struct dst_entry *dst;
struct flowi6 fl6;
@ -61,7 +46,7 @@ static bool nf_dup_ipv6_route(struct sk_buff *skb, const struct in6_addr *gw,
return true;
}
void nf_dup_ipv6(struct sk_buff *skb, unsigned int hooknum,
void nf_dup_ipv6(struct net *net, struct sk_buff *skb, unsigned int hooknum,
const struct in6_addr *gw, int oif)
{
if (this_cpu_read(nf_skb_duplicated))
@ -81,7 +66,7 @@ void nf_dup_ipv6(struct sk_buff *skb, unsigned int hooknum,
struct ipv6hdr *iph = ipv6_hdr(skb);
--iph->hop_limit;
}
if (nf_dup_ipv6_route(skb, gw, oif)) {
if (nf_dup_ipv6_route(net, skb, gw, oif)) {
__this_cpu_write(nf_skb_duplicated, true);
ip6_local_out(skb);
__this_cpu_write(nf_skb_duplicated, false);

View File

@ -262,9 +262,9 @@ int nf_nat_icmpv6_reply_translation(struct sk_buff *skb,
EXPORT_SYMBOL_GPL(nf_nat_icmpv6_reply_translation);
unsigned int
nf_nat_ipv6_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
nf_nat_ipv6_fn(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state,
unsigned int (*do_chain)(const struct nf_hook_ops *ops,
unsigned int (*do_chain)(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
struct nf_conn *ct))
@ -272,7 +272,7 @@ nf_nat_ipv6_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
struct nf_conn *ct;
enum ip_conntrack_info ctinfo;
struct nf_conn_nat *nat;
enum nf_nat_manip_type maniptype = HOOK2MANIP(ops->hooknum);
enum nf_nat_manip_type maniptype = HOOK2MANIP(state->hook);
__be16 frag_off;
int hdrlen;
u8 nexthdr;
@ -303,7 +303,7 @@ nf_nat_ipv6_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
if (hdrlen >= 0 && nexthdr == IPPROTO_ICMPV6) {
if (!nf_nat_icmpv6_reply_translation(skb, ct, ctinfo,
ops->hooknum,
state->hook,
hdrlen))
return NF_DROP;
else
@ -317,21 +317,21 @@ nf_nat_ipv6_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
if (!nf_nat_initialized(ct, maniptype)) {
unsigned int ret;
ret = do_chain(ops, skb, state, ct);
ret = do_chain(priv, skb, state, ct);
if (ret != NF_ACCEPT)
return ret;
if (nf_nat_initialized(ct, HOOK2MANIP(ops->hooknum)))
if (nf_nat_initialized(ct, HOOK2MANIP(state->hook)))
break;
ret = nf_nat_alloc_null_binding(ct, ops->hooknum);
ret = nf_nat_alloc_null_binding(ct, state->hook);
if (ret != NF_ACCEPT)
return ret;
} else {
pr_debug("Already setup manip %s for ct %p\n",
maniptype == NF_NAT_MANIP_SRC ? "SRC" : "DST",
ct);
if (nf_nat_oif_changed(ops->hooknum, ctinfo, nat, state->out))
if (nf_nat_oif_changed(state->hook, ctinfo, nat, state->out))
goto oif_changed;
}
break;
@ -340,11 +340,11 @@ nf_nat_ipv6_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
/* ESTABLISHED */
NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
ctinfo == IP_CT_ESTABLISHED_REPLY);
if (nf_nat_oif_changed(ops->hooknum, ctinfo, nat, state->out))
if (nf_nat_oif_changed(state->hook, ctinfo, nat, state->out))
goto oif_changed;
}
return nf_nat_packet(ct, ctinfo, ops->hooknum, skb);
return nf_nat_packet(ct, ctinfo, state->hook, skb);
oif_changed:
nf_ct_kill_acct(ct, ctinfo, skb);
@ -353,9 +353,9 @@ oif_changed:
EXPORT_SYMBOL_GPL(nf_nat_ipv6_fn);
unsigned int
nf_nat_ipv6_in(const struct nf_hook_ops *ops, struct sk_buff *skb,
nf_nat_ipv6_in(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state,
unsigned int (*do_chain)(const struct nf_hook_ops *ops,
unsigned int (*do_chain)(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
struct nf_conn *ct))
@ -363,7 +363,7 @@ nf_nat_ipv6_in(const struct nf_hook_ops *ops, struct sk_buff *skb,
unsigned int ret;
struct in6_addr daddr = ipv6_hdr(skb)->daddr;
ret = nf_nat_ipv6_fn(ops, skb, state, do_chain);
ret = nf_nat_ipv6_fn(priv, skb, state, do_chain);
if (ret != NF_DROP && ret != NF_STOLEN &&
ipv6_addr_cmp(&daddr, &ipv6_hdr(skb)->daddr))
skb_dst_drop(skb);
@ -373,9 +373,9 @@ nf_nat_ipv6_in(const struct nf_hook_ops *ops, struct sk_buff *skb,
EXPORT_SYMBOL_GPL(nf_nat_ipv6_in);
unsigned int
nf_nat_ipv6_out(const struct nf_hook_ops *ops, struct sk_buff *skb,
nf_nat_ipv6_out(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state,
unsigned int (*do_chain)(const struct nf_hook_ops *ops,
unsigned int (*do_chain)(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
struct nf_conn *ct))
@ -391,7 +391,7 @@ nf_nat_ipv6_out(const struct nf_hook_ops *ops, struct sk_buff *skb,
if (skb->len < sizeof(struct ipv6hdr))
return NF_ACCEPT;
ret = nf_nat_ipv6_fn(ops, skb, state, do_chain);
ret = nf_nat_ipv6_fn(priv, skb, state, do_chain);
#ifdef CONFIG_XFRM
if (ret != NF_DROP && ret != NF_STOLEN &&
!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
@ -403,7 +403,7 @@ nf_nat_ipv6_out(const struct nf_hook_ops *ops, struct sk_buff *skb,
(ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
ct->tuplehash[dir].tuple.src.u.all !=
ct->tuplehash[!dir].tuple.dst.u.all)) {
err = nf_xfrm_me_harder(skb, AF_INET6);
err = nf_xfrm_me_harder(state->net, skb, AF_INET6);
if (err < 0)
ret = NF_DROP_ERR(err);
}
@ -414,9 +414,9 @@ nf_nat_ipv6_out(const struct nf_hook_ops *ops, struct sk_buff *skb,
EXPORT_SYMBOL_GPL(nf_nat_ipv6_out);
unsigned int
nf_nat_ipv6_local_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state,
unsigned int (*do_chain)(const struct nf_hook_ops *ops,
unsigned int (*do_chain)(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
struct nf_conn *ct))
@ -430,7 +430,7 @@ nf_nat_ipv6_local_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
if (skb->len < sizeof(struct ipv6hdr))
return NF_ACCEPT;
ret = nf_nat_ipv6_fn(ops, skb, state, do_chain);
ret = nf_nat_ipv6_fn(priv, skb, state, do_chain);
if (ret != NF_DROP && ret != NF_STOLEN &&
(ct = nf_ct_get(skb, &ctinfo)) != NULL) {
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
@ -446,7 +446,7 @@ nf_nat_ipv6_local_fn(const struct nf_hook_ops *ops, struct sk_buff *skb,
ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
ct->tuplehash[dir].tuple.dst.u.all !=
ct->tuplehash[!dir].tuple.src.u.all) {
err = nf_xfrm_me_harder(skb, AF_INET6);
err = nf_xfrm_me_harder(state->net, skb, AF_INET6);
if (err < 0)
ret = NF_DROP_ERR(err);
}

View File

@ -34,7 +34,7 @@ nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range *range,
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
ctinfo == IP_CT_RELATED_REPLY));
if (ipv6_dev_get_saddr(dev_net(out), out,
if (ipv6_dev_get_saddr(nf_ct_net(ct), out,
&ipv6_hdr(skb)->daddr, 0, &src) < 0)
return NF_DROP;

View File

@ -16,20 +16,20 @@
#include <net/netfilter/nf_tables.h>
#include <net/netfilter/nf_tables_ipv6.h>
static unsigned int nft_do_chain_ipv6(const struct nf_hook_ops *ops,
static unsigned int nft_do_chain_ipv6(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
struct nft_pktinfo pkt;
/* malformed packet, drop it */
if (nft_set_pktinfo_ipv6(&pkt, ops, skb, state) < 0)
if (nft_set_pktinfo_ipv6(&pkt, skb, state) < 0)
return NF_DROP;
return nft_do_chain(&pkt, ops);
return nft_do_chain(&pkt, priv);
}
static unsigned int nft_ipv6_output(const struct nf_hook_ops *ops,
static unsigned int nft_ipv6_output(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -40,7 +40,7 @@ static unsigned int nft_ipv6_output(const struct nf_hook_ops *ops,
return NF_ACCEPT;
}
return nft_do_chain_ipv6(ops, skb, state);
return nft_do_chain_ipv6(priv, skb, state);
}
struct nft_af_info nft_af_ipv6 __read_mostly = {

View File

@ -24,44 +24,44 @@
#include <net/netfilter/nf_nat_l3proto.h>
#include <net/ipv6.h>
static unsigned int nft_nat_do_chain(const struct nf_hook_ops *ops,
static unsigned int nft_nat_do_chain(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state,
struct nf_conn *ct)
{
struct nft_pktinfo pkt;
nft_set_pktinfo_ipv6(&pkt, ops, skb, state);
nft_set_pktinfo_ipv6(&pkt, skb, state);
return nft_do_chain(&pkt, ops);
return nft_do_chain(&pkt, priv);
}
static unsigned int nft_nat_ipv6_fn(const struct nf_hook_ops *ops,
static unsigned int nft_nat_ipv6_fn(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_nat_ipv6_fn(ops, skb, state, nft_nat_do_chain);
return nf_nat_ipv6_fn(priv, skb, state, nft_nat_do_chain);
}
static unsigned int nft_nat_ipv6_in(const struct nf_hook_ops *ops,
static unsigned int nft_nat_ipv6_in(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_nat_ipv6_in(ops, skb, state, nft_nat_do_chain);
return nf_nat_ipv6_in(priv, skb, state, nft_nat_do_chain);
}
static unsigned int nft_nat_ipv6_out(const struct nf_hook_ops *ops,
static unsigned int nft_nat_ipv6_out(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_nat_ipv6_out(ops, skb, state, nft_nat_do_chain);
return nf_nat_ipv6_out(priv, skb, state, nft_nat_do_chain);
}
static unsigned int nft_nat_ipv6_local_fn(const struct nf_hook_ops *ops,
static unsigned int nft_nat_ipv6_local_fn(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
return nf_nat_ipv6_local_fn(ops, skb, state, nft_nat_do_chain);
return nf_nat_ipv6_local_fn(priv, skb, state, nft_nat_do_chain);
}
static const struct nf_chain_type nft_chain_nat_ipv6 = {

View File

@ -22,7 +22,7 @@
#include <net/netfilter/nf_tables_ipv6.h>
#include <net/route.h>
static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops,
static unsigned int nf_route_table_hook(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -33,7 +33,7 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops,
u32 mark, flowlabel;
/* malformed packet, drop it */
if (nft_set_pktinfo_ipv6(&pkt, ops, skb, state) < 0)
if (nft_set_pktinfo_ipv6(&pkt, skb, state) < 0)
return NF_DROP;
/* save source/dest address, mark, hoplimit, flowlabel, priority */
@ -45,7 +45,7 @@ static unsigned int nf_route_table_hook(const struct nf_hook_ops *ops,
/* flowlabel and prio (includes version, which shouldn't change either */
flowlabel = *((u32 *)ipv6_hdr(skb));
ret = nft_do_chain(&pkt, ops);
ret = nft_do_chain(&pkt, priv);
if (ret != NF_DROP && ret != NF_QUEUE &&
(memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) ||
memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr)) ||

View File

@ -28,7 +28,7 @@ static void nft_dup_ipv6_eval(const struct nft_expr *expr,
struct in6_addr *gw = (struct in6_addr *)&regs->data[priv->sreg_addr];
int oif = regs->data[priv->sreg_dev];
nf_dup_ipv6(pkt->skb, pkt->ops->hooknum, gw, oif);
nf_dup_ipv6(pkt->net, pkt->skb, pkt->hook, gw, oif);
}
static int nft_dup_ipv6_init(const struct nft_ctx *ctx,

View File

@ -35,8 +35,7 @@ static void nft_redir_ipv6_eval(const struct nft_expr *expr,
range.flags |= priv->flags;
regs->verdict.code = nf_nat_redirect_ipv6(pkt->skb, &range,
pkt->ops->hooknum);
regs->verdict.code = nf_nat_redirect_ipv6(pkt->skb, &range, pkt->hook);
}
static struct nft_expr_type nft_redir_ipv6_type;

View File

@ -24,15 +24,14 @@ static void nft_reject_ipv6_eval(const struct nft_expr *expr,
const struct nft_pktinfo *pkt)
{
struct nft_reject *priv = nft_expr_priv(expr);
struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out);
switch (priv->type) {
case NFT_REJECT_ICMP_UNREACH:
nf_send_unreach6(net, pkt->skb, priv->icmp_code,
pkt->ops->hooknum);
nf_send_unreach6(pkt->net, pkt->skb, priv->icmp_code,
pkt->hook);
break;
case NFT_REJECT_TCP_RST:
nf_send_reset6(net, pkt->skb, pkt->ops->hooknum);
nf_send_reset6(pkt->net, pkt->skb, pkt->hook);
break;
default:
break;

View File

@ -269,7 +269,7 @@ unsigned int nf_iterate(struct list_head *head,
/* Optimization: we don't need to hold module
reference here, since function can't sleep. --RR */
repeat:
verdict = (*elemp)->hook(*elemp, skb, state);
verdict = (*elemp)->hook((*elemp)->priv, skb, state);
if (verdict != NF_ACCEPT) {
#ifdef CONFIG_NETFILTER_DEBUG
if (unlikely((verdict & NF_VERDICT_MASK)

View File

@ -519,8 +519,7 @@ int
ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
const struct xt_action_param *par, struct ip_set_adt_opt *opt)
{
struct ip_set *set = ip_set_rcu_get(
dev_net(par->in ? par->in : par->out), index);
struct ip_set *set = ip_set_rcu_get(par->net, index);
int ret = 0;
BUG_ON(!set);
@ -558,8 +557,7 @@ int
ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
const struct xt_action_param *par, struct ip_set_adt_opt *opt)
{
struct ip_set *set = ip_set_rcu_get(
dev_net(par->in ? par->in : par->out), index);
struct ip_set *set = ip_set_rcu_get(par->net, index);
int ret;
BUG_ON(!set);
@ -581,8 +579,7 @@ int
ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
const struct xt_action_param *par, struct ip_set_adt_opt *opt)
{
struct ip_set *set = ip_set_rcu_get(
dev_net(par->in ? par->in : par->out), index);
struct ip_set *set = ip_set_rcu_get(par->net, index);
int ret = 0;
BUG_ON(!set);

View File

@ -316,7 +316,7 @@ struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p)
static int
ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb,
const struct ip_vs_iphdr *iph,
int inverse, struct ip_vs_conn_param *p)
struct ip_vs_conn_param *p)
{
__be16 _ports[2], *pptr;
struct net *net = skb_net(skb);
@ -325,7 +325,7 @@ ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb,
if (pptr == NULL)
return 1;
if (likely(!inverse))
if (likely(!ip_vs_iph_inverse(iph)))
ip_vs_conn_fill_param(net, af, iph->protocol, &iph->saddr,
pptr[0], &iph->daddr, pptr[1], p);
else
@ -336,11 +336,11 @@ ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb,
struct ip_vs_conn *
ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
const struct ip_vs_iphdr *iph, int inverse)
const struct ip_vs_iphdr *iph)
{
struct ip_vs_conn_param p;
if (ip_vs_conn_fill_param_proto(af, skb, iph, inverse, &p))
if (ip_vs_conn_fill_param_proto(af, skb, iph, &p))
return NULL;
return ip_vs_conn_in_get(&p);
@ -440,11 +440,11 @@ struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p)
struct ip_vs_conn *
ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
const struct ip_vs_iphdr *iph, int inverse)
const struct ip_vs_iphdr *iph)
{
struct ip_vs_conn_param p;
if (ip_vs_conn_fill_param_proto(af, skb, iph, inverse, &p))
if (ip_vs_conn_fill_param_proto(af, skb, iph, &p))
return NULL;
return ip_vs_conn_out_get(&p);

View File

@ -245,20 +245,30 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
const union nf_inet_addr fwmark = { .ip = htonl(svc->fwmark) };
union nf_inet_addr snet; /* source network of the client,
after masking */
const union nf_inet_addr *src_addr, *dst_addr;
if (likely(!ip_vs_iph_inverse(iph))) {
src_addr = &iph->saddr;
dst_addr = &iph->daddr;
} else {
src_addr = &iph->daddr;
dst_addr = &iph->saddr;
}
/* Mask saddr with the netmask to adjust template granularity */
#ifdef CONFIG_IP_VS_IPV6
if (svc->af == AF_INET6)
ipv6_addr_prefix(&snet.in6, &iph->saddr.in6,
ipv6_addr_prefix(&snet.in6, &src_addr->in6,
(__force __u32) svc->netmask);
else
#endif
snet.ip = iph->saddr.ip & svc->netmask;
snet.ip = src_addr->ip & svc->netmask;
IP_VS_DBG_BUF(6, "p-schedule: src %s:%u dest %s:%u "
"mnet %s\n",
IP_VS_DBG_ADDR(svc->af, &iph->saddr), ntohs(src_port),
IP_VS_DBG_ADDR(svc->af, &iph->daddr), ntohs(dst_port),
IP_VS_DBG_ADDR(svc->af, src_addr), ntohs(src_port),
IP_VS_DBG_ADDR(svc->af, dst_addr), ntohs(dst_port),
IP_VS_DBG_ADDR(svc->af, &snet));
/*
@ -276,7 +286,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
*/
{
int protocol = iph->protocol;
const union nf_inet_addr *vaddr = &iph->daddr;
const union nf_inet_addr *vaddr = dst_addr;
__be16 vport = 0;
if (dst_port == svc->port) {
@ -366,8 +376,8 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
/*
* Create a new connection according to the template
*/
ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, &iph->saddr,
src_port, &iph->daddr, dst_port, &param);
ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, src_addr,
src_port, dst_addr, dst_port, &param);
cp = ip_vs_conn_new(&param, dest->af, &dest->addr, dport, flags, dest,
skb->mark);
@ -418,7 +428,8 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
struct ip_vs_conn *cp = NULL;
struct ip_vs_scheduler *sched;
struct ip_vs_dest *dest;
__be16 _ports[2], *pptr;
__be16 _ports[2], *pptr, cport, vport;
const void *caddr, *vaddr;
unsigned int flags;
*ignored = 1;
@ -429,14 +440,26 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
if (pptr == NULL)
return NULL;
if (likely(!ip_vs_iph_inverse(iph))) {
cport = pptr[0];
caddr = &iph->saddr;
vport = pptr[1];
vaddr = &iph->daddr;
} else {
cport = pptr[1];
caddr = &iph->daddr;
vport = pptr[0];
vaddr = &iph->saddr;
}
/*
* FTPDATA needs this check when using local real server.
* Never schedule Active FTPDATA connections from real server.
* For LVS-NAT they must be already created. For other methods
* with persistence the connection is created on SYN+ACK.
*/
if (pptr[0] == FTPDATA) {
IP_VS_DBG_PKT(12, svc->af, pp, skb, 0,
if (cport == FTPDATA) {
IP_VS_DBG_PKT(12, svc->af, pp, skb, iph->off,
"Not scheduling FTPDATA");
return NULL;
}
@ -444,19 +467,25 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
/*
* Do not schedule replies from local real server.
*/
if ((!skb->dev || skb->dev->flags & IFF_LOOPBACK) &&
(cp = pp->conn_in_get(svc->af, skb, iph, 1))) {
IP_VS_DBG_PKT(12, svc->af, pp, skb, 0,
"Not scheduling reply for existing connection");
__ip_vs_conn_put(cp);
return NULL;
if ((!skb->dev || skb->dev->flags & IFF_LOOPBACK)) {
iph->hdr_flags ^= IP_VS_HDR_INVERSE;
cp = pp->conn_in_get(svc->af, skb, iph);
iph->hdr_flags ^= IP_VS_HDR_INVERSE;
if (cp) {
IP_VS_DBG_PKT(12, svc->af, pp, skb, iph->off,
"Not scheduling reply for existing"
" connection");
__ip_vs_conn_put(cp);
return NULL;
}
}
/*
* Persistent service
*/
if (svc->flags & IP_VS_SVC_F_PERSISTENT)
return ip_vs_sched_persist(svc, skb, pptr[0], pptr[1], ignored,
return ip_vs_sched_persist(svc, skb, cport, vport, ignored,
iph);
*ignored = 0;
@ -464,7 +493,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
/*
* Non-persistent service
*/
if (!svc->fwmark && pptr[1] != svc->port) {
if (!svc->fwmark && vport != svc->port) {
if (!svc->port)
pr_err("Schedule: port zero only supported "
"in persistent services, "
@ -496,10 +525,9 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
struct ip_vs_conn_param p;
ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol,
&iph->saddr, pptr[0], &iph->daddr,
pptr[1], &p);
caddr, cport, vaddr, vport, &p);
cp = ip_vs_conn_new(&p, dest->af, &dest->addr,
dest->port ? dest->port : pptr[1],
dest->port ? dest->port : vport,
flags, dest, skb->mark);
if (!cp) {
*ignored = -1;
@ -519,6 +547,17 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
return cp;
}
#ifdef CONFIG_SYSCTL
static inline int ip_vs_addr_is_unicast(struct net *net, int af,
union nf_inet_addr *addr)
{
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6)
return ipv6_addr_type(&addr->in6) & IPV6_ADDR_UNICAST;
#endif
return (inet_addr_type(net, addr->ip) == RTN_UNICAST);
}
#endif
/*
* Pass or drop the packet.
@ -528,33 +567,28 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph)
{
__be16 _ports[2], *pptr;
__be16 _ports[2], *pptr, dport;
#ifdef CONFIG_SYSCTL
struct net *net;
struct netns_ipvs *ipvs;
int unicast;
#endif
pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports, iph);
if (pptr == NULL) {
if (!pptr)
return NF_DROP;
}
dport = likely(!ip_vs_iph_inverse(iph)) ? pptr[1] : pptr[0];
#ifdef CONFIG_SYSCTL
net = skb_net(skb);
#ifdef CONFIG_IP_VS_IPV6
if (svc->af == AF_INET6)
unicast = ipv6_addr_type(&iph->daddr.in6) & IPV6_ADDR_UNICAST;
else
#endif
unicast = (inet_addr_type(net, iph->daddr.ip) == RTN_UNICAST);
/* if it is fwmark-based service, the cache_bypass sysctl is up
and the destination is a non-local unicast, then create
a cache_bypass connection entry */
ipvs = net_ipvs(net);
if (ipvs->sysctl_cache_bypass && svc->fwmark && unicast) {
if (ipvs->sysctl_cache_bypass && svc->fwmark &&
!(iph->hdr_flags & (IP_VS_HDR_INVERSE | IP_VS_HDR_ICMP)) &&
ip_vs_addr_is_unicast(net, svc->af, &iph->daddr)) {
int ret;
struct ip_vs_conn *cp;
unsigned int flags = (svc->flags & IP_VS_SVC_F_ONEPACKET &&
@ -598,9 +632,12 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
* listed in the ipvs table), pass the packets, because it is
* not ipvs job to decide to drop the packets.
*/
if ((svc->port == FTPPORT) && (pptr[1] != FTPPORT))
if (svc->port == FTPPORT && dport != FTPPORT)
return NF_ACCEPT;
if (unlikely(ip_vs_iph_icmp(iph)))
return NF_DROP;
/*
* Notify the client that the destination is unreachable, and
* release the socket buffer.
@ -934,10 +971,10 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related,
IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
"Checking outgoing ICMP for");
ip_vs_fill_ip4hdr(cih, &ciph);
ciph.len += offset;
ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, true, &ciph);
/* The embedded headers contain source and dest in reverse order */
cp = pp->conn_out_get(AF_INET, skb, &ciph, 1);
cp = pp->conn_out_get(AF_INET, skb, &ciph);
if (!cp)
return NF_ACCEPT;
@ -951,12 +988,11 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related,
unsigned int hooknum, struct ip_vs_iphdr *ipvsh)
{
struct icmp6hdr _icmph, *ic;
struct ipv6hdr _ip6h, *ip6h; /* The ip header contained within ICMP */
struct ip_vs_iphdr ciph = {.flags = 0, .fragoffs = 0};/*Contained IP */
struct ip_vs_conn *cp;
struct ip_vs_protocol *pp;
union nf_inet_addr snet;
unsigned int writable;
unsigned int offset;
*related = 1;
ic = frag_safe_skb_hp(skb, ipvsh->len, sizeof(_icmph), &_icmph, ipvsh);
@ -984,31 +1020,23 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related,
ic->icmp6_type, ntohs(icmpv6_id(ic)),
&ipvsh->saddr, &ipvsh->daddr);
/* Now find the contained IP header */
ciph.len = ipvsh->len + sizeof(_icmph);
ip6h = skb_header_pointer(skb, ciph.len, sizeof(_ip6h), &_ip6h);
if (ip6h == NULL)
if (!ip_vs_fill_iph_skb_icmp(AF_INET6, skb, ipvsh->len + sizeof(_icmph),
true, &ciph))
return NF_ACCEPT; /* The packet looks wrong, ignore */
ciph.saddr.in6 = ip6h->saddr; /* conn_out_get() handles reverse order */
ciph.daddr.in6 = ip6h->daddr;
/* skip possible IPv6 exthdrs of contained IPv6 packet */
ciph.protocol = ipv6_find_hdr(skb, &ciph.len, -1, &ciph.fragoffs, NULL);
if (ciph.protocol < 0)
return NF_ACCEPT; /* Contained IPv6 hdr looks wrong, ignore */
pp = ip_vs_proto_get(ciph.protocol);
if (!pp)
return NF_ACCEPT;
/* The embedded headers contain source and dest in reverse order */
cp = pp->conn_out_get(AF_INET6, skb, &ciph, 1);
cp = pp->conn_out_get(AF_INET6, skb, &ciph);
if (!cp)
return NF_ACCEPT;
snet.in6 = ciph.saddr.in6;
writable = ciph.len;
offset = ciph.len;
return handle_response_icmp(AF_INET6, skb, &snet, ciph.protocol, cp,
pp, writable, sizeof(struct ipv6hdr),
pp, offset, sizeof(struct ipv6hdr),
hooknum);
}
#endif
@ -1093,7 +1121,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
{
struct ip_vs_protocol *pp = pd->pp;
IP_VS_DBG_PKT(11, af, pp, skb, 0, "Outgoing packet");
IP_VS_DBG_PKT(11, af, pp, skb, iph->off, "Outgoing packet");
if (!skb_make_writable(skb, iph->len))
goto drop;
@ -1130,7 +1158,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
if (ip_vs_route_me_harder(af, skb, hooknum))
goto drop;
IP_VS_DBG_PKT(10, af, pp, skb, 0, "After SNAT");
IP_VS_DBG_PKT(10, af, pp, skb, iph->off, "After SNAT");
ip_vs_out_stats(cp, skb);
ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pd);
@ -1186,7 +1214,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
if (!net_ipvs(net)->enable)
return NF_ACCEPT;
ip_vs_fill_iph_skb(af, skb, &iph);
ip_vs_fill_iph_skb(af, skb, false, &iph);
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6) {
if (unlikely(iph.protocol == IPPROTO_ICMPV6)) {
@ -1221,13 +1249,13 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
ip_vs_defrag_user(hooknum)))
return NF_STOLEN;
ip_vs_fill_ip4hdr(skb_network_header(skb), &iph);
ip_vs_fill_iph_skb(AF_INET, skb, false, &iph);
}
/*
* Check if the packet belongs to an existing entry
*/
cp = pp->conn_out_get(af, skb, &iph, 0);
cp = pp->conn_out_get(af, skb, &iph);
if (likely(cp))
return handle_response(af, skb, pd, cp, &iph, hooknum);
@ -1272,7 +1300,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
}
}
}
IP_VS_DBG_PKT(12, af, pp, skb, 0,
IP_VS_DBG_PKT(12, af, pp, skb, iph.off,
"ip_vs_out: packet continues traversal as normal");
return NF_ACCEPT;
}
@ -1283,10 +1311,10 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
* Check if packet is reply for established ip_vs_conn.
*/
static unsigned int
ip_vs_reply4(const struct nf_hook_ops *ops, struct sk_buff *skb,
ip_vs_reply4(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
return ip_vs_out(ops->hooknum, skb, AF_INET);
return ip_vs_out(state->hook, skb, AF_INET);
}
/*
@ -1294,10 +1322,10 @@ ip_vs_reply4(const struct nf_hook_ops *ops, struct sk_buff *skb,
* Check if packet is reply for established ip_vs_conn.
*/
static unsigned int
ip_vs_local_reply4(const struct nf_hook_ops *ops, struct sk_buff *skb,
ip_vs_local_reply4(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
return ip_vs_out(ops->hooknum, skb, AF_INET);
return ip_vs_out(state->hook, skb, AF_INET);
}
#ifdef CONFIG_IP_VS_IPV6
@ -1308,10 +1336,10 @@ ip_vs_local_reply4(const struct nf_hook_ops *ops, struct sk_buff *skb,
* Check if packet is reply for established ip_vs_conn.
*/
static unsigned int
ip_vs_reply6(const struct nf_hook_ops *ops, struct sk_buff *skb,
ip_vs_reply6(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
return ip_vs_out(ops->hooknum, skb, AF_INET6);
return ip_vs_out(state->hook, skb, AF_INET6);
}
/*
@ -1319,14 +1347,50 @@ ip_vs_reply6(const struct nf_hook_ops *ops, struct sk_buff *skb,
* Check if packet is reply for established ip_vs_conn.
*/
static unsigned int
ip_vs_local_reply6(const struct nf_hook_ops *ops, struct sk_buff *skb,
ip_vs_local_reply6(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
return ip_vs_out(ops->hooknum, skb, AF_INET6);
return ip_vs_out(state->hook, skb, AF_INET6);
}
#endif
static unsigned int
ip_vs_try_to_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
int *verdict, struct ip_vs_conn **cpp,
struct ip_vs_iphdr *iph)
{
struct ip_vs_protocol *pp = pd->pp;
if (!iph->fragoffs) {
/* No (second) fragments need to enter here, as nf_defrag_ipv6
* replayed fragment zero will already have created the cp
*/
/* Schedule and create new connection entry into cpp */
if (!pp->conn_schedule(af, skb, pd, verdict, cpp, iph))
return 0;
}
if (unlikely(!*cpp)) {
/* sorry, all this trouble for a no-hit :) */
IP_VS_DBG_PKT(12, af, pp, skb, iph->off,
"ip_vs_in: packet continues traversal as normal");
if (iph->fragoffs) {
/* Fragment that couldn't be mapped to a conn entry
* is missing module nf_defrag_ipv6
*/
IP_VS_DBG_RL("Unhandled frag, load nf_defrag_ipv6\n");
IP_VS_DBG_PKT(7, af, pp, skb, iph->off,
"unhandled fragment");
}
*verdict = NF_ACCEPT;
return 0;
}
return 1;
}
/*
* Handle ICMP messages in the outside-to-inside direction (incoming).
* Find any that might be relevant, check against existing connections,
@ -1345,7 +1409,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
struct ip_vs_protocol *pp;
struct ip_vs_proto_data *pd;
unsigned int offset, offset2, ihl, verdict;
bool ipip;
bool ipip, new_cp = false;
*related = 1;
@ -1416,15 +1480,24 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
"Checking incoming ICMP for");
offset2 = offset;
ip_vs_fill_ip4hdr(cih, &ciph);
ciph.len += offset;
ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, !ipip, &ciph);
offset = ciph.len;
/* The embedded headers contain source and dest in reverse order.
* For IPIP this is error for request, not for reply.
*/
cp = pp->conn_in_get(AF_INET, skb, &ciph, ipip ? 0 : 1);
if (!cp)
return NF_ACCEPT;
cp = pp->conn_in_get(AF_INET, skb, &ciph);
if (!cp) {
int v;
if (!sysctl_schedule_icmp(net_ipvs(net)))
return NF_ACCEPT;
if (!ip_vs_try_to_schedule(AF_INET, skb, pd, &v, &cp, &ciph))
return v;
new_cp = true;
}
verdict = NF_DROP;
@ -1501,7 +1574,10 @@ ignore_ipip:
verdict = ip_vs_icmp_xmit(skb, cp, pp, offset, hooknum, &ciph);
out:
__ip_vs_conn_put(cp);
if (likely(!new_cp))
__ip_vs_conn_put(cp);
else
ip_vs_conn_put(cp);
return verdict;
}
@ -1511,13 +1587,13 @@ static int ip_vs_in_icmp_v6(struct sk_buff *skb, int *related,
unsigned int hooknum, struct ip_vs_iphdr *iph)
{
struct net *net = NULL;
struct ipv6hdr _ip6h, *ip6h;
struct icmp6hdr _icmph, *ic;
struct ip_vs_iphdr ciph = {.flags = 0, .fragoffs = 0};/*Contained IP */
struct ip_vs_conn *cp;
struct ip_vs_protocol *pp;
struct ip_vs_proto_data *pd;
unsigned int offs_ciph, writable, verdict;
unsigned int offset, verdict;
bool new_cp = false;
*related = 1;
@ -1546,18 +1622,9 @@ static int ip_vs_in_icmp_v6(struct sk_buff *skb, int *related,
ic->icmp6_type, ntohs(icmpv6_id(ic)),
&iph->saddr, &iph->daddr);
/* Now find the contained IP header */
ciph.len = iph->len + sizeof(_icmph);
offs_ciph = ciph.len; /* Save ip header offset */
ip6h = skb_header_pointer(skb, ciph.len, sizeof(_ip6h), &_ip6h);
if (ip6h == NULL)
return NF_ACCEPT; /* The packet looks wrong, ignore */
ciph.saddr.in6 = ip6h->saddr; /* conn_in_get() handles reverse order */
ciph.daddr.in6 = ip6h->daddr;
/* skip possible IPv6 exthdrs of contained IPv6 packet */
ciph.protocol = ipv6_find_hdr(skb, &ciph.len, -1, &ciph.fragoffs, NULL);
if (ciph.protocol < 0)
return NF_ACCEPT; /* Contained IPv6 hdr looks wrong, ignore */
offset = iph->len + sizeof(_icmph);
if (!ip_vs_fill_iph_skb_icmp(AF_INET6, skb, offset, true, &ciph))
return NF_ACCEPT;
net = skb_net(skb);
pd = ip_vs_proto_data_get(net, ciph.protocol);
@ -1569,36 +1636,49 @@ static int ip_vs_in_icmp_v6(struct sk_buff *skb, int *related,
if (ciph.fragoffs)
return NF_ACCEPT;
IP_VS_DBG_PKT(11, AF_INET6, pp, skb, offs_ciph,
IP_VS_DBG_PKT(11, AF_INET6, pp, skb, offset,
"Checking incoming ICMPv6 for");
/* The embedded headers contain source and dest in reverse order
* if not from localhost
*/
cp = pp->conn_in_get(AF_INET6, skb, &ciph,
(hooknum == NF_INET_LOCAL_OUT) ? 0 : 1);
cp = pp->conn_in_get(AF_INET6, skb, &ciph);
if (!cp) {
int v;
if (!sysctl_schedule_icmp(net_ipvs(net)))
return NF_ACCEPT;
if (!ip_vs_try_to_schedule(AF_INET6, skb, pd, &v, &cp, &ciph))
return v;
new_cp = true;
}
if (!cp)
return NF_ACCEPT;
/* VS/TUN, VS/DR and LOCALNODE just let it go */
if ((hooknum == NF_INET_LOCAL_OUT) &&
(IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)) {
__ip_vs_conn_put(cp);
return NF_ACCEPT;
verdict = NF_ACCEPT;
goto out;
}
/* do the statistics and put it back */
ip_vs_in_stats(cp, skb);
/* Need to mangle contained IPv6 header in ICMPv6 packet */
writable = ciph.len;
offset = ciph.len;
if (IPPROTO_TCP == ciph.protocol || IPPROTO_UDP == ciph.protocol ||
IPPROTO_SCTP == ciph.protocol)
writable += 2 * sizeof(__u16); /* Also mangle ports */
offset += 2 * sizeof(__u16); /* Also mangle ports */
verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, writable, hooknum, &ciph);
verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset, hooknum, &ciph);
__ip_vs_conn_put(cp);
out:
if (likely(!new_cp))
__ip_vs_conn_put(cp);
else
ip_vs_conn_put(cp);
return verdict;
}
@ -1633,7 +1713,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
if (unlikely((skb->pkt_type != PACKET_HOST &&
hooknum != NF_INET_LOCAL_OUT) ||
!skb_dst(skb))) {
ip_vs_fill_iph_skb(af, skb, &iph);
ip_vs_fill_iph_skb(af, skb, false, &iph);
IP_VS_DBG_BUF(12, "packet type=%d proto=%d daddr=%s"
" ignored in hook %u\n",
skb->pkt_type, iph.protocol,
@ -1646,7 +1726,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable))
return NF_ACCEPT;
ip_vs_fill_iph_skb(af, skb, &iph);
ip_vs_fill_iph_skb(af, skb, false, &iph);
/* Bad... Do not break raw sockets */
if (unlikely(skb->sk != NULL && hooknum == NF_INET_LOCAL_OUT &&
@ -1680,13 +1760,21 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
/* Protocol supported? */
pd = ip_vs_proto_data_get(net, iph.protocol);
if (unlikely(!pd))
if (unlikely(!pd)) {
/* The only way we'll see this packet again is if it's
* encapsulated, so mark it with ipvs_property=1 so we
* skip it if we're ignoring tunneled packets
*/
if (sysctl_ignore_tunneled(ipvs))
skb->ipvs_property = 1;
return NF_ACCEPT;
}
pp = pd->pp;
/*
* Check if the packet belongs to an existing connection entry
*/
cp = pp->conn_in_get(af, skb, &iph, 0);
cp = pp->conn_in_get(af, skb, &iph);
conn_reuse_mode = sysctl_conn_reuse_mode(ipvs);
if (conn_reuse_mode && !iph.fragoffs &&
@ -1700,32 +1788,15 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
cp = NULL;
}
if (unlikely(!cp) && !iph.fragoffs) {
/* No (second) fragments need to enter here, as nf_defrag_ipv6
* replayed fragment zero will already have created the cp
*/
if (unlikely(!cp)) {
int v;
/* Schedule and create new connection entry into &cp */
if (!pp->conn_schedule(af, skb, pd, &v, &cp, &iph))
if (!ip_vs_try_to_schedule(af, skb, pd, &v, &cp, &iph))
return v;
}
if (unlikely(!cp)) {
/* sorry, all this trouble for a no-hit :) */
IP_VS_DBG_PKT(12, af, pp, skb, 0,
"ip_vs_in: packet continues traversal as normal");
if (iph.fragoffs) {
/* Fragment that couldn't be mapped to a conn entry
* is missing module nf_defrag_ipv6
*/
IP_VS_DBG_RL("Unhandled frag, load nf_defrag_ipv6\n");
IP_VS_DBG_PKT(7, af, pp, skb, 0, "unhandled fragment");
}
return NF_ACCEPT;
}
IP_VS_DBG_PKT(11, af, pp, skb, iph.off, "Incoming packet");
IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet");
/* Check the server status */
if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {
/* the destination server is not available */
@ -1776,10 +1847,10 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
* Schedule and forward packets from remote clients
*/
static unsigned int
ip_vs_remote_request4(const struct nf_hook_ops *ops, struct sk_buff *skb,
ip_vs_remote_request4(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
return ip_vs_in(ops->hooknum, skb, AF_INET);
return ip_vs_in(state->hook, skb, AF_INET);
}
/*
@ -1787,10 +1858,10 @@ ip_vs_remote_request4(const struct nf_hook_ops *ops, struct sk_buff *skb,
* Schedule and forward packets from local clients
*/
static unsigned int
ip_vs_local_request4(const struct nf_hook_ops *ops, struct sk_buff *skb,
ip_vs_local_request4(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
return ip_vs_in(ops->hooknum, skb, AF_INET);
return ip_vs_in(state->hook, skb, AF_INET);
}
#ifdef CONFIG_IP_VS_IPV6
@ -1800,10 +1871,10 @@ ip_vs_local_request4(const struct nf_hook_ops *ops, struct sk_buff *skb,
* Schedule and forward packets from remote clients
*/
static unsigned int
ip_vs_remote_request6(const struct nf_hook_ops *ops, struct sk_buff *skb,
ip_vs_remote_request6(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
return ip_vs_in(ops->hooknum, skb, AF_INET6);
return ip_vs_in(state->hook, skb, AF_INET6);
}
/*
@ -1811,10 +1882,10 @@ ip_vs_remote_request6(const struct nf_hook_ops *ops, struct sk_buff *skb,
* Schedule and forward packets from local clients
*/
static unsigned int
ip_vs_local_request6(const struct nf_hook_ops *ops, struct sk_buff *skb,
ip_vs_local_request6(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
return ip_vs_in(ops->hooknum, skb, AF_INET6);
return ip_vs_in(state->hook, skb, AF_INET6);
}
#endif
@ -1830,7 +1901,7 @@ ip_vs_local_request6(const struct nf_hook_ops *ops, struct sk_buff *skb,
* and send them to ip_vs_in_icmp.
*/
static unsigned int
ip_vs_forward_icmp(const struct nf_hook_ops *ops, struct sk_buff *skb,
ip_vs_forward_icmp(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
int r;
@ -1846,12 +1917,12 @@ ip_vs_forward_icmp(const struct nf_hook_ops *ops, struct sk_buff *skb,
if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable))
return NF_ACCEPT;
return ip_vs_in_icmp(skb, &r, ops->hooknum);
return ip_vs_in_icmp(skb, &r, state->hook);
}
#ifdef CONFIG_IP_VS_IPV6
static unsigned int
ip_vs_forward_icmp_v6(const struct nf_hook_ops *ops, struct sk_buff *skb,
ip_vs_forward_icmp_v6(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
int r;
@ -1859,7 +1930,7 @@ ip_vs_forward_icmp_v6(const struct nf_hook_ops *ops, struct sk_buff *skb,
struct netns_ipvs *ipvs;
struct ip_vs_iphdr iphdr;
ip_vs_fill_iph_skb(AF_INET6, skb, &iphdr);
ip_vs_fill_iph_skb(AF_INET6, skb, false, &iphdr);
if (iphdr.protocol != IPPROTO_ICMPV6)
return NF_ACCEPT;
@ -1869,7 +1940,7 @@ ip_vs_forward_icmp_v6(const struct nf_hook_ops *ops, struct sk_buff *skb,
if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable))
return NF_ACCEPT;
return ip_vs_in_icmp_v6(skb, &r, ops->hooknum, &iphdr);
return ip_vs_in_icmp_v6(skb, &r, state->hook, &iphdr);
}
#endif

View File

@ -1844,6 +1844,18 @@ static struct ctl_table vs_vars[] = {
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
.procname = "schedule_icmp",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
.procname = "ignore_tunneled",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
#ifdef CONFIG_IP_VS_DEBUG
{
.procname = "debug_level",
@ -3895,7 +3907,8 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net)
tbl[idx++].data = &ipvs->sysctl_backup_only;
ipvs->sysctl_conn_reuse_mode = 1;
tbl[idx++].data = &ipvs->sysctl_conn_reuse_mode;
tbl[idx++].data = &ipvs->sysctl_schedule_icmp;
tbl[idx++].data = &ipvs->sysctl_ignore_tunneled;
ipvs->sysctl_hdr = register_net_sysctl(net, "net/ipv4/vs", tbl);
if (ipvs->sysctl_hdr == NULL) {

View File

@ -70,7 +70,7 @@ ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
const char *dptr;
int retc;
ip_vs_fill_iph_skb(p->af, skb, &iph);
ip_vs_fill_iph_skb(p->af, skb, false, &iph);
/* Only useful with UDP */
if (iph.protocol != IPPROTO_UDP)

View File

@ -42,10 +42,10 @@ struct isakmp_hdr {
static void
ah_esp_conn_fill_param_proto(struct net *net, int af,
const struct ip_vs_iphdr *iph, int inverse,
const struct ip_vs_iphdr *iph,
struct ip_vs_conn_param *p)
{
if (likely(!inverse))
if (likely(!ip_vs_iph_inverse(iph)))
ip_vs_conn_fill_param(net, af, IPPROTO_UDP,
&iph->saddr, htons(PORT_ISAKMP),
&iph->daddr, htons(PORT_ISAKMP), p);
@ -57,14 +57,13 @@ ah_esp_conn_fill_param_proto(struct net *net, int af,
static struct ip_vs_conn *
ah_esp_conn_in_get(int af, const struct sk_buff *skb,
const struct ip_vs_iphdr *iph,
int inverse)
const struct ip_vs_iphdr *iph)
{
struct ip_vs_conn *cp;
struct ip_vs_conn_param p;
struct net *net = skb_net(skb);
ah_esp_conn_fill_param_proto(net, af, iph, inverse, &p);
ah_esp_conn_fill_param_proto(net, af, iph, &p);
cp = ip_vs_conn_in_get(&p);
if (!cp) {
/*
@ -73,7 +72,7 @@ ah_esp_conn_in_get(int af, const struct sk_buff *skb,
*/
IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for outin packet "
"%s%s %s->%s\n",
inverse ? "ICMP+" : "",
ip_vs_iph_icmp(iph) ? "ICMP+" : "",
ip_vs_proto_get(iph->protocol)->name,
IP_VS_DBG_ADDR(af, &iph->saddr),
IP_VS_DBG_ADDR(af, &iph->daddr));
@ -85,18 +84,18 @@ ah_esp_conn_in_get(int af, const struct sk_buff *skb,
static struct ip_vs_conn *
ah_esp_conn_out_get(int af, const struct sk_buff *skb,
const struct ip_vs_iphdr *iph, int inverse)
const struct ip_vs_iphdr *iph)
{
struct ip_vs_conn *cp;
struct ip_vs_conn_param p;
struct net *net = skb_net(skb);
ah_esp_conn_fill_param_proto(net, af, iph, inverse, &p);
ah_esp_conn_fill_param_proto(net, af, iph, &p);
cp = ip_vs_conn_out_get(&p);
if (!cp) {
IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for inout packet "
"%s%s %s->%s\n",
inverse ? "ICMP+" : "",
ip_vs_iph_icmp(iph) ? "ICMP+" : "",
ip_vs_proto_get(iph->protocol)->name,
IP_VS_DBG_ADDR(af, &iph->saddr),
IP_VS_DBG_ADDR(af, &iph->daddr));

View File

@ -18,16 +18,24 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
struct netns_ipvs *ipvs;
sctp_chunkhdr_t _schunkh, *sch;
sctp_sctphdr_t *sh, _sctph;
__be16 _ports[2], *ports = NULL;
sh = skb_header_pointer(skb, iph->len, sizeof(_sctph), &_sctph);
if (sh == NULL) {
*verdict = NF_DROP;
return 0;
if (likely(!ip_vs_iph_icmp(iph))) {
sh = skb_header_pointer(skb, iph->len, sizeof(_sctph), &_sctph);
if (sh) {
sch = skb_header_pointer(
skb, iph->len + sizeof(sctp_sctphdr_t),
sizeof(_schunkh), &_schunkh);
if (sch && (sch->type == SCTP_CID_INIT ||
sysctl_sloppy_sctp(ipvs)))
ports = &sh->source;
}
} else {
ports = skb_header_pointer(
skb, iph->len, sizeof(_ports), &_ports);
}
sch = skb_header_pointer(skb, iph->len + sizeof(sctp_sctphdr_t),
sizeof(_schunkh), &_schunkh);
if (sch == NULL) {
if (!ports) {
*verdict = NF_DROP;
return 0;
}
@ -35,9 +43,13 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
net = skb_net(skb);
ipvs = net_ipvs(net);
rcu_read_lock();
if ((sch->type == SCTP_CID_INIT || sysctl_sloppy_sctp(ipvs)) &&
(svc = ip_vs_service_find(net, af, skb->mark, iph->protocol,
&iph->daddr, sh->dest))) {
if (likely(!ip_vs_iph_inverse(iph)))
svc = ip_vs_service_find(net, af, skb->mark, iph->protocol,
&iph->daddr, ports[1]);
else
svc = ip_vs_service_find(net, af, skb->mark, iph->protocol,
&iph->saddr, ports[0]);
if (svc) {
int ignored;
if (ip_vs_todrop(ipvs)) {

View File

@ -40,19 +40,43 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
struct ip_vs_service *svc;
struct tcphdr _tcph, *th;
struct netns_ipvs *ipvs;
__be16 _ports[2], *ports = NULL;
th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph);
if (th == NULL) {
net = skb_net(skb);
ipvs = net_ipvs(net);
/* In the event of icmp, we're only guaranteed to have the first 8
* bytes of the transport header, so we only check the rest of the
* TCP packet for non-ICMP packets
*/
if (likely(!ip_vs_iph_icmp(iph))) {
th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph);
if (th) {
if (th->rst || !(sysctl_sloppy_tcp(ipvs) || th->syn))
return 1;
ports = &th->source;
}
} else {
ports = skb_header_pointer(
skb, iph->len, sizeof(_ports), &_ports);
}
if (!ports) {
*verdict = NF_DROP;
return 0;
}
net = skb_net(skb);
ipvs = net_ipvs(net);
/* No !th->ack check to allow scheduling on SYN+ACK for Active FTP */
rcu_read_lock();
if ((th->syn || sysctl_sloppy_tcp(ipvs)) && !th->rst &&
(svc = ip_vs_service_find(net, af, skb->mark, iph->protocol,
&iph->daddr, th->dest))) {
if (likely(!ip_vs_iph_inverse(iph)))
svc = ip_vs_service_find(net, af, skb->mark, iph->protocol,
&iph->daddr, ports[1]);
else
svc = ip_vs_service_find(net, af, skb->mark, iph->protocol,
&iph->saddr, ports[0]);
if (svc) {
int ignored;
if (ip_vs_todrop(ipvs)) {

View File

@ -36,17 +36,32 @@ udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
struct net *net;
struct ip_vs_service *svc;
struct udphdr _udph, *uh;
__be16 _ports[2], *ports = NULL;
/* IPv6 fragments, only first fragment will hit this */
uh = skb_header_pointer(skb, iph->len, sizeof(_udph), &_udph);
if (uh == NULL) {
if (likely(!ip_vs_iph_icmp(iph))) {
/* IPv6 fragments, only first fragment will hit this */
uh = skb_header_pointer(skb, iph->len, sizeof(_udph), &_udph);
if (uh)
ports = &uh->source;
} else {
ports = skb_header_pointer(
skb, iph->len, sizeof(_ports), &_ports);
}
if (!ports) {
*verdict = NF_DROP;
return 0;
}
net = skb_net(skb);
rcu_read_lock();
svc = ip_vs_service_find(net, af, skb->mark, iph->protocol,
&iph->daddr, uh->dest);
if (likely(!ip_vs_iph_inverse(iph)))
svc = ip_vs_service_find(net, af, skb->mark, iph->protocol,
&iph->daddr, ports[1]);
else
svc = ip_vs_service_find(net, af, skb->mark, iph->protocol,
&iph->saddr, ports[0]);
if (svc) {
int ignored;

View File

@ -280,35 +280,29 @@ static int ip_vs_sh_dest_changed(struct ip_vs_service *svc,
static inline __be16
ip_vs_sh_get_port(const struct sk_buff *skb, struct ip_vs_iphdr *iph)
{
__be16 port;
struct tcphdr _tcph, *th;
struct udphdr _udph, *uh;
sctp_sctphdr_t _sctph, *sh;
__be16 _ports[2], *ports;
/* At this point we know that we have a valid packet of some kind.
* Because ICMP packets are only guaranteed to have the first 8
* bytes, let's just grab the ports. Fortunately they're in the
* same position for all three of the protocols we care about.
*/
switch (iph->protocol) {
case IPPROTO_TCP:
th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph);
if (unlikely(th == NULL))
return 0;
port = th->source;
break;
case IPPROTO_UDP:
uh = skb_header_pointer(skb, iph->len, sizeof(_udph), &_udph);
if (unlikely(uh == NULL))
return 0;
port = uh->source;
break;
case IPPROTO_SCTP:
sh = skb_header_pointer(skb, iph->len, sizeof(_sctph), &_sctph);
if (unlikely(sh == NULL))
ports = skb_header_pointer(skb, iph->len, sizeof(_ports),
&_ports);
if (unlikely(!ports))
return 0;
port = sh->source;
break;
default:
port = 0;
}
return port;
if (likely(!ip_vs_iph_inverse(iph)))
return ports[0];
else
return ports[1];
default:
return 0;
}
}
@ -322,6 +316,9 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
struct ip_vs_dest *dest;
struct ip_vs_sh_state *s;
__be16 port = 0;
const union nf_inet_addr *hash_addr;
hash_addr = ip_vs_iph_inverse(iph) ? &iph->daddr : &iph->saddr;
IP_VS_DBG(6, "ip_vs_sh_schedule(): Scheduling...\n");
@ -331,9 +328,9 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
s = (struct ip_vs_sh_state *) svc->sched_data;
if (svc->flags & IP_VS_SVC_F_SCHED_SH_FALLBACK)
dest = ip_vs_sh_get_fallback(svc, s, &iph->saddr, port);
dest = ip_vs_sh_get_fallback(svc, s, hash_addr, port);
else
dest = ip_vs_sh_get(svc, s, &iph->saddr, port);
dest = ip_vs_sh_get(svc, s, hash_addr, port);
if (!dest) {
ip_vs_scheduler_err(svc, "no destination available");
@ -341,7 +338,7 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
}
IP_VS_DBG_BUF(6, "SH: source IP address %s --> server %s:%d\n",
IP_VS_DBG_ADDR(svc->af, &iph->saddr),
IP_VS_DBG_ADDR(svc->af, hash_addr),
IP_VS_DBG_ADDR(dest->af, &dest->addr),
ntohs(dest->port));

View File

@ -224,7 +224,7 @@ static inline bool ensure_mtu_is_adequate(int skb_af, int rt_mode,
if (!skb->dev)
skb->dev = net->loopback_dev;
/* only send ICMP too big on first fragment */
if (!ipvsh->fragoffs)
if (!ipvsh->fragoffs && !ip_vs_iph_icmp(ipvsh))
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
IP_VS_DBG(1, "frag needed for %pI6c\n",
&ipv6_hdr(skb)->saddr);
@ -242,7 +242,8 @@ static inline bool ensure_mtu_is_adequate(int skb_af, int rt_mode,
return true;
if (unlikely(ip_hdr(skb)->frag_off & htons(IP_DF) &&
skb->len > mtu && !skb_is_gso(skb))) {
skb->len > mtu && !skb_is_gso(skb) &&
!ip_vs_iph_icmp(ipvsh))) {
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
htonl(mtu));
IP_VS_DBG(1, "frag needed for %pI4\n",
@ -656,10 +657,12 @@ int
ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
{
struct ipv6hdr *iph = ipv6_hdr(skb);
EnterFunction(10);
rcu_read_lock();
if (__ip_vs_get_out_rt_v6(cp->af, skb, NULL, &ipvsh->daddr.in6, NULL,
if (__ip_vs_get_out_rt_v6(cp->af, skb, NULL, &iph->daddr, NULL,
ipvsh, 0, IP_VS_RT_MODE_NON_LOCAL) < 0)
goto tx_error;
@ -723,7 +726,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
if (ct && !nf_ct_is_untracked(ct)) {
IP_VS_DBG_RL_PKT(10, AF_INET, pp, skb, 0,
IP_VS_DBG_RL_PKT(10, AF_INET, pp, skb, ipvsh->off,
"ip_vs_nat_xmit(): "
"stopping DNAT to local address");
goto tx_error;
@ -733,8 +736,9 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
/* From world but DNAT to loopback address? */
if (local && ipv4_is_loopback(cp->daddr.ip) && was_input) {
IP_VS_DBG_RL_PKT(1, AF_INET, pp, skb, 0, "ip_vs_nat_xmit(): "
"stopping DNAT to loopback address");
IP_VS_DBG_RL_PKT(1, AF_INET, pp, skb, ipvsh->off,
"ip_vs_nat_xmit(): stopping DNAT to loopback "
"address");
goto tx_error;
}
@ -751,7 +755,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
ip_hdr(skb)->daddr = cp->daddr.ip;
ip_send_check(ip_hdr(skb));
IP_VS_DBG_PKT(10, AF_INET, pp, skb, 0, "After DNAT");
IP_VS_DBG_PKT(10, AF_INET, pp, skb, ipvsh->off, "After DNAT");
/* FIXME: when application helper enlarges the packet and the length
is larger than the MTU of outgoing device, there will be still
@ -812,7 +816,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
if (ct && !nf_ct_is_untracked(ct)) {
IP_VS_DBG_RL_PKT(10, AF_INET6, pp, skb, 0,
IP_VS_DBG_RL_PKT(10, AF_INET6, pp, skb, ipvsh->off,
"ip_vs_nat_xmit_v6(): "
"stopping DNAT to local address");
goto tx_error;
@ -823,7 +827,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
/* From world but DNAT to loopback address? */
if (local && skb->dev && !(skb->dev->flags & IFF_LOOPBACK) &&
ipv6_addr_type(&cp->daddr.in6) & IPV6_ADDR_LOOPBACK) {
IP_VS_DBG_RL_PKT(1, AF_INET6, pp, skb, 0,
IP_VS_DBG_RL_PKT(1, AF_INET6, pp, skb, ipvsh->off,
"ip_vs_nat_xmit_v6(): "
"stopping DNAT to loopback address");
goto tx_error;
@ -841,7 +845,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
goto tx_error;
ipv6_hdr(skb)->daddr = cp->daddr.in6;
IP_VS_DBG_PKT(10, AF_INET6, pp, skb, 0, "After DNAT");
IP_VS_DBG_PKT(10, AF_INET6, pp, skb, ipvsh->off, "After DNAT");
/* FIXME: when application helper enlarges the packet and the length
is larger than the MTU of outgoing device, there will be still

View File

@ -168,6 +168,7 @@ nf_ct_get_tuple(const struct sk_buff *skb,
unsigned int dataoff,
u_int16_t l3num,
u_int8_t protonum,
struct net *net,
struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_l3proto *l3proto,
const struct nf_conntrack_l4proto *l4proto)
@ -181,12 +182,13 @@ nf_ct_get_tuple(const struct sk_buff *skb,
tuple->dst.protonum = protonum;
tuple->dst.dir = IP_CT_DIR_ORIGINAL;
return l4proto->pkt_to_tuple(skb, dataoff, tuple);
return l4proto->pkt_to_tuple(skb, dataoff, net, tuple);
}
EXPORT_SYMBOL_GPL(nf_ct_get_tuple);
bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff,
u_int16_t l3num, struct nf_conntrack_tuple *tuple)
u_int16_t l3num,
struct net *net, struct nf_conntrack_tuple *tuple)
{
struct nf_conntrack_l3proto *l3proto;
struct nf_conntrack_l4proto *l4proto;
@ -205,7 +207,7 @@ bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff,
l4proto = __nf_ct_l4proto_find(l3num, protonum);
ret = nf_ct_get_tuple(skb, nhoff, protoff, l3num, protonum, tuple,
ret = nf_ct_get_tuple(skb, nhoff, protoff, l3num, protonum, net, tuple,
l3proto, l4proto);
rcu_read_unlock();
@ -1029,7 +1031,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl,
u32 hash;
if (!nf_ct_get_tuple(skb, skb_network_offset(skb),
dataoff, l3num, protonum, &tuple, l3proto,
dataoff, l3num, protonum, net, &tuple, l3proto,
l4proto)) {
pr_debug("resolve_normal_ct: Can't get tuple\n");
return NULL;

View File

@ -398,7 +398,7 @@ static inline struct dccp_net *dccp_pernet(struct net *net)
}
static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
struct nf_conntrack_tuple *tuple)
struct net *net, struct nf_conntrack_tuple *tuple)
{
struct dccp_hdr _hdr, *dh;

View File

@ -45,7 +45,7 @@ static inline struct nf_generic_net *generic_pernet(struct net *net)
static bool generic_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
struct nf_conntrack_tuple *tuple)
struct net *net, struct nf_conntrack_tuple *tuple)
{
tuple->src.u.all = 0;
tuple->dst.u.all = 0;

View File

@ -190,9 +190,8 @@ static bool gre_invert_tuple(struct nf_conntrack_tuple *tuple,
/* gre hdr info to tuple */
static bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
struct nf_conntrack_tuple *tuple)
struct net *net, struct nf_conntrack_tuple *tuple)
{
struct net *net = dev_net(skb->dev ? skb->dev : skb_dst(skb)->dev);
const struct gre_hdr_pptp *pgrehdr;
struct gre_hdr_pptp _pgrehdr;
__be16 srckey;

View File

@ -156,7 +156,7 @@ static inline struct sctp_net *sctp_pernet(struct net *net)
}
static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
struct nf_conntrack_tuple *tuple)
struct net *net, struct nf_conntrack_tuple *tuple)
{
const struct sctphdr *hp;
struct sctphdr _hdr;

View File

@ -277,7 +277,7 @@ static inline struct nf_tcp_net *tcp_pernet(struct net *net)
}
static bool tcp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
struct nf_conntrack_tuple *tuple)
struct net *net, struct nf_conntrack_tuple *tuple)
{
const struct tcphdr *hp;
struct tcphdr _hdr;

View File

@ -38,6 +38,7 @@ static inline struct nf_udp_net *udp_pernet(struct net *net)
static bool udp_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
struct net *net,
struct nf_conntrack_tuple *tuple)
{
const struct udphdr *hp;

View File

@ -48,6 +48,7 @@ static inline struct udplite_net *udplite_pernet(struct net *net)
static bool udplite_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
struct net *net,
struct nf_conntrack_tuple *tuple)
{
const struct udphdr *hp;

View File

@ -83,7 +83,7 @@ out:
rcu_read_unlock();
}
int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family)
int nf_xfrm_me_harder(struct net *net, struct sk_buff *skb, unsigned int family)
{
struct flowi fl;
unsigned int hh_len;
@ -99,7 +99,7 @@ int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family)
dst = ((struct xfrm_dst *)dst)->route;
dst_hold(dst);
dst = xfrm_lookup(dev_net(dst->dev), dst, &fl, skb->sk, 0);
dst = xfrm_lookup(net, dst, &fl, skb->sk, 0);
if (IS_ERR(dst))
return PTR_ERR(dst);

View File

@ -48,9 +48,7 @@ static void __nft_trace_packet(const struct nft_pktinfo *pkt,
const struct nft_chain *chain,
int rulenum, enum nft_trace type)
{
struct net *net = dev_net(pkt->in ? pkt->in : pkt->out);
nf_log_trace(net, pkt->xt.family, pkt->ops->hooknum, pkt->skb, pkt->in,
nf_log_trace(pkt->net, pkt->pf, pkt->hook, pkt->skb, pkt->in,
pkt->out, &trace_loginfo, "TRACE: %s:%s:%s:%u ",
chain->table->name, chain->name, comments[type],
rulenum);
@ -111,10 +109,10 @@ struct nft_jumpstack {
};
unsigned int
nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
nft_do_chain(struct nft_pktinfo *pkt, void *priv)
{
const struct nft_chain *chain = ops->priv, *basechain = chain;
const struct net *net = dev_net(pkt->in ? pkt->in : pkt->out);
const struct nft_chain *chain = priv, *basechain = chain;
const struct net *net = pkt->net;
const struct nft_rule *rule;
const struct nft_expr *expr, *last;
struct nft_regs regs;

View File

@ -17,13 +17,13 @@
static inline void
nft_netdev_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
const struct nf_hook_ops *ops, struct sk_buff *skb,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
struct iphdr *iph, _iph;
u32 len, thoff;
nft_set_pktinfo(pkt, ops, skb, state);
nft_set_pktinfo(pkt, skb, state);
iph = skb_header_pointer(skb, skb_network_offset(skb), sizeof(*iph),
&_iph);
@ -48,7 +48,6 @@ nft_netdev_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
static inline void
__nft_netdev_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
@ -82,33 +81,32 @@ __nft_netdev_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
}
static inline void nft_netdev_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
const struct nf_hook_ops *ops,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
nft_set_pktinfo(pkt, ops, skb, state);
__nft_netdev_set_pktinfo_ipv6(pkt, ops, skb, state);
nft_set_pktinfo(pkt, skb, state);
__nft_netdev_set_pktinfo_ipv6(pkt, skb, state);
}
static unsigned int
nft_do_chain_netdev(const struct nf_hook_ops *ops, struct sk_buff *skb,
nft_do_chain_netdev(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state)
{
struct nft_pktinfo pkt;
switch (eth_hdr(skb)->h_proto) {
case htons(ETH_P_IP):
nft_netdev_set_pktinfo_ipv4(&pkt, ops, skb, state);
nft_netdev_set_pktinfo_ipv4(&pkt, skb, state);
break;
case htons(ETH_P_IPV6):
nft_netdev_set_pktinfo_ipv6(&pkt, ops, skb, state);
nft_netdev_set_pktinfo_ipv6(&pkt, skb, state);
break;
default:
nft_set_pktinfo(&pkt, ops, skb, state);
nft_set_pktinfo(&pkt, skb, state);
break;
}
return nft_do_chain(&pkt, ops);
return nft_do_chain(&pkt, priv);
}
static struct nft_af_info nft_af_netdev __read_mostly = {

View File

@ -31,9 +31,8 @@ static void nft_log_eval(const struct nft_expr *expr,
const struct nft_pktinfo *pkt)
{
const struct nft_log *priv = nft_expr_priv(expr);
struct net *net = dev_net(pkt->in ? pkt->in : pkt->out);
nf_log_packet(net, pkt->ops->pf, pkt->ops->hooknum, pkt->skb, pkt->in,
nf_log_packet(pkt->net, pkt->pf, pkt->hook, pkt->skb, pkt->in,
pkt->out, &priv->loginfo, "%s", priv->prefix);
}

Some files were not shown because too many files have changed in this diff Show More