PERFORCE change 120775 for review
Fredrik Lindberg
fli at FreeBSD.org
Sat Jun 2 12:35:44 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=120775
Change 120775 by fli at fli_genesis on 2007/06/02 12:34:55
- Add a generic timer functions tmr_{start,stop}
- Add a periodic cache cleaner.
- Add link up/down and address add/remove events.
- Add basic packet parsing to pkgprocess(), including caching.
- Add wrapper functions to interface locks.
- Move socket and read-ready event setup to its own function.
- Add cache initialization to interface setup.
- Add if_del() that frees resources allocated to an interface.
- Add get_linkstatus() returns current link status for an interface.
- Add if_indextodata() returns ifindex -> struct md_if
- Debugging and style fixes.
Affected files ...
.. //depot/projects/soc2007/fli-mdns_sd/mdnsd/mdnsd.c#2 edit
Differences ...
==== //depot/projects/soc2007/fli-mdns_sd/mdnsd/mdnsd.c#2 (text+ko) ====
@@ -24,15 +24,23 @@
*
*/
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+#include <net/route.h>
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
#include <strings.h>
#include <unistd.h>
-#include <err.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <arpa/inet.h>
-#include <ifaddrs.h>
#include "mdnsd.h"
#include "log.h"
@@ -43,6 +51,9 @@
int stack_unlock(void *);
static struct md_if * if_new(struct md_glob *, const char *);
+static int if_del(struct md_glob *, struct md_if *);
+static inline int if_aquire(struct md_if *, int);
+static inline void if_release(struct md_if *, int);
int sig(struct event_sig *, ev_arg);
int sig_init(int, struct event_sig *, ev_arg);
@@ -50,10 +61,101 @@
int evh_udp_recv(const struct event_io *, const ev_arg);
int evh_tcp_recv(const struct event_io *, const ev_arg);
int evh_tcpcli(const struct event_io *, const ev_arg);
+int evh_routesock_init(int, struct event_io *, ev_arg);
+int evh_routesock(struct event_io *, ev_arg);
+
+int tmr_start(struct md_glob *, uint32_t, ev_handler_tmr, void *);
+void tmr_stop(struct md_glob *, int);
+static int evh_cacheclean(const struct event_tmr *, const ev_arg);
static void usage(char *);
/*
+ * Generic timer intialization
+ */
+static int
+tmr_init(int what, struct event_tmr *ev, ev_arg arg)
+{
+
+ switch (what) {
+ case EVENT_INIT_OPEN:
+ ev->evtmr_timeout = arg.int32;
+ break;
+ case EVENT_INIT_CLOSE:
+ break;
+ }
+ return (0);
+}
+
+/*
+ * Start a timer, returns a unique timer identifier
+ */
+int
+tmr_start(struct md_glob *g, uint32_t timeout, ev_handler_tmr handler,
+ void *arg)
+{
+ int id;
+ ev_arg eva, evai;
+
+ evai.int32 = timeout;
+ eva.ptr = arg;
+ id = event_add(g->g_evl, EVENT_TYPE_TMR, handler, &eva,
+ tmr_init, &evai);
+ return (id);
+}
+
+void
+tmr_stop(struct md_glob *g, int timer)
+{
+
+ event_del(g->g_evl, timer, NULL);
+}
+
+/*
+ * Periodic cache cleaner, removes expired cache entries
+ */
+static int
+evh_cacheclean(const struct event_tmr *ev, const ev_arg arg)
+{
+ struct md_if *mif = arg.ptr;
+
+ if (if_aquire(mif, 1) != 0)
+ return (0);
+ cache_clean(&mif->mif_cache);
+ if_release(mif, 1);
+ return (0);
+}
+
+/*
+ * Link state change.
+ * This routine is called 3 seconds after the real link state change
+ * occured, this is to catch and ignore sporadic link changes.
+ */
+static int
+evh_linkchg(const struct event_tmr *ev, const ev_arg arg)
+{
+ struct md_if *mif = arg.ptr;
+
+ if (if_aquire(mif, 1) != 0)
+ return (0);
+ mif->mif_flags &= ~MIF_LINKCHG;
+ tmr_stop(mif->mif_glob, mif->mif_tmr);
+ if (mif->mif_flags & MIF_LINKUP) {
+ mif->mif_flags &= ~MIF_LINKUP;
+ cache_destroy(&mif->mif_cache);
+ cache_init(&mif->mif_cache);
+ dprintf(DEBUG_MISC, "Link state change to DOWN on %s", mif->mif_ifnam);
+ }
+ else {
+ mif->mif_flags |= MIF_LINKUP;
+ /* TODO: call verify unique records */
+ dprintf(DEBUG_MISC, "Link state change to UP on %s", mif->mif_ifnam);
+ }
+ if_release(mif, 1);
+ return (0);
+}
+
+/*
* Signal handler to SIG{INT,HUP}
*/
int
@@ -107,12 +209,15 @@
pkgprocess(struct md_if *mif, struct mdns_pkgchain *pc, int type,
struct sockaddr *from, socklen_t fromlen)
{
+ struct mdns_packet *pkg;
+ struct mdns_rrset rs;
+ struct mdns_qset qs;
+ struct mdns_head hdr;
+ int i, error;
#ifdef DEBUG
char addr[SOCK_MAXADDRLEN+1];
void *sinaddr = NULL;
-#endif
-#ifdef DEBUG
switch (from->sa_family) {
case AF_INET:
sinaddr = &((struct sockaddr_in *)from)->sin_addr;
@@ -121,12 +226,49 @@
case AF_INET6:
sinaddr = &((struct sockaddr_in6 *)from)->sin6_addr;
break;
-#endif
+#endif /* INET6 */
}
inet_ntop(from->sa_family, sinaddr, addr, SOCK_MAXADDRLEN);
- dprintf(DEBUG_MISC, "Packet from: %s", addr);
-#endif
+ dprintf(DEBUG_RECV, "Packet received peer=%s, if=%s", addr, mif->mif_ifnam);
+#endif /* DEBUG */
+
+ pkg = mdns_pkgchain_curpkg(pc);
+ mdns_pkg_gethdr(pkg, &hdr);
+ dprintf(DEBUG_RECV, "questions=%d, answers=%d, authority=%d",
+ hdr.h_cquestion, hdr.h_canswer, hdr.h_cauth);
+
+ if (hdr.h_flags & MDNS_HEAD_QUERY) {
+ for (i = 0; i < hdr.h_cquestion; i++) {
+ error = mdns_pkg_getquestion(pkg, i, &qs);
+ if (error != 0)
+ break;
+
+ /* TODO: check db and reply. Do not reply if answer is
+ in answer section with ttl > own ttl/2 */
+ }
+ }
+ else if (hdr.h_flags & MDNS_HEAD_RESP) {
+ for (i = 0; i < hdr.h_canswer; i++) {
+ error = mdns_pkg_getanswer(pkg, i, &rs);
+ if (error != 0)
+ break;
+ /* TODO: check db for conflicts */
+ /* TODO: check for waiting clients */
+ /* TODO: check for pending questions matching this */
+ /* TODO: check for pending answers matching this */
+
+ /*
+ * Purge records older than 1 second if this is supposed to
+ * be a uniqe rrset (cache flush bit set)
+ */
+ if (rs.r_cflush)
+ cache_purge(&mif->mif_cache, 1, rs.r_name, rs.r_type);
+ error = cache_add(&mif->mif_cache, &rs, NULL);
+ if (error == 1)
+ free(rs.r_data);
+ }
+ }
return (0);
}
@@ -158,7 +300,7 @@
#endif
}
- RW_RLOCK(mif, mif_lock);
+ if_aquire(mif, 0);
/*
* Initialize a packet chain, receive the packet and hand it to the
@@ -169,7 +311,10 @@
n = mdns_recv(&mif->mif_handle, &pc, sa.sa_family, saptr, &salen);
if (n <= 0) {
- dprintf(DEBUG_MISC, "Failed to read anything from socket");
+ if (n == 0) {
+ dprintf(DEBUG_RECV, "No data on UDP socket sock=%d, mif=%x",
+ fd, mif);
+ }
error = -1;
goto out;
}
@@ -179,7 +324,7 @@
out:
mdns_pkgchain_free(&mif->mif_handle, &pc);
- RW_UNLOCK(mif, mif_lock);
+ if_release(mif, 0);
return (error);
}
@@ -213,8 +358,9 @@
error = event_add(g->g_evl, EVENT_TYPE_IO, evh_tcp_recv, &eva,
evh_ioread_init, &evai);
- if (error < 0)
+ if (error < 0) {
dprintf(DEBUG_EVENT, "Failed to add event to TCP client sock");
+ }
#ifdef DEBUG
switch (sa.sa_family) {
@@ -228,7 +374,7 @@
#endif
}
inet_ntop(sa.sa_family, sinaddr, addr, SOCK_MAXADDRLEN);
- dprintf(DEBUG_MISC, "TCP connection from: %s, sock=%d\n", addr, sock);
+ dprintf(DEBUG_RECV, "TCP connection from: %s, sock=%d\n", addr, sock);
#endif
RW_UNLOCK(g, g_lock);
@@ -250,14 +396,18 @@
socklen_t salen;
fd = ev->evio_fd;
- RW_RLOCK(mif, mif_lock);
+ if (if_aquire(mif, 0) != 0)
+ return (-1);
mdns_pkgchain_init(&mif->mif_handle, &pc, MDNS_PC_CONT, stack_lock,
stack_unlock, mif);
n = mdns_tcp_recv(&mif->mif_handle, fd, &pc);
if (n <= 0) {
- dprintf(DEBUG_MISC, "Failed to read anything from socket");
+ if (n == 0) {
+ dprintf(DEBUG_RECV, "No data on TCP socket sock=%d, mif=%x",
+ fd, mif);
+ }
error = -1;
goto out;
}
@@ -270,7 +420,7 @@
out:
mdns_pkgchain_free(&mif->mif_handle, &pc);
- RW_UNLOCK(mif, mif_lock);
+ if_release(mif, 0);
return (error);
}
@@ -284,8 +434,8 @@
struct md_if *mif;
mif = (struct md_if *)arg;
- RW_UNLOCK(mif, mif_lock);
- RW_WLOCK(mif, mif_lock);
+ if_release(mif, 0);
+ if_aquire(mif, 1);
return (0);
}
@@ -299,8 +449,8 @@
struct md_if *mif;
mif = (struct md_if *)arg;
- RW_UNLOCK(mif, mif_lock);
- RW_RLOCK(mif, mif_lock);
+ if_release(mif, 1);
+ if_aquire(mif, 0);
return (0);
}
@@ -337,43 +487,68 @@
return (0);
}
+static inline int
+if_aquire(struct md_if *mif, int write)
+{
+ RW_WLOCK(mif, mif_lock);
+ if (mif->mif_flags & MIF_DYING) {
+ RW_UNLOCK(mif, mif_lock);
+ return (-1);;
+ }
+ mif->mif_refcnt++;
+ if (!write) {
+ RW_UNLOCK(mif, mif_lock);
+ RW_RLOCK(mif, mif_lock);
+ }
+ return (0);
+}
+
+static inline void
+if_release(struct md_if *mif, int write)
+{
+
+ if (!write) {
+ RW_UNLOCK(mif, mif_lock);
+ RW_WLOCK(mif, mif_lock);
+ }
+
+ mif->mif_refcnt--;
+ if ((mif->mif_flags & MIF_DYING) && mif->mif_refcnt == 0) {
+ MDNS_INIT_UNSET(mif, mif_magic);
+ free(mif);
+ }
+ else {
+ RW_UNLOCK(mif, mif_lock);
+ }
+}
+
+#define ADD2EVLIST(mif, id) { \
+ struct md_if_ev *ifev; \
+ ifev = malloc(sizeof(struct md_if_ev)); \
+ ifev->ifev_id = id; \
+ TAILQ_INSERT_TAIL(&mif->mif_evlist, ifev, ifev_next); \
+}
+
/*
- * Allocate a new interface
+ * Intialize sockets and hooks up read-ready events
*/
-static struct md_if *
-if_new(struct md_glob *g, const char *ifnam)
+static void
+setup_socks(struct md_if *mif)
{
- struct md_if *mif;
+ struct md_glob *g;
int i, error, *socks, socklen;
ev_arg eva, evai;
- mif = malloc(sizeof(struct md_if));
- if (mif == NULL)
- return (NULL);
- bzero(mif, sizeof(struct md_if));
- mif->mif_index = if_nametoindex(ifnam);
- if (mif->mif_index == 0)
- goto out;
-
- /* Initialize low-level mdns stack on this interface */
- error = mdns_init(&mif->mif_handle, g->g_bp, ifnam);
- if (error != 0)
- goto out;
-
- RW_INIT(mif, mif_lock, NULL);
- RW_WLOCK(mif, mif_lock);
- mif->mif_glob = g;
-
+ g = mif->mif_glob;
eva.ptr = mif;
-
/* Open up UDP and TCP INET sockets */
error = mdns_open(&mif->mif_handle, MDNS_UDP, PF_INET);
if (error != 0)
- logger(LOG_ERR,"Failed to setup multicast UDP sockets (INET)");
+ logger(LOG_ERR, "Failed to setup multicast UDP sockets (INET)");
error = mdns_open(&mif->mif_handle, MDNS_TCP, PF_INET);
if (error != 0)
- logger(LOG_ERR,"Failed to setup TCP sockets (INET)");
+ logger(LOG_ERR, "Failed to setup TCP sockets (INET)");
/* Install read-ready event to UDP INET socket */
socks = mdns_get_sock(&mif->mif_handle, MDNS_UDP, PF_INET, &socklen);
@@ -381,18 +556,27 @@
evai.fd = socks[0];
error = event_add(g->g_evl, EVENT_TYPE_IO, evh_udp_recv, &eva,
evh_ioread_init, &evai);
- if (error < 0)
- dprintf(DEBUG_EVENT, "Failed to add event to UDP INET socks");
+ if (error >= 0) {
+ ADD2EVLIST(mif, error);
+ }
+ else {
+ dprintf(DEBUG_EVENT, "Failed to add read event for UDP (INET)");
+ }
}
+ /* Install read-ready event to TCP INET socket */
socks = mdns_get_sock(&mif->mif_handle, MDNS_TCP, PF_INET, &socklen);
if (socklen > 0) {
for (i = 0; i < socklen; i++) {
evai.fd = socks[i];
error = event_add(g->g_evl, EVENT_TYPE_IO, evh_tcpcli, &eva,
evh_ioread_init, &evai);
- if (error < 0)
- dprintf(DEBUG_EVENT, "Failed to add event to TCP INET sock");
+ if (error >= 0) {
+ ADD2EVLIST(mif, error);
+ }
+ else {
+ dprintf(DEBUG_EVENT, "Failed to add read event to TCP (INET)");
+ }
}
}
@@ -403,7 +587,7 @@
logger(LOG_ERR, "Failed to setup multicast UDP sockets (INET6)");
error = mdns_open(&mif->mif_handle, MDNS_TCP, PF_INET6);
if (error != 0)
- logger(LOG_ERR,"Failed to setup TCP sockets (INET6)");
+ logger(LOG_ERR, "Failed to setup TCP sockets (INET6)");
/* Install read-ready event to UDP INET6 socket */
socks = mdns_get_sock(&mif->mif_handle, MDNS_UDP, PF_INET6, &socklen);
@@ -411,34 +595,269 @@
evai.fd = socks[0];
error = event_add(g->g_evl, EVENT_TYPE_IO, evh_udp_recv, &eva,
evh_ioread_init, &evai);
- if (error < 0)
- dprintf(DEBUG_EVENT, "Failed to add event to UDP INET6 socks");
+ if (error >= 0) {
+ ADD2EVLIST(mif, error);
+ }
+ else {
+ dprintf(DEBUG_EVENT, "Failed to add read event for UDP (INET6)");
+ }
}
+
+ /* Install read-ready event to TCP INET6 socket */
socks = mdns_get_sock(&mif->mif_handle, MDNS_TCP, PF_INET6, &socklen);
if (socklen > 0) {
for (i = 0; i < socklen; i++) {
evai.fd = socks[i];
error = event_add(g->g_evl, EVENT_TYPE_IO, evh_tcpcli, &eva,
evh_ioread_init, &evai);
- if (error < 0)
- dprintf(DEBUG_EVENT, "Failed to add event to TCP INET6 sock");
+ if (error >= 0) {
+ ADD2EVLIST(mif, error);
+ }
+ else {
+ dprintf(DEBUG_EVENT, "Failed to add read event to TCP (INET6)");
+ }
}
}
#endif
+}
+#undef ADD2EVLIST
+
+/*
+ * Get link status for an interface
+ */
+static int
+get_linkstatus(const char *ifnam)
+{
+ struct ifmediareq ifmr;
+ int fd, error;
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0)
+ return (LINK_STATE_UNKNOWN);
+
+ memset(&ifmr, 0, sizeof(ifmr));
+ strlcpy(ifmr.ifm_name, ifnam, sizeof(ifmr.ifm_name));
+ error = ioctl(fd, SIOCGIFMEDIA, &ifmr);
+ if (error < 0) {
+ close(fd);
+ return (LINK_STATE_UNKNOWN);
+ }
+ close(fd);
+
+ if (ifmr.ifm_status & IFM_AVALID) {
+ if (ifmr.ifm_status & IFM_ACTIVE)
+ return (LINK_STATE_UP);
+ else
+ return (LINK_STATE_DOWN);
+ }
+ return (LINK_STATE_UNKNOWN);
+}
+
+
+/*
+ * Allocate a new interface
+ */
+static struct md_if *
+if_new(struct md_glob *g, const char *ifnam)
+{
+ struct md_if *mif;
+ int error;
+
+ mif = malloc(sizeof(struct md_if));
+ if (mif == NULL)
+ return (NULL);
+ bzero(mif, sizeof(struct md_if));
+ mif->mif_index = if_nametoindex(ifnam);
+ if (mif->mif_index == 0)
+ goto out;
+ strncpy(mif->mif_ifnam, ifnam, IFNAMSIZ);
+ /* Initialize low-level mdns stack on this interface */
+ error = mdns_init(&mif->mif_handle, g->g_bp, ifnam);
+ if (error != 0)
+ goto out;
+
+ RW_INIT(mif, mif_lock, NULL);
+ RW_WLOCK(mif, mif_lock);
+ mif->mif_glob = g;
+ TAILQ_INIT(&mif->mif_evlist);
+ cache_init(&mif->mif_cache);
+ mif->mif_cache.c_timer = tmr_start(g, 1000, evh_cacheclean, mif);
+ if (get_linkstatus(ifnam) != LINK_STATE_DOWN)
+ mif->mif_flags |= MIF_LINKUP;
+ setup_socks(mif);
+ MDNS_INIT_SET(mif, mif_magic);
+ RW_UNLOCK(mif, mif_lock);
+
RW_WLOCK(g, g_lock);
TAILQ_INSERT_TAIL(&g->g_ifs, mif, mif_next);
RW_UNLOCK(g, g_lock);
- RW_UNLOCK(mif, mif_lock);
+ logger(LOG_NOTICE, "Added interface %s", mif->mif_ifnam);
- logger(LOG_NOTICE, "Added interface %s", ifnam);
-
return (mif);
out:
free(mif);
return (NULL);
}
+/*
+ * Remove an interface
+ */
+static int
+if_del(struct md_glob *g, struct md_if *mif)
+{
+ struct md_if_ev *ifev, *ifev2;
+
+ MDNS_INIT_ASSERT(mif, mif_magic);
+
+ if (if_aquire(mif, 1) != 0)
+ return (-1);
+ mif->mif_flags |= MIF_DYING;
+
+ RW_WLOCK(g, g_lock);
+ TAILQ_REMOVE(&g->g_ifs, mif, mif_next);
+ RW_UNLOCK(g, g_lock);
+
+ TAILQ_FOREACH_SAFE(ifev, &mif->mif_evlist, ifev_next, ifev2) {
+ event_del(g->g_evl, ifev->ifev_id, NULL);
+ free(ifev);
+ }
+ tmr_stop(g, mif->mif_cache.c_timer);
+
+ mdns_destroy(&mif->mif_handle);
+ cache_destroy(&mif->mif_cache);
+
+ logger(LOG_NOTICE, "Removed interface %s", mif->mif_ifnam);
+ if_release(mif, 1);
+ return (0);
+}
+
+static struct md_if *
+if_indextodata(struct md_glob *g, int index)
+{
+ struct md_if *mif;
+
+ TAILQ_FOREACH(mif, &g->g_ifs, mif_next) {
+ if (index == mif->mif_index)
+ return (mif);
+ }
+ return (NULL);
+}
+
+/*
+ * Routing socket event handler initialization
+ */
+int
+evh_routesock_init(int what, struct event_io *ev, ev_arg arg)
+{
+ int sock;
+
+ switch (what) {
+ case EVENT_INIT_OPEN:
+ sock = socket(AF_ROUTE, SOCK_RAW, 0);
+ if (sock < 0)
+ return (-1);
+ ev->evio_fd = sock;
+ ev->evio_dir = EVENT_IO_READ;
+ break;
+ case EVENT_INIT_CLOSE:
+ close(ev->evio_fd);
+ break;
+ }
+ return (0);
+}
+
+/*
+ * Routing socket event handler
+ * This will monitor a routing socket and add/remove interfaces as
+ * appropriate.
+ */
+int
+evh_routesock(struct event_io *ev, ev_arg arg)
+{
+#define RS_BUFLEN (sizeof(struct rt_msghdr) + 512)
+ struct md_glob *g = (struct md_glob *)arg.ptr;
+ struct md_if *mif;
+ struct if_msghdr *ifm;
+ int len, sock;
+ char *next, *lim;
+ struct md_if_ev *ifev, *ifev2;
+ char buf[RS_BUFLEN], ifnam[IFNAMSIZ];
+
+ sock = ev->evio_fd;
+
+ len = read(sock, buf, RS_BUFLEN);
+ if (len <= 0)
+ return (0);
+
+ lim = buf + len;
+ for (next = buf; next < lim; next += ifm->ifm_msglen) {
+ ifm = (struct if_msghdr *) next;
+ if (ifm->ifm_flags & IFF_LOOPBACK)
+ continue;
+
+ RW_RLOCK(g, g_lock);
+ mif = if_indextodata(g, ifm->ifm_index);
+ RW_UNLOCK(g, g_lock);
+
+ if (ifm->ifm_type == RTM_IFINFO) {
+ if (ifm->ifm_flags & IFF_UP && mif == NULL) {
+ if (ifm->ifm_flags & IFF_MULTICAST)
+ if (if_indextoname(ifm->ifm_index, ifnam) != NULL)
+ if_new(g, ifnam);
+ }
+ else if (!(ifm->ifm_flags & IFF_UP) && mif != NULL) {
+ if_del(g, mif);
+ }
+ else {
+ if (if_aquire(mif, 1) != 0)
+ continue;
+
+ if (mif->mif_flags & MIF_LINKCHG) {
+ tmr_stop(g, mif->mif_tmr);
+ mif->mif_flags &= ~MIF_LINKCHG;
+ dprintf(DEBUG_MISC,
+ "Link on %s re-restored, ignoring state change",
+ mif->mif_ifnam);
+ }
+ else if ((ifm->ifm_data.ifi_link_state == LINK_STATE_UP &&
+ !(mif->mif_flags & MIF_LINKUP)) ||
+ (ifm->ifm_data.ifi_link_state == LINK_STATE_DOWN &&
+ mif->mif_flags & MIF_LINKUP)) {
+ mif->mif_flags |= MIF_LINKCHG;
+ mif->mif_tmr = tmr_start(g, 3000, evh_linkchg, mif);
+ }
+
+ if_release(mif, 1);
+ }
+ }
+ else if (mif == NULL) {
+ continue;
+ }
+
+ /* This is a bit crude */
+ if (ifm->ifm_type == RTM_NEWADDR || ifm->ifm_type == RTM_DELADDR ||
+ ifm->ifm_type == RTM_NEWMADDR) {
+ if_aquire(mif, 1);
+ TAILQ_FOREACH_SAFE(ifev, &mif->mif_evlist, ifev_next, ifev2) {
+ event_del(g->g_evl, ifev->ifev_id, NULL);
+ free(ifev);
+ }
+ mdns_close(&mif->mif_handle, MDNS_UDP, PF_INET);
+ mdns_close(&mif->mif_handle, MDNS_TCP, PF_INET);
+#ifdef INET6
+ mdns_close(&mif->mif_handle, MDNS_UDP, PF_INET6);
+ mdns_close(&mif->mif_handle, MDNS_TCP, PF_INET6);
+#endif
+ setup_socks(mif);
+ if_release(mif, 1);
+ }
+ }
+
+ return (0);
+#undef RS_BUFLEN
+}
+
static void
usage(char *exec)
{
@@ -452,6 +871,7 @@
int error, ch, nodaemon = 0;
char *ifnam, *cfgfile = NULL;
struct ifaddrs *ifap, *ifa;
+ struct md_if *mif, *mif2;
struct md_glob glob;
ev_arg eva;
@@ -512,9 +932,9 @@
event_add(glob.g_evl, EVENT_TYPE_SIG, sig, NULL, sig_init, &eva);
/* Add interfaces that are up */
- error = getifaddrs(&ifap);
- if (error != 0)
- err(EXIT_FAILURE, "getifaddrs");
+ error = getifaddrs(&ifap);
+ if (error != 0)
+ err(EXIT_FAILURE, "getifaddrs");
ifnam = NULL;
for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_flags & IFF_LOOPBACK ||
@@ -527,9 +947,17 @@
}
freeifaddrs(ifap);
+ eva.ptr = &glob;
+ event_add(glob.g_evl, EVENT_TYPE_IO, evh_routesock, &eva,
+ evh_routesock_init, NULL);
+
/* Launch the event dispatcher */
error = event_dispatch(glob.g_evl, glob.g_wq);
+ TAILQ_FOREACH_SAFE(mif, &glob.g_ifs, mif_next, mif2) {
+ if_del(&glob, mif);
+ }
+
wq_destroy(glob.g_wq);
event_destroy(glob.g_evl);
mdns_bufpool_destroy(glob.g_bp);
More information about the p4-projects
mailing list