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:
commit
99cb99aa05
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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_ */
|
||||
|
@ -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_ */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
struct tcf_connmark_info {
|
||||
struct tcf_common common;
|
||||
struct net *net;
|
||||
u16 zone;
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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)
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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)) ||
|
||||
|
@ -28,7 +28,7 @@ static void nft_dup_ipv6_eval(const struct nft_expr *expr,
|
||||
struct in6_addr *gw = (struct in6_addr *)®s->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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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, ¶m);
|
||||
ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, src_addr,
|
||||
src_port, dst_addr, dst_port, ¶m);
|
||||
|
||||
cp = ip_vs_conn_new(¶m, 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
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
|
@ -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)) {
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 = {
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user