1

There are several tutorials out there to setup an Ad Hoc network, for example Ad Hoc setup in RPi 3. But how can I do this using systemd-networkd? And all what I've found is using unprotected communication without encryption. Is it possible to use a setup with WPA encryption?

0

There are mainly three setups to have a peer to peer network:

  • unprotected ad-hoc interface by configuring the WiFi device
  • unprotected ad-hoc interface using wpa_supplicant
  • protected ad-hoc interface using wpa_supplicant and WPA encryption

For reference I use a RPi 3B+ with Raspbian Stretch Lite 2019-04-08 from scratch updated with
sudo apt update && sudo apt full-upgrade && sudo reboot at 2019-04-14.


♦ Setup systemd-networkd

For detailed information look at (1). Here only in short. Execute these commands:

# disable classic networking
rpi ~$ sudo -Es
rpi ~# systemctl mask networking.service
rpi ~# systemctl mask dhcpcd.service
rpi ~# mv /etc/network/interfaces /etc/network/interfaces~
rpi ~# sed -i '1i resolvconf=NO' /etc/resolvconf.conf

# enable systemd-networkd
rpi ~# systemctl enable systemd-networkd.service
rpi ~# systemctl enable systemd-resolved.service
rpi ~# ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

Configure interface wlan0 with this file. Give it your own ip address:

rpi ~# cat > /etc/systemd/network/08-wlan0.network <<EOF
[Match]
Name=wlan0
[Network]
Address=192.168.4.1/24
EOF

♦ Setup unprotected ad-hoc interface by configuring WiFi device

First Setup systemd-networkd.

To configure the wifi into ad-hoc mode we only have to execute two commands (don't do that now):

iw wlan0 set type ibss
iw wlan0 ibss join RPiNet 2412 # frequency 2412 is channel 1

For a mapping of frequencies to channels look at 3. I use a systemd unit so we can also stop the service. Create a new unit file with:

rpi ~# systemctl --force --full edit ad-hoc-interface@wlan0.service

In the empty editor insert these statements, save it and quit the editor:

[Unit]
Description=Unprotected ad-hoc (IBSS) interface
Requires=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device
Wants=network.target
Before=network.target

[Service]
Environment="SSID=IBSS-RPiNet" "FREQUENCY=2412"
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/sbin/iw %I set type ibss
ExecStart=/sbin/iw %I ibss join $SSID $FREQUENCY
ExecStopPost=-/sbin/iw dev %I ibss leave
ExecStopPost=-/sbin/iw %I set type managed

[Install]
WantedBy=network.target

Enable the service:

rpi ~# systemctl enable ad-hoc-interface@wlan0.service

reboot.

Check with:

rpi ~$ iw dev
rpi ~$ iw dev wlan0 link
rpi ~$ ip addr
rpi ~$ sudo iw dev wlan0 scan | grep -B8 -A3 "SSID: IBSS-RPiNet"

You should be able to:

rpi ~$ sudo systemctl stop ad-hoc-interface@wlan0.service
rpi ~$ sudo systemctl start ad-hoc-interface@wlan0.service

To change the ssid and frequency you can edit the unit file:

rpi ~$ sudo systemctl --full edit ad-hoc-interface@wlan0.service

♦ Setup unprotected ad-hoc interface using wpa_supplicant

If you start from a fresh flashed Raspbian image then first Setup systemd-networkd.

If you have tried unprotected ad-hoc interface by configuring the WiFi device then do sudo systemctl --now disable ad-hoc-interface@wlan0.service.

Then Setup wpa_supplicant with this file and your settings (ssid) and enable it:

rpi ~$ sudo -Es
rpi ~# cat > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf <<EOF
country=DE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
    ssid="IBSS-RPiNet"
    frequency=2412
    mode=1   # IBSS (ad-hoc, peer-to-peer)
    key_mgmt=NONE
}
EOF

1pi ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
rpi ~# systemctl enable wpa_supplicant@wlan0.service

I have found that the wpa_supplicant.service uses driver nl80211 by default. But it cannot handle ad-hoc mode (see developer section). We have to use driver wext. To modify the service we create a drop-in file:

rpi ~# systemctl edit wpa_supplicant@wlan0.service

In the editor insert these statements, save it and quit the editor:

[Service]
ExecStart=
ExecStart=/sbin/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -Dwext -i%I

reboot.

Check with:

rpi ~$ iw dev
rpi ~$ iw dev wlan0 link
rpi ~$ ip addr
rpi ~$ sudo iw dev wlan0 scan | grep -B8 -A3 "IBSS-RPiNet"

♦ Setup protected RSN (WPA) ad-hoc interface using wpa_supplicant

First of all it must be said that Raspberry Pi does not support encrypted IBSS connections!. You have to use an additional USB WiFi dongle that usually registers an interface wlan1. My dongle shows:

rpi ~$ iw list | less
Wiphy phy1
        [..]
        Device supports RSN-IBSS.
        [..]

You cannot find this support entry for Wiphy pyh0 that is the on-board WiFi device.

So plug in your compatible WiFi dongle and if you start from a fresh flashed Raspbian image then first Setup systemd-networkd.

If you have tried unprotected ad-hoc interface by configuring the WiFi device then do sudo systemctl --now disable ad-hoc-interface@wlan0.service.

If you have tried unprotected ad-hoc interface using wpa_supplicant then do sudo systemctl --now disable wpa_supplicant@wlan0.service.

Then Setup wpa_supplicant with this file and your settings (ssid, psk and frequency) and enable it:

rpi ~$ sudo -Es
rpi ~# cat > /etc/wpa_supplicant/wpa_supplicant-wlan1.conf <<EOF
country=DE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
    ssid="IBSS-RPiNet"
    key_mgmt=WPA-PSK
    proto=RSN
    psk="verySecretPassword"
    mode=1
    frequency=2412
}
EOF

1pi ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan1.conf
rpi ~# systemctl enable wpa_supplicant@wlan1.service

reboot.

Check with:

rpi ~$ iw dev
rpi ~$ iw dev wlan1 link
rpi ~$ ip addr
rpi ~$ sudo iw dev wlan1 scan | grep -B8 -A3 "IBSS-RPiNet"

♦ Installing additional nodes

On additional nodes setup ad-hoc mode just the same way you have done with the first one as shown above. The only difference is that you must give unique ip addresses in /etc/systemd/network/08-wlan0.network for each node of course.


♦ For developers and for troubleshooting

This are some things I have done to find the answer. I do not want to discard them because it has taken some effort and it may help me later and others on similar issues.

manual setup
For testing how it works you can execute these commands [2]. Be sure the interface isn't occupied by another service:

rpi ~$ sudo -Es
rpi ~# iw wlan0 set type ibss
rpi ~# ip link set wlan0 up
rpi ~# iw wlan0 ibss join RPiNet 2432
rpi ~# ip addr add 192.168.1.2/24 dev wlan0
rpi ~# ip route add 192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.2
rpi ~# exit

rpi ~$ # check with:
rpi ~$ iw dev
rpi ~$ iw dev wlan0 link
rpi ~$ ip addr
rpi ~$ sudo iw dev wlan0 scan | grep -B8 -A3 "SSID: RPiNet"

You can do this also on a second raspi with another ip address, e.g. 192.168.1.3. Then you can ping it.

unusable background driver nl80211 with on-board wifi
On testing with wpa_supplicant using ad-hoc mode I always get a strange initialization that looks like this:

rpi ~$ iw dev
phy#0
        Unnamed/non-netdev interface
                wdev 0x2
                addr 86:50:89:38:f2:93
                type P2P-device
                txpower 31.00 dBm
        Interface wlan0
                ifindex 3
                wdev 0x1
                addr b8:27:eb:06:e8:8b
                type managed
                channel 34 (5170 MHz), width: 20 MHz, center1: 5170 MHz
                txpower 31.00 dBm

Using another USB/WiFi dongle I do not get this strange Unnamed/non-netdev interface and I can use background driver nl80211. So it's definitely a bug on the Raspberry Pi.

When you get this Unnamed/non-netdev interface (type P2P-device) then you have a problem. It occupies the interface. When trying to iw wlan0 set type ibss I got the error messages:

Jul 07 22:06:17 wpa_supplicant[262]: nl80211: Failed to set interface into IBSS mode
Jul 07 22:06:17 wpa_supplicant[262]: wlan0: Association request to the driver failed

Looking with systemctl cat wpa_supplicant@wlan0.service you can see that wpa_supplicant is using first driver nl80211 and then driver wext. This is given by parameter -Dnl80211,wext

rpi ~$ systemctl cat wpa_supplicant@wlan0.service | grep '^ExecStart='
ExecStart=/sbin/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -Dnl80211,wext -i%I

I found using background driver wext avoids this unnamed interface with on-board WiFi (wlan0). For a detailed verification of this issue you can look at Raspberry Pi 2018-04-18 - Cannot put device into adhoc mode. So we have to use a drop-in file to change the parameter to -Dwext.


refefences:
[1] Howto migrate from networking to systemd-networkd with dynamic failover
[2] Ad-hoc networking
[3] List of WLAN channels
[4] Raspberry Pi 2018-04-18 - Cannot put device into adhoc mode
[5] Kernel trace in brcmfmac wifi driver when joining ad-hoc network w/another brcmfmac device
[6] Linux WiFi Ad-hoc mode
[7] What is the difference between Ad-Hoc and Mesh Network? (also with p2p)
[8] Why Wi-Fi Direct can not replace Ad-hoc mode

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.