summaryrefslogtreecommitdiffstats
path: root/include/net/ip_vs.h
diff options
context:
space:
mode:
authorAlex Gartrell2015-08-26 18:40:28 +0200
committerSimon Horman2015-09-01 03:33:21 +0200
commitb0e010c527de742cb18e8d50a06dfd1a995b5382 (patch)
treeccbfeafee9c6b8ba83764bb0d2f2e9de5ea1bbb1 /include/net/ip_vs.h
parentnetfilter: reduce sparse warnings (diff)
downloadkernel-qcow2-linux-b0e010c527de742cb18e8d50a06dfd1a995b5382.tar.gz
kernel-qcow2-linux-b0e010c527de742cb18e8d50a06dfd1a995b5382.tar.xz
kernel-qcow2-linux-b0e010c527de742cb18e8d50a06dfd1a995b5382.zip
ipvs: replace ip_vs_fill_ip4hdr with ip_vs_fill_iph_skb_off
This removes some duplicated code and makes the ICMPv6 path look more like the ICMP path. Signed-off-by: Alex Gartrell <agartrell@fb.com> Acked-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Simon Horman <horms@verge.net.au>
Diffstat (limited to 'include/net/ip_vs.h')
-rw-r--r--include/net/ip_vs.h49
1 files changed, 29 insertions, 20 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 9b9ca87a4210..0c8309f34982 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -104,6 +104,7 @@ static inline struct net *seq_file_single_net(struct seq_file *seq)
extern int ip_vs_conn_tab_size;
struct ip_vs_iphdr {
+ __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 +121,56 @@ 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,
+ struct ip_vs_iphdr *iphdr)
{
+ 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(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr)
+{
+ return ip_vs_fill_iph_skb_off(af, skb, skb_network_offset(skb), iphdr);
}
static inline void ip_vs_addr_copy(int af, union nf_inet_addr *dst,