Compare commits

..
24 Commits
Author SHA1 Message Date
Juro Bystricky afb7572adf configure.ac: bump version to 2.2.1
Version bump from 2.2.0 to 2.2.1

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
2019-08-02 15:05:03 -07:00
Juro Bystricky 3337c45b08 man pages: remove references to telemd
"telemd" was replaced by "telemprobd" a long time
ago, however several man pages still contain refererences
to "telemd".
This patch replaces all references accordingly.

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
2019-08-02 15:04:43 -07:00
Juro Bystricky 672e741e5d Fix build for logtype=systemd
Build is broken for multiple binaries when configured for logging
to systemd journal:

$ ./configure --enable-logtype=systemd
$ make

All binaries that use the routine "telem_log" must link to additional
libraries when logging to systemd journal.

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
2019-07-29 09:57:46 -07:00
Juro Bystricky e19e72a5b3 crash_probe: Limit the size of backtrace
A simple program that is highly recursive (or very deeply nested)
and causes stack overflow or segmentation fault can take hours
for crash_probe to process.
This patch fixes this by limiting the size of the stacktrace to 64.
(64 is also the size of the stack trace used by systemd).
64 lines of 80 characters == 5120 bytes. Enough to leave room for
telemetry headers and have a reasonable chance of making the 8k payload
limit.

If the stack trace is truncated, the payload will contain a message:

"Too many frames. Backtrace truncated".

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
2019-07-25 08:40:04 -07:00
Juro Bystricky 9a25115d8e configure.ac: bump version to 2.2.0
Version bump from 2.1.1 to 2.2.0

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
2019-07-09 09:36:31 -07:00
Juro Bystricky 11c5808fd9 telem_journal: improve usage message
No functional changes.
Provide additional info in the usage message, based on user feedback.
While in there, some additional minor changes..

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
2019-06-12 10:42:33 -07:00
Juro Bystricky 9f67a1ca8a Updated AUTHORS
Added recent authors.
Also removed TODO, as it has not been maintained for several years.

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
2019-06-12 10:40:30 -07:00
Juro Bystricky 781d9382d0 Fix compiler warnings [-Wstringop-truncation]
Modify code to avoid generating compiler warning such as:
warning: ‘__builtin_strncpy’ output truncated before terminating nul copying as many bytes from a string as its length [-Wstringop-truncation]

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
2019-06-05 10:56:52 -07:00
Juro Bystricky 2a29191c5f telem_record_gen.c: fix for compiler warning [-Wstringop-overflow=]
Replace strncpy with memcpy to avoid GCC9 warning:
warning: ‘__builtin___strncpy_chk’ specified bound depends on the length of the source argument [-Wstringop-overflow=]

There is no danger of overflow. The destination buffer is guaranteed to
be of MAX_PAYLOAD_LENGTH.

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
2019-06-05 10:56:36 -07:00
Juro Bystricky c264cd044c check_probes.c: fix for compiler warning [-Wstringop-overflow=]
Replaced strncpy with memcpy and added some buffer overflow checks in
order to avoid GCC9 compiler warning:
warning: ‘__builtin___strncpy_chk’ specified bound depends on the length of the source argument [-Wstringop-overflow=]

While in there, removed one unused global variable and declared the remaining
global variables as static.

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
2019-06-05 10:56:18 -07:00
California Sullivan ad4dde288b journal.c: reduce severity of message when failing to opening old records
The default configuration for telemetry is to not store records that
were successfully sent. This would result in a multitude of errors when
calling the journal program with --include_record, as the records no
longer existed to open.

Signed-off-by: California Sullivan <california.l.sullivan@intel.com>
2019-06-03 14:23:34 -07:00
Alex Jaramillo 48527a343b Protect security checks from removal
Compiler optimization can remove certain security checks for undefined
behavior. Add compiler flags that restrict arbitrary decisions when
handling undefined behaviors.

* fno-strict-overflow, do not assume signed overflow does not occur.
* fno-delete-null-pointer-checks, do not assume null pointer deference
does not exists.
* fwrapv, always wrap signed overflow.

Signed-off-by: Alex Jaramillo <alex.jch@gmail.com>
2019-05-30 11:02:44 -07:00
California Sullivan d13073ff25 src: standardize log and debug messages
Use the telem_log, telem_debug, and telem_perror macros to print
messages instead of printf and fprintf where appropriate. These macros
may be configured to print to many standard locations at compile time,
such as the syslog, the journal, or stderr. The remaining uses of
fprintf in printing errors is only for command line utilities.

When using telem_debug, we don't need to surround it with #ifdef DEBUG
statements, as the macro does that itself.

Finally, stop hiding real errors behind #ifdef DEBUGs. If an error
occurs, it should be logged.

Signed-off-by: California Sullivan <california.l.sullivan@intel.com>
2019-05-02 14:44:35 -07:00
California Sullivan 43c506382a log.h: fix telem_debug macro
The telem_debug macro was apparently never tested previously, as it
didn't compile.

Signed-off-by: California Sullivan <california.l.sullivan@intel.com>
2019-05-02 14:44:35 -07:00
Juro Bystricky aca23d1c54 Minor houskeeping
Moved a misplaced comment to where it belongs.
Fixed incorrectly formatted log string.

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
2019-04-25 09:27:24 -07:00
Juro Bystricky 2639e4d042 daemons: name space separation
The telempostd and telemprobd daemons both used identical
name "initialize_daemon" for daemon initialization.
Although the name was identical, the code for each daemon initialization
was different, leading to some potential confusion.
Also moved telemprobd specific code "stage_record" from iorecord.c to
telemdaemon.c
Modified local.mk accordingly.

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
2019-04-22 19:45:40 -07:00
California Sullivan cc70c3ffba telemetry.c: support variants in the system_name header
Read the VARIANT_ID field of the os-release file and add it to our
system_name header. This allows differentiation of different variants of
an operating system on the backend.

The header will be unchanged on operating systems without a VARIANT_ID
in their os-release file. Also continue limiting the header length to 80
characters.

Signed-off-by: California Sullivan <california.l.sullivan@intel.com>
2019-04-22 10:31:09 -07:00
California Sullivan ba62496248 telempostdaemon: fix retries loop
The 'else if (retry_attempt == MAX_RETRY_ATTEMPTS)' section would get
hit the first time through the loop on every invocation, printing the
failed to deliver error to the journal.

To fix it, initialize retry_attempt to zero and check that we're above
zero retries to enter retry sections.

This fixes the false "Record deliver failed after 8 attempts" message
that was getting spewed into the journal.

Signed-off-by: California Sullivan <california.l.sullivan@intel.com>
2019-04-22 10:30:45 -07:00
California Sullivan d873c4e067 configuration: rework to allow layered configuration
Have a default configuration set in the binary, with conf files only
being used to change from the defaults. This allows making simpler
configs which only toggle specific options, which may be useful for user
configuration or testing. See src/data/example.2.conf for an example of
a new simplified config.

By default the telemetrics-client is configured with
https://clr.telemetry.intel.com/v2/collector as the built-in server
location. This is the normal Clear Linux telemetrics backend. It can
be changed via the configure flag --with-backendserveraddr=URI. This
allows anyone else using this project to easily specify their own
default backend without patching. As per usual, users can specify a
different server location in a configuration file.

Signed-off-by: California Sullivan <california.l.sullivan@intel.com>
2019-04-22 10:29:59 -07:00
Juro Bystricky 335ed440bc telem_record_gen: various changes
1. Declare all local routines as static
2. Added support for custom config files (implemented the option "-f")
3. bugfix: -P option with non existing file would not fail.
4. More stringent parsing of classification, avoid hard coded numbers,
   use pre-defined constants from "common.h" instead.
   Also detect MAX_SUBCAT_LENGTH violation.
5. Some local routines were declared as "bool" instead of "int":
   These routines used to return 1 if successful and 0 if failed.
   This was confusing as all API routines return 0 upon success
   and non-zero value if error.
6. Replaced the whole routine "allocate_payload_buffer" with a single
   call to "calloc".

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
2019-04-22 09:30:02 -07:00
Juro Bystricky 297e59fe5b Improve support of non-default configuration files.
Most probes allow passing of non-default configuration file
via command line using the "-f" switch.
For example:

$ hprobe -f custom_cfg_file.conf

If the file "custom_cfg_file.conf" contains

server = http://<my backend server>

one would expect the hprobe payload will be sent to the server
http://<my backend server>. However, this is not the case, as the
various daemons delivering the payload to the backend are blissfully
unaware of the of the config file hprobe wanted to use.

The solution is to include the absolute path of the config file
specified on the command line as part of the payload. Once the
payload is about to be sent via the routine "post_record_http",
the routine checks if a non-default config file was requested.
If so, configuration is re-initialized with the file.
Upon exit, the routine re-initializes the original (default) configuration.

The non-default file may not exist at the send time anymore,
for example when sending some spooled records. In that case we
intentionally don't send anything to the backend.

If the record does not contain the optional configuration file
information, it's business as usual.

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
2019-04-22 09:29:30 -07:00
Juro Bystricky 4a2cfd99ad spool.c: fix memory leak
In case of memory allocation failures or record parsing failures,
"transmit_spooled_record" may have returned without freeing any previously
allocated memory.

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
2019-03-22 14:37:33 -07:00
Alex Jaramillo 46f2e0c8cb Release v2.1.1 2019-02-25 21:14:14 +00:00
Juro Bystricky ffc0554346 pythonprobe: fix folders
Python3 expects two "well known" folders to exist in order to generate exception
payloads:

/var/tmp/telemetry
/var/lib/telemetry/python

Both folders must exist at the above absolute locations in order to properly
create and submit Python3 telemetry unhandled exception payload.

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
2019-02-25 13:07:06 -08:00
47 changed files with 789 additions and 526 deletions
+3
View File
@@ -3,3 +3,6 @@ Patrick McCarty <patrick.mccarty@intel.com>
Rob Nesius <robert.a.nesius@intel.com>
Gabrielle N. Beyer <gabrielle.n.beyer@intel.com>
Pam Leonard <pam.leonard@intel.com>
Alex V. Jaramillo <alex.v.jaramillo@intel.com>
California Sullivan <california.l.sullivan@intel.com>
Juro Bystricky <juro.bystricky@intel.com>
-24
View File
@@ -1,24 +0,0 @@
Build
=====
- make sure our AM_CFLAGS do not break older compilers, e.g. compilers
that do not support -fstack-protector-strong
Probes
======
- add pstore probe (Archana)
- journal probe: detect kernel oopses (Patrick)
- crash probe: add function/register value info to crash payloads (Patrick)
- crash probe: if some symbols are missing from backtraces, attempt the
debuginfo lookup again after a certain timeout (Patrick)
- crash probe: for non-debug builds, ensure that we are invoked by the kernel,
and write tests to verify that attempts to run the crash probe for non-debug
builds fail. (Patrick)
Library
=======
- add API for structured payloads
Other
=====
- set fixed size for system-wide core file ulimit, and afterward notify QA team
to update the BAT test that checks for the ulimit value.
+6 -2
View File
@@ -12,7 +12,10 @@ AM_CFLAGS = \
-Wunreachable-code \
-funsigned-char \
-fPIE \
-fPIC
-fPIC \
-fno-strict-overflow \
-fno-delete-null-pointer-checks \
-fwrapv
AM_CPPFLAGS = \
-D_FORTIFY_SOURCE=2 \
@@ -25,6 +28,7 @@ AM_CPPFLAGS = \
-DDATADIR=\"$(datadir)\" \
-DLOCALSTATEDIR=\"$(localstatedir)\" \
-DPSTOREDIR=\"$(localstatedir)/cache/telemetry/pstore\" \
-DTESTOOPSDIR=\"$(top_srcdir)/tests/oops_test_files\"
-DTESTOOPSDIR=\"$(top_srcdir)/tests/oops_test_files\" \
-DBACKEND_ADDR=\"$(BACKEND_ADDR)\"
# vim: filetype=automake tabstop=8 shiftwidth=8 noexpandtab
+6 -1
View File
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([telemetrics-client], [2.1.0], [https://clearlinux.org/])
AC_INIT([telemetrics-client], [2.2.1], [https://clearlinux.org/])
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([1.14 -Wall -Werror -Wno-extra-portability foreign subdir-objects])
AM_SILENT_RULES([yes])
@@ -119,6 +119,11 @@ AC_ARG_WITH([loglevel], AS_HELP_STRING([--with-loglevel=NUM],
[loglevel=5])
AC_DEFINE_UNQUOTED([MAX_LOG_LEVEL], [${loglevel}], [Maximum log level for binaries])
AC_ARG_WITH([backendserveraddr], AS_HELP_STRING([--with-backendserveraddr=URI],
[uri to telemetrics backend server @<:@default=https://clr.telemetry.intel.com/v2/collector@:>@]), [backendaddr=${withval}])
test -z "${backendaddr}" && backendaddr=https://clr.telemetry.intel.com/v2/collector
AC_SUBST(BACKEND_ADDR, [${backendaddr}])
AC_ARG_ENABLE([logtype], AS_HELP_STRING([--enable-logtype],
[Vector for logging: stderr (default), syslog, systemd]),
[case ${enableval} in
+1 -1
View File
@@ -89,7 +89,7 @@ Event id to use in the record. If not provided a randomly generated id will be a
.SH SEE ALSO
.INDENT 0.0
.IP \(bu 2
\fBtelemd\fP(1)
\fBtelemprobd\fP(1)
.IP \(bu 2
\fI\%https://github.com/clearlinux/telemetrics\-client\fP
.IP \(bu 2
+1 -1
View File
@@ -76,6 +76,6 @@ RETURN VALUES
SEE ALSO
========
* ``telemd``\(1)
* ``telemprobd``\(1)
* https://github.com/clearlinux/telemetrics-client
* https://clearlinux.org/documentation/
+1 -1
View File
@@ -66,7 +66,7 @@ Checks if telemetry client daemons are active (telemprobd and telempostd).
.SH SEE ALSO
.INDENT 0.0
.IP \(bu 2
\fBtelemd\fP(1)
\fBtelemprobd\fP(1)
.IP \(bu 2
\fI\%https://github.com/clearlinux/telemetrics\-client\fP
.IP \(bu 2
+1 -1
View File
@@ -52,6 +52,6 @@ RETURN VALUES
SEE ALSO
========
* ``telemd``\(1)
* ``telemprobd``\(1)
* https://github.com/clearlinux/telemetrics-client
* https://clearlinux.org/documentation/
+1 -1
View File
@@ -60,7 +60,7 @@ The function \fBtm_set_payload()\fP attaches the provided telemetry record
data to the telemetry record. The current maximum payload size is 8192b.
.sp
The function \fBtm_send_record()\fP delivers the record to the local
\fBtelemd\fP(1) service.
\fBtelemprobd\fP(1) service.
.sp
The function \fBtm_set_config_file()\fP can be used to provide an alternate
configuration path to the telemetry library.
+1 -1
View File
@@ -44,7 +44,7 @@ The function ``tm_set_payload()`` attaches the provided telemetry record
data to the telemetry record. The current maximum payload size is 8192b.
The function ``tm_send_record()`` delivers the record to the local
``telemd``\(1) service.
``telemprobd``\(1) service.
The function ``tm_set_config_file()`` can be used to provide an alternate
configuration path to the telemetry library.
+6
View File
@@ -102,6 +102,11 @@ static const uint32_t RECORD_FORMAT_VERSION = 4;
/* Maximum records that can be processed in a single spool run loop*/
#define TM_SPOOL_MAX_PROCESS_RECORDS 60
/* Definitions for config file override */
#define CFG_PREFIX "CFG:"
#define CFG_PREFIX_LENGTH 4
#define CFG_PREFIX_32BIT 0x3a474643
/* Very simple structure. Array of header strings and a payload. Calling
* program is reponsible for passing in the payload as a simple string.
*/
@@ -114,4 +119,5 @@ struct telem_record {
const char *get_header_name(int ind);
/* vi: set ts=8 sw=8 sts=4 et tw=80 cino=(0: */
+110 -58
View File
@@ -28,6 +28,7 @@
#include "configuration.h"
#include "util.h"
#include "common.h"
#include "log.h"
#include "nica/inifile.h"
@@ -38,17 +39,46 @@ static NcHashmap *keyfile = NULL;
static bool cmd_line_cfg = false;
/* Conf strings, integers, and booleans expected in the conf file */
const char *config_key_str[] = { NULL, "server", "socket_path", "spool_dir",
"rate_limit_strategy", "cainfo",
"tidheader", NULL };
static const char *config_key_str[] = { "server",
"socket_path",
"spool_dir",
"rate_limit_strategy",
"cainfo",
"tidheader"};
const char *config_key_int[] = { NULL, "record_expiry", "spool_max_size",
"spool_process_time", "record_window_length",
"byte_window_length", "record_burst_limit",
"byte_burst_limit", NULL };
static const char *config_key_int[] = { "record_expiry",
"spool_max_size",
"spool_process_time",
"record_window_length",
"byte_window_length",
"record_burst_limit",
"byte_burst_limit" };
static const char *config_key_bool[] = { "rate_limit_enabled",
"daemon_recycling_enabled",
"record_retention_enabled",
"record_server_delivery_enabled" };
static const char *config_str_default[] = { DEFAULT_SERVER_ADDR,
DEFAULT_SOCKET_PATH,
DEFAULT_SPOOL_DIR,
DEFAULT_RATE_LIMIT_STRATEGY,
DEFAULT_CAINFO,
DEFAULT_TIDHEADER };
static const bool config_bool_default[] = { DEFAULT_RATE_LIMIT_ENABLED,
DEFAULT_DAEMON_RECYCLING_ENABLED,
DEFAULT_RECORD_RETENTION_ENABLED,
DEFAULT_RECORD_SERVER_DELIVERY_ENABLED };
static const int config_int_default[] = { DEFAULT_RECORD_EXPIRY,
DEFAULT_SPOOL_MAX_SIZE,
DEFAULT_SPOOL_PROCESS_TIME,
DEFAULT_RECORD_WINDOW_LENGTH,
DEFAULT_BYTE_WINDOW_LENGTH,
DEFAULT_RECORD_BURST_LIMIT,
DEFAULT_BYTE_BURST_LIMIT };
const char *config_key_bool[] = { NULL, "rate_limit_enabled", "daemon_recycling_enabled",
"record_retention_enabled", "record_server_delivery_enabled", NULL };
static struct configuration config = { { 0 }, { 0 }, { 0 }, false, NULL };
@@ -73,6 +103,19 @@ static int validate_config_file(const char *f)
}
const char *get_config_file(void)
{
return config_file;
}
const char *get_cmd_line_config_file(void)
{
if (cmd_line_cfg == true) {
return config_file;
}
return NULL;
}
int set_config_file(const char *filename)
{
int ret;
@@ -90,6 +133,25 @@ int set_config_file(const char *filename)
return ret;
}
bool set_default_config_values(struct configuration *config)
{
for (int i = 0; i < CONF_STR_MAX; i++) {
config->strValues[i] = strdup(config_str_default[i]);
if (config->strValues[i] == NULL) {
telem_log(LOG_ERR, "Could not set config item %s: %s\n",
config_key_str[i], strerror(errno));
return false;
}
}
for (int i = 0; i < CONF_INT_MAX; i++) {
config->intValues[i] = config_int_default[i];
}
for (int i = 0; i < CONF_BOOL_MAX; i++) {
config->boolValues[i] = config_bool_default[i];
}
return true;
}
bool read_config_from_file(char *config_file, struct configuration *config)
{
if (keyfile != NULL) {
@@ -98,73 +160,64 @@ bool read_config_from_file(char *config_file, struct configuration *config)
keyfile = nc_ini_file_parse(config_file);
if (!keyfile) {
#ifdef DEBUG
fprintf(stderr, "ERR: Failed to read config file\n");
#endif
telem_log(LOG_ERR, "Failed to read config file\n");
return false;
} else {
for (int i = CONF_STR_MIN + 1; i < CONF_STR_MAX; i++) {
for (int i = 0; i < CONF_STR_MAX; i++) {
char *ptr;
ptr = nc_hashmap_get(nc_hashmap_get(keyfile, "settings"), config_key_str[i]);
if (ptr) {
config->strValues[i] = strdup(ptr);
if (config->strValues[i] == NULL) {
telem_log(LOG_ERR, "Could not set config item %s: %s\n",
config_key_str[i], strerror(errno));
return false;
}
} else {
fprintf(stderr, "ERR: missing key with string value: %s\n", config_key_str[i]);
return false;
config->strValues[i] = strdup(config_str_default[i]);
}
}
for (int i = CONF_INT_MIN + 1; i < CONF_INT_MAX; i++) {
for (int i = 0; i < CONF_INT_MAX; i++) {
char *ptr;
ptr = nc_hashmap_get(nc_hashmap_get(keyfile, "settings"), config_key_int[i]);
if (ptr) {
errno = 0;
config->intValues[i] = strtoll(ptr, NULL, 10);
if (errno != 0) {
telem_log(LOG_ERR, "Error while parsing value of option %s: %s\n",
config_key_int[i], strerror(errno));
return false;
}
} else {
fprintf(stderr, "ERR: missing key with integer value: %s\n", config_key_int[i]);
return false;
config->intValues[i] = config_int_default[i];
}
}
for (int i = CONF_BOOL_MIN + 1; i < CONF_BOOL_MAX; i++) {
for (int i = 0; i < CONF_BOOL_MAX; i++) {
char *ptr;
ptr = nc_hashmap_get(nc_hashmap_get(keyfile, "settings"), config_key_bool[i]);
config->boolValues[i] = false;
if (ptr) {
if (strcasecmp(ptr, "TRUE") == 0) {
if ((strcasecmp(ptr, "TRUE") == 0) || (strcmp(ptr, "1") == 0)) {
config->boolValues[i] = true;
}
if (strcasecmp(ptr, "1") == 0) {
config->boolValues[i] = true;
}
} else {
/* New configuration keys, CONF_RECORD_RETENTION_ENABLED and CONF_RECORD_SERVER_DELIVERY_ENABLED
* default values, otherwise update will require changes in custom configurations */
if (i == CONF_RECORD_RETENTION_ENABLED) {
#ifdef DEBUG
fprintf(stderr, "WARN: missing boolean optional key: %s\n", config_key_bool[i]);
#endif
config->boolValues[i] = RECORD_RETENTION_ENABLED_DEFAULT;
} else if (i == CONF_RECORD_SERVER_DELIVERY_ENABLED) {
#ifdef DEBUG
fprintf(stderr, "WARN: missing boolean optional key: %s\n", config_key_bool[i]);
#endif
config->boolValues[i] = RECORD_SERVER_DELIVERY_ENABLED_DEFAULT;
} else if ((strcasecmp(ptr, "FALSE") == 0) || (strcmp(ptr, "0") == 0)) {
config->boolValues[i] = false;
} else {
fprintf(stderr, "ERR: missing key with boolean value: %s\n", config_key_bool[i]);
telem_log(LOG_ERR, "Configuration item '%s' requires a boolean value\n",
config_key_bool[i]);
return false;
}
} else {
config->boolValues[i] = config_bool_default[i];
}
}
}
config->initialized = true;
return true;
}
void initialize_config(void)
static void initialize_config(void)
{
if (config.initialized) {
return;
@@ -175,26 +228,25 @@ void initialize_config(void)
if (access(etc_config_file, R_OK) == 0) {
config_file = etc_config_file;
} else {
if (access(default_config_file,
R_OK) == 0) {
if (access(default_config_file, R_OK) == 0) {
config_file = default_config_file;
} else {
/* If there is no default config, exit with failure */
#ifdef DEBUG
fprintf(stderr, "ERR: No configuration file"
" found, exiting\n");
#endif
exit(EXIT_FAILURE);
}
}
}
if (!read_config_from_file(config_file, &config)) {
/* Error while parsing file */
#ifdef DEBUG
fprintf(stderr, "ERR: Error while parsing configuration file\n");
#endif
exit(EXIT_FAILURE);
if (config_file) {
if (!read_config_from_file(config_file, &config)) {
/* Error while parsing file */
exit(EXIT_FAILURE);
}
}
else {
if (!set_default_config_values(&config)) {
exit(EXIT_FAILURE);
}
}
config.initialized = true;
}
void reload_config(void)
@@ -214,7 +266,7 @@ void free_configuration(void)
return;
}
for (int i = CONF_STR_MIN + 1; i < CONF_STR_MAX; i++) {
for (int i = 0; i < CONF_STR_MAX; i++) {
free(config.strValues[i]);
}
+33 -8
View File
@@ -18,13 +18,31 @@
#include <stdbool.h>
#include <stdint.h>
/* Default configuration settings */
#define DEFAULT_SERVER_ADDR BACKEND_ADDR
#define DEFAULT_SOCKET_PATH "/run/telem-0"
#define DEFAULT_SPOOL_DIR LOCALSTATEDIR "/spool/telemetry"
#define DEFAULT_RATE_LIMIT_STRATEGY "spool"
#define DEFAULT_CAINFO ""
#define DEFAULT_TIDHEADER "X-Telemetry-TID: 6907c830-eed9-4ce9-81ae-76daf8d88f0f"
#define DEFAULT_RECORD_EXPIRY 1200
#define DEFAULT_SPOOL_MAX_SIZE 5120
#define DEFAULT_SPOOL_PROCESS_TIME 120
#define DEFAULT_RECORD_WINDOW_LENGTH 15
#define DEFAULT_BYTE_WINDOW_LENGTH 20
#define DEFAULT_RECORD_BURST_LIMIT 1000
#define DEFAULT_BYTE_BURST_LIMIT -1
#define DEFAULT_RATE_LIMIT_ENABLED true
#define DEFAULT_DAEMON_RECYCLING_ENABLED true
#define DEFAULT_RECORD_RETENTION_ENABLED false
#define DEFAULT_RECORD_SERVER_DELIVERY_ENABLED true
#define TM_MAX_WINDOW_LENGTH (1 /*h*/ * 60 /*m*/)
#define RECORD_RETENTION_ENABLED_DEFAULT false
#define RECORD_SERVER_DELIVERY_ENABLED_DEFAULT true
enum config_str_keys {
CONF_STR_MIN = 0,
CONF_SERVER_ADDR,
CONF_SERVER_ADDR = 0,
CONF_SOCKET_PATH,
CONF_SPOOL_DIR,
CONF_RATE_LIMIT_STRATEGY,
@@ -34,8 +52,7 @@ enum config_str_keys {
};
enum config_int_keys {
CONF_INT_MIN = 0,
CONF_RECORD_EXPIRY,
CONF_RECORD_EXPIRY = 0,
CONF_SPOOL_MAX_SIZE,
CONF_SPOOL_PROCESS_TIME,
CONF_RECORD_WINDOW_LENGTH,
@@ -46,8 +63,7 @@ enum config_int_keys {
};
enum config_bool_keys {
CONF_BOOL_MIN = 0,
CONF_RATE_LIMIT_ENABLED,
CONF_RATE_LIMIT_ENABLED = 0,
CONF_DAEMON_RECYCLING_ENABLED,
CONF_RECORD_RETENTION_ENABLED,
CONF_RECORD_SERVER_DELIVERY_ENABLED,
@@ -65,6 +81,15 @@ typedef struct configuration {
/* Sets the configuration file to be used later */
int set_config_file(const char *filename);
/* Gets the configuration currently in use */
const char *get_config_file(void);
/* Gets the configuration specified via command line or NULL */
const char *get_cmd_line_config_file(void);
/* Sets all default configuration values to a given config */
bool set_default_config_values(struct configuration *config);
/* Parses the ini format config file */
bool read_config_from_file(char *filename, struct configuration *config);
+4
View File
@@ -0,0 +1,4 @@
[settings]
server=http://127.0.0.1
cainfo=/tmp/cacert.crt
+3 -1
View File
@@ -5,13 +5,15 @@ pathfix = @sed \
-e 's|@localstatedir[@]|$(localstatedir)|g' \
-e 's|@PACKAGE_VERSION[@]|$(PACKAGE_VERSION)|g' \
-e 's|@SOCKETDIR[@]|$(SOCKETDIR)|g' \
-e 's|@systemctldir[@]|$(SYSTEMD_SYSTEMCTLDIR)|g'
-e 's|@systemctldir[@]|$(SYSTEMD_SYSTEMCTLDIR)|g' \
-e 's|@BACKEND_ADDR[@]|$(BACKEND_ADDR)|g'
EXTRA_DIST += \
%D%/40-core-ulimit.conf \
%D%/40-crash-probe.conf.in \
%D%/example.conf \
%D%/example.1.conf \
%D%/example.2.conf \
%D%/hprobe.service.in \
%D%/hprobe.timer \
%D%/bert-probe.service.in \
+1 -1
View File
@@ -3,7 +3,7 @@ Description=Python Probe Daemon Staging
ConditionPathExists=!/etc/telemetrics/opt-out
[Path]
DirectoryNotEmpty=@localstatedir@/lib/telemetry/python
DirectoryNotEmpty=/var/lib/telemetry/python
[Install]
WantedBy=multi-user.target
+2 -1
View File
@@ -1,7 +1,8 @@
d @localstatedir@/lib/telemetry 0755 telemetry telemetry -
d @localstatedir@/lib/telemetry/python 01777 telemetry telemetry -
d @localstatedir@/spool/telemetry 0750 telemetry telemetry -
d @localstatedir@/log/telemetry 0750 telemetry telemetry -
d @localstatedir@/log/telemetry/records 0750 telemetry telemetry -
d @localstatedir@/cache/telemetry 0750 telemetry telemetry -
d @localstatedir@/cache/telemetry/pstore 0750 telemetry telemetry -
d /var/lib/telemetry/python 01777 telemetry telemetry -
d /var/tmp/telemetry 01777 telemetry telemetry -
+19 -17
View File
@@ -1,67 +1,69 @@
# values represent their default state
# copy to /etc/telemetrics/telemetrics.conf and modify for user config
[settings]
# ip address of destination server for record delivery
server=https://clr.telemetry.intel.com/v2/collector
#server=@BACKEND_ADDR@
socket_path=@SOCKETDIR@/telem-0
#socket_path=@SOCKETDIR@/telem-0
# certificate file to use to validate ssl endpoint
cainfo=
#cainfo=
# Telemetry id - post header used to group records in ingestion service,
# which may be ingesting for more than one set of clients. Can be set
# to any string.
tidheader=X-Telemetry-TID:\s6907c830-eed9-4ce9-81ae-76daf8d88f0f
#tidheader=X-Telemetry-TID:\s6907c830-eed9-4ce9-81ae-76daf8d88f0f
# record expiry time in minutes
record_expiry=1200
#record_expiry=1200
spool_dir=@localstatedir@/spool/telemetry
#spool_dir=@localstatedir@/spool/telemetry
# maximum size of the spool directory in KB, -1 = quota disabled.
# The block size of the files in this directory is considered,
# and not the actual size of the record itself.
spool_max_size=5120
#spool_max_size=5120
# time in seconds for processing spool
# Valid range: 120..300. Values outside this range are clamped.
spool_process_time=120
#spool_process_time=120
# rate limit enabled - if this is set to false then all rate-limiting disabled.
# It is possible to disable each rate-limit individually below.
rate_limit_enabled=true
#rate_limit_enabled=true
# rate limiting record burst limit
# Valid Range: 0..INT_MAX, -1 = disabled.
record_burst_limit=1000
#record_burst_limit=1000
# rate limiting record window length in minutes
# Valid Range: 0..59
record_window_length=15
#record_window_length=15
# rate limiting byte burst limit
# Valid Range: 0..INT_MAX, -1 = disabled.
byte_burst_limit=-1
#byte_burst_limit=-1
# rate limiting byte window length in minutes
# Valid Range: 0..59
byte_window_length=20
#byte_window_length=20
# rate limit strategy - what to do with record if rate-limiting prevents
# delivery over network
# Valid stategies: spool, drop
rate_limit_strategy=spool
#rate_limit_strategy=spool
# daemon recycling enabled - if daemon has been running for a while (2 hours),
# has not any client nor spool data, then it exits.
# this is to ensure that latest code runs.
daemon_recycling_enabled=true
#daemon_recycling_enabled=true
# record server delivery enabled - when enabled records will be delivered
# to server otherwise records will be ignored. This configuration can be used
# with 'record_retention_enable' configuration value to keep records local only.
record_server_delivery_enabled=true
#record_server_delivery_enabled=true
# record retention enabled - when enabled a copy of reported telemetry records
# will be kept locally. This configuration combined with 'record_server_delivery_enabled'
# value can be used to keep records local only.
record_retention_enabled=false
#record_retention_enabled=false
+34 -50
View File
@@ -41,62 +41,20 @@ bool _fgets(char *s, int n, FILE *stream)
return true;
}
void stage_record(char *filepath, char *headers[], char *body)
{
int tmpfd;
FILE *tmpfile = NULL;
// Use default path if not provided
if (filepath == NULL) {
telem_log(LOG_ERR, "filepath value must be provided, aborting\n");
exit(EXIT_FAILURE);
}
tmpfd = mkstemp(filepath);
if (!tmpfd) {
telem_perror("Error opening staging file");
close(tmpfd);
if (unlink(filepath)) {
telem_perror("Error deleting staging file");
}
goto clean_exit;
}
// open file
tmpfile = fdopen(tmpfd, "a");
if (!tmpfile) {
telem_perror("Error opening temp stage file");
close(tmpfd);
if (unlink(filepath)) {
telem_perror("Error deleting temp stage file");
}
goto clean_exit;
}
// write headers
for (int i = 0; i < NUM_HEADERS; i++) {
fprintf(tmpfile, "%s\n", headers[i]);
}
//write body
fprintf(tmpfile, "%s\n", body);
fflush(tmpfile);
fclose(tmpfile);
clean_exit:
return;
}
bool read_record(char *fullpath, char *headers[], char **body)
bool read_record(char *fullpath, char *headers[], char **body, char **cfg_file)
{
int i, ret = 0;
bool result = false;
FILE *fp = NULL;
long offset;
char line[LINE_MAX] = { 0 };
#if (LINE_MAX > PATH_MAX)
char line[LINE_MAX+1] = { 0 };
#else
char line[PATH_MAX+1] = { 0 };
#endif
struct stat buf;
long size;
uint32_t cfg_prefix = 0;
ret = stat(fullpath, &buf);
if (ret == -1) {
@@ -111,9 +69,35 @@ bool read_record(char *fullpath, char *headers[], char **body)
return false;
}
// First line may contain configuration file path
if (fread(&cfg_prefix, CFG_PREFIX_LENGTH, 1, fp) != 1) {
telem_log(LOG_ERR, "Error while parsing staged record configuration info.\n");
goto read_error;
}
if (cfg_prefix == CFG_PREFIX_32BIT) {
if (!_fgets(line, sizeof(line), fp)) {
telem_log(LOG_ERR, "Error while parsing staged record [%x]\n", cfg_prefix);
goto read_error;
}
size_t pathlen = strlen(line);
*cfg_file = malloc(pathlen + 1);
if (cfg_file == NULL) {
telem_log(LOG_ERR, "Could not allocate memory for config file path\n");
goto read_error;
}
strcpy (*cfg_file, line);
telem_debug("DEBUG: cfg_file specified: %s\n", *cfg_file);
} else {
telem_debug("DEBUG: no user cfg file specified, cfg_prefix: %08x\n", cfg_prefix);
*cfg_file = NULL;
rewind(fp);
}
for (i = 0; i < NUM_HEADERS; i++) {
const char *header_name = get_header_name(i);
if (!_fgets(line, LINE_MAX, fp)) {
if (!_fgets(line, sizeof(line), fp)) {
telem_log(LOG_ERR, "Error while parsing staged record\n");
fclose(fp);
return false;
+1 -11
View File
@@ -16,16 +16,6 @@
#include <stdbool.h>
/**
* Save a telemetry record to disk
*
* @param path pointer to a directory to save record
* @param headers pointer to array of headers and values
* @param body record message content
*
*/
void stage_record(char *path, char *headers[], char *body);
/**
* Reads a telemetry record
*
@@ -35,4 +25,4 @@ void stage_record(char *path, char *headers[], char *body);
*
* @return true if successful otherwise false
*/
bool read_record(char *fullpath, char *headers[], char **body);
bool read_record(char *fullpath, char *headers[], char **body, char **cfg);
+12 -9
View File
@@ -24,14 +24,18 @@
#include "common.h"
#include "journal.h"
void print_usage(void)
static void print_usage(void)
{
printf(" Usage\n");
printf("Usage:\n");
printf(" telem_journal [-Vi] [-r <record_id>] [-e <event_id>] [-c <classification>] [-b <boot_id>]\n\n");
printf("Where:\n");
printf(" -r, --record_id Print record with specific record_id\n");
printf(" -e, --event_id Print records with specific event_id\n");
printf(" -c, --classification Print records with specific classification\n");
printf(" -b, --boot_id Print records with specific boot_id\n");
printf(" -i, --include_record Include record content\n");
printf(" -i, --include_record Include record content if available.\n");
printf(" Content only available when telemetry is configured\n");
printf(" with \"record_retention_enabled=true\"\n");
printf(" -V, --verbose Verbose output\n");
printf(" -h, --help Display this help message\n");
}
@@ -41,8 +45,8 @@ int main(int argc, char **argv)
int rc = EXIT_SUCCESS;
int count = 0;
int verbose_output = 0;
int record = 0;
bool verbose_output = false;
bool record = false;
char *boot_id = NULL;
char *record_id = NULL;
char *event_id = NULL;
@@ -78,16 +82,15 @@ int main(int argc, char **argv)
boot_id = optarg;
break;
case 'V':
verbose_output = 1;
verbose_output = true;
break;
case 'i':
record = 1;
record = true;
break;
case 'h':
print_usage();
exit(EXIT_SUCCESS);
case '?':
/** default */
default:
print_usage();
exit(EXIT_FAILURE);
}
+22 -58
View File
@@ -58,9 +58,7 @@ static int serialize_journal_entry(struct JournalEntry *entry, char **buff)
if (asprintf(buff, "%s\036%lld\036%s\036%s\036%s", entry->record_id, (long long int)entry->timestamp,
entry->classification, entry->event_id, entry->boot_id) < 0) {
#ifdef DEBUG
fprintf(stderr, "Error: unable to serialize data in buff\n");
#endif
telem_log(LOG_ERR, "Error: Unable to serialize data in buff\n");
rc = -1;
}
@@ -204,9 +202,7 @@ static int save_entry(FILE *fptr, struct JournalEntry *entry)
}
if ((rc = serialize_journal_entry(entry, &serialized_data)) == 0) {
#ifdef DEBUG
printf("Saving: %s\n", serialized_data);
#endif
telem_debug("DEBUG: Saving: %s\n", serialized_data);
fprintf(fptr, "%s\n", serialized_data);
fflush(fptr);
free(serialized_data);
@@ -229,9 +225,7 @@ static int read_boot_id(char buff[])
fs = fopen(BOOTID_FILE, "r");
if (!fs) {
#ifdef DEBUG
fprintf(stderr, "Unable to open %s for reading: %d\n", BOOTID_FILE, errno);
#endif
telem_log(LOG_ERR, "Error: Unable to open %s for reading: %d\n", BOOTID_FILE, errno);
return rc;
}
@@ -264,9 +258,7 @@ static int skip_n_lines(int n, FILE *fptr, int (*found_record)(char *))
struct JournalEntry *entry = NULL;
if (fptr == NULL) {
#ifdef DEBUG
fprintf(stderr, "fptr argument to skip_n_lines is invalid\n");
#endif
telem_log(LOG_ERR, "fptr argument to skip_n_lines is invalid\n");
// File descriptor in bad state
return EBADFD;
}
@@ -327,9 +319,7 @@ static int copy_to_tmp(FILE *fptr, char *tmp_path)
if (fclose(fptr_tmp) != 0) {
rc = errno;
#ifdef DEBUG
perror("Error: ");
#endif
telem_perror("Error");
}
free(line);
@@ -350,22 +340,18 @@ TelemJournal *open_journal(const char *journal_file)
fptr = fopen(journal_file, "a+");
}
if (fptr == NULL) {
#ifdef DEBUG
perror("Error while opening journal file: ");
#endif
telem_perror("Error while opening journal file");
return NULL;
}
if (read_boot_id(boot_id) != 0) {
#ifdef DEBUG
perror("Error while reading boot_id: ");
#endif
telem_perror("Error while reading boot_id");
return NULL;
}
telem_journal = malloc(sizeof(struct TelemJournal));
if (!telem_journal) {
fprintf(stderr, "Unable to allocate more memory\n");
telem_log(LOG_CRIT, "CRIT: Unable to allocate memory\n");
return NULL;
}
@@ -379,9 +365,7 @@ TelemJournal *open_journal(const char *journal_file)
telem_journal->latest_record_id = NULL;
telem_journal->prune_entry_callback = NULL;
#ifdef DEBUG
printf("Records in db: %d\n", telem_journal->record_count);
#endif
telem_debug("Records in db: %d\n", telem_journal->record_count);
return telem_journal;
}
@@ -433,7 +417,7 @@ static void print_record(char *record_id)
recordfp = fopen(filepath, "r");
if (!recordfp) {
telem_perror("Error when opening a record to print");
telem_log(LOG_INFO, "Could not open record %s: %s\n", record_id, strerror(errno));
return;
}
@@ -476,7 +460,7 @@ int print_journal(TelemJournal *telem_journal, char *classification,
if (rc == -1) {
return rc;
} else if (rc != 0) {
fprintf(stderr, "An error occurred while advancing journal file: %s\n", strerror(rc));
telem_log(LOG_ERR, "An error occurred while advancing journal file: %s\n", strerror(rc));
}
}
@@ -563,9 +547,7 @@ int new_journal_entry(TelemJournal *telem_journal, char *classification,
struct JournalEntry *entry = NULL;
if (telem_journal == NULL) {
#ifdef DEBUG
fprintf(stderr, "Error: telem_journal was not initialized\n");
#endif
telem_log(LOG_ERR, "telem_journal was not initialized\n");
return rc;
}
@@ -579,7 +561,7 @@ int new_journal_entry(TelemJournal *telem_journal, char *classification,
entry = malloc(sizeof(struct JournalEntry));
if (!entry) {
fprintf(stderr, "Error: unable to allocate more memory\n");
telem_log(LOG_CRIT, "CRIT: unable to allocate memory\n");
return rc;
}
entry->classification = NULL;
@@ -588,16 +570,12 @@ int new_journal_entry(TelemJournal *telem_journal, char *classification,
entry->boot_id = NULL;
if (get_random_id(&record_id) != 0) {
#ifdef DEBUG
fprintf(stderr, "Error: unable to generate random id\n");
#endif
telem_log(LOG_ERR, "Erorr: Unable to generate random id\n");
goto quit;
}
if (read_boot_id(boot_id) != 0) {
#ifdef DEBUG
fprintf(stderr, "Error: unable to read boot_id\n");
#endif
telem_log(LOG_ERR, "Error: Unable to read boot_id\n");
goto quit;
}
@@ -615,9 +593,7 @@ int new_journal_entry(TelemJournal *telem_journal, char *classification,
if ((rc = save_entry(telem_journal->fptr, entry)) == 0) {
telem_journal->record_count = telem_journal->record_count + 1;
#ifdef DEBUG
fprintf(stdout, "%d records in journal\n", telem_journal->record_count);
#endif
telem_debug("DEBUG: %d records in journal\n", telem_journal->record_count);
}
free(telem_journal->latest_record_id);
@@ -647,9 +623,7 @@ int prune_journal(struct TelemJournal *telem_journal, char *tmp_dir)
// jump to line# count
if ((rc = skip_n_lines(count, telem_journal->fptr, telem_journal->prune_entry_callback)) != 0) {
#ifdef DEBUG
fprintf(stderr, "Error: skipping %d journal lines\n", count);
#endif
telem_log(LOG_ERR, "Error skipping %d journal lines\n", count);
// if rc == -1 (n > #lines in file, change to errno style)
return (rc == -1) ? EADDRNOTAVAIL : rc;
}
@@ -665,38 +639,28 @@ int prune_journal(struct TelemJournal *telem_journal, char *tmp_dir)
}
// create new file with rest of file
if ((rc = copy_to_tmp(telem_journal->fptr, tmp_file_path)) != 0) {
#ifdef DEBUG
fprintf(stderr, "Error: copying partial journal to temp journal file\n");
#endif
telem_log(LOG_ERR, "Error copying partial journal to temp journal file\n");
goto quit;
}
// close file handler
if ((rc = fclose(telem_journal->fptr)) != 0) {
#ifdef DEBUG
fprintf(stderr, "Error: closing journal file handler\n");
#endif
telem_log(LOG_ERR, "Error closing journal file handler\n");
goto quit;
}
// overwrite file
if ((rc = rename(tmp_file_path, telem_journal->journal_file)) != 0) {
#ifdef DEBUG
fprintf(stderr, "Error: while overwriting journal file\n");
#endif
telem_log(LOG_ERR, "Error while overwriting journal file\n");
goto quit;
}
// reopen file handler
telem_journal->fptr = fopen(telem_journal->journal_file, "a+");
if (!telem_journal->fptr) {
#ifdef DEBUG
fprintf(stderr, "Error: re-opening journal file\n");
#endif
telem_log(LOG_ERR, "Error re-opening journal file\n");
return rc;
}
// update record count
telem_journal->record_count = telem_journal->record_count - count;
#ifdef DEBUG
fprintf(stdout, "record_count: %d\n", telem_journal->record_count);
#endif
telem_debug("DEBUG: record_count: %d\n", telem_journal->record_count);
}
rc = 0;
+6
View File
@@ -5,5 +5,11 @@ bin_PROGRAMS += \
%D%/journal.c \
src/util.c \
src/common.c
%C%_telem_journal_CFLAGS = \
$(AM_CFLAGS)
if LOG_SYSTEMD
%C%_telem_journal_CFLAGS += $(SYSTEMD_JOURNAL_CFLAGS)
%C%_telem_journal_LDADD = $(SYSTEMD_JOURNAL_LIBS)
endif
# vim: filetype=automake tabstop=8 shiftwidth=8 noexpandtab
-1
View File
@@ -6,7 +6,6 @@ bin_PROGRAMS = \
%D%/probe.c \
%D%/telemdaemon.c \
%D%/telemdaemon.h \
%D%/iorecord.c \
%D%/journal/journal.c \
%D%/journal/journal.h
+4 -4
View File
@@ -1,7 +1,7 @@
/*
* This program is part of the Clear Linux Project
*
* Copyright 2015 Intel Corporation
* Copyright 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify it under
* the terms and conditions of the GNU Lesser General Public License, as
@@ -17,6 +17,7 @@
#pragma once
#include <stdio.h>
#include <errno.h>
#include "config.h"
@@ -35,15 +36,14 @@
#include <systemd/sd-journal.h>
#endif
#else
#include <errno.h>
#include <string.h>
#include <syslog.h>
#endif
#ifdef DEBUG
#define telem_debug(...) do { \
(telem_log(LOG_DEBUG, "%s():[%d]", __func__, __LINE__), \
telem_log(LOG_DEBUG, __VA_ARGS__)); \
telem_log(LOG_DEBUG, "%s():[%d] ", __func__, __LINE__); \
telem_log(LOG_DEBUG, __VA_ARGS__); \
} while (0);
#else
#define telem_debug(...) do {} while (0);
+8 -2
View File
@@ -27,7 +27,13 @@
#include "configuration.h"
#include "telempostdaemon.h"
bool (*post_record_ptr)(char *[], char *) = post_record_http;
/*
* Using a function pointer for unit testing to isolate the call to actual post function.
* The call to post the record to the server is stubbed out in the unit tests
* using pointer to a fake function.
*/
bool (*post_record_ptr)(char *[], char *, char *) = post_record_http;
void print_usage(char *prog)
{
@@ -72,7 +78,7 @@ int main(int argc, char **argv)
}
}
initialize_daemon(&daemon);
initialize_post_daemon(&daemon);
daemon.current_spool_size = get_spool_dir_size();
+3 -9
View File
@@ -51,12 +51,6 @@
#include "telemdaemon.h"
#include "configuration.h"
/*
* Using a function pointer for unit testing to isolate the call to actual post function.
* The call to post the record to the server is stubbed out in the unit tests
* using pointer to a fake function.
*/
void print_usage(char *prog)
{
printf("%s: Usage\n", prog);
@@ -111,7 +105,7 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
}
initialize_daemon(&daemon);
initialize_probe_daemon(&daemon);
sigemptyset(&mask);
@@ -249,8 +243,8 @@ int main(int argc, char **argv)
}
if (fdsi.ssi_signo == SIGTERM || fdsi.ssi_signo == SIGINT) {
telem_log(LOG_INFO, "Received either a \
SIGINT/SIGTERM signal\n");
telem_log(LOG_INFO, "Received either a "
"SIGINT/SIGTERM signal\n");
goto clean_exit;
}
+19
View File
@@ -41,6 +41,8 @@
#include "probe.h"
#include "telemetry.h"
#define FRAMES_MAX 64
static Dwfl *d_core = NULL;
/*
@@ -298,6 +300,12 @@ static int frame_cb(Dwfl_Frame *frame, void *userdata)
}
}
nc_string_append_printf(*bt, "\n");
if (frame_counter >= FRAMES_MAX) {
errorstr = NULL;
return DWARF_CB_ABORT;
}
return DWARF_CB_OK;
}
@@ -390,6 +398,12 @@ static int process_corefile(nc_string **backtrace)
*backtrace = nc_string_dup("");
if (dwfl_getthreads(d_core, thread_cb, backtrace) != DWARF_CB_OK) {
/* We aborted unwinding, due to too many frames.
* We don't consider this as an error.
*/
if (frame_counter >= FRAMES_MAX) {
return 0;
}
/* When errors occur during the unwinding, we reach this point.
* If an error string is set for the particular error, send an
* "error" record to capture at least a partial backtrace if
@@ -656,6 +670,11 @@ int main(int argc, char **argv)
}
}
if (frame_counter >= FRAMES_MAX) {
telem_log(LOG_ERR, "Too many frames. Backtrace truncated.\n");
nc_string_append_printf(header, "Too many frames. Backtrace truncated.\n");
}
nc_string_prepend(backtrace, header->str);
if (!send_data(&backtrace, default_severity, clr_class)) {
+1 -1
View File
@@ -90,7 +90,7 @@ static char *create_payload(unsigned options)
num_bundles = scandir("/usr/share/clear/bundles", &entries, nodots, alphasort);
if (num_bundles < 0) {
telem_log(LOG_ERR, "scandir failed: %s\n", strerror(errno));
telem_perror("scandir failed");
free(payload);
return NULL;
}
+2 -2
View File
@@ -51,7 +51,7 @@ int main(void)
// Gets the size of the kernel ring buffer
log_size = klogctl(SYSLOG_ACTION_SIZE_BUFFER, NULL, 0);
if (log_size < 0) {
telem_log(LOG_ERR, "Cannot read size of kernel ring buffer: %s\n", strerror(errno));
telem_perror("Cannot read size of kernel ring buffer");
return 1;
}
@@ -70,7 +70,7 @@ int main(void)
memset(bufp, 0, buflen);
bytes_read = klogctl(SYSLOG_ACTION_READ, bufp, (int)buflen);
if (bytes_read < 0) {
telem_log(LOG_ERR, "Cannot read contents of kernel ring buffer: %s\n", strerror(errno));
telem_perror("Cannot read contents of kernel ring buffer");
return 1;
}
+9 -12
View File
@@ -91,10 +91,8 @@ void split_buf_by_line(char *bufp, int bytes)
start[linelength] = '\0';
parse_single_line(start, linelength);
if (oops_processed == true) {
#ifdef DEBUG
printf("[%s] oops_processed detected !\n", __func__);
#endif
break;
telem_debug("oops_processed detected !\n");
break;
}
linelength = 0;
}
@@ -128,7 +126,8 @@ void klog_process_oops_msgs(struct oops_log_msg *msg)
//Add the newline character to the end of each line
line = msg->lines[i];
linelength = strlen(line);
strncpy(bp, line, linelength);
// Copy the line (without the terminating NULL)
memcpy(bp, line, linelength);
bp[linelength] = '\n';
done += linelength + 1;
bp = contents + done;
@@ -136,16 +135,14 @@ void klog_process_oops_msgs(struct oops_log_msg *msg)
struct oops_log_msg oops_msg;
if (handle_entire_oops(contents, (long)size, &oops_msg)) {
#ifdef DEBUG
printf("Raw message:\n");
#ifdef DEBUG
telem_debug("DEBUG: Raw oops message:\n");
for (int i = 0; i < oops_msg.length; i++) {
printf("%s\n", oops_msg.lines[i]);
telem_log(LOG_DEBUG, "%s\n", oops_msg.lines[i]);
}
#endif
#endif
payload = parse_payload(&oops_msg);
#ifdef DEBUG
printf("Payload Parsed :%s\n", payload->str);
#endif
telem_debug("DEBUG: Payload Parsed :%s\n", payload->str);
oops_msg_cleanup(&oops_msg);
send_data(payload->str, (char *)oops_msg.pattern->classification, (uint32_t)oops_msg.pattern->severity);
nc_string_free(payload);
+36 -7
View File
@@ -9,24 +9,48 @@ bin_PROGRAMS += \
%D%/bertprobe
%C%_pythonprobe_SOURCES = %D%/python-probe.c
%C%_pythonprobe_CFLAGS = $(AM_CFLAGS)
%C%_pythonprobe_LDADD = $(top_builddir)/src/libtelemetry.la
%C%_pythonprobe_LDFLAGS = \
$(AM_LDFLAGS) \
-pie
if LOG_SYSTEMD
if HAVE_SYSTEMD_JOURNAL
%C%_pythonprobe_CFLAGS += $(SYSTEMD_JOURNAL_CFLAGS)
%C%_pythonprobe_LDADD += $(SYSTEMD_JOURNAL_LIBS)
endif
endif
%C%_hprobe_SOURCES = %D%/hello.c
%C%_hprobe_LDADD = $(top_builddir)/src/libtelemetry.la
%C%_hprobe_CFLAGS = $(AM_CFLAGS)
%C%_hprobe_LDFLAGS = \
$(AM_LDFLAGS) \
-pie
if LOG_SYSTEMD
if HAVE_SYSTEMD_JOURNAL
%C%_hprobe_CFLAGS += $(SYSTEMD_JOURNAL_CFLAGS)
%C%_hprobe_LDADD += $(SYSTEMD_JOURNAL_LIBS)
endif
endif
%C%_bertprobe_SOURCES = %D%/bert_probe.c \
src/nica/b64enc.c
%C%_bertprobe_CFLAGS = $(AM_CFLAGS)
%C%_bertprobe_LDADD = $(top_builddir)/src/libtelemetry.la
%C%_bertprobe_LDFLAGS = \
$(AM_LDFLAGS) \
-pie
if LOG_SYSTEMD
if HAVE_SYSTEMD_JOURNAL
%C%_bertprobe_CFLAGS += $(SYSTEMD_JOURNAL_CFLAGS)
%C%_bertprobe_LDADD += $(SYSTEMD_JOURNAL_LIBS)
endif
endif
%C%_telem_record_gen_SOURCES = %D%/telem_record_gen.c
%C%_telem_record_gen_CFLAGS = \
$(AM_CFLAGS)
@@ -35,6 +59,14 @@ bin_PROGRAMS += \
$(AM_LDFLAGS) \
-pie
if LOG_SYSTEMD
if HAVE_SYSTEMD_JOURNAL
%C%_telem_record_gen_CFLAGS += $(SYSTEMD_JOURNAL_CFLAGS)
%C%_telem_record_gen_LDADD += $(SYSTEMD_JOURNAL_LIBS)
endif
endif
%C%_pstoreclean_SOURCES = %D%/pstore_clean.c
%C%_pstoreclean_CFLAGS = \
$(AM_CFLAGS)
@@ -113,13 +145,6 @@ endif
-pie
if LOG_SYSTEMD
if HAVE_SYSTEMD_JOURNAL
%C%_klogscanner_CFLAGS += \
$(SYSTEMD_JOURNAL_CFLAGS)
%C%_klogscanner_LDADD += \
$(SYSTEMD_JOURNAL_LIBS)
endif
if HAVE_SYSTEMD_JOURNAL
%C%_klogscanner_CFLAGS += \
$(SYSTEMD_JOURNAL_CFLAGS)
@@ -149,6 +174,10 @@ bin_PROGRAMS += \
%C%_journalprobe_LDFLAGS = \
$(AM_LDFLAGS) \
-pie
if LOG_SYSTEMD
%C%_journalprobe_CFLAGS += $(SYSTEMD_JOURNAL_CFLAGS)
%C%_journalprobe_LDADD += $(SYSTEMD_JOURNAL_LIBS)
endif
endif
endif
+1 -1
View File
@@ -132,7 +132,7 @@ int main(int argc, char **argv)
if (mkdir(MOUNT, 0755) < 0) {
//If there is an error other than an existing directory
if (errno != EEXIST) {
telem_log(LOG_ERR, "Error creating directory /dev/pstore : %s\n", strerror(errno));
telem_perror("Error creating directory /dev/pstore");
//bail out?
exit(EXIT_FAILURE);
}
+4 -10
View File
@@ -65,14 +65,12 @@ void handle_complete_oops_message(struct oops_log_msg *msg)
#ifdef DEBUG
for (int i = 0; i < msg->length; i++) {
printf("%s\n", msg->lines[i]);
telem_debug("DEBUG: %s\n", msg->lines[i]);
}
#endif
payload = parse_payload(msg);
#ifdef DEBUG
printf("Payload Parsed :%s\n", payload->str);
#endif
telem_debug("DEBUG: Payload Parsed :%s\n", payload->str);
send_data(payload->str, (char *)msg->pattern->classification, (uint32_t)msg->pattern->severity);
nc_string_free(payload);
}
@@ -232,9 +230,7 @@ int main(int argc, char **argv)
// Look for only dmesg logs. Ignore other types of pstore dumps for now.
if (sscanf(entry->d_name, "dmesg-efi-%" PRIu64, &id) == 1) {
parse_id(id, &count, &part);
#ifdef DEBUG
printf("Extracted count :%d, part : %d\n", count, part);
#endif
telem_debug("DEBUG: Extracted count :%d, part : %d\n", count, part);
} else {
continue;
}
@@ -262,9 +258,7 @@ int main(int argc, char **argv)
nc_hashmap_iter_init(hash, &iter);
while (nc_hashmap_iter_next(&iter, (void **)&key, (void **)&value)) {
#ifdef DEBUG
printf("Count in the hash: %d\n", NC_UNHASH_KEY(key));
#endif
telem_debug("DEBUG: Count in the hash: %d\n", NC_UNHASH_KEY(key));
head = (struct chunk_list *)value;
elem = head;
+58 -65
View File
@@ -1,7 +1,7 @@
/*
* This program is part of the Clear Linux Project
*
* Copyright 2015 Intel Corporation
* Copyright 2019 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify it under
* the terms and conditions of the GNU Lesser General Public License, as
@@ -32,7 +32,6 @@
#include "common.h"
#include "telemetry.h"
static char *config_file = NULL;
static uint32_t severity = 1;
static char *opt_class = NULL;
static char *opt_payload = NULL;
@@ -53,6 +52,7 @@ static const struct option prog_opts[] = {
{ "payload-file", required_argument, 0, 'P' },
{ "record-version", required_argument, 0, 'R' },
{ "event-id", required_argument, 0, 'e' },
{ "config-file", required_argument, 0, 'f' },
{ 0, 0, 0, 0 }
};
@@ -74,31 +74,18 @@ static void print_help(void)
printf(" -e, --event-id Event id to use in the record\n");
printf(" -o, --echo Echo record to stdout\n");
printf(" -n, --no-post Do not post record just print\n");
printf(" -f, --config_file Specify a configuration file other than default\n");
printf("\n");
}
const unsigned int count_chars(const char *check, const char character)
static bool parse_options(int argc, char **argv)
{
unsigned int count = 0U;
if (check == NULL) {
return count;
}
for (; *check != '\0'; ++check) {
if (*check == character) {
++count;
}
}
return count;
}
int parse_options(int argc, char **argv)
{
int ret = 0;
bool ret = false;
char *endptr = NULL;
long unsigned int tmp = 0;
int opt;
while ((opt = getopt_long(argc, argv, "hc:Vs:c:p:P:R:e:on", prog_opts, NULL)) != -1) {
while ((opt = getopt_long(argc, argv, "hc:Vs:c:p:P:R:e:onf:", prog_opts, NULL)) != -1) {
switch (opt) {
case 'h':
print_help();
@@ -159,31 +146,38 @@ int parse_options(int argc, char **argv)
case 'n':
opt_nopost = true;
break;
case 'f':
if (tm_set_config_file(optarg) != 0) {
telem_log(LOG_ERR, "Configuration file path not valid\n");
exit(EXIT_FAILURE);
}
break;
}
}
ret = 1;
ret = true;
fail:
return ret;
}
int validate_opts(void)
static bool validate_opts(void)
{
size_t len;
int ret = 0;
size_t i, len;
int x, slashes = 0;
const char alphab[] = EVENT_ID_ALPHAB;
bool ret = false;
/* classification */
if (opt_class == NULL) {
fprintf(stderr, "Error: Classification required. See --help.\n");
return ret;
}
len = strlen(opt_class);
if ((len == 0) || (len > 120)) {
if ((len == 0) || (len > MAX_CLASS_LENGTH)) {
fprintf(stderr, "Error: Valid size for classification "
"is 1-120 chars\n");
"is 1-%d chars\n", MAX_CLASS_LENGTH);
return ret;
}
@@ -195,12 +189,27 @@ int validate_opts(void)
}
}
if (count_chars(opt_class, '/') != 2) {
for (i = 0, x = 0; i <= (len - 1); i++, x++) {
if (opt_class[i] == '/') {
slashes++;
x = 0;
} else {
if (x > MAX_SUBCAT_LENGTH) {
fprintf(stderr, "Error: Classification strings"
" between slashes should have at most"
" %d chars\n", MAX_SUBCAT_LENGTH);
return ret;
}
}
}
if (slashes != 2) {
fprintf(stderr, "Error: Classification needs to be in "
"most/to/least specific format, 2 \'/\' required.\n");
return ret;
}
/* Severity */
if ((severity) < 1 || (severity > 4)) {
fprintf(stderr, "Error: Valid range for severity is 1-4\n");
@@ -221,29 +230,12 @@ int validate_opts(void)
}
}
return 1;
return true;
}
int allocate_payload_buffer(char **payload)
static bool get_payload_from_file(char **payload)
{
int ret = 0;
*payload = (char *)malloc(MAX_PAYLOAD_LENGTH);
if (*payload == NULL) {
goto out1;
}
*payload = memset(*payload, 0, MAX_PAYLOAD_LENGTH);
ret = 1;
out1:
return ret;
}
int get_payload_from_file(char **payload)
{
int ret = 1;
bool ret = false;
FILE *fp = NULL;
size_t bytes_in = 0;
@@ -260,10 +252,10 @@ int get_payload_from_file(char **payload)
/* if fread fails */
if (bytes_in == 0 && ferror(fp) != 0) {
ret = 0;
goto out;
}
ret = true;
out:
if (fp) {
fclose(fp);
@@ -272,7 +264,7 @@ out:
}
void get_payload_from_opt(char **payload)
static void get_payload_from_opt(char **payload)
{
size_t len = 0;
@@ -280,10 +272,12 @@ void get_payload_from_opt(char **payload)
if (len >= MAX_PAYLOAD_LENGTH) {
len = MAX_PAYLOAD_LENGTH - 1;
}
strncpy(*payload, opt_payload, len);
/* "payload" is pre-allocated zeroed buffer of MAX_PAYLOAD_LENGTH */
memcpy(*payload, opt_payload, len);
}
void get_payload_from_stdin(char **payload)
static void get_payload_from_stdin(char **payload)
{
size_t bytes_in = 0;
int c;
@@ -299,40 +293,40 @@ void get_payload_from_stdin(char **payload)
}
int get_payload(char **payload)
static bool get_payload(char **payload)
{
int ret = 0;
bool ret = false;
if (!allocate_payload_buffer(payload)) {
goto out1;
}
*payload = (char *)calloc(sizeof(char), MAX_PAYLOAD_LENGTH);
if (*payload == NULL)
return false;
if (opt_payload_file) {
if (get_payload_from_file(payload)) {
ret = 1;
ret = true;
}
} else if (opt_payload) {
get_payload_from_opt(payload);
ret = 1;
ret = true;
} else {
get_payload_from_stdin(payload);
ret = 1;
ret = true;
}
if (ret == 0) {
if (ret == false) {
free(*payload);
*payload = NULL;
}
out1:
return ret;
}
int instanciate_record(struct telem_ref **t_ref, char *payload)
static int instanciate_record(struct telem_ref **t_ref, char *payload)
{
int ret = 0;
@@ -352,7 +346,7 @@ out1:
return ret;
}
int send_record(char *payload)
static int send_record(char *payload)
{
struct telem_ref *t_ref = NULL;
int ret = 0;
@@ -371,7 +365,7 @@ out:
return ret;
}
int print_record(char *payload)
static int print_record(char *payload)
{
struct telem_ref *t_ref = NULL;
int ret = 0;
@@ -415,7 +409,6 @@ int main(int argc, char **argv)
ret = EXIT_SUCCESS;
fail:
free(config_file);
free(opt_class);
free(opt_payload);
free(opt_event_id);
+52 -12
View File
@@ -202,9 +202,15 @@ void transmit_spooled_record(char *record_path, bool *post_succeeded, long size)
FILE *fp = NULL;
char *headers[NUM_HEADERS];
char *payload = NULL;
int i, k;
char line[LINE_MAX] = { 0 };
int num_headers = 0, k;
#if (LINE_MAX > PATH_MAX)
char line[LINE_MAX+1] = { 0 };
#else
char line[PATH_MAX+1] = { 0 };
#endif
long offset;
char *cfg_file = NULL;
uint32_t cfg_prefix = 0;
fp = fopen(record_path, "r");
if (fp == NULL) {
@@ -212,16 +218,47 @@ void transmit_spooled_record(char *record_path, bool *post_succeeded, long size)
return;
}
for (i = 0; i < NUM_HEADERS; i++) {
const char *header_name = get_header_name(i);
if (!fgets(line, LINE_MAX, fp)) {
// First line optionally contains configuration file path
if (fread(&cfg_prefix, CFG_PREFIX_LENGTH, 1, fp) != 1) {
telem_log(LOG_ERR, "Error while parsing spooled record configuration info.\n");
goto read_error;
}
if (cfg_prefix == CFG_PREFIX_32BIT) {
size_t pathlen;
char *nl;
if (!fgets(line, sizeof(line), fp)) {
telem_log(LOG_ERR, "Error while parsing record file\n");
fclose(fp);
return;
goto read_error;
}
if ((nl = strchr(line, '\n')) != NULL) {
*nl = '\0';
}
pathlen = strlen(line);
cfg_file = malloc(pathlen + 1);
if (cfg_file == NULL) {
telem_log(LOG_ERR, "Could not allocate memory for config file path\n");
goto read_error;
}
strcpy (cfg_file, line);
telem_debug("DEBUG: cfg_file: %s\n", cfg_file);
} else {
cfg_file = NULL;
rewind(fp);
}
for (num_headers = 0; num_headers < NUM_HEADERS; num_headers++) {
const char *header_name = get_header_name(num_headers);
if (!fgets(line, sizeof(line), fp)) {
telem_log(LOG_ERR, "Error while parsing record file\n");
goto read_error;
}
//Get rid of trailing newline
strtok(line, "\n");
if (get_header(line, header_name, &headers[i])) {
if (get_header(line, header_name, &headers[num_headers])) {
continue;
} else {
telem_log(LOG_ERR, "transmit_spooled_record: Incorrect"
@@ -242,8 +279,7 @@ void transmit_spooled_record(char *record_path, bool *post_succeeded, long size)
if (!payload) {
telem_log(LOG_ERR, "Could not allocate memory for payload\n");
fclose(fp);
return;
goto read_error;
}
memset(payload, 0, (size_t)size);
@@ -254,7 +290,7 @@ void transmit_spooled_record(char *record_path, bool *post_succeeded, long size)
goto read_error;
}
*post_succeeded = post_record_http(headers, payload);
*post_succeeded = post_record_http(headers, payload, cfg_file);
if (*post_succeeded) {
unlink(record_path);
}
@@ -267,9 +303,13 @@ read_error:
fclose(fp);
}
for (k = 0; k < i; k++) {
for (k = 0; k < num_headers; k++) {
free(headers[k]);
}
if (cfg_file) {
free(cfg_file);
}
}
int spool_record_compare(const void *entrya, const void *entryb, void *path)
+80 -6
View File
@@ -36,7 +36,7 @@
#include "log.h"
#include "configuration.h"
void initialize_daemon(TelemDaemon *daemon)
void initialize_probe_daemon(TelemDaemon *daemon)
{
client_list_head head;
LIST_INIT(&head);
@@ -165,7 +165,7 @@ bool handle_client(TelemDaemon *daemon, nfds_t ind, client *cl)
cl->offset = 0;
cl->size = RECORD_SIZE_LEN;
processed = true;
telem_log(LOG_DEBUG, "Record processed for client %d\n", cl->fd);
telem_debug("DEBUG: Record processed for client %d\n", cl->fd);
break;
}
} while (len > 0);
@@ -247,6 +247,61 @@ void machine_id_replace(char **machine_header, char *machine_id_override)
free(old_header);
}
static void stage_record(char *filepath, char *headers[], char *body, char *cfg_file)
{
int tmpfd;
FILE *tmpfile = NULL;
telem_debug("DEBUG: filepath:%s\n", filepath);
telem_debug("DEBUG: body:%s\n", body);
telem_debug("DEBUG: cfg:%s\n", cfg_file);
// Use default path if not provided
if (filepath == NULL) {
telem_log(LOG_ERR, "filepath value must be provided, aborting\n");
exit(EXIT_FAILURE);
}
tmpfd = mkstemp(filepath);
if (!tmpfd) {
telem_perror("Error opening staging file");
close(tmpfd);
if (unlink(filepath)) {
telem_perror("Error deleting staging file");
}
goto clean_exit;
}
// open file
tmpfile = fdopen(tmpfd, "a");
if (!tmpfile) {
telem_perror("Error opening temp stage file");
close(tmpfd);
if (unlink(filepath)) {
telem_perror("Error deleting temp stage file");
}
goto clean_exit;
}
// write cfg info if exists
if (cfg_file != NULL) {
fprintf(tmpfile, "%s%s\n", CFG_PREFIX, cfg_file);
}
// write headers
for (int i = 0; i < NUM_HEADERS; i++) {
fprintf(tmpfile, "%s\n", headers[i]);
}
//write body
fprintf(tmpfile, "%s\n", body);
fflush(tmpfile);
fclose(tmpfile);
clean_exit:
return;
}
void process_record(TelemDaemon *daemon, client *cl)
{
int i = 0;
@@ -259,11 +314,30 @@ void process_record(TelemDaemon *daemon, client *cl)
char *msg;
char *body;
char *recordpath = NULL;
char *cfg_file = NULL;;
size_t cfg_info_size = 0;
uint8_t *buf;
header_size = *(uint32_t *)cl->buf;
message_size = cl->size - header_size;
buf = cl->buf;
/* Check for an optional CFG_PREFIX in the first 32 bits */
if (*(uint32_t *)buf == CFG_PREFIX_32BIT) {
char *cfg = (char *)cl->buf;
cfg_file = cfg + CFG_PREFIX_LENGTH;
cfg_info_size = CFG_PREFIX_LENGTH + strlen(cfg_file) + 1;
telem_debug("DEBUG: cfg_file: %s\n", cfg_file);
}
buf += cfg_info_size;
header_size = *(uint32_t *)buf;
message_size = cl->size - (cfg_info_size + header_size);
telem_debug("DEBUG: cl->size: %zu\n", cl->size);
telem_debug("DEBUG: header_size: %zu\n", header_size);
telem_debug("DEBUG: message_size: %zu\n", message_size);
telem_debug("DEBUG: cfg_info_size: %zu\n", cfg_info_size);
assert(message_size > 0); //TODO:Check for min and max limits
msg = (char *)cl->buf + sizeof(uint32_t);
msg = (char *)buf + sizeof(uint32_t);
/* Copying the headers as strtok modifies the orginal buffer */
temp_headers = strndup(msg, header_size);
@@ -293,7 +367,7 @@ void process_record(TelemDaemon *daemon, client *cl)
exit(EXIT_FAILURE);
}
stage_record(recordpath, headers, body);
stage_record(recordpath, headers, body, cfg_file);
free(recordpath);
end:
free(temp_headers);
+1 -1
View File
@@ -62,7 +62,7 @@ typedef struct TelemDaemon {
*
* @param daemon A pointer to the daemon structure.
*/
void initialize_daemon(TelemDaemon *daemon);
void initialize_probe_daemon(TelemDaemon *daemon);
/**
* Add poll fd struct to the array of pollfds.
+88 -93
View File
@@ -35,6 +35,7 @@
#include "common.h"
#include "configuration.h"
#include "telemetry.h"
#include "log.h"
/**
* Return a file descriptor to either site's version file
@@ -76,9 +77,7 @@ static int set_header(char **dest, const char *prefix, char *value, size_t *head
rc = asprintf(dest, "%s: %s\n", prefix, value);
if (rc < 0) {
#ifdef DEBUG
fprintf(stderr, "CRIT: Out of memory\n");
#endif
telem_log(LOG_CRIT, "CRIT: Out of memory\n");
return -ENOMEM;
} else {
*header_size += (size_t)rc;
@@ -233,35 +232,49 @@ static int set_system_name_header(struct telem_ref *t_ref)
int fd;
char buf[SMALL_LINE_BUF] = { 0 };
char name[SMALL_LINE_BUF] = { 0 };
char variant[SMALL_LINE_BUF] = { 0 };
fd = version_file();
if (fd == -1) {
#ifdef DEBUG
fprintf(stderr, "WARNING: Cannot find os-release file\n");
#endif
telem_log(LOG_WARNING, "WARNING: Cannot find os-release file\n");
sprintf(name, "unknown");
} else {
fs = fdopen(fd, "r");
while (fgets(buf, SMALL_LINE_BUF, fs)) {
if (sscanf(buf, "ID=%s", name) < 1) {
continue;
} else {
if (sscanf(buf, "ID=%s", name) > 0) {
break;
}
}
rewind(fs);
while (fgets(buf, SMALL_LINE_BUF, fs)) {
if (sscanf(buf, "VARIANT_ID=%s", variant) > 0) {
break;
}
}
fclose(fs);
if (strlen(name) == 0) {
#ifdef DEBUG
fprintf(stderr, "WARNING: Cannot find os-release field: ID\n");
#endif
telem_log(LOG_WARNING, "WARNING: Cannot find os-release field: ID\n");
sprintf(name, "unknown");
}
fclose(fs);
if (strlen(variant) == 0) {
snprintf(buf, sizeof(buf), "%s", name);
} else {
/* We do not want the header to be greater than 80 characters, allow truncation */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-truncation"
if (snprintf(buf, sizeof(buf), "%s_%s", name, variant) > sizeof(buf)) {
telem_log(LOG_WARNING, "WARNING: truncating system name header to 80 characters\n");
}
telem_debug("DEBUG: Found variant OS information: %s\n", variant);
#pragma GCC diagnostic pop
}
}
return set_header(&(t_ref->record->headers[TM_SYSTEM_NAME]),
TM_SYSTEM_NAME_STR, name,
TM_SYSTEM_NAME_STR, buf,
&(t_ref->record->header_size));
}
@@ -285,9 +298,7 @@ static int set_system_build_header(struct telem_ref *t_ref)
fd = version_file();
if (fd == -1) {
#ifdef DEBUG
fprintf(stderr, "WARNING: Cannot find build version file\n");
#endif
telem_log(LOG_WARNING, "WARNING: Cannot find build version file\n");
sprintf(version, "0");
} else {
fs = fdopen(fd, "r");
@@ -300,9 +311,7 @@ static int set_system_build_header(struct telem_ref *t_ref)
}
if (strlen(version) == 0) {
#ifdef DEBUG
fprintf(stderr, "WARNING: Cannot find build version number\n");
#endif
telem_log(LOG_WARNING, "WARNING: Cannot find build version number\n");
sprintf(version, "0");
}
@@ -416,7 +425,7 @@ static int set_cpu_model_header(struct telem_ref *t_ref)
}
} else {
model_name = "blank";
fprintf(stderr, "NOTICE: Unable to find attribute:%s\n", attr_name);
telem_log(LOG_NOTICE, "NOTICE: Unable to find attribute:%s\n", attr_name);
}
status = set_header(
@@ -425,9 +434,7 @@ static int set_cpu_model_header(struct telem_ref *t_ref)
&(t_ref->record->header_size));
} else {
#ifdef DEBUG
fprintf(stderr, "NOTICE: Unable to open /proc/cpuinfo\n");
#endif
telem_log(LOG_NOTICE, "NOTICE: Unable to open /proc/cpuinfo\n");
status = -1;
}
@@ -461,9 +468,7 @@ static int get_dmi_value(const char *source, const char *key, char **buf)
*buf = (char *)malloc(sizeof(char) * SMALL_LINE_BUF);
if (*buf == NULL) {
#ifdef DEBUG
fprintf(stderr, "CRIT: Out of memory\n");
#endif
telem_log(LOG_CRIT, "CRIT: Out of memory\n");
return -ENOMEM;
}
@@ -486,9 +491,7 @@ static int get_dmi_value(const char *source, const char *key, char **buf)
if (new_size == 0) {
old_value = *buf;
if (asprintf(buf, "blank") < 0) {
#ifdef DEBUG
fprintf(stderr, "CRIT: Out of memory\n");
#endif
telem_log(LOG_CRIT, "CRIT: Out of memory\n");
ret = -ENOMEM;
}
free(old_value);
@@ -505,24 +508,18 @@ static int get_dmi_value(const char *source, const char *key, char **buf)
if (j == new_size) {
old_value = *buf;
if (asprintf(buf, "blank") < 0) {
#ifdef DEBUG
fprintf(stderr, "CRIT: Out of memory\n");
#endif
telem_log(LOG_CRIT, "CRIT: Out of memory\n");
ret = -ENOMEM;
}
free(old_value);
}
}
} else {
#ifdef DEBUG
fprintf(stderr, "NOTICE: Dmi file %s does not exist\n", source);
#endif
telem_debug("DEBUG: Dmi file %s does not exist\n", source);
old_value = *buf;
if (asprintf(buf, "no_%s_file", key) < 0) {
#ifdef DEBUG
fprintf(stderr, "CRIT: Out of memory\n");
#endif
telem_log(LOG_CRIT, "CRIT: Out of memory\n");
ret = -ENOMEM;
}
free(old_value);
@@ -927,17 +924,13 @@ int tm_create_record(struct telem_ref **t_ref, uint32_t severity,
*t_ref = (struct telem_ref *)malloc(sizeof(struct telem_ref));
if (*t_ref == NULL) {
#ifdef DEBUG
fprintf(stderr, "CRIT: Out of memory\n");
#endif
telem_log(LOG_CRIT, "CRIT: Out of memory\n");
return -ENOMEM;
}
(*t_ref)->record = (struct telem_record *)malloc(sizeof(struct telem_record));
if ((*t_ref)->record == NULL) {
#ifdef DEBUG
fprintf(stderr, "CRIT: Out of memory\n");
#endif
telem_log(LOG_CRIT, "CRIT: Out of memory\n");
free(*t_ref);
return -ENOMEM;
}
@@ -1010,19 +1003,13 @@ int tm_set_payload(struct telem_ref *t_ref, char *payload)
return -EINVAL;
}
t_ref->record->payload = (char *)malloc(sizeof(char) * payload_len + 1);
t_ref->record->payload = strdup(payload);
if (!t_ref->record->payload) {
#ifdef DEBUG
fprintf(stderr, "CRIT: Out of memory\n");
#endif
telem_log(LOG_CRIT, "CRIT: Out of memory\n");
return -ENOMEM;
}
memset(t_ref->record->payload, 0, sizeof(char) * payload_len + 1);
strncpy((char *)(t_ref->record->payload), (char *)payload, payload_len);
t_ref->record->payload_size = payload_len;
return ret;
@@ -1102,10 +1089,7 @@ static int tm_write_socket(int fd, char *buf, size_t nbytes)
if (b == -1 && errno != EAGAIN) {
ret = -errno;
#ifdef DEBUG
fprintf(stderr, "ERR: Write to daemon socket with"
" system error: %s\n", strerror(errno));
#endif
telem_perror("Error writing to daemon socket");
return ret;
} else if (b == -1 &&
(errno == EAGAIN || errno == EWOULDBLOCK)) {
@@ -1145,10 +1129,7 @@ static int tm_get_socket(void)
if (sfd == -1) {
ret = -errno;
#ifdef DEBUG
fprintf(stderr, "ERR: Attempt to allocate socket fd failed:"
" %s\n", strerror(errno));
#endif
telem_perror("Attempt to allocate socket fd failed");
return ret;
}
@@ -1159,10 +1140,7 @@ static int tm_get_socket(void)
if (setsockopt(sfd, SOL_SOCKET, SO_RCVTIMEO, &tv,
sizeof(tv)) < 0) {
ret = -errno;
#ifdef DEBUG
fprintf(stderr, "ERR: Failed to set socket timeout:"
" %s\n", strerror(errno));
#endif
telem_perror("Failed to set socket timeout");
goto out1;
}
@@ -1218,9 +1196,7 @@ static int tm_get_socket(void)
// Set non-blocking after the connect() succeeded
if ((sflags = fcntl(sfd, F_GETFL, NULL)) < 0) {
ret = -errno;
#ifdef DEBUG
fprintf(stderr, "ERR: Failed to get socket flags\n");
#endif
telem_log(LOG_ERR, "Failed to get socket flags\n");
goto out1;
}
@@ -1228,9 +1204,7 @@ static int tm_get_socket(void)
if (fcntl(sfd, F_SETFL, sflags) < 0) {
ret = -errno;
#ifdef DEBUG
fprintf(stderr, "ERR: Failed to set socket flags\n");
#endif
telem_log(LOG_ERR, "Failed to set socket flags\n");
goto out1;
}
@@ -1252,6 +1226,8 @@ int tm_send_record(struct telem_ref *t_ref)
int ret = 0;
int k = 0;
struct stat unused;
size_t cfg_file_name_size = 0;
const char *cfg_file_name = NULL;
k = stat(TM_OPT_OUT_FILE, &unused);
if (k == 0) {
@@ -1262,24 +1238,44 @@ int tm_send_record(struct telem_ref *t_ref)
sfd = tm_get_socket();
if (sfd < 0) {
#ifdef DEBUG
fprintf(stderr, "ERR: Failed to get socket fd: %s\n",
strerror(-sfd));
#endif
telem_log(LOG_ERR, "Failed to get socket fd: %s\n",
strerror(-sfd));
return sfd;
}
total_size = t_ref->record->header_size + t_ref->record->payload_size;
#ifdef DEBUG
fprintf(stderr, "DEBUG: Header size : %zu\n", t_ref->record->header_size);
fprintf(stderr, "DEBUG: Payload size : %zu\n", t_ref->record->payload_size);
fprintf(stderr, "DEBUG: Total size : %zu\n", total_size);
#endif
/*
* The user may want to use a custom (cmd line specified) config file.
* If that is the case, we need to include the absolute path in the data packet.
* We optionally add the string CFG:<absolute path> as the first string
* in the data. If the receiving end sees this in the data, it should
* use the config file specified to override any default telemetrics.conf
* files.
*/
cfg_file_name = get_cmd_line_config_file();
if (cfg_file_name != NULL) {
cfg_file_name_size = strlen(cfg_file_name) + 1;
total_size += (cfg_file_name_size + CFG_PREFIX_LENGTH);
}
if (cfg_file_name != NULL) {
telem_debug("DEBUG: CFG field size : %zu\n", cfg_file_name_size + CFG_PREFIX_LENGTH);
telem_debug("DEBUG: CFG file name : %s\n", cfg_file_name);
}
telem_debug("DEBUG: Header size : %zu\n", t_ref->record->header_size);
telem_debug("DEBUG: Payload size : %zu\n", t_ref->record->payload_size);
telem_debug("DEBUG: Total size : %zu\n", total_size);
/*
* Allocating buffer for what we intend to send. Buffer layout is:
* <uint32_t total_size><uint32_t header_size><headers + Payload>
* <uint32_t total_size> : so recv knows how much to read
* <custom cfg file field> : optional
* <uint32_t header_size>
* <headers + Payload>
* <null-byte>
* The additional char at the end ensures null termination
*/
@@ -1287,9 +1283,7 @@ int tm_send_record(struct telem_ref *t_ref)
data = malloc(record_size);
if (!data) {
#ifdef DEBUG
fprintf(stderr, "CRIT: Out of memory\n");
#endif
telem_log(LOG_CRIT, "CRIT: Out of memory\n");
close(sfd);
return -ENOMEM;
}
@@ -1299,6 +1293,13 @@ int tm_send_record(struct telem_ref *t_ref)
memcpy(data, &total_size, sizeof(uint32_t));
offset += sizeof(uint32_t);
if (cfg_file_name != NULL) {
memcpy(data + offset, CFG_PREFIX, CFG_PREFIX_LENGTH);
offset += CFG_PREFIX_LENGTH;
memcpy(data + offset, cfg_file_name, cfg_file_name_size);
offset += cfg_file_name_size;
}
memcpy(data + offset, &t_ref->record->header_size, sizeof(uint32_t));
offset += sizeof(uint32_t);
@@ -1311,17 +1312,11 @@ int tm_send_record(struct telem_ref *t_ref)
memcpy(data + offset, t_ref->record->payload, t_ref->record->payload_size);
#ifdef DEBUG
fprintf(stderr, "DEBUG: Data to be sent :\n\n%s\n", data + 2 * sizeof(uint32_t));
#endif
telem_debug("DEBUG: Data to be sent :\n\n%s\n", data + 2 * sizeof(uint32_t));
if ((ret = tm_write_socket(sfd, data, record_size)) == 0) {
#ifdef DEBUG
fprintf(stderr, "INFO: Successfully sent record over the socket\n");
#endif
telem_log(LOG_INFO, "INFO: Successfully sent record over the socket\n");
} else {
#ifdef DEBUG
fprintf(stderr, "ERR: Error while writing data to socket\n");
#endif
telem_log(LOG_ERR, "Error while writing data to socket\n");
}
close(sfd);
+55 -21
View File
@@ -178,7 +178,7 @@ static void initialize_record_delivery(TelemPostDaemon *daemon)
daemon->record_server_delivery_enabled = record_server_delivery_enabled_config();
}
void initialize_daemon(TelemPostDaemon *daemon)
void initialize_post_daemon(TelemPostDaemon *daemon)
{
assert(daemon);
@@ -210,7 +210,7 @@ size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
return size * nmemb;
}
bool post_record_http(char *headers[], char *body)
bool post_record_http(char *headers[], char *body, char *cfg)
{
CURL *curl;
int res = 0;
@@ -220,6 +220,22 @@ bool post_record_http(char *headers[], char *body)
long http_response = 0;
const char *cert_file = get_cainfo_config();
const char *tid_header = get_tidheader_config();
const char *saved_config_file = NULL;
if (cfg != NULL) {
saved_config_file = get_config_file();
if (set_config_file(cfg) != 0) {
telem_log(LOG_ERR, "set-config_file(): Failed to set %s\n", cfg);
// If we fail to load the specified config file, do not send the
// record out. We don't want to send the record out with different
// settings than explicitly requested.
// However, report success so the record gets deleted.
res = 0;
goto Done;
}
reload_config();
telem_debug("DEBUG: override server_addr:%s\n", server_addr_config());
}
// Initialize the libcurl global environment once per POST. This lets us
// clean up the environment after each POST so that when the daemon is
@@ -298,6 +314,17 @@ bool post_record_http(char *headers[], char *body)
curl_global_cleanup();
Done:
if (saved_config_file != NULL) {
if (set_config_file(saved_config_file) != 0) {
telem_log(LOG_ERR, "set-config_file(): Failed to set %s",
saved_config_file);
res = 1;
}
reload_config();
telem_debug("DEBUG: restored server_addr:%s\n", server_addr_config());
}
return res ? false : true;
}
@@ -405,7 +432,7 @@ static void apply_retention_policies(TelemPostDaemon *daemon, char *body)
/* Deliver record to backend if rate limiting policies are met otherwise
* spool record for future delivery */
static bool deliver_record(TelemPostDaemon *daemon, char *headers[], char *body)
static bool deliver_record(TelemPostDaemon *daemon, char *headers[], char *body, char* cfg_file)
{
bool ret = false;
@@ -427,7 +454,7 @@ static bool deliver_record(TelemPostDaemon *daemon, char *headers[], char *body)
/* Sends record if rate limiting is disabled, or all checks passed */
if (!daemon->rate_limit_enabled || (record_check_passed && byte_check_passed)) {
/* Send the record as https post */
record_sent = post_record_ptr(headers, body);
record_sent = post_record_ptr(headers, body, cfg_file);
/**
* This is the only point where an error condition could be returned
* if the record was not sent
@@ -472,13 +499,14 @@ bool process_staged_record(char *filename, bool is_retry, TelemPostDaemon *daemo
struct stat buf;
time_t current_time = time(NULL);
int64_t max_spool_size = 0;
char *cfg_file = NULL;
for (k = 0; k < NUM_HEADERS; k++) {
headers[k] = NULL;
}
/** Load record **/
if ((ret = read_record(filename, headers, &body)) == false) {
if ((ret = read_record(filename, headers, &body, &cfg_file)) == false) {
telem_log(LOG_WARNING, "unable to read record\n");
ret = true; // Record corrupted? true will remove record
goto end_processing_file;
@@ -512,9 +540,7 @@ bool process_staged_record(char *filename, bool is_retry, TelemPostDaemon *daemo
/** Record delivery **/
if (!daemon->record_server_delivery_enabled) {
#ifdef DEBUG
telem_log(LOG_WARNING, "record server delivery disabled\n");
#endif
telem_log(LOG_INFO, "record server delivery disabled\n");
// Not an error condition
ret = true;
goto end_processing_file;
@@ -522,9 +548,7 @@ bool process_staged_record(char *filename, bool is_retry, TelemPostDaemon *daemo
/** Spool policies **/
if (inside_direct_spool_window(daemon, time(NULL))) {
#ifdef DEBUG
telem_log(LOG_INFO, "process_record: delivering directly to spool\n");
#endif
/* Check spool max size conf */
max_spool_size = spool_max_size_config();
if (max_spool_size != -1 &&
@@ -545,7 +569,7 @@ bool process_staged_record(char *filename, bool is_retry, TelemPostDaemon *daemo
}
/** Deliver or spool **/
ret = deliver_record(daemon, headers, body);
ret = deliver_record(daemon, headers, body, cfg_file);
end_processing_file:
/** Update spool size if record will be removed **/
@@ -559,6 +583,9 @@ end_processing_file:
free(headers[k]);
}
if (cfg_file != NULL) {
free(cfg_file);
}
return ret;
}
@@ -616,7 +643,8 @@ int staging_records_loop(TelemPostDaemon *daemon)
void run_daemon(TelemPostDaemon *daemon)
{
int ret;
int retry_attempt = MAX_RETRY_ATTEMPTS;
/* retry_attempt of zero indicates we don't need to retry */
int retry_attempt = 0;
int spool_process_time = spool_process_time_config();
bool daemon_recycling_enabled = daemon_recycling_enabled_config();
time_t last_spool_run_time = time(NULL);
@@ -627,7 +655,7 @@ void run_daemon(TelemPostDaemon *daemon)
assert(daemon->pollfds[signlfd].fd);
assert(daemon->pollfds[watchfd].fd);
/* Post at boot failed initialize retries variable */
/* If we failed to send spooled records, indicate we need to retry */
if (daemon->bypass_http_post_ts != 0) {
retry_attempt = 1;
}
@@ -636,7 +664,8 @@ void run_daemon(TelemPostDaemon *daemon)
int retry_delay = spool_process_time;
malloc_trim(0);
if (retry_attempt < MAX_RETRY_ATTEMPTS) {
/* check if we need to retry sending spooled records */
if (retry_attempt > 0) {
retry_delay = retry_attempt * retry_attempt;
daemon->bypass_http_post_ts = 0;
telem_log(LOG_INFO, "Record delivery failed will retry in %d seconds",
@@ -712,18 +741,23 @@ void run_daemon(TelemPostDaemon *daemon)
telem_log(LOG_INFO, "Telemetry post daemon exiting for recycling\n");
break;
}
/* Check if this is a retry */
if (retry_attempt < MAX_RETRY_ATTEMPTS) {
/* Check if this was a retry attempt */
if (retry_attempt > 0) {
/* Stop attempting retries if successful, increment counter if not */
if (staging_records_loop(daemon) == 0) {
retry_attempt = MAX_RETRY_ATTEMPTS + 1;
retry_attempt = 0;
} else {
retry_attempt++;
}
} else if (retry_attempt == MAX_RETRY_ATTEMPTS) {
retry_attempt = MAX_RETRY_ATTEMPTS + 1;
telem_log(LOG_ERR, "Record deliver failed after %d attempts",
MAX_RETRY_ATTEMPTS);
/* Give up if counter reaches MAX_RETRY_ATTEMPTS */
if (retry_attempt == MAX_RETRY_ATTEMPTS) {
telem_log(LOG_ERR, "Record deliver failed after %d attempts",
MAX_RETRY_ATTEMPTS);
retry_attempt = 0;
}
}
/* Check spool */
if (difftime(now, last_spool_run_time) >= spool_process_time) {
spool_records_loop(&(daemon->current_spool_size));
+5 -3
View File
@@ -65,7 +65,7 @@ typedef struct TelemPostDaemon {
*
* @param daemon a pointer to telemetry post daemon
*/
void initialize_daemon(TelemPostDaemon *daemon);
void initialize_post_daemon(TelemPostDaemon *daemon);
/**
* Starts daemon
@@ -105,8 +105,10 @@ int staging_records_loop(TelemPostDaemon *daemon);
*
* @param headers a pointer to an array with keys and values
* @param body a pointer to the payload
* @param cfg_file a pointer to a non-default configuration
* file to be used.
*/
bool post_record_http(char *headers[], char *body);
bool post_record_http(char *headers[], char *body, char *cfg_file);
/**
* Pointer to function to isolate backend call during
@@ -115,7 +117,7 @@ bool post_record_http(char *headers[], char *body);
* @param headers pointer to array of keys
* @param body a pinter to payload
* */
extern bool (*post_record_ptr)(char *headers[], char *body);
extern bool (*post_record_ptr)(char *headers[], char *body, char *cfg_file);
/** Helper functions **/
/* rate limit check */
+5 -13
View File
@@ -33,6 +33,7 @@
#include "common.h"
#include "util.h"
#include "log.h"
bool get_header(const char *haystack, const char *needle, char **line)
{
@@ -100,10 +101,7 @@ long get_directory_size(const char *dir_path)
dir = opendir(dir_path);
if (!dir) {
ret = -errno;
#ifdef DEBUG
fprintf(stderr, "ERR: Error opening spool dir: %s\n",
strerror(errno));
#endif
telem_perror("Error opening spool dir");
return ret;
}
@@ -113,19 +111,15 @@ long get_directory_size(const char *dir_path)
}
ret = asprintf(&file_path, "%s/%s", dir_path, de->d_name);
if (ret < 0) {
#ifdef DEBUG
fprintf(stderr, "CRIT: Cannot allocate memory\n");
#endif
telem_log(LOG_CRIT, "CRIT: Cannot allocate memory\n");
closedir(dir);
return -ENOMEM;
}
ret = lstat(file_path, &buf);
if (ret < 0) {
#ifdef DEBUG
fprintf(stderr, "ERR: Could not stat file %s: %s\n",
telem_log(LOG_ERR, "Could not stat file %s: %s\n",
file_path, strerror(errno));
#endif
} else {
total_size += (buf.st_blocks * 512);
}
@@ -204,9 +198,7 @@ int validate_classification(char *classification)
}
if (slashes != 2) {
#ifdef DEBUG
fprintf(stderr, "ERR: Classification string should have two /s.\n");
#endif
telem_log(LOG_ERR, "Classification string should have two /s.\n");
return 1;
}
+51 -7
View File
@@ -55,18 +55,61 @@ START_TEST(check_read_valid_config)
}
END_TEST
START_TEST(check_read_valid_config_defaults)
START_TEST(check_default_config)
{
char *config_file = TOPSRCDIR "/src/data/example.conf";
configuration config = { { 0 }, { 0 }, { 0 }, false, NULL };
int ret = set_default_config_values(&config);
ck_assert(ret == true);
ck_assert_str_eq(config.strValues[CONF_SERVER_ADDR], DEFAULT_SERVER_ADDR);
ck_assert_str_eq(config.strValues[CONF_SOCKET_PATH], DEFAULT_SOCKET_PATH);
ck_assert_str_eq(config.strValues[CONF_SPOOL_DIR], DEFAULT_SPOOL_DIR);
ck_assert_str_eq(config.strValues[CONF_RATE_LIMIT_STRATEGY], DEFAULT_RATE_LIMIT_STRATEGY);
ck_assert_str_eq(config.strValues[CONF_CAINFO], DEFAULT_CAINFO);
ck_assert_str_eq(config.strValues[CONF_TIDHEADER], DEFAULT_TIDHEADER);
ck_assert_int_eq(config.intValues[CONF_RECORD_EXPIRY], DEFAULT_RECORD_EXPIRY);
ck_assert_int_eq(config.intValues[CONF_SPOOL_MAX_SIZE], DEFAULT_SPOOL_MAX_SIZE);
ck_assert_int_eq(config.intValues[CONF_SPOOL_PROCESS_TIME], DEFAULT_SPOOL_PROCESS_TIME);
ck_assert_int_eq(config.intValues[CONF_RECORD_WINDOW_LENGTH], DEFAULT_RECORD_WINDOW_LENGTH);
ck_assert_int_eq(config.intValues[CONF_BYTE_WINDOW_LENGTH], DEFAULT_BYTE_WINDOW_LENGTH);
ck_assert_int_eq(config.intValues[CONF_RECORD_BURST_LIMIT], DEFAULT_RECORD_BURST_LIMIT);
ck_assert_int_eq(config.intValues[CONF_BYTE_BURST_LIMIT], DEFAULT_BYTE_BURST_LIMIT);
ck_assert(config.boolValues[CONF_RATE_LIMIT_ENABLED] == DEFAULT_RATE_LIMIT_ENABLED);
ck_assert(config.boolValues[CONF_DAEMON_RECYCLING_ENABLED] == DEFAULT_DAEMON_RECYCLING_ENABLED);
ck_assert(config.boolValues[CONF_RECORD_RETENTION_ENABLED] == DEFAULT_RECORD_RETENTION_ENABLED);
ck_assert(config.boolValues[CONF_RECORD_SERVER_DELIVERY_ENABLED] == DEFAULT_RECORD_SERVER_DELIVERY_ENABLED);
}
END_TEST
START_TEST(check_layered_config)
{
char *config_file = TOPSRCDIR "/src/data/example.2.conf";
configuration config = { { 0 }, { 0 }, { 0 }, false, NULL };
int ret = read_config_from_file(config_file, &config);
ck_assert(ret == true);
// RECORD_RETENTION_ENABLED_DEFAULT = false
ck_assert(config.boolValues[CONF_RECORD_RETENTION_ENABLED] == RECORD_RETENTION_ENABLED_DEFAULT);
// RECORD_SERVER_DELIVERY_ENABLED_DEFAULT = true
ck_assert(config.boolValues[CONF_RECORD_SERVER_DELIVERY_ENABLED] == RECORD_SERVER_DELIVERY_ENABLED_DEFAULT);
ck_assert_str_eq(config.strValues[CONF_SERVER_ADDR], "http://127.0.0.1");
ck_assert_str_eq(config.strValues[CONF_SOCKET_PATH], DEFAULT_SOCKET_PATH);
ck_assert_str_eq(config.strValues[CONF_SPOOL_DIR], DEFAULT_SPOOL_DIR);
ck_assert_str_eq(config.strValues[CONF_RATE_LIMIT_STRATEGY], DEFAULT_RATE_LIMIT_STRATEGY);
ck_assert_str_eq(config.strValues[CONF_CAINFO], "/tmp/cacert.crt");
ck_assert_str_eq(config.strValues[CONF_TIDHEADER], DEFAULT_TIDHEADER);
ck_assert_int_eq(config.intValues[CONF_RECORD_EXPIRY], DEFAULT_RECORD_EXPIRY);
ck_assert_int_eq(config.intValues[CONF_SPOOL_MAX_SIZE], DEFAULT_SPOOL_MAX_SIZE);
ck_assert_int_eq(config.intValues[CONF_SPOOL_PROCESS_TIME], DEFAULT_SPOOL_PROCESS_TIME);
ck_assert_int_eq(config.intValues[CONF_RECORD_WINDOW_LENGTH], DEFAULT_RECORD_WINDOW_LENGTH);
ck_assert_int_eq(config.intValues[CONF_BYTE_WINDOW_LENGTH], DEFAULT_BYTE_WINDOW_LENGTH);
ck_assert_int_eq(config.intValues[CONF_RECORD_BURST_LIMIT], DEFAULT_RECORD_BURST_LIMIT);
ck_assert_int_eq(config.intValues[CONF_BYTE_BURST_LIMIT], DEFAULT_BYTE_BURST_LIMIT);
ck_assert(config.boolValues[CONF_RATE_LIMIT_ENABLED] == DEFAULT_RATE_LIMIT_ENABLED);
ck_assert(config.boolValues[CONF_DAEMON_RECYCLING_ENABLED] == DEFAULT_DAEMON_RECYCLING_ENABLED);
ck_assert(config.boolValues[CONF_RECORD_RETENTION_ENABLED] == DEFAULT_RECORD_RETENTION_ENABLED);
ck_assert(config.boolValues[CONF_RECORD_SERVER_DELIVERY_ENABLED] == DEFAULT_RECORD_SERVER_DELIVERY_ENABLED);
}
END_TEST
@@ -117,7 +160,8 @@ Suite *config_suite(void)
TCase *t = tcase_create("config");
tcase_add_test(t, check_read_config_for_invalid_file);
tcase_add_test(t, check_read_valid_config);
tcase_add_test(t, check_read_valid_config_defaults);
tcase_add_test(t, check_default_config);
tcase_add_test(t, check_layered_config);
tcase_add_test(t, check_read_valid_config_record_retention_delivery);
tcase_add_test(t, check_config_initialised);
+3 -3
View File
@@ -27,19 +27,19 @@
TelemPostDaemon tdaemon;
bool dummy_post(char *headers[], char *body)
bool dummy_post(char *headers[], char *body, char *cfg_file)
{
return true;
}
bool (*post_record_ptr)(char *headers[], char *body) = dummy_post;
bool (*post_record_ptr)(char *headers[], char *body, char *cfg_file) = dummy_post;
void setup(void)
{
char *config_file = ABSTOPSRCDIR "/src/data/example.conf";
set_config_file(config_file);
initialize_daemon(&tdaemon);
initialize_post_daemon(&tdaemon);
}
START_TEST(check_daemon_is_initialized)
+1 -1
View File
@@ -58,7 +58,7 @@ void setup(void)
char *config_file = ABSTOPSRCDIR "/src/data/example.conf";
set_config_file(config_file);
initialize_daemon(&tdaemon);
initialize_probe_daemon(&tdaemon);
}
START_TEST(check_daemon_is_initialized)
+8 -5
View File
@@ -29,14 +29,17 @@
#include "src/probes/klog_scanner.h"
#include "src/probes/oops_parser.h"
char reason[1024];
nc_string *bt;
nc_string *pl;
static char reason[1024];
static nc_string *pl;
void callback_func(struct oops_log_msg *msg)
{
strncpy(reason, msg->lines[0], strlen(msg->lines[0]) + 1);
size_t len = strlen(msg->lines[0]) + 1;
if (len > sizeof(reason)) {
len = sizeof(reason);
}
memcpy(reason, msg->lines[0], len);
reason[sizeof(reason) - 1] = 0;
pl = parse_payload(msg);
}
+21
View File
@@ -33,6 +33,13 @@ dist_check_SCRIPTS = \
@CHECK_LIBS@ \
$(top_builddir)/src/libtelem-shared.la
if HAVE_SYSTEMD_JOURNAL
if LOG_SYSTEMD
%C%_check_config_CFLAGS += $(SYSTEMD_JOURNAL_CFLAGS)
%C%_check_config_LDADD += $(SYSTEMD_JOURNAL_LIBS)
endif
endif
%C%_check_probd_SOURCES = \
%D%/check_probd.c \
src/telemdaemon.c \
@@ -180,6 +187,13 @@ EXTRA_DIST += \
%C%_check_journal_LDADD = \
@CHECK_LIBS@
if HAVE_SYSTEMD_JOURNAL
if LOG_SYSTEMD
%C%_check_journal_CFLAGS += $(SYSTEMD_JOURNAL_CFLAGS)
%C%_check_journal_LDADD += $(SYSTEMD_JOURNAL_LIBS)
endif
endif
%C%_check_libtelemetry_SOURCES = \
%D%/check_libtelemetry.c \
src/configuration.h \
@@ -195,4 +209,11 @@ EXTRA_DIST += \
$(top_builddir)/src/libtelemetry.la \
$(top_builddir)/src/libtelem-shared.la
if HAVE_SYSTEMD_JOURNAL
if LOG_SYSTEMD
%C%_check_libtelemetry_CFLAGS += $(SYSTEMD_JOURNAL_CFLAGS)
%C%_check_libtelemetry_LDADD += $(SYSTEMD_JOURNAL_LIBS)
endif
endif
# vim: filetype=automake tabstop=8 shiftwidth=8 noexpandtab