how to get notified when an interface goes down !

bsd_newbie

Member


Messages: 36

In my C program I keep a linked list of interfaces which are up...
I need a way to get notified when an interface goes down, so that I can delete the interface from this list.

Is there anyway to do this, without having to maintain messy linked lists in the code itself...

-newbie
 

crsd

Well-Known Member

Reaction score: 94
Messages: 419

just an idea: devd forwards all device events to /var/run/devd.pipe UNIX socket, you could try reading and parsing events from there. check devctl(4) also
 
OP
OP
B

bsd_newbie

Member


Messages: 36

Okay, so I have the following program, that means I will have to issue kqueue for each and every interface on the system ?
Other thing is I will have to know the exact location of the device file that corresponds to my network interface...it would
be nice to be just able to give a bunch of interfaces like ipw0,
em0 etc...

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>

int
main(void)
{
int f, kq, nev;
struct kevent change;
struct kevent event;

kq = kqueue();
if (kq == -1)
perror("kqueue");

f = open("/dev/net/ipw0", O_RDONLY);
if (f == -1)
perror("open");
EV_SET(&change, f, EVFILT_NETDEV,
EV_ADD | EV_ENABLE | EV_ONESHOT,
NOTE_LINKUP | NOTE_LINKDOWN | NOTE_LINKINV,
0, 0);

for (;;) {
nev = kevent(kq, &change, 1, &event, 1, NULL);
if (nev == -1)
perror("kevent");
else if (nev > 0) {
if (event.fflags & NOTE_LINKUP)
printf("link up\n");
if (event.fflags & NOTE_LINKDOWN)
printf("Link down\n");
}
}

close(kq);
close(f);
return EXIT_SUCCESS;
}
 

trev

Aspiring Daemon

Reaction score: 166
Messages: 798

bsd_newbie said:
Other thing is I will have to know the exact location of the device file that corresponds to my network interface...it would be nice to be just able to give a bunch of interfaces like ipw0,em0 etc...
You could hard code the interface/driver value pairs in a header file, but I would think it'd be more elegant and extensible to parse a text configuration file.
 
OP
OP
B

bsd_newbie

Member


Messages: 36

Thanks trev.

Okay, so this way I guess I can watch multiple interfaces.

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>

int
main(void)
{
int fd[2], kq, nev;
struct kevent change[2];
struct kevent event[2];
int i;

kq = kqueue();
if (kq == -1)
perror("kqueue");

fd[0] = open("/dev/net/ipw0", O_RDONLY);
if (fd[0] == -1)
perror("open");

fd[1] = open("/dev/net/em0", O_RDONLY);
if (fd[1] == -1)
perror("open");

for (i = 0; i < 2; i++) {
EV_SET(&change, fd, EVFILT_NETDEV,
EV_ADD | EV_ENABLE | EV_ONESHOT,
NOTE_LINKUP | NOTE_LINKDOWN | NOTE_LINKINV,
0, 0);
}


while (1) {
nev = kevent(kq, change, 2, event, 2, NULL);
if (nev == -1)
perror("kevent");
else if (nev > 0) {
for (i = 0; i < nev; i++) {
if (event.fflags & NOTE_LINKUP)
printf("link up\n");
if (event.fflags & NOTE_LINKDOWN)
printf("Link down\n");
}
}
}

close(kq);
return EXIT_SUCCESS;
}
 

trev

Aspiring Daemon

Reaction score: 166
Messages: 798

You are missing
Code:
#include <unistd.h>
for close() and also the event for NOTE_LINKINV.

Code:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <unistd.h>

int
main(void)
{
int fd, kq, nev;
struct kevent change, event;

kq = kqueue();
if (kq == -1)
        perror("kqueue");

fd = open("/dev/net/re0", O_RDONLY);
if (fd == -1)
        perror("open");

EV_SET(&change, fd, EVFILT_NETDEV,
        EV_ADD | EV_ENABLE | EV_ONESHOT,
        NOTE_LINKUP | NOTE_LINKDOWN | NOTE_LINKINV,
        0, 0);

for (;;) 
        {
        nev = kevent(kq, &change, 1, &event, 1, NULL);
        if (nev < 0)
                perror("kevent");
        else if (nev >= 0) 
                {
                        if (event.fflags & NOTE_LINKUP)
                                printf("Link up\n");
                      
                        if (event.fflags & NOTE_LINKDOWN)
                                printf("Link down\n");

                        if (event.fflags & NOTE_LINKINV)
                                {
                                printf("Link state invalid: %i\n", event.fflags);
                                sleep(3);
                                }
                }
        }

close(kq);
return EXIT_SUCCESS;
}
The only problem with this approach is that, at least on my system, marking an interface as down, is not detected. Marking an interface as up is detected as a link down followed by a link up.

Watching the port on the switch, when an interface is marked as down, the link and speed LEDs do not go out, but when marking it up, they do go out just before returning.

Hmmmm.
 
OP
OP
B

bsd_newbie

Member


Messages: 36

Mel_Flynn said:
check kqueue(2), specifically EVFILT_NETDEV.
It seems this kqueue and evflt_netdev mechanism does not work for virtual interfaces - I had couple of tunnel interfaces and when I did a ifconfig down and up on them, no notification was received.

This is so in 6.2, not sure about other releases.
 
Top