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.

Ingo
  • 40,606
  • 15
  • 76
  • 189
dazz
  • 155
  • 1
  • 1
  • 9
  • 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 Sep 27 '18 at 19:40

1 Answers1

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="wlan@hoeft-online.de"
    psk="verySecretPwassword"
}
EOF

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

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 wpa_supplicant@ap0.service
rpi ~# systemctl edit --full wpa_supplicant@ap0.service

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
Conflicts=wpa_supplicant@wlan0.service
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 wpa_supplicant@ap0.service

You should then be able to:

rpi ~$ sudo systemctl start wpa_supplicant@ap0.service
rpi ~$ sudo systemctl start wpa_supplicant@wlan0.service

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]: wpa_supplicant@ap0.service: Control process exited, code=exited status=240
raspberrypi systemd[1]: Failed to start WPA supplicant daemon (interface-specific version).
raspberrypi systemd[1]: wpa_supplicant@ap0.service: Unit entered failed state.
raspberrypi systemd[1]: wpa_supplicant@ap0.service: 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 wpa_supplicant@ap0.service

If it works you can add a line just before ExecStartPre= in wpa_supplicant@ap0.service. 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
Before=wpa_supplicant@ap0.service

[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
Ingo
  • 40,606
  • 15
  • 76
  • 189
  • Thank you for your detailed instructions. Easy to follow. – dazz Sep 28 '18 at 05: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 Sep 28 '18 at 05: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 Sep 28 '18 at 07: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 Sep 28 '18 at 08:13
  • wlan0 seems to be working as expected. I have problems when trying to swap to running ap mode. – dazz Sep 28 '18 at 08:14
  • You have to set the **two** underscores. Otherwise it will never work. Please google with `interface add ap0 type __ap`. And it works on my RasPis. What RasPi do you use? Is it a *RPi 3B+*? Do you start from scratch with `Raspbian Stretch Lite 2018-06-27` like me? The error message you give me is from systemd telling us *ExecStartPre* has failed. But there must be an error message from **iw** why it has failed. With `journalctl -b -e` you should find the output from **iw** (message prefixed with iw). – Ingo Sep 28 '18 at 09:00
  • OK I set the underscores. It is running on a RasPi 3 but I do have 3Bs and 3B+, all running Stretch Lite. The logs state a "usage" problem which indicates a typo. I have checked all the config files and they match the instructions. wlan0 is working OK. – dazz Sep 28 '18 at 10:59
  • running sudo iw dev ap0 info gives: command failed: no such device (-19). – dazz Sep 28 '18 at 11:00
  • A typo? That must be corrected of course. 3B or 3B+ doesn't matter. **wlan0** as client is mostly stable. "*no such device*" is right when addressing absent **ap0**. Just use `sudo iw dev`. I have updated my answer with a section *Troubleshooting*. Tell me if you get it to run or not. – Ingo Sep 28 '18 at 14:12
  • I went through all the config and I haven't found any typos. Today I will build a fresh version of Raspian and try to get this working, then compare to what I have on my current build. What I really want to do is have simultaneous and managed mode running at the same time. I found this article here: https://blog.thewalr.us/2017/09/26/raspberry-pi-zero-w-simultaneous-ap-and-managed-mode-wifi/ That would avoid any need to switch between the modes. I have no idea how/if that might be done with systemd-networkd. That would be the basis of another question. – dazz Sep 28 '18 at 19:30
  • @dazz Ah.. you want to run an access point together with client connection at the same time. No problem. You can find it at [Raspberry Pi Zero W as a WiFi repeater](https://raspberrypi.stackexchange.com/a/87506/79866). If something is unclear you can comment there. – Ingo Sep 28 '18 at 20:38
  • Running client and ap at the same time is what I really need/want but I didn't think it would be possible until I stumbled onto a solution. Thanks for your help. :-) – dazz Sep 29 '18 at 04:55
  • @dazz But there IS a solution, do you follow the link above? – Ingo Sep 29 '18 at 06:57
  • Yes, I am working through it now, on a fresh Raspian build. By following those instructions, I have installed hostapd. I didn't do that following the above instructions and the ones before that. I suspect that was my problem. – dazz Sep 29 '18 at 09:24
  • I have a question on the link above. This should be in the comments at the link but I can't put a comment there without 50 credits. I don't seem to be able to chat to you. The sentence beginning "We do not need this because..." is not clear to me. If something is not needed, can it be removed from your answer? – dazz Sep 29 '18 at 09:31
  • @dazz I have clarified that part in the answer. `hostapd` is needed if you want to run access point AND wifi client connection together. `wpa_supplicant` has problems with wifi driver doing both at the same time. This is on switching the connection as shown here not the case. But we get problems with the comments here. It's to much. Because of your restriction I would open a new question with reference to [Raspberry Pi Zero W as a WiFi repeater](https://raspberrypi.stackexchange.com/a/87506/79866) if there are some more questions. Then you are free to comment to your own question like here. – Ingo Sep 29 '18 at 10:54
  • I finished the setup to get ap and client wifi running together. On bootup, wlan0 works perfectly. Journalctl didn't report any attempt to run ap0. The status command reported ap0 loaded but not active. I then ran "systemctl start wpa_supplicant@ap0.service. Journal reported "systemd[1]: sys-subsystem-net-devices-ap0.device: Job sys-subsystem-net-devices-ap0.device/start timed out" – dazz Sep 29 '18 at 10:56
  • @dazz Make a new question with this. – Ingo Sep 29 '18 at 10:58
  • https://raspberrypi.stackexchange.com/questions/89484/trying-to-setup-wifi-ap-and-managed-client-mode-together-sub-system-time-out-o – dazz Sep 29 '18 at 11:09