mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-10-27 17:26:07 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			217 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			217 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/bin/bash
 | |
| 
 | |
| # Author: Joe Maimon
 | |
| # Released to public domain
 | |
| #
 | |
| # This program is free software; you can redistribute it and/or modify it
 | |
| # under the terms of the GNU General Public License as published by the Free
 | |
| # Software Foundation; either version 2 of the License, or (at your option)
 | |
| # any later version.
 | |
| #
 | |
| # This program is distributed in the hope that it will be useful, but WITHOUT
 | |
| # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | |
| # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | |
| # more details.
 | |
| #
 | |
| # You should have received a copy of the GNU General Public License along
 | |
| # with this program; see the file COPYING; if not, write to the Free Software
 | |
| # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 | |
| #
 | |
| 
 | |
| PROGNAME=`basename $0`
 | |
| VERSION="0.0.6"
 | |
| #api fields
 | |
| EV_ID="eventid"
 | |
| EV_TYPE="type"
 | |
| EV_OTYPE="old_type"
 | |
| EV_NUMNHS="num_nhs"
 | |
| EV_INT="interface"
 | |
| EV_LADDR="local_address"
 | |
| EV_VCINIT="vc_initiated"
 | |
| EV_LNBMA="local_nbma"
 | |
| EV_LCERT="local_cert"
 | |
| EV_RADDR="remote_addr"
 | |
| EV_RNBMA="remote_nbma"
 | |
| EV_RCERT="remote_cert"
 | |
| 
 | |
| usage()
 | |
| {
 | |
|         echo "Usage: $PROGNAME [-s nhrp-sock] [-d] [-i interface-name] [-t table] [-e execute-cmd] [-u user] [-g group] [-r] [-l logfile]"
 | |
|         echo ""
 | |
|         echo "-s nhrp-sock file"
 | |
|         echo "-i interface-name to execute on, may be repeated multiple times"
 | |
|         echo "-t tableid to execute on for immdiate preceeding interface"
 | |
|         echo "-e execute command for immmediate preceeding interface"
 | |
|         echo "   The command will be passed the following arguments $EV_ID $EV_TYPE $EV_INT $EV_LNMBA $EV_RADDR $EV_RNBMA int_table"
 | |
|         echo "-u user to own the sock"
 | |
|         echo "-g group to own the sock"
 | |
|         echo "-r send rejection (testing)"
 | |
|         echo "-l logfile to record conversation with nhrpd"
 | |
|         echo "-d daemonize"
 | |
| 
 | |
|         exit 1
 | |
| }
 | |
| 
 | |
| declare -A EXECARR
 | |
| declare -A TABLEARR
 | |
| declare -Ag NHRPEVENT
 | |
| SOCK="/var/run/frr/nhrp.sock"
 | |
| USER="frr"
 | |
| GROUP="frr"
 | |
| DAEMON=0
 | |
| j=0
 | |
| RESULT="accept"
 | |
| 
 | |
| while getopts rds:i:u:g:l:t:e: opt; do
 | |
|         case "$opt" in
 | |
|                 d)
 | |
|                         DAEMON=1
 | |
|                         ;;
 | |
|                 s)
 | |
|                         SOCK="$OPTARG"
 | |
|                         ;;
 | |
|                 i)
 | |
|                         INTARR[((j++))]="$OPTARG"
 | |
|                         ;;
 | |
|                 e)
 | |
|                         if [[ "$j" == "0" ]] || [[ "${INTARR[((j-1))]}" == "" ]]; then
 | |
|                                 echo "execute argument must follow interface argument"
 | |
|                                 usage
 | |
|                         fi
 | |
|                         EXECARR["${INTARR[((j-1))]}"]="$OPTARG"
 | |
|                         ;;
 | |
|                 t)
 | |
|                         if [[ "$j" == "0" ]] || [[ "${INTARR[((j-1))]}" == "" ]]; then
 | |
|                                 echo "execute argument must follow interface argument"
 | |
|                                 usage
 | |
|                         fi
 | |
|                         TABLEARR["${INTARR[((j-1))]}"]="$OPTARG"
 | |
|                         ;;
 | |
|                 u)
 | |
|                         USER="$OPTARG"
 | |
|                         ;;
 | |
|                 g)
 | |
|                         GROUP="$OPTARG"
 | |
|                         ;;
 | |
|                 r)
 | |
|                         RESULT="reject"
 | |
|                         ;;
 | |
|                 l)
 | |
|                         EVLOGFILE="${OPTARG}"
 | |
|                         ;;
 | |
|         esac;
 | |
| done
 | |
| 
 | |
| if [[ "$EVLOGFILE" != "" ]]; then
 | |
|         if [[ ! -w "${EVLOGFILE}" ]]; then
 | |
|                 touch "$EVLOGFILE" || ( echo "Cannot write to logfile $EVLOGFILE" ; usage )
 | |
|         fi
 | |
|         echo -e "PROG: $0 Startup\nPROG: Arguments $*" >> $EVLOGFILE
 | |
| fi
 | |
| 
 | |
| 
 | |
| function mainloop()
 | |
| {
 | |
| 
 | |
| if [[ "$EVLOGFILE" != "" ]]; then
 | |
|         echo -e "PROG: `date -R`\nPROG: Starting mainloop" >> $EVLOGFILE
 | |
| fi
 | |
| 
 | |
| coproc socat - UNIX-LISTEN:$SOCK,unlink-early,setuid-early=$USER,unlink-close=0 || exit 1
 | |
| test -S $SOCK && chown $USER:$GROUP $SOCK
 | |
| 
 | |
| OLDIFS="$IFS"
 | |
| 
 | |
| TABLE="table "
 | |
| 
 | |
| while read -r S; do
 | |
|         if [[ "$EVLOGFILE" != "" ]]; then
 | |
|                 echo "IN: $S" >> $EVLOGFILE
 | |
|         fi
 | |
|         if [[ "$S" == "" ]]; then
 | |
|                 if [[ "${NHRPEVENT[$EV_ID]}" != "" ]]; then
 | |
|                         OUTMSG="eventid=${NHRPEVENT[$EV_ID]}\nresult=$RESULT\n"
 | |
|                         echo -e "$OUTMSG" >&"${COPROC[1]}"
 | |
|                         if [[ "$EVLOGFILE" != "" ]]; then
 | |
|                                 echo -e "OUT:\n${OUTMSG}" >> $EVLOGFILE;
 | |
|                         fi
 | |
|                 fi
 | |
| 
 | |
| 
 | |
|                 for((i=0;i<${#INTARR[@]};i++)); do
 | |
|                         if [[ "${NHRPEVENT[$EV_INT]}" == "" ]]; then break; fi
 | |
|                         if [[ "${INTARR[$i]}" != "${NHRPEVENT[$EV_INT]}" ]]; then continue; fi
 | |
|                         EVINT="${NHRPEVENT[$EV_INT]}"
 | |
|                         if [[ "${NHRPEVENT[$EV_RADDR]}" == "" ]]; then break; fi
 | |
|                         if [[ "${NHRPEVENT[$EV_RNBMA]}" == "" ]]; then break; fi
 | |
|                         if [[ "${NHRPEVENT[$EV_TYPE]}" != "dynamic" ]]; then break; fi
 | |
| 
 | |
|                         INTEXEC=${EXECARR["$EVINT"]}
 | |
|                         INTABLE=${TABLEARR["$EVINT"]}
 | |
| 
 | |
|                         unset CMD
 | |
|                         unset CMDEND
 | |
|                         CMDADD="ip neigh add "
 | |
|                         CMDREPL="ip neigh replace"
 | |
|                         CMDBEG="$CMDADD"
 | |
|                         if [[ "$INTEXEC" != "" ]]; then
 | |
|                                 CMD="$INTEXEC ${NHRPEVENT[$EV_ID]:-nil}"
 | |
|                                 CMD="$CMD ${NHRPEVENT[$EV_TYPE]:-nil}"
 | |
|                                 CMD="$CMD ${NHRPEVENT[$EV_INT]:-nil}"
 | |
|                                 CMD="$CMD ${NHRPEVENT[$EV_LNBMA]:-nil}"
 | |
|                                 CMD="$CMD ${NHRPEVENT[$EV_RADDR]:-nil}"
 | |
|                                 CMD="$CMD ${NHRPEVENT[$EV_RNBMA]:-nil}"
 | |
|                                 CMD="$CMD ${INTABLE:-nil}"
 | |
|                                 unset CMDBEG
 | |
|                         else
 | |
|                                 CMDTAB="${INTABLE:+${TABLE}${INTABLE}}"
 | |
|                                 CMDEND="$CMDEND ${NHRPEVENT[$EV_RADDR]} dev $EVINT lladdr ${NHRPEVENT[$EV_RNBMA]} nud noarp"
 | |
|                                 CMD="$CMDEND"
 | |
|                         fi
 | |
|                         unset CMDTAB
 | |
|                         for ((k=0;k<2;k++)); do
 | |
|                                 for ((l=0;l<2;l++)); do
 | |
|                                         if [[ "$EVLOGFILE" != "" ]]; then
 | |
|                                                 echo "PROG: Executing $CMD" >> $EVLOGFILE
 | |
|                                                         CMDOUT=`$CMDBEG $CMD $CMDTAB 2>&1`
 | |
|                                                         CMDRET="$?"
 | |
|                                                         if [[ "$CMDOUT" != "" ]]; then
 | |
|                                                                 echo "PROG: Execution output: $CMDOUT" >> $EVLOGFILE
 | |
|                                                         fi
 | |
|                                         else
 | |
|                                                 $CMDBEG $CMD $CMDTAB
 | |
|                                         fi
 | |
|                                         if [[ "$CMDTAB" == "" ]] || [[ "$INTEXEC" != "" ]]; then break; fi
 | |
|                                 done
 | |
|                                 if [[ "$INTEXEC" != "" ]] || [[ "$CMDRET" == "0" ]]; then
 | |
|                                         break
 | |
|                                 fi
 | |
|                                 CMDBEG="$CMDREPL"
 | |
|                         done
 | |
|                         break
 | |
|                 done
 | |
| 
 | |
|                 unset NHRPEVENT
 | |
|                 declare -Ag NHRPEVENT
 | |
|                 continue
 | |
|                 continue;
 | |
|         fi
 | |
|         IFS="${IFS}="
 | |
|         SA=($S)
 | |
|         IFS="$OLDIFS"
 | |
|         eval NHRPEVENT[${SA[0]}]="\"${SA[1]}\""
 | |
| 
 | |
| done <&"${COPROC[0]}"
 | |
| 
 | |
| if [[ "$COPROC_PID" != "" ]]; then kill "$COPROC_PID"; fi
 | |
| 
 | |
| }
 | |
| 
 | |
| while true; do
 | |
|         mainloop $*
 | |
|         if [[ "$DAEMON" == "0" ]]; then
 | |
|                 break;
 | |
|         fi
 | |
|         sleep 10
 | |
| done
 | 
