diff options
author | Max Wölfing | 2019-03-14 12:17:20 +0100 |
---|---|---|
committer | Max Wölfing | 2019-03-14 12:17:20 +0100 |
commit | aec6e0b4c5669824b463e75c0e4d44e99f6be413 (patch) | |
tree | d39948812074a262778ab320ecc69f64293bde42 | |
download | aur-aec6e0b4c5669824b463e75c0e4d44e99f6be413.tar.gz |
Initial release of netctl-mm
-rw-r--r-- | .SRCINFO | 15 | ||||
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | PKGBUILD | 16 | ||||
-rw-r--r-- | mobile_mm | 210 | ||||
-rw-r--r-- | mobile_mm.profile | 43 |
5 files changed, 285 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..f844430863ba --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,15 @@ +pkgbase = netctl-mm + pkgdesc = Mobile broadband support for netctl using ModemManager + pkgver = 0.0.6 + pkgrel = 1 + arch = any + license = GPL + depends = netctl + depends = modemmanager + source = mobile_mm.profile + source = mobile_mm + md5sums = ccad269de8f7c0d0cb89d3112849023d + md5sums = 67b54403ec1f95330ffc11c35fb722c3 + +pkgname = netctl-mm + diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..468cd87d3ce8 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pkg.tar.xz diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..eb9196111c12 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,16 @@ +# Maintainer: Max Wölfing <ff0x@infr.cat> +pkgname=netctl-mm +pkgver=0.0.6 +pkgrel=1 +pkgdesc="Mobile broadband support for netctl using ModemManager" +arch=(any) +license=('GPL') +depends=(netctl modemmanager) +source=(mobile_mm.profile mobile_mm) +md5sums=('ccad269de8f7c0d0cb89d3112849023d' + '67b54403ec1f95330ffc11c35fb722c3') + +package() { + install -Dm644 "$srcdir/mobile_mm.profile" "$pkgdir/etc/netctl/examples/mobile_mm" + install -Dm644 "$srcdir/mobile_mm" "$pkgdir/usr/lib/netctl/connections/mobile_mm" +} diff --git a/mobile_mm b/mobile_mm new file mode 100644 index 000000000000..219790cc1436 --- /dev/null +++ b/mobile_mm @@ -0,0 +1,210 @@ +# Contributed by Max Wölfing <ff0x@infr.cat> +# Version: 0.0.6 + +# KNOWN BUGS: +# - After suspend/hibernate the mobile broadband connection is not going to reconnect automatically (that's probably ok) +# and sometimes, the modem is PUK-locked afterwards. The netctl connection is still show as active. +# To fix this issue just run 'netctl restart <profile>'. This will also unlock the modem if required. + +. "$SUBR_DIR/ip" +. "$SUBR_DIR/rfkill" + +if ! hash mmcli; then + report_error "'mmcli' not found. Please install 'modemmanager' first" + exit 1 +else + __MMCLI=$(command -v mmcli) +fi + +# Try to get the modem ID or start ModemManager if available +MODEM_ID="$($__MMCLI -L 2>/dev/null | awk '/\/Modem\// {print $1}' | cut -d/ -f 6)" +if [[ -z "$MODEM_ID" ]] || [[ ! "$MODEM_ID" =~ ^[0-9]+$ ]]; then + if ! systemctl is-active ModemManager.service &>/dev/null; then + systemctl start ModemManager.service + + # Wait until ModemManager has initialised the modem + TIMEOUT_MODEM=${TimeoutModem:-5} + until [[ $($__MMCLI -L 2>/dev/null | awk '/\/Modem\// {print $1}' | cut -d/ -f 6) =~ ^[0-9]+$ ]] || [ $TIMEOUT_MODEM -eq 0 ]; do + sleep 1 + ((TIMEOUT_MODEM--)) + done + + # Finally get the modem ID + MODEM_ID="$($__MMCLI -L 2>/dev/null | awk '/\/Modem\// {print $1}' | cut -d/ -f 6)" + if [[ -z "$MODEM_ID" ]] || [[ ! "$MODEM_ID" =~ ^[0-9]+$ ]]; then + report_error "No modem found. Please ensure you have ModemManager installed and the service is started" + exit 1 + fi + fi +fi + +# Get the modem path +MODEM=$($__MMCLI -L 2>/dev/null | sed -n 's#.*\(/org/.*/Modem/[0-9]\+\).*#\1#p') +if [[ -z "$MODEM" ]]; then + report_error "No modem found. Please ensure you have ModemManager installed and the service is started" + exit 1 +fi + +# Get the modem status +MODEM_STATUS=$($__MMCLI -m "$MODEM" | awk '/Status/ {for(i=1; i<5; i++) {getline; if ($2=="state:") {gsub("\047","",$3); print $3}}}') +if [[ "$MODEM_STATUS" == 'locked' ]]; then + report_notice "Modem is locked. Trying to supply PIN, if provided in the connection profile.." + if [[ $Pin ]]; then + PUK=""; [[ $Puk ]] && PUK="--puk=${Puk}" + SIM_PATH=$($__MMCLI -m "$MODEM" 2>/dev/null | grep 'SIM' | awk '{print $4}' | sed "s/'//g") + if [[ ! -z "$SIM_PATH" ]]; then + $__MMCLI -m "$MODEM_ID" -i "$SIM_PATH" $PUK --pin="${Pin}" >/dev/null 2>&1 + MODEM_STATUS=$($__MMCLI -L 2>/dev/null | sed -n "s/.*state: '\([^ \t]\+\)'.*/\1/p") + if [[ "$MODEM_STATUS" == 'locked' ]]; then + report_error "Modem is still locked. Maybe the supplied PIN is wrong or the PUK is required" + exit 1 + fi + fi + else + report_error "Modem is locked. PIN (and maybe PUK) required. Please add correspondig options to the connection profile" + exit 1 + fi +fi + +function mobile_mm_up { + local mmcli_args=() + + if ! is_interface "$Interface"; then + report_notice "Interface '$Interface' does not exist. Is this a problem?" + fi + + if [[ $RFKill ]]; then + rf_enable "$Interface" "$RFKill" || return 1 + fi + + if [[ -z $AccessPointName ]]; then + report_error "Option 'AccessPointName' is required" + return 1 + else + mmcli_args+=("apn=${AccessPointName}") + fi + + [[ $Pin ]] && mmcli_args+=("pin=${Pin}") + + local ip_type="ipv4" + if [[ $IP6 ]] && [[ ! "$IP6" =~ (dhcp|no) ]]; then + report_notice "Currently only the following options are supported for 'IP6' ('dhcp', 'no'). Continueing with disabled IPv6" + IP6="no" + fi + [[ "$IP6" == 'dhcp' ]] && ip_type="ipv4v6" + mmcli_args+=("ip-type=${ip_type}") + + if [[ $User ]] && [[ $Password ]]; then + mmcli_args+=("user=${User}") + mmcli_args+=("password=${Password}") + fi + + local roaming=0 + is_yes "${Roaming:-0}" && roaming=1 + mmcli_args+=("allow-roaming=${roaming}") + + mmcli_args+=("number=${PhoneNumber:-*99#}") + + local connect_args + connect_args=$(printf ",%s" "${mmcli_args[@]}") + connect_args=${connect_args:1} + + if [[ $Mode ]] && [[ ! "$Mode" =~ ^(ANY|2G|3G|4G)$ ]]; then + report_notice "Mode must be one of (ANY, 2G, 3G, 4G). Selecting 4G as preferred mode" + Mode="4G" + else + Mode="4G" + fi + + report_debug "Full connect string: $__MMCLI -m $MODEM --timeout ${TimeoutConnect:-60} --set-allowed-modes=ANY --set-preferred-mode=${Mode} --simple-connect=$connect_args" + $__MMCLI -m "$MODEM" --set-allowed-modes=ANY --timeout ${TimeoutConnect:-60} --set-preferred-mode="${Mode}" --simple-connect="$connect_args" $(if [ "$NETCTL_DEBUG" == 'yes' ]; then echo '2>/dev/null'; fi) + local bearer bearer_interface + bearer=$($__MMCLI -m "$MODEM" $(if [ "$NETCTL_DEBUG" == 'yes' ]; then echo '2>/dev/null'; fi) | sed -n 's#.*\(/org/.*/Bearer/[0-9]\+\).*#\1#p') + bearer_interface=$($__MMCLI -m "$MODEM" -b "$bearer" $(if [ "$NETCTL_DEBUG" == 'yes' ]; then echo '2>/dev/null'; fi) | sed -n "s/.*interface: \(.*\)/\1/p") + + if [[ -z "$bearer_interface" ]]; then + report_error "No bearer interface found" + return 1 + fi + if [[ "$bearer_interface" != "$Interface" ]]; then + report_notice "Network interface used by the bearer is not the same as provided by your connection profile. Please update the profile using the right bearer interface: '$bearer_interface'" + Interface=$bearer_interface + fi + + # Disable IPv6 before bringing the interface up to prevent SLAAC + if [[ "$IP6" == "no" ]]; then + sysctl -q -w "net.ipv6.conf.${Interface/.//}.disable_ipv6=1" + fi + + if ! bring_interface_up "$Interface"; then + report_error "Failed to bring interface '$Interface' up" + return 1 + fi + + # Some cards are plain slow to come up. Don't fail immediately. + if ! timeout_wait "${TimeoutCarrier:-5}" '(( $(< "/sys/class/net/$Interface/carrier") ))'; then + report_error "No connection found on interface '$Interface' (timeout)" + bring_interface_down "$Interface" + return 1 + fi + + # Configuring IPv4 + if [[ $($__MMCLI -m "$MODEM" -b "$bearer" 2>/dev/null | sed -n "s/IPv4.*method: \(.*\)/\1/p") == *static* ]]; then + IP="static" + for bearer_config in $($__MMCLI -m "$MODEM" -b "$bearer" 2>/dev/null | awk '/IPv4/ {for(i=1; i<5; i++) {getline; print $2 $3 $4}}' | sed "s/'//g"); do + [[ $bearer_config == *address:* ]] && interface_address="${bearer_config#*:}" + [[ $bearer_config == *prefix:* ]] && interface_prefix="${bearer_config#*:}" + [[ $bearer_config == *gateway:* ]] && interface_gateway="${bearer_config#*:}" + [[ $bearer_config == *DNS:* ]] && interface_dns="${bearer_config#*:}" + done + + Address=("${interface_address}/${interface_prefix}") + Gateway="$interface_gateway" + [[ "${UsePeerDNS:-true}" == 'true' ]] && DNS=("$(echo $interface_dns | sed 's/,/ /g')") + else + IP="dhcp" + fi + + # Configuring IPv6 + if [[ "$IP6" == 'dhcp' ]]; then + if [[ $($__MMCLI -m "$MODEM" -b "$bearer" 2>/dev/null | sed -n "s/IPv6.*method: \(.*\)/\1/p") != *dhcp* ]]; then + report_error "IPv6 (dhcp) not supported by modem. Skipping" + else + IP6="dhcp" + fi + fi + + if ! ip_set; then + bring_interface_down "$Interface" + return 1 + fi +} + +function mobile_mm_down { + local bearer_interface + bearer=$($__MMCLI -m "$MODEM" 2>/dev/null | sed -n 's#.*\(/org/.*/Bearer/[0-9]\+\).*#\1#p') + bearer_interface=$($__MMCLI -m "$MODEM" -b "$bearer" 2>/dev/null | sed -n "s/.*interface: '\([^ \t]\+\)'.*/\1/p") + + if [[ $($__MMCLI -m "$MODEM" -b "$bearer" 2>/dev/null | sed -n "s/IPv4.*method: '\([^ \t]\+\)'.*/\1/p") == *static* ]]; then + for bearer_config in $($__MMCLI -m "$MODEM" -b "$bearer" 2>/dev/null | awk '/IPv4/ {for(i=1; i<5; i++) {getline; print $2 $3 $4}}' | sed "s/'//g"); do + [[ $bearer_config == *address:* ]] && interface_address="${bearer_config#*:}" + [[ $bearer_config == *prefix:* ]] && interface_prefix="${bearer_config#*:}" + [[ $bearer_config == *gateway:* ]] && interface_gateway="${bearer_config#*:}" + [[ $bearer_config == *DNS:* ]] && interface_dns="${bearer_config#*:}" + done + + Address=("${interface_address}/${interface_prefix}") + Gateway="$interface_gateway" + [[ "${UsePeerDNS:-true}" == 'true' ]] && DNS=("$(echo $interface_dns | sed 's/,/ /g')") + fi + + $__MMCLI -m "$MODEM" --simple-disconnect 2>/dev/null + ip_unset + interface_delete "$Interface" + + if [[ $RFKill ]]; then + rf_disable "$Interface" "$RFKill" + fi +} + +# vim: ft=sh ts=2 et sw=2: diff --git a/mobile_mm.profile b/mobile_mm.profile new file mode 100644 index 000000000000..9054e7d4700b --- /dev/null +++ b/mobile_mm.profile @@ -0,0 +1,43 @@ +Description='Example MM/MBIM mobile connection' +Interface=wwp0s20u4 +Connection=mobile_mm + +# Block/unblock your radio +#RFKill=tpacpi_wwan_sw + +# Currently only 'dhcp' or 'no' supported +#IP6=no + +# Use default route provided by the peer (default: true) +#DefaultRoute=false +# Use DNS provided by the peer (default: true) +#UsePeerDNS=true +# Alternative, set your nameservers using the option below +#DNS=('1.1.1.1' '2606:4700:4700::1111') + +# The user and password are not always required +#User='example@yourprovider.com' +#Password='very secret' + +# The access point name you are connecting to +AccessPointName=apn + +# If your device has a PIN code, set it here. +#Pin= +# If your device is PUK-locked, we will try to unlock it. +#Puk= + +#The number to dial. Defaults to '*99#' +#PhoneNumber=*99***1# + +# Enable/Disable roaming (default: no) +#Roaming=yes + +# Amount of seconds, we will wait until initialisation of modem will be interrupted, defaults to 5s +#TimeoutModem=10 + +# Amount of seconds, we will wait for the connetion is established, defaults to 60s +#TimeoutConnect=120 + +# Mode can be one of (ANY, 2G, 3G, 4G). Defaults to 4G. +#Mode=4G |