3

$ uname -a Linux pi 4.9.59+ #1047 Sun Oct 29 11:47:10 GMT 2017 armv6l GNU/Linux

System fully updated via apt.

I'm aware there are many, many questions and blogs on this topic, but after several days of looking and asking friends I can't find an answer.

My Raspberry Pi Zero W has two wireless interfaces: wlan0 and wlan1.

I want wlan0 to be an AP and wlan1 to connect to an AP.

So I need wlan0 to have a static IP and wlan1 to get one from DHCP over wireless.

If I set a static IP for wlan0 in dhcpcd.conf, dhcpcd still calls wpa_supplicant and so even with a static IP it joins the AP - which causes conflicts when trying to run hostapd.

If I set a static IP for wlan0 via interfaces, dhcpcd fails because it detected the interface being configured in interfaces - eventhough I'd added denyinterface wlan0 to the dhcpcd.conf.

I know that wpa_supplicant has a command-line parameter for interface, but I haven't been able to find a way of limiting which interfaces get passed from the dhcpcd hook.

The question is: what configuration should I use in dhcpcd.conf (or elsewhere?) so I can get a static IP address on wlan0 and not have it connect to an AP AND get an IP address via DHCP on wlan1 and have it connect to an AP? phew

UPDATE 1:

I've tried using systemctl start dhcpcd@wlan0.service to have a per-interface config, but there is no dhcpcd@.service file, only dhcpcd.service.

UPDATE 2:

I've added a system unit file (if that's the right word?) for dhcpcd@.service:

[Unit]
Description=dhcpcd on %I
Wants=network.target
Before=network.target

[Service]
Type=forking
PIDFile=/var/run/dhcpcd-%I.pid
ExecStart=/sbin/dhcpcd --config /etc/dhcpcd-%I.conf -A -q -w %I
ExecStop=/sbin/dhcpcd -k %I

[Install]
Alias=multi-user.target.wants/dhcpcd@eth0.service

(Modified from: https://github.com/devkral/systemd-arch-units/blob/master/service/dhcpcd@.service)

This means I can successfully apply an interface-specific config into which I put a static IP address configuration and nohook wpa_supplicant.

This correctly doesn't call wpa_supplicant, but doesn't seem to set the IP address either. No errors on run and I can see it's loading the correct conf file, but ip addr shows no IP address on the interface.

Bridgey
  • 183
  • 1
  • 2
  • 7
  • 2
    Does this answer your question? [How do I set up networking/WiFi/static IP address on Raspbian/Raspberry Pi OS?](https://raspberrypi.stackexchange.com/questions/37920/how-do-i-set-up-networking-wifi-static-ip-address-on-raspbian-raspberry-pi-os) – Milliways Feb 07 '21 at 23:02

3 Answers3

5

I solved this by using the interface-specific unit (/lib/systemd/system/dhcpcd@.service), with an interface-specific dhcpcd.conf.

For wlan0, static IP address and no wpa_supplicant:

/etc/dhcpcd-wlan0.conf

interface wlan0
static ip_address==192.168.100.1/24

denyinterfaces wlan0    # don't send DHCP requests
nohook wpa_supplicant   # don't call the wpa_supplicant hook

For wlan1, no changes to the default /etc/dhcpcd.conf, but had to create an interface-specific version:

cp /etc/dhcpcd.conf /etc/dhcpcd-wlan1.conf

Then, start dhcpcd for each interface:

systemctl start dhcpcd@wlan0
systemctl start dhcpcd@wlan1

UPDATE

Although this is an answer, @Nasha above was correct: you can specify a different wpa_supplicant.conf file per interface. Leaving this (wrong) answer here as it may prove useful.

Bridgey
  • 183
  • 1
  • 2
  • 7
  • 1
    I think this is a better way to do it for the host AP / client AP case, as for this case we want to disable wpa_supplicant completely for the host AP. Thanks for leaving the answer up! :) – Donald Harvey Mar 15 '18 at 12:42
3

You don't need a unit for that. Use /etc/dhcpcd.conf. From the man pages:

denyinterfaces pattern

When discovering interfaces, the interface name must not match pattern which is a space or comma separated list of patterns passed to fnmatch(3).

So just add denyinterfaces wlan1 to dhcpcd.conf and dhcpcd will ignore that interface when sending DHCP requests.

  • Thanks for the comment. In this case, can I still configure the static IP address in `dhcpcd.conf` or would I need to do it somewhere else, like `interfaces`? – Bridgey Nov 01 '17 at 18:03
  • Although this prevents DHCP requests being sent for the denied interface, it is still included in the interfaces when hooks are executed. Therefore, `wpa_supplicant` is still called for the denied interface. I'm trying to avoid `wpa_supplicant` being called for the denied interface. – Bridgey Nov 01 '17 at 18:17
  • You don't have to prevent `wpa_supplicant` from being called for the denied interface as the former is also responsible for putting the wireless adapter in access point mode instead of just client mode. Just find a way to provide it with 2 different configs... although I'm almost certain it's possible to configure multiple adapters in different modes from the same one and only `wpa_supplicant.conf`. Someone can confirm? –  Nov 02 '17 at 10:25
  • you're right about the `wpa_supplicant.conf` per interface! `10-wpa_supplicant` hook shows the list of files, in order, that are checked. `wpa_supplicant-"$interface".conf` is at the top of the list. If you update the answer I can mark it as the correct one? – Bridgey Nov 08 '17 at 21:26
  • @Bridgey I don't have my Pi accessible for the moment (all my available machines are Gentoo), I'll check that as soon as I can. –  Nov 15 '17 at 13:27
1

Option 1 - Using nohook wpa_supplicant

The /etc/dhcpcd.conf configuration file of dhcpcd can be edited to define which wireless interfaces need wpa_supplicant.

For each identified interface, dhcpcd executes all scripts (hooks) found in /lib/dhcpcd/dhcpcd-hooks in lexical order. One of the scripts is 10-wpa_supplicant, which starts wpa_supplicant. It can be edited, e.g., to customize wpa_supplicant command-line parameters.

In order to disable the wpa_supplicant hook for an interface, use nohook wpa_supplicant for that interface.

Example:

interface wlan1 # these two lines are not strictly needed, as wlan0 uses the default configuration
    dhcp

interface wlan0 # this defines static addressing and netmask to wlan0, uses only IP V4 addressing and disables wpa_supplicant for this interface
    static ip_address=192.168.50.1/24
    ipv4only
    nohook wpa_supplicant

In the above example, the wlan1 interface will start by default all its hooks, including the wpa_supplicant hook, which runs wpa_supplicant with the following command-line arguments:

wpa_supplicant -B -c/etc/wpa_supplicant/wpa_supplicant.conf -iwlan1 -Dnl80211,wext

Also, a DHCP client is configured for this interface (that is the default configuration; in other terms, the wlan1 entry is redundant).

In the same example, the wlan0 interface (e.g, the one to be used as AP), defines a static IP address and network mask: Also, it disables the wpa_supplicant hook, so that wpa_supplicant is not activated for this interface.

Option 2 - Using denyinterfaces

The denyinterfaces directive of /etc/dhcpcd.conf disables processing specific interfaces. In this case, specific configurations, like setting a static IP address of an interface, should be done by different services (like systemd-networkd via configuration files in /etc/systemd/network/ directory).

Example:

denyinterfaces wlan0 # wlan0 will not be managed with default settings (e.g., running wpa_supplicant hook). Besides, all subsequent configurations related to wlan0 will be ignored.

Option 3 - Disabling or uninstalling dhcpcd5

dhcpcd can be disabled using the following command:

systemctl disable dhcpcd

Or it can also be uninstalled:

sudo apt-get --autoremove purge dhcpcd5

After disabling or uninstalling the dhcpcd service, wpa_supplicant can be either activated by configuring the old /etc/network/interfaces, or via specific service.

Example with /etc/network/interfaces:

allow-hotplug wlan1
iface wlan1 inet manual
  wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

Example to run wpa_supplicant with a specific service on a specific interface (wlan1 in this case):

SYSTEMD_EDITOR=tee systemctl edit --force --full wpa_supplicant@.service <<\EOF
[Unit]
Description= WPA supplicant on wlan%i interface
Before=network.target
After=dbus.service
Wants=network.target

[Service]
Type=dbus
BusName=fi.w1.wpa_supplicant1
ExecStart=/sbin/wpa_supplicant -s -iwlan%i -c/etc/wpa_supplicant/ /wpa_supplicant_wlan%i.conf -Dnl80211,wext

[Install]
WantedBy=multi-user.target
Alias=dbus-fi.w1.wpa_supplicant1.service
EOF

systemctl enable wpa_supplicant@1.service
systemctl start wpa_supplicant@1.service
rfkill unblock wlan

The following command will be launched:

/sbin/wpa_supplicant -s -iwlan1 -c/etc/wpa_supplicant/wpa_supplicant_wlan1.conf -Dnl80211,wext
ircama
  • 128
  • 1
  • 6