mirror of
https://github.com/clearlinux/telemetrics-client.git
synced 2026-09-01 11:15:51 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df94f719ab | ||
|
|
0c34fab4fa | ||
|
|
bd51b7c692 | ||
|
|
77874c9c40 | ||
|
|
6a91a71475 | ||
|
|
0b10f69f2b | ||
|
|
b7f5eb0a7c | ||
|
|
4d32436b6c | ||
|
|
3a73ca4e75 | ||
|
|
b506773879 | ||
|
|
3b3f882c3a | ||
|
|
4f97b51f10 | ||
|
|
f3e29b5e5a | ||
|
|
5820a1b959 | ||
|
|
44d423a7c4 | ||
|
|
1bcaf35a6c | ||
|
|
00556dde05 | ||
|
|
d162311e31 | ||
|
|
f23bc1ae12 | ||
|
|
d0ee68ba43 | ||
|
|
9bb9288153 | ||
|
|
b9ec06fe9a | ||
|
|
32b306daa9 | ||
|
|
c3b8d81b6d | ||
|
|
f4f012af7b | ||
|
|
9db4e1d8c9 | ||
|
|
a0efa230b7 | ||
|
|
f14d6ff4c5 | ||
|
|
b61b152cb0 | ||
|
|
ee25d1568d | ||
|
|
622fcfca10 | ||
|
|
33609c5607 | ||
|
|
8ebc882955 | ||
|
|
d30eb663b3 | ||
|
|
885e325e1e | ||
|
|
fffe18a96b | ||
|
|
d9925e1f96 | ||
|
|
c3ae907651 | ||
|
|
8ca299314c | ||
|
|
53d4c229a7 | ||
|
|
7a3082eb59 | ||
|
|
071ad2c883 | ||
|
|
72ea0d9360 | ||
|
|
49823eae83 | ||
|
|
a12c1d8761 | ||
|
|
eb1e670b5f | ||
|
|
5cbd31cbf2 | ||
|
|
4119bdea33 | ||
|
|
2395f6bf3e | ||
|
|
bc7e2610ee | ||
|
|
a4774bde2e | ||
|
|
63574e7406 | ||
|
|
ce35876b55 | ||
|
|
055e55b2f3 | ||
|
|
84b4266bc2 | ||
|
|
e7d9d7b0ba | ||
|
|
b0effc8850 | ||
|
|
e9ce8bc1ae | ||
|
|
ea1480fb04 | ||
|
|
a6e81aa3bb | ||
|
|
fffe9755ad | ||
|
|
b465d35b24 | ||
|
|
e2aeda86eb | ||
|
|
6b4089075f | ||
|
|
83bb3df20a | ||
|
|
e855a19c88 | ||
|
|
7173e1fede | ||
|
|
a4bc8b55dd | ||
|
|
d81ac1e8f3 | ||
|
|
b0d448e9e7 | ||
|
|
88ee43f528 | ||
|
|
49a1d41a3a | ||
|
|
0e20d62c9e | ||
|
|
d314c1a88b | ||
|
|
b9ad4c2f14 | ||
|
|
9fd3c280ba | ||
|
|
75255fff50 | ||
|
|
b2adc08d4f | ||
|
|
e6357bb051 | ||
|
|
15b5df2f47 | ||
|
|
f516d85e59 | ||
|
|
ce2ad0c2b0 |
@@ -0,0 +1,29 @@
|
||||
name: C/C++ CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get --fix-missing install libcurl4-gnutls-dev valgrind libelf-dev libdw-dev libjson-c-dev check
|
||||
- name: autogen
|
||||
run: sh autogen.sh
|
||||
- name: configure
|
||||
run: ./configure
|
||||
- name: make
|
||||
run: make -j8
|
||||
- name: check
|
||||
run: make check
|
||||
- name: valgrind memcheck
|
||||
run: make check-valgrind
|
||||
- name: make distcheck
|
||||
run: make distcheck
|
||||
+1
-3
@@ -35,14 +35,13 @@ build-aux/m4/ltversion.m4
|
||||
/tags
|
||||
telemprobd
|
||||
telempostd
|
||||
telemctl
|
||||
autoscan.log
|
||||
configure.scan
|
||||
tprobe
|
||||
hprobe
|
||||
bertprobe
|
||||
crashprobe
|
||||
journalprobe
|
||||
pythonprobe
|
||||
telem-record-gen
|
||||
klogscanner
|
||||
pstoreclean
|
||||
@@ -58,7 +57,6 @@ tests/check_config
|
||||
tests/check_daemon
|
||||
tests/check_journal
|
||||
tests/check_libtelemetry
|
||||
tests/check_ncb64
|
||||
tests/check_postd
|
||||
tests/check_probd
|
||||
tests/check_probes
|
||||
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
dist: trusty
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
|
||||
os:
|
||||
- linux
|
||||
|
||||
before_script:
|
||||
./autogen.sh
|
||||
|
||||
language: c
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- libcurl4-gnutls-dev
|
||||
- valgrind
|
||||
- autoconf
|
||||
- automake
|
||||
- check
|
||||
- libelf-dev
|
||||
- libdw-dev
|
||||
|
||||
install:
|
||||
- wget https://github.com/libcheck/check/releases/download/0.12.0/check-0.12.0.tar.gz
|
||||
- tar -xvf check-0.12.0.tar.gz
|
||||
- pushd check-0.12.0 && ./configure --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu && make -j48 && sudo make install && popd
|
||||
|
||||
script:
|
||||
- ./configure && make && make check
|
||||
|
||||
after_failure: cat test-suite.log
|
||||
+1
-2
@@ -4,7 +4,7 @@ ACLOCAL_AMFLAGS = -I build-aux/m4
|
||||
|
||||
EXTRA_DIST = \
|
||||
AUTHORS \
|
||||
LICENSE.LGPL-2.1
|
||||
LICENSE
|
||||
|
||||
DISTCHECK_CONFIGURE_FLAGS = \
|
||||
--with-systemdsystemunitdir=$$dc_install_base/$(systemdunitdir) \
|
||||
@@ -15,7 +15,6 @@ DISTCHECK_CONFIGURE_FLAGS = \
|
||||
include $(top_srcdir)/build-aux/make/cflags.make
|
||||
include $(top_srcdir)/build-aux/make/ldflags.make
|
||||
include $(top_srcdir)/docs/local.mk
|
||||
include $(top_srcdir)/scripts/local.mk
|
||||
include $(top_srcdir)/src/local.mk
|
||||
include $(top_srcdir)/src/data/local.mk
|
||||
include $(top_srcdir)/src/nica/local.mk
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
[](https://travis-ci.org/clearlinux/telemetrics-client)
|
||||
## DISCONTINUATION OF PROJECT.
|
||||
|
||||
This project will no longer be maintained by Intel.
|
||||
|
||||
Intel will not provide or guarantee development of or support for this project, including but not limited to, maintenance, bug fixes, new releases or updates. Patches to this project are no longer accepted by Intel. If you have an ongoing need to use this project, are interested in independently developing it, or would like to maintain patches for the community, please create your own fork of the project.
|
||||
|
||||
Contact: webadmin@linux.intel.com
|
||||

|
||||
|
||||
Telemetrics-client
|
||||
==================
|
||||
@@ -67,38 +74,47 @@ Descriptions of config options are listed below in the Usage section.
|
||||
|
||||
Starting the client
|
||||
---------------------
|
||||
To use the telemetrics client a one time explicit ```opt-in``` is required (this is
|
||||
also true when the contents of the directory ```/etc/telemetrics/``` are removed).
|
||||
To opt-in to telemetrics-client use the command:
|
||||
|
||||
```{r, engine='bash', count_lines}
|
||||
telemctl opt-in
|
||||
```
|
||||
|
||||
**Note** this is a change from previous versions, before 2.3.0 installation of
|
||||
telemetrics client was enough to enable the client and if needed the client could
|
||||
be disabled with ```telemctl opt-out```. This command in previous versions created
|
||||
```/etc/telemetrics/opt-out``` file (after telemetrics-client version 2.3.0 this
|
||||
file can be safely removed).
|
||||
|
||||
If the client was compiled with systemd support the respective activation units
|
||||
should be already in place (after a ```make install``` invocation). In this case
|
||||
the client wil start automatically when data is made available to it. i.e. when
|
||||
executing an ```/usr/bin/hprobe``` command.
|
||||
|
||||
Method 1 (recommended):
|
||||
executing an ```/usr/bin/hprobe``` command. Otherwise use the following command:
|
||||
|
||||
```{r, engine='bash', count_lines}
|
||||
telemctl start
|
||||
```
|
||||
|
||||
Note: the above invocation technically readies the service for both socket and
|
||||
path activation, so you may not see an "active" status.
|
||||
|
||||
Method 2:
|
||||
path activation, so you may not see an "active" status. To check the status of
|
||||
telemetrics-client use:
|
||||
|
||||
```{r, engine='bash', count_lines}
|
||||
systemctl start telemprobd.service
|
||||
systemctl start telempostd.service
|
||||
telemctl is-active
|
||||
telemprobd : active
|
||||
telempostd : active
|
||||
```
|
||||
|
||||
Method 3:
|
||||
|
||||
```{r, engine='bash', count_lines}
|
||||
telemprobd &
|
||||
telempostd &
|
||||
```
|
||||
Starting individual service units ```telempostd.service``` or ```telemeprobd.service```
|
||||
is discouraged.
|
||||
|
||||
Configure the client to autostart at boot
|
||||
---------------------
|
||||
|
||||
As longs as the first time ```opt-in``` was performed, the following methods are valid:
|
||||
|
||||
|
||||
Method 1 (recommended):
|
||||
|
||||
Enable the socket-activated service and path unit:
|
||||
@@ -324,7 +340,12 @@ $ org.clearlinux/hello/world Mon 2018-04-02 17:48:01 UTC a19a0d41ba16788881e
|
||||
$ hello
|
||||
```
|
||||
|
||||
## Using tarball
|
||||
|
||||
When building the telemetrics-client using the tarball, a signature is provided for
|
||||
validation. Please follow the steps outlined in the release's README.txt for guidance.
|
||||
|
||||
## Security Disclosures
|
||||
|
||||
To report a security issue or receive security advisories please follow procedures
|
||||
in this [link](https://01.org/security).
|
||||
in [link](security.md).
|
||||
|
||||
@@ -0,0 +1,239 @@
|
||||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_valgrind_check.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_VALGRIND_DFLT(memcheck|helgrind|drd|sgcheck, on|off)
|
||||
# AX_VALGRIND_CHECK()
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# AX_VALGRIND_CHECK checks whether Valgrind is present and, if so, allows
|
||||
# running `make check` under a variety of Valgrind tools to check for
|
||||
# memory and threading errors.
|
||||
#
|
||||
# Defines VALGRIND_CHECK_RULES which should be substituted in your
|
||||
# Makefile; and $enable_valgrind which can be used in subsequent configure
|
||||
# output. VALGRIND_ENABLED is defined and substituted, and corresponds to
|
||||
# the value of the --enable-valgrind option, which defaults to being
|
||||
# enabled if Valgrind is installed and disabled otherwise. Individual
|
||||
# Valgrind tools can be disabled via --disable-valgrind-<tool>, the
|
||||
# default is configurable via the AX_VALGRIND_DFLT command or is to use
|
||||
# all commands not disabled via AX_VALGRIND_DFLT. All AX_VALGRIND_DFLT
|
||||
# calls must be made before the call to AX_VALGRIND_CHECK.
|
||||
#
|
||||
# If unit tests are written using a shell script and automake's
|
||||
# LOG_COMPILER system, the $(VALGRIND) variable can be used within the
|
||||
# shell scripts to enable Valgrind, as described here:
|
||||
#
|
||||
# https://www.gnu.org/software/gnulib/manual/html_node/Running-self_002dtests-under-valgrind.html
|
||||
#
|
||||
# Usage example:
|
||||
#
|
||||
# configure.ac:
|
||||
#
|
||||
# AX_VALGRIND_DFLT([sgcheck], [off])
|
||||
# AX_VALGRIND_CHECK
|
||||
#
|
||||
# in each Makefile.am with tests:
|
||||
#
|
||||
# @VALGRIND_CHECK_RULES@
|
||||
# VALGRIND_SUPPRESSIONS_FILES = my-project.supp
|
||||
# EXTRA_DIST = my-project.supp
|
||||
#
|
||||
# This results in a "check-valgrind" rule being added. Running `make
|
||||
# check-valgrind` in that directory will recursively run the module's test
|
||||
# suite (`make check`) once for each of the available Valgrind tools (out
|
||||
# of memcheck, helgrind and drd) while the sgcheck will be skipped unless
|
||||
# enabled again on the commandline with --enable-valgrind-sgcheck. The
|
||||
# results for each check will be output to test-suite-$toolname.log. The
|
||||
# target will succeed if there are zero errors and fail otherwise.
|
||||
#
|
||||
# Alternatively, a "check-valgrind-$TOOL" rule will be added, for $TOOL in
|
||||
# memcheck, helgrind, drd and sgcheck. These are useful because often only
|
||||
# some of those tools can be ran cleanly on a codebase.
|
||||
#
|
||||
# The macro supports running with and without libtool.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2014, 2015, 2016 Philip Withnall <philip.withnall@collabora.co.uk>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 17
|
||||
|
||||
dnl Configured tools
|
||||
m4_define([valgrind_tool_list], [[memcheck], [helgrind], [drd], [sgcheck]])
|
||||
m4_set_add_all([valgrind_exp_tool_set], [sgcheck])
|
||||
m4_foreach([vgtool], [valgrind_tool_list],
|
||||
[m4_define([en_dflt_valgrind_]vgtool, [on])])
|
||||
|
||||
AC_DEFUN([AX_VALGRIND_DFLT],[
|
||||
m4_define([en_dflt_valgrind_$1], [$2])
|
||||
])dnl
|
||||
|
||||
AM_EXTRA_RECURSIVE_TARGETS([check-valgrind])
|
||||
m4_foreach([vgtool], [valgrind_tool_list],
|
||||
[AM_EXTRA_RECURSIVE_TARGETS([check-valgrind-]vgtool)])
|
||||
|
||||
AC_DEFUN([AX_VALGRIND_CHECK],[
|
||||
dnl Check for --enable-valgrind
|
||||
AC_ARG_ENABLE([valgrind],
|
||||
[AS_HELP_STRING([--enable-valgrind], [Whether to enable Valgrind on the unit tests])],
|
||||
[enable_valgrind=$enableval],[enable_valgrind=])
|
||||
|
||||
AS_IF([test "$enable_valgrind" != "no"],[
|
||||
# Check for Valgrind.
|
||||
AC_CHECK_PROG([VALGRIND],[valgrind],[valgrind])
|
||||
AS_IF([test "$VALGRIND" = ""],[
|
||||
AS_IF([test "$enable_valgrind" = "yes"],[
|
||||
AC_MSG_ERROR([Could not find valgrind; either install it or reconfigure with --disable-valgrind])
|
||||
],[
|
||||
enable_valgrind=no
|
||||
])
|
||||
],[
|
||||
enable_valgrind=yes
|
||||
])
|
||||
])
|
||||
|
||||
AM_CONDITIONAL([VALGRIND_ENABLED],[test "$enable_valgrind" = "yes"])
|
||||
AC_SUBST([VALGRIND_ENABLED],[$enable_valgrind])
|
||||
|
||||
# Check for Valgrind tools we care about.
|
||||
[valgrind_enabled_tools=]
|
||||
m4_foreach([vgtool],[valgrind_tool_list],[
|
||||
AC_ARG_ENABLE([valgrind-]vgtool,
|
||||
m4_if(m4_defn([en_dflt_valgrind_]vgtool),[off],dnl
|
||||
[AS_HELP_STRING([--enable-valgrind-]vgtool, [Whether to use ]vgtool[ during the Valgrind tests])],dnl
|
||||
[AS_HELP_STRING([--disable-valgrind-]vgtool, [Whether to skip ]vgtool[ during the Valgrind tests])]),
|
||||
[enable_valgrind_]vgtool[=$enableval],
|
||||
[enable_valgrind_]vgtool[=])
|
||||
AS_IF([test "$enable_valgrind" = "no"],[
|
||||
enable_valgrind_]vgtool[=no],
|
||||
[test "$enable_valgrind_]vgtool[" ]dnl
|
||||
m4_if(m4_defn([en_dflt_valgrind_]vgtool), [off], [= "yes"], [!= "no"]),[
|
||||
AC_CACHE_CHECK([for Valgrind tool ]vgtool,
|
||||
[ax_cv_valgrind_tool_]vgtool,[
|
||||
ax_cv_valgrind_tool_]vgtool[=no
|
||||
m4_set_contains([valgrind_exp_tool_set],vgtool,
|
||||
[m4_define([vgtoolx],[exp-]vgtool)],
|
||||
[m4_define([vgtoolx],vgtool)])
|
||||
AS_IF([`$VALGRIND --tool=]vgtoolx[ --help >/dev/null 2>&1`],[
|
||||
ax_cv_valgrind_tool_]vgtool[=yes
|
||||
])
|
||||
])
|
||||
AS_IF([test "$ax_cv_valgrind_tool_]vgtool[" = "no"],[
|
||||
AS_IF([test "$enable_valgrind_]vgtool[" = "yes"],[
|
||||
AC_MSG_ERROR([Valgrind does not support ]vgtool[; reconfigure with --disable-valgrind-]vgtool)
|
||||
],[
|
||||
enable_valgrind_]vgtool[=no
|
||||
])
|
||||
],[
|
||||
enable_valgrind_]vgtool[=yes
|
||||
])
|
||||
])
|
||||
AS_IF([test "$enable_valgrind_]vgtool[" = "yes"],[
|
||||
valgrind_enabled_tools="$valgrind_enabled_tools ]m4_bpatsubst(vgtool,[^exp-])["
|
||||
])
|
||||
AC_SUBST([ENABLE_VALGRIND_]vgtool,[$enable_valgrind_]vgtool)
|
||||
])
|
||||
AC_SUBST([valgrind_tools],["]m4_join([ ], valgrind_tool_list)["])
|
||||
AC_SUBST([valgrind_enabled_tools],[$valgrind_enabled_tools])
|
||||
|
||||
[VALGRIND_CHECK_RULES='
|
||||
# Valgrind check
|
||||
#
|
||||
# Optional:
|
||||
# - VALGRIND_SUPPRESSIONS_FILES: Space-separated list of Valgrind suppressions
|
||||
# files to load. (Default: empty)
|
||||
# - VALGRIND_FLAGS: General flags to pass to all Valgrind tools.
|
||||
# (Default: --num-callers=30)
|
||||
# - VALGRIND_$toolname_FLAGS: Flags to pass to Valgrind $toolname (one of:
|
||||
# memcheck, helgrind, drd, sgcheck). (Default: various)
|
||||
|
||||
# Optional variables
|
||||
VALGRIND_SUPPRESSIONS ?= $(addprefix --suppressions=,$(VALGRIND_SUPPRESSIONS_FILES))
|
||||
VALGRIND_FLAGS ?= --num-callers=30
|
||||
VALGRIND_memcheck_FLAGS ?= --leak-check=full --show-reachable=no
|
||||
VALGRIND_helgrind_FLAGS ?= --history-level=approx
|
||||
VALGRIND_drd_FLAGS ?=
|
||||
VALGRIND_sgcheck_FLAGS ?=
|
||||
|
||||
# Internal use
|
||||
valgrind_log_files = $(addprefix test-suite-,$(addsuffix .log,$(valgrind_tools)))
|
||||
|
||||
valgrind_memcheck_flags = --tool=memcheck $(VALGRIND_memcheck_FLAGS)
|
||||
valgrind_helgrind_flags = --tool=helgrind $(VALGRIND_helgrind_FLAGS)
|
||||
valgrind_drd_flags = --tool=drd $(VALGRIND_drd_FLAGS)
|
||||
valgrind_sgcheck_flags = --tool=exp-sgcheck $(VALGRIND_sgcheck_FLAGS)
|
||||
|
||||
valgrind_quiet = $(valgrind_quiet_$(V))
|
||||
valgrind_quiet_ = $(valgrind_quiet_$(AM_DEFAULT_VERBOSITY))
|
||||
valgrind_quiet_0 = --quiet
|
||||
valgrind_v_use = $(valgrind_v_use_$(V))
|
||||
valgrind_v_use_ = $(valgrind_v_use_$(AM_DEFAULT_VERBOSITY))
|
||||
valgrind_v_use_0 = @echo " USE " $(patsubst check-valgrind-%-am,%,$''@):;
|
||||
|
||||
# Support running with and without libtool.
|
||||
ifneq ($(LIBTOOL),)
|
||||
valgrind_lt = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=execute
|
||||
else
|
||||
valgrind_lt =
|
||||
endif
|
||||
|
||||
# Use recursive makes in order to ignore errors during check
|
||||
check-valgrind-am:
|
||||
ifeq ($(VALGRIND_ENABLED),yes)
|
||||
$(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k \
|
||||
$(foreach tool, $(valgrind_enabled_tools), check-valgrind-$(tool))
|
||||
else
|
||||
@echo "Need to reconfigure with --enable-valgrind"
|
||||
endif
|
||||
|
||||
# Valgrind running
|
||||
VALGRIND_TESTS_ENVIRONMENT = \
|
||||
$(TESTS_ENVIRONMENT) \
|
||||
env VALGRIND=$(VALGRIND) \
|
||||
G_SLICE=always-malloc,debug-blocks \
|
||||
G_DEBUG=fatal-warnings,fatal-criticals,gc-friendly
|
||||
|
||||
VALGRIND_LOG_COMPILER = \
|
||||
$(valgrind_lt) \
|
||||
$(VALGRIND) $(VALGRIND_SUPPRESSIONS) --error-exitcode=1 $(VALGRIND_FLAGS)
|
||||
|
||||
define valgrind_tool_rule
|
||||
check-valgrind-$(1)-am:
|
||||
ifeq ($$(VALGRIND_ENABLED)-$$(ENABLE_VALGRIND_$(1)),yes-yes)
|
||||
ifneq ($$(TESTS),)
|
||||
$$(valgrind_v_use)$$(MAKE) check-TESTS \
|
||||
TESTS_ENVIRONMENT="$$(VALGRIND_TESTS_ENVIRONMENT)" \
|
||||
LOG_COMPILER="$$(VALGRIND_LOG_COMPILER)" \
|
||||
LOG_FLAGS="$$(valgrind_$(1)_flags)" \
|
||||
TEST_SUITE_LOG=test-suite-$(1).log
|
||||
endif
|
||||
else ifeq ($$(VALGRIND_ENABLED),yes)
|
||||
@echo "Need to reconfigure with --enable-valgrind-$(1)"
|
||||
else
|
||||
@echo "Need to reconfigure with --enable-valgrind"
|
||||
endif
|
||||
endef
|
||||
|
||||
$(foreach tool,$(valgrind_tools),$(eval $(call valgrind_tool_rule,$(tool))))
|
||||
|
||||
A''M_DISTCHECK_CONFIGURE_FLAGS ?=
|
||||
A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-valgrind
|
||||
|
||||
MOSTLYCLEANFILES ?=
|
||||
MOSTLYCLEANFILES += $(valgrind_log_files)
|
||||
|
||||
.PHONY: check-valgrind $(add-prefix check-valgrind-,$(valgrind_tools))
|
||||
']
|
||||
|
||||
AC_SUBST([VALGRIND_CHECK_RULES])
|
||||
m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([VALGRIND_CHECK_RULES])])
|
||||
])
|
||||
+15
-3
@@ -2,7 +2,7 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.69])
|
||||
AC_INIT([telemetrics-client], [2.2.1], [https://clearlinux.org/])
|
||||
AC_INIT([telemetrics-client], [2.4.3], [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])
|
||||
@@ -20,11 +20,20 @@ AC_PROG_INSTALL
|
||||
AC_PROG_LN_S
|
||||
AC_PROG_MAKE_SET
|
||||
|
||||
# Valgrind check
|
||||
AX_VALGRIND_DFLT(memcheck, on)
|
||||
AX_VALGRIND_DFLT(helgrind, off)
|
||||
AX_VALGRIND_DFLT(drd, off)
|
||||
AX_VALGRIND_DFLT(sgcheck, off)
|
||||
|
||||
AX_VALGRIND_CHECK
|
||||
|
||||
# Checks for libraries.
|
||||
|
||||
# check >= 0.9.12 is required for TAP output
|
||||
PKG_CHECK_MODULES([CHECK], [check >= 0.12])
|
||||
PKG_CHECK_MODULES([CURL], [libcurl])
|
||||
PKG_CHECK_MODULES([JSON_C], [json-c])
|
||||
AC_CHECK_LIB([elf], [elf_begin], [have_elflib=yes], [AC_MSG_ERROR([Unable to find libelf from elfutils])])
|
||||
AC_CHECK_LIB([dw], [dwfl_begin], [have_dwlib=yes], [AC_MSG_ERROR([Unable to find libdw from elfutils])])
|
||||
AS_IF([test "x$have_elflib" = "xyes" -a "x$have_dwlib" = "xyes"],
|
||||
@@ -41,6 +50,7 @@ AC_CHECK_HEADERS([elfutils/libdwfl.h])
|
||||
AC_CHECK_HEADERS([fcntl.h])
|
||||
AC_CHECK_HEADERS([getopt.h])
|
||||
AC_CHECK_HEADERS([inttypes.h])
|
||||
AC_CHECK_HEADERS([json-c/json.h])
|
||||
AC_CHECK_HEADERS([libelf.h])
|
||||
AC_CHECK_HEADERS([limits.h])
|
||||
AC_CHECK_HEADERS([stdarg.h])
|
||||
@@ -120,8 +130,8 @@ AC_ARG_WITH([loglevel], AS_HELP_STRING([--with-loglevel=NUM],
|
||||
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
|
||||
[uri to telemetrics backend server @<:@default=https://clr.telemetry.intel.com/v3/collector@:>@]), [backendaddr=${withval}])
|
||||
test -z "${backendaddr}" && backendaddr=https://clr.telemetry.intel.com/v3/collector
|
||||
AC_SUBST(BACKEND_ADDR, [${backendaddr}])
|
||||
|
||||
AC_ARG_ENABLE([logtype], AS_HELP_STRING([--enable-logtype],
|
||||
@@ -171,4 +181,6 @@ systemconfdir: $confpath
|
||||
socketdir: $socketpath
|
||||
loglevel: $loglevel
|
||||
logtype: $logtype
|
||||
|
||||
valgrind: $enable_valgrind
|
||||
])
|
||||
|
||||
+6
-5
@@ -34,7 +34,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.sp
|
||||
\fBtelemctl\fP
|
||||
.sp
|
||||
\fB/etc/telemetrics/opt\-out\fP
|
||||
\fB/etc/telemetrics/opt\-in\fP
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
Control actions for telemetry services. The command can be used to start,
|
||||
@@ -48,12 +48,13 @@ restart, or stop \fBtelemprobd\fP(1) and \fBtelempostd\fP(1), or to opt\-in or o
|
||||
Starts, stops or restarts all running telemetry services.
|
||||
.IP \(bu 2
|
||||
\fBopt\-in\fP:
|
||||
Opts in to telemetry, and starts telemetry services. The opt\-out file
|
||||
\fB/etc/telemetrics/opt\-out\fP is removed.
|
||||
Opts in to telemetry and the opt\-in file \fB/etc/telemetrics/opt\-in\fP
|
||||
is created. Note: this is a one time required operation before
|
||||
telemetry can be used the first time.
|
||||
.IP \(bu 2
|
||||
\fBopt\-out\fP:
|
||||
Opts out of telemetry, and stops telemetry services. The opt\-out file
|
||||
\fB/etc/telemetrics/opt\-out\fP is created.
|
||||
Opts out of telemetry, and stops telemetry services. The opt\-in file
|
||||
\fB/etc/telemetrics/opt\-in\fP is deleted.
|
||||
.IP \(bu 2
|
||||
\fBis\-active\fP:
|
||||
Checks if telemetry client daemons are active (telemprobd and telempostd).
|
||||
|
||||
@@ -15,7 +15,7 @@ SYNOPSIS
|
||||
|
||||
``telemctl``
|
||||
|
||||
``/etc/telemetrics/opt-out``
|
||||
``/etc/telemetrics/opt-in``
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
@@ -32,12 +32,13 @@ OPTIONS
|
||||
Starts, stops or restarts all running telemetry services.
|
||||
|
||||
* ``opt-in``:
|
||||
Opts in to telemetry, and starts telemetry services. The opt-out file
|
||||
``/etc/telemetrics/opt-out`` is removed.
|
||||
Opts in to telemetry and the opt-in file ``/etc/telemetrics/opt-in``
|
||||
is created. Note: this is a one time required operation before
|
||||
telemetry can be used the first time.
|
||||
|
||||
* ``opt-out``:
|
||||
Opts out of telemetry, and stops telemetry services. The opt-out file
|
||||
``/etc/telemetrics/opt-out`` is created.
|
||||
Opts out of telemetry, and stops telemetry services. The opt-in file
|
||||
``/etc/telemetrics/opt-in`` is deleted.
|
||||
|
||||
* ``is-active``:
|
||||
Checks if telemetry client daemons are active (telemprobd and telempostd).
|
||||
|
||||
@@ -45,6 +45,8 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
\fBvoid tm_free_record(struct telem_ref *t_ref)\fP
|
||||
.sp
|
||||
\fBint tm_set_config_file(const char *c_file)\fP
|
||||
.sp
|
||||
\fBint tm_is_opted_in(void)\fP
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
The functions in the telemetry library facilitate the delivery of
|
||||
@@ -64,11 +66,15 @@ The function \fBtm_send_record()\fP delivers the record to the local
|
||||
.sp
|
||||
The function \fBtm_set_config_file()\fP can be used to provide an alternate
|
||||
configuration path to the telemetry library.
|
||||
.sp
|
||||
\fBtm_is_opted_in\fP is a utility provided to check if the one time opt\-in
|
||||
has been performed.
|
||||
.SH RETURN VALUES
|
||||
.sp
|
||||
All these functions return \fB0\fP on success, or a non\-zero return value
|
||||
if an error occurred. The function \fBtm_free_record()\fP does not return
|
||||
any value.
|
||||
any value. \fBtm_is_opted_in\fP returns \fB1\fP when telemetry is opted\-in
|
||||
otherwise \fB0\fP\&.
|
||||
.SH SEE ALSO
|
||||
.INDENT 0.0
|
||||
.IP \(bu 2
|
||||
|
||||
@@ -27,6 +27,8 @@ SYNOPSIS
|
||||
|
||||
``int tm_set_config_file(const char *c_file)``
|
||||
|
||||
``int tm_is_opted_in(void)``
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
@@ -49,13 +51,16 @@ The function ``tm_send_record()`` delivers the record to the local
|
||||
The function ``tm_set_config_file()`` can be used to provide an alternate
|
||||
configuration path to the telemetry library.
|
||||
|
||||
``tm_is_opted_in`` is a utility provided to check if the one time opt-in
|
||||
has been performed.
|
||||
|
||||
RETURN VALUES
|
||||
=============
|
||||
|
||||
All these functions return ``0`` on success, or a non-zero return value
|
||||
if an error occurred. The function ``tm_free_record()`` does not return
|
||||
any value.
|
||||
any value. ``tm_is_opted_in`` returns ``1`` when telemetry is opted-in
|
||||
otherwise ``0``.
|
||||
|
||||
|
||||
SEE ALSO
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
dist_bin_SCRIPTS = %D%/telemctl
|
||||
|
||||
# vim: filetype=automake tabstop=8 shiftwidth=8 noexpandtab
|
||||
@@ -1,150 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
declare -a SPECIAL_UNITS=(
|
||||
hprobe.timer
|
||||
telemprobd.socket
|
||||
telempostd.path
|
||||
klogscanner.service
|
||||
journal-probe-tail.service
|
||||
python-probe.path
|
||||
)
|
||||
|
||||
declare -a SERVICES=(
|
||||
hprobe.service
|
||||
pstore-probe.service
|
||||
telemprobd.service
|
||||
telempostd.service
|
||||
journal-probe.service
|
||||
)
|
||||
|
||||
SCRIPT="$0"
|
||||
TELEM_DIR=/etc/telemetrics
|
||||
OPT_OUT_FILE=${TELEM_DIR}/opt-out
|
||||
TELEM_WRK_DIRS_CONF=/usr/lib/tmpfiles.d/telemetrics-dirs.conf
|
||||
|
||||
create_work_dirs() {
|
||||
# Creates dirs if missing, adjust ownership if exists
|
||||
systemd-tmpfiles --create ${TELEM_WRK_DIRS_CONF}
|
||||
}
|
||||
|
||||
telem_remove_work_dirs() {
|
||||
# Remove dirs
|
||||
awk '/^d/{print $2}' ${TELEM_WRK_DIRS_CONF} | xargs rm -rf;
|
||||
}
|
||||
|
||||
exit_ok() {
|
||||
echo "$1" > /dev/stderr
|
||||
exit 0
|
||||
}
|
||||
|
||||
exit_err() {
|
||||
echo "$1" > /dev/stderr
|
||||
exit 1
|
||||
}
|
||||
|
||||
notice() {
|
||||
echo "$1" > /dev/stderr
|
||||
}
|
||||
|
||||
for_each_service() {
|
||||
local action=$1 && shift
|
||||
local -a array=($*)
|
||||
for service in "${array[@]}"; do
|
||||
systemctl $action $service
|
||||
[ $? -ne 0 ] && notice "Failed to $action ${service}. Continuing..."
|
||||
done
|
||||
}
|
||||
|
||||
telem_stop() {
|
||||
# the special units must be stopped first so that activation no longer happens
|
||||
for_each_service "stop" ${SPECIAL_UNITS[@]}
|
||||
for_each_service "stop" ${SERVICES[@]}
|
||||
}
|
||||
|
||||
telem_start() {
|
||||
[ -f $OPT_OUT_FILE ] && exit_err "Opt out is enabled. Cannot start services."
|
||||
# trigger systemd-tmpfiles work dirs creation
|
||||
create_work_dirs
|
||||
# the units in SERVICES are activated as needed, so no need to start them
|
||||
for_each_service "start" ${SPECIAL_UNITS[@]}
|
||||
}
|
||||
|
||||
telem_is_active() {
|
||||
# check only activation units
|
||||
echo "telemprobd :" $(systemctl is-active telemprobd.socket)
|
||||
echo "telempostd :" $(systemctl is-active telempostd.path)
|
||||
}
|
||||
|
||||
telem_opt_out() {
|
||||
[ -f $OPT_OUT_FILE ] && exit_ok "Already opted out. Nothing to do."
|
||||
mkdir -p $TELEM_DIR || exit_err "Failed to create ${TELEM_DIR}."
|
||||
touch $OPT_OUT_FILE || exit_err "Failed to create ${OPT_OUT_FILE}."
|
||||
telem_stop
|
||||
telem_remove_work_dirs
|
||||
}
|
||||
|
||||
telem_opt_in() {
|
||||
[ ! -f $OPT_OUT_FILE ] && exit_ok "Already opted in. Nothing to do."
|
||||
rm -f $OPT_OUT_FILE || exit_err "Failed to remove ${OPT_OUT_FILE}."
|
||||
telem_start
|
||||
}
|
||||
|
||||
telem_restart() {
|
||||
telem_stop
|
||||
telem_start
|
||||
}
|
||||
|
||||
telem_journal_cli() {
|
||||
telem_journal "$@"
|
||||
}
|
||||
|
||||
usage() {
|
||||
format=' %-10s %s\n'
|
||||
printf "\n"
|
||||
printf "%s - Control actions for telemetry services\n" "$SCRIPT"
|
||||
printf "\n"
|
||||
printf "$format" "stop" "Stops all running telemetry services"
|
||||
printf "$format" "start" "Starts all telemetry services"
|
||||
printf "$format" "restart" "Restarts all telemetry services"
|
||||
printf "$format" "is-active" "Checks if telemprobd and telempostd are active"
|
||||
printf "$format" "opt-in" "Opts in to telemetry, and starts telemetry services"
|
||||
printf "$format" "opt-out" "Opts out of telemetry, and stops telemetry services"
|
||||
printf "$format" "journal" "Prints telemtry journal contents. Use -h argument with"
|
||||
printf "$format" "" "command for more options"
|
||||
printf "\n"
|
||||
exit 2
|
||||
}
|
||||
|
||||
if [ "$1" != "journal" ] && [ $# -ne 1 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
if [ $EUID -ne 0 ]; then
|
||||
exit_err "Must be root to run this command. Exiting..."
|
||||
fi
|
||||
|
||||
SUBCOMMAND=$1
|
||||
|
||||
case $SUBCOMMAND in
|
||||
opt-out)
|
||||
telem_opt_out ;;
|
||||
opt-in)
|
||||
telem_opt_in ;;
|
||||
stop)
|
||||
telem_stop ;;
|
||||
start)
|
||||
telem_start ;;
|
||||
restart)
|
||||
telem_restart ;;
|
||||
is-active)
|
||||
telem_is_active ;;
|
||||
journal)
|
||||
telem_journal_cli "$@" ;;
|
||||
*)
|
||||
notice "Unknown command passed to $SCRIPT"
|
||||
usage ;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# vi: ts=8 sw=2 sts=2 et tw=80
|
||||
@@ -0,0 +1,9 @@
|
||||
# Security Policy
|
||||
Intel is committed to rapidly addressing security vulnerabilities affecting our
|
||||
customers and providing clear guidance on the solution, impact, severity and
|
||||
mitigation.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
Please report any security vulnerabilities in this project [utilizing the
|
||||
guidelines here](https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html).
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ static const uint32_t RECORD_FORMAT_VERSION = 4;
|
||||
#define TM_SITE_VERSION_FILE "/etc/os-release"
|
||||
#define TM_DIST_VERSION_FILE "/usr/lib/os-release"
|
||||
|
||||
#define TM_OPT_OUT_FILE "/etc/telemetrics/opt-out"
|
||||
#define TM_OPT_IN_FILE "/etc/telemetrics/opt-in"
|
||||
|
||||
/* Currently max supported payload size is 8kb */
|
||||
#define MAX_PAYLOAD_LENGTH 8192
|
||||
|
||||
@@ -152,6 +152,18 @@ bool set_default_config_values(struct configuration *config)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Needed for unit testing */
|
||||
void free_config_struct(struct configuration *config)
|
||||
{
|
||||
if (keyfile != NULL) {
|
||||
nc_hashmap_free(keyfile);
|
||||
}
|
||||
|
||||
for (int i = 0; i < CONF_STR_MAX; i++) {
|
||||
free(config->strValues[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool read_config_from_file(char *config_file, struct configuration *config)
|
||||
{
|
||||
if (keyfile != NULL) {
|
||||
@@ -275,6 +287,14 @@ void free_configuration(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Needed for unit testing */
|
||||
void free_config_file(void)
|
||||
{
|
||||
if (config_file) {
|
||||
free(config_file);
|
||||
}
|
||||
}
|
||||
|
||||
const char *server_addr_config()
|
||||
{
|
||||
initialize_config();
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
[Unit]
|
||||
Description=Telemetrics BERT Probe
|
||||
Requires=telemprobd.socket
|
||||
After=telemprobd.socket
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/sys/firmware/acpi/tables/data/BERT
|
||||
|
||||
[Service]
|
||||
ExecStart=@bindir@/bertprobe
|
||||
User=telemetry
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -2,7 +2,7 @@
|
||||
Description=Telemetrics Heartbeat Probe
|
||||
Requires=telemprobd.socket
|
||||
After=telemprobd.socket
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Service]
|
||||
ExecStart=@bindir@/hprobe -Hlu
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
[Unit]
|
||||
Description=Daily Heartbeat for Telemetrics
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Timer]
|
||||
OnCalendar=daily
|
||||
AccuracySec=12h
|
||||
RandomizedDelaySec=21600
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Description=Telemetrics Systemd Journal Probe
|
||||
Requires=telemprobd.socket
|
||||
After=telemprobd.socket
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Service]
|
||||
ExecStart=@bindir@/journalprobe -t
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Description=Telemetrics Systemd Journal Probe
|
||||
Requires=telemprobd.socket
|
||||
After=telemprobd.socket
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Service]
|
||||
ExecStart=@bindir@/journalprobe
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
[Unit]
|
||||
Description=Telemetrics Kernel Log Scanner
|
||||
ConditionVirtualization=!container
|
||||
Requires=telemprobd.socket
|
||||
After=telemprobd.socket
|
||||
|
||||
|
||||
@@ -16,11 +16,8 @@ EXTRA_DIST += \
|
||||
%D%/example.2.conf \
|
||||
%D%/hprobe.service.in \
|
||||
%D%/hprobe.timer \
|
||||
%D%/bert-probe.service.in \
|
||||
%D%/journal-probe.service.in \
|
||||
%D%/journal-probe-tail.service.in \
|
||||
%D%/python-probe.service.in \
|
||||
%D%/python-probe.path.in \
|
||||
%D%/pstore-probe.service.in \
|
||||
%D%/klogscanner.service.in \
|
||||
%D%/pstore-clean.service.in \
|
||||
@@ -55,11 +52,8 @@ systemdunitdir = @SYSTEMD_UNITDIR@
|
||||
systemdunit_DATA = \
|
||||
%D%/hprobe.service \
|
||||
%D%/hprobe.timer \
|
||||
%D%/bert-probe.service \
|
||||
%D%/journal-probe.service \
|
||||
%D%/journal-probe-tail.service \
|
||||
%D%/python-probe.service \
|
||||
%D%/python-probe.path \
|
||||
%D%/pstore-probe.service \
|
||||
%D%/klogscanner.service \
|
||||
%D%/pstore-clean.service \
|
||||
@@ -72,9 +66,6 @@ systemdunit_DATA = \
|
||||
%D%/hprobe.service: %D%/hprobe.service.in
|
||||
$(pathfix) < $< > $@
|
||||
|
||||
%D%/bert-probe.service: %D%/bert-probe.service.in
|
||||
$(pathfix) < $< > $@
|
||||
|
||||
%D%/journal-probe.service: %D%/journal-probe.service.in
|
||||
$(pathfix) < $< > $@
|
||||
|
||||
@@ -96,12 +87,6 @@ systemdunit_DATA = \
|
||||
%D%/telempostd.service: %D%/telempostd.service.in
|
||||
$(pathfix) < $< > $@
|
||||
|
||||
%D%/python-probe.service: %D%/python-probe.service.in
|
||||
$(pathfix) < $< > $@
|
||||
|
||||
%D%/python-probe.path: %D%/python-probe.path.in
|
||||
$(pathfix) < $< > $@
|
||||
|
||||
%D%/telemprobd.service: %D%/telemprobd.service.in
|
||||
$(pathfix) < $< > $@
|
||||
|
||||
@@ -125,8 +110,6 @@ clean-local:
|
||||
%D%/telemprobd.socket \
|
||||
%D%/telempostd.service \
|
||||
%D%/telempostd.path \
|
||||
%D%/python-probe.service \
|
||||
%D%/python-probe.path \
|
||||
%D%/telemprobd-update-trigger.service \
|
||||
%D%/telemetrics.conf \
|
||||
%D%/telemetrics-dirs.conf \
|
||||
@@ -138,5 +121,4 @@ clean-local:
|
||||
%D%/klogscanner.service \
|
||||
%D%/pstore-clean.service \
|
||||
%D%/hprobe.service \
|
||||
%D%/bert-probe.service \
|
||||
%D%/.dirstamp
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
Description=Telemetrics Pstore Probe
|
||||
Requires=telemprobd.socket
|
||||
After=telemprobd.socket
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Service]
|
||||
ExecStart=@bindir@/pstoreprobe
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
[Unit]
|
||||
Description=Python Probe Daemon Staging
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
|
||||
[Path]
|
||||
DirectoryNotEmpty=/var/lib/telemetry/python
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,13 +0,0 @@
|
||||
[Unit]
|
||||
Description=Telemetrics Python Probe
|
||||
Requires=telemprobd.socket
|
||||
After=telemprobd.socket
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
|
||||
[Service]
|
||||
User=telemetry
|
||||
ExecStart=@bindir@/pythonprobe
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -4,5 +4,3 @@ 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 -
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[Unit]
|
||||
Description=Telemetry Post Daemon staging
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Path]
|
||||
DirectoryNotEmpty=@localstatedir@/spool/telemetry
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[Unit]
|
||||
Description=Telemetrics Post Daemon
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Service]
|
||||
ExecStart=@bindir@/telempostd
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[Unit]
|
||||
Description=Telemetrics Daemon
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Service]
|
||||
ExecStart=@bindir@/telemprobd
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[Unit]
|
||||
Description=Telemetrics Daemon
|
||||
ConditionPathExists=!/etc/telemetrics/opt-out
|
||||
ConditionPathExists=/etc/telemetrics/opt-in
|
||||
|
||||
[Socket]
|
||||
ListenStream=@SOCKETDIR@/telem-0
|
||||
|
||||
+9
-12
@@ -43,7 +43,7 @@ bool _fgets(char *s, int n, FILE *stream)
|
||||
|
||||
bool read_record(char *fullpath, char *headers[], char **body, char **cfg_file)
|
||||
{
|
||||
int i, ret = 0;
|
||||
int i = 0;
|
||||
bool result = false;
|
||||
FILE *fp = NULL;
|
||||
long offset;
|
||||
@@ -52,23 +52,20 @@ bool read_record(char *fullpath, char *headers[], char **body, char **cfg_file)
|
||||
#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) {
|
||||
telem_log(LOG_ERR, "Unable to stat record %s in staging\n", fullpath);
|
||||
return false;
|
||||
}
|
||||
size = buf.st_size;
|
||||
|
||||
fp = fopen(fullpath, "r");
|
||||
if (fp == NULL) {
|
||||
telem_log(LOG_ERR, "Unable to open file %s in staging\n", fullpath);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the file size
|
||||
fseek(fp, 0 , SEEK_END);
|
||||
size = ftell(fp);
|
||||
fseek(fp, 0 , SEEK_SET);
|
||||
|
||||
// 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");
|
||||
@@ -83,7 +80,7 @@ bool read_record(char *fullpath, char *headers[], char **body, char **cfg_file)
|
||||
|
||||
size_t pathlen = strlen(line);
|
||||
*cfg_file = malloc(pathlen + 1);
|
||||
if (cfg_file == NULL) {
|
||||
if (*cfg_file == NULL) {
|
||||
telem_log(LOG_ERR, "Could not allocate memory for config file path\n");
|
||||
goto read_error;
|
||||
}
|
||||
@@ -127,8 +124,8 @@ bool read_record(char *fullpath, char *headers[], char **body, char **cfg_file)
|
||||
}
|
||||
memset(*body, 0, (size_t)size);
|
||||
|
||||
//read rest of file
|
||||
size_t newlen = fread(*body, sizeof(char), (size_t)size, fp);
|
||||
//read rest of file. '-1' ensures it's null terminated
|
||||
size_t newlen = fread(*body, sizeof(char), (size_t)size - 1, fp);
|
||||
if (newlen == 0) {
|
||||
telem_perror("Error reading staged file");
|
||||
result = false;
|
||||
|
||||
+19
-12
@@ -99,11 +99,14 @@ static int deserialize_journal_entry(char *line, struct JournalEntry **entry)
|
||||
size_t offset = 0;
|
||||
struct JournalEntry *e = NULL;
|
||||
|
||||
if (line == NULL) {
|
||||
/* Assume an error... */
|
||||
*entry = NULL;
|
||||
|
||||
if (line == NULL || !strlen(line)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
e = malloc(sizeof(struct JournalEntry));
|
||||
e = calloc(1, sizeof(struct JournalEntry));
|
||||
if (!e) {
|
||||
return -1;
|
||||
}
|
||||
@@ -138,10 +141,6 @@ static int deserialize_journal_entry(char *line, struct JournalEntry **entry)
|
||||
e->boot_id = out;
|
||||
rc = 0;
|
||||
break;
|
||||
default:
|
||||
assert(i < 0 && i > 4);
|
||||
free(out);
|
||||
rc = 1;
|
||||
}
|
||||
} else {
|
||||
rc = -1;
|
||||
@@ -273,6 +272,8 @@ static int skip_n_lines(int n, FILE *fptr, int (*found_record)(char *))
|
||||
break;
|
||||
}
|
||||
if (found_record != NULL) {
|
||||
if (!strlen(line))
|
||||
continue;
|
||||
deserialize_journal_entry(line, &entry);
|
||||
if (entry) {
|
||||
found_record(entry->record_id);
|
||||
@@ -346,12 +347,14 @@ TelemJournal *open_journal(const char *journal_file)
|
||||
|
||||
if (read_boot_id(boot_id) != 0) {
|
||||
telem_perror("Error while reading boot_id");
|
||||
fclose(fptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
telem_journal = malloc(sizeof(struct TelemJournal));
|
||||
if (!telem_journal) {
|
||||
telem_log(LOG_CRIT, "CRIT: Unable to allocate memory\n");
|
||||
fclose(fptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -418,6 +421,7 @@ static void print_record(char *record_id)
|
||||
recordfp = fopen(filepath, "r");
|
||||
if (!recordfp) {
|
||||
telem_log(LOG_INFO, "Could not open record %s: %s\n", record_id, strerror(errno));
|
||||
free(filepath);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -465,6 +469,8 @@ int print_journal(TelemJournal *telem_journal, char *classification,
|
||||
}
|
||||
|
||||
while (getline(&line, &len, journal_fileptr) != -1) {
|
||||
if (!strlen(line))
|
||||
continue;
|
||||
deserialize_journal_entry(line, &entry);
|
||||
if (entry) {
|
||||
/* filter entry out if one is provided */
|
||||
@@ -482,16 +488,16 @@ int print_journal(TelemJournal *telem_journal, char *classification,
|
||||
// Check prefixes when classification ends in /*, otherwise use strcomp
|
||||
if (is_class_prefix(classification)) {
|
||||
if (strncmp(entry->classification, classification, strlen(classification) - 1) != 0) {
|
||||
continue;
|
||||
goto skip_print;
|
||||
}
|
||||
} else if (strcmp(entry->classification, classification) != 0) {
|
||||
continue;
|
||||
goto skip_print;
|
||||
}
|
||||
}
|
||||
/* end filters section */
|
||||
ts = *localtime(&entry->timestamp);
|
||||
if (strftime(str_time, sizeof(str_time), "%a %Y-%m-%d %H:%M:%S %Z", &ts) == 0) {
|
||||
continue;
|
||||
goto skip_print;
|
||||
}
|
||||
/* print record metadata */
|
||||
fprintf(stdout, "%-30s %s %s %s %s\n", entry->classification, str_time, entry->record_id, entry->event_id, entry->boot_id);
|
||||
@@ -500,9 +506,9 @@ int print_journal(TelemJournal *telem_journal, char *classification,
|
||||
print_record(entry->record_id);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
skip_print:
|
||||
free_journal_entry(entry);
|
||||
free_journal_entry(entry);
|
||||
}
|
||||
}
|
||||
free(line);
|
||||
fclose(journal_fileptr);
|
||||
@@ -656,7 +662,8 @@ int prune_journal(struct TelemJournal *telem_journal, char *tmp_dir)
|
||||
telem_journal->fptr = fopen(telem_journal->journal_file, "a+");
|
||||
if (!telem_journal->fptr) {
|
||||
telem_log(LOG_ERR, "Error re-opening journal file\n");
|
||||
return rc;
|
||||
rc = 1;
|
||||
goto quit;
|
||||
}
|
||||
// update record count
|
||||
telem_journal->record_count = telem_journal->record_count - count;
|
||||
|
||||
+15
-5
@@ -1,6 +1,17 @@
|
||||
bin_PROGRAMS = \
|
||||
%D%/telemprobd \
|
||||
%D%/telempostd
|
||||
%D%/telempostd \
|
||||
%D%/telemctl
|
||||
|
||||
%C%_telemctl_SOURCES = \
|
||||
%D%/telemctl.c
|
||||
|
||||
%C%_telemctl_CFLAGS = \
|
||||
$(AM_CFLAGS)
|
||||
|
||||
%C%_telemctl_LDFLAGS = \
|
||||
$(AM_LDFLAGS) \
|
||||
-pie
|
||||
|
||||
%C%_telemprobd_SOURCES = \
|
||||
%D%/probe.c \
|
||||
@@ -50,7 +61,7 @@ endif
|
||||
%D%/iorecord.c \
|
||||
%D%/iorecord.h
|
||||
|
||||
%C%_telempostd_LDADD = $(CURL_LIBS) \
|
||||
%C%_telempostd_LDADD = $(CURL_LIBS) $(JSON_C_LIBS) \
|
||||
%D%/libtelem-shared.la \
|
||||
%D%/libtelemetry.la
|
||||
|
||||
@@ -79,8 +90,8 @@ endif
|
||||
|
||||
# set library version info
|
||||
SHAREDLIB_CURRENT=4
|
||||
SHAREDLIB_REVISION=0
|
||||
SHAREDLIB_AGE=1
|
||||
SHAREDLIB_REVISION=1
|
||||
SHAREDLIB_AGE=0
|
||||
|
||||
noinst_LTLIBRARIES = %D%/libtelem-shared.la
|
||||
|
||||
@@ -90,7 +101,6 @@ noinst_LTLIBRARIES = %D%/libtelem-shared.la
|
||||
%D%/configuration.c \
|
||||
%D%/nica/inifile.c \
|
||||
%D%/nica/hashmap.c \
|
||||
%D%/nica/b64enc.c \
|
||||
%D%/configuration.h \
|
||||
%D%/common.c \
|
||||
%D%/common.h
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
* This file is part of libnica.
|
||||
*
|
||||
* Copyright © 2017 Intel Corporation
|
||||
*
|
||||
* libnica is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1
|
||||
* of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "b64enc.h"
|
||||
|
||||
#define B64_LINE_LEN 76
|
||||
|
||||
static int padding[] = {0, 2, 1, 0};
|
||||
static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
|
||||
/*
|
||||
* base 64 encoding of 3 bytes to 4 printable characters
|
||||
* (https://tools.ietf.org/html/rfc4648).
|
||||
*
|
||||
* i.e. (Reference: https://en.wikipedia.org/wiki/Base64)
|
||||
*
|
||||
* [ M ] [ a ] [ n ]
|
||||
* bin 01001101 01100001 01101110
|
||||
*
|
||||
* b64 01001101 01100001 01101110 >> 18 & 0x3F -> 010011 -> ( 19 dec) T
|
||||
* ------
|
||||
*
|
||||
* b64 01001101 01100001 01101110 >> 12 & 0x3F -> 010110 -> ( 22 dec) W
|
||||
* -------
|
||||
*
|
||||
* b64 01001101 01100001 01101110 >> 6 & 0x3F -> 000101 -> ( 5 dec) F
|
||||
* -------
|
||||
*
|
||||
* b64 01001101 01100001 01101110 >> 0 & 0x3F -> 101110 -> (117 dec) u
|
||||
* ------
|
||||
*
|
||||
*/
|
||||
static void b64_3b(char bin[3], char *out) {
|
||||
|
||||
uint32_t x = (((uint32_t) bin[0] << 16) & 0xFF0000) |
|
||||
(((uint32_t) bin[1] << 8) & 0xFF00) |
|
||||
(((uint32_t) bin[2]) & 0xFF);
|
||||
|
||||
out[3] = table[x & 0x3F];
|
||||
out[2] = table[x >> 6 & 0x3F];
|
||||
out[1] = table[x >> 12 & 0x3F];
|
||||
out[0] = table[x >> 18 & 0x3F];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Provide padding to already initialized b64 output
|
||||
*/
|
||||
static void b64_padding(char *out, int pad_size) {
|
||||
|
||||
if (pad_size > 0) {
|
||||
*out++ = '=';
|
||||
}
|
||||
|
||||
if (pad_size > 1) {
|
||||
*out++ = '=';
|
||||
}
|
||||
|
||||
*out = '\0';
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Encode file contents as b64 string
|
||||
*/
|
||||
int nc_b64enc_file(FILE *fh, char *buff, size_t buff_size) {
|
||||
|
||||
int ret_val = 1;
|
||||
int out_count = 0;
|
||||
int pad_size = 0;
|
||||
char *buff_ptr = buff;
|
||||
char bin[3] = {0, 0, 0};
|
||||
size_t len = 0;
|
||||
|
||||
while ((len = fread(bin, 1, 3, fh)) > 0) {
|
||||
b64_3b(bin, buff_ptr);
|
||||
/*
|
||||
Reset 2nd and 3rd bytes in case only one byte was read. If these
|
||||
bytes are not clean b64 output will be corrupted with old bits.
|
||||
*/
|
||||
bin[1] = bin[2] = 0;
|
||||
/*
|
||||
Advance pointer to the next free position of the b64 encoded
|
||||
buffer. This happens to be len + 1 (as longs as len >= 1 and len <= 3)
|
||||
|
||||
len = 1 byte -> b64 -> 2 bytes (or len + 1)
|
||||
len = 2 bytes -> b64 -> 3 bytes (or len + 1)
|
||||
len = 3 bytes -> b64 -> 4 bytes (or len + 1)
|
||||
*/
|
||||
buff_ptr += (len + 1);
|
||||
/*
|
||||
Line break every 76 characters
|
||||
*/
|
||||
out_count += (int) (len + 1);
|
||||
if (out_count % B64_LINE_LEN == 0) {
|
||||
*buff_ptr++ = '\n';
|
||||
}
|
||||
pad_size = padding[len];
|
||||
/*
|
||||
Check not to overflow buffer
|
||||
|
||||
buffer size <= b64 characters + padding length + null termination
|
||||
*/
|
||||
if (buff_size <= (size_t) (buff_ptr - buff) + (size_t) pad_size + 1) {
|
||||
ret_val = 0;
|
||||
goto end_b64_enc;
|
||||
}
|
||||
}
|
||||
|
||||
b64_padding(buff_ptr, pad_size);
|
||||
|
||||
end_b64_enc:
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
int nc_b64enc_filename(const char *filename, char *buff, size_t buff_size) {
|
||||
|
||||
int ret = 0;
|
||||
FILE *fh = NULL;
|
||||
|
||||
fh = fopen(filename, "rb");
|
||||
|
||||
if (fh == NULL) {
|
||||
goto nc_b64_clean;
|
||||
}
|
||||
|
||||
ret = nc_b64enc_file(fh, buff, buff_size);
|
||||
|
||||
nc_b64_clean:
|
||||
|
||||
if (fh) {
|
||||
fclose(fh);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* vi: set ts=8 sw=8 sts=4 et tw=80 cino=(0: */
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* This file is part of libnica.
|
||||
*
|
||||
* Copyright © 2017 Intel Corporation
|
||||
*
|
||||
* libnica is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This is a chained base64 encode implementation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "macros.h"
|
||||
|
||||
/*
|
||||
* Encodes contents of file handler in base64
|
||||
*
|
||||
* @param fh File handler to encode as base64
|
||||
* @param buff Output buffer where the base64 output should be written
|
||||
* @param buff_size Size of the output buffer
|
||||
*
|
||||
* @returns 1 in success and 0 in failure
|
||||
*/
|
||||
_nica_public_ int nc_b64enc_file(FILE *fh, char *buff, size_t buff_size);
|
||||
|
||||
|
||||
/*
|
||||
* Encodes contents of file (filename) in base64
|
||||
*
|
||||
* @param filename File to encode as base64
|
||||
* @param buff Output buffer where the base64 output should be written
|
||||
* @param buff_size Size of the output buffer
|
||||
*
|
||||
* @returns 1 in success and 0 in failure
|
||||
*/
|
||||
_nica_public_ int nc_b64enc_filename(const char *filename, char *buff, size_t buff_size);
|
||||
|
||||
+36
-24
@@ -151,33 +151,38 @@ static char *string_strip(char *str, ssize_t len, ssize_t *out_len)
|
||||
/* eat \s */
|
||||
static char *string_unescape(char *str)
|
||||
{
|
||||
char *c, *c1, *c2, *c3;;
|
||||
char *c, *c1, *c2, *c3;;
|
||||
|
||||
if (!str)
|
||||
return NULL;
|
||||
if (!str) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
c = calloc(strlen(str) + 1, 1);
|
||||
c1 = c;
|
||||
c = calloc(strlen(str) + 1, 1);
|
||||
if (c == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
c2 = str;
|
||||
while (c2 && *c2 != 0) {
|
||||
c3 = c2 + 1;
|
||||
if (*c2 == '\\') {
|
||||
if (*c3 == 's') {
|
||||
*c = ' ';
|
||||
c++;
|
||||
c2 += 2;
|
||||
} else {
|
||||
c2++;
|
||||
}
|
||||
} else {
|
||||
*c = *c2;
|
||||
c++;
|
||||
c2++;
|
||||
}
|
||||
}
|
||||
c1 = c;
|
||||
|
||||
free(str);
|
||||
c2 = str;
|
||||
while (c2 && *c2 != 0) {
|
||||
c3 = c2 + 1;
|
||||
if (*c2 == '\\') {
|
||||
if (*c3 == 's') {
|
||||
*c = ' ';
|
||||
c++;
|
||||
c2 += 2;
|
||||
} else {
|
||||
c2++;
|
||||
}
|
||||
} else {
|
||||
*c = *c2;
|
||||
c++;
|
||||
c2++;
|
||||
}
|
||||
}
|
||||
|
||||
free(str);
|
||||
return c1;
|
||||
}
|
||||
|
||||
@@ -300,7 +305,14 @@ int nc_ini_file_parse_full(const char *path, NcHashmap **out_map, int *error_lin
|
||||
key = strdup(buf);
|
||||
key = string_chew_terminated(key);
|
||||
value = string_chew_terminated(value);
|
||||
value = string_unescape(value);
|
||||
if (value != NULL) {
|
||||
value = string_unescape(value);
|
||||
if (value == NULL) {
|
||||
err_ret = NC_INI_ERROR_INTERNAL;
|
||||
fprintf(stderr, "[inifile] Fatal! Out of memory\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (streq(key, "")) {
|
||||
err_ret = NC_INI_ERROR_EMPTY_KEY;
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
The default probes provided along the telemetry client code are:
|
||||
|
||||
* bertprobe: this probe reports on the Boot Error Region Table if such
|
||||
entry is found in ```/sys/firmware/acpi/tables/BERT```.
|
||||
|
||||
* crashprobe: This probe processes core dump files. It can be registered as
|
||||
the kernel core file handler in /proc/sys/kernel/core_pattern.
|
||||
|
||||
@@ -15,12 +12,10 @@ The default probes provided along the telemetry client code are:
|
||||
from failed services.
|
||||
|
||||
* klogscanner: a probe to collect 'oops messages' when the kernel detects a
|
||||
problem.
|
||||
problem. Also reports errors in the Boot Error Region Table if detected.
|
||||
|
||||
* pstoreprobe: probe to collect messages left on pstore filesystem.
|
||||
|
||||
* pythonprobe: a probe that monitors Python generated traceback files.
|
||||
|
||||
* telem-record-gen: this is a "general-purpose probe" for sending custom
|
||||
records on-the-fly. This tool can be used stand alone or as a part of a
|
||||
script to implement a probe.
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* This program is part of the Clear Linux Project
|
||||
*
|
||||
* Copyright 2018 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
|
||||
* published by the Free Software Foundation; either version 2.1 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <getopt.h>
|
||||
#include "common.h"
|
||||
#include "telemetry.h"
|
||||
#include "nica/b64enc.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
|
||||
static const char bert_record_file[] = "/sys/firmware/acpi/tables/data/BERT";
|
||||
static const char telem_record_class[] = "org.clearlinux/bert/debug";
|
||||
static uint32_t severity = 2;
|
||||
static uint32_t payload_version = 1;
|
||||
|
||||
void print_usage(char *prog)
|
||||
{
|
||||
printf("%s: Usage\n", prog);
|
||||
printf(" -f, --config_file Specify a configuration file other than default\n");
|
||||
printf(" -h, --help Display this help message\n");
|
||||
printf(" -V, --version Print the program version\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct telem_ref *tm_handle = NULL;
|
||||
char *classification = (char *)telem_record_class;
|
||||
char *payload;
|
||||
int ret;
|
||||
|
||||
// Following vars are for arg parsing.
|
||||
int c;
|
||||
int opt_index = 0;
|
||||
struct option opts[] = {
|
||||
{ "config_file", 1, NULL, 'f' },
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "version", 0, NULL, 'V' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
while ((c = getopt_long(argc, argv, "f:hV", opts, &opt_index)) != -1) {
|
||||
switch (c) {
|
||||
case 'f':
|
||||
if (tm_set_config_file(optarg) != 0) {
|
||||
telem_log(LOG_ERR, "Configuration file"
|
||||
" path not valid\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
print_usage(argv[0]);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'V':
|
||||
printf(PACKAGE_VERSION "\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
case '?':
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
payload = calloc(sizeof(char), MAX_PAYLOAD_LENGTH);
|
||||
if (!payload) {
|
||||
printf("Unable to allocate more memory.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (!(ret = nc_b64enc_filename(bert_record_file, payload, MAX_PAYLOAD_LENGTH))) {
|
||||
printf("Failed to read payload from: %s\n", bert_record_file);
|
||||
ret = EXIT_FAILURE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((ret = tm_create_record(&tm_handle, severity, classification,
|
||||
payload_version)) < 0) {
|
||||
printf("Failed to create record: %s\n", strerror(-ret));
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((ret = tm_set_payload(tm_handle, payload)) < 0) {
|
||||
printf("Failed to set record payload: %s\n", strerror(-ret));
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((ret = tm_send_record(tm_handle)) < 0) {
|
||||
printf("Failed to send record to daemon: %s\n", strerror(-ret));
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = EXIT_SUCCESS;
|
||||
done:
|
||||
free(payload);
|
||||
tm_free_record(tm_handle);
|
||||
tm_handle = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* vi: set ts=8 sw=8 sts=4 et tw=80 cino=(0: */
|
||||
@@ -250,7 +250,7 @@ static int frame_cb(Dwfl_Frame *frame, void *userdata)
|
||||
" current frame: %s\n",
|
||||
dwfl_errmsg(-1));
|
||||
if (ret < 0) {
|
||||
return DWARF_CB_ABORT;
|
||||
errorstr = NULL;
|
||||
}
|
||||
return DWARF_CB_ABORT;
|
||||
}
|
||||
@@ -396,6 +396,7 @@ static int process_corefile(nc_string **backtrace)
|
||||
nc_string_free(*backtrace);
|
||||
}
|
||||
*backtrace = nc_string_dup("");
|
||||
frame_counter = 0;
|
||||
|
||||
if (dwfl_getthreads(d_core, thread_cb, backtrace) != DWARF_CB_OK) {
|
||||
/* We aborted unwinding, due to too many frames.
|
||||
@@ -586,7 +587,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (core_file) {
|
||||
core_fd = open(core_file, O_RDONLY);
|
||||
core_fd = open(core_file, O_RDONLY|O_NOFOLLOW);
|
||||
if (core_fd == -1) {
|
||||
telem_perror("Failed to open input core file");
|
||||
goto fail;
|
||||
|
||||
+1
-1
@@ -159,7 +159,7 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
case 'H':
|
||||
str = "org.clearlinux/heartbeat/ping";
|
||||
memcpy(classification, str, strlen(str));
|
||||
memcpy(classification, str, strlen(str) + 1);
|
||||
break;
|
||||
case 'l':
|
||||
payload_options |= PAYLOAD_LOCALE;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "log.h"
|
||||
#include "oops_parser.h"
|
||||
#include "klog_scanner.h"
|
||||
@@ -44,6 +45,11 @@ static bool send_data(char *backtrace, char *class, uint32_t severity)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Truncate payload if necessary, otherwise nothing will be sent */
|
||||
if (strlen(backtrace) > MAX_PAYLOAD_LENGTH) {
|
||||
backtrace[MAX_PAYLOAD_LENGTH-1] = 0;
|
||||
}
|
||||
|
||||
if ((ret = tm_set_payload(handle, backtrace)) < 0) {
|
||||
telem_log(LOG_ERR, "Failed to set payload: %s", strerror(-ret));
|
||||
tm_free_record(handle);
|
||||
|
||||
+1
-32
@@ -4,23 +4,7 @@ bin_PROGRAMS += \
|
||||
%D%/telem-record-gen \
|
||||
%D%/klogscanner \
|
||||
%D%/pstoreprobe \
|
||||
%D%/pythonprobe \
|
||||
%D%/pstoreclean \
|
||||
%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
|
||||
%D%/pstoreclean
|
||||
|
||||
%C%_hprobe_SOURCES = %D%/hello.c
|
||||
%C%_hprobe_LDADD = $(top_builddir)/src/libtelemetry.la
|
||||
@@ -36,21 +20,6 @@ if HAVE_SYSTEMD_JOURNAL
|
||||
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)
|
||||
|
||||
+78
-14
@@ -150,6 +150,24 @@ struct oops_pattern oops_patterns_arr[] = {
|
||||
TM_MEDIUM,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"ACPI Error:",
|
||||
"org.clearlinux/kernel/warning",
|
||||
TM_MEDIUM,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"Kernel panic - not syncing:",
|
||||
"org.clearlinux/kernel/panic",
|
||||
TM_CRITICAL,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"BERT: Error records from previous boot:",
|
||||
"org.clearlinux/bert/debug",
|
||||
TM_MEDIUM,
|
||||
false,
|
||||
},
|
||||
};
|
||||
|
||||
static int oops_patterns_cnt = sizeof(oops_patterns_arr) / sizeof(struct oops_pattern);
|
||||
@@ -322,6 +340,7 @@ void oops_msg_cleanup(struct oops_log_msg *msg)
|
||||
static struct oops_log_msg oops_msg;
|
||||
|
||||
static bool in_stack_dump = false;
|
||||
static bool in_bert_dump = false;
|
||||
|
||||
static oops_handler_t oops_handler;
|
||||
|
||||
@@ -345,6 +364,19 @@ void oops_parser_cleanup()
|
||||
free_pattern_regex();
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
[ 1.609112] BERT: Error records from previous boot:
|
||||
[ 1.609113] [Hardware Error]: event severity: fatal
|
||||
[ 1.609115] [Hardware Error]: Error 0, type: fatal
|
||||
[ 1.609116] [Hardware Error]: section type: unknown, 81212a96-09ed-4996-9471-8d729c8e69ed
|
||||
[ 1.609117] [Hardware Error]: section length: 0xc10
|
||||
[ 1.609119] [Hardware Error]: 00000000: 00000001 00000000 00000000 01001002 ................
|
||||
[ 1.609120] [Hardware Error]: 00000010: 01001002 00000001 c71f0d2f 00000003 ......../.......
|
||||
[ 1.609122] [Hardware Error]: 00000020: 00000001 0000004f 0c070048 800001ff ....O...H.......
|
||||
[ 1.609123] [Hardware Error]: 00000030: 02002080 7e15fe03 00000001 00000000 . .....~......
|
||||
...
|
||||
*/
|
||||
void parse_single_line(char *line, size_t size)
|
||||
{
|
||||
char *start;
|
||||
@@ -364,28 +396,30 @@ void parse_single_line(char *line, size_t size)
|
||||
continue;
|
||||
}
|
||||
telem_log(LOG_DEBUG, "Oops start has been detected\n");
|
||||
|
||||
oops_msg.pattern = pattern;
|
||||
oops_msg.lines[oops_msg.length] = strndup(start, (size_t)(line_end - start));
|
||||
if (oops_msg.lines[oops_msg.length] == NULL) {
|
||||
//telem_perror("Failed to copy string");
|
||||
exit(EXIT_FAILURE);
|
||||
return;
|
||||
} else {
|
||||
oops_msg.length++;
|
||||
}
|
||||
|
||||
oops_msg.length++;
|
||||
in_stack_dump = false;
|
||||
break;
|
||||
in_bert_dump = false;
|
||||
if (strstr(oops_msg.pattern->begin_line, "BERT:")) {
|
||||
in_bert_dump = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// If in the middle of oops
|
||||
if (oops_msg.length >= MAX_LINES) {
|
||||
fprintf(stderr,"*** MAX_LINES!!\n");
|
||||
end_found = true;
|
||||
// } else if (oops_msg.end_line && strstr(start, oops_msg.end_line)) {
|
||||
// end_found = false;
|
||||
} else if (strstr(start, "[ end trace")) {
|
||||
end_found = true;
|
||||
} else if (!in_stack_dump) {
|
||||
} else if (!in_stack_dump && !in_bert_dump) {
|
||||
// This line indicates the beginning of a stack trace;
|
||||
// the next line is most likely the topmost frame.
|
||||
if (starts_with(start, line_end, "Call Trace:")) {
|
||||
@@ -402,6 +436,10 @@ void parse_single_line(char *line, size_t size)
|
||||
in_stack_dump = false;
|
||||
end_found = true;
|
||||
}
|
||||
} else if (in_bert_dump) {
|
||||
if (!strstr(start, "[Hardware Error]:")) {
|
||||
end_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* if a new oops starts, this one has ended */
|
||||
@@ -469,7 +507,7 @@ static void stack_frame_append(struct stack_frame **head, struct stack_frame **t
|
||||
while (*start && !isspace(*start)) {
|
||||
start++;
|
||||
}
|
||||
if (start && *start == '\0') {
|
||||
if (*start == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -504,7 +542,7 @@ static void stack_frame_append(struct stack_frame **head, struct stack_frame **t
|
||||
while (*start && !isspace(*start)) {
|
||||
start++;
|
||||
}
|
||||
if (start && *start == '\0') {
|
||||
if (*start == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -539,6 +577,10 @@ static void stack_frame_free(struct stack_frame **head)
|
||||
|
||||
while (*head != NULL) {
|
||||
frame = (*head)->next;
|
||||
// First free memory allocation for function name
|
||||
if ((*head)->function) {
|
||||
free((*head)->function);
|
||||
}
|
||||
free(*head);
|
||||
*head = frame;
|
||||
}
|
||||
@@ -546,8 +588,8 @@ static void stack_frame_free(struct stack_frame **head)
|
||||
|
||||
/*
|
||||
* Function parses lines of the format :
|
||||
* CPU: 2 PID: 6429 Comm: insmod Tainted: P OE 3.19.0-18-generic #18-Ubuntu$
|
||||
* CPU: 2 PID: 0 Comm: swapper/2 Not tainted 3.10.4-100.fc18.x86_64 #1
|
||||
* CPU: 2 PID: 6429 Comm: insmod Tainted: POE 3.19.0-18-generic #18-Ubuntu$
|
||||
* CPU: 2 PID: 0 Comm: swapper/2 Not tainted 3.10.4-100.fc18.x86_64 #1
|
||||
* CPU: 3 PID: 0 Comm: swapper/3 Not tainted 4.0.5-300.fc22.x86_64 #1
|
||||
*/
|
||||
static void parse_kernel_cpu_line(char *line, char **kernel_version, char **tainted)
|
||||
@@ -796,6 +838,15 @@ static nc_string *parse_backtrace(struct oops_log_msg *msg)
|
||||
|
||||
if (str_starts_with_casei(line, "CPU: ") ||
|
||||
str_starts_with_casei(line, "PID: ")) {
|
||||
/* Can't assume that these variables (tainted,
|
||||
* an kernel_version) are not already allocated
|
||||
* otherwise it will leak memory */
|
||||
if (tainted) {
|
||||
free(tainted);
|
||||
}
|
||||
if (kernel_version) {
|
||||
free(kernel_version);
|
||||
}
|
||||
parse_kernel_cpu_line(line, &kernel_version, &tainted);
|
||||
continue;
|
||||
}
|
||||
@@ -835,15 +886,28 @@ static nc_string *parse_backtrace(struct oops_log_msg *msg)
|
||||
return backtrace;
|
||||
}
|
||||
|
||||
static void append_payload(nc_string *payload, struct oops_log_msg *msg)
|
||||
{
|
||||
for (int i = 1; i < msg->length; i++) {
|
||||
nc_string_cat(payload,msg->lines[i]);
|
||||
nc_string_cat(payload,"\n");
|
||||
}
|
||||
}
|
||||
|
||||
nc_string *parse_payload(struct oops_log_msg *msg)
|
||||
{
|
||||
nc_string *payload, *backtrace;
|
||||
|
||||
payload = nc_string_dup("Crash Report:\n");
|
||||
nc_string_append_printf(payload, "Reason: %s\n", msg->lines[0]);
|
||||
backtrace = parse_backtrace(msg);
|
||||
nc_string_cat(payload, backtrace->str);
|
||||
nc_string_free(backtrace);
|
||||
if (strstr(msg->lines[0], "BERT:")) {
|
||||
append_payload(payload, msg);
|
||||
} else {
|
||||
backtrace = parse_backtrace(msg);
|
||||
nc_string_cat(payload, backtrace->str);
|
||||
nc_string_free(backtrace);
|
||||
}
|
||||
|
||||
return payload;
|
||||
|
||||
}
|
||||
|
||||
@@ -44,14 +44,14 @@ int copy_file(char *src_file, char *dest_file)
|
||||
ssize_t bytes_read, bytes_written;
|
||||
int ret = -1;
|
||||
|
||||
src_fd = open(src_file, O_RDONLY);
|
||||
src_fd = open(src_file, O_RDONLY|O_NOFOLLOW);
|
||||
if (src_fd == -1) {
|
||||
telem_log(LOG_ERR, "Failed to open file %s:%s\n", src_file,
|
||||
strerror(errno));
|
||||
goto end;
|
||||
}
|
||||
|
||||
dest_fd = open(dest_file, O_WRONLY | O_CREAT, 0644);
|
||||
dest_fd = open(dest_file, O_WRONLY|O_CREAT|O_NOFOLLOW, 0644);
|
||||
if (dest_fd == -1) {
|
||||
telem_log(LOG_ERR, "Failed to create file %s:%s\n", dest_file,
|
||||
strerror(errno));
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
@@ -195,6 +196,13 @@ struct chunk_list {
|
||||
struct chunk_list *next;
|
||||
};
|
||||
|
||||
static void print_usage(char *prog)
|
||||
{
|
||||
printf("%s: Usage\n", prog);
|
||||
printf(" -f, --config_file This overides the other parameters\n");
|
||||
printf(" -h, --help Display this help message\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
DIR *pstore_dir;
|
||||
@@ -205,6 +213,32 @@ int main(int argc, char **argv)
|
||||
int max_part;
|
||||
size_t totalsize = 0;
|
||||
char *crash_dump = NULL;
|
||||
int c;
|
||||
int opt_index = 0;
|
||||
|
||||
struct option opts[] = {
|
||||
{ "config_file", 1, NULL, 'f' },
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
while ((c = getopt_long(argc, argv, "f:h", opts, &opt_index)) != -1) {
|
||||
switch (c) {
|
||||
case 'f':
|
||||
if (tm_set_config_file(optarg) != 0) {
|
||||
telem_log(LOG_ERR, "Configuration file"
|
||||
" path not valid\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
print_usage(argv[0]);
|
||||
exit(EXIT_SUCCESS);
|
||||
case '?':
|
||||
print_usage(argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Hash table used to store chunks belonging to a oops counter
|
||||
@@ -230,7 +264,13 @@ 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);
|
||||
telem_debug("DEBUG: Extracted count :%d, part : %d\n", count, part);
|
||||
telem_debug("dmesg-efi Extracted count :%d, part : %d\n",
|
||||
count, part);
|
||||
} else if (sscanf(entry->d_name, "dmesg-ramoops-%" PRIu64, &id) == 1) {
|
||||
count = (int)(id + 1);
|
||||
part = 1;
|
||||
telem_debug("dmesg-ramoops Extracted count :%d, part : %d\n",
|
||||
count, part);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,293 +0,0 @@
|
||||
/*
|
||||
* This program is part of the Clear Linux Project
|
||||
*
|
||||
* Copyright 2019 Intel Corporation
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "telemetry.h"
|
||||
|
||||
#define PYTHON_TELEMETRY_DIR "/var/lib/telemetry/python"
|
||||
|
||||
/* We expect something like: 1.python-exception.3.N2Qy24 */
|
||||
static bool validate_file_name(const char *filename, uint32_t *severity,
|
||||
char** class, uint32_t *version)
|
||||
{
|
||||
unsigned int ver, sev;
|
||||
char cls[PATH_MAX] = { 0 };
|
||||
char rnd[PATH_MAX] = { 0 };
|
||||
char *filename_base = basename(filename);
|
||||
char *str_class = NULL;
|
||||
|
||||
if (!filename_base) {
|
||||
telem_perror("basename failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sscanf(filename_base,"%u.%[^]0-9.].%u.%s", &ver, cls, &sev, rnd) == 4) {
|
||||
if (asprintf(&str_class, "org.clearlinux/python/%s", cls) < 29) {
|
||||
telem_log(LOG_ERR, "%s: invalid telemetry classification\n",
|
||||
str_class);
|
||||
return false;
|
||||
}
|
||||
*class = str_class;
|
||||
*version = ver;
|
||||
*severity = sev;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static char *read_file_into_buffer(const char *filename)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
char *contents = NULL;
|
||||
long sz;
|
||||
size_t size, bytes_read;
|
||||
|
||||
fp = fopen(filename, "r");
|
||||
if (fp == NULL) {
|
||||
telem_log(LOG_ERR, "Failed to open Python telemetry file %s: %s\n",
|
||||
filename, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (fseek(fp, 0, SEEK_END) == -1) {
|
||||
telem_log(LOG_ERR, "Failed to seek file %s: %s\n", filename,
|
||||
strerror(errno));
|
||||
goto error_end;
|
||||
}
|
||||
|
||||
sz = ftell(fp);
|
||||
if (sz == -1L) {
|
||||
telem_perror("ftell failed");
|
||||
goto error_end;
|
||||
}
|
||||
|
||||
if (sz == 0L) {
|
||||
telem_perror("File is empty\n");
|
||||
goto error_end;
|
||||
}
|
||||
|
||||
if (fseek(fp, 0, SEEK_SET) < 0) {
|
||||
telem_log(LOG_ERR, "fseek failed for file %s:%s\n", filename,
|
||||
strerror(errno));
|
||||
goto error_end;
|
||||
}
|
||||
|
||||
size = (size_t)sz;
|
||||
contents = calloc(sizeof(char), size);
|
||||
if (!contents) {
|
||||
telem_log(LOG_ERR, "Call to calloc failed\n");
|
||||
goto error_end;
|
||||
}
|
||||
|
||||
bytes_read = fread(contents, sizeof(char), size, fp);
|
||||
|
||||
if (bytes_read < size) {
|
||||
telem_log(LOG_ERR, "Error while reading file %s:%s\n", filename,
|
||||
strerror(errno));
|
||||
goto error_end;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return contents;
|
||||
|
||||
error_end:
|
||||
fclose(fp);
|
||||
if (contents) {
|
||||
free(contents);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void send_data(char *contents, uint32_t severity, char *class,
|
||||
uint32_t version)
|
||||
{
|
||||
struct telem_ref *handle = NULL;
|
||||
int ret;
|
||||
|
||||
if ((ret = tm_create_record(&handle, severity, class, version)) < 0) {
|
||||
telem_log(LOG_ERR, "Failed to create record: %s\n",
|
||||
strerror(-ret));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ret = tm_set_payload(handle, contents)) < 0) {
|
||||
telem_log(LOG_ERR, "Failed to set payload: %s\n",
|
||||
strerror(-ret));
|
||||
tm_free_record(handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ret = tm_send_record(handle)) < 0) {
|
||||
telem_log(LOG_ERR, "Failed to send record: %s\n",
|
||||
strerror(-ret));
|
||||
}
|
||||
|
||||
tm_free_record(handle);
|
||||
}
|
||||
|
||||
/* Send a valid file to the backend. */
|
||||
static void deliver_payload(const char *filename)
|
||||
{
|
||||
uint32_t severity;
|
||||
uint32_t version;
|
||||
char *class = NULL;
|
||||
char *contents = NULL;
|
||||
|
||||
if (validate_file_name(filename, &severity, &class, &version)) {
|
||||
if ((contents = read_file_into_buffer(filename)) != NULL) {
|
||||
send_data(contents, severity, class, version);
|
||||
free(contents);
|
||||
}
|
||||
|
||||
free(class);
|
||||
}
|
||||
|
||||
/* Keep PYTHON_TELEMETRY_DIR empty. Delete the file. */
|
||||
if (unlink(filename) != 0) {
|
||||
telem_log(LOG_ERR, "Failed to unlink %s: %s\n", filename,
|
||||
strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void drop_privs(void)
|
||||
{
|
||||
uid_t euid;
|
||||
|
||||
euid = geteuid();
|
||||
if (euid != 0) {
|
||||
telem_log(LOG_DEBUG, "Not root; skipping privilege drop\n");
|
||||
return;
|
||||
}
|
||||
|
||||
struct passwd *pw;
|
||||
|
||||
pw = getpwnam("telemetry");
|
||||
if (!pw) {
|
||||
telem_log(LOG_ERR, "telemetry user not found\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// The order is important here:
|
||||
// change supplemental groups, our gid, and then our uid
|
||||
if (initgroups(pw->pw_name, pw->pw_gid) != 0) {
|
||||
telem_perror("Failed to set supplemental group list");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (setgid(pw->pw_gid) != 0) {
|
||||
telem_perror("Failed to set GID");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (setuid(pw->pw_uid) != 0) {
|
||||
telem_perror("Failed to set UID");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
assert(getuid() == pw->pw_uid);
|
||||
assert(geteuid() == pw->pw_uid);
|
||||
assert(getgid() == pw->pw_gid);
|
||||
assert(getegid() == pw->pw_gid);
|
||||
}
|
||||
|
||||
static void print_usage(char *prog)
|
||||
{
|
||||
printf("%s: Usage\n", prog);
|
||||
printf(" -f, --config_file Specify a configuration file other than default\n");
|
||||
printf(" -h, --help Display this help message\n");
|
||||
printf(" -V, --version Print the program version\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
int c;
|
||||
int opt_index = 0;
|
||||
|
||||
struct option opts[] = {
|
||||
{ "config_file", 1, NULL, 'f' },
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "version", 0, NULL, 'V' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
drop_privs();
|
||||
|
||||
while ((c = getopt_long(argc, argv, "f:hV", opts, &opt_index)) != -1) {
|
||||
switch (c) {
|
||||
case 'f':
|
||||
if (tm_set_config_file(optarg) != 0) {
|
||||
telem_log(LOG_ERR, "Configuration file"
|
||||
" path not valid\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
print_usage(argv[0]);
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'V':
|
||||
printf(PACKAGE_VERSION "\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
case '?':
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (chdir(PYTHON_TELEMETRY_DIR)) {
|
||||
perror(PYTHON_TELEMETRY_DIR);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Process all existing files */
|
||||
dir = opendir(PYTHON_TELEMETRY_DIR);
|
||||
if (!dir) {
|
||||
perror(PYTHON_TELEMETRY_DIR);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
entry = readdir(dir);
|
||||
if (!entry) {
|
||||
break;
|
||||
}
|
||||
if (entry->d_name[0] == '.') {
|
||||
continue;
|
||||
}
|
||||
deliver_payload(entry->d_name);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
@@ -110,12 +110,21 @@ static bool parse_options(int argc, char **argv)
|
||||
severity = (uint32_t)tmp;
|
||||
break;
|
||||
case 'c':
|
||||
if (opt_class != NULL) {
|
||||
free(opt_class);
|
||||
}
|
||||
opt_class = strdup(optarg);
|
||||
break;
|
||||
case 'p':
|
||||
if (opt_payload != NULL) {
|
||||
free(opt_payload);
|
||||
}
|
||||
opt_payload = strdup(optarg);
|
||||
break;
|
||||
case 'P':
|
||||
if (opt_payload_file != NULL) {
|
||||
free(opt_payload_file);
|
||||
}
|
||||
opt_payload_file = strdup(optarg);
|
||||
break;
|
||||
case 'R':
|
||||
@@ -135,6 +144,9 @@ static bool parse_options(int argc, char **argv)
|
||||
payload_version = (uint32_t)tmp;
|
||||
break;
|
||||
case 'e':
|
||||
if (opt_event_id != NULL) {
|
||||
free(opt_event_id);
|
||||
}
|
||||
opt_event_id = strdup(optarg);
|
||||
if (opt_event_id == NULL) {
|
||||
goto fail;
|
||||
@@ -335,13 +347,13 @@ static int instanciate_record(struct telem_ref **t_ref, char *payload)
|
||||
goto out1;
|
||||
}
|
||||
|
||||
if ((ret = opt_event_id && tm_set_event_id(*t_ref, opt_event_id)) < 0) {
|
||||
goto out1;
|
||||
if (opt_event_id) {
|
||||
if ((ret = tm_set_event_id(*t_ref, opt_event_id)) < 0) {
|
||||
goto out1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = tm_set_payload(*t_ref, payload)) < 0) {
|
||||
goto out1;
|
||||
}
|
||||
ret = tm_set_payload(*t_ref, payload);
|
||||
out1:
|
||||
return ret;
|
||||
}
|
||||
@@ -356,6 +368,9 @@ static int send_record(char *payload)
|
||||
}
|
||||
|
||||
if ((ret = tm_send_record(t_ref)) < 0) {
|
||||
if (ret == -ECONNREFUSED) {
|
||||
fprintf(stderr, "Unable to send record. Make sure to opt-in to telemetry first 'telemctl opt-in'\n");
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -368,17 +383,17 @@ out:
|
||||
static int print_record(char *payload)
|
||||
{
|
||||
struct telem_ref *t_ref = NULL;
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
int ret;
|
||||
|
||||
if ((ret = instanciate_record(&t_ref, payload)) == 0) {
|
||||
int i;
|
||||
for (i = 0; i < NUM_HEADERS; i++) {
|
||||
fprintf(stdout, "%s", t_ref->record->headers[i]);
|
||||
}
|
||||
fprintf(stdout, "%s\n", t_ref->record->payload);
|
||||
tm_free_record(t_ref);
|
||||
}
|
||||
|
||||
tm_free_record(t_ref);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+20
-8
@@ -25,6 +25,7 @@
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "spool.h"
|
||||
#include "telempostdaemon.h"
|
||||
@@ -149,25 +150,32 @@ void process_spooled_record(const char *spool_dir, char *name,
|
||||
}
|
||||
|
||||
(*records_processed)++;
|
||||
ret = stat(record_name, &buf);
|
||||
if (ret == -1) {
|
||||
telem_perror("Unable to stat record in spool");
|
||||
free(record_name);
|
||||
return;
|
||||
// Use file descriptor to mitigate TOCTOU
|
||||
int fd = open(record_name, O_RDONLY|O_NOFOLLOW);
|
||||
if (fd == -1) {
|
||||
telem_perror("Unable to open record in spool");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
if (fstat(fd, &buf) == -1) {
|
||||
telem_perror("Unable to fstat record in spool");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* If file is a regular file , if uid is diff than process uid
|
||||
* or if mtime is greater than record expiry delete the file
|
||||
* If file is a regular file, if uid is different than process uid,
|
||||
* or if mtime is greater than record expiry, delete the file.
|
||||
*/
|
||||
|
||||
if (record_expiry_config() == -1) {
|
||||
telem_log(LOG_ERR, "Invalid record expiry value\n");
|
||||
close(fd);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!S_ISREG(buf.st_mode) ||
|
||||
(current_time - buf.st_mtime > (record_expiry_config() * 60)) ||
|
||||
(buf.st_uid != getuid())) {
|
||||
(buf.st_uid != getuid())) {
|
||||
unlink(record_name);
|
||||
} else if (post_succeeded && *records_sent <= TM_SPOOL_MAX_SEND_RECORDS) {
|
||||
transmit_spooled_record(record_name, &post_succeeded, buf.st_size);
|
||||
@@ -194,6 +202,9 @@ void process_spooled_record(const char *spool_dir, char *name,
|
||||
}
|
||||
}
|
||||
}
|
||||
exit:
|
||||
close(fd);
|
||||
clean:
|
||||
free(record_name);
|
||||
}
|
||||
|
||||
@@ -344,6 +355,7 @@ int spool_record_compare(const void *entrya, const void *entryb, void *path)
|
||||
ret = stat(pathb, &statentryb);
|
||||
if (ret == -1) {
|
||||
telem_log(LOG_ERR, "Unable to stat %s: %s\n", patha, strerror(errno));
|
||||
free(patha);
|
||||
free(pathb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+555
@@ -0,0 +1,555 @@
|
||||
/*
|
||||
* This program is part of the Clear Linux Project
|
||||
*
|
||||
* 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
|
||||
* published by the Free Software Foundation; either version 2.1 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <ftw.h>
|
||||
#include <unistd.h>
|
||||
#include <locale.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define TELEM_DIR "/etc/telemetrics"
|
||||
#define TM_OPT_IN TELEM_DIR"/opt-in"
|
||||
|
||||
#define TELEM_WRK_DIRS_CONF "/usr/lib/tmpfiles.d/telemetrics-dirs.conf"
|
||||
|
||||
#define cmd_create_tmp_files "systemd-tmpfiles --create " TELEM_WRK_DIRS_CONF
|
||||
#define cmd_mk_telemdir "mkdir -p " TELEM_DIR
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
static char *SPECIAL_UNITS[] = {
|
||||
"hprobe.timer",
|
||||
"telemprobd.socket",
|
||||
"telempostd.path",
|
||||
"klogscanner.service",
|
||||
"journal-probe-tail.service",
|
||||
};
|
||||
|
||||
#define NUM_SPECIAL_UNITS ARRAY_SIZE(SPECIAL_UNITS)
|
||||
|
||||
static char *SERVICES[] = {
|
||||
"hprobe.service",
|
||||
"pstore-probe.service",
|
||||
"telemprobd.service",
|
||||
"telempostd.service",
|
||||
"journal-probe.service",
|
||||
};
|
||||
|
||||
#define NUM_SERVICES ARRAY_SIZE(SERVICES)
|
||||
|
||||
static int telemctl_start(void);
|
||||
static int telemctl_stop(void);
|
||||
static int telemctl_restart(void);
|
||||
static int telemctl_is_active(void);
|
||||
static int telemctl_opt_out(void);
|
||||
static int telemctl_opt_in(void);
|
||||
static int telemctl_journal(char *);
|
||||
|
||||
struct telemcmd {
|
||||
bool root;
|
||||
char *cmd;
|
||||
union {
|
||||
int (*f1)(void);
|
||||
int (*f2)(char *);
|
||||
} f;
|
||||
char *doc;
|
||||
};
|
||||
|
||||
static struct telemcmd commands[] = {
|
||||
{true, "stop", {.f1=telemctl_stop}, "Stops all running telemetry services" },
|
||||
{true, "start", {.f1=telemctl_start}, "Starts all telemetry services" },
|
||||
{true, "restart", {.f1=telemctl_restart}, "Restarts all telemetry services" },
|
||||
{false, "is-active", {.f1=telemctl_is_active},"Checks if telemprobd and telempostd are active" },
|
||||
{true, "opt-in", {.f1=telemctl_opt_in}, "Opts in to telemetry, and starts telemetry services" },
|
||||
{true, "opt-out", {.f1=telemctl_opt_out}, "Opts out of telemetry, and stops telemetry services" },
|
||||
{true, "journal", {.f2=telemctl_journal}, "Prints telemetry journal contents. Use -h argument with\n command for more options"}
|
||||
};
|
||||
|
||||
static int syscmd(char *cmd, char *buff, int bufflen)
|
||||
{
|
||||
int status;
|
||||
#ifdef DEBUG
|
||||
printf("[debug] [%s] %s\n", __func__, cmd);
|
||||
#endif
|
||||
FILE *fp = popen(cmd, "r");
|
||||
if (fp == NULL) {
|
||||
perror("popen");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(buff, bufflen, fp) != NULL) {
|
||||
;
|
||||
}
|
||||
|
||||
status = pclose(fp);
|
||||
if (status == -1) {
|
||||
perror("pclose");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
Script code:
|
||||
|
||||
for_each_service() {
|
||||
local action=$1 && shift
|
||||
local -a array=($*)
|
||||
for service in "${array[@]}"; do
|
||||
systemctl $action $service
|
||||
[ $? -ne 0 ] && notice "Failed to $action ${service}. Continuing..."
|
||||
done
|
||||
}
|
||||
*/
|
||||
static int for_each_service(const char *command, char* services[], int numservices)
|
||||
{
|
||||
char buff[512];
|
||||
char cmd[256];
|
||||
int ret = 0, status;
|
||||
|
||||
for (int i = 0; i < numservices; i++) {
|
||||
snprintf(cmd, sizeof(cmd), "systemctl %s %s", command, services[i]);
|
||||
memset(buff, 0, sizeof(buff));
|
||||
status = syscmd(cmd, buff, sizeof(buff));
|
||||
if (status != 0 || buff[0] != 0) {
|
||||
fprintf(stderr, "%s", buff);
|
||||
fprintf(stderr, "Failed to %s %s. Continuing...", command, services[i]);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
Script code:
|
||||
|
||||
telem_start() {
|
||||
[ -f $OPT_OUT_FILE ] && exit_err "Opt out is enabled. Cannot start services."
|
||||
create_work_dirs
|
||||
for_each_service "start" ${SPECIAL_UNITS[@]}
|
||||
}
|
||||
|
||||
Modified to add explicit opt-in
|
||||
*/
|
||||
static int telemctl_start(void)
|
||||
{
|
||||
char buff[512];
|
||||
int status, ret;
|
||||
|
||||
if (access(TM_OPT_IN, F_OK) != 0) {
|
||||
fprintf(stderr, "Opt in to telemetry first.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Creates dirs if missing, adjust ownership if exists */
|
||||
memset(buff, 0, sizeof(buff));
|
||||
|
||||
/* Execute "systemd-tmpfiles --create ${TELEM_WRK_DIRS_CONF}" */
|
||||
status = syscmd(cmd_create_tmp_files, buff, sizeof(buff));
|
||||
fprintf(stderr, "%s", buff);
|
||||
|
||||
if (status == -1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = for_each_service("start", SPECIAL_UNITS, NUM_SPECIAL_UNITS);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Script code:
|
||||
|
||||
telem_stop() {
|
||||
for_each_service "stop" ${SPECIAL_UNITS[@]}
|
||||
for_each_service "stop" ${SERVICES[@]}
|
||||
}
|
||||
*/
|
||||
static int telemctl_stop(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* the special units must be stopped first so that activation no longer happens */
|
||||
ret = for_each_service("stop", SPECIAL_UNITS, NUM_SPECIAL_UNITS);
|
||||
ret |= for_each_service("stop", SERVICES, NUM_SERVICES);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
Script code:
|
||||
*
|
||||
telem_restart() {
|
||||
telem_stop
|
||||
telem_start
|
||||
}
|
||||
*/
|
||||
static int telemctl_restart(void)
|
||||
{
|
||||
if (telemctl_stop() == 0) {
|
||||
return telemctl_start();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Script code:
|
||||
|
||||
telem_is_active() {
|
||||
echo "telemprobd :" $(systemctl is-active telemprobd.socket)
|
||||
echo "telempostd :" $(systemctl is-active telempostd.path)
|
||||
}
|
||||
*/
|
||||
|
||||
static int telemctl_is_active(void)
|
||||
{
|
||||
char buff[256];
|
||||
|
||||
memset(buff, 0, sizeof(buff));
|
||||
if (syscmd("systemctl is-active telemprobd.socket", buff, sizeof(buff)) != -1) {
|
||||
printf("telemprobd : %s", buff);
|
||||
memset(buff, 0, sizeof(buff));
|
||||
if (syscmd("systemctl is-active telempostd.path",buff, sizeof(buff)) != -1) {
|
||||
printf("telempostd : %s", buff);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int unlink_cb(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
|
||||
{
|
||||
int rv = remove(fpath);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "[debug] [%s] remove fpath:%s rv:%d\n", __func__, fpath, rv);
|
||||
#endif
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
/* rm -rf path
|
||||
*
|
||||
* We run as root, so be extra careful when deleting folders.
|
||||
* We only delete folders owned by telemetry:telemetry.
|
||||
* As for the files, they can be owned by root.
|
||||
*/
|
||||
static int rm_rf(char *path)
|
||||
{
|
||||
struct stat info;
|
||||
if (stat(path, &info) == 0) {
|
||||
struct passwd *pw = getpwuid(info.st_uid);
|
||||
if (pw == NULL) {
|
||||
perror("getpwuid");
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(pw->pw_name, "telemetry") != 0) {
|
||||
fprintf(stderr, "Not removing \"%s\": Incorrect folder owner \"%s\"\n",
|
||||
path, pw->pw_name);
|
||||
return -1;
|
||||
}
|
||||
struct group *gr = getgrgid(info.st_gid);
|
||||
if (gr == NULL) {
|
||||
perror("getgrgid");
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(gr->gr_name, "telemetry") != 0) {
|
||||
fprintf(stderr, "Not removing \"%s\": Incorrect folder group \"%s\"\n",
|
||||
path, gr->gr_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return nftw(path, unlink_cb, 64, FTW_DEPTH | FTW_PHYS);
|
||||
} else {
|
||||
// Some folders are subfolders of folders already recursivley deleted.
|
||||
// So they may not exist anymore.
|
||||
if (errno != ENOENT) {
|
||||
fprintf(stderr, "file: %s :", path);
|
||||
perror("stat");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Script code:
|
||||
|
||||
telem_remove_work_dirs() {
|
||||
# Remove dirs
|
||||
awk '/^d/{print $2}' ${TELEM_WRK_DIRS_CONF} | xargs rm -rf;
|
||||
}
|
||||
|
||||
Notes:
|
||||
Parse /usr/lib/tmpfiles.d/telemetrics-dirs.conf
|
||||
This file was used to create the folders needed by telemetry.
|
||||
Now we want to delete them. The file contents is as:
|
||||
|
||||
d /usr/local/var/lib/telemetry 0755 telemetry telemetry -
|
||||
d /usr/local/var/spool/telemetry 0750 telemetry telemetry -
|
||||
d /usr/local/var/log/telemetry 0750 telemetry telemetry -
|
||||
d /usr/local/var/log/telemetry/records 0750 telemetry telemetry -
|
||||
d /usr/local/var/cache/telemetry 0750 telemetry telemetry -
|
||||
d /usr/local/var/cache/telemetry/pstore 0750 telemetry telemetry -
|
||||
*/
|
||||
static int telemctl_remove_work_dirs(void)
|
||||
{
|
||||
FILE *fp = fopen(TELEM_WRK_DIRS_CONF, "r");
|
||||
if (fp == NULL){
|
||||
fprintf(stderr, "Could not open file %s", TELEM_WRK_DIRS_CONF);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
char folder[PATH_MAX+1];
|
||||
char line[PATH_MAX+30];
|
||||
|
||||
if (fgets(line, sizeof(line), fp) == NULL) {
|
||||
if (ferror(fp)) {
|
||||
fprintf(stderr, "Error reading file %s\n", TELEM_WRK_DIRS_CONF);
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
// EOF
|
||||
break;
|
||||
}
|
||||
|
||||
int ret = sscanf(line, "d %s %*s telemetry telemetry - \n", folder);
|
||||
if (ret == 1) {
|
||||
/* Delete the folder. We may get an error trying to delete
|
||||
* folders already deleted. We ignore them, so don't bother
|
||||
* checking rmrtf return value */
|
||||
rm_rf(folder);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mk_telem_dir(void)
|
||||
{
|
||||
char buff[512];
|
||||
int status;
|
||||
struct stat sb;
|
||||
|
||||
if (stat(TELEM_DIR, &sb) == 0 && S_ISDIR(sb.st_mode)) {
|
||||
#ifdef DEBUG
|
||||
printf("[debug] [%s] Folder %s exists\n", __func__, TELEM_DIR);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(buff, 0, sizeof(buff));
|
||||
|
||||
/* Execute "mkdir -p TM_DIR" */
|
||||
status = syscmd(cmd_mk_telemdir, buff, sizeof(buff));
|
||||
fprintf(stderr, "%s", buff);
|
||||
|
||||
if (status == -1 || buff[0] != 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Script code:
|
||||
|
||||
telem_opt_out() {
|
||||
[ -f $OPT_OUT_FILE ] && exit_ok "Already opted out. Nothing to do."
|
||||
mkdir -p $TELEM_DIR || exit_err "Failed to create ${TELEM_DIR}."
|
||||
touch $OPT_OUT_FILE || exit_err "Failed to create ${OPT_OUT_FILE}."
|
||||
telem_stop
|
||||
telem_remove_work_dirs
|
||||
}
|
||||
*/
|
||||
static int telemctl_opt_out(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Remove TM_OPT_IN file */
|
||||
if (unlink(TM_OPT_IN) != 0) {
|
||||
if (errno == ENOENT) {
|
||||
fprintf(stderr, "Already opted out. Nothing to do.\n");
|
||||
return 0;
|
||||
}
|
||||
fprintf(stderr, "Failed to remove %s.\n", TM_OPT_IN);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = telemctl_stop();
|
||||
ret |= telemctl_remove_work_dirs();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
Script code:
|
||||
|
||||
telem_opt_in() {
|
||||
[ ! -f $OPT_OUT_FILE ] && exit_ok "Already opted in. Nothing to do."
|
||||
rm -f $OPT_OUT_FILE || exit_err "Failed to remove ${OPT_OUT_FILE}."
|
||||
telem_start
|
||||
}
|
||||
|
||||
Modified to add explicit opt-in
|
||||
*/
|
||||
static int telemctl_opt_in(void)
|
||||
{
|
||||
|
||||
/* Ensure TELEM_DIR exists */
|
||||
if (mk_telem_dir() != 0) {
|
||||
fprintf(stderr, "Failed to create %s\n", TELEM_DIR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Create a brand new file TM_OPT_IN, we may fail because the file exists already.
|
||||
* In that case we are already opted in and we are done here. */
|
||||
int fd = open(TM_OPT_IN, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH|O_NOFOLLOW);
|
||||
if (fd == -1) {
|
||||
if (errno == EEXIST) {
|
||||
fprintf(stderr, "Already opted in. Nothing to do.\n");
|
||||
return 0;
|
||||
} else {
|
||||
fprintf(stderr, "Failed to create %s.\n", TM_OPT_IN);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int journal_cmd(char *cmd)
|
||||
{
|
||||
int status;
|
||||
char buff[256];
|
||||
#ifdef DEBUG
|
||||
printf("[debug] [%s] %s\n", __func__, cmd);
|
||||
#endif
|
||||
FILE *fp = popen(cmd, "r");
|
||||
if (fp == NULL) {
|
||||
perror("popen");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(buff, sizeof(buff), fp) != NULL) {
|
||||
printf("%s", buff);
|
||||
}
|
||||
|
||||
status = pclose(fp);
|
||||
if (status == -1) {
|
||||
perror("pclose");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static char* concatargs(int argc, char** argv)
|
||||
{
|
||||
size_t len = 1 + strlen("telem_journal ");
|
||||
for (int i = 2; i < argc; i++) {
|
||||
len += strlen(argv[i]) + 1;
|
||||
}
|
||||
|
||||
char *buff = malloc(len*sizeof(char));
|
||||
|
||||
if (buff != NULL) {
|
||||
buff[0] = '\0';
|
||||
strcat(buff,"telem_journal ");
|
||||
|
||||
for (int i = 2; i < argc; i++) {
|
||||
strcat(buff, argv[i]);
|
||||
strcat(buff, " ");
|
||||
}
|
||||
}
|
||||
|
||||
return buff;
|
||||
}
|
||||
|
||||
static int telemctl_journal(char * x)
|
||||
{
|
||||
journal_cmd(x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void print_usage(char *str)
|
||||
{
|
||||
printf("%s - Control actions for telemetry services\n\n", str);
|
||||
|
||||
for (int i = 0; i < sizeof(commands)/sizeof(commands[0]); i++) {
|
||||
printf(" %-9s %s\n", commands[i].cmd, commands[i].doc);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, ret = EXIT_SUCCESS;
|
||||
bool is_root;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
if (argc == 1) {
|
||||
print_usage(argv[0]);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
is_root = getuid()?false:true;
|
||||
|
||||
for (i = 0; i < sizeof(commands)/sizeof(commands[0]); i++) {
|
||||
if (strcmp(commands[i].cmd, argv[1]) == 0) {
|
||||
if (commands[i].root == true && is_root == false) {
|
||||
fprintf(stderr, "Must be root to run this command. Exiting...\n");
|
||||
exit(1);
|
||||
}
|
||||
/* Special treatment for "journal", it can have cmd line arguments */
|
||||
if (strcmp(argv[1],"journal") != 0) {
|
||||
if (argc != 2) {
|
||||
print_usage(argv[0]);
|
||||
exit(2);
|
||||
}
|
||||
ret = commands[i].f.f1();
|
||||
} else {
|
||||
char *buff = concatargs(argc, argv);
|
||||
if (buff != NULL) {
|
||||
ret = commands[i].f.f2(buff);
|
||||
free(buff);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == sizeof(commands)/sizeof(commands[0])) {
|
||||
printf("Unknown command passed to %s\n\n", argv[0]);
|
||||
print_usage(argv[0]);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
exit(ret);
|
||||
}
|
||||
+90
-58
@@ -36,6 +36,8 @@
|
||||
#include "log.h"
|
||||
#include "configuration.h"
|
||||
|
||||
static void process_record(TelemDaemon *daemon, client *cl);
|
||||
|
||||
void initialize_probe_daemon(TelemDaemon *daemon)
|
||||
{
|
||||
client_list_head head;
|
||||
@@ -80,7 +82,8 @@ bool is_client_list_empty(client_list_head *client_head)
|
||||
return (client_head->lh_first == NULL);
|
||||
}
|
||||
|
||||
void terminate_client(TelemDaemon *daemon, client *cl, nfds_t index)
|
||||
|
||||
static void terminate_client(TelemDaemon *daemon, client *cl, nfds_t index)
|
||||
{
|
||||
/* Remove fd from the pollfds array */
|
||||
del_pollfd(daemon, index);
|
||||
@@ -91,24 +94,40 @@ void terminate_client(TelemDaemon *daemon, client *cl, nfds_t index)
|
||||
remove_client(&(daemon->client_head), cl);
|
||||
}
|
||||
|
||||
bool handle_client(TelemDaemon *daemon, nfds_t ind, client *cl)
|
||||
/*
|
||||
See "tm_send_record" for record retails.
|
||||
|
||||
recv buffer layout:
|
||||
* <uint32_t record_size> : so recv knows how much to read
|
||||
* <custom cfg file field> : optional, variable size (string)
|
||||
* <uint32_t header_size>
|
||||
* <headers + Payload>
|
||||
* <null-byte>
|
||||
|
||||
The routine handle_client only cares about "record_size".
|
||||
However, we need to validate if the record_size is reasonable. We assume the
|
||||
worst case scenario would be a record with max cfg file field. There is no
|
||||
exact way to determine header_size, so we assume each line at most 80 chars.
|
||||
|
||||
*/
|
||||
|
||||
#define MAX_RECORD_SIZE (2*sizeof(uint32_t) + CFG_PREFIX_LENGTH + PATH_MAX + \
|
||||
MAX_PAYLOAD_LENGTH + NUM_HEADERS*80)
|
||||
bool handle_client(TelemDaemon *daemon, nfds_t index, client *cl)
|
||||
{
|
||||
/* For now read data from fd */
|
||||
ssize_t len;
|
||||
size_t record_size = 0;
|
||||
size_t buf_size;
|
||||
bool processed = false;
|
||||
uint32_t record_size;
|
||||
|
||||
if (!cl->buf) {
|
||||
cl->buf = malloc(RECORD_SIZE_LEN);
|
||||
cl->size = RECORD_SIZE_LEN;
|
||||
}
|
||||
if (!cl->buf) {
|
||||
telem_log(LOG_ERR, "Unable to allocate memory, exiting\n");
|
||||
exit(EXIT_FAILURE);
|
||||
if (cl->buf != NULL) {
|
||||
free(cl->buf);
|
||||
cl->buf = NULL;
|
||||
}
|
||||
|
||||
malloc_trim(0);
|
||||
len = recv(cl->fd, cl->buf, RECORD_SIZE_LEN, MSG_PEEK | MSG_DONTWAIT);
|
||||
len = recv(cl->fd, &record_size, RECORD_SIZE_LEN, MSG_PEEK | MSG_DONTWAIT);
|
||||
if (len < 0) {
|
||||
telem_log(LOG_ERR, "Failed to talk to client %d: %s\n", cl->fd,
|
||||
strerror(errno));
|
||||
@@ -120,6 +139,39 @@ bool handle_client(TelemDaemon *daemon, nfds_t ind, client *cl)
|
||||
goto end_client;
|
||||
}
|
||||
|
||||
/* Read the record size first */
|
||||
len = recv(cl->fd, &record_size, RECORD_SIZE_LEN, 0);
|
||||
if (len < 0) {
|
||||
telem_log(LOG_ERR, "Failed to receive data from client"
|
||||
" %d: %s\n", cl->fd, strerror(errno));
|
||||
goto end_client;
|
||||
} else if (len == 0) {
|
||||
telem_log(LOG_DEBUG, "End of transmission for client"
|
||||
" %d\n", cl->fd);
|
||||
goto end_client;
|
||||
}
|
||||
|
||||
/* Now that we know the record size, allocate a new buffer
|
||||
* for the record body. We don't need to record size itself in the body.
|
||||
*/
|
||||
|
||||
if (record_size <= RECORD_SIZE_LEN || record_size > MAX_RECORD_SIZE) {
|
||||
telem_log(LOG_ERR, "Record size %u greater tham maximum allowed %lu."
|
||||
"Recored ignored\n", record_size,
|
||||
MAX_RECORD_SIZE);
|
||||
goto end_client;
|
||||
}
|
||||
|
||||
buf_size = record_size - RECORD_SIZE_LEN;
|
||||
cl->buf = calloc(1, buf_size);
|
||||
if (!cl->buf) {
|
||||
telem_log(LOG_ERR, "Unable to allocate memory, exiting\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
cl->size = buf_size;
|
||||
cl->offset = 0;
|
||||
|
||||
/* Read the actual record*/
|
||||
do {
|
||||
malloc_trim(0);
|
||||
len = recv(cl->fd, cl->buf + cl->offset, cl->size - cl->offset, 0);
|
||||
@@ -134,36 +186,11 @@ bool handle_client(TelemDaemon *daemon, nfds_t ind, client *cl)
|
||||
}
|
||||
|
||||
cl->offset += (size_t)len;
|
||||
if (cl->offset < RECORD_SIZE_LEN) {
|
||||
continue;
|
||||
}
|
||||
if (cl->size == RECORD_SIZE_LEN) {
|
||||
record_size = *(uint32_t *)(cl->buf);
|
||||
telem_log(LOG_DEBUG, "Total size of record: %zu\n", record_size);
|
||||
if (record_size == 0) { //record_size < RECORD_MIN_SIZE || record_size > RECORD_MAX_SIZE
|
||||
goto end_client;
|
||||
}
|
||||
// We just processed the record size field, so the remaining format
|
||||
// is (header size field + record body + terminating '\0' byte)
|
||||
cl->size = sizeof(uint32_t) + record_size + 1;
|
||||
cl->buf = realloc(cl->buf, cl->size);
|
||||
memset(cl->buf, 0, cl->size);
|
||||
cl->offset = 0;
|
||||
if (!cl->buf) {
|
||||
telem_log(LOG_ERR, "Unable to allocate memory, exiting\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
if (cl->offset != cl->size) {
|
||||
/* full record not received yet */
|
||||
continue;
|
||||
}
|
||||
if (cl->size != RECORD_SIZE_LEN) {
|
||||
/* entire record has been received */
|
||||
|
||||
if (cl->offset == cl->size) {
|
||||
process_record(daemon, cl);
|
||||
/* TODO: cleanup or terminate? */
|
||||
cl->offset = 0;
|
||||
cl->size = RECORD_SIZE_LEN;
|
||||
free(cl->buf);
|
||||
cl->buf = NULL;
|
||||
processed = true;
|
||||
telem_debug("DEBUG: Record processed for client %d\n", cl->fd);
|
||||
break;
|
||||
@@ -172,7 +199,7 @@ bool handle_client(TelemDaemon *daemon, nfds_t ind, client *cl)
|
||||
|
||||
end_client:
|
||||
telem_log(LOG_DEBUG, "Processed client %d: %s\n", cl->fd, processed ? "true" : "false");
|
||||
terminate_client(daemon, cl, ind);
|
||||
terminate_client(daemon, cl, index);
|
||||
return processed;
|
||||
}
|
||||
|
||||
@@ -222,14 +249,14 @@ char *read_machine_id_override()
|
||||
return machine_override;
|
||||
}
|
||||
|
||||
void machine_id_replace(char **machine_header, char *machine_id_override)
|
||||
static void machine_id_replace(char **machine_header, char *machine_id_override)
|
||||
{
|
||||
char machine_id[33] = { 0 };
|
||||
char *old_header;
|
||||
int ret;
|
||||
|
||||
if (machine_id_override) {
|
||||
strcpy(machine_id, machine_id_override);
|
||||
strncpy(machine_id, machine_id_override, sizeof(machine_id)-1);
|
||||
} else {
|
||||
if (!get_machine_id(machine_id)) {
|
||||
// TODO: decide if error handling is needed here
|
||||
@@ -255,23 +282,19 @@ static void stage_record(char *filepath, char *headers[], char *body, char *cfg_
|
||||
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) {
|
||||
if (tmpfd < 0) {
|
||||
telem_perror("Error opening staging file");
|
||||
close(tmpfd);
|
||||
if (unlink(filepath)) {
|
||||
telem_perror("Error deleting staging file");
|
||||
}
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
// open file
|
||||
// access the opened file as a stream
|
||||
tmpfile = fdopen(tmpfd, "a");
|
||||
if (!tmpfile) {
|
||||
telem_perror("Error opening temp stage file");
|
||||
@@ -292,7 +315,7 @@ static void stage_record(char *filepath, char *headers[], char *body, char *cfg_
|
||||
fprintf(tmpfile, "%s\n", headers[i]);
|
||||
}
|
||||
|
||||
//write body
|
||||
// write body
|
||||
fprintf(tmpfile, "%s\n", body);
|
||||
fflush(tmpfile);
|
||||
fclose(tmpfile);
|
||||
@@ -302,7 +325,7 @@ clean_exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void process_record(TelemDaemon *daemon, client *cl)
|
||||
static void process_record(TelemDaemon *daemon, client *cl)
|
||||
{
|
||||
int i = 0;
|
||||
int ret = 0;
|
||||
@@ -331,12 +354,21 @@ void process_record(TelemDaemon *daemon, client *cl)
|
||||
|
||||
buf += cfg_info_size;
|
||||
header_size = *(uint32_t *)buf;
|
||||
/* Header size can not be bigger than buffer size bail out early */
|
||||
if ((uint32_t)header_size >= (uint32_t)cl->size) {
|
||||
return;
|
||||
}
|
||||
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
|
||||
telem_debug("DEBUG: cl->size: %ld\n", cl->size);
|
||||
telem_debug("DEBUG: header_size: %ld\n", header_size);
|
||||
telem_debug("DEBUG: message_size: %ld\n", message_size);
|
||||
telem_debug("DEBUG: cfg_info_size: %ld\n", cfg_info_size);
|
||||
telem_debug("Total: %zu\n", header_size + cfg_info_size + message_size);
|
||||
/* Check message size bounds */
|
||||
if (message_size <= 0 || message_size > MAX_PAYLOAD_LENGTH) {
|
||||
telem_log(LOG_INFO, "Record message size out of bounds\n");
|
||||
return;
|
||||
}
|
||||
msg = (char *)buf + sizeof(uint32_t);
|
||||
|
||||
/* Copying the headers as strtok modifies the orginal buffer */
|
||||
@@ -430,7 +462,7 @@ bool get_machine_id(char *machine_id)
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = fscanf(id_file, "%s", machine_id);
|
||||
ret = fscanf(id_file, "%32s", machine_id);
|
||||
if (ret != 1) {
|
||||
telem_perror("Could not read machine id from file");
|
||||
fclose(id_file);
|
||||
|
||||
@@ -125,27 +125,6 @@ void remove_client(client_list_head *client_head, client *cl);
|
||||
*/
|
||||
bool is_client_list_empty(client_list_head *client_head);
|
||||
|
||||
/**
|
||||
* Terminate a client connection
|
||||
*
|
||||
* @param daemon Pointer to the daemon
|
||||
* @param cl Pointer to the client in the client list
|
||||
* @param index The index of the client file descriptor in the poll fd
|
||||
* array
|
||||
*
|
||||
*/
|
||||
void terminate_client(TelemDaemon *daemon, client *cl, nfds_t index);
|
||||
|
||||
/**
|
||||
* Process record from a client
|
||||
*
|
||||
* @param daemon Pointer to the daemon
|
||||
* @param cl Pointer to the client in the client list
|
||||
*
|
||||
* @return true on success, false on failure
|
||||
*/
|
||||
void process_record(TelemDaemon *daemon, client *cl);
|
||||
|
||||
/**
|
||||
* Get random machine id stored in file
|
||||
*
|
||||
|
||||
+25
-34
@@ -49,9 +49,9 @@ static int version_file(void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open(TM_SITE_VERSION_FILE, O_RDONLY);
|
||||
fd = open(TM_SITE_VERSION_FILE, O_RDONLY|O_NOFOLLOW);
|
||||
if (fd < 0) {
|
||||
fd = open(TM_DIST_VERSION_FILE, O_RDONLY);
|
||||
fd = open(TM_DIST_VERSION_FILE, O_RDONLY|O_NOFOLLOW);
|
||||
}
|
||||
|
||||
return fd;
|
||||
@@ -913,14 +913,6 @@ int tm_create_record(struct telem_ref **t_ref, uint32_t severity,
|
||||
char *classification, uint32_t payload_version)
|
||||
{
|
||||
int ret = 0;
|
||||
int k = 0;
|
||||
struct stat unused;
|
||||
|
||||
k = stat(TM_OPT_OUT_FILE, &unused);
|
||||
if (k == 0) {
|
||||
// Bail early if opt-out is enabled
|
||||
return -ECONNREFUSED;
|
||||
}
|
||||
|
||||
*t_ref = (struct telem_ref *)malloc(sizeof(struct telem_ref));
|
||||
if (*t_ref == NULL) {
|
||||
@@ -984,26 +976,19 @@ int tm_set_payload(struct telem_ref *t_ref, char *payload)
|
||||
{
|
||||
size_t payload_len;
|
||||
int ret = 0;
|
||||
int k = 0;
|
||||
struct stat unused;
|
||||
|
||||
k = stat(TM_OPT_OUT_FILE, &unused);
|
||||
if (k == 0) {
|
||||
// Bail early if opt-out is enabled
|
||||
return -ECONNREFUSED;
|
||||
}
|
||||
|
||||
payload_len = strlen((char *)payload);
|
||||
|
||||
if (payload_len > MAX_PAYLOAD_LENGTH) {
|
||||
if (payload == NULL) {
|
||||
telem_log(LOG_WARNING, "payload pointer is NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
payload_len = strnlen(payload, MAX_PAYLOAD_LENGTH);
|
||||
|
||||
if (payload_is_ascii(payload, payload_len) != 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
t_ref->record->payload = strdup(payload);
|
||||
t_ref->record->payload = strndup(payload, payload_len);
|
||||
|
||||
if (!t_ref->record->payload) {
|
||||
telem_log(LOG_CRIT, "CRIT: Out of memory\n");
|
||||
@@ -1053,7 +1038,7 @@ int tm_set_event_id(struct telem_ref *t_ref, char *event_id)
|
||||
int rc = -1;
|
||||
|
||||
if (!validate_event_id(event_id)) {
|
||||
if (t_ref && t_ref->record && t_ref->record->headers) {
|
||||
if (t_ref && t_ref->record) {
|
||||
// free default id before overriding
|
||||
free(t_ref->record->headers[TM_EVENT_ID]);
|
||||
// set new event_id
|
||||
@@ -1215,6 +1200,17 @@ out1:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tm_is_opted_in(void)
|
||||
{
|
||||
struct stat unused;
|
||||
|
||||
if (stat(TM_OPT_IN_FILE, &unused) == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tm_send_record(struct telem_ref *t_ref)
|
||||
{
|
||||
int i;
|
||||
@@ -1224,14 +1220,11 @@ int tm_send_record(struct telem_ref *t_ref)
|
||||
char *data = NULL;
|
||||
size_t offset = 0;
|
||||
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) {
|
||||
// Bail early if opt-out is enabled
|
||||
if (tm_is_opted_in() == 0) {
|
||||
// Bail early if opt-in is not existent
|
||||
return -ECONNREFUSED;
|
||||
}
|
||||
|
||||
@@ -1272,8 +1265,8 @@ int tm_send_record(struct telem_ref *t_ref)
|
||||
|
||||
/*
|
||||
* Allocating buffer for what we intend to send. Buffer layout is:
|
||||
* <uint32_t total_size> : so recv knows how much to read
|
||||
* <custom cfg file field> : optional
|
||||
* <uint32_t record_size> : so recv knows how much to read
|
||||
* <custom cfg file field> : optional
|
||||
* <uint32_t header_size>
|
||||
* <headers + Payload>
|
||||
* <null-byte>
|
||||
@@ -1281,16 +1274,14 @@ int tm_send_record(struct telem_ref *t_ref)
|
||||
*/
|
||||
record_size = (2 * sizeof(uint32_t)) + total_size + 1;
|
||||
|
||||
data = malloc(record_size);
|
||||
data = (char *)calloc(sizeof(char), record_size);
|
||||
if (!data) {
|
||||
telem_log(LOG_CRIT, "CRIT: Out of memory\n");
|
||||
close(sfd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(data, 0, record_size);
|
||||
|
||||
memcpy(data, &total_size, sizeof(uint32_t));
|
||||
memcpy(data, &record_size, sizeof(uint32_t));
|
||||
offset += sizeof(uint32_t);
|
||||
|
||||
if (cfg_file_name != NULL) {
|
||||
|
||||
@@ -120,6 +120,13 @@ int tm_set_payload(struct telem_ref *t_ref, char *payload);
|
||||
*/
|
||||
int tm_send_record(struct telem_ref *t_ref);
|
||||
|
||||
/**
|
||||
* Checks if telemetry was opted in
|
||||
*
|
||||
* @return 1 when opt-in, or 0 when opt-out
|
||||
*/
|
||||
int tm_is_opted_in(void);
|
||||
|
||||
/**
|
||||
* Release the memory allocated to a telemetrics record.
|
||||
*
|
||||
|
||||
@@ -21,3 +21,8 @@ TM_4_0_0 {
|
||||
global:
|
||||
tm_set_event_id;
|
||||
} TM_3_0_0;
|
||||
|
||||
TM_4_1_0 {
|
||||
global:
|
||||
tm_is_opted_in;
|
||||
} TM_4_0_0;
|
||||
|
||||
+90
-44
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This program is part of the Clear Linux Project
|
||||
*
|
||||
* Copyright 2018 Intel Corporation
|
||||
* Copyright 2018-2023 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
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <sys/stat.h>
|
||||
#include <curl/curl.h>
|
||||
#include <json-c/json.h>
|
||||
#include <sys/signalfd.h>
|
||||
|
||||
#include "log.h"
|
||||
@@ -210,13 +211,47 @@ size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
char *create_json_message(char *tm_headers[], char *tm_payload)
|
||||
{
|
||||
/*
|
||||
* Embed the telemetry record headers and the telemetry payload into a
|
||||
* JSON object string.
|
||||
*/
|
||||
char *json_string = NULL;
|
||||
json_object *root = json_object_new_object();
|
||||
|
||||
/* Add the telemetry record headers */
|
||||
|
||||
for (int i = 0; i < NUM_HEADERS; i++) {
|
||||
/* ex: arch: x86_64 */
|
||||
|
||||
/* Split the header field into name/value */
|
||||
strtok(tm_headers[i], ":");
|
||||
json_object *value = json_object_new_string(strtok(NULL, " "));
|
||||
json_object_object_add(root, tm_headers[i], value);
|
||||
}
|
||||
json_object *payload = json_object_new_string(tm_payload);
|
||||
json_object_object_add(root, "payload", payload);
|
||||
|
||||
/* Keep our own copy of the json string */
|
||||
json_string = strdup(json_object_to_json_string_ext(root,
|
||||
JSON_C_TO_STRING_PLAIN |
|
||||
JSON_C_TO_STRING_NOSLASHESCAPE));
|
||||
|
||||
/* Free the memory associated with the JSON objects */
|
||||
json_object_put(root);
|
||||
|
||||
return json_string;
|
||||
}
|
||||
|
||||
bool post_record_http(char *headers[], char *body, char *cfg)
|
||||
{
|
||||
CURL *curl;
|
||||
int res = 0;
|
||||
char *content = "Content-Type: application/text";
|
||||
char *content = "Content-Type: application/json";
|
||||
struct curl_slist *custom_headers = NULL;
|
||||
char errorbuf[CURL_ERROR_SIZE];
|
||||
char *json_body = NULL;
|
||||
long http_response = 0;
|
||||
const char *cert_file = get_cainfo_config();
|
||||
const char *tid_header = get_tidheader_config();
|
||||
@@ -231,12 +266,15 @@ bool post_record_http(char *headers[], char *body, char *cfg)
|
||||
// settings than explicitly requested.
|
||||
// However, report success so the record gets deleted.
|
||||
res = 0;
|
||||
goto Done;
|
||||
goto done;
|
||||
}
|
||||
reload_config();
|
||||
telem_debug("DEBUG: override server_addr:%s\n", server_addr_config());
|
||||
}
|
||||
|
||||
// Generate the JSON message body
|
||||
json_body = create_json_message(headers, body);
|
||||
|
||||
// Initialize the libcurl global environment once per POST. This lets us
|
||||
// clean up the environment after each POST so that when the daemon is
|
||||
// sitting idle, it will be consuming as little memory as possible.
|
||||
@@ -250,35 +288,35 @@ bool post_record_http(char *headers[], char *body, char *cfg)
|
||||
/* TODO: check if memory needs to be released */
|
||||
}
|
||||
|
||||
// Errors for any curl_easy_* functions will store nice error messages
|
||||
// in errorbuf, so send log messages with errorbuf contents
|
||||
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuf);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, server_addr_config());
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L);
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L);
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||
#ifdef DEBUG
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||
#endif
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
|
||||
|
||||
for (int i = 0; i < NUM_HEADERS; i++) {
|
||||
custom_headers = curl_slist_append(custom_headers, headers[i]);
|
||||
}
|
||||
custom_headers = curl_slist_append(custom_headers, tid_header);
|
||||
// This should be set by probes/libtelemetry in the future
|
||||
custom_headers = curl_slist_append(custom_headers, content);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, custom_headers);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(body));
|
||||
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
|
||||
// Errors for any curl_easy_* functions will store nice error messages
|
||||
// in errorbuf, so send log messages with errorbuf contents
|
||||
if (curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuf) != CURLE_OK ||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, server_addr_config()) != CURLE_OK ||
|
||||
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L) != CURLE_OK ||
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L) != CURLE_OK ||
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1) != CURLE_OK ||
|
||||
#ifdef DEBUG
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1) != CURLE_OK ||
|
||||
#endif
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback) != CURLE_OK ||
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, custom_headers) != CURLE_OK ||
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_body) != CURLE_OK ||
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(json_body)) != CURLE_OK ||
|
||||
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY) != CURLE_OK) {
|
||||
telem_log(LOG_ERR, "curl_easy_setopt(): Failed to set one or more options\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (strlen(cert_file) > 0) {
|
||||
if (access(cert_file, F_OK) != -1) {
|
||||
curl_easy_setopt(curl, CURLOPT_CAINFO, cert_file);
|
||||
if (curl_easy_setopt(curl, CURLOPT_CAINFO, cert_file) != CURLE_OK) {
|
||||
telem_log(LOG_ERR, "curl_easy_setopt(): Failed to set CAINFO\n");
|
||||
goto exit;
|
||||
}
|
||||
telem_log(LOG_INFO, "cafile was set to %s\n", cert_file);
|
||||
}
|
||||
}
|
||||
@@ -309,12 +347,17 @@ bool post_record_http(char *headers[], char *body, char *cfg)
|
||||
telem_log(LOG_INFO, "Record sent successfully\n");
|
||||
}
|
||||
|
||||
exit:
|
||||
curl_slist_free_all(custom_headers);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
curl_global_cleanup();
|
||||
|
||||
Done:
|
||||
done:
|
||||
if (json_body) {
|
||||
free(json_body);
|
||||
json_body = NULL;
|
||||
}
|
||||
|
||||
if (saved_config_file != NULL) {
|
||||
if (set_config_file(saved_config_file) != 0) {
|
||||
telem_log(LOG_ERR, "set-config_file(): Failed to set %s",
|
||||
@@ -363,8 +406,8 @@ save_err:
|
||||
|
||||
static void save_entry_to_journal(TelemPostDaemon *daemon, time_t t_stamp, char *headers[])
|
||||
{
|
||||
char *classification_value;
|
||||
char *event_id_value;
|
||||
char *classification_value = NULL;
|
||||
char *event_id_value = NULL;
|
||||
|
||||
if (get_header_value(headers[TM_CLASSIFICATION], &classification_value) &&
|
||||
get_header_value(headers[TM_EVENT_ID], &event_id_value)) {
|
||||
@@ -490,13 +533,13 @@ static bool deliver_record(TelemPostDaemon *daemon, char *headers[], char *body,
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool process_staged_record(char *filename, bool is_retry, TelemPostDaemon *daemon)
|
||||
bool process_staged_record(char *filename, TelemPostDaemon *daemon)
|
||||
{
|
||||
int k;
|
||||
bool ret = false;
|
||||
char *headers[NUM_HEADERS];
|
||||
char *body = NULL;
|
||||
struct stat buf;
|
||||
struct stat buf = { 0 };
|
||||
time_t current_time = time(NULL);
|
||||
int64_t max_spool_size = 0;
|
||||
char *cfg_file = NULL;
|
||||
@@ -520,7 +563,7 @@ bool process_staged_record(char *filename, bool is_retry, TelemPostDaemon *daemo
|
||||
}
|
||||
|
||||
/** Update spool directory size **/
|
||||
(daemon->current_spool_size) += (buf.st_blocks * 512);
|
||||
daemon->current_spool_size += (buf.st_blocks * 512);
|
||||
|
||||
/** Check that record is not expired **/
|
||||
if (!S_ISREG(buf.st_mode) ||
|
||||
@@ -530,20 +573,12 @@ bool process_staged_record(char *filename, bool is_retry, TelemPostDaemon *daemo
|
||||
goto end_processing_file;
|
||||
}
|
||||
|
||||
/* Retries should not be recorded */
|
||||
if (is_retry == false) {
|
||||
/** Journal entry **/
|
||||
save_entry_to_journal(daemon, current_time, headers);
|
||||
/** Record retention **/
|
||||
apply_retention_policies(daemon, body);
|
||||
}
|
||||
|
||||
/** Record delivery **/
|
||||
if (!daemon->record_server_delivery_enabled) {
|
||||
telem_log(LOG_INFO, "record server delivery disabled\n");
|
||||
// Not an error condition
|
||||
ret = true;
|
||||
goto end_processing_file;
|
||||
goto end_record_delivery;
|
||||
}
|
||||
|
||||
/** Spool policies **/
|
||||
@@ -571,10 +606,21 @@ bool process_staged_record(char *filename, bool is_retry, TelemPostDaemon *daemo
|
||||
/** Deliver or spool **/
|
||||
ret = deliver_record(daemon, headers, body, cfg_file);
|
||||
|
||||
end_record_delivery:
|
||||
/** Save record once it is properly delivered, if record
|
||||
* is spooled the record is not saved to journal until
|
||||
* delievered on a re-try **/
|
||||
if (ret) {
|
||||
/** Save to journal **/
|
||||
save_entry_to_journal(daemon, current_time, headers);
|
||||
/** Record retention **/
|
||||
apply_retention_policies(daemon, body);
|
||||
}
|
||||
|
||||
end_processing_file:
|
||||
/** Update spool size if record will be removed **/
|
||||
if (ret) {
|
||||
(daemon->current_spool_size) -= (buf.st_blocks * 512);
|
||||
daemon->current_spool_size -= (buf.st_blocks * 512);
|
||||
}
|
||||
telem_log(LOG_DEBUG, "spool_size: %ld\n", daemon->current_spool_size);
|
||||
free(body);
|
||||
@@ -625,7 +671,7 @@ int staging_records_loop(TelemPostDaemon *daemon)
|
||||
telem_log(LOG_ERR, "Failed to allocate memory for staging record full path\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (process_staged_record(record_path, true, daemon)) {
|
||||
if (process_staged_record(record_path, daemon)) {
|
||||
unlink(record_path);
|
||||
processed++;
|
||||
}
|
||||
@@ -721,7 +767,7 @@ void run_daemon(TelemPostDaemon *daemon)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
/* Process inotify event */
|
||||
if (process_staged_record(record_name, false, daemon)) {
|
||||
if (process_staged_record(record_name, daemon)) {
|
||||
unlink(record_name);
|
||||
}
|
||||
free(record_name);
|
||||
|
||||
@@ -85,11 +85,9 @@ void close_daemon(TelemPostDaemon *daemon);
|
||||
* Processed record written on disk
|
||||
*
|
||||
* @param filename a pointor to record on disk
|
||||
* @param is_retry a boolean value that indicates if
|
||||
* the record has been previously processed.
|
||||
* @param daemon post to telemetry post daemon
|
||||
*/
|
||||
bool process_staged_record(char *filename, bool is_retry, TelemPostDaemon *daemon);
|
||||
bool process_staged_record(char *filename, TelemPostDaemon *daemon);
|
||||
|
||||
/**
|
||||
* Scans staging directory to process files that were
|
||||
@@ -107,6 +105,7 @@ int staging_records_loop(TelemPostDaemon *daemon);
|
||||
* @param body a pointer to the payload
|
||||
* @param cfg_file a pointer to a non-default configuration
|
||||
* file to be used.
|
||||
* @return true if successful, false otherwise
|
||||
*/
|
||||
bool post_record_http(char *headers[], char *body, char *cfg_file);
|
||||
|
||||
|
||||
+2
-2
@@ -65,7 +65,7 @@ bool get_header_value(const char *header, char **value)
|
||||
*value = strdup(sep);
|
||||
}
|
||||
|
||||
return (bool)(value != NULL);
|
||||
return (bool)(*value != NULL);
|
||||
}
|
||||
|
||||
void *reallocate(void **addr, size_t *allocated, size_t requested)
|
||||
@@ -143,7 +143,7 @@ int get_random_id(char **buff)
|
||||
int frandom = -1;
|
||||
uint64_t random_id[2] = { '\0' };
|
||||
|
||||
frandom = open("/dev/urandom", O_RDONLY);
|
||||
frandom = open("/dev/urandom", O_RDONLY|O_NOFOLLOW);
|
||||
if (frandom < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
+12
-2
@@ -14,8 +14,10 @@
|
||||
* details.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <check.h>
|
||||
#include "configuration.h"
|
||||
#include "configuration_check.h"
|
||||
|
||||
START_TEST(check_read_config_for_invalid_file)
|
||||
{
|
||||
@@ -52,6 +54,7 @@ START_TEST(check_read_valid_config)
|
||||
"X-Telemetry-TID: 6907c830-eed9-4ce9-81ae-76daf8d88f0f");
|
||||
ck_assert(config.boolValues[CONF_DAEMON_RECYCLING_ENABLED] == true);
|
||||
|
||||
free_config_struct(&config);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -80,6 +83,8 @@ START_TEST(check_default_config)
|
||||
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);
|
||||
|
||||
free_config_struct(&config);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -110,6 +115,8 @@ START_TEST(check_layered_config)
|
||||
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);
|
||||
|
||||
free_config_struct(&config);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -123,6 +130,8 @@ START_TEST(check_read_valid_config_record_retention_delivery)
|
||||
|
||||
ck_assert(config.boolValues[CONF_RECORD_RETENTION_ENABLED] == true);
|
||||
ck_assert(config.boolValues[CONF_RECORD_SERVER_DELIVERY_ENABLED] == false);
|
||||
|
||||
free_config_struct(&config);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -176,6 +185,7 @@ int main(void)
|
||||
{
|
||||
Suite *s;
|
||||
SRunner *sr;
|
||||
int failed;
|
||||
|
||||
s = config_suite();
|
||||
sr = srunner_create(s);
|
||||
@@ -186,13 +196,13 @@ int main(void)
|
||||
srunner_set_tap(sr, "-");
|
||||
|
||||
srunner_run_all(sr, CK_SILENT);
|
||||
// failed = srunner_ntests_failed(sr);
|
||||
failed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
|
||||
// if you want the TAP driver to report a hard error based
|
||||
// on certain conditions (e.g. number of failed tests, etc.),
|
||||
// return non-zero here instead.
|
||||
return 0;
|
||||
return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* vi: set ts=8 sw=8 sts=4 et tw=80 cino=(0: */
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <check.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "common.h"
|
||||
#include "journal/journal.h"
|
||||
|
||||
@@ -239,6 +240,7 @@ int main(void)
|
||||
{
|
||||
Suite *s;
|
||||
SRunner *sr;
|
||||
int failed;
|
||||
|
||||
s = config_suite();
|
||||
sr = srunner_create(s);
|
||||
@@ -249,13 +251,13 @@ int main(void)
|
||||
srunner_set_tap(sr, "-");
|
||||
|
||||
srunner_run_all(sr, CK_SILENT);
|
||||
// failed = srunner_ntests_failed(sr);
|
||||
failed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
|
||||
// if you want the TAP driver to report a hard error based
|
||||
// on certain conditions (e.g. number of failed tests, etc.),
|
||||
// return non-zero here instead.
|
||||
return 0;
|
||||
return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* vi: set ts=8 sw=8 sts=4 et tw=80 cino=(0: */
|
||||
|
||||
+27
-11
@@ -41,7 +41,7 @@ void create_setup(void)
|
||||
* with the libcheck API...
|
||||
*/
|
||||
ck_assert_msg(ret != -ECONNREFUSED,
|
||||
"Opt-out enabled. Opt in to run these tests");
|
||||
"First time opt-in required to run test");
|
||||
}
|
||||
|
||||
START_TEST(record_create_non_null)
|
||||
@@ -98,12 +98,22 @@ void create_teardown(void)
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(is_opt_in)
|
||||
{
|
||||
int ret;
|
||||
ret = tm_is_opted_in();
|
||||
/* Smoke testing function */
|
||||
ck_assert_msg(ret == 0 || ret == 1,
|
||||
"Something wrong with opt-in check");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(record_create_invalid_class1)
|
||||
{
|
||||
int ret;
|
||||
ret = tm_create_record(&ref, 1, "t/t", 2000);
|
||||
ck_assert_msg(ret != -ECONNREFUSED,
|
||||
"Opt-out enabled. Opt in to run this test");
|
||||
"First time opt-in required to run test");
|
||||
ck_assert(ret == -EINVAL);
|
||||
}
|
||||
END_TEST
|
||||
@@ -113,7 +123,7 @@ START_TEST(record_create_invalid_class2)
|
||||
int ret;
|
||||
ret = tm_create_record(&ref, 1, "t/t/t/t", 2000);
|
||||
ck_assert_msg(ret != -ECONNREFUSED,
|
||||
"Opt-out enabled. Opt in to run this test");
|
||||
"First time opt-in required to run test");
|
||||
ck_assert(ret == -EINVAL);
|
||||
}
|
||||
END_TEST
|
||||
@@ -126,7 +136,7 @@ START_TEST(record_create_severity_underflow)
|
||||
// Severity of 0 is too low; raise it to 1, the minimum
|
||||
ret = tm_create_record(&ref, 0, "a/a/a", 2000);
|
||||
ck_assert_msg(ret != -ECONNREFUSED,
|
||||
"Opt-out enabled. Opt in to run this test");
|
||||
"First time opt-in required to run test");
|
||||
|
||||
if (asprintf(&result, "%s: %u\n", TM_SEVERITY_STR, 1) < 0) {
|
||||
return;
|
||||
@@ -146,7 +156,7 @@ START_TEST(record_create_severity_overflow)
|
||||
// Severity of 5 is too high; lower it to 4, the maximum
|
||||
ret = tm_create_record(&ref, 5, "b/b/b", 2000);
|
||||
ck_assert_msg(ret != -ECONNREFUSED,
|
||||
"Opt-out enabled. Opt in to run this test");
|
||||
"First time opt-in required to run test");
|
||||
|
||||
if (asprintf(&result, "%s: %u\n", TM_SEVERITY_STR, 4) < 0) {
|
||||
return;
|
||||
@@ -172,7 +182,7 @@ void event_id_setup(void)
|
||||
return;
|
||||
}
|
||||
ck_assert_msg(ret != -ECONNREFUSED,
|
||||
"Opt-out enabled. Opt in to run this test");
|
||||
"First time opt-in required to run test");
|
||||
}
|
||||
|
||||
START_TEST(record_set_event_id)
|
||||
@@ -233,9 +243,8 @@ END_TEST
|
||||
|
||||
void event_id_teardown(void)
|
||||
{
|
||||
if (ref) {
|
||||
free(ref);
|
||||
}
|
||||
// Free record
|
||||
create_teardown();
|
||||
free(original_event_id);
|
||||
}
|
||||
|
||||
@@ -252,6 +261,10 @@ Suite *lib_suite(void)
|
||||
tcase_add_test(t, record_create_version);
|
||||
suite_add_tcase(s, t);
|
||||
|
||||
t = tcase_create("Opt-in");
|
||||
tcase_add_test(t, is_opt_in);
|
||||
suite_add_tcase(s, t);
|
||||
|
||||
t = tcase_create("invalid classification");
|
||||
tcase_add_test(t, record_create_invalid_class1);
|
||||
tcase_add_test(t, record_create_invalid_class2);
|
||||
@@ -278,6 +291,7 @@ int main(void)
|
||||
{
|
||||
Suite *s;
|
||||
SRunner *sr;
|
||||
int failed;
|
||||
|
||||
s = lib_suite();
|
||||
sr = srunner_create(s);
|
||||
@@ -285,11 +299,13 @@ int main(void)
|
||||
srunner_set_log(sr, NULL);
|
||||
srunner_set_tap(sr, "-");
|
||||
|
||||
// set CK_NOFORK to attach gdb
|
||||
// srunner_set_fork_status(sr, CK_NOFORK);
|
||||
srunner_run_all(sr, CK_SILENT);
|
||||
|
||||
failed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
|
||||
return 0;
|
||||
return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* vi: set ts=8 sw=8 sts=4 et tw=80 cino=(0: */
|
||||
|
||||
@@ -1,192 +0,0 @@
|
||||
/*
|
||||
* This program is part of the Clear Linux Project
|
||||
*
|
||||
* Copyright 2017 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
|
||||
* published by the Free Software Foundation; either version 2.1 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
#define OUT_MAX_LEN 100
|
||||
|
||||
#include <stdio.h>
|
||||
#include <check.h>
|
||||
#include "nica/b64enc.h"
|
||||
|
||||
START_TEST(check_nc_b64_no_overflow)
|
||||
{
|
||||
size_t n = 2;
|
||||
char out[OUT_MAX_LEN];
|
||||
const char *filename = TOPSRCDIR "/tests/nc_b64enc_test_files/foobar";
|
||||
|
||||
ck_assert_msg(!nc_b64enc_filename(filename, &out[0], n), "Should quit since buffer smaller than content");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(check_nc_b64_enc_n_file_empty)
|
||||
{
|
||||
size_t n = OUT_MAX_LEN;
|
||||
char out[OUT_MAX_LEN];
|
||||
char *result = "\0";
|
||||
const char *filename = TOPSRCDIR "/tests/nc_b64enc_test_files/empty";
|
||||
|
||||
ck_assert_msg(nc_b64enc_filename(filename, &out[0], n), "Error opening file");
|
||||
ck_assert_str_eq(out, result);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(check_nc_b64_enc_n_file_fo)
|
||||
{
|
||||
size_t n = OUT_MAX_LEN;
|
||||
char out[OUT_MAX_LEN];
|
||||
char *result = "Zm8=";
|
||||
const char *filename = TOPSRCDIR "/tests/nc_b64enc_test_files/fo";
|
||||
|
||||
ck_assert_msg(nc_b64enc_filename(filename, &out[0], n), "Error opening file");
|
||||
ck_assert_str_eq(out, result);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(check_nc_b64_enc_n_file_foob)
|
||||
{
|
||||
size_t n = OUT_MAX_LEN;
|
||||
char out[OUT_MAX_LEN];
|
||||
char *result = "Zm9vYg==";
|
||||
const char *filename = TOPSRCDIR "/tests/nc_b64enc_test_files/foob";
|
||||
|
||||
ck_assert_msg(nc_b64enc_filename(filename, &out[0], n), "Error opening file");
|
||||
ck_assert_str_eq(out, result);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(check_nc_b64_enc_n_file_foobar)
|
||||
{
|
||||
size_t n = OUT_MAX_LEN;
|
||||
char out[OUT_MAX_LEN];
|
||||
char *result = "Zm9vYmFyZm9vYmFy";
|
||||
const char *filename = TOPSRCDIR "/tests/nc_b64enc_test_files/foobar";
|
||||
|
||||
ck_assert_msg(nc_b64enc_filename(filename, &out[0], n), "Error opening file");
|
||||
ck_assert_str_eq(out, result);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(check_nc_b64_enc_n_file_long_text)
|
||||
{
|
||||
size_t out_len = 8000;
|
||||
char out[out_len];
|
||||
const char *expected_out = \
|
||||
"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIG5vbnVtbXkgdml0YWUsIGluIHZpdmFtdXMgc3Vz\n"
|
||||
"cGVuZGlzc2UgYWMuIFNlbXBlciBzZWQgcGhhcmV0cmEgc2NlbGVyaXNxdWUuIEVnZXQgZWxlaWZl\n"
|
||||
"bmQgYW1ldCB2ZWwgbnVuYyB2b2x1dHBhdCBjdXJzdXMsIGF1Y3RvciBwbGF0ZWEgcHJldGl1bSwg\n"
|
||||
"bWF0dGlzIHJpc3VzIGZhY2lsaXNpcyBmYXVjaWJ1cywgc3VzcGVuZGlzc2UgZGlhbSwgbGVjdHVz\n"
|
||||
"IG1ldHVzIG51bGxhLiBOdW5jIGp1c3RvIGZhY2lsaXNpIG5hbSBmZWxpcyB2ZWwgbGFvcmVldCwg\n"
|
||||
"bmliaCBsZW8gbWFzc2Egc3VzcGVuZGlzc2UgYWNjdW1zYW4gY29udmFsbGlzLCBzZWQgcXVpcyBw\n"
|
||||
"ZWxsZW50ZXNxdWUgZWdlc3RhcywgbG9yZW0gYW50ZSBtb3JiaSBtYXR0aXMgdml0YWUuIFByYWVz\n"
|
||||
"ZW50IGluIHJ1dHJ1bSBlZ2V0IGFjLCB2aXZhbXVzIHBlZGUgc3VzcGVuZGlzc2UgbGVjdHVzIG51\n"
|
||||
"bGxhbSwgZXQgcGVkZSBldSBvZGlvIHBlZGUsIGV0aWFtIGxlbyBlZ2VzdGFzIGluLCBub251bW15\n"
|
||||
"IHNlbXBlci4gQSBhY2N1bXNhbiBkdWksIHZlc3RpYnVsdW0gcmlkaWN1bHVzIGV0IGluLCBqdXN0\n"
|
||||
"byBldCBwbGFjZXJhdCBkdWlzIHV0IHZpdmFtdXMgbGliZXJvLiBWZXN0aWJ1bHVtIGVnZXQgdXQg\n"
|
||||
"bW9sbGlzLCBudW5jIGEgc29sbGljaXR1ZGluLCBmcmluZ2lsbGEgZXJvcyBwb3N1ZXJlIG1vbGxp\n"
|
||||
"cyBhYyBuYXRvcXVlIHBlZGUsIHJpc3VzIG51bGxhIHJ1dHJ1bSB0dXJwaXMgYSB2aXRhZSBpZC4g\n"
|
||||
"SW5jZXB0b3MgdGluY2lkdW50IHF1aWRlbSBhcmN1IHR1cnBpcyBudW5jIHNvbGxpY2l0dWRpbi4g\n"
|
||||
"UGhhc2VsbHVzIG1ldHVzIGVyYXQgcGxhY2VyYXQsIGluIGVyYXQgbG9yZW0gbWF1cmlzIG51bGxh\n"
|
||||
"LCBhdCBsaWJlcm8gZXJhdCBzdXNwZW5kaXNzZSBzYXBpZW4gbW9udGVzIHJob25jdXMsIG1hZ25h\n"
|
||||
"IHF1YW0uIEp1c3RvIHByYWVzZW50IGxhY3VzIG1hc3NhLCByZXByZWhlbmRlcml0IG51bmMsIHJp\n"
|
||||
"c3VzIGRpZ25pc3NpbSBmZWxpcyBub24sIGRpZ25pc3NpbSBvZGlvIHRlbGx1cyBhbGlxdWFtLCBl\n"
|
||||
"bmltIHNvZGFsZXMgdGVtcG9yIHF1aXNxdWUgc29kYWxlcyBtYWduaXMgcG9ydHRpdG9yLiBMaWd1\n"
|
||||
"bGEgc2VkIHJpc3VzLCBldSBlc3QgcXVpc3F1ZSwgY2xhc3Mgbm9uIGF1dGUgZXUsIHBsYXRlYSBz\n"
|
||||
"Y2VsZXJpc3F1ZSBpZCBpbnRlZ2VyIGRpZ25pc3NpbW9zIGludGVnZXIgc3VzY2lwaXQuClZlaGlj\n"
|
||||
"dWxhIGVpdXMgbmVjLCBjb252YWxsaXMgbWFlY2VuYXMgbGVjdHVzIHB1cnVzIHF1aXNxdWUgYWxp\n"
|
||||
"cXVhbSwgZXQgZXQsIGxhY2luaWEgZGlzIGRpZ25pc3NpbSBsb3JlbS4gVm9sdXB0YXRlbSB1dCwg\n"
|
||||
"dml2ZXJyYSBhZW5lYW4gcGhhc2VsbHVzIGZlbGlzLCBmZXJtZW50dW0gbGlndWxhIGVnZXQgdWxs\n"
|
||||
"YW1jb3JwZXIgYW1ldCwgbWF1cmlzIGxlbyBsdWN0dXMuIEV0IGV0aWFtIHNlbXBlciBwaGFyZXRy\n"
|
||||
"YSBuaWJoIG1pIG1hdXJpcy4gSGVuZHJlcml0IHNlZCBhbGlxdWFtLCBlZ2V0IGlkIHRlbGx1cyBt\n"
|
||||
"YWduYSwgc2VkIGxhb3JlZXQgdWx0cmljZXMgZW5pbSwgbW9sbGlzIHN1c3BlbmRpc3NlIGluLiBF\n"
|
||||
"dSBudWxsYW0gbG9yZW0gc2l0IGV0aWFtLCBvcmNpIGluIGxpYmVyby4gTnVuYyBpcHN1bSBtYXVy\n"
|
||||
"aXMgZXQgc2VtIGhhYy4gRGljdHVtIGZhdWNpYnVzIGRpcyB2aXRhZSBpbiB2b2x1dHBhdCBtb3Ji\n"
|
||||
"aSwgYSBkaWN0dW0sIHF1aXNxdWUgbWF1cmlzLCBhdWN0b3IgbmVjIHZlbCBwZWxsZW50ZXNxdWUg\n"
|
||||
"dWxsYW1jb3JwZXIgZXRpYW0uIEN1bSBsaWJlcm8gd2lzaSBhY2N1bXNhbiBhbGlxdWFtIGNvbnNl\n"
|
||||
"Y3RldHVlciB0ZWxsdXMsIHBoYXNlbGx1cyBjdXJhZSwgYXQgaWxsdW0gYW50ZSBwcmV0aXVtIG5p\n"
|
||||
"YmggbW9yYmkuIFNlZCBibGFuZGl0IHB1bHZpbmFyIHB1bHZpbmFyLiBEaWN0dW0gZXN0IG51bmMg\n"
|
||||
"ZWxlaWZlbmQsIHZlbGl0IHZlbGl0IHRlbXBvciBhY2N1bXNhbiBsb2JvcnRpcyBsYW9yZWV0IGNv\n"
|
||||
"bmd1ZS4gU2l0IGFtZXQsIHNlZCBuaWJoIHBvcnJvIG5lcXVlIGF1Y3RvciBoeW1lbmFlb3MgcG9z\n"
|
||||
"dWVyZSwgb2RpbyBudWxsYSBibGFuZGl0IGNvbmd1ZSBlbGl0LiBJZCBmYXVjaWJ1cyBldCB0ZW1w\n"
|
||||
"dXMgbWFsZXN1YWRhIHBsYXRlYS4=";
|
||||
const char *filename = TOPSRCDIR "/tests/nc_b64enc_test_files/long_text";
|
||||
|
||||
ck_assert_msg(nc_b64enc_filename(filename, &out[0], out_len), "Error opening file");
|
||||
ck_assert_str_eq(out, expected_out);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(check_nc_b64_enc_n_filehandler_foobar)
|
||||
{
|
||||
size_t n = OUT_MAX_LEN;
|
||||
char out[OUT_MAX_LEN];
|
||||
char *result = "Zm9vYmFyZm9vYmFy";
|
||||
const char *filename = TOPSRCDIR "/tests/nc_b64enc_test_files/foobar";
|
||||
FILE *fh = NULL;
|
||||
|
||||
fh = fopen(filename, "rb");
|
||||
|
||||
if (fh == NULL) {
|
||||
ck_abort_msg("Unable to open foobar file");
|
||||
}
|
||||
|
||||
ck_assert_msg(nc_b64enc_file(fh, &out[0], n), "Result does not match");
|
||||
ck_assert_str_eq(out, result);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *config_suite(void)
|
||||
{
|
||||
// A suite is comprised of test cases, defined below
|
||||
Suite *s = suite_create("nc_b64enc");
|
||||
|
||||
// Individual unit tests are added to "test cases"
|
||||
TCase *t = tcase_create("nc_b64enc");
|
||||
tcase_add_test(t, check_nc_b64_no_overflow);
|
||||
tcase_add_test(t, check_nc_b64_enc_n_file_empty);
|
||||
tcase_add_test(t, check_nc_b64_enc_n_file_fo);
|
||||
tcase_add_test(t, check_nc_b64_enc_n_file_foob);
|
||||
tcase_add_test(t, check_nc_b64_enc_n_file_foobar);
|
||||
tcase_add_test(t, check_nc_b64_enc_n_file_long_text);
|
||||
tcase_add_test(t, check_nc_b64_enc_n_filehandler_foobar);
|
||||
|
||||
suite_add_tcase(s, t);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
Suite *s;
|
||||
SRunner *sr;
|
||||
|
||||
s = config_suite();
|
||||
sr = srunner_create(s);
|
||||
|
||||
// Use the TAP driver for now, so that each
|
||||
// unit test will PASS/FAIL in the log output.
|
||||
srunner_set_log(sr, NULL);
|
||||
srunner_set_tap(sr, "-");
|
||||
|
||||
srunner_run_all(sr, CK_SILENT);
|
||||
// failed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
|
||||
// if you want the TAP driver to report a hard error based
|
||||
// on certain conditions (e.g. number of failed tests, etc.),
|
||||
// return non-zero here instead.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vi: set ts=8 sw=8 sts=4 et tw=80 cino=(0: */
|
||||
+7
-6
@@ -62,7 +62,7 @@ START_TEST(check_handle_client_with_no_data)
|
||||
bool success;
|
||||
char *filename = ABSTOPSRCDIR "/tests/telempostd/empty_message";
|
||||
|
||||
success = process_staged_record(filename, false, &tdaemon);
|
||||
success = process_staged_record(filename, &tdaemon);
|
||||
// Return true to remove corrupted record
|
||||
ck_assert(success == true);
|
||||
}
|
||||
@@ -75,7 +75,7 @@ START_TEST(check_handle_client_with_incorrect_data)
|
||||
bool success;
|
||||
char *filename = ABSTOPSRCDIR "/tests/telempostd/incorrect_message";
|
||||
|
||||
success = process_staged_record(filename, false, &tdaemon);
|
||||
success = process_staged_record(filename, &tdaemon);
|
||||
// Return true to remove corrupted record
|
||||
ck_assert(success == true);
|
||||
}
|
||||
@@ -88,7 +88,7 @@ START_TEST(check_process_record_with_correct_size_and_data)
|
||||
bool success;
|
||||
char *filename = ABSTOPSRCDIR "/tests/telempostd/correct_message";
|
||||
|
||||
success = process_staged_record(filename, false, &tdaemon);
|
||||
success = process_staged_record(filename, &tdaemon);
|
||||
ck_assert(success == true);
|
||||
}
|
||||
END_TEST
|
||||
@@ -100,7 +100,7 @@ START_TEST(check_process_record_with_incorrect_headers)
|
||||
bool success;
|
||||
char *filename = ABSTOPSRCDIR "/tests/telempostd/incorrect_headers";
|
||||
|
||||
success = process_staged_record(filename, false, &tdaemon);
|
||||
success = process_staged_record(filename, &tdaemon);
|
||||
// Return true to remove corrupted record
|
||||
ck_assert(success == true);
|
||||
}
|
||||
@@ -421,6 +421,7 @@ int main(void)
|
||||
{
|
||||
Suite *s;
|
||||
SRunner *sr;
|
||||
int failed;
|
||||
|
||||
s = config_suite();
|
||||
sr = srunner_create(s);
|
||||
@@ -431,13 +432,13 @@ int main(void)
|
||||
srunner_set_tap(sr, "-");
|
||||
|
||||
srunner_run_all(sr, CK_SILENT);
|
||||
// failed = srunner_ntests_failed(sr);
|
||||
failed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
|
||||
// if you want the TAP driver to report a hard error based
|
||||
// on certain conditions (e.g. number of failed tests, etc.),
|
||||
// return non-zero here instead.
|
||||
return 0;
|
||||
return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* vi: set ts=8 sw=8 sts=4 et tw=80 cino=(0: */
|
||||
|
||||
+30
-5
@@ -22,6 +22,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "configuration.h"
|
||||
#include "configuration_check.h"
|
||||
#include "telemdaemon.h"
|
||||
#include "common.h"
|
||||
|
||||
@@ -61,12 +62,19 @@ void setup(void)
|
||||
initialize_probe_daemon(&tdaemon);
|
||||
}
|
||||
|
||||
void teardown(void)
|
||||
{
|
||||
free_config_file();
|
||||
}
|
||||
|
||||
START_TEST(check_daemon_is_initialized)
|
||||
{
|
||||
setup();
|
||||
|
||||
ck_assert(tdaemon.nfds == 0);
|
||||
ck_assert(tdaemon.pollfds == NULL);
|
||||
|
||||
teardown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -84,9 +92,9 @@ START_TEST(check_add_del_poll_fd)
|
||||
|
||||
int fd = 1;
|
||||
int short events = 1;
|
||||
add_pollfd(&tdaemon, fd, events);
|
||||
add_pollfd(&tdaemon, ++fd, events);
|
||||
add_pollfd(&tdaemon, ++fd, events);
|
||||
add_pollfd(&tdaemon, 1, events);
|
||||
add_pollfd(&tdaemon, 2, events);
|
||||
add_pollfd(&tdaemon, 3, events);
|
||||
ck_assert_msg(tdaemon.nfds == 3, "Failed to add pollfd");
|
||||
|
||||
fd = get_poll_fd(&tdaemon, 0);
|
||||
@@ -110,6 +118,10 @@ START_TEST(check_add_del_poll_fd)
|
||||
ck_assert_msg(tdaemon.nfds == 0, "Failed to delete pollfd");
|
||||
fd = get_poll_fd(&tdaemon, 0);
|
||||
ck_assert(fd == -1);
|
||||
|
||||
/* Cleaning alloctions */
|
||||
free(tdaemon.pollfds);
|
||||
teardown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -133,6 +145,8 @@ START_TEST(check_add_remove_client)
|
||||
remove_client(&(tdaemon.client_head), cl3);
|
||||
//ck_assert(tdaemon.client_head.lh_first == NULL);
|
||||
ck_assert_msg(is_client_list_empty(&(tdaemon.client_head)), "Failed to remove clients\n");
|
||||
|
||||
teardown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -171,6 +185,8 @@ START_TEST(check_handle_client_with_no_data)
|
||||
ck_assert_msg(is_client_list_empty(&(tdaemon.client_head)), "Failed to remove client with no data\n");
|
||||
ck_assert_msg(tdaemon.nfds == 0, "Failed to remove poll fd for client with n data\n");
|
||||
close(server_fd);
|
||||
|
||||
teardown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -197,6 +213,8 @@ START_TEST(check_handle_client_with_incorrect_data)
|
||||
ck_assert_msg(is_client_list_empty(&(tdaemon.client_head)), "Failed to remove client with no data\n");
|
||||
ck_assert_msg(tdaemon.nfds == 0, "Failed to remove poll fd for client with n data\n");
|
||||
close(server_fd);
|
||||
|
||||
teardown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -228,6 +246,8 @@ START_TEST(check_handle_client_with_incorrect_size)
|
||||
ck_assert_msg(is_client_list_empty(&(tdaemon.client_head)), "Failed to remove client with no data\n");
|
||||
ck_assert_msg(tdaemon.nfds == 0, "Failed to remove poll fd for client with n data\n");
|
||||
close(server_fd);
|
||||
|
||||
teardown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -332,6 +352,8 @@ START_TEST(check_process_record_with_incorrect_headers)
|
||||
ck_assert_msg(tdaemon.nfds == 0, "Failed to remove poll fd for client with incorrect headers\n");
|
||||
close(server_fd);
|
||||
free(record);
|
||||
|
||||
teardown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -361,6 +383,7 @@ int main(void)
|
||||
{
|
||||
Suite *s;
|
||||
SRunner *sr;
|
||||
int failed;
|
||||
|
||||
s = config_suite();
|
||||
sr = srunner_create(s);
|
||||
@@ -370,14 +393,16 @@ int main(void)
|
||||
srunner_set_log(sr, NULL);
|
||||
srunner_set_tap(sr, "-");
|
||||
|
||||
// set CK_NOFORK to attach gdb
|
||||
// srunner_set_fork_status(sr, CK_NOFORK);
|
||||
srunner_run_all(sr, CK_SILENT);
|
||||
// failed = srunner_ntests_failed(sr);
|
||||
failed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
|
||||
// if you want the TAP driver to report a hard error based
|
||||
// on certain conditions (e.g. number of failed tests, etc.),
|
||||
// return non-zero here instead.
|
||||
return 0;
|
||||
return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* vi: set ts=8 sw=8 sts=4 et tw=80 cino=(0: */
|
||||
|
||||
+11
-23
@@ -57,6 +57,10 @@ void setup_payload(char *oopsfile)
|
||||
oops_parser_init(callback_func);
|
||||
split_buf_by_line(buf, buflen);
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
// Tests for checking backtrace
|
||||
@@ -249,6 +253,8 @@ START_TEST(sysctl1_payload)
|
||||
ck_assert(strstr(pl->str, "#24 sys_ioctl"));
|
||||
ck_assert(strstr(pl->str, "#25 sysenter_past_esp"));
|
||||
ck_assert(strstr(pl->str, "#26 quirk_ali7101_acpi"));
|
||||
|
||||
nc_string_free(pl);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
@@ -679,27 +685,6 @@ Suite *config_suite(void)
|
||||
tcase_add_test(t, bug_kernel_handle_payload);
|
||||
tcase_add_test(t, bug_kernel_handle_payload_new_format);
|
||||
|
||||
//TODO fix
|
||||
//tcase_add_test(t, badness_payload);
|
||||
|
||||
/*
|
||||
tcase_add_test(t, watchdog_oops);
|
||||
tcase_add_test(t, warning_oops);
|
||||
tcase_add_test(t, warn_on_oops);
|
||||
tcase_add_test(t, two_warnings_oops);
|
||||
tcase_add_test(t, sysctl1_oops);
|
||||
tcase_add_test(t, sysctl2_oops);
|
||||
tcase_add_test(t, softlockup_oops);
|
||||
tcase_add_test(t, rtnl_oops);
|
||||
tcase_add_test(t, kernel_null_pointer_oops);
|
||||
tcase_add_test(t, kernel_bug_oops);
|
||||
tcase_add_test(t, irq_oops);
|
||||
tcase_add_test(t, general_protection_fault_oops);
|
||||
tcase_add_test(t, double_fault_oops);
|
||||
tcase_add_test(t, bad_page_map_oops);
|
||||
tcase_add_test(t, bug_kernel_handle_oops);
|
||||
tcase_add_test(t, badness_oops);
|
||||
*/
|
||||
suite_add_tcase(s, t);
|
||||
|
||||
return s;
|
||||
@@ -709,6 +694,7 @@ int main(void)
|
||||
{
|
||||
Suite *s;
|
||||
SRunner *sr;
|
||||
int failed;
|
||||
|
||||
s = config_suite();
|
||||
sr = srunner_create(s);
|
||||
@@ -720,14 +706,16 @@ int main(void)
|
||||
srunner_set_log(sr, NULL);
|
||||
srunner_set_tap(sr, "-");
|
||||
|
||||
// set CK_NOFORK to attach gdb
|
||||
// srunner_set_fork_status(sr, CK_NOFORK);
|
||||
srunner_run_all(sr, CK_SILENT);
|
||||
// failed = srunner_ntests_failed(sr);
|
||||
failed = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
|
||||
// if you want the TAP driver to report a hard error based
|
||||
// on certain conditions (e.g. number of failed tests, etc.),
|
||||
// return non-zero here instead.
|
||||
return 0;
|
||||
return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* vi: set ts=8 sw=8 sts=4 et tw=80 cino=(0: */
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* This program is part of the Clear Linux Project
|
||||
*
|
||||
* Copyright 2020 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
|
||||
* published by the Free Software Foundation; either version 2.1 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/* Function used only for unit testing */
|
||||
/* Frees configuration structure */
|
||||
void free_config_struct(struct configuration *config);
|
||||
|
||||
/* Frees configuration file name string */
|
||||
void free_config_file(void);
|
||||
+16
-21
@@ -1,4 +1,6 @@
|
||||
EXTRA_DIST += %D%/taplib.sh
|
||||
EXTRA_DIST += \
|
||||
%D%/taplib.sh \
|
||||
%D%/telemetrics-client.supp
|
||||
|
||||
TEST_EXTENSIONS = .sh
|
||||
|
||||
@@ -15,7 +17,6 @@ check_PROGRAMS = \
|
||||
%D%/check_probd \
|
||||
%D%/check_postd \
|
||||
%D%/check_probes \
|
||||
%D%/check_ncb64 \
|
||||
%D%/check_journal \
|
||||
%D%/check_libtelemetry
|
||||
|
||||
@@ -23,6 +24,7 @@ dist_check_SCRIPTS = \
|
||||
%D%/create-core.sh
|
||||
|
||||
%C%_check_config_SOURCES = \
|
||||
%D%/configuration_check.h \
|
||||
%D%/check_config.c
|
||||
|
||||
%C%_check_config_CFLAGS = \
|
||||
@@ -41,6 +43,7 @@ endif
|
||||
endif
|
||||
|
||||
%C%_check_probd_SOURCES = \
|
||||
%D%/configuration_check.h \
|
||||
%D%/check_probd.c \
|
||||
src/telemdaemon.c \
|
||||
src/telemdaemon.h \
|
||||
@@ -90,6 +93,7 @@ EXTRA_DIST += \
|
||||
%C%_check_postd_LDADD = \
|
||||
@CHECK_LIBS@ \
|
||||
@CURL_LIBS@ \
|
||||
@JSON_C_LIBS@ \
|
||||
$(top_builddir)/src/libtelem-shared.la
|
||||
|
||||
if LOG_SYSTEMD
|
||||
@@ -155,25 +159,6 @@ if HAVE_SYSTEMD_JOURNAL
|
||||
endif
|
||||
endif
|
||||
|
||||
%C%_check_ncb64_SOURCES = \
|
||||
%D%/check_ncb64.c \
|
||||
src/nica/b64enc.h \
|
||||
src/nica/b64enc.c
|
||||
|
||||
%C%_check_ncb64_CFLAGS = \
|
||||
$(AM_CFLAGS) \
|
||||
@CHECK_CFLAGS@
|
||||
|
||||
%C%_check_ncb64_LDADD = \
|
||||
@CHECK_LIBS@
|
||||
|
||||
EXTRA_DIST += \
|
||||
%D%/nc_b64enc_test_files/empty \
|
||||
%D%/nc_b64enc_test_files/fo \
|
||||
%D%/nc_b64enc_test_files/foob \
|
||||
%D%/nc_b64enc_test_files/foobar \
|
||||
%D%/nc_b64enc_test_files/long_text
|
||||
|
||||
%C%_check_journal_SOURCES = \
|
||||
%D%/check_journal.c \
|
||||
src/journal/journal.c \
|
||||
@@ -216,4 +201,14 @@ if LOG_SYSTEMD
|
||||
endif
|
||||
endif
|
||||
|
||||
@VALGRIND_CHECK_RULES@
|
||||
VALGRIND_SUPPRESSIONS_FILES = %D%/telemetrics-client.supp
|
||||
VALGRIND_FLAGS = \
|
||||
--error-exitcode=1 \
|
||||
--track-origins=yes \
|
||||
--leak-resolution=low \
|
||||
--verbose \
|
||||
--leak-check=full \
|
||||
--show-possibly-lost=no
|
||||
|
||||
# vim: filetype=automake tabstop=8 shiftwidth=8 noexpandtab
|
||||
|
||||
+17
-9
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* This program is part of the Clear Linux Project
|
||||
*
|
||||
* Copyright 2015 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
|
||||
* published by the Free Software Foundation; either version 2.1 of the License,
|
||||
* or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
@@ -36,26 +52,18 @@ char *readfile(char *filepath)
|
||||
if (fread(bufp, sizeof(char), buflen, fp) != buflen) {
|
||||
telem_log(LOG_ERR, "Error reading file\n");
|
||||
} else {
|
||||
bufp[++buflen] = '\0';
|
||||
bufp[buflen] = '\0';
|
||||
}
|
||||
}
|
||||
if (fclose(fp) != 0) {
|
||||
printf("Error closing file: %s\n", strerror(errno));
|
||||
}
|
||||
//free(bufp);
|
||||
} else {
|
||||
telem_log(LOG_ERR, "Wrong file pathname: %s", filepath);
|
||||
}
|
||||
|
||||
return bufp;
|
||||
}
|
||||
/*
|
||||
char *getbuf()
|
||||
{
|
||||
|
||||
return bufp;
|
||||
}
|
||||
*/
|
||||
|
||||
unsigned long getbuflen()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# This program is part of the Clear Linux Project
|
||||
#
|
||||
# Copyright 2020 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
|
||||
# published by the Free Software Foundation; either version 2.1 of the License,
|
||||
# or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
# details.
|
||||
|
||||
|
||||
# False positive when check is run with CK_FORK=yes
|
||||
{
|
||||
ck_fork_yes_false_positive
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
fun:UnknownInlinedFun
|
||||
fun:UnknownInlinedFun
|
||||
fun:tag_string_to_list
|
||||
fun:UnknownInlinedFun
|
||||
fun:srunner_run_tagged
|
||||
fun:main
|
||||
}
|
||||
|
||||
# False positive returned by call to shell script from
|
||||
# with in test.
|
||||
{
|
||||
ck_shell_call
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
fun:xmalloc
|
||||
fun:set_default_locale
|
||||
fun:main
|
||||
}
|
||||
Reference in New Issue
Block a user