Add packet capture functions 13/193413/2
authorhyunuktak <hyunuk.tak@samsung.com>
Tue, 20 Nov 2018 08:44:09 +0000 (17:44 +0900)
committerhyunuktak <hyunuk.tak@samsung.com>
Thu, 29 Nov 2018 07:19:16 +0000 (16:19 +0900)
Change-Id: I287425157c7ca377a585e8b11e502a29c7b189b6
Signed-off-by: hyunuktak <hyunuk.tak@samsung.com>
16 files changed:
include/stc-manager-gdbus.h [changed mode: 0644->0755]
include/stc-manager-plugin-pcap.h [new file with mode: 0755]
include/stc-manager.h [changed mode: 0644->0755]
include/stc-pcap.h [new file with mode: 0755]
interfaces/CMakeLists.txt
interfaces/stcmanager-iface-pcap.xml [new file with mode: 0644]
packaging/stc-manager.spec
plugin/CMakeLists.txt
plugin/pcap/CMakeLists.txt [new file with mode: 0644]
plugin/pcap/include/stc-plugin-pcap.h [new file with mode: 0755]
plugin/pcap/stc-plugin-pcap.c [new file with mode: 0755]
src/CMakeLists.txt
src/stc-manager-gdbus.c [changed mode: 0644->0755]
src/stc-manager-plugin-pcap.c [new file with mode: 0644]
src/stc-manager.c [changed mode: 0644->0755]
src/stc-pcap.c [new file with mode: 0755]

old mode 100644 (file)
new mode 100755 (executable)
index 860b766..263077d
@@ -26,6 +26,7 @@
 #define STC_DBUS_SERVICE_STATISTICS_PATH   "/net/stc/statistics"
 #define STC_DBUS_SERVICE_RESTRICTION_PATH  "/net/stc/restriction"
 #define STC_DBUS_SERVICE_FIREWALL_PATH     "/net/stc/firewall"
+#define STC_DBUS_SERVICE_PCAP_PATH         "/net/stc/pcap"
 #define STC_DBUS_SERVICE_MANAGER_PATH      "/net/stc/manager"
 
 #define STC_DBUS_REPLY_ERROR_NONE(invocation) \
diff --git a/include/stc-manager-plugin-pcap.h b/include/stc-manager-plugin-pcap.h
new file mode 100755 (executable)
index 0000000..728004f
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 __STC_MANAGER_PLUGIN_PCAP_H__
+#define __STC_MANAGER_PLUGIN_PCAP_H__
+
+#define STC_PLUGIN_PCAP_FILEPATH               "/usr/lib/stc-plugin-pcap.so"
+
+#include "stc-plugin-pcap.h"
+
+int stc_plugin_pcap_init(void);
+int stc_plugin_pcap_deinit(void);
+
+int stc_plugin_pcap_lookup_dev(void);
+int stc_plugin_pcap_lookup_net(void);
+int stc_plugin_pcap_find_alldevs(void);
+int stc_plugin_pcap_register_loop_pcap(const char *ifname,
+                       int group);
+int stc_plugin_pcap_unregister_loop_pcap(const char *ifname,
+                       int group);
+
+#endif /* __STC_MANAGER_PLUGIN_PROCFS_H__ */
old mode 100644 (file)
new mode 100755 (executable)
index d1f4d93..fabbbb1
@@ -236,6 +236,7 @@ typedef struct {
        gpointer statistics_obj;
        gpointer restriction_obj;
        gpointer firewall_obj;
+       gpointer pcap_obj;
        gpointer manager_obj;
 
        GDBusObjectManagerServer *obj_mgr;
diff --git a/include/stc-pcap.h b/include/stc-pcap.h
new file mode 100755 (executable)
index 0000000..d99d450
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 __STC_PCAP_H__
+#define __STC_PCAP_H__
+
+#include <glib.h>
+#include "stc-manager.h"
+#include "stc-manager-gdbus.h"
+
+/*****************************************************************************
+ * Macros and Typedefs
+ *****************************************************************************/
+
+#define STC_PCAP_IFNAME             "ifname"
+#define STC_PCAP_NFLOG_GROUP        "nflog_group"
+
+typedef struct {
+    char *ifname;
+    int nflog_group;
+} stc_pcap_s;
+
+/*****************************************************************************
+ * Functions Declaration
+ *****************************************************************************/
+
+gboolean handle_pcap_start(StcPcap *object,
+                               GDBusMethodInvocation *invocation,
+                               GVariant *parameters,
+                               void *user_data);
+
+gboolean handle_pcap_stop(StcPcap *object,
+                               GDBusMethodInvocation *invocation,
+                               GVariant *parameters,
+                               void *user_data);
+
+#endif /* __STC_PCAP_H__ */
index 8f03ebf..dc26fa1 100644 (file)
@@ -10,6 +10,7 @@ ADD_CUSTOM_COMMAND(
                        ${INTERFACES}/stcmanager-iface-restriction.xml
                        ${INTERFACES}/stcmanager-iface-statistics.xml
                        ${INTERFACES}/stcmanager-iface-firewall.xml
+                       ${INTERFACES}/stcmanager-iface-pcap.xml
                        COMMENT "Generating GDBus .c/.h")
 
 ADD_CUSTOM_TARGET(GENERATED_DBUS_CODE DEPENDS dbus)
diff --git a/interfaces/stcmanager-iface-pcap.xml b/interfaces/stcmanager-iface-pcap.xml
new file mode 100644 (file)
index 0000000..4320ab6
--- /dev/null
@@ -0,0 +1,12 @@
+<node>
+       <interface name="net.stc.pcap">
+               <method name='Start'>
+                       <arg type='a{sv}' name='parameters' direction='in'/>
+                       <arg type='i' name='error_code' direction='out'/>
+               </method>
+               <method name='Stop'>
+                       <arg type='a{sv}' name='parameters' direction='in'/>
+                       <arg type='i' name='error_code' direction='out'/>
+               </method>
+       </interface>
+</node>
index b4a267a..b14ee3f 100644 (file)
@@ -57,6 +57,13 @@ Summary: STC manager exception proc file system plugin
 %description plugin-procfs
 A smart traffic control manager extension for proc file system plugin
 
+%package plugin-pcap
+Summary: STC manager exception packet capture plugin
+BuildRequires:  libpcap-devel
+
+%description plugin-pcap
+A smart traffic control manager extension for packet capture plugin
+
 %package plugin-tether
 Summary: Tethering plugin for data usage of tethering clients
 
@@ -154,6 +161,10 @@ cp resources/dbus/stc-manager.conf %{buildroot}%{_sysconfdir}/dbus-1/system.d/st
 %manifest %{name}.manifest
 %attr(500,root,root) %{_libdir}/stc-plugin-procfs.so
 
+%files plugin-pcap
+%manifest %{name}.manifest
+%attr(500,root,root) %{_libdir}/stc-plugin-pcap.so
+
 %files plugin-tether
 %manifest %{name}.manifest
 %attr(500,root,root) %{_libdir}/stc-plugin-tether.so
index e591d7a..04c53b8 100644 (file)
@@ -18,4 +18,5 @@ INCLUDE_DIRECTORIES(${MONITOR_SOURCE_DIR}/include)
 ADD_SUBDIRECTORY(appstatus)
 ADD_SUBDIRECTORY(exception)
 ADD_SUBDIRECTORY(procfs)
+ADD_SUBDIRECTORY(pcap)
 ADD_SUBDIRECTORY(tether)
diff --git a/plugin/pcap/CMakeLists.txt b/plugin/pcap/CMakeLists.txt
new file mode 100644 (file)
index 0000000..be4b022
--- /dev/null
@@ -0,0 +1,36 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(stc-plugin-pcap C)
+
+# Set required packages
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(pcap_plugin REQUIRED
+       dlog
+       gio-2.0
+       gio-unix-2.0
+       glib-2.0
+       )
+
+FOREACH(flag ${pcap_plugin_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -g -Werror -fvisibility=hidden")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_C_FLAGS_RELEASE "-O2")
+
+ADD_DEFINITIONS("-DUSE_DLOG")
+
+SET(SRCS_PLUGIN
+       stc-plugin-pcap.c
+       )
+
+# library build
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS_PLUGIN})
+ADD_DEPENDENCIES(${PROJECT_NAME} GENERATED_DBUS_CODE)
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pcap_plugin_LDFLAGS} -lpcap)
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES PREFIX "" OUTPUT_NAME ${PROJECT_NAME})
+
+# install
+INSTALL(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION ${LIBDIR})
diff --git a/plugin/pcap/include/stc-plugin-pcap.h b/plugin/pcap/include/stc-plugin-pcap.h
new file mode 100755 (executable)
index 0000000..a2b8c34
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 __STC_PLUGIN_PCAP_H__
+#define __STC_PLUGIN_PCAP_H__
+
+#include <glib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+#include <pcap.h>
+#include <arpa/inet.h>
+#include <net/ethernet.h>
+#include <net/if_arp.h>
+#include <netinet/ether.h>
+#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+
+#include "stc-error.h"
+#include "stc-manager.h"
+
+#define BUFF_SIZE_IP        16
+#define BUFF_SIZE_IP6       46
+#define BUFF_SIZE_HOST      32
+#define BUFF_SIZE_ID        64
+#define BUFF_SIZE_TIME      64
+#define BUFF_SIZE_NAME      256
+
+#define PORT_FTP_DATA       20
+#define PORT_FTP_CTL        21
+#define PORT_SMTP           25
+#define PORT_DNS            53
+#define PORT_BOOTP_S        67
+#define PORT_BOOTP_C        68
+#define PORT_HTTP           80
+#define PORT_NTP            123
+#define PORT_HTTPS          443
+#define PORT_SMTP_MSG       587
+
+#define ARP_REQUEST         1
+#define ARP_REPLY           2
+#define ARP_RREQUEST        3
+#define ARP_RREPLY          4
+
+#define BOOTP_REQUEST       1
+#define BOOTP_REPLY         2
+
+#define BOOTP_CHADDR_LEN    16
+#define BOOTP_SNAME_LEN     64
+#define BOOTP_FILE_LEN      128
+#define BOOTP_MOPTION_LEN   60
+
+#define BOOTP_MAGIC_DHCP    0x63825363
+
+#define DHCP_TAG_SUBNET_MASK         1
+#define DHCP_TAG_ROUTER              3
+#define DHCP_TAG_DNS                 6
+#define DHCP_TAG_HOST_NAME           12
+#define DHCP_TAG_REQUESTED_IP        50
+#define DHCP_TAG_IP_LEASE_TIME       51
+#define DHCP_TAG_MSG_TYPE            53
+#define DHCP_TAG_SERVER_ID           54
+#define DHCP_TAG_MSG_SIZE            57
+#define DHCP_TAG_CLIENT_ID           61
+#define DHCP_TAG_END                 255
+
+#define DHCP_MSG_TYPE_DISCOVER       1
+#define DHCP_MSG_TYPE_OFFER          2
+#define DHCP_MSG_TYPE_REQUEST        3
+#define DHCP_MSG_TYPE_DECLINE        4
+#define DHCP_MSG_TYPE_ACK            5
+#define DHCP_MSG_TYPE_NAK            6
+#define DHCP_MSG_TYPE_RELEASE        7
+#define DHCP_MSG_TYPE_INFORM         8
+
+#define DHCP_CLIENT_ID_ETHERNET      1
+#define DHCP_CLIENT_ID_IEEE802       2
+#define DHCP_CLIENT_ID_ARCNET        7
+#define DHCP_CLIENT_ID_LOCALTALK     11
+#define DHCP_CLIENT_ID_LOCALNET      12
+#define DHCP_CLIENT_ID_SMDS          14
+#define DHCP_CLIENT_ID_FRAMERELAY    15
+#define DHCP_CLIENT_ID_ATM1          16
+#define DHCP_CLIENT_ID_HDLC          17
+#define DHCP_CLIENT_ID_FIBRECHANNEL  18
+#define DHCP_CLIENT_ID_ATM2          19
+#define DHCP_CLIENT_ID_SERIALLINE    20
+
+#define NTP_STRATUM_UNSPECIFIED      0
+#define NTP_STRATUM_PRIM_REF         1
+#define NTP_STRATUM_INFO_QUERY       62
+#define NTP_STRATUM_INFO_REPLY       63
+
+#define        NTP_JAN_1970                 2208988800U /* 1970 - 1900 in seconds */
+
+#define DNS_QTYPE_A                  1
+#define DNS_QTYPE_CNAME              5
+#define DNS_QTYPE_AAAA               28
+
+#define DNS_QCLASS_IN                1
+#define DNS_QCLASS_CHAOS             3
+#define DNS_QCLASS_HS                4
+#define DNS_QCLASS_ANY               255
+
+typedef struct {
+       char *name;
+       int group;
+       GThread *thread;
+       pcap_t *handle;
+} stc_pcap_data_s;
+
+typedef struct {
+       uint16_t id;
+       uint16_t flags;
+       uint16_t questions;
+       uint16_t answerRR;
+       uint16_t authorityRR;
+       uint16_t additionalRR;
+} dns_t;
+
+typedef struct {
+       uint16_t type;
+       uint16_t class;
+} dns_query_t;
+
+typedef struct {
+       uint16_t type;
+       uint16_t class;
+       uint16_t ttl;
+       uint16_t rdlen;
+       char rdata[];
+} dns_recode_t;
+
+typedef struct {
+       uint8_t op;                             /* packet opcode type */
+       uint8_t htype;                          /* hardware addr type */
+       uint8_t hlen;                           /* hardware addr length */
+       uint8_t hops;                           /* gateway hops */
+       uint32_t xid;                           /* transaction ID */
+       uint16_t secs;                          /* seconds since boot began */
+       uint16_t flags;                         /* flags */
+       struct in_addr ciaddr;                  /* client IP address */
+       struct in_addr yiaddr;                  /* 'your' IP address */
+       struct in_addr siaddr;                  /* server IP address */
+       struct in_addr giaddr;                  /* gateway(relay agent) IP address */
+       uint8_t chaddr[BOOTP_CHADDR_LEN];       /* client hardware address */
+       uint8_t sname[BOOTP_SNAME_LEN];         /* server host name */
+       uint8_t file[BOOTP_FILE_LEN];           /* boot file name */
+       uint32_t magic;                         /* must be 0x63825363 (network order) */
+       uint8_t moption[BOOTP_MOPTION_LEN];
+} bootp_t;
+
+typedef struct {
+       uint16_t second;
+       uint16_t fraction;
+} ntp_short_t;
+
+typedef struct {
+       uint32_t second;
+       uint32_t fraction;
+} ntp_long_t;
+
+typedef struct {
+       uint8_t flags;                          /* Mode, version and leap indicator */
+       uint8_t stratum;                        /* Stratum details */
+       uint8_t poll;                           /* Maximum interval in log2 seconds */
+       uint8_t precision;                      /* Clock precision in log2 seconds */
+       ntp_short_t rootdelay;                  /* Root delay */
+       ntp_short_t rootdisp;                   /* Root dispersion */
+       uint32_t refid;                         /* Reference ID */
+       ntp_long_t reftime;                     /* Reference timestamp */
+       ntp_long_t orgtime;                     /* Origin timestamp */
+       ntp_long_t rectime;                     /* Receive timestamp */
+       ntp_long_t xmttime;                     /* Transmit timestamp */
+} ntp_t;
+
+typedef struct ether_header    eth_t;
+typedef struct ip              ip_t;
+typedef struct ip6_hdr         ip6_t;
+typedef struct arphdr          arp_t;
+typedef struct icmphdr         icmp_t;
+typedef struct tcphdr          tcp_t;
+typedef struct udphdr          udp_t;
+
+#define SIZE_ETHER_HEADER      sizeof(eth_t)
+#define SIZE_IP_HEADER         sizeof(ip_t)
+#define SIZE_ARP_HEADER        sizeof(arp_t)
+#define SIZE_ICMP_HEADER       sizeof(icmp_t)
+#define SIZE_TCP_HEADER        sizeof(tcp_t)
+#define SIZE_UDP_HEADER        sizeof(udp_t)
+#define SIZE_DNS_HEADER        sizeof(dns_t)
+
+#define IS_SRC_OR_DST_PORT(p) (source == (p) || dest == (p))
+
+typedef struct {
+       int (*initialize_plugin) (void);
+       int (*deinitialize_plugin) (void);
+       int (*lookup_dev) (void);
+       int (*lookup_net) (void);
+       int (*find_alldevs) (void);
+       int (*register_loop_pcap) (const char *ifname, int group);
+       int (*unregister_loop_pcap) (const char *ifname, int group);
+} stc_plugin_pcap_s;
+
+#endif /* __STC_PLUGIN_PCAP_H__ */
diff --git a/plugin/pcap/stc-plugin-pcap.c b/plugin/pcap/stc-plugin-pcap.c
new file mode 100755 (executable)
index 0000000..8cba6bd
--- /dev/null
@@ -0,0 +1,1329 @@
+/*
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * 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 "stc-plugin-pcap.h"
+
+//LCOV_EXCL_START
+static GHashTable *g_pcap_tables = NULL;
+static bool g_pcap_start_fm = false;
+static struct timeval g_pcap_tv = { 0, };
+
+static void __pcap_data_free(gpointer value)
+{
+       stc_pcap_data_s *data = (stc_pcap_data_s *)value;
+
+       g_thread_unref(data->thread);
+
+       FREE(data->name);
+       FREE(data);
+}
+
+/*
+static void __pcap_data_info(const u_char *packet, int len)
+{
+       GString *data;
+
+       data = g_string_sized_new(len);
+       if (data == NULL)
+               return;
+
+       while(len--)
+               g_string_append_printf(data, "%02x", *(packet++));
+
+       STC_LOGD("[%s]", g_string_free(data, FALSE));
+}
+*/
+
+static void __pcap_ntp_time_info(uint32_t s, char *time)
+{
+       time_t seconds; 
+       char *curr = NULL;
+       int len = 0;
+       uint32_t sec = ntohl(s);
+
+       if (sec) {
+               seconds = sec - NTP_JAN_1970;
+               curr = ctime(&seconds);
+               len = strlen(curr);
+               curr[len - 1] = '\0';
+
+               snprintf(time, len, "%s", curr);
+       } else {
+               snprintf(time, 10, "00:00:00");
+       }
+}
+
+static void __pcap_ntp_refid_info(ntp_t *ntp_h, char *refid)
+{
+       switch (ntp_h->stratum) {
+       case NTP_STRATUM_UNSPECIFIED:
+               snprintf(refid, BUFF_SIZE_ID, "%s", "(unspec)");
+               break;
+       case NTP_STRATUM_PRIM_REF:
+               snprintf(refid, BUFF_SIZE_ID, "%s", "(prim_ref)");
+               break;
+       case NTP_STRATUM_INFO_QUERY:
+               snprintf(refid, BUFF_SIZE_ID, "%s INFO_QEURY",
+                       inet_ntoa(*((struct in_addr *)&ntp_h->refid)));
+               break;
+       case NTP_STRATUM_INFO_REPLY:
+               snprintf(refid, BUFF_SIZE_ID, "%s INFO_REPLY",
+                       inet_ntoa(*((struct in_addr *)&ntp_h->refid)));
+               break;
+       default:
+               snprintf(refid, BUFF_SIZE_ID, "%s",
+                       inet_ntoa(*((struct in_addr *)&ntp_h->refid)));
+               break;
+       }
+}
+
+static uint16_t __pcap_ntp_fraction_info(uint16_t f)
+{
+       uint16_t fraction;
+       double ff;
+
+       ff = ntohs(f) / 65536.0;
+       fraction = (uint16_t)(ff * 1000000.0);
+
+       return fraction;
+}
+
+static void __pcap_ntp_info(const u_char *packet)
+{
+       ntp_t *ntp_h = (ntp_t *)(packet +
+               SIZE_ETHER_HEADER + SIZE_IP_HEADER + SIZE_UDP_HEADER);
+       char refid[BUFF_SIZE_ID];
+       char reftime[BUFF_SIZE_TIME];
+       char orgtime[BUFF_SIZE_TIME];
+       char rectime[BUFF_SIZE_TIME];
+       char xmttime[BUFF_SIZE_TIME];
+
+       __pcap_ntp_refid_info(ntp_h, refid);
+       __pcap_ntp_time_info(ntp_h->reftime.second, reftime);
+       __pcap_ntp_time_info(ntp_h->orgtime.second, orgtime);
+       __pcap_ntp_time_info(ntp_h->rectime.second, rectime);
+       __pcap_ntp_time_info(ntp_h->xmttime.second, xmttime);
+
+       STC_LOGD("Flags[0x%02x] Stratum[%u] Poll[%u:%us] Precision[%u] "
+               "Root delay[%u.%06us] Root dispersion[%u.%06us] Ref ID[%s]",
+               ntp_h->flags, ntp_h->stratum, ntp_h->poll,
+               ntp_h->precision, 1 << ntp_h->precision,
+               ntohs(ntp_h->rootdelay.second),
+               __pcap_ntp_fraction_info(ntp_h->rootdelay.fraction),
+               ntohs(ntp_h->rootdisp.second),
+               __pcap_ntp_fraction_info(ntp_h->rootdisp.fraction),
+               refid);
+
+       STC_LOGD("Reference[%s] Origin[%s] Receive[%s] Transmit[%s]",
+               reftime, orgtime, rectime, xmttime);
+}
+
+static const char *__pcap_dhcp_client_id_info(uint8_t data)
+{
+       char *info = NULL;
+
+       switch (data) {
+       case DHCP_CLIENT_ID_ETHERNET:
+               info = "Ethernet";
+               break;
+       case DHCP_CLIENT_ID_IEEE802:
+               info = "IEEE 802 Networks";
+               break;
+       case DHCP_CLIENT_ID_ARCNET:
+               info = "ARCNET";
+               break;
+       case DHCP_CLIENT_ID_LOCALTALK:
+               info = "LocalTalk";
+               break;
+       case DHCP_CLIENT_ID_LOCALNET:
+               info = "LocalNet";
+               break;
+       case DHCP_CLIENT_ID_SMDS:
+               info = "SMDS";
+               break;
+       case DHCP_CLIENT_ID_FRAMERELAY:
+               info = "Frame Relay";
+               break;
+       case DHCP_CLIENT_ID_ATM1:
+               info = "ATM(Async Transfer Mode)";
+               break;
+       case DHCP_CLIENT_ID_HDLC:
+               info = "HDLC";
+               break;
+       case DHCP_CLIENT_ID_FIBRECHANNEL:
+               info = "Fibre Channel";
+               break;
+       case DHCP_CLIENT_ID_ATM2:
+               info = "ATM(Async Transfer Mode)";
+               break;
+       case DHCP_CLIENT_ID_SERIALLINE:
+               info = "Serial Line";
+               break;
+       default:
+               info = "Unknown";
+               break;
+       }
+
+       return info;
+}
+
+static const char *__pcap_dhcp_msg_type_info(uint8_t type)
+{
+       char *info = NULL;
+
+       switch (type) {
+       case DHCP_MSG_TYPE_DISCOVER:
+               info = "Discover";
+               break;
+       case DHCP_MSG_TYPE_OFFER:
+               info = "Offer";
+               break;
+       case DHCP_MSG_TYPE_REQUEST:
+               info = "Request";
+               break;
+       case DHCP_MSG_TYPE_DECLINE:
+               info = "Decline";
+               break;
+       case DHCP_MSG_TYPE_ACK:
+               info = "ACK";
+               break;
+       case DHCP_MSG_TYPE_NAK:
+               info = "NAK";
+               break;
+       case DHCP_MSG_TYPE_RELEASE:
+               info = "Release";
+               break;
+       case DHCP_MSG_TYPE_INFORM:
+               info = "Inform";
+               break;
+       default:
+               info = "Unknown";
+               break;
+       }
+
+       return info;
+}
+
+static void __pcap_bootp_magic_info(uint32_t magic,
+                                       uint8_t *moption, u_int16_t len)
+{
+       if (ntohl(magic) == BOOTP_MAGIC_DHCP) {
+               char buf[BOOTP_MOPTION_LEN];
+               uint8_t *opt = moption;
+
+               STC_LOGD("Magic cookie[DHCP]");
+
+               while(len > 0) {
+                       uint8_t tag = opt[0];
+                       uint8_t length = opt[1];
+                       uint8_t *data = &opt[2];
+                       char addr[BUFF_SIZE_IP];
+                       char host[BUFF_SIZE_HOST];
+
+                       switch (tag) {
+                       case DHCP_TAG_SUBNET_MASK:
+                               inet_ntop(AF_INET, (struct in_addr *)data,
+                                       addr, BUFF_SIZE_IP);
+                               STC_LOGD("Subnet mask[%s]", addr);
+                               break;
+                       case DHCP_TAG_ROUTER:
+                               inet_ntop(AF_INET, (struct in_addr *)data,
+                                       addr, BUFF_SIZE_IP);
+                               STC_LOGD("Router[%s]", addr);
+                               break;
+                       case DHCP_TAG_DNS:
+                               inet_ntop(AF_INET, (struct in_addr *)data,
+                                       addr, BUFF_SIZE_IP);
+                               STC_LOGD("Domain name server[%s]", addr);
+                               break;
+                       case DHCP_TAG_HOST_NAME:
+                               snprintf(buf, ((length < BOOTP_MOPTION_LEN) ?
+                                               (length + 1) : BOOTP_MOPTION_LEN), "%s", (char *)data);
+                               STC_LOGD("Host name[%s]", buf);
+                               break;
+                       case DHCP_TAG_REQUESTED_IP:
+                               inet_ntop(AF_INET, (struct in_addr *)data,
+                                       addr, BUFF_SIZE_IP);
+                               STC_LOGD("Requested IP[%s]", addr);
+                               break;
+                       case DHCP_TAG_IP_LEASE_TIME:
+                               STC_LOGD("IP address lease time[%us]",
+                                       ntohl(*(uint32_t *)data));
+                               break;
+                       case DHCP_TAG_MSG_TYPE:
+                               STC_LOGD("DHCP message type[%u:%s]", *data,
+                                       __pcap_dhcp_msg_type_info(*data));
+                               break;
+                       case DHCP_TAG_SERVER_ID:
+                               inet_ntop(AF_INET, (struct in_addr *)data,
+                                       addr, BUFF_SIZE_IP);
+                               STC_LOGD("DHCP server identifier[%s]", addr);
+                               break;
+                       case DHCP_TAG_MSG_SIZE:
+                               STC_LOGD("Maximum DHCP message size[%u]",
+                                       ntohs(*(uint16_t *)data));
+                               break;
+                       case DHCP_TAG_CLIENT_ID:
+                               STC_LOGD("Client identifier HW type[0x%02x:%s]", *data,
+                                       __pcap_dhcp_client_id_info(*data));
+                               if (*data == DHCP_CLIENT_ID_ETHERNET) {
+                                       g_strlcpy(host,
+                                               ether_ntoa((const struct ether_addr *)&data[1]),
+                                               sizeof(host));
+                                       STC_LOGD("Client identifier MAC[%s]", host);
+                               }
+                               break;
+                       case DHCP_TAG_END:
+                               STC_LOGD("End");
+                               return;
+                       default:
+                               STC_LOGD("Unknown[%u]", tag);
+                               break;
+                       }
+
+                       opt += (2 + length);
+                       len -= (2 + length);
+               }
+       }
+}
+
+static const char *__pcap_bootp_op_info(uint8_t op)
+{
+       char *info = NULL;
+
+       switch (op) {
+       case BOOTP_REQUEST:
+               info = "Request";
+               break;
+       case BOOTP_REPLY:
+               info = "Reply";
+               break;
+       default:
+               info = "Unknown";
+               break;
+       }
+
+       return info;
+}
+
+static void __pcap_bootp_info(const u_char *packet)
+{
+       udp_t *udp_h = (udp_t *)(packet
+               + SIZE_ETHER_HEADER + SIZE_IP_HEADER);
+       bootp_t *bootp_h = (bootp_t *)(packet +
+               SIZE_ETHER_HEADER + SIZE_IP_HEADER + SIZE_UDP_HEADER);
+       char ciaddr[BUFF_SIZE_IP];
+       char yiaddr[BUFF_SIZE_IP];
+       char siaddr[BUFF_SIZE_IP];
+       char giaddr[BUFF_SIZE_IP];
+       char chaddr[BUFF_SIZE_HOST];
+       u_int16_t len;
+
+       inet_ntop(AF_INET, &bootp_h->ciaddr, ciaddr, BUFF_SIZE_IP);
+       inet_ntop(AF_INET, &bootp_h->yiaddr, yiaddr, BUFF_SIZE_IP);
+       inet_ntop(AF_INET, &bootp_h->siaddr, siaddr, BUFF_SIZE_IP);
+       inet_ntop(AF_INET, &bootp_h->giaddr, giaddr, BUFF_SIZE_IP);
+
+       g_strlcpy(chaddr,
+               ether_ntoa((const struct ether_addr *)bootp_h->chaddr),
+               sizeof(chaddr));
+
+       STC_LOGD("Message type[%u:%s] HW type[0x%02x] HW len[%u] Hops[%u] "
+               "Transaction ID[0x%08x] Seconds elapsed[%u] Flags[0x%04x]",
+               bootp_h->op, __pcap_bootp_op_info(bootp_h->op),
+               bootp_h->htype, bootp_h->hlen, bootp_h->hops,
+               ntohl(bootp_h->xid), ntohs(bootp_h->secs), ntohs(bootp_h->flags));
+
+       STC_LOGD("Client[%s] Your(client)[%s] Next server[%s] "
+               "Relay agent[%s] Client MAC[%s]",
+               ciaddr, yiaddr, siaddr, giaddr, chaddr);
+
+       len = ntohs(udp_h->len);
+       __pcap_bootp_magic_info(bootp_h->magic, bootp_h->moption, len);
+}
+
+static char *__pcap_dns_type_info(uint16_t type)
+{
+       char *info = NULL;
+
+       switch (type) {
+       case DNS_QTYPE_A:
+               info = "A";
+               break;
+       case DNS_QTYPE_CNAME:
+               info = "CNAME";
+               break;
+       case DNS_QTYPE_AAAA:
+               info = "AAAA";
+               break;
+       default:
+               info = "Unknown";
+               break;
+       }
+
+       return info;
+}
+
+static char *__pcap_dns_class_info(uint16_t class)
+{
+       char *info = NULL;
+
+       switch (class) {
+       case DNS_QCLASS_IN:
+               info = "IN";
+               break;
+       case DNS_QCLASS_CHAOS:
+               info = "CHAOS";
+               break;
+       case DNS_QCLASS_HS:
+               info = "HS";
+               break;
+       case DNS_QCLASS_ANY:
+               info = "ANY";
+               break;
+       default:
+               info = "Unknown";
+               break;
+       }
+
+       return info;
+}
+
+static uint8_t * __pcap_dns_name_info(uint8_t *dns_h,
+                               uint8_t *data, u_char *name)
+{
+       uint8_t *sec = data;
+       u_char *dname = name;
+       uint8_t *nxt = NULL;
+
+       *name = '\0';
+       while (1) {
+               if ((*sec & 0xC0)) {
+                       nxt = sec + 2;
+                       sec = (uint8_t *)dns_h +
+                               (htons(*(uint16_t *)sec) & 0x3FFF);
+               } else {
+                       if (*sec == 0) {
+                               *dname = '\0';
+                               sec += 1;
+                               break;
+                       }
+
+                       if (dname - name + *sec + 1 > BUFF_SIZE_NAME - 1) {
+                               *name = '\0';
+                               return NULL;
+                       }
+
+                       memcpy(dname, sec + 1, *sec);
+                       dname += *sec;
+                       sec += *sec + 1;
+                       *dname = '.';
+                       dname++;
+               }
+       }
+
+       *(--dname) = '\0';
+
+       if (nxt == NULL)
+               nxt = sec;
+
+       return (uint8_t *)nxt;
+}
+
+static void __pcap_dns_data_info(const u_char *packet)
+{
+       dns_t *dns_h = (dns_t *)(packet +
+               SIZE_ETHER_HEADER + SIZE_IP_HEADER +
+               SIZE_UDP_HEADER);
+       uint8_t *data = (uint8_t *)(packet +
+               SIZE_ETHER_HEADER + SIZE_IP_HEADER +
+               SIZE_UDP_HEADER + SIZE_DNS_HEADER);
+       uint16_t qdcount = ntohs(dns_h->questions);
+       uint16_t ancount = ntohs(dns_h->answerRR);
+       int i = 0;
+
+       for (i = 0; i < qdcount; ++i) {
+               u_char name[BUFF_SIZE_NAME];
+               uint16_t type;
+               uint16_t class;
+
+               if (i == 0)
+                       STC_LOGD("[Queries]");
+
+               data = __pcap_dns_name_info((uint8_t *)dns_h, data, name);
+               if (data == NULL)
+                       return;
+
+               type = ntohs(*(uint16_t *)&data[0]);
+               class = ntohs(*(uint16_t *)&data[2]);
+
+               STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s]",
+                       name, type, __pcap_dns_type_info(type),
+                       class, __pcap_dns_class_info(class));
+
+               data += 4;
+       }
+
+       for (i = 0; i < ancount; ++i) {
+               u_char name[BUFF_SIZE_NAME];
+               u_char cname[BUFF_SIZE_NAME];
+               uint16_t type;
+               uint16_t class;
+               uint32_t ttl;
+               uint16_t length;
+               char ip[BUFF_SIZE_IP];
+
+               if (i == 0)
+                       STC_LOGD("[Answers]");
+
+               data = __pcap_dns_name_info((uint8_t *)dns_h, data, name);
+               if (data == NULL)
+                       return;
+
+               type = ntohs(*(uint16_t *)&data[0]);
+               class = ntohs(*(uint16_t *)&data[2]);
+               ttl = ntohl(*(uint32_t *)&data[4]);
+               length = ntohs(*(uint16_t *)&data[8]);
+
+               if (class == DNS_QCLASS_IN) {
+                       switch (type) {
+                       case DNS_QTYPE_A:
+                               inet_ntop(AF_INET, (struct in_addr *)&data[10],
+                                       ip, BUFF_SIZE_IP);
+                               STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s] "
+                                       "TTL[%u] Data length[%u] Address[%s]",
+                                       name, type, __pcap_dns_type_info(type),
+                                       class, __pcap_dns_class_info(class),
+                                       ttl, length, ip);
+                               break;
+                       case DNS_QTYPE_CNAME:
+                               __pcap_dns_name_info((uint8_t *)dns_h, &data[10], cname);
+                               if (data == NULL)
+                                       return;
+                               STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s] "
+                                       "TTL[%u] Data length[%u] CName[%s]",
+                                       name, type, __pcap_dns_type_info(type),
+                                       class, __pcap_dns_class_info(class),
+                                       ttl, length, cname);
+                               break;
+                       case DNS_QTYPE_AAAA:
+                               break;
+                       default:
+                               STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s] "
+                                       "TTL[%u] Data length[%u]",
+                                       name, type, __pcap_dns_type_info(type),
+                                       class, __pcap_dns_class_info(class),
+                                       ttl, length);
+                               break;
+                       }
+               }
+
+               data += (length + 10);
+       }
+}
+
+static void __pcap_dns_info(const u_char *packet)
+{
+       dns_t *dns_h = (dns_t *)(packet +
+               SIZE_ETHER_HEADER + SIZE_IP_HEADER + SIZE_UDP_HEADER);
+
+       STC_LOGD("Transaction ID[0x%x] Flags[0x%x] Questions[%u] "
+               "Answer RRs[%u] Authority RRs[%u] Additional RRs[%u]",
+               ntohs(dns_h->id), ntohs(dns_h->flags),
+               ntohs(dns_h->questions), ntohs(dns_h->answerRR),
+               ntohs(dns_h->authorityRR), ntohs(dns_h->additionalRR));
+
+       __pcap_dns_data_info(packet);
+}
+
+static const char *__pcap_icmp_code_info(u_int8_t type, u_int8_t code)
+{
+       char *info = NULL;
+
+       switch (type) {
+       case ICMP_DEST_UNREACH:
+               switch (code) {
+               case ICMP_NET_UNREACH:
+                       info = "Network Unreachable";
+                       break;
+               case ICMP_HOST_UNREACH:
+                       info = "Host Unreachable";
+                       break;
+               case ICMP_PROT_UNREACH:
+                       info = "Protocol Unreachable";
+                       break;
+               case ICMP_PORT_UNREACH:
+                       info = "Port Unreachable";
+                       break;
+               case ICMP_FRAG_NEEDED:
+                       info = "Fragmentation Needed/DF set";
+                       break;
+               case ICMP_SR_FAILED:
+                       info = "Source Route failed";
+                       break;
+               case ICMP_NET_UNKNOWN:
+                       break;
+               case ICMP_HOST_UNKNOWN:
+                       break;
+               case ICMP_HOST_ISOLATED:
+                       break;
+               case ICMP_NET_ANO:
+                       break;
+               case ICMP_HOST_ANO:
+                       break;
+               case ICMP_NET_UNR_TOS:
+                       break;
+               case ICMP_HOST_UNR_TOS:
+                       break;
+               case ICMP_PKT_FILTERED:
+                       info = "Packet filtered";
+                       break;
+               case ICMP_PREC_VIOLATION:
+                       info = "Precedence violation";
+                       break;
+               case ICMP_PREC_CUTOFF:
+                       info = "Precedence cut off";
+                       break;
+               default:
+                       info = "Unknown";
+                       break;
+               }
+               break;
+       case ICMP_REDIRECT:
+               switch (code) {
+               case ICMP_REDIR_NET:
+                       info = "Redirect Net";
+                       break;
+               case ICMP_REDIR_HOST:
+                       info = "Redirect Host";
+                       break;
+               case ICMP_REDIR_NETTOS:
+                       info = "Redirect Net for TOS";
+                       break;
+               case ICMP_REDIR_HOSTTOS:
+                       info = "Redirect Host for TOS";
+                       break;
+               default:
+                       info = "Unknown";
+                       break;
+               }
+               break;
+       case ICMP_TIME_EXCEEDED:
+               switch (code) {
+               case ICMP_EXC_TTL:
+                       info = "TTL count exceeded";
+                       break;
+               case ICMP_EXC_FRAGTIME:
+                       info = "Fragment Reass time exceeded";
+                       break;
+               default:
+                       info = "Unknown";
+                       break;
+               }
+               break;
+       default:
+               info = "Unknown";
+               break;
+       }
+
+       return info;
+}
+
+static const char *__pcap_icmp_type_info(u_int8_t type)
+{
+       char *info = NULL;
+
+       switch (type) {
+       case ICMP_ECHOREPLY:
+               info = "Echo Reply";
+               break;
+       case ICMP_DEST_UNREACH:
+               info = "Destination Unreachable";
+               break;
+       case ICMP_SOURCE_QUENCH:
+               info = "Source Quench";
+               break;
+       case ICMP_REDIRECT:
+               info = "Redirect";
+               break;
+       case ICMP_ECHO:
+               info = "Echo Request";
+               break;
+       case ICMP_TIME_EXCEEDED:
+               info = "Time Exceeded";
+               break;
+       case ICMP_PARAMETERPROB:
+               info = "Parameter Problem";
+               break;
+       case ICMP_TIMESTAMP:
+               info = "Timestamp Request";
+               break;
+       case ICMP_TIMESTAMPREPLY:
+               info = "Timestamp Reply";
+               break;
+       case ICMP_INFO_REQUEST:
+               info = "Information Request";
+               break;
+       case ICMP_INFO_REPLY:
+               info = "Information Reply";
+               break;
+       case ICMP_ADDRESS:
+               info = "Address Mask Request";
+               break;
+       case ICMP_ADDRESSREPLY:
+               info = "Address Mask Reply";
+               break;
+       default:
+               info = "Unknown";
+               break;
+       }
+
+       return info;
+}
+
+static void __pcap_icmp_info(const u_char *packet)
+{
+       icmp_t *icmp_h = (icmp_t *)(packet +
+               SIZE_ETHER_HEADER + SIZE_IP_HEADER);
+
+       STC_LOGD("Type[%u:%s] Code[%u:%s] Checksum[0x%x]",
+               icmp_h->type, __pcap_icmp_type_info(icmp_h->type),
+               icmp_h->code, __pcap_icmp_code_info(icmp_h->type, icmp_h->code),
+               ntohs(icmp_h->checksum));
+}
+
+static void __pcap_tcp_info(const u_char *packet)
+{
+       tcp_t *tcp_h = (tcp_t *)(packet +
+               SIZE_ETHER_HEADER + SIZE_IP_HEADER);
+       u_int16_t source = ntohs(tcp_h->source);
+       u_int16_t dest = ntohs(tcp_h->dest);
+
+       STC_LOGD("Source[%u] Destination[%u] Sequence[%u] "
+               "Acknowledgment seq[%u] Window size[%u] ",
+               ntohs(tcp_h->source), ntohs(tcp_h->dest),
+               ntohl(tcp_h->seq), ntohl(tcp_h->ack_seq),
+               ntohs(tcp_h->window));
+
+       STC_LOGD("Checksum[0x%x] URG[%u] ACK[%u] PUSH[%u] "
+               "RST[%u] SYN[%u] FIN[%u]",
+               ntohs(tcp_h->check),
+               tcp_h->urg, tcp_h->ack, tcp_h->psh,
+               tcp_h->rst, tcp_h->syn, tcp_h->fin);
+
+       if (IS_SRC_OR_DST_PORT(PORT_DNS))
+               __pcap_dns_info(packet);
+}
+
+static void __pcap_udp_info(const u_char *packet)
+{
+       udp_t *udp_h = (udp_t *)(packet
+               + SIZE_ETHER_HEADER + SIZE_IP_HEADER);
+       u_int16_t source = ntohs(udp_h->source);
+       u_int16_t dest = ntohs(udp_h->dest);
+
+       STC_LOGD("Source[%u] Destination[%u] Len[%u] Checksum[0x%x]",
+               source, dest, ntohs(udp_h->len), ntohs(udp_h->check));
+
+       if (IS_SRC_OR_DST_PORT(PORT_DNS))
+               __pcap_dns_info(packet);
+       else if (IS_SRC_OR_DST_PORT(PORT_BOOTP_C) ||
+               IS_SRC_OR_DST_PORT(PORT_BOOTP_S))
+               __pcap_bootp_info(packet);
+       else if (IS_SRC_OR_DST_PORT(PORT_NTP))
+               __pcap_ntp_info(packet);        
+}
+
+static const char *__pcap_eth_type_info(u_int16_t type)
+{
+       char *info = NULL;
+
+       switch (type) {
+       case ETHERTYPE_IP:
+               info = "IP";
+               break;
+       case ETHERTYPE_IPV6:
+               info = "IPv6";
+               break;
+       case ETHERTYPE_ARP:
+               info = "ARP";
+               break;
+       case ETHERTYPE_REVARP:
+               info = "REVARP";
+               break;
+       case ETHERTYPE_LOOPBACK:
+               info = "LOOPBACK";
+               break;
+       default:
+               info = "Unknown";
+               break;
+       }
+
+       return info;
+}
+
+static const char *__pcap_arp_opcode_info(u_int16_t opcode)
+{
+       char *info = NULL;
+
+       switch (opcode) {
+       case ARP_REQUEST:
+               info = "Request";
+               break;
+       case ARP_REPLY:
+               info = "Reply";
+               break;
+       case ARP_RREQUEST:
+               info = "RRequest";
+               break;
+       case ARP_RREPLY:
+               info = "RReply";
+               break;
+       default:
+               info = "Unknown";
+               break;
+       }
+
+       return info;
+}
+
+static void __pcap_arp_info(const u_char *packet)
+{
+       arp_t *arp_h = (arp_t *)(packet + SIZE_ETHER_HEADER);
+       u_int8_t *sha = (u_int8_t *)(packet +
+               SIZE_ETHER_HEADER + SIZE_ARP_HEADER);
+       u_int8_t *spa = (u_int8_t *)(sha + arp_h->ar_hln);
+       u_int8_t *tha = (u_int8_t *)(spa + arp_h->ar_pln);
+       u_int8_t *tpa = (u_int8_t *)(tha + arp_h->ar_hln);
+       u_int16_t ar_op = ntohs(arp_h->ar_op);
+       char sma[BUFF_SIZE_HOST];
+       char sia[BUFF_SIZE_IP];
+       char tma[BUFF_SIZE_HOST];
+       char tia[BUFF_SIZE_IP];
+       u_int16_t ar_pro;
+
+       g_strlcpy(sma,
+               ether_ntoa((const struct ether_addr *)sha),
+               sizeof(sma));
+       g_strlcpy(tma,
+               ether_ntoa((const struct ether_addr *)tha),
+               sizeof(tma));
+
+       inet_ntop(AF_INET, (struct in_addr *)spa, sia, BUFF_SIZE_IP);
+       inet_ntop(AF_INET, (struct in_addr *)tpa, tia, BUFF_SIZE_IP);
+
+       ar_pro = ntohs(arp_h->ar_pro);
+
+       STC_LOGD("HW type[%u] Protocol type[0x%04x:%s] "
+               "HW size[%u] Protocol size[%u] Opcode[%u:%s] ",
+               ntohs(arp_h->ar_hrd), ar_pro,
+               __pcap_eth_type_info(ar_pro),
+               arp_h->ar_hln, arp_h->ar_pln,
+               ar_op, __pcap_arp_opcode_info(ar_op));
+
+       STC_LOGD("Sender MAC[%s] Sender IP[%s] "
+               "Target MAC[%s] Target IP[%s]",
+               sma, sia, tma, tia);
+}
+
+static const char *__pcap_ip_protocol_info(u_int8_t p)
+{
+       char *info = NULL;
+
+       switch (p) {
+       case IPPROTO_IP:
+               info = "IP";
+               break;
+       case IPPROTO_ICMP:
+               info = "ICMP";
+               break;
+       case IPPROTO_IPIP:
+               info = "IPIP";
+               break;
+       case IPPROTO_TCP:
+               info = "TCP";
+               break;
+       case IPPROTO_UDP:
+               info = "UDP";
+               break;
+       case IPPROTO_IPV6:
+               info = "IPv6";
+               break;
+       case IPPROTO_ICMPV6:
+               info = "ICMPv6";
+               break;
+       default:
+               info = "Unknown";
+               break;
+       }
+
+       return info;
+}
+
+static void __pcap_ipv6_info(const u_char *packet)
+{
+       ip6_t *ip6_h = (ip6_t *)(packet + SIZE_ETHER_HEADER);
+       char ip6_src[BUFF_SIZE_IP6];
+       char ip6_dst[BUFF_SIZE_IP6];
+
+       inet_ntop(AF_INET6, &ip6_h->ip6_src, ip6_src, BUFF_SIZE_IP6);
+       inet_ntop(AF_INET6, &ip6_h->ip6_dst, ip6_dst, BUFF_SIZE_IP6);
+
+       STC_LOGD("Flow[0x%08x] Payload len[%u] Next hdr[%u:%s] "
+               "Hop limit[%u] Source[%s] Destination[%s]",
+               ntohl(ip6_h->ip6_flow), ntohs(ip6_h->ip6_plen),
+               ip6_h->ip6_nxt, __pcap_ip_protocol_info(ip6_h->ip6_nxt),
+               ip6_h->ip6_hlim, ip6_src, ip6_dst);
+
+       switch (ip6_h->ip6_nxt) {
+       case IPPROTO_IP:
+               break;
+       case IPPROTO_ICMP:
+               break;
+       case IPPROTO_IPIP:
+               break;
+       case IPPROTO_TCP:
+               break;
+       case IPPROTO_UDP:
+               break;
+       case IPPROTO_IPV6:
+               break;
+       case IPPROTO_ICMPV6:
+               break;
+       default:
+               break;
+       }
+}
+
+static void __pcap_ip_info(const u_char *packet)
+{
+       ip_t *ip_h = (ip_t *)(packet + SIZE_ETHER_HEADER);
+       char ip_src[BUFF_SIZE_IP];
+       char ip_dst[BUFF_SIZE_IP];
+
+       inet_ntop(AF_INET, &ip_h->ip_src, ip_src, BUFF_SIZE_IP);
+       inet_ntop(AF_INET, &ip_h->ip_dst, ip_dst, BUFF_SIZE_IP);
+
+       STC_LOGD("Header len[%u] TOS[0x%02x] Total len[%u] "
+               "ID[0x%04x] Flags[0x%02x] TTL[%u] Protocol[%u:%s] "
+               "Checksum[0x%04x] Source[%s] Destination[%s]",
+               ip_h->ip_hl << 2, ip_h->ip_tos,
+               ntohs(ip_h->ip_len), ntohs(ip_h->ip_id),
+               (ntohs(ip_h->ip_off) & 0xe000) >> 13,
+               ip_h->ip_ttl, ip_h->ip_p,
+               __pcap_ip_protocol_info(ip_h->ip_p),
+               ntohs(ip_h->ip_sum), ip_src, ip_dst);
+
+       switch (ip_h->ip_p) {
+       case IPPROTO_ICMP:
+               __pcap_icmp_info(packet);
+               break;
+       case IPPROTO_TCP:
+               __pcap_tcp_info(packet);
+               break;
+       case IPPROTO_UDP:
+               __pcap_udp_info(packet);
+               break;
+       default:
+               break;
+       }
+}
+
+static void __pcap_eth_info(const u_char *packet)
+{
+       eth_t *eth_h = (eth_t *)packet;
+       u_int8_t *eth_shost = eth_h->ether_shost;
+       u_int8_t *eth_dhost = eth_h->ether_dhost;
+       char shost[BUFF_SIZE_HOST];
+       char dhost[BUFF_SIZE_HOST];
+       u_int16_t ether_type;
+
+       g_strlcpy(shost,
+               ether_ntoa((const struct ether_addr *)eth_shost),
+               sizeof(shost));
+
+       g_strlcpy(dhost,
+               ether_ntoa((const struct ether_addr *)eth_dhost),
+               sizeof(dhost));
+
+       ether_type = ntohs(eth_h->ether_type);
+
+       STC_LOGD("Source[%s] Destination[%s] Type[0x%04x:%s]",
+               shost, dhost, ether_type, __pcap_eth_type_info(ether_type));
+}
+
+static void __pcap_fm_info(const struct pcap_pkthdr *pkthdr)
+{
+       char *curr = NULL;
+       int len = 0;
+       struct timeval ts = pkthdr->ts;
+       __time_t tv_sec = ts.tv_sec;
+       __suseconds_t tv_usec = tv_usec;
+
+       if (g_pcap_start_fm == false) {
+               g_pcap_tv = ts;
+               g_pcap_start_fm = true;
+       }
+
+       curr = ctime((const time_t *)&tv_sec);
+       len = strlen(curr);
+       curr[len - 1] = '\0';
+
+       STC_LOGD("Arrival time[%s] Timeval[%.06f] "
+               "Frame len[%u] Capture len[%u]", curr,
+               (float)((tv_sec - g_pcap_tv.tv_sec) * 1000000 +
+               (tv_usec - g_pcap_tv.tv_usec)) / 1000000,
+               pkthdr->len, pkthdr->caplen);
+}
+
+static void __pcap_handler(u_char *param,
+                       const struct pcap_pkthdr *pkthdr,
+                       const u_char *packet) {
+       eth_t *eth_h;
+       unsigned short eth_type;
+       /* int len = pkthdr->len; */
+
+       __pcap_fm_info(pkthdr);
+
+       eth_h = (eth_t *)packet;
+       __pcap_eth_info(packet);
+
+       eth_type = ntohs(eth_h->ether_type);
+       switch (eth_type) {
+       case ETHERTYPE_IP:
+               __pcap_ip_info(packet);
+               /* __pcap_data_info(pcaket, len); */
+               break;
+       case ETHERTYPE_IPV6:
+               __pcap_ipv6_info(packet);
+               break;
+       case ETHERTYPE_ARP:
+       case ETHERTYPE_REVARP:
+               __pcap_arp_info(packet);
+               break;
+       case ETHERTYPE_LOOPBACK:
+               break;
+       default:
+               break;
+       }
+}
+
+static gboolean __pcap_thread_source_func(gpointer data)
+{
+       char buf[MAX_IFACE_LENGTH];
+       stc_pcap_data_s *lookup;
+       stc_pcap_data_s *pcap_data = (stc_pcap_data_s *)data;
+
+       g_pcap_tv.tv_sec = 0;
+       g_pcap_tv.tv_usec = 0;
+       g_pcap_start_fm = false;
+
+       if (g_pcap_tables == NULL)
+               return false;
+
+       snprintf(buf, sizeof(buf), "%s_%d",
+               pcap_data->name, pcap_data->group);
+
+       lookup = g_hash_table_lookup(g_pcap_tables, buf);
+       if (!lookup) {
+               STC_LOGE("pcap loop not found");
+               return false;
+       }
+
+       g_hash_table_remove(g_pcap_tables, buf);
+       STC_LOGD("Successfully removed pcap loop [%s]", buf);
+
+       return false;
+}
+
+static gpointer __pcap_thread_func(gpointer data)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       char errbuf[PCAP_ERRBUF_SIZE];
+       pcap_if_t *alldevs = NULL;
+       pcap_if_t *dev = NULL;
+       char *name = NULL;
+       GSource *source = NULL;
+       GMainContext *context = NULL;
+       stc_pcap_data_s *pcap_data = (stc_pcap_data_s *)data;
+
+       if (pcap_findalldevs(&alldevs, errbuf) < 0 ||
+               alldevs == NULL) {
+               STC_LOGE("Failed to find all devs [%s]", errbuf);
+               goto thread_exit;
+       }
+
+       for (dev = alldevs; dev; dev = dev->next) {
+               if (g_strcmp0(dev->name, pcap_data->name) == 0) {
+                       name = g_strdup(dev->name);
+                       break;
+               }
+       }
+
+       pcap_freealldevs(alldevs);
+
+       if (name == NULL) {
+               STC_LOGE("Failed to find dev [%s]", pcap_data->name);
+               goto thread_exit;
+       }
+
+       STC_LOGD("Pcap source dev [%s]", name);
+
+       pcap_data->handle = pcap_open_live(name, 65535, 1, 1000, errbuf);
+       if (pcap_data->handle == NULL) {
+               STC_LOGE("Failed to open live [%s]", errbuf);
+               goto thread_exit;
+       }
+
+       pcap_loop(pcap_data->handle, 0, __pcap_handler, NULL);
+
+       pcap_close(pcap_data->handle);
+
+thread_exit:
+       FREE(name);
+
+       context = g_main_context_default();
+
+       source = g_idle_source_new();
+
+       g_source_set_callback(source,
+               __pcap_thread_source_func, pcap_data, NULL);
+       g_source_attach(source, context);
+
+       g_source_unref(source);
+       
+       __STC_LOG_FUNC_EXIT__;
+       return NULL;
+}
+
+int stc_plugin_pcap_initialize(void)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       g_pcap_tables = g_hash_table_new_full(g_str_hash,
+               g_str_equal, g_free, __pcap_data_free);
+
+       __STC_LOG_FUNC_EXIT__;
+       return STC_ERROR_NONE;
+}
+
+int stc_plugin_pcap_deinitialize(void)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       if (g_pcap_tables) {
+               g_hash_table_destroy(g_pcap_tables);
+               g_pcap_tables = NULL;
+       }
+
+       __STC_LOG_FUNC_EXIT__;
+       return STC_ERROR_NONE;
+}
+
+int stc_plugin_pcap_lookup_dev(void)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       char *dev = NULL;
+       char errbuf[PCAP_ERRBUF_SIZE];
+
+       dev = pcap_lookupdev(errbuf);
+       if (dev == NULL) {
+               STC_LOGE("Failed to look up dev [%s]", errbuf);
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_FAIL;
+       }
+
+       STC_LOGD("Dev [%s]", dev);
+
+       __STC_LOG_FUNC_EXIT__;
+       return STC_ERROR_NONE;
+}
+
+int stc_plugin_pcap_lookup_net(void)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       char *dev = NULL;
+       char net[BUFF_SIZE_IP];
+       char mask[BUFF_SIZE_IP];
+       char errbuf[PCAP_ERRBUF_SIZE];
+       int ret;
+       bpf_u_int32 netp;
+       bpf_u_int32 maskp;
+
+       dev = pcap_lookupdev(errbuf);
+       if (dev == NULL) {
+               STC_LOGE("Failed to look up dev [%s]", errbuf);
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_FAIL;
+       }
+
+       STC_LOGD("Dev [%s]", dev);
+
+       ret = pcap_lookupnet(dev, &netp, &maskp, errbuf);
+       if (ret == -1) {
+               STC_LOGE("Failed to look up net [%s]", errbuf);
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_FAIL;
+       }
+
+       inet_ntop(AF_INET, &netp, net, BUFF_SIZE_IP);
+       STC_LOGD("Net [%s]", net);
+
+       inet_ntop(AF_INET, &maskp, mask, BUFF_SIZE_IP);
+       STC_LOGD("Mask [%s]", mask);
+
+       __STC_LOG_FUNC_EXIT__;
+       return STC_ERROR_NONE;
+}
+
+int stc_plugin_pcap_find_alldevs(void)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       char net[BUFF_SIZE_IP];
+       char mask[BUFF_SIZE_IP];
+       char errbuf[PCAP_ERRBUF_SIZE];
+       pcap_if_t *alldevs = NULL;
+       pcap_if_t *dev = NULL;
+       bpf_u_int32 netp;
+       bpf_u_int32 maskp;
+
+       if (pcap_findalldevs(&alldevs, errbuf) < 0 ||
+               alldevs == NULL) {
+               STC_LOGE("Failed to find all devs [%s]", errbuf);
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_FAIL;
+       }
+
+       for (dev = alldevs; dev; dev = dev->next) {
+               STC_LOGD("Dev [%s]", dev->name);
+
+               if (dev->description)
+                       STC_LOGD("Decs [%s]", dev->description);
+
+               if (pcap_lookupnet(dev->name, &netp, &maskp, errbuf) == -1) {
+                       STC_LOGE("Failed to look up net [%s]", errbuf);
+                       continue;
+               }
+
+               inet_ntop(AF_INET, &netp, net, BUFF_SIZE_IP);
+               STC_LOGD("Net [%s]", net);
+
+               inet_ntop(AF_INET, &maskp, mask, BUFF_SIZE_IP);
+               STC_LOGD("Mask [%s]", mask);
+       }
+
+       pcap_freealldevs(alldevs);
+
+       __STC_LOG_FUNC_EXIT__;
+       return STC_ERROR_NONE;
+}
+
+int stc_plugin_pcap_register_loop_pcap(const char *ifname,
+                       int group)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       stc_pcap_data_s *data;
+       stc_pcap_data_s *lookup;
+       char buf[MAX_IFACE_LENGTH];
+
+       ret_value_msg_if(g_pcap_tables == NULL,
+               STC_ERROR_FAIL,
+               "pcap tables is not initialized!");
+
+       ret_value_msg_if(ifname == NULL,
+               STC_ERROR_FAIL,
+               "Invalid parameter [ifname]");
+
+       snprintf(buf, sizeof(buf), "%s_%d", ifname, group);
+
+       lookup = g_hash_table_lookup(g_pcap_tables, buf);
+       if (lookup) {
+               STC_LOGD("pcap loop already present");
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_ALREADY_DATA;
+       }
+
+       data = MALLOC0(stc_pcap_data_s, 1);
+       if (!data) {
+               STC_LOGE("data allocation failed");
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_OUT_OF_MEMORY;
+       }
+
+       data->name = g_strdup(ifname);
+       data->group = group;
+       data->thread = g_thread_new(buf, __pcap_thread_func, data);
+
+       g_hash_table_insert(g_pcap_tables, g_strdup(buf), data);
+       STC_LOGD("Successfully added pcap loop [%s]", buf);
+
+       __STC_LOG_FUNC_EXIT__;
+       return STC_ERROR_NONE;
+}
+
+int stc_plugin_pcap_unregister_loop_pcap(const char *ifname,
+                       int group)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       stc_pcap_data_s *lookup;
+       char buf[MAX_IFACE_LENGTH];
+
+       ret_value_msg_if(g_pcap_tables == NULL,
+               STC_ERROR_FAIL,
+               "pcap tables is not initialized!");
+
+       ret_value_msg_if(ifname == NULL,
+               STC_ERROR_FAIL,
+               "Invalid parameter [ifname]");
+
+       snprintf(buf, sizeof(buf), "%s_%d", ifname, group);
+
+       lookup = g_hash_table_lookup(g_pcap_tables, buf);
+       if (!lookup) {
+               STC_LOGE("pcap loop not found");
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_NO_DATA;
+       }
+
+       pcap_breakloop(lookup->handle);
+
+       __STC_LOG_FUNC_EXIT__;
+       return STC_ERROR_NONE;
+}
+
+API stc_plugin_pcap_s stc_plugin_pcap = {
+       .initialize_plugin =
+               stc_plugin_pcap_initialize,
+       .deinitialize_plugin =
+               stc_plugin_pcap_deinitialize,
+       .lookup_dev =
+               stc_plugin_pcap_lookup_dev,
+       .lookup_net =
+               stc_plugin_pcap_lookup_net,
+       .find_alldevs =
+               stc_plugin_pcap_find_alldevs,
+       .register_loop_pcap =
+               stc_plugin_pcap_register_loop_pcap,
+       .unregister_loop_pcap =
+               stc_plugin_pcap_unregister_loop_pcap
+};
+//LCOV_EXCL_STOP
index c845dd0..2ec0178 100644 (file)
@@ -31,6 +31,7 @@ SET(PLUGIN_DIR                  ${CMAKE_SOURCE_DIR}/plugin)
 SET(APPSTATUS_SOURCE_DIR        ${PLUGIN_DIR}/appstatus)
 SET(EXCEPTION_SOURCE_DIR        ${PLUGIN_DIR}/exception)
 SET(PROCFS_SOURCE_DIR           ${PLUGIN_DIR}/procfs)
+SET(PCAP_SOURCE_DIR             ${PLUGIN_DIR}/pcap)
 SET(TETHER_SOURCE_DIR           ${PLUGIN_DIR}/tether)
 
 INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
@@ -54,6 +55,7 @@ INCLUDE_DIRECTORIES(${LIMITATION_SOURCE_DIR}/include)
 INCLUDE_DIRECTORIES(${APPSTATUS_SOURCE_DIR}/include)
 INCLUDE_DIRECTORIES(${EXCEPTION_SOURCE_DIR}/include)
 INCLUDE_DIRECTORIES(${PROCFS_SOURCE_DIR}/include)
+INCLUDE_DIRECTORIES(${PCAP_SOURCE_DIR}/include)
 INCLUDE_DIRECTORIES(${TETHER_SOURCE_DIR}/include)
 
 FILE(GLOB SOURCE_SRCS        ${SOURCE_DIR}/*.c)
old mode 100644 (file)
new mode 100755 (executable)
index b265c80..ef74b17
@@ -19,6 +19,7 @@
 #include "stc-statistics.h"
 #include "stc-restriction.h"
 #include "stc-firewall.h"
+#include "stc-pcap.h"
 #include "stc-connection.h"
 #include "stc-manager-util.h"
 #include "stc-manager-plugin-appstatus.h"
@@ -232,6 +233,45 @@ static gboolean __stc_manager_gdbus_firewall_init(stc_s *stc)
        return ret;
 }
 
+static gboolean __stc_manager_gdbus_pcap_init(stc_s *stc)
+{
+       __STC_LOG_FUNC_ENTER__;
+       gboolean ret = TRUE;
+       gchar *s = NULL;
+
+       StcObjectSkeleton *object = NULL;
+       StcPcap *pcap = NULL;
+       s = g_strdup_printf(STC_DBUS_SERVICE_PCAP_PATH);
+
+       /* Add interface to default object path */
+       object = stc_object_skeleton_new(s);
+       g_free(s);
+
+       pcap = stc_pcap_skeleton_new();
+       stc_object_skeleton_set_pcap(object, pcap);
+       g_object_unref(pcap);
+
+       /* Register for method callbacks as signal callbacks */
+
+       g_signal_connect(pcap, "handle-start",
+                        G_CALLBACK(handle_pcap_start),
+                        stc);
+
+       g_signal_connect(pcap, "handle-stop",
+                        G_CALLBACK(handle_pcap_stop),
+                        stc);
+
+       /* Export the object (@manager takes its own reference to @object) */
+       g_dbus_object_manager_server_export(stc->obj_mgr,
+                                           G_DBUS_OBJECT_SKELETON(object));
+       g_object_unref(object);
+
+       stc->pcap_obj = (gpointer)pcap;
+
+       __STC_LOG_FUNC_EXIT__;
+       return ret;
+}
+
 static gboolean __stc_manager_gdbus_manager_init(stc_s *stc)
 {
        __STC_LOG_FUNC_ENTER__;
@@ -297,6 +337,11 @@ static void __stc_manager_gdbus_on_bus_acquired(GDBusConnection *connection,
                /* Deinitialize and quit manager */
        }
 
+       if (__stc_manager_gdbus_pcap_init(stc) == FALSE) {
+               STC_LOGE("Cannot signal connect to pcap"); //LCOV_EXCL_LINE
+               /* Deinitialize and quit manager */
+       }
+
        if (__stc_manager_gdbus_manager_init(stc) == FALSE) {
                STC_LOGE("Cannot signal connect to manager"); //LCOV_EXCL_LINE
                /* Deinitialize and quit manager */
@@ -362,6 +407,7 @@ void stc_manager_gdbus_deinit(gpointer stc_data)
        stc->statistics_obj = NULL;
        stc->restriction_obj = NULL;
        stc->firewall_obj = NULL;
+       stc->pcap_obj = NULL;
        stc->manager_obj = NULL;
        __STC_LOG_FUNC_EXIT__;
 }
diff --git a/src/stc-manager-plugin-pcap.c b/src/stc-manager-plugin-pcap.c
new file mode 100644 (file)
index 0000000..c9432a2
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 <dlfcn.h>
+
+#include "stc-manager.h"
+#include "stc-manager-plugin-pcap.h"
+
+static gboolean stc_plugin_enabled = FALSE;
+static void *handle_plugin;
+static stc_plugin_pcap_s *stc_plugin;
+
+//LCOV_EXCL_START
+int stc_plugin_pcap_init(void)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       handle_plugin = dlopen(STC_PLUGIN_PCAP_FILEPATH, RTLD_NOW);
+       if (!handle_plugin) {
+               STC_LOGE("Can't load %s: %s", STC_PLUGIN_PCAP_FILEPATH, dlerror());
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       stc_plugin = dlsym(handle_plugin, "stc_plugin_pcap");
+       if (!stc_plugin) {
+               STC_LOGE("Can't load symbol: %s", dlerror());
+               dlclose(handle_plugin);
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       stc_plugin->initialize_plugin();
+       stc_plugin_enabled = TRUE;
+
+       __STC_LOG_FUNC_EXIT__;
+       return STC_ERROR_NONE;
+}
+
+int stc_plugin_pcap_deinit(void)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       if (!stc_plugin_enabled) {
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       stc_plugin->deinitialize_plugin();
+       stc_plugin_enabled = FALSE;
+       dlclose(handle_plugin);
+
+       __STC_LOG_FUNC_EXIT__;
+       return STC_ERROR_NONE;
+}
+
+int stc_plugin_pcap_lookup_dev(void)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       if (!stc_plugin_enabled) {
+               STC_LOGE("Plugin wasn't enabled");
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       if (!stc_plugin) {
+               STC_LOGE("Plugin wasn't loaded");
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       __STC_LOG_FUNC_EXIT__;
+       return stc_plugin->lookup_dev();
+}
+
+int stc_plugin_pcap_lookup_net(void)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       if (!stc_plugin_enabled) {
+               STC_LOGE("Plugin wasn't enabled");
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       if (!stc_plugin) {
+               STC_LOGE("Plugin wasn't loaded");
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       __STC_LOG_FUNC_EXIT__;
+       return stc_plugin->lookup_net();
+}
+
+int stc_plugin_pcap_find_alldevs(void)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       if (!stc_plugin_enabled) {
+               STC_LOGE("Plugin wasn't enabled");
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       if (!stc_plugin) {
+               STC_LOGE("Plugin wasn't loaded");
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       __STC_LOG_FUNC_EXIT__;
+       return stc_plugin->find_alldevs();
+}
+
+int stc_plugin_pcap_register_loop_pcap(const char *ifname,
+                       int group)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       if (!stc_plugin_enabled) {
+               STC_LOGE("Plugin wasn't enabled");
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       if (!stc_plugin) {
+               STC_LOGE("Plugin wasn't loaded");
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       __STC_LOG_FUNC_EXIT__;
+       return stc_plugin->register_loop_pcap(ifname, group);
+}
+
+int stc_plugin_pcap_unregister_loop_pcap(const char *ifname,
+                       int group)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       if (!stc_plugin_enabled) {
+               STC_LOGE("Plugin wasn't enabled");
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       if (!stc_plugin) {
+               STC_LOGE("Plugin wasn't loaded");
+               __STC_LOG_FUNC_EXIT__;
+               return STC_ERROR_UNINITIALIZED;
+       }
+
+       __STC_LOG_FUNC_EXIT__;
+       return stc_plugin->unregister_loop_pcap(ifname, group);
+}
+//LCOV_EXCL_STOP
old mode 100644 (file)
new mode 100755 (executable)
index 79acd88..46401fb
@@ -32,6 +32,7 @@
 #include "stc-manager-plugin-exception.h"
 #include "stc-manager-plugin-procfs.h"
 #include "stc-manager-plugin-tether.h"
+#include "stc-manager-plugin-pcap.h"
 
 #define BUF_SIZE_FOR_ERR 100
 
@@ -91,6 +92,7 @@ static void __stc_manager_deinit(void)
        stc_plugin_exception_deinit();
        stc_plugin_procfs_deinit();
        stc_plugin_tether_deinit();
+       stc_plugin_pcap_deinit();
 
        inotify_deregister(INFO_STORAGE_DIR);
        inotify_deinitialize();
@@ -133,6 +135,7 @@ static stc_s *__stc_manager_init(void)
        stc_plugin_exception_init();
        stc_plugin_procfs_init();
        stc_plugin_tether_init();
+       stc_plugin_pcap_init();
 #endif
 
        stc_firewall_init();
diff --git a/src/stc-pcap.c b/src/stc-pcap.c
new file mode 100755 (executable)
index 0000000..368971e
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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 "stc-db.h"
+#include "stc-pcap.h"
+#include "stc-manager-plugin-pcap.h"
+
+#define PCAP_DBUS_ERROR_NAME "net.stc.pcap.Error.Failed"
+
+#define STC_PCAP_DBUS_REPLY_ERROR(invocation, err_num) \
+       g_dbus_method_invocation_return_dbus_error((invocation), \
+                                                  PCAP_DBUS_ERROR_NAME, \
+                                                  stc_err_strs[-(err_num)])
+
+static const gchar *stc_err_strs[] = {
+       "ERROR_NONE",
+       "FAIL",
+       "DB_FAILED",
+       "OUT_OF_MEMORY",
+       "INVALID_PARAMETER",
+       "NO_DATA",
+       "ALREADY_DATA",
+       "UNINITIALIZED",
+       "PERMISSION_DENIED",
+       "NOTIMPL"
+};
+
+gboolean __validate_pcap(stc_pcap_s *pcap)
+{
+       __STC_LOG_FUNC_ENTER__;
+
+       if (pcap == NULL) {
+               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
+               return FALSE; //LCOV_EXCL_LINE
+       }
+
+       if (pcap->ifname == NULL ||
+               pcap->ifname[0] == '\0') {
+               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
+               return FALSE; //LCOV_EXCL_LINE
+       }
+
+       __STC_LOG_FUNC_EXIT__;
+       return TRUE;
+}
+
+static void __stc_extract_pcap(const char *key, GVariant *value,
+                                          void *user_data)
+{
+       stc_pcap_s *pcap = (stc_pcap_s *) user_data;
+       if (pcap == NULL) {
+               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
+               return; //LCOV_EXCL_LINE
+       }
+
+       if (!g_strcmp0(key, STC_PCAP_IFNAME)) {
+               guint str_length;
+               const gchar *str = g_variant_get_string(value, &str_length);
+               pcap->ifname = g_strdup(str);
+               STC_LOGD("ifname: [%s]", pcap->ifname);
+
+       } else if (!g_strcmp0(key, STC_PCAP_NFLOG_GROUP)) {
+               pcap->nflog_group = g_variant_get_uint32(value);
+               STC_LOGD("nflog group: [%d]", pcap->nflog_group);
+
+       } else {
+               STC_LOGD("Unknown select rule"); //LCOV_EXCL_LINE
+       }
+}
+
+gboolean handle_pcap_start(StcPcap *object,
+                               GDBusMethodInvocation *invocation,
+                               GVariant *parameters,
+                               void *user_data)
+{
+       __STC_LOG_FUNC_ENTER__;
+       GVariantIter *iter = NULL;
+       stc_pcap_s pcap;
+       int ret = STC_ERROR_NONE;
+
+       memset(&pcap, 0, sizeof(stc_pcap_s));
+
+       g_variant_get(parameters, "a{sv}", &iter);
+       if (iter != NULL) {
+               stc_manager_gdbus_dict_foreach(iter,
+                                              __stc_extract_pcap,
+                                              &pcap);
+               g_variant_iter_free(iter);
+       }
+
+       if (__validate_pcap(&pcap) == FALSE) {
+               STC_PCAP_DBUS_REPLY_ERROR(invocation, //LCOV_EXCL_LINE
+                                                STC_ERROR_INVALID_PARAMETER);
+               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
+               return TRUE;
+       }
+
+       ret = stc_plugin_pcap_register_loop_pcap(pcap.ifname, pcap.nflog_group);
+       if (ret != STC_ERROR_NONE) {
+               STC_PCAP_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
+               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
+               return TRUE;
+       }
+
+       STC_DBUS_REPLY_ERROR_NONE(invocation);
+       __STC_LOG_FUNC_EXIT__;
+       return TRUE;
+}
+
+gboolean handle_pcap_stop(StcPcap *object,
+                               GDBusMethodInvocation *invocation,
+                               GVariant *parameters,
+                               void *user_data)
+{
+       __STC_LOG_FUNC_ENTER__;
+       GVariantIter *iter = NULL;
+       stc_pcap_s pcap;
+       int ret = STC_ERROR_NONE;
+
+       memset(&pcap, 0, sizeof(stc_pcap_s));
+
+       g_variant_get(parameters, "a{sv}", &iter);
+       if (iter != NULL) {
+               stc_manager_gdbus_dict_foreach(iter,
+                                              __stc_extract_pcap,
+                                              &pcap);
+               g_variant_iter_free(iter);
+       }
+
+       if (__validate_pcap(&pcap) == FALSE) {
+               STC_PCAP_DBUS_REPLY_ERROR(invocation, //LCOV_EXCL_LINE
+                                                STC_ERROR_INVALID_PARAMETER);
+               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
+               return TRUE;
+       }
+
+       ret = stc_plugin_pcap_unregister_loop_pcap(pcap.ifname, pcap.nflog_group);
+       if (ret != STC_ERROR_NONE) {
+               STC_PCAP_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
+               __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
+               return TRUE;
+       }
+
+       STC_DBUS_REPLY_ERROR_NONE(invocation);
+       __STC_LOG_FUNC_EXIT__;
+       return TRUE;
+}