This commit fixes two cases of providing sk on tunneling, one to the update_pmtu handler and the second case is to the ip_local_out() call. For local clients, we can see at LOCAL_OUT a netfilter hook's state->sk that is different from the protocol's skb->sk. This can be the case for UDP_TUNNEL where different sk is provided to ip_local_out. If such packet is then forwarded via IPVS tunnel we may need to provide state->sk to the update_pmtu handler. Fix that by passing the netfilter's hook state via the packet_xmit and conn_schedule handlers to call the update_pmtu handler with state->sk instead of skb->sk. While here, change maybe_update_pmtu() to be family independent by using dst and do not request neigh confirm via the last update_pmtu arg because we do not generate the event based on remote signal. The second problem is that on tunnel forwarding we call ip_local_out() with skb->sk. As we push our own outer IP header in ip_vs_tunnel_xmit*(), the right thing is to provide NULL instead. For consistency, even if we do not walk the netfilter hooks and just pass the packet with NF_ACCEPT, provide ip_vs_null_xmit_v6 handler to properly indicate that we are sending IPv6 packet. Before now we used ip_vs_null_xmit for both families. Fixes: 79b16aadea32 ("udp_tunnel: Pass UDP socket down through udp_tunnel{, 6}_xmit_skb().") Fixes: 7026b1ddb6b8 ("netfilter: Pass socket pointer down through okfn().") Signed-off-by: Julian Anastasov --- include/net/ip_vs.h | 45 ++++++---- net/netfilter/ipvs/ip_vs_conn.c | 2 +- net/netfilter/ipvs/ip_vs_core.c | 41 +++++---- net/netfilter/ipvs/ip_vs_proto_ah_esp.c | 2 +- net/netfilter/ipvs/ip_vs_proto_sctp.c | 5 +- net/netfilter/ipvs/ip_vs_proto_tcp.c | 5 +- net/netfilter/ipvs/ip_vs_proto_udp.c | 5 +- net/netfilter/ipvs/ip_vs_xmit.c | 106 +++++++++++++++--------- 8 files changed, 134 insertions(+), 77 deletions(-) diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index f5fe2e0af64a..737a2982f857 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -731,7 +731,8 @@ struct ip_vs_protocol { 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_iphdr *iph, + const struct nf_hook_state *state); struct ip_vs_conn * (*conn_in_get)(struct netns_ipvs *ipvs, @@ -872,7 +873,8 @@ struct ip_vs_conn { * NF_ACCEPT can be returned when destination is local. */ int (*packet_xmit)(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph, + const struct nf_hook_state *state); struct rcu_head rcu_head; }; @@ -1870,7 +1872,8 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, struct ip_vs_proto_data *pd, int *ignored, struct ip_vs_iphdr *iph); int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, - struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph); + struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph, + const struct nf_hook_state *state); void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg); @@ -1985,32 +1988,46 @@ static inline int ip_vs_est_max_threads(struct netns_ipvs *ipvs) /* Various IPVS packet transmitters (from ip_vs_xmit.c) */ int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph, + const struct nf_hook_state *state); int ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph, + const struct nf_hook_state *state); int ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph, + const struct nf_hook_state *state); int ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph, + const struct nf_hook_state *state); int ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph, + const struct nf_hook_state *state); int ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, unsigned int toff, - unsigned int hooknum, struct ip_vs_iphdr *ciph); + const struct nf_hook_state *state, + struct ip_vs_iphdr *ciph); void ip_vs_dest_dst_rcu_free(struct rcu_head *head); #ifdef CONFIG_IP_VS_IPV6 +int ip_vs_null_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph, + const struct nf_hook_state *state); int ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph, + const struct nf_hook_state *state); int ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph, + const struct nf_hook_state *state); int ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph, + const struct nf_hook_state *state); int ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph); + struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph, + const struct nf_hook_state *state); int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, unsigned int toff, - unsigned int hooknum, struct ip_vs_iphdr *ciph); + const struct nf_hook_state *state, + struct ip_vs_iphdr *ciph); #endif #ifdef CONFIG_SYSCTL diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index 2895b2b11968..7f20e8ea5598 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c @@ -1084,7 +1084,7 @@ static inline void ip_vs_bind_xmit_v6(struct ip_vs_conn *cp) break; case IP_VS_CONN_F_LOCALNODE: - cp->packet_xmit = ip_vs_null_xmit; + cp->packet_xmit = ip_vs_null_xmit_v6; break; case IP_VS_CONN_F_BYPASS: diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 8cdcab7d6edf..38dcd2d49f34 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -761,7 +761,8 @@ static inline int ip_vs_addr_is_unicast(struct net *net, int af, * no destination is available for a new connection. */ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, - struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph) + struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph, + const struct nf_hook_state *state) { __be16 _ports[2], *pptr, dport; struct netns_ipvs *ipvs = svc->ipvs; @@ -806,7 +807,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb, ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd, iph->len); /* transmit the first SYN packet */ - ret = cp->packet_xmit(skb, cp, pd->pp, iph); + ret = cp->packet_xmit(skb, cp, pd->pp, iph, state); /* do not touch skb anymore */ if ((cp->flags & IP_VS_CONN_F_ONE_PACKET) && cp->control) @@ -1649,7 +1650,8 @@ static unsigned int ip_vs_try_to_schedule(struct netns_ipvs *ipvs, 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_iphdr *iph, + const struct nf_hook_state *state) { struct ip_vs_protocol *pp = pd->pp; @@ -1659,7 +1661,8 @@ ip_vs_try_to_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb, */ /* Schedule and create new connection entry into cpp */ - if (!pp->conn_schedule(ipvs, af, skb, pd, verdict, cpp, iph)) + if (!pp->conn_schedule(ipvs, af, skb, pd, verdict, cpp, iph, + state)) return 0; } @@ -1759,7 +1762,7 @@ static int ipvs_gre_decap(struct netns_ipvs *ipvs, struct sk_buff *skb, */ static int ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related, - unsigned int hooknum, struct ip_vs_iphdr *iph) + const struct nf_hook_state *state, struct ip_vs_iphdr *iph) { struct icmphdr _icmph, *ic; struct iphdr _ciph, *cih; /* The ip header contained within the ICMP */ @@ -1778,7 +1781,8 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related, /* reassemble IP fragments */ if (ip_is_fragment(ip_hdr(skb))) { - if (ip_vs_gather_frags(ipvs, skb, ip_vs_defrag_user(hooknum))) + if (ip_vs_gather_frags(ipvs, skb, + ip_vs_defrag_user(state->hook))) return NF_STOLEN; if (!ip_vs_fill_iph_skb(AF_INET, skb, false, iph)) return NF_ACCEPT; @@ -1895,7 +1899,8 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related, if (tunnel || !sysctl_schedule_icmp(ipvs)) return NF_ACCEPT; - if (!ip_vs_try_to_schedule(ipvs, AF_INET, skb, pd, &v, &cp, &ciph)) + if (!ip_vs_try_to_schedule(ipvs, AF_INET, skb, pd, &v, &cp, + &ciph, state)) return v; new_cp = true; } @@ -1982,7 +1987,7 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related, /* do the statistics and put it back */ ip_vs_in_stats(cp, skb); - verdict = ip_vs_icmp_xmit(skb, cp, pp, iph->len, hooknum, &ciph); + verdict = ip_vs_icmp_xmit(skb, cp, pp, iph->len, state, &ciph); out: if (likely(!new_cp)) @@ -1995,7 +2000,7 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related, #ifdef CONFIG_IP_VS_IPV6 static int ip_vs_in_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb, - int *related, unsigned int hooknum, + int *related, const struct nf_hook_state *state, struct ip_vs_iphdr *iph) { struct icmp6hdr _icmph, *ic; @@ -2061,7 +2066,8 @@ static int ip_vs_in_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb, if (!sysctl_schedule_icmp(ipvs)) return NF_ACCEPT; - if (!ip_vs_try_to_schedule(ipvs, AF_INET6, skb, pd, &v, &cp, &ciph)) + if (!ip_vs_try_to_schedule(ipvs, AF_INET6, skb, pd, &v, &cp, + &ciph, state)) return v; new_cp = true; @@ -2082,7 +2088,7 @@ static int ip_vs_in_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb, /* do the statistics and put it back */ ip_vs_in_stats(cp, skb); - verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, iph->len, hooknum, &ciph); + verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, iph->len, state, &ciph); out: if (likely(!new_cp)) @@ -2151,7 +2157,7 @@ ip_vs_in_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state if (unlikely(iph.protocol == IPPROTO_ICMPV6)) { int related; int verdict = ip_vs_in_icmp_v6(ipvs, skb, &related, - hooknum, &iph); + state, &iph); if (related) return verdict; @@ -2161,7 +2167,7 @@ ip_vs_in_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state if (unlikely(iph.protocol == IPPROTO_ICMP)) { int related; int verdict = ip_vs_in_icmp(ipvs, skb, &related, - hooknum, &iph); + state, &iph); if (related) return verdict; @@ -2249,7 +2255,8 @@ ip_vs_in_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state if (unlikely(!cp)) { int v; - if (!ip_vs_try_to_schedule(ipvs, af, skb, pd, &v, &cp, &iph)) + if (!ip_vs_try_to_schedule(ipvs, af, skb, pd, &v, &cp, &iph, + state)) return v; } @@ -2258,7 +2265,7 @@ ip_vs_in_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state ip_vs_in_stats(cp, skb); ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd, iph.len); if (cp->packet_xmit) - ret = cp->packet_xmit(skb, cp, pp, &iph); + ret = cp->packet_xmit(skb, cp, pp, &iph, state); /* do not touch skb anymore */ else { IP_VS_DBG_RL("warning: packet_xmit is null"); @@ -2321,11 +2328,11 @@ ip_vs_forward_icmp(void *priv, struct sk_buff *skb, if (iphdr.protocol != IPPROTO_ICMPV6) return NF_ACCEPT; - return ip_vs_in_icmp_v6(ipvs, skb, &r, state->hook, &iphdr); + return ip_vs_in_icmp_v6(ipvs, skb, &r, state, &iphdr); #endif } - return ip_vs_in_icmp(ipvs, skb, &r, state->hook, &iphdr); + return ip_vs_in_icmp(ipvs, skb, &r, state, &iphdr); } static const struct nf_hook_ops ip_vs_ops4[] = { diff --git a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c index 44e14acc187e..c7f90b29be51 100644 --- a/net/netfilter/ipvs/ip_vs_proto_ah_esp.c +++ b/net/netfilter/ipvs/ip_vs_proto_ah_esp.c @@ -102,7 +102,7 @@ static int ah_esp_conn_schedule(struct netns_ipvs *ipvs, 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_iphdr *iph, const struct nf_hook_state *state) { /* * AH/ESP is only related traffic. Pass the packet to IP stack. diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c index 83d1443ebe01..c8a5b9362a5b 100644 --- a/net/netfilter/ipvs/ip_vs_proto_sctp.c +++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c @@ -17,7 +17,7 @@ static int sctp_conn_schedule(struct netns_ipvs *ipvs, 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_iphdr *iph, const struct nf_hook_state *state) { struct ip_vs_service *svc; struct sctp_chunkhdr _schunkh, *sch; @@ -76,7 +76,8 @@ sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb, *cpp = ip_vs_schedule(svc, skb, pd, &ignored, iph); if (!*cpp && ignored <= 0) { if (!ignored) - *verdict = ip_vs_leave(svc, skb, pd, iph); + *verdict = ip_vs_leave(svc, skb, pd, iph, + state); else *verdict = NF_DROP; return 0; diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c index 2e55b62445c6..ef016938eb58 100644 --- a/net/netfilter/ipvs/ip_vs_proto_tcp.c +++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c @@ -35,7 +35,7 @@ static int tcp_conn_schedule(struct netns_ipvs *ipvs, 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_iphdr *iph, const struct nf_hook_state *state) { struct ip_vs_service *svc; struct tcphdr _tcph, *th; @@ -95,7 +95,8 @@ tcp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb, *cpp = ip_vs_schedule(svc, skb, pd, &ignored, iph); if (!*cpp && ignored <= 0) { if (!ignored) - *verdict = ip_vs_leave(svc, skb, pd, iph); + *verdict = ip_vs_leave(svc, skb, pd, iph, + state); else *verdict = NF_DROP; return 0; diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c b/net/netfilter/ipvs/ip_vs_proto_udp.c index 92c0b76c1a02..6a118783863f 100644 --- a/net/netfilter/ipvs/ip_vs_proto_udp.c +++ b/net/netfilter/ipvs/ip_vs_proto_udp.c @@ -31,7 +31,7 @@ static int udp_conn_schedule(struct netns_ipvs *ipvs, 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_iphdr *iph, const struct nf_hook_state *state) { struct ip_vs_service *svc; struct udphdr _udph, *uh; @@ -82,7 +82,8 @@ udp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb, *cpp = ip_vs_schedule(svc, skb, pd, &ignored, iph); if (!*cpp && ignored <= 0) { if (!ignored) - *verdict = ip_vs_leave(svc, skb, pd, iph); + *verdict = ip_vs_leave(svc, skb, pd, iph, + state); else *verdict = NF_DROP; return 0; diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index f5f72a2135e1..931ecd849fe5 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -205,13 +205,15 @@ static inline bool crosses_local_route_boundary(int skb_af, struct sk_buff *skb, return false; } -static inline void maybe_update_pmtu(int skb_af, struct sk_buff *skb, int mtu) +static inline void maybe_update_pmtu(int skb_af, struct sk_buff *skb, int mtu, + const struct nf_hook_state *state) { - struct sock *sk = skb->sk; - struct rtable *ort = skb_rtable(skb); + struct dst_entry *dst = skb_dst(skb); + struct sock *sk = state->sk; - if (!skb->dev && sk && sk_fullsock(sk)) - ort->dst.ops->update_pmtu(&ort->dst, sk, NULL, mtu, true); + if (state->hook == NF_INET_LOCAL_OUT && sk && sk_is_inet(sk) && + sk_fullsock(sk)) + dst->ops->update_pmtu(dst, sk, NULL, mtu, false); } static inline bool ensure_mtu_is_adequate(struct netns_ipvs *ipvs, int skb_af, @@ -316,7 +318,7 @@ static int __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest, __be32 daddr, int rt_mode, __be32 *ret_saddr, - struct ip_vs_iphdr *ipvsh) + struct ip_vs_iphdr *ipvsh, const struct nf_hook_state *state) { struct net *net = ipvs->net; struct ip_vs_dest_dst *dest_dst; @@ -417,7 +419,7 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, IP_VS_DBG_RL("%s(): mtu less than 68\n", __func__); goto err_put; } - maybe_update_pmtu(skb_af, skb, mtu); + maybe_update_pmtu(skb_af, skb, mtu, state); } if (!ensure_mtu_is_adequate(ipvs, skb_af, rt_mode, ipvsh, skb, mtu)) @@ -489,7 +491,8 @@ static int __ip_vs_get_out_rt_v6(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest, struct in6_addr *daddr, struct in6_addr *ret_saddr, - struct ip_vs_iphdr *ipvsh, int do_xfrm, int rt_mode) + struct ip_vs_iphdr *ipvsh, int do_xfrm, int rt_mode, + const struct nf_hook_state *state) { struct net *net = ipvs->net; struct ip_vs_dest_dst *dest_dst; @@ -596,7 +599,7 @@ __ip_vs_get_out_rt_v6(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, IPV6_MIN_MTU); goto err_put; } - maybe_update_pmtu(skb_af, skb, mtu); + maybe_update_pmtu(skb_af, skb, mtu, state); } if (!ensure_mtu_is_adequate(ipvs, skb_af, rt_mode, ipvsh, skb, mtu)) @@ -720,13 +723,29 @@ static inline int ip_vs_send_or_cont(int pf, struct sk_buff *skb, */ int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) + struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh, + const struct nf_hook_state *state) { /* we do not touch skb and do not need pskb ptr */ return ip_vs_send_or_cont(NFPROTO_IPV4, skb, cp, 1); } +#ifdef CONFIG_IP_VS_IPV6 +/* + * NULL transmitter (do nothing except return NF_ACCEPT) + */ +int +ip_vs_null_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, + struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh, + const struct nf_hook_state *state) +{ + /* we do not touch skb and do not need pskb ptr */ + return ip_vs_send_or_cont(NFPROTO_IPV6, skb, cp, 1); +} +#endif + + /* * Bypass transmitter * Let packets bypass the destination when the destination is not @@ -734,12 +753,14 @@ ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, */ int ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) + struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh, + const struct nf_hook_state *state) { struct iphdr *iph = ip_hdr(skb); if (__ip_vs_get_out_rt(cp->ipvs, cp->af, skb, NULL, iph->daddr, - IP_VS_RT_MODE_NON_LOCAL, NULL, ipvsh) < 0) + IP_VS_RT_MODE_NON_LOCAL, NULL, ipvsh, + state) < 0) goto tx_error; ip_send_check(iph); @@ -759,13 +780,15 @@ ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, #ifdef CONFIG_IP_VS_IPV6 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 ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh, + const struct nf_hook_state *state) { struct ipv6hdr *iph = ipv6_hdr(skb); if (__ip_vs_get_out_rt_v6(cp->ipvs, cp->af, skb, NULL, &iph->daddr, NULL, - ipvsh, 0, IP_VS_RT_MODE_NON_LOCAL) < 0) + ipvsh, 0, IP_VS_RT_MODE_NON_LOCAL, + state) < 0) goto tx_error; /* Another hack: avoid icmp_send in ip_fragment */ @@ -787,7 +810,8 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, */ int ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) + struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh, + const struct nf_hook_state *state) { struct rtable *rt; /* Route to the other host */ int local, rc, was_input; @@ -807,7 +831,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, local = __ip_vs_get_out_rt(cp->ipvs, cp->af, skb, cp->dest, cp->daddr.ip, IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | - IP_VS_RT_MODE_RDR, NULL, ipvsh); + IP_VS_RT_MODE_RDR, NULL, ipvsh, state); if (local < 0) goto tx_error; rt = skb_rtable(skb); @@ -871,7 +895,8 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, #ifdef CONFIG_IP_VS_IPV6 int ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) + struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh, + const struct nf_hook_state *state) { struct rt6_info *rt; /* Route to the other host */ int local, rc; @@ -891,7 +916,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, NULL, ipvsh, 0, IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | - IP_VS_RT_MODE_RDR); + IP_VS_RT_MODE_RDR, state); if (local < 0) goto tx_error; rt = dst_rt6_info(skb_dst(skb)); @@ -1147,7 +1172,8 @@ ipvs_gre_encap(struct net *net, struct sk_buff *skb, */ int ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) + struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh, + const struct nf_hook_state *state) { struct netns_ipvs *ipvs = cp->ipvs; struct net *net = ipvs->net; @@ -1169,7 +1195,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | IP_VS_RT_MODE_CONNECT | - IP_VS_RT_MODE_TUNNEL, &saddr, ipvsh); + IP_VS_RT_MODE_TUNNEL, &saddr, ipvsh, state); if (local < 0) goto tx_error; if (local) @@ -1278,7 +1304,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, ret = ip_vs_tunnel_xmit_prepare(skb, cp); if (ret == NF_ACCEPT) - ip_local_out(net, skb->sk, skb); + ip_local_out(net, NULL, skb); else if (ret == NF_DROP) kfree_skb(skb); @@ -1292,7 +1318,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, #ifdef CONFIG_IP_VS_IPV6 int ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) + struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh, + const struct nf_hook_state *state) { struct netns_ipvs *ipvs = cp->ipvs; struct net *net = ipvs->net; @@ -1314,7 +1341,7 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, &saddr, ipvsh, 1, IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | - IP_VS_RT_MODE_TUNNEL); + IP_VS_RT_MODE_TUNNEL, state); if (local < 0) goto tx_error; if (local) @@ -1420,7 +1447,7 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, ret = ip_vs_tunnel_xmit_prepare(skb, cp); if (ret == NF_ACCEPT) - ip6_local_out(net, skb->sk, skb); + ip6_local_out(net, NULL, skb); else if (ret == NF_DROP) kfree_skb(skb); @@ -1439,14 +1466,15 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, */ int ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) + struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh, + const struct nf_hook_state *state) { int local; local = __ip_vs_get_out_rt(cp->ipvs, cp->af, skb, cp->dest, cp->daddr.ip, IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | - IP_VS_RT_MODE_KNOWN_NH, NULL, ipvsh); + IP_VS_RT_MODE_KNOWN_NH, NULL, ipvsh, state); if (local < 0) goto tx_error; if (local) @@ -1469,7 +1497,8 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, #ifdef CONFIG_IP_VS_IPV6 int ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) + struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh, + const struct nf_hook_state *state) { int local; @@ -1478,7 +1507,7 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, NULL, ipvsh, 0, IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | - IP_VS_RT_MODE_KNOWN_NH); + IP_VS_RT_MODE_KNOWN_NH, state); if (local < 0) goto tx_error; if (local) @@ -1505,7 +1534,7 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, int ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, unsigned int toff, - unsigned int hooknum, struct ip_vs_iphdr *ciph) + const struct nf_hook_state *state, struct ip_vs_iphdr *ciph) { struct rtable *rt; /* Route to the other host */ int rc; @@ -1519,7 +1548,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, translate address/port back */ if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) { if (cp->packet_xmit) - rc = cp->packet_xmit(skb, cp, pp, ciph); + rc = cp->packet_xmit(skb, cp, pp, ciph, state); else rc = NF_ACCEPT; /* do not touch skb anymore */ @@ -1533,11 +1562,11 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, was_input = rt_is_input_route(skb_rtable(skb)); /* LOCALNODE from FORWARD hook is not supported */ - rt_mode = (hooknum != NF_INET_FORWARD) ? + rt_mode = (state->hook != NF_INET_FORWARD) ? IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL; - local = __ip_vs_get_out_rt(cp->ipvs, cp->af, skb, cp->dest, cp->daddr.ip, rt_mode, - NULL, ciph); + local = __ip_vs_get_out_rt(cp->ipvs, cp->af, skb, cp->dest, + cp->daddr.ip, rt_mode, NULL, ciph, state); if (local < 0) goto tx_error; rt = skb_rtable(skb); @@ -1599,8 +1628,8 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, #ifdef CONFIG_IP_VS_IPV6 int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, - struct ip_vs_protocol *pp, unsigned int toff, - unsigned int hooknum, struct ip_vs_iphdr *ciph) + struct ip_vs_protocol *pp, unsigned int toff, + const struct nf_hook_state *state, struct ip_vs_iphdr *ciph) { bool has_ports = false; struct rt6_info *rt; /* Route to the other host */ @@ -1614,7 +1643,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, translate address/port back */ if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) { if (cp->packet_xmit) - rc = cp->packet_xmit(skb, cp, pp, ciph); + rc = cp->packet_xmit(skb, cp, pp, ciph, state); else rc = NF_ACCEPT; /* do not touch skb anymore */ @@ -1627,11 +1656,12 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, */ /* LOCALNODE from FORWARD hook is not supported */ - rt_mode = (hooknum != NF_INET_FORWARD) ? + rt_mode = (state->hook != NF_INET_FORWARD) ? IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL; local = __ip_vs_get_out_rt_v6(cp->ipvs, cp->af, skb, cp->dest, - &cp->daddr.in6, NULL, ciph, 0, rt_mode); + &cp->daddr.in6, NULL, ciph, 0, rt_mode, + state); if (local < 0) goto tx_error; rt = dst_rt6_info(skb_dst(skb)); -- 2.56.0