tree: 236482b6860489c83e10afb39ba9aa78efe3f47b [path history] [tgz]
  1. init/
  2. seccomp/
  3. src/
  4. udev/
  5. Cargo.toml
  6. OWNERS
  7. README.md
ippusb_bridge/README.md

Ippusb Bridge

ippusb_bridge manages communication with a printer that supports the USB IPP protocol. After being started by udev when a supported device is plugged in, ippusb_bridge proxies HTTP requests to the printer's web server through its IPP-over-USB endpoints. This allows driverless network protocols such as eSCL and IPP to be used over USB. ippusb_bridge listens on a local socket under /run/ippusb by default, but can also be configured to listen on a local TCP port.

ippusb_bridge was originally a drop-in replacement for ippusbxd for Chrome OS. Similar to ipp-usb, ippusb_bridge adds full understanding of HTTP requests so that it doesn‘t leave the IPP-over-USB tunnel in an invalid state if a client doesn’t fully process a request or response. We would originally have preferred to use ipp-usb on Chrome OS instead, but its binary size (~9MB) precludes it.

Since then, ippusb_bridge has also taken over the functionality of ippusb_manager (which no longer exists) and has gained other Chrome OS specific features (local sockets, sharing USB interfaces with cupsd, etc).

Googlers: see http://go/cros-image-size-process-proposal for context on why 9 MB is considered “too big” for inclusion.

Invocation

  • ippusb_bridge registers udev rules that spawn it when udevd detects a newly-attached USB printer that supports IPP-over-USB interfaces.
  • The udev trigger launches an upstart job for process lifecycle management.
  • Because it processes untrusted data (print jobs and other HTTP exchanges), ippusb_bridge runs in a minijailed environment with seccomp filters.

General Operation

  • The primary goal of ippusb_bridge is to maintain a Unix socket in a predictable location, facilitating communication from either cupsd, lorgnette, or other local software that has appropriate permissions.
    • This particular functionality is unique to the copy of CUPS packaged for Chromium OS.
    • The socket's containing directory is /run/ippusb and its basename is built from its vendor ID and product ID: ${VID}-${PID}.sock. These IDs propagate from the udev trigger down to a command-line argument given to ippusb_bridge.
  • ippusb_bridge continues running, ferrying messages back and forth across the given Unix socket, until the printer is unplugged.
  • When no clients are actively using an IPP-over-USB interface, ippusb_bridge releases the interfaces after a timeout. This allows traditional cupsd communication to the same device through the standard printer USB classes. ippusb_bridge automatically reclaims interfaces when a new client connects.

Debugging

Upstart

Upstart will try to keep ippusb_bridge running as long as the USB device is plugged in. If you need to run it by hand, you can stop the upstart job first:

stop ippusb-bridge BUS=NNN DEV=MMM VID=xxxx PID=yyyy

NNN and MMM need to be 3 characters. xxxx and yyyy need to be 4 lowercase hex characters.

If you run it by hand without the -s argument, ippusb_bridge will listen on localhost:60000 instead of a socket in /run/ippusb. This can be handy if you have want to compare the behavior with ipp-usb or some other software that doesn‘t support local sockets. Since ippusb_bridge doesn’t advertise on mDNS, you will need to manually construct a scanner URL, such as airscan:escl:Test:http://localhost:60000/eSCL/.

Note that running by hand may produce different behavior due to the lack of sandboxing. If you need to reproduce the sandboxed environment, you can replace stop with start in the above command to get upstart to launch ippusb_bridge again.

Signals

ippusb_bridge expects to be stopped with SIGINT, not SIGTERM. If you kill it by hand, be sure to use kill -INT. Otherwise, ippusb_bridge will leave its socket behind in /run/ippusb and will not start again until the socket is removed manually.

Protocol traces

If you run ippusb_bridge with the -v flag, it will dump most HTTP traffic to the log. You can add this flag to the upstart job and stop/start as described above, or run ippusb_bridge by hand. Note that the traffic will not be decoded.

cupsd and sane-airscan also have their own mechanisms for dumping higher-level protocol info, or see below for a way to get the lower-level USB traffic if needed.

USB

If the USB tunnel gets into a funny state, restarting ippusb_bridge will often clean it up when it resets the device's active configuration. It is not uncommon to trigger USB problems during development, but if you find a reproducible way to leave the tunnel in a non-functioning state during normal operation, please file a bug.

When things are going wrong with low-level communication, it can be helpful to sniff the raw USB packets:

  1. modprobe usbmon
  2. lsusb and find the bus where the printer is attached
  3. tcpdump -i usbmonN -w /tmp/usbmon.pcap, where N is the bus number
  4. Copy /tmp/usbmon.pcap to your workstation and open it in wireshark. You may need to enable some additional USB protocols under Analyze -> Enabled Protocols

Miscellanea

  • ippusb_bridge depends on the tiny_http crate. tiny_http was patched
    • to build without SSL features and
    • to support operating over Unix sockets.