Printing under FreeBSD

Recently I took delivery of a new multi-functional laser printer. Contrary to my old laser printer, that was connected to my aging 2009 Mac Pro via USB, this new printer has WiFi. This has been a great convenience; everyone in our household can now easily print from their MacBook or Chromebook without having to turn on the Mac Pro.

On my FreeBSD laptop - my primary development machine - I had to do a bit more work. Nothing really complicated, but there are one or two steps that you need to be aware of.

Installing CUPS

The CUPS Unix Printing System is the most popular and convenient printing system for Unix based systems. Installing it under FreeBSD was a simple matter of:

$ sudo pkg install cups
$ sudo sysrc cupsd_enable=YES
$ sudo service cupsd start

Installing Avahi

As I was not connecting the printer via USB I didn’t have to mess with devfs rules. I did, however, want my new printer to be discoverable by my FreeBSD laptop. As the printer supports mDNS I figured all I needed to do was install Avahi:

$ pkg install avahi
$ sudo sysrc avahi_daemon_enable=YES
$ sudo service avahi-daemon start

Unfortunately avahi-browse --all --verbose did not show the printer. Courtesy of the ipfw firewall. Briefly turning the firewall off (sudo service ipfw stop) and rerunning the avahi-browser --all --verbose command did show the printer along with a bunch of other devices:

Server version: avahi 0.7; Host name: ketoembar.local
E Ifce Prot Name                                          Type                 Domain
+  wlan0 IPv4 ketoembar                                     _ssh._tcp            local
+  wlan0 IPv4 ketoembar                                     _sftp-ssh._tcp       local
: Cache exhausted
+  wlan0 IPv4 sonos7828CA933A46                             _spotify-connect._tcp local
+  wlan0 IPv4 sonosB8E93733E324                             _spotify-connect._tcp local
+  wlan0 IPv4 Sonos-7828CA933A46                            _sonos._tcp          local
+  wlan0 IPv4 Sonos-B8E93733E324                            _sonos._tcp          local
+  wlan0 IPv4 Lexmark MC2535adwe                            _http._tcp           local
+  wlan0 IPv4 freenas                                       _adisk._tcp          local
+  wlan0 IPv4 freenas                                       _afpovertcp._tcp     local
+  wlan0 IPv4 freenas                                       _device-info._tcp    local
+  wlan0 IPv4 freenas                                       _http._tcp           local
+  wlan0 IPv4 freenas                                       _https._tcp          local
+  wlan0 IPv4 freenas                                       _middleware._tcp     local
+  wlan0 IPv4 freenas                                       _middleware-ssl._tcp local
+  wlan0 IPv4 freenas                                       _nfs._tcp            local
+  wlan0 IPv4 freenas                                       _smb._tcp            local
+  wlan0 IPv4 Lexmark MC2535adwe                            _ftp._tcp            local
+  wlan0 IPv4 Lexmark MC2535adwe                            _scanner._tcp        local
+  wlan0 IPv4 Lexmark MC2535adwe                            _printer._tcp        local
+  wlan0 IPv4 Lexmark MC2535adwe                            _uscan._tcp          local
+  wlan0 IPv4 Lexmark MC2535adwe                            _uscans._tcp         local
+  wlan0 IPv4 Lexmark MC2535adwe                            _ipp._tcp            local
+  wlan0 IPv4 Lexmark MC2535adwe                            _ipps._tcp           local
+  wlan0 IPv4 Lexmark MC2535adwe                            _privet._tcp         local
+  wlan0 IPv4 2389aaf6-4b77-58f5-7c2f-6f7231ca67d0          _googlezone._tcp     local
+  wlan0 IPv4 Chromecast-Ultra-2389aaf64b7758f57c2f6f7231ca67d0 _googlecast._tcp     local
: All for now

Amending the Firewall Ruleset

mDNS multicast UDP packets can either be sent with a high-numbered ephemeral UDP source port (>= 1024) in case of one-shot multicast DNS queries or with a source port of 5353 in case of continuous multicast DNS querying. In both cases the destination port is 5353. Hence amending the firewall ruleset was a matter of adding these two rules:

02600 allow udp from any to any 5353
02700 allow udp from any 5353 to any 1024-65535 in

Starting the firewall again using sudo service ipfw start and running avahi-browser --all --verbose showed mDNS now to be working properly with the firewall active.

Extending Host Name lookups

With these changes CUPS was able to find my printer (CUPS admin interface: http://127.0.0.1:631/admin -> Find New Printers). But even though I had the printer properly configured using a PPD file from Open Printing, CUPS was not able to communicate with it. Turned out I had to extend host name lookups to utilize mDNS as well. This was a two step process.

First, one needs to run the Avahi unicast DNS server avahi-dnsconfd:

$ sudo sysrc avahi_dnsconfd_enable=YES
$ sudo service avahi-dnsconfd start

Second, one needs to update /etc/nsswitch.conf by changing the line:

hosts: files dns

to:

hosts: files mdns_minimal dns mdns

No need to restart anything. The change to /etc/nsswitch.conf was picked up immediately and CUPS could communicate with my printer.

Conclusion

Setting up printing to a networked printer under FreeBSD is not complicated. It only requires four steps. Of which the firewall one was arguably the most “complicated” one; I had to read up how mDNS works to come up with the proper firewall rules. The other thing to be aware of is to extend host name lookups to additionally utilize mDNS.