Tinymbim ======== Tinymbim is a command-line utility to control an MBIM-compatible mobile broadband modem on Linux using its cdc-wdm or wwan control device. The MBIM protocol is insanely overengineered, with a specification running to 230 pages, but this tool supports a simple subset sufficient to bring up a mobile internet connection. Demonstration ------------- Using a Quectel EP06-E 4G/LTE broadband modem configured in MBIM mode, with the kernel drivers enabled (as discussed below) and a Vodafone UK SIM: # ls -l /dev/cdc-wdm0 crw------- 1 root root 180, 176 Jul 23 11:38 /dev/cdc-wdm0 # mbim /dev/cdc-wdm0 open # mbim /dev/cdc-wdm0 subscriber ready-state initialized sim-icc-id nnnnnnnnnnnnnnnnnnnn subscriber-id nnnnnnnnnnnnnnn # mbim /dev/cdc-wdm0 connect internet session-id 0 activation-state activated ip-type ipv4 # mbim /dev/cdc-wdm0 config interface wwan0 address 10.25.152.131/29 gateway 10.25.152.132 dns 10.206.128.1 dns 10.206.128.1 mtu 1500 Configuring and testing the interface: # ip address add 10.25.152.131/29 dev wwan0 # ip link set wwan0 up # ip route add default via 10.25.152.132 # ping 8.8.8.8 PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=115 time=55.9 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=115 time=57.7 ms [...] Closing the session: # ip link set wwan down # ip address flush dev wwan0 # mbim /dev/cdc-wdm0 close Usage ----- The mbim utility is invoked as mbim DEVICE CMD [ARG]... where DEVICE is the path to a cdc-wdm or wwan control device and CMD is one of the commands below. There are no flags or options. Run with no arguments or an unknown command, it summarises supported commands to standard error. All commands that generate output do so in key-value lines as seen in the demonstration above. Each key consists of lower-case letters and hyphens, i.e. /[a-z-]+/, followed by a space, then the field value. Integer values are always decimal. Strings are unquoted but scrubbed of newlines, NULs and other control characters, making the format safe and unambiguous for a shell read loop. Enum values contain a single keyword of the form /[a-z0-9-]+/, and mask values are a list of zero or more such keywords joined with spaces. Device open and close --------------------- Before interacting with a device, it must be initialised with 'mbim open'. This command succeeds silently, or fails with an error if the modem is not configured to speak MBIM, the kernel does not have CONFIG_USB_NET_CDC_MBIM support, or the wrong device is specified. Conversely, 'mbim close' shuts down an open device. It is not necessary to disconnect or detach before closing. Device capabilities ------------------- List the capabilities of the device with 'mbim caps', including cellular technology, available data classes, hardware model and firmware version. For example: # mbim /dev/cdc-wdm0 caps device-type remote cellular-class gsm voice-class none sim-class removable data-class umts hsdpa hsupa lte sms-caps pdu-receive pdu-send control-caps reg-manual max-sessions 8 device-id nnnnnnnnnnnnnnn firmware-info EP06ELAR03A08M4G hardware-info EP06-E Subscriber ready-state ---------------------- 'mbim subscriber' queries the ready-state, which will be 'initialized' if the SIM is inserted, unlocked and initialised. It seems to be necessary to run this command after opening the device, or 'mbim connect' will fail. Radio power state ----------------- Read or set the radio power state with 'mbim radio'. Run without arguments, it lists the hardware and software radio switch state. Run with an argument of '0' or 'off', it turns off the software radio switch. With any other argument, such as '1' or 'on', it turns on the software radio switch. PIN status ---------- 'mbim pin' queries the PIN status if no argument is given, or enters a PIN to unlock the SIM if one is supplied as an argument. Home provider ------------- Find the subscriber's home provider using 'mbim home'. For example: # mbim /dev/cdc-wdm0 home provider-id 23415 provider-name vodafone UK provider-state home cellular-class gsm Visible providers ----------------- List all providers within range using 'mbim visible'. For example: # mbim /dev/cdc-wdm0 visible provider-id 23415 provider-name vodafone UK provider-state home preferred visible registered cellular-class gsm provider-id 23430 provider-name EE provider-state forbidden visible cellular-class gsm The provider-id values can be used when manually selecting a provider with 'mbim register'. This command can take some time to complete, and it may fail with a 'Device is busy' error if there is an active IP connection. Registration ------------ Without an argument, 'mbim register' reads the current device registration state, including the current provider, cellular and data classes, and whether automatic selection is enabled. Run as 'mbim register auto', it configures the device to select the best provider network automatically. Run with a provider ID as an argument, it manually registers with the specified provider network. Attach and detach ----------------- Attach or detach from the provider's packet service using 'mbim attach' or 'mbim detach'. These return nominal uplink and downlink speeds on success. Apparently 'mbim attach' is not required before 'mbim connect'. Signal strength --------------- Check the signal strength and error rate with 'mbim signal'. This returns two keys: rssi is the signal strength in dBm and error-rate runs from 0 if the bit error rate < 0.2% to 7 if the bit error rate > 12.8%. If either value is unknown, it is omitted entirely from the output. Connect and disconnect ---------------------- 'mbim connect APN' brings up an IP connection using the access string APN. The device selects a default address family but prefixing APN with 'ipv4:', 'ipv6:' or 'ipv4v6:' will override its choice.. If authentication is required, three extra parameters can be given: the method (pap, chap or mschapv2), username and password. For example: # mbim /dev/cdc-wdm0 connect ipv4:internet chap web web session-id 0 activation-state activated ip-type ipv4 Disconnect using 'mbim disconnect'. This is required before reconnecting with a different APN, IP family or authentication details. IP configuration ---------------- Once an IP connection is successfully established, read the configuration to apply to the host-side network interface with 'mbim config'. For example: # mbim /dev/cdc-wdm0 config interface wwan0 address 10.25.152.131/29 gateway 10.25.152.132 dns 10.206.128.1 dns 10.206.128.1 mtu 1500 The interface name is deduced from sysfs, and is the network interface corresponding to the given cdc-wdm or wwan device. It always appears before other keys to simplify scripts consuming the key-value output lines. The address, gateway and dns keys may be repeated to supply multiple IPv4 or IPv6 addresses, and the netmask is included in the case of the address key. Exactly one address is supplied per key. The interface name can also be obtained on its own with 'mbim interface'. Unlike 'mbim config', this also works without an open device or established connection and returns an error if no interface name could be found. Bringing up a network connection -------------------------------- The minimal sequence of operations needed to bring up an internet connection appears to be 'mbim open', 'mbim subscriber' then 'mbim connect'. (Without the 'mbim subscriber' query, 'mbim connect' fails on my EP06-E modem.) The wwan interface can then be configured from the output of 'mbim config' using 'ip address add' and 'ip link set up'. To shut down a connection, flush addresses with 'ip address flush', take the link down with 'ip link set down', then call 'mbim close'. These steps are automated by the included wwan demonstration script. 4G/LTE carriers supporting IPv6 typically delegate a single /64 which a router might want to advertise to a local network. A simple way to achieve this is to move the assigned global address from the wwan interface to the lan interface, enable IPv6 forwarding and router advertisements, and leave the wwan link-local address and default route untouched. See section 4.2 of RFC 7278 for more details. Differences from umbim and libmbim/mbimcli ------------------------------------------ Libmbim and mbimcli have broad support for MBIM features including firmware update, concurrent sessions, phonebook and device service stream; umbim and tinymbim focus on just the 'basic connect' interface needed to bring up a network connection. Tinymbim exposes explicit device open and close commands, whereas libmbim and umbim implicitly open and close depending on the --no-open=TID and --no-close options to mbimcli, or the -n and -t TID options to umbim. Because open and close are distinct commands, tinymbim sends exactly one message per invocation. This allows tinymbim to use its PID as a reliably unique transaction ID, sparing users the noise of managing TIDs manually. Modems are complex devices, usually running hard-to-audit proprietary software. They are best treated as an untrusted part of the network and a potential adversary. Tinymbim rigorously validates every offset and length within response packets to avoid dereferencing out-of-bounds memory, scrubs control characters from strings, and rejects invalid unicode strings. Tinymbim does not link against external libraries or require heavyweight build infrastructure; umbim depends on libubox and builds with cmake; libmbim depends on glib and builds with meson, pkgconfig and python. Building and installing ----------------------- Unpack the source tar.gz file and change to the unpacked directory. Run 'make' then 'make install' to install the mbim utility in /bin. Alternatively, you can set DESTDIR and/or BINDIR to install in a different location, or strip and copy the compiled binary into the correct place manually. Tinymbim assumes a Linux-specific cdc-wdm device interface, but otherwise should build and work out of the box on reasonably recent musl/glibc and clang/gcc. Your kernel will need CONFIG_USB_WDM and CONFIG_USB_NET_CDC_MBIM to support MBIM modems, which by default appear as a character device /dev/cdc-wdm0 plus a network interface wwan0. Some modems must be manually reconfigured to present as MBIM devices. For example, my Quectel EP06-E needed AT+QCFG="usbnet",2 to switch into MBIM mode, although this setting then persists across power-cycles. Please report any problems or bugs to Chris Webb <chris@arachsys.com>. Copying ------- Tinymbim is based on OpenWrt umbim by John Crispin <blogic@openwrt.org>, although Chris Webb <chris@arachsys.com> is now to blame for any bugs as the user interface and internal structure have been heavily modified. This software is distributed under the terms of the GNU GPL version 2, as included in GPLV2.