Skip site navigation (1)Skip section navigation (2)
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>