devd: device state change daemon

Introduction

devd(8) is a tool included in the FreeBSD base system. It provides a way of running userland tools when a specific kernel event happens. For example, if plugging a smartphone configured for USB tethering, we could have a devd(8) rule that runs dhclient(8) for that interface name.

devd.conf configuration

devd.conf(5) is the configuration file for defining devd(8) rules. There's already one in the base system: /etc/devd.conf, which can be left unmodified in most situations. Instead, let's use the /usr/local/etc/devd directory for files with the .conf extension.

If a port or package installed a file there, that directory should already exist; otherwise, create it:

# mkdir -p /usr/local/etc/devd

The configuration consists of two features: statements and comments. All statements end with a semicolon. Many statements have substatements, that also end with a semicolon.

statement priority {
    substatement "value";
    ...
    substatement "value";
};

Statements can occur in any order in the configuration file and can be repeated as often as necessary.

Each statement has a priority, except the options (see below). The priority is an arbitrary number, where zero is the lowest priority. If two or more statements match, only the statement with the greatest priority is processed.

The currently supported statements are as follows:

One way to understand the statements is to directly read /etc/devd.conf and review the above mentioned. It might also be useful to read /etc/devd.conf and verify if an installed port or package we have installed created /usr/local/etc/devd; that is a good starting point.

Sub-Statements

options

attach and detach

nomatch

The following sub-statements have the same effect that attach and detach, so they will be mentioned without a description.

match

The following sub-statements have the same effect that the above sub-statement, so they will be mentioned without a description. The exception is action and match. The first is to offer an useful example and the second is because match is something different.

Variables and the notify event

There are a lot of variables, systems, subsystems, types and notifications that can be used in statements that include a match sub-statement, but this article need not cover them because they can be found in devd.conf(5). See sections Variables that can be used with the match statement and Notify matching in devd.conf(5).

Comments

The comments are trivial to C/C++ or Shell/Perl programmers.

C-style comments start with the two characters ‘/*’ (slash, star) and end with ‘*/’ (star, slash). This style can cover one line or multiple lines but cannot be nested.

   1 /* This is the start of a comment.
   2     This is still part of the comment.
   3 /* This is an incorrect attempt at nesting a comment. */
   4     This is no longer in any comment. */

C++-style comments start with the two characters ‘//’ (slash, slash) and continue to the end of the physical line. If we need to cover more than one line, is necessary to put again this type of comments in the next line.

   1 // This is the start of a comment.  The next line
   2 // is a new comment, even though it is logically
   3 // part of the previous comment.
   4 

The above may be written using perl-style comments:

   1 # This is the start of a comment.  The next line
   2 # is a new comment, even though it is logically
   3 # part of the previous comment.

Notes on Variable Expansion

To avoid problems with shell special characters in action sub-statements, here's what happens to, say, $foo:

  1. The characters $' are inserted.

  2. The string $foo is removed.

  3. The value of the foo variable is inserted into the buffer with all single quote characters prefixed by a backslash.

See sh(1) for what this construct means. In any context, these conditions are safe, but single quotes can cause unwanted effects. Suppose foo=meta and bar=var:

action "echo '$foo $bar'";

They will be present in the shell through the system(3) function:

echo '$'meta' $'var''

Which produces the following output:

echo $meta $var

Is this the result we want? Probably not. To produce a correct result, it is necessary to rewrite the rule as follows:

action "echo $foo' '$bar"

Be careful.

devd(8) in debug mode

By default devd(8) runs as a service:

# service devd status
devd is running as pid 2310.

To understand what devd(8) does, we need to run it in the foreground instead of the background. Likewise, it is highly recommended to read /var/log/messages and the output of dmesg(8) while writing and testing rules.

# service devd stop
Stopping devd.
Waiting for PIDS: 2310.
# devd -d
Parsing /etc/devd.conf
setting scsi-controller-regex=(aac|aacraid|ahc|ahd|amr|ciss|esp|ida|iir|ips|isp|mlx|mly|mpr|mps|mpt|sym|trm)[0-9]+
setting wifi-driver-regex=(ath|bwi|bwn|ipw|iwi|iwm|iwn|malo|mwl|otus|ral|rsu|rtwn|rum|run|uath|upgt|ural|urtw|wi|wpi|wtap|zyd)[0-9]+
Parsing files in /etc/devd
Parsing /etc/devd/uath.conf
Parsing /etc/devd/hyperv.conf
Parsing /etc/devd/zfs.conf
Parsing /etc/devd/iwmbtfw.conf
Parsing /etc/devd/asus.conf
Parsing /etc/devd/devmatch.conf
Parsing /etc/devd/ulpt.conf
Parsing files in /usr/local/etc/devd
Parsing /usr/local/etc/devd/cups.conf

The output is very descriptive. We see what devd(8) parses, which we can use for troubleshooting.

As mentioned, dmesg(8) and /var/log/messages can be our best friends. This is the output of dmesg(8) when a USB key is connected:

umass0 on uhub0
umass0: <SanDisk Cruzer Blade, class 0/0, rev 2.00/1.27, addr 2> on usbus4
umass0:  SCSI over Bulk-Only; quirks = 0x8100
umass0:2:0: Attached to scbus2
da0 at umass-sim0 bus 0 scbus2 target 0 lun 0
da0: <SanDisk Cruzer Blade 1.27> Removable Direct Access SPC-4 SCSI device
da0: Serial Number 200515364102BCF2AC69
da0: 40.000MB/s transfers
da0: 7633MB (15633408 512 byte sectors)
da0: quirks=0x2<NO_6_BYTE>

We have enough information to create statements. We will create usb_attach.conf in /usr/local/etc/devd as an example.

/usr/local/etc/devd/usb_attach.conf:

attach 100 {
        device-name "umass0";
        action "logger $device-name is plugged in";
};

detach 100 {
        device-name "umass0";
        action "logger $device-name is unplugged";
};

When a device matches umass0, its name is printed using logger(1). We can see the message in /var/log/messages:

Jul 11 15:57:01 dtxdf-laptop dtxdf-fbsd[4832]: umass0 is unplugged
Jul 11 15:57:01 dtxdf-laptop kernel: ugen4.2: <SanDisk Cruzer Blade> at usbus4 (disconnected)
Jul 11 15:57:01 dtxdf-laptop kernel: umass0: at uhub0, port 2, addr 2 (disconnected)
Jul 11 15:57:01 dtxdf-laptop kernel: da0 at umass-sim0 bus 0 scbus2 target 0 lun 0
Jul 11 15:57:01 dtxdf-laptop kernel: da0: <SanDisk Cruzer Blade 1.27>  s/n 200515364102BCF2AC69 detached
Jul 11 15:57:01 dtxdf-laptop kernel: (da0:umass-sim0:0:0:0): Periph destroyed
Jul 11 15:57:01 dtxdf-laptop kernel: umass0: detached
Jul 11 15:57:07 dtxdf-laptop dtxdf-fbsd[4836]: umass0 is plugged in
Jul 11 15:57:07 dtxdf-laptop kernel: ugen4.2: <SanDisk Cruzer Blade> at usbus4
Jul 11 15:57:07 dtxdf-laptop kernel: umass0 on uhub0
Jul 11 15:57:07 dtxdf-laptop kernel: umass0: <SanDisk Cruzer Blade, class 0/0, rev 2.00/1.27, addr 2> on usbus4
Jul 11 15:57:07 dtxdf-laptop kernel: umass0:  SCSI over Bulk-Only; quirks = 0x8100
Jul 11 15:57:07 dtxdf-laptop kernel: umass0:2:0: Attached to scbus2
Jul 11 15:57:08 dtxdf-laptop kernel: da0 at umass-sim0 bus 0 scbus2 target 0 lun 0
Jul 11 15:57:08 dtxdf-laptop kernel: da0: <SanDisk Cruzer Blade 1.27> Removable Direct Access SPC-4 SCSI device
Jul 11 15:57:08 dtxdf-laptop kernel: da0: Serial Number 200515364102BCF2AC69
Jul 11 15:57:08 dtxdf-laptop kernel: da0: 40.000MB/s transfers
Jul 11 15:57:08 dtxdf-laptop kernel: da0: 7633MB (15633408 512 byte sectors)
Jul 11 15:57:08 dtxdf-laptop kernel: da0: quirks=0x2<NO_6_BYTE>

This example can be extended, for example, to mount a partition when a device is plugged in. To avoid problems with device names /dev/da[0-9], it is strongly recommended to partition and label them. To simplify this task, we can use diskinfo(8) to get the serial number of our device to use as a unique label in our inventory.

$ diskinfo -s da0
200515364102BCF2AC69

The serial number is very large, but the final characters can be used. To finish the label, we could concatenate a logical abbreviation of the purpose of the partition and the final five characters. The end result is:

rt2AC69

We are ready to partition:

# gpart create -s gpt da0
da0 created
# gpart add -t freebsd-ufs -l rt2AC69 da0
da0p1 added
# newfs -j /dev/gpt/rt2AC69
/dev/gpt/rt2AC69: 7633.5MB (15633328 sectors) block size 32768, fragment size 4096
        using 13 cylinder groups of 625.22MB, 20007 blks, 80128 inodes.
        with soft updates
super-block backups (for fsck_ffs -b #) at:
 192, 1280640, 2561088, 3841536, 5121984, 6402432, 7682880, 8963328, 10243776, 11524224, 12804672, 14085120, 15365568
Using inode 4 in cg 0 for 33554432 byte journal
newfs: soft updates journaling set
# mount /dev/gpt/rt2AC69 /mnt
# echo "Hello!" > /mnt/hello.txt
# cat /mnt/hello.txt
Hello!
# umount /mnt

Here the da0 device with GPT is used and a single partition is added. That partition is formatted and mounted on /mnt to write a file called hello.txt. Last, the partition is unmounted.

Unplug the device and plug it back in. The label is also useful for debugging, as it will be printed in the devd(8) output.

Processing event '!system=GEOM subsystem=DEV type=CREATE cdev=gpt/rt2AC69'
Pushing table
setting *=!system=GEOM subsystem=DEV type=CREATE cdev=gpt/rt2AC69
setting _=system=GEOM subsystem=DEV type=CREATE cdev=gpt/rt2AC69
setting timestamp=1657571585.404812
setting system=GEOM
setting subsystem=DEV
setting type=CREATE
setting cdev=gpt/rt2AC69
Processing notify event
Testing system=GEOM against ^DEVFS$, invert=0
Testing system=GEOM against ^DEVFS$, invert=0
Testing system=GEOM against ^DEVFS$, invert=0
Testing system=GEOM against ^DEVFS$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^ETHERNET$, invert=0
Testing system=GEOM against ^DEVFS$, invert=0
Testing system=GEOM against ^DEVFS$, invert=0
Testing system=GEOM against ^ACPI$, invert=0
Testing system=GEOM against ^ACPI$, invert=0
Testing system=GEOM against ^ACPI$, invert=0
Testing system=GEOM against ^ACPI$, invert=0
Testing system=GEOM against ^DEVFS$, invert=0
Testing system=GEOM against ^DEVFS$, invert=0
Testing system=GEOM against ^HYPERV_NIC_VF$, invert=0
Testing system=GEOM against ^ETHERNET$, invert=0
Testing system=GEOM against ^ZFS$, invert=0
Testing system=GEOM against ^ZFS$, invert=0
Testing system=GEOM against ^ZFS$, invert=0
Testing system=GEOM against ^ZFS$, invert=0
Testing system=GEOM against ^ZFS$, invert=0
Testing system=GEOM against ^ZFS$, invert=0
Testing system=GEOM against ^ZFS$, invert=0
Testing system=GEOM against ^ZFS$, invert=0
Testing system=GEOM against ^ZFS$, invert=0
Testing system=GEOM against ^ZFS$, invert=0
Testing system=GEOM against ^ZFS$, invert=0
Testing system=GEOM against ^ZFS$, invert=0
Testing system=GEOM against ^IFNET$, invert=0
Testing system=GEOM against ^IFNET$, invert=0
Testing system=GEOM against ^IFNET$, invert=0
Testing system=GEOM against ^ACPI$, invert=0
Testing system=GEOM against ^ACPI$, invert=0
Testing system=GEOM against ^ACPI$, invert=0
Testing system=GEOM against ^ACPI$, invert=0
Testing system=GEOM against ^ACPI$, invert=0
Testing system=GEOM against ^ACPI$, invert=0
Popping table

When we plug in our USB key, devd(8) output is very large, so using a tool like screen(1) or tmux(1) is highly recommended, as both of them have a feature called Copy Mode that is useful for searching the output buffer. However, traditional tools like script(1) with a pager like less(1) or more(1) can be used for this purpose.

The idea is to search devd(8) output to get the exact point of the event we need. When we've done that, we need to check whether the parameters that devd(8) is using are the required ones. In this example, the following parameters are relevant:

setting system=GEOM
setting subsystem=DEV
setting type=CREATE
setting cdev=gpt/rt2AC69

See "Variables and the notify event" for more details on those parameters.

We need to modify usb_attach.conf with the parameters described above:

notify 100 {
        match "system" "GEOM";
        match "subsystem" "DEV";
        match "type" "CREATE";
        match "cdev" "gpt/rt2AC69";
        action "sleep 2 && /usr/local/bin/scripts/automount.sh $cdev";
};

notify 100 {
        match "system" "GEOM";
        match "subsystem" "DEV";
        match "type" "DESTROY";
        match "cdev" "gpt/rt2AC69";
        action "sleep 2 && /usr/local/bin/scripts/autoumount.sh $cdev";
};

In many cases we need to do something and, in turn, its counterpart. In this case, we need two scripts: the first is to create a directory and mount its partition, and the second is to delete the directory and forcibly unmount it. Forcibly unmounting the file system seems a bad idea, but since the device was unplugged without unmounting its partition, it's necessary.

automount.sh:

set -e

: ${RTDIR:=/mnt}

dev=$1
if [ -z "${dev}" ]; then
    echo "usage: automount.sh device" >&2
    exit 1
fi

_dev=`basename "${dev}"`
mntdir="${RTDIR}/${_dev}"

fsck -p "/dev/${dev}"
mkdir -p "${mntdir}"
mount "/dev/${dev}" "${mntdir}"

autoumount.sh:

: ${RTDIR:=/mnt}

dev=$1
if [ -z "${dev}" ]; then
    echo "usage: autoumount.sh device" >&2
    exit 1
fi

_dev=`basename "${dev}"`
mntdir="${RTDIR}/${_dev}"

umount -f "${mntdir}" 2> /dev/null
rmdir "${mntdir}"

When the device is plugged in, devd(8) automatically mounts its partition.

Processing event '!system=GEOM subsystem=DEV type=CREATE cdev=gpt/rt2AC69'
Pushing table
setting *=!system=GEOM subsystem=DEV type=CREATE cdev=gpt/rt2AC69
setting _=system=GEOM subsystem=DEV type=CREATE cdev=gpt/rt2AC69
setting timestamp=1657575727.806329
setting system=GEOM
setting subsystem=DEV
setting type=CREATE
setting cdev=gpt/rt2AC69
Processing notify event
Testing system=GEOM against ^DEVFS$, invert=0
Testing system=GEOM against ^DEVFS$, invert=0
Testing system=GEOM against ^DEVFS$, invert=0
Testing system=GEOM against ^DEVFS$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^USB$, invert=0
Testing system=GEOM against ^GEOM$, invert=0
Testing subsystem=DEV against ^DEV$, invert=0
Testing type=CREATE against ^CREATE$, invert=0
Testing cdev=gpt/rt2AC69 against ^gpt/rt2AC69$, invert=0
Executing 'sleep 2 && /usr/local/bin/scripts/automount.sh $'gpt/rt2AC69''
/dev/gpt/rt2AC69: FILE SYSTEM CLEAN; SKIPPING CHECKS
/dev/gpt/rt2AC69: clean, 1880626 free (26 frags, 235075 blocks, 0.0% fragmentation)
Popping table

cat /mnt/rt2AC69/hello.txt
Hello!

There is no need to reinvent the wheel

There is an implementation in the FreeBSD base system that is better than our automounter, called automountd(8), but for teaching purposes it was a perfect way to understand devd(8).

However, No need to reinvent the wheel can be applied to the new rules for devd(8). Some rules that we can find in /etc/devd can be changed a bit to suit our needs.

An example is when using USB tethering from an Android device which creates an urndis(8) interface, which in turn can be configured using dhclient(8).

If we connect our Android device to our machine, we will see useful information:

Pushing table
setting *=!system=IFNET subsystem=ue0 type=ATTACH
setting _=system=IFNET subsystem=ue0 type=ATTACH
setting timestamp=1657576470.672852
setting system=IFNET
setting subsystem=ue0
setting type=ATTACH
Processing notify event
Testing system=IFNET against ^DEVFS$, invert=0
Testing system=IFNET against ^DEVFS$, invert=0
Testing system=IFNET against ^DEVFS$, invert=0
Testing system=IFNET against ^DEVFS$, invert=0
Testing system=IFNET against ^USB$, invert=0
Testing system=IFNET against ^USB$, invert=0
Testing system=IFNET against ^USB$, invert=0
Testing system=IFNET against ^USB$, invert=0
Testing system=IFNET against ^USB$, invert=0
Testing system=IFNET against ^USB$, invert=0
Testing system=IFNET against ^USB$, invert=0
Testing system=IFNET against ^USB$, invert=0
Testing system=IFNET against ^USB$, invert=0
Testing system=IFNET against ^USB$, invert=0
Testing system=IFNET against ^USB$, invert=0
Testing system=IFNET against ^USB$, invert=0
Testing system=IFNET against ^USB$, invert=0
Testing system=IFNET against ^USB$, invert=0
Testing system=IFNET against ^USB$, invert=0
Testing system=IFNET against ^USB$, invert=0
Testing system=IFNET against ^GEOM$, invert=0
Testing system=IFNET against ^GEOM$, invert=0
Testing system=IFNET against ^DEVFS$, invert=0
Testing system=IFNET against ^DEVFS$, invert=0
Testing system=IFNET against ^ACPI$, invert=0
Testing system=IFNET against ^ACPI$, invert=0
Testing system=IFNET against ^ACPI$, invert=0
Testing system=IFNET against ^ACPI$, invert=0
Testing system=IFNET against ^DEVFS$, invert=0
Testing system=IFNET against ^DEVFS$, invert=0
Testing system=IFNET against ^HYPERV_NIC_VF$, invert=0
Testing system=IFNET against ^ETHERNET$, invert=0
Testing system=IFNET against ^ZFS$, invert=0
Testing system=IFNET against ^ZFS$, invert=0
Testing system=IFNET against ^ZFS$, invert=0
Testing system=IFNET against ^ZFS$, invert=0
Testing system=IFNET against ^ZFS$, invert=0
Testing system=IFNET against ^ZFS$, invert=0
Testing system=IFNET against ^ZFS$, invert=0
Testing system=IFNET against ^ZFS$, invert=0
Testing system=IFNET against ^ZFS$, invert=0
Testing system=IFNET against ^ZFS$, invert=0
Testing system=IFNET against ^ZFS$, invert=0
Testing system=IFNET against ^ZFS$, invert=0
Testing system=IFNET against ^IFNET$, invert=0
Testing subsystem=ue0 against ^(usbus|wlan)[0-9]+$, invert=1
Testing type=ATTACH against ^ATTACH$, invert=0
Executing '/etc/pccard_ether $'ue0' start'
Starting Network: ue0.
ue0: flags=8802<BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 1500
        ether 00:00:00:00:00:00
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
Popping table
Processing event '!system=ETHERNET subsystem=ue0 type=IFATTACH'
Pushing table
setting *=!system=ETHERNET subsystem=ue0 type=IFATTACH
setting _=system=ETHERNET subsystem=ue0 type=IFATTACH
setting timestamp=1657576471.170142
setting system=ETHERNET
setting subsystem=ue0
setting type=IFATTACH
Processing notify event
Testing system=ETHERNET against ^DEVFS$, invert=0
Testing system=ETHERNET against ^DEVFS$, invert=0
Testing system=ETHERNET against ^DEVFS$, invert=0
Testing system=ETHERNET against ^DEVFS$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^GEOM$, invert=0
Testing system=ETHERNET against ^GEOM$, invert=0
Testing system=ETHERNET against ^DEVFS$, invert=0
Testing system=ETHERNET against ^DEVFS$, invert=0
Testing system=ETHERNET against ^ACPI$, invert=0
Testing system=ETHERNET against ^ACPI$, invert=0
Testing system=ETHERNET against ^ACPI$, invert=0
Testing system=ETHERNET against ^ACPI$, invert=0
Testing system=ETHERNET against ^DEVFS$, invert=0
Testing system=ETHERNET against ^DEVFS$, invert=0
Testing system=ETHERNET against ^HYPERV_NIC_VF$, invert=0
Testing system=ETHERNET against ^ETHERNET$, invert=0
Testing type=IFATTACH against ^IFATTACH$, invert=0
Executing '/usr/libexec/hyperv/hyperv_vfattach $'ue0' 0'
Popping table

There is a rule that matches and runs the /usr/libexec/hyperv/hyper_vfattach tool. If we want to know what file is using that tool, we can use grep(1):

$ egrep -r '/usr/libexec/hyperv/hyperv_vfattach' /etc/devd
/etc/devd/hyperv.conf:  action "/usr/libexec/hyperv/hyperv_vfattach $subsystem 0";

We must remember that /etc/devd is not the only directory used for devd(8), so it is important to search all directories used by the options statement.

/etc/devd/hyperv.conf:

notify 10 {
        match "system"          "ETHERNET";
        match "type"            "IFATTACH";
        action "/usr/libexec/hyperv/hyperv_vfattach $subsystem 0";
};

Now it's trivial to add a new rule:

/usr/local/etc/devd/usb_tethering.conf:

notify 20 {
        match "system"          "ETHERNET";
        match "type"            "IFATTACH";
        match "subsystem"       "ue[0-9]+";
        action "/sbin/dhclient $subsystem";
};

We must increase the priority and add the subsystem for urndis(4). We also set dhclient(8) to action and when our device is plugged in, we should have an Internet connection automatically.

Processing event '!system=ETHERNET subsystem=ue0 type=IFATTACH'
Pushing table
setting *=!system=ETHERNET subsystem=ue0 type=IFATTACH
setting _=system=ETHERNET subsystem=ue0 type=IFATTACH
setting timestamp=1657577216.269419
setting system=ETHERNET
setting subsystem=ue0
setting type=IFATTACH
Processing notify event
Testing system=ETHERNET against ^DEVFS$, invert=0
Testing system=ETHERNET against ^DEVFS$, invert=0
Testing system=ETHERNET against ^DEVFS$, invert=0
Testing system=ETHERNET against ^DEVFS$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^USB$, invert=0
Testing system=ETHERNET against ^GEOM$, invert=0
Testing system=ETHERNET against ^GEOM$, invert=0
Testing system=ETHERNET against ^ETHERNET$, invert=0
Testing type=IFATTACH against ^IFATTACH$, invert=0
Testing subsystem=ue0 against ^ue[0-9]+$, invert=0
Executing '/sbin/dhclient $'ue0''
DHCPDISCOVER on ue0 to 255.255.255.255 port 67 interval 8
DHCPOFFER from 192.168.42.129
DHCPREQUEST on ue0 to 255.255.255.255 port 67
DHCPACK from 192.168.42.129
bound to 192.168.42.2 -- renewal in 1800 seconds.
Popping table

Afterword

Now we can use devd(8) to exploit our dynamic hardware control, but remember that it is not a substitute for man pages, so please read also devd(8), devd.conf(5) and devctl(8).


CategoryHowTo

Devd (last edited 2022-09-26T22:19:04+0000 by PauAmma)