William A. Kennington III | e33ec59 | 2021-03-10 17:43:48 -0800 | [diff] [blame] | 1 | #!/bin/bash |
| 2 | # Copyright 2021 Google LLC |
| 3 | # |
| 4 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | # you may not use this file except in compliance with the License. |
| 6 | # You may obtain a copy of the License at |
| 7 | # |
| 8 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | # |
| 10 | # Unless required by applicable law or agreed to in writing, software |
| 11 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | # See the License for the specific language governing permissions and |
| 14 | # limitations under the License. |
| 15 | |
| 16 | # A list of functions which get executed for each netlink event received. |
| 17 | # These are configured by the files included below. |
| 18 | GBMC_IP_MONITOR_HOOKS=() |
| 19 | |
| 20 | # Load configurations from a known location in the filesystem to populate |
| 21 | # hooks that are executed after each event. |
| 22 | shopt -s nullglob |
| 23 | for conf in /usr/share/gbmc-ip-monitor/*.sh; do |
| 24 | source "$conf" |
| 25 | done |
| 26 | |
| 27 | gbmc_ip_monitor_run_hooks() { |
| 28 | local hook |
| 29 | for hook in "${GBMC_IP_MONITOR_HOOKS[@]}"; do |
| 30 | "$hook" || continue |
| 31 | done |
| 32 | } |
| 33 | |
| 34 | gbmc_ip_monitor_generate_init() { |
| 35 | ip link | sed 's,^[^ ],[LINK]\0,' |
| 36 | local intf= |
| 37 | local line |
| 38 | while read line; do |
| 39 | [[ "$line" =~ ^([0-9]+:[[:space:]][^:]+) ]] && intf="${BASH_REMATCH[1]}" |
| 40 | [[ "$line" =~ ^[[:space:]]*inet ]] && echo "[ADDR]$intf $line" |
| 41 | done < <(ip addr) |
| 42 | ip -4 route | sed 's,^,[ROUTE],' |
| 43 | ip -6 route | sed 's,^,[ROUTE],' |
| 44 | echo '[INIT]' |
| 45 | } |
| 46 | |
| 47 | gbmc_ip_monitor_parse_line() { |
| 48 | local line="$1" |
| 49 | if [[ "$line" == '[INIT]'* ]]; then |
| 50 | change=init |
| 51 | echo "Initialized" >&2 |
| 52 | elif [[ "$line" == '[ADDR]'* ]]; then |
| 53 | change=addr |
| 54 | action=add |
| 55 | pfx_re='^\[ADDR\](Deleted )?[0-9]+:[[:space:]]*' |
| 56 | intf_re='([^ ]+)[[:space:]]+' |
| 57 | fam_re='([^ ]+)[[:space:]]+' |
| 58 | addr_re='([^/]+)/[0-9]+[[:space:]]+(brd[[:space:]]+[^ ]+[[:space:]]+)?' |
| 59 | scope_re='scope[[:space:]]+([^ ]+)[[:space:]]*(.*)' |
| 60 | combined_re="${pfx_re}${intf_re}${fam_re}${addr_re}${scope_re}" |
| 61 | if ! [[ "$line" =~ ${combined_re} ]]; then |
| 62 | echo "Failed to parse addr: $line" >&2 |
| 63 | return 1 |
| 64 | fi |
| 65 | if [ -n "${BASH_REMATCH[1]}" ]; then |
| 66 | action=del |
| 67 | fi |
| 68 | intf="${BASH_REMATCH[2]}" |
| 69 | fam="${BASH_REMATCH[3]}" |
| 70 | ip="${BASH_REMATCH[4]}" |
| 71 | scope="${BASH_REMATCH[6]}" |
| 72 | flags="${BASH_REMATCH[7]}" |
| 73 | elif [[ "$line" == '[ROUTE]'* ]]; then |
| 74 | line="${line#[ROUTE]}" |
| 75 | change=route |
| 76 | action=add |
| 77 | if ! [[ "$line" =~ ^\[ROUTE\](Deleted )?(.*)$ ]]; then |
| 78 | echo "Failed to parse link: $line" >&2 |
| 79 | return 1 |
| 80 | fi |
| 81 | if [ -n "${BASH_REMATCH[1]}" ]; then |
| 82 | action=del |
| 83 | fi |
| 84 | route="${BASH_REMATCH[2]}" |
| 85 | elif [[ "$line" == '[LINK]'* ]]; then |
| 86 | change=link |
| 87 | action=add |
| 88 | pfx_re='^\[LINK\](Deleted )?[0-9]+:[[:space:]]*' |
| 89 | intf_re='([^:]+):[[:space:]]+' |
| 90 | if ! [[ "$line" =~ ${pfx_re}${intf_re} ]]; then |
| 91 | echo "Failed to parse link: $line" >&2 |
| 92 | return 1 |
| 93 | fi |
| 94 | if [ -n "${BASH_REMATCH[1]}" ]; then |
| 95 | action=del |
| 96 | fi |
| 97 | intf="${BASH_REMATCH[2]}" |
| 98 | read line || break |
| 99 | data=($line) |
| 100 | mac="${data[1]}" |
| 101 | else |
| 102 | return 2 |
| 103 | fi |
| 104 | } |
| 105 | |
| 106 | cleanup() { |
| 107 | local st="$?" |
| 108 | trap - HUP INT QUIT ABRT TERM EXIT |
| 109 | jobs -l -p | xargs -r kill || true |
| 110 | exit $st |
| 111 | } |
| 112 | trap cleanup HUP INT QUIT ABRT TERM EXIT |
| 113 | |
| 114 | return 0 2>/dev/null |
| 115 | |
| 116 | while read line; do |
William A. Kennington III | 593f2bd | 2021-04-26 13:31:45 -0700 | [diff] [blame] | 117 | gbmc_ip_monitor_parse_line "$line" || continue |
William A. Kennington III | e33ec59 | 2021-03-10 17:43:48 -0800 | [diff] [blame] | 118 | gbmc_ip_monitor_run_hooks || continue |
| 119 | if [ "$change" = 'init' ]; then |
| 120 | systemd-notify --ready |
| 121 | fi |
| 122 | done < <(gbmc_ip_monitor_generate_init; exec ip monitor link addr route label) |