X-Git-Url: https://git.octo.it/?p=rrdtool.git;a=blobdiff_plain;f=src%2Frrd_daemon.c;h=154f0dee366bff3208a5a1ba9b6cc2d20664202c;hp=7913a599bf3995e70288a30666fe992c2804b386;hb=116616fe64adf308a6bd11677245cca0bc8c5e05;hpb=d4767fd82947243885f6874c97c0ba477d86c6e7 diff --git a/src/rrd_daemon.c b/src/rrd_daemon.c index 7913a59..154f0de 100644 --- a/src/rrd_daemon.c +++ b/src/rrd_daemon.c @@ -106,11 +106,17 @@ #include #include #include +#include #include /* }}} */ -#define RRDD_LOG(severity, ...) syslog ((severity), __VA_ARGS__) +#define RRDD_LOG(severity, ...) \ + do { \ + if (stay_foreground) \ + fprintf(stderr, __VA_ARGS__); \ + syslog ((severity), __VA_ARGS__); \ + } while (0) #ifndef __GNUC__ # define __attribute__(x) /**/ @@ -140,6 +146,9 @@ struct listen_socket_s ssize_t wbuf_len; uint32_t permissions; + + gid_t socket_group; + mode_t socket_permissions; }; typedef struct listen_socket_s listen_socket_t; @@ -265,6 +274,7 @@ static uint64_t stats_journal_rotate = 0; static pthread_mutex_t stats_lock = PTHREAD_MUTEX_INITIALIZER; /* Journaled updates */ +#define JOURNAL_REPLAY(s) ((s) == NULL) #define JOURNAL_BASE "rrd.journal" static journal_set *journal_cur = NULL; static journal_set *journal_old = NULL; @@ -528,7 +538,7 @@ static int add_response_info(listen_socket_t *sock, char *fmt, ...) /* {{{ */ char buffer[CMD_MAX]; int len; - if (sock == NULL) return 0; /* journal replay mode */ + if (JOURNAL_REPLAY(sock)) return 0; if (sock->batch_start) return 0; /* no extra info returned when in BATCH */ va_start(argp, fmt); @@ -575,7 +585,7 @@ static int send_response (listen_socket_t *sock, response_code rc, ssize_t wrote; int rclen, len; - if (sock == NULL) return rc; /* journal replay mode */ + if (JOURNAL_REPLAY(sock)) return rc; if (sock->batch_start) { @@ -816,9 +826,10 @@ static int flush_old_values (int max_age) for (k = 0; k < cfd.keys_num; k++) { + gboolean status = g_tree_remove(cache_tree, cfd.keys[k]); /* should never fail, since we have held the cache_lock * the entire time */ - assert( g_tree_remove(cache_tree, cfd.keys[k]) == TRUE ); + assert(status == TRUE); } if (cfd.keys != NULL) @@ -1043,7 +1054,7 @@ static int check_file_access (const char *file, listen_socket_t *sock) /* {{{ */ assert(file != NULL); if (!config_write_base_only - || sock == NULL /* journal replay */ + || JOURNAL_REPLAY(sock) || config_base_dir == NULL) return 1; @@ -1272,7 +1283,7 @@ static int handle_request_forget(HANDLER_PROTO) /* {{{ */ if (found == TRUE) { - if (sock != NULL) + if (!JOURNAL_REPLAY(sock)) journal_write("forget", file); return send_response(sock, RESP_OK, "Gone!\n"); @@ -1312,7 +1323,8 @@ static int handle_request_update (HANDLER_PROTO) /* {{{ */ cache_item_t *ci; /* save it for the journal later */ - strncpy(orig_buf, buffer, sizeof(orig_buf)-1); + if (!JOURNAL_REPLAY(sock)) + strncpy(orig_buf, buffer, buffer_size); status = buffer_get_field (&buffer, &buffer_size, &file); if (status != 0) @@ -1397,7 +1409,7 @@ static int handle_request_update (HANDLER_PROTO) /* {{{ */ assert (ci != NULL); /* don't re-write updates in replay mode */ - if (sock != NULL) + if (!JOURNAL_REPLAY(sock)) journal_write("update", orig_buf); while (buffer_size > 0) @@ -1673,6 +1685,9 @@ static int socket_permission_check (listen_socket_t *sock, /* {{{ */ { ssize_t i; + if (JOURNAL_REPLAY(sock)) + return (1); + if (cmd == NULL) return (-1); @@ -1709,7 +1724,7 @@ static int socket_permission_add (listen_socket_t *sock, /* {{{ */ /* check whether commands are received in the expected context */ static int command_check_context(listen_socket_t *sock, command_t *cmd) { - if (sock == NULL) + if (JOURNAL_REPLAY(sock)) return (cmd->context & CMD_CONTEXT_JOURNAL); else if (sock->batch_start) return (cmd->context & CMD_CONTEXT_BATCH); @@ -1761,7 +1776,6 @@ static int handle_request_help (HANDLER_PROTO) /* {{{ */ return send_response(sock, RESP_OK, resp_txt); } /* }}} int handle_request_help */ -/* if sock==NULL, we are in journal replay mode */ static int handle_request (DISPATCH_PROTO) /* {{{ */ { char *buffer_ptr = buffer; @@ -2322,6 +2336,23 @@ static int open_listen_socket_unix (const listen_socket_t *sock) /* {{{ */ return (-1); } + /* tweak the sockets group ownership */ + if (sock->socket_group != (gid_t)-1) + { + if ( (chown(path, getuid(), sock->socket_group) != 0) || + (chmod(path, (S_IRUSR|S_IWUSR|S_IXUSR | S_IRGRP|S_IWGRP)) != 0) ) + { + fprintf(stderr, "rrdcached: failed to set socket group permissions (%s)\n", strerror(errno)); + } + } + + if (sock->socket_permissions != (mode_t)-1) + { + if (chmod(path, sock->socket_permissions) != 0) + fprintf(stderr, "rrdcached: failed to set socket file permissions (%o): %s\n", + (unsigned int)sock->socket_permissions, strerror(errno)); + } + status = listen (fd, /* backlog = */ 10); if (status != 0) { @@ -2387,8 +2418,8 @@ static int open_listen_socket_network(const listen_socket_t *sock) /* {{{ */ fprintf (stderr, "rrdcached: Garbage after address: %s\n", port); return (-1); } - } /* if (*addr = ']') */ - else if (strchr (addr, '.') != NULL) /* Hostname or IPv4 */ + } /* if (*addr == '[') */ + else { port = rindex(addr, ':'); if (port != NULL) @@ -2742,7 +2773,10 @@ static int read_options (int argc, char **argv) /* {{{ */ char **permissions = NULL; size_t permissions_len = 0; - while ((option = getopt(argc, argv, "gl:P:f:w:z:t:Bb:p:Fj:h?")) != -1) + gid_t socket_group = (gid_t)-1; + mode_t socket_permissions = (mode_t)-1; + + while ((option = getopt(argc, argv, "gl:s:m:P:f:w:z:t:Bb:p:Fj:h?")) != -1) { switch (option) { @@ -2798,6 +2832,9 @@ static int read_options (int argc, char **argv) /* {{{ */ } /* }}} Done adding permissions. */ + new->socket_group = socket_group; + new->socket_permissions = socket_permissions; + if (!rrd_add_ptr((void ***)&config_listen_address_list, &config_listen_address_list_len, new)) { @@ -2807,6 +2844,54 @@ static int read_options (int argc, char **argv) /* {{{ */ } break; + /* set socket group permissions */ + case 's': + { + gid_t group_gid; + struct group *grp; + + group_gid = strtoul(optarg, NULL, 10); + if (errno != EINVAL && group_gid>0) + { + /* we were passed a number */ + grp = getgrgid(group_gid); + } + else + { + grp = getgrnam(optarg); + } + + if (grp) + { + socket_group = grp->gr_gid; + } + else + { + /* no idea what the user wanted... */ + fprintf (stderr, "read_options: couldn't map \"%s\" to a group, Sorry\n", optarg); + return (5); + } + } + break; + + /* set socket file permissions */ + case 'm': + { + long tmp; + char *endptr = NULL; + + tmp = strtol (optarg, &endptr, 8); + if ((endptr == optarg) || (! endptr) || (*endptr != '\0') + || (tmp > 07777) || (tmp < 0)) { + fprintf (stderr, "read_options: Invalid file mode \"%s\".\n", + optarg); + return (5); + } + + socket_permissions = (mode_t)tmp; + } + break; + case 'P': { char *optcopy; @@ -2907,6 +2992,13 @@ static int read_options (int argc, char **argv) /* {{{ */ return (3); } + if (rrd_mkdir_p (config_base_dir, 0777) != 0) + { + fprintf (stderr, "Failed to create base directory '%s': %s\n", + config_base_dir, rrd_strerror (errno)); + return (3); + } + /* make sure that the base directory is not resolved via * symbolic links. this makes some performance-enhancing * assumptions possible (we don't have to resolve paths @@ -2914,17 +3006,8 @@ static int read_options (int argc, char **argv) /* {{{ */ */ if (realpath(config_base_dir, base_realpath) == NULL) { - fprintf (stderr, "Invalid base directory '%s'.\n", config_base_dir); - return 5; - } - else if (strncmp(config_base_dir, - base_realpath, sizeof(base_realpath)) != 0) - { - fprintf(stderr, - "Base directory (-b) resolved via file system links!\n" - "Please consult rrdcached '-b' documentation!\n" - "Consider specifying the real directory (%s)\n", - base_realpath); + fprintf (stderr, "Failed to canonicalize the base directory '%s': " + "%s\n", config_base_dir, rrd_strerror(errno)); return 5; } @@ -2942,6 +3025,24 @@ static int read_options (int argc, char **argv) /* {{{ */ } _config_base_dir_len = len; + + len = strlen (base_realpath); + while ((len > 0) && (base_realpath[len - 1] == '/')) + { + base_realpath[len - 1] = '\0'; + len--; + } + + if (strncmp(config_base_dir, + base_realpath, sizeof(base_realpath)) != 0) + { + fprintf(stderr, + "Base directory (-b) resolved via file system links!\n" + "Please consult rrdcached '-b' documentation!\n" + "Consider specifying the real directory (%s)\n", + base_realpath); + return 5; + } } break; @@ -3004,6 +3105,7 @@ static int read_options (int argc, char **argv) /* {{{ */ " -g Do not fork and run in the foreground.\n" " -j Directory in which to create the journal files.\n" " -F Always flush all updates at shutdown\n" + " -s Make socket g+rw to named group\n" "\n" "For more information and a detailed description of all options " "please refer\n"