From: taesub kim Date: Tue, 24 Oct 2017 05:02:08 +0000 (+0900) Subject: Added APIs get the tcp dump and network state X-Git-Tag: accepted/tizen/unified/20171206.063059^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F81%2F157281%2F12;p=platform%2Fcore%2Fconnectivity%2Fnet-config.git Added APIs get the tcp dump and network state Change-Id: Ife799113a9a77e3b18e777475347943ffa902c9e Signed-off-by: Taesub Kim --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ac8f89..960c0b1 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,6 +73,11 @@ IF(TIZEN_WEARABLE) ADD_DEFINITIONS(-DTIZEN_WEARABLE) ENDIF(TIZEN_WEARABLE) +IF(TIZEN_DEBUG_ENABLE) + ADD_DEFINITIONS(-DTIZEN_DEBUG_ENABLE) + SET(SRCS ${SRCS} src/network-dump.c) +ENDIF(TIZEN_DEBUG_ENABLE) + INCLUDE(FindPkgConfig) PKG_CHECK_MODULES(pkgs REQUIRED dlog diff --git a/include/network-dump.h b/include/network-dump.h new file mode 100755 index 0000000..7fb514b --- /dev/null +++ b/include/network-dump.h @@ -0,0 +1,50 @@ +/* + * Network Configuration Module + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef __NETCONFIG_NETWORK_DUMP_H__ +#define __NETCONFIG_NETWORK_DUMP_H__ + +#ifdef __cplusplus +extern "C" { +#endif +#include + +#define DUMP_SERVICE_BUS_NAME "org.tizen.system.dumpservice" +#define DUMP_SERVICE_OBJECT_PATH "/Org/Tizen/System/DumpService" +#define DUMP_SERVICE_INTERFACE "org.tizen.system.dumpservice" + +#define DUMP_SIGNAL "Dump" +#define DUMP_START_SIGNAL "Start" +#define DUMP_FINISH_SIGNAL "Finish" + +#define NETWORK_LOG_PATH "/opt/usr/data/network" +#define KILLALL_EXEC_PATH "/usr/bin/killall" +#define TCPDUMP_EXEC_PATH "/usr/sbin/tcpdump" + +gboolean handle_start_tcpdump(Tcpdump *object, GDBusMethodInvocation *context); +gboolean handle_stop_tcpdump(Tcpdump *object, GDBusMethodInvocation *context); +gboolean handle_get_tcpdump_state(Tcpdump *object, GDBusMethodInvocation *context); +int netconfig_dump_log(const char *path); +void check_dump_state_and_start(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/util.h b/include/util.h index 299d8d3..cc8a1a8 100755 --- a/include/util.h +++ b/include/util.h @@ -55,6 +55,8 @@ int __netconfig_get_interface_index(const char *interface_name); int netconfig_execute_cmd(const char *cmd); int netconfig_execute_file(const char *file_path, char *const args[], char *const env[]); +int netconfig_execute_file_no_wait(const char *file_path, + char *const args[]); int netconfig_execute_clatd(const char *file_path, char *const args[]); int netconfig_add_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len); int netconfig_del_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len); diff --git a/include/wifi.h b/include/wifi.h index 3025156..84d030f 100755 --- a/include/wifi.h +++ b/include/wifi.h @@ -30,8 +30,8 @@ extern "C" { #include "generated-code.h" -#define WIFI_STORAGEDIR "/var/lib/misc/wifi" -#define WIFI_CERT_STORAGEDIR "/var/lib/misc/wifi/cert" +#define WIFI_STORAGEDIR "/var/lib/wifi" +#define WIFI_CERT_STORAGEDIR "/var/lib/wifi/cert" #define CONNMAN_STORAGEDIR "/var/lib/connman" void __netconfig_wifi_connect_reply(GObject *source_object, GAsyncResult *res, diff --git a/interfaces/netconfig-iface-network-state.xml b/interfaces/netconfig-iface-network-state.xml index f0000a3..41b65e0 100755 --- a/interfaces/netconfig-iface-network-state.xml +++ b/interfaces/netconfig-iface-network-state.xml @@ -46,4 +46,13 @@ + + + + + + + + + diff --git a/packaging/net-config.spec b/packaging/net-config.spec index 15ef805..4b1b85b 100755 --- a/packaging/net-config.spec +++ b/packaging/net-config.spec @@ -73,6 +73,7 @@ TIZEN Network Configuration service extension for telephony FW. cmake -DCMAKE_INSTALL_PREFIX=%{_prefix} \ -DTIZEN_WLAN_PASSPOINT=1 \ -DTIZEN_WLAN_USE_P2P_INTERFACE=1 \ + -DTIZEN_DEBUG_ENABLE=1 \ %if 0%{?model_build_feature_wlan_concurrent_mode} -DWLAN_CONCURRENT_MODE=1 \ %endif @@ -132,6 +133,12 @@ ln -s %{TZ_SYS_ETC}/resolv.conf %{buildroot}%{_sysconfdir}/resolv.conf mkdir -p %{buildroot}%{_sysconfdir}/dbus-1/system.d cp resources/etc/dbus-1/system.d/net-config.conf %{buildroot}%{_sysconfdir}/dbus-1/system.d/net-config.conf +#log dump +mkdir -p %{buildroot}/opt/etc/dump.d/module.d/ +cp resources/opt/etc/dump.d/module.d/network_dump.sh %{buildroot}/opt/etc/dump.d/module.d/network_dump.sh +mkdir -p %{buildroot}/opt/var/lib/net-config/ +cp resources/opt/etc/dump.d/module.d/network_dump.sh %{buildroot}/opt/var/lib/net-config/network_dump.sh + %if 0%{?model_build_feature_wlan_wearable} == 1 #softreset scripts mkdir -p %{buildroot}/usr/system/RestoreDir/softreset @@ -181,6 +188,8 @@ ln -sf %{_unitdir}/net-config.service %{_sysconfdir}/systemd/default-extra-depen %attr(644,root,root) %{_unitdir}/multi-user.target.wants/net-config.service %endif %license LICENSE +%attr(500,root,root) /opt/etc/dump.d/module.d/network_dump.sh +%attr(500,network_fw,network_fw) /opt/var/lib/net-config/network_dump.sh %if 0%{?model_build_feature_wlan_wearable} == 1 %attr(700,network_fw,network_fw) /usr/system/RestoreDir/softreset/network_softreset.sh %endif diff --git a/resources/etc/dbus-1/system.d/net-config.conf b/resources/etc/dbus-1/system.d/net-config.conf index dcef481..87d4161 100755 --- a/resources/etc/dbus-1/system.d/net-config.conf +++ b/resources/etc/dbus-1/system.d/net-config.conf @@ -23,6 +23,10 @@ + + + + diff --git a/resources/opt/etc/dump.d/module.d/network_dump.sh b/resources/opt/etc/dump.d/module.d/network_dump.sh new file mode 100755 index 0000000..cf46685 --- /dev/null +++ b/resources/opt/etc/dump.d/module.d/network_dump.sh @@ -0,0 +1,42 @@ +#!/bin/sh +PATH=/bin:/usr/bin:/sbin:/usr/sbin + +#-------------------------------------- +# network dump +#-------------------------------------- + +# not allow to use relative path +if [[ $1 == "/"* ]]; then + echo "Absolute path" +else + echo "Relative path" + exit -1 +fi + +export DISPLAY=:0.0 +NETWORK_DATA_DIR=/opt/usr/data/network +NETWORK_DEBUG=$1/network + +@BIN_DIR@/mkdir -p ${NETWORK_DEBUG} + +@BIN_DIR@/netstat -na > ${NETWORK_DEBUG}/netstat +@SBIN_DIR@/route -n > ${NETWORK_DEBUG}/route +@SBIN_DIR@/route -A inet6 -n > ${NETWORK_DEBUG}/route6 +@BIN_DIR@/cat /proc/net/wireless > ${NETWORK_DEBUG}/wireless +@BIN_DIR@/cat /etc/resolv.conf > ${NETWORK_DEBUG}/resolv.conf +@SBIN_DIR@/ifconfig -a > ${NETWORK_DEBUG}/ifconfig +/usr/sbin/iptables -L > ${NETWORK_DEBUG}/iptables +/usr/sbin/ip6tables -L > ${NETWORK_DEBUG}/ip6tables +@BIN_DIR@/cat /proc/net/tcp > ${NETWORK_DEBUG}/tcp +@BIN_DIR@/cat /proc/net/tcp6 > ${NETWORK_DEBUG}/tcp6 +@BIN_DIR@/cat /proc/net/route > ${NETWORK_DEBUG}/proc_route +@SBIN_DIR@/ip -4 rule > ${NETWORK_DEBUG}/ip4_rule +@SBIN_DIR@/ip -6 rule > ${NETWORK_DEBUG}/ip6_rule +@SBIN_DIR@/ip -4 route show table all > ${NETWORK_DEBUG}/ip4_route +@SBIN_DIR@/ip -6 route show table all > ${NETWORK_DEBUG}/ip6_route +/usr/bin/vconftool -r get memory/dnet >> ${NETWORK_DEBUG}/status +/usr/bin/vconftool -r get memory/wifi >> ${NETWORK_DEBUG}/status +/usr/bin/vconftool -r get file/private/wifi >> ${NETWORK_DEBUG}/status +/usr/bin/vconftool -r get db/wifi >> ${NETWORK_DEBUG}/status +@BIN_DIR@/mv ${NETWORK_DATA_DIR}/tcpdump*.pcap* ${NETWORK_DEBUG} +@BIN_DIR@/tar -czf ${NETWORK_DEBUG}/network_file_log.tar.gz -C ${NETWORK_DATA_DIR} . diff --git a/src/main.c b/src/main.c index 3e864b1..26451f6 100755 --- a/src/main.c +++ b/src/main.c @@ -38,6 +38,7 @@ #include "network-monitor.h" #include "signal-handler.h" #include "network-statistics.h" +#include "network-dump.h" static GMainLoop *main_loop = NULL; @@ -127,6 +128,9 @@ int main(int argc, char *argv[]) /* For device policy manager */ netconfig_dpm_init(); + /* Start tcpdump if dump state is on */ + check_dump_state_and_start(); + /*In case no emulator, set the ETH0 Mac address*/ if (TIZEN_TV && emulator_is_emulated() == FALSE) __netconfig_set_ether_macaddr(); diff --git a/src/network-dump.c b/src/network-dump.c new file mode 100755 index 0000000..ea4a416 --- /dev/null +++ b/src/network-dump.c @@ -0,0 +1,253 @@ +/* + * Network Configuration Module + * + * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include "log.h" + +#include "util.h" +#include "netdbus.h" +#include "neterror.h" +#include "network-dump.h" +#include + +#define NETWORK_DUMP_SCRIPT "/opt/var/lib/net-config/network_dump.sh" + +#define TCP_DUMP_IN_BOOT_TIME "/opt/usr/data/tcp_dump_mode" + +static gboolean tcpdump_running = FALSE; + +static const char *get_current_time(void) +{ + struct timeval mytime; + struct tm stTempTime; + static char time_string[128]; + + + struct tm { + int tm_sec; // Seconds + int tm_min; // Minutes + int tm_hour; // Hour (0--23) + int tm_mday; // Day of month (1--31) + int tm_mon; // Month (0--11) + int tm_year; // Year (calendar year minus 1900) + int tm_wday; // Weekday (0--6; Sunday = 0) + int tm_yday; // Day of year (0--365) + int tm_isdst; // 0 if daylight savings time is not in effect) + }; + + gettimeofday(&mytime, NULL); + localtime_r(&mytime.tv_sec, &stTempTime); + g_snprintf(time_string, 128, "%04d.%02d.%02d-%02d_%02d_%02d", + stTempTime.tm_year + 1900, stTempTime.tm_mon + 1, stTempTime.tm_mday, + stTempTime.tm_hour, stTempTime.tm_min, stTempTime.tm_sec); + time_string[127] = '\0'; + + return time_string; +} + +static int _start_dump(gchar *dump_path) +{ + int rv = 0; + gchar *path = NETWORK_DUMP_SCRIPT; + char *const args[] = { NETWORK_DUMP_SCRIPT, dump_path, NULL }; + char *const envs[] = { NULL }; + + rv = netconfig_execute_file(path, args, envs); + if (rv < 0) { + ERR("Fail to execute network log dump shell"); + return -EIO; + } + return 0; +} + +static gboolean _stop_tcpdump(void) +{ + int ret; + const char *path = KILLALL_EXEC_PATH; + char *const args[] = { KILLALL_EXEC_PATH, "tcpdump", NULL }; + char *const envs[] = { NULL }; + + if (!tcpdump_running) { + DBG("tcpdump is not running"); + return FALSE; + } + + ret = netconfig_execute_file(path, args, envs); + if (ret < 0) { + DBG("Failed to Kill tcpdump, ret : %d\n", ret); + return FALSE; + } + + tcpdump_running = FALSE; + + return TRUE; +} + +static gboolean _start_tcpdump(void) +{ + int ret; + const char *start_path = TCPDUMP_EXEC_PATH; + char filename[128] = { 0, }; + g_snprintf(filename, 128, "%s/tcpdump-%s.pcap", NETWORK_LOG_PATH, get_current_time()); + char *const start_args[] = { TCPDUMP_EXEC_PATH, + "-W", "5", "-C", "50", "-i", "any", "-s", "0", "-w", filename, NULL}; + + if (tcpdump_running) { + DBG("kill tcpdump."); + gboolean ret = _stop_tcpdump(); + if (!ret) + DBG("Failed to kill tcpdump.. ret : %d", ret); + } + + ret = netconfig_execute_file_no_wait(start_path, start_args); + if (ret < 0) { + DBG("Failed to start tcpdump, ret : %d", ret); + return FALSE; + } + + tcpdump_running = TRUE; + + return tcpdump_running; +} + +static gboolean _get_dump_state(void) +{ + int ret = access(TCP_DUMP_IN_BOOT_TIME, F_OK); + if (ret != 0) { + ERR("Dumpstate Get Failed (%d).", ret); + return FALSE; + } + + return TRUE; +} + +gboolean handle_start_tcpdump(Tcpdump *object, + GDBusMethodInvocation *context) +{ + gboolean ret = FALSE; + + ret = _start_tcpdump(); + if (!ret) { + netconfig_error_dbus_method_return(context, + NETCONFIG_ERROR_INTERNAL, "StartTCPDumpFailed"); + return TRUE; + } + + DBG("Successfully started tcpdump and running.."); + tcpdump_complete_start_tcpdump(object, context); + + return TRUE; +} + +gboolean handle_stop_tcpdump(Tcpdump *object, GDBusMethodInvocation *context) +{ + gboolean ret = FALSE; + + if (!tcpdump_running) { + DBG("tcpdump not running"); + tcpdump_complete_stop_tcpdump(object, context); + return TRUE; + } + + ret = _stop_tcpdump(); + if (!ret) { + netconfig_error_dbus_method_return(context, + NETCONFIG_ERROR_INTERNAL, "StopTCPDumpFailed"); + return TRUE; + } + + DBG("Successfully stopped tcpdump"); + tcpdump_complete_stop_tcpdump(object, context); + + return TRUE; +} + +gboolean handle_get_tcpdump_state(Tcpdump *object, GDBusMethodInvocation *context) +{ + DBG("tcpdump %s running", tcpdump_running ? "is" : "is not"); + + tcpdump_complete_get_tcpdump_state(object, context, tcpdump_running); + + return TRUE; +} + +static void _send_dump_signal(const gchar *sig_name) +{ + gboolean reply; + GVariant *params; + GDBusConnection *connection = NULL; + GError *error = NULL; + + connection = netdbus_get_connection(); + if (connection == NULL) { + DBG("GDBusconnection is NULL"); + return; + } + + params = g_variant_new("(i)", getpid()); + reply = g_dbus_connection_emit_signal(connection, + NULL, + DUMP_SERVICE_OBJECT_PATH, + DUMP_SERVICE_INTERFACE, + sig_name, + params, + &error); + if (reply != TRUE) { + if (error != NULL) { + ERR("Failed to send signal [%s]", error->message); + g_error_free(error); + } + return; + } +} + +int netconfig_dump_log(const char *path) +{ + gchar *dump_path = NULL; + + if (!path) { + ERR("path is NULL. Dump Fail"); + return -1; + } + ERR("Dump is started"); + _send_dump_signal(DUMP_START_SIGNAL); + + dump_path = g_strdup(path); + _start_dump(dump_path); + _stop_tcpdump(); + g_free(dump_path); + + _send_dump_signal(DUMP_FINISH_SIGNAL); + ERR("Dump is finished"); + return 0; +} + +void check_dump_state_and_start(void) +{ + if (!_get_dump_state()) + return; + + if (!_start_tcpdump()) { + ERR("Failed to start tcpdump"); + return; + } + DBG("Successfully started tcpdump and running.."); + +} diff --git a/src/network-state.c b/src/network-state.c index 794db9f..99b2d62 100755 --- a/src/network-state.c +++ b/src/network-state.c @@ -38,6 +38,9 @@ #include "network-dpm.h" #include "network-monitor.h" #include "netsupplicant.h" +#if defined TIZEN_DEBUG_ENABLE +#include "network-dump.h" +#endif #include "generated-code.h" /* Define TCP buffer sizes for various networks */ @@ -88,6 +91,9 @@ typedef struct { } net_profile_name_t; static Network *netconfigstate = NULL; +#if defined TIZEN_DEBUG_ENABLE +static Tcpdump *tcpdump_object = NULL; +#endif struct netconfig_default_connection { char *profile; @@ -1409,6 +1415,9 @@ void state_object_create_and_init(void) { DBG("Creating network state object"); GDBusInterfaceSkeleton *interface_network = NULL; +#if defined TIZEN_DEBUG_ENABLE + GDBusInterfaceSkeleton *interface_tcpdump = NULL; +#endif GDBusConnection *connection = NULL; GDBusObjectManagerServer *server = netdbus_get_state_manager(); if (server == NULL) @@ -1452,9 +1461,30 @@ void state_object_create_and_init(void) NETCONFIG_NETWORK_STATE_PATH, NULL)) { ERR("Export with path failed"); } + +#if defined TIZEN_DEBUG_ENABLE + /*Interface netconfig.tcpdump*/ + tcpdump_object = tcpdump_skeleton_new(); + + interface_tcpdump = G_DBUS_INTERFACE_SKELETON(tcpdump_object); + g_signal_connect(tcpdump_object, "handle-start-tcpdump", + G_CALLBACK(handle_start_tcpdump), NULL); + g_signal_connect(tcpdump_object, "handle-stop-tcpdump", + G_CALLBACK(handle_stop_tcpdump), NULL); + g_signal_connect(tcpdump_object, "handle-get-tcpdump-state", + G_CALLBACK(handle_get_tcpdump_state), NULL); + + if (!g_dbus_interface_skeleton_export(interface_tcpdump, connection, + NETCONFIG_NETWORK_STATE_PATH, NULL)) { + ERR("Export with path failed"); + } +#endif } void state_object_deinit(void) { g_object_unref(netconfigstate); +#if defined TIZEN_DEBUG_ENABLE + g_object_unref(tcpdump_object); +#endif } diff --git a/src/signal-handler.c b/src/signal-handler.c index a858856..f53b49a 100755 --- a/src/signal-handler.c +++ b/src/signal-handler.c @@ -39,6 +39,9 @@ #include "wifi-background-scan.h" #include "wifi-tdls.h" #include "ip-conflict-detect.h" +#if defined TIZEN_DEBUG_ENABLE +#include "network-dump.h" +#endif #define DBUS_SERVICE_DBUS "org.freedesktop.DBus" #define DBUS_INTERFACE_DBUS "org.freedesktop.DBus" @@ -91,6 +94,9 @@ static const char supplicant_signals[SIG_MAX][MAX_SIG_LEN] = { }; static int supp_subscription_ids[SIG_MAX] = {0}; +#if defined TIZEN_DEBUG_ENABLE +static int dumpservice_subscription_id = 0; +#endif typedef void (*supplicant_signal_cb)(GDBusConnection *conn, const gchar *name, const gchar *path, const gchar *interface, @@ -585,9 +591,14 @@ static void _supplicant_driver_hanged(GDBusConnection *conn, DBG("Driver Hanged handling!"); ERR("Critical. Wi-Fi firmware crashed"); +#if !defined TIZEN_WEARABLE + netconfig_send_message_to_net_popup("Wi-Fi Error", + "Wi-Fi Driver Hanged. Please get log dump and report", "popup", NULL); +#endif wifi_power_recover_firmware(); return; + } static void _supplicant_session_overlapped(GDBusConnection *conn, @@ -604,6 +615,28 @@ static void _supplicant_session_overlapped(GDBusConnection *conn, #endif } +#if defined TIZEN_DEBUG_ENABLE +static void __netconfig_dumpservice_handler(GDBusConnection *conn, + const gchar *name, const gchar *path, const gchar *interface, + const gchar *sig, GVariant *param, gpointer user_data) +{ + int mode; + gchar *signal_path = NULL; + + if (param == NULL) + return; + + g_variant_get(param, "(is)", &mode, &signal_path); + DBG("Path: %s and mode: %d", signal_path, mode); + + netconfig_dump_log(signal_path); + if (signal_path) + g_free(signal_path); + + return; +} +#endif + static void _supplicant_tdls_connected(GDBusConnection *conn, const gchar *name, const gchar *path, const gchar *interface, const gchar *sig, GVariant *param, gpointer user_data) @@ -941,6 +974,22 @@ void register_gdbus_signal(void) INFO("Successfully register Supplicant DBus signal filters"); +#if defined TIZEN_DEBUG_ENABLE + dumpservice_subscription_id = g_dbus_connection_signal_subscribe( + connection, + NULL, + DUMP_SERVICE_INTERFACE, + DUMP_SIGNAL, + NULL, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + __netconfig_dumpservice_handler, + NULL, + NULL); + + INFO("Successfully registered Dumpservice DBus signal filter"); +#endif + /* In case ConnMan precedes this signal register, * net-config should update the default connected profile. */ @@ -972,4 +1021,8 @@ void deregister_gdbus_signal(void) } } +#if defined TIZEN_DEBUG_ENABLE + g_dbus_connection_signal_unsubscribe(connection, + dumpservice_subscription_id); +#endif } diff --git a/src/utils/util.c b/src/utils/util.c index 762fe24..77c2d2d 100755 --- a/src/utils/util.c +++ b/src/utils/util.c @@ -160,7 +160,7 @@ void netconfig_start_timer(guint msecs, } if ((timer_id != NULL && *timer_id != 0)) { - DBG("timer already is registered"); + ERR("timer already is registered"); return; } @@ -531,6 +531,59 @@ int netconfig_execute_clatd(const char *file_path, char *const args[]) 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)); +} + +int netconfig_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; + + 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"); + 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(errno)); + return -1; + } + } else if (pid > 0) { + ERR("Successfully launched child process"); + return rv; + } + + DBG("failed to fork(%s)", strerror(errno)); + return -EIO; +} + int __netconfig_get_interface_index(const char *interface_name) { struct ifreq ifr;