X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fidmapd%2Fidmapd.c;h=9d66225e01d7642aa40223bbacccc0a4a31c8292;hp=19bf7a601b5ba562258420facc9fec2083047d5e;hb=96892b29a50af1055bfc3ca74930e9782ead6c71;hpb=bdfe0d28ee4c23dec311423a34b2a3ec65b5b318 diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c index 19bf7a6..9d66225 100644 --- a/utils/idmapd/idmapd.c +++ b/utils/idmapd/idmapd.c @@ -55,7 +55,6 @@ #include #include #include -#include #include #include #include @@ -66,7 +65,8 @@ #include "config.h" #endif /* HAVE_CONFIG_H */ -#include "cfg.h" +#include "xlog.h" +#include "conffile.h" #include "queue.h" #include "nfslib.h" @@ -117,8 +117,24 @@ struct idmap_client { 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}, +{ + .ic_which = IC_IDNAME, + .ic_clid = "", + .ic_id = "Server", + .ic_path = IC_IDNAME_CHAN, + .ic_fd = -1, + .ic_dirfd = -1, + .ic_scanned = 0 +}, +{ + .ic_which = IC_NAMEID, + .ic_clid = "", + .ic_id = "Server", + .ic_path = IC_NAMEID_CHAN, + .ic_fd = -1, + .ic_dirfd = -1, + .ic_scanned = 0 +}, }; TAILQ_HEAD(idmap_clientq, idmap_client); @@ -129,7 +145,6 @@ static void svrreopen(int, short, void *); static int nfsopen(struct idmap_client *); static void nfscb(int, short, void *); static void nfsdcb(int, short, void *); -static int validateascii(char *, u_int32_t); static int addfield(char **, ssize_t *, char *); static int getfield(char **, char *, size_t); @@ -137,15 +152,13 @@ static void imconv(struct idmap_client *, struct idmap_msg *); static void idtonameres(struct idmap_msg *); static void nametoidres(struct idmap_msg *); -static int nfsdopen(); +static int nfsdopen(void); static int nfsdopenone(struct idmap_client *); +static void nfsdreopen_one(struct idmap_client *); static void nfsdreopen(void); -size_t strlcat(char *, const char *, size_t); -size_t strlcpy(char *, const char *, size_t); -ssize_t atomicio(ssize_t (*)(), int, void *, size_t); void mydaemon(int, int); -void release_parent(); +void release_parent(void); static int verbose = 0; #define DEFAULT_IDMAP_CACHE_EXPIRY 600 /* seconds */ @@ -155,7 +168,7 @@ static char *nobodyuser, *nobodygroup; static uid_t nobodyuid; static gid_t nobodygid; -/* Used by cfg.c */ +/* Used by conffile.c in libnfs.a */ char *conf_path; static int @@ -168,7 +181,10 @@ flush_nfsd_cache(char *path, time_t now) fd = open(path, O_RDWR); if (fd == -1) return -1; - write(fd, stime, strlen(stime)); + if (write(fd, stime, strlen(stime)) != (ssize_t)strlen(stime)) { + errx(1, "Flushing nfsd cache failed: errno %d (%s)", + errno, strerror(errno)); + } close(fd); return 0; } @@ -186,71 +202,6 @@ flush_nfsd_idmap_cache(void) return ret; } -static void -msg_format(char *rtnbuff, int rtnbuffsize, int errval, - const char *fmt, va_list args) -{ - char buff[1024]; - int n; - - vsnprintf(buff, sizeof(buff), fmt, args); - - if ((n = strlen(buff)) > 0 && buff[n-1] == '\n') - buff[--n] = '\0'; - - snprintf(rtnbuff, rtnbuffsize, "%s: %s", buff, strerror(errval)); -} - -static void -idmapd_warn(const char *fmt, ...) -{ - int errval = errno; /* save this! */ - char buff[1024]; - va_list args; - - va_start(args, fmt); - msg_format(buff, sizeof(buff), errval, fmt, args); - va_end(args); - - syslog(LOG_WARNING, "%s", buff); -} - -static void -idmapd_warnx(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vsyslog(LOG_WARNING, fmt, args); - va_end(args); -} - -static void -idmapd_err(int eval, const char *fmt, ...) -{ - int errval = errno; /* save this! */ - char buff[1024]; - va_list args; - - va_start(args, fmt); - msg_format(buff, sizeof(buff), errval, fmt, args); - va_end(args); - - syslog(LOG_ERR, "%s", buff); - exit(eval); -} - -static void -idmapd_errx(int eval, const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - vsyslog(LOG_ERR, fmt, args); - va_end(args); - exit(eval); -} - int main(int argc, char **argv) { @@ -275,7 +226,7 @@ main(int argc, char **argv) progname++; else progname = argv[0]; - openlog(progname, LOG_PID, LOG_DAEMON); + xlog_open(progname); #define GETOPTSTR "vfd:p:U:G:c:CS" opterr=0; /* Turn off error messages */ @@ -346,7 +297,7 @@ main(int argc, char **argv) nobodygid = gr->gr_gid; #ifdef HAVE_NFS4_SET_DEBUG - nfs4_set_debug(verbose, idmapd_warnx); + nfs4_set_debug(verbose, xlog_warn); #endif if (conf_path == NULL) conf_path = _PATH_IDMAPDCONF; @@ -359,15 +310,14 @@ main(int argc, char **argv) event_init(); if (verbose > 0) - idmapd_warnx("Expiration time is %d seconds.", + xlog_warn("Expiration time is %d seconds.", cache_entry_expiration); if (serverstart) { nfsdret = nfsdopen(); if (nfsdret == 0) { ret = flush_nfsd_idmap_cache(); if (ret) - idmapd_errx(1, - "main: Failed to flush nfsd idmap cache\n"); + xlog_err("main: Failed to flush nfsd idmap cache\n: %s", strerror(errno)); } } @@ -382,7 +332,7 @@ main(int argc, char **argv) char timeout_buf[12]; if ((timeout_fd = open(CLIENT_CACHE_TIMEOUT_FILE, O_RDWR)) == -1) { - idmapd_warnx("Unable to open '%s' to set " + xlog_warn("Unable to open '%s' to set " "client cache expiration time " "to %d seconds\n", CLIENT_CACHE_TIMEOUT_FILE, @@ -391,7 +341,7 @@ main(int argc, char **argv) len = snprintf(timeout_buf, sizeof(timeout_buf), "%d", cache_entry_expiration); if ((write(timeout_fd, timeout_buf, len)) != len) - idmapd_warnx("Error writing '%s' to " + xlog_warn("Error writing '%s' to " "'%s' to set client " "cache expiration time\n", timeout_buf, @@ -401,15 +351,17 @@ main(int argc, char **argv) } if ((fd = open(pipefsdir, O_RDONLY)) == -1) - idmapd_err(1, "main: open(%s)", pipefsdir); + xlog_err("main: open(%s): %s", pipefsdir, strerror(errno)); if (fcntl(fd, F_SETSIG, SIGUSR1) == -1) - idmapd_err(1, "main: fcntl(%s)", pipefsdir); + xlog_err("main: fcntl(%s): %s", pipefsdir, strerror(errno)); if (fcntl(fd, F_NOTIFY, - DN_CREATE | DN_DELETE | DN_MODIFY | DN_MULTISHOT) == -1) - idmapd_err(1, "main: fcntl(%s)", pipefsdir); - + DN_CREATE | DN_DELETE | DN_MODIFY | DN_MULTISHOT) == -1) { + xlog_err("main: fcntl(%s): %s", pipefsdir, strerror(errno)); + if (errno == EINVAL) + xlog_err("main: Possibly no Dnotify support in kernel."); + } TAILQ_INIT(&icq); /* These events are persistent */ @@ -428,29 +380,29 @@ main(int argc, char **argv) } if (nfsdret != 0 && fd == 0) - idmapd_errx(1, "main: Neither NFS client nor NFSd found"); + xlog_err("main: Neither NFS client nor NFSd found"); release_parent(); if (event_dispatch() < 0) - idmapd_errx(1, "main: event_dispatch returns errno %d (%s)", + xlog_err("main: event_dispatch returns errno %d (%s)", errno, strerror(errno)); /* NOTREACHED */ return 1; } static void -dirscancb(int fd, short which, void *data) +dirscancb(int UNUSED(fd), short UNUSED(which), void *data) { int nent, i; struct dirent **ents; - struct idmap_client *ic; + struct idmap_client *ic, *nextic; char path[PATH_MAX]; struct idmap_clientq *icq = data; nent = scandir(pipefsdir, &ents, NULL, alphasort); if (nent == -1) { - idmapd_warn("dirscancb: scandir(%s)", pipefsdir); + xlog_warn("dirscancb: scandir(%s): %s", pipefsdir, strerror(errno)); return; } @@ -464,7 +416,7 @@ dirscancb(int fd, short which, void *data) goto next; if ((ic = calloc(1, sizeof(*ic))) == NULL) - return; + goto out; strlcpy(ic->ic_clid, ents[i]->d_name + 4, sizeof(ic->ic_clid)); path[0] = '\0'; @@ -472,21 +424,21 @@ dirscancb(int fd, short which, void *data) pipefsdir, ents[i]->d_name); if ((ic->ic_dirfd = open(path, O_RDONLY, 0)) == -1) { - idmapd_warn("dirscancb: open(%s)", path); + xlog_warn("dirscancb: open(%s): %s", path, strerror(errno)); free(ic); - return; + goto out; } strlcat(path, "/idmap", sizeof(path)); strlcpy(ic->ic_path, path, sizeof(ic->ic_path)); if (verbose > 0) - idmapd_warnx("New client: %s", ic->ic_clid); + xlog_warn("New client: %s", ic->ic_clid); if (nfsopen(ic) == -1) { close(ic->ic_dirfd); free(ic); - return; + goto out; } ic->ic_id = "Client"; @@ -498,31 +450,39 @@ dirscancb(int fd, short which, void *data) } } - TAILQ_FOREACH(ic, icq, ic_next) { + ic = TAILQ_FIRST(icq); + while(ic != NULL) { + nextic=TAILQ_NEXT(ic, ic_next); if (!ic->ic_scanned) { event_del(&ic->ic_event); close(ic->ic_fd); close(ic->ic_dirfd); TAILQ_REMOVE(icq, ic, ic_next); if (verbose > 0) { - idmapd_warnx("Stale client: %s", ic->ic_clid); - idmapd_warnx("\t-> closed %s", ic->ic_path); + xlog_warn("Stale client: %s", ic->ic_clid); + xlog_warn("\t-> closed %s", ic->ic_path); } free(ic); } else ic->ic_scanned = 0; + ic = nextic; } + +out: + for (i = 0; i < nent; i++) + free(ents[i]); + free(ents); return; } static void -svrreopen(int fd, short which, void *data) +svrreopen(int UNUSED(fd), short UNUSED(which), void *UNUSED(data)) { nfsdreopen(); } static void -clntscancb(int fd, short which, void *data) +clntscancb(int UNUSED(fd), short UNUSED(which), void *data) { struct idmap_clientq *icq = data; struct idmap_client *ic; @@ -536,7 +496,7 @@ clntscancb(int fd, short which, void *data) } static void -nfsdcb(int fd, short which, void *data) +nfsdcb(int UNUSED(fd), short which, void *data) { struct idmap_client *ic = data; struct idmap_msg im; @@ -551,10 +511,11 @@ nfsdcb(int fd, short which, void *data) goto out; if ((len = read(ic->ic_fd, buf, sizeof(buf))) <= 0) { - idmapd_warnx("nfsdcb: read(%s) failed: errno %d (%s)", + xlog_warn("nfsdcb: read(%s) failed: errno %d (%s)", ic->ic_path, len?errno:0, len?strerror(errno):"End of File"); - goto out; + nfsdreopen_one(ic); + return; } /* Get rid of newline and terminate buffer*/ @@ -565,15 +526,15 @@ nfsdcb(int fd, short which, void *data) /* Authentication name -- ignored for now*/ if (getfield(&bp, authbuf, sizeof(authbuf)) == -1) { - idmapd_warnx("nfsdcb: bad authentication name in upcall\n"); - return; + xlog_warn("nfsdcb: bad authentication name in upcall\n"); + goto out; } if (getfield(&bp, typebuf, sizeof(typebuf)) == -1) { - idmapd_warnx("nfsdcb: bad type in upcall\n"); - return; + xlog_warn("nfsdcb: bad type in upcall\n"); + goto out; } if (verbose > 0) - idmapd_warnx("nfsdcb: authbuf=%s authtype=%s", + xlog_warn("nfsdcb: authbuf=%s authtype=%s", authbuf, typebuf); im.im_type = strcmp(typebuf, "user") == 0 ? @@ -583,27 +544,27 @@ nfsdcb(int fd, short which, void *data) case IC_NAMEID: im.im_conv = IDMAP_CONV_NAMETOID; if (getfield(&bp, im.im_name, sizeof(im.im_name)) == -1) { - idmapd_warnx("nfsdcb: bad name in upcall\n"); - return; + xlog_warn("nfsdcb: bad name in upcall\n"); + goto out; } break; case IC_IDNAME: im.im_conv = IDMAP_CONV_IDTONAME; if (getfield(&bp, buf1, sizeof(buf1)) == -1) { - idmapd_warnx("nfsdcb: bad id in upcall\n"); - return; + xlog_warn("nfsdcb: bad id in upcall\n"); + goto out; } tmp = strtoul(buf1, (char **)NULL, 10); im.im_id = (u_int32_t)tmp; if ((tmp == ULONG_MAX && errno == ERANGE) || (unsigned long)im.im_id != tmp) { - idmapd_warnx("nfsdcb: id '%s' too big!\n", buf1); - return; + xlog_warn("nfsdcb: id '%s' too big!\n", buf1); + goto out; } break; default: - idmapd_warnx("nfsdcb: Unknown which type %d", ic->ic_which); - return; + xlog_warn("nfsdcb: Unknown which type %d", ic->ic_which); + goto out; } imconv(ic, &im); @@ -663,14 +624,14 @@ nfsdcb(int fd, short which, void *data) break; default: - idmapd_warnx("nfsdcb: Unknown which type %d", ic->ic_which); - return; + xlog_warn("nfsdcb: Unknown which type %d", ic->ic_which); + goto out; } bsiz = sizeof(buf) - bsiz; - if (atomicio(write, ic->ic_fd, buf, bsiz) != bsiz) - idmapd_warnx("nfsdcb: write(%s) failed: errno %d (%s)", + if (atomicio((void*)write, ic->ic_fd, buf, bsiz) != bsiz) + xlog_warn("nfsdcb: write(%s) failed: errno %d (%s)", ic->ic_path, errno, strerror(errno)); out: @@ -680,29 +641,31 @@ out: static void imconv(struct idmap_client *ic, struct idmap_msg *im) { + u_int32_t len; + switch (im->im_conv) { case IDMAP_CONV_IDTONAME: idtonameres(im); if (verbose > 1) - idmapd_warnx("%s %s: (%s) id \"%d\" -> name \"%s\"", + xlog_warn("%s %s: (%s) id \"%d\" -> name \"%s\"", ic->ic_id, ic->ic_clid, im->im_type == IDMAP_TYPE_USER ? "user" : "group", im->im_id, im->im_name); break; case IDMAP_CONV_NAMETOID: - if (validateascii(im->im_name, sizeof(im->im_name)) == -1) { - im->im_status |= IDMAP_STATUS_INVALIDMSG; + len = strnlen(im->im_name, IDMAP_NAMESZ - 1); + /* Check for NULL termination just to be careful */ + if (im->im_name[len+1] != '\0') return; - } nametoidres(im); if (verbose > 1) - idmapd_warnx("%s %s: (%s) name \"%s\" -> id \"%d\"", + xlog_warn("%s %s: (%s) name \"%s\" -> id \"%d\"", ic->ic_id, ic->ic_clid, im->im_type == IDMAP_TYPE_USER ? "user" : "group", im->im_name, im->im_id); break; default: - idmapd_warnx("imconv: Invalid conversion type (%d) in message", + xlog_warn("imconv: Invalid conversion type (%d) in message", im->im_conv); im->im_status |= IDMAP_STATUS_INVALIDMSG; break; @@ -710,7 +673,7 @@ imconv(struct idmap_client *ic, struct idmap_msg *im) } static void -nfscb(int fd, short which, void *data) +nfscb(int UNUSED(fd), short which, void *data) { struct idmap_client *ic = data; struct idmap_msg im; @@ -720,7 +683,7 @@ nfscb(int fd, short which, void *data) if (atomicio(read, ic->ic_fd, &im, sizeof(im)) != sizeof(im)) { if (verbose > 0) - idmapd_warn("nfscb: read(%s)", ic->ic_path); + xlog_warn("nfscb: read(%s): %s", ic->ic_path, strerror(errno)); if (errno == EPIPE) return; goto out; @@ -735,8 +698,8 @@ nfscb(int fd, short which, void *data) if (im.im_status == IDMAP_STATUS_LOOKUPFAIL) im.im_status = IDMAP_STATUS_SUCCESS; - if (atomicio(write, ic->ic_fd, &im, sizeof(im)) != sizeof(im)) - idmapd_warn("nfscb: write(%s)", ic->ic_path); + if (atomicio((void*)write, ic->ic_fd, &im, sizeof(im)) != sizeof(im)) + xlog_warn("nfscb: write(%s): %s", ic->ic_path, strerror(errno)); out: event_add(&ic->ic_event, NULL); } @@ -747,7 +710,7 @@ nfsdreopen_one(struct idmap_client *ic) int fd; if (verbose > 0) - idmapd_warnx("ReOpening %s", ic->ic_path); + xlog_warn("ReOpening %s", ic->ic_path); if ((fd = open(ic->ic_path, O_RDWR, 0)) != -1) { if ((ic->ic_event.ev_flags & EVLIST_INIT)) @@ -759,7 +722,7 @@ nfsdreopen_one(struct idmap_client *ic) event_set(&ic->ic_event, ic->ic_fd, EV_READ, nfsdcb, ic); event_add(&ic->ic_event, NULL); } else { - idmapd_warnx("nfsdreopen: Opening '%s' failed: errno %d (%s)", + xlog_warn("nfsdreopen: Opening '%s' failed: errno %d (%s)", ic->ic_path, errno, strerror(errno)); } } @@ -773,7 +736,7 @@ nfsdreopen() } static int -nfsdopen() +nfsdopen(void) { return ((nfsdopenone(&nfsd_ic[IC_NAMEID]) == 0 && nfsdopenone(&nfsd_ic[IC_IDNAME]) == 0) ? 0 : -1); @@ -784,7 +747,7 @@ nfsdopenone(struct idmap_client *ic) { if ((ic->ic_fd = open(ic->ic_path, O_RDWR, 0)) == -1) { if (verbose > 0) - idmapd_warnx("nfsdopenone: Opening %s failed: " + xlog_warn("nfsdopenone: Opening %s failed: " "errno %d (%s)", ic->ic_path, errno, strerror(errno)); return (-1); @@ -794,7 +757,7 @@ nfsdopenone(struct idmap_client *ic) event_add(&ic->ic_event, NULL); if (verbose > 0) - idmapd_warnx("Opened %s", ic->ic_path); + xlog_warn("Opened %s", ic->ic_path); return (0); } @@ -810,16 +773,16 @@ nfsopen(struct idmap_client *ic) DN_CREATE | DN_DELETE | DN_MULTISHOT); break; default: - idmapd_warn("nfsopen: open(%s)", ic->ic_path); + xlog_warn("nfsopen: open(%s): %s", ic->ic_path, strerror(errno)); return (-1); } } else { event_set(&ic->ic_event, ic->ic_fd, EV_READ, nfscb, ic); event_add(&ic->ic_event, NULL); - fcntl(ic->ic_dirfd, F_SETSIG, 0); fcntl(ic->ic_dirfd, F_NOTIFY, 0); + fcntl(ic->ic_dirfd, F_SETSIG, 0); if (verbose > 0) - idmapd_warnx("Opened %s", ic->ic_path); + xlog_warn("Opened %s", ic->ic_path); } return (0); @@ -892,25 +855,6 @@ nametoidres(struct idmap_msg *im) } } -static int -validateascii(char *string, u_int32_t len) -{ - int i; - - for (i = 0; i < len; i++) { - if (string[i] == '\0') - break; - - if (string[i] & 0x80) - return (-1); - } - - if (string[i] != '\0') - return (-1); - - return (i + 1); -} - static int addfield(char **bpp, ssize_t *bsizp, char *fld) { @@ -951,7 +895,7 @@ static int getfield(char **bpp, char *fld, size_t fldsz) { char *bp; - u_int val, n; + int val, n; while ((bp = strsep(bpp, " ")) != NULL && bp[0] == '\0') ; @@ -963,9 +907,9 @@ getfield(char **bpp, char *fld, size_t fldsz) if (*bp == '\\') { if ((n = sscanf(bp, "\\%03o", &val)) != 1) return (-1); - if (val > (char)-1) + if (val > UCHAR_MAX) return (-1); - *fld++ = (char)val; + *fld++ = val; bp += 4; } else { *fld++ = *bp; @@ -1030,20 +974,26 @@ mydaemon(int nochdir, int noclose) dup2(tempfd, 0); dup2(tempfd, 1); dup2(tempfd, 2); - closeall(3); - } else - closeall(0); + close(tempfd); + } else { + err(1, "mydaemon: can't open /dev/null: errno %d", + errno); + exit(1); + } } return; } void -release_parent() +release_parent(void) { int status; if (pipefds[1] > 0) { - write(pipefds[1], &status, 1); + if (write(pipefds[1], &status, 1) != 1) { + err(1, "Writing to parent pipe failed: errno %d (%s)\n", + errno, strerror(errno)); + } close(pipefds[1]); pipefds[1] = -1; }