2 ###############################################################################
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2012 IPFire Network Development Team #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
20 ###############################################################################
22 # Functions for static routing.
26 # Apply configured static routes.
30 init_register route_init
33 local ${NETWORK_CONFIG_ROUTES_PARAMS}
35 while [ $# -gt 0 ]; do
38 gateway
=$
(cli_get_val
${1})
50 mtu
=$
(cli_get_val
${1})
53 if isset network
; then
54 error
"Bad number of arguments. Network passed twice or more"
66 if ! ip_is_network
${network} && ! ip_is_valid
${network}; then
67 error
"The given network is invalid: ${network}"
71 if route_find_duplicate
${network}; then
72 error
"A route to ${network} does already exist."
76 # Check if gateway and unreachable are both enabled.
77 if isset gateway
; then
78 if enabled unreachable
; then
79 error
"You cannot use both, --gateway=${gateway} and --unreachable at the same time."
83 if enabled prohibit
; then
84 error
"You cannot use both, --gateway=${gateway} and --prohibit at the same time."
88 if enabled blackhole
; then
89 error
"You cannot use both, --gateway=${gateway} and --blackhole at the same time."
93 # Check if network and gateway IP protocol version match.
94 if ! ip_is_valid
${gateway}; then
95 error
"--gateway= is not a valid IP address."
99 # Check if the gateway is part of the statically routed network
100 if ip_network_is_subset_of
${gateway} ${network}; then
101 error
"The gateway is in the routed network"
105 local network_proto
=$
(ip_detect_protocol
${network})
106 assert isset network_proto
108 local gateway_proto
=$
(ip_detect_protocol
${gateway})
109 assert isset gateway_proto
111 if [ "${network_proto}" != "${gateway_proto}" ]; then
112 error
"The IP protocol version of the given network and gateway did not match."
117 local counter
=$
(list_count true
${unreachable} ${prohibit} ${blackhole})
118 if [ ${counter} -gt 1 ]; then
119 error
"You can only use one of --unreachable, --prohibit or --blackhole."
124 if isset mtu
&& ! isinteger mtu
; then
125 error
"MTU must be an integer number: ${mtu}"
130 list_append line
"network=\"${network}\""
132 # Add gateway to configuration entry when it is set.
133 if isset gateway
; then
134 list_append line
"gateway=\"${gateway}\""
137 # Add unreachable to configuration entry when it is set.
139 for arg
in unreachable prohibit blackhole
; do
140 if enabled
${arg}; then
141 list_append line
"${arg}=\"true\""
148 list_append line
"mtu=\"${mtu}\""
151 # Write line to file.
152 print
"${line}" >> ${NETWORK_CONFIG_ROUTES}
154 log INFO
"New route to network '${network}' has been added."
160 local error
=${EXIT_OK}
162 for _network
in $@
; do
164 if ! ip_is_network
${_network} && ! ip_is_valid
${_network}; then
165 error
"Invalid IP address or network: ${_network}"
172 local ${NETWORK_CONFIG_ROUTES_PARAMS}
175 route_parse_line
${line}
176 [ $?
-eq ${EXIT_OK} ] ||
continue
178 # Skip the rule, we want to delete.
179 if [ "${network}" = "${_network}" ]; then
185 done < ${NETWORK_CONFIG_ROUTES} > ${NETWORK_CONFIG_ROUTES}.tmp
186 mv ${NETWORK_CONFIG_ROUTES}{.tmp
,}
188 if enabled found
; then
189 log INFO
"Route to network '${_network}' has been removed."
191 error
"No route to network '${_network}' was found."
202 while [ $# -gt 0 ]; do
205 protocol
=$
(cli_get_val
${1})
208 warning
"Unrecognized argument: ${1}"
214 if [ ! -r "${NETWORK_CONFIG_ROUTES}" ]; then
215 print
"No static routes defined."
219 local format
="%-40s %-20s %-4s"
220 print
"${format}" "NETWORK/HOST" "GATEWAY" "MTU"
222 local ${NETWORK_CONFIG_ROUTES_PARAMS}
225 route_parse_line
${line}
226 [ $?
-eq ${EXIT_OK} ] ||
continue
229 for arg
in unreachable prohibit blackhole
; do
230 if enabled
${arg}; then
236 # Filter all entries with a wrong protocol.
237 if isset protocol
; then
238 local proto
=$
(ip_detect_protocol
${network})
239 [ "${protocol}" = "${proto}" ] ||
continue
242 # Print something when no MTU was set.
247 print
"${format}" "${network}" "${gateway}" "${mtu}"
248 done < ${NETWORK_CONFIG_ROUTES}
251 route_find_duplicate
() {
254 [ -r "${NETWORK_CONFIG_ROUTES}" ] ||
return ${EXIT_FALSE}
256 local ${NETWORK_CONFIG_ROUTES_PARAMS}
259 route_parse_line
${line}
260 [ $?
-eq ${EXIT_OK} ] ||
continue
262 # Check if the network is already in use.
263 [ "${network}" = "${_network}" ] && return ${EXIT_TRUE}
264 done < ${NETWORK_CONFIG_ROUTES}
272 # Reset all possible settings.
273 for arg in ${NETWORK_CONFIG_ROUTES_PARAMS}; do
274 printf -v ${arg} "%s
" ""
280 network=$(cli_get_val ${arg})
283 gateway=$(cli_get_val ${arg})
286 unreachable=$(cli_get_val ${arg})
289 prohibit=$(cli_get_val ${arg})
292 blackhole=$(cli_get_val ${arg})
295 mtu=$(cli_get_val ${arg})
298 done <<< "$
(args $@
)"
300 ### Check if all values are correctly set.
302 # network must be set.
303 isset network || return ${EXIT_ERROR}
305 # Is network or IP valid?
306 if ! ip_is_network ${network} && ! ip_is_valid ${network}; then
307 error "The given network is invalid
: ${network}"
311 # Check gateway settings.
312 if isset gateway; then
313 # When gateway is set, unreachable cannot be set.
314 isset unreachable && return ${EXIT_ERROR}
316 # Must be a valid IP address.
317 ip_is_valid ${gateway} || return ${EXIT_ERROR}
319 # Check if the gateway is part of the statically routed network
320 if ip_network_is_subset_of ${gateway} ${network}; then
324 # Check if exactly one of unreachable, prohibit or blackhole is set.
325 local counter=$(list_count true ${unreachable} ${prohibit} ${blackhole})
326 [ ${counter} -eq 1 ] || return ${EXIT_ERROR}
329 # mtu must be an integer number.
331 isinteger mtu || return ${EXIT_ERROR}
341 log DEBUG "Applying static routes...
"
343 # Flush the routing table.
344 route_table_flush ${table}
346 local ${NETWORK_CONFIG_ROUTES_PARAMS}
349 route_parse_line ${line}
350 [ $? -eq ${EXIT_OK} ] || continue
354 for arg in unreachable prohibit blackhole; do
355 if enabled ${arg}; then
362 route_entry_add ${network} --table="static
" --proto="static
" \
363 --type="${type}" --gateway="${gateway}" --mtu="${mtu}"
366 if [ ${ret} -ne ${EXIT_OK} ]; then
367 log WARNING "Could not
set route
'${network}'.
"
369 done < ${NETWORK_CONFIG_ROUTES}
371 # Create a lookup rule for the static routing table.
372 route_rule_add --lookup="static
" --priority=1000
385 while [ $# -gt 0 ]; do
388 gateway=$(cli_get_val ${1})
391 table=$(cli_get_val ${1})
394 type=$(cli_get_val ${1})
397 proto=$(cli_get_val ${1})
400 mtu=$(cli_get_val ${1})
403 if isset network; then
404 warning "Unrecognized argument
: ${1}"
414 assert isoneof type unicast broadcast unreachable prohibit blackhole
418 if ! ip_is_network ${network} && ! ip_is_valid ${network}; then
419 error "The given network is invalid
: ${network}"
427 # Detect the protocol of the given network.
428 local protocol=$(ip_detect_protocol ${network})
430 case "${protocol}" in
432 command="ip
-6 route add
"
435 command="ip route add
"
438 log ERROR "Could not detect protocol
for ${network}"
444 list_append command "${type}"
446 # Add network/prefix.
447 list_append command "${network}"
449 if [ "${type}" = "unicast
" ]; then
451 assert ip_is_valid ${gateway}
453 list_append command "via
${gateway}"
456 # Add table (if any).
458 # Create routing table, if it does not exist, yet.
459 route_table_create ${table}
461 list_append command "table
${table}"
466 list_append command "proto
${proto}"
471 list_append command "mtu
${mtu}"
477 route_table_create() {
481 if route_table_exists ${table}; then
485 # Get the next free id.
486 local id=$(_route_table_next_id)
489 # Write everything to file.
490 print "%d
\t%s
" "${id}" "${table}" >> /etc/iproute2/rt_tables
492 log DEBUG "Created routing table
'${table}'.
"
497 _route_table_next_id() {
498 # The Linux kernel is able to manage 255 routing tables (1-255).
499 # This function returns the next free id, starting from 255.
502 for next_id in {255..1}; do
503 if ! route_table_exists --id="${next_id}"; then
512 route_table_flush() {
516 while [ $# -gt 0 ]; do
519 protocol=$(cli_get_val ${1})
528 # If the table does not exists, there is nothing to
530 route_table_exists ${table} || return ${EXIT_OK}
534 for proto in ${IP_SUPPORTED_PROTOCOLS}; do
535 # Skip unwanted protocols.
536 if isset protocol; then
537 [ "${protocol}" = "${proto}" ] || continue
543 command="ip
-6 route flush
"
546 command="ip route flush
"
551 list_append command "table
${table}"
560 route_table_exists() {
563 while [ $# -gt 0 ]; do
566 _id=$(cli_get_val ${1})
577 while read -r id table; do
579 [ "${id:0:1}" = "#" ] && continue
581 if [ "${_table}" = "${table}" ] || [ "${_id}" = "${id}" ]; then
585 done < /etc
/iproute
2/rt_tables
592 local protocols
=${IP_SUPPORTED_PROTOCOLS}
595 while [ $# -gt 0 ]; do
598 lookup
=$
(cli_get_val
${1})
601 priority
=$
(cli_get_val
${1})
604 protocols
=$
(cli_get_val
${1})
606 assert isoneof protocols
${IP_SUPPORTED_PROTOCOLS}
609 warning
"Unhandled argument: ${1}"
615 local command options
617 if isset lookup
; then
618 route_table_create
${lookup}
620 list_append options
"lookup ${lookup}"
623 if isset priority
; then
624 assert isinteger priority
626 list_append options
"prio ${priority}"
630 for proto
in ${protocols}; do
634 command="ip -6 rule add ${options}"
637 command="ip rule add ${options}"
642 # Skip, if the rule does already exist.
644 --protocol=${proto} \
646 --priority=${priority} \
653 route_rule_exists
() {
659 while [ $# -gt 0 ]; do
662 from
=$
(cli_get_val
${1})
665 lookup
=$
(cli_get_val
${1})
668 prio
=$
(cli_get_val
${1})
671 proto
=$
(cli_get_val
${1})
674 warning
"Unrecognized argument: ${1}"
683 command="ip -6 rule show"
686 command="ip rule show"
691 local _lookup _from _prio
693 while read -r line
; do
694 _route_rule_exists_parse
${line}
697 [ "${from}" = "${_from}" ] ||
continue
701 [ "${prio}" = "${_prio}" ] ||
continue
704 if isset lookup
; then
705 [ "${lookup}" = "${_lookup}" ] ||
continue
709 done <<< "$(${command})"
714 _route_rule_exists_parse
() {
715 # Reset all variables.
720 while [ $# -gt 0 ]; do
735 # Skip unknown arguments.