summaryrefslogtreecommitdiffstats
path: root/package/network/utils/umbim/files/lib/netifd/proto/mbim.sh
blob: 50913e7fa0461e2732583dd1499dffaba6de5964 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
#!/bin/sh

[ -n "$INCLUDE_ONLY" ] || {
	. /lib/functions.sh
	. ../netifd-proto.sh
	init_proto "$@"
}
#DBG=-v

proto_mbim_init_config() {
	available=1
	no_device=1
	proto_config_add_string "device:device"
	proto_config_add_string apn
	proto_config_add_string pincode
	proto_config_add_string delay
	proto_config_add_boolean allow_roaming
	proto_config_add_boolean allow_partner
	proto_config_add_string auth
	proto_config_add_string username
	proto_config_add_string password
	[ -e /proc/sys/net/ipv6 ] && proto_config_add_string ipv6
	proto_config_add_string dhcp
	proto_config_add_string dhcpv6
	proto_config_add_string pdptype
	proto_config_add_int mtu
	proto_config_add_defaults
}

_proto_mbim_get_field() {
        local field="$1"
        shift
        local mbimconfig="$@"
        echo "$mbimconfig" | while read -r line; do
                variable=${line%%:*}
                [ "$variable" = "$field" ] || continue;
                value=${line##* }
                echo -n "$value "
        done
}

_proto_mbim_setup() {
	local interface="$1"
	local tid=2
	local ret

	local device apn pincode delay auth username password allow_roaming allow_partner
	local dhcp dhcpv6 pdptype ip4table ip6table mtu $PROTO_DEFAULT_OPTIONS
	json_get_vars device apn pincode delay auth username password allow_roaming allow_partner
	json_get_vars dhcp dhcpv6 pdptype ip4table ip6table mtu $PROTO_DEFAULT_OPTIONS

	[ ! -e /proc/sys/net/ipv6 ] && ipv6=0 || json_get_var ipv6 ipv6

	[ -n "$ctl_device" ] && device=$ctl_device

	[ -n "$device" ] || {
		echo "mbim[$$]" "No control device specified"
		proto_notify_error "$interface" NO_DEVICE
		proto_set_available "$interface" 0
		return 1
	}
	[ -c "$device" ] || {
		echo "mbim[$$]" "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" ] || {
		echo "mbim[$$]" "Failed to find matching interface"
		proto_notify_error "$interface" NO_IFNAME
		proto_set_available "$interface" 0
		return 1
	}

	[ -n "$apn" ] || {
		echo "mbim[$$]" "No APN specified"
		proto_notify_error "$interface" NO_APN
		return 1
	}

	[ -n "$delay" ] && sleep "$delay"

	echo "mbim[$$]" "Reading capabilities"
	umbim $DBG -n -d $device caps || {
		echo "mbim[$$]" "Failed to read modem caps"
		tid=$((tid + 1))
		umbim $DBG -t $tid -d "$device" disconnect
		proto_notify_error "$interface" PIN_FAILED
		return 1
	}
	tid=$((tid + 1))

	[ "$pincode" ] && {
		echo "mbim[$$]" "Sending pin"
		umbim $DBG -n -t $tid -d $device unlock "$pincode" || {
			echo "mbim[$$]" "Unable to verify PIN"
			tid=$((tid + 1))
			umbim $DBG -t $tid -d "$device" disconnect
			proto_notify_error "$interface" PIN_FAILED
			proto_block_restart "$interface"
			return 1
		}
	}
	tid=$((tid + 1))

	echo "mbim[$$]" "Checking pin"
	umbim $DBG -n -t $tid -d $device pinstate
	[ $? -eq 2 ] && {
		echo "mbim[$$]" "PIN required"
		tid=$((tid + 1))
		umbim $DBG -t $tid -d "$device" disconnect
		proto_notify_error "$interface" PIN_FAILED
		proto_block_restart "$interface"
		return 1
	}
	tid=$((tid + 1))

	echo "mbim[$$]" "Checking subscriber"
	umbim $DBG -n -t $tid -d $device subscriber || {
		echo "mbim[$$]" "Subscriber init failed"
		tid=$((tid + 1))
		umbim $DBG -t $tid -d "$device" disconnect
		proto_notify_error "$interface" NO_SUBSCRIBER
		return 1
	}
	tid=$((tid + 1))

	echo "mbim[$$]" "Register with network"
	connected=0
	umbim $DBG -n -t $tid -d $device registration
	reg_status=$?
	case $reg_status in
		0)	echo "mbim[$$]" "Registered in home mode"
			tid=$((tid + 1))
			connected=1;;
		4)	if [ "$allow_roaming" = "1" ]; then
				echo "mbim[$$]" "Registered in roaming mode"
				tid=$((tid + 1))
				connected=1
			fi;;
		5) 	if [ "$allow_partner" = "1" ]; then
				echo "mbim[$$]" "Registered in partner mode"
				tid=$((tid + 1))
				connected=1
			fi;;
	esac
	if [ $connected -ne 1 ]; then
		echo "mbim[$$]" "Subscriber registration failed (code $reg_status)"
		tid=$((tid + 1))
		umbim $DBG -t $tid -d "$device" disconnect
		proto_notify_error "$interface" NO_REGISTRATION
		return 1
	fi

	echo "mbim[$$]" "Attach to network"
	umbim $DBG -n -t $tid -d $device attach || {
		echo "mbim[$$]" "Failed to attach to network"
		tid=$((tid + 1))
		umbim $DBG -t $tid -d "$device" disconnect
		proto_notify_error "$interface" ATTACH_FAILED
		return 1
	}
	tid=$((tid + 1))

	pdptype=$(echo "$pdptype" | awk '{print tolower($0)}')
	[ "$ipv6" = 0 ] && pdptype="ipv4"

	local req_pdptype="" # Pass "default" PDP type to umbim if unconfigured
	[ "$pdptype" = "ipv4" -o "$pdptype" = "ipv6" -o "$pdptype" = "ipv4v6" ] && req_pdptype="$pdptype:"

	local connect_state
	echo "mbim[$$]" "Connect to network"
	connect_state=$(umbim $DBG -n -t $tid -d $device connect "$req_pdptype$apn" "$auth" "$username" "$password") || {
		echo "mbim[$$]" "Failed to connect bearer"
		tid=$((tid + 1))
		umbim $DBG -t $tid -d "$device" disconnect
		proto_notify_error "$interface" CONNECT_FAILED
		return 1
	}
	tid=$((tid + 1))

	echo "$connect_state"
	local iptype="$(echo "$connect_state" | grep iptype: | awk '{print $4}')"

	echo "mbim[$$]" "Connected"

	local zone="$(fw3 -q network "$interface" 2>/dev/null)"

	echo "mbim[$$]" "Setting up $ifname"
	local mbimconfig="$(umbim $DBG -n -t $tid -d $device config)"
	echo "$mbimconfig"
	tid=$((tid + 1))

	proto_init_update "$ifname" 1
	proto_send_update "$interface"

	[ -z "$dhcp" ] && dhcp="auto"
	[ -z "$dhcpv6" ] && dhcpv6="auto"

	[ "$iptype" != "ipv6" ] && {
		json_init
		json_add_string name "${interface}_4"
		json_add_string ifname "@$interface"
		ipv4address=$(_proto_mbim_get_field ipv4address "$mbimconfig")
		if [ -n "$ipv4address" -a "$dhcp" != 1 ]; then
			json_add_string proto "static"

			json_add_array ipaddr
			for address in $ipv4address; do
				json_add_string "" "$address"
			done
			json_close_array

			json_add_string gateway $(_proto_mbim_get_field ipv4gateway "$mbimconfig")
		elif [ "$dhcp" != 0 ]; then
			echo "mbim[$$]" "Starting DHCP on $ifname"
			json_add_string proto "dhcp"
		fi

		[ "$peerdns" = 0 -a "$dhcp" != 1 ] || {
			json_add_array dns
			for server in $(_proto_mbim_get_field ipv4dnsserver "$mbimconfig"); do
				json_add_string "" "$server"
			done
			json_close_array
		}

		proto_add_dynamic_defaults
		[ -n "$zone" ] && json_add_string zone "$zone"
		[ -n "$ip4table" ] && json_add_string ip4table "$ip4table"
		json_close_object
		ubus call network add_dynamic "$(json_dump)"
	}

	[ "$iptype" != "ipv4" ] && {
		json_init
		json_add_string name "${interface}_6"
		json_add_string ifname "@$interface"
		ipv6address=$(_proto_mbim_get_field ipv6address "$mbimconfig")
		if [ -n "$ipv6address" -a "$dhcpv6" != 1 ]; then
			json_add_string proto "static"

			json_add_array ip6addr
			for address in $ipv6address; do
				json_add_string "" "$address"
			done
			json_close_array

			json_add_array ip6prefix
			for address in $ipv6address; do
				json_add_string "" "$address"
			done
			json_close_array

			json_add_string ip6gw $(_proto_mbim_get_field ipv6gateway "$mbimconfig")

		elif [ "$dhcpv6" != 0 ]; then
			echo "mbim[$$]" "Starting DHCPv6 on $ifname"
			json_add_string proto "dhcpv6"
			json_add_string extendprefix 1
		fi

		[ "$peerdns" = 0 -a "$dhcpv6" != 1 ] || {
			json_add_array dns
			for server in $(_proto_mbim_get_field ipv6dnsserver "$mbimconfig"); do
				json_add_string "" "$server"
			done
			json_close_array
		}

		proto_add_dynamic_defaults
		[ -n "$zone" ] && json_add_string zone "$zone"
		[ -n "$ip6table" ] && json_add_string ip6table "$ip6table"
		json_close_object
		ubus call network add_dynamic "$(json_dump)"
	}

	[ -z "$mtu" ] && {
		local ipv4mtu=$(_proto_mbim_get_field ipv4mtu "$mbimconfig")
		ipv4mtu="${ipv4mtu:-0}"
		local ipv6mtu=$(_proto_mbim_get_field ipv6mtu "$mbimconfig")
		ipv6mtu="${ipv6mtu:-0}"

		mtu=$((ipv6mtu > ipv4mtu ? ipv6mtu : ipv4mtu))
	}
	[ -n "$mtu" -a "$mtu" != 0 ] && {
		echo Setting MTU of $ifname to $mtu
		/sbin/ip link set dev $ifname mtu $mtu
	}

	uci_set_state network $interface tid "$tid"
}

proto_mbim_setup() {
	local ret

	_proto_mbim_setup $@
	ret=$?

	[ "$ret" = 0 ] || {
		logger "mbim bringup failed, retry in 15s"
		sleep 15
	}

	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

	echo "mbim[$$]" "Stopping network"
	[ -n "$tid" ] && {
		umbim $DBG -t $tid -d "$device" disconnect
		uci_revert_state network $interface tid
	}

	proto_init_update "*" 0
	proto_send_update "$interface"
}

[ -n "$INCLUDE_ONLY" ] || add_protocol mbim