NetBSD desktop pt.2: Set up wireless networking on NetBSD with wpa_supplicant and dhcpcd


#1

Introduction

NetBSD nowadays supports many modern high-speed PCIe and USB wifi adapters, especially starting with 8.0, while wpa_supplicant has become a de facto standard for a powerful yet reasonably lightweight deamon capable of managing WPA/WPA2/IEEE 802.1X / (and WEP) connections on *nix systems, albeit Illumos will use wpad(1M) (early wpa_supplicant fork from Sun) + wificonfig(1M) client by default, and OpenBSD will use stock ifconfig (OpenBSD’s ifconfig is the only ifconfig version capable of managing WPA connections). However both wpad and OBSD’s ifconfig do not support secure 802.1X authentication through Extensible Authentication Protocol (EAP) in the form of EAP-TLS, EAP-TTLS, EAP-PEAP, EAP-MD5 and other auth algorithms.

Since most (all) ISPs use DHCP to automate network configuration for costumers on DSL standard home contracts, we’ll need a DHCP client too. While both OpenBSD and FreeBSD still use and maintain their own dhclient(8) forks, starting with 7.x, NetBSD recommends switching to dhcpcd(8), which was developed Roy Marples, who, among the other things, is also an historical NetBSD developer. Many Linux distributions now include dhcpcd in base, preferring it over ISC’s dhclient version, given the latter is less versatile than dhcpd’s hooks system, not as well maintained, more complex and proven vulnerable in more than one occasion.

dhcpcd runs in background and actively manages re-requests after expired lease time without needing to be called again. dhcpcd also provides a 10-wpa_supplicant hook which watches for wpa_supplicant events and manages DHCP re-request subsequently (e.g. allowing USB NICs hotplugging)

discover and configure your WLAN interface

NetBSD names network interfaces after the driver providing support for the device of interest. For example my Atheros NIC is based upon AR9285 chipset and as such, supported by athn(4) driver. As a consequence my network interface is called athn0. Drivers for most common NICs are already built in the GENERIC kernel: device will by recognized at boot and appear in dmesg:

athn0 at pci2 dev 0 function 0: Atheros AR9285
athn0: rev 2 (1T1R), ROM rev 13, address 0c:ee:e6:d9:25:29
athn0: interrupting at ioapic0 pin 16
athn0: 11b rates: 1Mbps 2Mbps 5.5Mbps 11Mbps
athn0: 11g rates: 1Mbps 2Mbps 5.5Mbps 11Mbps 6Mbps 9Mbps 12Mbps 18Mbps 24Mbps    36Mbps 48Mbps 54Mbps

For less common devices not compiled in GENERIC, you’ll need to either load the correct driver using modload(8), or include it in your custom kernel config. In order to verify your device is supported in NetBSD 8, ask for support, and/or understand which driver to load, you’ll need to know the chipset and optionally vendor/model id corresponding to your device specs. For PCI/PCIe cards you can grasp it with pcictl(8), in my case

% pcictl pci0 list | grep -i lan
   002:00:0: Atheros Communications AR9285 Wireless LAN (miscellaneous network, revision 0x01)

Otherwise, if you own a USB device, you can use usbdevs(8). After connecting my EDUP EP-MS150ND:

 % usbdevs -v | grep -i lan
    port 1 addr 3: high speed, power 500 mA, config 1, RTL8188S WLAN Adapter(0x8171), Manufacturer Realtek(0x0bda), rev 2.00(0x0200), serial 00e04c000001

Then you can compare the data you collected with PCI Hardware Supported by NetBSD as well as search amid the various drivers man pages available in the 4th category. For USB devices, check out the “Wireless network interfaces” section inside usb(4) man page. Drivers’ mans are fundamental, and should never be overlooked, since they specify the degree of support, provide troubleshooting, explain if some firmware or a license agreement is required and how to load or sign it respectively.

If properly recognized your interface will be listed under net.interfaces (as well as in ifconfig -l),

 % sysctl net.interfaces
   net.interfaces.athn0.rcvq.drops = 0
   net.interfaces.athn0.sndq.len = 0
   net.interfaces.athn0.sndq.maxlen = 256
   net.interfaces.athn0.sndq.drops = 0

A /etc/ifconfig.nnX file (e.g. /etc/ifconfig.athn0 ), containing interface-specific configuration files or variables, should now be created, refer to ifconfig.if(5) and ifconfig(5). Keep in mind each line is parsed by network() service as an ifconfig argument. A typical config will look like:

up
media autoselect
mode 11g
powersave
dhcp

Obviously power-saving through powersave option is totally optional (has downsides). Advanced users may want to replace media autoselect with another media definition for the IEEE802.11 WLAN link type (e.g. frequency hopping, refer to ifmedia(4)).

configure wpa_supplicant

Unless you know exactly the ssid,key-management proto, encryption method, optional auth algorithm etc…, of the network you wish to connect to already, you’ll need to know more about it:

 % ifconfig ahtn0 up
 % ifconfig athn0 list scan
    SSID                    BSSID              CHAN RATE  S:N     INT CAPS
    InfostradaWifi          b0:39:56:ac:49:a6   11   54M  28:0    100 EP   RSN WME
    DIRECT-x4M2020 Series   32:cd:a7:a0:f7:17   11   54M  17:0    100 EP   RSN WME
    Vodafone-45778202       bc:15:ac:e2:b5:8b   13   54M  32:0    100 EP   RSN WME
    Vodafone-WiFi           bc:15:ac:e2:b5:8d   13   54M  31:0    100 E    WME
    FASTWEB-1-bt5StJiRg6fZ  84:26:15:40:a5:b6    6   54M   3:0    100 EP   WPA WME
    La isla bonita!         cc:b2:55:e8:bc:f1    6   54M  47:0    100 EPS  WPA WME

I want to connect to ‘La isla bonita’, which uses a standard WPA Personal proto, wpa_suplicant’s default; all I’ll need to do is creating

ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=wheel
update_config=1
ap_scan=1
fast_reauth=1
eapol_version=2

network={
        ssid="La isla bonita!"
        key_mgmt=WPA-PSK
        psk="*********"
}
  • for hidden network add:

         scan_ssid=1
    
  • for WPA2 add:

         proto=RSN
         group=TKIP
    
  • for a open (insecure) WEP network:

       network={
         ssid="$network_ssid"
         key_mgmt=NONE
         auth_alg=OPEN
       }
    
  • Shared WEP key connection

    network={
        ssid="$network_ssid"
        key_mgmt=NONE
        wep_key0="**********"
        wep_tx_keyidx=0
        auth_alg=SHARED
     }
    

EAP is bit trickier and will not be covered here, refer to wpa_supplicant.conf(5);

Further notes:

  • priority=n value allows one to specify a preference when more than one known network is in reach

  • bssid= will come in handy when more netowrks with the same name are available but one is preferred (e.g. you have a powerline installed somewhere nearer than router)

important tweaks for correct services behaviour

  • You generally won’t need to edit DNS server on /etc/resolv,conf, as file is automatically generated and updated by resolvconf(8)

  • On a guided installation, NetBSD sysinstall will induce user to have a separate /usr partition. While this still results convenient on FFSv2 from a stability and security perspective, it can prove annoying when trying to start RC services at boot whose binaries by default reside on /usr, one of which is wpa_supplicant:

    $ which wpa_supplicant
      /usr/sbin/wpa_supplicant
    

if wpa_supplicant=YES is set inside /etc/rc.conf, rc(8) will likely attempt to start wpa_supplicant service before /usr partition is mounted at boot, thus failing in finding the wpa_supplicant command itself. According to rc.conf(8), in order to fix this we need to add /usr to critical_filesystems_local variable:

To stay sure, let’s add the new line at the beginning of rc.conf, just after rc_configured=YES:

$ sed -i '/rc_configured=YES/a \                                             
   > critical_filesystems_local="OPTIONAL:/var OPTIONAL:/usr"
   > ' /etc/rc.conf
  • On NetBSD 8, /etc/rc.d/wpa_supplicant service still calls dhclient instead of dhcpcd by default in the # BEFORE: NETWORKING.. query, resulting in wpa_supplicant not being tracked as service a dependency for dhcpcd. Let’s fix this:

      $ sed -i 's/dhclient/dhcpcd/g' /etc/rc.d/wpa_supplicant
    

enabling wpa_supplicant and dhcpcd

After much talking (yes, I tend to talk too much) we can finally enable wpa_supplicant and dhcpcd inside /etc/rc.conf, as follows:

 wpa_supplicant=YES
 wpa_supplicant_flags="-B -D bsd -i athn0 -c /etc/wpa_supplicant.conf"
 dhcpcd=YES
 dhcpcd_flags="-qM athn0 -b"

At reboot, we should have wireless up and working:

% ping ftp.netbsd.org
    PING ftp.netbsd.org (199.233.217.201): 56 data bytes
    64 bytes from 199.233.217.201: icmp_seq=0 ttl=241 time=185.933469 ms

% ifconfig athn0
    athn0: flags=0x8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    ssid "La isla bonita!" nwkey *****
    powersave on (100ms sleep)
    bssid cc:b2:55:e8:bc:f1 chan 6
    address: 0c:ee:e6:d9:25:29
    media: IEEE802.11 autoselect (OFDM48 mode 11g)
    status: active
    inet 192.168.1.13/24 broadcast 192.168.1.255 flags 0x0
    inet6 fe80::eee:e6ff:fed9:2529%athn0/64 flags 0x0 scopeid 0x1

NetBSD provides the wlanctl(8) utility to print node tables from WLAN interfaces; let’s use it:

 % wlanctl athn0
       athn0: mac cc:b2:55:e8:bc:f1 bss cc:b2:55:e8:bc:f1
       node flags 0005<bss,scan>
       ess <La isla bonita!>
       chan 6 freq 2437MHz flags 04e0<cck,ofdm,2.4GHz,dynamic cck-ofdm>
       capabilities 0531<ess,privacy,short preamble,short slot-time>
       beacon-interval 100 TU tsft 887008563584 us
       rates 1.0 2.0 5.5 6.0 9.0 11.0 12.0 18.0 24.0 36.0 [48.0] 54.0
       assoc-id 49154 assoc-failed 0 inactivity 300s
       rssi 44 txseq 10647 rxseq 12832

If you have no internet connection check out /var/log/messages for dhcpcd and wpa_supplicant errors. You may want to append a debug line to /etc/ifconfig.nnX, and pass -d option to both wpa_supplicant_flags=... and dhcpcd_flags=... inside /etc/rc.conf, so as to enable more verbose stderr, and restart both services with service() utility.

GUI fontends to wpa_supplicant and dhcpcd

At least 2 lightweight solutions are available inside pkgsrc:

  • net/wpa_gui. Has been my favourite for years, not only on NetBSD, verbose notifications and what else: recommended. Here’s a screenshot; to start it automatically, by default minimized to tray, add to ~/.xinitrc:

       sleep 5 && wpa_gui -t &
    

Hope this will prove useful to anybody


#2

Believe it or not, I’ve finally got an Intel chip to replace the crappy broadcom card that I had on my NetBSD laptop :yum:
I’ve replaced the chip and confirmed it’s detecting my three wifi bands.

I was actually planning in configuring the connection in the coming days, as I’ve been a bit too busy with other things lately, and was going to add the steps to my other thread.

Now you’ve, not only saved me from doing it, but also saved me from having to figure out all the steps, Thanks!! :joy:

EDIT: I’ll try to get it to work without wpa_gui though, as I have on Void. Trying to keep all my systems Qt-free :wink:


#3

This is EXCELLENT! Where have you been all my life? This is so helpful. Easy to follow, good examples. Great job.