ipvs ipv6 fragment handling
Subsystems (5)
RFC 1/1 ipvs ipv6 fragment handling
Hello,
Long time since the last ipvs patches from me...
IPVS do not have any kind of fragmentation handling for IPv6, neither can it handle extension headers in front of upper layer headers.
The last issue is easy to fix with ipv6_find_hdr() which also is a part of this RFC. This implementation relies on how nf_defrag_ipv6 works today.
Netfilter-team (Patrick) pls let me know if ipv6-nat makes any big changes to the defrag procedure.
IPVS do like conntrack i.e. use the skb->nfct_reasm;
(i.e. when all fragments is collected, nf_ct_frag6_output() starts a "re-play" of all fragments into the interrupted PREROUTING chain att prio -399 with nfct_reasm pointing to the assembled packet.)
IPVS adds a new hook into prerouting chain at prio -100 to catch fragments, and copy fw-mark and routing info from the first packet with an upper layer header.
For the first fragment ip_vs_in() and ip_vs_out() uses the skb->nfct_reasm to "store" fw-mark" and skb_dst().
Which will be copied into the following fragments.
This patch needs "NETFILTER added flags to ipv6_find_hdr()" patch
The patch is far from ready since this is only a RFC,
ex ip_vs_nat_xmit_v6() doesn't work since it writes right into the fragment header.. tunnel is not tested at all.
Only Direct routing is tested. (not to localhost)
Plenty of formatting rules is violated and there is also debug printouts to remove... (and kmail seems to corrupt tabs)
IPVS will depend on ip6tables and its defragmentation but NOT on conntrack. Is the design idea OK ?
Will IPv6-NAT break everything ?
Is there a reason not to use the skb->nfct_reasm as "storage" for mark and dst_entry ?
This doesn't violate the RFC 2460 "fragmentation in IPv6 is performed only by source nodes"
include/net/ip_vs.h +45 -4
@@ -22,6 +22,9 @@#include <linux/ip.h> #include <linux/ipv6.h> /* for struct ipv6hdr */ #include <net/ipv6.h> +#if defined(CONFIG_IPV6 ) || defined(CONFIG_IPV6_MODULE ) +#include <linux/netfilter_ipv6/ip6_tables.h> +#endif #if defined(CONFIG_NF_CONNTRACK ) || defined(CONFIG_NF_CONNTRACK_MODULE )#include <net/netfilter/nf_conntrack.h> #endif
@@ -105,8 +108,10 @@ extern int ip_vs_conn_tab_size;struct ip_vs_iphdr { -int len; -__u8 protocol; +__s32 len;/* offset where to find next header */ +__s32 flags; +__u16 fragoffs; +__s16 protocol;union nf_inet_addr saddr;union nf_inet_addr daddr; };
@@ -132,6 +137,42 @@ ip_vs_fill_iphdr(int af, const void *nh, struct ip_vs_iphdr *iphdr) } } +static inline void +ip_vs_fill_iph_skb (int af,const struct sk_buff *skb,struct ip_vs_iphdr *iphdr) +{ + iphdr->len =0 ; + iphdr->flags =0 ; +#ifdef CONFIG_IP_VS_IPV6 +if (af ==AF_INET6 ) { +const struct ipv6hdr *iph = (struct ipv6hdr *)skb_network_header (skb); + + iphdr->protocol =ipv6_find_hdr (skb, &iphdr->len,-1 , + &iphdr->fragoffs, + &iphdr->flags); + iphdr->saddr.in6 = iph->saddr; + iphdr->daddr.in6 = iph->daddr; + } else +#endif + { +const struct iphdr *iph = (struct iphdr *)skb_network_header (skb); + iphdr->len = iph->ihl *4 ; + iphdr->protocol = iph->protocol; + iphdr->saddr.ip = iph->saddr; + iphdr->daddr.ip = iph->daddr; + } +} +#if defined(CONFIG_NF_DEFRAG_IPV6 ) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE ) +static inline struct sk_buff *skb_nfct_reasm (const struct sk_buff *skb) +{ +return skb->nfct_reasm; +} +#else +static inline struct sk_buff *skb_reasm (const struct sk_buff *skb) +{ +return NULL ; +} +#endif +static inline void ip_vs_addr_copy (int af,union nf_inet_addr *dst,const union nf_inet_addr *src) {
@@ -412,7 +453,7 @@ struct ip_vs_protocol {const struct sk_buff *skb, const struct ip_vs_iphdr *iph, unsigned int proto_off, - int inverse); + int inverse, unsigned short foffs);int (*snat_handler)(struct sk_buff *skb,struct ip_vs_protocol *pp,struct ip_vs_conn *cp);
@@ -1001,7 +1042,7 @@ 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,unsigned int proto_off, -int inverse); +int inverse,unsigned short foffs);/* put back the conn without restarting its timer */ static inline void __ip_vs_conn_put (struct ip_vs_conn *cp)
net/netfilter/ipvs/ip_vs_conn.c +10 -4
@@ -432,13 +432,19 @@ 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, -unsigned int proto_off,int inverse) +const struct ip_vs_iphdr *iph,unsigned int proto_off, +int inverse,unsigned short foffs) {struct ip_vs_conn_param p; -if (ip_vs_conn_fill_param_proto (af, skb, iph, proto_off, inverse, &p)) -return NULL ; +if (unlikely (foffs)) { +if (ip_vs_conn_fill_param_proto (af,skb_nfct_reasm (skb), iph, + proto_off, inverse, &p)) +return NULL ; + }else { +if (ip_vs_conn_fill_param_proto (af, skb, iph, proto_off, inverse, &p)) +return NULL ; + }return ip_vs_conn_out_get (&p); }
net/netfilter/ipvs/ip_vs_core.c +217 -125
581 lines not on this page · raw message
net/netfilter/ipvs/ip_vs_proto_ah_esp.c +1 -1
@@ -87,7 +87,7 @@ static struct ip_vs_conn * ah_esp_conn_out_get(int af, const struct sk_buff *skb, const struct ip_vs_iphdr *iph, unsigned int proto_off, - int inverse) + int inverse, unsigned short foffs) { struct ip_vs_conn *cp;struct ip_vs_conn_param p;
net/netfilter/ipvs/ip_vs_proto_tcp.c +1 -1
@@ -40,7 +40,7 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,struct tcphdr _tcph, *th;struct ip_vs_iphdr iph; -ip_vs_fill_iphdr (af,skb_network_header (skb), &iph); +ip_vs_fill_iph_skb (af, skb, &iph); th =skb_header_pointer (skb, iph.len,sizeof (_tcph), &_tcph);if (th ==NULL ) {
net/netfilter/ipvs/ip_vs_proto_udp.c +1 -1
@@ -37,7 +37,7 @@ udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,struct udphdr _udph, *uh;struct ip_vs_iphdr iph; -ip_vs_fill_iphdr (af,skb_network_header (skb), &iph); +ip_vs_fill_iph_skb (af, skb, &iph); uh =skb_header_pointer (skb, iph.len,sizeof (_udph), &_udph);if (uh ==NULL ) {
net/netfilter/ipvs/ip_vs_xmit.c +5 -0
@@ -1080,6 +1080,11 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,IP_VS_XMIT (NFPROTO_IPV6 , skb, cp,1 ); } +IP_VS_DBG (1 ,"DR XMIT(%p): %pI6c %pI6c via %pI6c dp:%d fw:%d hdr:%d proto:%d len:%d\n" , + skb, &cp->caddr, &cp->vaddr, &cp->daddr, +ntohs (cp->dport), cp->fwmark, +ipv6_hdr (skb)->nexthdr, cp->protocol, skb->len); +/* MTU checking */ mtu =dst_mtu (&rt->dst);if (skb->len > mtu) {
net/netfilter/xt_ipvs.c +1 -1
@@ -85,7 +85,7 @@ ipvs_mt(const struct sk_buff *skb, struct xt_action_param *par)/* * Check if the packet belongs to an existing entry */ - cp = pp->conn_out_get (family, skb, &iph, iph.len,1 /* inverse */ ); + cp = pp->conn_out_get (family, skb, &iph, iph.len,1 /* inverse */ ,0 );if (unlikely (cp ==NULL )) { match = false; goto out;
---
Regards
Hans Schillstrom <[email protected]>
Simon Horman
maintainerQuoted 2 lines · Hans Schillstrom
Hello,
Long time since the last ipvs patches from me...
Hi Hans,
I apologise that I have not reviewed this patch yet. I will find time to do so soon.