qmi: add sourcefilter option support
[openwrt/staging/pepe2k.git] / package / network / utils / uqmi / files / lib / netifd / proto / qmi.sh
index 8c335b57758bcc311b0c67cfb74ae9892394b482..bec46325bcac3e70d9a840d343191e7e2e1e4c52 100755 (executable)
@@ -23,6 +23,7 @@ proto_qmi_init_config() {
        proto_config_add_int v6profile
        proto_config_add_boolean dhcp
        proto_config_add_boolean dhcpv6
+       proto_config_add_boolean sourcefilter
        proto_config_add_boolean autoconnect
        proto_config_add_int plmn
        proto_config_add_int timeout
@@ -38,9 +39,10 @@ proto_qmi_setup() {
        local ip4table ip6table
        local cid_4 pdh_4 cid_6 pdh_6
        local ip_6 ip_prefix_length gateway_6 dns1_6 dns2_6
+       local profile_pdptype
 
        json_get_vars device apn v6apn auth username password pincode delay modes
-       json_get_vars pdptype profile v6profile dhcp dhcpv6 autoconnect plmn ip4table
+       json_get_vars pdptype profile v6profile dhcp dhcpv6 sourcefilter autoconnect plmn ip4table
        json_get_vars ip6table timeout mtu $PROTO_DEFAULT_OPTIONS
 
        [ "$timeout" = "" ] && timeout="10"
@@ -84,8 +86,8 @@ proto_qmi_setup() {
        echo "Waiting for SIM initialization"
        local uninitialized_timeout=0
        # timeout 3s for first call to avoid hanging uqmi
-       uqmi -d "$device" --get-pin-status -t 3000 > /dev/null 2>&1
-       while uqmi -s -d "$device" --get-pin-status | grep '"UIM uninitialized"' > /dev/null; do
+       uqmi -d "$device" -t 3000 --get-pin-status > /dev/null 2>&1
+       while uqmi -s -d "$device" -t 1000 --get-pin-status | grep '"UIM uninitialized"' > /dev/null; do
                [ -e "$device" ] || return 1
                if [ "$uninitialized_timeout" -lt "$timeout" -o "$timeout" = "0" ]; then
                        let uninitialized_timeout++
@@ -101,7 +103,7 @@ proto_qmi_setup() {
        # Check if UIM application is stuck in illegal state
        local uim_state_timeout=0
        while true; do
-               json_load "$(uqmi -s -d "$device" --uim-get-sim-state)"
+               json_load "$(uqmi -s -d "$device" -t 1000 --uim-get-sim-state)"
                json_get_var card_application_state card_application_state
 
                # SIM card is either completely absent or state is labeled as illegal
@@ -110,9 +112,9 @@ proto_qmi_setup() {
                        echo "SIM in illegal state - Power-cycling SIM"
 
                        # Try to reset SIM application
-                       uqmi -d "$device" --uim-power-off --uim-slot 1
+                       uqmi -d "$device" -t 1000 --uim-power-off --uim-slot 1
                        sleep 3
-                       uqmi -d "$device" --uim-power-on --uim-slot 1
+                       uqmi -d "$device" -t 1000 --uim-power-on --uim-slot 1
 
                        if [ "$uim_state_timeout" -lt "$timeout" ] || [ "$timeout" = "0" ]; then
                                let uim_state_timeout++
@@ -129,10 +131,10 @@ proto_qmi_setup() {
                fi
        done
 
-       if uqmi -s -d "$device" --uim-get-sim-state | grep -q '"Not supported"\|"Invalid QMI command"' &&
-          uqmi -s -d "$device" --get-pin-status | grep -q '"Not supported"\|"Invalid QMI command"' ; then
+       if uqmi -s -d "$device" -t 1000 --uim-get-sim-state | grep -q '"Not supported"\|"Invalid QMI command"' &&
+          uqmi -s -d "$device" -t 1000 --get-pin-status | grep -q '"Not supported"\|"Invalid QMI command"' ; then
                [ -n "$pincode" ] && {
-                       uqmi -s -d "$device" --verify-pin1 "$pincode" > /dev/null || uqmi -s -d "$device" --uim-verify-pin1 "$pincode" > /dev/null || {
+                       uqmi -s -d "$device" -t 1000 --verify-pin1 "$pincode" > /dev/null || uqmi -s -d "$device" -t 1000 --uim-verify-pin1 "$pincode" > /dev/null || {
                                echo "Unable to verify PIN"
                                proto_notify_error "$interface" PIN_FAILED
                                proto_block_restart "$interface"
@@ -140,10 +142,10 @@ proto_qmi_setup() {
                        }
                }
        else
-               json_load "$(uqmi -s -d "$device" --get-pin-status)"
+               json_load "$(uqmi -s -d "$device" -t 1000 --get-pin-status)"
                json_get_var pin1_status pin1_status
                if [ -z "$pin1_status" ]; then
-                       json_load "$(uqmi -s -d "$device" --uim-get-sim-state)"
+                       json_load "$(uqmi -s -d "$device" -t 1000 --uim-get-sim-state)"
                        json_get_var pin1_status pin1_status
                fi
                json_get_var pin1_verify_tries pin1_verify_tries
@@ -166,7 +168,7 @@ proto_qmi_setup() {
                                        return 1
                                }
                                if [ -n "$pincode" ]; then
-                                       uqmi -s -d "$device" --verify-pin1 "$pincode" > /dev/null 2>&1 || uqmi -s -d "$device" --uim-verify-pin1 "$pincode" > /dev/null 2>&1 || {
+                                       uqmi -s -d "$device" -t 1000 --verify-pin1 "$pincode" > /dev/null 2>&1 || uqmi -s -d "$device" -t 1000 --uim-verify-pin1 "$pincode" > /dev/null 2>&1 || {
                                                echo "Unable to verify PIN"
                                                proto_notify_error "$interface" PIN_FAILED
                                                proto_block_restart "$interface"
@@ -193,7 +195,7 @@ proto_qmi_setup() {
        fi
 
        if [ -n "$plmn" ]; then
-               json_load "$(uqmi -s -d "$device" --get-plmn)"
+               json_load "$(uqmi -s -d "$device" -t 1000 --get-plmn)"
                json_get_var plmn_mode mode
                json_get_vars mcc mnc || {
                        mcc=0
@@ -216,26 +218,17 @@ proto_qmi_setup() {
                fi
        fi
 
-       if [ -n "$mcc" -a -n "$mnc" ]; then
-               uqmi -s -d "$device" --set-plmn --mcc "$mcc" --mnc "$mnc" > /dev/null 2>&1 || {
-                       echo "Unable to set PLMN"
-                       proto_notify_error "$interface" PLMN_FAILED
-                       proto_block_restart "$interface"
-                       return 1
-               }
-       fi
-
        # Cleanup current state if any
-       uqmi -s -d "$device" --stop-network 0xffffffff --autoconnect > /dev/null 2>&1
-       uqmi -s -d "$device" --set-ip-family ipv6 --stop-network 0xffffffff --autoconnect > /dev/null 2>&1
+       uqmi -s -d "$device" -t 1000 --stop-network 0xffffffff --autoconnect > /dev/null 2>&1
+       uqmi -s -d "$device" -t 1000 --set-ip-family ipv6 --stop-network 0xffffffff --autoconnect > /dev/null 2>&1
 
        # Go online
-       uqmi -s -d "$device" --set-device-operating-mode online > /dev/null 2>&1
+       uqmi -s -d "$device" -t 1000 --set-device-operating-mode online > /dev/null 2>&1
 
        # Set IP format
-       uqmi -s -d "$device" --set-data-format 802.3 > /dev/null 2>&1
-       uqmi -s -d "$device" --wda-set-data-format 802.3 > /dev/null 2>&1
-       dataformat="$(uqmi -s -d "$device" --wda-get-data-format)"
+       uqmi -s -d "$device" -t 1000 --set-data-format 802.3 > /dev/null 2>&1
+       uqmi -s -d "$device" -t 1000 --wda-set-data-format 802.3 > /dev/null 2>&1
+       dataformat="$(uqmi -s -d "$device" -t 1000 --wda-get-data-format)"
 
        if [ "$dataformat" = '"raw-ip"' ]; then
 
@@ -248,16 +241,33 @@ proto_qmi_setup() {
                echo "Y" > /sys/class/net/$ifname/qmi/raw_ip
        fi
 
-       uqmi -s -d "$device" --sync > /dev/null 2>&1
+       uqmi -s -d "$device" -t 1000 --sync > /dev/null 2>&1
 
-       uqmi -s -d "$device" --network-register > /dev/null 2>&1
+       uqmi -s -d "$device" -t 20000 --network-register > /dev/null 2>&1
+
+       # PLMN selection must happen after the call to network-register
+       if [ -n "$mcc" -a -n "$mnc" ]; then
+               uqmi -s -d "$device" -t 1000 --set-plmn --mcc "$mcc" --mnc "$mnc" > /dev/null 2>&1 || {
+                       echo "Unable to set PLMN"
+                       proto_notify_error "$interface" PLMN_FAILED
+                       proto_block_restart "$interface"
+                       return 1
+               }
+       fi
+
+       [ -n "$modes" ] && {
+               uqmi -s -d "$device" -t 1000 --set-network-modes "$modes" > /dev/null 2>&1
+               sleep 3
+               # Scan network to not rely on registration-timeout after RAT change
+               uqmi -s -d "$device" -t 30000 --network-scan > /dev/null 2>&1
+       }
 
        echo "Waiting for network registration"
        sleep 5
        local registration_timeout=0
        local registration_state=""
        while true; do
-               registration_state=$(uqmi -s -d "$device" --get-serving-system 2>/dev/null | jsonfilter -e "@.registration" 2>/dev/null)
+               registration_state=$(uqmi -s -d "$device" -t 1000 --get-serving-system 2>/dev/null | jsonfilter -e "@.registration" 2>/dev/null)
 
                [ "$registration_state" = "registered" ] && break
 
@@ -265,7 +275,7 @@ proto_qmi_setup() {
                        if [ "$registration_timeout" -lt "$timeout" ] || [ "$timeout" = "0" ]; then
                                [ "$registration_state" = "searching" ] || {
                                        echo "Device stopped network registration. Restart network registration"
-                                       uqmi -s -d "$device" --network-register > /dev/null 2>&1
+                                       uqmi -s -d "$device" -t 20000 --network-register > /dev/null 2>&1
                                }
                                let registration_timeout++
                                sleep 1
@@ -281,7 +291,6 @@ proto_qmi_setup() {
                return 1
        done
 
-       [ -n "$modes" ] && uqmi -s -d "$device" --set-network-modes "$modes" > /dev/null 2>&1
 
        echo "Starting network $interface"
 
@@ -289,6 +298,13 @@ proto_qmi_setup() {
 
        [ "$pdptype" = "ip" -o "$pdptype" = "ipv6" -o "$pdptype" = "ipv4v6" ] || pdptype="ip"
 
+       # Configure PDP type and APN for profile 1.
+       # In case GGSN rejects IPv4v6 PDP, modem might not be able to
+       # establish a non-LTE data session.
+       profile_pdptype="$pdptype"
+       [ "$profile_pdptype" = "ip" ] && profile_pdptype="ipv4"
+       uqmi -s -d "$device" -t 1000 --modify-profile "3gpp,1" --apn "$apn" --pdp-type "$profile_pdptype" > /dev/null 2>&1
+
        if [ "$pdptype" = "ip" ]; then
                [ -z "$autoconnect" ] && autoconnect=1
                [ "$autoconnect" = 0 ] && autoconnect=""
@@ -297,16 +313,16 @@ proto_qmi_setup() {
        fi
 
        [ "$pdptype" = "ip" -o "$pdptype" = "ipv4v6" ] && {
-               cid_4=$(uqmi -s -d "$device" --get-client-id wds)
+               cid_4=$(uqmi -s -d "$device" -t 1000 --get-client-id wds)
                if ! [ "$cid_4" -eq "$cid_4" ] 2> /dev/null; then
                        echo "Unable to obtain client ID"
                        proto_notify_error "$interface" NO_CID
                        return 1
                fi
 
-               uqmi -s -d "$device" --set-client-id wds,"$cid_4" --set-ip-family ipv4 > /dev/null 2>&1
+               uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --set-ip-family ipv4 > /dev/null 2>&1
 
-               pdh_4=$(uqmi -s -d "$device" --set-client-id wds,"$cid_4" \
+               pdh_4=$(uqmi -s -d "$device" -t 5000 --set-client-id wds,"$cid_4" \
                        --start-network \
                        ${apn:+--apn $apn} \
                        ${profile:+--profile $profile} \
@@ -318,35 +334,35 @@ proto_qmi_setup() {
                # pdh_4 is a numeric value on success
                if ! [ "$pdh_4" -eq "$pdh_4" ] 2> /dev/null; then
                        echo "Unable to connect IPv4"
-                       uqmi -s -d "$device" --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1
+                       uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1
                        proto_notify_error "$interface" CALL_FAILED
                        return 1
                fi
 
                # Check data connection state
-               connstat=$(uqmi -s -d "$device" --set-client-id wds,"$cid_4" --get-data-status)
+               connstat=$(uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --get-data-status)
                [ "$connstat" == '"connected"' ] || {
                        echo "No data link!"
-                       uqmi -s -d "$device" --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1
+                       uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1
                        proto_notify_error "$interface" CALL_FAILED
                        return 1
                }
        }
 
        [ "$pdptype" = "ipv6" -o "$pdptype" = "ipv4v6" ] && {
-               cid_6=$(uqmi -s -d "$device" --get-client-id wds)
+               cid_6=$(uqmi -s -d "$device" -t 1000 --get-client-id wds)
                if ! [ "$cid_6" -eq "$cid_6" ] 2> /dev/null; then
                        echo "Unable to obtain client ID"
                        proto_notify_error "$interface" NO_CID
                        return 1
                fi
 
-               uqmi -s -d "$device" --set-client-id wds,"$cid_6" --set-ip-family ipv6 > /dev/null 2>&1
+               uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --set-ip-family ipv6 > /dev/null 2>&1
 
                : "${v6apn:=${apn}}"
                : "${v6profile:=${profile}}"
 
-               pdh_6=$(uqmi -s -d "$device" --set-client-id wds,"$cid_6" \
+               pdh_6=$(uqmi -s -d "$device" -t 5000 --set-client-id wds,"$cid_6" \
                        --start-network \
                        ${v6apn:+--apn $v6apn} \
                        ${v6profile:+--profile $v6profile} \
@@ -358,16 +374,16 @@ proto_qmi_setup() {
                # pdh_6 is a numeric value on success
                if ! [ "$pdh_6" -eq "$pdh_6" ] 2> /dev/null; then
                        echo "Unable to connect IPv6"
-                       uqmi -s -d "$device" --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1
+                       uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1
                        proto_notify_error "$interface" CALL_FAILED
                        return 1
                fi
 
                # Check data connection state
-               connstat=$(uqmi -s -d "$device" --set-client-id wds,"$cid_6" --set-ip-family ipv6 --get-data-status)
+               connstat=$(uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --set-ip-family ipv6 --get-data-status)
                [ "$connstat" == '"connected"' ] || {
                        echo "No data link!"
-                       uqmi -s -d "$device" --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1
+                       uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1
                        proto_notify_error "$interface" CALL_FAILED
                        return 1
                }
@@ -392,7 +408,7 @@ proto_qmi_setup() {
 
        [ -n "$pdh_6" ] && {
                if [ -z "$dhcpv6" -o "$dhcpv6" = 0 ]; then
-                       json_load "$(uqmi -s -d $device --set-client-id wds,$cid_6 --get-current-settings)"
+                       json_load "$(uqmi -s -d $device -t 1000 --set-client-id wds,$cid_6 --get-current-settings)"
                        json_select ipv6
                        json_get_var ip_6 ip
                        json_get_var gateway_6 gateway
@@ -426,6 +442,7 @@ proto_qmi_setup() {
                        proto_add_dynamic_defaults
                        # RFC 7278: Extend an IPv6 /64 Prefix to LAN
                        json_add_string extendprefix 1
+                       [ "$sourcefilter" = "0" ] && json_add_boolean sourcefilter "0"
                        [ -n "$zone" ] && json_add_string zone "$zone"
                        json_close_object
                        ubus call network add_dynamic "$(json_dump)"
@@ -434,7 +451,7 @@ proto_qmi_setup() {
 
        [ -n "$pdh_4" ] && {
                if [ "$dhcp" = 0 ]; then
-                       json_load "$(uqmi -s -d $device --set-client-id wds,$cid_4 --get-current-settings)"
+                       json_load "$(uqmi -s -d $device -t 1000 --set-client-id wds,$cid_4 --get-current-settings)"
                        json_select ipv4
                        json_get_var ip_4 ip
                        json_get_var gateway_4 gateway
@@ -477,16 +494,16 @@ qmi_wds_stop() {
 
        [ -n "$cid" ] || return
 
-       uqmi -s -d "$device" --set-client-id wds,"$cid" \
+       uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid" \
                --stop-network 0xffffffff \
                --autoconnect > /dev/null 2>&1
 
        [ -n "$pdh" ] && {
-               uqmi -s -d "$device" --set-client-id wds,"$cid" \
+               uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid" \
                        --stop-network "$pdh" > /dev/null 2>&1
        }
 
-       uqmi -s -d "$device" --set-client-id wds,"$cid" \
+       uqmi -s -d "$device" -t 1000 --set-client-id wds,"$cid" \
                --release-client-id wds > /dev/null 2>&1
 }