mbim: add sourcefilter option support
[openwrt/staging/blocktrron.git] / package / network / utils / umbim / files / lib / netifd / proto / mbim.sh
1 #!/bin/sh
2
3 [ -n "$INCLUDE_ONLY" ] || {
4 . /lib/functions.sh
5 . ../netifd-proto.sh
6 init_proto "$@"
7 }
8 #DBG=-v
9
10 proto_mbim_init_config() {
11 available=1
12 no_device=1
13 proto_config_add_string "device:device"
14 proto_config_add_string apn
15 proto_config_add_string pincode
16 proto_config_add_string delay
17 proto_config_add_boolean allow_roaming
18 proto_config_add_boolean allow_partner
19 proto_config_add_string auth
20 proto_config_add_string username
21 proto_config_add_string password
22 [ -e /proc/sys/net/ipv6 ] && proto_config_add_string ipv6
23 proto_config_add_string dhcp
24 proto_config_add_string dhcpv6
25 proto_config_add_boolean sourcefilter
26 proto_config_add_string pdptype
27 proto_config_add_int mtu
28 proto_config_add_defaults
29 }
30
31 _proto_mbim_get_field() {
32 local field="$1"
33 shift
34 local mbimconfig="$@"
35 echo "$mbimconfig" | while read -r line; do
36 variable=${line%%:*}
37 [ "$variable" = "$field" ] || continue;
38 value=${line##* }
39 echo -n "$value "
40 done
41 }
42
43 _proto_mbim_setup() {
44 local interface="$1"
45 local tid=2
46 local ret
47
48 local device apn pincode delay auth username password allow_roaming allow_partner
49 local dhcp dhcpv6 pdptype ip4table ip6table mtu $PROTO_DEFAULT_OPTIONS
50 json_get_vars device apn pincode delay auth username password allow_roaming allow_partner
51 json_get_vars dhcp dhcpv6 sourcefilter pdptype ip4table ip6table mtu $PROTO_DEFAULT_OPTIONS
52
53 [ ! -e /proc/sys/net/ipv6 ] && ipv6=0 || json_get_var ipv6 ipv6
54
55 [ -n "$ctl_device" ] && device=$ctl_device
56
57 [ -n "$device" ] || {
58 echo "mbim[$$]" "No control device specified"
59 proto_notify_error "$interface" NO_DEVICE
60 proto_set_available "$interface" 0
61 return 1
62 }
63 [ -c "$device" ] || {
64 echo "mbim[$$]" "The specified control device does not exist"
65 proto_notify_error "$interface" NO_DEVICE
66 proto_set_available "$interface" 0
67 return 1
68 }
69
70 devname="$(basename "$device")"
71 devpath="$(readlink -f /sys/class/usbmisc/$devname/device/)"
72 ifname="$( ls "$devpath"/net )"
73
74 [ -n "$ifname" ] || {
75 echo "mbim[$$]" "Failed to find matching interface"
76 proto_notify_error "$interface" NO_IFNAME
77 proto_set_available "$interface" 0
78 return 1
79 }
80
81 [ -n "$apn" ] || {
82 echo "mbim[$$]" "No APN specified"
83 proto_notify_error "$interface" NO_APN
84 return 1
85 }
86
87 [ -n "$delay" ] && sleep "$delay"
88
89 echo "mbim[$$]" "Reading capabilities"
90 umbim $DBG -n -d $device caps || {
91 echo "mbim[$$]" "Failed to read modem caps"
92 tid=$((tid + 1))
93 umbim $DBG -t $tid -d "$device" disconnect
94 proto_notify_error "$interface" PIN_FAILED
95 return 1
96 }
97 tid=$((tid + 1))
98
99 [ "$pincode" ] && {
100 echo "mbim[$$]" "Sending pin"
101 umbim $DBG -n -t $tid -d $device unlock "$pincode" || {
102 echo "mbim[$$]" "Unable to verify PIN"
103 tid=$((tid + 1))
104 umbim $DBG -t $tid -d "$device" disconnect
105 proto_notify_error "$interface" PIN_FAILED
106 proto_block_restart "$interface"
107 return 1
108 }
109 }
110 tid=$((tid + 1))
111
112 echo "mbim[$$]" "Checking pin"
113 umbim $DBG -n -t $tid -d $device pinstate
114 [ $? -eq 2 ] && {
115 echo "mbim[$$]" "PIN required"
116 tid=$((tid + 1))
117 umbim $DBG -t $tid -d "$device" disconnect
118 proto_notify_error "$interface" PIN_FAILED
119 proto_block_restart "$interface"
120 return 1
121 }
122 tid=$((tid + 1))
123
124 echo "mbim[$$]" "Checking subscriber"
125 umbim $DBG -n -t $tid -d $device subscriber || {
126 echo "mbim[$$]" "Subscriber init failed"
127 tid=$((tid + 1))
128 umbim $DBG -t $tid -d "$device" disconnect
129 proto_notify_error "$interface" NO_SUBSCRIBER
130 return 1
131 }
132 tid=$((tid + 1))
133
134 echo "mbim[$$]" "Register with network"
135 connected=0
136 umbim $DBG -n -t $tid -d $device registration
137 reg_status=$?
138 case $reg_status in
139 0) echo "mbim[$$]" "Registered in home mode"
140 tid=$((tid + 1))
141 connected=1;;
142 4) if [ "$allow_roaming" = "1" ]; then
143 echo "mbim[$$]" "Registered in roaming mode"
144 tid=$((tid + 1))
145 connected=1
146 fi;;
147 5) if [ "$allow_partner" = "1" ]; then
148 echo "mbim[$$]" "Registered in partner mode"
149 tid=$((tid + 1))
150 connected=1
151 fi;;
152 esac
153 if [ $connected -ne 1 ]; then
154 echo "mbim[$$]" "Subscriber registration failed (code $reg_status)"
155 tid=$((tid + 1))
156 umbim $DBG -t $tid -d "$device" disconnect
157 proto_notify_error "$interface" NO_REGISTRATION
158 return 1
159 fi
160
161 echo "mbim[$$]" "Attach to network"
162 umbim $DBG -n -t $tid -d $device attach || {
163 echo "mbim[$$]" "Failed to attach to network"
164 tid=$((tid + 1))
165 umbim $DBG -t $tid -d "$device" disconnect
166 proto_notify_error "$interface" ATTACH_FAILED
167 return 1
168 }
169 tid=$((tid + 1))
170
171 pdptype=$(echo "$pdptype" | awk '{print tolower($0)}')
172 [ "$ipv6" = 0 ] && pdptype="ipv4"
173
174 local req_pdptype="" # Pass "default" PDP type to umbim if unconfigured
175 [ "$pdptype" = "ipv4" -o "$pdptype" = "ipv6" -o "$pdptype" = "ipv4v6" ] && req_pdptype="$pdptype:"
176
177 local connect_state
178 echo "mbim[$$]" "Connect to network"
179 connect_state=$(umbim $DBG -n -t $tid -d $device connect "$req_pdptype$apn" "$auth" "$username" "$password") || {
180 echo "mbim[$$]" "Failed to connect bearer"
181 tid=$((tid + 1))
182 umbim $DBG -t $tid -d "$device" disconnect
183 proto_notify_error "$interface" CONNECT_FAILED
184 return 1
185 }
186 tid=$((tid + 1))
187
188 echo "$connect_state"
189 local iptype="$(echo "$connect_state" | grep iptype: | awk '{print $4}')"
190
191 echo "mbim[$$]" "Connected"
192
193 local zone="$(fw3 -q network "$interface" 2>/dev/null)"
194
195 echo "mbim[$$]" "Setting up $ifname"
196 local mbimconfig="$(umbim $DBG -n -t $tid -d $device config)"
197 echo "$mbimconfig"
198 tid=$((tid + 1))
199
200 proto_init_update "$ifname" 1
201 proto_send_update "$interface"
202
203 [ -z "$dhcp" ] && dhcp="auto"
204 [ -z "$dhcpv6" ] && dhcpv6="auto"
205
206 [ "$iptype" != "ipv6" ] && {
207 json_init
208 json_add_string name "${interface}_4"
209 json_add_string ifname "@$interface"
210 ipv4address=$(_proto_mbim_get_field ipv4address "$mbimconfig")
211 if [ -n "$ipv4address" -a "$dhcp" != 1 ]; then
212 json_add_string proto "static"
213
214 json_add_array ipaddr
215 for address in $ipv4address; do
216 json_add_string "" "$address"
217 done
218 json_close_array
219
220 json_add_string gateway $(_proto_mbim_get_field ipv4gateway "$mbimconfig")
221 elif [ "$dhcp" != 0 ]; then
222 echo "mbim[$$]" "Starting DHCP on $ifname"
223 json_add_string proto "dhcp"
224 fi
225
226 [ "$peerdns" = 0 -a "$dhcp" != 1 ] || {
227 json_add_array dns
228 for server in $(_proto_mbim_get_field ipv4dnsserver "$mbimconfig"); do
229 json_add_string "" "$server"
230 done
231 json_close_array
232 }
233
234 proto_add_dynamic_defaults
235 [ -n "$zone" ] && json_add_string zone "$zone"
236 [ -n "$ip4table" ] && json_add_string ip4table "$ip4table"
237 json_close_object
238 ubus call network add_dynamic "$(json_dump)"
239 }
240
241 [ "$iptype" != "ipv4" ] && {
242 json_init
243 json_add_string name "${interface}_6"
244 json_add_string ifname "@$interface"
245 ipv6address=$(_proto_mbim_get_field ipv6address "$mbimconfig")
246 if [ -n "$ipv6address" -a "$dhcpv6" != 1 ]; then
247 json_add_string proto "static"
248
249 json_add_array ip6addr
250 for address in $ipv6address; do
251 json_add_string "" "$address"
252 done
253 json_close_array
254
255 json_add_array ip6prefix
256 for address in $ipv6address; do
257 json_add_string "" "$address"
258 done
259 json_close_array
260
261 json_add_string ip6gw $(_proto_mbim_get_field ipv6gateway "$mbimconfig")
262
263 elif [ "$dhcpv6" != 0 ]; then
264 echo "mbim[$$]" "Starting DHCPv6 on $ifname"
265 json_add_string proto "dhcpv6"
266 json_add_string extendprefix 1
267 [ "$sourcefilter" = "0" ] && json_add_boolean sourcefilter "0"
268 fi
269
270 [ "$peerdns" = 0 -a "$dhcpv6" != 1 ] || {
271 json_add_array dns
272 for server in $(_proto_mbim_get_field ipv6dnsserver "$mbimconfig"); do
273 json_add_string "" "$server"
274 done
275 json_close_array
276 }
277
278 proto_add_dynamic_defaults
279 [ -n "$zone" ] && json_add_string zone "$zone"
280 [ -n "$ip6table" ] && json_add_string ip6table "$ip6table"
281 json_close_object
282 ubus call network add_dynamic "$(json_dump)"
283 }
284
285 [ -z "$mtu" ] && {
286 local ipv4mtu=$(_proto_mbim_get_field ipv4mtu "$mbimconfig")
287 ipv4mtu="${ipv4mtu:-0}"
288 local ipv6mtu=$(_proto_mbim_get_field ipv6mtu "$mbimconfig")
289 ipv6mtu="${ipv6mtu:-0}"
290
291 mtu=$((ipv6mtu > ipv4mtu ? ipv6mtu : ipv4mtu))
292 }
293 [ -n "$mtu" -a "$mtu" != 0 ] && {
294 echo Setting MTU of $ifname to $mtu
295 /sbin/ip link set dev $ifname mtu $mtu
296 }
297
298 uci_set_state network $interface tid "$tid"
299 }
300
301 proto_mbim_setup() {
302 local ret
303
304 _proto_mbim_setup $@
305 ret=$?
306
307 [ "$ret" = 0 ] || {
308 logger "mbim bringup failed, retry in 15s"
309 sleep 15
310 }
311
312 return $ret
313 }
314
315 proto_mbim_teardown() {
316 local interface="$1"
317
318 local device
319 json_get_vars device
320 local tid=$(uci_get_state network $interface tid)
321
322 [ -n "$ctl_device" ] && device=$ctl_device
323
324 echo "mbim[$$]" "Stopping network"
325 [ -n "$tid" ] && {
326 umbim $DBG -t $tid -d "$device" disconnect
327 uci_revert_state network $interface tid
328 }
329
330 proto_init_update "*" 0
331 proto_send_update "$interface"
332 }
333
334 [ -n "$INCLUDE_ONLY" ] || add_protocol mbim