#!/bin/bash # author : Petr Simandl www.simandl.cz # release date : 07/09/2004 # name : sedlo # description : dynamic side routing tables tool # license : GPL sl_version="0.0.3pre1-wsh-4" PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin sl_nmcnf="sedlo.conf" sl_sedlocnf="/etc/$sl_nmcnf" sl_sedlocache="/var/cache/sedlo" sl_rttab="/etc/iproute2/rt_tables" sl_rtnmin=110 sl_rtnmax=200 # sl_rule_prio_min - The lowest priority for rules created by # sedlo. Each configured user has one or more dynamic rules for # internet routing as specified in the config file. sl_rule_prio_min=2000 sl_ipnodef="10.0.0.0/8" slm_unknown="Nezname parametry : " sl_ipcmd=`which ip` sl_trcmd=`which tr` sl_wgetcmd=`which wget` sl_hnmcmd=`which hostname` sl_awkcmd=`which awk` sl_catcmd=`which cat` sl_grepcmd=`which grep` if [ -r $sl_sedlocnf ] then sl_nop=1 else echo "$sl_sedlocnf not found or is not readable" exit 1 fi if [ -w $sl_rttab ] then sl_nop=1 else echo "Can't write to $sl_rttab" exit 1 fi # Read local configuration file sl_local_conf_murlcfg=`cat $sl_sedlocnf | grep "^mcnf" | head -n 1 | awk '{print $2}'` sl_local_conf_blackhole=`cat $sl_sedlocnf | grep "^blackhole" | head -n 1 | awk '{print $2}'` sl_local_conf_me2igw=`awk '/^me2igw/ { print $2 "*" $3 "*" $4 }' < $sl_sedlocnf` sl_local_conf_myigws=`awk '/^myigw/ { print $2; }' < $sl_sedlocnf` ###################################################################### s_flru() { # Existing rules which were created by sedlo (priority # sl_rule_prio_min and above) are deleted. All other rules are # preserved. [ $scm_info -gt 0 ] && echo "Flushing all rules created by sedlo" ip rule ls \ | awk -F ':' -v PRIO=$sl_rule_prio_min '{ if ($1 == PRIO) { print $2, " prio ", PRIO; PRIO=PRIO+1;} }' \ | sed -e 's!all!0/0!' \ | while read RULE; do [ $scm_info -gt 1 ] && echo -n '#' ip rule del $RULE; done [ $scm_info -gt 1 ] && echo # new line after ###s } # s_flru ###################################################################### s_fillrules() { s_flru # Flush all rules if [ $scm_info -gt 0 ]; then echo "Creating rules" ; fi sl_rule_prio=$sl_rule_prio_min # rules should have unique prio - see the iproute manual # Insert rule for internal traffic ip ru add from 0/0 to $sl_ipnodef table main prio $sl_rule_prio sl_rule_prio=$((sl_rule_prio + 1)) # Prepare rules for later processing. Delete comments and format them # for better parsing. sl_ips=`awk '/^ip/ {gsub("#.*$", ""); print $2"*"$4"*"$5"*"$6}' < $sl_sedlocache/$sl_nmcnf` # $sl_ips format: ip_range*igw1*igw2*igw3 default_rule="" default_igws=`awk '/^default/ { print $2"*"$3"*"$4; }' < $sl_sedlocache/$sl_nmcnf` [ "x$default_igws" != "x" ] && default_rule="DEFAULT*$default_igws" # $default_rule format: DEFAULT*igw1name*igw2name*igw3name this_router="ME2IGW*$sl_local_conf_me2igw" # $this_router format: THIS_ROUTER*igw1name*igw2name*igw3name for sl_ip in $this_router $sl_ips $default_rule do sl_ipn=`echo $sl_ip | awk -F '*' '{print $1}'` # Client IP sl_ipgws=`echo $sl_ip | awk -F '*' '{print $2,$3,$4}'` # iGW names sl_attempt=1 # Which iGW is assigned (1st, 2nd or 3rd) sl_rule_ok=no # whether there is a functional iGW for this rule for sl_ipgw in $sl_ipgws do sl_tbl=`ip ro ls ta $sl_ipgw` if [ "$sl_tbl x" != " x" ] then [ $scm_info -gt 1 ] && echo "Creating new rules to send $sl_ipn to table $sl_ipgw (attempt $sl_attempt)"; case "$sl_ipn" in "DEFAULT") ip ru add table $sl_ipgw prio $sl_rule_prio ;; "ME2IGW") ip ru add iif lo table $sl_ipgw prio $sl_rule_prio ;; *) ip ru add from $sl_ipn table $sl_ipgw prio $sl_rule_prio ;; esac sl_rule_prio=$((sl_rule_prio + 1)) sl_rule_ok=yes break else sl_attempt=$((sl_attempt + 1)) fi done if [ "x$sl_rule_ok" = "xno" ]; then case "$sl_ipn" in "DEFAULT") # Despite of there is no default iGW accessible, create # a rule for a default iGW. This prevents Internet # packets to enter the main table. first_igw=`echo $sl_ip|awk -F '*' '{ print $2 }'` [ $scm_info -gt 1 ] && echo "Creating new rule to send $sl_ipn to table $first_igw (the last attempt)"; ip ru add table $first_igw prio $sl_rule_prio sl_rule_prio=$((sl_rule_prio + 1)) ;; esac fi done # Flushing the cache is necessary in order to new rules become # efective. ip route flush cache } # s_fillrules ###################################################################### s_filltables() { if [ $scm_info -gt 0 ]; then echo "Filling tables" ; fi sl_igws=`awk '/^igw/ {print $3"*"$2}' < $sl_sedlocache/$sl_nmcnf` # $sl_igws format: "name*ip_addr" for each iGW for sl_igw in $sl_igws do # iGW name sl_igwn=`echo $sl_igw | awk -F '*' '{print $1}'` if echo $sl_local_conf_myigws|grep --word-regexp --fixed-strings --quiet $sl_igwn; then # This iGW name is listed in local config as myigw. Setup # fixed route table. myigw_ip=`awk "/^myigw[[:space:]]+$sl_igwn/ { print \\$3; }" < $sl_sedlocnf` ip ro replace default via $myigw_ip table $sl_igwn else # Normal iGW - create a default route based on the main route # table state. # iGW IP with slash is escaped with a backslash 10.51.0.0/16 -> 10.21.0.0\/16 sl_igwip=`echo $sl_igw | awk -F '*' '{gsub( "/", "\\\\/", $2); print $2}'` # Where to send packets for this iGW (can be "via " or "dev ") sl_igwgt=`ip ro ls | awk "/^$sl_igwip/ {print \\$2, \\$3}"` # TODO: Try to find IGW IP in a IP subnet. It allows an iGW to # publish their settings, becouse it will be the same # regardless # of router's cloud. sl_tbl=`ip ro ls ta $sl_igwn` if [ "$sl_igwgt x" = " x" ] # route to igw not found then if [ $scm_info -gt 1 ]; then echo "Route not found for igw $sl_igwn - leaving table empty" ; fi if [ "$sl_tbl x" != " x" ] # if table is not empty, flush it then ip ro fl ta $sl_igwn fi else sl_no_default_routes_count=`ip ro ls ta $sl_igwn|grep -c -v '^default'` if [ $sl_no_default_routes_count -gt 0 ] # if the table contains other than default routes, flush it then ip ro fl ta $sl_igwn fi ip ro replace default $sl_igwgt table $sl_igwn if [ $scm_info -gt 1 ]; then echo "Table filled for igw $sl_igwn" ; fi fi sl_tbl_new=`ip ro ls ta $sl_igwn` # If an iGW state changes from reachable to unreachable or # vice versa, rules needs to be rebuilt. if [ "x$sl_tbl" = "x" -a "x$sl_tbl_new" != "x" -o \ "x$sl_tbl" != "x" -a "x$sl_tbl_new" = "x" ]; then sl_rules_update_needed=yes fi fi done } # s_filltables ###################################################################### s_mktables() { if [ $scm_info -gt 0 ]; then echo "Creating tables " ; fi sl_igws=`awk '/^igw/ {print $3}' < $sl_sedlocache/$sl_nmcnf` sl_cnt="$sl_rtnmax" for sl_igw in $sl_igws do sl_igwrttb=`awk "/$sl_igw/ {print \\$2}" < $sl_rttab` if [ "$sl_igwrttb x" = " x" ] # Table is not present in rttab then [ $scm_info -gt 1 ] && echo "Creating table for $sl_igw" sl_ok="no" until [ "$sl_cnt" -eq "$sl_rtnmin" ] || [ "$sl_ok" = "yes" ] do sl_igwrttb=`awk "/^[^#]*$sl_cnt/ {print \\$1}" < $sl_rttab` if [ "$sl_igwrttb x" = " x" ] # This number is free then sl_ok="yes" echo "$sl_cnt $sl_igw" >> $sl_rttab fi sl_cnt=$(($sl_cnt - 1 )) done else [ $scm_info -gt 1 ] && echo "Table found for $sl_igw no action taken" fi done } # s_mktables ###################################################################### s_getcfg() { if [ $scm_info -gt 0 ]; then echo "Getting config" ; fi if [ $scm_info -gt 1 ]; then echo "Using main config $sl_local_conf_murlcfg" ; fi if [ $scm_info -gt 1 ]; then echo "Using local config $sl_sedlocnf" ; fi wget --timeout=10 --tries 1 $sl_local_conf_murlcfg -O "$sl_sedlocache/$sl_nmcnf.main.tmp" -q if [ -s $sl_sedlocache/$sl_nmcnf.main.tmp ] then date > $sl_sedlocache/last_getcnf.txt cp $sl_sedlocache/$sl_nmcnf.main.tmp $sl_sedlocache/$sl_nmcnf.main if [ $scm_info -gt 1 ]; then echo "Main config accepted" ; fi else # Test if there is an old cached config file. This happens when # wget is not installed when run first. if [ ! -r $sl_sedlocache/$sl_nmcnf.main ]; then echo "No cached main config file found ($sl_sedlocache/${sl_nmcnf}.main)" exit 1; fi if [ $scm_info -gt 1 ]; then echo "Main config not accepted - using cached config" ; fi echo -n "Main config not found " > $sl_sedlocache/last_getcnf.txt || exit 1 date >> $sl_sedlocache/last_getcnf.txt fi # Preparing cached config from local and main one. The ^ip lines form # local config should have higher priority than the same lines in the # main config. For ^igw lines, the oposite is true. The default iGW # (first iGW in the config) should be the same for whole cloud. echo "# generated file" > $sl_sedlocache/$sl_nmcnf || exit 1 sl_conf_main_first=`ls $sl_sedlocache/$sl_nmcnf.main $sl_sedlocnf` sl_conf_local_first=`ls $sl_sedlocnf $sl_sedlocache/$sl_nmcnf.main` #cat $sl_file | grep "^mcnf" | tr ';' '#' | awk '{print $1"\t"$2}' >> $sl_sedlocache/$sl_nmcnf || exit grep --no-filename --extended-regexp "^(igw|default)" $sl_conf_main_first| tr ';' '#' | awk '{print $1"\t"$2"\t"$3}' >> $sl_sedlocache/$sl_nmcnf || exit 1 grep --no-filename "^ip" $sl_conf_local_first| tr ';' '#' | awk '{print $1"\t"$2"\t"$3"\t"$4"\t"$5"\t"$6}' >> $sl_sedlocache/$sl_nmcnf || exit 1 #cat $sl_sedlocache/$sl_nmcnf | sort | uniq > $sl_sedlocache/$sl_nmcnf.uniq #mv $sl_sedlocache/$sl_nmcnf.uniq $sl_sedlocache/$sl_nmcnf } ###################################################################### s_version() { echo sedlo $sl_version } # s_version ###################################################################### s_report() { echo "##### SEDLO #####" echo "date : `date`" echo "version : $sl_version" echo "local_config : $sl_sedlocnf" echo "main_config : $sl_local_conf_murlcfg" echo "last update : `cat $sl_sedlocache/last_getcnf.txt`" echo "##### TABLES #####" tables=`awk "/^[^#]/ { if (\\\$1 >= $sl_rtnmin && \\\$1 <= $sl_rtnmax) print \\\$2; }" < $sl_rttab` for table in $tables; do echo "${table}:" ip ro ls table ${table}|awk '{ print " " $0; }' done echo "##### RULES #####" ip ru ls } # s_report ###################################################################### sl_lock_filename="/tmp/sedlo.lock" sl_tmp_lock_filename="/tmp/sedlo.$$" sl_try_lock() { echo $$ > $sl_tmp_lock_filename 2>/dev/null || { echo >&2 "You don't have permission to access `dirname $TEMPFILE`" return 1 } ln $sl_tmp_lock_filename $sl_lock_filename 2>/dev/null && { rm -f $sl_tmp_lock_filename return 0 } rm -f $sl_tmp_lock_filename return 1 } # sl_invalid_lock: returns 0 (success) if the lock file doesn't # contain valid PID of sedlo process. sl_invalid_lock() { local pid local proc_name [ -f $sl_lock_filename ] || return 1 # lock doesn't exist so it # can't be invalid pid=$(< $sl_lock_filename) proc_name=$(ps --pid $pid -o comm --no-headers) if [ "$proc_name" = "sedlo" ]; then return 1 # the lock is valid else return 0 # the lock is invalid fi; } sl_lock() { trap sl_unlock EXIT timeout=10 while [ $timeout -gt 0 ]; do sl_try_lock && break [ $timeout -eq 10 -a $scm_info -gt 0 ] && echo "Trying to lock sedlo..." sleep 1 timeout=$((timeout - 1)) done if [ $timeout -eq 0 ]; then sl_invalid_lock && rm -f $sl_lock_filename && sl_try_lock && return 0 echo >&2 "Can't lock $sl_lock_filename." echo >&2 "Probably sedlo is already running with PID `< $sl_lock_filename`." exit 2 fi } sl_unlock() { if [ -f $sl_lock_filename ]; then [ "`< $sl_lock_filename`" = "$$" ] && rm -f $sl_lock_filename fi [ -f $sl_tmp_lock_filename ] && rm -f $sl_tmp_lock_filename } ###################################################################### s_help() { cat <> $sl_rttab fi sl_cnt=$(($sl_cnt - 1 )) done else if [ $scm_info -gt 1 ]; then echo "Table found for $sl_igw no action taken" ; fi fi done } # s_mktables ###################################################################### s_getcfg() { if [ $scm_info -gt 0 ]; then echo "Getting config" ; fi if [ $scm_info -gt 1 ]; then echo "Using main config $sl_murlcfg" ; fi if [ $scm_info -gt 1 ]; then echo "Using local config $sl_sedlocnf" ; fi wget $sl_murlcfg -O "$sl_sedlocache/$sl_nmcnf.main" -q if [ -s $sl_sedlocache/$sl_nmcnf.main ] then sl_nop=1 else if [ $scm_info -gt 1 ]; then echo "Main config not found $sl_sedlocache/$sl_nmcnf.main" ; fi fi echo "# generated file" > $sl_sedlocache/$sl_nmcnf for sl_file in `ls $sl_sedlocnf $sl_sedlocache/$sl_nmcnf.main ` do cat $sl_file | grep "^mcnf" | awk '{print $1"\t"$2}' >> $sl_sedlocache/$sl_nmcnf cat $sl_file | grep "^igw" | awk '{print $1"\t"$2"\t"$3}' >> $sl_sedlocache/$sl_nmcnf cat $sl_file | grep "^ip" | awk '{print $1"\t"$2"\t"$3"\t"$4"\t"$5"\t"$6}' >> $sl_sedlocache/$sl_nmcnf done cat $sl_sedlocache/$sl_nmcnf | sort | uniq > $sl_sedlocache/$sl_nmcnf.uniq mv $sl_sedlocache/$sl_nmcnf.uniq $sl_sedlocache/$sl_nmcnf } ###################################################################### s_version() { echo sedlo $sl_version exit 0 } # s_version ###################################################################### s_report() { echo "##### SEDLO #####" echo "version : $sl_version" echo "local_config : $sl_sedlocnf" echo "main_config : $sl_murlcfg" echo "##### TABLES #####" cat $sl_rttab echo "##### RULES #####" $sl_ipcmd ru ls exit 0 } # s_report ###################################################################### s_help() { echo Pouziti: sedlo [param] echo param: echo -v vypise verzi echo -help vypise napovedu echo -info1 malo upovidany echo -info2 hodne upovidany echo -nogetcfg zajisti ze se nedude znovu nacitat konfigurace a pouzije se predchozi z cache echo -report vypise prehled pravidel a tabulek exit 0 } # s_help ###################################################################### ###################################################################### sl_unknown="" scm_nogetcfg=0 scm_info=0 # parsing input parameters while [ "a$1" != "a" ] do case $1 in -v) s_version ;; -h) s_help ;; -report) s_report ;; -help) s_help ;; -nogetcfg) scm_nogetcfg=1 shift ;; -info1) scm_info=1 shift ;; -info2) scm_info=2 shift ;; *) sl_unknown="$sl_unknown$1 " shift esac done # printing the list of bad parameters (if there are some) if [ "a$sl_unknown" != "a" ] then echo "$slm_unknown $sl_unknown" s_help fi if [ $scm_nogetcfg -eq 0 ] then s_getcfg fi s_mktables s_filltables s_fillrules exit 0 WebSVN - sedlo - Diff - Rev 4 and 3 - /trunk/sedlo
  jablonka.czprosek.czf

sedlo

Subversion Repositories:
[/] [trunk/] [sedlo] - Diff between revs 3 and 4

Show entire file Ignore whitespace

Rev 3 Rev 4

Powered by WebSVN 2.2.1