uqmi: fix indentation style and boundary
[openwrt/staging/noltari.git] / package / network / utils / uqmi / files / lib / netifd / proto / qmi.sh
1 #!/bin/sh
2
3 [ -n "$INCLUDE_ONLY" ] || {
4 . /lib/functions.sh
5 . ../netifd-proto.sh
6 init_proto "$@"
7 }
8
9 proto_qmi_init_config() {
10 available=1
11 no_device=1
12 proto_config_add_string "device:device"
13 proto_config_add_string apn
14 proto_config_add_string auth
15 proto_config_add_string username
16 proto_config_add_string password
17 proto_config_add_string pincode
18 proto_config_add_int delay
19 proto_config_add_string modes
20 proto_config_add_string pdptype
21 proto_config_add_int profile
22 proto_config_add_boolean dhcpv6
23 proto_config_add_boolean autoconnect
24 proto_config_add_int plmn
25 proto_config_add_int timeout
26 proto_config_add_int mtu
27 proto_config_add_defaults
28 }
29
30 proto_qmi_setup() {
31 local interface="$1"
32 local dataformat connstat
33 local device apn auth username password pincode delay modes pdptype
34 local profile dhcpv6 autoconnect plmn timeout mtu $PROTO_DEFAULT_OPTIONS
35 local ip4table ip6table
36 local cid_4 pdh_4 cid_6 pdh_6
37 local ip_6 ip_prefix_length gateway_6 dns1_6 dns2_6
38
39 json_get_vars device apn auth username password pincode delay modes
40 json_get_vars pdptype profile dhcpv6 autoconnect plmn ip4table
41 json_get_vars ip6table timeout mtu $PROTO_DEFAULT_OPTIONS
42
43 [ "$timeout" = "" ] && timeout="10"
44
45 [ "$metric" = "" ] && metric="0"
46
47 [ -n "$ctl_device" ] && device=$ctl_device
48
49 [ -n "$device" ] || {
50 echo "No control device specified"
51 proto_notify_error "$interface" NO_DEVICE
52 proto_set_available "$interface" 0
53 return 1
54 }
55
56 [ -n "$delay" ] && sleep "$delay"
57
58 device="$(readlink -f $device)"
59 [ -c "$device" ] || {
60 echo "The specified control device does not exist"
61 proto_notify_error "$interface" NO_DEVICE
62 proto_set_available "$interface" 0
63 return 1
64 }
65
66 devname="$(basename "$device")"
67 devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)"
68 ifname="$( ls "$devpath"/net )"
69 [ -n "$ifname" ] || {
70 echo "The interface could not be found."
71 proto_notify_error "$interface" NO_IFACE
72 proto_set_available "$interface" 0
73 return 1
74 }
75
76 [ -n "$mtu" ] && {
77 echo "Setting MTU to $mtu"
78 /sbin/ip link set dev $ifname mtu $mtu
79 }
80
81 echo "Waiting for SIM initialization"
82 local uninitialized_timeout=0
83 while uqmi -s -d "$device" --get-pin-status | grep '"UIM uninitialized"' > /dev/null; do
84 [ -e "$device" ] || return 1
85 if [ "$uninitialized_timeout" -lt "$timeout" ]; then
86 let uninitialized_timeout++
87 sleep 1;
88 else
89 echo "SIM not initialized"
90 proto_notify_error "$interface" SIM_NOT_INITIALIZED
91 proto_block_restart "$interface"
92 return 1
93 fi
94 done
95
96 if uqmi -s -d "$device" --get-pin-status | grep '"Not supported"\|"Invalid QMI command"' > /dev/null; then
97 [ -n "$pincode" ] && {
98 uqmi -s -d "$device" --verify-pin1 "$pincode" > /dev/null || uqmi -s -d "$device" --uim-verify-pin1 "$pincode" > /dev/null || {
99 echo "Unable to verify PIN"
100 proto_notify_error "$interface" PIN_FAILED
101 proto_block_restart "$interface"
102 return 1
103 }
104 }
105 else
106 . /usr/share/libubox/jshn.sh
107 json_load "$(uqmi -s -d "$device" --get-pin-status)"
108 json_get_var pin1_status pin1_status
109 json_get_var pin1_verify_tries pin1_verify_tries
110
111 case "$pin1_status" in
112 disabled)
113 echo "PIN verification is disabled"
114 ;;
115 blocked)
116 echo "SIM locked PUK required"
117 proto_notify_error "$interface" PUK_NEEDED
118 proto_block_restart "$interface"
119 return 1
120 ;;
121 not_verified)
122 [ "$pin1_verify_tries" -lt "3" ] && {
123 echo "PIN verify count value is $pin1_verify_tries this is below the limit of 3"
124 proto_notify_error "$interface" PIN_TRIES_BELOW_LIMIT
125 proto_block_restart "$interface"
126 return 1
127 }
128 if [ -n "$pincode" ]; then
129 uqmi -s -d "$device" --verify-pin1 "$pincode" > /dev/null 2>&1 || uqmi -s -d "$device" --uim-verify-pin1 "$pincode" > /dev/null 2>&1 || {
130 echo "Unable to verify PIN"
131 proto_notify_error "$interface" PIN_FAILED
132 proto_block_restart "$interface"
133 return 1
134 }
135 else
136 echo "PIN not specified but required"
137 proto_notify_error "$interface" PIN_NOT_SPECIFIED
138 proto_block_restart "$interface"
139 return 1
140 fi
141 ;;
142 verified)
143 echo "PIN already verified"
144 ;;
145 *)
146 echo "PIN status failed ($pin1_status)"
147 proto_notify_error "$interface" PIN_STATUS_FAILED
148 proto_block_restart "$interface"
149 return 1
150 ;;
151 esac
152 fi
153
154 [ -n "$plmn" ] && {
155 local mcc mnc
156 if [ "$plmn" = 0 ]; then
157 mcc=0
158 mnc=0
159 echo "Setting PLMN to auto"
160 else
161 mcc=${plmn:0:3}
162 mnc=${plmn:3}
163 echo "Setting PLMN to $plmn"
164 fi
165 uqmi -s -d "$device" --set-plmn --mcc "$mcc" --mnc "$mnc" > /dev/null 2>&1 || {
166 echo "Unable to set PLMN"
167 proto_notify_error "$interface" PLMN_FAILED
168 proto_block_restart "$interface"
169 return 1
170 }
171 }
172
173 # Cleanup current state if any
174 uqmi -s -d "$device" --stop-network 0xffffffff --autoconnect > /dev/null 2>&1
175
176 # Set IP format
177 uqmi -s -d "$device" --set-data-format 802.3 > /dev/null 2>&1
178 uqmi -s -d "$device" --wda-set-data-format 802.3 > /dev/null 2>&1
179 dataformat="$(uqmi -s -d "$device" --wda-get-data-format)"
180
181 if [ "$dataformat" = '"raw-ip"' ]; then
182
183 [ -f /sys/class/net/$ifname/qmi/raw_ip ] || {
184 echo "Device only supports raw-ip mode but is missing this required driver attribute: /sys/class/net/$ifname/qmi/raw_ip"
185 return 1
186 }
187
188 echo "Device does not support 802.3 mode. Informing driver of raw-ip only for $ifname .."
189 echo "Y" > /sys/class/net/$ifname/qmi/raw_ip
190 fi
191
192 uqmi -s -d "$device" --sync > /dev/null 2>&1
193
194 echo "Waiting for network registration"
195 local registration_timeout=0
196 while uqmi -s -d "$device" --get-serving-system | grep '"searching"' > /dev/null; do
197 [ -e "$device" ] || return 1
198 if [ "$registration_timeout" -lt "$timeout" ]; then
199 let registration_timeout++
200 sleep 1;
201 else
202 echo "Network registration failed"
203 proto_notify_error "$interface" NETWORK_REGISTRATION_FAILED
204 proto_block_restart "$interface"
205 return 1
206 fi
207 done
208
209 [ -n "$modes" ] && uqmi -s -d "$device" --set-network-modes "$modes" > /dev/null 2>&1
210
211 echo "Starting network $interface"
212
213 pdptype=$(echo "$pdptype" | awk '{print tolower($0)}')
214 [ "$pdptype" = "ip" -o "$pdptype" = "ipv6" -o "$pdptype" = "ipv4v6" ] || pdptype="ip"
215
216 if [ "$pdptype" = "ip" ]; then
217 [ -z "$autoconnect" ] && autoconnect=1
218 [ "$autoconnect" = 0 ] && autoconnect=""
219 else
220 [ "$autoconnect" = 1 ] || autoconnect=""
221 fi
222
223 [ "$pdptype" = "ip" -o "$pdptype" = "ipv4v6" ] && {
224 cid_4=$(uqmi -s -d "$device" --get-client-id wds)
225 if ! [ "$cid_4" -eq "$cid_4" ] 2> /dev/null; then
226 echo "Unable to obtain client ID"
227 proto_notify_error "$interface" NO_CID
228 return 1
229 fi
230
231 uqmi -s -d "$device" --set-client-id wds,"$cid_4" --set-ip-family ipv4 > /dev/null 2>&1
232
233 pdh_4=$(uqmi -s -d "$device" --set-client-id wds,"$cid_4" \
234 --start-network \
235 ${apn:+--apn $apn} \
236 ${profile:+--profile $profile} \
237 ${auth:+--auth-type $auth} \
238 ${username:+--username $username} \
239 ${password:+--password $password} \
240 ${autoconnect:+--autoconnect})
241
242 # pdh_4 is a numeric value on success
243 if ! [ "$pdh_4" -eq "$pdh_4" ] 2> /dev/null; then
244 echo "Unable to connect IPv4"
245 uqmi -s -d "$device" --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1
246 proto_notify_error "$interface" CALL_FAILED
247 return 1
248 fi
249
250 # Check data connection state
251 connstat=$(uqmi -s -d "$device" --get-data-status)
252 [ "$connstat" == '"connected"' ] || {
253 echo "No data link!"
254 uqmi -s -d "$device" --set-client-id wds,"$cid_4" --release-client-id wds > /dev/null 2>&1
255 proto_notify_error "$interface" CALL_FAILED
256 return 1
257 }
258 }
259
260 [ "$pdptype" = "ipv6" -o "$pdptype" = "ipv4v6" ] && {
261 cid_6=$(uqmi -s -d "$device" --get-client-id wds)
262 if ! [ "$cid_6" -eq "$cid_6" ] 2> /dev/null; then
263 echo "Unable to obtain client ID"
264 proto_notify_error "$interface" NO_CID
265 return 1
266 fi
267
268 uqmi -s -d "$device" --set-client-id wds,"$cid_6" --set-ip-family ipv6 > /dev/null 2>&1
269
270 pdh_6=$(uqmi -s -d "$device" --set-client-id wds,"$cid_6" \
271 --start-network \
272 ${apn:+--apn $apn} \
273 ${profile:+--profile $profile} \
274 ${auth:+--auth-type $auth} \
275 ${username:+--username $username} \
276 ${password:+--password $password} \
277 ${autoconnect:+--autoconnect})
278
279 # pdh_6 is a numeric value on success
280 if ! [ "$pdh_6" -eq "$pdh_6" ] 2> /dev/null; then
281 echo "Unable to connect IPv6"
282 uqmi -s -d "$device" --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1
283 proto_notify_error "$interface" CALL_FAILED
284 return 1
285 fi
286
287 # Check data connection state
288 connstat=$(uqmi -s -d "$device" --get-data-status)
289 [ "$connstat" == '"connected"' ] || {
290 echo "No data link!"
291 uqmi -s -d "$device" --set-client-id wds,"$cid_6" --release-client-id wds > /dev/null 2>&1
292 proto_notify_error "$interface" CALL_FAILED
293 return 1
294 }
295 }
296
297 echo "Setting up $ifname"
298 proto_init_update "$ifname" 1
299 proto_set_keep 1
300 proto_add_data
301 [ -n "$pdh_4" ] && {
302 json_add_string "cid_4" "$cid_4"
303 json_add_string "pdh_4" "$pdh_4"
304 }
305 [ -n "$pdh_6" ] && {
306 json_add_string "cid_6" "$cid_6"
307 json_add_string "pdh_6" "$pdh_6"
308 }
309 proto_close_data
310 proto_send_update "$interface"
311
312 local zone="$(fw3 -q network "$interface" 2>/dev/null)"
313
314 [ -n "$pdh_6" ] && {
315 if [ -z "$dhcpv6" -o "$dhcpv6" = 0 ]; then
316 json_load "$(uqmi -s -d $device --set-client-id wds,$cid_6 --get-current-settings)"
317 json_select ipv6
318 json_get_var ip_6 ip
319 json_get_var gateway_6 gateway
320 json_get_var dns1_6 dns1
321 json_get_var dns2_6 dns2
322 json_get_var ip_prefix_length ip-prefix-length
323
324 proto_init_update "$ifname" 1
325 proto_set_keep 1
326 proto_add_ipv6_address "$ip_6" "128"
327 proto_add_ipv6_prefix "${ip_6}/${ip_prefix_length}"
328 proto_add_ipv6_route "$gateway_6" "128"
329 [ "$defaultroute" = 0 ] || proto_add_ipv6_route "::0" 0 "$gateway_6" "" "" "${ip_6}/${ip_prefix_length}"
330 [ "$peerdns" = 0 ] || {
331 proto_add_dns_server "$dns1_6"
332 proto_add_dns_server "$dns2_6"
333 }
334 [ -n "$zone" ] && {
335 proto_add_data
336 json_add_string zone "$zone"
337 proto_close_data
338 }
339 proto_send_update "$interface"
340 else
341 json_init
342 json_add_string name "${interface}_6"
343 json_add_string ifname "@$interface"
344 json_add_string proto "dhcpv6"
345 [ -n "$ip6table" ] && json_add_string ip6table "$ip6table"
346 proto_add_dynamic_defaults
347 # RFC 7278: Extend an IPv6 /64 Prefix to LAN
348 json_add_string extendprefix 1
349 [ -n "$zone" ] && json_add_string zone "$zone"
350 json_close_object
351 ubus call network add_dynamic "$(json_dump)"
352 fi
353 }
354
355 [ -n "$pdh_4" ] && {
356 json_init
357 json_add_string name "${interface}_4"
358 json_add_string ifname "@$interface"
359 json_add_string proto "dhcp"
360 [ -n "$ip4table" ] && json_add_string ip4table "$ip4table"
361 proto_add_dynamic_defaults
362 [ -n "$zone" ] && json_add_string zone "$zone"
363 json_close_object
364 ubus call network add_dynamic "$(json_dump)"
365 }
366 }
367
368 qmi_wds_stop() {
369 local cid="$1"
370 local pdh="$2"
371
372 [ -n "$cid" ] || return
373
374 uqmi -s -d "$device" --set-client-id wds,"$cid" \
375 --stop-network 0xffffffff \
376 --autoconnect > /dev/null 2>&1
377
378 [ -n "$pdh" ] && {
379 uqmi -s -d "$device" --set-client-id wds,"$cid" \
380 --stop-network "$pdh" > /dev/null 2>&1
381 }
382
383 uqmi -s -d "$device" --set-client-id wds,"$cid" \
384 --release-client-id wds > /dev/null 2>&1
385 }
386
387 proto_qmi_teardown() {
388 local interface="$1"
389
390 local device cid_4 pdh_4 cid_6 pdh_6
391 json_get_vars device
392
393 [ -n "$ctl_device" ] && device=$ctl_device
394
395 echo "Stopping network $interface"
396
397 json_load "$(ubus call network.interface.$interface status)"
398 json_select data
399 json_get_vars cid_4 pdh_4 cid_6 pdh_6
400
401 qmi_wds_stop "$cid_4" "$pdh_4"
402 qmi_wds_stop "$cid_6" "$pdh_6"
403
404 proto_init_update "*" 0
405 proto_send_update "$interface"
406 }
407
408 [ -n "$INCLUDE_ONLY" ] || {
409 add_protocol qmi
410 }