Date: Sat, 21 Jul 2007 19:28:27 GMT From: Fredrik Lindberg <fli@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 123861 for review Message-ID: <200707211928.l6LJSRjw011392@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=123861 Change 123861 by fli@fli_nexus on 2007/07/21 19:28:25 - Break out response processing to its own routine and hook up the query system to it. - Follow cache system changes. - Add initialization to the query system and to the unix pipe server. - Add bits needed to the interface array. - Add -u and -g flags that allow one to specify another user to run the daemon as. - Attempt to raise privileges during unix pipe setup, they are dropped before any other processing begins. Affected files ... .. //depot/projects/soc2007/fli-mdns_sd/mdnsd/mdnsd.c#5 edit Differences ... ==== //depot/projects/soc2007/fli-mdns_sd/mdnsd/mdnsd.c#5 (text+ko) ==== @@ -35,8 +35,10 @@ #include <err.h> #include <fcntl.h> +#include <grp.h> #include <ifaddrs.h> #include <locale.h> +#include <pwd.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> @@ -141,7 +143,7 @@ struct md_if *mif; RW_RLOCK(g, g_lock); - TAILQ_FOREACH(mif, &g->g_ifs, mif_next) { + TAILQ_FOREACH(mif, &g->g_ifs_head, mif_next) { if (if_aquire(mif, 1) != 0) continue; @@ -169,7 +171,7 @@ if (mif->mif_flags & MIF_LINKUP) { mif->mif_flags &= ~MIF_LINKUP; cache_destroy(&mif->mif_cache); - cache_init(&mif->mif_cache); + cache_init(&mif->mif_cache, &mif->mif_q); dprintf(DEBUG_MISC, "Link state change to DOWN on %s", mif->mif_ifnam); } @@ -340,7 +342,7 @@ * Process the answer section first */ if (hdr->h_canswer > 0) - cache_init(&ac); + cache_init(&ac, NULL); for (i = 0; i < hdr->h_canswer; i++) { error = mdns_pkg_getanswer(pkg, i, &rs); if (error != 0) @@ -518,6 +520,55 @@ } /* + * Process a response + */ +static void +process_resp(struct md_if *mif, struct mdns_packet *pkg, struct mdns_head *hdr, + struct sockaddr *from, socklen_t fromlen __unused) +{ + struct dbr_rec *dr; + int i, error; + struct mdns_rrset rs; + + for (i = 0; i < hdr->h_canswer; i++) { + error = mdns_pkg_getanswer(pkg, i, &rs); + if (error != 0) + break; + if (rs.r_class != mdns_c_in) { + free(rs.r_data); + continue; + } + + dprintf(DEBUG_RECV, "response to %s, class=%d, type=%d", + rs.r_name, rs.r_class, rs.r_type); + + dr = dbr_find(&mif->mif_dbr, rs.r_name); + if (dr != NULL && !(dr->dr_flags & DR_SHARED)) { + dprintf(DEBUG_SEND, "Conflicting name %s", rs.r_name); + dbr_defend(&mif->mif_dbr, dr, &rs, from->sa_family); + continue; + } + + /* Notify pending consumers */ + query_notify(&mif->mif_q, &rs, mif->mif_index, + from->sa_family, ((i + 1) < hdr->h_canswer)); + + /* 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 unique 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); + } +} + +/* * Process a mdns packet and generate appropriate responses * mif - Interface handle * pc - Packet chain @@ -531,9 +582,7 @@ { struct mdns_packet *pkg; struct mdns_head hdr; - struct mdns_rrset rs; - struct dbr_rec *dr; - int i, error, sinaddr_len, legacy; + int sinaddr_len, legacy; in_port_t port; void *sinaddr = NULL; struct sockaddr_in *sin; @@ -588,41 +637,7 @@ * We are processing a response */ 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; - if (rs.r_class != mdns_c_in) { - free(rs.r_data); - continue; - } - - dr = dbr_find(&mif->mif_dbr, rs.r_name); - if (dr != NULL && !(dr->dr_flags & DR_SHARED)) { - dprintf(DEBUG_SEND, "Conflicting name %s " - "with peer %s", rs.r_name, addr); - dbr_defend(&mif->mif_dbr, dr, &rs, - from->sa_family); - continue; - } - - - /* 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 unique 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); - } + process_resp(mif, pkg, &hdr, from, fromlen); } return (0); } @@ -986,7 +1001,7 @@ if_new(struct md_glob *g, const char *ifnam) { struct md_if *mif; - int error; + int error, diff; struct aq_func aqf; mif = malloc(sizeof(struct md_if)); @@ -1012,8 +1027,11 @@ if (get_linkstatus(ifnam) != LINK_STATE_DOWN) mif->mif_flags |= MIF_LINKUP; + /* Client queries system */ + queries_init(&mif->mif_q, mif); + /* Initialize cache */ - cache_init(&mif->mif_cache); + cache_init(&mif->mif_cache, &mif->mif_q); /* Initialize output queue */ oq_init(&mif->mif_oq, mif); @@ -1040,7 +1058,15 @@ cfg_read(&mif->mif_dbr, ifnam, g->g_cfgfile); RW_WLOCK(g, g_lock); - TAILQ_INSERT_TAIL(&g->g_ifs, mif, mif_next); + TAILQ_INSERT_TAIL(&g->g_ifs_head, mif, mif_next); + if (mif->mif_index >= g->g_ifs_max) { + diff = mif->mif_index - g->g_ifs_max; + g->g_ifs = realloc(g->g_ifs, + sizeof(struct md_if *) * (mif->mif_index + 1)); + bzero(g->g_ifs + g->g_ifs_max, sizeof(struct md_if *) * diff); + g->g_ifs_max = mif->mif_index; + } + g->g_ifs[mif->mif_index] = mif; RW_UNLOCK(g, g_lock); RW_UNLOCK(mif, mif_lock); @@ -1069,7 +1095,8 @@ mif->mif_flags |= MIF_DYING; RW_WLOCK(g, g_lock); - TAILQ_REMOVE(&g->g_ifs, mif, mif_next); + TAILQ_REMOVE(&g->g_ifs_head, mif, mif_next); + g->g_ifs[mif->mif_index] = NULL; RW_UNLOCK(g, g_lock); TAILQ_FOREACH_SAFE(ifev, &mif->mif_evlist, ifev_next, ifev2) { @@ -1086,6 +1113,7 @@ mdns_destroy(&mif->mif_stack); cache_destroy(&mif->mif_cache); dbr_destroy(&mif->mif_dbr); + queries_destroy(&mif->mif_q); logger(LOG_NOTICE, "Removed interface %s", mif->mif_ifnam); if_release(mif, 1); @@ -1097,7 +1125,7 @@ { struct md_if *mif; - TAILQ_FOREACH(mif, &g->g_ifs, mif_next) { + TAILQ_FOREACH(mif, &g->g_ifs_head, mif_next) { if (idx == mif->mif_index) return (mif); } @@ -1231,20 +1259,26 @@ usage(char *exec) { - printf("usage %s [-h] [-d] [-f config]\n", exec); + printf("usage %s [-h] [-d] [-f config] " + "[-u username] [-g group]\n", exec); } int main(int argc, char *argv[]) { int error, ch, nodaemon = 0; - char *ifnam, *cfgfile = NULL; + char *ifnam, *cfgfile = NULL, *servpath = NULL; + char *username = NULL, *group = NULL; struct ifaddrs *ifap, *ifa; struct md_if *mif, *mif2; + struct passwd *pw; + struct group *grp; + ev_arg eva; + uid_t uid, euid; + gid_t gid, egid; struct md_glob glob; - ev_arg eva; - while ((ch = getopt(argc, argv, "h?df")) != -1) { + while ((ch = getopt(argc, argv, "h?df:u:g:")) != -1) { switch (ch) { case '?': case 'h': @@ -1255,6 +1289,12 @@ break; case 'f': cfgfile = argv[optind - 1]; + case 'u': + username = argv[optind - 1]; + break; + case 'g': + group = argv[optind - 1]; + break; default: usage(argv[0]); exit(EXIT_FAILURE); @@ -1264,7 +1304,7 @@ bzero(&glob, sizeof(struct md_glob)); RW_INIT(&glob, g_lock, NULL); MTX_INIT(&glob, g_bp_mtx, NULL); - TAILQ_INIT(&glob.g_ifs); + TAILQ_INIT(&glob.g_ifs_head); glob.g_cfgfile = cfgfile != NULL ? cfgfile : strdup(DEFAULT_CFGFILE); /* Initialize logging */ @@ -1332,13 +1372,46 @@ tmr_start(&glob, 1000, evh_cacheclean, &glob, 0); + uid = getuid(); + euid = geteuid(); + setuid(euid); + + gid = getgid(); + egid = getegid(); + setgid(egid); + + /* Open UNIX pipe to clients */ + error = csrv_open(&glob.g_cs, &glob, servpath != NULL ? + servpath : DEFAULT_CLISRV_PIPE); + if (error == 0) + glob.g_flags |= GLOB_CSOPEN; + + if (username != NULL) { + pw = getpwnam(username); + if (pw != NULL) + uid = pw->pw_uid; + } + if (group != NULL) { + grp = getgrnam(group); + if (grp != NULL) + gid = grp->gr_gid; + } + + /* Drop privileges */ + setuid(uid); + setgid(gid); + /* Launch the event dispatcher */ error = event_dispatch(glob.g_evl, glob.g_wq); - TAILQ_FOREACH_SAFE(mif, &glob.g_ifs, mif_next, mif2) { + + TAILQ_FOREACH_SAFE(mif, &glob.g_ifs_head, mif_next, mif2) { if_del(&glob, mif); } + if (glob.g_flags & GLOB_CSOPEN) + csrv_close(&glob.g_cs); + wq_destroy(glob.g_wq); event_destroy(glob.g_evl); mdns_bufpool_destroy(glob.g_bp);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200707211928.l6LJSRjw011392>