}
function routing_default_update() {
- local zone
local routes
+ local zones=$(zones_get_nonlocal)
+ if [ -z "${zones}" ]; then
+ zones=$(zones_get_local)
+ fi
+
local gateway
+ local proto
local weight
+ local zone
+ local cmd
+
+ for proto in ${IP_SUPPORTED_PROTOCOLS}; do
+ # Clear routes
+ routes=""
+
+ cmd="ip $([ "${proto}" = "ipv6" ] && echo "-6") route"
+
+ for zone in ${zones}; do
+ # Skip if zone is not up
+ routing_db_exists ${zone} ${proto} || continue
+
+ if [ "$(routing_db_get ${zone} ${proto} active)" = "1" ]; then
+ gateway=$(routing_db_get ${zone} ${proto} remote-ip-address)
- log INFO "Updating default route."
+ # Go on if the device is not there anymore.
+ device_exists ${zone} || continue
- for zone in $(zones_get_nonlocal); do
- # Skip if zone is not up
- red_db_exists ${zone} || continue
+ # On other devices, we will use the gateway if we got one.
+ if isset gateway; then
+ routes="${routes} nexthop via ${gateway}"
- if [ "$(red_db_get ${zone} active)" = "1" ]; then
- gateway=$(red_db_get ${zone} remote-ip-address)
- weight=$(red_db_get ${zone} weight)
+ # If we have got a Point-to-Point device, we will directly send all
+ # packets into the pipe.
+ elif device_is_ptp ${zone}; then
+ routes="${routes} dev ${zone}"
- routes="${routes} nexthop via ${gateway}"
-
- if [ -n "${weight}" ]; then
- routes="${routes} weight ${weight}"
+ # If none of the cases above apply, we cannot go on.
+ else
+ continue
+ fi
+
+ # Apply weight.
+ weight=$(routing_db_get ${zone} ${proto} weight)
+ if isinteger ${weight}; then
+ routes="${routes} weight ${weight}"
+ fi
+ else
+ log DEBUG "Ignoring zone '${zone}' which is not active."
fi
- else
- log DEBUG "Ignoring zone '${zone}' which is not active."
- fi
- done
+ done
+
+ # Remove too much spaces.
+ routes=$(echo ${routes})
- if [ -z "${routes}" ]; then
- if routing_has_default; then
- ip route del default
+ # Remove all default routes.
+ while ${cmd} | grep -q "^default"; do
+ ${cmd} del default
+ done
+
+ if [ -z "${routes}" ]; then
+ log INFO "Removed default route for ${proto}."
+ return ${EXIT_OK}
fi
- return ${EXIT_OK}
- fi
- ip route replace default ${routes}
+ log INFO "Setting default route for ${proto}: ${routes}"
+
+ cmd ${cmd} add default ${routes}
+ assert [ $? -eq 0 ]
+
+ case "${proto}" in
+ ipv6)
+ # Apply radvd configuration.
+ radvd_update
+ ;;
+ esac
+ done
}
+# XXX deprecated function
function routing_table_exists() {
+ route_table_exists $@
+}
+
+# XXX deprecated function
+function routing_table_create() {
+ route_table_create $@
+}
+
+function routing_db_path() {
local zone=${1}
+ local proto=${2}
+
+ assert isset zone
+ assert isset proto
+ assert isoneof proto ${IP_SUPPORTED_PROTOCOLS}
- grep -q "${zone}$" < /etc/iproute2/rt_tables
+ echo "${ROUTING_DB_DIR}/${zone}/${proto}"
}
-function routing_table_create() {
+function routing_db_exists() {
+ [ -d "$(routing_db_path $@)" ]
+}
+
+function routing_db_create() {
+ routing_db_exists $@ && return ${EXIT_OK}
+
+ mkdir -p $(routing_db_path $@)
+}
+
+function routing_db_remove() {
+ rm -rf $(routing_db_path $@)
+}
+
+function routing_db_set() {
+ local zone=${1}
+ local proto=${2}
+ local parameter=${3}
+ shift 3
+
+ local value="$@"
+
+ log INFO "Updating database (${zone} - ${proto}): ${parameter} = ${value}"
+
+ routing_db_create ${zone} ${proto}
+
+ echo "${value}" > $(routing_db_path ${zone} ${proto})/${parameter}
+}
+
+function routing_db_get() {
+ local zone=${1}
+ local proto=${2}
+ local parameter=${3}
+ shift 3
+
+ cat $(routing_db_path ${zone} ${proto})/${parameter} 2>/dev/null
+}
+
+function routing_db_from_ppp() {
+ local zone=${1}
+ local proto=${2}
+
+ assert isset zone
+ assert isset proto
+
+ # Save ppp configuration
+ routing_db_set ${zone} ${proto} type "ppp"
+
+ if [ "${proto}" = "ipv6" ]; then
+ routing_db_set ${zone} ${proto} local-ip-address ${PPP_LLLOCAL}
+ routing_db_set ${zone} ${proto} remote-ip-address ${PPP_LLREMOTE}
+ elif [ "${proto}" = "ipv4" ]; then
+ routing_db_set ${zone} ${proto} local-ip-address ${PPP_IPLOCAL}
+ routing_db_set ${zone} ${proto} remote-ip-address ${PPP_IPREMOTE}
+ fi
+
+ routing_db_set ${zone} ${proto} dns ${PPP_DNS1} ${PPP_DNS2}
+
+ routing_db_set ${zone} ${proto} remote-address ${PPP_MACREMOTE,,}
+}
+
+function routing_update() {
local zone=${1}
+ assert isset zone
- if ! zone_is_nonlocal ${zone}; then
- error_log "Can only create routing tables for non-local zones."
- return ${EXIT_ERROR}
+ # Nothing to do for local zones.
+ if zone_is_local ${zone}; then
+ return ${EXIT_OK}
fi
- if routing_table_exists ${zone}; then
+ local proto=${2}
+ local table=${zone}
+ assert isset proto
+
+ local ip_cmd="ip"
+ if [ "${proto}" = "ipv6" ]; then
+ ip_cmd="${ip_cmd} -6"
+ fi
+
+ # Create routing table if not exists
+ routing_table_create ${table}
+
+ log DEBUG "Flushing routing table ${table}"
+ cmd ${ip_cmd} route flush table ${table}
+
+ # Exit here if there is no routing information.
+ if ! routing_db_exists ${zone} ${proto}; then
return ${EXIT_OK}
fi
- log INFO "Creating routing table for zone '${zone}'"
+ local local_ip_address=$(routing_db_get ${zone} ${proto} local-ip-address)
+ local remote_ip_address=$(routing_db_get ${zone} ${proto} remote-ip-address)
- local id=$(( ${zone#red} + 1 ))
+ case "${proto}" in
+ ipv4)
+ local net_address=$(ipv4_get_netaddress ${local_ip_address})
- echo "${id} ${zone}" >> /etc/iproute2/rt_tables
-}
+ log DEBUG "Adding route for subnet ${local_ip_address} to table ${table}"
+ cmd ${ip_cmd} route add table ${table} ${net_address} dev ${zone}
+ ;;
+ esac
+
+ log DEBUG "Adding default route for table ${table}"
+ local routing_cmd="${ip_cmd} route add table ${table} default"
+ if isset remote_ip_address; then
+ routing_cmd="${routing_cmd} via ${remote_ip_address}"
+ else
+ routing_cmd="${routing_cmd} dev ${zone}"
+ fi
+ cmd ${routing_cmd}
-function routing_table_remove() {
- : # XXX do we need this?
+ cmd ${ip_cmd} rule add from ${local_ip_address} lookup ${table}
}