From 81fe01583f761f8da52523c23ae7762d57f6967a Mon Sep 17 00:00:00 2001 From: Jaehyun Kim Date: Mon, 13 Sep 2021 02:34:20 +0900 Subject: [PATCH] Add support for online monitoring report Change-Id: I957ee296b2835713bb5c59845f76393412ef5856 Signed-off-by: Jaehyun Kim --- packaging/net-config.spec | 7 + plugin/online-monitor/common_info_dump.sh | 104 ++++++++ plugin/online-monitor/report-manager.c | 395 +++++++++++++++++++++++++++++- plugin/online-monitor/supp_log_dump.sh | 27 ++ 4 files changed, 532 insertions(+), 1 deletion(-) create mode 100755 plugin/online-monitor/common_info_dump.sh create mode 100755 plugin/online-monitor/supp_log_dump.sh diff --git a/packaging/net-config.spec b/packaging/net-config.spec index 81c7123..c5fcbf8 100755 --- a/packaging/net-config.spec +++ b/packaging/net-config.spec @@ -198,6 +198,8 @@ mv %{_builddir}/%{name}-%{version}/net-config.wearable %{buildroot}%{_bindir} #online-monitor cp plugin/online-monitor/online_monitor.conf %{buildroot}/%{_localstatedir}/lib/net-config +cp plugin/online-monitor/common_info_dump.sh %{buildroot}/opt/var/lib/net-config/ +cp plugin/online-monitor/supp_log_dump.sh %{buildroot}/opt/var/lib/net-config/ %post chsmack -a 'System::Shared' %{_sysconfdir}/resolv.conf @@ -290,3 +292,8 @@ mv /var/lib/net-config/settings-robot /var/lib/net-config/settings %manifest net-config.manifest %attr(500,network_fw,network_fw) %{_libdir}/net-config-plugin-online-monitor.so %attr(644,root,root) %{_localstatedir}/lib/net-config/online_monitor.conf +%attr(750,network_fw,network_fw) /opt/var/lib/net-config/common_info_dump.sh +%attr(750,network_fw,network_fw) /opt/var/lib/net-config/supp_log_dump.sh + +%post plugin-online-monitor +/usr/bin/mkdir -p /opt/usr/data/network/online_mon diff --git a/plugin/online-monitor/common_info_dump.sh b/plugin/online-monitor/common_info_dump.sh new file mode 100755 index 0000000..611309c --- /dev/null +++ b/plugin/online-monitor/common_info_dump.sh @@ -0,0 +1,104 @@ +#!/bin/sh +PATH=/bin:/usr/bin:/sbin:/usr/sbin + +#-------------------------------------- +# Common Information Dump +#-------------------------------------- + +# not allow to use relative path +if [[ $0 == "/"* ]]; then + echo "Absolute path" +else + echo "Relative path" + exit -1 +fi + +export DISPLAY=:0.0 + +REPORT_TYPE=offline_detection +COMMON_INFO_FILE=$1 + +echo $2 > ${COMMON_INFO_FILE} +echo $3 >> ${COMMON_INFO_FILE} + +if [ $4 == ${REPORT_TYPE} ]; then +echo "" >> ${COMMON_INFO_FILE} +echo "[Default Connection Information]" >> ${COMMON_INFO_FILE} +dbus-send --system --print-reply --dest=net.connman / net.connman.Manager.GetDefaultService >> ${COMMON_INFO_FILE} +fi + +echo "" >> ${COMMON_INFO_FILE} +echo [netstat -na] >> ${COMMON_INFO_FILE} +/usr/bin/netstat -na >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [route -n] >> ${COMMON_INFO_FILE} +/usr/sbin/route -n >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [route -A inet6 -n] >> ${COMMON_INFO_FILE} +/usr/sbin/route -A inet6 -n >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [proc/net/wireless] >> ${COMMON_INFO_FILE} +/usr/bin/cat /proc/net/wireless >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [resolv.conf] >> ${COMMON_INFO_FILE} +/usr/bin/cat /etc/resolv.conf >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [ifconfig -a] >> ${COMMON_INFO_FILE} +/usr/sbin/ifconfig -a >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [iptables -L] >> ${COMMON_INFO_FILE} +/usr/sbin/iptables -L >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [ip6tables -L] >> ${COMMON_INFO_FILE} +/usr/sbin/ip6tables -L >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [/proc/net/tcp] >> ${COMMON_INFO_FILE} +/usr/bin/cat /proc/net/tcp >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [/proc/net/tcp6] >> ${COMMON_INFO_FILE} +/usr/bin/cat /proc/net/tcp6 >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [/proc/net/route] >> ${COMMON_INFO_FILE} +/usr/bin/cat /proc/net/route >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [ip -4 rule] >> ${COMMON_INFO_FILE} +/usr/sbin/ip -4 rule >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [ip -6 rule] >> ${COMMON_INFO_FILE} +/usr/sbin/ip -6 rule >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [ip -4 route show table all] >> ${COMMON_INFO_FILE} +/usr/sbin/ip -4 route show table all >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [ip -6 route show table all] >> ${COMMON_INFO_FILE} +/usr/sbin/ip -6 route show table all >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [memory/dnet] >> ${COMMON_INFO_FILE} +/usr/bin/vconftool -r get memory/dnet >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [memory/wifi] >> ${COMMON_INFO_FILE} +/usr/bin/vconftool -r get memory/wifi >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [file/private/wifi] >> ${COMMON_INFO_FILE} +/usr/bin/vconftool -r get file/private/wifi >> ${COMMON_INFO_FILE} +echo "" >> ${COMMON_INFO_FILE} + +echo [db/wifi] >> ${COMMON_INFO_FILE} +/usr/bin/vconftool -r get db/wifi >> ${COMMON_INFO_FILE} diff --git a/plugin/online-monitor/report-manager.c b/plugin/online-monitor/report-manager.c index a825ebf..dd0a224 100755 --- a/plugin/online-monitor/report-manager.c +++ b/plugin/online-monitor/report-manager.c @@ -17,24 +17,417 @@ * */ +#include +#include #include "online-monitor.h" +#define ONLINE_MON_LOG_PATH "/opt/usr/data/network/online_mon/" + +#define OFFLINE_DETECT_COMMON_LOG ONLINE_MON_LOG_PATH "offline_detection_common.log" +#define OFFLINE_DETECT_DLOG ONLINE_MON_LOG_PATH "offline_detection_dlog.log" +#define OFFLINE_DETECT_PACKET_DUMP ONLINE_MON_LOG_PATH "offline_detection_dump.log" +#define OFFLINE_DETECT_PACKET_DUMP0 ONLINE_MON_LOG_PATH "offline_detection_dump.log0" +#define OFFLINE_DETECT_PACKET_DUMP1 ONLINE_MON_LOG_PATH "offline_detection_dump.log1" + +#define DOWNGRADE_COMMON_LOG ONLINE_MON_LOG_PATH "downgrade_common.log" +#define DOWNGRADE_DLOG ONLINE_MON_LOG_PATH "downgrade_dlog.log" +#define DOWNGRADE_SUPP_LOG ONLINE_MON_LOG_PATH "downgrade_supp.log" + +#define KILLALL_EXEC_PATH "/usr/bin/killall" +#define TCPDUMP_EXEC_PATH "/usr/sbin/tcpdump" +#define COMMON_INFO_SCRIPT "/opt/var/lib/net-config/common_info_dump.sh" +#define SUPPLICANT_LOG_SCRIPT "/opt/var/lib/net-config/supp_log_dump.sh" +#define DLOGUTIL_EXEC_PATH "/usr/bin/dlogutil" + +static struct { + char *ifname; + online_monitor_state_e state; + online_monitor_detection_e reason; + gboolean tcpdump_started; + int detection_count; + int downgrade_count; + int max_log_count; +} report_manager_info; + +static inline void report_manager_update_file_revision(int rev, const char *file_path) +{ + int next_log_rev = 0; + char *log_file = NULL; + char *next_log_file = NULL; + + next_log_rev = rev + 1; + + log_file = g_strdup_printf("%s.%d", file_path, rev); + next_log_file = g_strdup_printf("%s.%d", file_path, next_log_rev); + + if (next_log_rev >= report_manager_info.max_log_count - 1) + remove(next_log_file); + + if (access(next_log_file, F_OK) == 0) + report_manager_update_file_revision(next_log_rev, file_path); + + if (rename(log_file, next_log_file) != 0) + remove(log_file); + + g_free(log_file); + g_free(next_log_file); +} + +static inline void report_manager_make_backup(const char *file_path) +{ + const int rev = 0; + char *backup = NULL; + + backup = g_strdup_printf("%s.%d", file_path, rev); + + if (access(backup, F_OK) == 0) + report_manager_update_file_revision(rev, file_path); + + if (rename(file_path, backup) != 0) + remove(file_path); + + g_free(backup); +} + +static int report_manager_execute_file(const char *file_path, + char *const args[], char *const envs[]) +{ + pid_t pid = 0; + int status = 0; + int rv = 0; + errno = 0; + register unsigned int index = 0; + char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, }; + + while (args[index] != NULL) { + DBG("%s", args[index]); + index++; + } + + if (!(pid = fork())) { + DBG("pid(%d), ppid (%d)", getpid(), getppid()); + DBG("Inside child, exec (%s) command", file_path); + + errno = 0; + if (execve(file_path, args, envs) == -1) { + DBG("Fail to execute command (%s)", + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER)); + exit(1); + } + } else if (pid > 0) { + if (waitpid(pid, &status, 0) == -1) + DBG("wait pid (%u) status (%d)", pid, status); + + if (WIFEXITED(status)) { + rv = WEXITSTATUS(status); + DBG("exited, status=%d", rv); + } else if (WIFSIGNALED(status)) { + DBG("killed by signal %d", WTERMSIG(status)); + } else if (WIFSTOPPED(status)) { + DBG("stopped by signal %d", WSTOPSIG(status)); + } else if (WIFCONTINUED(status)) { + DBG("continued"); + } + + return rv; + } + + DBG("failed to fork(%s)", + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER)); + return -EIO; +} + +static void no_wait_signal_handler() +{ + pid_t child_pid = 0; + int state = 0; + + child_pid = waitpid(-1, &state, WNOHANG); + + DBG("child_id(%d) state(%d)", child_pid, WEXITSTATUS(state)); +} + +static int report_manager_execute_file_no_wait(const char *file_path, char *const args[]) +{ + pid_t pid = 0; + int rv = 0; + errno = 0; + register unsigned int index = 0; + + struct sigaction act; + int state = 0; + char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, }; + + act.sa_handler = no_wait_signal_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + + state = sigaction(SIGCHLD, &act, 0); + if (state != 0) { + DBG("sigaction() : %d", state); + return -1; + } + + while (args[index] != NULL) { + DBG("%s", args[index]); + index++; + } + + if (!(pid = fork())) { + DBG("pid(%d), ppid (%d)", getpid(), getppid()); + DBG("Inside child, exec (%s) command", file_path); + + errno = 0; + if (execvp(file_path, args) == -1) { + ERR("Fail to execute command (%s)", + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER)); + return -1; + } + } else if (pid > 0) { + ERR("Successfully launched child process"); + return rv; + } + + DBG("failed to fork(%s)", + strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER)); + return -EIO; +} + +static gboolean report_manager_stop_tcpdump(void) +{ + int ret; + const char *path = KILLALL_EXEC_PATH; + char *const args[] = { KILLALL_EXEC_PATH, "tcpdump", NULL }; + char *const envs[] = { NULL }; + + if (!report_manager_info.tcpdump_started) { + DBG("tcpdump is not running"); + return FALSE; + } + + ret = report_manager_execute_file(path, args, envs); + if (ret < 0) { + DBG("Failed to Kill tcpdump, ret : %d\n", ret); + return FALSE; + } + + report_manager_info.tcpdump_started = FALSE; + + return TRUE; +} + +static gboolean report_manager_start_tcpdump(void) +{ + int ret; + const char *start_path = TCPDUMP_EXEC_PATH; + + if (access(OFFLINE_DETECT_PACKET_DUMP0, F_OK) == 0) + report_manager_make_backup(OFFLINE_DETECT_PACKET_DUMP0); + if (access(OFFLINE_DETECT_PACKET_DUMP1, F_OK) == 0) + report_manager_make_backup(OFFLINE_DETECT_PACKET_DUMP1); + + char *const start_args[] = { TCPDUMP_EXEC_PATH, + "-W", "2", "-C", "25", "-i", report_manager_info.ifname, + "-s", "0", "-w", OFFLINE_DETECT_PACKET_DUMP, NULL}; + + if (report_manager_info.tcpdump_started) { + DBG("kill tcpdump."); + gboolean ret = report_manager_stop_tcpdump(); + + if (!ret) + DBG("Failed to kill tcpdump.. ret : %d", ret); + + return FALSE; + } + + ret = report_manager_execute_file_no_wait(start_path, start_args); + if (ret < 0) { + DBG("Failed to start tcpdump, ret : %d", ret); + return FALSE; + } + + report_manager_info.tcpdump_started = TRUE; + + return report_manager_info.tcpdump_started; +} + +static char *convert_detection_reason(online_monitor_detection_e reason) +{ + switch (reason) { + case ONLINE_MONITOR_DETECTION_UNREACHABLE: + return "Destination Unreachable"; + case ONLINE_MONITOR_DETECTION_DNS_REFUSED: + return "DNS Refused"; + case ONLINE_MONITOR_DETECTION_NO_DNS_RESPONSE: + return "No DNS Response"; + default: + return "None"; + } +} + +static void report_manager_start_common_info_dump(gboolean is_downgrade) +{ + int rv = 0; + gchar *path = COMMON_INFO_SCRIPT; + char log_file_name[100] = { 0, }; + char detection_count[64] = { 0, }; + char sub_info[64] = { 0, }; + char report_type[32] = { 0, }; + + if (is_downgrade) { + g_snprintf(log_file_name, 100, DOWNGRADE_COMMON_LOG); + g_snprintf(detection_count, 64, "Offline Detection Count: %d", + report_manager_info.detection_count); + g_snprintf(sub_info, 64, "Downgrade Count: %d", + report_manager_info.downgrade_count); + g_snprintf(report_type, 32, "downgrade"); + } else { + g_snprintf(log_file_name, 100, OFFLINE_DETECT_COMMON_LOG); + g_snprintf(detection_count, 64, "Offline Detection Count: %d", + report_manager_info.detection_count); + g_snprintf(sub_info, 64, "Detection Reason: %s", + convert_detection_reason(report_manager_info.reason)); + g_snprintf(report_type, 32, "offline_detection"); + } + + if (access(log_file_name, F_OK) == 0) + report_manager_make_backup(log_file_name); + + char *const args[] = { COMMON_INFO_SCRIPT, + log_file_name, detection_count, sub_info, report_type, NULL }; + char *const envs[] = { NULL }; + + rv = report_manager_execute_file(path, args, envs); + + if (rv < 0) + ERR("Fail to execute network log dump shell"); +} + +static void report_manager_start_dlog_dump(gboolean is_downgrade) +{ + int rv = 0; + gchar *path = DLOGUTIL_EXEC_PATH; + char log_file_name[100] = { 0, }; + + if (is_downgrade) + g_snprintf(log_file_name, 100, DOWNGRADE_DLOG); + else + g_snprintf(log_file_name, 100, OFFLINE_DETECT_DLOG); + + if (access(log_file_name, F_OK) == 0) + report_manager_make_backup(log_file_name); + + char *const args[] = { DLOGUTIL_EXEC_PATH, "-f", log_file_name, "-d", "-t", "2000", NULL }; + char *const envs[] = { NULL }; + + rv = report_manager_execute_file(path, args, envs); + + if (rv < 0) + ERR("Fail to execute dlog dump command"); +} + +static void report_manager_start_supp_dump(void) +{ + int rv = 0; + gchar *path = SUPPLICANT_LOG_SCRIPT; + + if (access(DOWNGRADE_SUPP_LOG, F_OK) == 0) + report_manager_make_backup(DOWNGRADE_SUPP_LOG); + + char *const args[] = { SUPPLICANT_LOG_SCRIPT, DOWNGRADE_SUPP_LOG, NULL }; + char *const envs[] = { NULL }; + + rv = report_manager_execute_file(path, args, envs); + + if (rv < 0) + ERR("Fail to execute supplicant log dump shell"); +} + +static void report_manager_start_downgrade_dump(void) +{ + online_monitor_config_t *config = online_monitor_get_configuration(); + + report_manager_stop_tcpdump(); + + if (config->common_info) + report_manager_start_common_info_dump(TRUE); + + if (config->dlog) + report_manager_start_dlog_dump(TRUE); + + if (config->supplicant_log) + report_manager_start_supp_dump(); +} + +static void report_manager_start_detection_dump(void) +{ + online_monitor_config_t *config = online_monitor_get_configuration(); + + if (config->common_info) + report_manager_start_common_info_dump(FALSE); + + if (config->dlog) + report_manager_start_dlog_dump(FALSE); + + if (config->packet_dump) + report_manager_start_tcpdump(); +} + static void report_manager_state_chaged_cb(online_monitor_state_e state, char *ifname, online_monitor_detection_e reason) { DBG("state %d, ifname %s, reason %d", state, ifname, reason); + + report_manager_info.state = state; + report_manager_info.reason = reason; + + switch (state) { + case ONLINE_MONITOR_STATE_MONITORING_STARTED: + report_manager_info.ifname = ifname; + break; + case ONLINE_MONITOR_STATE_MONITORING_STOPPED: + report_manager_stop_tcpdump(); + report_manager_info.ifname = NULL; + break; + case ONLINE_MONITOR_STATE_OFFLINE_DETECTED: + report_manager_info.detection_count++; + report_manager_start_detection_dump(); + break; + case ONLINE_MONITOR_STATE_URL_CHECK_SUCCEEDED: + report_manager_stop_tcpdump(); + break; + case ONLINE_MONITOR_STATE_URL_CHECK_FAILED: + report_manager_info.downgrade_count++; + report_manager_start_downgrade_dump(); + break; + default : + break; + } } int report_manager_init(void) { - online_monitor_notifier_register(report_manager_state_chaged_cb); + online_monitor_config_t *config = online_monitor_get_configuration(); + + if (config->common_info || config->dlog || config->supplicant_log || config->packet_dump) + online_monitor_notifier_register(report_manager_state_chaged_cb); + + memset(&report_manager_info, 0, sizeof(report_manager_info)); + + report_manager_info.max_log_count = config->max_report_count; + report_manager_info.state = ONLINE_MONITOR_STATE_INITIALIZED; DBG("report_manager initialized"); + return 0; } int report_manager_deinit(void) { online_monitor_notifier_unregister(report_manager_state_chaged_cb); + report_manager_stop_tcpdump(); + + report_manager_info.state = ONLINE_MONITOR_STATE_UNINITIALIZED; DBG("report_manager deinitialized"); + return 0; } diff --git a/plugin/online-monitor/supp_log_dump.sh b/plugin/online-monitor/supp_log_dump.sh new file mode 100755 index 0000000..745f55e --- /dev/null +++ b/plugin/online-monitor/supp_log_dump.sh @@ -0,0 +1,27 @@ +#!/bin/sh +PATH=/bin:/usr/bin:/sbin:/usr/sbin + +#-------------------------------------- +# Supplicant Log Dump +#-------------------------------------- + +# not allow to use relative path +if [[ $0 == "/"* ]]; then + echo "Absolute path" +else + echo "Relative path" + exit -1 +fi + +export DISPLAY=:0.0 + +SUPP_LOG_FILE=$1 +SUPP_LOG_SIZE=$(stat -c %s "/opt/usr/data/network/wpa_supplicant.log") + +if [[ SUPP_LOG_SIZE -lt 200000 ]]; then +if [[ -f "/opt/usr/data/network/wpa_supplicant.log.0" ]]; then + cp /opt/usr/data/network/wpa_supplicant.log.0 ${SUPP_LOG_FILE} +fi +fi + +cat /opt/usr/data/network/wpa_supplicant.log >> ${SUPP_LOG_FILE} -- 2.7.4