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
--- /dev/null
+/*
+ * 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 <sys/time.h>
+
+#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
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);
#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,
<arg type="s" name="address" direction="out"/>
</method>
</interface>
+ <interface name="net.netconfig.tcpdump">
+ <method name="StartTCPDump">
+ </method>
+ <method name="StopTCPDump">
+ </method>
+ <method name="GetTCPDumpState">
+ <arg type="b" name="state" direction="out"/>
+ </method>
+ </interface>
</node>
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
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
%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
<allow send_destination="net.netconfig" send_interface="net.netconfig.wifi" send_member="SetIpConflictPeriod" />
<allow send_destination="net.netconfig" send_interface="net.netconfig.wifi" send_member="GetIpConflictPeriod" />
+ <allow send_destination="net.netconfig" send_interface="net.netconfig.tcpdump" send_member="StartTCPDump" />
+ <allow send_destination="net.netconfig" send_interface="net.netconfig.tcpdump" send_member="StopTCPDump" />
+ <allow send_destination="net.netconfig" send_interface="net.netconfig.tcpdump" send_member="CheckTCPDumpStatus" />
+
<check send_destination="net.netconfig" send_interface="net.netconfig.network" send_member="AddRoute" privilege="http://tizen.org/privilege/network.set" />
<check send_destination="net.netconfig" send_interface="net.netconfig.network" send_member="RemoveRoute" privilege="http://tizen.org/privilege/network.set" />
<check send_destination="net.netconfig" send_interface="net.netconfig.network" send_member="EthernetCableState" privilege="http://tizen.org/privilege/network.get" />
--- /dev/null
+#!/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} .
#include "network-monitor.h"
#include "signal-handler.h"
#include "network-statistics.h"
+#include "network-dump.h"
static GMainLoop *main_loop = NULL;
/* 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();
--- /dev/null
+/*
+ * 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 <glib.h>
+
+#include "log.h"
+
+#include "util.h"
+#include "netdbus.h"
+#include "neterror.h"
+#include "network-dump.h"
+#include <unistd.h>
+
+#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..");
+
+}
#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 */
} 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;
{
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)
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
}
#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"
};
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,
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,
#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)
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.
*/
}
}
+#if defined TIZEN_DEBUG_ENABLE
+ g_dbus_connection_signal_unsubscribe(connection,
+ dumpservice_subscription_id);
+#endif
}
}
if ((timer_id != NULL && *timer_id != 0)) {
- DBG("timer already is registered");
+ ERR("timer already is registered");
return;
}
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;