dhcpcd icon indicating copy to clipboard operation
dhcpcd copied to clipboard

Add support for /etc/dhcpcd/hooks/

Open perkelix opened this issue 9 months ago • 15 comments

In its current form, dhcpcd ships its configured hooks in --libexecdir and its extra sample hooks in /usr/share/dhcpcd/hooks/.

It would be desirable for dhcpcd to also source e.g. /etc/dhcpcd/hooks/ for administrator-added scripts.

At the same time, it would be desirable for BUILDING.md or README.md to document the existence of EGHOOKSCRIPTS and explain the difference with HOOKSCRIPTS.

perkelix avatar Mar 26 '25 09:03 perkelix

Administrator added scripts are /etc/dhcpcd.enter-hook and /etc/dhcpcd.exit-hook. If the admin wants to source a directory inside these scripts they are more than welcome to.

rsmarples avatar Apr 15 '25 11:04 rsmarples

At the same time, it would be desirable for BUILDING.md or README.md to document the existence of EGHOOKSCRIPTS and explain the difference with HOOKSCRIPTS.

BUILDING.md already has this:

Not all the hooks in dhcpcd-hooks are installed by default. By default we install 01-test, 20-resolv.confand 30-hostname. The other hooks, 10-wpa_supplicant, 15-timezone and 29-lookup-hostname are installed to $(datadir)/dhcpcd/hooks by default and need to be copied to $(libexecdir)/dhcpcd-hooks for use.

I think it's already explained there?

rsmarples avatar Apr 15 '25 11:04 rsmarples

That still doesn't tell us which one is which or what configure keys to use for either case.

perkelix avatar Apr 16 '25 07:04 perkelix

datadir defaults to /usr/share and libexecdir defaults to /libexec. I used the gnu configure variables here to make life easy I thought?

rsmarples avatar Apr 16 '25 08:04 rsmarples

The variables' name remains opaque. It leaves downstream guessing.

--with-hooks="timesyncd.conf"

...apparently results in:

HOOKSCRIPTS = 50-timesyncd.conf

I emphasize apparently because it I wouldn't have known without experimenting with the configure options, which is how –among other thigns– I found out that --with-hooks expects filenames without the numeric prefix.

What option would populate the EGHOOKSCRIPTS line and what it's used for remains opaque.

"We install this here and that there" doesn't tell us much. i.e. BUILDING.md needs to show an example for both cases:

Not all the hooks in dhcpcd-hooks are installed by default. By default, we install 01-test, 20-resolv.confand 30-hostname into $(libexecdir)/dhcpcd-hooks for use. The other hooks, 10-wpa_supplicant, 15-timezone and 29-lookup-hostname are installed as examples into $(datadir)/dhcpcd/hooks by default. The configure program attempts to find hooks for daemons you have installed. These will appear on the HOOKSCRIPTS line in configure's output, along with any hook added using the --with-hooks option without the numeric prefix e.g. ./configure -with-hook=ntp.conf

This leaves EGHOOKSCRIPTS undocumented.

perkelix avatar Apr 16 '25 09:04 perkelix

Looking into the source code for dhcpcd-run-hooks, I notice:

for hook in \
    @SYSCONFDIR@/dhcpcd.enter-hook \
    @HOOKDIR@/* \
    @SYSCONFDIR@/dhcpcd.exit-hook
do

Could this possibly be converted to:

for hook in \
    @SYSCONFDIR@/dhcpcd/enter-hooks.d/* \
    @HOOKDIR@/* \
    @SYSCONFDIR@/dhcpcd/exit-hooks.d/*
do

...for upcoming releases, @rsmarples? This would probably accomplish what was requested at Debian.

perkelix avatar Apr 19 '25 11:04 perkelix

Sorry for not doing anything on this for a while. If we're going to have an /etc/dhcpcd to avoid putting many things directly into /etc then we should move the config layout as well. Maybe something like this?

/etc/dhcpcd
    ./dhcpcd.conf
    ./enter-hook
    ./enter-hooks.d/
    ./exit-hooks.d/
    ./exit-hook

/etc/dhcpcd could then be a symlink to /var/chroot/dhcpcd/etc/dhcpcd if we ever need dhcpcd.conf inside the chroot

rsmarples avatar Jun 02 '25 09:06 rsmarples

@perkelix does that fix it for you?

rsmarples avatar Jun 16 '25 12:06 rsmarples

Let's ask @DanielG since he's the one who initially requested this.

perkelix avatar Jun 16 '25 12:06 perkelix

Hi Roy, Martin!

Thanks for taking the time to implement this Roy :-).

Unfortunately I don't think c75b0b7 quite captures the use-cases I have in mind yet. If I'm not mistaken there's a bug in there also: shell wildcards don't give sorted output so the evaluation order would be unpredictable!

Wildcard Woes

Apart from that plain shell wildcards are generally a bad idea in config directories admins may touch because of editor backups.

Traditionally Debian uses run-parts (manpage) for an implementation that avoids this pitfall and more (.dpkg* files that may happen if other packages ship config files in the .d dirs).

Looking at the code I believe the default regex used there is ^[a-zA-Z0-9_-]+$ but it's a bit hard to interpret. Note how that excludes everything with a period (.dpkg* etc) and anything with a tilde~ typical for backup files.

Preferring Precedence

Further, I was more thinking along the lines of Chris' design https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1101003#27

  1. packaged software probably wants to avoid dropping new scripts as conffiles into /etc; so it would make sense to provide an extension point in /usr that the admin can override in /etc

This leans on how people are used to things working on Linux these days as systemd uses a similar convention all over the place. IIRC there's even a "standard" for it somewhere around the freedesktop sphere but I can't find it now ofc.

Basically: A script at /etc/dhcpcd/hooks/42-example would be preferred over a script at /usr/share/dhcpcd/hooks/42-example.

The are two main reasons for doing it this way:

  • It's easier to tell what's happening by looking at the filesystem and applying a system wide convention than having to read the dhcpcd specific enter/extit scripts and figure out how the skip_hooks= logic works.

  • Some people are working towards image based systems that only have files in /usr "Hermetic /usr". They will appreciate this feature. I have a similar use-case but the technical details are less easily explained :-).

Thanks, --Daniel

DanielG avatar Jun 17 '25 12:06 DanielG

Hi Roy, Martin!

Thanks for taking the time to implement this Roy :-).

Welcome

Unfortunately I don't think c75b0b7 quite captures the use-cases I have in mind yet. If I'm not mistaken there's a bug in there also: shell wildcards don't give sorted output so the evaluation order would be unpredictable!

Wildcard Woes

Apart from that plain shell wildcards are generally a bad idea in config directories admins may touch because of editor backups.

Traditionally Debian uses run-parts (manpage) for an implementation that avoids this pitfall and more (.dpkg* files that may happen if other packages ship config files in the .d dirs).

Looking at the code I believe the default regex used there is ^[a-zA-Z0-9_-]+$ but it's a bit hard to interpret. Note how that excludes everything with a period (.dpkg* etc) and anything with a tilde~ typical for backup files.

POSIX has this to say about pathname expansion: https://pubs.opengroup.org/onlinepubs/000095399/utilities/xcu_chap02.html#tag_02_13

If a filename begins with a period ( '.' ), the period shall be explicitly matched by using a period as the first character of the pattern or immediately following a slash character.

So . files are ignored.

If the pattern matches any existing filenames or pathnames, the pattern shall be replaced with those filenames and pathnames, sorted according to the collating sequence in effect in the current locale.

So they are also sorted.

dhcpcd-run-hooks also exlcudes anything ending with a ~ So this covers your concerns yes?

Preferring Precedence

Further, I was more thinking along the lines of Chris' design https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1101003#27

  1. packaged software probably wants to avoid dropping new scripts as conffiles into /etc; so it would make sense to provide an extension point in /usr that the admin can override in /etc

This leans on how people are used to things working on Linux these days as systemd uses a similar convention all over the place. IIRC there's even a "standard" for it somewhere around the freedesktop sphere but I can't find it now ofc.

Basically: A script at /etc/dhcpcd/hooks/42-example would be preferred over a script at /usr/share/dhcpcd/hooks/42-example.

The are two main reasons for doing it this way:

* It's easier to tell what's happening by looking at the filesystem and applying a system wide convention than having to read the dhcpcd specific enter/extit scripts and figure out how the `skip_hooks=` logic works.

* Some people  are working towards image based systems that only have files in /usr "Hermetic /usr". They will appreciate this feature. I have a similar use-case but the technical details are less easily explained :-).

packages can drop their stuff into /libexec/dhcpcd-hooks or where-ever Debian installed the hooks and example hooks to. /etc/dhcpcd is solely for the administrator, not packages. Infact, do we even need enter/exit hook directories? Maybe just /etc/dhcpcd/hooks where the admin can symlink scripts from the examples to be included?

rsmarples avatar Jun 17 '25 18:06 rsmarples

packages can drop their stuff into /libexec/dhcpcd-hooks or where-ever Debian installed the hooks and example hooks to. /etc/dhcpcd is solely for the administrator, not packages. Infact, do we even need enter/exit hook directories? Maybe just /etc/dhcpcd/hooks where the admin can symlink scripts from the examples to be included?

For this one, I can answer:

We need separate enter/exit hook directories in $libexec so that packages can drop their own hooks at a standardized location. Meanwhile, $config is only for administrator content. Hence https://github.com/NetworkConfiguration/dhcpcd/issues/494#issuecomment-2816674450

perkelix avatar Jun 18 '25 04:06 perkelix

Why does the directory need to be separate? Because it’s a directory you don’t need enter/exit just get the two digit numerical prefix on the file name in the correct position. One directory is fine.

rsmarples avatar Jun 18 '25 06:06 rsmarples

  1. We need separate enter/exit directories because packages install separate scripts depending on what they need done when the network is brought up or down, and thus need separate directories to source these.

  2. Daniel wants this both in $libexec and $config because the former is not meant to be modified, while the later is meant to accommodate administrator scripts and configs. The (number) globbing aspect is a minor one. The key point is that whatever is in $config should override whatever is in $libexec if there's discrepancies. This is how systemd and the whole FreeDesktop codebase is designed: ship stock configs in /usr, let the administrator override them in whole or in part (or add custom extras) via /etc.

perkelix avatar Jun 18 '25 06:06 perkelix

  1. We need separate enter/exit directories because packages install separate scripts depending on what they need done when the network is brought up or down, and thus need separate directories to source these.

No. enter is run first, then hooks exit is last. Doesn't matter what the reason is, that is passed to the script which needs to work out why it's called from the environment variables set by dhcpcd.

As we talk this though, I really think I can roll back a lot of this change here. See below

  1. Daniel wants this both in $libexec and $config because the former is not meant to be modified, while the later is meant to accommodate administrator scripts and configs. The (number) globbing aspect is a minor one. The key point is that whatever is in $config should override whatever is in $libexec if there's discrepancies. This is how systemd and the whole FreeDesktop codebase is designed: ship stock configs in /usr, let the administrator override them in whole or in part (or add custom extras) via /etc.

$libexec/dhcpcd/hooks # packages including dhcpcd install here, run by default $datadir/dhcpcd/hooks # packages including dhcpcd install here, not run by default $etc/dhcpcd/hooks # administrator can symlink from $datadir/dhcpcd/hooks here or create own, run by default

Any hook can be disabled via nohook in dhcpcd.conf

The number aspect is important as that decides the order in which things are run.

Having a hook from $etc override system hook of the same name is an interesting idea. Gathering and sorting in shell will be a challenge as sort(1) lives in /usr which is network mounted in some systems and the hook script need to cope with that. Yes I'm aware that this doesn't matter to Debian, but it matters to others and that might be a show stopper for that right away.

rsmarples avatar Jun 18 '25 09:06 rsmarples