Add support to call scripts at carrier detect/drop time (on network
interfaces that report this). Basically from Brian Grayson, fixes his PR bin/23191.
This commit is contained in:
parent
710460b874
commit
06eb7200cc
|
@ -1,4 +1,4 @@
|
|||
.\" $NetBSD: ifwatchd.8,v 1.19 2003/07/04 12:48:30 wiz Exp $
|
||||
.\" $NetBSD: ifwatchd.8,v 1.20 2004/01/04 22:19:51 martin Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2001-2003 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
|
@ -34,7 +34,7 @@
|
|||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd March 5, 2003
|
||||
.Dd January 4, 2004
|
||||
.Os
|
||||
.Dt IFWATCHD 8
|
||||
.Sh NAME
|
||||
|
@ -47,11 +47,14 @@
|
|||
.Op Fl D Ar departure-script
|
||||
.Op Fl d Ar down-script
|
||||
.Op Fl u Ar up-script
|
||||
.Op Fl c Ar carrier-script
|
||||
.Op Fl n Ar no-carrier-script
|
||||
.Ar ifname(s)
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is used to monitor dynamic interfaces (for example PPP interfaces)
|
||||
for address changes.
|
||||
for address changes, and to monitor static interfaces for carrier
|
||||
changes.
|
||||
Sometimes these interfaces are accompanied by a daemon program,
|
||||
which can take care of running any necessary scripts (like
|
||||
.Xr pppd 8
|
||||
|
@ -61,13 +64,15 @@ but sometimes the interfaces run completely autonomously (like
|
|||
.Xr pppoe 4 ) .
|
||||
.Pp
|
||||
.Nm
|
||||
provides a generic way to watch this type of changes.
|
||||
provides a generic way to watch these types of changes.
|
||||
It works by monitoring the routing socket and interpreting
|
||||
.Ql RTM_NEWADDR
|
||||
.Pq address added
|
||||
and
|
||||
.Pq address added ,
|
||||
.Ql RTM_DELADDR
|
||||
.Pq address deleted
|
||||
and
|
||||
.Ql RTM_IFINFO
|
||||
.Pq carrier detect or loss of carrier
|
||||
messages.
|
||||
It does not need special privileges to do this.
|
||||
The scripts called for up or down events are run with the same user
|
||||
|
@ -80,6 +85,9 @@ The following options are available:
|
|||
.It Fl A Ar arrival-script
|
||||
Specify the command to invoke on arrival of new interfaces (like
|
||||
PCMCIA cards).
|
||||
.It Fl c Ar carrier-script
|
||||
Specify the command to invoke when the carrier status transitions from
|
||||
no carrier to carrier.
|
||||
.It Fl D Ar departure-script
|
||||
Specify the command to invoke when an interface departs (for example
|
||||
a PCMCIA card is removed.)
|
||||
|
@ -105,12 +113,11 @@ By default
|
|||
.Nm
|
||||
calls them on startup to account for this (and make the scripts
|
||||
easier.)
|
||||
.It Fl n Ar no-carrier-script
|
||||
Specify the command to invoke when the carrier status transitions from
|
||||
carrier to no carrier.
|
||||
.It Fl q
|
||||
Be quiet and don't log non-error messages to syslog.
|
||||
.It Ar ifname(s)
|
||||
The name of the interface to watch.
|
||||
Multiple interfaces may be specified.
|
||||
Events for other interfaces are ignored.
|
||||
.It Fl u Ar up-script
|
||||
Specify the command to invoke on
|
||||
.Dq interface up
|
||||
|
@ -120,11 +127,12 @@ Run in verbose debug mode and do not detach from the controlling
|
|||
terminal.
|
||||
Output verbose progress messages and flag errors ignored during
|
||||
normal operation.
|
||||
Adding more
|
||||
.Fl v
|
||||
increases the verbosity.
|
||||
.Em You do not want to use this option in
|
||||
.Pa /etc/rc.conf !
|
||||
.It Ar ifname(s)
|
||||
The name of the interface to watch.
|
||||
Multiple interfaces may be specified.
|
||||
Events for other interfaces are ignored.
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
.Bd -literal -offset indent
|
||||
|
@ -159,6 +167,33 @@ Use
|
|||
in your
|
||||
.Pa /etc/ifconfig.pppoe0
|
||||
file in the on-demand case.
|
||||
.Pp
|
||||
The next example is for dhclient users.
|
||||
.Bd -literal -offset indent
|
||||
# ifwatchd -i -c /etc/dhcp/carrier-detect tlp0
|
||||
.Ed
|
||||
.Pp
|
||||
With the above command, the carrier-detect script will be invoked when
|
||||
a carrier is detected on the interface
|
||||
.Ar tlp0 .
|
||||
Note that the
|
||||
.Ar -i
|
||||
flag prevents any action based on the initial state.
|
||||
A script like the following should work for most users, although it
|
||||
will not work for machines with multiple interfaces running
|
||||
.Cm dhclient .
|
||||
.Bd -literal -offset indent
|
||||
#! /bin/sh
|
||||
# Arguments: ifname tty speed address destination
|
||||
# If there is a dhclient already running, kill it.
|
||||
# (This step could be put in a distinct no-carrier script,
|
||||
# if desired.)
|
||||
if [ -f /var/run/dhclient.pid ]; then
|
||||
/bin/kill `/bin/cat /var/run/dhclient.pid`
|
||||
fi
|
||||
# Start dhclient again on this interface
|
||||
/sbin/dhclient $1
|
||||
.Ed
|
||||
.Sh PARAMETERS PASSED TO SCRIPTS
|
||||
The invoked scripts get passed these parameters:
|
||||
.Bl -tag -width destination
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ifwatchd.c,v 1.18 2003/12/27 00:05:46 martin Exp $ */
|
||||
/* $NetBSD: ifwatchd.c,v 1.19 2004/01/04 22:19:51 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
|
||||
|
@ -66,7 +66,8 @@
|
|||
#include <ifaddrs.h>
|
||||
#include <syslog.h>
|
||||
|
||||
enum event { ARRIVAL, DEPARTURE, UP, DOWN };
|
||||
enum event { ARRIVAL, DEPARTURE, UP, DOWN, CARRIER, NO_CARRIER };
|
||||
|
||||
/* local functions */
|
||||
static void usage(void);
|
||||
static void dispatch(void*, size_t);
|
||||
|
@ -74,6 +75,7 @@ static void check_addrs(char *cp, int addrs, enum event ev);
|
|||
static void invoke_script(struct sockaddr *sa, struct sockaddr *dst, enum event ev, int ifindex, const char *ifname_hint);
|
||||
static void list_interfaces(const char *ifnames);
|
||||
static void check_announce(struct if_announcemsghdr *ifan);
|
||||
static void check_carrier(int if_index, int carrier);
|
||||
static void rescan_interfaces(void);
|
||||
static void free_interfaces(void);
|
||||
static int find_interface(int index);
|
||||
|
@ -100,18 +102,23 @@ static const char *arrival_script = NULL;
|
|||
static const char *departure_script = NULL;
|
||||
static const char *up_script = NULL;
|
||||
static const char *down_script = NULL;
|
||||
static char DummyTTY[] = _PATH_DEVNULL;
|
||||
static char DummySpeed[] = "9600";
|
||||
static const char *carrier_script = NULL;
|
||||
static const char *no_carrier_script = NULL;
|
||||
static const char DummyTTY[] = _PATH_DEVNULL;
|
||||
static const char DummySpeed[] = "9600";
|
||||
static const char **scripts[] = {
|
||||
&arrival_script,
|
||||
&departure_script,
|
||||
&up_script,
|
||||
&down_script
|
||||
&down_script,
|
||||
&carrier_script,
|
||||
&no_carrier_script
|
||||
};
|
||||
|
||||
struct interface_data {
|
||||
SLIST_ENTRY(interface_data) next;
|
||||
int index;
|
||||
int last_carrier_status;
|
||||
char * ifname;
|
||||
};
|
||||
SLIST_HEAD(,interface_data) ifs = SLIST_HEAD_INITIALIZER(ifs);
|
||||
|
@ -124,21 +131,32 @@ main(int argc, char **argv)
|
|||
char msg[2048], *msgp;
|
||||
|
||||
openlog(argv[0], LOG_PID|LOG_CONS, LOG_DAEMON);
|
||||
while ((c = getopt(argc, argv, "qvhiu:d:A:D:")) != -1)
|
||||
while ((c = getopt(argc, argv, "qvhic:n:u:d:A:D:")) != -1)
|
||||
switch (c) {
|
||||
case 'h':
|
||||
usage();
|
||||
return 0;
|
||||
|
||||
case 'i':
|
||||
inhibit_initial = 1;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
carrier_script = optarg;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
no_carrier_script = optarg;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
up_script = optarg;
|
||||
break;
|
||||
|
@ -174,6 +192,8 @@ main(int argc, char **argv)
|
|||
up_script, down_script);
|
||||
printf("arrival_script: %s\ndeparture_script: %s\n",
|
||||
arrival_script, departure_script);
|
||||
printf("carrier_script: %s\nno_carrier_script: %s\n",
|
||||
carrier_script, no_carrier_script);
|
||||
printf("verbosity = %d\n", verbose);
|
||||
}
|
||||
|
||||
|
@ -218,11 +238,14 @@ usage()
|
|||
fprintf(stderr,
|
||||
"usage:\n"
|
||||
"\tifwatchd [-hiqv] [-A arrival-script] [-D departure-script]\n"
|
||||
"\t\t [-d down-script] [-u up-script] ifname(s)\n"
|
||||
"\t\t [-d down-script] [-u up-script]\n"
|
||||
"\t\t [-c carrier-script] [-n no-carrier-script] ifname(s)\n"
|
||||
"\twhere:\n"
|
||||
"\t -A <cmd> specify command to run on interface arrival event\n"
|
||||
"\t -c <cmd> specify command to run on interface carrier-detect event\n"
|
||||
"\t -D <cmd> specify command to run on interface departure event\n"
|
||||
"\t -d <cmd> specify command to run on interface down event\n"
|
||||
"\t -n <cmd> specify command to run on interface no-carrier-detect event\n"
|
||||
"\t -h show this help message\n"
|
||||
"\t -i no (!) initial run of the up script if the interface\n"
|
||||
"\t is already up on ifwatchd startup\n"
|
||||
|
@ -236,6 +259,7 @@ static void
|
|||
dispatch(void *msg, size_t len)
|
||||
{
|
||||
struct rt_msghdr *hd = msg;
|
||||
struct if_msghdr *ifmp;
|
||||
struct ifa_msghdr *ifam;
|
||||
enum event ev;
|
||||
|
||||
|
@ -250,6 +274,10 @@ dispatch(void *msg, size_t len)
|
|||
rescan_interfaces();
|
||||
check_announce((struct if_announcemsghdr *)msg);
|
||||
return;
|
||||
case RTM_IFINFO:
|
||||
ifmp = (struct if_msghdr*)msg;
|
||||
check_carrier(ifmp->ifm_index, ifmp->ifm_data.ifi_link_state);
|
||||
return;
|
||||
}
|
||||
if (verbose)
|
||||
printf("unknown message ignored\n");
|
||||
|
@ -380,7 +408,8 @@ invoke_script(sa, dest, ev, ifindex, ifname_hint)
|
|||
}
|
||||
}
|
||||
|
||||
static void list_interfaces(const char *ifnames)
|
||||
static void
|
||||
list_interfaces(const char *ifnames)
|
||||
{
|
||||
char * names = strdup(ifnames);
|
||||
char * name, *lasts;
|
||||
|
@ -392,6 +421,7 @@ static void list_interfaces(const char *ifnames)
|
|||
name = strtok_r(NULL, sep, &lasts)) {
|
||||
p = malloc(sizeof(*p));
|
||||
SLIST_INSERT_HEAD(&ifs, p, next);
|
||||
p->last_carrier_status = -1;
|
||||
p->ifname = strdup(name);
|
||||
p->index = if_nametoindex(p->ifname);
|
||||
if (!quiet)
|
||||
|
@ -403,6 +433,45 @@ static void list_interfaces(const char *ifnames)
|
|||
free(names);
|
||||
}
|
||||
|
||||
static void
|
||||
check_carrier(int if_index, int carrier_status)
|
||||
{
|
||||
struct interface_data * p;
|
||||
enum event ev;
|
||||
|
||||
SLIST_FOREACH(p, &ifs, next)
|
||||
if (p->index == if_index)
|
||||
break;
|
||||
|
||||
if (p == NULL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Treat it as an event worth handling if:
|
||||
* - the carrier status changed, or
|
||||
* - this is the first time we've been called, and
|
||||
* inhibit_initial is not set
|
||||
*/
|
||||
|
||||
if ((carrier_status != p->last_carrier_status) ||
|
||||
((p->last_carrier_status == -1) && !inhibit_initial)) {
|
||||
switch (carrier_status) {
|
||||
case LINK_STATE_UP:
|
||||
ev = CARRIER;
|
||||
break;
|
||||
case LINK_STATE_DOWN:
|
||||
ev = NO_CARRIER;
|
||||
break;
|
||||
default:
|
||||
if (verbose)
|
||||
printf("unknown link status ignored\n");
|
||||
return;
|
||||
}
|
||||
invoke_script(NULL, NULL, ev, if_index, p->ifname);
|
||||
p->last_carrier_status = carrier_status;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
check_announce(struct if_announcemsghdr *ifan)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue