From 9bf4755e932e0036db1bc03285e8c2a3b8ed0ede Mon Sep 17 00:00:00 2001
From: Giovanni Di Stasi <giovanni.distasi@unina.it>
Date: Tue, 9 Jul 2013 14:29:32 +0200
Subject: [PATCH] vsys for new lxc based planetlab code

---
 root-context/exec/sliceip.lxc | 368 ++++++++++++++++++++++++++++++++++
 1 file changed, 368 insertions(+)
 create mode 100644 root-context/exec/sliceip.lxc

diff --git a/root-context/exec/sliceip.lxc b/root-context/exec/sliceip.lxc
new file mode 100644
index 0000000..d91a776
--- /dev/null
+++ b/root-context/exec/sliceip.lxc
@@ -0,0 +1,368 @@
+#!/bin/bash
+#
+# Giovanni Di Stasi
+# <giovanni.distasi on the unina.it domain>
+# Copyright (C) 2009-2013 UniNa
+#
+# This is a backend script to be used with
+# the vsys system. It allows to define and 
+# manage slice-specific routing tables. 
+# The routing rules added to these routing 
+# tables affect only the respective slices.  
+#
+# This script is meant to be called from a 
+# frontend script in the slice environment. 
+#
+# Fronted usage:
+#
+# sliceip route show 
+#   Shows the current routing rules of the
+#   slice-specific routing table
+#
+# sliceip route add to <destination> via <gateway> dev <interface>
+#   Adds a rule to reach <destination> through the host
+#   <gateway> that can be reached on the interface <interface>
+# ...
+# 
+# sliceip in general supports all the commands of the "ip" command of
+# the "iproute2" suite. Refer to ip manpage for further information.
+# 
+# Some examples:
+#	sliceip route add to 143.225.229.142 via 192.168.8.2 dev ath0
+#	sliceip route add default via 10.1.1.1 dev ath0
+#	sliceip route add to 143.225.229.142  nexthop via 192.168.0.1 dev eth1  \
+#	weight 1 src 192.168.0.2 nexthop via 192.168.1.1 dev eth2 weight 1 
+#
+# sliceip can also be used without a frontend program as follows.
+#
+# First use cat to show the output:
+# cat < /vsys/sliceip.out &
+# Then issue a command as, e.g., the following routing rule:
+# echo "route add to some_ip via some_other_ip dev eth0" > /vsys/sliceip.in
+#
+# If you want to test the script from the root context you need 
+# to call it as vsys would do:
+# sliceip <slice_name>
+# Then you can issue to its standard input the commands previously explained
+# (but you have to remove the initial "sliceip"). Ex.:
+#	 route add to 143.225.229.142 via 192.168.8.2 dev ath0
+#
+# A frontend sliceip script can therefore be created as follows:
+# #!/bin/bash
+# cat < /vsys/sliceip.out &
+# echo $* > /vsys/sliceip.in
+#
+# Notes for PlanetLab developers:
+# For sliceip to work correctly it is required that, at boot time 
+# i) stale entries of /etc/iproute2/rt_tables are removed, i.e. lines that 
+# contain slcip; ii) /tmp/ is cleaned.
+
+PATH=/bin:/usr/bin:/sbin:/usr/sbin 
+
+# sliver which called the script
+sliver=$1
+
+#file used
+RT_TABLES="/etc/iproute2/rt_tables"
+
+# routing tables from 6 to 249 are used
+FIRST_TABLE=6
+LAST_TABLE=249
+
+DEBUG=0
+
+
+
+# wrapper function used to execute system commands
+function exec(){
+	local command=$1	
+
+	if ! [[ $command ]]; then
+		echo "Error in exec. No argument."
+	else
+		if ! $command; then
+			if [[ $DEBUG == 1 ]]; then echo "Error executing \"$1\""; fi
+		fi
+	fi
+
+}
+
+# Returns the number of routing rules in routing table $table
+function get_num_rules(){
+  local table=$1
+  
+  ip route show table $table | wc -l
+
+}
+
+
+# Assign a routing table to the sliver (by creating a mapping in
+# /etc/iproute2/rt_tables).
+# If all the routing tables are assigned, remove the mappings
+# for slivers that do not have rules in their routing
+# tables.
+function create_table(){
+
+	  local table_sliver=$1
+
+	  #if the table already exists, returns immediately
+	  if grep "$table_sliver" $RT_TABLES >/dev/null 2>&1; then
+	    return 0
+	  fi
+	
+	  #... otherwise find a free routing table to assign to the sliver
+	  k=$FIRST_TABLE
+	  while [[ $k -lt $((LAST_TABLE+1)) ]] && grep "$k " $RT_TABLES >/dev/null 2>&1 ; do
+		k=$((k+1));
+	  done
+	
+	  #if all were already assigned, remove unused assignements
+	  if [[ $k == $((LAST_TABLE+1)) ]]; then
+	      k=$FIRST_TABLE
+	      while [[ $k -lt $((LAST_TABLE+1)) ]] && grep "$k " $RT_TABLES >/dev/null 2>&1 ; do
+		if [[ `get_num_rules $k` == 0 ]]; then
+		 delete_table `cat $RT_TABLES | grep "$k " | cut -d " " -f 2`
+		fi
+		k=$((k+1));
+	      done
+
+      	      #pick the first that has become available, if any
+	      k=$FIRST_TABLE
+	      while [[ $k -lt $((LAST_TABLE+1)) ]] && grep "$k " $RT_TABLES >/dev/null 2>&1 ; do
+		k=$((k+1));
+	      done
+	      
+	      #otherwise give up and return that no table is available
+	      if [[ $k == $((LAST_TABLE+1)) ]]; then
+		echo "No routing tables available. Exiting."
+		return 1
+	      fi
+	
+	  fi
+	
+	  echo "$k $table_sliver" >> $RT_TABLES
+
+	  set_routes $sliver $table_sliver
+	  	  
+	  return 0
+}
+
+# Delete the slice-specific routing table
+function delete_table(){
+	local table_name=$1
+	local sliver=`basename $table_name "_slcip"`
+
+	if ! grep $table_name $RT_TABLES > /dev/null 2>&1; then
+		return 1			
+	else
+		exec "ip route flush table $table_name" >/dev/null 2>&1
+		unset_routes $sliver $table_name
+		remove_line "$RT_TABLES" "$table_name"  	
+	fi
+
+	return 0
+}
+
+# Remove a line from a file
+function remove_line(){
+	local filename=$1
+	local regex=$2
+
+	#remove interface line from the file
+	exec "sed -i /${regex}/d $filename"
+}
+
+# Get the slice-specific routing table name
+function get_table_name(){
+	local sliver=$1;
+	echo "${sliver}_slcip"
+}
+
+# Remove files used by sliceip and the added routing tables 
+function clean_iproute_conf(){
+	while grep "slcip" $RT_TABLES >/dev/null 2>&1; do
+		remove_line $RT_TABLES "slcip"
+	done
+}
+
+
+# Get sliver's virtual interface
+function get_sliver_veth(){
+  local sliver=$1
+  cat /var/run/libvirt/lxc/$sliver.xml | grep "target dev"  | cut -d "=" -f 2 | cut -d "'" -f 2
+}
+
+function get_sliver_ip(){
+  local sliver=$1
+  local interface=eth0	
+  local ip=""
+	
+  ip=`echo "ifconfig $interface" | lxcsu $sliver | grep inet\ addr | cut -d ":" -f 2 | cut -d " " -f 1`;
+
+  if valid_dotted_quad $ip; then 
+	echo $ip;
+  else 
+	echo "";
+  fi	
+			
+}  
+
+
+
+# set the firewall rules.
+# Basically source routing is enabled.
+function set_routes(){
+	local sliver=$1
+	local table_name=$2
+	#local sliver_veth=`get_sliver_veth $sliver`
+	local sliver_ip=`get_sliver_ip $sliver`
+
+	# Set $table_name as routing table for the sliver
+	# through source routing
+	#exec "ip rule add iif $sliver_veth table $table_name"	
+	exec "ip rule add from $sliver_ip table $table_name"	
+
+	exec "ip route flush cache"  >/dev/null 2>&1
+
+	#Flush stale routing rules in $table_name
+	exec "ip route flush table $table_name"
+}
+
+
+# Remove the firewall rules. 
+function unset_routes(){
+	local sliver=$1
+	local table_name=$2
+	#local sliver_veth=`get_sliver_veth $sliver`
+	local sliver_ip=`get_sliver_ip $sliver`
+
+
+	# Unset $table_name as routing table for the sliver
+	# through source routing
+	exec "ip rule del from $sliver_ip table $table_name"	
+
+	exec "ip route flush cache"  >/dev/null 2>&1
+}
+
+
+# Get the ip address of an interface
+function get_address(){
+	local interface=$1	
+	local ip=""
+	
+	ip=`ifconfig $interface | grep inet\ addr | cut -d ":" -f 2 | cut -d " " -f 1`;
+
+	if valid_dotted_quad $ip; then 
+		echo $ip;
+	else 
+		echo "";
+	fi	
+			
+}
+
+
+# Log function
+function logm(){
+	logger $1
+}
+
+
+
+
+# Check an ip address for correcteness  
+function valid_dotted_quad(){
+    oldIFS=$IFS
+    IFS=.
+    set -f
+    set -- $1
+    if [ $# -eq 4 ]
+    then
+      for seg
+      do
+        case $seg in
+            ""|*[!0-9]*) return 1; break ;; ## Segment empty or non-numeric char
+            *) [ $seg -gt 255 ] && return 2 ;;
+        esac
+      done
+    else
+      return 3 ## Not 4 segments
+    fi
+    IFS=$oldIFS
+    set +f
+    return 0;
+}
+
+# Check to see if the command start with "route"
+function checkCommand(){
+
+  local cmd="$1"
+  local first=`echo "$cmd" | awk '{print $1}'`
+  #local second=`echo $cmd | awk '{print $2}'`
+  
+  
+  if [[ "$first" != "route" ]]; then
+    echo "Command must start with route."
+    return 1
+  fi
+  
+  return 0
+  
+}
+
+# BEGIN
+# the script starts here
+
+if [[ $sliver == "" ]]; then
+	echo "I need the first argument (the sliver name)";
+	exit 1
+fi
+
+# read a line from the vsys pipe
+read line
+
+# separate the first two words of the line from the rest
+command=`echo $line | awk '{print $1 " " $2}'`
+rest=`echo $line | awk '{ for (i = 3; i<=NF; i++) { printf "%s ",$i } }'`
+
+#rest=`echo ${line#* }`
+
+
+
+case "$command" in
+  enable)
+	#enable and disable kept for compatibility
+	logger "sliceip command received from $sliver: $line"	
+	;;
+
+  disable)
+	logger "sliceip command received from $sliver: $line"
+	;;
+
+  *)
+	logger "sliceip command received from $sliver: $line"
+  	
+	#no concurrent executions of sliceip allowed  
+	while ! mkdir /tmp/sliceip.lock >/dev/null 2>&1; do
+	  sleep 0.5
+	done
+	
+	table_sliver=`get_table_name $sliver`
+	
+	#checks the command, creates the routing table and adds the rule
+	if checkCommand "$command" && create_table $table_sliver; then
+	  
+	
+	  #add the routing rule - ip is called with the same parameters of sliceip but the indication of 
+	  #the table in which the rule is to be inserted is inserted		
+	  exec "ip $command table $table_sliver $rest"
+	
+	fi
+	
+	#remove the lock
+	rmdir /tmp/sliceip.lock
+	  
+	;;
+
+esac
+
+exit 0
-- 
2.47.0