From owner-p4-projects@FreeBSD.ORG Sat Jun 2 12:35:44 2007 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 3952216A468; Sat, 2 Jun 2007 12:35:44 +0000 (UTC) X-Original-To: perforce@FreeBSD.org Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id D793116A46B for ; Sat, 2 Jun 2007 12:35:43 +0000 (UTC) (envelope-from fli@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id C724C13C448 for ; Sat, 2 Jun 2007 12:35:43 +0000 (UTC) (envelope-from fli@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.8/8.13.8) with ESMTP id l52CZhQ6018915 for ; Sat, 2 Jun 2007 12:35:43 GMT (envelope-from fli@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.8/8.13.8/Submit) id l52CZhK3018909 for perforce@freebsd.org; Sat, 2 Jun 2007 12:35:43 GMT (envelope-from fli@FreeBSD.org) Date: Sat, 2 Jun 2007 12:35:43 GMT Message-Id: <200706021235.l52CZhK3018909@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to fli@FreeBSD.org using -f From: Fredrik Lindberg To: Perforce Change Reviews Cc: Subject: PERFORCE change 120775 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 02 Jun 2007 12:35:44 -0000 http://perforce.freebsd.org/chv.cgi?CH=120775 Change 120775 by fli@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 +#include +#include + +#include +#include +#include +#include + +#include +#include #include #include +#include +#include #include #include -#include -#include -#include -#include -#include #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);