uqmi: use UUCP-style locking on control device
authorDaniel Golle <daniel@makrotopia.org>
Tue, 24 Nov 2020 18:54:31 +0000 (18:54 +0000)
committerDaniel Golle <daniel@makrotopia.org>
Sun, 19 Feb 2023 20:46:06 +0000 (20:46 +0000)
Use UUCP-style locking to avoid interfering with running commands, eg.
by running 'ifup wwan' while 'ifdown wwan' has not completed yet,
multiple parallel instances of uqmi would occur and mess things up.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
package/network/utils/uqmi/Makefile
package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh

index 02265d400c1db33cc020f8150e1c9a37945097c6..e229db904808fe5e7869a3c7a65399e18049f1e6 100644 (file)
@@ -1,7 +1,7 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=uqmi
-PKG_RELEASE:=$(AUTORELEASE)
+PKG_RELEASE:=3
 
 PKG_SOURCE_PROTO:=git
 PKG_SOURCE_URL=$(PROJECT_GIT)/project/uqmi.git
index c2c5fc1eca0baf714be018f7864e2ab1bdc07403..bd895ebe6bc66ab8fb547d6044165625aa9a433a 100755 (executable)
@@ -28,16 +28,19 @@ proto_qmi_init_config() {
        proto_config_add_defaults
 }
 
-proto_qmi_setup() {
+qmi_setup() {
        local interface="$1"
+       local device="$2"
        local dataformat connstat plmn_mode mcc mnc
-       local device apn auth username password pincode delay modes pdptype
+       local apn auth username password pincode delay modes pdptype
        local profile dhcp dhcpv6 autoconnect plmn timeout mtu $PROTO_DEFAULT_OPTIONS
        local ip4table ip6table
        local cid_4 pdh_4 cid_6 pdh_6
        local ip_6 ip_prefix_length gateway_6 dns1_6 dns2_6
 
-       json_get_vars device apn auth username password pincode delay modes
+       flock -x 1000 || return -1000
+
+       json_get_vars apn auth username password pincode delay modes
        json_get_vars pdptype profile dhcp dhcpv6 autoconnect plmn ip4table
        json_get_vars ip6table timeout mtu $PROTO_DEFAULT_OPTIONS
 
@@ -45,35 +48,8 @@ proto_qmi_setup() {
 
        [ "$metric" = "" ] && metric="0"
 
-       [ -n "$ctl_device" ] && device=$ctl_device
-
-       [ -n "$device" ] || {
-               echo "No control device specified"
-               proto_notify_error "$interface" NO_DEVICE
-               proto_set_available "$interface" 0
-               return 1
-       }
-
        [ -n "$delay" ] && sleep "$delay"
 
-       device="$(readlink -f $device)"
-       [ -c "$device" ] || {
-               echo "The specified control device does not exist"
-               proto_notify_error "$interface" NO_DEVICE
-               proto_set_available "$interface" 0
-               return 1
-       }
-
-       devname="$(basename "$device")"
-       devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)"
-       ifname="$( ls "$devpath"/net )"
-       [ -n "$ifname" ] || {
-               echo "The interface could not be found."
-               proto_notify_error "$interface" NO_IFACE
-               proto_set_available "$interface" 0
-               return 1
-       }
-
        [ -n "$mtu" ] && {
                echo "Setting MTU to $mtu"
                /sbin/ip link set dev $ifname mtu $mtu
@@ -432,9 +408,50 @@ proto_qmi_setup() {
        }
 }
 
+proto_qmi_setup() {
+       local device lock ret
+       json_get_vars device
+
+       [ -n "$ctl_device" ] && device=$ctl_device
+
+       [ -n "$device" ] || {
+               echo "No control device specified"
+               proto_notify_error "$interface" NO_DEVICE
+               proto_set_available "$interface" 0
+               return 1
+       }
+
+       device="$(readlink -f $device)"
+       [ -c "$device" ] || {
+               echo "The specified control device does not exist"
+               proto_notify_error "$interface" NO_DEVICE
+               proto_set_available "$interface" 0
+               return 1
+       }
+
+       devname="$(basename "$device")"
+       devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)"
+       ifname="$( ls "$devpath"/net )"
+       [ -n "$ifname" ] || {
+               echo "The interface could not be found."
+               proto_notify_error "$interface" NO_IFACE
+               proto_set_available "$interface" 0
+               return 1
+       }
+       lock="/var/lock/..LCK.$(basename "$device")"
+       {
+               qmi_setup "$1" "$device"
+       } 1000>"$lock"
+       ret=$?
+       [ "$ret" != "-1000" ] && rm "$lock"
+       echo "exited with code $ret"
+       return $ret
+}
+
 qmi_wds_stop() {
-       local cid="$1"
-       local pdh="$2"
+       local device="$1"
+       local cid="$2"
+       local pdh="$3"
 
        [ -n "$cid" ] || return
 
@@ -451,23 +468,33 @@ qmi_wds_stop() {
                --release-client-id wds > /dev/null 2>&1
 }
 
+qmi_wds_stop_all() {
+       local device="$1"
+       flock -x 1000 || return -1000
+       json_load "$(ubus call network.interface.$interface status)"
+       json_select data
+       json_get_vars cid_4 pdh_4 cid_6 pdh_6
+       qmi_wds_stop "$device" "$cid_4" "$pdh_4"
+       qmi_wds_stop "$device" "$cid_6" "$pdh_6"
+}
+
 proto_qmi_teardown() {
        local interface="$1"
 
-       local device cid_4 pdh_4 cid_6 pdh_6
+       local device lock cid_4 pdh_4 cid_6 pdh_6
        json_get_vars device
 
        [ -n "$ctl_device" ] && device=$ctl_device
 
-       echo "Stopping network $interface"
-
-       json_load "$(ubus call network.interface.$interface status)"
-       json_select data
-       json_get_vars cid_4 pdh_4 cid_6 pdh_6
+       device="$(readlink -f $device)"
 
-       qmi_wds_stop "$cid_4" "$pdh_4"
-       qmi_wds_stop "$cid_6" "$pdh_6"
+       echo "Stopping network $interface"
 
+       lock="/var/lock/..LCK.$(basename "$device")"
+       {
+               qmi_wds_stop_all "$device"
+       } 1000>"$lock"
+       [ "$?" != "-1000" ] && rm "$lock"
        proto_init_update "*" 0
        proto_send_update "$interface"
 }