]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/idmapd/idmapd.c
idmapd update from Steve Dickson
[nfs-utils.git] / utils / idmapd / idmapd.c
index 02604df16d1a6e4bd47d45ff47e45e30dd43774a..4c1327351025af2895e6b746143e829f4d8096f5 100644 (file)
                (w) = p;                        \
 } while (0)
 
-#define IC_IDNAME 1
-#define IC_NAMEID 2
+#define IC_IDNAME 0
+#define IC_IDNAME_CHAN  NFSD_DIR "/nfs4.idtoname/channel"
+#define IC_IDNAME_FLUSH NFSD_DIR "/nfs4.idtoname/flush"
+
+#define IC_NAMEID 1
+#define IC_NAMEID_CHAN  NFSD_DIR "/nfs4.nametoid/channel"
+#define IC_NAMEID_FLUSH NFSD_DIR "/nfs4.nametoid/flush"
+
 struct idmap_client {
-       int                        ic_fd;
-       int                        ic_dirfd;
+       short                      ic_which;
        char                       ic_clid[30];
+       char                      *ic_id;
        char                       ic_path[PATH_MAX];
+       int                        ic_fd;
+       int                        ic_dirfd;
        int                        ic_scanned;
        struct event               ic_event;
-       char                      *ic_id;
-       short                      ic_which;
        TAILQ_ENTRY(idmap_client)  ic_next;
 };
+static struct idmap_client nfsd_ic[2] = {
+{IC_IDNAME, "Server", "", IC_IDNAME_CHAN, -1, -1, 0},
+{IC_NAMEID, "Server", "", IC_NAMEID_CHAN, -1, -1, 0},
+};
 
 TAILQ_HEAD(idmap_clientq, idmap_client);
 
@@ -122,7 +132,7 @@ static void idtonameres(struct idmap_msg *);
 static void nametoidres(struct idmap_msg *);
 
 static int nfsdopen(char *);
-static int nfsdopenone(struct idmap_client *, short, char *);
+static int nfsdopenone(struct idmap_client *);
 static void nfsdreopen(void);
 
 size_t  strlcat(char *, const char *, size_t);
@@ -136,11 +146,38 @@ static char pipefsdir[PATH_MAX];
 static char *nobodyuser, *nobodygroup;
 static uid_t nobodyuid;
 static gid_t nobodygid;
-static struct idmap_client nfsd_ic[2];
 
 /* Used by cfg.c */
 char *conf_path;
 
+static int
+flush_nfsd_cache(char *path, time_t now)
+{
+       int fd;
+       char stime[20];
+
+       sprintf(stime, "%ld\n", now);
+       fd = open(path, O_RDWR);
+       if (fd == -1)
+               return -1;
+       write(fd, stime, strlen(stime));
+       close(fd);
+       return 0;
+}
+
+static int
+flush_nfsd_idmap_cache(void)
+{
+       time_t now = time(NULL);
+       int ret;
+
+       ret = flush_nfsd_cache(IC_IDNAME_FLUSH, now);
+       if (ret)
+               return ret;
+       ret = flush_nfsd_cache(IC_NAMEID_FLUSH, now);
+       return ret;
+}
+
 int
 main(int argc, char **argv)
 {
@@ -153,6 +190,7 @@ main(int argc, char **argv)
        struct stat sb;
        char *xpipefsdir = NULL;
        int serverstart = 1, clientstart = 1;
+       int ret;
 
        conf_path = _PATH_IDMAPDCONF;
        nobodyuser = NFS4NOBODY_USER;
@@ -230,8 +268,14 @@ main(int argc, char **argv)
 
        event_init();
 
-       if (serverstart)
+       if (serverstart) {
                nfsdret = nfsdopen(NFSD_DIR);
+               if (nfsdret == 0) {
+                       ret = flush_nfsd_idmap_cache();
+                       if (ret)
+                               errx(1, "Failed to flush nfsd idmap cache\n");
+               }
+       }
 
        if (clientstart) {
                struct timeval now = {
@@ -561,23 +605,22 @@ nfsdreopen_one(struct idmap_client *ic)
 
        if (verbose > 0)
                warnx("ReOpening %s", ic->ic_path);
+
        if ((fd = open(ic->ic_path, O_RDWR, 0)) != -1) {
                if (ic->ic_fd != -1)
                        close(ic->ic_fd);
+               if ((ic->ic_event.ev_flags & EVLIST_INIT))
+                       event_del(&ic->ic_event);
+
                ic->ic_event.ev_fd = ic->ic_fd = fd;
-               if ((ic->ic_event.ev_flags & EVLIST_INIT) == 0) {
-                       event_set(&ic->ic_event, ic->ic_fd, EV_READ, nfsdcb, ic);
-                       event_add(&ic->ic_event, NULL);
-               }
+               event_set(&ic->ic_event, ic->ic_fd, EV_READ, nfsdcb, ic);
+               event_add(&ic->ic_event, NULL);
        } else {
                warnx("nfsdreopen: Opening '%s' failed: errno %d (%s)",
                        ic->ic_path, errno, strerror(errno));
        }
 }
 
-/*
- * Note: nfsdreopen assumes nfsdopen has already been called
- */
 static void
 nfsdreopen()
 {
@@ -589,18 +632,13 @@ nfsdreopen()
 static int
 nfsdopen(char *path)
 {
-       return ((nfsdopenone(&nfsd_ic[0], IC_NAMEID, path) == 0 &&
-                   nfsdopenone(&nfsd_ic[1], IC_IDNAME, path) == 0) ? 0 : -1);
+       return ((nfsdopenone(&nfsd_ic[IC_NAMEID]) == 0 &&
+                   nfsdopenone(&nfsd_ic[IC_IDNAME]) == 0) ? 0 : -1);
 }
 
 static int
-nfsdopenone(struct idmap_client *ic, short which, char *path)
+nfsdopenone(struct idmap_client *ic)
 {
-       char *whichstr;
-
-       whichstr = which == IC_IDNAME ? "idtoname" : "nametoid";
-       snprintf(ic->ic_path, sizeof(ic->ic_path),
-               "%s/nfs4.%s/channel", path, whichstr);
        if ((ic->ic_fd = open(ic->ic_path, O_RDWR, 0)) == -1) {
                if (verbose > 0)
                        warnx("Opening %s failed: errno %d (%s)",
@@ -611,10 +649,6 @@ nfsdopenone(struct idmap_client *ic, short which, char *path)
        event_set(&ic->ic_event, ic->ic_fd, EV_READ, nfsdcb, ic);
        event_add(&ic->ic_event, NULL);
 
-       ic->ic_which = which;
-       ic->ic_id = "Server";
-       strlcpy(ic->ic_clid, "Server", strlen("Server"));
-
        if (verbose > 0)
                warnx("Opened %s", ic->ic_path);
 
@@ -681,9 +715,7 @@ idtonameres(struct idmap_msg *im)
                                        sizeof(im->im_name));
                break;
        }
-       /* XXX Hack? would rather return failure instead of writing nobody
-        * as above, but kernel seems not to deal well with that as of
-        * 2.6.8-rc3. */
+       /* XXX Hack? */
        im->im_status = IDMAP_STATUS_SUCCESS;
 }
 
@@ -692,6 +724,14 @@ nametoidres(struct idmap_msg *im)
 {
        int ret = 0;
 
+       /* XXX: nobody fallbacks shouldn't always happen:
+        *      server id -> name should be OK
+        *      client name -> id should be OK
+        * but not otherwise */
+       /* XXX: move nobody stuff to library calls
+        * (nfs4_get_nobody_user(domain), nfs4_get_nobody_group(domain)) */
+       /* XXX: should make this call higher up in the call chain (so we'd
+        * have a chance on looking up server/whatever. */
        switch (im->im_type) {
        case IDMAP_TYPE_USER:
                ret = nfs4_name_to_uid(im->im_name, &im->im_id);
@@ -704,9 +744,7 @@ nametoidres(struct idmap_msg *im)
                        im->im_id = nobodygid;
                break;
        }
-       /* XXX Hack? would rather return failure instead of writing nobody
-        * as above, but kernel seems not to deal well with that as of
-        * 2.6.8-rc3. */
+       /* XXX? */
        im->im_status = IDMAP_STATUS_SUCCESS;
 }
 
@@ -809,7 +847,7 @@ int pipefds[2] = { -1, -1};
 void
 mydaemon(int nochdir, int noclose)
 {
-       int pid, status, tempfd, fdmax, filedes;
+       int pid, status, tempfd;
 
        if (pipe(pipefds) < 0)
                err(1, "mydaemon: pipe() failed: errno %d (%s)\n", errno, strerror(errno));
@@ -842,13 +880,10 @@ mydaemon(int nochdir, int noclose)
 
        if (noclose == 0) {
                tempfd = open("/dev/null", O_RDWR);
-               close(0); dup2(tempfd, 0);
-               close(1); dup2(tempfd, 1);
-               close(2); dup2(tempfd, 2);
-               fdmax = sysconf (_SC_OPEN_MAX);
-               for (filedes = 3; filedes < fdmax; filedes++)
-                       if (filedes != pipefds[1])
-                               close (filedes);
+               dup2(tempfd, 0);
+               dup2(tempfd, 1);
+               dup2(tempfd, 2);
+               closeall(3);
        }
 
        return;