#!/bin/bash

#	Copyright (c) 2016 Brocade Communications Systems, Inc.
#	All rights reserved.

#	Ethernet Port Monitor - ethif - Use this CLI to display or set the link operating modes.

PATH=/fabos/link_bin:/bin:/usr/bin:/sbin:/usr/sbin:/fabos/link_abin:/fabos/link_sbin:/fabos/link_rbin:/fabos/factory:/fabos/xtool
STS_OK=0
STS_ERR=255

TOTAL_ARGS=0

ETHIF_OPT="help"

INTERFACE=0
value=0
AN_VALUE=0
SPEED_VALUE=0
CAP_VALUE=0
NETSCAN_VALUE=0
NSSCAN_OPT=0
FORCE=0

TIME_VAL=0
new_config=0
RETRY_VAL=0
TCP_PARAM="No"

NS_PARAM="No"

TIME_VAL=0
new_config=0
RETRY_VAL=0
TCP_PARAM="No"

SWBD=`/sbin/sin | /bin/sed -n -e 's/^.\+\(SWBD\)\([[:digit:]]\{1,\}\).\+$/\2/gp' 2> /dev/null`
LINUX_VER=`/bin/uname -r | /usr/bin/cut -c1-6` 
chassis_info=`/bin/getchassisconfig`

ischassis=`echo $chassis_info | \
        sed -n -e 's/.*Chassis based system: //gp' | \
        sed -n -e 's/ .*//gp'`


display_usage() {
	echo
	echo "ethif --show                                       :To display link attributes of all ethernet interfaces"
	echo "ethif --show <interface>                           :To display link attributes of specific ethernet interface"
	echo
	echo "ethif --show -tcptimeoutlevel                      :To display TCP timeout level. (Refer man page for more details)"
	echo
	echo "ethif --show mgmtporttrack -config|-all|           :To display management port tracker attributes and configuration"
	echo "-port <number>|-family [ipv4|ipv6]|"
	echo "-proto [tcp|udp]|-state [active|inactive]|"
	echo "-dump|-backend"
	echo
	echo "ethif --set <interface> -auto-negotiate|           :To set link attributes for specified interface"
	echo "-an [on|off] -speed [10|100|1000] -duplex [full]"
	echo
	echo "ethif --set -tcptimeoutlevel [1|2|3|4|5]           :To set TCP timeout level for half open connections"
	echo
	echo "ethif --set mgmtporttrack -interval <30s-300s>     :To set management port tracker poll interval"
	echo
	echo "ethif [--enable|--disable] mgmtporttrack           :To enable/disable management port tracker feature"
	echo
	if [ ! $LINUX_VER \< "2.6.34" ]; then
		echo "ethif --reseterror <interface>                     :To clear network interface error counters"
		echo
	fi
	echo "ethif --help                                       :To display usage"
	echo	
}

display_mgmtport_usage() {

		echo "Usage:"
		echo "ethif --show mgmtporttrack -all - Displays most recent X number of connections."
		echo "ethif --show mgmtporttrack -port <port> - Displays most recent X number of connections to local port <port>"
		echo "ethif --show mgmtporttrack -proto tcp|udp - Displays most recent X number of tcp/udp connections."
		echo "ethif --show mgmtporttrack -family ipv4|ipv6 - Displays most recent X number of v4/v6 connections."
		echo "ethif --show mgmtporttrack -state active|inactive - Displays X number of current/past connections."
		echo "ethif --show mgmtporttrack -dump - Dumps all the network port connection data to /var/log/mgmtportdump.txt"
		echo "ethif --show mgmtporttrack -config - Display the current configuration state."
		echo "ethif --show mgmtporttrack -backend - Displays most recent backend network connections in case of chassis."
		echo "ethif --enable mgmtporttrack - Enables the mgmtporttrack feature."
		echo "ethif --disable mgmtporttrack - Disables the mgmtporttrack feature."
		echo "ethif --set mgmtporttrack -interval <30s-300s> - Set the interval for querying the network stack to monitor connections."
		exit $STS_ERR
}

process_args() {

	argc=$#
	argv=("$@")
	TOTAL_ARGS=$argc

	for ((i=0;i<$argc;i=$((i+2))))
	do

		opt=${argv[$i]}
		value=${argv[$i+1]}

		if [ $i -eq 0 ]; then

			# Make sure that the first argument is only "show" or "set" or "help"

			if [ "$opt" == "--show" ]; then
				ETHIF_OPT="show"
				if [ "$value" == "-tcptimeoutlevel" ]; then
				  TCP_PARAM="Yes"
				elif [  "$value" == "mgmtporttrack" ]; then
                                  NS_PARAM="Yes"
				else	
				   INTERFACE=$value
				fi
			elif [ "$opt" == "--set" ]; then
				ETHIF_OPT="set"
				if [ "$value" == "-tcptimeoutlevel" ]; then
				      TCP_PARAM="Yes"
				      RETRY_VAL=${argv[$i+2]}
				else
				      INTERFACE=$value
				fi
				
				if [ "$value" == "mgmtporttrack" ]; then
				      NS_PARAM="Yes"
				fi
				#INTERFACE=$value
			elif [ "$opt" == "--reseterror" ]; then
				ETHIF_OPT="reseterror"
				INTERFACE=$value
			elif [ "$opt" == "--enable" ]; then 
				ETHIF_OPT="$opt"
				if [ "$value" == "mgmtporttrack" ]; then
					NS_PARAM="Yes"
				else
				   	return $STS_ERR
				fi
			elif [ "$opt" == "--disable" ]; then
				ETHIF_OPT="$opt"
				if [ "$value" == "mgmtporttrack" ]; then
					NETSCAN_VALUE=""
					NS_PARAM="Yes"
				else
				   	return $STS_ERR
				fi
			elif [ "$opt" == "--help" ]; then
				ETHIF_OPT="help"
			else
				echo "Unsupported option."
				return $STS_ERR
	        fi
			continue

		fi

		if [ "$opt" == "-auto-negotiate" -o "$opt" == "-an" ]; then
			AN_VALUE=$value
		elif [ "$opt" == "-speed" ]; then
			SPEED_VALUE="$value"
		elif [ "$opt" == "-duplex" ]; then
			CAP_VALUE="$value"
		elif [ "$opt" == "-force" ]; then
                        FORCE=1
		elif [ "$opt" == "-dump" ]; then
			NSSCAN_OPT="$opt"
			NETSCAN_VALUE=""
		elif [ "$opt" == "-port" ]; then
			NSSCAN_OPT="$opt"
			NETSCAN_VALUE="$value"
		elif [ "$opt" == "-proto" ]; then
			NSSCAN_OPT="$opt"
			NETSCAN_VALUE="$value"
		elif [ "$opt" == "-family" ]; then
			NSSCAN_OPT="$opt"
			NETSCAN_VALUE="$value"
		elif [ "$opt" == "-state" ]; then
			NSSCAN_OPT="$opt"
			NETSCAN_VALUE="$value"
                elif [ "$opt" == "-interval" ]; then
                        NSSCAN_OPT="$opt"
                        NETSCAN_VALUE="$value"
		elif [ "$opt" == "-all" ]; then
                        NSSCAN_OPT="$opt"
                        NETSCAN_VALUE=""
		elif [ "$opt" == "-config" ]; then
			NSSCAN_OPT="$opt"
			NETSCAN_VALUE=""
		elif [ "$opt" == "-backend" ]; then
			NSSCAN_OPT="$opt"
			NETSCAN_VALUE=""
		else
			return $STS_ERR
		fi

	done

	return $STS_OK
}

validate_args() {

	if [ $TOTAL_ARGS -eq 0 -o $ETHIF_OPT = "help" -a $TOTAL_ARGS -eq 1 ]; then
		return $STS_OK
	fi

	if [ $ETHIF_OPT = "help" -a $TOTAL_ARGS -gt 1 ]; then
		# Make sure that help is not followed by any attributes."
		echo "Unsuppported options for the help command."
		return $STS_ERR
		fi

	if [ "$TCP_PARAM" = "Yes" ]; then
		if [ $ETHIF_OPT = "set" ]; then

			if [ $TOTAL_ARGS -lt 3 ]; then
				echo "TCP timeout level not specified"
				return $STS_ERR

			elif [ "$RETRY_VAL" -ge "1" -a "$RETRY_VAL" -le "5" ]; then
				return $STS_OK
			else
				echo "Unknown or invalid value of TCP timeout level."
				return $STS_ERR
			fi

		elif [ $ETHIF_OPT = "show" ]; then
			return $STS_OK
		fi
	fi
	if [ "$NS_PARAM" = "Yes" ]; then
		if [ $ETHIF_OPT = "set" -o $ETHIF_OPT = "show" ]; then
			if [ $TOTAL_ARGS -lt 3 ]; then
				echo "Invalid number of arguments specified"
				display_mgmtport_usage
			elif [ "$NSSCAN_OPT" = "-port" -o "$NSSCAN_OPT" = "-proto" -o "$NSSCAN_OPT" = "-state" -o "$NSSCAN_OPT" = "-family" -o \
				 "$NSSCAN_OPT" = "-interval" ]; then
				if [ $TOTAL_ARGS -lt 4 ]; then
					echo "Invalid number of arguments specified"
					display_mgmtport_usage
				fi
			fi
			if [ "$NSSCAN_OPT" != "-port" -a "$NSSCAN_OPT" != "-proto" -a "$NSSCAN_OPT" != "-state" -a "$NSSCAN_OPT" != "-family" -a \
				"$NSSCAN_OPT" != "-dump" -a "$NSSCAN_OPT" != "-backend" -a "$NSSCAN_OPT" != "-all" -a \
				"$NSSCAN_OPT" != "-interval" -a "$NSSCAN_OPT" != "-config" ]; then
				echo "Invalid argument specified"
				display_mgmtport_usage
			fi
		fi
		if [ $ETHIF_OPT = "show" -o $ETHIF_OPT = "set" -o $ETHIF_OPT = "--enable" -o $ETHIF_OPT = "--disable" ]; then
			return $STS_OK	
		fi
	fi	
	
	if [ "$ischassis" = "Yes" ]; then
		if [ $ETHIF_OPT = "show" ]; then
			if [ ! -z "$INTERFACE" -a "$INTERFACE" != "eth0" -a "$INTERFACE" != "eth3" -a "$INTERFACE" != "bond0" ]; then
				echo "Interface can only be eth0, eth3 or bond0."
				return $STS_ERR
			fi
		else
			if [ -z "$INTERFACE" -o "$INTERFACE" != "eth0" -a "$INTERFACE" != "eth3" ]; then
				echo "Interface can only be eth0 or eth3."
				return $STS_ERR
			fi
		fi
	else
		if [ $ETHIF_OPT = "show" ]; then
			if [ ! -z "$INTERFACE" -a "$INTERFACE" != "eth0" ]; then
				echo "Interface can only be eth0."
				return $STS_ERR
			fi	
		else
			if [ -z "$INTERFACE" -o "$INTERFACE" != "eth0" ]; then
                                echo "Interface can only be eth0."
                                return $STS_ERR
                        fi
			if [ $ETHIF_OPT = "set" ]; then
				if [ $SWBD == "189" -o $SWBD == "191" ]; then
					echo "Speed configuration is not supported in this platform."
					return $STS_ERR
				fi
			fi
		fi
	fi
	
	if [ $ETHIF_OPT = "reseterror" -a $LINUX_VER \< "2.6.34" ]; then
                echo "Unsupported options for the command."
                return $STS_ERR
        fi
	

	if [ $ETHIF_OPT = "reseterror" -a $TOTAL_ARGS -gt 2 ]; then
                echo "Unsupported options for the command."
                return $STS_ERR
        fi
	

	if [ $ETHIF_OPT = "help" -o $ETHIF_OPT = "show" -o $ETHIF_OPT = "reseterror" ]; then
		# Return as we have completed the validation for help or show or reseterror.
		return $STS_OK
	fi

	if [ $ETHIF_OPT = "set" -a $TOTAL_ARGS -eq 2 ]; then
		return $STS_OK
	fi

	if [ "$AN_VALUE" == "" -o "$AN_VALUE" != "ON" -a "$AN_VALUE" != "OFF" -a "$AN_VALUE" != "on" -a "$AN_VALUE" != "off" ] ; then
		echo "Unknown or invalid value for \"an\"."
		return $STS_ERR
	fi

	if [ "$SPEED_VALUE" == "" -o "$SPEED_VALUE" != "1000" -a "$SPEED_VALUE" != "100" -a "$SPEED_VALUE" != "10" ] ; then
		echo "Unknown or invalid value for \"speed\"."
		return $STS_ERR
	fi

	#Restrict Graphite and Carbon to support only 1G Speed
        if [ $SWBD == "157" -o $SWBD == "158" -o $SWBD == "176" -o $SWBD == "177" ]; then
                if [ $SPEED_VALUE != "1000" ]; then
                        echo "Unknown or invalid value for \"speed\"."
                        return $STS_ERR
                fi
        fi

	if [ "$CAP_VALUE" == "" -o "$CAP_VALUE" != "FULL" -a "$CAP_VALUE" != "full" ] ; then
		echo "Unknown or invalid value for \"cap\"."
		return $STS_ERR

    fi

	return $STS_OK
}

ethif_show() {
	if [ $NS_PARAM = "Yes" ]; then
		if [ $NSSCAN_OPT = "-dump" -o $NSSCAN_OPT = "-backend" ]; then
			if [ $ROLE_ID != "root" ]; then
				echo "Permission denied for $ROLE_ID account"
				return $STS_OK
			fi
		fi
		/fabos/rbin/netscan -$NSSCAN_OPT  $NETSCAN_VALUE
		return $STS_OK	
	fi

	if [ $TCP_PARAM = "Yes" ]; then
		read new_config</proc/sys/net/ipv4/tcp_synack_retries
   	        if [ $new_config == 1 ]; then
                    TIME_VAL=3
           	elif [ $new_config == 2 ]; then
		    TIME_VAL=7
           	elif [ $new_config == 3 ]; then
                    TIME_VAL=15
		elif [ $new_config == 4 ]; then
		    TIME_VAL=31
           	elif [ $new_config == 5 ]; then
                    TIME_VAL=63
                fi
		echo "TCP timeout level : $new_config (~$TIME_VAL seconds)"  
		return $STS_OK
	fi
	echo "$INTERFACE interface:"
	echo

	if [ $INTERFACE = "bond0" ]; then

		# Read the entire output of bond0 and display the slave interfaces
		echo -n "bond0 includes physical interfaces:"
		/bin/cat /proc/net/bonding/bond0 | /bin/grep -i "Slave Interface" |
		while read LINE; do
			INTF=${LINE##*: }
			echo -n " $INTF"
		done

		echo
		ACT_INTF=`/bin/cat /proc/net/bonding/bond0 | /bin/grep -i "Currently Active Slave"`
		ACT_INTF=${ACT_INTF##*: }
		echo "Currently Active Interface: $ACT_INTF"

		# Read the entire output of bond0 and display the interfaces other than Active
		echo -n "Currently Slave Interface:"
		/bin/cat /proc/net/bonding/bond0 | /bin/grep -i "Slave Interface" |
		while read LINE; do
 			INTF=${LINE##*: }
			if [ $INTF != $ACT_INTF ]; then
				echo -n " $INTF "
			fi
		done

		echo

		if [ $ACT_INTF = "None" ]; then
			/fabos/rbin/ifmodeshow "eth0" -support
		else
			# Display the link mode and mac address of curent active interface
			/fabos/rbin/ifmodeshow $ACT_INTF -support
		fi

	else

		/fabos/rbin/ifmodeshow $INTERFACE -support

	fi

	echo

	/sbin/ifconfig $INTERFACE

	return $STS_OK
}

ethif_set() {

	if [ $ETHIF_OPT = "set" -a $TCP_PARAM = "Yes" ]; then
		read new_config</proc/sys/net/ipv4/tcp_synack_retries
		if [ $new_config = $RETRY_VAL ]; then
			echo "No change in configuration. Timeout level already set to $RETRY_VAL"
			return $STS_OK
		fi
#set the proc entry
		echo $RETRY_VAL > /proc/sys/net/ipv4/tcp_synack_retries
   	        if [ $RETRY_VAL == 1 ]; then
                    TIME_VAL=3
           	elif [ $RETRY_VAL == 2 ]; then
		    TIME_VAL=7
           	elif [ $RETRY_VAL == 3 ]; then
                    TIME_VAL=15
		elif [ $RETRY_VAL == 4 ]; then
		    TIME_VAL=31
           	elif [ $RETRY_VAL == 5 ]; then
                    TIME_VAL=63
                fi
		echo "Timeout level changed to $RETRY_VAL (~$TIME_VAL seconds)"
		myFABOS_SWITCHNO=$FABOS_SWITCHNO
		FABOS_SWITCHNO=0;
#set config entry	
	        /fabos/cliexec/config set ipadm.tcptimeoutlevel 2 "$RETRY_VAL"
	        /fabos/cliexec/config update
		FABOS_SWITCHNO=${myFABOS_SWITCHNO};
#audit log
		/fabos/cliexec/errlogtest -i IPAD-1006 -a $RETRY_VAL
#set peer proc entry
           if [ "$ischassis" = "Yes" ]; then
                stby_addr="$(otherhost)"
                #echo $stby_addr
                /usr/bin/rsh $stby_addr "/bin/echo $RETRY_VAL > /proc/sys/net/ipv4/tcp_synack_retries"
           fi
	return $STS_OK

	fi

	if [ $ETHIF_OPT = "set" -a $TOTAL_ARGS -eq 2 ]; then
		/fabos/rbin/ifmodeset $INTERFACE -support
	elif [ $ETHIF_OPT = "set" -a $NS_PARAM == "Yes" ]; then
		/fabos/rbin/netscan -$NSSCAN_OPT $NETSCAN_VALUE
	#elif [ $ETHIF_OPT = "enable" -a $NS_PARAM == "Yes" ]; then
	#	/fabos/rbin/netscan $NSSCAN_OPT
	else
		/fabos/rbin/ifmodeset $INTERFACE -an $AN_VALUE -speed $SPEED_VALUE -cap $CAP_VALUE -force $FORCE -support
	fi

	return $STS_OK
}

#check half duplex support
ethif_duplex_support() {
        for bd in 148 171 141 142 157 158 165 166; do
                if [ $SWBD == "$bd" ]; then
                        return $STS_ERR
                fi
        done
        return $STS_OK
}

ethif_clear() {
	
	echo "Statistics cleared for $INTERFACE"

	echo $INTERFACE > /proc/net/clear-statistics
	if [ "$ischassis" = "Yes" ]; then
		echo "bond0" > /proc/net/clear-statistics
	fi
	
	#record a raslog for reesterror counters
        /fabos/cliexec/errlogtest -i SWCH-1032 -a $INTERFACE
	
	return $STS_OK
} 

ethif_enable_disable() {
        if [ $ETHIF_OPT = "--enable" -o $ETHIF_OPT = "--disable" ]; then
		if [ $NS_PARAM == "Yes" ]; then
                /fabos/rbin/netscan $ETHIF_OPT
		fi		
	fi
	return $STS_OK
}
distname=$(/sbin/sin|grep -i "platform:"|/usr/bin/cut -d" " -f2|/usr/bin/cut -d "," -f 1)
swbdnum=$(/bin/echo $distname | /bin/awk -F"SWBD" '{print $2}')
otherhost(){
 HASHOW="$(hashow)"
 that=${HASHOW#*Remote CP \(Slot}
 that="${that%%,*}"
 otherCpSlot=${that}
   case ${swbdnum} in
     '165' | '166' | '179' | '180')
 	ip=`echo "127.3.1."$otherCpSlot | /bin/awk -F ' ' '{print $1$2}'`
 	printf $ip
 	;;
    *)
	printf 0.0.0.0
	;;
     esac
}

# First perform the rbac check to see whether the command is supported.
/fabos/libexec/rbac_check `/bin/basename $0`
ret=$?
if [ $ret -ne 0 -a $ret -ne 2 ]; then
	exit $STS_ERR
fi

# Now process the args to perform the rbac check for options.
process_args $@
#if [ $? -ne $STS_OK ];then
#	display_usage
#	exit $STS_ERR
#fi

# Perform the rbac check for the options.
/fabos/libexec/rbac_check -opt `/bin/basename $0` $ETHIF_OPT
ret=$?
if [ $ret -ne 0 -a $ret -ne 2 ];then
	exit $STS_ERR
fi

# Validate the args.
validate_args
if [ $? -ne $STS_OK ]; then
	display_usage
	exit $STS_ERR
fi

if [ $ETHIF_OPT = "help" ]; then
	display_usage
elif [ $ETHIF_OPT = "show" ]; then
	if [ -z $INTERFACE ]; then
		if [ "$ischassis" = "Yes" ]; then
			INTERFACE="bond0";
			ethif_show
			INTERFACE="eth0";
			ethif_show
			INTERFACE="eth3";
			ethif_show
		else
			INTERFACE="eth0";
			ethif_show
		fi
	else
		ethif_show
	fi
elif [ $ETHIF_OPT = "set" ]; then
	ethif_set
elif [ $ETHIF_OPT = "reseterror" ]; then
	ethif_clear
elif [ $ETHIF_OPT = "--enable" -o $ETHIF_OPT = "--disable" ]; then
	ethif_enable_disable
else
	echo "Unknown option."
	display_usage
fi

exit $STS_OK
