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 if cli_help_requested
"$@"; then
27 cli_show_man network-route
39 error
"Unrecognized action: ${action}"
40 cli_run_help network route
50 if cli_help_requested
"$@"; then
51 cli_show_man network-route-static
63 # Remove an existing route.
77 error
"Unrecognized action: ${action}"
78 cli_run_help network route
84 # Applying all routes.
91 local ${NETWORK_CONFIG_ROUTES_PARAMS}
93 while [ $# -gt 0 ]; do
96 gateway
=$
(cli_get_val
"${1}")
108 mtu
=$
(cli_get_val
"${1}")
111 if isset network
; then
112 error
"Bad number of arguments. Network passed twice or more"
124 if ! ip_net_is_valid
${network} && ! ip_is_valid
${network}; then
125 error
"The given network is invalid: ${network}"
129 if route_find_duplicate
${network}; then
130 error
"A route to ${network} does already exist."
134 # Check if gateway and unreachable are both enabled.
135 if isset gateway
; then
136 if enabled unreachable
; then
137 error
"You cannot use both, --gateway=${gateway} and --unreachable at the same time."
141 if enabled prohibit
; then
142 error
"You cannot use both, --gateway=${gateway} and --prohibit at the same time."
146 if enabled blackhole
; then
147 error
"You cannot use both, --gateway=${gateway} and --blackhole at the same time."
151 # Check if network and gateway IP protocol version match.
152 if ! ip_is_valid
${gateway}; then
153 error
"--gateway= is not a valid IP address."
157 # Check if the gateway is part of the statically routed network
158 if ip_network_is_subset_of
${gateway} ${network}; then
159 error
"The gateway is in the routed network"
163 local network_proto
=$
(ip_detect_protocol
${network})
164 assert isset network_proto
166 local gateway_proto
=$
(ip_detect_protocol
${gateway})
167 assert isset gateway_proto
169 if [ "${network_proto}" != "${gateway_proto}" ]; then
170 error
"The IP protocol version of the given network and gateway did not match."
175 local counter
=$
(list_count true
${unreachable} ${prohibit} ${blackhole})
176 if [ ${counter} -gt 1 ]; then
177 error
"You can only use one of --unreachable, --prohibit or --blackhole."
182 if isset mtu
&& ! isinteger mtu
; then
183 error
"MTU must be an integer number: ${mtu}"
188 list_append line
"network=\"${network}\""
190 # Add gateway to configuration entry when it is set.
191 if isset gateway
; then
192 list_append line
"gateway=\"${gateway}\""
195 # Add unreachable to configuration entry when it is set.
197 for arg
in unreachable prohibit blackhole
; do
198 if enabled
${arg}; then
199 list_append line
"${arg}=\"true\""
206 list_append line
"mtu=\"${mtu}\""
209 # Write line to file.
210 print
"${line}" >> ${NETWORK_CONFIG_ROUTES}
212 log INFO
"New route to network '${network}' has been added."
218 local error
=${EXIT_OK}
220 for _network
in "$@"; do
222 if ! ip_net_is_valid
${_network} && ! ip_is_valid
${_network}; then
223 error
"Invalid IP address or network: ${_network}"
230 local ${NETWORK_CONFIG_ROUTES_PARAMS}
233 route_parse_line
${line}
234 [ $?
-eq ${EXIT_OK} ] ||
continue
236 # Skip the rule, we want to delete.
237 if [ "${network}" = "${_network}" ]; then
243 done < ${NETWORK_CONFIG_ROUTES} > ${NETWORK_CONFIG_ROUTES}.tmp
244 mv ${NETWORK_CONFIG_ROUTES}{.tmp
,}
246 if enabled found
; then
247 log INFO
"Route to network '${_network}' has been removed."
249 error
"No route to network '${_network}' was found."
260 while [ $# -gt 0 ]; do
263 protocol
=$
(cli_get_val
"${1}")
266 warning
"Unrecognized argument: ${1}"
272 if [ ! -r "${NETWORK_CONFIG_ROUTES}" ]; then
273 print
"No static routes defined."
277 local format
="%-40s %-20s %-4s"
278 print
"${format}" "NETWORK/HOST" "GATEWAY" "MTU"
280 local ${NETWORK_CONFIG_ROUTES_PARAMS}
283 route_parse_line
${line}
284 [ $?
-eq ${EXIT_OK} ] ||
continue
287 for arg
in unreachable prohibit blackhole
; do
288 if enabled
${arg}; then
294 # Filter all entries with a wrong protocol.
295 if isset protocol
; then
296 local proto
=$
(ip_detect_protocol
${network})
297 [ "${protocol}" = "${proto}" ] ||
continue
300 # Print something when no MTU was set.
305 print
"${format}" "${network}" "${gateway}" "${mtu}"
306 done < ${NETWORK_CONFIG_ROUTES}
309 route_find_duplicate
() {
312 [ -r "${NETWORK_CONFIG_ROUTES}" ] ||
return ${EXIT_FALSE}
314 local ${NETWORK_CONFIG_ROUTES_PARAMS}
317 route_parse_line
${line}
318 [ $?
-eq ${EXIT_OK} ] ||
continue
320 # Check if the network is already in use.
321 [ "${network}" = "${_network}" ] && return ${EXIT_TRUE}
322 done < ${NETWORK_CONFIG_ROUTES}
330 # Reset all possible settings.
331 for arg in ${NETWORK_CONFIG_ROUTES_PARAMS}; do
332 printf -v ${arg} "%s
" ""
338 network=$(cli_get_val "${arg}")
341 gateway=$(cli_get_val "${arg}")
344 unreachable=$(cli_get_val "${arg}")
347 prohibit=$(cli_get_val "${arg}")
350 blackhole=$(cli_get_val "${arg}")
353 mtu=$(cli_get_val "${arg}")
356 done <<< "$
(args
"$@")"
358 ### Check if all values are correctly set.
360 # network must be set.
361 isset network || return ${EXIT_ERROR}
363 # Is network or IP valid?
364 if ! ip_net_is_valid ${network} && ! ip_is_valid ${network}; then
365 error "The given network is invalid
: ${network}"
369 # Check gateway settings.
370 if isset gateway; then
371 # When gateway is set, unreachable cannot be set.
372 isset unreachable && return ${EXIT_ERROR}
374 # Must be a valid IP address.
375 ip_is_valid ${gateway} || return ${EXIT_ERROR}
377 # Check if the gateway is part of the statically routed network
378 if ip_network_is_subset_of ${gateway} ${network}; then
382 # Check if exactly one of unreachable, prohibit or blackhole is set.
383 local counter=$(list_count true ${unreachable} ${prohibit} ${blackhole})
384 [ ${counter} -eq 1 ] || return ${EXIT_ERROR}
387 # mtu must be an integer number.
389 isinteger mtu || return ${EXIT_ERROR}
410 while [ $# -gt 0 ]; do
413 gateway=$(cli_get_val "${1}")
416 table=$(cli_get_val "${1}")
419 type=$(cli_get_val "${1}")
422 proto=$(cli_get_val "${1}")
425 mtu=$(cli_get_val "${1}")
428 if isset network; then
429 warning "Unrecognized argument
: ${1}"
439 assert isoneof type unicast broadcast unreachable prohibit blackhole
443 if ! ip_net_is_valid ${network} && ! ip_is_valid ${network}; then
444 error "The given network is invalid
: ${network}"
452 # Detect the protocol of the given network.
453 local protocol=$(ip_detect_protocol ${network})
455 case "${protocol}" in
457 command="ip
-6 route add
"
460 command="ip route add
"
463 log ERROR "Could not detect protocol
for ${network}"
469 list_append command "${type}"
471 # Add network/prefix.
472 list_append command "${network}"
474 if [ "${type}" = "unicast
" ]; then
476 assert ip_is_valid ${gateway}
478 list_append command "via
${gateway}"
481 # Add table (if any).
483 # Create routing table, if it does not exist, yet.
484 route_table_create ${table}
486 list_append command "table
${table}"
491 list_append command "proto
${proto}"
496 list_append command "mtu
${mtu}"
502 route_table_create() {
506 if route_table_exists ${table}; then
510 # Get the next free id.
511 local id=$(_route_table_next_id)
514 # Write everything to file.
515 print "%d
\t%s
" "${id}" "${table}" >> /etc/iproute2/rt_tables
517 log DEBUG "Created routing table
'${table}'.
"
522 _route_table_next_id() {
523 # The Linux kernel is able to manage 255 routing tables (1-255).
524 # This function returns the next free id, starting from 255.
527 for next_id in {255..1}; do
528 if ! route_table_exists --id="${next_id}"; then
537 route_table_flush() {
541 while [ $# -gt 0 ]; do
544 protocol=$(cli_get_val "${1}")
553 # If the table does not exists, there is nothing to
555 route_table_exists ${table} || return ${EXIT_OK}
559 for proto in ${IP_SUPPORTED_PROTOCOLS}; do
560 # Skip unwanted protocols.
561 if isset protocol; then
562 [ "${protocol}" = "${proto}" ] || continue
568 command="ip
-6 route flush
"
571 command="ip route flush
"
576 list_append command "table
${table}"
585 route_table_exists() {
588 while [ $# -gt 0 ]; do
591 _id=$(cli_get_val "${1}")
602 while read -r id table; do
604 [ "${id:0:1}" = "#" ] && continue
606 if [ "${_table}" = "${table}" ] || [ "${_id}" = "${id}" ]; then
610 done < /etc
/iproute
2/rt_tables
617 local protocols
=${IP_SUPPORTED_PROTOCOLS}
620 while [ $# -gt 0 ]; do
623 lookup
=$
(cli_get_val
"${1}")
626 priority
=$
(cli_get_val
"${1}")
629 protocols
=$
(cli_get_val
"${1}")
631 assert isoneof protocols
${IP_SUPPORTED_PROTOCOLS}
634 warning
"Unhandled argument: ${1}"
640 local command options
642 if isset lookup
; then
643 route_table_create
${lookup}
645 list_append options
"lookup ${lookup}"
648 if isset priority
; then
649 assert isinteger priority
651 list_append options
"prio ${priority}"
655 for proto
in ${protocols}; do
659 command="ip -6 rule add ${options}"
662 command="ip rule add ${options}"
667 # Skip, if the rule does already exist.
669 --protocol=${proto} \
671 --priority=${priority} \
678 route_rule_exists
() {
684 while [ $# -gt 0 ]; do
687 from
=$
(cli_get_val
"${1}")
690 lookup
=$
(cli_get_val
"${1}")
693 prio
=$
(cli_get_val
"${1}")
696 proto
=$
(cli_get_val
"${1}")
699 warning
"Unrecognized argument: ${1}"
708 command="ip -6 rule show"
711 command="ip rule show"
716 local _lookup _from _prio
718 while read -r line
; do
719 _route_rule_exists_parse
${line}
722 [ "${from}" = "${_from}" ] ||
continue
726 [ "${prio}" = "${_prio}" ] ||
continue
729 if isset lookup
; then
730 [ "${lookup}" = "${_lookup}" ] ||
continue
734 done <<< "$(${command})"
739 _route_rule_exists_parse
() {
740 # Reset all variables.
745 while [ $# -gt 0 ]; do
760 # Skip unknown arguments.