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})
50 mtu
=$
(cli_get_val
${1})
61 if ! ip_is_valid
${network}; then
62 error
"The given network is invalid: ${network}"
66 if route_find_duplicate
${network}; then
67 error
"A route to ${network} does already exist."
71 # Check if gateway and unreachable are both enabled.
72 if isset gateway
; then
73 if enabled unreachable
; then
74 error
"You cannot use both, --gateway=${gateway} and --unreachable at the same time."
78 if enabled prohibit
; then
79 error
"You cannot use both, --gateway=${gateway} and --prohibit at the same time."
83 if enabled blackhole
; then
84 error
"You cannot use both, --gateway=${gateway} and --blackhole at the same time."
88 # Check if network and gateway IP protocol version match.
89 if ! ip_is_valid
${gateway}; then
90 error
"--gateway= is not a valid IP address."
94 local network_proto
=$
(ip_detect_protocol
${network})
95 local gateway_proto
=$
(ip_detect_protocol
${gateway})
97 if [ "${network_proto}" != "${gateway_proto}" ]; then
98 error
"The IP protocol version of the given network and gateway did not match."
103 local counter
=$
(list_count true
${unreachable} ${prohibit} ${blackhole})
104 if [ ${counter} -gt 1 ]; then
105 error
"You can only use one of --unreachable, --prohibit or --blackhole."
110 if isset mtu
&& ! isinteger mtu
; then
111 error
"MTU must be an integer number: ${mtu}"
116 list_append line
"network=\"${network}\""
118 # Add gateway to configuration entry when it is set.
119 if isset gateway
; then
120 list_append line
"gateway=\"${gateway}\""
123 # Add unreachable to configuration entry when it is set.
125 for arg
in unreachable prohibit blackhole
; do
126 if enabled
${arg}; then
127 list_append line
"${arg}=\"true\""
134 list_append line
"mtu=\"${mtu}\""
137 # Write line to file.
138 print
"${line}" >> ${NETWORK_CONFIG_ROUTES}
140 log INFO
"New route to network '${network}' has been added."
144 function route_remove
() {
146 assert isset _network
150 local ${NETWORK_CONFIG_ROUTES_PARAMS}
153 route_parse_line
${line}
154 [ $?
-eq ${EXIT_OK} ] ||
continue
156 # Skip the rule, we want to delete.
157 if [ "${network}" = "${_network}" ]; then
163 done < ${NETWORK_CONFIG_ROUTES} > ${NETWORK_CONFIG_ROUTES}.tmp
164 mv ${NETWORK_CONFIG_ROUTES}{.tmp
,}
166 if enabled found
; then
167 log INFO
"Route to network '${_network}' has been removed."
169 error
"No route to network '${_network}' was found."
176 function route_list
() {
179 while [ $# -gt 0 ]; do
182 protocol
=$
(cli_get_val
${1})
185 warning
"Unrecognized argument: ${1}"
191 if [ ! -r "${NETWORK_CONFIG_ROUTES}" ]; then
192 print
"No static routes defined."
196 local format
="%-40s %-20s %-4s"
197 print
"${format}" "NETWORK/HOST" "GATEWAY" "MTU"
199 local ${NETWORK_CONFIG_ROUTES_PARAMS}
202 route_parse_line
${line}
203 [ $?
-eq ${EXIT_OK} ] ||
continue
206 for arg
in unreachable prohibit blackhole
; do
207 if enabled
${arg}; then
213 # Filter all entries with a wrong protocol.
214 if isset protocol
; then
215 local proto
=$
(ip_detect_protocol
${network})
216 [ "${protocol}" = "${proto}" ] ||
continue
219 # Print something when no MTU was set.
224 print
"${format}" "${network}" "${gateway}" "${mtu}"
225 done < ${NETWORK_CONFIG_ROUTES}
228 function route_find_duplicate
() {
231 [ -r "${NETWORK_CONFIG_ROUTES}" ] ||
return ${EXIT_FALSE}
233 local ${NETWORK_CONFIG_ROUTES_PARAMS}
236 route_parse_line
${line}
237 [ $?
-eq ${EXIT_OK} ] ||
continue
239 # Check if the network is already in use.
240 [ "${network}" = "${_network}" ] && return ${EXIT_TRUE}
241 done < ${NETWORK_CONFIG_ROUTES}
246 function route_parse_line() {
249 # Reset all possible settings.
250 for arg in ${NETWORK_CONFIG_ROUTES_PARAMS}; do
251 printf -v ${arg} "%s
" ""
257 network=$(cli_get_val ${arg})
260 gateway=$(cli_get_val ${arg})
263 unreachable=$(cli_get_val ${arg})
266 prohibit=$(cli_get_val ${arg})
269 blackhole=$(cli_get_val ${arg})
272 mtu=$(cli_get_val ${arg})
275 done <<< "$
(args $@
)"
277 ### Check if all values are correctly set.
279 # network must be set.
280 isset network || return ${EXIT_ERROR}
282 # network must be a valid.
283 ip_is_network ${network} || return ${EXIT_ERROR}
285 # Check gateway settings.
286 if isset gateway; then
287 # When gateway is set, unreachable cannot be set.
288 isset unreachable && return ${EXIT_ERROR}
290 # Must be a valid IP address.
291 ip_is_valid ${gateway} || return ${EXIT_ERROR}
293 # Check if exactly one of unreachable, prohibit or blackhole is set.
294 local counter=$(list_count true ${unreachable} ${prohibit} ${blackhole})
295 [ ${counter} -eq 1 ] || return ${EXIT_ERROR}
298 # mtu must be an integer number.
300 isinteger mtu || return ${EXIT_ERROR}
306 function route_apply() {
310 log INFO "Applying static routes...
"
312 # Flush the routing table.
313 route_table_flush ${table}
315 local ${NETWORK_CONFIG_ROUTES_PARAMS}
318 route_parse_line ${line}
319 [ $? -eq ${EXIT_OK} ] || continue
323 for arg in unreachable prohibit blackhole; do
324 if enabled ${arg}; then
331 route_entry_add ${network} --table="static
" --proto="static
" \
332 --type="${type}" --gateway="${gateway}" --mtu="${mtu}"
335 if [ ${ret} -ne ${EXIT_OK} ]; then
336 log WARNING "Could not
set route
'${network}'.
"
338 done < ${NETWORK_CONFIG_ROUTES}
340 # Create a lookup rule for the static routing table.
341 route_rule_add --lookup="static
" --priority=1000
344 function route_entry_add() {
354 while [ $# -gt 0 ]; do
357 gateway=$(cli_get_val ${1})
360 table=$(cli_get_val ${1})
363 type=$(cli_get_val ${1})
366 proto=$(cli_get_val ${1})
369 mtu=$(cli_get_val ${1})
372 if isset network; then
373 warning "Unrecognized argument
: ${1}"
383 assert isoneof type unicast broadcast unreachable prohibit blackhole
384 assert ip_is_network ${network}
389 # Detect the protocol of the given network.
390 local protocol=$(ip_detect_protocol ${network})
391 case "${protocol}" in
393 command="ip
-6 route add
"
396 command="ip route add
"
402 list_append command "${type}"
404 # Add network/prefix.
405 list_append command "${network}"
407 if [ "${type}" = "unicast
" ]; then
409 assert ip_is_valid ${gateway}
411 list_append command "via
${gateway}"
414 # Add table (if any).
416 # Create routing table, if it does not exist, yet.
417 route_table_create ${table}
419 list_append command "table
${table}"
424 list_append command "proto
${proto}"
429 list_append command "mtu
${mtu}"
432 cmd_quiet "${command}"
435 function route_table_create() {
439 if route_table_exists ${table}; then
443 # Get the next free id.
444 local id=$(_route_table_next_id)
447 # Write everything to file.
448 print "%d
\t%s
" "${id}" "${table}" >> /etc/iproute2/rt_tables
450 log DEBUG "Created routing table
'${table}'.
"
455 function _route_table_next_id() {
456 # The Linux kernel is able to manage 255 routing tables (1-255).
457 # This function returns the next free id, starting from 255.
460 for next_id in {255..1}; do
461 if ! route_table_exists --id="${next_id}"; then
470 function route_table_flush() {
474 while [ $# -gt 0 ]; do
477 protocol=$(cli_get_val ${1})
486 # If the table does not exists, there is nothing to
488 route_table_exists ${table} || return ${EXIT_OK}
492 for proto in ${IP_SUPPORTED_PROTOCOLS}; do
493 # Skip unwanted protocols.
494 if isset protocol; then
495 [ "${protocol}" = "${proto}" ] || continue
501 command="ip
-6 route flush
"
504 command="ip route flush
"
509 list_append command "table
${table}"
518 function route_table_exists() {
521 while [ $# -gt 0 ]; do
524 _id=$(cli_get_val ${1})
535 while read -r id table; do
537 [ "${id:0:1}" = "#" ] && continue
539 if [ "${_table}" = "${table}" ] || [ "${_id}" = "${id}" ]; then
543 done < /etc
/iproute
2/rt_tables
548 function route_rule_add
() {
550 local protocols
=${IP_SUPPORTED_PROTOCOLS}
553 while [ $# -gt 0 ]; do
556 lookup
=$
(cli_get_val
${1})
559 priority
=$
(cli_get_val
${1})
562 protocols
=$
(cli_get_val
${1})
564 assert isoneof protocols
${IP_SUPPORTED_PROTOCOLS}
567 warning
"Unhandled argument: ${1}"
573 local command options
575 if isset lookup
; then
576 route_table_create
${lookup}
578 list_append options
"lookup ${lookup}"
581 if isset priority
; then
582 assert isinteger priority
584 list_append options
"prio ${priority}"
588 for proto
in ${protocols}; do
592 command="ip -6 rule add ${options}"
595 command="ip rule add ${options}"
600 # Skip, if the rule does already exist.
602 --protocol=${proto} \
604 --priority=${priority} \
611 function route_rule_exists
() {
617 while [ $# -gt 0 ]; do
620 from
=$
(cli_get_val
${1})
623 lookup
=$
(cli_get_val
${1})
626 prio
=$
(cli_get_val
${1})
629 proto
=$
(cli_get_val
${1})
632 warning
"Unrecognized argument: ${1}"
641 command="ip -6 rule show"
644 command="ip rule show"
649 local _lookup _from _prio
651 while read -r line
; do
652 _route_rule_exists_parse
${line}
655 [ "${from}" = "${_from}" ] ||
continue
659 [ "${prio}" = "${_prio}" ] ||
continue
662 if isset lookup
; then
663 [ "${lookup}" = "${_lookup}" ] ||
continue
667 done <<< "$(${command})"
672 function _route_rule_exists_parse
() {
673 # Reset all variables.
678 while [ $# -gt 0 ]; do
693 # Skip unknown arguments.