]>
Commit | Line | Data |
---|---|---|
cb965348 MT |
1 | #!/bin/bash |
2 | ############################################################################### | |
3 | # # | |
4 | # IPFire.org - A linux based firewall # | |
5 | # Copyright (C) 2012 IPFire Network Development Team # | |
6 | # # | |
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. # | |
11 | # # | |
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. # | |
16 | # # | |
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/>. # | |
19 | # # | |
20 | ############################################################################### | |
21 | # | |
22 | # Functions for static routing. | |
23 | # | |
24 | ||
68e62bea | 25 | cli_route() { |
2212045f | 26 | if cli_help_requested "$@"; then |
68e62bea MT |
27 | cli_show_man network-route |
28 | exit ${EXIT_OK} | |
29 | fi | |
30 | ||
31 | local action=${1} | |
32 | shift | |
33 | ||
34 | case "${action}" in | |
35 | static) | |
2212045f | 36 | cli_route_static "$@" |
68e62bea MT |
37 | ;; |
38 | *) | |
39 | error "Unrecognized action: ${action}" | |
40 | cli_run_help network route | |
41 | ||
42 | exit ${EXIT_ERROR} | |
43 | ;; | |
44 | esac | |
45 | ||
46 | exit ${EXIT_OK} | |
47 | } | |
48 | ||
49 | cli_route_static() { | |
2212045f | 50 | if cli_help_requested "$@"; then |
68e62bea MT |
51 | cli_show_man network-route-static |
52 | exit ${EXIT_OK} | |
53 | fi | |
54 | ||
55 | local action=${1} | |
56 | shift | |
57 | ||
58 | case "${action}" in | |
59 | # Add a new route. | |
60 | add) | |
2212045f | 61 | route_add "$@" |
68e62bea MT |
62 | ;; |
63 | # Remove an existing route. | |
64 | remove) | |
2212045f | 65 | route_remove "$@" |
68e62bea MT |
66 | ;; |
67 | # List all routes. | |
68 | list) | |
2212045f | 69 | route_list "$@" |
68e62bea MT |
70 | return ${EXIT_OK} |
71 | ;; | |
72 | # Reload all routes | |
73 | reload) | |
2212045f | 74 | route_apply "$@" |
68e62bea MT |
75 | ;; |
76 | *) | |
77 | error "Unrecognized action: ${action}" | |
78 | cli_run_help network route | |
79 | ||
80 | exit ${EXIT_ERROR} | |
81 | ;; | |
82 | esac | |
83 | ||
84 | # Applying all routes. | |
85 | route_apply | |
86 | ||
87 | exit ${EXIT_OK} | |
88 | } | |
89 | ||
1c6a4e30 | 90 | route_add() { |
cb965348 MT |
91 | local ${NETWORK_CONFIG_ROUTES_PARAMS} |
92 | ||
93 | while [ $# -gt 0 ]; do | |
94 | case "${1}" in | |
95 | --gateway=*) | |
2212045f | 96 | gateway=$(cli_get_val "${1}") |
cb965348 MT |
97 | ;; |
98 | --unreachable) | |
99 | unreachable="true" | |
100 | ;; | |
55ea0266 MT |
101 | --prohibit) |
102 | prohibit="true" | |
103 | ;; | |
104 | --blackhole) | |
105 | blackhole="true" | |
106 | ;; | |
478de6f9 | 107 | --mtu=*) |
2212045f | 108 | mtu=$(cli_get_val "${1}") |
478de6f9 | 109 | ;; |
cb965348 | 110 | *) |
47fe7766 JS |
111 | if isset network; then |
112 | error "Bad number of arguments. Network passed twice or more" | |
113 | return ${EXIT_ERROR} | |
114 | else | |
115 | network=${1} | |
116 | fi | |
cb965348 MT |
117 | ;; |
118 | esac | |
119 | shift | |
120 | done | |
121 | ||
122 | assert isset network | |
123 | ||
8b0958b2 | 124 | if ! ip_net_is_valid ${network} && ! ip_is_valid ${network}; then |
cb965348 MT |
125 | error "The given network is invalid: ${network}" |
126 | return ${EXIT_ERROR} | |
127 | fi | |
128 | ||
129 | if route_find_duplicate ${network}; then | |
130 | error "A route to ${network} does already exist." | |
131 | return ${EXIT_ERROR} | |
132 | fi | |
133 | ||
134 | # Check if gateway and unreachable are both enabled. | |
cb965348 | 135 | if isset gateway; then |
55ea0266 MT |
136 | if enabled unreachable; then |
137 | error "You cannot use both, --gateway=${gateway} and --unreachable at the same time." | |
138 | return ${EXIT_ERROR} | |
139 | fi | |
140 | ||
141 | if enabled prohibit; then | |
142 | error "You cannot use both, --gateway=${gateway} and --prohibit at the same time." | |
143 | return ${EXIT_ERROR} | |
144 | fi | |
145 | ||
146 | if enabled blackhole; then | |
147 | error "You cannot use both, --gateway=${gateway} and --blackhole at the same time." | |
148 | return ${EXIT_ERROR} | |
149 | fi | |
150 | ||
151 | # Check if network and gateway IP protocol version match. | |
d2021e87 MT |
152 | if ! ip_is_valid ${gateway}; then |
153 | error "--gateway= is not a valid IP address." | |
154 | return ${EXIT_ERROR} | |
155 | fi | |
156 | ||
4a7c3c02 MT |
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" | |
160 | return ${EXIT_ERROR} | |
161 | fi | |
162 | ||
cb965348 | 163 | local network_proto=$(ip_detect_protocol ${network}) |
b449504e JS |
164 | assert isset network_proto |
165 | ||
cb965348 | 166 | local gateway_proto=$(ip_detect_protocol ${gateway}) |
b449504e | 167 | assert isset gateway_proto |
cb965348 MT |
168 | |
169 | if [ "${network_proto}" != "${gateway_proto}" ]; then | |
170 | error "The IP protocol version of the given network and gateway did not match." | |
171 | return ${EXIT_ERROR} | |
172 | fi | |
55ea0266 MT |
173 | |
174 | else | |
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." | |
178 | return ${EXIT_ERROR} | |
179 | fi | |
cb965348 MT |
180 | fi |
181 | ||
478de6f9 MT |
182 | if isset mtu && ! isinteger mtu; then |
183 | error "MTU must be an integer number: ${mtu}" | |
184 | return ${EXIT_ERROR} | |
185 | fi | |
186 | ||
cb965348 MT |
187 | local line |
188 | list_append line "network=\"${network}\"" | |
189 | ||
190 | # Add gateway to configuration entry when it is set. | |
191 | if isset gateway; then | |
192 | list_append line "gateway=\"${gateway}\"" | |
193 | fi | |
194 | ||
195 | # Add unreachable to configuration entry when it is set. | |
55ea0266 MT |
196 | local arg |
197 | for arg in unreachable prohibit blackhole; do | |
198 | if enabled ${arg}; then | |
199 | list_append line "${arg}=\"true\"" | |
200 | break | |
201 | fi | |
202 | done | |
cb965348 | 203 | |
478de6f9 MT |
204 | # Add MTU (if set). |
205 | if isset mtu; then | |
206 | list_append line "mtu=\"${mtu}\"" | |
207 | fi | |
208 | ||
cb965348 MT |
209 | # Write line to file. |
210 | print "${line}" >> ${NETWORK_CONFIG_ROUTES} | |
211 | ||
212 | log INFO "New route to network '${network}' has been added." | |
213 | return ${EXIT_OK} | |
214 | } | |
215 | ||
1c6a4e30 | 216 | route_remove() { |
e618256e JS |
217 | local _network |
218 | local error=${EXIT_OK} | |
219 | ||
2212045f | 220 | for _network in "$@"; do |
e618256e | 221 | # Validate input |
8b0958b2 | 222 | if ! ip_net_is_valid ${_network} && ! ip_is_valid ${_network}; then |
e618256e JS |
223 | error "Invalid IP address or network: ${_network}" |
224 | error=${EXIT_ERROR} | |
f04e7377 | 225 | continue |
cb965348 MT |
226 | fi |
227 | ||
e618256e JS |
228 | local found="false" |
229 | ||
230 | local ${NETWORK_CONFIG_ROUTES_PARAMS} | |
231 | local line | |
232 | while read line; do | |
233 | route_parse_line ${line} | |
234 | [ $? -eq ${EXIT_OK} ] || continue | |
235 | ||
236 | # Skip the rule, we want to delete. | |
237 | if [ "${network}" = "${_network}" ]; then | |
238 | found="true" | |
239 | continue | |
240 | fi | |
241 | ||
242 | print "${line}" | |
243 | done < ${NETWORK_CONFIG_ROUTES} > ${NETWORK_CONFIG_ROUTES}.tmp | |
244 | mv ${NETWORK_CONFIG_ROUTES}{.tmp,} | |
245 | ||
246 | if enabled found; then | |
247 | log INFO "Route to network '${_network}' has been removed." | |
248 | else | |
249 | error "No route to network '${_network}' was found." | |
250 | error=${EXIT_ERROR} | |
251 | fi | |
252 | done | |
cb965348 | 253 | |
e618256e | 254 | return ${error} |
cb965348 MT |
255 | } |
256 | ||
1c6a4e30 | 257 | route_list() { |
cb965348 MT |
258 | local protocol |
259 | ||
260 | while [ $# -gt 0 ]; do | |
261 | case "${1}" in | |
262 | --protocol=*) | |
2212045f | 263 | protocol=$(cli_get_val "${1}") |
cb965348 MT |
264 | ;; |
265 | *) | |
266 | warning "Unrecognized argument: ${1}" | |
267 | ;; | |
268 | esac | |
269 | shift | |
270 | done | |
271 | ||
272 | if [ ! -r "${NETWORK_CONFIG_ROUTES}" ]; then | |
273 | print "No static routes defined." | |
274 | return ${EXIT_OK} | |
275 | fi | |
276 | ||
478de6f9 MT |
277 | local format="%-40s %-20s %-4s" |
278 | print "${format}" "NETWORK/HOST" "GATEWAY" "MTU" | |
cb965348 MT |
279 | |
280 | local ${NETWORK_CONFIG_ROUTES_PARAMS} | |
281 | local line | |
282 | while read line; do | |
283 | route_parse_line ${line} | |
284 | [ $? -eq ${EXIT_OK} ] || continue | |
285 | ||
55ea0266 MT |
286 | local arg |
287 | for arg in unreachable prohibit blackhole; do | |
288 | if enabled ${arg}; then | |
289 | gateway="<${arg}>" | |
290 | break | |
291 | fi | |
292 | done | |
cb965348 MT |
293 | |
294 | # Filter all entries with a wrong protocol. | |
295 | if isset protocol; then | |
296 | local proto=$(ip_detect_protocol ${network}) | |
297 | [ "${protocol}" = "${proto}" ] || continue | |
298 | fi | |
299 | ||
478de6f9 MT |
300 | # Print something when no MTU was set. |
301 | if ! isset mtu; then | |
302 | mtu="-" | |
303 | fi | |
304 | ||
305 | print "${format}" "${network}" "${gateway}" "${mtu}" | |
cb965348 MT |
306 | done < ${NETWORK_CONFIG_ROUTES} |
307 | } | |
308 | ||
1c6a4e30 | 309 | route_find_duplicate() { |
cb965348 MT |
310 | local _network=${1} |
311 | ||
312 | [ -r "${NETWORK_CONFIG_ROUTES}" ] || return ${EXIT_FALSE} | |
313 | ||
314 | local ${NETWORK_CONFIG_ROUTES_PARAMS} | |
315 | local line | |
316 | while read line; do | |
317 | route_parse_line ${line} | |
d2021e87 | 318 | [ $? -eq ${EXIT_OK} ] || continue |
cb965348 MT |
319 | |
320 | # Check if the network is already in use. | |
321 | [ "${network}" = "${_network}" ] && return ${EXIT_TRUE} | |
322 | done < ${NETWORK_CONFIG_ROUTES} | |
323 | ||
324 | return ${EXIT_FALSE} | |
325 | } | |
326 | ||
1c6a4e30 | 327 | route_parse_line() { |
cb965348 MT |
328 | local arg |
329 | ||
330 | # Reset all possible settings. | |
331 | for arg in ${NETWORK_CONFIG_ROUTES_PARAMS}; do | |
332 | printf -v ${arg} "%s" "" | |
333 | done | |
334 | ||
335 | while read arg; do | |
336 | case "${arg}" in | |
337 | network=*) | |
2212045f | 338 | network=$(cli_get_val "${arg}") |
cb965348 MT |
339 | ;; |
340 | gateway=*) | |
2212045f | 341 | gateway=$(cli_get_val "${arg}") |
cb965348 MT |
342 | ;; |
343 | unreachable=*) | |
2212045f | 344 | unreachable=$(cli_get_val "${arg}") |
cb965348 | 345 | ;; |
55ea0266 | 346 | prohibit=*) |
2212045f | 347 | prohibit=$(cli_get_val "${arg}") |
55ea0266 MT |
348 | ;; |
349 | blackhole=*) | |
2212045f | 350 | blackhole=$(cli_get_val "${arg}") |
55ea0266 | 351 | ;; |
478de6f9 | 352 | mtu=*) |
2212045f | 353 | mtu=$(cli_get_val "${arg}") |
478de6f9 | 354 | ;; |
cb965348 | 355 | esac |
2212045f | 356 | done <<< "$(args "$@")" |
cb965348 MT |
357 | |
358 | ### Check if all values are correctly set. | |
359 | ||
360 | # network must be set. | |
361 | isset network || return ${EXIT_ERROR} | |
362 | ||
146b2b81 | 363 | # Is network or IP valid? |
8b0958b2 | 364 | if ! ip_net_is_valid ${network} && ! ip_is_valid ${network}; then |
146b2b81 JS |
365 | error "The given network is invalid: ${network}" |
366 | return ${EXIT_ERROR} | |
367 | fi | |
cb965348 MT |
368 | |
369 | # Check gateway settings. | |
370 | if isset gateway; then | |
371 | # When gateway is set, unreachable cannot be set. | |
372 | isset unreachable && return ${EXIT_ERROR} | |
373 | ||
374 | # Must be a valid IP address. | |
375 | ip_is_valid ${gateway} || return ${EXIT_ERROR} | |
4a7c3c02 MT |
376 | |
377 | # Check if the gateway is part of the statically routed network | |
378 | if ip_network_is_subset_of ${gateway} ${network}; then | |
379 | return ${EXIT_ERROR} | |
380 | fi | |
cb965348 | 381 | else |
55ea0266 MT |
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} | |
cb965348 MT |
385 | fi |
386 | ||
478de6f9 MT |
387 | # mtu must be an integer number. |
388 | if isset mtu; then | |
389 | isinteger mtu || return ${EXIT_ERROR} | |
390 | fi | |
391 | ||
cb965348 MT |
392 | return ${EXIT_OK} |
393 | } | |
d2021e87 | 394 | |
1c6a4e30 | 395 | route_apply() { |
0a578797 MT |
396 | # Re-generate BIRD configuration |
397 | bird_generate_config | |
d2021e87 | 398 | |
0a578797 MT |
399 | # Reload the daemon |
400 | bird_reload | |
d2021e87 MT |
401 | } |
402 | ||
1c6a4e30 | 403 | route_entry_add() { |
d2021e87 MT |
404 | local gateway |
405 | local network | |
406 | local proto | |
407 | local table | |
408 | local type="unicast" | |
478de6f9 | 409 | local mtu |
d2021e87 MT |
410 | |
411 | local command | |
412 | ||
413 | while [ $# -gt 0 ]; do | |
414 | case "${1}" in | |
415 | --gateway=*) | |
2212045f | 416 | gateway=$(cli_get_val "${1}") |
d2021e87 MT |
417 | ;; |
418 | --table=*) | |
2212045f | 419 | table=$(cli_get_val "${1}") |
d2021e87 MT |
420 | ;; |
421 | --type=*) | |
2212045f | 422 | type=$(cli_get_val "${1}") |
d2021e87 MT |
423 | ;; |
424 | --proto=*) | |
2212045f | 425 | proto=$(cli_get_val "${1}") |
d2021e87 | 426 | ;; |
478de6f9 | 427 | --mtu=*) |
2212045f | 428 | mtu=$(cli_get_val "${1}") |
478de6f9 | 429 | ;; |
d2021e87 MT |
430 | *) |
431 | if isset network; then | |
432 | warning "Unrecognized argument: ${1}" | |
433 | else | |
434 | network=${1} | |
435 | fi | |
436 | ;; | |
437 | esac | |
438 | shift | |
439 | done | |
440 | ||
441 | # Validate input. | |
442 | assert isoneof type unicast broadcast unreachable prohibit blackhole | |
146b2b81 JS |
443 | |
444 | assert isset network | |
445 | ||
8b0958b2 | 446 | if ! ip_net_is_valid ${network} && ! ip_is_valid ${network}; then |
146b2b81 JS |
447 | error "The given network is invalid: ${network}" |
448 | return ${EXIT_ERROR} | |
449 | fi | |
450 | ||
478de6f9 MT |
451 | if isset mtu; then |
452 | assert isinteger mtu | |
453 | fi | |
d2021e87 MT |
454 | |
455 | # Detect the protocol of the given network. | |
456 | local protocol=$(ip_detect_protocol ${network}) | |
146b2b81 | 457 | |
d2021e87 MT |
458 | case "${protocol}" in |
459 | ipv6) | |
460 | command="ip -6 route add" | |
461 | ;; | |
462 | ipv4) | |
463 | command="ip route add" | |
464 | ;; | |
1008bbb9 MT |
465 | *) |
466 | log ERROR "Could not detect protocol for ${network}" | |
467 | return ${EXIT_ERROR} | |
468 | ;; | |
d2021e87 | 469 | esac |
d2021e87 MT |
470 | |
471 | # Add type. | |
472 | list_append command "${type}" | |
473 | ||
474 | # Add network/prefix. | |
475 | list_append command "${network}" | |
476 | ||
477 | if [ "${type}" = "unicast" ]; then | |
478 | assert isset gateway | |
479 | assert ip_is_valid ${gateway} | |
480 | ||
481 | list_append command "via ${gateway}" | |
482 | fi | |
483 | ||
484 | # Add table (if any). | |
485 | if isset table; then | |
486 | # Create routing table, if it does not exist, yet. | |
487 | route_table_create ${table} | |
488 | ||
489 | list_append command "table ${table}" | |
490 | fi | |
491 | ||
492 | # Add proto. | |
493 | if isset proto; then | |
494 | list_append command "proto ${proto}" | |
495 | fi | |
496 | ||
478de6f9 MT |
497 | # Add MTU. |
498 | if isset mtu; then | |
499 | list_append command "mtu ${mtu}" | |
500 | fi | |
501 | ||
a6c3c15c | 502 | cmd "${command}" |
d2021e87 MT |
503 | } |
504 | ||
1c6a4e30 | 505 | route_table_create() { |
d2021e87 MT |
506 | local table=${1} |
507 | assert isset table | |
508 | ||
509 | if route_table_exists ${table}; then | |
510 | return ${EXIT_OK} | |
511 | fi | |
512 | ||
513 | # Get the next free id. | |
514 | local id=$(_route_table_next_id) | |
515 | assert isset id | |
516 | ||
517 | # Write everything to file. | |
518 | print "%d\t%s" "${id}" "${table}" >> /etc/iproute2/rt_tables | |
519 | ||
520 | log DEBUG "Created routing table '${table}'." | |
521 | ||
522 | return ${EXIT_OK} | |
523 | } | |
524 | ||
1c6a4e30 | 525 | _route_table_next_id() { |
d2021e87 MT |
526 | # The Linux kernel is able to manage 255 routing tables (1-255). |
527 | # This function returns the next free id, starting from 255. | |
528 | local next_id | |
529 | ||
530 | for next_id in {255..1}; do | |
531 | if ! route_table_exists --id="${next_id}"; then | |
532 | print "${next_id}" | |
533 | return ${EXIT_OK} | |
534 | fi | |
535 | done | |
536 | ||
537 | return ${EXIT_FALSE} | |
538 | } | |
539 | ||
1c6a4e30 | 540 | route_table_flush() { |
d2021e87 MT |
541 | local protocol |
542 | local table | |
543 | ||
544 | while [ $# -gt 0 ]; do | |
545 | case "${1}" in | |
546 | --protocol=*) | |
2212045f | 547 | protocol=$(cli_get_val "${1}") |
d2021e87 MT |
548 | ;; |
549 | *) | |
550 | table="${1}" | |
551 | ;; | |
552 | esac | |
553 | shift | |
554 | done | |
555 | ||
556 | # If the table does not exists, there is nothing to | |
557 | # flush. | |
558 | route_table_exists ${table} || return ${EXIT_OK} | |
559 | ||
560 | local command | |
561 | local proto | |
562 | for proto in ${IP_SUPPORTED_PROTOCOLS}; do | |
563 | # Skip unwanted protocols. | |
564 | if isset protocol; then | |
565 | [ "${protocol}" = "${proto}" ] || continue | |
566 | fi | |
567 | ||
568 | command="" | |
569 | case "${proto}" in | |
570 | ipv6) | |
571 | command="ip -6 route flush" | |
572 | ;; | |
573 | ipv4) | |
574 | command="ip route flush" | |
575 | ;; | |
576 | esac | |
577 | assert isset command | |
578 | ||
579 | list_append command "table ${table}" | |
580 | ||
581 | # Execute command. | |
582 | cmd "${command}" | |
583 | done | |
584 | ||
585 | return ${EXIT_OK} | |
586 | } | |
587 | ||
1c6a4e30 | 588 | route_table_exists() { |
d2021e87 MT |
589 | local _id _table |
590 | ||
591 | while [ $# -gt 0 ]; do | |
592 | case "${1}" in | |
593 | --id=*) | |
2212045f | 594 | _id=$(cli_get_val "${1}") |
d2021e87 MT |
595 | ;; |
596 | *) | |
597 | _table=${1} | |
598 | break | |
599 | ;; | |
600 | esac | |
601 | shift | |
602 | done | |
603 | ||
604 | local id table | |
605 | while read -r id table; do | |
606 | # Skip all comments. | |
607 | [ "${id:0:1}" = "#" ] && continue | |
608 | ||
609 | if [ "${_table}" = "${table}" ] || [ "${_id}" = "${id}" ]; then | |
610 | # Found a match. | |
611 | return ${EXIT_TRUE} | |
612 | fi | |
613 | done < /etc/iproute2/rt_tables | |
614 | ||
615 | return ${EXIT_FALSE} | |
616 | } | |
617 | ||
1c6a4e30 | 618 | route_rule_add() { |
d2021e87 MT |
619 | local priority |
620 | local protocols=${IP_SUPPORTED_PROTOCOLS} | |
621 | local lookup | |
622 | ||
623 | while [ $# -gt 0 ]; do | |
624 | case "${1}" in | |
625 | --lookup=*) | |
2212045f | 626 | lookup=$(cli_get_val "${1}") |
d2021e87 MT |
627 | ;; |
628 | --priority=*) | |
2212045f | 629 | priority=$(cli_get_val "${1}") |
d2021e87 MT |
630 | ;; |
631 | --protocol=*) | |
2212045f | 632 | protocols=$(cli_get_val "${1}") |
d2021e87 MT |
633 | |
634 | assert isoneof protocols ${IP_SUPPORTED_PROTOCOLS} | |
635 | ;; | |
636 | *) | |
637 | warning "Unhandled argument: ${1}" | |
638 | ;; | |
639 | esac | |
640 | shift | |
641 | done | |
642 | ||
643 | local command options | |
644 | ||
645 | if isset lookup; then | |
646 | route_table_create ${lookup} | |
647 | ||
648 | list_append options "lookup ${lookup}" | |
649 | fi | |
650 | ||
651 | if isset priority; then | |
652 | assert isinteger priority | |
653 | ||
654 | list_append options "prio ${priority}" | |
655 | fi | |
656 | ||
657 | local proto | |
658 | for proto in ${protocols}; do | |
659 | command= | |
660 | case "${proto}" in | |
661 | ipv6) | |
662 | command="ip -6 rule add ${options}" | |
663 | ;; | |
664 | ipv4) | |
665 | command="ip rule add ${options}" | |
666 | ;; | |
667 | esac | |
668 | assert isset command | |
669 | ||
670 | # Skip, if the rule does already exist. | |
671 | route_rule_exists \ | |
672 | --protocol=${proto} \ | |
673 | --lookup=${lookup} \ | |
674 | --priority=${priority} \ | |
675 | && continue | |
676 | ||
677 | cmd "${command}" | |
678 | done | |
679 | } | |
680 | ||
1c6a4e30 | 681 | route_rule_exists() { |
d2021e87 MT |
682 | local from |
683 | local lookup | |
684 | local proto | |
685 | local prio | |
686 | ||
687 | while [ $# -gt 0 ]; do | |
688 | case "${1}" in | |
689 | --from=*) | |
2212045f | 690 | from=$(cli_get_val "${1}") |
d2021e87 MT |
691 | ;; |
692 | --lookup=*) | |
2212045f | 693 | lookup=$(cli_get_val "${1}") |
d2021e87 MT |
694 | ;; |
695 | --priority=*) | |
2212045f | 696 | prio=$(cli_get_val "${1}") |
d2021e87 MT |
697 | ;; |
698 | --protocol=*) | |
2212045f | 699 | proto=$(cli_get_val "${1}") |
d2021e87 MT |
700 | ;; |
701 | *) | |
702 | warning "Unrecognized argument: ${1}" | |
703 | ;; | |
704 | esac | |
705 | shift | |
706 | done | |
707 | ||
708 | local command | |
709 | case "${proto}" in | |
710 | ipv6) | |
711 | command="ip -6 rule show" | |
712 | ;; | |
713 | ipv4) | |
714 | command="ip rule show" | |
715 | ;; | |
716 | esac | |
717 | assert isset command | |
718 | ||
719 | local _lookup _from _prio | |
720 | local line | |
721 | while read -r line; do | |
722 | _route_rule_exists_parse ${line} | |
723 | ||
724 | if isset from; then | |
725 | [ "${from}" = "${_from}" ] || continue | |
726 | fi | |
727 | ||
728 | if isset prio; then | |
729 | [ "${prio}" = "${_prio}" ] || continue | |
730 | fi | |
731 | ||
732 | if isset lookup; then | |
733 | [ "${lookup}" = "${_lookup}" ] || continue | |
734 | fi | |
735 | ||
736 | return ${EXIT_TRUE} | |
737 | done <<< "$(${command})" | |
738 | ||
739 | return ${EXIT_FALSE} | |
740 | } | |
741 | ||
1c6a4e30 | 742 | _route_rule_exists_parse() { |
d2021e87 MT |
743 | # Reset all variables. |
744 | _lookup= | |
745 | _from= | |
746 | _prio= | |
747 | ||
748 | while [ $# -gt 0 ]; do | |
749 | case "${1}" in | |
750 | lookup) | |
751 | _lookup=${2} | |
752 | shift 2 | |
753 | ;; | |
754 | from) | |
755 | _from=${2} | |
756 | shift 2 | |
757 | ;; | |
758 | *:) | |
759 | _prio=${1//:/} | |
760 | shift | |
761 | ;; | |
762 | *) | |
763 | # Skip unknown arguments. | |
764 | shift | |
765 | ;; | |
766 | esac | |
767 | done | |
768 | } |