gateway: add SmartGatewayPolicyRoutingScript configuration parameter
authorFerry Huberts <ferry.huberts@pelagic.nl>
Tue, 4 Dec 2012 11:56:19 +0000 (12:56 +0100)
committerFerry Huberts <ferry.huberts@pelagic.nl>
Thu, 13 Dec 2012 12:23:29 +0000 (13:23 +0100)
Signed-off-by: Ferry Huberts <ferry.huberts@pelagic.nl>
Reviewed-by: Henning Rogge <hrogge@googlemail.com>
13 files changed:
Makefile
Makefile.inc
README-Olsr-Extensions
files/olsrd.conf.default.full
files/olsrd.conf.default.lq
files/olsrd.conf.default.lq-fisheye
files/sgw_policy_routing_setup.sh [new file with mode: 0755]
lib/jsoninfo/src/olsrd_jsoninfo.c
src/cfgparser/cfgfile_gen.c
src/cfgparser/olsrd_conf.c
src/cfgparser/oparse.y
src/cfgparser/oscan.lex
src/olsr_cfg.h

index 4e1f2d8..3e36be5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -122,6 +122,12 @@ install_bin:
                mkdir -p $(SBINDIR)
                install -m 755 $(EXENAME) $(SBINDIR)
                $(STRIP) $(SBINDIR)/$(EXENAME)
+               $(MAKECMDPREFIX)if [ -e $(SBINDIR)/$(SGW_POLICY_SCRIPT) ]; then \
+                       cp -f files/$(SGW_POLICY_SCRIPT) $(SBINDIR)/$(SGW_POLICY_SCRIPT).new; \
+                       echo "Policy routing script was saved as $(SBINDIR)/$(SGW_POLICY_SCRIPT).new"; \
+               else \
+                       cp -f files/$(SGW_POLICY_SCRIPT) $(SBINDIR)/$(SGW_POLICY_SCRIPT); \
+               fi
 
 uninstall_bin:
                rm -f $(SBINDIR)/$(EXENAME)
index 9ef9881..c9e4ed1 100644 (file)
@@ -68,6 +68,7 @@ MANDIR   ?= $(SHAREDIR)/man
 EXENAME  ?= olsrd
 CFGNAME  ?= $(EXENAME).conf
 CFGFILE  ?= $(ETCDIR)/$(CFGNAME)
+SGW_POLICY_SCRIPT ?= sgw_policy_routing_setup.sh
 
 DOCDIR_OLSRD ?= $(DOCDIR)/$(EXENAME)
 
index 35b5160..3030a9f 100644 (file)
@@ -256,30 +256,36 @@ All other parameters will be ignored if SmartGateway is set to "no"
    breaking connections (due to the selection of a new gateway) on a dynamic
    network.
    The default setting is 1.
-2- SmartGatewayEgressInterfaces determines the egress interfaces that are part
+2- SmartGatewayPolicyRoutingScript controles the policy routing script that is
+   executed during startup and shutdown of olsrd. The script is only executed
+   when SmartGatewayUseCount is set to a value larger than 1. The script must
+   setup policy routing rules such that multi-gateway mode works. A sample
+   script is included.
+   The default setting is 'not set'.
+3- SmartGatewayEgressInterfaces determines the egress interfaces that are part
    of the multi-gateway setup and therefore only relevant when
    SmartGatewayUseCount is larger than 1 (in which case it must be explicitly
    set).
    The default setting is 'not set'.
-3- SmartGatewayMarkOffsetEgress and SmartGatewayMarkOffsetTunnels determine
+4- SmartGatewayMarkOffsetEgress and SmartGatewayMarkOffsetTunnels determine
    the ranges of policy routing rule markings that are used in a multi-gateway
    setup. The ranges are not allowed to overlap. Both settings are only
    relevant when a multi-gateway setup is used.
    The default settings are 91 and 101 respectively.
-4- SmartGatewayAllowNAT controls whether you want to allow the selection
+5- SmartGatewayAllowNAT controls whether you want to allow the selection
    of an outgoing ipv4 gateway with NAT (Network Address Translation).
    The default setting is "yes".
-5- SmartGatewayPeriod determines the period (in milliseconds) on which
+6- SmartGatewayPeriod determines the period (in milliseconds) on which
    a new smart gateway selection is performed.
    The default setting is 10000 milliseconds.
-6- SmartGatewayStableCount determines the number of times the link state
+7- SmartGatewayStableCount determines the number of times the link state
    database must be stable before a new smart gateway is selected.
    The default setting is 6.
-7- SmartGatewayThreshold controls whether you want to allow re-selection
+8- SmartGatewayThreshold controls whether you want to allow re-selection
    of a new outgoing gateway if its routing cost is lower or equal to the
    configured percentage of the routing cost of the current gateway.
    The default setting is 0, which disables it.
-8- SmartGatewayWeightExitLinkUp, SmartGatewayWeightExitLinkDown,
+9- SmartGatewayWeightExitLinkUp, SmartGatewayWeightExitLinkDown,
    SmartGatewayWeightEtx and SmartGatewayDividerEtx control the weighing
    of gateway bandwidth and ETX costs.
 
index a99894c..3869f13 100644 (file)
 
 # SmartGatewayUseCount 1
 
+# Determines the policy routing script that is executed during startup and
+# shutdown of olsrd. The script is only executed when SmartGatewayUseCount
+# is set to a value larger than 1. The script must setup policy routing
+# rules such that multi-gateway mode works. A sample script is included.
+# (default is not set)
+
+# SmartGatewayPolicyRoutingScript ""
+
 # Determines the egress interfaces that are part of the multi-gateway setup and
 # therefore only relevant when SmartGatewayUseCount is larger than 1 (in which
 # case it must be explicitly set).
index 51c09d5..84016c5 100644 (file)
 
 # SmartGatewayUseCount 1
 
+# Determines the policy routing script that is executed during startup and
+# shutdown of olsrd. The script is only executed when SmartGatewayUseCount
+# is set to a value larger than 1. The script must setup policy routing
+# rules such that multi-gateway mode works. A sample script is included.
+# (default is not set)
+
+# SmartGatewayPolicyRoutingScript ""
+
 # Determines the egress interfaces that are part of the multi-gateway setup and
 # therefore only relevant when SmartGatewayUseCount is larger than 1 (in which
 # case it must be explicitly set).
index 26c05d0..0b8ccf1 100644 (file)
 
 # SmartGatewayUseCount 1
 
+# Determines the policy routing script that is executed during startup and
+# shutdown of olsrd. The script is only executed when SmartGatewayUseCount
+# is set to a value larger than 1. The script must setup policy routing
+# rules such that multi-gateway mode works. A sample script is included.
+# (default is not set)
+
+# SmartGatewayPolicyRoutingScript ""
+
 # Determines the egress interfaces that are part of the multi-gateway setup and
 # therefore only relevant when SmartGatewayUseCount is larger than 1 (in which
 # case it must be explicitly set).
diff --git a/files/sgw_policy_routing_setup.sh b/files/sgw_policy_routing_setup.sh
new file mode 100755 (executable)
index 0000000..5bd5b65
--- /dev/null
@@ -0,0 +1,174 @@
+#!/bin/sh
+
+set -e
+set -u
+
+###############################################################################
+#
+# SETTINGS
+#
+###############################################################################
+
+declare IPVERSION_4="ipv4"
+declare IPVERSION_6="ipv6"
+
+declare MODE_GENERIC="generic"
+declare MODE_OLSRIF="olsrif"
+declare MODE_SGWSRVTUN="sgwsrvtun"
+declare MODE_EGRESSIF="egressif"
+declare MODE_SGWTUN="sgwtun"
+
+declare ADDMODE_ADD="add"
+declare ADDMODE_DEL="del"
+
+
+###############################################################################
+#
+# HELPER FUNCTIONS
+#
+###############################################################################
+
+function usage() {
+  echo ""
+  echo "The script was called as:"
+  echo "  ${script} ${arguments[@]:-}"
+  echo ""
+  echo "Usage:"
+  echo "  ${scriptBasename} ipVersion mode addMode [ifname [ifmark]]"
+  echo "    - ipVersion: ${IPVERSION_4} or ${IPVERSION_6}"
+  echo "    - mode     : ${MODE_GENERIC}, ${MODE_OLSRIF}, ${MODE_SGWSRVTUN}, ${MODE_EGRESSIF} or ${MODE_SGWTUN}"
+  echo "    - addMode  : ${ADDMODE_ADD} or ${ADDMODE_DEL}"
+  echo "    - ifname   : an interface name, not relevant for generic mode"
+  echo "    - ifmark   : an interface marking (number), only relevant for ${MODE_EGRESSIF} and ${MODE_SGWTUN} modes"
+}
+
+function error() {
+local -i firstLine=1
+  while [ ${#} -gt 0 ]; do
+    if [ ${firstLine} -eq 1 ]; then
+      echo "Error: ${1}"
+    else
+      echo "       ${1}"
+    fi
+    firstLine=0
+    shift 1
+  done
+}
+
+
+###############################################################################
+#
+# MODE FUNCTIONS
+#
+###############################################################################
+
+function generic() {
+  "${IPTABLES}" ${IPTABLES_ARGS} -t mangle "${ADDMODE_IPTABLES}" OUTPUT -j CONNMARK --restore-mark
+}
+
+function olsrif() {
+  "${IPTABLES}" ${IPTABLES_ARGS} -t mangle "${ADDMODE_IPTABLES}" PREROUTING -i "${1}" -j CONNMARK --restore-mark
+}
+
+function sgwsrvtun() {
+  "${IPTABLES}" ${IPTABLES_ARGS} -t mangle "${ADDMODE_IPTABLES}" PREROUTING -i "${1}" -j CONNMARK --restore-mark
+}
+
+function egressif() {
+  "${IPTABLES}" ${IPTABLES_ARGS} -t mangle "${ADDMODE_IPTABLES}" POSTROUTING -m conntrack --ctstate NEW -o "${1}" -j CONNMARK --set-mark "${2}"
+  "${IPTABLES}" ${IPTABLES_ARGS} -t mangle "${ADDMODE_IPTABLES}" INPUT       -m conntrack --ctstate NEW -i "${1}" -j CONNMARK --set-mark "${2}"
+  "${IP}" ${IP_ARGS} rule "${ADDMODE_IP}" fwmark "${2}" table "${2}" pref "${2}"
+}
+
+function sgwtun() {
+  "${IPTABLES}" ${IPTABLES_ARGS} -t mangle "${ADDMODE_IPTABLES}" POSTROUTING -m conntrack --ctstate NEW -o "${1}" -j CONNMARK --set-mark "${2}"
+  "${IP}" ${IP_ARGS} rule "${ADDMODE_IP}" fwmark "${2}" table "${2}" pref "${2}"
+}
+
+
+###############################################################################
+#
+# MAIN
+#
+###############################################################################
+
+declare script="${0}"
+declare scriptBasename="$(basename "${script}")"
+declare scriptDir="$(dirname "${script}")"
+declare -a arguments=( ${@} )
+declare -i argc=${#}
+
+# we always need 3 arguments, check it
+if [ ${argc} -lt 3 ]; then
+  error "Need at least 3 arguments"
+  usage
+  exit 1
+fi
+
+# get first 3 arguments
+declare ipVersion=${1}
+declare mode="${2}"
+declare addMode="${3}"
+shift 3
+argc=${#}
+
+# check IP version argument
+if [ ! "${ipVersion}" == "${IPVERSION_4}" ] && \
+   [ ! "${ipVersion}" == "${IPVERSION_6}" ]; then
+  error "Illegal IP version"
+  usage
+  exit 1
+fi
+
+# check mode argument
+if [ ! "${mode}" == "${MODE_GENERIC}" ] && \
+   [ ! "${mode}" == "${MODE_OLSRIF}" ] && \
+   [ ! "${mode}" == "${MODE_SGWSRVTUN}" ] && \
+   [ ! "${mode}" == "${MODE_EGRESSIF}" ] && \
+   [ ! "${mode}" == "${MODE_SGWTUN}" ]; then
+  error "Illegal mode"
+  usage
+  exit 1
+fi
+
+# check addMode argument
+if [ ! "${addMode}" == "${ADDMODE_ADD}" ] && \
+   [ ! "${addMode}" == "${ADDMODE_DEL}" ]; then
+  error "Illegal addMode"
+  usage
+  exit 1
+fi
+
+# check argument count for all modes
+if ([ "${mode}" == "${MODE_GENERIC}" ]   && [ ${argc} -ne 0 ]) || \
+   ([ "${mode}" == "${MODE_OLSRIF}" ]    && [ ${argc} -ne 1 ]) || \
+   ([ "${mode}" == "${MODE_SGWSRVTUN}" ] && [ ${argc} -ne 1 ]) || \
+   ([ "${mode}" == "${MODE_EGRESSIF}"  ] && [ ${argc} -ne 2 ]) || \
+   ([ "${mode}" == "${MODE_SGWTUN}"  ]   && [ ${argc} -ne 2 ]); then
+  error "Not enough arguments or too many arguments"
+  usage
+  exit 1
+fi
+
+# process ipVersion argument
+declare IPTABLES="iptables"
+declare IPTABLES_ARGS=""
+declare IP="ip"
+declare IP_ARGS="-4"
+if [ "${ipVersion}" == "${IPVERSION_6}" ]; then
+  IPTABLES="ip6tables"
+  IPTABLES_ARGS=""
+  IP="ip"
+  IP_ARGS="-6"
+fi
+
+# process addMode argument
+declare ADDMODE_IPTABLES="-I"
+declare ADDMODE_IP="add"
+if [ "${addMode}" == "${ADDMODE_DEL}" ]; then
+  ADDMODE_IPTABLES="-D"
+  ADDMODE_IP="del"
+fi
+
+# call the mode
+"${mode}" "${@}"
index b5b9f4c..ff264ab 100644 (file)
@@ -987,6 +987,7 @@ ipc_print_config(struct autobuf *abuf)
   abuf_json_boolean(abuf, "smartGateway", olsr_cnf->smart_gw_active);
   if (olsr_cnf->smart_gw_active) {
     abuf_json_int(abuf, "smartGatewayUseCount", olsr_cnf->smart_gw_use_count);
+    abuf_json_string(abuf, "smartGatewayPolicyRoutingScript", olsr_cnf->smart_gw_policyrouting_script);
     {
       struct autobuf egressbuf;
       struct sgw_egress_if * egressif = olsr_cnf->smart_gw_egress_interfaces;
index 88e8bce..803ce6f 100644 (file)
@@ -448,6 +448,17 @@ void olsrd_write_cnf_autobuf(struct autobuf *out, struct olsrd_config *cnf) {
       cnf->smart_gw_use_count);
   abuf_puts(out,
     "\n"
+    "# Determines the policy routing script that is executed during startup and\n"
+    "# shutdown of olsrd. The script is only executed when SmartGatewayUseCount\n"
+    "# is set to a value larger than 1. The script must setup policy routing\n"
+    "# rules such that multi-gateway mode works. A sample script is included.\n"
+    "# (default is not set)\n"
+    "\n");
+  abuf_appendf(out, "%sSmartGatewayPolicyRoutingScript %s\n",
+      !cnf->smart_gw_policyrouting_script ? "# " : "",
+      !cnf->smart_gw_policyrouting_script ? "" : cnf->smart_gw_policyrouting_script);
+  abuf_puts(out,
+    "\n"
     "# Determines the egress interfaces that are part of the multi-gateway setup and\n"
     "# therefore only relevant when SmartGatewayUseCount is larger than 1 (in which\n"
     "# case it must be explicitly set).\n"
index 8b2d3ec..5272ba8 100644 (file)
@@ -59,6 +59,7 @@
 #include <linux/types.h>
 #include <linux/rtnetlink.h>
 #include <linux/version.h>
+#include <sys/stat.h>
 #endif /* __linux__ */
 
 extern FILE *yyin;
@@ -563,6 +564,36 @@ olsrd_sanity_check_cnf(struct olsrd_config *cnf)
   if (cnf->smart_gw_use_count > 1) {
     struct sgw_egress_if * sgwegressif = cnf->smart_gw_egress_interfaces;
 
+    if (!cnf->smart_gw_policyrouting_script) {
+      fprintf(stderr, "Error, no policy routing script configured in multi-gateway mode\n");
+      return -1;
+    }
+
+    {
+      struct stat statbuf;
+
+      int r = stat(cnf->smart_gw_policyrouting_script, &statbuf);
+      if (r) {
+        fprintf(stderr, "Error, policy routing script not found: %s\n", strerror(errno));
+        return -1;
+      }
+
+      if (!S_ISREG(statbuf.st_mode)) {
+        fprintf(stderr, "Error, policy routing script not a regular file\n");
+        return -1;
+      }
+
+      if (statbuf.st_uid) {
+        fprintf(stderr, "Error, policy routing script must be owned by root\n");
+        return -1;
+      }
+
+      if (statbuf.st_mode & S_IXUSR) {
+        fprintf(stderr, "Error, policy routing script is not executable\n");
+        return -1;
+      }
+    }
+
     /* egress interface(s) must be set */
     if (!sgwegressif) {
       fprintf(stderr, "Error, no egress interfaces configured in multi-gateway mode\n");
@@ -857,6 +888,7 @@ set_default_cnf(struct olsrd_config *cnf)
 
   cnf->smart_gw_active = DEF_SMART_GW;
   cnf->smart_gw_use_count = DEF_GW_USE_COUNT;
+  cnf->smart_gw_policyrouting_script = NULL;
   cnf->smart_gw_egress_interfaces = NULL;
   cnf->smart_gw_egress_interfaces_count = 0;
   cnf->smart_gw_mark_offset_egress = DEF_GW_MARK_OFFSET_EGRESS;
@@ -991,6 +1023,8 @@ olsrd_print_cnf(struct olsrd_config *cnf)
 
   printf("SmGw. Use Count  : %u\n", cnf->smart_gw_use_count);
 
+  printf("SmGw. Pol. Script: %s\n", cnf->smart_gw_policyrouting_script);
+
   printf("SmGw. Egress I/Fs:");
   {
     struct sgw_egress_if * sgwegressif = cnf->smart_gw_egress_interfaces;
index c637dc7..c396f39 100644 (file)
@@ -217,6 +217,7 @@ static int add_ipv6_addr(YYSTYPE ipaddr_arg, YYSTYPE prefixlen_arg)
 %token TOK_USE_NIIT
 %token TOK_SMART_GW
 %token TOK_SMART_GW_USE_COUNT
+%token TOK_SMART_GW_POLICYROUTING_SCRIPT
 %token TOK_SMART_GW_EGRESS_IFS
 %token TOK_SMART_GW_MARK_OFFSET_EGRESS
 %token TOK_SMART_GW_MARK_OFFSET_TUNNELS
@@ -308,6 +309,7 @@ stmt:       idebug
           | suse_niit
           | bsmart_gw
           | ismart_gw_use_count
+          | ssmart_gw_policyrouting_script
           | ismart_gw_mark_offset_egress
           | ismart_gw_mark_offset_tunnels
           | bsmart_gw_allow_nat
@@ -1321,6 +1323,14 @@ ismart_gw_use_count: TOK_SMART_GW_USE_COUNT TOK_INTEGER
 }
 ;
 
+ssmart_gw_policyrouting_script: TOK_SMART_GW_POLICYROUTING_SCRIPT TOK_STRING
+{
+  PARSER_DEBUG_PRINTF("Smart gateway policy routing script: %s\n", $2->string);
+  olsr_cnf->smart_gw_policyrouting_script = $2->string;
+  free($2);
+}
+;
+
 ssgw_egress_ifs:   TOK_SMART_GW_EGRESS_IFS sgw_egress_ifs
 ;
 
index a86c161..1f88680 100644 (file)
@@ -471,6 +471,11 @@ IPV6ADDR {IPV6PAT1}|{IPV6PAT2}|{IPV6PAT3}|{IPV6PAT4}|{IPV6PAT5}|{IPV6PAT6}|{IPV6
     return TOK_SMART_GW_USE_COUNT;
 }
 
+"SmartGatewayPolicyRoutingScript" {
+    yylval = NULL;
+    return TOK_SMART_GW_POLICYROUTING_SCRIPT;
+}
+
 "SmartGatewayEgressInterfaces" {
     yylval = NULL;
     return TOK_SMART_GW_EGRESS_IFS;
index e6f6a49..7fb95fa 100644 (file)
@@ -291,6 +291,7 @@ struct olsrd_config {
 
   bool smart_gw_active, smart_gw_allow_nat, smart_gw_uplink_nat;
   uint8_t smart_gw_use_count;
+  char *smart_gw_policyrouting_script;
   struct sgw_egress_if * smart_gw_egress_interfaces;
   uint8_t smart_gw_egress_interfaces_count;
   uint8_t smart_gw_mark_offset_egress;