Compare commits

...

1 Commits

Author SHA1 Message Date
vdutta
afba559956 icwmp: Fix race condition in dhcp ACS provisioning 2021-11-26 15:55:32 +05:30
6 changed files with 113 additions and 192 deletions

View File

@@ -8,7 +8,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=icwmp
PKG_VERSION:=8.2.11-2021-11-23
PKG_VERSION:=8.2.12-2021-11-26
PKG_FIXUP:=autoreconf
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/icwmp.git
PKG_SOURCE_PROTO:=git
@@ -82,19 +82,18 @@ define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/etc/icwmpd
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_DIR) $(1)/etc/hotplug.d/iface
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_DIR) $(1)/etc/uci-defaults
$(INSTALL_DIR) $(1)/lib/upgrade/keep.d
$(INSTALL_BIN) $(PKG_BUILD_DIR)/bin/icwmpd $(1)/usr/sbin/icwmpd
$(INSTALL_DATA) ./files/etc/config/cwmp $(1)/etc/config/cwmp
$(INSTALL_BIN) ./files/etc/firewall.cwmp $(1)/etc/firewall.cwmp
$(INSTALL_BIN) ./files/etc/hotplug.d/iface/99-icwmp $(1)/etc/hotplug.d/iface/99-icwmp
$(INSTALL_BIN) ./files/etc/init.d/icwmpd $(1)/etc/init.d/icwmpd
$(INSTALL_BIN) ./files/etc/uci-defaults/85-cwmp-set-userid $(1)/etc/uci-defaults/
$(INSTALL_BIN) ./files/etc/uci-defaults/90-cwmpfirewall $(1)/etc/uci-defaults/
$(INSTALL_BIN) ./files/etc/uci-defaults/95-icwmp-generate-ssl $(1)/etc/uci-defaults/
$(INSTALL_DATA) ./files/lib/upgrade/keep.d/icwmp $(1)/lib/upgrade/keep.d/icwmp
$(INSTALL_BIN) ./files/etc/icwmpd/update.sh $(1)/etc/icwmpd/update.sh
endef
$(eval $(call BuildPackage,$(PKG_NAME)))

View File

@@ -1,5 +1,4 @@
config acs 'acs'
option url ''
option userid '' #$OUI-$SER
option passwd 'iopsys'
option periodic_inform_enable 'true'

View File

@@ -1,128 +0,0 @@
#!/bin/sh
. /lib/functions/network.sh
[ "$ACTION" == "ifup" -o "$ACTION" == "ifupdate" ] || exit 0
[ -f /etc/config/cwmp ] || exit 0
handle_icwmp_restart() {
[ -f /tmp/switching_mode ] && exit 0
[ -f /tmp/wificontrol.txt -a -f /tmp/netmode-conf.pid ] && exit 0
[ "$INTERFACE" == "loopback" ] && exit 0
local defwan=$(uci -q get cwmp.cpe.default_wan_interface)
[ -n "$defwan" -a "$(uci -q get network.$defwan)" == "interface" -a "$defwan" != "$INTERFACE" ] && exit 0
local islan="$(uci -q get network.$INTERFACE.is_lan)"
[ "$islan" == "1" ] && exit 0
local proto="$(uci -q get network.$INTERFACE.proto)"
[ "$proto" == "none" ] && exit 0
local ifname="$(uci -q get network.$INTERFACE.ifname)"
[ "${ifname:0:1}" == "@" ] && exit 0
mkdir -p /tmp/ipv4
network_flush_cache
local previpaddr=""
local curipaddr=""
local ipaddrfile=/tmp/ipv4/$INTERFACE-ipaddr
previpaddr=$(cat $ipaddrfile 2>/dev/null)
network_get_ipaddr curipaddr $INTERFACE
[ -n "$curipaddr" ] && echo $curipaddr > $ipaddrfile || rm -f $ipaddrfile
local prevgateway=""
local curgateway=""
local gatewayfile=/tmp/ipv4/$INTERFACE-gateway
prevgateway=$(cat $gatewayfile 2>/dev/null)
network_get_gateway curgateway $INTERFACE
[ -n "$curgateway" ] && echo $curgateway > $gatewayfile || rm -f $gatewayfile
local prevsubnets=""
local cursubnets=""
local subnetsfile=/tmp/ipv4/$INTERFACE-subnets
prevsubnets=$(cat $subnetsfile 2>/dev/null)
network_get_subnets cursubnets $INTERFACE
[ -n "$cursubnets" ] && echo $cursubnets > $subnetsfile || rm -f $subnetsfile
local prevdnsservers=""
local curdnsservers=""
local dnsserverfile=/tmp/ipv4/$INTERFACE-dnsservers
prevdnsservers=$(cat $dnsserverfile 2>/dev/null)
network_get_dnsserver curdnsservers $INTERFACE
[ -n "$curdnsservers" ] && echo $curdnsservers > $dnsserverfile || rm -f $dnsserverfile
local prevdev=""
local curdev=""
local devfile=/tmp/ipv4/$INTERFACE-dev
prevdev=$(cat $devfile 2>/dev/null)
network_get_device curdev $INTERFACE
[ -n "$curdev" ] && echo $curdev > $devfile || rm -f $devfile
if [ ! -f /var/state/cwmp ]
then
if [ -f /etc/icwmpd/cwmp ]
then
uci -c /etc/icwmpd delete cwmp.acs
uci -c /etc/icwmpd commit cwmp
cp /etc/icwmpd/cwmp /var/state/cwmp
else
touch /var/state/cwmp
fi
fi
uci -q -c /var/state/ get cwmp.cpe
if [ "$?" -ne 0 ]; then
unnamedcpe=`uci -q -c /var/state/ add cwmp cpe`
uci -c /var/state/ -q rename cwmp.$unnamedcpe='cpe'
fi
local vendorspecinf=`ubus call network.interface.${defwan} status | jsonfilter -e "@.data.vendorspecinf"`
[ -n "$vendorspecinf" ] && {
local url=""
case $vendorspecinf in
http://*|https://*)
url="$vendorspecinf"
;;
*)
for optval in $vendorspecinf; do
case $optval in
1=*)
url="$(echo $optval | cut -d"=" -f2-)"
;;
esac
done
;;
esac
[ -n "$url" ] && uci -q set cwmp.acs.dhcp_url="$url"
uci commit cwmp
}
local prevopt43url=""
local curopt43url=""
local opt43urlfile=/tmp/ipv4/$INTERFACE-opt43url
prevopt43url=$(cat $opt43urlfile 2>/dev/null)
curopt43url="$(uci -c /var/state -q get cwmp.acs.dhcp_url)"
[ -n "$curopt43url" ] && echo $curopt43url > $opt43urlfile || rm -f $opt43urlfile
[ \
"$prevdev" == "$curdev" -a \
"$previpaddr" = "$curipaddr" -a \
"$prevgateway" = "$curgateway" -a \
"$prevsubnets" = "$cursubnets" -a \
"$prevdnsservers" = "$curdnsservers" \
] && {
[ "$prevopt43url" = "$curopt43url" ] && exit 0
[ -z "$prevopt43url" ] && exit 0
}
echo "Restarting icwmp"|logger -t cwmp.hotplug -p info
/etc/init.d/icwmpd reload &
}
handle_icwmp_restart

View File

@@ -0,0 +1,42 @@
#!/bin/sh
log() {
echo $@ |logger -t cwmp.update -p info
}
handle_icwmp_update() {
local defwan=$(uci -q get cwmp.cpe.default_wan_interface)
local vendorspecinf=`ubus call network.interface.${defwan} status | jsonfilter -e "@.data.vendorspecinf"`
log "Handling dhcp option value ${vendorspecinf}"
[ -n "$vendorspecinf" ] && {
local url=""
local old_url=$(uci -q get cwmp.acs.dhcp_url)
case $vendorspecinf in
http://*|https://*)
url="$vendorspecinf"
;;
*)
for optval in $vendorspecinf; do
case $optval in
1=*)
url="$(echo $optval | cut -d"=" -f2-)"
;;
esac
done
;;
esac
if [ -n "$url" ]; then
log "## icwmp url[${old_url}] changed to [${url}]"
if [ -z "${old_url}" -o "${url}" != "${old_url}" ]; then
log "Restarting icwmp url[${old_url}] changed to [${url}]"
uci -q set cwmp.acs.dhcp_url="$url"
ubus call uci commit '{"config":"cwmp"}'
fi
fi
}
}
handle_icwmp_update

View File

@@ -16,7 +16,7 @@ log() {
}
enable_dhcp_option43() {
local wan=$1
local wan="${1}"
### Ask for DHCP Option 43 only if CWMP is enabled ###
local reqopts="$(uci -q get network.$wan.reqopts)"
@@ -43,25 +43,6 @@ enable_dhcp_option43() {
fi
}
wait_for_option43() {
local time=$1
local tm=0
log "Waiting for discovery of ACS URL from dhcp server ..."
while [ $tm -le $time ]
do
acs_url=`uci -q get cwmp.acs.dhcp_url`
if [ "$acs_url" != "" ]
then
break
else
sleep 1
fi
tm=$((tm+1))
done
}
wait_for_resolvfile() {
local time=$1
local tm=1
@@ -76,11 +57,23 @@ wait_for_resolvfile() {
done
}
set_wan_interface() {
local l3_device=""
local default_wan_interface=""
get_default_wan_interface() {
local default_wan_interface
config_load cwmp
config_get default_wan_interface cpe default_wan_interface "wan"
echo ${default_wan_interface}
}
set_wan_interface() {
local wan_interface="${1}"
local l3_device=""
if [ -z "${wan_interface}" ]; then
return 0;
fi
json_load "$(ifstatus $default_wan_interface)"
json_get_var l3_device l3_device
if [ "$l3_device" != "" ];then
@@ -101,7 +94,7 @@ copy_cwmp_etc_files_to_varstate() {
touch /var/state/cwmp
fi
fi
mkdir -p /var/state/icwmpd
if [ -f /etc/icwmpd/.icwmpd_backup_session.xml ]
then
@@ -135,14 +128,15 @@ validate_acs_section()
'periodic_inform_enable:bool' \
'periodic_inform_interval:uinteger' \
'periodic_inform_time:string' \
'url:string:http://192.168.1.1' \
'url:string' \
'dhcp_url:string' \
'dhcp_discovery:or("enable", "disable")' \
'compression:or("GZIP","Deflate","Disabled")' \
'retry_min_wait_interval:range(1, 65535)' \
'retry_interval_multiplier:range(1000, 65535)' \
'https_ssl_capath:file' \
'ipv6_enable:bool'
}
validate_cpe_section()
@@ -166,7 +160,7 @@ validate_cpe_section()
'exec_download:bool' \
'periodic_notify_enable:bool' \
'enable:bool' \
'periodic_notify_interval:uinteger'
'periodic_notify_interval:uinteger'
}
validate_defaults() {
@@ -177,6 +171,11 @@ validate_defaults() {
return 1;
}
[ -z "${url}" -a -z "${dhcp_url}" ] && {
log "ACS url is empty can't start"
return 1;
}
validate_cpe_section || {
log "Validation of cpe section failed"
return 1;
@@ -190,56 +189,48 @@ validate_defaults() {
return 0;
}
validate_acs_url() {
dhcp_url=`uci -q get cwmp.acs.dhcp_url`
[ -z "${url}" -a -z "${dhcp_url}" ] && {
log "ACS url is empty"
return 1;
}
return 0
}
start_service() {
enable_cwmp=`uci -q get cwmp.cpe.enable`
local enable_cwmp=`uci -q get cwmp.cpe.enable`
local wan_interface=$(get_default_wan_interface)
local dhcp_discovery=`uci -q get cwmp.acs.dhcp_discovery`
if [ "$enable_cwmp" = "0" -o "$enable_cwmp" = "false" ]; then
log "CWMP is not enabled"
return
return 0
fi
log "## Enable ${enable_cwmp}, wan ${wan_interface}, dhcp ${dhcp_discovery}"
# Set wan interface if not configured
set_wan_interface "${wan_interface}"
# Set dhcp option 43 if dhcp discovery enabled
if [ "${dhcp_discovery}" == "enable" -o "${dhcp_discovery}" == "1" ]; then
enable_dhcp_option43 "${wan_interface}"
fi
[ -f /sbin/netifd ] && log "Waiting for Network to be started ..." && ubus -t 5 wait_for network.interface
[ -f /usr/sbin/dnsmasq ] && log "Waiting for DNS Proxy to be started ..." && ubus -t 5 wait_for dnsmasq
[ -f /etc/config/dhcp ] && log "Waiting for DNS Server(s) ..." && wait_for_resolvfile 20
log "Waiting for usp.raw to be started"
ubus wait_for usp.raw
# Copy backup data so that if it restart latter on it gets the info
copy_cwmp_etc_files_to_varstate
validate_defaults || {
log "Validation of defaults failed"
return 1;
}
# Set wan interface if not configured
set_wan_interface
# Set dhcp option 43 if dhcp discovery enabled
if [ "${dhcp_discovery}" == "enable" -o "${dhcp_discovery}" == "1" ]; then
enable_dhcp_option43 $default_wan_interface
wait_for_option43 30
fi
validate_acs_url || {
log "Validation of ACS URL failed"
return 1;
}
copy_cwmp_etc_files_to_varstate
procd_open_instance icwmp
procd_set_param command "$PROG"
procd_append_param command -b
procd_set_param respawn \
${respawn_threshold:-5} \
${respawn_timeout:-10} ${respawn_retry:-3}
procd_set_param watch network.interface
procd_close_instance
}
@@ -249,11 +240,25 @@ stop_service()
}
reload_service() {
log "Restarting CWMP client"
stop
start
}
service_triggers() {
procd_add_config_trigger "config.change" "cwmp" /etc/init.d/icwmpd reload
procd_add_reload_trigger "cwmp"
procd_open_trigger
json_add_array
json_add_string "" "interface.update"
json_add_array
json_add_array
json_add_string "" "run_script"
json_add_string "" "/etc/icwmpd/update.sh"
json_close_array
json_close_array
json_add_int "" "2000"
json_close_array
procd_close_trigger
}

View File

@@ -3,12 +3,16 @@
. /lib/functions.sh
regenerate_ssl_link(){
[ ! -d "/etc/ssl/certs" ] && return 0;
[ ! -f "/etc/ssl/certs/*.pem" ] && return 0;
local cert_dir="/etc/ssl/certs"
local all_file=$(ls $cert_dir/*.pem)
for cfile in $all_file
do
ln -s $cfile $cert_dir/$(openssl x509 -hash -noout -in $cfile).0
done
}
regenerate_ssl_link
regenerate_ssl_link