![]() ![]() |
sedlo |
Subversion Repositories: |
Compare with Previous - Blame - Download
#!/bin/bash# author : Petr Simandl www.simandl.cz# release date : 03/06/2007# name : sedlo# description : dynamic side routing tables tool# license : GPLsl_version="0.0.4pre11"PATH=$PATH:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbinsl_nmcnf="sedlo.conf"sl_sedlocnf="/etc/$sl_nmcnf"sl_sedlocache="/var/cache/sedlo"mkdir -p /var/cache/sedlosl_rttab="/etc/iproute2/rt_tables"sl_rtnmin=110sl_rtnmax=200#all traffic that is handled as internal (CZF traffic)sl_ipnodef="10.0.0.0/8"#this will specify base priority in rule tablesl_priobase=10000#this will specify base priority in rule table select masksl_priorulesmask="100.."#no default traffic will have rule at higher prioritysl_prionodef=$(($sl_priobase - 1))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`sl_diffcmd=`which diff`if [ -e $sl_sedlocnf ]thensl_nop=1elseecho "$sl_sedlocnf not found"exit 1fiif [ -e $sl_rttab ]thensl_nop=1elseecho "$sl_rttab not found"exit 1fisl_murlcfg=`cat $sl_sedlocnf | grep "^mcnf" | uniq | awk '{print $2" "$3" "$4}'`#######################################################################this will delete all rules at sl_prionodef and sl_priorulesmask prioritiess_flruall(){if [ $scm_info -gt 0 ]; then echo "Flushing all rules" ; fisl_rules=`$sl_ipcmd ru ls | $sl_grepcmd "^"$sl_prionodef":" | $sl_trcmd '[:blank:]' '*'`for sl_rule in $sl_rulesdosl_ipgws=`echo $sl_rule | $sl_awkcmd -F '*' '{print $2,$3,$4,$5,$6,$7}'`$sl_ipcmd ru del $sl_ipgws#this should make faster applying of new routing tables$sl_ipcmd ro flush cachedonesl_rules=`$sl_ipcmd ru ls | $sl_grepcmd "^"$sl_priorulesmask":" | $sl_trcmd '[:blank:]' '*'`for sl_rule in $sl_rulesdosl_ipgws=`echo $sl_rule | $sl_awkcmd -F '*' '{print $2,$3,$4,$5,$6,$7}'`$sl_ipcmd ru del $sl_ipgws#this should make faster applying of new routing tables$sl_ipcmd ro flush cachedone} # s_flruall######################################################################s_checknodefru(){#checking if we have present nodef rule and if not we create itsl_nodefrule=`$sl_ipcmd ru ls | $sl_grepcmd "^"$sl_prionodef":" | $sl_trcmd '[:blank:]' '*'`#echo $sl_nodefruleif [ "$sl_nodefrule x" == " x" ]thenif [ $scm_info -gt 0 ]; then echo "Creating rule for nodef route" ; fi$sl_ipcmd ru add from $sl_ipnodef to $sl_ipnodef lookup main prio $sl_prionodeffi}####################################################################### here we get each ip and we create a rule to send this ip to a# certain table# this routine can be skipped when the number of ips and ip directions# are still the same = old and new configs are the sames_fillrules(){#this will check no default rule if exists and if not it will be createds_checknodefruif [ $scm_info -gt 0 ]; then echo "Checking rules for ips" ; fisl_ips=`$sl_catcmd $sl_sedlocache/$sl_nmcnf | $sl_grepcmd "^ip" | $sl_awkcmd '{print $2"*"$4"*"$5"*"$6}'`sl_rules=`$sl_ipcmd ru ls | $sl_grepcmd ^$sl_priorulesmask":" | $sl_trcmd '[:blank:]' '*'`#for all IPs we check and leave, change or create rulefor sl_ip in $sl_ipsdosl_ipn=`echo $sl_ip | $sl_awkcmd -F '*' '{print $1}'`sl_ipgws=`echo $sl_ip | $sl_awkcmd -F '*' '{print $2,$3,$4}'`sl_ok="no"#for all GWs we check rulesfor sl_ipgw in $sl_ipgwsdosl_tbl=`$sl_ipcmd ro ls ta $sl_ipgw`#check if table existsif [ "$sl_tbl x" != " x" ] && [ "$sl_ok" = "no" ]then#we have IP and GW table#check if the rule alredady existssl_oldrule=`echo $sl_rules | $sl_trcmd " " "\n" | $sl_grepcmd "\*"$sl_ipn"\*"`sl_exactrule=`echo $sl_oldrule | $sl_trcmd " " "\n" | $sl_grepcmd "\*"$sl_ipgw"\*"`if [ "$sl_exactrule x" == " x" ]then#exact rule doesn't exist so we check if an old rule for this IP is presentif [ "$sl_oldrule x" != " x" ]then#some old rule(s) for IP is present so we delete itfor sl_rule in $sl_oldruledosl_ipgws=`echo $sl_rule | $sl_awkcmd -F '*' '{print $2,$3,$4,$5,$6,$7}'`if [ $scm_info -gt 0 ]; then echo "Deleting old rule $sl_ipgws" ; fi$sl_ipcmd ru del $sl_ipgws#this should make faster applying of new routing tables$sl_ipcmd ro flush cachedonefi#getting subnet mask if existssl_subnet=`echo $sl_ip | $sl_awkcmd -F '/' '{print $2}' | $sl_awkcmd -F '*' '{print $1}' `if [ "$sl_subnet x" == " x" ]then#if subnet was not found we set subnet to 32sl_subnet=32else#this is just to be sure to have subnet between 1 and 32if [ $sl_subnet -gt 32 ]; then sl_subnet=32 ; fiif [ $sl_subnet -lt 1 ]; then sl_subnet=1 ; fifi#bigger subnets have lower prioritysl_priorule=$(($sl_priobase + 32))sl_priorule=$(($sl_priorule - $sl_subnet))if [ $scm_info -gt 0 ]; then echo "Creating new rule to send $sl_ipn to table $sl_ipgw" ; fi$sl_ipcmd ru add from $sl_ipn lookup $sl_ipgw prio $sl_prioruleelseif [ $scm_info -gt 1 ]; then echo "Rule to send $sl_ipn to table $sl_ipgw already exists" ; fifisl_ok="yes"else#we have no tableif [ "$sl_ok" = "no" ]thenif [ $scm_info -gt 1 ]; then echo "For $sl_ipn table $sl_ipgw not used because it is empty" ; fielseif [ $scm_info -gt 1 ]; then echo "For $sl_ipn table $sl_ipgw not used because it has lower priority" ; fififidonedone#finally we check all rules and if there is a rule without IP from config we delete itfor sl_rule in $sl_rulesdosl_iprule=`echo $sl_rule | $sl_awkcmd -F '*' '{print $3}'`sl_ipconf=`echo $sl_ips | $sl_trcmd " " "\n" | $sl_grepcmd "^"$sl_iprule"\*"`if [ "$sl_ipconf x" == " x" ]then#we have a rule without an IP in config so we delete this rulesl_ipgws=`echo $sl_rule | $sl_awkcmd -F '*' '{print $2,$3,$4,$5,$6,$7}'`if [ $scm_info -gt 0 ]; then echo "Deleting non config rule $sl_ipgws" ; fi$sl_ipcmd ru del $sl_ipgws#this should make faster applying of new routing tables$sl_ipcmd ro flush cachefidone} # s_fillrules####################################################################### here we look into the main routing table for path to our iGWs# and we fill these tables with two halves default nets that# point to appropriate direction# this routine can be skipped when the routing table is the sames_filltables(){if [ $scm_info -gt 0 ]; then echo "Checking main routing table" ; fiif [ $scm_info -gt 0 ]; then echo "Filling tables" ; fisl_igws=`$sl_catcmd $sl_sedlocache/$sl_nmcnf | $sl_grepcmd -E "^igw|^myigw" | $sl_awkcmd '{print $3"*"$2"*"$1}'`for sl_igw in $sl_igwsdosl_igwn=`echo $sl_igw | $sl_awkcmd -F '*' '{print $1}'`sl_igwip=`echo $sl_igw | $sl_awkcmd -F '*' '{print $2}'`sl_igwtype=`echo $sl_igw | $sl_awkcmd -F '*' '{print $3}'`#oprava falesneho routovani na lokalni iface - pokud jsme lokalni igw tak se nema najit ip#protoze cesta dal neni - jsme totiz uz na lokalnim iface#head je tam proto ze se pro prespolni(a bgp) muze objevit vice rout s ruznou metrikou tak vezmem jen prvni (head)#s nejmensi metrikou (sort)sl_igwgt=`$sl_ipcmd ro ls | $sl_grepcmd -v "proto kernel" | $sl_grepcmd "^$sl_igwip " | sort | $sl_awkcmd '{print $3}' | head -n 1`# equal cost multipath detection - just first IP is taken as way to igwif [ "$sl_igwgt x" = "zebra x" ]thensl_igwgt=`$sl_ipcmd ro ls | $sl_grepcmd -A 1 "^$sl_igwip " | $sl_grepcmd "nexthop" | $sl_awkcmd '{print $3}'`fi#if myigw then fill table for local gateway with single ip from configif [ "$sl_igwtype x" = "myigw x" ]thensl_igwgt=$sl_igwipfi#testing if the igw has not a route in global routing tableif [ "$sl_igwgt x" = " x" ]thenif [ $scm_info -gt 1 ]; then echo "Route not found for igw $sl_igwn" ; fisl_myigw=`cat $sl_sedlocnf | $sl_grepcmd "^myigw" | $sl_grepcmd $sl_igwn | $sl_awkcmd '{print $3}'`#testing if the igw without route is in local config#if not we go to flush its table and set flag to redo rulesif [ "$sl_myigw x" = " x" ]then#getting num of routes of igwsl_igwnr=`$sl_ipcmd ro ls ta all | $sl_grepcmd -c "table ${sl_igwn} "`if [ "$sl_igwnr x" = "0 x" ]thenif [ $scm_info -gt 1 ]; then echo "Table $sl_igwn is already empty - no action taken" ; fielseif [ $scm_info -gt 1 ]; then echo "Table $sl_igwn will be flushed and rules rearranged" ; fi$sl_ipcmd ro fl ta $sl_igwn#because this igw dissapeared we set a flag for rules recreationsl_diffigw=1fielseif [ $scm_info -gt 1 ]; then echo "Igw $sl_igwn found in local config - leaving table as is" ; fifielsesl_tbl=`$sl_ipcmd ro ls ta $sl_igwn`#if the table is empty we fill it and we set flag for rules recreationif [ "$sl_tbl x" = " x" ]thensl_diffigw=1$sl_ipcmd ro add 0.0.0.0/1 via $sl_igwgt ta $sl_igwn$sl_ipcmd ro add 128.0.0.0/1 via $sl_igwgt ta $sl_igwnif [ "$sl_igwtype x" = "myigw x" ]thenif [ $scm_info -gt 1 ]; then echo "Table $sl_igwn filled with default myigw $sl_igwgt" ; fielseif [ $scm_info -gt 1 ]; then echo "Table $sl_igwn filled with default gw $sl_igwgt" ; fifi#the table is not empty so we check if routes are the sameelse#picking default gateway from the tablesl_igwogt=`$sl_ipcmd ro ls ta $sl_igwn | $sl_awkcmd '{print $3}' | uniq`#checking if the old default is same as the new oneif [ "$sl_igwogt x" = "$sl_igwgt x" ]thenif [ $scm_info -gt 1 ]; then echo "Table $sl_igwn will not be changed and default is $sl_igwgt" ; fielse#the new default is different so we will flush the table, fill new defaultif [ $scm_info -gt 1 ]; then echo "Table $sl_igwn will be rewritten to default $sl_igwgt" ; fi#flushing old default route in the table$sl_ipcmd ro fl ta $sl_igwn#filling new default$sl_ipcmd ro add 0.0.0.0/1 via $sl_igwgt ta $sl_igwn$sl_ipcmd ro add 128.0.0.0/1 via $sl_igwgt ta $sl_igwnfififidone} # s_filltables####################################################################### filling rttab with tables from config# only new tables are created with a new uniq number that is not important because# usually we handle tables just by their names# this routine acts only when a new iGW appears - only adding a table is supported# no deleting is implemented because it seems to be not necessary to delete an old table# because there is space enough and after reboot table will not be createds_mktables(){if [ $scm_info -gt 0 ]; then echo "Checking tables" ; fisl_igws=`$sl_catcmd $sl_sedlocache/$sl_nmcnf | $sl_grepcmd -E "^igw|^myigw" | $sl_awkcmd '{print $3}'`for sl_igw in $sl_igwsdosl_igwrttb=`$sl_catcmd $sl_rttab | $sl_awkcmd '{print $2}' | $sl_grepcmd $sl_igw `if [ "$sl_igwrttb x" = " x" ]thenif [ $scm_info -gt 1 ]; then echo "Creating table for $sl_igw" ; fisl_cnt="$sl_rtnmax"sl_ok="no"until [ "$sl_cnt" -eq "$sl_rtnmin" ] || [ "$sl_ok" = "yes" ]do#space is used to recognized two and three digit numberssl_igwrttb=`cat $sl_rttab | awk '{print $1" "}' | grep "$sl_cnt " `if [ "$sl_igwrttb x" = " x" ]thensl_ok="yes"echo "$sl_cnt $sl_igw" >> $sl_rttabfisl_cnt=$(($sl_cnt - 1 ))done# a new table was created so we should set a flag for rules creationsl_difftbl=1elseif [ $scm_info -gt 1 ]; then echo "Table found for $sl_igw no action taken" ; fifidone} # s_mktables######################################################################s_getcfg(){if [ $scm_info -gt 0 ]; then echo "Getting config" ; fiif [ $scm_info -gt 1 ]; then echo "Using main config $sl_murlcfg" ; fiif [ $scm_info -gt 1 ]; then echo "Using local config $sl_sedlocnf" ; firm -f "$sl_sedlocache/$sl_nmcnf.main.tmp"$sl_wgetcmd -q -t 3 $sl_murlcfg -O "$sl_sedlocache/$sl_nmcnf.main.tmp"if [ -s $sl_sedlocache/$sl_nmcnf.main.tmp ]thendate > $sl_sedlocache/last_getcnf.txtcp $sl_sedlocache/$sl_nmcnf.main.tmp $sl_sedlocache/$sl_nmcnf.mainif [ $scm_info -gt 1 ]; then echo "Main config downloaded and accepted" ; fielseif [ $scm_info -gt 1 ]; then echo "Main config not downloaded - cached config will be used" ; fiecho -n "Main config not downloaded " > $sl_sedlocache/last_getcnf.txtdate >> $sl_sedlocache/last_getcnf.txtfi# before generating a new cached config we store the old one for# comparison with the new onerm -f "$sl_sedlocache/$sl_nmcnf.old"if [ -s $sl_sedlocache/$sl_nmcnf ]thencp $sl_sedlocache/$sl_nmcnf $sl_sedlocache/$sl_nmcnf.oldelsetouch $sl_sedlocache/$sl_nmcnf.oldfi# preparing cached config from local and main# the local config should be processed as the first to have# higher priority for rules from local configecho "# generated file" > $sl_sedlocache/$sl_nmcnffor sl_file in `ls $sl_sedlocnf ; ls $sl_sedlocache/$sl_nmcnf.main `docat $sl_file | grep "^mcnf" | $sl_trcmd ';' '#' | awk '{print $1"\t"$2}' >> $sl_sedlocache/$sl_nmcnfcat $sl_file | grep "^igw" | $sl_trcmd ';' '#' | awk '{print $1"\t"$2"\t"$3}' >> $sl_sedlocache/$sl_nmcnfcat $sl_file | grep "^ip" | $sl_trcmd ';' '#' | awk '{print $1"\t"$2"\t"$3"\t"$4"\t"$5"\t"$6}' >> $sl_sedlocache/$sl_nmcnfdone#local gateways taken from local configcat $sl_sedlocnf | grep "^myigw" | $sl_trcmd ';' '#' | awk '{print $1"\t"$2"\t"$3}' >> $sl_sedlocache/$sl_nmcnf#cat $sl_sedlocache/$sl_nmcnf | sort | uniq > $sl_sedlocache/$sl_nmcnf.uniq#mv $sl_sedlocache/$sl_nmcnf.uniq $sl_sedlocache/$sl_nmcnfsl_diffcfg=`diff $sl_sedlocache/$sl_nmcnf $sl_sedlocache/$sl_nmcnf.old | grep -c .`if [ $sl_diffcfg -gt 0 ]thenif [ $scm_info -gt 0 ]; then echo "New config is different than the old one" ; fielseif [ $scm_info -gt 0 ]; then echo "New config is the same as the old one" ; fifi# showing number of rules in config and systemsl_numru=`ip ru ls | grep -c lookup`sl_numip=`grep -c ^ip $sl_sedlocache/$sl_nmcnf`sl_numru=$(($sl_numru - 3 ))if [ $sl_numip -gt $sl_numru ]thenif [ $scm_info -gt 0 ]; then echo "We have less rules ($sl_numru) than new config has ips ($sl_numip)" ; fi# sl_diffcfg="1"elseif [ $scm_info -gt 0 ]; then echo "We have $sl_numru rules and $sl_numip ips" ; fifi}######################################################################s_version(){echo sedlo $sl_version} # s_version######################################################################s_report(){echo Content-type: text/htmlechoecho "Sedlo na routeru `hostname`"echo "<pre>"echo "##### SEDLO #####"echo "date : `date`"echo "version : $sl_version"echo "local_config : $sl_sedlocnf"echo "main_config : <a href=\"$sl_murlcfg\">$sl_murlcfg</a>"echo "last update : `cat $sl_sedlocache/last_getcnf.txt`"echo "##### TABLES #####"cat $sl_rttabecho ; echo "##### DEFAULT ROUTES IN TABLES #####"$sl_ipcmd ro ls ta all | $sl_grepcmd table | $sl_grepcmd -v local | $sl_trcmd " " "\t"echo ; echo "##### RULES FOR IPS #####"$sl_ipcmd ru ls | $sl_trcmd " " "\t"echo "</pre>"} # s_report######################################################################s_help(){echo Pouziti: sedlo [param]echo param:echo -V vypise verziecho -help vypise napoveduecho -v malo upovidanyecho -vv hodne upovidanyecho -nogetcfg zajisti ze se nedude znovu nacitat konfigurace a pouzije se predchozi z cacheecho -report vypise prehled pravidel a tabulekecho -flru odstrani vsechny pravidlaecho -force bezpodminecne znovu obnovi vsechny pravidla} # s_help############################################################################################################################################sl_unknown=""scm_nogetcfg=0scm_flru=0scm_info=0scm_force=0sl_diffigw=0sl_difftbl=0# parsing input parameterswhile [ "a$1" != "a" ]docase $1 in-V)s_versionexit 0;;-h)s_helpexit 0;;-report)s_reportexit 0;;-flru)scm_flru=1shift;;-force)scm_force=1shift;;-help)s_helpexit 0;;-nogetcfg)scm_nogetcfg=1shift;;-v)scm_info=1shift;;-vv)scm_info=2shift;;*)sl_unknown="$sl_unknown$1 "shiftesacdone# printing the list of bad parameters (if there are some)if [ "a$sl_unknown" != "a" ]thenecho "$slm_unknown $sl_unknown"s_helpexit 0fiif [ $scm_flru -eq 1 ]thens_flruallexit 0fiif [ $scm_nogetcfg -eq 0 ]thens_getcfgfis_mktabless_filltables#toto je pro ladici ucely#echo $sl_difftbl#echo $sl_diffcfg#echo $sl_diffigw#echo $scm_force#exit 0#flushing and filling rules is done only when#new table is created#config is changed#some igw dissapears or appears#-force command line parameter was usedif [ $sl_difftbl -gt 0 ] || [ $sl_diffcfg -gt 0 ] || [ $sl_diffigw -gt 0 ] || [ $scm_force -gt 0 ]thens_fillrulesfiexit 0