Detect DHCP Network Changes?

I have a machine running FreeBSD 12.3 and I am looking for a way to monitor network changes through a shell script, specifically related to the network interfaces.

Some examples of things that I would like to detect are:
  • When a network interface changes status (e.g. from active to no carrier)
  • When a new DHCP IP addressed is assigned to a network interface
Is this achievable in FreeBSD?
 
I would like more information.

Do you get an IP from a DHCP server (like your ISP) and you want to monitor that connection and interface?

Or Perhaps you are running your own DHCP server and you want to know when your DHCP server is handing out leases?
 
There is a file based approach you could use for a client to monitor DHCP lease assignment.

You could have security/tripwire monitor your lease file.
For example whenever /var/db/dhclient.leases.em0 is wrote to tripwire would trigger a report.
You would setup tripwire to run via cron and run an integrity test. It would flag the change to lease file.

Note: em0 is my interface name for dhclient leases. Please substitute your interface name.
 
I am sure there are easier ways of monitoring a single lease file and check interface status with a scheduled ping.

So yes FreeBSD can monitor itself. Have you tried a basic script?
 
Many times when I need to monitor something I use FreeBSD resources to accomplish that.
For example look at /etc/periodic/daily/420.status-network
You can scrape parts of that for the beginning of a new script.

 
You could use some clever devd.conf(5) rules to detect LINK_UP and LINK_DOWN. And use a dhclient-script(8) hook to detect DHCP changes.
I believe that this suggestion will work for me. I will attempted to implement. I'll be sure to drop back to this forum if I have another question.


I would like more information.

Do you get an IP from a DHCP server (like your ISP) and you want to monitor that connection and interface?

Or Perhaps you are running your own DHCP server and you want to know when your DHCP server is handing out leases?
I am receiving IPs from a DHCP server.

There is a file based approach you could use for a client to monitor DHCP lease assignment.

You could have security/tripwire monitor your lease file.
For example whenever /var/db/dhclient.leases.em0 is wrote to tripwire would trigger a report.
You would setup tripwire to run via cron and run an integrity test. It would flag the change to lease file.

Note: em0 is my interface name for dhclient leases. Please substitute your interface name.
My aim was to achieve this natively within FreeBSD without installing any additional packages.

Many times when I need to monitor something I use FreeBSD resources to accomplish that.
For example look at /etc/periodic/daily/420.status-network
You can scrape parts of that for the beginning of a new script.

Perhaps this suggestion may work for me as well. Again, if I have anymore questions I'll be sure to ask.

If there are any more suggestions others may have, please continue to add them.

Thanks all!
 
You could use some clever devd.conf(5) rules to detect LINK_UP and LINK_DOWN. And use a dhclient-script(8) hook to detect DHCP changes.
So I implemented this suggestion. From my results, I can successfully detect a "LINK_DOWN" by unplugging my attached ethernet cord, however I can not detect a "LINK_UP" when the cable is reattached. Is this the wrong way to simulate a "LINK_UP"? If so, the detaching and reattaching of the ethernet cord is in essence what I would like to detect.
 
To add on to my previous question, I also attempted to use a dhclient-script(8) hook to detect DHCP changes. I have a /etc/dhclient-exit-hooks directory. In there it contains a simple shell script to echo to the command line when an event occurs, however it does not seem to execute when I disconnect and reconnect an ethernet cord. Any ideas as to why?

Bash:
#!/bin/sh

if [[ “$interface” = “em0”]] || [[“$interface” = “em1” ]] ; then
 case “$reason” in BOUND|RENEW|REBIND|REBOOT|EXPIRE|FAIL|TIMEOUT)
            echo Event occured
       ;;
       esac
fi
 
I have a /etc/dhclient-exit-hooks directory.
you need a file not a dir
/etc/dhclient-exit-hooks should be your script
put something like this at the top for more logging
Code:
#!/bin/sh
exec >>/tmp/dhclient.log 2>&1
date "+====== %Y-%m-%d %H:%M:%S ================"
set -x
 
you need a file not a dir
/etc/dhclient-exit-hooks should be your script
put something like this at the top for more logging

Ahhh, I see. Thanks for the clarification. I feel as if I am very close to achieving my goal.

So after making that correction. my dhclient-exit-hooks script seems to work, somewhat. It seems to detect when I connect an ethernet cable and establish a connection, however it does not detect when I remove it. On the contrary, when using the devd.conf rules, it seems to detect when the ethernet cable is removed, but not re-inserted. When both are implemented together, they accomplish what I am trying to achieve. However I feel as one of these implementations should be able to handle what I need., not both. If I am wrong please let me know. Worse case scenario is that I implement both. Below are both scripts.

For some clarification, I am testing this by running an executable called "displayip" which simply makes an ifconfig call and tells me the status and ip (if there is one) of the relative network interface. In the dhclient-exit-hooks script, I added pretty much all of the available reasons as so that the network interface status information is kept up to date in real time. Could that be the source of my issue?

Also the same logic I applied with the devd.conf rules. I added both "ATTACH" and "DETACH" as types because my initial testing with "LINK_UP" and "LINK_DOWN" only resulted in "LINK_DOWN" working.


dhclient-exit-hooks:
Bash:
#!/bin/bash
exec >>/tmp/dhclient.log 2>&1
date "+==============%Y-%m-%d %H:%M:%S================"
set -x

if [ "${interface}" = "em0" ] || [ "${interface}" = "em1" ] || [ "${interface}" = "igb0" ] || [ "${interface}" = "igb1" ]; then
    case "${reason}" in BOUND|RENEW|REBIND|REBOOT|EXPIRE|FAIL|TIMEOUT|MEDIUM|PREINIT)
        /usr/home/develop/Display/displayip
    ;;
    esac
fi

displayip.conf:
Code:
notify 0 {
    match "system"        "IFNET";
    match "subsystem"    "(em0|em1|igb0|igb1)";
    match "type"        "LINK_DOWN";
    action                "/usr/home/develop/Display/displayip";

notify 0 {
    match "system"        "IFNET";
    match "subsystem"    "(em0|em1|igb0|igb1)";
    match "type"        "LINK_UP";
    action                 "/usr/home/develop/Display/displayip";
};

notify 0 {
    match "system"        "IFNET";
    match "subsystem"    "(em0|em1|igb0|igb1)";
    match "type"        "ATTACH";
    action                "/usr/home/develop/Display/displayip";
};

notify 0 {
    match "system"        "IFNET";
    match "subsystem"    "(em0|em1|igb0|igb1)";
    match "type"        "DETACH";
    action                "/usr/home/develop/Display/displayip";
}
 
don't think this shebang line will work on FreeBSD; it should be something like #!/usr/local/bin/bash

I'm not sure about the exact filespec because I only use #!/bin/sh
normally it won't
but the above script does not exec the "hook script" it sources it so it does not matter
 
Back
Top