3

This question is an extension of the information on this post.
This question looks the same as this one but it is not. I am using systemd-networkd.

I successfully followed the instructions in the post to create a simple stand-alone AP. Just what I wanted.

I'd like to be able to swap between being a wifi AP and just a normal wifi client. The default would be a client. For my application, if the RPi reboots, I want the default client wifi config to run, not as an AP. I need to assign a static IP for AP operation, and I need to assign a dynamic IP for normal client wifi operation.

I think there are three things I need to do.

  1. point WPA_supplicant to an alternative config file,

  2. enable the default service to run on boot and,

  3. swap the WLAN network config between static and dynamic IP addresses(application specific).

I don't know the best way to modify the wpa settings in software. I definitely do not want to reboot. That is toooo slow.

I also need to change the network settings. According to the manual: man systemd.network

Along with the network file foo.network, a "drop-in" directory foo.network.d/ may exist. All files with the suffix ".conf" from this directory will be parsed after the file itself is parsed. This is useful to alter or add configuration settings, without having to modify the main configuration file. Each drop-in file must have appropriate section headers.

Not sure of the best way to swap network configurations. I could swap .conf file(s) in/out of the drop-in directory to make the network changes. Then restart the network service.

1
  • I am thinking that I could convert /etc/wpa_supplicant/wpa_supplicant-wlan0.conf into a symbolic link that pointed to either a client or ap config file. I don't know if networkd stop/start would cause wpa_supplicant to reload the config file.
    – dazz
    Commented Sep 27, 2018 at 19:40

1 Answer 1

1

UPDATE: 2019-01-21
Because I get a question from time to time about this setup I decided to present an accepted answer at Switch between wifi client and access point without reboot.
Please refer to that answer because the following isn't maintained anymore!


According to your referenced link you are already using systemd-networkd. So I will start with configuring wlan0 as client connection. For reference I use Raspbian Stretch Lite 2018-06-27 full upgraded with sudo apt update && sudo apt full-upgrade && reboot done at 2018-09-27.

Setup wpa_supplicant as wifi client with wlan0

Setup wpa_supplicant with this file and your settings 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="[email protected]"
    psk="verySecretPwassword"
}
EOF

rpi ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
rpi ~# systemctl disable wpa_supplicant.service
rpi ~# systemctl enable [email protected]

Setup wpa_supplicant as access point with ap0

Create this configuration file:

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

network={
    ssid="RPiNet"
    mode=2
    key_mgmt=WPA-PSK
    psk="anotherPassword"
    frequency=2412
}
EOF

rpi ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-ap0.conf

Configure interfaces

Create these two configuration files:

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

rpi ~# cat > /etc/systemd/network/12-ap0.network <<EOF
[Match]
Name=ap0
[Network]
Address=192.168.4.1/24
DHCPServer=yes
[DHCPServer]
DNS=84.200.69.80 84.200.70.40
EOF

Modify service for access point to use ap0

ap0 is a virtual interface and it must be created and deleted with start/stop of the service. It is also required to modify dependencies. This cannot be done with a drop in file, so we have to modify the full service. In addition this service conflicts with the client connection service with wlan0. We set a dependency Conflicts= so we do not have to care about stopping the other service. Do it with:

rpi ~# systemctl disable [email protected]
rpi ~# systemctl edit --full [email protected]

Modify/insert only these lines: Requires=, After=, Conflicts=, ExecStartPre= and ExecStopPost= as shown. Leave all other untouched, save it and quit the editor:

[Unit]
Description=WPA supplicant daemon (interface-specific version)
Requires=sys-subsystem-net-devices-wlan0.device
After=sys-subsystem-net-devices-wlan0.device
[email protected]
Before=network.target
Wants=network.target

# NetworkManager users will probably want the dbus version instead.

[Service]
Type=simple
ExecStartPre=/sbin/iw dev wlan0 interface add ap0 type __ap
ExecStart=/sbin/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -Dnl80211,wext -i%I
ExecStopPost=/sbin/iw dev ap0 del

[Install]
Alias=multi-user.target.wants/wpa_supplicant@%i.service

Reboot.

Check with:

rpi ~$ sudo iw dev
rpi ~$ systemctl status [email protected]

You should then be able to:

rpi ~$ sudo systemctl start [email protected]
rpi ~$ sudo systemctl start [email protected]

No need to stop a service.

You may install this little helper to get faster random numbers for encryption:

rpi ~$ sudo apt install rng-tools

Troubleshooting

If you do not use Raspbian Stretch Lite 2018-06-27 full upgraded with sudo apt update && sudo apt full-upgrade && reboot like me then you should download the image and try with it if you have a spare SD Card. This is to ensure it's not a problem with the hardware. If you use this version but have already done some installations and/or configurations it may be possible that you run into a common problem with configuring an access point.

If the physical interface, here it is wlan0, is occupied by a driver you may not be able to set an additional virtual interface ap0 on it. The error message is: command failed: Device or resource busy (-16). You can find this message in the journal. Look for messages like following with:

rpi ~$ journalctl -b -e
...
raspberrypi systemd[1]: Starting WPA supplicant daemon (interface-specific version)...
raspberrypi iw[641]: command failed: Device or resource busy (-16)
raspberrypi systemd[1]: [email protected]: Control process exited, code=exited status=240
raspberrypi systemd[1]: Failed to start WPA supplicant daemon (interface-specific version).
raspberrypi systemd[1]: [email protected]: Unit entered failed state.
raspberrypi systemd[1]: [email protected]: Failed with result 'exit-code'.

Here you see the line prefixed with: raspberrypi iw[641]:. It is the line we are looking for. It is now up do you to find what service on your installation occupies the wifi device. You can test if the access point starts when you delete ap0 before:

rpi ~$ sudo iw dev ap0 del
rpi ~$ sudo systemctl start [email protected]

If it works you can add a line just before ExecStartPre= in [email protected]. Consider the minus sign after the equal sign. It supresses error messages in case there is no ap0:

ExecStartPre=-/sbin/iw dev ap0 del

Now we have two ExecStartPre. You can try to set ap0 before any other service. This is done with this extra service, created with sudo systemctl edit --force --full interface-ap0.service:

[Unit]
Description=Interface for the access point
Documentation=https://raspberrypi.stackexchange.com/q/89428/79866
Requires=sys-subsystem-net-devices-wlan0.device
After=sys-subsystem-net-devices-wlan0.device
Wants=network.target
Before=network.target
[email protected]

[Service]
Type=oneshot
ExecStart=/sbin/iw dev wlan0 interface add ap0 type __ap

[Install]
WantedBy=multi-user.target

Enable it:

rpi ~$ sudo systemctl enable interface-ap0.service

Reboot.

But interface-ap0.service may not help if the unknown service, occupying the wifi device, also starts Before=network.target. If you find the unknown service you can add a line Before=name-of-unknown.service In the Unit section of interface-ap0.service.

Maybe you can find some hints with:

rpi ~$ systemctl list-dependencies
19
  • Thank you for your detailed instructions. Easy to follow.
    – dazz
    Commented Sep 28, 2018 at 5:38
  • It doesn't quite work yet. The logs indicate the command 'ExecStartPre=/sbin/iw dev wlan0 interface add ap0 type __ap' failed. Could it be the 'type__ap' part??
    – dazz
    Commented Sep 28, 2018 at 5:55
  • No, the type is OK. But the wifi driver brcmfmac is a bit buggy with access point so it it very sensitive. Is it the error message command failed: Device or resource busy (-16)?
    – Ingo
    Commented Sep 28, 2018 at 7:52
  • No. I am getting the error message: Process 581: ExecStartPre=/sbin/iw dev wlan0 interface add ap0 type ap (code=exited, status=2) Note that I have removed the underscores between type and ap. They didn't seem to match the documentation I found. Still doesn't work without the underscores.
    – dazz
    Commented Sep 28, 2018 at 8:13
  • wlan0 seems to be working as expected. I have problems when trying to swap to running ap mode.
    – dazz
    Commented Sep 28, 2018 at 8:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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