From 8f24ee6382756e88cc30a06e9a7da0d76b877423 Mon Sep 17 00:00:00 2001 From: Steven Barth Date: Fri, 11 Sep 2015 06:46:40 +0000 Subject: [PATCH] uqmi: Add proper IPv6 support Use the new --ip-family option to start both IPv4 and IPv6 sessions by default. Autoconnect can't be used when starting two sessions, so revert back to using the client IDs and packet data handles for handling the network connection. Some modem firmwares do not implement a RA server, therefore by default use outband IP configuration and static addressing. Some other firmwares report bogus IP configuration with the WDS get current settings command. In this case inband configuration with DHCP/RA can be optionally enabled by setting option dhcp to 1. Per 3GPP standard a /64 prefix is served to all clients, which is extended to LAN as specified in RFC 7278. v2: Restrict the IPv6 gateway route source address Signed-off-by: Matti Laakso SVN-Revision: 46843 --- package/network/utils/uqmi/Makefile | 4 +- .../utils/uqmi/files/lib/netifd/proto/qmi.sh | 205 +++++++++++++----- 2 files changed, 148 insertions(+), 61 deletions(-) mode change 100755 => 100644 package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh diff --git a/package/network/utils/uqmi/Makefile b/package/network/utils/uqmi/Makefile index 8ca7b85f64..16e7fea0a9 100644 --- a/package/network/utils/uqmi/Makefile +++ b/package/network/utils/uqmi/Makefile @@ -1,13 +1,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=uqmi -PKG_VERSION:=2014-12-03 +PKG_VERSION:=2015-08-13 PKG_RELEASE=$(PKG_SOURCE_VERSION) PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=git://nbd.name/uqmi.git PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) -PKG_SOURCE_VERSION:=86bcdb8cca652676a78b2df8b5e3fb27a40c60a4 +PKG_SOURCE_VERSION:=8a97586e9445a60e355dea13aa87885ab3dcb277 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz PKG_MAINTAINER:=Matti Laakso # PKG_MIRROR_MD5SUM:= diff --git a/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh b/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh old mode 100755 new mode 100644 index b416da6bc8..8ee7dbdecf --- a/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh +++ b/package/network/utils/uqmi/files/lib/netifd/proto/qmi.sh @@ -17,28 +17,25 @@ proto_qmi_init_config() { proto_config_add_string pincode proto_config_add_string delay proto_config_add_string modes + proto_config_add_boolean ipv6 + proto_config_add_boolean dhcp } -qmi_disconnect() { - # disable previous autoconnect state using the global handle - # do not reuse previous wds client id to prevent hangs caused by stale data - uqmi -s -d "$device" \ - --stop-network 0xffffffff \ - --autoconnect > /dev/null -} - -qmi_wds_release() { - [ -n "$cid" ] || return 0 - - uqmi -s -d "$device" --set-client-id wds,"$cid" --release-client-id wds - uci_revert_state network $interface cid -} - -_proto_qmi_setup() { +proto_qmi_setup() { local interface="$1" - local device apn auth username password pincode delay modes cid pdh - json_get_vars device apn auth username password pincode delay modes + local device apn auth username password pincode delay modes ipv6 dhcp + local cid_4 pdh_4 cid_6 pdh_6 ipv4 + local ip subnet gateway dns1 dns2 ip_6 ip_prefix_length gateway_6 dns1_6 dns2_6 + json_get_vars device apn auth username password pincode delay modes ipv6 dhcp + + ipv4=1 + + if [ "$ipv6" = 0 ]; then + ipv6="" + else + ipv6=1 + fi [ -n "$ctl_device" ] && device=$ctl_device @@ -86,8 +83,6 @@ _proto_qmi_setup() { return 1 } - qmi_disconnect - uqmi -s -d "$device" --set-data-format 802.3 uqmi -s -d "$device" --wda-set-data-format 802.3 @@ -99,67 +94,159 @@ _proto_qmi_setup() { [ -n "$modes" ] && uqmi -s -d "$device" --set-network-modes "$modes" echo "Starting network $apn" - cid=`uqmi -s -d "$device" --get-client-id wds` + + cid_4=`uqmi -s -d "$device" --get-client-id wds` [ $? -ne 0 ] && { echo "Unable to obtain client ID" proto_notify_error "$interface" NO_CID return 1 } - uqmi -s -d "$device" --set-client-id wds,"$cid" \ + pdh_4=`uqmi -s -d "$device" --set-client-id wds,"$cid_4" \ --start-network "$apn" \ ${auth:+--auth-type $auth} \ ${username:+--username $username} \ ${password:+--password $password} \ - --autoconnect > /dev/null - - echo "Starting DHCP" - proto_init_update "$ifname" 1 - proto_send_update "$interface" - - json_init - json_add_string name "${interface}_4" - json_add_string ifname "@$interface" - json_add_string proto "dhcp" - json_close_object - ubus call network add_dynamic "$(json_dump)" - - json_init - json_add_string name "${interface}_6" - json_add_string ifname "@$interface" - json_add_string proto "dhcpv6" - json_add_string extendprefix 1 - json_close_object - ubus call network add_dynamic "$(json_dump)" -} - -proto_qmi_setup() { - local ret - - _proto_qmi_setup $@ - ret=$? - - [ "$ret" = 0 ] || { - logger "qmi bringup failed, retry in 15s" - sleep 15 + --ip-family ipv4` + [ $? -ne 0 ] && { + echo "Unable to connect IPv4" + uqmi -s -d "$device" --set-client-id wds,"$cid_4" --release-client-id wds + ipv4="" } - return $rt + [ -n "$ipv6" ] && { + cid_6=`uqmi -s -d "$device" --get-client-id wds` + if [ $? = 0 ]; then + pdh_6=`uqmi -s -d "$device" --set-client-id wds,"$cid_6" \ + --start-network "$apn" \ + ${auth:+--auth-type $auth} \ + ${username:+--username $username} \ + ${password:+--password $password} \ + --ip-family ipv6` + [ $? -ne 0 ] && { + echo "Unable to connect IPv6" + uqmi -s -d "$device" --set-client-id wds,"$cid_6" --release-client-id wds + ipv6="" + } + else + echo "Unable to connect IPv6" + ipv6="" + fi + } + + [ -z "$ipv4" -a -z "$ipv6" ] && { + echo "Unable to connect" + proto_notify_error "$interface" CALL_FAILED + return 1 + } + + if [ -z "$dhcp" ]; then + echo "Setting up $ifname" + [ -n "$ipv4" ] && { + json_load "$(uqmi -s -d $device --set-client-id wds,$cid_4 --get-current-settings)" + json_select ipv4 + json_get_vars ip subnet gateway dns1 dns2 + + proto_init_update "$ifname" 1 + proto_set_keep 1 + proto_add_ipv4_address "$ip" "$subnet" + proto_add_dns_server "$dns1" + proto_add_dns_server "$dns2" + proto_add_ipv4_route "0.0.0.0" 0 "$gateway" + proto_add_data + json_add_string "cid_4" "$cid_4" + json_add_string "pdh_4" "$pdh_4" + proto_close_data + proto_send_update "$interface" + } + + [ -n "$ipv6" ] && { + json_load "$(uqmi -s -d $device --set-client-id wds,$cid_6 --get-current-settings)" + json_select ipv6 + json_get_var ip_6 ip + json_get_var gateway_6 gateway + json_get_var dns1_6 dns1 + json_get_var dns2_6 dns2 + json_get_var ip_prefix_length ip-prefix-length + + proto_init_update "$ifname" 1 + proto_set_keep 1 + # RFC 7278: Extend an IPv6 /64 Prefix to LAN + proto_add_ipv6_address "$ip_6" "128" + proto_add_ipv6_prefix "${ip_6}/${ip_prefix_length}" + proto_add_ipv6_route "$gateway_6" "128" + proto_add_ipv6_route "::0" 0 "$gateway_6" "" "" "${ip_6}/${ip_prefix_length}" + proto_add_dns_server "$dns1_6" + proto_add_dns_server "$dns2_6" + proto_add_data + json_add_string "cid_6" "$cid_6" + json_add_string "pdh_6" "$pdh_6" + proto_close_data + proto_send_update "$interface" + } + else + echo "Starting DHCP on $ifname" + proto_init_update "$ifname" 1 + proto_add_data + [ -n "$ipv4" ] && { + json_add_string "cid_4" "$cid_4" + json_add_string "pdh_4" "$pdh_4" + } + [ -n "$ipv6" ] && { + json_add_string "cid_6" "$cid_6" + json_add_string "pdh_6" "$pdh_6" + } + proto_close_data + proto_send_update "$interface" + + [ -n "$ipv4" ] && { + json_init + json_add_string name "${interface}_4" + json_add_string ifname "@$interface" + json_add_string proto "dhcp" + json_close_object + ubus call network add_dynamic "$(json_dump)" + } + + [ -n "$ipv6" ] && { + json_init + json_add_string name "${interface}_6" + json_add_string ifname "@$interface" + json_add_string proto "dhcpv6" + # RFC 7278: Extend an IPv6 /64 Prefix to LAN + json_add_string extendprefix 1 + json_close_object + ubus call network add_dynamic "$(json_dump)" + } + fi } proto_qmi_teardown() { local interface="$1" - local device + local device cid_4 pdh_4 cid_6 pdh_6 json_get_vars device [ -n "$ctl_device" ] && device=$ctl_device - local cid=$(uci_get_state network $interface cid) - echo "Stopping network" - qmi_disconnect - qmi_wds_release + + json_load "$(ubus call network.interface.$interface status)" + json_select data + json_get_vars cid_4 pdh_4 cid_6 pdh_6 + + [ -n "$cid_4" ] && { + [ -n "$pdh_4" ] && { + uqmi -s -d "$device" --set-client-id wds,"$cid_4" --stop-network "$pdh_4" + uqmi -s -d "$device" --set-client-id wds,"$cid_4" --release-client-id wds + } + } + [ -n "$cid_6" ] && { + [ -n "$pdh_6" ] && { + uqmi -s -d "$device" --set-client-id wds,"$cid_6" --stop-network "$pdh_6" + uqmi -s -d "$device" --set-client-id wds,"$cid_6" --release-client-id wds + } + } proto_init_update "*" 0 proto_send_update "$interface"