PERFORCE change 123861 for review
Fredrik Lindberg
fli at FreeBSD.org
Sat Jul 21 19:28:28 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=123861
Change 123861 by fli at 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);
More information about the p4-projects
mailing list