diff options
author | jlemon <jlemon@FreeBSD.org> | 2001-09-29 18:32:35 +0000 |
---|---|---|
committer | jlemon <jlemon@FreeBSD.org> | 2001-09-29 18:32:35 +0000 |
commit | 7659fef3a078e47125e1a905f5fa87b72120204a (patch) | |
tree | 41ed7f4f55ee1dac9abffd2dcf1b0837ca214741 | |
parent | b0e345dfe553238af5a174f92e6f954e9afb3439 (diff) | |
download | FreeBSD-src-7659fef3a078e47125e1a905f5fa87b72120204a.zip FreeBSD-src-7659fef3a078e47125e1a905f5fa87b72120204a.tar.gz |
Add ability to attach knotes to network devices.
Introduce EVFILT_NETDEV to report network device changes.
-rw-r--r-- | sys/net/if.c | 74 | ||||
-rw-r--r-- | sys/sys/event.h | 10 |
2 files changed, 82 insertions, 2 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 52b2398..18c9bb6 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -100,6 +100,12 @@ LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners); static int if_indexlim = 8; static struct klist ifklist; +static void filt_netdetach(struct knote *kn); +static int filt_netdev(struct knote *kn, long hint); + +static struct filterops netdev_filtops = + { 1, NULL, filt_netdetach, filt_netdev }; + /* * System initialization */ @@ -114,6 +120,7 @@ MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address"); static d_open_t netopen; static d_close_t netclose; static d_ioctl_t netioctl; +static d_kqfilter_t netkqfilter; static struct cdevsw net_cdevsw = { /* open */ netopen, @@ -128,7 +135,8 @@ static struct cdevsw net_cdevsw = { /* maj */ CDEV_MAJOR, /* dump */ nodump, /* psize */ nopsize, - /* flags */ 0 + /* flags */ D_KQFILTER, + /* kqfilter */ netkqfilter, }; static int @@ -172,6 +180,68 @@ netioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td) return (error); } +static int +netkqfilter(dev_t dev, struct knote *kn) +{ + struct klist *klist; + struct ifnet *ifp; + int idx; + + idx = minor(dev); + if (idx == 0) { + klist = &ifklist; + } else { + ifp = ifnet_byindex(idx); + if (ifp == NULL) + return (1); + klist = &ifp->if_klist; + } + + switch (kn->kn_filter) { + case EVFILT_NETDEV: + kn->kn_fop = &netdev_filtops; + break; + default: + return (1); + } + + kn->kn_hook = (caddr_t)klist; + + /* XXX locking? */ + SLIST_INSERT_HEAD(klist, kn, kn_selnext); + + return (0); +} + +static void +filt_netdetach(struct knote *kn) +{ + struct klist *klist = (struct klist *)kn->kn_hook; + + if (kn->kn_status & KN_DETACHED) + return; + SLIST_REMOVE(klist, kn, knote, kn_selnext); +} + +static int +filt_netdev(struct knote *kn, long hint) +{ + + /* + * Currently NOTE_EXIT is abused to indicate device detach. + */ + if (hint == NOTE_EXIT) { + kn->kn_data = NOTE_LINKINV; + kn->kn_status |= KN_DETACHED; + kn->kn_flags |= (EV_EOF | EV_ONESHOT); + return (1); + } + kn->kn_data = hint; /* current status */ + if (kn->kn_sfflags & hint) + kn->kn_fflags |= hint; + return (kn->kn_fflags != 0); +} + /* * Network interface utility routines. * @@ -258,6 +328,7 @@ if_attach(ifp) TAILQ_INIT(&ifp->if_addrhead); TAILQ_INIT(&ifp->if_prefixhead); TAILQ_INIT(&ifp->if_multiaddrs); + SLIST_INIT(&ifp->if_klist); getmicrotime(&ifp->if_lastchange); if (if_index >= if_indexlim) if_grow(); @@ -385,6 +456,7 @@ if_detach(ifp) (void) rnh->rnh_walktree(rnh, if_rtdel, ifp); } + KNOTE(&ifp->if_klist, NOTE_EXIT); TAILQ_REMOVE(&ifnet, ifp, if_link); mtx_destroy(&ifp->if_snd.ifq_mtx); splx(s); diff --git a/sys/sys/event.h b/sys/sys/event.h index a899580..806ab70 100644 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -36,8 +36,9 @@ #define EVFILT_PROC (-5) /* attached to struct proc */ #define EVFILT_SIGNAL (-6) /* attached to struct proc */ #define EVFILT_TIMER (-7) /* timers */ +#define EVFILT_NETDEV (-8) /* network devices */ -#define EVFILT_SYSCOUNT 7 +#define EVFILT_SYSCOUNT 8 #define EV_SET(kevp, a, b, c, d, e, f) do { \ (kevp)->ident = (a); \ @@ -105,6 +106,13 @@ struct kevent { #define NOTE_CHILD 0x00000004 /* am a child process */ /* + * data/hint flags for EVFILT_NETDEV, shared with userspace + */ +#define NOTE_LINKUP 0x0001 /* link is up */ +#define NOTE_LINKDOWN 0x0002 /* link is down */ +#define NOTE_LINKINV 0x0004 /* link state is invalid */ + +/* * This is currently visible to userland to work around broken * programs which pull in <sys/proc.h> or <sys/select.h>. */ |