2 * Network Configuration Module
4 * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
24 #include <net/ethernet.h>
25 #ifdef USE_IOCTL_MONITOR
26 #include <sys/ioctl.h>
28 #ifdef USE_NETLINK_MONITOR
29 #include <asm/types.h>
30 #include <asm/types.h>
31 #include <sys/socket.h>
32 #include <linux/netlink.h>
33 #include <linux/rtnetlink.h>
34 #include <net/if_arp.h>
35 #endif /* USE_NETLINK_MONITOR */
39 #include "mesh-util.h"
40 #include "mesh-device-monitor.h"
42 #ifdef USE_NETLINK_MONITOR
43 static void mesh_read_netlink_msg(void *pdata)
48 struct sockaddr_nl sa;
50 struct ifinfomsg *ifimsg;
51 struct rtattr *attribute;
52 struct iovec iov = { buf, sizeof(buf) };
53 struct msghdr msg = { (void *)&sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
55 mesh_interface_s *info = NULL;
56 mesh_service *service = (mesh_service *)pdata;
57 meshd_check_null_ret("service", service);
58 info = service->interface_info;
59 meshd_check_null_ret("info", info);
61 len = recvmsg(service->netlink_fd, &msg, 0);
63 MESH_LOGE("recvmsg error");
67 for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len); nh = NLMSG_NEXT(nh, len)) {
68 if (nh->nlmsg_type == NLMSG_ERROR) {
69 MESH_LOGE("Read Netlink Message Error!!");
72 if (nh->nlmsg_type == NLMSG_DONE) {
73 MESH_LOGD("Read Netlink Message Done");
77 ifimsg = NLMSG_DATA(nh);
78 MESH_LOGD("Message : [%u %u %u 0x%X 0x%X]",
84 /* Monitor external interface state change */
85 if (ARPHRD_ETHER != ifimsg->ifi_type)
88 attribute = IFLA_RTA(ifimsg);
89 if (IFLA_IFNAME == attribute->rta_type) {
90 if (!g_strcmp0(info->external_interface, RTA_DATA(attribute))) {
91 MESH_LOGD("Event from external interface : [%s]", RTA_DATA(attribute));
92 if (RTM_NEWLINK == nh->nlmsg_type && false == info->can_be_gate &&
93 IFF_LOWER_UP == (ifimsg->ifi_flags & IFF_LOWER_UP)) {
94 MESH_LOGD("RTM_NEWLINK : [%s]", RTA_DATA(attribute));
95 info->can_be_gate = true;
96 } else if (RTM_DELLINK == nh->nlmsg_type) {
97 MESH_LOGD("RTM_DELLINK : [%s]", RTA_DATA(attribute));
98 info->can_be_gate = false;
105 static gboolean _on_socket_msg_received(GIOChannel *source,
106 GIOCondition condition, gpointer data)
111 mesh_read_netlink_msg(data);
113 /* Do not remove I/O source */
117 int mesh_device_monitor(void *pdata)
119 struct sockaddr_nl sa;
121 GIOChannel *recv_channel = NULL;
123 mesh_service *service = (mesh_service *)pdata;
124 meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
126 memset(&sa, 0, sizeof(sa));
127 sa.nl_family = AF_NETLINK;
128 sa.nl_groups = RTMGRP_LINK;
130 service->netlink_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
131 if(-1 == service->netlink_fd) {
132 MESH_LOGE("Netlink socket creation error");
133 return MESHD_ERROR_OPERATION_FAILED;
136 if(bind(service->netlink_fd, (struct sockaddr *) &sa, sizeof(sa)) == -1) {
137 MESH_LOGE("bind error");
138 return MESHD_ERROR_OPERATION_FAILED;
141 recv_channel = g_io_channel_unix_new(service->netlink_fd);
142 event_source = g_io_add_watch(recv_channel, (G_IO_IN | G_IO_ERR),
143 _on_socket_msg_received, (gpointer)service);
144 g_io_channel_unref(recv_channel);
148 #endif /* USE_NETLINK_MONITOR */
150 #ifdef USE_IOCTL_MONITOR
151 /* Check send notification status */
152 static gboolean g_chk_eth_send_notification = FALSE;
153 #define MAX_SIZE_ERROR_BUFFER 128
155 static int _ethernet_cable_plugin_status_check()
161 struct _stMData *mdata;
163 char error_buf[MAX_SIZE_ERROR_BUFFER] = {};
165 soketfd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
167 MESH_LOGE("Failed to create socket");
171 /* Set Timeout for IOCTL Call */
175 if (setsockopt(soketfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,
176 sizeof(struct timeval)) < 0) {
178 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
179 MESH_LOGE("Failed to set socket option : [%d] [%s]", -errno, error_buf);
183 memset(&ifr, 0, sizeof(ifr));
184 g_strlcpy(ifr.ifr_name, "eth0", IFNAMSIZ);
185 if (ioctl(soketfd, SIOCGMIIPHY, &ifr) < 0){
187 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
188 MESH_LOGE("SIOCGMIIPHY on eth0 failed : [%d] [%s]", errno, error_buf);
192 mdata = (struct _stMData *)&ifr.ifr_data;
193 mdata->reg_num = ETH_REG_BMSR;
195 if (ioctl(soketfd, SIOCGMIIREG, &ifr) < 0){
197 strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
198 MESH_LOGE("SIOCGMIIREG on %s failed , [%d] [%s] ", ifr.ifr_name,errno,error_buf);
201 ret = mdata->val_out;
202 ret = ret & BMSR_LINK_VALID;
204 MESH_LOGD("value of ret : %d",ret);
207 if (!g_chk_eth_send_notification) {
208 MESH_LOGE("Return Value : [%d]", ret);
210 g_chk_eth_send_notification = TRUE;
211 } else if (ret == 0) {
212 if (g_chk_eth_send_notification) {
213 MESH_LOGE("Return Value : [%d]", ret);
215 g_chk_eth_send_notification = FALSE;
225 int mesh_get_ethernet_cable_state(int *status)
228 meshd_check_null_ret_error("status", status, MESHD_ERROR_INVALID_PARAMETER);
230 if ((error = _ethernet_cable_plugin_status_check()) != 0) {
231 MESH_LOGE("Error !!! Failed to check ethernet cable status [%d]\n", error);
235 if (g_chk_eth_send_notification == TRUE)
236 *status = 1; /* Ethernet cable Attached */
238 *status = 0; /* Ethernet cable Deattached */
239 return MESHD_ERROR_NONE;