SET(PKG_MODULES
gio-2.0
gio-unix-2.0
+# gudev-1.0
dlog
libnl-3.0
libnl-genl-3.0
ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"")
ADD_DEFINITIONS("-DUSE_DLOG")
ADD_DEFINITIONS("-DTIZEN_DEBUG_ENABLE")
+IF(USE_UDEV_MONITOR)
+ ADD_DEFINITIONS(-DUSE_UDEV_MONITOR)
+ENDIF(USE_UDEV_MONITOR)
+IF(USE_NETLINK_MONITOR)
+ ADD_DEFINITIONS(-DUSE_NETLINK_MONITOR)
+ENDIF(USE_NETLINK_MONITOR)
+IF(USE_IOCTL_MONITOR)
+ ADD_DEFINITIONS(-DUSE_IOCTL_MONITOR)
+ENDIF(USE_IOCTL_MONITOR)
IF(TIZEN_FEATURE_MESH_ON_DEMAND)
ADD_DEFINITIONS(-DTIZEN_FEATURE_MESH_ON_DEMAND)
ENDIF(TIZEN_FEATURE_MESH_ON_DEMAND)
--- /dev/null
+/*
+ * Network Configuration Module
+ *
+ * Copyright (c) 2017 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 __MESH_DEVICE_MONITOR_H__
+#define __MESH_DEVICE_MONITOR_H__
+
+#ifdef USE_IOCTL_MONITOR
+#define ETH_REG_BMSR 0x01
+#define BMSR_LINK_VALID 0x0004
+
+#define SIOCGMIIPHY 0x8947 /* Get address of MII PHY in use. */
+#define SIOCGMIIREG 0x8948 /* Read MII PHY register */
+
+struct _stMData {
+ unsigned short phy_id;
+ unsigned short reg_num;
+ unsigned short val_in;
+ unsigned short val_out;
+};
+int mesh_get_ethernet_cable_state(int *status);
+#endif /* USE_IOCTL_MONITOR */
+
+#ifdef USE_NETLINK_MONITOR
+int mesh_device_monitor(void *pdata);
+#endif /* USE_NETLINK_MONITOR */
+
+#endif /* __MESH_DEVICE_MONITOR_H__ */
#ifndef __MESH_MONITOR_H__
#define __MESH_MONITOR_H__
-int mesh_start_peer_monitor(void *pdata);
+int mesh_start_monitor_service(void *pdata);
-int mesh_stop_peer_monitor(void *pdata);
+int mesh_stop_monitor_service(void *pdata);
#endif /* __MESH_MONITOR_H__ */
\ No newline at end of file
#include <glib.h>
#include <gio/gio.h>
+#ifdef USE_UDEV_MONITOR
+#include <gudev/gudev.h>
+#endif /* USE_UDEV_MONITOR */
#include <tizen.h>
/**< Internal error code with mesh daemon. It should be matched with API side */
gchar *mesh_interface; /**< The name of mesh network interface */
gchar *softap_interface; /**< The name of SoftAP network interface */
gchar *external_interface; /**< The name of external network interface */
+ gboolean can_be_gate; /**< Whether this device can be Mesh Gate */
gchar *mesh_id; /**< Mesh ID */
gint mesh_channel; /**< The channel number of mesh network */
+#ifdef USE_UDEV_MONITOR
+ GUdevClient *udev_client; /**< The udev event client */
+#endif /* USE_UDEV_MONITOR */
} mesh_interface_s;
/**< Saved mesh network list structure */
GList *station_list; /**< Mesh station list */
GList *mpath_list; /**< MPath list */
+ int netlink_fd; /**< Netlink event socket file descriptor */
+ int monitor_timer; /**< Timer ID for peer monitoring service */
} mesh_service;
#endif /* __MESH_H__ */
%define CHECK_MESH_PRIVILEGE False
+%define UDEV_MONITOR False
+%define NETLINK_MONITOR False
+%define IOCTL_MONITOR False
Name: meshd
Summary: mesh network daemon
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(gio-2.0)
BuildRequires: pkgconfig(gio-unix-2.0)
+#BuildRequires: pkgconfig(gudev-1.0)
BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(libnl-3.0)
BuildRequires: pkgconfig(dbus-1)
--- /dev/null
+/*
+ * Network Configuration Module
+ *
+ * Copyright (c) 2017 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 <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <net/if.h>
+#include <net/ethernet.h>
+#ifdef USE_IOCTL_MONITOR
+#include <sys/ioctl.h>
+#endif
+#ifdef USE_NETLINK_MONITOR
+#include <asm/types.h>
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <net/if_arp.h>
+#endif /* USE_NETLINK_MONITOR */
+
+#include "mesh.h"
+#include "mesh-log.h"
+#include "mesh-util.h"
+#include "mesh-device-monitor.h"
+
+#ifdef USE_NETLINK_MONITOR
+static void mesh_read_netlink_msg(void *pdata)
+{
+ int len;
+ int buf[1024];
+
+ struct sockaddr_nl sa;
+ struct nlmsghdr *nh;
+ struct ifinfomsg *ifimsg;
+ struct rtattr *attribute;
+ struct iovec iov = { buf, sizeof(buf) };
+ struct msghdr msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
+
+ mesh_interface_s *info = NULL;
+ mesh_service *service = (mesh_service *)pdata;
+ meshd_check_null_ret("service", service);
+ info = service->interface_info;
+ meshd_check_null_ret("info", info);
+
+ len = recvmsg(service->netlink_fd, &msg, 0);
+ if(-1 == len) {
+ MESH_LOGE("recvmsg error");
+ return;
+ }
+
+ for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) {
+ if (nh->nlmsg_type == NLMSG_ERROR) {
+ MESH_LOGE("Read Netlink Message Error!!");
+ continue;
+ }
+ if (nh->nlmsg_type == NLMSG_DONE) {
+ MESH_LOGD("Read Netlink Message Done");
+ return;
+ }
+
+ ifimsg = NLMSG_DATA(nh);
+ MESH_LOGD("Message : [%u %u %u 0x%X 0x%X]",
+ ifimsg->ifi_family,
+ ifimsg->ifi_type,
+ ifimsg->ifi_index,
+ ifimsg->ifi_flags,
+ ifimsg->ifi_change);
+ /* Monitor external interface state change */
+ if (ARPHRD_ETHER != ifimsg->ifi_type)
+ return;
+
+ attribute = IFLA_RTA(ifimsg);
+ if (IFLA_IFNAME == attribute->rta_type) {
+ if (!g_strcmp0(info->external_interface, RTA_DATA(attribute))) {
+ MESH_LOGD("Event from external interface : [%s]", RTA_DATA(attribute));
+ if (RTM_NEWLINK == nh->nlmsg_type && false == info->can_be_gate &&
+ IFF_LOWER_UP == (ifimsg->ifi_flags & IFF_LOWER_UP)) {
+ MESH_LOGD("RTM_NEWLINK : [%s]", RTA_DATA(attribute));
+ info->can_be_gate = true;
+ } else if (RTM_DELLINK == nh->nlmsg_type) {
+ MESH_LOGD("RTM_DELLINK : [%s]", RTA_DATA(attribute));
+ info->can_be_gate = false;
+ }
+ }
+ }
+ }
+}
+
+static gboolean _on_socket_msg_received(GIOChannel *source,
+ GIOCondition condition, gpointer data)
+{
+ NOTUSED(source);
+ NOTUSED(condition);
+
+ mesh_read_netlink_msg(data);
+
+ /* Do not remove I/O source */
+ return TRUE;
+}
+
+int mesh_device_monitor(void *pdata)
+{
+ struct sockaddr_nl sa;
+ guint event_source;
+ GIOChannel *recv_channel = NULL;
+
+ mesh_service *service = (mesh_service *)pdata;
+ meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
+
+ memset(&sa, 0, sizeof(sa));
+ sa.nl_family = AF_NETLINK;
+ sa.nl_groups = RTMGRP_LINK;
+
+ service->netlink_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if(-1 == service->netlink_fd) {
+ MESH_LOGE("Netlink socket creation error");
+ return MESHD_ERROR_OPERATION_FAILED;
+ }
+
+ if(bind(service->netlink_fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
+ MESH_LOGE("bind error");
+ return MESHD_ERROR_OPERATION_FAILED;
+ }
+
+ recv_channel = g_io_channel_unix_new(service->netlink_fd);
+ event_source = g_io_add_watch(recv_channel, (G_IO_IN | G_IO_ERR),
+ _on_socket_msg_received, (gpointer)service);
+ g_io_channel_unref(recv_channel);
+
+ return 0;
+}
+#endif /* USE_NETLINK_MONITOR */
+
+#ifdef USE_IOCTL_MONITOR
+/* Check send notification status */
+static gboolean g_chk_eth_send_notification = FALSE;
+#define MAX_SIZE_ERROR_BUFFER 128
+
+static int _ethernet_cable_plugin_status_check()
+{
+ struct ifreq ifr;
+ int soketfd = -1;
+ int error = 0;
+ int ret = 0;
+ struct _stMData *mdata;
+ struct timeval tv;
+ char error_buf[MAX_SIZE_ERROR_BUFFER] = {};
+
+ soketfd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+ if (soketfd < 0) {
+ MESH_LOGE("Failed to create socket");
+ return -errno;
+ }
+
+ /* Set Timeout for IOCTL Call */
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ if (setsockopt(soketfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,
+ sizeof(struct timeval)) < 0) {
+
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+ MESH_LOGE("Failed to set socket option : [%d] [%s]", -errno, error_buf);
+ goto done;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ g_strlcpy(ifr.ifr_name, "eth0", IFNAMSIZ);
+ if (ioctl(soketfd, SIOCGMIIPHY, &ifr) < 0){
+ error = -errno;
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+ MESH_LOGE("SIOCGMIIPHY on eth0 failed : [%d] [%s]", errno, error_buf);
+ goto done;
+ }
+
+ mdata = (struct _stMData *)&ifr.ifr_data;
+ mdata->reg_num = ETH_REG_BMSR;
+
+ if (ioctl(soketfd, SIOCGMIIREG, &ifr) < 0){
+ error = -errno;
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+ MESH_LOGE("SIOCGMIIREG on %s failed , [%d] [%s] ", ifr.ifr_name,errno,error_buf);
+ goto done;
+ }
+ ret = mdata->val_out;
+ ret = ret & BMSR_LINK_VALID;
+
+ MESH_LOGD("value of ret : %d",ret);
+
+ if (ret == 4) {
+ if (!g_chk_eth_send_notification) {
+ MESH_LOGE("Return Value : [%d]", ret);
+ }
+ g_chk_eth_send_notification = TRUE;
+ } else if (ret == 0) {
+ if (g_chk_eth_send_notification) {
+ MESH_LOGE("Return Value : [%d]", ret);
+ }
+ g_chk_eth_send_notification = FALSE;
+ }
+
+
+ error = 0;
+done:
+ close(soketfd);
+ return error;
+}
+
+int mesh_get_ethernet_cable_state(int *status)
+{
+ int error = 0;
+ meshd_check_null_ret_error("status", status, MESHD_ERROR_INVALID_PARAMETER);
+
+ if ((error = _ethernet_cable_plugin_status_check()) != 0) {
+ MESH_LOGE("Error !!! Failed to check ethernet cable status [%d]\n", error);
+ return error;
+ }
+
+ if (g_chk_eth_send_notification == TRUE)
+ *status = 1; /* Ethernet cable Attached */
+ else
+ *status = 0; /* Ethernet cable Deattached */
+ return MESHD_ERROR_NONE;
+}
+#endif
*/
#include <glib.h>
#include <gio/gio.h>
-
+#ifdef USE_UDEV_MONITOR
+#include <gudev/gudev.h>
+#endif /* USE_UDEV_MONITOR */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
return result;
}
+#ifdef USE_UDEV_MONITOR
+static void __on_uevent(GUdevClient *client, gchar *action, GUdevDevice *device, gpointer user_data)
+{
+ NOTUSED(client);
+ NOTUSED(device);
+ NOTUSED(user_data);
+
+ MESH_LOGD("KSR : action:[%s]", action);
+}
+
+static void _interface_status_monitor_init(mesh_interface_s *info)
+{
+ const gchar *subsystem[] = {"net", NULL};
+
+ info->udev_client = g_udev_client_new(subsystem);
+ g_signal_connect(info->udev_client, "uevent", G_CALLBACK(__on_uevent), info);
+}
+#endif /* USE_UDEV_MONITOR */
+
int mesh_interface_initialize(mesh_interface_s *info)
{
if (NULL == info) {
MESH_LOGD(" SoftAP : [%s]", info->softap_interface);
MESH_LOGD(" External: [%s]", info->external_interface);
+#ifdef USE_UDEV_MONITOR
+ _interface_status_monitor_init(info);
+#endif /* USE_UDEV_MONITOR */
return MESHD_ERROR_NONE;
}
return MESHD_ERROR_NONE;
}
+
#include "mesh-util.h"
#include "mesh-request.h"
#include "mesh-netlink.h"
-#include "mesh-monitor.h"
+#include "mesh-interface.h"
+#include "mesh-peer-monitor.h"
+#include "mesh-device-monitor.h"
#define MESH_MONITORING_TIME 5
#define MESH_MAXIMUM_BEACON_LOST_COUNT 10
-static guint g_timer = 0;
-
static void _on_station_list_destroy(gpointer data)
{
mesh_station_info_s *info = (mesh_station_info_s*)data;
#endif
static gboolean _on_mesh_monitor_cb(gpointer pdata)
{
+ int ret;
+#ifdef USE_IOCTL_MONITOR
+ int state;
+#else
+ bool state;
+#endif /* USE_IOCTL_MONITOR */
mesh_service *service = (mesh_service *)pdata;
-
- MESH_LOGD("Evaluting...");
+ if (service) {
+ mesh_interface_s *info = service->interface_info;
+ if (info) {
+ /* Exceptionally, checking external interface processes here. */
+#ifdef USE_IOCTL_MONITOR
+ ret = mesh_get_ethernet_cable_state(&state);
+#else
+ ret = mesh_interface_check_external_exists(info->external_interface, &state);
+#endif /* USE_IOCTL_MONITOR */
+ MESH_LOGE("Status : %d %d %d", ret, info->can_be_gate, state);
+ if (MESHD_ERROR_NONE == ret) {
+ if (info->can_be_gate != state) {
+ /* Detect external network state (i.e. Ethernet)
+ and decide to make gate enabled */
+ if (state)
+ mesh_request_set_mesh_gate(info->bridge_interface,
+ info->mesh_interface, info->external_interface);
+ else
+ mesh_request_unset_mesh_gate(info->bridge_interface,
+ info->mesh_interface, info->external_interface);
+
+ MESH_LOGD("External interface state has been changed : [%d]", state);
+ info->can_be_gate = state;
+ }
+ }
#if 0
- _get_mpath_info(service);
+ _get_mpath_info(service);
#endif
- _get_station_info(service);
+ _get_station_info(service);
+ }
+ }
return G_SOURCE_CONTINUE;
}
-int mesh_start_peer_monitor(void *pdata)
+int mesh_start_monitor_service(void *pdata)
{
int ret = MESHD_ERROR_NONE;
mesh_service *service = (mesh_service *)pdata;
+ meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- if (g_timer)
- mesh_stop_peer_monitor(pdata);
+ if (service->monitor_timer)
+ mesh_stop_monitor_service(pdata);
- g_timer = g_timeout_add_seconds(MESH_MONITORING_TIME, _on_mesh_monitor_cb, service);
+ service->monitor_timer = g_timeout_add_seconds(MESH_MONITORING_TIME, _on_mesh_monitor_cb, service);
MESH_LOGD("Peer Monitoring Service Started");
return ret;
}
-int mesh_stop_peer_monitor(void *pdata)
+int mesh_stop_monitor_service(void *pdata)
{
int ret = MESHD_ERROR_NONE;
mesh_service *service = (mesh_service *)pdata;
+ meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- NOTUSED(service);
-
- if (g_timer) {
- g_source_remove(g_timer);
- g_timer = 0;
+ if (service->monitor_timer) {
+ g_source_remove(service->monitor_timer);
+ service->monitor_timer = 0;
}
MESH_LOGD("Peer Monitoring Service Stopped");
#include "mesh-util.h"
#include "mesh-gdbus.h"
#include "mesh-service.h"
-#include "mesh-monitor.h"
+#include "mesh-peer-monitor.h"
+#include "mesh-device-monitor.h"
#include "mesh-service-interface.h"
#include "mesh-generated-code.h"
if (MESHD_ERROR_NONE != ret)
MESH_LOGE("Failed to mesh_request_enable_network [%d]", ret);
-#if 0
- /* Detect external network state (i.e. Ethernet)
- and decide to make gate enabled */
- ret = mesh_request_set_mesh_gate(info->bridge_interface,
- info->mesh_interface, info->external_interface);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to mesh_request_set_mesh_gate [%d]", ret);
-#endif
-
- if (MESHD_ERROR_NONE == ret)
- mesh_start_peer_monitor(service);
-
+ mesh_start_monitor_service(service);
+#ifdef USE_NETLINK_MONITOR
+ mesh_device_monitor(service);
+#endif /* USE_NETLINK_MONITOR */
net_mesh_complete_enable_mesh(object, invocation, ret);
return TRUE;
MESH_LOGE("Failed to disable mesh network !");
/* Stop Mesh Node Monitoring Service */
- mesh_stop_peer_monitor(service);
-
+ mesh_stop_monitor_service(service);
/* Make response */
net_mesh_complete_disable_mesh(object, invocation, ret);