Skip to content

Instantly share code, notes, and snippets.

@tehnerd
Created May 20, 2015 20:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tehnerd/5251fecef9688b5b921d to your computer and use it in GitHub Desktop.
Save tehnerd/5251fecef9688b5b921d to your computer and use it in GitHub Desktop.
ipvs tunnel client's src copy
tehnerd@iva-nms:~/linux$ git diff -u e639914f7384a36a6aed563961e2a5ba6e417fc7
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 615b20b..12f4c26 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -924,6 +924,7 @@ struct netns_ipvs {
int sysctl_nat_icmp_send;
int sysctl_pmtu_disc;
int sysctl_backup_only;
+ int sysctl_tun_src_client_copy;
/* ip_vs_lblc */
int sysctl_lblc_expiration;
@@ -1042,6 +1043,11 @@ static inline int sysctl_backup_only(struct netns_ipvs *ipvs)
ipvs->sysctl_backup_only;
}
+static inline int sysctl_tun_src_client_copy(struct netns_ipvs *ipvs)
+{
+ return ipvs->sysctl_tun_src_client_copy;
+}
+
#else
static inline int sysctl_sync_threshold(struct netns_ipvs *ipvs)
@@ -1109,6 +1115,12 @@ static inline int sysctl_backup_only(struct netns_ipvs *ipvs)
return 0;
}
+static inline int sysctl_tun_src_client_copy(struct netns_ipvs *ipvs)
+{
+ return 0;
+}
+
+
#endif
/* IPVS core functions
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 5b373c3..e4bbdce 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1809,6 +1809,12 @@ static struct ctl_table vs_vars[] = {
.mode = 0644,
.proc_handler = proc_dointvec,
},
+ {
+ .procname = "tun_src_client_copy",
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ },
#ifdef CONFIG_IP_VS_DEBUG
{
.procname = "debug_level",
@@ -3730,6 +3736,9 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net)
ipvs->sysctl_pmtu_disc = 1;
tbl[idx++].data = &ipvs->sysctl_pmtu_disc;
tbl[idx++].data = &ipvs->sysctl_backup_only;
+ ipvs->sysctl_tun_src_client_copy = 0;
+ tbl[idx++].data = &ipvs->sysctl_tun_src_client_copy;
+
ipvs->sysctl_hdr = register_net_sysctl(net, "net/ipv4/vs", tbl);
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 1f93313..18e14ea 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -989,7 +989,15 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
iph->protocol = next_protocol;
iph->tos = dsfield;
iph->daddr = cp->daddr.ip;
- iph->saddr = saddr;
+ if (sysctl_tun_src_client_copy(ipvs)) {
+ if (cp->af == AF_INET) {
+ iph->saddr = cp->caddr.ip;
+ } else {
+ iph->saddr = saddr;
+ }
+ } else {
+ iph->saddr = saddr;
+ }
iph->ttl = ttl;
ip_select_ident(skb, NULL);
@@ -1030,6 +1038,7 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
struct ipv6hdr *iph; /* Our new IP header */
unsigned int max_headroom; /* The extra header space needed */
int ret, local;
+ struct netns_ipvs *ipvs = net_ipvs(skb_net(skb));
EnterFunction(10);
@@ -1081,7 +1090,17 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
memset(&iph->flow_lbl, 0, sizeof(iph->flow_lbl));
ipv6_change_dsfield(iph, 0, dsfield);
iph->daddr = cp->daddr.in6;
- iph->saddr = saddr;
+ if(sysctl_tun_src_client_copy(ipvs)){
+ if (cp->af == AF_INET6) {
+ iph->saddr = cp->caddr.in6;
+ } else {
+ //Add some check, that source isnt in 1918 space
+ saddr.s6_addr32[2] &= cp->caddr.ip;
+ iph->saddr = saddr;
+ }
+ } else {
+ iph->saddr = saddr;
+ }
iph->hop_limit = ttl;
/* Another hack: avoid icmp_send in ip_fragment */
tehnerd@iva-nms:~/linux$
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment