From 88a9b2f97349986d746562f19b700ff05580b0f2 Mon Sep 17 00:00:00 2001 From: Naredula Janardhana Reddy Date: Mon, 30 Jan 2012 16:50:02 +0530 Subject: [PATCH] Bug 13375: Summary of changes : - Added a new flag "-s" to ipassoc command to carry if the ip address is used for SNAT or not. - SNAT is completly decoupled from the first flag. first flag is used to decide if the ip address is first ip address of the interface. - -s and -f are independent, SNAT can be enabled on the non-first ip also. --- .../VirtualRoutingResource.java | 6 +- .../vmware/resource/VmwareResource.java | 7 +- .../xen/resource/CitrixResourceBase.java | 7 +- .../systemvm/debian/config/root/ipassoc.sh | 103 +++++++++++------- 4 files changed, 74 insertions(+), 49 deletions(-) diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index ff467db2190..e1bb37bcc92 100755 --- a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -583,9 +583,9 @@ public class VirtualRoutingResource implements Manager { } String cidrSize = Long.toString(NetUtils.getCidrSize(vlanNetmask)); if (sourceNat) { - command.add("-f"); - command.add("-l", publicIpAddress + "/" + cidrSize); - } else if (firstIP) { + command.add("-s"); + } + if (firstIP) { command.add( "-f"); command.add( "-l", publicIpAddress + "/" + cidrSize); } else { diff --git a/core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index f571ded0cd7..896805bc999 100755 --- a/core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -729,10 +729,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } String cidrSize = Long.toString(NetUtils.getCidrSize(vlanNetmask)); if (sourceNat) { - args += " -f "; - args += " -l "; - args += publicIpAddress + "/" + cidrSize; - } else if (firstIP) { + args += " -s "; + } + if (firstIP) { args += " -f "; args += " -l "; args += publicIpAddress + "/" + cidrSize; diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 1f6d2fedf8b..82af103b498 100755 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -1584,10 +1584,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } String cidrSize = Long.toString(NetUtils.getCidrSize(vlanNetmask)); if (sourceNat) { - args += " -f"; - args += " -l "; - args += publicIpAddress + "/" + cidrSize; - } else if (firstIP) { + args += " -s"; + } + if (firstIP) { args += " -f"; args += " -l "; args += publicIpAddress + "/" + cidrSize; diff --git a/patches/systemvm/debian/config/root/ipassoc.sh b/patches/systemvm/debian/config/root/ipassoc.sh index 65007268c4b..63505e3a14e 100644 --- a/patches/systemvm/debian/config/root/ipassoc.sh +++ b/patches/systemvm/debian/config/root/ipassoc.sh @@ -1,29 +1,26 @@ #!/usr/bin/env bash +# Copyright (C) 2011 Citrix Systems, Inc. All rights reserved +# +# This software is licensed under the GNU General Public License v3 or later. +# +# It is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or any later version. +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# - # - # Copyright (C) 2010 Cloud.com, Inc. All rights reserved. - # - # This software is licensed under the GNU General Public License v3 or later. - # - # It is free software: you can redistribute it and/or modify - # it under the terms of the GNU General Public License as published by - # the Free Software Foundation, either version 3 of the License, or any later version. - # This program is distributed in the hope that it will be useful, - # but WITHOUT ANY WARRANTY; without even the implied warranty of - # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - # GNU General Public License for more details. - # - # You should have received a copy of the GNU General Public License - # along with this program. If not, see . - # # $Id: ipassoc.sh 9804 2010-06-22 18:36:49Z alex $ $HeadURL: svn://svn.lab.vmops.com/repos/vmdev/java/scripts/network/domr/ipassoc.sh $ # ipassoc.sh -- associate/disassociate a public ip with an instance -# -# # @VERSION@ source /root/func.sh @@ -207,10 +204,33 @@ add_routing() { fi return 0; } +add_snat() { + if [ "$sflag" == "0" ] + then + return 0; + fi -add_nat_entry() { local pubIp=$1 - logger -t cloud "$(basename $0):Adding nat entry for ip $pubIp on interface $ethDev" + local ipNoMask=$(echo $1 | awk -F'/' '{print $1}') + logger -t cloud "$(basename $0):Added SourceNAT $pubIp on interface $ethDev" + sudo iptables -t nat -D POSTROUTING -j SNAT -o $ethDev --to-source $ipNoMask ; + sudo iptables -t nat -I POSTROUTING -j SNAT -o $ethDev --to-source $ipNoMask ; + return $? +} +remove_snat() { + if [ "$sflag" == "0" ] + then + return 0; + fi + + local pubIp=$1 + logger -t cloud "$(basename $0):Removing SourceNAT $pubIp on interface $ethDev" + sudo iptables -t nat -D POSTROUTING -j SNAT -o $ethDev --to-source $ipNoMask; + return $? +} +add_first_ip() { + local pubIp=$1 + logger -t cloud "$(basename $0):Adding first ip $pubIp on interface $ethDev" local ipNoMask=$(echo $1 | awk -F'/' '{print $1}') local mask=$(echo $1 | awk -F'/' '{print $2}') sudo ip link show $ethDev | grep "state DOWN" > /dev/null @@ -223,18 +243,20 @@ add_nat_entry() { # remove if duplicat ip with 32 mask, this happens when we are promting the ip to primary sudo ip addr del dev $ethDev $ipNoMask/32 > /dev/null fi + sudo iptables -D FORWARD -i $ethDev -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT sudo iptables -D FORWARD -i eth0 -o $ethDev -j ACCEPT - sudo iptables -t nat -D POSTROUTING -j SNAT -o $ethDev --to-source $ipNoMask ; sudo iptables -A FORWARD -i $ethDev -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT sudo iptables -A FORWARD -i eth0 -o $ethDev -j ACCEPT - sudo iptables -t nat -I POSTROUTING -j SNAT -o $ethDev --to-source $ipNoMask ; + + add_snat $1 if [ $? -gt 0 -a $? -ne 2 ] then - logger -t cloud "$(basename $0):Failed adding nat entry for ip $pubIp on interface $ethDev" + logger -t cloud "$(basename $0):Failed adding source nat entry for ip $pubIp on interface $ethDev" return 1 fi - logger -t cloud "$(basename $0):Added nat entry for ip $pubIp on interface $ethDev" + + logger -t cloud "$(basename $0):Added first ip $pubIp on interface $ethDev" if [ $if_keep_state -ne 1 -o $old_state -ne 0 ] then sudo ip link set $ethDev up @@ -245,22 +267,24 @@ add_nat_entry() { return 0 } -del_nat_entry() { +remove_first_ip() { local pubIp=$1 - logger -t cloud "$(basename $0):Deleting nat entry for ip $pubIp on interface $ethDev" + logger -t cloud "$(basename $0):Removing first ip $pubIp on interface $ethDev" local ipNoMask=$(echo $1 | awk -F'/' '{print $1}') local mask=$(echo $1 | awk -F'/' '{print $2}') [ "$mask" == "" ] && mask="32" + sudo iptables -D FORWARD -i $ethDev -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT sudo iptables -D FORWARD -i eth0 -o $ethDev -j ACCEPT - sudo iptables -t nat -D POSTROUTING -j SNAT -o $ethDev --to-source $ipNoMask; + remove_snat $1 + sudo ip addr del dev $ethDev "$ipNoMask/$mask" - - remove_routing $1 if [ $? -gt 0 -a $? -ne 2 ] then + remove_routing $1 return 1 fi + remove_routing $1 return $? } @@ -274,7 +298,7 @@ add_an_ip () { local old_state=$? sudo ip addr add dev $ethDev $pubIp ; - + add_snat $1 if [ $if_keep_state -ne 1 -o $old_state -ne 0 ] then sudo ip link set $ethDev up @@ -292,12 +316,14 @@ remove_an_ip () { local mask=$(echo $1 | awk -F'/' '{print $2}') local existingIpMask=$(sudo ip addr show dev $ethDev | grep inet | awk '{print $2}' | grep -w $ipNoMask) [ "$existingIpMask" == "" ] && return 0 + remove_snat $1 local existingMask=$(echo $existingIpMask | awk -F'/' '{print $2}') if [ "$existingMask" == "32" ] then sudo ip addr del dev $ethDev $existingIpMask result=$? fi + if [ "$existingMask" != "32" ] then replaceIpMask=`sudo ip addr show dev $ethDev | grep inet | grep -v $existingIpMask | awk '{print $2}' | sort -t/ -k2 -n|tail -1` @@ -306,21 +332,21 @@ remove_an_ip () { sudo ip addr del dev $ethDev $replaceIpMask; replaceIp=`echo $replaceIpMask | awk -F/ '{print $1}'`; sudo ip addr add dev $ethDev $replaceIp/$existingMask; - sudo iptables -t nat -D POSTROUTING -j SNAT -o $ethDev --to-source $ipNoMask ; - sudo iptables -t nat -A POSTROUTING -j SNAT -o $ethDev --to-source $replaceIp ; fi result=$? fi - remove_routing $1 + if [ $result -gt 0 -a $result -ne 2 ] then + remove_routing $1 return 1 fi + remove_routing $1 return 0 } #set -x - +sflag=0 lflag= fflag= cflag= @@ -344,7 +370,7 @@ then if_keep_state=1 fi -while getopts 'fADa:l:c:g:' OPTION +while getopts 'sfADa:l:c:g:' OPTION do case $OPTION in A) Aflag=1 @@ -355,6 +381,8 @@ do ;; f) fflag=1 ;; + s) sflag=1 + ;; l) lflag=1 publicIp="$OPTARG" ;; @@ -370,7 +398,6 @@ do esac done - #Either the A flag or the D flag but not both if [ "$Aflag$Dflag" != "1" ] then @@ -387,7 +414,7 @@ fi if [ "$fflag" == "1" ] && [ "$Aflag" == "1" ] then - add_nat_entry $publicIp && + add_first_ip $publicIp && add_vpn_chain_for_ip $publicIp && add_fw_chain_for_ip $publicIp unlock_exit $? $lock $locked @@ -402,7 +429,7 @@ fi if [ "$fflag" == "1" ] && [ "$Dflag" == "1" ] then - del_nat_entry $publicIp && + remove_first_ip $publicIp && del_fw_chain_for_ip $publicIp && del_vpn_chain_for_ip $publicIp unlock_exit $? $lock $locked