4

$ 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
  • 223
  • 1
  • 3
  • 7

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
  • 223
  • 1
  • 3
  • 7
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.

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
  • 188
  • 1
  • 7