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.
25 function route_init
() {
26 # Apply configured static routes.
30 init_register route_init
32 function route_add
() {
33 local ${NETWORK_CONFIG_ROUTES_PARAMS}
35 while [ $# -gt 0 ]; do
38 gateway
=$
(cli_get_val
${1})
52 if ! ip_is_valid
${network}; then
53 error
"The given network is invalid: ${network}"
57 if route_find_duplicate
${network}; then
58 error
"A route to ${network} does already exist."
62 # Check if gateway and unreachable are both enabled.
63 if isset gateway
&& enabled unreachable
; then
64 error
"You cannot use both, --gateway=${gateway} and --unreachable at the same time."
68 # Check if network and gateway IP protocol version match.
69 if isset gateway
; then
70 if ! ip_is_valid
${gateway}; then
71 error
"--gateway= is not a valid IP address."
75 local network_proto
=$
(ip_detect_protocol
${network})
76 local gateway_proto
=$
(ip_detect_protocol
${gateway})
78 if [ "${network_proto}" != "${gateway_proto}" ]; then
79 error
"The IP protocol version of the given network and gateway did not match."
85 list_append line
"network=\"${network}\""
87 # Add gateway to configuration entry when it is set.
88 if isset gateway
; then
89 list_append line
"gateway=\"${gateway}\""
92 # Add unreachable to configuration entry when it is set.
93 if enabled unreachable
; then
94 list_append line
"unreachable=\"true\""
98 print
"${line}" >> ${NETWORK_CONFIG_ROUTES}
100 log INFO
"New route to network '${network}' has been added."
104 function route_remove
() {
106 assert isset _network
110 local ${NETWORK_CONFIG_ROUTES_PARAMS}
113 route_parse_line
${line}
114 [ $?
-eq ${EXIT_OK} ] ||
continue
116 # Skip the rule, we want to delete.
117 if [ "${network}" = "${_network}" ]; then
123 done < ${NETWORK_CONFIG_ROUTES} > ${NETWORK_CONFIG_ROUTES}.tmp
124 mv ${NETWORK_CONFIG_ROUTES}{.tmp
,}
126 if enabled found
; then
127 log INFO
"Route to network '${_network}' has been removed."
129 error
"No route to network '${_network}' was found."
136 function route_list
() {
139 while [ $# -gt 0 ]; do
142 protocol
=$
(cli_get_val
${1})
145 warning
"Unrecognized argument: ${1}"
151 if [ ! -r "${NETWORK_CONFIG_ROUTES}" ]; then
152 print
"No static routes defined."
156 local format
="%-40s %-20s"
157 print
"${format}" "NETWORK/HOST" "GATEWAY"
159 local ${NETWORK_CONFIG_ROUTES_PARAMS}
162 route_parse_line
${line}
163 [ $?
-eq ${EXIT_OK} ] ||
continue
165 if enabled unreachable
; then
166 gateway
="<unreachable>"
169 # Filter all entries with a wrong protocol.
170 if isset protocol
; then
171 local proto
=$
(ip_detect_protocol
${network})
172 [ "${protocol}" = "${proto}" ] ||
continue
175 print
"${format}" "${network}" "${gateway}"
176 done < ${NETWORK_CONFIG_ROUTES}
179 function route_find_duplicate
() {
182 [ -r "${NETWORK_CONFIG_ROUTES}" ] ||
return ${EXIT_FALSE}
184 local ${NETWORK_CONFIG_ROUTES_PARAMS}
187 route_parse_line
${line}
188 [ $?
-eq ${EXIT_OK} ] ||
continue
190 # Check if the network is already in use.
191 [ "${network}" = "${_network}" ] && return ${EXIT_TRUE}
192 done < ${NETWORK_CONFIG_ROUTES}
197 function route_parse_line() {
200 # Reset all possible settings.
201 for arg in ${NETWORK_CONFIG_ROUTES_PARAMS}; do
202 printf -v ${arg} "%s
" ""
208 network=$(cli_get_val ${arg})
211 gateway=$(cli_get_val ${arg})
214 unreachable=$(cli_get_val ${arg})
217 done <<< "$
(args $@
)"
219 ### Check if all values are correctly set.
221 # network must be set.
222 isset network || return ${EXIT_ERROR}
224 # network must be a valid.
225 ip_is_network ${network} || return ${EXIT_ERROR}
227 # Check gateway settings.
228 if isset gateway; then
229 # When gateway is set, unreachable cannot be set.
230 isset unreachable && return ${EXIT_ERROR}
232 # Must be a valid IP address.
233 ip_is_valid ${gateway} || return ${EXIT_ERROR}
235 # Either gateway or unreachable must be set.
236 isset unreachable || return ${EXIT_ERROR}
242 function route_apply() {
246 # Flush the routing table.
247 route_table_flush ${table}
249 local ${NETWORK_CONFIG_ROUTES_PARAMS}
252 route_parse_line ${line}
253 [ $? -eq ${EXIT_OK} ] || continue
256 if enabled unreachable; then
261 route_entry_add ${network} --table="static
" --proto="static
" \
262 --type="${type}" --gateway="${gateway}"
265 if [ ${ret} -ne ${EXIT_OK} ]; then
266 log WARNING "Could not
set route
'${network}'.
"
268 done < ${NETWORK_CONFIG_ROUTES}
270 # Create a lookup rule for the static routing table.
271 route_rule_add --lookup="static
" --priority=1000
274 function route_entry_add() {
283 while [ $# -gt 0 ]; do
286 gateway=$(cli_get_val ${1})
289 table=$(cli_get_val ${1})
292 type=$(cli_get_val ${1})
295 proto=$(cli_get_val ${1})
298 if isset network; then
299 warning "Unrecognized argument
: ${1}"
309 assert isoneof type unicast broadcast unreachable prohibit blackhole
310 assert ip_is_network ${network}
312 # Detect the protocol of the given network.
313 local protocol=$(ip_detect_protocol ${network})
314 case "${protocol}" in
316 command="ip
-6 route add
"
319 command="ip route add
"
325 list_append command "${type}"
327 # Add network/prefix.
328 list_append command "${network}"
330 if [ "${type}" = "unicast
" ]; then
332 assert ip_is_valid ${gateway}
334 list_append command "via
${gateway}"
337 # Add table (if any).
339 # Create routing table, if it does not exist, yet.
340 route_table_create ${table}
342 list_append command "table
${table}"
347 list_append command "proto
${proto}"
353 function route_table_create() {
357 if route_table_exists ${table}; then
361 # Get the next free id.
362 local id=$(_route_table_next_id)
365 # Write everything to file.
366 print "%d
\t%s
" "${id}" "${table}" >> /etc/iproute2/rt_tables
368 log DEBUG "Created routing table
'${table}'.
"
373 function _route_table_next_id() {
374 # The Linux kernel is able to manage 255 routing tables (1-255).
375 # This function returns the next free id, starting from 255.
378 for next_id in {255..1}; do
379 if ! route_table_exists --id="${next_id}"; then
388 function route_table_flush() {
392 while [ $# -gt 0 ]; do
395 protocol=$(cli_get_val ${1})
404 # If the table does not exists, there is nothing to
406 route_table_exists ${table} || return ${EXIT_OK}
410 for proto in ${IP_SUPPORTED_PROTOCOLS}; do
411 # Skip unwanted protocols.
412 if isset protocol; then
413 [ "${protocol}" = "${proto}" ] || continue
419 command="ip
-6 route flush
"
422 command="ip route flush
"
427 list_append command "table
${table}"
436 function route_table_exists() {
439 while [ $# -gt 0 ]; do
442 _id=$(cli_get_val ${1})
453 while read -r id table; do
455 [ "${id:0:1}" = "#" ] && continue
457 if [ "${_table}" = "${table}" ] || [ "${_id}" = "${id}" ]; then
461 done < /etc
/iproute
2/rt_tables
466 function route_rule_add
() {
468 local protocols
=${IP_SUPPORTED_PROTOCOLS}
471 while [ $# -gt 0 ]; do
474 lookup
=$
(cli_get_val
${1})
477 priority
=$
(cli_get_val
${1})
480 protocols
=$
(cli_get_val
${1})
482 assert isoneof protocols
${IP_SUPPORTED_PROTOCOLS}
485 warning
"Unhandled argument: ${1}"
491 local command options
493 if isset lookup
; then
494 route_table_create
${lookup}
496 list_append options
"lookup ${lookup}"
499 if isset priority
; then
500 assert isinteger priority
502 list_append options
"prio ${priority}"
506 for proto
in ${protocols}; do
510 command="ip -6 rule add ${options}"
513 command="ip rule add ${options}"
518 # Skip, if the rule does already exist.
520 --protocol=${proto} \
522 --priority=${priority} \
529 function route_rule_exists
() {
535 while [ $# -gt 0 ]; do
538 from
=$
(cli_get_val
${1})
541 lookup
=$
(cli_get_val
${1})
544 prio
=$
(cli_get_val
${1})
547 proto
=$
(cli_get_val
${1})
550 warning
"Unrecognized argument: ${1}"
559 command="ip -6 rule show"
562 command="ip rule show"
567 local _lookup _from _prio
569 while read -r line
; do
570 _route_rule_exists_parse
${line}
573 [ "${from}" = "${_from}" ] ||
continue
577 [ "${prio}" = "${_prio}" ] ||
continue
580 if isset lookup
; then
581 [ "${lookup}" = "${_lookup}" ] ||
continue
585 done <<< "$(${command})"
590 function _route_rule_exists_parse
() {
591 # Reset all variables.
596 while [ $# -gt 0 ]; do
611 # Skip unknown arguments.