lede-packages-rs

git clone git://archive.git.mtrnord.blog/MTRNord/lede-packages-rs.git
Log | Files | Refs | README | LICENSE

mini_snmpd.init (10010B)


      1 #!/bin/sh /etc/rc.common
      2 # Copyright (C) 2009-2016 OpenWrt.org
      3 # Copyright (C) 2016 Luke McKee <hojuruku@gmail.com>
      4 # Procd init script reference: http://wiki.prplfoundation.org/wiki/Procd_reference
      5 
      6 START=98
      7 USE_PROCD=1
      8 PROG=/usr/bin/mini_snmpd
      9 NAME=mini_snmpd
     10 
     11 _log() {
     12         logger -p daemon.info -t mini_snmpd "$@"
     13 }
     14 
     15 _err() {
     16         logger -p daemon.err -t mini_snmpd "$@"
     17 }
     18 
     19 
     20 # mini_snmpd 1.3+ now starts later in the game. Expects filesystems monitored to be already mounted, or wont pass args to mini_snmpd 
     21 # and at least configuration entry for network physical interface defined in /etc/config/network
     22 # It handles network interfaces not yet present (e.g. ppp) but will statfs() the root/wrong filesystem if device not mounted
     23 # Tip: complex scripts run faster without in openwrt if you stop busybox forking and searching for applets. Faster bootups
     24 #	CONFIG_BUSYBOX_CONFIG_FEATURE_SH_NOFORK
     25 # 	CONFIG_BUSYBOX_CONFIG_FEATURE_PREFER_APPLETS
     26 # 	BUSYBOX_CONFIG_ASH_OPTIMIZE_FOR_SIZE [=n]
     27 #	CONFIG_BUSYBOX_CONFIG_ASH_CMDCMD
     28 
     29 mini_snmpd_validation="enabled:bool:0 \
     30 		ipv6:bool:0 \
     31 		debug:bool:0 \
     32 		auth:bool:1 \
     33 		community:rangelength(1,32):public \
     34 		contact:maxlength(255) \
     35 		location:maxlength(255) \
     36 		listen_interface:uciname \
     37 		udp_port:port \
     38 		tcp_port:port \
     39 		vendor_oid:string \
     40 		mib_timeout:and(min(1),uinteger) \
     41 		disks:list(directory) \
     42 		interfaces:list(uciname) \
     43 		respawn_threshold:uinteger respawn_timeout:uinteger respawn_retry:uinteger"
     44 # busybox ash has no array variable support, when put validations in a string be careful to have no spaces in each validate constraint
     45 # this makes it very difficult to use the 'or(uciname, "all")' test, so listen_interface '' or undefined now meands bind to "all".
     46 # this is the sarafice you have to make to avoid typing it all in twice in this script so we can give feedback to user on what's misconfigered
     47 # in syslog
     48 
     49 append_disk() {
     50 	local disk="$1" disk_count
     51 	[ -z $disk_count ] && disk_count=0
     52 	if grep -qF "$disk" /proc/mounts ; then
     53 		# check the fileystem is mountpoint, and directory search permissions available for statfs()
     54 		# presence as a directory -d test done is already done by uci_validate_section()
     55 		[ -x "$disk" ] || {
     56 			_err "$cfg: mountpoint $disk for snmp monitoring EACCES error. Check permissions, ignoring"
     57 			return 1
     58 		}
     59 		if [ $disk_count -lt 4 ] ;  then  
     60 			append disks_arg "$disk" ','
     61 			disk_count=$((disk_count++))
     62 		else
     63 			_err "$cfg: more than 4 mountpoints defined in uci. Disc $disk ignored."
     64 		fi
     65 	else
     66 		_err "$cfg: mountpoint $disk for snmp monitoring not mounted, ignoring."
     67 	fi
     68 }
     69 
     70 append_interface() {
     71 	local name="$1" netdev netdev_count
     72 	[ -z $netdev_count ] && netdev_count=0
     73 	# for the purposes of snmp monitoring it doesn't need to be up, it just needs to exist in /proc/net/dev
     74 	netdev=$(ubus -S call network.interface dump|jsonfilter -e "@.interface[@.interface=\"$name\"].l3_device")  
     75 	if [ -n "$netdev" ] && grep -qF "$netdev" /proc/net/dev ]; then 
     76 		[ $netdev_count -ge 4 ] && {
     77 			_err "$cfg: too many network interfaces configured, ignoring $name"
     78 			return
     79 		}
     80 		netdev_count=$((netdev_count++))	
     81 		if [ -n "$interfaces_arg" ]; then	
     82 			append interfaces_arg "$netdev" ','
     83 		else	
     84 			append interfaces_arg "$netdev"
     85 		fi
     86 	else
     87 		 _err "$cfg: physical interface for network $name not found in uci or kernel so not monitoring"
     88 	fi
     89 }
     90 
     91 append_arg() {
     92 	local var="$2"
     93 	local opt="$1"
     94 	[ -n "$var" ] && procd_append_param command $opt "$var"
     95 }
     96 
     97 watch_interfaces() {
     98 	local cfg="$1"
     99 	local enabled listen_interface # listen_interface_up
    100 	config_get_bool enabled "$cfg" "enabled" '1'
    101 	[ "$enabled" -gt 0 ] || return 0
    102 	config_get listen_interface "$cfg" listen_interface
    103 	# listen_interface_up=$(ubus -S call network.interface dump | jsonfilter -e "@.interface[@.interface=\"$listen_interface\"].up")
    104 	# If the interface is up & instance is running we'll watch at the instance level and only restart that instance if it's bound interface changes
    105 	# Regardless of ubus knowing about an interface (in the case it's not yet configured)
    106 	[ -n "$listen_interface" ] && trigger_interfaces="${listen_interface} ${trigger_interfaces} "
    107 }
    108 
    109 validate_mini_snmpd_section() {
    110 	# validate a mini_snmpd instance in uci config file mini_snmpd
    111 	# http://luci.subsignal.org/trac/wiki/Documentation/Datatypes ubox/validate/validate.c
    112 	uci_validate_section mini_snmpd mini_snmpd "${1}" $mini_snmpd_validation
    113 }
    114 
    115 
    116 service_triggers() {
    117         config_load 'mini_snmpd'
    118         procd_open_trigger
    119         procd_add_config_trigger "config.change" "mini_snmpd" /etc/init.d/mini_snmpd reload
    120         config_foreach watch_interfaces 'mini_snmpd' 
    121 	# this only watches interfaces for which there is no running instance due to interface down / not in ubus
    122 	# hence start not reload, this trigger will not affect running instances as another start will not change their procd command arguments
    123 	# or stop the already running process
    124         [ -n "$trigger_interfaces" ] & {
    125                 for n in $trigger_interfaces ; do
    126 			procd_add_interface_trigger "interface.*" $n /etc/init.d/mini_snmpd start
    127                 done
    128         }
    129         procd_close_trigger
    130 	procd_add_validation validate_mini_snmpd_section
    131 }
    132 
    133 
    134 start_instance() {
    135 	local cfg validation_failed validation_err disks_arg interfaces_arg
    136 	cfg="$1"	
    137 	#uci_validate_section should unset undefined variables from other instances
    138 	#however defining uci variables as local will scope them to this instance
    139 	#"local variables are also visible to functions called by the parent function" so it's good practice
    140 	local enabled ipv6 debug auth community contact location listen_interface \
    141 		udp_port tcp_port vendor_oid mib_timeout
    142 	local disks="" interfaces=""
    143 	validate_mini_snmpd_section "$cfg" 2>/dev/null || validation_failed=1
    144 	[ "$enabled" == 1 ] || { 
    145 		_log "instance:$cfg disabled not starting" 
    146 		 return 1
    147 	}
    148 	
    149 	local listen_interface_json listen_interface_ip listen_interface_device listen_interface_up ubus_exit ubus_err
    150 	[ -n "$listen_interface" ] && {
    151 		listen_interface_json=$(ubus -S call network.interface.$listen_interface status)
    152 		ubus_exit=$?
    153 		[ $ubus_exit = 4 ] && {
    154 			_err "$cfg: listen_interface $listen_interface not properly configured in ubus network.interface.* not starting this instance "
    155 			return 1
    156 		}
    157 		[ $ubus_exit = 255 -a -z "$listen_interface_json" ] && { 
    158 			_log "$cfg: ubusd not yet up, will try to start mini_snmpd shorlty when procd detects $listen_interface comes up"
    159 			return 1
    160 		}
    161 		[ -z "$listen_interface_json" ] && { 
    162 			ubus_err=`ubus call network.interface.$listen_interface status 2>&1 >/dev/null`
    163 			_err "$cfg: unknown ubus error. exit: $ubus_exit errormsg: $ubus_err "
    164 			return 1
    165 		}
    166 		listen_interface_up=$(jsonfilter -s "$listen_interface_json" -e '@.up')
    167 		if [ "$ipv6" = 1 ]; then
    168 			listen_interface_ip=$(jsonfilter -s "$listen_interface_json" -e "@['ipv6-address'][0].address")
    169 		else
    170 			listen_interface_ip=$(jsonfilter -s "$listen_interface_json" -e "@['ipv4-address'][0].address")
    171 		fi
    172 		[ -n "$listen_interface_ip" -a "$listen_interface_up" = 'true' ] || {
    173 			_log "$cfg:listen interface $listen_interface not up yet / not configured properly"
    174 			_log "$cfg:procd will try again when interface state changes"
    175 			return 1
    176 		}
    177 		listen_interface_device=$(jsonfilter -s "$listen_interface_json" -e '@.l3_device')
    178 	}
    179 
    180 	[ $validation_failed ] && {  
    181 		_err "validation of $NAME configuration for $cfg instance failed, all tests should be within constraints"
    182 		_err "please edit the configuration values below using [l]uci "
    183 		validation_err=`/sbin/validate_data mini_snmpd mini_snmpd "$cfg" $mini_snmpd_validation 2>&1 | sed '/with\ false$/!d;s/validates\ as\ /needs\ to\ be\ /;s/with\ false//' `
    184 		_err "${validation_err}"
    185 		return 1
    186 	}
    187 	config_list_foreach "$cfg" 'disks' append_disk
    188 	config_list_foreach "$cfg" 'interfaces' append_interface
    189 	# test if variables are unset or zero length
    190 	[ -z "${disks_arg:+1}" -a -z "${interfaces_arg:+1}" ] && {
    191 		_err "$cfg: you haven't sucessfully configured any mountpoints or disks for this instance, not starting"
    192 		return 1
    193 	}
    194 	
    195 	procd_open_instance
    196 
    197 	procd_set_param command "$PROG" -n
    198  	procd_set_param stdout "1"
    199 	procd_set_param stderr "1"
    200 	# don't the like default respawn values? you can override through uci.
    201 	# vars left as global so you only need to do it in the first mini_snmpd instance
    202 	procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-10} ${respawn_retry:-1}
    203 	# this monitors ubus changes
    204 	[ -n "$listen_interface" ] && {
    205 		 #procd_open_trigger
    206 		 #procd_add_interface_trigger "interface.*" $listen_interface /etc/init.d/mini_snmpd reload 
    207 		 #procd_close_trigger
    208 		 procd_add_reload_interface_trigger $listen_interface #or use shorthand of above
    209 	}
    210 	# this re-starts the daemon if a properly configured network interface is changed whilst it is already running
    211 	# igmpproxy has this as well as "procd_set_param netdev" 
    212 
    213 	append_arg "-c" "$community" 
    214 	append_arg "-L" "${location}"
    215 	append_arg "-C" "${contact}" 
    216 	append_arg "-p" $udp_port  
    217 	append_arg "-P" $tcp_port  
    218 	append_arg "-V" "${vendor_oid}"  
    219 	append_arg "-t" $mib_timeout 
    220 	
    221 	[ "$ipv6" = 1  ] && procd_append_param command "-6"
    222 	[ "$debug" = 1 ] && procd_append_param command "-v"
    223 	# uci_validate_section() aka /sbin/validate_data can only cast default values not defined in /etc/config/* to string 
    224 	# e.g. ="1" however it sets bools defined in /etc/config/* to =1 / =0
    225 	[ "$auth" = 1 -o "$auth" = "1" ] && procd_append_param command "-a"
    226 	[ -n "$disks_arg" ] && procd_append_param command "-d $disks_arg" 
    227 	[ -n "$interfaces_arg" ] && procd_append_param command "-i $interfaces_arg"
    228 	[ -n "$listen_interface_device" ] && {
    229 		 procd_append_param command "-I" "$listen_interface_device"
    230 		 # and this monitors the hardware device for changes outside of ubus - just a guess
    231 		 procd_set_param netdev $listen_interface_device
    232 	}
    233 	procd_close_instance
    234 }
    235 
    236 start_service() {
    237 	config_load 'mini_snmpd'
    238 	config_foreach start_instance 'mini_snmpd'
    239 }
    240