modemmanager: check modem state before establishing a connection
[feed/packages.git] / net / modemmanager / files / modemmanager.proto
1 #!/bin/sh
2 # Copyright (C) 2016-2019 Aleksander Morgado <aleksander@aleksander.es>
3
4 [ -x /usr/bin/mmcli ] || exit 0
5 [ -x /usr/sbin/pppd ] || exit 0
6
7 [ -n "$INCLUDE_ONLY" ] || {
8 . /lib/functions.sh
9 . ../netifd-proto.sh
10 . ./ppp.sh
11 init_proto "$@"
12 }
13
14 cdr2mask ()
15 {
16 # Number of args to shift, 255..255, first non-255 byte, zeroes
17 set -- $(( 5 - ($1 / 8) )) 255 255 255 255 $(( (255 << (8 - ($1 % 8))) & 255 )) 0 0 0
18 if [ "$1" -gt 1 ]
19 then
20 shift "$1"
21 else
22 shift
23 fi
24 echo "${1-0}"."${2-0}"."${3-0}"."${4-0}"
25 }
26
27 # This method expects as first argument a list of key-value pairs, as returned by mmcli --output-keyvalue
28 # The second argument must be exactly the name of the field to read
29 #
30 # Sample output:
31 # $ mmcli -m 0 -K
32 # modem.dbus-path : /org/freedesktop/ModemManager1/Modem/0
33 # modem.generic.device-identifier : ed6eff2e3e0f90463da1c2a755b2acacd1335752
34 # modem.generic.manufacturer : Dell Inc.
35 # modem.generic.model : DW5821e Snapdragon X20 LTE
36 # modem.generic.revision : T77W968.F1.0.0.4.0.GC.009\n026
37 # modem.generic.carrier-configuration : GCF
38 # modem.generic.carrier-configuration-revision : 08E00009
39 # modem.generic.hardware-revision : DW5821e Snapdragon X20 LTE
40 # ....
41 modemmanager_get_field() {
42 local list=$1
43 local field=$2
44 local value=""
45
46 [ -z "${list}" ] || [ -z "${field}" ] && return
47
48 # there is always at least a whitespace after each key, and we use that as part of the
49 # key matching we do (e.g. to avoid getting 'modem.generic.state-failed-reason' as a result
50 # when grepping for 'modem.generic.state'.
51 line=$(echo "${list}" | grep "${field} ")
52 value=$(echo ${line#*:})
53
54 # not found?
55 [ -n "${value}" ] || return 2
56
57 # only print value if set
58 [ "${value}" != "--" ] && echo "${value}"
59 return 0
60 }
61
62 # build a comma-separated list of values from the list
63 modemmanager_get_multivalue_field() {
64 local list=$1
65 local field=$2
66 local value=""
67 local length idx item
68
69 [ -z "${list}" ] || [ -z "${field}" ] && return
70
71 length=$(modemmanager_get_field "${list}" "${field}.length")
72 [ -n "${length}" ] || return 0
73 [ "$length" -ge 1 ] || return 0
74
75 idx=1
76 while [ $idx -le "$length" ]; do
77 item=$(modemmanager_get_field "${list}" "${field}.value\[$idx\]")
78 [ -n "${item}" ] && [ "${item}" != "--" ] && {
79 [ -n "${value}" ] && value="${value}, "
80 value="${value}${item}"
81 }
82 idx=$((idx + 1))
83 done
84
85 # nothing built?
86 [ -n "${value}" ] || return 2
87
88 # only print value if set
89 echo "${value}"
90 return 0
91 }
92
93 modemmanager_cleanup_connection() {
94 local modemstatus="$1"
95
96 local bearercount idx bearerpath
97
98 bearercount=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.length")
99
100 # do nothing if no bearers reported
101 [ -n "${bearercount}" ] && [ "$bearercount" -ge 1 ] && {
102 # explicitly disconnect just in case
103 mmcli --modem="${device}" --simple-disconnect >/dev/null 2>&1
104 # and remove all bearer objects, if any found
105 idx=1
106 while [ $idx -le "$bearercount" ]; do
107 bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[$idx\]")
108 mmcli --modem "${device}" --delete-bearer="${bearerpath}" >/dev/null 2>&1
109 idx=$((idx + 1))
110 done
111 }
112 }
113
114 modemmanager_connected_method_ppp_ipv4() {
115 local interface="$1"
116 local ttyname="$2"
117 local username="$3"
118 local password="$4"
119 local allowedauth="$5"
120
121 # all auth types are allowed unless a user given list is given
122 local authopts
123 local pap=1
124 local chap=1
125 local mschap=1
126 local mschapv2=1
127 local eap=1
128
129 [ -n "$allowedauth" ] && {
130 pap=0 chap=0 mschap=0 mschapv2=0 eap=0
131 for auth in $allowedauth; do
132 case $auth in
133 "pap") pap=1 ;;
134 "chap") chap=1 ;;
135 "mschap") mschap=1 ;;
136 "mschapv2") mschapv2=1 ;;
137 "eap") eap=1 ;;
138 *) ;;
139 esac
140 done
141 }
142
143 [ $pap -eq 1 ] || append authopts "refuse-pap"
144 [ $chap -eq 1 ] || append authopts "refuse-chap"
145 [ $mschap -eq 1 ] || append authopts "refuse-mschap"
146 [ $mschapv2 -eq 1 ] || append authopts "refuse-mschap-v2"
147 [ $eap -eq 1 ] || append authopts "refuse-eap"
148
149 proto_run_command "${interface}" /usr/sbin/pppd \
150 "${ttyname}" \
151 115200 \
152 nodetach \
153 noaccomp \
154 nobsdcomp \
155 nopcomp \
156 novj \
157 noauth \
158 $authopts \
159 ${username:+ user "$username"} \
160 ${password:+ password "$password"} \
161 lcp-echo-failure 5 \
162 lcp-echo-interval 15 \
163 lock \
164 crtscts \
165 nodefaultroute \
166 usepeerdns \
167 ipparam "${interface}" \
168 ip-up-script /lib/netifd/ppp-up \
169 ip-down-script /lib/netifd/ppp-down
170 }
171
172 modemmanager_disconnected_method_ppp_ipv4() {
173 local interface="$1"
174
175 echo "running disconnection (ppp method)"
176
177 [ -n "${ERROR}" ] && {
178 local errorstring
179 errorstring=$(ppp_exitcode_tostring "${ERROR}")
180 case "$ERROR" in
181 0)
182 ;;
183 2)
184 proto_notify_error "$interface" "$errorstring"
185 proto_block_restart "$interface"
186 ;;
187 *)
188 proto_notify_error "$interface" "$errorstring"
189 ;;
190 esac
191 } || echo "pppd result code not given"
192
193 proto_kill_command "$interface"
194 }
195
196 modemmanager_connected_method_dhcp_ipv4() {
197 local interface="$1"
198 local wwan="$2"
199 local metric="$3"
200
201 proto_init_update "${wwan}" 1
202 proto_set_keep 1
203 proto_send_update "${interface}"
204
205 json_init
206 json_add_string name "${interface}_4"
207 json_add_string ifname "@${interface}"
208 json_add_string proto "dhcp"
209 proto_add_dynamic_defaults
210 [ -n "$metric" ] && json_add_int metric "${metric}"
211 json_close_object
212 ubus call network add_dynamic "$(json_dump)"
213 }
214
215 modemmanager_connected_method_static_ipv4() {
216 local interface="$1"
217 local wwan="$2"
218 local address="$3"
219 local prefix="$4"
220 local gateway="$5"
221 local mtu="$6"
222 local dns1="$7"
223 local dns2="$8"
224 local metric="$9"
225
226 local mask=""
227
228 [ -n "${address}" ] || {
229 proto_notify_error "${interface}" ADDRESS_MISSING
230 return
231 }
232
233 [ -n "${prefix}" ] || {
234 proto_notify_error "${interface}" PREFIX_MISSING
235 return
236 }
237 mask=$(cdr2mask "${prefix}")
238
239 [ -n "${mtu}" ] && /sbin/ip link set dev "${wwan}" mtu "${mtu}"
240
241 proto_init_update "${wwan}" 1
242 proto_set_keep 1
243 echo "adding IPv4 address ${address}, netmask ${mask}"
244 proto_add_ipv4_address "${address}" "${mask}"
245 [ -n "${gateway}" ] && {
246 echo "adding default IPv4 route via ${gateway}"
247 proto_add_ipv4_route "0.0.0.0" "0" "${gateway}" "${address}"
248 }
249 [ -n "${dns1}" ] && {
250 echo "adding primary DNS at ${dns1}"
251 proto_add_dns_server "${dns1}"
252 }
253 [ -n "${dns2}" ] && {
254 echo "adding secondary DNS at ${dns2}"
255 proto_add_dns_server "${dns2}"
256 }
257 [ -n "$metric" ] && json_add_int metric "${metric}"
258 proto_send_update "${interface}"
259 }
260
261 modemmanager_connected_method_dhcp_ipv6() {
262 local interface="$1"
263 local wwan="$2"
264 local metric="$3"
265
266 proto_init_update "${wwan}" 1
267 proto_set_keep 1
268 proto_send_update "${interface}"
269
270 json_init
271 json_add_string name "${interface}_6"
272 json_add_string ifname "@${interface}"
273 json_add_string proto "dhcpv6"
274 proto_add_dynamic_defaults
275 json_add_string extendprefix 1 # RFC 7278: Extend an IPv6 /64 Prefix to LAN
276 [ -n "$metric" ] && json_add_int metric "${metric}"
277 json_close_object
278 ubus call network add_dynamic "$(json_dump)"
279 }
280
281 modemmanager_connected_method_static_ipv6() {
282 local interface="$1"
283 local wwan="$2"
284 local address="$3"
285 local prefix="$4"
286 local gateway="$5"
287 local mtu="$6"
288 local dns1="$7"
289 local dns2="$8"
290 local metric="$9"
291
292 [ -n "${address}" ] || {
293 proto_notify_error "${interface}" ADDRESS_MISSING
294 return
295 }
296
297 [ -n "${prefix}" ] || {
298 proto_notify_error "${interface}" PREFIX_MISSING
299 return
300 }
301
302 [ -n "${mtu}" ] && /sbin/ip link set dev "${wwan}" mtu "${mtu}"
303
304 proto_init_update "${wwan}" 1
305 proto_set_keep 1
306 echo "adding IPv6 address ${address}, prefix ${prefix}"
307 proto_add_ipv6_address "${address}" "128"
308 proto_add_ipv6_prefix "${address}/${prefix}"
309 [ -n "${gateway}" ] && {
310 echo "adding default IPv6 route via ${gateway}"
311 proto_add_ipv6_route "${gateway}" "128"
312 proto_add_ipv6_route "::0" "0" "${gateway}" "" "" "${address}/${prefix}"
313 }
314 [ -n "${dns1}" ] && {
315 echo "adding primary DNS at ${dns1}"
316 proto_add_dns_server "${dns1}"
317 }
318 [ -n "${dns2}" ] && {
319 echo "adding secondary DNS at ${dns2}"
320 proto_add_dns_server "${dns2}"
321 }
322 [ -n "$metric" ] && json_add_int metric "${metric}"
323 proto_send_update "${interface}"
324 }
325
326 proto_modemmanager_init_config() {
327 available=1
328 no_device=1
329 proto_config_add_string device
330 proto_config_add_string apn
331 proto_config_add_string 'allowedauth:list(string)'
332 proto_config_add_string username
333 proto_config_add_string password
334 proto_config_add_string allowedmode
335 proto_config_add_string preferredmode
336 proto_config_add_string pincode
337 proto_config_add_string iptype
338 proto_config_add_string plmn
339 proto_config_add_int signalrate
340 proto_config_add_boolean lowpower
341 proto_config_add_boolean allow_roaming
342 proto_config_add_defaults
343 }
344
345 # Append param to the global 'connectargs' variable.
346 append_param() {
347 local param="$1"
348
349 [ -z "$param" ] && return
350 [ -z "$connectargs" ] || connectargs="${connectargs},"
351 connectargs="${connectargs}${param}"
352 }
353
354 modemmanager_set_allowed_mode() {
355 local device="$1"
356 local interface="$2"
357 local allowedmode="$3"
358
359 echo "setting allowed mode to '${allowedmode}'"
360 mmcli --modem="${device}" --set-allowed-modes="${allowedmode}" || {
361 proto_notify_error "${interface}" MM_INVALID_ALLOWED_MODES_LIST
362 proto_block_restart "${interface}"
363 return 1
364 }
365 }
366
367 modemmanager_check_state() {
368 local device="$1"
369 local modemstatus="$2"
370 local pincode="$3"
371
372 local state reason
373
374 state="$(modemmanager_get_field "${modemstatus}" "state")"
375 state="${state%% *}"
376 reason="$(modemmanager_get_field "${modemstatus}" "state-failed-reason")"
377
378 case "$state" in
379 "failed")
380 case "$reason" in
381 "sim-missing")
382 echo "SIM missing"
383 proto_notify_error "${interface}" MM_FAILED_REASON_SIM_MISSING
384 proto_block_restart "${interface}"
385 return 1
386 ;;
387 *)
388 proto_notify_error "${interface}" MM_FAILED_REASON_UNKNOWN
389 proto_block_restart "${interface}"
390 return 1
391 ;;
392 esac
393 ;;
394 "locked")
395 if [ -n "$pincode" ]; then
396 mmcli --modem="${device}" -i any --pin=${pincode} || {
397 proto_notify_error "${interface}" MM_PINCODE_WRONG
398 proto_block_restart "${interface}"
399 return 1
400 }
401 else
402 echo "PIN required"
403 proto_notify_error "${interface}" MM_PINCODE_REQUIRED
404 proto_block_restart "${interface}"
405 return 1
406 fi
407 ;;
408 esac
409 }
410
411 modemmanager_set_preferred_mode() {
412 local device="$1"
413 local interface="$2"
414 local allowedmode="$3"
415 local preferredmode="$4"
416
417 [ -z "${preferredmode}" ] && {
418 echo "no preferred mode configured"
419 proto_notify_error "${interface}" MM_NO_PREFERRED_MODE_CONFIGURED
420 proto_block_restart "${interface}"
421 return 1
422 }
423
424 [ -z "${allowedmode}" ] && {
425 echo "no allowed mode configured"
426 proto_notify_error "${interface}" MM_NO_ALLOWED_MODE_CONFIGURED
427 proto_block_restart "${interface}"
428 return 1
429 }
430
431 echo "setting preferred mode to '${preferredmode}' (${allowedmode})"
432 mmcli --modem="${device}" \
433 --set-preferred-mode="${preferredmode}" \
434 --set-allowed-modes="${allowedmode}" || {
435 proto_notify_error "${interface}" MM_FAILED_SETTING_PREFERRED_MODE
436 proto_block_restart "${interface}"
437 return 1
438 }
439 }
440
441 proto_modemmanager_setup() {
442 local interface="$1"
443
444 local modempath modemstatus bearercount bearerpath connectargs bearerstatus beareriface
445 local bearermethod_ipv4 bearermethod_ipv6 auth cliauth
446 local operatorname operatorid registration accesstech signalquality
447 local allowedmode preferredmode
448
449 local device apn allowedauth username password pincode
450 local iptype plmn metric signalrate allow_roaming
451
452 local address prefix gateway mtu dns1 dns2
453
454 json_get_vars device apn allowedauth username password
455 json_get_vars pincode iptype plmn metric signalrate allow_roaming
456 json_get_vars allowedmode preferredmode
457
458 # validate sysfs path given in config
459 [ -n "${device}" ] || {
460 echo "No device specified"
461 proto_notify_error "${interface}" NO_DEVICE
462 proto_set_available "${interface}" 0
463 return 1
464 }
465
466 # validate that ModemManager is handling the modem at the sysfs path
467 modemstatus=$(mmcli --modem="${device}" --output-keyvalue)
468 modempath=$(modemmanager_get_field "${modemstatus}" "modem.dbus-path")
469 [ -n "${modempath}" ] || {
470 echo "Device not managed by ModemManager"
471 proto_notify_error "${interface}" DEVICE_NOT_MANAGED
472 proto_set_available "${interface}" 0
473 return 1
474 }
475 echo "modem available at ${modempath}"
476
477 modemmanager_check_state "$device" "${modemstatus}" "$pincode"
478 [ "$?" -ne "0" ] && return 1
479
480 [ -z "${allowedmode}" ] || {
481 case "$allowedmode" in
482 "2g")
483 modemmanager_set_allowed_mode "$device" \
484 "$interface" "2g"
485 ;;
486 "3g")
487 modemmanager_set_allowed_mode "$device" \
488 "$interface" "3g"
489 ;;
490 "4g")
491 modemmanager_set_allowed_mode "$device" \
492 "$interface" "4g"
493 ;;
494 "5g")
495 modemmanager_set_allowed_mode "$device" \
496 "$interface" "5g"
497 ;;
498 *)
499 modemmanager_set_preferred_mode "$device" \
500 "$interface" "${allowedmode}" "${preferredmode}"
501 ;;
502 esac
503 # check error for allowed_mode and preferred_mode function call
504 [ "$?" -ne "0" ] && return 1
505 }
506
507 # always cleanup before attempting a new connection, just in case
508 modemmanager_cleanup_connection "${modemstatus}"
509
510 # if allowedauth list given, build option string
511 for auth in $allowedauth; do
512 cliauth="${cliauth}${cliauth:+|}$auth"
513 done
514
515 # setup connect args; APN mandatory (even if it may be empty)
516 echo "starting connection with apn '${apn}'..."
517 proto_notify_error "${interface}" MM_CONNECT_IN_PROGRESS
518
519 # setup allow-roaming parameter
520 if [ -n "${allow_roaming}" ] && [ "${allow_roaming}" -eq 0 ];then
521 allow_roaming="no"
522 else
523 # allowed unless a user set the opposite
524 allow_roaming="yes"
525 fi
526
527 # Append options to 'connectargs' variable
528 append_param "apn=${apn}"
529 append_param "allow-roaming=${allow_roaming}"
530 append_param "${iptype:+ip-type=${iptype}}"
531 append_param "${plmn:+operator-id=${plmn}}"
532 append_param "${cliauth:+allowed-auth=${cliauth}}"
533 append_param "${username:+user=${username}}"
534 append_param "${password:+password=${password}}"
535
536 mmcli --modem="${device}" --timeout 120 --simple-connect="${connectargs}" || {
537 proto_notify_error "${interface}" MM_CONNECT_FAILED
538 proto_block_restart "${interface}"
539 return 1
540 }
541
542 # check if Signal refresh rate is set
543 if [ -n "${signalrate}" ] && [ "${signalrate}" -eq "${signalrate}" ] 2>/dev/null; then
544 echo "setting signal refresh rate to ${signalrate} seconds"
545 mmcli --modem="${device}" --signal-setup="${signalrate}"
546 else
547 echo "signal refresh rate is not set"
548 fi
549
550 # log additional useful information
551 modemstatus=$(mmcli --modem="${device}" --output-keyvalue)
552 operatorname=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.operator-name")
553 [ -n "${operatorname}" ] && echo "network operator name: ${operatorname}"
554 operatorid=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.operator-code")
555 [ -n "${operatorid}" ] && echo "network operator MCCMNC: ${operatorid}"
556 registration=$(modemmanager_get_field "${modemstatus}" "modem.3gpp.registration-state")
557 [ -n "${registration}" ] && echo "registration type: ${registration}"
558 accesstech=$(modemmanager_get_multivalue_field "${modemstatus}" "modem.generic.access-technologies")
559 [ -n "${accesstech}" ] && echo "access technology: ${accesstech}"
560 signalquality=$(modemmanager_get_field "${modemstatus}" "modem.generic.signal-quality.value")
561 [ -n "${signalquality}" ] && echo "signal quality: ${signalquality}%"
562
563 # we won't like it if there are more than one bearers, as that would mean the
564 # user manually created them, and that's unsupported by this proto
565 bearercount=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.length")
566 [ -n "${bearercount}" ] && [ "$bearercount" -eq 1 ] || {
567 proto_notify_error "${interface}" INVALID_BEARER_LIST
568 return 1
569 }
570
571 # load connected bearer information
572 bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[1\]")
573 bearerstatus=$(mmcli --bearer "${bearerpath}" --output-keyvalue)
574
575 # load network interface and method information
576 beareriface=$(modemmanager_get_field "${bearerstatus}" "bearer.status.interface")
577 bearermethod_ipv4=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.method")
578 bearermethod_ipv6=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.method")
579
580 # setup IPv4
581 [ -n "${bearermethod_ipv4}" ] && {
582 echo "IPv4 connection setup required in interface ${interface}: ${bearermethod_ipv4}"
583 case "${bearermethod_ipv4}" in
584 "dhcp")
585 modemmanager_connected_method_dhcp_ipv4 "${interface}" "${beareriface}" "${metric}"
586 ;;
587 "static")
588 address=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.address")
589 prefix=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.prefix")
590 gateway=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.gateway")
591 mtu=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.mtu")
592 dns1=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.dns.value\[1\]")
593 dns2=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.dns.value\[2\]")
594 modemmanager_connected_method_static_ipv4 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}"
595 ;;
596 "ppp")
597 modemmanager_connected_method_ppp_ipv4 "${interface}" "${beareriface}" "${username}" "${password}" "${allowedauth}"
598 ;;
599 *)
600 proto_notify_error "${interface}" UNKNOWN_METHOD
601 return 1
602 ;;
603 esac
604 }
605
606 # setup IPv6
607 # note: if using ipv4v6, both IPv4 and IPv6 settings will have the same MTU and metric values reported
608 [ -n "${bearermethod_ipv6}" ] && {
609 echo "IPv6 connection setup required in interface ${interface}: ${bearermethod_ipv6}"
610 case "${bearermethod_ipv6}" in
611 "dhcp")
612 modemmanager_connected_method_dhcp_ipv6 "${interface}" "${beareriface}" "${metric}"
613 ;;
614 "static")
615 address=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.address")
616 prefix=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.prefix")
617 gateway=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.gateway")
618 mtu=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.mtu")
619 dns1=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.dns.value\[1\]")
620 dns2=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.dns.value\[2\]")
621 modemmanager_connected_method_static_ipv6 "${interface}" "${beareriface}" "${address}" "${prefix}" "${gateway}" "${mtu}" "${dns1}" "${dns2}" "${metric}"
622 ;;
623 "ppp")
624 proto_notify_error "${interface}" "unsupported method"
625 return 1
626 ;;
627 *)
628 proto_notify_error "${interface}" UNKNOWN_METHOD
629 return 1
630 ;;
631 esac
632 }
633
634 return 0
635 }
636
637 proto_modemmanager_teardown() {
638 local interface="$1"
639
640 local modemstatus bearerpath errorstring
641 local bearermethod_ipv4 bearermethod_ipv6
642
643 local device lowpower iptype
644 json_get_vars device lowpower iptype
645
646 echo "stopping network"
647
648 # load connected bearer information, just the first one should be ok
649 modemstatus=$(mmcli --modem="${device}" --output-keyvalue)
650 bearerpath=$(modemmanager_get_field "${modemstatus}" "modem.generic.bearers.value\[1\]")
651 [ -n "${bearerpath}" ] || {
652 echo "couldn't load bearer path: disconnecting anyway"
653 mmcli --modem="${device}" --simple-disconnect >/dev/null 2>&1
654 return
655 }
656
657 # load bearer connection methods
658 bearerstatus=$(mmcli --bearer "${bearerpath}" --output-keyvalue)
659 bearermethod_ipv4=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv4-config.method")
660 [ -n "${bearermethod_ipv4}" ] &&
661 echo "IPv4 connection teardown required in interface ${interface}: ${bearermethod_ipv4}"
662 bearermethod_ipv6=$(modemmanager_get_field "${bearerstatus}" "bearer.ipv6-config.method")
663 [ -n "${bearermethod_ipv6}" ] &&
664 echo "IPv6 connection teardown required in interface ${interface}: ${bearermethod_ipv6}"
665
666 # disconnection handling only requires special treatment in IPv4/PPP
667 [ "${bearermethod_ipv4}" = "ppp" ] && modemmanager_disconnected_method_ppp_ipv4 "${interface}"
668
669 # disconnect
670 mmcli --modem="${device}" --simple-disconnect ||
671 proto_notify_error "${interface}" DISCONNECT_FAILED
672
673 # disable
674 mmcli --modem="${device}" --disable
675
676 # low power, only if requested
677 [ "${lowpower:-0}" -lt 1 ] ||
678 mmcli --modem="${device}" --set-power-state-low
679 }
680
681 [ -n "$INCLUDE_ONLY" ] || {
682 add_protocol modemmanager
683 }