#include "rpcmisc.h"
#include "misc.h"
+#include "nsm.h"
#include "statd.h"
#include "notlist.h"
#include "ha-callout.h"
notify_list * rtnl = NULL; /* Run-time notify list. */
-#define LINELEN (4*(8+1)+SM_PRIV_SIZE*2+1)
-
/*
* Reject requests from non-loopback addresses in order
* to prevent attack described in CERT CA-99.05.
char *mon_name = argp->mon_id.mon_name,
*my_name = argp->mon_id.my_id.my_name;
struct my_id *id = &argp->mon_id.my_id;
- char *path;
char *cp;
- int fd;
notify_list *clnt;
- struct in_addr my_addr;
+ struct sockaddr_in my_addr = {
+ .sin_family = AF_INET,
+ .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
+ };
char *dnsname;
struct hostent *hostinfo = NULL;
*/
if (!caller_is_localhost(rqstp))
goto failure;
- my_addr.s_addr = htonl(INADDR_LOOPBACK);
/* 2. Reject any registrations for non-lockd services.
*
goto failure;
}
- NL_ADDR(clnt) = my_addr;
+ NL_ADDR(clnt) = my_addr.sin_addr;
NL_MY_PROG(clnt) = id->my_prog;
NL_MY_VERS(clnt) = id->my_vers;
NL_MY_PROC(clnt) = id->my_proc;
/*
* Now, Create file on stable storage for host.
*/
-
- path=xmalloc(strlen(SM_DIR)+strlen(dnsname)+2);
- sprintf(path, "%s/%s", SM_DIR, dnsname);
- if ((fd = open(path, O_WRONLY|O_SYNC|O_CREAT|O_APPEND,
- S_IRUSR|S_IWUSR)) < 0) {
- /* Didn't fly. We won't monitor. */
- xlog(L_ERROR, "creat(%s) failed: %m", path);
+ if (!nsm_insert_monitored_host(dnsname,
+ (struct sockaddr *)(char *)&my_addr, argp)) {
nlist_free(NULL, clnt);
- free(path);
goto failure;
}
- {
- char buf[LINELEN + 1 + SM_MAXSTRLEN*2 + 4];
- char *e;
- int i;
- e = buf + sprintf(buf, "%08x %08x %08x %08x ",
- my_addr.s_addr, id->my_prog,
- id->my_vers, id->my_proc);
- for (i=0; i<SM_PRIV_SIZE; i++)
- e += sprintf(e, "%02x", 0xff & (argp->priv[i]));
- if (e+1-buf != LINELEN) abort();
- e += sprintf(e, " %s %s\n", mon_name, my_name);
- if (write(fd, buf, e-buf) != (e-buf)) {
- xlog_warn("writing to %s failed: errno %d (%s)",
- path, errno, strerror(errno));
- }
- }
- free(path);
/* PRC: do the HA callout: */
ha_callout("add-client", mon_name, my_name, -1);
nlist_insert(&rtnl, clnt);
- close(fd);
xlog(D_GENERAL, "MONITORING %s for %s", mon_name, my_name);
success:
result.res_stat = STAT_SUCC;
return (&result);
}
-void load_state(void)
+static unsigned int
+load_one_host(const char *hostname, const struct sockaddr *sap,
+ const struct mon *m,
+ __attribute__ ((unused)) const time_t timestamp)
{
- DIR *d;
- struct dirent *de;
- char buf[LINELEN + 1 + SM_MAXSTRLEN + 2];
-
- d = opendir(SM_DIR);
- if (!d)
- return;
- while ((de = readdir(d))) {
- char *path;
- FILE *f;
- int p;
-
- if (de->d_name[0] == '.')
- continue;
- path = xmalloc(strlen(SM_DIR)+strlen(de->d_name)+2);
- sprintf(path, "%s/%s", SM_DIR, de->d_name);
- f = fopen(path, "r");
- free(path);
- if (f == NULL)
- continue;
- while (fgets(buf, sizeof(buf), f) != NULL) {
- int addr, proc, prog, vers;
- char priv[SM_PRIV_SIZE];
- char *monname, *myname;
- char *b;
- int i;
- notify_list *clnt;
-
- buf[sizeof(buf)-1] = 0;
- b = strchr(buf, '\n');
- if (b) *b = 0;
- sscanf(buf, "%x %x %x %x ",
- &addr, &prog, &vers, &proc);
- b = buf+36;
- for (i=0; i<SM_PRIV_SIZE; i++) {
- sscanf(b, "%2x", &p);
- priv[i] = p;
- b += 2;
- }
- b++;
- monname = b;
- while (*b && *b != ' ') b++;
- if (*b) *b++ = '\0';
- while (*b == ' ') b++;
- myname = b;
- clnt = nlist_new(myname, monname, 0);
- if (!clnt)
- break;
- NL_ADDR(clnt).s_addr = addr;
- NL_MY_PROG(clnt) = prog;
- NL_MY_VERS(clnt) = vers;
- NL_MY_PROC(clnt) = proc;
- clnt->dns_name = xstrdup(de->d_name);
- memcpy(NL_PRIV(clnt), priv, SM_PRIV_SIZE);
- nlist_insert(&rtnl, clnt);
- }
- fclose(f);
+ const struct sockaddr_in *sin = (const struct sockaddr_in *)sap;
+ notify_list *clnt;
+
+ clnt = nlist_new(m->mon_id.my_id.my_name,
+ m->mon_id.mon_name, 0);
+ if (clnt == NULL)
+ return 0;
+
+ clnt->dns_name = strdup(hostname);
+ if (clnt->dns_name == NULL) {
+ nlist_free(NULL, clnt);
+ return 0;
}
- closedir(d);
-}
+ xlog(D_GENERAL, "Adding record for %s to the monitor list...",
+ hostname);
+
+ NL_ADDR(clnt) = sin->sin_addr;
+ NL_MY_PROG(clnt) = m->mon_id.my_id.my_prog;
+ NL_MY_VERS(clnt) = m->mon_id.my_id.my_vers;
+ NL_MY_PROC(clnt) = m->mon_id.my_id.my_proc;
+ memcpy(NL_PRIV(clnt), m->priv, SM_PRIV_SIZE);
+
+ nlist_insert(&rtnl, clnt);
+ return 1;
+}
+void load_state(void)
+{
+ unsigned int count;
+ count = nsm_load_monitor_list(load_one_host);
+ if (count)
+ xlog(D_GENERAL, "Loaded %u previously monitored hosts");
+}
/*
* Services SM_UNMON requests.
/* PRC: do the HA callout: */
ha_callout("del-client", mon_name, my_name, -1);
- xunlink(SM_DIR, clnt->dns_name);
+ nsm_delete_monitored_host(clnt->dns_name);
nlist_free(&rtnl, clnt);
return (&result);
temp = NL_NEXT(clnt);
/* PRC: do the HA callout: */
ha_callout("del-client", mon_name, my_name, -1);
- xunlink(SM_DIR, clnt->dns_name);
+ nsm_delete_monitored_host(clnt->dns_name);
nlist_free(&rtnl, clnt);
++count;
clnt = temp;
#include <sys/resource.h>
#include <sys/wait.h>
#include <grp.h>
+
#include "statd.h"
#include "nfslib.h"
+#include "nsm.h"
/* Socket operations */
#include <sys/types.h>
#include <sys/socket.h>
-/* Added to enable specification of state directory path at run-time
- * j_carlos_gomez@yahoo.com
- */
-
-char * DIR_BASE = DEFAULT_DIR_BASE;
-
-char * SM_DIR = DEFAULT_SM_DIR;
-char * SM_BAK_DIR = DEFAULT_SM_BAK_DIR;
-char * SM_STAT_PATH = DEFAULT_SM_STAT_PATH;
-
-/* ----- end of state directory path stuff ------- */
-
int run_mode = 0; /* foreground logging mode */
/* LH - I had these local to main, but it seemed silly to have
};
extern void sm_prog_1 (struct svc_req *, register SVCXPRT *);
-static void load_state_number(void);
#ifdef SIMULATIONS
extern void simulator (int, char **);
}
}
-static void drop_privs(void)
-{
- struct stat st;
-
- if (stat(SM_DIR, &st) == -1 &&
- stat(DIR_BASE, &st) == -1) {
- st.st_uid = 0;
- st.st_gid = 0;
- }
-
- if (st.st_uid == 0) {
- xlog_warn("Running as 'root'. "
- "chown %s to choose different user\n", SM_DIR);
- return;
- }
- /* better chown the pid file before dropping, as if it
- * if over nfs we might loose access
- */
- if (pidfd >= 0) {
- if (fchown(pidfd, st.st_uid, st.st_gid) < 0) {
- xlog(L_ERROR, "Unable to change owner of %s: %d (%s)",
- SM_DIR, strerror (errno));
- }
- }
- setgroups(0, NULL);
- if (setgid(st.st_gid) == -1
- || setuid(st.st_uid) == -1) {
- xlog(L_ERROR, "Fail to drop privileges");
- exit(1);
- }
-}
-
static void run_sm_notify(int outport)
{
char op[20];
MY_NAME = xstrdup(optarg);
break;
case 'P':
-
- if ((DIR_BASE = xstrdup(optarg)) == NULL) {
- fprintf(stderr, "%s: xstrdup(%s) failed!\n",
- argv[0], optarg);
+ if (!nsm_setup_pathnames(argv[0], optarg))
exit(1);
- }
-
- SM_DIR = xmalloc(strlen(DIR_BASE) + 1 + sizeof("sm"));
- SM_BAK_DIR = xmalloc(strlen(DIR_BASE) + 1 + sizeof("sm.bak"));
- SM_STAT_PATH = xmalloc(strlen(DIR_BASE) + 1 + sizeof("state"));
-
- if ((SM_DIR == NULL)
- || (SM_BAK_DIR == NULL)
- || (SM_STAT_PATH == NULL)) {
-
- fprintf(stderr, "%s: xmalloc() failed!\n",
- argv[0]);
- exit(1);
- }
- if (DIR_BASE[strlen(DIR_BASE)-1] == '/') {
- sprintf(SM_DIR, "%ssm", DIR_BASE );
- sprintf(SM_BAK_DIR, "%ssm.bak", DIR_BASE );
- sprintf(SM_STAT_PATH, "%sstate", DIR_BASE );
- } else {
- sprintf(SM_DIR, "%s/sm", DIR_BASE );
- sprintf(SM_BAK_DIR, "%s/sm.bak", DIR_BASE );
- sprintf(SM_STAT_PATH, "%s/state", DIR_BASE );
- }
break;
case 'H': /* PRC: specify the ha-callout program */
if ((ha_callout_prog = xstrdup(optarg)) == NULL) {
/* Child. */
close(pipefds[0]);
setsid ();
- if (chdir (DIR_BASE) == -1) {
- perror("statd: Could not chdir");
- exit(1);
- }
while (pipefds[1] <= 2) {
pipefds[1] = dup(pipefds[1]);
* pass on any SM_NOTIFY that arrives
*/
load_state();
- load_state_number();
+
+ MY_STATE = nsm_get_state(0);
+ if (MY_STATE == 0)
+ exit(1);
+ xlog(D_GENERAL, "Local NSM state number: %d", MY_STATE);
+ nsm_update_kernel_state(MY_STATE);
+
pmap_unset (SM_PROG, SM_VERS);
/* this registers both UDP and TCP services */
pipefds[1] = -1;
}
- drop_privs();
+ if (!nsm_drop_privileges(pidfd))
+ exit(1);
for (;;) {
/*
}
return 0;
}
-
-static void
-load_state_number(void)
-{
- int fd;
- const char *file = "/proc/sys/fs/nfs/nsm_local_state";
-
- if ((fd = open(SM_STAT_PATH, O_RDONLY)) == -1)
- return;
-
- if (read(fd, &MY_STATE, sizeof(MY_STATE)) != sizeof(MY_STATE)) {
- xlog_warn("Unable to read state from '%s': errno %d (%s)",
- SM_STAT_PATH, errno, strerror(errno));
- }
- close(fd);
- fd = open(file, O_WRONLY);
- if (fd >= 0) {
- char buf[20];
- snprintf(buf, sizeof(buf), "%d", MY_STATE);
- if (write(fd, buf, strlen(buf)) != strlen(buf))
- xlog_warn("Writing to '%s' failed: errno %d (%s)",
- file, errno, strerror(errno));
- close(fd);
- }
-
-}