]>
Commit | Line | Data |
---|---|---|
f725df0f | 1 | #!/bin/bash |
47a3a827 | 2 | # SPDX-License-Identifier: GPL-2.0-or-later |
f725df0f | 3 | |
fe67f1f9 JAG |
4 | # Author: Joe Maimon |
5 | # Released to public domain | |
6 | # | |
f725df0f JM |
7 | |
8 | PROGNAME=`basename $0` | |
9 | VERSION="0.0.6" | |
10 | #api fields | |
11 | EV_ID="eventid" | |
12 | EV_TYPE="type" | |
13 | EV_OTYPE="old_type" | |
14 | EV_NUMNHS="num_nhs" | |
15 | EV_INT="interface" | |
16 | EV_LADDR="local_address" | |
17 | EV_VCINIT="vc_initiated" | |
18 | EV_LNBMA="local_nbma" | |
19 | EV_LCERT="local_cert" | |
20 | EV_RADDR="remote_addr" | |
21 | EV_RNBMA="remote_nbma" | |
22 | EV_RCERT="remote_cert" | |
23 | ||
24 | usage() | |
25 | { | |
26 | echo "Usage: $PROGNAME [-s nhrp-sock] [-d] [-i interface-name] [-t table] [-e execute-cmd] [-u user] [-g group] [-r] [-l logfile]" | |
27 | echo "" | |
28 | echo "-s nhrp-sock file" | |
29 | echo "-i interface-name to execute on, may be repeated multiple times" | |
30 | echo "-t tableid to execute on for immdiate preceeding interface" | |
31 | echo "-e execute command for immmediate preceeding interface" | |
32 | echo " The command will be passed the following arguments $EV_ID $EV_TYPE $EV_INT $EV_LNMBA $EV_RADDR $EV_RNBMA int_table" | |
33 | echo "-u user to own the sock" | |
34 | echo "-g group to own the sock" | |
35 | echo "-r send rejection (testing)" | |
36 | echo "-l logfile to record conversation with nhrpd" | |
37 | echo "-d daemonize" | |
38 | ||
39 | exit 1 | |
40 | } | |
41 | ||
42 | declare -A EXECARR | |
43 | declare -A TABLEARR | |
44 | declare -Ag NHRPEVENT | |
45 | SOCK="/var/run/frr/nhrp.sock" | |
46 | USER="frr" | |
47 | GROUP="frr" | |
48 | DAEMON=0 | |
49 | j=0 | |
50 | RESULT="accept" | |
51 | ||
52 | while getopts rds:i:u:g:l:t:e: opt; do | |
53 | case "$opt" in | |
54 | d) | |
55 | DAEMON=1 | |
56 | ;; | |
57 | s) | |
58 | SOCK="$OPTARG" | |
59 | ;; | |
60 | i) | |
61 | INTARR[((j++))]="$OPTARG" | |
62 | ;; | |
63 | e) | |
64 | if [[ "$j" == "0" ]] || [[ "${INTARR[((j-1))]}" == "" ]]; then | |
65 | echo "execute argument must follow interface argument" | |
66 | usage | |
67 | fi | |
68 | EXECARR["${INTARR[((j-1))]}"]="$OPTARG" | |
69 | ;; | |
70 | t) | |
71 | if [[ "$j" == "0" ]] || [[ "${INTARR[((j-1))]}" == "" ]]; then | |
72 | echo "execute argument must follow interface argument" | |
73 | usage | |
74 | fi | |
75 | TABLEARR["${INTARR[((j-1))]}"]="$OPTARG" | |
76 | ;; | |
77 | u) | |
78 | USER="$OPTARG" | |
79 | ;; | |
80 | g) | |
81 | GROUP="$OPTARG" | |
82 | ;; | |
83 | r) | |
84 | RESULT="reject" | |
85 | ;; | |
86 | l) | |
87 | EVLOGFILE="${OPTARG}" | |
88 | ;; | |
89 | esac; | |
90 | done | |
91 | ||
92 | if [[ "$EVLOGFILE" != "" ]]; then | |
93 | if [[ ! -w "${EVLOGFILE}" ]]; then | |
94 | touch "$EVLOGFILE" || ( echo "Cannot write to logfile $EVLOGFILE" ; usage ) | |
95 | fi | |
96 | echo -e "PROG: $0 Startup\nPROG: Arguments $*" >> $EVLOGFILE | |
97 | fi | |
98 | ||
99 | ||
100 | function mainloop() | |
101 | { | |
102 | ||
103 | if [[ "$EVLOGFILE" != "" ]]; then | |
104 | echo -e "PROG: `date -R`\nPROG: Starting mainloop" >> $EVLOGFILE | |
105 | fi | |
106 | ||
107 | coproc socat - UNIX-LISTEN:$SOCK,unlink-early,setuid-early=$USER,unlink-close=0 || exit 1 | |
108 | test -S $SOCK && chown $USER:$GROUP $SOCK | |
109 | ||
110 | OLDIFS="$IFS" | |
111 | ||
112 | TABLE="table " | |
113 | ||
114 | while read -r S; do | |
115 | if [[ "$EVLOGFILE" != "" ]]; then | |
116 | echo "IN: $S" >> $EVLOGFILE | |
117 | fi | |
118 | if [[ "$S" == "" ]]; then | |
119 | if [[ "${NHRPEVENT[$EV_ID]}" != "" ]]; then | |
120 | OUTMSG="eventid=${NHRPEVENT[$EV_ID]}\nresult=$RESULT\n" | |
121 | echo -e "$OUTMSG" >&"${COPROC[1]}" | |
122 | if [[ "$EVLOGFILE" != "" ]]; then | |
123 | echo -e "OUT:\n${OUTMSG}" >> $EVLOGFILE; | |
124 | fi | |
125 | fi | |
126 | ||
127 | ||
128 | for((i=0;i<${#INTARR[@]};i++)); do | |
129 | if [[ "${NHRPEVENT[$EV_INT]}" == "" ]]; then break; fi | |
130 | if [[ "${INTARR[$i]}" != "${NHRPEVENT[$EV_INT]}" ]]; then continue; fi | |
131 | EVINT="${NHRPEVENT[$EV_INT]}" | |
132 | if [[ "${NHRPEVENT[$EV_RADDR]}" == "" ]]; then break; fi | |
133 | if [[ "${NHRPEVENT[$EV_RNBMA]}" == "" ]]; then break; fi | |
134 | if [[ "${NHRPEVENT[$EV_TYPE]}" != "dynamic" ]]; then break; fi | |
135 | ||
136 | INTEXEC=${EXECARR["$EVINT"]} | |
137 | INTABLE=${TABLEARR["$EVINT"]} | |
138 | ||
139 | unset CMD | |
140 | unset CMDEND | |
141 | CMDADD="ip neigh add " | |
142 | CMDREPL="ip neigh replace" | |
143 | CMDBEG="$CMDADD" | |
144 | if [[ "$INTEXEC" != "" ]]; then | |
145 | CMD="$INTEXEC ${NHRPEVENT[$EV_ID]:-nil}" | |
146 | CMD="$CMD ${NHRPEVENT[$EV_TYPE]:-nil}" | |
147 | CMD="$CMD ${NHRPEVENT[$EV_INT]:-nil}" | |
148 | CMD="$CMD ${NHRPEVENT[$EV_LNBMA]:-nil}" | |
149 | CMD="$CMD ${NHRPEVENT[$EV_RADDR]:-nil}" | |
150 | CMD="$CMD ${NHRPEVENT[$EV_RNBMA]:-nil}" | |
151 | CMD="$CMD ${INTABLE:-nil}" | |
152 | unset CMDBEG | |
153 | else | |
154 | CMDTAB="${INTABLE:+${TABLE}${INTABLE}}" | |
155 | CMDEND="$CMDEND ${NHRPEVENT[$EV_RADDR]} dev $EVINT lladdr ${NHRPEVENT[$EV_RNBMA]} nud noarp" | |
156 | CMD="$CMDEND" | |
157 | fi | |
158 | unset CMDTAB | |
159 | for ((k=0;k<2;k++)); do | |
160 | for ((l=0;l<2;l++)); do | |
161 | if [[ "$EVLOGFILE" != "" ]]; then | |
162 | echo "PROG: Executing $CMD" >> $EVLOGFILE | |
163 | CMDOUT=`$CMDBEG $CMD $CMDTAB 2>&1` | |
164 | CMDRET="$?" | |
165 | if [[ "$CMDOUT" != "" ]]; then | |
166 | echo "PROG: Execution output: $CMDOUT" >> $EVLOGFILE | |
167 | fi | |
168 | else | |
169 | $CMDBEG $CMD $CMDTAB | |
170 | fi | |
171 | if [[ "$CMDTAB" == "" ]] || [[ "$INTEXEC" != "" ]]; then break; fi | |
172 | done | |
173 | if [[ "$INTEXEC" != "" ]] || [[ "$CMDRET" == "0" ]]; then | |
174 | break | |
175 | fi | |
176 | CMDBEG="$CMDREPL" | |
177 | done | |
178 | break | |
179 | done | |
180 | ||
181 | unset NHRPEVENT | |
182 | declare -Ag NHRPEVENT | |
183 | continue | |
184 | continue; | |
185 | fi | |
186 | IFS="${IFS}=" | |
187 | SA=($S) | |
188 | IFS="$OLDIFS" | |
189 | eval NHRPEVENT[${SA[0]}]="\"${SA[1]}\"" | |
190 | ||
191 | done <&"${COPROC[0]}" | |
192 | ||
193 | if [[ "$COPROC_PID" != "" ]]; then kill "$COPROC_PID"; fi | |
194 | ||
195 | } | |
196 | ||
197 | while true; do | |
198 | mainloop $* | |
199 | if [[ "$DAEMON" == "0" ]]; then | |
200 | break; | |
201 | fi | |
202 | sleep 10 | |
203 | done |