#!/bin/sh [ -n "$INCLUDE_ONLY" ] || { . /lib/functions.sh . ../netifd-proto.sh init_proto "$@" } # DBG=-v ROOTER=/usr/lib/rooter ROOTER_LINK="/tmp/links" log() { modlog "MBIM Connect $CURRMODEM" "$@" } enb=$(uci -q get custom.connect.ipv6) if [ -z $enb ]; then enb="1" fi ifname1="ifname" if [ -e /etc/newstyle ]; then ifname1="device" fi get_connect() { NAPN=$(uci -q get modem.modeminfo$CURRMODEM.apn) NAPN2=$(uci -q get modem.modeminfo$CURRMODEM.apn2) NUSER=$(uci -q get modem.modeminfo$CURRMODEM.user) NPASS=$(uci -q get modem.modeminfo$CURRMODEM.passw) NAUTH=$(uci -q get modem.modeminfo$CURRMODEM.auth) PINC=$(uci -q get modem.modeminfo$CURRMODEM.pincode) PDPT=$(uci -q get modem.modeminfo$CURRMODEM.pdptype) isplist=$(uci -q get modem.modeminfo$CURRMODEM.isplist) apn=$NAPN apn2=$NAPN2 username="$NUSER" password="$NPASS" auth=$NAUTH pincode=$PINC if [ "$PDPT" = 0 ]; then ipt="" else IPVAR=$(uci -q get modem.modem$CURRMODEM.pdptype) case "$IPVAR" in "IP" ) ipt="ipv4:" ;; "IPV6" ) ipt="ipv6:" ;; "IPV4V6" ) ipt="ipv4v6:" ;; esac fi } get_sub() { log "Checking subscriber" tid=$((tid + 1)) SUB=$(umbim $DBG -n -t $tid -d $device subscriber) retq=$? if [ $retq -ne 0 ]; then log "Subscriber init failed" proto_notify_error "$interface" NO_SUBSCRIBER return 1 fi CNUM=$(echo "$SUB" | awk '/number:/ {print $2}') IMSI=$(echo "$SUB" | awk '/subscriberid:/ {print $2}') uci set modem.modem$CURRMODEM.imsi=$IMSI ICCID=$(echo "$SUB" | awk '/simiccid:/ {print $2}') uci set modem.modem$CURRMODEM.iccid=$ICCID uci commit modem } proto_mbim_init_config() { available=1 no_device=1 proto_config_add_string "device:device" proto_config_add_string apn proto_config_add_string apn2 proto_config_add_string pincode proto_config_add_string delay proto_config_add_string auth proto_config_add_string username proto_config_add_string password } _proto_mbim_setup() { local interface="$1" local tid=2 local ret v6cap pdns v4dns v6dns if [ ! -f /tmp/bootend.file ]; then return 0 fi CURRMODEM=$(uci -q get network.$interface.currmodem) uci set modem.modem$CURRMODEM.connected=0 uci commit modem rm -f $ROOTER_LINK/reconnect$CURRMODEM jkillall getsignal$CURRMODEM rm -f $ROOTER_LINK/getsignal$CURRMODEM jkillall con_monitor$CURRMODEM rm -f $ROOTER_LINK/con_monitor$CURRMODEM jkillall mbim_monitor$CURRMODEM rm -f $ROOTER_LINK/mbim_monitor$CURRMODEM local device apn pincode delay json_get_vars device apn apn2 pincode delay auth username password case $auth in "0" ) auth= ;; "1" ) auth="pap" ;; "2" ) auth="chap" ;; "*" ) auth= ;; esac IMEI="Unknown" IMSI="Unknown" ICCID="Unknown" CNUM="*" CNUMx="*" [ -n "$ctl_device" ] && device=$ctl_device [ -n "$device" ] || { log "No control device specified" proto_notify_error "$interface" NO_DEVICE proto_set_available "$interface" 0 return 1 } [ -c "$device" ] || { log "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" ] || { log "Failed to find matching interface" proto_notify_error "$interface" NO_IFNAME proto_set_available "$interface" 0 return 1 } [ -n "$delay" ] && sleep "$delay" log "Query radio state" umbim $DBG -n -d $device radio | grep "off" STATUS=$? [ "$STATUS" -ne 0 ] || { sleep 1 log "Setting FCC Auth" uqmi $DBG -s -m -d $device --fcc-auth sleep 1 } log "Reading capabilities" tid=$((tid + 1)) DCAPS=$(umbim $DBG -n -t $tid -d $device caps) retq=$? if [ $retq -ne 0 ]; then log "Failed to read modem caps" tid=$((tid + 1)) umbim $DBG -t $tid -d "$device" disconnect proto_notify_error "$interface" PIN_FAILED return 1 fi CUSTOM=$(echo "$DCAPS" | awk '/customdataclass:/ {print $2}') IMEI=$(echo "$DCAPS" | awk '/deviceid:/ {print $2}') uci set modem.modem$CURRMODEM.imei=$IMEI echo 'CUSTOM="'"$CUSTOM"'"' > /tmp/mbimcustom$CURRMODEM get_sub if [ ! -f /tmp/profile$CURRMODEM ]; then $ROOTER/connect/get_profile.sh $CURRMODEM fi get_connect log "Checking PIN state" tid=$((tid + 1)) umbim $DBG -n -t $tid -d $device pinstate retq=$? if [ $retq -eq 2 ]; then log "PIN is required" if [ ! -z $pincode ]; then log "Sending PIN" tid=$((tid + 1)) umbim $DBG -n -t $tid -d $device unlock "$pincode" 2>/dev/null retq=$? if [ $retq -ne 0 ]; then log "PIN unlock failed" exit 1 else log "PIN unlocked" sleep 3 CHKPORT=$(uci get modem.modem$CURRMODEM.commport) if [ ! -z $CHKPORT ]; then $ROOTER/common/gettype.sh $CURRMODEM else get_sub fi fi else log "PIN is missing in the profile" exit 1 fi else log "PIN is not required" fi log "Register with network" for i in $(seq 30); do tid=$((tid + 1)) REG=$(umbim $DBG -n -t $tid -d $device registration) retq=$? [ $retq -ne 2 ] && break sleep 2 done if [ $retq != 0 ]; then if [ $retq != 4 ]; then log "Subscriber registration failed" proto_notify_error "$interface" NO_REGISTRATION return 1 fi fi MCCMNC=$(echo "$REG" | awk '/provider_id:/ {print $2}') PROV=$(echo "$REG" | awk '/provider_name:/ {print $2}') MCC=${MCCMNC:0:3} MNC=${MCCMNC:3} tid=$((tid + 1)) log "Attach to network" ATTACH=$(umbim $DBG -n -t $tid -d $device attach) retq=$? if [ $retq != 0 ]; then log "Failed to attach to network" proto_notify_error "$interface" ATTACH_FAILED return 1 fi UP=$(echo "$ATTACH" | awk '/uplinkspeed:/ {print $2}') DOWN=$(echo "$ATTACH" | awk '/downlinkspeed:/ {print $2}') tid=$((tid + 1)) for isp in $isplist do NAPN=$(echo $isp | cut -d, -f2) NPASS=$(echo $isp | cut -d, -f4) CID=$(echo $isp | cut -d, -f5) NUSER=$(echo $isp | cut -d, -f6) NAUTH=$(echo $isp | cut -d, -f7) if [ "$NPASS" = "nil" ]; then NPASS="NIL" fi if [ "$NUSER" = "nil" ]; then NUSER="NIL" fi if [ "$NAUTH" = "nil" ]; then NAUTH="0" fi apn=$NAPN username="$NUSER" password="$NPASS" auth=$NAUTH case $auth in "0" ) auth="none" ;; "1" ) auth="pap" ;; "2" ) auth="chap" ;; "*" ) auth="none" ;; esac if [ ! -e /etc/config/isp ]; then log "Connect to network using $apn" else log "Connect to network" fi if [ ! -e /etc/config/isp ]; then log "$ipt $apn $auth $username $password" fi tidd=0 tcnt=4 while ! umbim $DBG -n -t $tid -d $device connect "$ipt""$apn" "$auth" "$username" "$password"; do tid=$((tid + 1)) sleep 1; tidd=$((tidd + 1)) if [ $tidd -gt $tcnt ]; then break; fi done if [ $tidd -le $tcnt ]; then break fi done if [ $tidd -gt $tcnt ]; then log "Failed to connect to network" return 1 fi tid=$((tid + 1)) log "Get IP config" CONFIG=$(umbim $DBG -n -t $tid -d $device config) || { log "config failed" return 1 } IP=$(echo -e "$CONFIG"|grep "ipv4address"|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)") GATE=$(echo -e "$CONFIG"|grep "ipv4gateway"|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)") DNS1=$(echo -e "$CONFIG"|grep "ipv4dnsserver"|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" |sed -n 1p) DNS2=$(echo -e "$CONFIG"|grep "ipv4dnsserver"|grep -E -o "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" |sed -n 2p) if [ $enb = "1" ]; then IP6=$(echo "$CONFIG" | awk '/ipv6address:/ {print $2}' | cut -d / -f 1) DNS3=$(echo "$CONFIG" | awk '/ipv6dnsserver:/ {print $2}' | sed -n 1p) DNS4=$(echo "$CONFIG" | awk '/ipv6dnsserver:/ {print $2}' | sed -n 2p) fi echo "$GATE" > /tmp/mbimgateway [ -n "$IP" ] && echo "IP: $IP" [ -n "$DNS1" ] && echo "DNS1: $DNS1" [ -n "$DNS2" ] && echo "DNS2: $DNS2" if [ $enb = "1" ]; then [ -n "$IP6" ] && echo "IPv6: $IP6" [ -n "$DNS3" ] && echo "DNS3: $DNS3" [ -n "$DNS4" ] && echo "DNS4: $DNS4" fi log "Connected, setting IP" if [ $enb = "1" ]; then if [ -n "$IP6" -a -z "$IP" ]; then log "Running IPv6-only mode" nat46=1 fi if [[ $(echo "$IP6" | grep -o "^[23]") ]]; then # Global unicast IP acquired v6cap=1 elif [[ $(echo "$IP6" | grep -o "^[0-9a-fA-F]\{1,4\}:") ]]; then # non-routable address v6cap=2 else v6cap=0 fi fi INTER=$(uci get modem.modem$CURRMODEM.inter) if [ -e /tmp/v4dns$INTER -o -e /tmp/v6dns$INTER ]; then pdns=1 if [ -e /tmp/v4dns$INTER ]; then v4dns=$(cat /tmp/v4dns$INTER 2>/dev/null) fi if [ $enb = "1" ]; then if [ -e /tmp/v6dns$INTER ]; then v6dns=$(cat /tmp/v6dns$INTER 2>/dev/null) fi fi else v4dns="$DNS1 $DNS2" if [ $enb = "1" ]; then v6dns="$DNS3 $DNS4" fi fi proto_init_update "$ifname" 1 if [ -n "$IP" ]; then proto_add_ipv4_address $IP "255.255.255.255" proto_add_ipv4_route "0.0.0.0" 0 fi for DNSV in $(echo "$v4dns"); do proto_add_dns_server "$DNSV" done if [ $enb = "1" ]; then if [ "$v6cap" -gt 0 ]; then # RFC 7278: Extend an IPv6 /64 Prefix to LAN proto_add_ipv6_address $IP6 128 if [ "$v6cap" = 1 ]; then proto_add_ipv6_prefix $IP6/64 proto_add_ipv6_route "::0" 0 "" "" "" $IP6/64 for DNSV in $(echo "$v6dns"); do proto_add_dns_server "$DNSV" done fi fi fi proto_add_data json_add_string zone wan proto_close_data proto_send_update "$interface" if [ $enb = "1" ]; then if [ "$v6cap" -gt 0 ]; then local zone="$(fw3 -q network "$interface" 2>/dev/null)" fi if [ "$v6cap" = 2 ]; then log "Adding IPv6 dynamic interface" json_init json_add_string name "${interface}_6" json_add_string ${ifname1} "@$interface" json_add_string proto "dhcpv6" json_add_string extendprefix 1 [ -n "$zone" ] && json_add_string zone "$zone" [ "$nat46" = 1 ] || json_add_string iface_464xlat 0 json_add_boolean peerdns 0 json_add_array dns for DNSV in $(echo "$v6dns"); do json_add_string "" "$DNSV" done json_close_array proto_add_dynamic_defaults json_close_object ubus call network add_dynamic "$(json_dump)" elif [ "$v6cap" = 1 -a "$nat46" = 1 ]; then log "Adding 464XLAT (CLAT) dynamic interface" json_init json_add_string name "CLAT$INTER" json_add_string proto "464xlat" json_add_string tunlink "${interface}" [ -n "$zone" ] && json_add_string zone "$zone" proto_add_dynamic_defaults json_close_object ubus call network add_dynamic "$(json_dump)" fi fi tid=$((tid + 1)) uci_set_state network $interface tid "$tid" # SIGNAL=$(umbim $DBG -n -t $tid -d $device signal) # CSQ=$(echo "$SIGNAL" | awk '/rssi:/ {print $2}') $ROOTER/log/logger "Modem #$CURRMODEM Connected" log "Modem $CURRMODEM Connected" IDP=$(uci get modem.modem$CURRMODEM.idP) IDV=$(uci get modem.modem$CURRMODEM.idV) if [ ! -s /tmp/msimdata$CURRMODEM ]; then echo $IDV" : "$IDP > /tmp/msimdatax$CURRMODEM echo "$IMEI" >> /tmp/msimdatax$CURRMODEM echo "$IMSI" >> /tmp/msimdatax$CURRMODEM echo "$ICCID" >> /tmp/msimdatax$CURRMODEM echo "1" >> /tmp/msimdatax$CURRMODEM mv -f /tmp/msimdatax$CURRMODEM /tmp/msimdata$CURRMODEM fi if [ ! -s /tmp/msimnum$CURRMODEM ]; then echo "$CNUM" > /tmp/msimnumx$CURRMODEM echo "$CNUMx" >> /tmp/msimnumx$CURRMODEM mv -f /tmp/msimnumx$CURRMODEM /tmp/msimnum$CURRMODEM fi uci set modem.modem$CURRMODEM.custom=$CUSTOM uci set modem.modem$CURRMODEM.provider=$PROV uci set modem.modem$CURRMODEM.down=$DOWN" kbps Down | " uci set modem.modem$CURRMODEM.up=$UP" kbps Up" uci set modem.modem$CURRMODEM.mcc=$MCC uci set modem.modem$CURRMODEM.mnc=" "$MNC uci set modem.modem$CURRMODEM.sig="--" uci set modem.modem$CURRMODEM.sms=0 uci commit modem COMMPORT=$(uci get modem.modem$CURRMODEM.commport) if [ -z $COMMPORT ]; then ln -s $ROOTER/mbim/mbimdata.sh $ROOTER_LINK/getsignal$CURRMODEM else $ROOTER/sms/check_sms.sh $CURRMODEM & ln -s $ROOTER/signal/modemsignal.sh $ROOTER_LINK/getsignal$CURRMODEM # send custom AT startup command if [ $(uci -q get modem.modeminfo$CURRMODEM.at) -eq "1" ]; then ATCMDD=$(uci -q get modem.modeminfo$CURRMODEM.atc) if [ ! -z "${ATCMDD}" ]; then OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$COMMPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") OX=$($ROOTER/common/processat.sh "$OX") ERROR="ERROR" if `echo ${OX} | grep "${ERROR}" 1>/dev/null 2>&1` then log "Error sending custom AT command: $ATCMDD with result: $OX" else log "Sent custom AT command: $ATCMDD with result: $OX" fi fi fi fi ln -s $ROOTER/connect/reconnect.sh $ROOTER_LINK/reconnect$CURRMODEM $ROOTER_LINK/getsignal$CURRMODEM $CURRMODEM $PROT & ln -s $ROOTER/connect/conmon.sh $ROOTER_LINK/con_monitor$CURRMODEM $ROOTER_LINK/con_monitor$CURRMODEM $CURRMODEM & #ln -s $ROOTER/mbim/monitor.sh $ROOTER_LINK/mbim_monitor$CURRMODEM #$ROOTER_LINK/mbim_monitor$CURRMODEM $CURRMODEM $device & uci set modem.modem$CURRMODEM.connected=1 uci commit modem if [ -e $ROOTER/connect/postconnect.sh ]; then $ROOTER/connect/postconnect.sh $CURRMODEM fi if [ -e $ROOTER/timezone.sh ]; then TZ=$(uci -q get modem.modeminfo$CURRMODEM.tzone) if [ "$TZ" = "1" ]; then $ROOTER/timezone.sh & fi fi CLB=$(uci -q get modem.modeminfo$CURRMODEM.lb) if [ -e /etc/config/mwan3 ]; then INTER=$(uci get modem.modeminfo$CURRMODEM.inter) if [ -z $INTER ]; then INTER=0 else if [ $INTER = 0 ]; then INTER=$CURRMODEM fi fi ENB=$(uci -q get mwan3.wan$CURRMODEM.enabled) if [ ! -z $ENB ]; then if [ $CLB = "1" ]; then uci set mwan3.wan$INTER.enabled=1 else uci set mwan3.wan$INTER.enabled=0 fi uci commit mwan3 /usr/sbin/mwan3 restart fi fi rm -f /tmp/usbwait return 0 } proto_mbim_setup() { local ret _proto_mbim_setup $@ ret=$? [ "$ret" = 0 ] || { log "MBIM bringup failed, retry in 5s" CPORT=$(uci get modem.modem$CURRMODEM.commport) ATCMDD="AT+COPS=0" OX=$($ROOTER/gcom/gcom-locked "/dev/ttyUSB$CPORT" "run-at.gcom" "$CURRMODEM" "$ATCMDD") sleep 5 } exit 0 return $ret } proto_mbim_teardown() { local interface="$1" local device json_get_vars device local tid=$(uci_get_state network $interface tid) [ -n "$ctl_device" ] && device=$ctl_device if [ -n "$device" ]; then log "Stopping network" if [ -n "$tid" ]; then tid=$((tid + 1)) umbim $DBG -t $tid -d "$device" disconnect uci_revert_state network $interface tid else umbim $DBG -d "$device" disconnect fi fi proto_init_update "*" 0 proto_send_update "$interface" } [ -n "$INCLUDE_ONLY" ] || add_protocol mbim