CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-PROJECT(meshd C)
+PROJECT(wmeshd C)
MESSAGE(===================================================================)
MESSAGE(Building...meshd)
ADD_CUSTOM_COMMAND(
OUTPUT dbus
COMMAND gdbus-codegen
- --interface-prefix net.mesh.
- --generate-c-code mesh-generated-code
+ --interface-prefix net.wmesh.
+ --generate-c-code wmesh-generated-code
#--c-namespace mesh
--c-generate-object-manager
--generate-docbook generated-docs
- ${INTROSPECTION_PATH}/mesh.xml
- ${INTROSPECTION_PATH}/manager.xml
+ ${INTROSPECTION_PATH}/wmesh.xml
+ ${INTROSPECTION_PATH}/wmanager.xml
COMMENT "Generating mesh GDBus .c/.h"
)
ADD_CUSTOM_TARGET(GENERATED_DBUS_CODE DEPENDS dbus)
MESSAGE(" - Compiling...")
FILE(GLOB DAEMON_SRCS *.c ${CMAKE_SOURCE_DIR}/src/*.c)
-SET(DAEMON_SRCS ${DAEMON_SRCS} ${CMAKE_SOURCE_DIR}/mesh-generated-code.c)
-SET_SOURCE_FILES_PROPERTIES(${CMAKE_SOURCE_DIR}/mesh-generated-code.c PROPERTIES GENERATED TRUE)
+SET(DAEMON_SRCS ${DAEMON_SRCS} ${CMAKE_SOURCE_DIR}/wmesh-generated-code.c)
+SET_SOURCE_FILES_PROPERTIES(${CMAKE_SOURCE_DIR}/wmesh-generated-code.c PROPERTIES GENERATED TRUE)
INCLUDE_DIRECTORIES(${daemon_pkgs_INCLUDE_DIRS})
LINK_DIRECTORIES(${daemon_pkgs_LIBRARY_DIRS})
INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin)
MESSAGE(" - Copying...meshd")
-CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/files/mesh.sh.in ${CMAKE_SOURCE_DIR}/files/mesh.sh @ONLY)
-INSTALL(FILES ${CMAKE_SOURCE_DIR}/files/mesh.sh DESTINATION ${SBIN_DIR})
+CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/files/wmesh.sh.in ${CMAKE_SOURCE_DIR}/files/wmesh.sh @ONLY)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/files/wmesh.sh DESTINATION ${SBIN_DIR})
+++ /dev/null
-#!/bin/sh
-PATH=/bin:/usr/bin:/sbin:/usr/sbin
-MESH_INTERFACE='mesh0'
-BRIDGE_INTERFACE='br0'
-ETHER_INTERFACE='wlan0'
-HOSTAP_CONFIG='/etc/mesh/hostapd.conf'
-MESH_CHANNEL='161'
-
-MESH_ID='meshnet'
-WLAN_INTERFACE=$3
-ROLE=$1
-
-usage()
-{
- /bin/echo "$0 <gate|station> <start|stop> [interface] [mesh_id]"
- /bin/echo "ex) Mesh Gate :"
- /bin/echo " $0 gate start"
- /bin/echo " $0 gate start wlan0 mesh-area"
- /bin/echo "ex) Mesh Station :"
- /bin/echo " $0 station start"
- /bin/echo " $0 station start wlan1 mesh-area"
- exit 1
-}
-
-start()
-{
- # Verify interface
- if [ -a "/sys/class/net/$WLAN_INTERFACE" ]
- then
- /bin/echo "Use interface [$WLAN_INTERFACE]."
- else
- /bin/echo "Interface [$WLAN_INTERFACE] is not valid."
- exit 1
- fi
-
- case $ROLE in
- "gate")
- /bin/echo "Setting mesh gate..."
- /bin/echo " setting mesh interface.."
-
-## Enable mesh
- # Add virtual interface
- @SBIN_DIR@/iw dev $WLAN_INTERFACE set type managed
- @SBIN_DIR@/ifconfig $WLAN_INTERFACE up
- @SBIN_DIR@/iw dev $WLAN_INTERFACE interface add $MESH_INTERFACE type mp
- @SBIN_DIR@/ifconfig $WLAN_INTERFACE down
- @SBIN_DIR@/ifconfig $MESH_INTERFACE up
-
- # Create bridge with mesh network
- /bin/echo " setting bridge.."
- @SBIN_DIR@/brctl addbr $BRIDGE_INTERFACE
- @SBIN_DIR@/brctl stp $BRIDGE_INTERFACE on
- #@SBIN_DIR@/brctl setfd $BRIDGE_INTERFACE 0
- @SBIN_DIR@/brctl addif $BRIDGE_INTERFACE $MESH_INTERFACE
- @SBIN_DIR@/ifconfig $MESH_INTERFACE down
- @SBIN_DIR@/ifconfig $MESH_INTERFACE 0.0.0.0 up
- @SBIN_DIR@/ifconfig $BRIDGE_INTERFACE up
-
-## Join mesh
- # Join(create) specific mesh network
- # NOTICE: [iw dev ## set channel] should be performed before join
- @SBIN_DIR@/iw dev $MESH_INTERFACE set channel $MESH_CHANNEL
- @SBIN_DIR@/iw dev $MESH_INTERFACE mesh join $MESH_ID
-
-## Set gate
- # Add external network into bridge
- @SBIN_DIR@/brctl addif $BRIDGE_INTERFACE $ETHER_INTERFACE
- @SBIN_DIR@/ifconfig $ETHER_INTERFACE down
- @SBIN_DIR@/ifconfig $ETHER_INTERFACE 0.0.0.0 up
-
- # Announce mesh gate
- /bin/echo " announce mesh gate.."
- @SBIN_DIR@/iw $MESH_INTERFACE set mesh_param mesh_hwmp_rootmode=4
- @SBIN_DIR@/iw $MESH_INTERFACE set mesh_param mesh_gate_announcements=1
-
- # Get MAC address from eth0
- #ETH_MAC_ADDR=`@SBIN_DIR@/ifconfig $ETHER_INTERFACE | /usr/bin/sed -n '/ether/p' | /usr/bin/awk "{print \\$2}"`
- #echo "========================"
- #echo $ETH_MAC_ADDR
- #@SBIN_DIR@/ifconfig $BRIDGE_INTERFACE hw ether $ETH_MAC_ADDR
-
- # Do scan
- @SBIN_DIR@/iw $MESH_INTERFACE scan > /dev/null
-
- # Set IP into bridge interface
- /bin/echo " Get IP address with DHCP.."
- #/usr/bin/dhcp -v -i $BRIDGE_INTERFACE
- DHCP_IP=`/usr/bin/dhcp -i br0 | grep 'obtained' | /usr/bin/awk "{print \\$3}"`
- /bin/echo " IP [$DHCP_IP] obtained"
- @SBIN_DIR@/ifconfig $BRIDGE_INTERFACE $DHCP_IP
- ;;
- "station")
- /bin/echo "Setting mesh station..."
- # Add virtual interface
- /bin/echo " setting mesh interface.."
- @SBIN_DIR@/iw dev $WLAN_INTERFACE set type managed
- @SBIN_DIR@/ifconfig $WLAN_INTERFACE up
- @SBIN_DIR@/iw dev $WLAN_INTERFACE interface add $MESH_INTERFACE type mp
- @SBIN_DIR@/ifconfig $WLAN_INTERFACE down
- @SBIN_DIR@/ifconfig $MESH_INTERFACE up
-
- # Create bridge with mesh network
- /bin/echo " setting bridge.."
- @SBIN_DIR@/brctl addbr $BRIDGE_INTERFACE
- @SBIN_DIR@/brctl stp $BRIDGE_INTERFACE on
- @SBIN_DIR@/brctl setfd $BRIDGE_INTERFACE 0
- @SBIN_DIR@/brctl addif $BRIDGE_INTERFACE $MESH_INTERFACE
- @SBIN_DIR@/ifconfig $MESH_INTERFACE down
- @SBIN_DIR@/ifconfig $MESH_INTERFACE 0.0.0.0 up
- @SBIN_DIR@/ifconfig $BRIDGE_INTERFACE up
-
- # Join(create) specific mesh network
- # NOTICE: [iw dev ## set channel] should be performed before join
- @SBIN_DIR@/iw dev $MESH_INTERFACE set channel $MESH_CHANNEL
- @SBIN_DIR@/iw dev $MESH_INTERFACE mesh join $MESH_ID
-
- # Set Soft AP interface
- if [ "wlan0" == "$WLAN_INTERFACE" ]; then
- # Use wlan0 as mesh interface
- sed -i 's/wlan0/wlan1/' $HOSTAP_CONFIG
- else
- # Use wlan1 as mesh interface
- sed -i 's/wlan1/wlan0/' $HOSTAP_CONFIG
- fi
-
- # Change interface mode with wlan script (for artik)
- if [ -a "/usr/bin/wlan.sh" ]; then
- if [ "wlan0" == "$WLAN_INTERFACE" ]; then
- sed -i 's/wlan0/wlan1/' /usr/bin/wlan.sh
- fi
- @BIN_DIR@/wlan.sh stop
- @BIN_DIR@/wlan.sh softap
- if [ "wlan0" == "$WLAN_INTERFACE" ]; then
- sed -i 's/wlan1/wlan0/' /usr/bin/wlan.sh
- fi
- fi
- @SBIN_DIR@/iw $MESH_INTERFACE scan > /dev/null
-
- # Launch hostapd
- /bin/echo " launching soft ap.."
- @SBIN_DIR@/hostapd -e /opt/var/lib/misc/hostapd.bin $HOSTAP_CONFIG -f /var/log/hostapd_mesh.log -dd &
-
- # Set IP into bridge interface
- /bin/echo " Get IP address with DHCP.."
- #/usr/bin/dhcp -v -i $BRIDGE_INTERFACE
- DHCP_IP=`/usr/bin/dhcp -v -i br0 | grep 'obtained' | /usr/bin/awk "{print \\$3}"`
- /bin/echo " IP [$DHCP_IP] obtained"
- @SBIN_DIR@/ifconfig $BRIDGE_INTERFACE $DHCP_IP
- ;;
- *)
- /bin/echo "Role [$ROLE] is not valid."
- ;;
- esac
-}
-
-stop()
-{
- case $ROLE in
- "station")
- @BIN_DIR@/pkill -x hostapd
- ;;
- esac
-
- # Remove interfaces
- if [ -a "/sys/class/net/$BRIDGE_INTERFACE" ]
- then
- @SBIN_DIR@/ifconfig $BRIDGE_INTERFACE down
- @SBIN_DIR@/brctl delbr $BRIDGE_INTERFACE
- fi
-
- if [ -a "/sys/class/net/$MESH_INTERFACE" ]
- then
- @SBIN_DIR@/iw dev $MESH_INTERFACE del
- fi
-
- # Revert wlan interface
- @SBIN_DIR@/ifconfig $WLAN_INTERFACE up
-}
-
-if [ $# -lt 2 ]; then
- usage
-fi
-
-if [ -n "$4" ]
-then
- /bin/echo "Use mesh id [$MESH_ID]"
- MESH_ID="$4"
-fi
-
-if [ -z "$WLAN_INTERFACE" ]
-then
- case $ROLE in
- "gate")
- WLAN_INTERFACE='wlan0'
- ;;
- "station")
- WLAN_INTERFACE='wlan1'
- ;;
- *)
- WLAN_INTERFACE=''
- usage
- ;;
- esac
-fi
-
-case $2 in
- "start")
- start
- ;;
- "stop")
- stop
- ;;
- *)
- usage
- ;;
-esac
--- /dev/null
+#!/bin/sh
+PATH=/bin:/usr/bin:/sbin:/usr/sbin
+MESH_INTERFACE='mesh0'
+BRIDGE_INTERFACE='br0'
+ETHER_INTERFACE='wlan0'
+HOSTAP_CONFIG='/etc/mesh/hostapd.conf'
+MESH_CHANNEL='161'
+
+MESH_ID='meshnet'
+WLAN_INTERFACE=$3
+ROLE=$1
+
+usage()
+{
+ /bin/echo "$0 <gate|station> <start|stop> [interface] [mesh_id]"
+ /bin/echo "ex) Mesh Gate :"
+ /bin/echo " $0 gate start"
+ /bin/echo " $0 gate start wlan0 mesh-area"
+ /bin/echo "ex) Mesh Station :"
+ /bin/echo " $0 station start"
+ /bin/echo " $0 station start wlan1 mesh-area"
+ exit 1
+}
+
+start()
+{
+ # Verify interface
+ if [ -a "/sys/class/net/$WLAN_INTERFACE" ]
+ then
+ /bin/echo "Use interface [$WLAN_INTERFACE]."
+ else
+ /bin/echo "Interface [$WLAN_INTERFACE] is not valid."
+ exit 1
+ fi
+
+ case $ROLE in
+ "gate")
+ /bin/echo "Setting mesh gate..."
+ /bin/echo " setting mesh interface.."
+
+## Enable mesh
+ # Add virtual interface
+ @SBIN_DIR@/iw dev $WLAN_INTERFACE set type managed
+ @SBIN_DIR@/ifconfig $WLAN_INTERFACE up
+ @SBIN_DIR@/iw dev $WLAN_INTERFACE interface add $MESH_INTERFACE type mp
+ @SBIN_DIR@/ifconfig $WLAN_INTERFACE down
+ @SBIN_DIR@/ifconfig $MESH_INTERFACE up
+
+ # Create bridge with mesh network
+ /bin/echo " setting bridge.."
+ @SBIN_DIR@/brctl addbr $BRIDGE_INTERFACE
+ @SBIN_DIR@/brctl stp $BRIDGE_INTERFACE on
+ #@SBIN_DIR@/brctl setfd $BRIDGE_INTERFACE 0
+ @SBIN_DIR@/brctl addif $BRIDGE_INTERFACE $MESH_INTERFACE
+ @SBIN_DIR@/ifconfig $MESH_INTERFACE down
+ @SBIN_DIR@/ifconfig $MESH_INTERFACE 0.0.0.0 up
+ @SBIN_DIR@/ifconfig $BRIDGE_INTERFACE up
+
+## Join mesh
+ # Join(create) specific mesh network
+ # NOTICE: [iw dev ## set channel] should be performed before join
+ @SBIN_DIR@/iw dev $MESH_INTERFACE set channel $MESH_CHANNEL
+ @SBIN_DIR@/iw dev $MESH_INTERFACE mesh join $MESH_ID
+
+## Set gate
+ # Add external network into bridge
+ @SBIN_DIR@/brctl addif $BRIDGE_INTERFACE $ETHER_INTERFACE
+ @SBIN_DIR@/ifconfig $ETHER_INTERFACE down
+ @SBIN_DIR@/ifconfig $ETHER_INTERFACE 0.0.0.0 up
+
+ # Announce mesh gate
+ /bin/echo " announce mesh gate.."
+ @SBIN_DIR@/iw $MESH_INTERFACE set mesh_param mesh_hwmp_rootmode=4
+ @SBIN_DIR@/iw $MESH_INTERFACE set mesh_param mesh_gate_announcements=1
+
+ # Get MAC address from eth0
+ #ETH_MAC_ADDR=`@SBIN_DIR@/ifconfig $ETHER_INTERFACE | /usr/bin/sed -n '/ether/p' | /usr/bin/awk "{print \\$2}"`
+ #echo "========================"
+ #echo $ETH_MAC_ADDR
+ #@SBIN_DIR@/ifconfig $BRIDGE_INTERFACE hw ether $ETH_MAC_ADDR
+
+ # Do scan
+ @SBIN_DIR@/iw $MESH_INTERFACE scan > /dev/null
+
+ # Set IP into bridge interface
+ /bin/echo " Get IP address with DHCP.."
+ #/usr/bin/dhcp -v -i $BRIDGE_INTERFACE
+ DHCP_IP=`/usr/bin/dhcp -i br0 | grep 'obtained' | /usr/bin/awk "{print \\$3}"`
+ /bin/echo " IP [$DHCP_IP] obtained"
+ @SBIN_DIR@/ifconfig $BRIDGE_INTERFACE $DHCP_IP
+ ;;
+ "station")
+ /bin/echo "Setting mesh station..."
+ # Add virtual interface
+ /bin/echo " setting mesh interface.."
+ @SBIN_DIR@/iw dev $WLAN_INTERFACE set type managed
+ @SBIN_DIR@/ifconfig $WLAN_INTERFACE up
+ @SBIN_DIR@/iw dev $WLAN_INTERFACE interface add $MESH_INTERFACE type mp
+ @SBIN_DIR@/ifconfig $WLAN_INTERFACE down
+ @SBIN_DIR@/ifconfig $MESH_INTERFACE up
+
+ # Create bridge with mesh network
+ /bin/echo " setting bridge.."
+ @SBIN_DIR@/brctl addbr $BRIDGE_INTERFACE
+ @SBIN_DIR@/brctl stp $BRIDGE_INTERFACE on
+ @SBIN_DIR@/brctl setfd $BRIDGE_INTERFACE 0
+ @SBIN_DIR@/brctl addif $BRIDGE_INTERFACE $MESH_INTERFACE
+ @SBIN_DIR@/ifconfig $MESH_INTERFACE down
+ @SBIN_DIR@/ifconfig $MESH_INTERFACE 0.0.0.0 up
+ @SBIN_DIR@/ifconfig $BRIDGE_INTERFACE up
+
+ # Join(create) specific mesh network
+ # NOTICE: [iw dev ## set channel] should be performed before join
+ @SBIN_DIR@/iw dev $MESH_INTERFACE set channel $MESH_CHANNEL
+ @SBIN_DIR@/iw dev $MESH_INTERFACE mesh join $MESH_ID
+
+ # Set Soft AP interface
+ if [ "wlan0" == "$WLAN_INTERFACE" ]; then
+ # Use wlan0 as mesh interface
+ sed -i 's/wlan0/wlan1/' $HOSTAP_CONFIG
+ else
+ # Use wlan1 as mesh interface
+ sed -i 's/wlan1/wlan0/' $HOSTAP_CONFIG
+ fi
+
+ # Change interface mode with wlan script (for artik)
+ if [ -a "/usr/bin/wlan.sh" ]; then
+ if [ "wlan0" == "$WLAN_INTERFACE" ]; then
+ sed -i 's/wlan0/wlan1/' /usr/bin/wlan.sh
+ fi
+ @BIN_DIR@/wlan.sh stop
+ @BIN_DIR@/wlan.sh softap
+ if [ "wlan0" == "$WLAN_INTERFACE" ]; then
+ sed -i 's/wlan1/wlan0/' /usr/bin/wlan.sh
+ fi
+ fi
+ @SBIN_DIR@/iw $MESH_INTERFACE scan > /dev/null
+
+ # Launch hostapd
+ /bin/echo " launching soft ap.."
+ @SBIN_DIR@/hostapd -e /opt/var/lib/misc/hostapd.bin $HOSTAP_CONFIG -f /var/log/hostapd_mesh.log -dd &
+
+ # Set IP into bridge interface
+ /bin/echo " Get IP address with DHCP.."
+ #/usr/bin/dhcp -v -i $BRIDGE_INTERFACE
+ DHCP_IP=`/usr/bin/dhcp -v -i br0 | grep 'obtained' | /usr/bin/awk "{print \\$3}"`
+ /bin/echo " IP [$DHCP_IP] obtained"
+ @SBIN_DIR@/ifconfig $BRIDGE_INTERFACE $DHCP_IP
+ ;;
+ *)
+ /bin/echo "Role [$ROLE] is not valid."
+ ;;
+ esac
+}
+
+stop()
+{
+ case $ROLE in
+ "station")
+ @BIN_DIR@/pkill -x hostapd
+ ;;
+ esac
+
+ # Remove interfaces
+ if [ -a "/sys/class/net/$BRIDGE_INTERFACE" ]
+ then
+ @SBIN_DIR@/ifconfig $BRIDGE_INTERFACE down
+ @SBIN_DIR@/brctl delbr $BRIDGE_INTERFACE
+ fi
+
+ if [ -a "/sys/class/net/$MESH_INTERFACE" ]
+ then
+ @SBIN_DIR@/iw dev $MESH_INTERFACE del
+ fi
+
+ # Revert wlan interface
+ @SBIN_DIR@/ifconfig $WLAN_INTERFACE up
+}
+
+if [ $# -lt 2 ]; then
+ usage
+fi
+
+if [ -n "$4" ]
+then
+ /bin/echo "Use mesh id [$MESH_ID]"
+ MESH_ID="$4"
+fi
+
+if [ -z "$WLAN_INTERFACE" ]
+then
+ case $ROLE in
+ "gate")
+ WLAN_INTERFACE='wlan0'
+ ;;
+ "station")
+ WLAN_INTERFACE='wlan1'
+ ;;
+ *)
+ WLAN_INTERFACE=''
+ usage
+ ;;
+ esac
+fi
+
+case $2 in
+ "start")
+ start
+ ;;
+ "stop")
+ stop
+ ;;
+ *)
+ usage
+ ;;
+esac
+++ /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_BRIDGE_H__
-#define __MESH_BRIDGE_H__
-
-int mesh_bridge_create(const char* interface);
-int mesh_bridge_remove(const char* interface);
-int mesh_bridge_add_interface(const char* bridge_name, const char* interface);
-int mesh_bridge_del_interface(const char* bridge_name, const char* interface);
-int mesh_bridge_set_stp(const char* bridge_name, bool state);
-
-#endif /* __MESH_BRIDGE_H__ */
+++ /dev/null
-/*
- * 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_GDBUS_H__
-#define __MESH_GDBUS_H__
-
-#include "mesh.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* DBus object paths of connman */
-#define CONNMAN_SERVER_NAME "net.connman"
-#define CONNMAN_OBJECT_PATH "/"
-#define CONNMAN_OBJECT_PATH_MESH "/net/connman/mesh"
-#define CONNMAN_OBJECT_PATH_TECH_MESH "/net/connman/technology/mesh"
-
-/* DBus interfaces of connman */
-#define CONNMAN_INTERFACE_MANAGER "net.connman.Manager"
-#define CONNMAN_INTERFACE_MESH "net.connman.Mesh"
-#define CONNMAN_INTERFACE_TECH "net.connman.Technology"
-
-#define MESH_DBUS_PROXY_TIMEOUT ((9.5 + 2) * 1000) /**< default timeout for GDBus */
-
-int meshd_dbus_start(mesh_service *service);
-int meshd_dbus_stop(mesh_service *service);
-
-int mesh_gdbus_create_mesh_interface(mesh_service *service);
-int mesh_gdbus_remove_mesh_interface(mesh_service *service);
-int mesh_gdbus_mesh_scan(mesh_service *service);
-int mesh_gdbus_mesh_specific_scan(mesh_service *service, gchar *mesh_id,
- gint channel);
-int mesh_gdbus_mesh_cancel_scan(mesh_service *service);
-int mesh_gdbus_get_mesh_networks(mesh_service *service);
-int mesh_gdbus_get_joined_mesh_network(mesh_service *service);
-int mesh_gdbus_get_connected_peers(mesh_service *service);
-
-int mesh_gdbus_create_network(mesh_service *service, gchar *mesh_id,
- gint channel, meshd_security_type_e sec);
-int mesh_gdbus_set_passphrase(mesh_service *service, mesh_scan_result_s *info,
- gchar *passphrase);
-int mesh_gdbus_connect_network(mesh_service *service, mesh_scan_result_s *info);
-int mesh_gdbus_disconnect_network(mesh_service *service, mesh_scan_result_s *info);
-int mesh_gdbus_remove_network(mesh_service *service, mesh_scan_result_s *info);
-int mesh_gdbus_enable_ethernet_interface(mesh_service *service, bool state);
-int mesh_gdbus_set_mesh_gate(mesh_service *service);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /** __MESH_GDBUS_H__ */
+++ /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_INTERFACE_H__
-#define __MESH_INTERFACE_H__
-
-typedef enum {
- MESH_INTERFACE_UP = 1, /**< Interface up */
- MESH_INTERFACE_DOWN, /**< Interface down */
- MESH_INTERFACE_DO_NOTHING, /**< Do not handle up/down */
-} mesh_set_interface_type_e;
-
-int mesh_interface_set(const char* interface, const char* ip_addr,
- mesh_set_interface_type_e type);
-//int mesh_interface_set_mac_addr(const char* interface, const char* mac_addr);
-int mesh_interface_initialize(mesh_interface_s *info);
-int mesh_interface_check(const char* interface);
-int mesh_interface_check_external_exists(
- const char* external_interface, bool *state);
-int mesh_interface_check_bridge_interface_exists(const char* bridge, const char* interface);
-char* mesh_interface_get_address(const char* if_name);
-
-#endif /* __MESH_INTERFACE_H__ */
+++ /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_LOG_H__
-#define __MESH_LOG_H__
-
-#ifdef USE_DLOG
-#include <dlog.h>
-
-#undef LOG_TAG
-#define LOG_TAG "MESH_MANAGER"
-
-#define MESH_LOGV(format, args...) LOGV(format, ##args)
-#define MESH_LOGD(format, args...) LOGD(format, ##args)
-#define MESH_LOGI(format, args...) LOGI(format, ##args)
-#define MESH_LOGW(format, args...) LOGW(format, ##args)
-#define MESH_LOGE(format, args...) LOGE(format, ##args)
-#define MESH_LOGF(format, args...) LOGF(format, ##args)
-
-#define __MESH_LOG_FUNC_ENTER__ LOGD("Enter")
-#define __MESH_LOG_FUNC_EXIT__ LOGD("Quit")
-
-#define MESH_SECLOGI(format, args...) SECURE_LOG(LOG_INFO, LOG_TAG, format, ##args)
-#define MESH_SECLOGD(format, args...) SECURE_LOG(LOG_DEBUG, LOG_TAG, format, ##args)
-
-#else /* USE_DLOG */
-
-#define MESH_LOGV(format, args...)
-#define MESH_LOGD(format, args...)
-#define MESH_LOGI(format, args...)
-#define MESH_LOGW(format, args...)
-#define MESH_LOGE(format, args...)
-#define MESH_LOGF(format, args...)
-
-#define __MESH_LOG_FUNC_ENTER__
-#define __MESH_LOG_FUNC_EXIT__
-
-#define MESH_SECLOGI(format, args...)
-#define MESH_SECLOGD(format, args...)
-
-#endif /* USE_DLOG */
-
-#endif /* __MESH_LOG_H__ */
+++ /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_NETLINK_H__
-#define __MESH_NETLINK_H__
-
-int mesh_netlink_set_mesh_parameter(const char* mesh_if_name,
- const char* param_name, unsigned int value);
-
-int mesh_netlink_get_station_info(const char* mesh_if_name, GList **station_list);
-int mesh_netlink_del_station_info(const char* mesh_if_name, char *peer);
-int mesh_netlink_get_mpath_info(const char* mesh_if_name, GList **mpath_list);
-
-int mesh_netlink_register_event_handler();
-int mesh_netlink_unregister_event_handler();
-
-#endif /* __MESH_NETLINK_H__ */
+++ /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_MONITOR_H__
-#define __MESH_MONITOR_H__
-
-int mesh_start_monitor_service(void *pdata);
-int mesh_stop_monitor_service(void *pdata);
-
-#endif /* __MESH_MONITOR_H__ */
\ No newline at end of file
+++ /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_REQUEST_H__
-#define __MESH_REQUEST_H__
-
-/* Newly functions */
-int mesh_request_enable_network(mesh_service *service);
-int mesh_request_disable_network(mesh_service *service);
-int mesh_request_scan(mesh_service *service);
-int mesh_request_specific_scan(mesh_service *service, gchar *mesh_id,
- gint channel);
-int mesh_request_cancel_scan(mesh_service *service);
-int mesh_request_get_networks(mesh_service *service);
-int mesh_request_get_joined_network(mesh_service *service);
-int mesh_request_get_connected_peers(mesh_service *service);
-
-int mesh_request_create_mesh_network(mesh_service *service, gchar *mesh_id,
- gint channel, meshd_security_type_e sec);
-int mesh_request_connect_mesh_network(mesh_service *service, gchar *mesh_id,
- gint channel, meshd_security_type_e sec, gchar *passphrase);
-int mesh_request_disconnect_mesh_network(mesh_service *service,
- gchar *mesh_id, gint channel, meshd_security_type_e sec);
-int mesh_request_remove_mesh_network(mesh_service *service,
- gchar *mesh_id, gint channel, meshd_security_type_e sec);
-
-int mesh_request_set_mesh_gate(const char* bridge_interface,
- const char* mesh_interface, const char* external_interface);
-int mesh_request_unset_mesh_gate(const char* bridge_interface,
- const char* mesh_interface, const char* external_interface);
-
-
-/* Bridge network */
-int mesh_request_add_bridge_interface(const char* bridge_interface,
- const char* interface);
-int mesh_request_remove_bridge_interface(const char* bridge_interface,
- const char* interface);
-
-/* Soft AP */
-int mesh_request_set_softap_config(const char* softap_interface,
- const char *ssid, const char* mode, int channel, int visibility,
- int max_sta, int security, const char* passphrase);
-int mesh_request_enable_softap(
- const char* bridge_interface, const char* softap_interface);
-int mesh_request_disable_softap(
- const char* bridge_interface, const char* softap_interface);
-
-/* Mesh Station & path */
-int mesh_request_get_station_info(const char* mesh_interface, GList **station_list);
-int mesh_request_get_mpath_info(const char* mesh_interface, GList **mpath_list);
-
-int mesh_request_register_event_handler();
-int mesh_request_unregister_event_handler();
-
-/* Notifications */
-void mesh_notify_scan_done();
-void mesh_notify_connection_state(const char* mesh_id, const char* bssid,
- int channel, meshd_security_type_e sec, meshd_connection_state_e state);
-void mesh_notify_station_joined(const char* bssid);
-void mesh_notify_station_left(const char* bssid);
-
-#endif /* __MESH_REQUEST_H__ */
+++ /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_SERVICE_INTERFACE_H__
-#define __MESH_SERVICE_INTERFACE_H__
-
-#include "mesh-generated-code.h"
-
-/**< Mesh D-BUS service*/
-#define MESH_DBUS_SERVICE "net.mesh"
-
-/**< Mesh D-BUS service path */
-#define MESH_DBUS_PATH "/net/mesh"
-
-#ifndef MESH_DBUS_INTERFACE
-#define MESH_DBUS_INTERFACE "net.mesh"
-//#warning "MESH_DBUS_INTERFACE is redefined"
-#endif
-
-#ifndef MESH_DBUS_OBJPATH
-#define MESH_DBUS_OBJPATH "/net/mesh"
-//#warning "MESH_DBUS_OBJPATH is redefined"
-#endif
-
-#ifndef MESH_DBUS_MANAGER_OBJPATH
-#define MESH_DBUS_MANAGER_OBJPATH "/net/mesh/manager"
-//#warning "MESH_DBUS_MANAGER_OBJPATH is redefined"
-#endif
-
-NetMesh* meshd_dbus_get_object();
-int64_t meshd_dbus_generate_signal_number();
-gboolean meshd_service_interface_init(mesh_service *service);
-void meshd_service_interface_deinit(mesh_service *service);
-
-#endif /* __MESH_SERVICE_INTERFACE_H__ */
+++ /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_SERVICE_H__
-#define __MESH_SERVICE_H__
-
-mesh_service *meshd_service_new();
-void meshd_service_free(mesh_service *service);
-gboolean meshd_service_run(mesh_service *service);
-gboolean meshd_service_exit(mesh_service *service);
-
- #endif /* __MESH_SERVICE_H__ */
\ No newline at end of file
+++ /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_SOFTAP_H__
-#define __MESH_SOFTAP_H__
-
-int mesh_softap_set_configuration(const char* softap_interface,
- const char *ssid, const char* mode, int channel, int visibility,
- int max_sta, int security, const char* passphrase);
-int mesh_softap_enable_softap();
-int mesh_softap_disable_softap();
-
- #endif /* __MESH_SOFTAP_H__ */
\ No newline at end of file
+++ /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_UTIL_H__
-#define __MESH_UTIL_H__
-
-#include <glib.h>
-
-#define NOTUSED(var) (var = var)
-
-#define meshd_check_null_ret_error(name, value, error) do { \
- if (G_UNLIKELY(NULL == (value))) { \
- MESH_LOGE("%s is NULL", name); \
- return error; \
- } \
-} while (FALSE)
-
-#define meshd_check_null_ret(name, value) do { \
- if (G_UNLIKELY(NULL == (value))) { \
- MESH_LOGE("%s is NULL", name); \
- return; \
- } \
-} while (FALSE)
-
-#endif /* __MESH_UTIL_H__ */
+++ /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_H__
-#define __MESH_H__
-
-#include <glib.h>
-#include <gio/gio.h>
-#include <tizen.h>
-
-/**< Internal error code with mesh daemon. It should be matched with API side */
-typedef enum {
- MESHD_ERROR_NONE = 0, /**< Successful */
- MESHD_ERROR_IO_ERROR, /**< I/O error */
- MESHD_ERROR_NO_DATA, /**< Data not exists */
- MESHD_ERROR_OUT_OF_MEMORY, /**< out of memory */
- MESHD_ERROR_OPERATION_FAILED, /**< operation failed */
- MESHD_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
- MESHD_ERROR_ALREADY_REGISTERED, /**< Request already registered */
- MESHD_ERROR_IN_PROGRESS /**< operation is in progress */
-} meshd_error_e;
-
-/**< Internal enum for connection state. It should be matched with API side */
-typedef enum {
- MESHD_CONNECTION_STATE_DISCONNECTED = 0, /**< Disconnected state */
- MESHD_CONNECTION_STATE_ASSOCIATION, /**< Association state */
- MESHD_CONNECTION_STATE_CONFIGURATION, /**< Configuration state */
- MESHD_CONNECTION_STATE_CONNECTED /**< Connected state */
-} meshd_connection_state_e;
-
-/**< Internal enum for security type. It should be matched with API side */
-typedef enum {
- MESHD_SECURITY_NONE = 0, /**< No security */
- MESHD_SECURITY_SAE, /**< SAE */
-} meshd_security_type_e;
-
-/**< mesh interface information structure */
-typedef struct {
- gchar *bridge_interface; /**< Bridge name between mesh and others */
- gchar *base_interface; /**< Base interface mesh interface created on */
- 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 */
-
- bool gate_announce; /**< Gate Announce Dnable/Disable */
- int hwmp_root_mode; /**< HWMP Root Mode (0, 2,3 or 4) */
- int stp; /**< Spanning Tree Protocol Enable/Disablel */
-} mesh_interface_s;
-
-/**< Saved mesh network list structure */
-typedef struct _mesh_network_info {
- char* mesh_id; /**< The mesh id */
- char* bssid; /**< BSSID */
- int channel; /**< Channel */
- meshd_security_type_e security; /**< Security type */
- meshd_connection_state_e state; /**< Connection state */
-} mesh_network_info_s;
-
-/**< Mesh network scan result structure */
-typedef struct {
- gchar *object_path; /**< Object path from connman */
- gchar *mesh_id; /**< The mesh id */
- gchar *bssid; /**< BSSID */
- gint rssi; /**< RSSI */
- gint channel; /**< Channel */
- gint data_rate; /**< Data rate */
- meshd_security_type_e security; /**< Security type */
- meshd_connection_state_e state; /**< Connection state */
-} mesh_scan_result_s;
-
-/**< Mesh peer structure */
-typedef struct {
- gchar *address; /**< MAC address of connected peer */
-} mesh_peer_info_s;
-
-/**< Connected mesh network station */
-typedef struct {
- gchar *bssid; /* station bssid ex) 7c:dd:90:62:37:cf */
- guint inactive_time; /**< inactive time ex) 1685 ms */
- guint64 rx_bytes; /**< rx bytes ex) 34174 */
- guint rx_packets; /**< rx packet ex) 1181 */
- guint64 tx_bytes; /**< tx bytes ex) 6877 */
- guint tx_packets; /**< tx packets ex) 76 */
- guint tx_retries; /**< tx retries ex) 0 */
- guint tx_failed; /**< tx failed ex) 0 */
- guint beacon_loss; /**< beacon loss count ex) 0 */
- guint64 beacon_rx; /**< beacon rx ex) 0 */
- guint64 rx_drop_misc; /**< rx drop misc ex) 0 */
- gint rssi; /**< Signal ex) -64 dBm */
- gint rssi_avg; /**< Average Signal ex) -63 dBm */
- guint beacon_signal_avg;
- guint64 t_offset;
- guint tx_bitrate; /**< tx bitrate ex) 54.0 MBit/s => 540 */
- guint rx_bitrate; /**< rx bitrate ex) 5.5 MBit/s => 55 */
- guint64 rx_duration;
- gushort llid; /**< mesh_llid ex) 51731 */
- gushort plid; /**< mesh plid ex) 35432 */
- guchar mesh_plink; /**< mesh plink ex) ESTAB */
- guint local_ps_mode; /**< mesh local power save mode ex) ACTIVE */
- guint peer_ps_mode; /**< mesh peer power save mode ex) ACTIVE */
- guint non_peer_ps_mode; /**< mesh non-peer power save mode ex) ACTIVE */
- gboolean authorized; /**< autorized ex) yes */
- gboolean authenticated; /**< authenticated ex) yes */
- gboolean associated; /**< associated ex) yes */
- gboolean preamble; /**< preamble ex) long */
- gboolean wme; /**< WMM/WME supported ex) yes */
- gboolean mfp; /**< MFP ex) no */
- gboolean tdls_peer; /**< TDLS peer ex) no */
- guchar dtim_period; /**< DTIM period ex) 0 */
- gushort beacon_interval; /**< beacon interval ex) 1000 */
- gboolean cts_protection; /**< CTS protection */
- gboolean short_preamble; /**< short preamble */
- gboolean short_slot_time; /**< short slot time supported ex) yes */
- guint connected_time; /**< connected time : ex) 256 seconds */
-} mesh_station_info_s;
-
-/**< Mesh path information structure */
-typedef struct {
- gchar *dest_addr; /**< Destination address */
- gchar *next_hop; /**< Next Hop */
- gchar *interface; /**< Interface name */
- guint sn; /**< SN */
- guint metric; /**< Metric */
- guint qlen; /**< QLEN */
- guint exptime; /**< Expired time */
- guint discovery_timeout; /**< Discovery timeout */
- guchar discovery_retries; /**< Discovery retries */
- guchar flags; /**< Flags */
-} mesh_mpath_info_s;
-
-
-/**< mesh service structure */
-typedef struct _mesh_service {
- GMainLoop *main_loop; /**< Service main-loop */
- guint dbus_id; /**< D-Bus id */
- guint activation_dbus_id; /**< D-Bus id for activation */
-
- gpointer connection; /**< Connection handle for D-Bus call to other process */
- GCancellable *ca; /**< Cancellable object for D-Bus call (Daemon->other) */
- GList *dbus_sub_ids; /**< The list of subscribed signals */
-
- mesh_interface_s *interface_info; /**< Name of network interfaces */
- gboolean mesh_activated; /**< Stored if mesh network is activated */
- GList *scanned_mesh_network; /**< Scanned mesh network list */
- GList *connected_mesh_peers; /**< Connected mesh peer list */
- mesh_network_info_s *joined_network; /**< Joined network info */
-
- 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__ */
--- /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 __WMESH_BRIDGE_H__
+#define __WMESH_BRIDGE_H__
+
+int wmesh_bridge_create(const char* interface);
+int wmesh_bridge_remove(const char* interface);
+int wmesh_bridge_add_interface(const char* bridge_name, const char* interface);
+int wmesh_bridge_del_interface(const char* bridge_name, const char* interface);
+int wmesh_bridge_set_stp(const char* bridge_name, bool state);
+
+#endif /* __WMESH_BRIDGE_H__ */
--- /dev/null
+/*
+ * 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 __WMESH_GDBUS_H__
+#define __WMESH_GDBUS_H__
+
+#include "wmesh.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* DBus object paths of connman */
+#define CONNMAN_SERVER_NAME "net.connman"
+#define CONNMAN_OBJECT_PATH "/"
+#define CONNMAN_OBJECT_PATH_MESH "/net/connman/mesh"
+#define CONNMAN_OBJECT_PATH_TECH_MESH "/net/connman/technology/mesh"
+
+/* DBus interfaces of connman */
+#define CONNMAN_INTERFACE_MANAGER "net.connman.Manager"
+#define CONNMAN_INTERFACE_MESH "net.connman.Mesh"
+#define CONNMAN_INTERFACE_TECH "net.connman.Technology"
+
+#define WMESH_DBUS_PROXY_TIMEOUT ((9.5 + 2) * 1000) /**< default timeout for GDBus */
+
+int wmeshd_dbus_start(wmesh_service *service);
+int wmeshd_dbus_stop(wmesh_service *service);
+
+int wmesh_gdbus_create_mesh_interface(wmesh_service *service);
+int wmesh_gdbus_remove_mesh_interface(wmesh_service *service);
+int wmesh_gdbus_mesh_scan(wmesh_service *service);
+int wmesh_gdbus_mesh_specific_scan(wmesh_service *service, gchar *mesh_id,
+ gint channel);
+int wmesh_gdbus_mesh_cancel_scan(wmesh_service *service);
+int wmesh_gdbus_get_mesh_networks(wmesh_service *service);
+int wmesh_gdbus_get_joined_mesh_network(wmesh_service *service);
+int wmesh_gdbus_get_connected_peers(wmesh_service *service);
+
+int wmesh_gdbus_create_network(wmesh_service *service, gchar *mesh_id,
+ gint channel, wmeshd_security_type_e sec);
+int wmesh_gdbus_set_passphrase(wmesh_service *service, wmesh_scan_result_s *info,
+ gchar *passphrase);
+int wmesh_gdbus_connect_network(wmesh_service *service, wmesh_scan_result_s *info);
+int wmesh_gdbus_disconnect_network(wmesh_service *service, wmesh_scan_result_s *info);
+int wmesh_gdbus_remove_network(wmesh_service *service, wmesh_scan_result_s *info);
+int wmesh_gdbus_enable_ethernet_interface(wmesh_service *service, bool state);
+int wmesh_gdbus_set_mesh_gate(wmesh_service *service);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /** __WMESH_GDBUS_H__ */
--- /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 __WMESH_INTERFACE_H__
+#define __WMESH_INTERFACE_H__
+
+typedef enum {
+ WMESH_INTERFACE_UP = 1, /**< Interface up */
+ WMESH_INTERFACE_DOWN, /**< Interface down */
+ WMESH_INTERFACE_DO_NOTHING, /**< Do not handle up/down */
+} wmesh_set_interface_type_e;
+
+int wmesh_interface_set(const char* interface, const char* ip_addr,
+ wmesh_set_interface_type_e type);
+//int wmesh_interface_set_mac_addr(const char* interface, const char* mac_addr);
+int wmesh_interface_initialize(wmesh_interface_s *info);
+int wmesh_interface_check(const char* interface);
+int wmesh_interface_check_external_exists(
+ const char* external_interface, bool *state);
+int wmesh_interface_check_bridge_interface_exists(const char* bridge, const char* interface);
+char* wmesh_interface_get_address(const char* if_name);
+
+#endif /* __WMESH_INTERFACE_H__ */
--- /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 __WMESH_LOG_H__
+#define __WMESH_LOG_H__
+
+#ifdef USE_DLOG
+#include <dlog.h>
+
+#undef LOG_TAG
+#define LOG_TAG "WMESH_MANAGER"
+
+#define WMESH_LOGV(format, args...) LOGV(format, ##args)
+#define WMESH_LOGD(format, args...) LOGD(format, ##args)
+#define WMESH_LOGI(format, args...) LOGI(format, ##args)
+#define WMESH_LOGW(format, args...) LOGW(format, ##args)
+#define WMESH_LOGE(format, args...) LOGE(format, ##args)
+#define WMESH_LOGF(format, args...) LOGF(format, ##args)
+
+#define __WMESH_LOG_FUNC_ENTER__ LOGD("Enter")
+#define __WMESH_LOG_FUNC_EXIT__ LOGD("Quit")
+
+#define WMESH_SECLOGI(format, args...) SECURE_LOG(LOG_INFO, LOG_TAG, format, ##args)
+#define WMESH_SECLOGD(format, args...) SECURE_LOG(LOG_DEBUG, LOG_TAG, format, ##args)
+
+#else /* USE_DLOG */
+
+#define WMESH_LOGV(format, args...)
+#define WMESH_LOGD(format, args...)
+#define WMESH_LOGI(format, args...)
+#define WMESH_LOGW(format, args...)
+#define WMESH_LOGE(format, args...)
+#define WMESH_LOGF(format, args...)
+
+#define __WMESH_LOG_FUNC_ENTER__
+#define __WMESH_LOG_FUNC_EXIT__
+
+#define WMESH_SECLOGI(format, args...)
+#define WMESH_SECLOGD(format, args...)
+
+#endif /* USE_DLOG */
+
+#endif /* __WMESH_LOG_H__ */
--- /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 __WMESH_NETLINK_H__
+#define __WMESH_NETLINK_H__
+
+int wmesh_netlink_set_mesh_parameter(const char* mesh_if_name,
+ const char* param_name, unsigned int value);
+
+int wmesh_netlink_get_station_info(const char* mesh_if_name, GList **station_list);
+int wmesh_netlink_del_station_info(const char* mesh_if_name, char *peer);
+int wmesh_netlink_get_mpath_info(const char* mesh_if_name, GList **mpath_list);
+
+int wmesh_netlink_register_event_handler();
+int wmesh_netlink_unregister_event_handler();
+
+#endif /* __WMESH_NETLINK_H__ */
--- /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 __WMESH_MONITOR_H__
+#define __WMESH_MONITOR_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int wmesh_start_monitor_service(void *pdata);
+int wmesh_stop_monitor_service(void *pdata);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __WMESH_MONITOR_H__ */
--- /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 __WMESH_REQUEST_H__
+#define __WMESH_REQUEST_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Newly functions */
+int wmesh_request_enable_network(wmesh_service *service);
+int wmesh_request_disable_network(wmesh_service *service);
+int wmesh_request_scan(wmesh_service *service);
+int wmesh_request_specific_scan(wmesh_service *service, gchar *mesh_id,
+ gint channel);
+int wmesh_request_cancel_scan(wmesh_service *service);
+int wmesh_request_get_networks(wmesh_service *service);
+int wmesh_request_get_joined_network(wmesh_service *service);
+int wmesh_request_get_connected_peers(wmesh_service *service);
+
+int wmesh_request_create_mesh_network(wmesh_service *service, gchar *mesh_id,
+ gint channel, wmeshd_security_type_e sec);
+int wmesh_request_connect_mesh_network(wmesh_service *service, gchar *mesh_id,
+ gint channel, wmeshd_security_type_e sec, gchar *passphrase);
+int wmesh_request_disconnect_mesh_network(wmesh_service *service,
+ gchar *mesh_id, gint channel, wmeshd_security_type_e sec);
+int wmesh_request_remove_mesh_network(wmesh_service *service,
+ gchar *mesh_id, gint channel, wmeshd_security_type_e sec);
+
+int wmesh_request_set_mesh_gate(const char* bridge_interface,
+ const char* mesh_interface, const char* external_interface);
+int wmesh_request_unset_mesh_gate(const char* bridge_interface,
+ const char* mesh_interface, const char* external_interface);
+
+
+/* Bridge network */
+int wmesh_request_add_bridge_interface(const char* bridge_interface,
+ const char* interface);
+int wmesh_request_remove_bridge_interface(const char* bridge_interface,
+ const char* interface);
+
+/* Soft AP */
+int wmesh_request_set_softap_config(const char* softap_interface,
+ const char *ssid, const char* mode, int channel, int visibility,
+ int max_sta, int security, const char* passphrase);
+int wmesh_request_enable_softap(
+ const char* bridge_interface, const char* softap_interface);
+int wmesh_request_disable_softap(
+ const char* bridge_interface, const char* softap_interface);
+
+/* Mesh Station & path */
+int wmesh_request_get_station_info(const char* mesh_interface, GList **station_list);
+int wmesh_request_get_mpath_info(const char* mesh_interface, GList **mpath_list);
+
+int wmesh_request_register_event_handler();
+int wmesh_request_unregister_event_handler();
+
+/* Notifications */
+void wmesh_notify_scan_done();
+void wmesh_notify_connection_state(const char* mesh_id, const char* bssid,
+ int channel, wmeshd_security_type_e sec, wmeshd_connection_state_e state);
+void wmesh_notify_station_joined(const char* bssid);
+void wmesh_notify_station_left(const char* bssid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __WMESH_REQUEST_H__ */
--- /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 __WMESH_SERVICE_INTERFACE_H__
+#define __WMESH_SERVICE_INTERFACE_H__
+
+#include "wmesh-generated-code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**< Mesh D-BUS service*/
+#define WMESH_DBUS_SERVICE "net.wmesh"
+
+/**< Mesh D-BUS service path */
+#define WMESH_DBUS_PATH "/net/wmesh"
+
+#ifndef WMESH_DBUS_INTERFACE
+#define WMESH_DBUS_INTERFACE "net.wmesh"
+//#warning "WMESH_DBUS_INTERFACE is redefined"
+#endif
+
+#ifndef WMESH_DBUS_OBJPATH
+#define WMESH_DBUS_OBJPATH "/net/wmesh"
+//#warning "WMESH_DBUS_OBJPATH is redefined"
+#endif
+
+#ifndef WMESH_DBUS_MANAGER_OBJPATH
+#define WMESH_DBUS_MANAGER_OBJPATH "/net/wmesh/manager"
+//#warning "WMESH_DBUS_MANAGER_OBJPATH is redefined"
+#endif
+
+NetWmesh* wmeshd_dbus_get_object();
+int64_t wmeshd_dbus_generate_signal_number();
+gboolean wmeshd_service_interface_init(wmesh_service *service);
+void wmeshd_service_interface_deinit(wmesh_service *service);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __WMESH_SERVICE_INTERFACE_H__ */
--- /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 __WMESH_SERVICE_H__
+#define __WMESH_SERVICE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+wmesh_service *wmeshd_service_new();
+void wmeshd_service_free(wmesh_service *service);
+gboolean wmeshd_service_run(wmesh_service *service);
+gboolean wmeshd_service_exit(wmesh_service *service);
+
+#ifdef __cplusplus
+}
+#endif
+
+ #endif /* __WMESH_SERVICE_H__ */
--- /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 __WMESH_SOFTAP_H__
+#define __WMESH_SOFTAP_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int wmesh_softap_set_configuration(const char* softap_interface,
+ const char *ssid, const char* mode, int channel, int visibility,
+ int max_sta, int security, const char* passphrase);
+int wmesh_softap_enable_softap();
+int wmesh_softap_disable_softap();
+
+#ifdef __cplusplus
+}
+#endif
+
+ #endif /* __WMESH_SOFTAP_H__ */
--- /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 __WMESH_UTIL_H__
+#define __WMESH_UTIL_H__
+
+#include <glib.h>
+
+#define NOTUSED(var) (var = var)
+
+#define wmeshd_check_null_ret_error(name, value, error) do { \
+ if (G_UNLIKELY(NULL == (value))) { \
+ WMESH_LOGE("%s is NULL", name); \
+ return error; \
+ } \
+} while (FALSE)
+
+#define wmeshd_check_null_ret(name, value) do { \
+ if (G_UNLIKELY(NULL == (value))) { \
+ WMESH_LOGE("%s is NULL", name); \
+ return; \
+ } \
+} while (FALSE)
+
+#endif /* __WMESH_UTIL_H__ */
--- /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 __WMESH_H__
+#define __WMESH_H__
+
+#include <glib.h>
+#include <gio/gio.h>
+#include <tizen.h>
+
+/**< Internal error code with mesh daemon. It should be matched with API side */
+typedef enum {
+ WMESHD_ERROR_NONE = 0, /**< Successful */
+ WMESHD_ERROR_IO_ERROR, /**< I/O error */
+ WMESHD_ERROR_NO_DATA, /**< Data not exists */
+ WMESHD_ERROR_OUT_OF_MEMORY, /**< out of memory */
+ WMESHD_ERROR_OPERATION_FAILED, /**< operation failed */
+ WMESHD_ERROR_INVALID_PARAMETER, /**< Invalid parameter */
+ WMESHD_ERROR_ALREADY_REGISTERED, /**< Request already registered */
+ WMESHD_ERROR_IN_PROGRESS /**< operation is in progress */
+} meshd_error_e;
+
+/**< Internal enum for connection state. It should be matched with API side */
+typedef enum {
+ WMESHD_CONNECTION_STATE_DISCONNECTED = 0, /**< Disconnected state */
+ WMESHD_CONNECTION_STATE_ASSOCIATION, /**< Association state */
+ WMESHD_CONNECTION_STATE_CONFIGURATION, /**< Configuration state */
+ WMESHD_CONNECTION_STATE_CONNECTED /**< Connected state */
+} wmeshd_connection_state_e;
+
+/**< Internal enum for security type. It should be matched with API side */
+typedef enum {
+ WMESHD_SECURITY_NONE = 0, /**< No security */
+ WMESHD_SECURITY_SAE, /**< SAE */
+} wmeshd_security_type_e;
+
+/**< mesh interface information structure */
+typedef struct {
+ gchar *bridge_interface; /**< Bridge name between mesh and others */
+ gchar *base_interface; /**< Base interface mesh interface created on */
+ 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 */
+
+ bool gate_announce; /**< Gate Announce Dnable/Disable */
+ int hwmp_root_mode; /**< HWMP Root Mode (0, 2,3 or 4) */
+ int stp; /**< Spanning Tree Protocol Enable/Disablel */
+} wmesh_interface_s;
+
+/**< Saved mesh network list structure */
+typedef struct _wmesh_network_info {
+ char* mesh_id; /**< The mesh id */
+ char* bssid; /**< BSSID */
+ int channel; /**< Channel */
+ wmeshd_security_type_e security; /**< Security type */
+ wmeshd_connection_state_e state; /**< Connection state */
+} wmesh_network_info_s;
+
+/**< Mesh network scan result structure */
+typedef struct {
+ gchar *object_path; /**< Object path from connman */
+ gchar *mesh_id; /**< The mesh id */
+ gchar *bssid; /**< BSSID */
+ gint rssi; /**< RSSI */
+ gint channel; /**< Channel */
+ gint data_rate; /**< Data rate */
+ wmeshd_security_type_e security; /**< Security type */
+ wmeshd_connection_state_e state; /**< Connection state */
+} wmesh_scan_result_s;
+
+/**< Mesh peer structure */
+typedef struct {
+ gchar *address; /**< MAC address of connected peer */
+} wmesh_peer_info_s;
+
+/**< Connected mesh network station */
+typedef struct {
+ gchar *bssid; /* station bssid ex) 7c:dd:90:62:37:cf */
+ guint inactive_time; /**< inactive time ex) 1685 ms */
+ guint64 rx_bytes; /**< rx bytes ex) 34174 */
+ guint rx_packets; /**< rx packet ex) 1181 */
+ guint64 tx_bytes; /**< tx bytes ex) 6877 */
+ guint tx_packets; /**< tx packets ex) 76 */
+ guint tx_retries; /**< tx retries ex) 0 */
+ guint tx_failed; /**< tx failed ex) 0 */
+ guint beacon_loss; /**< beacon loss count ex) 0 */
+ guint64 beacon_rx; /**< beacon rx ex) 0 */
+ guint64 rx_drop_misc; /**< rx drop misc ex) 0 */
+ gint rssi; /**< Signal ex) -64 dBm */
+ gint rssi_avg; /**< Average Signal ex) -63 dBm */
+ guint beacon_signal_avg;
+ guint64 t_offset;
+ guint tx_bitrate; /**< tx bitrate ex) 54.0 MBit/s => 540 */
+ guint rx_bitrate; /**< rx bitrate ex) 5.5 MBit/s => 55 */
+ guint64 rx_duration;
+ gushort llid; /**< mesh_llid ex) 51731 */
+ gushort plid; /**< mesh plid ex) 35432 */
+ guchar mesh_plink; /**< mesh plink ex) ESTAB */
+ guint local_ps_mode; /**< mesh local power save mode ex) ACTIVE */
+ guint peer_ps_mode; /**< mesh peer power save mode ex) ACTIVE */
+ guint non_peer_ps_mode; /**< mesh non-peer power save mode ex) ACTIVE */
+ gboolean authorized; /**< autorized ex) yes */
+ gboolean authenticated; /**< authenticated ex) yes */
+ gboolean associated; /**< associated ex) yes */
+ gboolean preamble; /**< preamble ex) long */
+ gboolean wme; /**< WMM/WME supported ex) yes */
+ gboolean mfp; /**< MFP ex) no */
+ gboolean tdls_peer; /**< TDLS peer ex) no */
+ guchar dtim_period; /**< DTIM period ex) 0 */
+ gushort beacon_interval; /**< beacon interval ex) 1000 */
+ gboolean cts_protection; /**< CTS protection */
+ gboolean short_preamble; /**< short preamble */
+ gboolean short_slot_time; /**< short slot time supported ex) yes */
+ guint connected_time; /**< connected time : ex) 256 seconds */
+} wmesh_station_info_s;
+
+/**< Mesh path information structure */
+typedef struct {
+ gchar *dest_addr; /**< Destination address */
+ gchar *next_hop; /**< Next Hop */
+ gchar *interface; /**< Interface name */
+ guint sn; /**< SN */
+ guint metric; /**< Metric */
+ guint qlen; /**< QLEN */
+ guint exptime; /**< Expired time */
+ guint discovery_timeout; /**< Discovery timeout */
+ guchar discovery_retries; /**< Discovery retries */
+ guchar flags; /**< Flags */
+} wmesh_mpath_info_s;
+
+
+/**< mesh service structure */
+typedef struct _wmesh_service {
+ GMainLoop *main_loop; /**< Service main-loop */
+ guint dbus_id; /**< D-Bus id */
+ guint activation_dbus_id; /**< D-Bus id for activation */
+
+ gpointer connection; /**< Connection handle for D-Bus call to other process */
+ GCancellable *ca; /**< Cancellable object for D-Bus call (Daemon->other) */
+ GList *dbus_sub_ids; /**< The list of subscribed signals */
+
+ wmesh_interface_s *interface_info; /**< Name of network interfaces */
+ gboolean mesh_activated; /**< Stored if mesh network is activated */
+ GList *scanned_mesh_network; /**< Scanned mesh network list */
+ GList *connected_mesh_peers; /**< Connected mesh peer list */
+ wmesh_network_info_s *joined_network; /**< Joined network info */
+
+ 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 */
+} wmesh_service;
+
+ #endif /* __WMESH_H__ */
-gdbus-codegen --interface-prefix net.mesh. \
- --generate-c-code mesh-generated-code \
+gdbus-codegen --interface-prefix net.wmesh. \
+ --generate-c-code wmesh-generated-code \
--c-generate-object-manager \
--generate-docbook generated-docs \
- mesh.xml \
- manager.xml
+ wmesh.xml \
+ wmanager.xml
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<!DOCTYPE node PUBLIC
- "-//freedesktop//DTD D-Bus Object Introspection 1.0//EN"
- "http://standards.freedesktop.org/dbus/1.0/introspect.dtd">
-
-<node>
- <interface name="net.mesh.manager">
- <!-- Method definitions -->
- <method name="enable">
- <arg type="i" name="result" direction="out"/>
- </method>
- <method name="disable">
- <arg type="i" name="result" direction="out"/>
- </method>
- </interface>
-</node>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" ?>\r
-\r
-<!DOCTYPE node PUBLIC\r
- "-//freedesktop//DTD D-Bus Object Introspection 1.0//EN"\r
- "http://standards.freedesktop.org/dbus/1.0/introspect.dtd">\r
-\r
-<node>\r
- <interface name="net.mesh">\r
- <!-- Method definitions -->\r
- <method name="scan">\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="specific_scan">\r
- <arg type="s" name="mesh_id" direction="in"/>\r
- <arg type="i" name="channel" direction="in"/>\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="cancel_scan">\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="get_found_mesh_networks">\r
- <arg type="aa{sv}" name="network" direction="out"/>\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="get_connected_peers">\r
- <arg type="aa{sv}" name="network" direction="out"/>\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="enable_mesh">\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="disable_mesh">\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="is_joined">\r
- <arg type="b" name="state" direction="out"/>\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="get_joined_mesh_network">\r
- <arg type="s" name="mesh_id" direction="out"/>\r
- <arg type="s" name="bssid" direction="out"/>\r
- <arg type="i" name="channel" direction="out"/>\r
- <arg type="i" name="security" direction="out"/>\r
- <arg type="i" name="state" direction="out"/>\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="set_gate">\r
- <arg type="b" name="gate_announce" direction="in"/>\r
- <arg type="q" name="hwmp_root_mode" direction="in"/>\r
- <arg type="q" name="stp" direction="in"/>\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="unset_gate">\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="set_softap">\r
- <arg type="s" name="ssid" direction="in"/>\r
- <arg type="s" name="passphrase" direction="in"/>\r
- <arg type="s" name="mode" direction="in"/>\r
- <arg type="i" name="channel" direction="in"/>\r
- <arg type="i" name="visibility" direction="in"/>\r
- <arg type="i" name="max_sta" direction="in"/>\r
- <arg type="i" name="security" direction="in"/>\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="enable_softap">\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="disable_softap">\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="create_mesh_network">\r
- <arg type="s" name="mesh_id" direction="in"/>\r
- <arg type="i" name="channel" direction="in"/>\r
- <arg type="i" name="security" direction="in"/>\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="connect_mesh_network">\r
- <arg type="s" name="mesh_id" direction="in"/>\r
- <arg type="i" name="channel" direction="in"/>\r
- <arg type="i" name="security" direction="in"/>\r
- <arg type="s" name="passphrase" direction="in"/>\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="disconnect_mesh_network">\r
- <arg type="s" name="mesh_id" direction="in"/>\r
- <arg type="i" name="channel" direction="in"/>\r
- <arg type="i" name="security" direction="in"/>\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="forget_mesh_network">\r
- <arg type="s" name="mesh_id" direction="in"/>\r
- <arg type="i" name="channel" direction="in"/>\r
- <arg type="i" name="security" direction="in"/>\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="set_interfaces">\r
- <arg type="s" name="mesh" direction="in"/>\r
- <arg type="s" name="gate" direction="in"/>\r
- <arg type="s" name="softap" direction="in"/>\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="get_station_info">\r
- <arg type="aa{sv}" name="station" direction="out"/>\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
- <method name="get_mpath_info">\r
- <arg type="aa{sv}" name="mpath" direction="out"/>\r
- <arg type="i" name="result" direction="out"/>\r
- </method>\r
-\r
- <!-- Signal (D-Bus) definitions -->\r
- <signal name="mesh_enabled">\r
- <arg type="i" name="result" direction="out"/>\r
- </signal>\r
- <signal name="scan_done">\r
- </signal>\r
- <signal name="connection_state">\r
- <arg type="s" name="mesh_id" direction="out"/>\r
- <arg type="s" name="bssid" direction="out"/>\r
- <arg type="i" name="channel" direction="out"/>\r
- <arg type="i" name="security" direction="out"/>\r
- <arg type="i" name="state" direction="out"/>\r
- </signal>\r
- <signal name="sta_joined">\r
- <arg type="s" name="bssid" direction="out"/>\r
- </signal>\r
- <signal name="sta_left">\r
- <arg type="s" name="bssid" direction="out"/>\r
- </signal>\r
- </interface>\r
-</node>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!DOCTYPE node PUBLIC
+ "-//freedesktop//DTD D-Bus Object Introspection 1.0//EN"
+ "http://standards.freedesktop.org/dbus/1.0/introspect.dtd">
+
+<node>
+ <interface name="net.wmesh.manager">
+ <!-- Method definitions -->
+ <method name="enable">
+ <arg type="i" name="result" direction="out"/>
+ </method>
+ <method name="disable">
+ <arg type="i" name="result" direction="out"/>
+ </method>
+ </interface>
+</node>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>\r
+\r
+<!DOCTYPE node PUBLIC\r
+ "-//freedesktop//DTD D-Bus Object Introspection 1.0//EN"\r
+ "http://standards.freedesktop.org/dbus/1.0/introspect.dtd">\r
+\r
+<node>\r
+ <interface name="net.wmesh">\r
+ <!-- Method definitions -->\r
+ <method name="scan">\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="specific_scan">\r
+ <arg type="s" name="mesh_id" direction="in"/>\r
+ <arg type="i" name="channel" direction="in"/>\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="cancel_scan">\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="get_found_mesh_networks">\r
+ <arg type="aa{sv}" name="network" direction="out"/>\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="get_connected_peers">\r
+ <arg type="aa{sv}" name="network" direction="out"/>\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="enable_mesh">\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="disable_mesh">\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="is_joined">\r
+ <arg type="b" name="state" direction="out"/>\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="get_joined_mesh_network">\r
+ <arg type="s" name="mesh_id" direction="out"/>\r
+ <arg type="s" name="bssid" direction="out"/>\r
+ <arg type="i" name="channel" direction="out"/>\r
+ <arg type="i" name="security" direction="out"/>\r
+ <arg type="i" name="state" direction="out"/>\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="set_gate">\r
+ <arg type="b" name="gate_announce" direction="in"/>\r
+ <arg type="q" name="hwmp_root_mode" direction="in"/>\r
+ <arg type="q" name="stp" direction="in"/>\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="unset_gate">\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="set_softap">\r
+ <arg type="s" name="ssid" direction="in"/>\r
+ <arg type="s" name="passphrase" direction="in"/>\r
+ <arg type="s" name="mode" direction="in"/>\r
+ <arg type="i" name="channel" direction="in"/>\r
+ <arg type="i" name="visibility" direction="in"/>\r
+ <arg type="i" name="max_sta" direction="in"/>\r
+ <arg type="i" name="security" direction="in"/>\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="enable_softap">\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="disable_softap">\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="create_mesh_network">\r
+ <arg type="s" name="mesh_id" direction="in"/>\r
+ <arg type="i" name="channel" direction="in"/>\r
+ <arg type="i" name="security" direction="in"/>\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="connect_mesh_network">\r
+ <arg type="s" name="mesh_id" direction="in"/>\r
+ <arg type="i" name="channel" direction="in"/>\r
+ <arg type="i" name="security" direction="in"/>\r
+ <arg type="s" name="passphrase" direction="in"/>\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="disconnect_mesh_network">\r
+ <arg type="s" name="mesh_id" direction="in"/>\r
+ <arg type="i" name="channel" direction="in"/>\r
+ <arg type="i" name="security" direction="in"/>\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="forget_mesh_network">\r
+ <arg type="s" name="mesh_id" direction="in"/>\r
+ <arg type="i" name="channel" direction="in"/>\r
+ <arg type="i" name="security" direction="in"/>\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="set_interfaces">\r
+ <arg type="s" name="mesh" direction="in"/>\r
+ <arg type="s" name="gate" direction="in"/>\r
+ <arg type="s" name="softap" direction="in"/>\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="get_station_info">\r
+ <arg type="aa{sv}" name="station" direction="out"/>\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+ <method name="get_mpath_info">\r
+ <arg type="aa{sv}" name="mpath" direction="out"/>\r
+ <arg type="i" name="result" direction="out"/>\r
+ </method>\r
+\r
+ <!-- Signal (D-Bus) definitions -->\r
+ <signal name="mesh_enabled">\r
+ <arg type="i" name="result" direction="out"/>\r
+ </signal>\r
+ <signal name="scan_done">\r
+ </signal>\r
+ <signal name="connection_state">\r
+ <arg type="s" name="mesh_id" direction="out"/>\r
+ <arg type="s" name="bssid" direction="out"/>\r
+ <arg type="i" name="channel" direction="out"/>\r
+ <arg type="i" name="security" direction="out"/>\r
+ <arg type="i" name="state" direction="out"/>\r
+ </signal>\r
+ <signal name="sta_joined">\r
+ <arg type="s" name="bssid" direction="out"/>\r
+ </signal>\r
+ <signal name="sta_left">\r
+ <arg type="s" name="bssid" direction="out"/>\r
+ </signal>\r
+ </interface>\r
+</node>\r
+++ /dev/null
-<manifest>
- <request>
- <domain name="_"/>
- </request>
-</manifest>
+++ /dev/null
-<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
- "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
-<busconfig>
- <policy user="root">
- <allow own="net.mesh"/>
- <allow own="net.mesh.manager"/>
- <allow send_destination="net.mesh"/>
- <allow send_destination="net.mesh.manager"/>
- <allow receive_sender="net.mesh"/>
- </policy>
- <policy context="default">
- <allow send_destination="net.mesh" send_interface="net.mesh" />
- <allow send_destination="net.mesh.manager" send_interface="net.mesh.manager" />
-
- <!-- Manager -->
- <check send_destination="net.mesh.manager" send_interface="net.mesh.manager"
- send_member="enable" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh.manager" send_interface="net.mesh.manager"
- send_member="disable" privilege="http://tizen.org/privilege/mesh"/>
-
- <!-- Normal methods -->
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="scan" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="specific_scan" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="cancel_scan" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="get_found_mesh_networks" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="get_connected_peers" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="enable_mesh" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="disable_mesh" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="get_joined_mesh_network" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="set_gate" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="unset_gate" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="set_softap" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="enable_softap" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="disable_softap" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="create_mesh_network" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="connect_mesh_network" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="disconnect_mesh_network" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="forget_mesh_network" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="set_interfaces" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="get_station_info" privilege="http://tizen.org/privilege/mesh"/>
- <check send_destination="net.mesh" send_interface="net.mesh"
- send_member="get_mpath_info" privilege="http://tizen.org/privilege/mesh"/>
-
- </policy>
-</busconfig>
--- /dev/null
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <policy user="root">
+ <allow own="net.wmesh"/>
+ <allow own="net.wmesh.manager"/>
+ <allow send_destination="net.wmesh"/>
+ <allow send_destination="net.wmesh.manager"/>
+ <allow receive_sender="net.wmesh"/>
+ </policy>
+ <policy context="default">
+ <allow send_destination="net.wmesh" send_interface="net.wmesh" />
+ <allow send_destination="net.wmesh.manager" send_interface="net.wmesh.manager" />
+
+ <!-- Manager -->
+ <check send_destination="net.wmesh.manager" send_interface="net.wmesh.manager"
+ send_member="enable" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh.manager" send_interface="net.wmesh.manager"
+ send_member="disable" privilege="http://tizen.org/privilege/wmesh"/>
+
+ <!-- Normal methods -->
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="scan" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="specific_scan" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="cancel_scan" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="get_found_mesh_networks" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="get_connected_peers" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="enable_mesh" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="disable_mesh" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="get_joined_mesh_network" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="set_gate" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="unset_gate" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="set_softap" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="enable_softap" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="disable_softap" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="create_mesh_network" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="connect_mesh_network" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="disconnect_mesh_network" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="forget_mesh_network" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="set_interfaces" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="get_station_info" privilege="http://tizen.org/privilege/wmesh"/>
+ <check send_destination="net.wmesh" send_interface="net.wmesh"
+ send_member="get_mpath_info" privilege="http://tizen.org/privilege/wmesh"/>
+
+ </policy>
+</busconfig>
+++ /dev/null
-[Unit]
-Description=Mesh Network Manager service
-Requires=dbus.socket
-After=dbus.socket
-
-[Service]
-Type=dbus
-BusName=net.mesh.manager
-SmackProcessLabel=System
-ExecStart=/usr/bin/meshd
-CapabilityBoundingSet=~CAP_MAC_ADMIN
-CapabilityBoundingSet=~CAP_MAC_OVERRIDE
+++ /dev/null
-%define CHECK_MESH_PRIVILEGE False
-
-Name: meshd
-Summary: mesh network daemon
-Version: 0.0.1
-Release: 1
-Group: Network & Connectivity/Wireless
-License: Apache-2.0
-Source0: %{name}-%{version}.tar.gz
-Source1: dbus-meshd.conf
-Source2: net.mesh.service
-Source3: meshd.service
-BuildRequires: pkgconfig(glib-2.0)
-BuildRequires: pkgconfig(gio-2.0)
-BuildRequires: pkgconfig(gio-unix-2.0)
-BuildRequires: pkgconfig(dlog)
-BuildRequires: pkgconfig(libnl-3.0)
-BuildRequires: pkgconfig(dbus-1)
-BuildRequires: pkgconfig(libcrypto)
-BuildRequires: pkgconfig(libtzplatform-config)
-BuildRequires: pkgconfig(capi-network-wifi-manager)
-BuildRequires: cmake
-# if meshd do dhcp instead of connman
-Requires: net-tools
-Requires: toybox-symlinks-dhcp
-
-%description
-Manager for handling mesh network
-
-%prep
-%setup -q
-chmod 644 %{SOURCE0}
-chmod 644 %{SOURCE1}
-chmod 644 %{SOURCE2}
-chmod 644 %{SOURCE3}
-%if %{CHECK_MESH_PRIVILEGE} == "True"
-cp -a %{SOURCE1} ./meshd.conf
-%endif
-cp -a %{SOURCE2} .
-cp -a %{SOURCE3} .
-
-%build
-CFLAGS=$(echo $CFLAGS | sed 's/-O2/-O0/' | sed 's/-O1/-O0/' | sed 's/-Wp,-D_FORTIFY_SOURCE=2//')
-CXXFLAGS=$(echo $CXXFLAGS | sed 's/-O2/-O0/' | sed 's/-O1/-O0/' | sed 's/-Wp,-D_FORTIFY_SOURCE=2//')
-
-cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} \
- -DTIZEN_FEATURE_MESH_ON_DEMAND=1 \
- -DLIB_DIR=%{_libdir} \
- -DBIN_DIR=%{_bindir} \
- -DSBIN_DIR=%{_sbindir}
-
-make %{?_smp_mflags}
-
-%install
-rm -rf %{buildroot}
-
-%make_install
-
-%if %{CHECK_MESH_PRIVILEGE} == "True"
-mkdir -p %{buildroot}%{_sysconfdir}/dbus-1/system.d
-cp meshd.conf %{buildroot}%{_sysconfdir}/dbus-1/system.d/meshd.conf
-%endif
-mkdir -p %{buildroot}%{_datadir}/dbus-1/system-services/
-cp net.mesh.service %{buildroot}%{_datadir}/dbus-1/system-services/net.mesh.service
-mkdir -p %{buildroot}%{_unitdir}
-cp meshd.service %{buildroot}%{_unitdir}/meshd.service
-
-%post
-chmod 755 %{_sbindir}/mesh.sh
-
-# For configuration files
-mkdir -p %TZ_SYS_VAR/lib/mesh
-
-%files
-%manifest meshd.manifest
-%license LICENSE
-%defattr(-,root,root,-)
-%caps(cap_net_raw,cap_net_admin=eip) %attr(750,system,system) %{_bindir}/meshd
-%if %{CHECK_MESH_PRIVILEGE} == "True"
-%config %{_sysconfdir}/dbus-1/system.d/meshd.conf
-%endif
-%attr(644,root,root) %{_datadir}/dbus-1/system-services/*
-%attr(644,root,root) %{_unitdir}/meshd.service
-%attr(750,root,root) %{_sbindir}/mesh.sh
+++ /dev/null
-[D-BUS Service]
-Name=net.mesh.manager
-
-Exec=/bin/false
-User=root
-SystemdService=meshd.service
--- /dev/null
+[D-BUS Service]
+Name=net.wmesh.manager
+
+Exec=/bin/false
+User=root
+SystemdService=wmeshd.service
--- /dev/null
+[Unit]
+Description=Wi-Fi Mesh Network Manager service
+Requires=dbus.socket
+After=dbus.socket
+
+[Service]
+Type=dbus
+BusName=net.wmesh.manager
+SmackProcessLabel=System
+ExecStart=/usr/bin/wmeshd
+CapabilityBoundingSet=~CAP_MAC_ADMIN
+CapabilityBoundingSet=~CAP_MAC_OVERRIDE
--- /dev/null
+%define CHECK_WMESH_PRIVILEGE False
+
+Name: wmeshd
+Summary: Wi-Fi mesh network daemon
+Version: 0.0.1
+Release: 1
+Group: Network & Connectivity/Wireless
+License: Apache-2.0
+Source0: %{name}-%{version}.tar.gz
+Source1: dbus-wmeshd.conf
+Source2: net.wmesh.service
+Source3: wmeshd.service
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(gio-2.0)
+BuildRequires: pkgconfig(gio-unix-2.0)
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(libnl-3.0)
+BuildRequires: pkgconfig(dbus-1)
+BuildRequires: pkgconfig(libcrypto)
+BuildRequires: pkgconfig(libtzplatform-config)
+BuildRequires: pkgconfig(capi-network-wifi-manager)
+BuildRequires: cmake
+# if meshd do dhcp instead of connman
+Requires: net-tools
+Requires: toybox-symlinks-dhcp
+
+%description
+Manager for handling Wi-Fi mesh network
+
+%prep
+%setup -q
+chmod 644 %{SOURCE0}
+chmod 644 %{SOURCE1}
+chmod 644 %{SOURCE2}
+chmod 644 %{SOURCE3}
+%if %{CHECK_WMESH_PRIVILEGE} == "True"
+cp -a %{SOURCE1} ./wmeshd.conf
+%endif
+cp -a %{SOURCE2} .
+cp -a %{SOURCE3} .
+
+%build
+CFLAGS=$(echo $CFLAGS | sed 's/-O2/-O0/' | sed 's/-O1/-O0/' | sed 's/-Wp,-D_FORTIFY_SOURCE=2//')
+CXXFLAGS=$(echo $CXXFLAGS | sed 's/-O2/-O0/' | sed 's/-O1/-O0/' | sed 's/-Wp,-D_FORTIFY_SOURCE=2//')
+
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} \
+ -DTIZEN_FEATURE_MESH_ON_DEMAND=1 \
+ -DLIB_DIR=%{_libdir} \
+ -DBIN_DIR=%{_bindir} \
+ -DSBIN_DIR=%{_sbindir}
+
+make %{?_smp_mflags}
+
+%install
+rm -rf %{buildroot}
+
+%make_install
+
+%if %{CHECK_WMESH_PRIVILEGE} == "True"
+mkdir -p %{buildroot}%{_sysconfdir}/dbus-1/system.d
+cp wmeshd.conf %{buildroot}%{_sysconfdir}/dbus-1/system.d/wmeshd.conf
+%endif
+mkdir -p %{buildroot}%{_datadir}/dbus-1/system-services/
+cp net.wmesh.service %{buildroot}%{_datadir}/dbus-1/system-services/net.wmesh.service
+mkdir -p %{buildroot}%{_unitdir}
+cp wmeshd.service %{buildroot}%{_unitdir}/wmeshd.service
+
+%post
+chmod 755 %{_sbindir}/wmesh.sh
+
+# For configuration files
+mkdir -p %TZ_SYS_VAR/lib/wmesh
+
+%files
+%manifest wmeshd.manifest
+%license LICENSE
+%defattr(-,root,root,-)
+%caps(cap_net_raw,cap_net_admin=eip) %attr(750,system,system) %{_bindir}/wmeshd
+%if %{CHECK_WMESH_PRIVILEGE} == "True"
+%config %{_sysconfdir}/dbus-1/system.d/wmeshd.conf
+%endif
+%attr(644,root,root) %{_datadir}/dbus-1/system-services/*
+%attr(644,root,root) %{_unitdir}/wmeshd.service
+%attr(750,root,root) %{_sbindir}/wmesh.sh
+++ /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 <glib.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <linux/if.h>
-#include <linux/if_bridge.h>
-#include <linux/sockios.h>
-
-extern unsigned int if_nametoindex(const char *__ifname);
-
-#include "mesh.h"
-#include "mesh-log.h"
-#include "mesh-util.h"
-#include "mesh-service.h"
-#include "mesh-bridge.h"
-
-#define ERROR_MESSAGE_LENGTH 256
-
-int mesh_bridge_create(const char* bridge_name)
-{
- int ret = MESHD_ERROR_NONE;
- int val = 0;
- int br_fd = 0;
- char bridge[IFNAMSIZ];
- char str_error[ERROR_MESSAGE_LENGTH];
-#if !defined(SIOCBRADDBR)
- unsigned long arg[3] = { BRCTL_ADD_BRIDGE, (unsigned long)bridge };
-#endif
-
- if (NULL == bridge_name || strlen(bridge_name) > IFNAMSIZ) {
- MESH_LOGE("Invalid parameter [%p]", bridge_name);
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- br_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (br_fd < 0) {
- strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
- MESH_LOGD("Failed to open socket [%s(%d)]", str_error, errno);
-
- return MESHD_ERROR_IO_ERROR;
- }
-
- snprintf(bridge, IFNAMSIZ, "%s", bridge_name);
-#ifdef SIOCBRADDBR
- val = ioctl(br_fd, SIOCBRADDBR, bridge_name);
-#else
- val = ioctl(br_fd, SIOCSIFBR, arg);
-#endif
- if (val < 0) {
- strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
- MESH_LOGD("Failed to create bridge [%s(%d)]", str_error, errno);
-
- ret = MESHD_ERROR_IO_ERROR;
- }
-
- close(br_fd);
-
- return ret;
-}
-
-int mesh_bridge_remove(const char* bridge_name)
-{
- int ret = MESHD_ERROR_NONE;
- int val = 0;
- int br_fd = 0;
- char bridge[IFNAMSIZ];
- char str_error[ERROR_MESSAGE_LENGTH];
-#if !defined(SIOCBRDELBR)
- unsigned long arg[3] = { BRCTL_DEL_BRIDGE, (unsigned long)bridge };
-#endif
-
- if (NULL == bridge_name || strlen(bridge_name) > IFNAMSIZ) {
- MESH_LOGE("Invalid parameter [%p]", bridge_name);
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- br_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (br_fd < 0) {
- strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
- MESH_LOGD("Failed to open socket [%s(%d)]", str_error, errno);
-
- return MESHD_ERROR_IO_ERROR;
- }
-
- snprintf(bridge, IFNAMSIZ, "%s", bridge_name);
-#ifdef SIOCBRDELBR
- val = ioctl(br_fd, SIOCBRDELBR, bridge_name);
-#else
- val = ioctl(br_fd, SIOCSIFBR, arg);
-#endif
- if (val < 0) {
- strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
- MESH_LOGD("Failed to remove bridge [%s(%d)]", str_error, errno);
-
- ret = MESHD_ERROR_IO_ERROR;
- }
-
- close(br_fd);
-
- return ret;
-}
-
-int mesh_bridge_add_interface(const char* bridge_name, const char* interface)
-{
- int ret = MESHD_ERROR_NONE;
- int val = 0;
- int br_fd = 0;
-
- struct ifreq ifr;
- int if_index = if_nametoindex(interface);
-
- char str_error[ERROR_MESSAGE_LENGTH];
-#if !defined(SIOCBRADDIF)
- unsigned long args[4] = { BRCTL_ADD_IF, if_index, 0, 0 };
-#endif
-
- if (NULL == bridge_name || strlen(bridge_name) > IFNAMSIZ) {
- MESH_LOGE("Invalid parameter [%p]", bridge_name);
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- if (NULL == interface || strlen(interface) > IFNAMSIZ) {
- MESH_LOGE("Invalid parameter [%p]", interface);
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- br_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (br_fd < 0) {
- strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
- MESH_LOGD("Failed to open socket [%s(%d)]", str_error, errno);
-
- return MESHD_ERROR_IO_ERROR;
- }
-
- snprintf(ifr.ifr_name, IFNAMSIZ, "%s", bridge_name);
-#ifdef SIOCBRADDIF
- ifr.ifr_ifindex = if_index;
- val = ioctl(br_fd, SIOCBRADDIF, &ifr);
-#else
- ifr.ifr_data = (char *)args;
- val = ioctl(br_fd, SIOCDEVPRIVATE, &ifr);
-#endif
- if (val < 0) {
- strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
- MESH_LOGD("Failed to add interface [%s] into bridge [%s(%d)]",
- interface, str_error, errno);
-
- ret = MESHD_ERROR_IO_ERROR;
- }
-
- close(br_fd);
-
- return ret;
-}
-
-int mesh_bridge_del_interface(const char* bridge_name, const char* interface)
-{
- int ret = MESHD_ERROR_NONE;
- int val = 0;
- int br_fd = 0;
-
- struct ifreq ifr;
- int if_index = if_nametoindex(interface);
-
- char str_error[ERROR_MESSAGE_LENGTH];
-#if !defined(SIOCBRDELIF)
- unsigned long args[4] = { BRCTL_DEL_IF, if_index, 0, 0 };
-#endif
-
- if (NULL == bridge_name || strlen(bridge_name) > IFNAMSIZ) {
- MESH_LOGE("Invalid parameter [%p]", bridge_name);
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- if (NULL == interface || strlen(interface) > IFNAMSIZ) {
- MESH_LOGE("Invalid parameter [%p]", interface);
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- br_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (br_fd < 0) {
- strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
- MESH_LOGD("Failed to open socket [%s(%d)]", str_error, errno);
-
- return MESHD_ERROR_IO_ERROR;
- }
-
- snprintf(ifr.ifr_name, IFNAMSIZ, "%s", bridge_name);
-#ifdef SIOCBRDELIF
- ifr.ifr_ifindex = if_index;
- val = ioctl(br_fd, SIOCBRDELIF, &ifr);
-#else
- ifr.ifr_data = (char *)args;
- val = ioctl(br_fd, SIOCDEVPRIVATE, &ifr);
-#endif
- if (val < 0) {
- strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
- MESH_LOGD("Failed to delete interface [%s] from bridge [%s(%d)]",
- interface, str_error, errno);
-
- ret = MESHD_ERROR_IO_ERROR;
- }
-
- close(br_fd);
-
- return ret;
-}
-
-int mesh_bridge_set_stp(const char* bridge_name, bool state)
-{
- int ret = MESHD_ERROR_NONE;
- int val = 0;
- int br_fd = 0;
- char str_error[ERROR_MESSAGE_LENGTH];
- int stp_state = (state) ? 1 : 0;
- struct ifreq ifr;
- unsigned long arg[4] = {
- BRCTL_SET_BRIDGE_STP_STATE,
- stp_state, 0, 0 };
-
- if (NULL == bridge_name || strlen(bridge_name) > IFNAMSIZ) {
- MESH_LOGE("Invalid parameter [%p]", bridge_name);
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- br_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
- if (br_fd < 0) {
- strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
- MESH_LOGD("Failed to open socket [%s(%d)]", str_error, errno);
-
- return MESHD_ERROR_IO_ERROR;
- }
-
- strncpy(ifr.ifr_name, bridge_name, IFNAMSIZ);
- ifr.ifr_data = (char *)arg;
-
- val = ioctl(br_fd, SIOCDEVPRIVATE, &ifr);
- if (val < 0) {
- strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
- MESH_LOGE("Failed to set bridge[%s] stp state", bridge_name);
- MESH_LOGE(" %s(%d)", str_error, errno);
-
- ret = MESHD_ERROR_IO_ERROR;
- }
-
- close(br_fd);
-
- return ret;
-}
+++ /dev/null
-/*
- * 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 "mesh-log.h"
-#include "mesh-util.h"
-#include "mesh-gdbus.h"
-#include "mesh-request.h"
-
-#include <linux/nl80211.h>
-
-static GDBusProxy *_gproxy_connman = NULL;
-static GDBusProxy *_gproxy_connman_mesh = NULL;
-static GDBusProxy *_gproxy_connman_technology = NULL;
-static GDBusProxy *_gproxy_connman_ethernet = NULL;
-
-static int _meshd_close_gdbus_call(mesh_service *service);
-static int _mesh_gdbus_get_mesh_network_property(mesh_service *service,
- const gchar* object_path, mesh_network_info_s *result);
-
-static int __channel_to_frequency(int channel, enum nl80211_band band)
-{
- if (channel <= 0)
- return 0;
-
- switch (band) {
- case NL80211_BAND_2GHZ:
- if (channel == 14)
- return 2484;
- else if (channel < 14)
- return 2407 + channel * 5;
- break;
- case NL80211_BAND_5GHZ:
- if (channel >= 182 && channel <= 196)
- return 4000 + channel * 5;
- else
- return 5000 + channel * 5;
- break;
- default:
- break;
- }
-
- /* not supported */
- return 0;
-}
-
-static int __frequency_to_channel(int freq)
-{
- if (freq == 2484)
- return 14;
- else if (freq < 2484)
- return (freq - 2407) / 5;
- else if (freq >= 4910 && freq <= 4980)
- return (freq - 4000) / 5;
- else if (freq <= 45000)
- return (freq - 5000) / 5;
- else if (freq >= 58320 && freq <= 64800)
- return (freq - 56160) / 2160;
- else
- return 0;
-}
-
-static GDBusProxy *_proxy_get_connman(mesh_service *service)
-{
- GDBusProxy *proxy = NULL;
- meshd_check_null_ret_error("service", service, NULL);
-
- if (NULL == _gproxy_connman) {
- proxy = g_dbus_proxy_new_sync(service->connection,
- G_DBUS_PROXY_FLAGS_NONE, NULL,
- CONNMAN_SERVER_NAME,
- CONNMAN_OBJECT_PATH,
- CONNMAN_INTERFACE_MANAGER,
- NULL, NULL);
- } else
- proxy = _gproxy_connman;
-
- return proxy;
-}
-
-static GDBusProxy *_proxy_get_connman_mesh(mesh_service *service)
-{
- GDBusProxy *proxy = NULL;
- meshd_check_null_ret_error("service", service, NULL);
-
- if (NULL == _gproxy_connman_mesh) {
- proxy = g_dbus_proxy_new_sync(service->connection,
- G_DBUS_PROXY_FLAGS_NONE, NULL,
- CONNMAN_SERVER_NAME,
- CONNMAN_OBJECT_PATH_MESH,
- CONNMAN_INTERFACE_MESH,
- NULL, NULL);
- } else
- proxy = _gproxy_connman_mesh;
-
- return proxy;
-}
-
-static GDBusProxy *_proxy_get_connman_ethernet(mesh_service *service)
-{
- GDBusProxy *proxy = NULL;
- meshd_check_null_ret_error("service", service, NULL);
-
- if (NULL == _gproxy_connman_ethernet) {
- proxy = g_dbus_proxy_new_sync(service->connection,
- G_DBUS_PROXY_FLAGS_NONE, NULL,
- CONNMAN_SERVER_NAME, /* Name */
- "/net/connman/technology/ethernet", /* Object Path */
- CONNMAN_INTERFACE_TECH, /* interface Name */
- NULL, NULL);
- } else
- proxy = _gproxy_connman_ethernet;
-
- return proxy;
-}
-
-static GDBusProxy *_proxy_get_connman_technology(mesh_service *service)
-{
- GDBusProxy *proxy = NULL;
- meshd_check_null_ret_error("service", service, NULL);
-
- if (NULL == _gproxy_connman_technology) {
- proxy = g_dbus_proxy_new_sync(service->connection,
- G_DBUS_PROXY_FLAGS_NONE, NULL,
- CONNMAN_SERVER_NAME,
- CONNMAN_OBJECT_PATH_TECH_MESH,
- CONNMAN_INTERFACE_TECH,
- NULL, NULL);
- } else
- proxy = _gproxy_connman_technology;
-
- return proxy;
-}
-
-static void _dbus_name_owner_notify(GObject *object, GParamSpec *pspec,
- gpointer *user_data)
-{
- GDBusProxy *proxy = G_DBUS_PROXY(object);
- gchar *name_owner = g_dbus_proxy_get_name_owner(proxy);
- mesh_service *service = (mesh_service*)user_data;
-
- NOTUSED(pspec);
-
- if (NULL == name_owner) {
- MESH_LOGE("name_owner is not exists !");
- _meshd_close_gdbus_call(service);
- }
-
- g_free(name_owner);
-}
-
-static int _meshd_create_gdbus_call(mesh_service *service)
-{
- int id;
- GError *error = NULL;
-
- if (NULL == service)
- return MESHD_ERROR_INVALID_PARAMETER;
-
- if (NULL != service->connection)
- return MESHD_ERROR_ALREADY_REGISTERED;
-
- service->connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
- if (service->connection == NULL) {
- if (error != NULL) {
- MESH_LOGE("Failed to connect to the D-BUS daemon [%s]", error->message);
- g_error_free(error);
- }
- return MESHD_ERROR_IO_ERROR;
- }
-
- id = g_signal_connect(service->connection, "notify::g-name-owner",
- G_CALLBACK(_dbus_name_owner_notify), service);
- if (0 == id) {
- MESH_LOGE("g_signal_connect() Fail");
- g_object_unref(service->connection);
- service->connection = NULL;
- return MESHD_ERROR_IO_ERROR;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-static int _meshd_close_gdbus_call(mesh_service *service)
-{
- /* CHECK: is connection ref count required? */
- g_object_unref(service->connection);
- service->connection = NULL;
-
- return MESHD_ERROR_NONE;
-}
-
-static void _meshd_signal_handler(GDBusConnection *connection,
- const gchar *sender_name, const gchar *object_path, const gchar *interface_name,
- const gchar *signal_name, GVariant *parameters, gpointer user_data)
-{
- mesh_service *service = (mesh_service*)user_data;
- mesh_network_info_s network_info = { 0, 0, 0, 0, 0 };
- int ret = MESHD_ERROR_NONE;
-
- meshd_check_null_ret("user_data", user_data);
- NOTUSED(connection);
- NOTUSED(sender_name);
- NOTUSED(interface_name);
-
- MESH_LOGD("signal received = %s", signal_name);
- if (0 == g_strcmp0(signal_name, "ScanDone")) {
- /* TODO: Handle event */
- mesh_notify_scan_done();
- } else if (0 == g_strcmp0(signal_name, "PropertyChanged")) {
- const gchar* var = NULL;
- gchar* key = NULL;
- GVariant *variant = NULL;
- meshd_connection_state_e state = MESHD_CONNECTION_STATE_DISCONNECTED;
-
- if (NULL == parameters) {
- MESH_LOGE("Unexpected parameter");
- return;
- }
-
- g_variant_get(parameters, "(sv)", &key, &variant);
- if (NULL == variant) {
- MESH_LOGE("Invalid variant");
- return;
- }
-
- /* State [???] */
- var = g_variant_get_string(variant, NULL);
- MESH_LOGD(" %s [%s]", key, var);
- MESH_LOGD(" %s", object_path);
-
- ret = _mesh_gdbus_get_mesh_network_property(service, object_path, &network_info);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Cannot get valid network property !");
-
- if (g_strcmp0("association", var) == 0) {
- /* Joined mesh network */
- state = MESHD_CONNECTION_STATE_ASSOCIATION;
- } else if (g_strcmp0("configuration", var) == 0) {
- /* Trying to get IP address */
- state = MESHD_CONNECTION_STATE_CONFIGURATION;
- } else if (g_strcmp0("ready", var) == 0 || g_strcmp0("online", var) == 0) {
- /* IP address is obtained */
- state = MESHD_CONNECTION_STATE_CONNECTED;
- } else if (g_strcmp0("disconnect", var) == 0 || g_strcmp0("failure", var) == 0) {
- state = MESHD_CONNECTION_STATE_DISCONNECTED;
- } else {
- MESH_LOGE(" Unhandled state !");
- g_free(network_info.mesh_id);
- g_free(network_info.bssid);
- return;
- }
-
- mesh_notify_connection_state(network_info.mesh_id, network_info.bssid,
- network_info.channel, network_info.security, state);
-
- g_free(network_info.mesh_id);
- g_free(network_info.bssid);
- }
-}
-
-static void _meshd_subscribe_event(mesh_service *service)
-{
- unsigned int id = 0;
-
- meshd_check_null_ret("service", service);
-
- id = g_dbus_connection_signal_subscribe(
- (GDBusConnection *)service->connection,
- CONNMAN_SERVER_NAME, CONNMAN_INTERFACE_MANAGER,
- "ScanDone", "/", NULL,
- G_DBUS_CALL_FLAGS_NONE, _meshd_signal_handler, service, NULL);
- if (0 == id) {
- MESH_LOGE("g_dbus_connection_signal_subscribe(ScanDone) Fail(%d)", errno);
- return;
- }
- service->dbus_sub_ids = g_list_append(service->dbus_sub_ids, GUINT_TO_POINTER(id));
- MESH_LOGD("[Signal subscribe] : ScanDone (%d)", id);
-
- /* To monitor mesh profiles */
- id = g_dbus_connection_signal_subscribe(
- (GDBusConnection *)service->connection,
- CONNMAN_SERVER_NAME,
- CONNMAN_INTERFACE_MESH,
- "PropertyChanged",
- NULL, /* Path */
- NULL,
- G_DBUS_CALL_FLAGS_NONE, _meshd_signal_handler, service, NULL);
- if (0 == id) {
- MESH_LOGE("g_dbus_connection_signal_subscribe(ScanDone) Fail(%d)", errno);
- return;
- }
- service->dbus_sub_ids = g_list_append(service->dbus_sub_ids, GUINT_TO_POINTER(id));
- MESH_LOGD("[Signal subscribe] : PropertyChanged (%d)", id);
-
- /* End of subscription */
-}
-
-static void _on_unsubscribe_ids(gpointer data, gpointer user_data)
-{
- unsigned int id = GPOINTER_TO_UINT(data);
- mesh_service *service = (mesh_service*)user_data;
-
- MESH_LOGD("[Signal unsubscribe] : %d", id);
- g_dbus_connection_signal_unsubscribe(
- (GDBusConnection *)service->connection, id);
-}
-
-static void _meshd_unsubscribe_event(mesh_service *service)
-{
- meshd_check_null_ret("service", service);
-
- g_list_foreach(service->dbus_sub_ids, _on_unsubscribe_ids, service);
-
- g_list_free(service->dbus_sub_ids);
- service->dbus_sub_ids = NULL;
-}
-
-int meshd_dbus_start(mesh_service *service)
-{
- int rv;
-
- rv = _meshd_create_gdbus_call(service);
- if (MESHD_ERROR_NONE != rv)
- return rv;
-
- service->ca = g_cancellable_new();
-
- /* Create all required proxies here */
- _gproxy_connman = _proxy_get_connman(service);
- meshd_check_null_ret_error("_gproxy_connman", _gproxy_connman,
- MESHD_ERROR_IO_ERROR);
- g_dbus_proxy_set_default_timeout(
- G_DBUS_PROXY(_gproxy_connman), MESH_DBUS_PROXY_TIMEOUT);
-
- _gproxy_connman_mesh = _proxy_get_connman_mesh(service);
- meshd_check_null_ret_error("_gproxy_connman_mesh", _gproxy_connman_mesh,
- MESHD_ERROR_IO_ERROR);
- g_dbus_proxy_set_default_timeout(
- G_DBUS_PROXY(_gproxy_connman_mesh), MESH_DBUS_PROXY_TIMEOUT);
-
- _gproxy_connman_technology = _proxy_get_connman_technology(service);
- meshd_check_null_ret_error("_gproxy_connman_technology", _gproxy_connman_technology,
- MESHD_ERROR_IO_ERROR);
- g_dbus_proxy_set_default_timeout(
- G_DBUS_PROXY(_gproxy_connman_technology), MESH_DBUS_PROXY_TIMEOUT);
-
- _gproxy_connman_ethernet = _proxy_get_connman_ethernet(service);
- meshd_check_null_ret_error("_gproxy_connman_ethernet", _gproxy_connman_ethernet,
- MESHD_ERROR_IO_ERROR);
- g_dbus_proxy_set_default_timeout(
- G_DBUS_PROXY(_gproxy_connman_ethernet), MESH_DBUS_PROXY_TIMEOUT);
-
- /* Subscribe events */
- _meshd_subscribe_event(service);
-
- return MESHD_ERROR_NONE;
-}
-
-int meshd_dbus_stop(mesh_service *service)
-{
- int rv;
-
- if (NULL == service)
- return MESHD_ERROR_INVALID_PARAMETER;
-
- /* Unsubscribe events */
- _meshd_unsubscribe_event(service);
-
- /* Unref all proxies here */
- if (_gproxy_connman) {
- g_object_unref(_gproxy_connman);
- _gproxy_connman = NULL;
- }
- if (_gproxy_connman_mesh) {
- g_object_unref(_gproxy_connman_mesh);
- _gproxy_connman_mesh = NULL;
- }
- if (_gproxy_connman_technology) {
- g_object_unref(_gproxy_connman_technology);
- _gproxy_connman_technology = NULL;
- }
-
- g_cancellable_cancel(service->ca);
- g_object_unref(service->ca);
- service->ca = NULL;
-
- rv = _meshd_close_gdbus_call(service);
- return rv;
-}
-
-int mesh_gdbus_create_mesh_interface(mesh_service *service)
-{
- int ret = MESHD_ERROR_NONE;
- GVariant *variant = NULL;
- GError *error = NULL;
- GVariant *var_dict = NULL;
- GVariantDict dict;
- mesh_interface_s *info = NULL;
-
- meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("connection", service->connection,
- MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("_gproxy_connman_technology",
- _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
-
- info = service->interface_info;
-
- g_variant_dict_init(&dict, NULL);
- g_variant_dict_insert(&dict, "Ifname", "s", info->mesh_interface);
- g_variant_dict_insert(&dict, "ParentIfname", "s", info->base_interface);
- g_variant_dict_insert(&dict, "BridgeIfname", "s", info->bridge_interface);
- var_dict = g_variant_dict_end(&dict);
-
- variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
- g_variant_new("(sv)", "MeshInterfaceAdd", var_dict),
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, &error);
- if (variant) {
- MESH_LOGD("Successfully requested. [MeshInterfaceAdd]");
- } else if (error) {
- ret = MESHD_ERROR_IO_ERROR;
- MESH_LOGE("Failed DBus call [%s]", error->message);
-
- /* Interface not exists */
- if (g_strrstr(error->message, "No such device"))
- ret = MESHD_ERROR_INVALID_PARAMETER;
- g_error_free(error);
- }
-
- return ret;
-}
-
-int mesh_gdbus_remove_mesh_interface(mesh_service *service)
-{
- int ret = MESHD_ERROR_NONE;
- GVariant *variant = NULL;
- GError *error = NULL;
- GVariant *var_dict = NULL;
- GVariantDict dict;
- mesh_interface_s *info = NULL;
-
- meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("connection", service->connection,
- MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("_gproxy_connman_technology",
- _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
-
- info = service->interface_info;
-
- g_variant_dict_init(&dict, NULL);
- g_variant_dict_insert(&dict, "Ifname", "s", info->mesh_interface);
- var_dict = g_variant_dict_end(&dict);
-
- variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
- g_variant_new("(sv)", "MeshInterfaceRemove", var_dict),
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, &error);
- if (variant) {
- MESH_LOGD("Successfully requested. [MeshInterfaceRemove]");
- } else if (error) {
- ret = MESHD_ERROR_IO_ERROR;
- MESH_LOGE("Failed DBus call [%s]", error->message);
-
- /* Interface not exists (Not created yet) */
- if (g_strrstr(error->message, "No such device"))
- ret = MESHD_ERROR_NONE;
- g_error_free(error);
- }
-
- return ret;
-}
-
-int mesh_gdbus_mesh_scan(mesh_service *service)
-{
- meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("connection", service->connection,
- MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("_gproxy_connman_technology",
- _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
-
- g_dbus_proxy_call(_gproxy_connman_technology, "Scan",
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, NULL, NULL);
-
- MESH_LOGD("Successfully requested. [Scan]");
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_gdbus_mesh_specific_scan(mesh_service *service, gchar *mesh_id, gint channel)
-{
- GVariant *variant = NULL;
- GError *error = NULL;
- GVariant *var_dict = NULL;
- GVariantDict dict;
-
- enum nl80211_band band = (channel <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
- gushort freq = __channel_to_frequency(channel, band);
-
- meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("connection", service->connection,
- MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("_gproxy_connman_technology",
- _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
-
- g_variant_dict_init(&dict, NULL);
- g_variant_dict_insert(&dict, "Name", "s", mesh_id);
- g_variant_dict_insert(&dict, "Frequency", "q", freq);
- var_dict = g_variant_dict_end(&dict);
-
- variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
- g_variant_new("(sv)", "MeshSpecificScan", var_dict),
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, &error);
- if (variant) {
- MESH_LOGD("Successfully requested. [MeshSpecificScan]");
- } else if (error) {
- MESH_LOGE("Failed DBus call [%s]", error->message);
- g_error_free(error);
- return MESHD_ERROR_IO_ERROR;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_gdbus_mesh_cancel_scan(mesh_service *service)
-{
- int ret = MESHD_ERROR_NONE;
- GVariant *variant = NULL;
- GError *error = NULL;
- GVariant *var_dict = NULL;
- GVariantDict dict;
-
- meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("connection", service->connection,
- MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("_gproxy_connman_technology",
- _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
-
- g_variant_dict_init(&dict, NULL);
- var_dict = g_variant_dict_end(&dict);
-
- variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
- g_variant_new("(sv)", "AbortScan", var_dict),
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, &error);
- if (variant) {
- MESH_LOGD("Successfully requested. [AbortScan]");
- } else if (error) {
- ret = MESHD_ERROR_IO_ERROR;
- MESH_LOGE("Failed DBus call [%s]", error->message);
-
- /* Scan is not in progress */
- if (g_strrstr(error->message, "Already exists"))
- ret = MESHD_ERROR_NONE;
-
- g_error_free(error);
- }
-
- return ret;
-}
-
-static void _on_scan_result_destroy(gpointer data)
-{
- mesh_scan_result_s *scan_item = (mesh_scan_result_s *)data;
-
- if (scan_item) {
- g_free(scan_item->mesh_id);
- g_free(scan_item->bssid);
- g_free(scan_item->object_path);
- }
- g_free(scan_item);
-}
-
-static void _on_peer_info_destroy(gpointer data)
-{
- mesh_peer_info_s *peer = (mesh_peer_info_s *)data;
-
- if (peer)
- g_free(peer->address);
- g_free(peer);
-}
-
-static void _get_joined_network(mesh_service *service, GVariant *variant)
-{
- GVariantIter *peer = NULL;
- GVariantIter *property = NULL;
- gchar *key = NULL;
- GVariant *val = NULL;
- gsize len = 0;
- GVariant *child;
- const gchar* obj_path = NULL;
- const gchar* buf = NULL;
-
- g_variant_get(variant, "(a(oa{sv}))", &peer);
- while ((child = g_variant_iter_next_value(peer))) {
- mesh_network_info_s *joined_info = NULL;
- gboolean valid_state = TRUE;
-
- g_variant_get(child, "(oa{sv})", &obj_path, &property);
- MESH_LOGD(" Object: [%s]", obj_path);
- if (NULL == obj_path) {
- MESH_LOGE("Null object");
- continue;
- }
-
- /* Create an information structure for joined network */
- joined_info = g_try_new0(mesh_network_info_s, 1);
- if (NULL == joined_info) {
- MESH_LOGE("Failed to allocate !");
- return;
- }
-
- while (g_variant_iter_loop(property, "{sv}", &key, &val)) {
- if (strcasecmp(key, "Name") == 0) {
- buf = g_variant_get_string(val, &len);
- joined_info->mesh_id = g_strdup(buf);
- } else if (strcasecmp(key, "BSSID") == 0) {
- buf = g_variant_get_string(val, &len);
- joined_info->bssid = g_strdup(buf);
- } else if (strcasecmp(key, "State") == 0) {
- buf = g_variant_get_string(val, &len);
- MESH_LOGD(" State : %s", buf);
-
- /* Skip ignorable state */
- if (g_strcmp0(buf, "idle") == 0
- || g_strcmp0(buf, "disconnect") == 0
- || g_strcmp0(buf, "failure") == 0) {
- valid_state = FALSE;
- break;
- } else if (g_strcmp0(buf, "association") == 0) {
- joined_info->state = MESHD_CONNECTION_STATE_ASSOCIATION;
- } else if (g_strcmp0(buf, "configuration") == 0) {
- joined_info->state = MESHD_CONNECTION_STATE_CONFIGURATION;
- } else if (g_strcmp0(buf, "ready") == 0 || g_strcmp0(buf, "online") == 0) {
- joined_info->state = MESHD_CONNECTION_STATE_CONNECTED;
- }
- } else if (strcasecmp(key, "Security") == 0) {
- buf = g_variant_get_string(val, &len);
- if (g_strcmp0("sae", buf) == 0)
- joined_info->security = MESHD_SECURITY_SAE;
- else
- joined_info->security = MESHD_SECURITY_NONE;
- } else if (strcasecmp(key, "Frequency") == 0) {
- joined_info->channel = __frequency_to_channel(g_variant_get_uint16(val));
- }
- }
-
- /* Skip ignorable state */
- if (FALSE == valid_state) {
- g_free(joined_info->mesh_id);
- g_free(joined_info->bssid);
- continue;
- }
-
- MESH_LOGD(" Mesh ID : %s", joined_info->mesh_id);
- MESH_LOGD(" BSSID : %s", joined_info->bssid);
- MESH_LOGD(" Channel : %d", joined_info->channel);
- MESH_LOGD(" Security : %s",
- (MESHD_SECURITY_SAE == joined_info->security) ? "SAE" : "NONE");
- service->joined_network = joined_info;
-
- g_variant_iter_free(property);
-
- /* If found, stop loop iteration */
- break;
- }
- g_variant_iter_free(peer);
-}
-
-static void _get_mesh_peers(mesh_service *service, GVariant *variant)
-{
- GVariantIter *peer = NULL;
- GVariantIter *property = NULL;
- gchar *key = NULL;
- GVariant *val = NULL;
- gsize len = 0;
- GVariant *child;
- const gchar* obj_path = NULL;
-
- g_variant_get(variant, "(a(oa{sv}))", &peer);
- while ((child = g_variant_iter_next_value(peer))) {
- mesh_scan_result_s *scan_info = NULL;
-
- scan_info = g_try_new0(mesh_scan_result_s, 1);
- if (NULL == scan_info) {
- MESH_LOGE("Failed to allocate !");
- return;
- }
-
- g_variant_get(child, "(oa{sv})", &obj_path, &property);
- if (NULL == obj_path) {
- MESH_LOGE("Null object");
- g_free(scan_info);
- continue;
- }
- MESH_LOGD(" Obj path : [%s]", obj_path);
- scan_info->object_path = g_strdup(obj_path);
-
- while (g_variant_iter_loop(property, "{sv}", &key, &val)) {
- if (strcasecmp(key, "Name") == 0) {
- const char *buf = g_variant_get_string(val, &len);
- scan_info->mesh_id = g_strdup(buf);
- MESH_LOGD(" Mesh ID : %s", scan_info->mesh_id);
- } else if (strcasecmp(key, "BSSID") == 0) {
- const char *buf = g_variant_get_string(val, &len);
- scan_info->bssid = g_strdup(buf);
- MESH_LOGD(" BSSID : %s", scan_info->bssid);
- } else if (strcasecmp(key, "State") == 0) {
- const char *buf = g_variant_get_string(val, &len);
- MESH_LOGD(" State : %s", buf);
-
- if (g_strcmp0(buf, "idle") == 0
- || g_strcmp0(buf, "disconnect") == 0
- || g_strcmp0(buf, "failure") == 0) {
- scan_info->state = MESHD_CONNECTION_STATE_DISCONNECTED;
- } else if (g_strcmp0(buf, "association") == 0) {
- scan_info->state = MESHD_CONNECTION_STATE_ASSOCIATION;
- } else if (g_strcmp0(buf, "configuration") == 0) {
- scan_info->state = MESHD_CONNECTION_STATE_CONFIGURATION;
- } else if (g_strcmp0(buf, "ready") == 0 || g_strcmp0(buf, "online") == 0) {
- scan_info->state = MESHD_CONNECTION_STATE_CONNECTED;
- }
- } else if (strcasecmp(key, "Security") == 0) {
- const char *buf = g_variant_get_string(val, &len);
- MESH_LOGD(" Security : %s", buf);
- if (g_strcmp0("sae", buf) == 0)
- scan_info->security = MESHD_SECURITY_SAE;
- else
- scan_info->security = MESHD_SECURITY_NONE;
- } else if (strcasecmp(key, "Frequency") == 0) {
- scan_info->channel = __frequency_to_channel(g_variant_get_uint16(val));
- MESH_LOGD(" Channel : %d", scan_info->channel);
- } else if (strcasecmp(key, "Favorite") == 0) {
- const char *buf = g_variant_get_string(val, &len);
- MESH_LOGD(" Favorite : %s", buf);
- } else if (strcasecmp(key, "Strength") == 0) {
- scan_info->rssi = (gint)g_variant_get_byte(val);
- MESH_LOGD(" RSSI : %d", scan_info->rssi);
- }
- }
- /* Last element */
- service->scanned_mesh_network =
- g_list_prepend(service->scanned_mesh_network, scan_info);
-
- g_variant_iter_free(property);
- }
- g_variant_iter_free(peer);
-}
-
-static void _get_connected_mesh_peers(mesh_service *service, GVariant *variant)
-{
- GVariantIter *peer = NULL;
- GVariant *val = NULL;
- gsize len = 0;
- GVariant *child;
- GVariant *dict = NULL;
-
- g_variant_get(variant, "(a(a{sv}))", &peer);
- while ((child = g_variant_iter_next_value(peer))) {
- mesh_peer_info_s *peer_info = NULL;
-
- peer_info = g_try_new0(mesh_peer_info_s, 1);
- if (NULL == peer_info) {
- MESH_LOGE("Failed to allocate !");
- return;
- }
-
- /* a{sv} <- (a{sv}) */
- dict = g_variant_get_child_value(child, 0);
- val = g_variant_lookup_value(dict, "PeerAddress", NULL);
- if (NULL != val) {
- const char *buf = g_variant_get_string(val, &len);
- peer_info->address = g_strdup(buf);
- MESH_LOGD(" Address : %s", peer_info->address);
- g_variant_unref(val);
- } else {
- MESH_LOGE("Unable to get address !");
- g_free(peer_info);
- continue;
- }
-
- service->connected_mesh_peers =
- g_list_prepend(service->connected_mesh_peers, peer_info);
- }
- g_variant_iter_free(peer);
-}
-
-int mesh_gdbus_get_mesh_networks(mesh_service *service)
-{
- GVariant *variant = NULL;
- GError *error = NULL;
-
- meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("connection", service->connection,
- MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("_gproxy_connman",
- _gproxy_connman, MESHD_ERROR_IO_ERROR);
-
- variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetMeshPeers",
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, &error);
- if (variant) {
- MESH_LOGD("Successfully requested. [GetMeshPeers]");
-
- if (service->scanned_mesh_network) {
- g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy);
- service->scanned_mesh_network = NULL;
- }
-
- _get_mesh_peers(service, variant);
-
- /* List item is saved with reversed order for efficiency. */
- service->scanned_mesh_network =
- g_list_reverse(service->scanned_mesh_network);
- } else if (error) {
- MESH_LOGE("Failed DBus call [%s]", error->message);
- g_error_free(error);
- return MESHD_ERROR_IO_ERROR;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_gdbus_get_joined_mesh_network(mesh_service *service)
-{
- GVariant *variant = NULL;
- GError *error = NULL;
-
- meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("connection", service->connection,
- MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("_gproxy_connman",
- _gproxy_connman, MESHD_ERROR_IO_ERROR);
-
- variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetMeshPeers",
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, &error);
- if (variant) {
- MESH_LOGD("Successfully requested. [GetMeshPeers]");
-
- if (service->joined_network) {
- g_free(service->joined_network->mesh_id);
- g_free(service->joined_network->bssid);
- g_free(service->joined_network);
- service->joined_network = NULL;
- }
-
- _get_joined_network(service, variant);
- } else if (error) {
- MESH_LOGE("Failed DBus call [%s]", error->message);
- g_error_free(error);
- return MESHD_ERROR_IO_ERROR;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_gdbus_get_connected_peers(mesh_service *service)
-{
- GVariant *variant = NULL;
- GError *error = NULL;
-
- meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("connection", service->connection,
- MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("_gproxy_connman",
- _gproxy_connman, MESHD_ERROR_IO_ERROR);
-
- variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetConnectedMeshPeers",
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, &error);
- if (variant) {
- MESH_LOGD("Successfully requested. [GetConnectedMeshPeers]");
-
- if (service->connected_mesh_peers) {
- g_list_free_full(service->connected_mesh_peers, _on_peer_info_destroy);
- service->connected_mesh_peers = NULL;
- }
-
- _get_connected_mesh_peers(service, variant);
-
- /* List item is saved with reversed order for efficiency. */
- service->connected_mesh_peers =
- g_list_reverse(service->connected_mesh_peers);
- } else if (error) {
- MESH_LOGE("Failed DBus call [%s]", error->message);
- g_error_free(error);
- return MESHD_ERROR_IO_ERROR;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-static void _get_mesh_property(GVariant *variant, mesh_network_info_s *result)
-{
- GVariantIter *property = NULL;
- gchar *key = NULL;
- GVariant *val = NULL;
- gsize len = 0;
-
- MESH_LOGD("Type [%s]", g_variant_get_type_string(variant));
-
- g_variant_get(variant, "(a{sv})", &property);
-
- while (g_variant_iter_loop(property, "{sv}", &key, &val)) {
- if (strcasecmp(key, "Name") == 0) {
- const char *buf = g_variant_get_string(val, &len);
- result->mesh_id = g_strdup(buf);
- MESH_LOGD(" Mesh ID : %s", result->mesh_id);
- } else if (strcasecmp(key, "BSSID") == 0) {
- const char *buf = g_variant_get_string(val, &len);
- result->bssid = g_strdup(buf);
- MESH_LOGD(" BSSID : %s", result->bssid);
- } else if (strcasecmp(key, "State") == 0) {
- const char *buf = g_variant_get_string(val, &len);
- MESH_LOGD(" State : %s", buf);
-
- if (g_strcmp0(buf, "idle") == 0
- || g_strcmp0(buf, "disconnect") == 0
- || g_strcmp0(buf, "failure") == 0) {
- result->state = MESHD_CONNECTION_STATE_DISCONNECTED;
- } else if (g_strcmp0(buf, "association") == 0) {
- result->state = MESHD_CONNECTION_STATE_ASSOCIATION;
- } else if (g_strcmp0(buf, "configuration") == 0) {
- result->state = MESHD_CONNECTION_STATE_CONFIGURATION;
- } else if (g_strcmp0(buf, "ready") == 0 || g_strcmp0(buf, "online") == 0) {
- result->state = MESHD_CONNECTION_STATE_CONNECTED;
- }
- } else if (strcasecmp(key, "Security") == 0) {
- const char *buf = g_variant_get_string(val, &len);
- MESH_LOGD(" Security : %s", buf);
- if (g_strcmp0("sae", buf) == 0)
- result->security = MESHD_SECURITY_SAE;
- else
- result->security = MESHD_SECURITY_NONE;
- } else if (strcasecmp(key, "Frequency") == 0) {
- result->channel = __frequency_to_channel(g_variant_get_uint16(val));
- MESH_LOGD(" Channel : %d", result->channel);
- } else if (strcasecmp(key, "Favorite") == 0) {
- const char *buf = g_variant_get_string(val, &len);
- MESH_LOGD(" Favorite : %s", buf);
- } else if (strcasecmp(key, "Strength") == 0) {
- gint rssi = (gint)g_variant_get_byte(val);
- MESH_LOGD(" RSSI : %d", rssi);
- }
- }
- g_variant_iter_free(property);
-}
-
-static int _mesh_gdbus_get_mesh_network_property(mesh_service *service,
- const gchar* object_path, mesh_network_info_s *result)
-{
- GVariant *variant = NULL;
- GError *error = NULL;
-
- meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("connection", service->connection,
- MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("result", result, MESHD_ERROR_INVALID_PARAMETER);
-
- variant = g_dbus_connection_call_sync(service->connection,
- CONNMAN_SERVER_NAME,
- object_path,
- CONNMAN_INTERFACE_MESH,
- "GetProperties",
- NULL, NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, &error);
- if (variant) {
- MESH_LOGD("Successfully requested. [GetProperties]");
-
- /* Get properties */
- _get_mesh_property(variant, result);
- } else if (error) {
- LOGE("Failed DBus call [%s]", error->message);
- g_error_free(error);
- return MESHD_ERROR_IO_ERROR;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_gdbus_create_network(mesh_service *service, gchar *mesh_id,
- gint channel, meshd_security_type_e sec)
-{
- GVariant *variant = NULL;
- GError *error = NULL;
- GVariant *var_dict = NULL;
- GVariantBuilder builder;
- const gchar* security = (MESHD_SECURITY_SAE == sec) ? "sae" : "none";
-
- enum nl80211_band band = (channel <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
- gushort freq = __channel_to_frequency(channel, band);
-
- meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("connection", service->connection,
- MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("_gproxy_connman_technology",
- _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
-
- g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
- g_variant_builder_open(&builder, G_VARIANT_TYPE("a{sv}"));
-
- g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
- g_variant_builder_add(&builder, "s", "Name");
- g_variant_builder_add(&builder, "v", g_variant_new_string(mesh_id));
- g_variant_builder_close(&builder); /* {sv} */
-
- g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
- g_variant_builder_add(&builder, "s", "Frequency");
- g_variant_builder_add(&builder, "v", g_variant_new_uint16(freq));
- g_variant_builder_close(&builder); /* {sv} */
-
- g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
- g_variant_builder_add(&builder, "s", "Security");
- g_variant_builder_add(&builder, "v", g_variant_new_string(security));
- g_variant_builder_close(&builder); /* {sv} */
-
- g_variant_builder_close(&builder); /* a{sv} */
-
- var_dict = g_variant_builder_end(&builder);
-
- variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
- g_variant_new("(sv)", "MeshCreateNetwork", var_dict),
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, &error);
- if (variant) {
- MESH_LOGD("Successfully requested. [MeshCreateNetwork]");
- } else if (error) {
- MESH_LOGE("Failed DBus call [%s]", error->message);
- g_error_free(error);
- return MESHD_ERROR_IO_ERROR;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_gdbus_set_passphrase(mesh_service *service, mesh_scan_result_s *info, gchar *passphrase)
-{
- GVariant *variant = NULL;
- GError *error = NULL;
-
- meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("passphrase", passphrase, MESHD_ERROR_INVALID_PARAMETER);
-
- variant = g_dbus_connection_call_sync(service->connection,
- CONNMAN_SERVER_NAME,
- info->object_path,
- CONNMAN_INTERFACE_MESH,
- "SetProperty",
- g_variant_new("(sv)", "Passphrase", g_variant_new_string(passphrase)),
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, &error);
- if (variant) {
- MESH_LOGD("Successfully requested. [SetProperty]");
- } else if (error) {
- LOGE("Failed DBus call [%s]", error->message);
- g_error_free(error);
- return MESHD_ERROR_IO_ERROR;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-#if 0
-static void on_response_connect_network(GObject *source_object,
- GAsyncResult *res, gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- GError *error = NULL;
- GVariant *variant = NULL;
-
- NOTUSED(user_data);
-
- variant = g_dbus_connection_call_finish(
- G_DBUS_CONNECTION(source_object), res, &error);
- if (variant) {
- MESH_LOGD("Successfully requested. [Connect]");
-
- /* TODO: Unregister property change event */
- } else if (error) {
- ret = MESHD_ERROR_IO_ERROR;
- LOGE("Failed DBus call [%s]", error->message);
-
- if (g_strrstr(error->message, "Already exists"))
- ret = MESHD_ERROR_ALREADY_REGISTERED;
- else if (g_strrstr(error->message, "In progress"))
- ret = MESHD_ERROR_IN_PROGRESS;
- else
- ret = MESHD_ERROR_IO_ERROR;
-
- g_error_free(error);
- }
-}
-#endif
-
-int mesh_gdbus_connect_network(mesh_service *service, mesh_scan_result_s *info)
-{
- meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("info", info, MESHD_ERROR_INVALID_PARAMETER);
-
- g_dbus_connection_call(service->connection,
- CONNMAN_SERVER_NAME,
- info->object_path,
- CONNMAN_INTERFACE_MESH,
- "Connect",
- NULL, NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL, /* G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED */
- NULL, NULL);
- MESH_LOGD("Successfully requested. [Connect]");
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_gdbus_disconnect_network(mesh_service *service, mesh_scan_result_s *info)
-{
- GVariant *variant = NULL;
- GError *error = NULL;
-
- meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("info", info, MESHD_ERROR_INVALID_PARAMETER);
-
- variant = g_dbus_connection_call_sync(service->connection,
- CONNMAN_SERVER_NAME,
- info->object_path,
- CONNMAN_INTERFACE_MESH,
- "Disconnect",
- NULL, NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, &error);
- if (variant) {
- MESH_LOGD("Successfully requested. [Disconnect]");
- } else if (error) {
- LOGE("Failed DBus call [%s]", error->message);
- g_error_free(error);
- return MESHD_ERROR_IO_ERROR;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_gdbus_remove_network(mesh_service *service, mesh_scan_result_s *info)
-{
- GVariant *variant = NULL;
- GError *error = NULL;
-
- meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("info", info, MESHD_ERROR_INVALID_PARAMETER);
-
- variant = g_dbus_connection_call_sync(service->connection,
- CONNMAN_SERVER_NAME,
- info->object_path,
- CONNMAN_INTERFACE_MESH,
- "Remove",
- NULL, NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, &error);
- if (variant) {
- MESH_LOGD("Successfully requested. [Remove]");
- } else if (error) {
- LOGE("Failed DBus call [%s]", error->message);
- g_error_free(error);
- return MESHD_ERROR_IO_ERROR;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-
-int mesh_gdbus_enable_ethernet_interface(mesh_service *service, bool state)
-{
- int ret = MESHD_ERROR_NONE;
- GVariant *variant = NULL;
- GError *error = NULL;
- mesh_interface_s *info = NULL;
-
- meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("connection", service->connection,
- MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("_gproxy_connman_technology",
- _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
-
- info = service->interface_info;
- meshd_check_null_ret_error("info", info, MESHD_ERROR_INVALID_PARAMETER);
-
- variant = g_dbus_proxy_call_sync(_gproxy_connman_ethernet, "SetProperty",
- g_variant_new("(sv)", "Powered", g_variant_new_boolean(state)),
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, &error);
- if (variant) {
- MESH_LOGD("Successfully requested. [Powered]");
- } else if (error) {
- ret = MESHD_ERROR_IO_ERROR;
- MESH_LOGE("Failed DBus call [%s]", error->message);
-
- /* Interface not exists (Not created yet) */
- if (g_strrstr(error->message, "No such device"))
- ret = MESHD_ERROR_NONE;
- g_error_free(error);
- }
-
- return ret;
-}
-
-int mesh_gdbus_set_mesh_gate(mesh_service *service)
-{
- int ret = MESHD_ERROR_NONE;
- GVariant *variant = NULL;
- GError *error = NULL;
- GVariant *var_dict = NULL;
- GVariantDict dict;
- mesh_interface_s *info = NULL;
-
- meshd_check_null_ret_error("service", service, MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("connection", service->connection,
- MESHD_ERROR_INVALID_PARAMETER);
- meshd_check_null_ret_error("_gproxy_connman_technology",
- _gproxy_connman_technology, MESHD_ERROR_IO_ERROR);
-
- info = service->interface_info;
-
- g_variant_dict_init(&dict, NULL);
- g_variant_dict_insert(&dict, "GateAnnounce", "b", info->gate_announce);
- g_variant_dict_insert(&dict, "HWMPRootMode", "q", info->hwmp_root_mode);
- g_variant_dict_insert(&dict, "STP", "q", info->stp);
- var_dict = g_variant_dict_end(&dict);
-
- variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
- g_variant_new("(sv)", "SetMeshGate", var_dict),
- G_DBUS_CALL_FLAGS_NONE,
- -1, NULL, &error);
- if (variant) {
- MESH_LOGD("Successfully requested. [SetMeshGate]");
- } else if (error) {
- ret = MESHD_ERROR_IO_ERROR;
- MESH_LOGE("Failed DBus call [%s]", error->message);
-
- /* Interface not exists */
- if (g_strrstr(error->message, "No such device"))
- ret = MESHD_ERROR_INVALID_PARAMETER;
- g_error_free(error);
- }
-
- return ret;
-}
-
+++ /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 <glib.h>
-#include <gio/gio.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <net/if.h>
-#include <arpa/inet.h>
-#include <sys/ioctl.h>
-#include <sys/wait.h>
-
-#include <errno.h>
-
-#include "mesh.h"
-#include "mesh-log.h"
-#include "mesh-util.h"
-#include "mesh-service.h"
-#include "mesh-interface.h"
-
-#define IPV4_MAX_LENGTH 16
-#define BUF_LENGTH 256
-
-#define MESH_DEFAULT_BASE_INTERFACE "wlan0"
-#define MESH_DEFAULT_MESH_INTERFACE "mesh0"
-#define MESH_DEFAULT_BRIDGE_INTERFACE "br0"
-#define MESH_DEFAULT_EXTERNAL_INTERFACE "eth0"
-#define MESH_DEFAULT_SOFTAP_INTERFACE "wlan1"
-
-typedef enum {
- ETHERNET_CABLE_DETACHED = 0,
- ETHERNET_CABLE_ATTACHED
-} cable_state_e;
-
-int mesh_interface_set(const char *interface, const char* ip_addr,
- mesh_set_interface_type_e type)
-{
- int sock = 0;
- struct ifreq ifr;
- int ret = 0;
-
- char ip[IPV4_MAX_LENGTH] = {0,};
- char buf[BUF_LENGTH] = {0,};
-
- if (interface == NULL) {
- MESH_LOGE("Invalid interface name !");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- sock = socket(AF_INET, SOCK_STREAM, 0);
- if (sock < 0) {
- MESH_LOGE("Cannot open network interface socket");
- return MESHD_ERROR_IO_ERROR;
- }
-
- MESH_LOGD("Initialize interface [%s]...", interface);
- snprintf(ifr.ifr_name, IFNAMSIZ, "%s", interface);
-
- /* Set IP Address */
- if (NULL != ip_addr) {
- struct sockaddr_in sai;
- memset(&sai, 0, sizeof(struct sockaddr_in));
- sai.sin_family = AF_INET;
- sai.sin_port = 0;
- snprintf(ip, IPV4_MAX_LENGTH, "%s", ip_addr);
-
- MESH_LOGD("Setting IP address: [%s]\n", ip);
- if (!inet_aton(ip, &sai.sin_addr)) {
- MESH_LOGE("Failed to convert ip address");
- close(sock);
- return MESHD_ERROR_OPERATION_FAILED;
- }
-
- memcpy(&ifr.ifr_addr, &sai, sizeof(sai));
-
- ret = ioctl(sock, SIOCSIFADDR, &ifr);
- if (ret < 0) {
- (void) strerror_r(errno, buf, BUF_LENGTH);
- MESH_LOGE("Failed to set IP[%s] for interface[%s] : %s",
- ip, ifr.ifr_name, buf);
- }
- }
-
- /* Get status flag */
- if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
- (void) strerror_r(errno, buf, BUF_LENGTH);
- MESH_LOGE("Failed to get interface[%s] status : %s",
- ifr.ifr_name, buf);
- }
- snprintf(ifr.ifr_name, IFNAMSIZ, "%s", interface);
-
- /* Set status flag */
- if (MESH_INTERFACE_UP == type) {
- ifr.ifr_flags |= (IFF_UP);
- if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
- (void) strerror_r(errno, buf, BUF_LENGTH);
- MESH_LOGE("Failed to change interface[%s] status UP : %s",
- ifr.ifr_name, buf);
- }
- } else if (MESH_INTERFACE_DOWN == type) {
- ifr.ifr_flags &= (~IFF_UP);
- if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
- (void) strerror_r(errno, buf, BUF_LENGTH);
- MESH_LOGE("Failed to change interface[%s] status DOWN : %s",
- ifr.ifr_name, buf);
- }
- } else {
- MESH_LOGD("Do not change up/down status");
- }
-
- close(sock);
- return MESHD_ERROR_NONE;
-}
-
-#if 0
-/* Returns interface name in sequence order which is exists */
-static char* _get_interface_exists_in_seq(const char* prefix)
-{
- char *res = NULL;
- char buf[32];
- int ret;
- int i = 0;
- const int IF_INDEX_MAX = 9;
-
- for (i = 0; i <= IF_INDEX_MAX; i++) {
- snprintf(buf, sizeof(buf), "/sys/class/net/%s%d", prefix, i);
-
- ret = access(buf, F_OK);
- if (ret >= 0) {
- /* This name is exists. use it */
- snprintf(buf, sizeof(buf), "%s%d", prefix, i);
- res = g_strdup(buf);
- MESH_LOGD(" use [%s]", res);
- break;
- }
- }
-
- return res;
-}
-
-/* Returns interface name in sequence order which is exists */
-static char* _get_interface_not_exists_in_seq(const char* prefix)
-{
- char *res = NULL;
- char buf[32];
- int ret;
- int i = 0;
- const int IF_INDEX_MAX = 9;
-
- for (i = 0; i <= IF_INDEX_MAX; i++) {
- snprintf(buf, sizeof(buf), "/sys/class/net/%s%d", prefix, i);
-
- ret = access(buf, F_OK);
- if (ret < 0) {
- /* This name is not exists. use it */
- snprintf(buf, sizeof(buf), "%s%d", prefix, i);
- res = g_strdup(buf);
- MESH_LOGD(" use [%s]", res);
- break;
- }
- }
-
- return res;
-}
-#endif
-
-static bool _check_interface_exists(const char* if_name)
-{
- int ret;
- char buf[32];
- int i = 0;
- const int IF_INDEX_MAX = 9;
-
- for (i = 0; i <= IF_INDEX_MAX; i++) {
- snprintf(buf, sizeof(buf), "/sys/class/net/%s", if_name);
-
- ret = access(buf, F_OK);
- if (ret >= 0) {
- /* This name is exists. */
- return true;
- }
- }
-
- return false;
-}
-
-/* Check if interface is bridged */
-static bool _check_bridge_interface_exists(const char* bridge, const char* if_name)
-{
- int ret;
- char buf[32];
- int i = 0;
- const int IF_INDEX_MAX = 9;
-
- for (i = 0; i <= IF_INDEX_MAX; i++) {
- snprintf(buf, sizeof(buf), "/sys/class/net/%s/brif/%s", bridge, if_name);
-
- ret = access(buf, F_OK);
- if (ret >= 0) {
- /* This name is exists. */
- return true;
- }
- }
-
- return false;
-}
-
-char* mesh_interface_get_address(const char* if_name)
-{
- FILE *pf;
- char buf[32] = { 0, };
- char *result = NULL;
-
- snprintf(buf, sizeof(buf), "/sys/class/net/%s/address", if_name);
- pf = fopen(buf, "r");
- if (NULL != pf) {
- fgets(buf, 31, pf);
- MESH_LOGD("Interface[%s] address[%s]", if_name, buf);
-
- if (strlen(buf) > 0)
- result = g_strdup(buf);
-
- fclose(pf);
- }
-
- return result;
-}
-
-int mesh_interface_initialize(mesh_interface_s *info)
-{
- if (NULL == info) {
- MESH_LOGE("Invalid parameter");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- info->bridge_interface = g_strdup(MESH_DEFAULT_BRIDGE_INTERFACE);
- if (NULL == info->bridge_interface) {
- MESH_LOGE("Failed to get bridge interface !");
- return MESHD_ERROR_OPERATION_FAILED;
- }
-
- info->base_interface = g_strdup(MESH_DEFAULT_BASE_INTERFACE);
- if (NULL == info->bridge_interface) {
- MESH_LOGE("Failed to get base interface !");
- return MESHD_ERROR_OPERATION_FAILED;
- }
-
- info->mesh_interface = g_strdup(MESH_DEFAULT_MESH_INTERFACE);
- if (NULL == info->bridge_interface) {
- MESH_LOGE("Failed to get mesh interface !");
- return MESHD_ERROR_OPERATION_FAILED;
- }
-
- info->softap_interface = g_strdup(MESH_DEFAULT_SOFTAP_INTERFACE);
- info->external_interface = g_strdup(MESH_DEFAULT_EXTERNAL_INTERFACE);
-
- MESH_LOGD("Interface configuration for mesh network :");
- MESH_LOGD(" Base : [%s]", info->base_interface);
- MESH_LOGD(" Mesh : [%s]", info->mesh_interface);
- MESH_LOGD(" Bridge : [%s]", info->bridge_interface);
- MESH_LOGD(" SoftAP : [%s]", info->softap_interface);
- MESH_LOGD(" External: [%s]", info->external_interface);
-
- return MESHD_ERROR_NONE;
-}
-
-static int _check_ethernet_cable_plugin_status(const char* interface,
- cable_state_e *status)
-{
- FILE *fd = NULL;
- int ret = -1;
- int rv = 0;
- char error_buf[256] = {0, };
- char file_path[256] = {0, };
-
- snprintf(file_path, 256, "/sys/class/net/%s/carrier", interface);
-
- if (0 == access(file_path, F_OK)) {
- fd = fopen(file_path, "r");
- if (fd == NULL) {
- MESH_LOGE("Error! Could not open /sys/class/net/%s/carrier file",
- interface);
- return MESHD_ERROR_IO_ERROR;
- }
- } else {
- MESH_LOGE("Error! Could not access /sys/class/net/%s/carrier file",
- interface);
- return MESHD_ERROR_IO_ERROR;
- }
-
- errno = 0;
- rv = fscanf(fd, "%d", &ret);
- if (rv < 0) {
- strerror_r(errno, error_buf, 256);
- MESH_LOGE("Error! Failed to read from file, rv:[%d], error:[%s]",
- rv, error_buf);
- fclose(fd);
- return MESHD_ERROR_IO_ERROR;
- }
-
- if (ret == 1) {
- MESH_LOGD("/sys/class/net/%s/carrier : [%d]", interface, ret);
- *status = ETHERNET_CABLE_ATTACHED;
- } else if (ret == 0) {
- MESH_LOGD("/sys/class/net/%s/carrier : [%d]", interface, ret);
- *status = ETHERNET_CABLE_DETACHED;
- }
-
- fclose(fd);
- return MESHD_ERROR_NONE;
-}
-
-int mesh_interface_check_external_exists(const char* external_interface, bool *state)
-{
- /* TODO: Current logic checks only ethernet interface.
- This logic should consider wireless interface if can */
- int ret = MESHD_ERROR_NONE;
- cable_state_e cable_state = ETHERNET_CABLE_DETACHED;
-
- if (NULL == external_interface || NULL == state)
- return MESHD_ERROR_INVALID_PARAMETER;
-
- bool ex = _check_interface_exists(external_interface);
- if (FALSE == ex) {
- MESH_LOGE("External interface[%s] was not found.", external_interface);
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- /* If external interface seems Ethernet, check cable state */
- if (g_str_has_prefix(external_interface, "eth")) {
- ret = _check_ethernet_cable_plugin_status(external_interface, &cable_state);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to get Ethernet cable state");
- return MESHD_ERROR_OPERATION_FAILED;
- }
- }
-
- *state = FALSE;
- if (ETHERNET_CABLE_ATTACHED == cable_state)
- *state = TRUE;
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_interface_check(const char* interface)
-{
- bool ex = FALSE;
-
- if (NULL == interface || strlen(interface) == 0)
- return MESHD_ERROR_INVALID_PARAMETER;
-
- ex = _check_interface_exists(interface);
- if (FALSE == ex) {
- MESH_LOGE("Interface[%s] was not found.", interface);
- return MESHD_ERROR_NO_DATA;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_interface_check_bridge_interface_exists(const char* bridge, const char* interface)
-{
- bool ex = FALSE;
-
- if (NULL == bridge || NULL == interface ||
- strlen(bridge) == 0 || strlen(interface) == 0)
- return MESHD_ERROR_INVALID_PARAMETER;
-
- ex = _check_bridge_interface_exists(bridge, interface);
- if (FALSE == ex) {
- MESH_LOGE("Interface[%s] was not found.", interface);
- return MESHD_ERROR_NO_DATA;
- }
-
- return MESHD_ERROR_NONE;
-}
-
+++ /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 <glib.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <net/if.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <netlink/genl/genl.h>
-#include <netlink/genl/family.h>
-#include <netlink/genl/ctrl.h>
-#include <netlink/msg.h>
-#include <netlink/attr.h>
-#include <netlink/netlink.h>
-
-#include "mesh.h"
-#include "mesh-log.h"
-#include "mesh-util.h"
-#include "mesh-netlink.h"
-#include "mesh-request.h"
-
-#include <linux/nl80211.h>
-//#include "nl80211.h"
-
-#define MESH_PARAM_HWMP_ROOTMODE "mesh_hwmp_rootmode"
-#define MESH_PARAM_GATE_ANNOUNCE "mesh_gate_announcements"
-#define MAX_MAC_ADDR_LEN 18
-#define ETH_ALEN 6
-
-#define BIT(x) (1ULL<<(x))
-
-typedef enum {
- MESH_NL_CALLBACK_FINISHED = 0,
- MESH_NL_CALLBACK_TRYING,
-} mesh_nl_callback_state_e;
-
-typedef struct {
- int nl80211_id;
- int callback_state;
- guint event_source;
-
- struct nl_sock *nl_socket;
- struct nl_msg *msg;
- struct nl_cb *cb;
- struct nl_cb *s_cb;
-
- bool error_occured;
- GList **station_list;
- GList **mpath_list;
-} mesh_nl_state;
-
-typedef struct {
- const char *group;
- int id;
-} multicast_group_id_args;
-
-enum plink_state {
- LISTEN,
- OPN_SNT,
- OPN_RCVD,
- CNF_RCVD,
- ESTAB,
- HOLDING,
- BLOCKED
-};
-
-/* For event handler */
-static mesh_nl_state *event_state = NULL;
-
-static int __initialize_nl80211(mesh_nl_state *state)
-{
- int err = MESHD_ERROR_NONE;
-
- state->nl_socket = nl_socket_alloc();
- if (!state->nl_socket) {
- MESH_LOGE("Failed to allocate netlink socket.");
- return MESHD_ERROR_OUT_OF_MEMORY;
- }
-
- if (genl_connect(state->nl_socket)) {
- MESH_LOGE("Failed to connect to generic netlink.");
- err = MESHD_ERROR_OPERATION_FAILED;
- goto DESTROY;
- }
-
- nl_socket_set_buffer_size(state->nl_socket, 8192, 8192);
-
- state->nl80211_id = genl_ctrl_resolve(state->nl_socket, "nl80211");
- if (state->nl80211_id < 0) {
- MESH_LOGE("nl80211 not found.");
- err = MESHD_ERROR_NO_DATA;
- goto DESTROY;
- }
-
- return 0;
-
-DESTROY:
- nl_socket_free(state->nl_socket);
- return err;
-}
-
-static void __clean_nl80211(mesh_nl_state *state)
-{
- if (!state)
- return;
-
- if (state->nl_socket) {
- nl_socket_free(state->nl_socket);
- state->nl_socket = NULL;
- state->nl80211_id = -1;
- }
-}
-
-static int __get_device_index_from_string(const char* if_name, int *index)
-{
- int device_index = 0;
-
- if (NULL == if_name) {
- MESH_LOGE("Invalid parameter");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- device_index = if_nametoindex(if_name);
- if (device_index == 0) {
- MESH_LOGE("No interface index found [%s]", if_name);
- return MESHD_ERROR_NO_DATA;
- }
- *index = device_index;
-
- return MESHD_ERROR_NONE;
-}
-
-static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
-{
- mesh_nl_state *state = (mesh_nl_state *)arg;
- char buf[256] = { 0, };
-
- NOTUSED(nla);
-
- state->callback_state = MESH_NL_CALLBACK_FINISHED;
- state->error_occured = TRUE;
- strerror_r(err->error, buf, 255);
-
- MESH_LOGD("error_handler");
- MESH_LOGE(" %s (%d)", buf, err->error);
-
- return NL_STOP;
-}
-
-static int finish_handler(struct nl_msg *msg, void *arg)
-{
- mesh_nl_state *state = (mesh_nl_state *)arg;
-
- state->callback_state = MESH_NL_CALLBACK_FINISHED;
-
- MESH_LOGD("finish_handler");
- NOTUSED(msg);
-
- return NL_SKIP;
-}
-
-static int ack_handler(struct nl_msg *msg, void *arg)
-{
- mesh_nl_state *state = (mesh_nl_state *)arg;
-
- state->callback_state = MESH_NL_CALLBACK_FINISHED;
-
- MESH_LOGD("ack_handler");
- NOTUSED(msg);
-
- return NL_STOP;
-}
-
-static int ack_simple_handler(struct nl_msg *msg, void *arg)
-{
- int *ret = arg;
-
- (void) msg;
- *ret = 0;
-
- MESH_LOGD("ack_simple_handler");
-
- return NL_STOP;
-}
-
-static int family_handler(struct nl_msg *msg, void *arg)
-{
- multicast_group_id_args *group = (multicast_group_id_args *)arg;
- struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
- struct nlattr *tb[CTRL_ATTR_MAX + 1];
- struct nlattr *mcast_group;
- int rem_mcast_group;
-
- MESH_LOGD("family_handler");
-
- nla_parse(tb, CTRL_ATTR_MAX,
- genlmsg_attrdata(gnlh, 0),
- genlmsg_attrlen(gnlh, 0), NULL);
- if (!tb[CTRL_ATTR_MCAST_GROUPS])
- return NL_SKIP;
-
- nla_for_each_nested(mcast_group, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcast_group) {
- struct nlattr *tb_mcast_group[CTRL_ATTR_MCAST_GRP_MAX + 1];
-
- nla_parse(tb_mcast_group, CTRL_ATTR_MCAST_GRP_MAX,
- nla_data(mcast_group), nla_len(mcast_group), NULL);
-
- if (!tb_mcast_group[CTRL_ATTR_MCAST_GRP_NAME] ||
- !tb_mcast_group[CTRL_ATTR_MCAST_GRP_ID])
- continue;
-
- if (strncmp(nla_data(tb_mcast_group[CTRL_ATTR_MCAST_GRP_NAME]),
- group->group,
- nla_len(tb_mcast_group[CTRL_ATTR_MCAST_GRP_NAME])))
- continue;
-
- group->id = nla_get_u32(tb_mcast_group[CTRL_ATTR_MCAST_GRP_ID]);
- MESH_LOGD("mcast group id [%d]", group->id);
- break;
- }
-
- return NL_SKIP;
-}
-
-static int __nl_get_multicast_id(struct nl_sock *sock, const char *family, const char *group)
-{
- struct nl_msg *msg;
- struct nl_cb *cb;
- int ret, ctrlid;
- multicast_group_id_args group_args = {
- .group = group,
- .id = -ENOENT,
- };
-
- msg = nlmsg_alloc();
- if (!msg)
- return -ENOMEM;
-
- cb = nl_cb_alloc(NL_CB_DEFAULT);
- if (!cb) {
- ret = -ENOMEM;
- goto FAILURE;
- }
-
- ctrlid = genl_ctrl_resolve(sock, "nlctrl");
-
- genlmsg_put(msg, 0, 0, ctrlid, 0,
- 0, CTRL_CMD_GETFAMILY, 0);
-
- ret = -ENOBUFS;
- NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);
-
- ret = nl_send_auto(sock, msg);
- if (ret < 0) {
- MESH_LOGE("Failed to nl_send_auto");
- goto out;
- }
-
- ret = 1;
- nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &ret);
- nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_simple_handler, &ret);
- nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, family_handler, &group_args);
-
- while (ret > 0)
- nl_recvmsgs(sock, cb);
-
- if (ret == 0)
- ret = group_args.id;
-
- MESH_LOGD("mcid : [%d]", ret);
-
- nla_put_failure:
- out:
- nl_cb_put(cb);
-
- FAILURE:
- nlmsg_free(msg);
- return ret;
-}
-
-static int __prepare_listen_events(mesh_nl_state *state)
-{
- int mcid, ret;
-
- /* Configuration multicast group */
- mcid = __nl_get_multicast_id(state->nl_socket, "nl80211", "config");
- if (mcid < 0) {
- MESH_LOGE("Failed to get nl80211 config");
- return mcid;
- }
- MESH_LOGD("Mesh multicast id (config): [%d]", mcid);
-
- ret = nl_socket_add_membership(state->nl_socket, mcid);
- if (ret) {
- MESH_LOGE("Failed to nl_socket_add_membership");
- return ret;
- }
-
- /* Scan multicast group */
- mcid = __nl_get_multicast_id(state->nl_socket, "nl80211", "scan");
- if (mcid >= 0) {
- ret = nl_socket_add_membership(state->nl_socket, mcid);
- if (ret) {
- MESH_LOGE("Failed to nl_socket_add_membership");
- return ret;
- }
- }
- MESH_LOGD("Mesh multicast id (scan): [%d]", mcid);
-
- /* Regulatory multicast group */
- mcid = __nl_get_multicast_id(state->nl_socket, "nl80211", "regulatory");
- if (mcid >= 0) {
- ret = nl_socket_add_membership(state->nl_socket, mcid);
- if (ret) {
- MESH_LOGE("Failed to nl_socket_add_membership");
- return ret;
- }
- }
- MESH_LOGD("Mesh multicast id (regulatory): [%d]", mcid);
-
- /* MLME multicast group */
- mcid = __nl_get_multicast_id(state->nl_socket, "nl80211", "mlme");
- if (mcid >= 0) {
- ret = nl_socket_add_membership(state->nl_socket, mcid);
- if (ret) {
- MESH_LOGE("Failed to nl_socket_add_membership");
- return ret;
- }
- }
- MESH_LOGD("Mesh multicast id (mlme): [%d]", mcid);
-
- mcid = __nl_get_multicast_id(state->nl_socket, "nl80211", "vendor");
- if (mcid >= 0) {
- ret = nl_socket_add_membership(state->nl_socket, mcid);
- if (ret) {
- MESH_LOGE("Failed to nl_socket_add_membership");
- return ret;
- }
- }
- MESH_LOGD("Mesh multicast id (vendor): [%d]", mcid);
-
- return 0;
-}
-
-static mesh_nl_state *_create_mesh_nl_state()
-{
- mesh_nl_state *state = g_new0(mesh_nl_state, 1);
-
- state->nl80211_id = -1;
- state->callback_state = MESH_NL_CALLBACK_TRYING;
- state->error_occured = FALSE;
-
- return state;
-}
-
-static void _delete_mesh_nl_state(mesh_nl_state **state)
-{
- if (NULL == state || NULL == *state)
- return;
-
- g_free(*state);
- *state = NULL;
-}
-
-static int valid_handler(struct nl_msg *msg, void *arg)
-{
- struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
- mesh_nl_state *state = (mesh_nl_state *)arg;
- MESH_LOGD("valid_handler");
-
- if (gnlh->cmd == NL80211_CMD_SCAN_ABORTED) {
- MESH_LOGD(" Got NL80211_CMD_SCAN_ABORTED.");
- state->callback_state = MESH_NL_CALLBACK_FINISHED;
-
- /* Notify scan done status */
- mesh_notify_scan_done();
- } else if (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS) {
- MESH_LOGD(" Got NL80211_CMD_NEW_SCAN_RESULTS.");
- state->callback_state = MESH_NL_CALLBACK_FINISHED;
-
- /* Notify scan done status */
- mesh_notify_scan_done();
- } else {
- MESH_LOGD(" Got [%d]", gnlh->cmd);
- }
-
- return NL_SKIP;
-}
-
-static int no_seq_check(struct nl_msg *msg, void *arg)
-{
- NOTUSED(msg);
- NOTUSED(arg);
-
- return NL_OK;
-}
-
-static void __clean_netlink_message(mesh_nl_state *state)
-{
- if (!state)
- return;
-
- if (state->cb)
- nl_cb_put(state->cb);
- if (state->s_cb)
- nl_cb_put(state->s_cb);
- if (state->msg)
- nlmsg_free(state->msg);
-
- state->cb = NULL;
- state->s_cb = NULL;
- state->msg = NULL;
-
- MESH_LOGD("message and callback cleaned");
-}
-
-static int __initialize_netlink_message(mesh_nl_state *state)
-{
- int err = MESHD_ERROR_NONE;
-
- if (NULL == state) {
- MESH_LOGE("Invalid parameter !");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- /* Create netlink message */
- state->msg = nlmsg_alloc();
- if (NULL == state->msg) {
- MESH_LOGE("Failed to allocate netlink message");
- return MESHD_ERROR_OUT_OF_MEMORY;
- }
-
- /* NL_CB_DEFAULT */
- state->cb = nl_cb_alloc(NL_CB_DEFAULT);
- state->s_cb = nl_cb_alloc(NL_CB_DEFAULT);
- if (!state->cb) {
- MESH_LOGE("Failed to allocate netlink callback");
- err = MESHD_ERROR_OUT_OF_MEMORY;
- goto DESTROY;
- }
-
- /* Set socket callback */
- nl_socket_set_cb(state->nl_socket, state->s_cb);
-
- /* Set callbacks */
- nl_cb_err(state->cb, NL_CB_CUSTOM, error_handler, state);
- nl_cb_set(state->cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, state);
- nl_cb_set(state->cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, state);
- nl_cb_set(state->cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, state);
-
- MESH_LOGD("netlink socket initialized");
-
- return MESHD_ERROR_NONE;
-
-DESTROY:
- __clean_netlink_message(state);
-
- return err;
-}
-
-static gboolean _on_socket_event_io_received(GIOChannel *source,
- GIOCondition condition, gpointer data)
-{
- mesh_nl_state *state = (mesh_nl_state *)data;
- int test = 0;
-
- NOTUSED(source);
- NOTUSED(condition);
-
- MESH_LOGD("[Event] I/O received");
-
- while (nl_recvmsgs_report(state->nl_socket, state->cb) > 0)
- MESH_LOGD(" count [%02d]", ++test);
-
- /* Do not remove I/O source */
- return TRUE;
-}
-
-static void _on_remove_event_io_handler()
-{
- if (event_state) {
- g_source_remove(event_state->event_source);
-
- __clean_netlink_message(event_state);
- __clean_nl80211(event_state);
- _delete_mesh_nl_state(&event_state);
- }
-}
-
-static void mac_addr_n2a(char *mac_addr, unsigned char *arg)
-{
- /* 11:22:33:44:55:66 (Len:17) */
- snprintf(mac_addr, MAX_MAC_ADDR_LEN,
- "%02X:%02X:%02X:%02X:%02X:%02X",
- arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
-}
-#if defined(NL80211_STA_INFO_CHAIN_SIGNAL) || defined(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)
-static char *get_chain_signal(struct nlattr *attr_list)
-{
- struct nlattr *attr;
- static char buf[64];
- char *cur = buf;
- int i = 0, rem;
- const char *prefix;
-
- if (!attr_list)
- return (char *)"";
-
- nla_for_each_nested(attr, attr_list, rem) {
- if (i++ > 0)
- prefix = ", ";
- else
- prefix = "[";
-
- cur += snprintf(cur, sizeof(buf) - (cur - buf), "%s%d", prefix,
- (int8_t) nla_get_u8(attr));
- }
-
- if (i)
- snprintf(cur, sizeof(buf) - (cur - buf), "] ");
-
- return buf;
-}
-#endif /* NL80211_STA_INFO_CHAIN_SIGNAL || NL80211_STA_INFO_CHAIN_SIGNAL_AVG */
-
-static int parse_bitrate(struct nlattr *bitrate_attr, char *buf, int buflen)
-{
- int rate = 0;
- int pos = 0;
- char str_rate[32] = { 0, };
- char str_buf[128] = { 0, };
- struct nlattr *rate_info[NL80211_RATE_INFO_MAX + 1];
- static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
- [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
- [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
- [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
- [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
- [NL80211_RATE_INFO_BITRATE32] = { .type = NLA_U32 },
- };
-
- if (nla_parse_nested(rate_info, NL80211_RATE_INFO_MAX, bitrate_attr, rate_policy)) {
- if (buf)
- snprintf(buf, buflen, "failed to parse nested rate attributes!");
- return 0;
- }
-
- if (rate_info[NL80211_RATE_INFO_MCS])
- pos += snprintf(str_buf + pos, 128 - pos,
- " MCS %d", nla_get_u8(rate_info[NL80211_RATE_INFO_MCS]));
- if (rate_info[NL80211_RATE_INFO_40_MHZ_WIDTH])
- pos += snprintf(str_buf + pos, 128 - pos, " 40MHz");
- if (rate_info[NL80211_RATE_INFO_SHORT_GI])
- pos += snprintf(str_buf + pos, 128 - pos, " short GI");
- if (rate_info[NL80211_RATE_INFO_VHT_MCS])
- pos += snprintf(str_buf + pos, 128 - pos,
- " VHT-MCS %d", nla_get_u8(rate_info[NL80211_RATE_INFO_VHT_MCS]));
- if (rate_info[NL80211_RATE_INFO_VHT_NSS])
- pos += snprintf(str_buf + pos, 128 - pos,
- " VHT-NSS %d", nla_get_u8(rate_info[NL80211_RATE_INFO_VHT_NSS]));
- if (rate_info[NL80211_RATE_INFO_80_MHZ_WIDTH])
- pos += snprintf(str_buf + pos, 128 - pos, " 80MHz");
- if (rate_info[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
- pos += snprintf(str_buf + pos, 128 - pos, " 80P80MHz");
- if (rate_info[NL80211_RATE_INFO_160_MHZ_WIDTH])
- pos += snprintf(str_buf + pos, 128 - pos, " 160MHz");
-
- if (rate_info[NL80211_RATE_INFO_BITRATE32])
- rate = nla_get_u32(rate_info[NL80211_RATE_INFO_BITRATE32]);
- else if (rate_info[NL80211_RATE_INFO_BITRATE])
- rate = nla_get_u16(rate_info[NL80211_RATE_INFO_BITRATE]);
- if (rate > 0)
- snprintf(str_rate, 32, "%d.%d MBit/s", rate / 10, rate % 10);
-
- if (buf)
- snprintf(buf, buflen, "%s%s", str_rate, str_buf);
-
- return rate;
-}
-
-static void parse_bss_param(struct nlattr *bss_param_attr, mesh_station_info_s *station_info)
-{
- struct nlattr *bss_param_info[NL80211_STA_BSS_PARAM_MAX + 1], *info;
- static struct nla_policy bss_poilcy[NL80211_STA_BSS_PARAM_MAX + 1] = {
- [NL80211_STA_BSS_PARAM_CTS_PROT] = { .type = NLA_FLAG },
- [NL80211_STA_BSS_PARAM_SHORT_PREAMBLE] = { .type = NLA_FLAG },
- [NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME] = { .type = NLA_FLAG },
- [NL80211_STA_BSS_PARAM_DTIM_PERIOD] = { .type = NLA_U8 },
- [NL80211_STA_BSS_PARAM_BEACON_INTERVAL] = { .type = NLA_U16 },
- };
-
- if (nla_parse_nested(bss_param_info, NL80211_STA_BSS_PARAM_MAX, bss_param_attr, bss_poilcy))
- MESH_LOGE("failed to parse nested bss param attributes!");
-
- info = bss_param_info[NL80211_STA_BSS_PARAM_DTIM_PERIOD];
- if (info) {
- station_info->dtim_period = nla_get_u8(info);
- MESH_LOGD(" DTIM period:\t%u", station_info->dtim_period);
- }
- info = bss_param_info[NL80211_STA_BSS_PARAM_BEACON_INTERVAL];
- if (info) {
- station_info->beacon_interval = nla_get_u16(info);
- MESH_LOGD(" beacon interval:%u", station_info->beacon_interval);
- }
- info = bss_param_info[NL80211_STA_BSS_PARAM_CTS_PROT];
- if (info) {
- MESH_LOGD(" CTS protection:");
- if (nla_get_u16(info)) {
- MESH_LOGD(" yes");
- station_info->cts_protection = TRUE;
- } else {
- MESH_LOGD(" no");
- station_info->cts_protection = FALSE;
- }
- }
- info = bss_param_info[NL80211_STA_BSS_PARAM_SHORT_PREAMBLE];
- if (info) {
- MESH_LOGD(" short preamble:");
- if (nla_get_u16(info)) {
- MESH_LOGD(" yes");
- station_info->short_preamble = TRUE;
- } else {
- MESH_LOGD(" no");
- station_info->short_preamble = FALSE;
- }
- }
- info = bss_param_info[NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME];
- if (info) {
- MESH_LOGD(" short slot time:");
- if (nla_get_u16(info)) {
- MESH_LOGD(" yes");
- station_info->short_slot_time = TRUE;
- } else {
- MESH_LOGD(" no");
- station_info->short_slot_time = FALSE;
- }
- }
-}
-
-static void print_power_mode(struct nlattr *a)
-{
- enum nl80211_mesh_power_mode pm = nla_get_u32(a);
-
- switch (pm) {
- case NL80211_MESH_POWER_ACTIVE:
- MESH_LOGD("ACTIVE");
- break;
- case NL80211_MESH_POWER_LIGHT_SLEEP:
- MESH_LOGD("LIGHT SLEEP");
- break;
- case NL80211_MESH_POWER_DEEP_SLEEP:
- MESH_LOGD("DEEP SLEEP");
- break;
- default:
- MESH_LOGD("UNKNOWN");
- break;
- }
-}
-
-static int _on_receive_station_info(struct nl_msg *msg, void *arg)
-{
- struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
- struct nlattr *sta_info[NL80211_STA_INFO_MAX + 1];
- struct nlattr *attr_info[NL80211_ATTR_MAX + 1];
- struct nl80211_sta_flag_update *sta_flags;
- static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
- [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
- [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
- [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
- [NL80211_STA_INFO_LLID] = { .type = NLA_U16 },
- [NL80211_STA_INFO_PLID] = { .type = NLA_U16 },
- [NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 },
- [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
- [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
- [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
- [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
- [NL80211_STA_INFO_TX_RETRIES] = { .type = NLA_U32 },
- [NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
- [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
- [NL80211_STA_INFO_BSS_PARAM] = { .type = NLA_NESTED },
- [NL80211_STA_INFO_STA_FLAGS] = { .minlen = sizeof(struct nl80211_sta_flag_update) },
- [NL80211_STA_INFO_BEACON_LOSS] = { .type = NLA_U32},
- [NL80211_STA_INFO_T_OFFSET] = { .type = NLA_U64 },
- [NL80211_STA_INFO_LOCAL_PM] = { .type = NLA_U32 },
- [NL80211_STA_INFO_PEER_PM] = { .type = NLA_U32 },
- [NL80211_STA_INFO_NONPEER_PM] = { .type = NLA_U32 },
- [NL80211_STA_INFO_RX_BYTES64] = { .type = NLA_U64 },
- [NL80211_STA_INFO_TX_BYTES64] = { .type = NLA_U64 },
-#ifdef NL80211_STA_INFO_CHAIN_SIGNAL
- [NL80211_STA_INFO_CHAIN_SIGNAL] = { .type = NLA_NESTED },
-#endif /* NL80211_STA_INFO_CHAIN_SIGNAL */
-
-#ifdef NL80211_STA_INFO_CHAIN_SIGNAL_AVG
- [NL80211_STA_INFO_CHAIN_SIGNAL_AVG] = { .type = NLA_NESTED },
-#endif /* NL80211_STA_INFO_CHAIN_SIGNAL_AVG */
-
-#ifdef NL80211_STA_INFO_RX_DROP_MISC
- [NL80211_STA_INFO_RX_DROP_MISC] = { .type = NLA_U64 },
-#endif /* NL80211_STA_INFO_RX_DROP_MISC */
-
-#ifdef NL80211_STA_INFO_RX_DURATION
- [NL80211_STA_INFO_BEACON_RX] = { .type = NLA_U64 },
-#endif /* NL80211_STA_INFO_RX_DURATION */
-
-#ifdef NL80211_STA_INFO_TID_STATS
- [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
-#endif /* NL80211_STA_INFO_TID_STATS */
-
-#ifdef NL80211_STA_INFO_RX_DURATION
- [NL80211_STA_INFO_RX_DURATION] = { .type = NLA_U64 },
-#endif /* NL80211_STA_INFO_RX_DURATION */
- };
- char mac_addr[MAX_MAC_ADDR_LEN], dev[IF_NAMESIZE];
-#ifdef NL80211_STA_INFO_CHAIN_SIGNAL
- char *chain;
-#endif /* NL80211_STA_INFO_CHAIN_SIGNAL */
- char *attr_mac = NULL;
- mesh_nl_state *state = (mesh_nl_state *)arg;
- mesh_station_info_s *station_info = NULL;
-
- nla_parse(attr_info, NL80211_ATTR_MAX,
- genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
-
- if (!attr_info[NL80211_ATTR_STA_INFO]) {
- MESH_LOGE("[Station] missing station stats !");
- return NL_SKIP;
- }
-
- if (nla_parse_nested(sta_info, NL80211_STA_INFO_MAX,
- attr_info[NL80211_ATTR_STA_INFO], stats_policy)) {
- MESH_LOGE("[Station] Failed to parse nested attributes!");
- return NL_SKIP;
- }
-
- /* Allocation */
- station_info = g_try_new0(mesh_station_info_s, 1);
- if (NULL == station_info) {
- MESH_LOGE("Failed to allocate station info !");
- return NL_SKIP;
- }
-
- /* BSSID */
- attr_mac = nla_data(attr_info[NL80211_ATTR_MAC]);
- snprintf(mac_addr, MAX_MAC_ADDR_LEN, "%02X:%02X:%02X:%02X:%02X:%02X",
- attr_mac[0], attr_mac[1], attr_mac[2],
- attr_mac[3], attr_mac[4], attr_mac[5]);
- if_indextoname(nla_get_u32(attr_info[NL80211_ATTR_IFINDEX]), dev);
- station_info->bssid = g_strdup(mac_addr);
- MESH_LOGD("Station %s [dev %s]", station_info->bssid, dev);
-
- /* Inactive time */
- if (0 != sta_info[NL80211_STA_INFO_INACTIVE_TIME]) {
- station_info->inactive_time =
- nla_get_u32(sta_info[NL80211_STA_INFO_INACTIVE_TIME]);
- MESH_LOGE(" inactive time:\t%u ms", station_info->inactive_time);
- }
-
- /* RX Bytes */
- if (0 != sta_info[NL80211_STA_INFO_RX_BYTES]) {
- station_info->rx_bytes =
- nla_get_u32(sta_info[NL80211_STA_INFO_RX_BYTES]);
- MESH_LOGD(" rx bytes:\t%u", station_info->rx_bytes);
- } else if (0 != sta_info[NL80211_STA_INFO_RX_BYTES64]) {
- station_info->rx_bytes =
- (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_RX_BYTES64]);
- MESH_LOGE(" rx bytes:\t%llu", station_info->rx_bytes);
- }
-
- /* RX Packets */
- if (0 != sta_info[NL80211_STA_INFO_RX_PACKETS]) {
- station_info->rx_packets =
- nla_get_u32(sta_info[NL80211_STA_INFO_RX_PACKETS]);
- MESH_LOGD(" rx packets:\t%u", station_info->rx_packets);
- }
-
- /* TX Bytes */
- if (0 != sta_info[NL80211_STA_INFO_TX_BYTES]) {
- station_info->tx_bytes =
- nla_get_u32(sta_info[NL80211_STA_INFO_TX_BYTES]);
- MESH_LOGD(" tx bytes:\t%u", station_info->tx_bytes);
- } else if (0 != sta_info[NL80211_STA_INFO_TX_BYTES64]) {
- station_info->tx_bytes =
- (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_TX_BYTES64]);
- MESH_LOGD(" tx bytes:\t%llu", station_info->rx_packets);
- }
-
- /* LLID, PLID */
- if (0 != sta_info[NL80211_STA_INFO_LLID]) {
- station_info->llid = nla_get_u16(sta_info[NL80211_STA_INFO_LLID]);
- MESH_LOGD(" mesh llid:\t%d", station_info->llid);
- }
- if (0 != sta_info[NL80211_STA_INFO_PLID]) {
- station_info->llid = nla_get_u16(sta_info[NL80211_STA_INFO_PLID]);
- MESH_LOGD(" mesh plid:\t%d", station_info->plid);
- }
-
- /* Plink state */
- if (0 != sta_info[NL80211_STA_INFO_PLINK_STATE]) {
- char state_name[10];
- station_info->mesh_plink =
- nla_get_u8(sta_info[NL80211_STA_INFO_PLINK_STATE]);
- switch (station_info->mesh_plink) {
- case LISTEN:
- snprintf(state_name, 10, "%s", "LISTEN");
- break;
- case OPN_SNT:
- snprintf(state_name, 10, "%s", "OPN_SNT");
- break;
- case OPN_RCVD:
- snprintf(state_name, 10, "%s", "OPN_RCVD");
- break;
- case CNF_RCVD:
- snprintf(state_name, 10, "%s", "CNF_RCVD");
- break;
- case ESTAB:
- snprintf(state_name, 10, "%s", "ESTAB");
- break;
- case HOLDING:
- snprintf(state_name, 10, "%s", "HOLDING");
- break;
- case BLOCKED:
- snprintf(state_name, 10, "%s", "BLOCKED");
- break;
- default:
- snprintf(state_name, 10, "%s", "UNKNOWN");
- break;
- }
- MESH_LOGD(" mesh plink:\t%s", state_name);
- }
-#ifdef NL80211_STA_INFO_CHAIN_SIGNAL
- /* RSSI Signal */
- chain = get_chain_signal(sta_info[NL80211_STA_INFO_CHAIN_SIGNAL]);
- if (0 != sta_info[NL80211_STA_INFO_SIGNAL]) {
- station_info->rssi =
- (int8_t)nla_get_u8(sta_info[NL80211_STA_INFO_SIGNAL]);
- MESH_LOGD(" signal: \t%d %sdBm", station_info->rssi, chain);
- }
-#endif /* NL80211_STA_INFO_CHAIN_SIGNAL */
- /* TX Bitrate */
- if (0 != sta_info[NL80211_STA_INFO_TX_BITRATE]) {
- char buf[100];
- station_info->tx_bitrate =
- parse_bitrate(sta_info[NL80211_STA_INFO_TX_BITRATE], buf, sizeof(buf));
- MESH_LOGD(" tx bitrate:\t%s", buf);
- }
-
- if (0 != sta_info[NL80211_STA_INFO_TX_PACKETS]) {
- station_info->tx_packets =
- nla_get_u32(sta_info[NL80211_STA_INFO_TX_PACKETS]);
- MESH_LOGD(" tx packets:\t%u", station_info->tx_packets);
- }
- if (0 != sta_info[NL80211_STA_INFO_TX_RETRIES]) {
- station_info->tx_retries =
- nla_get_u32(sta_info[NL80211_STA_INFO_TX_RETRIES]);
- MESH_LOGD(" tx retries:\t%u", station_info->tx_retries);
- }
- if (0 != sta_info[NL80211_STA_INFO_TX_FAILED]) {
- station_info->tx_failed =
- nla_get_u32(sta_info[NL80211_STA_INFO_TX_FAILED]);
- MESH_LOGD(" tx failed:\t%u", station_info->tx_failed);
- }
-#ifdef NL80211_STA_INFO_CHAIN_SIGNAL_AVG
- /* Signal average */
- chain = get_chain_signal(sta_info[NL80211_STA_INFO_CHAIN_SIGNAL_AVG]);
- if (0 != sta_info[NL80211_STA_INFO_SIGNAL_AVG]) {
- station_info->rssi_avg =
- (int8_t)nla_get_u8(sta_info[NL80211_STA_INFO_SIGNAL_AVG]);
- MESH_LOGD(" signal avg:\t%d %sdBm", station_info->rssi_avg, chain);
- }
-#endif /* NL80211_STA_INFO_CHAIN_SIGNAL_AVG */
- if (0 != sta_info[NL80211_STA_INFO_RX_BITRATE]) {
- char buf[100];
- station_info->rx_bitrate =
- parse_bitrate(sta_info[NL80211_STA_INFO_RX_BITRATE], buf, sizeof(buf));
- MESH_LOGD(" rx bitrate:\t%s", buf);
- }
-
- if (0 != sta_info[NL80211_STA_INFO_BSS_PARAM])
- parse_bss_param(sta_info[NL80211_STA_INFO_BSS_PARAM], station_info);
-
- if (0 != sta_info[NL80211_STA_INFO_CONNECTED_TIME]) {
- station_info->connected_time =
- nla_get_u32(sta_info[NL80211_STA_INFO_CONNECTED_TIME]);
- MESH_LOGD(" connected time:\t%u seconds", station_info->connected_time);
- }
-
- if (0 != sta_info[NL80211_STA_INFO_STA_FLAGS]) {
- sta_flags = (struct nl80211_sta_flag_update *)
- nla_data(sta_info[NL80211_STA_INFO_STA_FLAGS]);
-
- if (sta_flags->mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
- MESH_LOGD(" authorized:");
- if (sta_flags->set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
- MESH_LOGD(" yes");
- station_info->authorized = TRUE;
- } else {
- MESH_LOGD(" no");
- station_info->authorized = FALSE;
- }
- }
-
- if (sta_flags->mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
- MESH_LOGD(" authenticated:");
- if (sta_flags->set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
- MESH_LOGD(" yes");
- station_info->authenticated = TRUE;
- } else {
- MESH_LOGD(" no");
- station_info->authenticated = FALSE;
- }
- }
-
- if (sta_flags->mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) {
- MESH_LOGD(" associated:");
- if (sta_flags->set & BIT(NL80211_STA_FLAG_ASSOCIATED)) {
- MESH_LOGD(" yes");
- station_info->associated = TRUE;
- } else {
- MESH_LOGD(" no");
- station_info->associated = FALSE;
- }
- }
-
- if (sta_flags->mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
- MESH_LOGD(" preamble:");
- if (sta_flags->set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
- MESH_LOGD(" short");
- station_info->preamble = TRUE;
- } else {
- MESH_LOGD(" long");
- station_info->preamble = FALSE;
- }
- }
-
- if (sta_flags->mask & BIT(NL80211_STA_FLAG_WME)) {
- MESH_LOGD(" WMM/WME:");
- if (sta_flags->set & BIT(NL80211_STA_FLAG_WME)) {
- MESH_LOGD(" yes");
- station_info->wme = TRUE;
- } else {
- MESH_LOGD(" no");
- station_info->wme = FALSE;
- }
- }
-
- if (sta_flags->mask & BIT(NL80211_STA_FLAG_MFP)) {
- MESH_LOGD(" MFP:");
- if (sta_flags->set & BIT(NL80211_STA_FLAG_MFP)) {
- MESH_LOGD(" yes");
- station_info->mfp = TRUE;
- } else {
- MESH_LOGD(" no");
- station_info->mfp = FALSE;
- }
- }
-
- if (sta_flags->mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
- MESH_LOGD(" TDLS peer:");
- if (sta_flags->set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
- MESH_LOGD(" yes");
- station_info->tdls_peer = TRUE;
- } else {
- MESH_LOGD(" no");
- station_info->tdls_peer = FALSE;
- }
- }
- }
-
- if (0 != sta_info[NL80211_STA_INFO_BEACON_LOSS]) {
- station_info->beacon_loss =
- nla_get_u32(sta_info[NL80211_STA_INFO_BEACON_LOSS]);
- MESH_LOGD(" beacon loss:\t%u", station_info->beacon_loss);
- }
-
- if (0 != sta_info[NL80211_STA_INFO_T_OFFSET]) {
- station_info->t_offset =
- (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_T_OFFSET]);
- MESH_LOGD(" Toffset:\t%llu us", station_info->t_offset);
- }
-
- if (0 != sta_info[NL80211_STA_INFO_LOCAL_PM]) {
- station_info->local_ps_mode =
- nla_get_u32(sta_info[NL80211_STA_INFO_LOCAL_PM]);
- MESH_LOGD(" mesh local PS mode:\t");
- print_power_mode(sta_info[NL80211_STA_INFO_LOCAL_PM]);
- }
- if (0 != sta_info[NL80211_STA_INFO_PEER_PM]) {
- station_info->peer_ps_mode =
- nla_get_u32(sta_info[NL80211_STA_INFO_PEER_PM]);
- MESH_LOGD(" mesh peer PS mode:\t");
- print_power_mode(sta_info[NL80211_STA_INFO_PEER_PM]);
- }
- if (0 != sta_info[NL80211_STA_INFO_NONPEER_PM]) {
- station_info->non_peer_ps_mode =
- nla_get_u32(sta_info[NL80211_STA_INFO_NONPEER_PM]);
- MESH_LOGD(" mesh non-peer PS mode:\t");
- print_power_mode(sta_info[NL80211_STA_INFO_NONPEER_PM]);
- }
-#ifdef NL80211_STA_INFO_RX_DROP_MISC
- if (0 != sta_info[NL80211_STA_INFO_RX_DROP_MISC]) {
- station_info->rx_drop_misc =
- (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_RX_DROP_MISC]);
- MESH_LOGD(" rx drop misc:\t%llu", station_info->rx_drop_misc);
- }
-#endif /* NL80211_STA_INFO_RX_DROP_MISC */
-
-#ifdef NL80211_STA_INFO_BEACON_RX
- if (0 != sta_info[NL80211_STA_INFO_BEACON_RX]) {
- station_info->beacon_rx =
- (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_BEACON_RX]);
- MESH_LOGD(" beacon rx:\t%llu", station_info->beacon_rx);
- }
-#endif /* NL80211_STA_INFO_BEACON_RX */
-
-#ifdef NL80211_STA_INFO_BEACON_SIGNAL_AVG
- if (0 != sta_info[NL80211_STA_INFO_BEACON_SIGNAL_AVG]) {
- station_info->beacon_signal_avg =
- nla_get_u8(sta_info[NL80211_STA_INFO_BEACON_SIGNAL_AVG]);
- MESH_LOGD(" beacon signal avg:\t%d dBm", station_info->beacon_signal_avg);
- }
-#endif /* NL80211_STA_INFO_BEACON_SIGNAL_AVG */
-
-#ifdef NL80211_STA_INFO_RX_DURATION
- if (0 != sta_info[NL80211_STA_INFO_RX_DURATION]) {
- station_info->rx_duration =
- (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_RX_DURATION]);
- MESH_LOGD(" rx duration:\t%lld us", station_info->rx_duration);
- }
-#endif /* NL80211_STA_INFO_RX_DURATION */
- MESH_LOGD("");
- *(state->station_list) = g_list_prepend(*(state->station_list), station_info);
-
- return NL_SKIP;
-}
-
-static int _on_receive_mpath_info(struct nl_msg *msg, void *arg)
-{
- struct nlattr *tb[NL80211_ATTR_MAX + 1];
- struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
- struct nlattr *pinfo[NL80211_MPATH_INFO_MAX + 1];
- char dst[20], next_hop[20], dev[20];
- static struct nla_policy mpath_policy[NL80211_MPATH_INFO_MAX + 1] = {
- [NL80211_MPATH_INFO_FRAME_QLEN] = { .type = NLA_U32 },
- [NL80211_MPATH_INFO_SN] = { .type = NLA_U32 },
- [NL80211_MPATH_INFO_METRIC] = { .type = NLA_U32 },
- [NL80211_MPATH_INFO_EXPTIME] = { .type = NLA_U32 },
- [NL80211_MPATH_INFO_DISCOVERY_TIMEOUT] = { .type = NLA_U32 },
- [NL80211_MPATH_INFO_DISCOVERY_RETRIES] = { .type = NLA_U8 },
- [NL80211_MPATH_INFO_FLAGS] = { .type = NLA_U8 },
- };
-
- mesh_nl_state *state = (mesh_nl_state *)arg;
- mesh_mpath_info_s *mpath_info = NULL;
-
- nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
- genlmsg_attrlen(gnlh, 0), NULL);
-
- /*
- * TODO: validate the interface and mac address!
- * Otherwise, there's a race condition as soon as
- * the kernel starts sending mpath notifications.
- */
-
- if (!tb[NL80211_ATTR_MPATH_INFO]) {
- MESH_LOGE("missing mesh path info!");
- return NL_SKIP;
- }
- if (nla_parse_nested(pinfo, NL80211_MPATH_INFO_MAX,
- tb[NL80211_ATTR_MPATH_INFO],
- mpath_policy)) {
- MESH_LOGE("failed to parse nested attributes!");
- return NL_SKIP;
- }
-
- mpath_info = g_try_new0(mesh_mpath_info_s, 1);
- if (NULL == mpath_info) {
- MESH_LOGE("Failed to allocate mesh path info !");
- return NL_SKIP;
- }
-
- mac_addr_n2a(dst, nla_data(tb[NL80211_ATTR_MAC]));
- mpath_info->dest_addr = g_strdup(dst);
- MESH_LOGD("Destination Address : %s", mpath_info->dest_addr);
-
- mac_addr_n2a(next_hop, nla_data(tb[NL80211_ATTR_MPATH_NEXT_HOP]));
- mpath_info->next_hop = g_strdup(next_hop);
- MESH_LOGD("Next hop Address : %s", mpath_info->next_hop);
-
- if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
- mpath_info->interface = g_strdup(dev);
- MESH_LOGD("Interface : %s", mpath_info->interface);
-
- if (pinfo[NL80211_MPATH_INFO_SN]) {
- mpath_info->sn = nla_get_u32(pinfo[NL80211_MPATH_INFO_SN]);
- MESH_LOGD("SN : %u", mpath_info->sn);
- }
- if (pinfo[NL80211_MPATH_INFO_METRIC]) {
- mpath_info->metric = nla_get_u32(pinfo[NL80211_MPATH_INFO_METRIC]);
- MESH_LOGD("Metric : %u", mpath_info->metric);
- }
- if (pinfo[NL80211_MPATH_INFO_FRAME_QLEN]) {
- mpath_info->qlen = nla_get_u32(pinfo[NL80211_MPATH_INFO_FRAME_QLEN]);
- MESH_LOGD("QLEN : %u", mpath_info->qlen);
- }
- if (pinfo[NL80211_MPATH_INFO_EXPTIME]) {
- mpath_info->exptime = nla_get_u32(pinfo[NL80211_MPATH_INFO_EXPTIME]);
- MESH_LOGD("ExpTime : %u", mpath_info->exptime);
- }
- if (pinfo[NL80211_MPATH_INFO_DISCOVERY_TIMEOUT]) {
- mpath_info->discovery_timeout =
- nla_get_u32(pinfo[NL80211_MPATH_INFO_DISCOVERY_TIMEOUT]);
- MESH_LOGD("Discovery Timeout : %u", mpath_info->discovery_timeout);
- }
- if (pinfo[NL80211_MPATH_INFO_DISCOVERY_RETRIES]) {
- mpath_info->discovery_retries =
- nla_get_u8(pinfo[NL80211_MPATH_INFO_DISCOVERY_RETRIES]);
- MESH_LOGD("Discovery Retries : %u", mpath_info->discovery_retries);
- }
- if (pinfo[NL80211_MPATH_INFO_FLAGS]) {
- mpath_info->flags = nla_get_u8(pinfo[NL80211_MPATH_INFO_FLAGS]);
- MESH_LOGD("Flags : 0x%x", mpath_info->flags);
- }
-
- MESH_LOGD("");
- *(state->mpath_list) = g_list_prepend(*(state->mpath_list), mpath_info);
-
- return NL_SKIP;
-}
-
-static int _on_receive_mesh_event(struct nl_msg *msg, void *arg)
-{
- struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
- struct nlattr *tb[NL80211_ATTR_MAX + 1];
- char ifname[16] = { 0, };
- char macbuf[MAX_MAC_ADDR_LEN];
-
- NOTUSED(arg);
-
- nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
-
- if (tb[NL80211_ATTR_IFINDEX]) {
- if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), ifname);
- MESH_LOGD("%s: ", ifname);
- }
-
- switch (gnlh->cmd) {
- case NL80211_CMD_NEW_STATION:
- mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
- MESH_LOGD("[%s] new station [%s]", ifname, macbuf);
- break;
- case NL80211_CMD_DEL_STATION:
- mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
- MESH_LOGD("[%s] del station [%s]", ifname, macbuf);
- break;
- case NL80211_CMD_NEW_MPATH:
- mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
- MESH_LOGD("[%s] new mpath [%s]", ifname, macbuf);
-
- mesh_notify_station_joined((const char*)macbuf);
- break;
- case NL80211_CMD_DEL_MPATH:
- mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
- MESH_LOGD("[%s] del mpath [%s]", ifname, macbuf);
-
- mesh_notify_station_left((const char*)macbuf);
- break;
- default:
- MESH_LOGD("event [%d] is not handled", gnlh->cmd);
- break;
- }
-
- return NL_SKIP;
-}
-
-static int _send_nl_set_mesh_parameter(const char* mesh_if_name,
- const char* param_name, unsigned int value)
-{
- mesh_nl_state state = {
- .nl80211_id = -1,
- .callback_state = MESH_NL_CALLBACK_TRYING,
- .event_source = 0,
- .nl_socket = NULL,
- .msg = NULL,
- .cb = NULL,
- .s_cb = NULL,
- .error_occured = FALSE,
- };
- struct nlattr *container;
-
- int err = MESHD_ERROR_NONE;
- int device_index = 0;
- int ret;
- int test = 0;
-
- ret = __initialize_nl80211(&state);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to initialize nl80211");
- return ret;
- }
-
- ret = __initialize_netlink_message(&state);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to initialize netlink message");
- goto DESTROY;
- }
-
- /* Set command into message */
- genlmsg_put(state.msg, 0, 0, state.nl80211_id, 0,
- 0, NL80211_CMD_SET_MESH_PARAMS, 0);
-
- /* Add attributes into message */
- ret = __get_device_index_from_string(mesh_if_name, &device_index);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to get mesh device index");
- err = ret;
- goto DESTROY;
- }
- NLA_PUT_U32(state.msg, NL80211_ATTR_IFINDEX, device_index);
-
- container = nla_nest_start(state.msg, NL80211_ATTR_MESH_PARAMS);
- if (!container) {
- MESH_LOGE("Failed to initialize netlink message");
- goto DESTROY;
- }
-
- /* Logic need to be changed if additional parameter is required */
- if (g_strcmp0(MESH_PARAM_HWMP_ROOTMODE, param_name) == 0) {
- MESH_LOGD(" [mesh_hwmp_rootmode] : [%d]", value);
- NLA_PUT_U8(state.msg, NL80211_MESHCONF_HWMP_ROOTMODE,
- (uint8_t)value);
- } else if (g_strcmp0(MESH_PARAM_GATE_ANNOUNCE, param_name) == 0) {
- MESH_LOGD(" [mesh_gate_announcements] : [%d]", value);
- NLA_PUT_U8(state.msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
- (uint8_t)value);
- } else {
- MESH_LOGE("Parameter [%s] is not required !", param_name);
- nla_nest_end(state.msg, container);
- goto DESTROY;
- }
- nla_nest_end(state.msg, container);
-
- /* Send message into kernel */
- ret = nl_send_auto(state.nl_socket, state.msg);
- if (ret < 0) {
- MESH_LOGE("Failed to nl_send_auto() [%s](%d)",
- nl_geterror(ret), ret);
- err = MESHD_ERROR_OPERATION_FAILED;
- goto DESTROY;
- }
-
- /* sync response */
- state.callback_state = MESH_NL_CALLBACK_TRYING;
- while (state.callback_state == MESH_NL_CALLBACK_TRYING) {
- MESH_LOGD(" count [%02d]", ++test);
- nl_recvmsgs(state.nl_socket, state.cb);
- }
-
-DESTROY:
- __clean_netlink_message(&state);
- __clean_nl80211(&state);
-
- return err;
-
-nla_put_failure:
- MESH_LOGE("Failed to message build");
- __clean_netlink_message(&state);
- __clean_nl80211(&state);
-
- return MESHD_ERROR_OPERATION_FAILED;
-}
-
-static int _send_nl_get_station_info(const char* if_name, GList **station_list)
-{
- mesh_nl_state state = {
- .nl80211_id = -1,
- .callback_state = MESH_NL_CALLBACK_TRYING,
- .event_source = 0,
- .nl_socket = NULL,
- .msg = NULL,
- .cb = NULL,
- .s_cb = NULL,
- .station_list = station_list
- };
- int err = MESHD_ERROR_NONE;
- int device_index = 0;
- int ret;
- int test = 0;
-
- ret = __initialize_nl80211(&state);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to initialize nl80211");
- return ret;
- }
-
- ret = __initialize_netlink_message(&state);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to initialize netlink message");
- goto DESTROY;
- }
-
- /* Set command into message */
- genlmsg_put(state.msg, 0, 0, state.nl80211_id, 0,
- NLM_F_DUMP, NL80211_CMD_GET_STATION, 0);
-
- /* Add attributes into message */
- MESH_LOGD("Dump station list with interface [%s]", if_name);
- ret = __get_device_index_from_string(if_name, &device_index);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to get mesh interface device index");
- err = ret;
- goto DESTROY;
- }
- NLA_PUT_U32(state.msg, NL80211_ATTR_IFINDEX, device_index);
-
- /* Register valid callback to dump result */
- nl_cb_set(state.cb, NL_CB_VALID, NL_CB_CUSTOM,
- _on_receive_station_info, &state);
-
- /* Send message into kernel */
- ret = nl_send_auto(state.nl_socket, state.msg);
- if (ret < 0) {
- MESH_LOGE("Failed to nl_send_auto() [%s](%d)",
- nl_geterror(ret), ret);
- err = MESHD_ERROR_OPERATION_FAILED;
- goto DESTROY;
- }
-
- /* sync response */
- state.callback_state = MESH_NL_CALLBACK_TRYING;
- while (state.callback_state == MESH_NL_CALLBACK_TRYING) {
- MESH_LOGD(" count [%02d]", ++test);
- nl_recvmsgs(state.nl_socket, state.cb);
- }
- MESH_LOGD("Finished");
-
-DESTROY:
- __clean_netlink_message(&state);
- __clean_nl80211(&state);
-
- return err;
-
-nla_put_failure:
- MESH_LOGE("Failed to message build");
- __clean_netlink_message(&state);
- __clean_nl80211(&state);
-
- return MESHD_ERROR_OPERATION_FAILED;
-}
-
-static int _send_nl_del_station_info(const char* if_name, char* peer)
-{
- mesh_nl_state state = {
- .nl80211_id = -1,
- .callback_state = MESH_NL_CALLBACK_FINISHED,
- .event_source = 0,
- .nl_socket = NULL,
- .msg = NULL,
- .cb = NULL,
- .s_cb = NULL,
- .station_list = NULL,
- };
- int err = MESHD_ERROR_NONE;
- int device_index = 0;
- int ret;
-
- ret = __initialize_nl80211(&state);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to initialize nl80211");
- return ret;
- }
-
- ret = __initialize_netlink_message(&state);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to initialize netlink message");
- goto DESTROY;
- }
-
- /* Set command into message */
- genlmsg_put(state.msg, 0, 0, state.nl80211_id, 0,
- NLM_F_DUMP, NL80211_CMD_DEL_STATION, 0);
-
- /* Add attributes into message */
- MESH_LOGD("Delete a station [%s] with interface [%s]", peer, if_name);
- ret = __get_device_index_from_string(if_name, &device_index);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to get mesh interface device index");
- err = ret;
- goto DESTROY;
- }
- NLA_PUT_U32(state.msg, NL80211_ATTR_IFINDEX, device_index);
- NLA_PUT(state.msg, NL80211_ATTR_MAC, ETH_ALEN, peer);
-
- /* Send message into kernel */
- ret = nl_send_auto(state.nl_socket, state.msg);
- if (ret < 0) {
- MESH_LOGE("Failed to nl_send_auto() [%s](%d)",
- nl_geterror(ret), ret);
- err = MESHD_ERROR_OPERATION_FAILED;
- goto DESTROY;
- }
-
-DESTROY:
- __clean_netlink_message(&state);
- __clean_nl80211(&state);
-
- return err;
-
-nla_put_failure:
- MESH_LOGE("Failed to message build");
- __clean_netlink_message(&state);
- __clean_nl80211(&state);
-
- return MESHD_ERROR_OPERATION_FAILED;
-}
-
-static int _send_nl_get_mpath_info(const char* if_name, GList **mpath_list)
-{
- mesh_nl_state state = {
- .nl80211_id = -1,
- .callback_state = MESH_NL_CALLBACK_TRYING,
- .event_source = 0,
- .nl_socket = NULL,
- .msg = NULL,
- .cb = NULL,
- .s_cb = NULL,
- .mpath_list = mpath_list
- };
- int err = MESHD_ERROR_NONE;
- int device_index = 0;
- int ret;
- int test = 0;
-
- ret = __initialize_nl80211(&state);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to initialize nl80211");
- return ret;
- }
-
- ret = __initialize_netlink_message(&state);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to initialize netlink message");
- goto DESTROY;
- }
-
- /* Set command into message */
- genlmsg_put(state.msg, 0, 0, state.nl80211_id, 0,
- NLM_F_DUMP, NL80211_CMD_GET_MPATH, 0);
-
- /* Add attributes into message */
- MESH_LOGD("Dump station list with interface [%s]", if_name);
- ret = __get_device_index_from_string(if_name, &device_index);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to get mesh interface device index");
- err = ret;
- goto DESTROY;
- }
- NLA_PUT_U32(state.msg, NL80211_ATTR_IFINDEX, device_index);
-
- /* Register valid callback to dump result */
- nl_cb_set(state.cb, NL_CB_VALID, NL_CB_CUSTOM,
- _on_receive_mpath_info, &state);
-
- /* Send message into kernel */
- ret = nl_send_auto(state.nl_socket, state.msg);
- if (ret < 0) {
- MESH_LOGE("Failed to nl_send_auto() [%s](%d)",
- nl_geterror(ret), ret);
- err = MESHD_ERROR_OPERATION_FAILED;
- goto DESTROY;
- }
-
- /* sync response */
- state.callback_state = MESH_NL_CALLBACK_TRYING;
- while (state.callback_state == MESH_NL_CALLBACK_TRYING) {
- MESH_LOGD(" count [%02d]", ++test);
- nl_recvmsgs(state.nl_socket, state.cb);
- }
- MESH_LOGD("Finished");
-
-DESTROY:
- __clean_netlink_message(&state);
- __clean_nl80211(&state);
-
- return err;
-
-nla_put_failure:
- MESH_LOGE("Failed to message build");
- __clean_netlink_message(&state);
- __clean_nl80211(&state);
-
- return MESHD_ERROR_OPERATION_FAILED;
-}
-
-static int _send_nl_register_event_handler()
-{
- int err = MESHD_ERROR_NONE;
- int ret;
- GIOChannel *recv_channel = NULL;
-
- if (event_state) {
- MESH_LOGE("Already event handler registered !");
- return MESHD_ERROR_IN_PROGRESS;
- }
-
- event_state = _create_mesh_nl_state("");
-
- ret = __initialize_nl80211(event_state);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to initialize nl80211");
- return ret;
- }
-
- /* Subscribe multicast group should be proceed before scanning */
- ret = __prepare_listen_events(event_state);
- if (ret) {
- MESH_LOGE("__prepare_listen_events : [%d]", ret);
- goto DESTROY;
- }
-
- ret = __initialize_netlink_message(event_state);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to initialize netlink message");
- goto DESTROY;
- }
-
- /* Set command into message */
- genlmsg_put(event_state->msg, 0, 0, event_state->nl80211_id, 0, 0, 0, 0);
-
- /* Set callbacks for event handler */
- nl_cb_set(event_state->cb, NL_CB_VALID, NL_CB_CUSTOM,
- _on_receive_mesh_event, event_state);
- /* No sequence checking for multicast messages. */
- nl_cb_set(event_state->cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
-
- MESH_LOGD("Register event handler");
-
- /* Change socket type to non-blocking */
- ret = nl_socket_set_nonblocking(event_state->nl_socket);
- if (ret < 0)
- MESH_LOGE("Failed to non-blocking socket [%s](%d)", nl_geterror(ret), ret);
-
- /* Register I/O callback to wait asynchronously */
- if (FALSE == event_state->error_occured) {
- recv_channel = g_io_channel_unix_new(nl_socket_get_fd(event_state->nl_socket));
- event_state->event_source = g_io_add_watch(recv_channel,
- (G_IO_IN | G_IO_ERR), _on_socket_event_io_received, event_state);
- g_io_channel_unref(recv_channel);
- } else {
- MESH_LOGE("Error responded. Failed to register event callback !!");
- goto DESTROY;
- }
-
- /* Resource should be free on I/O callback */
- return MESHD_ERROR_NONE;
-
-DESTROY:
- __clean_netlink_message(event_state);
- __clean_nl80211(event_state);
- _delete_mesh_nl_state(&event_state);
-
- return err;
-}
-
-int mesh_netlink_set_mesh_parameter(const char* mesh_if_name,
- const char* param_name, unsigned int value)
-{
- int ret = MESHD_ERROR_NONE;
-
- if (NULL == mesh_if_name || strlen(mesh_if_name) > IFNAMSIZ) {
- MESH_LOGE("Invalid parameter [%p]", mesh_if_name);
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("Set mesh[%s] param [%s] value [%d]",
- mesh_if_name, param_name, value);
- ret = _send_nl_set_mesh_parameter(mesh_if_name, param_name, value);
-
- return ret;
-}
-
-int mesh_netlink_get_station_info(const char* mesh_if_name, GList **station_list)
-{
- int ret = MESHD_ERROR_NONE;
-
- if (NULL == mesh_if_name || strlen(mesh_if_name) > IFNAMSIZ) {
- MESH_LOGE("Invalid parameter [%p]", mesh_if_name);
- return MESHD_ERROR_INVALID_PARAMETER;
- }
- if (NULL == station_list) {
- MESH_LOGE("Invalid parameter [%p]", station_list);
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("Get connected stations");
- ret = _send_nl_get_station_info(mesh_if_name, station_list);
-
- return ret;
-}
-
-int mesh_netlink_del_station_info(const char* mesh_if_name, char *peer)
-{
- int ret = MESHD_ERROR_NONE;
-
- if (NULL == mesh_if_name || strlen(mesh_if_name) > IFNAMSIZ) {
- MESH_LOGE("Invalid parameter [%p]", mesh_if_name);
- return MESHD_ERROR_INVALID_PARAMETER;
- }
- if (NULL == peer) {
- MESH_LOGE("Invalid parameter [%p]", peer);
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("Del connected station : [%s]", peer);
- ret = _send_nl_del_station_info(mesh_if_name, peer);
-
- return ret;
-}
-
-int mesh_netlink_get_mpath_info(const char* mesh_if_name, GList **mpath_list)
-{
- int ret = MESHD_ERROR_NONE;
-
- if (NULL == mesh_if_name || strlen(mesh_if_name) > IFNAMSIZ) {
- MESH_LOGE("Invalid parameter [%p]", mesh_if_name);
- return MESHD_ERROR_INVALID_PARAMETER;
- }
- if (NULL == mpath_list) {
- MESH_LOGE("Invalid parameter [%p]", mpath_list);
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("Get current mpath info");
- ret = _send_nl_get_mpath_info(mesh_if_name, mpath_list);
-
- return ret;
-}
-
-int mesh_netlink_register_event_handler()
-{
- int ret = MESHD_ERROR_NONE;
-
- MESH_LOGD("Register mesh event handler");
- ret = _send_nl_register_event_handler();
-
- return ret;
-}
-
-int mesh_netlink_unregister_event_handler()
-{
- int ret = MESHD_ERROR_NONE;
-
- MESH_LOGD("Unregister mesh event handler");
-
- _on_remove_event_io_handler();
-
- return ret;
-}
+++ /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 <glib.h>
-
-#include "mesh.h"
-#include "mesh-log.h"
-#include "mesh-util.h"
-#include "mesh-gdbus.h"
-#include "mesh-request.h"
-#include "mesh-netlink.h"
-#include "mesh-interface.h"
-#include "mesh-peer-monitor.h"
-
-#define MESH_MONITORING_TIME 5
-#define MESH_MAXIMUM_BEACON_LOST_COUNT 10
-
-static void _on_station_list_destroy(gpointer data)
-{
- mesh_station_info_s *info = (mesh_station_info_s*)data;
-
- if (info) {
- g_free(info->bssid);
- g_free(info);
- }
-}
-#if 0
-static void _on_mpath_list_destroy(gpointer data)
-{
- mesh_mpath_info_s *info = (mesh_mpath_info_s*)data;
-
- if (info) {
- g_free(info->dest_addr);
- g_free(info->next_hop);
- g_free(info->interface);
- g_free(info);
- }
-}
-#endif
-
-static int _get_station_info(void *pdata)
-{
- int is_new;
- int ret = MESHD_ERROR_NONE;
-
- GList *iter = NULL;
- GList *sta_list = NULL;
- GList *cmp_iter = NULL;
-
- mesh_service *service = (mesh_service *)pdata;
- mesh_interface_s *info = service->interface_info;
-
- ret = mesh_request_get_station_info(info->mesh_interface, &sta_list);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to mesh_request_get_station_info");
- return ret;
- }
-
- iter = service->station_list;
- while (iter) {
- mesh_station_info_s *item = (mesh_station_info_s*)iter->data;
- MESH_LOGD("[%s]", item->bssid);
- iter = g_list_next(iter);
- }
-
- iter = sta_list;
- while (iter) {
- mesh_station_info_s *item = (mesh_station_info_s*)iter->data;
-
- /* Found this in th existing station infomation list. */
- if (item->inactive_time > item->beacon_interval * MESH_MAXIMUM_BEACON_LOST_COUNT) {
- /* Remove this node from station list in kernel */
- mesh_netlink_del_station_info(info->mesh_interface, item->bssid);
- /* Remove current linked list */
- iter = g_list_remove(iter, item);
- /* Send existing node disjoined */
- MESH_LOGE("[%s] disjoined", item->bssid);
-
- }
-
- is_new = TRUE;
- cmp_iter = service->station_list;
- while (cmp_iter) {
- mesh_station_info_s *cmp_item = (mesh_station_info_s*)cmp_iter->data;
- if (0 == strncmp(item->bssid, cmp_item->bssid, sizeof("11:22:33:44:55:66"))) {
- is_new = FALSE;
- break;
- }
- cmp_iter = g_list_next(cmp_iter);
- }
-
- if (is_new) {
- /* Send new station joined event */
- MESH_LOGE("[%s] joined", item->bssid);
- }
-
- iter = g_list_next(iter);
- }
-
- /* Clear mesh station list */
- g_list_free_full(service->station_list, _on_station_list_destroy);
- /* Copy new mesh station list */
- service->station_list = sta_list;
-
- iter = service->station_list;
- while (iter) {
- mesh_station_info_s *item2 = (mesh_station_info_s*)iter->data;
- MESH_LOGE("[%s]", item2->bssid);
- iter = g_list_next(iter);
- }
-
- return ret;
-}
-#if 0
-static gboolean _get_mpath_info(void *pdata)
-{
- int ret = MESHD_ERROR_NONE;
- GVariantBuilder builder;
- GVariant* mpath_data;
- GList *iter = NULL;
-
- mesh_service *service = (mesh_service *)pdata;
- mesh_interface_s *info = service->interface_info;
-
- /* Clear mesh path list */
- g_list_free_full(service->mpath_list, _on_mpath_list_destroy);
- service->mpath_list = NULL;
-
- ret = mesh_request_get_mpath_info(info->mesh_interface, &service->mpath_list);
- if (MESHD_ERROR_NONE == ret) {
- /*
- * Example) sh-3.2# iw mesh0 mpath dump
- * DEST ADDR NEXT HOP IFACE SN METRIC QLEN EXPTIME DTIM DRET FLAGS
- * 7c:dd:90:62:37:cf 7c:dd:90:62:37:cf mesh0 221 152 0 10 100 0 0x5
- */
- /* Get mesh path information and make variant data */
- g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
-
- iter = service->mpath_list;
- while (iter != NULL) {
- mesh_mpath_info_s *item = (mesh_mpath_info_s*)iter->data;
-
- g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
- g_variant_builder_add(&builder, "{sv}", "DEST_ADDR",
- g_variant_new_string(item->dest_addr));
- g_variant_builder_add(&builder, "{sv}", "NEXT_HOP",
- g_variant_new_string(item->next_hop));
- g_variant_builder_add(&builder, "{sv}", "IFACE",
- g_variant_new_string(item->interface));
- g_variant_builder_add(&builder, "{sv}", "SN",
- g_variant_new_uint32(item->sn));
- g_variant_builder_add(&builder, "{sv}", "METRIC",
- g_variant_new_uint32(item->metric));
- g_variant_builder_add(&builder, "{sv}", "QLEN",
- g_variant_new_uint32(item->qlen));
- g_variant_builder_add(&builder, "{sv}", "EXPTIME",
- g_variant_new_uint32(item->exptime));
- g_variant_builder_add(&builder, "{sv}", "DTIM",
- g_variant_new_uint32(item->discovery_timeout));
- g_variant_builder_add(&builder, "{sv}", "DRET",
- g_variant_new_byte(item->discovery_retries));
- g_variant_builder_add(&builder, "{sv}", "FLAGS",
- g_variant_new_byte(item->flags));
- g_variant_builder_close(&builder);
-
- iter = g_list_next(iter);
- }
-
- mpath_data = g_variant_builder_end(&builder);
- g_object_unref(mpath_data);
- } else
- MESH_LOGE("Failed to mesh_request_get_mpath_info");
-
- return ret;
-}
-#endif
-static gboolean _on_mesh_monitor_cb(gpointer pdata)
-{
- int ret;
- bool state;
- mesh_service *service = (mesh_service *)pdata;
- if (service) {
- mesh_interface_s *info = service->interface_info;
- if (info) {
- /* Exceptionally, checking external interface processes here. */
- ret = mesh_interface_check_external_exists(info->external_interface, &state);
- MESH_LOGD("Status : %d %d %d", ret, info->can_be_gate, state);
- if (MESHD_ERROR_NONE == ret) {
- if (info->can_be_gate != state) {
- mesh_gdbus_enable_ethernet_interface(service, state);
-#if 0
- /* 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);
-#endif
- MESH_LOGD("External interface state has been changed : [%d]", state);
- info->can_be_gate = state;
- }
- } else {
- /* In error case, we call enable etheret again for OdroidU3 */
- mesh_gdbus_enable_ethernet_interface(service, true);
- }
-#if 0
- _get_mpath_info(service);
-#endif
- _get_station_info(service);
- }
- }
-
- return G_SOURCE_CONTINUE;
-}
-
-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 (service->monitor_timer)
- mesh_stop_monitor_service(pdata);
-
- 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_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 (service->monitor_timer) {
- g_source_remove(service->monitor_timer);
- service->monitor_timer = 0;
- }
-
- MESH_LOGD("Peer Monitoring Service Stopped");
- return ret;
-}
+++ /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 <stdlib.h>
-
-#include <glib.h>
-#include <gio/gio.h>
-
-#include "mesh.h"
-#include "mesh-log.h"
-#include "mesh-util.h"
-#include "mesh-service-interface.h"
-#include "mesh-generated-code.h"
-
-#include "mesh-bridge.h"
-#include "mesh-netlink.h"
-#include "mesh-interface.h"
-#include "mesh-request.h"
-#include "mesh-softap.h"
-#include "mesh-gdbus.h"
-
-int mesh_request_set_mesh_gate(const char* bridge_interface,
- const char* mesh_interface, const char* external_interface)
-{
- int ret = MESHD_ERROR_NONE;
- bool state = FALSE;
-
- ret = mesh_interface_check_external_exists(external_interface, &state);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to get external interface state !");
- return MESHD_ERROR_OPERATION_FAILED;
- }
- MESH_LOGD(" Ethernet cable state [%s]",
- (state) ? "Connected" : "Disconnected");
-
- /* Turn STP on */
- ret = mesh_bridge_set_stp(bridge_interface, TRUE);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to turn STP on !");
- return ret;
- }
-
- /* Set mesh parameters */
- ret = mesh_netlink_set_mesh_parameter(mesh_interface,
- "mesh_hwmp_rootmode", 4);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to set [mesh_hwmp_rootmode] : 4");
-
- ret = mesh_netlink_set_mesh_parameter(mesh_interface,
- "mesh_gate_announcements", 1);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to set [mesh_gate_announcements] : 1");
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_unset_mesh_gate(const char* bridge_interface,
- const char* mesh_interface, const char* external_interface)
-{
- int ret = MESHD_ERROR_NONE;
-
- NOTUSED(external_interface);
-
- /* Set mesh parameters */
- ret = mesh_netlink_set_mesh_parameter(mesh_interface,
- "mesh_hwmp_rootmode", 0);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to set [mesh_hwmp_rootmode] : 0");
-
- ret = mesh_netlink_set_mesh_parameter(mesh_interface,
- "mesh_gate_announcements", 0);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to set [mesh_gate_announcements] : 0");
-
- /* Turn STP off */
- ret = mesh_bridge_set_stp(bridge_interface, FALSE);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to turn STP off!");
- return ret;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_add_bridge_interface(const char* bridge_interface,
- const char* interface)
-{
- int ret = MESHD_ERROR_NONE;
-
- if (NULL == bridge_interface || NULL == interface) {
- MESH_LOGE("Invalid parameters");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("Adding interface[%s] into bridge[%s]...", interface, bridge_interface);
-
- /* Add external interface into bridge */
- ret = mesh_bridge_add_interface(bridge_interface, interface);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to add interface !");
- return ret;
- }
-
- /* Make external interface down */
- ret = mesh_interface_set(interface, NULL, MESH_INTERFACE_DOWN);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to change external interface state");
- return ret;
- }
-
- /* Make external interface up with cleared IP */
- ret = mesh_interface_set(interface, "0.0.0.0", MESH_INTERFACE_UP);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to change external interface state");
- return ret;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_remove_bridge_interface(const char* bridge_interface,
- const char* interface)
-{
- int ret = MESHD_ERROR_NONE;
-
- if (NULL == bridge_interface || NULL == interface) {
- MESH_LOGE("Invalid parameters");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("Removing interface[%s] from bridge[%s]...", interface, bridge_interface);
-
- ret = mesh_interface_check_bridge_interface_exists(bridge_interface, interface);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGD("Interface is not exist in bridge");
- return MESHD_ERROR_NONE;
- }
-
- /* Remove external interface into bridge */
- ret = mesh_bridge_del_interface(bridge_interface, interface);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to remove interface !");
- return ret;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_set_softap_config(const char* softap_interface,
- const char *ssid, const char* mode, int channel, int visibility,
- int max_sta, int security, const char* passphrase)
-{
- int ret = MESHD_ERROR_NONE;
-
- MESH_LOGD("Setting configuration for SoftAP");
-
- ret = mesh_softap_set_configuration(softap_interface, ssid, mode, channel,
- visibility, max_sta, security, passphrase);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to set Configuration for SoftAP");
- return ret;
- }
-
- return ret;
-}
-
-int mesh_request_enable_softap(
- const char* bridge_interface, const char* softap_interface)
-{
- int ret = MESHD_ERROR_NONE;
-
- MESH_LOGD("Request to turn SoftAP on");
- ret = mesh_softap_enable_softap(softap_interface);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to mesh_softap_enable_softap");
- return ret;
- }
-
- /* Add softAP interface into bridge */
- ret = mesh_request_add_bridge_interface(bridge_interface, softap_interface);
- if (MESHD_ERROR_NONE != ret) {
- mesh_softap_disable_softap();
- return ret;
- }
-
- return ret;
-}
-
-int mesh_request_disable_softap(
- const char* bridge_interface, const char* softap_interface)
-{
- int ret = MESHD_ERROR_NONE;
-
- MESH_LOGD("Request to turn SoftAP off");
- ret = mesh_softap_disable_softap();
-
- /* Remove softAP interface from bridge */
- ret = mesh_request_remove_bridge_interface(bridge_interface, softap_interface);
- if (MESHD_ERROR_NONE != ret)
- return ret;
-
- return ret;
-}
-
-int mesh_request_get_station_info(const char* mesh_interface, GList **station_list)
-{
- int ret = MESHD_ERROR_NONE;
-
- MESH_LOGD("Request to get station info");
-
- /* Get station info */
- ret = mesh_netlink_get_station_info(mesh_interface, station_list);
- if (MESHD_ERROR_NONE != ret)
- return ret;
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_get_mpath_info(const char* mesh_interface, GList **mpath_list)
-{
- int ret = MESHD_ERROR_NONE;
-
- MESH_LOGD("Request to get mpath info");
-
- /* Get MPath info */
- ret = mesh_netlink_get_mpath_info(mesh_interface, mpath_list);
- if (MESHD_ERROR_NONE != ret)
- return ret;
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_register_event_handler()
-{
- int ret = MESHD_ERROR_NONE;
-
- MESH_LOGD("Request to register mesh event handler");
-
- /* Get MPath info */
- ret = mesh_netlink_register_event_handler();
- if (MESHD_ERROR_NONE != ret)
- return ret;
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_unregister_event_handler()
-{
- int ret = MESHD_ERROR_NONE;
-
- MESH_LOGD("Request to unregister mesh event handler");
-
- /* Get MPath info */
- ret = mesh_netlink_unregister_event_handler();
- if (MESHD_ERROR_NONE != ret)
- return ret;
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_enable_network(mesh_service *service)
-{
- int ret;
- mesh_interface_s *info = NULL;
-
- if (NULL == service) {
- MESH_LOGE("Invalid parameter");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("[IPC] Enable mesh network");
-
- /* Check if mesh interface exists */
- info = service->interface_info;
- ret = mesh_interface_check(info->mesh_interface);
- if (MESHD_ERROR_NONE == ret) {
- /* Interface already exists */
- return MESHD_ERROR_NONE;
- }
-
- ret = mesh_gdbus_create_mesh_interface(service);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to create mesh network");
- return ret;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_disable_network(mesh_service *service)
-{
- int ret;
- if (NULL == service) {
- MESH_LOGE("Invalid parameter");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("[IPC] Disable mesh network");
-
- ret = mesh_gdbus_remove_mesh_interface(service);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to disable mesh network");
- return ret;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_scan(mesh_service *service)
-{
- int ret;
- if (NULL == service) {
- MESH_LOGE("Invalid parameter");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("[IPC] Request scan for mesh network");
-
- ret = mesh_gdbus_mesh_scan(service);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to request scan for mesh network");
- return ret;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_specific_scan(mesh_service *service, gchar *mesh_id, gint channel)
-{
- int ret;
- if (NULL == service) {
- MESH_LOGE("Invalid parameter");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("[IPC] Request specific scan for mesh network");
-
- ret = mesh_gdbus_mesh_specific_scan(service, mesh_id, channel);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to request specific scan for mesh network");
- return ret;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_cancel_scan(mesh_service *service)
-{
- int ret;
- if (NULL == service) {
- MESH_LOGE("Invalid parameter");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("[IPC] Cancel scan for mesh network");
-
- ret = mesh_gdbus_mesh_cancel_scan(service);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to cancel scan for mesh network");
- return ret;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_get_networks(mesh_service *service)
-{
- int ret;
- if (NULL == service) {
- MESH_LOGE("Invalid parameter");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("[IPC] Get mesh networks");
-
- ret = mesh_gdbus_get_mesh_networks(service);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to get mesh networks !");
- return ret;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-static int _select_matched_network(GList *scanned_network,
- const char *mesh_id, int mesh_channel, meshd_security_type_e sec,
- mesh_scan_result_s **info)
-{
- int ret = MESHD_ERROR_NONE;
- GList *iter = NULL;
- mesh_scan_result_s *item = NULL;
- gboolean found = FALSE;
-
- meshd_check_null_ret_error("scanned_network", scanned_network,
- MESHD_ERROR_INVALID_PARAMETER);
-
- iter = scanned_network;
- while (iter != NULL) {
- item = (mesh_scan_result_s*)iter->data;
-
- if (g_strcmp0(mesh_id, item->mesh_id) == 0) {
- if (item->channel == mesh_channel && item->security == sec) {
- *info = item;
- found = TRUE;
- break;
- }
- }
- iter = g_list_next(iter);
- }
-
- if (FALSE == found)
- return MESHD_ERROR_NO_DATA;
-
- return ret;
-}
-
-int mesh_request_get_joined_network(mesh_service *service)
-{
- int ret;
-
- if (NULL == service) {
- MESH_LOGE("Invalid parameter");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("[IPC] Get joined mesh network");
-
- ret = mesh_gdbus_get_joined_mesh_network(service);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to get joined mesh network");
- return ret;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_get_connected_peers(mesh_service *service)
-{
- int ret;
-
- if (NULL == service) {
- MESH_LOGE("Invalid parameter");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("[IPC] Get connected mesh peers");
-
- ret = mesh_gdbus_get_connected_peers(service);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to get connected mesh peers");
- return ret;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_create_mesh_network(mesh_service *service, gchar *mesh_id,
- gint channel, meshd_security_type_e sec)
-{
- int ret;
-
- if (NULL == service) {
- MESH_LOGE("Invalid parameter");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("[IPC] Create a new mesh network");
-
- ret = mesh_gdbus_create_network(service, mesh_id, channel, sec);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to create mesh network");
- return ret;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_connect_mesh_network(mesh_service *service, gchar *mesh_id,
- gint channel, meshd_security_type_e sec, gchar *passphrase)
-{
- int ret;
- mesh_scan_result_s *info = NULL;
-
- if (NULL == service) {
- MESH_LOGE("Invalid parameter");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("[IPC] Connect mesh network");
-
- /* Get mesh_id and channel from saved network */
- ret = _select_matched_network(service->scanned_mesh_network,
- mesh_id, channel, sec, &info);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to mesh_network_get_first_mesh_network");
- return ret;
- }
-
- /* Set passphrase */
- if (MESHD_SECURITY_NONE != sec) {
- if (NULL != passphrase) {
- ret = mesh_gdbus_set_passphrase(service, info, passphrase);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to set passphrase for mesh network");
- return ret;
- }
- } else {
- MESH_LOGE("Passphrase is required !");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
- }
-
- ret = mesh_gdbus_connect_network(service, info);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to connect mesh network");
- return ret;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_disconnect_mesh_network(mesh_service *service,
- gchar *mesh_id, gint channel, meshd_security_type_e sec)
-{
- int ret;
- mesh_scan_result_s *info = NULL;
-
- if (NULL == service) {
- MESH_LOGE("Invalid parameter");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("[IPC] Disconnect mesh network");
-
- /* Get mesh_id and channel from saved network */
- ret = _select_matched_network(service->scanned_mesh_network,
- mesh_id, channel, sec, &info);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to _select_matched_network");
- return ret;
- }
-
- ret = mesh_gdbus_disconnect_network(service, info);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to disconnect mesh network");
- return ret;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_request_remove_mesh_network(mesh_service *service,
- gchar *mesh_id, gint channel, meshd_security_type_e sec)
-{
- int ret;
- mesh_scan_result_s *info = NULL;
-
- if (NULL == service) {
- MESH_LOGE("Invalid parameter");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- MESH_LOGD("[IPC] Remove mesh network");
-
- /* Get mesh_id and channel from saved network */
- ret = _select_matched_network(service->scanned_mesh_network,
- mesh_id, channel, sec, &info);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to _select_matched_network");
- return ret;
- }
-
- ret = mesh_gdbus_remove_network(service, info);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to remove mesh network");
- return ret;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-/* Notifications */
-void mesh_notify_scan_done()
-{
- NetMesh *object = meshd_dbus_get_object();
-
- net_mesh_emit_scan_done(object);
-}
-
-void mesh_notify_connection_state(const char* mesh_id, const char* bssid,
- int channel, meshd_security_type_e sec, meshd_connection_state_e state)
-{
- NetMesh *object = meshd_dbus_get_object();
-
- net_mesh_emit_connection_state(object, mesh_id, bssid, channel, (int)sec, (int)state);
-}
-
-void mesh_notify_station_joined(const char* bssid)
-{
- NetMesh *object = meshd_dbus_get_object();
-
- net_mesh_emit_sta_joined(object, bssid);
-}
-
-void mesh_notify_station_left(const char* bssid)
-{
- NetMesh *object = meshd_dbus_get_object();
-
- net_mesh_emit_sta_left(object, bssid);
-}
+++ /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 <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-#include <gio/gio.h>
-#include <wifi-manager.h>
-
-#include "mesh.h"
-#include "mesh-log.h"
-#include "mesh-util.h"
-#include "mesh-gdbus.h"
-#include "mesh-service.h"
-#include "mesh-peer-monitor.h"
-#include "mesh-service-interface.h"
-#include "mesh-generated-code.h"
-
-#include "mesh-request.h"
-#include "mesh-interface.h"
-
-static NetMesh *meshd_dbus_object;
-static Manager *meshd_activator_dbus_object;
-
-/* global list to care resource handle for each client */
-static GList *meshd_dbus_client_list;
-static GMutex meshd_dbus_client_list_mutex;
-
-typedef struct _meshd_dbus_client_s {
- gchar *bus_name;
-} meshd_dbus_client_s;
-
-#define CASE_TO_STR(x) case x: return #x;
-
-static const char* wifi_error_to_string(wifi_manager_error_e err)
-{
- switch (err) {
- /* CHECK: List all enum values here */
- CASE_TO_STR(WIFI_MANAGER_ERROR_NONE)
- CASE_TO_STR(WIFI_MANAGER_ERROR_INVALID_PARAMETER)
- CASE_TO_STR(WIFI_MANAGER_ERROR_OUT_OF_MEMORY)
- CASE_TO_STR(WIFI_MANAGER_ERROR_INVALID_OPERATION)
- CASE_TO_STR(WIFI_MANAGER_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED)
- CASE_TO_STR(WIFI_MANAGER_ERROR_OPERATION_FAILED)
- CASE_TO_STR(WIFI_MANAGER_ERROR_NO_CONNECTION)
- CASE_TO_STR(WIFI_MANAGER_ERROR_NOW_IN_PROGRESS)
- CASE_TO_STR(WIFI_MANAGER_ERROR_ALREADY_EXISTS)
- CASE_TO_STR(WIFI_MANAGER_ERROR_OPERATION_ABORTED)
- CASE_TO_STR(WIFI_MANAGER_ERROR_DHCP_FAILED)
- CASE_TO_STR(WIFI_MANAGER_ERROR_INVALID_KEY)
- CASE_TO_STR(WIFI_MANAGER_ERROR_NO_REPLY)
- CASE_TO_STR(WIFI_MANAGER_ERROR_SECURITY_RESTRICTED)
- CASE_TO_STR(WIFI_MANAGER_ERROR_ALREADY_INITIALIZED)
- CASE_TO_STR(WIFI_MANAGER_ERROR_PERMISSION_DENIED)
- CASE_TO_STR(WIFI_MANAGER_ERROR_NOT_SUPPORTED)
- default :
- return "WIFI_MANAGER_ERROR_UNKNOWN";
- }
-}
-
-NetMesh* meshd_dbus_get_object()
-{
- return meshd_dbus_object;
-}
-
-int64_t meshd_dbus_generate_signal_number()
-{
- static int64_t i = 0;
-
- return i++;
-}
-
-static int _meshd_dbus_client_list_cleanup(GList *client_list)
-{
- meshd_dbus_client_s *client;
-
- meshd_check_null_ret_error("client_list", client_list, FALSE);
-
- client = client_list->data;
-
- free(client->bus_name);
- client->bus_name = NULL;
- free(client);
- g_list_free(client_list);
-
- return MESHD_ERROR_NONE;
-}
-
-static int _meshd_dbus_client_list_compare_bus_name(const void *a, const void *b)
-{
- const meshd_dbus_client_s *client = a;
-
- return g_strcmp0(client->bus_name, b);
-}
-
-static inline GList* _meshd_dbus_client_list_find_client(const gchar *owner)
-{
- return g_list_find_custom(meshd_dbus_client_list, owner,
- _meshd_dbus_client_list_compare_bus_name);
-}
-
-static void _meshd_dbus_name_owner_changed_cb(GDBusConnection *conn,
- const gchar *sender_name,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *signal_name,
- GVariant *parameters,
- gpointer user_data)
-{
- int ret;
- GList *client = NULL;
- gchar *name, *old_owner, *new_owner;
-
- NOTUSED(conn);
- NOTUSED(sender_name);
- NOTUSED(object_path);
- NOTUSED(interface_name);
- NOTUSED(signal_name);
- NOTUSED(user_data);
-
- g_variant_get(parameters, "(&s&s&s)", &name, &old_owner, &new_owner);
-
- if (0 == strlen(new_owner)) {
- g_mutex_lock(&meshd_dbus_client_list_mutex);
- client = _meshd_dbus_client_list_find_client(old_owner);
- if (client) { /* found bus name in our bus list */
- MESH_LOGD("bus(%s) stopped", old_owner);
- meshd_dbus_client_list = g_list_remove_link(meshd_dbus_client_list, client);
- }
- g_mutex_unlock(&meshd_dbus_client_list_mutex);
-
- if (client) {
- ret = _meshd_dbus_client_list_cleanup(client);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("_meshd_dbus_client_list_cleanup() Fail(%d)", ret);
- }
- }
-}
-
-static int _meshd_dbus_subscribe_name_owner_changed(GDBusConnection *conn)
-{
- unsigned int id;
-
- id = g_dbus_connection_signal_subscribe(conn,
- "org.freedesktop.DBus", /* bus name */
- "org.freedesktop.DBus", /* interface */
- "NameOwnerChanged", /* member */
- "/org/freedesktop/DBus", /* path */
- NULL, /* arg0 */
- G_DBUS_SIGNAL_FLAGS_NONE,
- _meshd_dbus_name_owner_changed_cb,
- NULL,
- NULL);
- if (0 == id) {
- MESH_LOGE("g_dbus_connection_signal_subscribe() Fail");
- return MESHD_ERROR_IO_ERROR;
- }
-
- return MESHD_ERROR_NONE;
-}
-
-static gboolean _meshd_dbus_handle_enable(Manager *object,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
- mesh_interface_s *info = service->interface_info;
-
- wifi_manager_h wifi_handle = NULL;
- bool wifi_activated = false;
-
- /* Initialize Wi-Fi driver */
- ret = wifi_manager_initialize(&wifi_handle);
- if (WIFI_MANAGER_ERROR_NONE != ret)
- MESH_LOGE("Failed to get wifi manager handle ! [%s(%X)]",
- wifi_error_to_string(ret), ret);
-
- wifi_manager_is_activated(wifi_handle, &wifi_activated);
- if (false == wifi_activated) {
- ret = wifi_manager_activate(wifi_handle, NULL, NULL);
- if (WIFI_MANAGER_ERROR_NONE != ret)
- MESH_LOGE("Failed to activate wifi ! [%s(%X)]",
- wifi_error_to_string(ret), ret);
- }
- wifi_manager_deinitialize(wifi_handle);
-
- if (service->mesh_activated) {
- /* Already activated */
- manager_complete_enable(object, invocation, MESHD_ERROR_NONE);
- goto FINISH;
- }
-
- /* Do API response first */
- manager_complete_enable(object, invocation, ret);
- service->mesh_activated = TRUE;
-
- meshd_check_null_ret_error("info", info, FALSE);
-
- /* Register event handler first */
- ret = mesh_request_register_event_handler();
- if (MESHD_ERROR_IN_PROGRESS == ret) {
- MESH_LOGE("Currently set netlink event handler !! [%d]", ret);
- ret = MESHD_ERROR_NONE;
- } else if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to register mesh event handler !! [%d]", ret);
- }
-
- ret = mesh_interface_initialize(service->interface_info);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to mesh_interface_initialize [%d]", ret);
- goto FINISH;
- }
-
-FINISH:
- net_mesh_emit_mesh_enabled(meshd_dbus_get_object(), ret);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_disable(Manager *object,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
- mesh_interface_s *info = service->interface_info;
-
- meshd_check_null_ret_error("info", info, FALSE);
-
- /* Make response first */
- manager_complete_disable(object, invocation, ret);
-
- ret = mesh_request_unregister_event_handler();
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to unregister mesh event handler !! [%d]", ret);
-
- /* Terminate daemon */
- meshd_service_exit(service);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_scan(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
- mesh_interface_s *info = service->interface_info;
-
- meshd_check_null_ret_error("info", info, FALSE);
-
- ret = mesh_request_scan(service);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to mesh_request_scan !");
-
- net_mesh_complete_scan(object, invocation, ret);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_specific_scan(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gchar *mesh_id,
- gint channel,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
- mesh_interface_s *info = service->interface_info;
-
- meshd_check_null_ret_error("info", info, FALSE);
-
- ret = mesh_request_specific_scan(service, mesh_id, channel);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to mesh_request_specific_scan !");
-
- net_mesh_complete_specific_scan(object, invocation, ret);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_cancel_scan(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
-
- ret = mesh_request_cancel_scan(service);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to mesh_request_cancel_scan");
-
- net_mesh_complete_cancel_scan(object, invocation, ret);
-
- return TRUE;
-}
-
-static void _on_scan_result_destroy(gpointer data)
-{
- mesh_scan_result_s *scan_item = (mesh_scan_result_s *)data;
-
- if (scan_item) {
- g_free(scan_item->mesh_id);
- g_free(scan_item->bssid);
- g_free(scan_item->object_path);
- }
- g_free(scan_item);
-}
-
-static void _on_peer_info_destroy(gpointer data)
-{
- mesh_peer_info_s *peer = (mesh_peer_info_s *)data;
- if (peer)
- g_free(peer->address);
- g_free(peer);
-}
-
-static void _on_station_list_destroy(gpointer data)
-{
- mesh_station_info_s *info = (mesh_station_info_s*)data;
-
- if (info) {
- g_free(info->bssid);
- g_free(info);
- }
-}
-
-static void _on_mpath_list_destroy(gpointer data)
-{
- mesh_mpath_info_s *info = (mesh_mpath_info_s*)data;
-
- if (info) {
- g_free(info->dest_addr);
- g_free(info->next_hop);
- g_free(info->interface);
- g_free(info);
- }
-}
-
-static gboolean _meshd_dbus_handle_get_found_mesh_networks(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
-
- GVariantBuilder builder;
- GVariant* networks;
- GList *iter = NULL;
- mesh_scan_result_s *scan_item = NULL;
-
- MESH_LOGD("Request to get scanned mesh network list");
-
- ret = mesh_request_get_networks(service);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to mesh_request_get_networks");
-
- g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
-
- /* scanned_mesh_network would be filled above request */
- iter = service->scanned_mesh_network;
- while (iter != NULL) {
- scan_item = (mesh_scan_result_s*)iter->data;
-
- g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
- g_variant_builder_add(&builder, "{sv}", "mesh_id",
- g_variant_new_string(scan_item->mesh_id));
- g_variant_builder_add(&builder, "{sv}", "bssid",
- g_variant_new_string(scan_item->bssid));
- g_variant_builder_add(&builder, "{sv}", "rssi",
- g_variant_new_int32(scan_item->rssi));
- g_variant_builder_add(&builder, "{sv}", "channel",
- g_variant_new_uint32(scan_item->channel));
- g_variant_builder_add(&builder, "{sv}", "data_rate",
- g_variant_new_int32(scan_item->data_rate));
- g_variant_builder_add(&builder, "{sv}", "security",
- g_variant_new_uint32((int)scan_item->security));
- g_variant_builder_add(&builder, "{sv}", "state",
- g_variant_new_uint32(scan_item->state));
- g_variant_builder_close(&builder);
-
- iter = g_list_next(iter);
- }
-
- networks = g_variant_builder_end(&builder);
-
- net_mesh_complete_get_found_mesh_networks(object, invocation, networks, ret);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_enable_mesh(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
-
- /* It handles creating virtual network and bridge */
- ret = mesh_request_enable_network(service);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to mesh_request_enable_network [%d]", ret);
-
- mesh_start_monitor_service(service);
-
- net_mesh_complete_enable_mesh(object, invocation, ret);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_disable_mesh(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
- mesh_interface_s *info = service->interface_info;
-
- meshd_check_null_ret_error("info", info, FALSE);
-
- if (FALSE == service->mesh_activated) {
- MESH_LOGD("Mesh network is not activated yet");
- ret = MESHD_ERROR_OPERATION_FAILED;
- net_mesh_complete_disable_mesh(object, invocation, ret);
- return TRUE;
- }
-
- ret = mesh_request_disable_network(service);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to disable mesh network !");
-
- /* Stop Mesh Node Monitoring Service */
- mesh_stop_monitor_service(service);
- /* Make response */
- net_mesh_complete_disable_mesh(object, invocation, ret);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_is_joined(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- gboolean state = FALSE;
- mesh_service *service = (mesh_service *)user_data;
-
- ret = mesh_request_get_joined_network(service);
- if (MESHD_ERROR_NONE == ret) {
- if (service->joined_network)
- state = TRUE;
- }
-
- net_mesh_complete_is_joined(object, invocation, state, ret);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_get_joined_mesh_network(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
- mesh_network_info_s *joined = NULL;
-
- ret = mesh_request_get_joined_network(service);
- if (MESHD_ERROR_NONE == ret) {
- joined = service->joined_network;
- if (joined) {
- net_mesh_complete_get_joined_mesh_network(object, invocation,
- joined->mesh_id, joined->bssid,
- joined->channel, (int)joined->security,
- joined->state, ret);
- } else {
- net_mesh_complete_get_joined_mesh_network(object, invocation,
- "", "", 0, 0, 0, MESHD_ERROR_NO_DATA);
- }
- } else {
- net_mesh_complete_get_joined_mesh_network(object, invocation,
- "", "", 0, 0, 0, ret);
- }
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_get_connected_peers(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
-
- GVariantBuilder builder;
- GVariant* peer_list;
- GList *iter = NULL;
- mesh_peer_info_s *peer = NULL;
-
- MESH_LOGD("Request to get connected peers");
-
- ret = mesh_request_get_connected_peers(service);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to mesh_request_get_connected_peers");
- g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
-
- iter = service->connected_mesh_peers;
- while (iter != NULL) {
- peer = (mesh_peer_info_s*)iter->data;
-
- g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
- g_variant_builder_add(&builder, "{sv}", "Address",
- g_variant_new_string(peer->address));
- g_variant_builder_close(&builder);
-
- iter = g_list_next(iter);
- }
-
- peer_list = g_variant_builder_end(&builder);
-
- net_mesh_complete_get_connected_peers(object, invocation, peer_list, ret);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_set_gate(NetMesh *object,
- GDBusMethodInvocation *invocation, gint16 gate_announce, guint hwmp_root_mode,
- gboolean stp, gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
- mesh_interface_s *info = service->interface_info;
-
- MESH_LOGD("gate_announce = %d", gate_announce);
- MESH_LOGD("HWMP_Root_Mode = %d", hwmp_root_mode);
- MESH_LOGD("STP = %d", stp);
-
- info->gate_announce = gate_announce;
- info->hwmp_root_mode = hwmp_root_mode;
- info->stp = stp;
-
- /* Set STP and gate_announce for connmand */
- ret = mesh_gdbus_set_mesh_gate(service);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to mesh_gdbus_set_mesh_gate [%d]", ret);
-
- /* Set STP and gate_announce right now */
- 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_gdbus_set_mesh_gate [%d]", ret);
-
-
- net_mesh_complete_set_gate(object, invocation, ret);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_unset_gate(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
- mesh_interface_s *info = service->interface_info;
-
- info->gate_announce = 0;
- info->hwmp_root_mode = 0;
- info->stp = 0;
-
- /* Set STP and gate_announce for connmand */
- ret = mesh_gdbus_set_mesh_gate(service);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to mesh_gdbus_set_mesh_gate [%d]", ret);
-
- /* Unset STP and Gate Annouce right now */
- ret = mesh_request_unset_mesh_gate(info->bridge_interface,
- info->mesh_interface, info->external_interface);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to mesh_request_unset_mesh_gate [%d]", ret);
-
- net_mesh_complete_unset_gate(object, invocation, ret);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_set_softap(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gchar *ssid, gchar *passphrase,
- gchar *mode, gint channel, gint visibility, gint max_sta,
- gint security, gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
- mesh_interface_s *info = service->interface_info;
-
- MESH_LOGD("SSID : %s", ssid);
- MESH_LOGD("mode : %s", mode);
- MESH_LOGD("channel : %d", channel);
- MESH_LOGD("visibility: %d", visibility);
- MESH_LOGD("max_sta : %d", max_sta);
- MESH_LOGD("security : %d", security);
-
- /* Save softAP information */
- ret = mesh_request_set_softap_config(info->softap_interface,
- ssid, mode, channel, visibility, max_sta,
- security, passphrase);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to mesh_request_set_softap_config [%d]", ret);
-
- net_mesh_complete_set_softap(object, invocation, ret);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_enable_softap(NetMesh *object,
- GDBusMethodInvocation *invocation, gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
- mesh_interface_s *info = service->interface_info;
-
- /* Check softAP interface and execute it */
- ret = mesh_request_enable_softap(info->bridge_interface, info->softap_interface);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to mesh_request_enable_softap [%d]", ret);
-
- net_mesh_complete_enable_softap(object, invocation, ret);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_disable_softap(NetMesh *object,
- GDBusMethodInvocation *invocation, gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
- mesh_interface_s *info = service->interface_info;
-
- /* Destroy softAP */
- ret = mesh_request_disable_softap(info->bridge_interface, info->softap_interface);
- if (MESHD_ERROR_NONE != ret)
- MESH_LOGE("Failed to mesh_request_disable_softap [%d]", ret);
-
- net_mesh_complete_disable_softap(object, invocation, ret);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_create_mesh_network(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gchar *mesh_id, gint channel, gint security,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
- meshd_security_type_e sec = (1 == security) ? MESHD_SECURITY_SAE : MESHD_SECURITY_NONE;
-
- ret = mesh_request_create_mesh_network(service, mesh_id, channel, sec);
-
- net_mesh_complete_create_mesh_network(object, invocation, ret);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_connect_mesh_network(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gchar *mesh_id, gint channel, gint security, gchar *passphrase,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
- meshd_security_type_e sec = (1 == security) ? MESHD_SECURITY_SAE : MESHD_SECURITY_NONE;
-
- ret = mesh_request_connect_mesh_network(service, mesh_id, channel, sec, passphrase);
-
- net_mesh_complete_connect_mesh_network(object, invocation, ret);
-
- return TRUE;
-}
-static gboolean _meshd_dbus_handle_disconnect_mesh_network(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gchar *mesh_id, gint channel, gint security,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
- meshd_security_type_e sec = (1 == security) ? MESHD_SECURITY_SAE : MESHD_SECURITY_NONE;
-
- ret = mesh_request_disconnect_mesh_network(service, mesh_id, channel, sec);
-
- net_mesh_complete_disconnect_mesh_network(object, invocation, ret);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_forget_mesh_network(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gchar *mesh_id, gint channel, gint security,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
- meshd_security_type_e sec = (1 == security) ? MESHD_SECURITY_SAE : MESHD_SECURITY_NONE;
-
- ret = mesh_request_remove_mesh_network(service, mesh_id, channel, sec);
-
- net_mesh_complete_forget_mesh_network(object, invocation, ret);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_set_interfaces(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gchar *mesh, gchar *gate, gchar *softap,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- mesh_service *service = (mesh_service *)user_data;
- mesh_interface_s *info = service->interface_info;
-
- g_free(info->mesh_interface);
- info->mesh_interface = g_strdup(mesh);
-
- g_free(info->external_interface);
- info->external_interface = g_strdup(gate);
-
- g_free(info->softap_interface);
- info->softap_interface = g_strdup(softap);
-
- MESH_LOGD("Interface configuration for mesh network :");
- MESH_LOGD(" Base : [%s]", info->base_interface);
- MESH_LOGD(" Mesh : [%s]", info->mesh_interface);
- MESH_LOGD(" Bridge : [%s]", info->bridge_interface);
- MESH_LOGD(" SoftAP : [%s]", info->softap_interface);
- MESH_LOGD(" External: [%s]", info->external_interface);
-
- net_mesh_complete_set_interfaces(object, invocation, ret);
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_get_station_info(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
-
- GVariantBuilder builder;
- GVariant* station;
- GList *iter = NULL;
-
- mesh_service *service = (mesh_service *)user_data;
- mesh_interface_s *info = service->interface_info;
-
- /* Clear mesh station list */
- g_list_free_full(service->station_list, _on_station_list_destroy);
- service->station_list = NULL;
-
- ret = mesh_request_get_station_info(
- info->mesh_interface, &service->station_list);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to mesh_request_get_station_info");
-
- g_dbus_method_invocation_return_error(invocation,
- G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Request Failed");
- } else {
- /*
- * sh-3.2# iw mesh0 station dump
- * Station 7c:dd:90:62:37:cf (on mesh0)
- * inactive time: 1685 ms
- * rx bytes: 34174
- * rx packets: 1181
- * tx bytes: 6877
- * tx packets: 76
- * tx retries: 0
- * tx failed: 0
- * beacon loss: 0
- * signal: -64 dBm
- * signal avg: -63 dBm
- * tx bitrate: 54.0 MBit/s
- * rx bitrate: 5.5 MBit/s
- * mesh llid: 51731
- * mesh plid: 35432
- * mesh plink: ESTAB
- * mesh local PS mode: ACTIVE
- * mesh peer PS mode: ACTIVE
- * mesh non-peer PS mode: ACTIVE
- * authorized: yes
- * authenticated: yes
- * associated: yes
- * preamble: long
- * WMM/WME: yes
- * MFP: no
- * TDLS peer: no
- * DTIM period: 0
- * beacon interval:1000
- * short slot time:yes
- * connected time: 256 seconds
- */
- /* Get station information and make variant data */
- g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
-
- iter = service->station_list;
- while (iter != NULL) {
- mesh_station_info_s *item = (mesh_station_info_s*)iter->data;
-
- g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
- g_variant_builder_add(&builder, "{sv}", "bssid",
- g_variant_new_string(item->bssid));
- g_variant_builder_add(&builder, "{sv}", "inactive_time",
- g_variant_new_uint32(item->inactive_time));
- g_variant_builder_add(&builder, "{sv}", "rx_bytes",
- g_variant_new_uint64(item->rx_bytes));
- g_variant_builder_add(&builder, "{sv}", "rx_packets",
- g_variant_new_uint32(item->rx_packets));
- g_variant_builder_add(&builder, "{sv}", "tx_bytes",
- g_variant_new_uint64(item->tx_bytes));
- g_variant_builder_add(&builder, "{sv}", "tx_packets",
- g_variant_new_uint32(item->tx_packets));
- g_variant_builder_add(&builder, "{sv}", "tx_retries",
- g_variant_new_uint32(item->tx_retries));
- g_variant_builder_add(&builder, "{sv}", "tx_failed",
- g_variant_new_uint32(item->tx_failed));
- g_variant_builder_add(&builder, "{sv}", "beacon_loss",
- g_variant_new_uint32(item->beacon_loss));
- g_variant_builder_add(&builder, "{sv}", "beacon_rx",
- g_variant_new_uint64(item->beacon_rx));
- g_variant_builder_add(&builder, "{sv}", "rx_drop_misc",
- g_variant_new_uint64(item->rx_drop_misc));
- g_variant_builder_add(&builder, "{sv}", "signal",
- g_variant_new_int32(item->rssi));
- g_variant_builder_add(&builder, "{sv}", "signal_avg",
- g_variant_new_int32(item->rssi_avg));
- g_variant_builder_add(&builder, "{sv}", "tx_bitrate",
- g_variant_new_uint32(item->tx_bitrate)); /* 10 times */
- g_variant_builder_add(&builder, "{sv}", "rx_bitrate",
- g_variant_new_uint32(item->rx_bitrate)); /* 10 times */
- g_variant_builder_add(&builder, "{sv}", "mesh_llid",
- g_variant_new_uint16(item->llid));
- g_variant_builder_add(&builder, "{sv}", "mesh_plid",
- g_variant_new_uint16(item->plid));
- g_variant_builder_add(&builder, "{sv}", "mesh_plink",
- g_variant_new_byte(item->mesh_plink)); /* 0 : DISCON, 1 : ESTAB */
- g_variant_builder_add(&builder, "{sv}", "local_ps_mode",
- g_variant_new_uint32(item->local_ps_mode)); /* 0 : INACTIVE, 1 : ACTIVE */
- g_variant_builder_add(&builder, "{sv}", "peer_ps_mode",
- g_variant_new_uint32(item->peer_ps_mode)); /* 0 : INACTIVE, 1 : ACTIVE */
- g_variant_builder_add(&builder, "{sv}", "non_peer_ps_mode",
- g_variant_new_uint32(item->non_peer_ps_mode)); /* 0 : INACTIVE, 1 : ACTIVE */
- g_variant_builder_add(&builder, "{sv}", "authorized",
- g_variant_new_boolean(item->authorized));
- g_variant_builder_add(&builder, "{sv}", "associated",
- g_variant_new_boolean(item->associated));
- g_variant_builder_add(&builder, "{sv}", "preamble",
- g_variant_new_boolean(item->preamble));
- g_variant_builder_add(&builder, "{sv}", "WMM_WME",
- g_variant_new_boolean(item->wme));
- g_variant_builder_add(&builder, "{sv}", "MFP",
- g_variant_new_boolean(item->mfp));
- g_variant_builder_add(&builder, "{sv}", "TDLS_peer",
- g_variant_new_boolean(item->tdls_peer));
- g_variant_builder_add(&builder, "{sv}", "DTIM_period",
- g_variant_new_byte(item->dtim_period));
- g_variant_builder_add(&builder, "{sv}", "beacon_interval",
- g_variant_new_uint16(item->beacon_interval));
- g_variant_builder_add(&builder, "{sv}", "short_slot_time",
- g_variant_new_boolean(item->short_slot_time));
- g_variant_builder_add(&builder, "{sv}", "connected_time",
- g_variant_new_uint32(item->connected_time));
- g_variant_builder_close(&builder);
-
- iter = g_list_next(iter);
- }
-
- station = g_variant_builder_end(&builder);
- net_mesh_complete_get_station_info(object, invocation, station, ret);
-
- g_object_unref(station);
- }
-
- return TRUE;
-}
-
-static gboolean _meshd_dbus_handle_get_mpath_info(NetMesh *object,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- int ret = MESHD_ERROR_NONE;
- GVariantBuilder builder;
- GVariant* mpath_data;
- GList *iter = NULL;
-
- mesh_service *service = (mesh_service *)user_data;
- mesh_interface_s *info = service->interface_info;
-
- /* Clear mesh path list */
- g_list_free_full(service->mpath_list, _on_mpath_list_destroy);
- service->mpath_list = NULL;
-
- ret = mesh_request_get_mpath_info(
- info->mesh_interface, &service->mpath_list);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("Failed to mesh_request_get_mpath_info");
-
- g_dbus_method_invocation_return_error(invocation,
- G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Request Failed");
- } else {
- /*
- * Example) sh-3.2# iw mesh0 mpath dump
- * DEST ADDR NEXT HOP IFACE SN METRIC QLEN EXPTIME DTIM DRET FLAGS
- * 7c:dd:90:62:37:cf 7c:dd:90:62:37:cf mesh0 221 152 0 10 100 0 0x5
- */
- /* Get mesh path information and make variant data */
- g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
-
- iter = service->mpath_list;
- while (iter != NULL) {
- mesh_mpath_info_s *item = (mesh_mpath_info_s*)iter->data;
-
- g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
- g_variant_builder_add(&builder, "{sv}", "DEST_ADDR",
- g_variant_new_string(item->dest_addr));
- g_variant_builder_add(&builder, "{sv}", "NEXT_HOP",
- g_variant_new_string(item->next_hop));
- g_variant_builder_add(&builder, "{sv}", "IFACE",
- g_variant_new_string(item->interface));
- g_variant_builder_add(&builder, "{sv}", "SN",
- g_variant_new_uint32(item->sn));
- g_variant_builder_add(&builder, "{sv}", "METRIC",
- g_variant_new_uint32(item->metric));
- g_variant_builder_add(&builder, "{sv}", "QLEN",
- g_variant_new_uint32(item->qlen));
- g_variant_builder_add(&builder, "{sv}", "EXPTIME",
- g_variant_new_uint32(item->exptime));
- g_variant_builder_add(&builder, "{sv}", "DTIM",
- g_variant_new_uint32(item->discovery_timeout));
- g_variant_builder_add(&builder, "{sv}", "DRET",
- g_variant_new_byte(item->discovery_retries));
- g_variant_builder_add(&builder, "{sv}", "FLAGS",
- g_variant_new_byte(item->flags));
- g_variant_builder_close(&builder);
-
- iter = g_list_next(iter);
- }
-
- mpath_data = g_variant_builder_end(&builder);
- net_mesh_complete_get_mpath_info(object, invocation, mpath_data, ret);
-
- g_object_unref(mpath_data);
- }
-
- return TRUE;
-}
-
-static void _meshd_dbus_on_activator_bus_acquired(GDBusConnection *conn,
- const gchar *name, gpointer user_data)
-{
- gboolean ret;
- GError *error = NULL;
- mesh_service *service = (mesh_service *)user_data;
-
- NOTUSED(name);
-
- meshd_activator_dbus_object = manager_skeleton_new();
- if (NULL == meshd_activator_dbus_object) {
- MESH_LOGE("manager_skeleton_new() Fail");
- return;
- }
-
- g_signal_connect(meshd_activator_dbus_object, "handle-enable",
- G_CALLBACK(_meshd_dbus_handle_enable), service);
- g_signal_connect(meshd_activator_dbus_object, "handle-disable",
- G_CALLBACK(_meshd_dbus_handle_disable), service);
-
- ret = g_dbus_interface_skeleton_export(
- G_DBUS_INTERFACE_SKELETON(meshd_activator_dbus_object),
- conn, MESH_DBUS_MANAGER_OBJPATH, &error);
- if (FALSE == ret) {
- MESH_LOGE("g_dbus_interface_skeleton_export() Fail(%s)", error->message);
- g_error_free(error);
- }
-}
-
-static void _meshd_dbus_on_bus_acquired(GDBusConnection *conn, const gchar *name,
- gpointer user_data)
-{
- gboolean ret;
- GError *error = NULL;
- mesh_service *service = (mesh_service *)user_data;
-
- NOTUSED(name);
-
- meshd_dbus_object = net_mesh_skeleton_new();
- if (NULL == meshd_dbus_object) {
- MESH_LOGE("net_mesh_skeleton_new() Fail");
- return;
- }
-
- g_signal_connect(meshd_dbus_object, "handle-scan",
- G_CALLBACK(_meshd_dbus_handle_scan), service);
- g_signal_connect(meshd_dbus_object, "handle-specific-scan",
- G_CALLBACK(_meshd_dbus_handle_specific_scan), service);
- g_signal_connect(meshd_dbus_object, "handle-cancel-scan",
- G_CALLBACK(_meshd_dbus_handle_cancel_scan), service);
- g_signal_connect(meshd_dbus_object, "handle-get-found-mesh-networks",
- G_CALLBACK(_meshd_dbus_handle_get_found_mesh_networks), service);
- g_signal_connect(meshd_dbus_object, "handle-enable-mesh",
- G_CALLBACK(_meshd_dbus_handle_enable_mesh), service);
- g_signal_connect(meshd_dbus_object, "handle-disable-mesh",
- G_CALLBACK(_meshd_dbus_handle_disable_mesh), service);
- g_signal_connect(meshd_dbus_object, "handle-is-joined",
- G_CALLBACK(_meshd_dbus_handle_is_joined), service);
- g_signal_connect(meshd_dbus_object, "handle-get-joined-mesh-network",
- G_CALLBACK(_meshd_dbus_handle_get_joined_mesh_network), service);
- g_signal_connect(meshd_dbus_object, "handle-get-connected-peers",
- G_CALLBACK(_meshd_dbus_handle_get_connected_peers), service);
- g_signal_connect(meshd_dbus_object, "handle-set-gate",
- G_CALLBACK(_meshd_dbus_handle_set_gate), service);
- g_signal_connect(meshd_dbus_object, "handle-unset-gate",
- G_CALLBACK(_meshd_dbus_handle_unset_gate), service);
- g_signal_connect(meshd_dbus_object, "handle-set-softap",
- G_CALLBACK(_meshd_dbus_handle_set_softap), service);
- g_signal_connect(meshd_dbus_object, "handle-enable-softap",
- G_CALLBACK(_meshd_dbus_handle_enable_softap), service);
- g_signal_connect(meshd_dbus_object, "handle-disable-softap",
- G_CALLBACK(_meshd_dbus_handle_disable_softap), service);
- g_signal_connect(meshd_dbus_object, "handle-create-mesh-network",
- G_CALLBACK(_meshd_dbus_handle_create_mesh_network), service);
- g_signal_connect(meshd_dbus_object, "handle-connect-mesh-network",
- G_CALLBACK(_meshd_dbus_handle_connect_mesh_network), service);
- g_signal_connect(meshd_dbus_object, "handle-disconnect-mesh-network",
- G_CALLBACK(_meshd_dbus_handle_disconnect_mesh_network), service);
- g_signal_connect(meshd_dbus_object, "handle-forget-mesh-network",
- G_CALLBACK(_meshd_dbus_handle_forget_mesh_network), service);
- g_signal_connect(meshd_dbus_object, "handle-set-interfaces",
- G_CALLBACK(_meshd_dbus_handle_set_interfaces), service);
- g_signal_connect(meshd_dbus_object, "handle-get-station-info",
- G_CALLBACK(_meshd_dbus_handle_get_station_info), service);
- g_signal_connect(meshd_dbus_object, "handle-get-mpath-info",
- G_CALLBACK(_meshd_dbus_handle_get_mpath_info), service);
-
- ret = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(meshd_dbus_object),
- conn, MESH_DBUS_OBJPATH, &error);
- if (FALSE == ret) {
- MESH_LOGE("g_dbus_interface_skeleton_export() Fail(%s)", error->message);
- g_error_free(error);
- }
-
- ret = _meshd_dbus_subscribe_name_owner_changed(conn);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("_meshd_dbus_subscribe_name_owner_changed() Fail(%d)", ret);
- return;
- }
-}
-
-static void _meshd_dbus_on_name_lost(GDBusConnection *conn, const gchar *name,
- gpointer user_data)
-{
- NOTUSED(conn);
- NOTUSED(user_data);
-
- MESH_LOGD("Lost the name %s", name);
-}
-
-static void _meshd_dbus_on_name_acquired(GDBusConnection *conn, const gchar *name,
- gpointer user_data)
-{
- NOTUSED(conn);
- NOTUSED(user_data);
-
- MESH_LOGD("Acquired the name %s", name);
-}
-
-static gboolean _meshd_dbus_interface_init(mesh_service *service)
-{
- guint id;
- guint activation_dbus_id;
- meshd_check_null_ret_error("service", service, FALSE);
-
- id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
- MESH_DBUS_INTERFACE,
- G_BUS_NAME_OWNER_FLAGS_REPLACE,
- _meshd_dbus_on_bus_acquired,
- _meshd_dbus_on_name_acquired,
- _meshd_dbus_on_name_lost,
- service,
- NULL);
- if (0 == id) {
- MESH_LOGE("g_bus_own_name() Fail");
- return FALSE;
- }
-
- /* Get D-Bus owner to activate mesh service daemon */
- activation_dbus_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
- MESH_DBUS_INTERFACE".manager",
- G_BUS_NAME_OWNER_FLAGS_REPLACE,
- _meshd_dbus_on_activator_bus_acquired,
- NULL,
- NULL,
- service,
- NULL);
-
- service->dbus_id = id;
- service->activation_dbus_id = activation_dbus_id;
- service->interface_info = g_new0(mesh_interface_s, 1);
- service->scanned_mesh_network = NULL;
-
- /* Initialize DBus sendor logic */
- meshd_dbus_start(service);
-
- return TRUE;
-}
-
-static void _meshd_dbus_deinit(mesh_service *service)
-{
- mesh_interface_s *info = NULL;
- meshd_check_null_ret("service", service);
-
- /* De-Initialize DBus sendor logic */
- meshd_dbus_stop(service);
-
- g_bus_unown_name(service->dbus_id);
- g_bus_unown_name(service->activation_dbus_id);
-
- info = service->interface_info;
- meshd_check_null_ret("info", info);
- if (info->bridge_interface)
- g_free(info->bridge_interface);
- if (info->base_interface)
- g_free(info->base_interface);
- if (info->mesh_interface)
- g_free(info->mesh_interface);
- if (info->softap_interface)
- g_free(info->softap_interface);
- if (info->external_interface)
- g_free(info->external_interface);
-
- if (service->joined_network) {
- g_free(service->joined_network->mesh_id);
- g_free(service->joined_network->bssid);
- g_free(service->joined_network);
- service->joined_network = NULL;
- }
-
- /* Clear scan list */
- if (service->scanned_mesh_network)
- g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy);
- service->scanned_mesh_network = NULL;
-
- /* Clear connected peers list */
- if (service->connected_mesh_peers)
- g_list_free_full(service->connected_mesh_peers, _on_peer_info_destroy);
- service->connected_mesh_peers = NULL;
-
- /* Clear mesh path list */
- if (service->mpath_list)
- g_list_free_full(service->mpath_list, _on_mpath_list_destroy);
- service->mpath_list = NULL;
-
- /* Clear mesh station list */
- if (service->station_list)
- g_list_free_full(service->station_list, _on_station_list_destroy);
- service->station_list = NULL;
-
- g_free(service->interface_info);
- service->interface_info = NULL;
-}
-
-/**< Mesh service interface initialization */
-gboolean meshd_service_interface_init(mesh_service *service)
-{
- guint ret;
- meshd_check_null_ret_error("service", service, FALSE);
-
- /* Initialize dbus interface */
- ret = _meshd_dbus_interface_init(service);
- if (FALSE == ret) {
- MESH_LOGE("_meshd_dbus_interface_init failed!!!");
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**< Mesh service interface de-initialization */
-void meshd_service_interface_deinit(mesh_service *service)
-{
- meshd_check_null_ret("service", service);
-
- /* De-initialize dbus interface */
- _meshd_dbus_deinit(service);
-}
+++ /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 <glib.h>
-
-#include "mesh.h"
-#include "mesh-log.h"
-#include "mesh-util.h"
-#include "mesh-service.h"
-
-mesh_service *meshd_service_new()
-{
- mesh_service *service;
-
- service = g_malloc0(sizeof(struct _mesh_service));
-
- /* Create g-main loop */
- service->main_loop = g_main_loop_new(NULL, FALSE);
- if (G_UNLIKELY(NULL == service->main_loop)) {
- MESH_LOGE("g-main loop creation failed!!!");
- g_free(service);
- return NULL;
- }
-
- return service;
-}
-
-void meshd_service_free(mesh_service *service)
-{
- meshd_check_null_ret("service", service);
-
- /* Unref 'g-main loop' */
- if (service->main_loop)
- g_main_loop_unref(service->main_loop);
-
- g_free(service);
-}
-
-gboolean meshd_service_run(mesh_service *service)
-{
- meshd_check_null_ret_error("service", service, FALSE);
- meshd_check_null_ret_error("service->main_loop", service->main_loop, FALSE);
-
- g_main_loop_run(service->main_loop);
-
- return TRUE;
-}
-
-gboolean meshd_service_exit(mesh_service *service)
-{
- meshd_check_null_ret_error("service", service, FALSE);
- meshd_check_null_ret_error("service->main_loop", service->main_loop, FALSE);
-
- g_main_loop_quit(service->main_loop);
-
- return TRUE;
-}
+++ /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 <glib.h>
-#include <tzplatform_config.h>
-#include <openssl/evp.h>
-#include <openssl/sha.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/wait.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "mesh.h"
-#include "mesh-log.h"
-#include "mesh-util.h"
-#include "mesh-service.h"
-#include "mesh-softap.h"
-
-#define MOBILE_AP_WIFI_KEY_MAX_LEN 64 /**< Maximum length of wifi hash key */
-
-#define HOSTAPD_VENDOR_ELEMENTS_WIFI_AP "DD050016321000" /* Specific application mode AP (e.g. GroupPlay) */
-#define HOSTAPD_CONF "interface=%s\n" \
- "driver=nl80211\n" \
- "ctrl_interface=%s\n" \
- "ssid=%s\n" \
- "channel=%d\n" \
- "ignore_broadcast_ssid=%d\n" \
- "hw_mode=%s\n" \
- "max_num_sta=%d\n" \
- "macaddr_acl=%d\n" \
- "accept_mac_file=%s\n" \
- "deny_mac_file=%s\n" \
- "ieee80211n=1\n"
-#define HOSTAPD_CONF_LEN 1024
-#define HOSTAPD_BIN "/usr/sbin/hostapd"
-#define HOSTAPD_DEBUG_FILE "/var/log/mesh_hostapd.log"
-#define HOSTAPD_ENTROPY_FILE tzplatform_mkpath(TZ_SYS_VAR, "/lib/misc/hostapd.bin")
-#define HOSTAPD_MESH_CONF_FILE tzplatform_mkpath(TZ_SYS_VAR, "/lib/mesh/mesh_hostapd.conf")
-#define HOSTAPD_CTRL_INTF_DIR tzplatform_mkpath(TZ_SYS_RUN, "/hostapd")
-#define HOSTAPD_PID_FILE tzplatform_mkpath(TZ_SYS_RUN, "/.mesh_hostapd.pid")
-#define HOSTAPD_ALLOWED_LIST tzplatform_mkpath(TZ_SYS_VAR, "/lib/hostapd/hostapd.accept")
-#define HOSTAPD_BLOCKED_LIST tzplatform_mkpath(TZ_SYS_VAR, "/lib/hostapd/hostapd.deny")
-#define HOSTAPD_RETRY_MAX 5
-#define HOSTAPD_RETRY_DELAY 500000 /* us */
-
-#define MH_CTRL_INTF "/tmp/mesh_hostapd_wpa_ctrl"
-
-#define PSK_ITERATION_COUNT 4096
-#define MAX_BUF_SIZE (256u)
-
-static int hostapd_ctrl_fd = 0;
-
-static int __get_psk_hexascii(const char *pass, const unsigned char *salt,
- char *psk, unsigned int psk_len)
-{
- int i = 0;
- int d_16 = 0;
- int r_16 = 0;
- unsigned char buf[SHA256_DIGEST_LENGTH] = {0, };
-
- if (pass == NULL || salt == NULL || psk == NULL
- || psk_len < (SHA256_DIGEST_LENGTH * 2 + 1)) {
- MESH_LOGE("Invalid parameter");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- if (!PKCS5_PBKDF2_HMAC_SHA1(pass, strlen(pass),
- salt, strlen((const char *)salt),
- PSK_ITERATION_COUNT, sizeof(buf), buf)) {
- MESH_LOGE("Getting psk is failed");
- return MESHD_ERROR_OPERATION_FAILED;
- }
-
- for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
- d_16 = buf[i] >> 4;
- r_16 = buf[i] & 0xf;
-
- psk[i << 1] = d_16 < 10 ? d_16 + '0' : d_16 - 10 + 'a';
- psk[(i << 1) + 1] = r_16 < 10 ? r_16 + '0' : r_16 - 10 + 'a';
- }
- psk[i << 1] = '\0';
-
- return MESHD_ERROR_NONE;
-}
-
-static int __config_hostapd(const char *softap_interface, const char *ssid,
- const char *security, const char *passphrase, const char* mode,
- int channel, int visibility, int mac_filter, int max_sta)
-{
- char *conf = NULL;
- char *old_conf;
- char buf[HOSTAPD_CONF_LEN] = "";
- FILE *fp = NULL;
- int ret;
- char key[MOBILE_AP_WIFI_KEY_MAX_LEN + 1];
- char *hw_mode = NULL;
-
- if (mode == NULL)
- hw_mode = g_strdup("g");
- else
- hw_mode = g_strdup(mode);
-
- /* Default conf. */
- snprintf(buf, sizeof(buf), HOSTAPD_CONF,
- softap_interface,
- HOSTAPD_CTRL_INTF_DIR,
- ssid,
- channel,
- (visibility ? 0 : 2),
- hw_mode,
- max_sta,
- mac_filter,
- HOSTAPD_ALLOWED_LIST,
- HOSTAPD_BLOCKED_LIST);
- conf = g_strdup(buf);
-
- free(hw_mode);
-
- /* Vendor elements conf. */
- snprintf(buf, sizeof(buf),
- "vendor_elements=%s\n", HOSTAPD_VENDOR_ELEMENTS_WIFI_AP);
- old_conf = conf;
- conf = g_strconcat(old_conf, buf, NULL);
- g_free(old_conf);
-
- /* Security conf. */
- if (security != NULL && g_strcmp0(security, "wpa2-psk") == 0) {
- ret = __get_psk_hexascii(passphrase,
- (const unsigned char *)ssid, key, sizeof(key));
- if (ret != MESHD_ERROR_NONE) {
- g_free(conf);
- MESH_LOGE("hex conversion failed");
- return MESHD_ERROR_OPERATION_FAILED;
- }
- snprintf(buf, sizeof(buf),
- "wpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n", key);
-
- old_conf = conf;
- conf = g_strconcat(old_conf, buf, NULL);
- g_free(old_conf);
- } else {
- MESH_LOGD("Open connection [%s]", security);
- }
-
- fp = fopen(HOSTAPD_MESH_CONF_FILE, "w");
- if (NULL == fp) {
- MESH_LOGE("Could not create the file.");
- g_free(conf);
- return MESHD_ERROR_IO_ERROR;
- }
-
- if (conf) {
- fputs(conf, fp);
- g_free(conf);
- }
- fclose(fp);
-
- return MESHD_ERROR_NONE;
-}
-
-static int __open_hostapd_intf(const char* softap_interface, int *fd,
- const char *intf)
-{
- int retry = 0;
- char ctrl_intf[255] = {0, };
- struct sockaddr_un src;
- struct sockaddr_un dest;
- struct stat stat_buf;
-
- if (fd == NULL || intf == NULL) {
- MESH_LOGE("fd is NULL");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- *fd = socket(PF_UNIX, SOCK_DGRAM, 0);
- if (*fd < 0) {
- MESH_LOGE("socket is failed");
- return MESHD_ERROR_OPERATION_FAILED;
- }
-
- src.sun_family = AF_UNIX;
- g_strlcpy(src.sun_path, intf, sizeof(src.sun_path));
-
- if (stat(src.sun_path, &stat_buf) == 0)
- unlink(src.sun_path);
-
- if (bind(*fd, (struct sockaddr *)&src, sizeof(src)) < 0) {
- MESH_LOGE("bind is failed");
- close(*fd);
- *fd = -1;
- unlink(src.sun_path);
- return MESHD_ERROR_OPERATION_FAILED;
- }
-
- snprintf(ctrl_intf, sizeof(ctrl_intf), "%s/%s",
- HOSTAPD_CTRL_INTF_DIR, softap_interface);
- dest.sun_family = AF_UNIX;
- g_strlcpy(dest.sun_path, ctrl_intf, sizeof(dest.sun_path));
-
- while (connect(*fd, (struct sockaddr *)&dest, sizeof(dest)) < 0) {
- if (++retry >= HOSTAPD_RETRY_MAX)
- goto FAIL;
- usleep(HOSTAPD_RETRY_DELAY);
- }
- MESH_LOGD("Successfully open interface[%s] to hostapd", intf);
-
- return MESHD_ERROR_NONE;
-
-FAIL:
- MESH_LOGE("Cannot make connection to hostapd");
- close(*fd);
- *fd = -1;
- unlink(src.sun_path);
-
- return MESHD_ERROR_OPERATION_FAILED;
-}
-
-static int __close_hostapd_intf(int *fd)
-{
- if (fd == NULL) {
- MESH_LOGE("fd is NULL");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- if (*fd > 0)
- close(*fd);
- *fd = -1;
-
- return MESHD_ERROR_NONE;
-}
-
-static int __get_pid_of_hostapd(pid_t *pid)
-{
- FILE *fd = NULL;
- int ret = -1;
- int rv = 0;
- char error_buf[256] = {0, };
- char file_path[256] = {0, };
-
- snprintf(file_path, 256, "%s", HOSTAPD_PID_FILE);
-
- if (0 == access(file_path, F_OK)) {
- fd = fopen(file_path, "r");
- if (fd == NULL) {
- MESH_LOGE("Error! Could not open pid file");
- return MESHD_ERROR_IO_ERROR;
- }
- } else {
- MESH_LOGE("Error! Could not access pid file");
- return MESHD_ERROR_IO_ERROR;
- }
-
- errno = 0;
- rv = fscanf(fd, "%d", &ret);
- if (rv < 0) {
- strerror_r(errno, error_buf, 256);
- MESH_LOGE("Error! Failed to read from file, rv:[%d], error:[%s]",
- rv, error_buf);
- fclose(fd);
- return MESHD_ERROR_IO_ERROR;
- }
-
- *pid = (pid_t)ret;
- MESH_LOGD(" PID: [%d]", ret);
-
- fclose(fd);
- return MESHD_ERROR_NONE;
-}
-
-static int __terminate_hostapd()
-{
- int ret;
- pid_t hostapd_pid = 0;
-
- /* Get pid */
- ret = __get_pid_of_hostapd(&hostapd_pid);
- if (MESHD_ERROR_NONE != ret) {
- MESH_LOGE("There is no hostapd");
- return MESHD_ERROR_NONE;
- }
-
- if (hostapd_pid == 0) {
- MESH_LOGE("There is no hostapd");
- return MESHD_ERROR_NONE;
- }
-
- ret = __close_hostapd_intf(&hostapd_ctrl_fd);
- if (ret != MESHD_ERROR_NONE)
- MESH_LOGE("__close_hostapd_intf is failed");
-
- kill(hostapd_pid, SIGTERM);
-
- return MESHD_ERROR_NONE;
-}
-
-static int __execute_hostapd()
-{
- pid_t pid = 0;
- int status;
- int ret = MESHD_ERROR_NONE;
-
- ret = __get_pid_of_hostapd(&pid);
- if (0 != pid) {
- MESH_LOGE("hostapd is running already");
- return MESHD_ERROR_NONE;
- }
-
- pid = fork();
- if (pid < 0) {
- MESH_LOGE("fork failed");
- return MESHD_ERROR_IO_ERROR;
- }
-
- if (pid == 0) {
- if (execl(HOSTAPD_BIN, HOSTAPD_BIN, "-e", HOSTAPD_ENTROPY_FILE,
- HOSTAPD_MESH_CONF_FILE,
- "-f", HOSTAPD_DEBUG_FILE,
- "-P", HOSTAPD_PID_FILE,
- "-ddd", "-B",
- (char *)NULL)) {
- MESH_LOGE("execl failed");
- }
-
- MESH_LOGE("Should not get here!");
- exit(1);
- } else {
- /* Reap child */
- waitpid(pid, &status, 0);
- MESH_LOGD(" child [%d] reaped with status(%d)", pid, status);
- }
-
- return MESHD_ERROR_NONE;
-}
-
-int mesh_softap_set_configuration(const char* softap_interface,
- const char *ssid, const char* mode, int channel, int visibility,
- int max_sta, int security, const char* passphrase)
-{
- int ret = MESHD_ERROR_NONE;
- const char *sec = (security == 0) ? NULL : "wpa2-psk";
- int mac_filter = 0;
-
- ret = __config_hostapd(softap_interface, ssid, sec, passphrase,
- mode, channel, visibility, mac_filter, max_sta);
-
- return ret;
-}
-
-int mesh_softap_enable_softap(const char* softap_interface)
-{
- int ret = MESHD_ERROR_NONE;
-
- if (NULL == softap_interface) {
- MESH_LOGE("Invalid parameter");
- return MESHD_ERROR_INVALID_PARAMETER;
- }
-
- ret = __execute_hostapd();
- if (ret != MESHD_ERROR_NONE) {
- MESH_LOGE("__execute_hostapd is failed");
- return MESHD_ERROR_OPERATION_FAILED;
- }
-
- ret = __open_hostapd_intf(softap_interface,
- &hostapd_ctrl_fd, MH_CTRL_INTF);
- if (ret != MESHD_ERROR_NONE) {
- MESH_LOGE("__open_hostapd_intf is failed");
- __terminate_hostapd();
- }
-
- return ret;
-}
-
-int mesh_softap_disable_softap()
-{
- int ret = MESHD_ERROR_NONE;
-
- ret = __terminate_hostapd();
- if (ret != MESHD_ERROR_NONE) {
- MESH_LOGE("__execute_hostapd is failed");
- return MESHD_ERROR_OPERATION_FAILED;
- }
-
- return ret;
-}
+++ /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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include "mesh.h"
-#include "mesh-log.h"
-#include "mesh-util.h"
-#include "mesh-service.h"
-#include "mesh-service-interface.h"
-
-/**< mesh service */
-mesh_service *meshsvc;
-
-int main(int argc, char *argv[])
-{
- mesh_service *service = NULL;
- int ret_code = 0;
- gboolean ret;
-
- __MESH_LOG_FUNC_ENTER__;
-
-#if !GLIB_CHECK_VERSION(2, 32, 0)
- if (!g_thread_supported())
- g_thread_init(NULL);
-#endif
-
-#if !GLIB_CHECK_VERSION(2, 36, 0)
- g_type_init();
-#endif
- NOTUSED(argc);
- NOTUSED(argv);
-
- MESH_LOGI("service mainloop start");
-
- /* Create mesh service */
- meshsvc = service = meshd_service_new();
-
- /* Initialize mesh service interface layer */
- ret = meshd_service_interface_init(service);
- if (G_UNLIKELY(FALSE == ret)) {
- MESH_LOGE("meshd_service_interface_init failed!");
- goto END;
- }
-
- /* Run mesh service */
- ret = meshd_service_run(service);
- if (G_UNLIKELY(FALSE == ret)) {
- MESH_LOGE("Run service failed!");
- ret_code = EXIT_FAILURE;
- }
-
-END:
- /* Free mesh service */
- meshd_service_interface_deinit(service);
- meshd_service_free(service);
- meshsvc = NULL;
-
- __MESH_LOG_FUNC_EXIT__;
- return 0;
-}
-
--- /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 <glib.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <linux/if.h>
+#include <linux/if_bridge.h>
+#include <linux/sockios.h>
+
+extern unsigned int if_nametoindex(const char *__ifname);
+
+#include "wmesh.h"
+#include "wmesh-log.h"
+#include "wmesh-util.h"
+#include "wmesh-service.h"
+#include "wmesh-bridge.h"
+
+#define ERROR_MESSAGE_LENGTH 256
+
+int wmesh_bridge_create(const char* bridge_name)
+{
+ int ret = WMESHD_ERROR_NONE;
+ int val = 0;
+ int br_fd = 0;
+ char bridge[IFNAMSIZ];
+ char str_error[ERROR_MESSAGE_LENGTH];
+#if !defined(SIOCBRADDBR)
+ unsigned long arg[3] = { BRCTL_ADD_BRIDGE, (unsigned long)bridge };
+#endif
+
+ if (NULL == bridge_name || strlen(bridge_name) > IFNAMSIZ) {
+ WMESH_LOGE("Invalid parameter [%p]", bridge_name);
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ br_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+ if (br_fd < 0) {
+ strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
+ WMESH_LOGD("Failed to open socket [%s(%d)]", str_error, errno);
+
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ snprintf(bridge, IFNAMSIZ, "%s", bridge_name);
+#ifdef SIOCBRADDBR
+ val = ioctl(br_fd, SIOCBRADDBR, bridge_name);
+#else
+ val = ioctl(br_fd, SIOCSIFBR, arg);
+#endif
+ if (val < 0) {
+ strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
+ WMESH_LOGD("Failed to create bridge [%s(%d)]", str_error, errno);
+
+ ret = WMESHD_ERROR_IO_ERROR;
+ }
+
+ close(br_fd);
+
+ return ret;
+}
+
+int wmesh_bridge_remove(const char* bridge_name)
+{
+ int ret = WMESHD_ERROR_NONE;
+ int val = 0;
+ int br_fd = 0;
+ char bridge[IFNAMSIZ];
+ char str_error[ERROR_MESSAGE_LENGTH];
+#if !defined(SIOCBRDELBR)
+ unsigned long arg[3] = { BRCTL_DEL_BRIDGE, (unsigned long)bridge };
+#endif
+
+ if (NULL == bridge_name || strlen(bridge_name) > IFNAMSIZ) {
+ WMESH_LOGE("Invalid parameter [%p]", bridge_name);
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ br_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+ if (br_fd < 0) {
+ strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
+ WMESH_LOGD("Failed to open socket [%s(%d)]", str_error, errno);
+
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ snprintf(bridge, IFNAMSIZ, "%s", bridge_name);
+#ifdef SIOCBRDELBR
+ val = ioctl(br_fd, SIOCBRDELBR, bridge_name);
+#else
+ val = ioctl(br_fd, SIOCSIFBR, arg);
+#endif
+ if (val < 0) {
+ strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
+ WMESH_LOGD("Failed to remove bridge [%s(%d)]", str_error, errno);
+
+ ret = WMESHD_ERROR_IO_ERROR;
+ }
+
+ close(br_fd);
+
+ return ret;
+}
+
+int wmesh_bridge_add_interface(const char* bridge_name, const char* interface)
+{
+ int ret = WMESHD_ERROR_NONE;
+ int val = 0;
+ int br_fd = 0;
+
+ struct ifreq ifr;
+ int if_index = if_nametoindex(interface);
+
+ char str_error[ERROR_MESSAGE_LENGTH];
+#if !defined(SIOCBRADDIF)
+ unsigned long args[4] = { BRCTL_ADD_IF, if_index, 0, 0 };
+#endif
+
+ if (NULL == bridge_name || strlen(bridge_name) > IFNAMSIZ) {
+ WMESH_LOGE("Invalid parameter [%p]", bridge_name);
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ if (NULL == interface || strlen(interface) > IFNAMSIZ) {
+ WMESH_LOGE("Invalid parameter [%p]", interface);
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ br_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+ if (br_fd < 0) {
+ strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
+ WMESH_LOGD("Failed to open socket [%s(%d)]", str_error, errno);
+
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ snprintf(ifr.ifr_name, IFNAMSIZ, "%s", bridge_name);
+#ifdef SIOCBRADDIF
+ ifr.ifr_ifindex = if_index;
+ val = ioctl(br_fd, SIOCBRADDIF, &ifr);
+#else
+ ifr.ifr_data = (char *)args;
+ val = ioctl(br_fd, SIOCDEVPRIVATE, &ifr);
+#endif
+ if (val < 0) {
+ strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
+ WMESH_LOGD("Failed to add interface [%s] into bridge [%s(%d)]",
+ interface, str_error, errno);
+
+ ret = WMESHD_ERROR_IO_ERROR;
+ }
+
+ close(br_fd);
+
+ return ret;
+}
+
+int wmesh_bridge_del_interface(const char* bridge_name, const char* interface)
+{
+ int ret = WMESHD_ERROR_NONE;
+ int val = 0;
+ int br_fd = 0;
+
+ struct ifreq ifr;
+ int if_index = if_nametoindex(interface);
+
+ char str_error[ERROR_MESSAGE_LENGTH];
+#if !defined(SIOCBRDELIF)
+ unsigned long args[4] = { BRCTL_DEL_IF, if_index, 0, 0 };
+#endif
+
+ if (NULL == bridge_name || strlen(bridge_name) > IFNAMSIZ) {
+ WMESH_LOGE("Invalid parameter [%p]", bridge_name);
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ if (NULL == interface || strlen(interface) > IFNAMSIZ) {
+ WMESH_LOGE("Invalid parameter [%p]", interface);
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ br_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+ if (br_fd < 0) {
+ strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
+ WMESH_LOGD("Failed to open socket [%s(%d)]", str_error, errno);
+
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ snprintf(ifr.ifr_name, IFNAMSIZ, "%s", bridge_name);
+#ifdef SIOCBRDELIF
+ ifr.ifr_ifindex = if_index;
+ val = ioctl(br_fd, SIOCBRDELIF, &ifr);
+#else
+ ifr.ifr_data = (char *)args;
+ val = ioctl(br_fd, SIOCDEVPRIVATE, &ifr);
+#endif
+ if (val < 0) {
+ strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
+ WMESH_LOGD("Failed to delete interface [%s] from bridge [%s(%d)]",
+ interface, str_error, errno);
+
+ ret = WMESHD_ERROR_IO_ERROR;
+ }
+
+ close(br_fd);
+
+ return ret;
+}
+
+int wmesh_bridge_set_stp(const char* bridge_name, bool state)
+{
+ int ret = WMESHD_ERROR_NONE;
+ int val = 0;
+ int br_fd = 0;
+ char str_error[ERROR_MESSAGE_LENGTH];
+ int stp_state = (state) ? 1 : 0;
+ struct ifreq ifr;
+ unsigned long arg[4] = {
+ BRCTL_SET_BRIDGE_STP_STATE,
+ stp_state, 0, 0 };
+
+ if (NULL == bridge_name || strlen(bridge_name) > IFNAMSIZ) {
+ WMESH_LOGE("Invalid parameter [%p]", bridge_name);
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ br_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+ if (br_fd < 0) {
+ strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
+ WMESH_LOGD("Failed to open socket [%s(%d)]", str_error, errno);
+
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ strncpy(ifr.ifr_name, bridge_name, IFNAMSIZ);
+ ifr.ifr_data = (char *)arg;
+
+ val = ioctl(br_fd, SIOCDEVPRIVATE, &ifr);
+ if (val < 0) {
+ strerror_r(errno, str_error, ERROR_MESSAGE_LENGTH);
+ WMESH_LOGE("Failed to set bridge[%s] stp state", bridge_name);
+ WMESH_LOGE(" %s(%d)", str_error, errno);
+
+ ret = WMESHD_ERROR_IO_ERROR;
+ }
+
+ close(br_fd);
+
+ return ret;
+}
--- /dev/null
+/*
+ * 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 "wmesh-log.h"
+#include "wmesh-util.h"
+#include "wmesh-gdbus.h"
+#include "wmesh-request.h"
+
+#include <linux/nl80211.h>
+
+static GDBusProxy *_gproxy_connman = NULL;
+static GDBusProxy *_gproxy_connman_mesh = NULL;
+static GDBusProxy *_gproxy_connman_technology = NULL;
+static GDBusProxy *_gproxy_connman_ethernet = NULL;
+
+static int _wmeshd_close_gdbus_call(wmesh_service *service);
+static int _wmesh_gdbus_get_mesh_network_property(wmesh_service *service,
+ const gchar* object_path, wmesh_network_info_s *result);
+
+static int __channel_to_frequency(int channel, enum nl80211_band band)
+{
+ if (channel <= 0)
+ return 0;
+
+ switch (band) {
+ case NL80211_BAND_2GHZ:
+ if (channel == 14)
+ return 2484;
+ else if (channel < 14)
+ return 2407 + channel * 5;
+ break;
+ case NL80211_BAND_5GHZ:
+ if (channel >= 182 && channel <= 196)
+ return 4000 + channel * 5;
+ else
+ return 5000 + channel * 5;
+ break;
+ default:
+ break;
+ }
+
+ /* not supported */
+ return 0;
+}
+
+static int __frequency_to_channel(int freq)
+{
+ if (freq == 2484)
+ return 14;
+ else if (freq < 2484)
+ return (freq - 2407) / 5;
+ else if (freq >= 4910 && freq <= 4980)
+ return (freq - 4000) / 5;
+ else if (freq <= 45000)
+ return (freq - 5000) / 5;
+ else if (freq >= 58320 && freq <= 64800)
+ return (freq - 56160) / 2160;
+ else
+ return 0;
+}
+
+static GDBusProxy *_proxy_get_connman(wmesh_service *service)
+{
+ GDBusProxy *proxy = NULL;
+ wmeshd_check_null_ret_error("service", service, NULL);
+
+ if (NULL == _gproxy_connman) {
+ proxy = g_dbus_proxy_new_sync(service->connection,
+ G_DBUS_PROXY_FLAGS_NONE, NULL,
+ CONNMAN_SERVER_NAME,
+ CONNMAN_OBJECT_PATH,
+ CONNMAN_INTERFACE_MANAGER,
+ NULL, NULL);
+ } else
+ proxy = _gproxy_connman;
+
+ return proxy;
+}
+
+static GDBusProxy *_proxy_get_connman_mesh(wmesh_service *service)
+{
+ GDBusProxy *proxy = NULL;
+ wmeshd_check_null_ret_error("service", service, NULL);
+
+ if (NULL == _gproxy_connman_mesh) {
+ proxy = g_dbus_proxy_new_sync(service->connection,
+ G_DBUS_PROXY_FLAGS_NONE, NULL,
+ CONNMAN_SERVER_NAME,
+ CONNMAN_OBJECT_PATH_MESH,
+ CONNMAN_INTERFACE_MESH,
+ NULL, NULL);
+ } else
+ proxy = _gproxy_connman_mesh;
+
+ return proxy;
+}
+
+static GDBusProxy *_proxy_get_connman_ethernet(wmesh_service *service)
+{
+ GDBusProxy *proxy = NULL;
+ wmeshd_check_null_ret_error("service", service, NULL);
+
+ if (NULL == _gproxy_connman_ethernet) {
+ proxy = g_dbus_proxy_new_sync(service->connection,
+ G_DBUS_PROXY_FLAGS_NONE, NULL,
+ CONNMAN_SERVER_NAME, /* Name */
+ "/net/connman/technology/ethernet", /* Object Path */
+ CONNMAN_INTERFACE_TECH, /* interface Name */
+ NULL, NULL);
+ } else
+ proxy = _gproxy_connman_ethernet;
+
+ return proxy;
+}
+
+static GDBusProxy *_proxy_get_connman_technology(wmesh_service *service)
+{
+ GDBusProxy *proxy = NULL;
+ wmeshd_check_null_ret_error("service", service, NULL);
+
+ if (NULL == _gproxy_connman_technology) {
+ proxy = g_dbus_proxy_new_sync(service->connection,
+ G_DBUS_PROXY_FLAGS_NONE, NULL,
+ CONNMAN_SERVER_NAME,
+ CONNMAN_OBJECT_PATH_TECH_MESH,
+ CONNMAN_INTERFACE_TECH,
+ NULL, NULL);
+ } else
+ proxy = _gproxy_connman_technology;
+
+ return proxy;
+}
+
+static void _dbus_name_owner_notify(GObject *object, GParamSpec *pspec,
+ gpointer *user_data)
+{
+ GDBusProxy *proxy = G_DBUS_PROXY(object);
+ gchar *name_owner = g_dbus_proxy_get_name_owner(proxy);
+ wmesh_service *service = (wmesh_service*)user_data;
+
+ NOTUSED(pspec);
+
+ if (NULL == name_owner) {
+ WMESH_LOGE("name_owner is not exists !");
+ _wmeshd_close_gdbus_call(service);
+ }
+
+ g_free(name_owner);
+}
+
+static int _wmeshd_create_gdbus_call(wmesh_service *service)
+{
+ int id;
+ GError *error = NULL;
+
+ if (NULL == service)
+ return WMESHD_ERROR_INVALID_PARAMETER;
+
+ if (NULL != service->connection)
+ return WMESHD_ERROR_ALREADY_REGISTERED;
+
+ service->connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+ if (service->connection == NULL) {
+ if (error != NULL) {
+ WMESH_LOGE("Failed to connect to the D-BUS daemon [%s]", error->message);
+ g_error_free(error);
+ }
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ id = g_signal_connect(service->connection, "notify::g-name-owner",
+ G_CALLBACK(_dbus_name_owner_notify), service);
+ if (0 == id) {
+ WMESH_LOGE("g_signal_connect() Fail");
+ g_object_unref(service->connection);
+ service->connection = NULL;
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+static int _wmeshd_close_gdbus_call(wmesh_service *service)
+{
+ /* CHECK: is connection ref count required? */
+ g_object_unref(service->connection);
+ service->connection = NULL;
+
+ return WMESHD_ERROR_NONE;
+}
+
+static void _wmeshd_signal_handler(GDBusConnection *connection,
+ const gchar *sender_name, const gchar *object_path, const gchar *interface_name,
+ const gchar *signal_name, GVariant *parameters, gpointer user_data)
+{
+ wmesh_service *service = (wmesh_service*)user_data;
+ wmesh_network_info_s network_info = { 0, 0, 0, 0, 0 };
+ int ret = WMESHD_ERROR_NONE;
+
+ wmeshd_check_null_ret("user_data", user_data);
+ NOTUSED(connection);
+ NOTUSED(sender_name);
+ NOTUSED(interface_name);
+
+ WMESH_LOGD("signal received = %s", signal_name);
+ if (0 == g_strcmp0(signal_name, "ScanDone")) {
+ /* TODO: Handle event */
+ wmesh_notify_scan_done();
+ } else if (0 == g_strcmp0(signal_name, "PropertyChanged")) {
+ const gchar* var = NULL;
+ gchar* key = NULL;
+ GVariant *variant = NULL;
+ wmeshd_connection_state_e state = WMESHD_CONNECTION_STATE_DISCONNECTED;
+
+ if (NULL == parameters) {
+ WMESH_LOGE("Unexpected parameter");
+ return;
+ }
+
+ g_variant_get(parameters, "(sv)", &key, &variant);
+ if (NULL == variant) {
+ WMESH_LOGE("Invalid variant");
+ return;
+ }
+
+ /* State [???] */
+ var = g_variant_get_string(variant, NULL);
+ WMESH_LOGD(" %s [%s]", key, var);
+ WMESH_LOGD(" %s", object_path);
+
+ ret = _wmesh_gdbus_get_mesh_network_property(service, object_path, &network_info);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Cannot get valid network property !");
+
+ if (g_strcmp0("association", var) == 0) {
+ /* Joined mesh network */
+ state = WMESHD_CONNECTION_STATE_ASSOCIATION;
+ } else if (g_strcmp0("configuration", var) == 0) {
+ /* Trying to get IP address */
+ state = WMESHD_CONNECTION_STATE_CONFIGURATION;
+ } else if (g_strcmp0("ready", var) == 0 || g_strcmp0("online", var) == 0) {
+ /* IP address is obtained */
+ state = WMESHD_CONNECTION_STATE_CONNECTED;
+ } else if (g_strcmp0("disconnect", var) == 0 || g_strcmp0("failure", var) == 0) {
+ state = WMESHD_CONNECTION_STATE_DISCONNECTED;
+ } else {
+ WMESH_LOGE(" Unhandled state !");
+ g_free(network_info.mesh_id);
+ g_free(network_info.bssid);
+ return;
+ }
+
+ wmesh_notify_connection_state(network_info.mesh_id, network_info.bssid,
+ network_info.channel, network_info.security, state);
+
+ g_free(network_info.mesh_id);
+ g_free(network_info.bssid);
+ }
+}
+
+static void _wmeshd_subscribe_event(wmesh_service *service)
+{
+ unsigned int id = 0;
+
+ wmeshd_check_null_ret("service", service);
+
+ id = g_dbus_connection_signal_subscribe(
+ (GDBusConnection *)service->connection,
+ CONNMAN_SERVER_NAME, CONNMAN_INTERFACE_MANAGER,
+ "ScanDone", "/", NULL,
+ G_DBUS_CALL_FLAGS_NONE, _wmeshd_signal_handler, service, NULL);
+ if (0 == id) {
+ WMESH_LOGE("g_dbus_connection_signal_subscribe(ScanDone) Fail(%d)", errno);
+ return;
+ }
+ service->dbus_sub_ids = g_list_append(service->dbus_sub_ids, GUINT_TO_POINTER(id));
+ WMESH_LOGD("[Signal subscribe] : ScanDone (%d)", id);
+
+ /* To monitor mesh profiles */
+ id = g_dbus_connection_signal_subscribe(
+ (GDBusConnection *)service->connection,
+ CONNMAN_SERVER_NAME,
+ CONNMAN_INTERFACE_MESH,
+ "PropertyChanged",
+ NULL, /* Path */
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE, _wmeshd_signal_handler, service, NULL);
+ if (0 == id) {
+ WMESH_LOGE("g_dbus_connection_signal_subscribe(ScanDone) Fail(%d)", errno);
+ return;
+ }
+ service->dbus_sub_ids = g_list_append(service->dbus_sub_ids, GUINT_TO_POINTER(id));
+ WMESH_LOGD("[Signal subscribe] : PropertyChanged (%d)", id);
+
+ /* End of subscription */
+}
+
+static void _on_unsubscribe_ids(gpointer data, gpointer user_data)
+{
+ unsigned int id = GPOINTER_TO_UINT(data);
+ wmesh_service *service = (wmesh_service*)user_data;
+
+ WMESH_LOGD("[Signal unsubscribe] : %d", id);
+ g_dbus_connection_signal_unsubscribe(
+ (GDBusConnection *)service->connection, id);
+}
+
+static void _wmeshd_unsubscribe_event(wmesh_service *service)
+{
+ wmeshd_check_null_ret("service", service);
+
+ g_list_foreach(service->dbus_sub_ids, _on_unsubscribe_ids, service);
+
+ g_list_free(service->dbus_sub_ids);
+ service->dbus_sub_ids = NULL;
+}
+
+int wmeshd_dbus_start(wmesh_service *service)
+{
+ int rv;
+
+ rv = _wmeshd_create_gdbus_call(service);
+ if (WMESHD_ERROR_NONE != rv)
+ return rv;
+
+ service->ca = g_cancellable_new();
+
+ /* Create all required proxies here */
+ _gproxy_connman = _proxy_get_connman(service);
+ wmeshd_check_null_ret_error("_gproxy_connman", _gproxy_connman,
+ WMESHD_ERROR_IO_ERROR);
+ g_dbus_proxy_set_default_timeout(
+ G_DBUS_PROXY(_gproxy_connman), WMESH_DBUS_PROXY_TIMEOUT);
+
+ _gproxy_connman_mesh = _proxy_get_connman_mesh(service);
+ wmeshd_check_null_ret_error("_gproxy_connman_mesh", _gproxy_connman_mesh,
+ WMESHD_ERROR_IO_ERROR);
+ g_dbus_proxy_set_default_timeout(
+ G_DBUS_PROXY(_gproxy_connman_mesh), WMESH_DBUS_PROXY_TIMEOUT);
+
+ _gproxy_connman_technology = _proxy_get_connman_technology(service);
+ wmeshd_check_null_ret_error("_gproxy_connman_technology", _gproxy_connman_technology,
+ WMESHD_ERROR_IO_ERROR);
+ g_dbus_proxy_set_default_timeout(
+ G_DBUS_PROXY(_gproxy_connman_technology), WMESH_DBUS_PROXY_TIMEOUT);
+
+ _gproxy_connman_ethernet = _proxy_get_connman_ethernet(service);
+ wmeshd_check_null_ret_error("_gproxy_connman_ethernet", _gproxy_connman_ethernet,
+ WMESHD_ERROR_IO_ERROR);
+ g_dbus_proxy_set_default_timeout(
+ G_DBUS_PROXY(_gproxy_connman_ethernet), WMESH_DBUS_PROXY_TIMEOUT);
+
+ /* Subscribe events */
+ _wmeshd_subscribe_event(service);
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmeshd_dbus_stop(wmesh_service *service)
+{
+ int rv;
+
+ if (NULL == service)
+ return WMESHD_ERROR_INVALID_PARAMETER;
+
+ /* Unsubscribe events */
+ _wmeshd_unsubscribe_event(service);
+
+ /* Unref all proxies here */
+ if (_gproxy_connman) {
+ g_object_unref(_gproxy_connman);
+ _gproxy_connman = NULL;
+ }
+ if (_gproxy_connman_mesh) {
+ g_object_unref(_gproxy_connman_mesh);
+ _gproxy_connman_mesh = NULL;
+ }
+ if (_gproxy_connman_technology) {
+ g_object_unref(_gproxy_connman_technology);
+ _gproxy_connman_technology = NULL;
+ }
+
+ g_cancellable_cancel(service->ca);
+ g_object_unref(service->ca);
+ service->ca = NULL;
+
+ rv = _wmeshd_close_gdbus_call(service);
+ return rv;
+}
+
+int wmesh_gdbus_create_mesh_interface(wmesh_service *service)
+{
+ int ret = WMESHD_ERROR_NONE;
+ GVariant *variant = NULL;
+ GError *error = NULL;
+ GVariant *var_dict = NULL;
+ GVariantDict dict;
+ wmesh_interface_s *info = NULL;
+
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("connection", service->connection,
+ WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("_gproxy_connman_technology",
+ _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
+
+ info = service->interface_info;
+
+ g_variant_dict_init(&dict, NULL);
+ g_variant_dict_insert(&dict, "Ifname", "s", info->mesh_interface);
+ g_variant_dict_insert(&dict, "ParentIfname", "s", info->base_interface);
+ g_variant_dict_insert(&dict, "BridgeIfname", "s", info->bridge_interface);
+ var_dict = g_variant_dict_end(&dict);
+
+ variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
+ g_variant_new("(sv)", "MeshInterfaceAdd", var_dict),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+ if (variant) {
+ WMESH_LOGD("Successfully requested. [MeshInterfaceAdd]");
+ } else if (error) {
+ ret = WMESHD_ERROR_IO_ERROR;
+ WMESH_LOGE("Failed DBus call [%s]", error->message);
+
+ /* Interface not exists */
+ if (g_strrstr(error->message, "No such device"))
+ ret = WMESHD_ERROR_INVALID_PARAMETER;
+ g_error_free(error);
+ }
+
+ return ret;
+}
+
+int wmesh_gdbus_remove_mesh_interface(wmesh_service *service)
+{
+ int ret = WMESHD_ERROR_NONE;
+ GVariant *variant = NULL;
+ GError *error = NULL;
+ GVariant *var_dict = NULL;
+ GVariantDict dict;
+ wmesh_interface_s *info = NULL;
+
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("connection", service->connection,
+ WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("_gproxy_connman_technology",
+ _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
+
+ info = service->interface_info;
+
+ g_variant_dict_init(&dict, NULL);
+ g_variant_dict_insert(&dict, "Ifname", "s", info->mesh_interface);
+ var_dict = g_variant_dict_end(&dict);
+
+ variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
+ g_variant_new("(sv)", "MeshInterfaceRemove", var_dict),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+ if (variant) {
+ WMESH_LOGD("Successfully requested. [MeshInterfaceRemove]");
+ } else if (error) {
+ ret = WMESHD_ERROR_IO_ERROR;
+ WMESH_LOGE("Failed DBus call [%s]", error->message);
+
+ /* Interface not exists (Not created yet) */
+ if (g_strrstr(error->message, "No such device"))
+ ret = WMESHD_ERROR_NONE;
+ g_error_free(error);
+ }
+
+ return ret;
+}
+
+int wmesh_gdbus_mesh_scan(wmesh_service *service)
+{
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("connection", service->connection,
+ WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("_gproxy_connman_technology",
+ _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
+
+ g_dbus_proxy_call(_gproxy_connman_technology, "Scan",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, NULL, NULL);
+
+ WMESH_LOGD("Successfully requested. [Scan]");
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_gdbus_mesh_specific_scan(wmesh_service *service, gchar *mesh_id, gint channel)
+{
+ GVariant *variant = NULL;
+ GError *error = NULL;
+ GVariant *var_dict = NULL;
+ GVariantDict dict;
+
+ enum nl80211_band band = (channel <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
+ gushort freq = __channel_to_frequency(channel, band);
+
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("connection", service->connection,
+ WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("_gproxy_connman_technology",
+ _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
+
+ g_variant_dict_init(&dict, NULL);
+ g_variant_dict_insert(&dict, "Name", "s", mesh_id);
+ g_variant_dict_insert(&dict, "Frequency", "q", freq);
+ var_dict = g_variant_dict_end(&dict);
+
+ variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
+ g_variant_new("(sv)", "MeshSpecificScan", var_dict),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+ if (variant) {
+ WMESH_LOGD("Successfully requested. [MeshSpecificScan]");
+ } else if (error) {
+ WMESH_LOGE("Failed DBus call [%s]", error->message);
+ g_error_free(error);
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_gdbus_mesh_cancel_scan(wmesh_service *service)
+{
+ int ret = WMESHD_ERROR_NONE;
+ GVariant *variant = NULL;
+ GError *error = NULL;
+ GVariant *var_dict = NULL;
+ GVariantDict dict;
+
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("connection", service->connection,
+ WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("_gproxy_connman_technology",
+ _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
+
+ g_variant_dict_init(&dict, NULL);
+ var_dict = g_variant_dict_end(&dict);
+
+ variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
+ g_variant_new("(sv)", "AbortScan", var_dict),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+ if (variant) {
+ WMESH_LOGD("Successfully requested. [AbortScan]");
+ } else if (error) {
+ ret = WMESHD_ERROR_IO_ERROR;
+ WMESH_LOGE("Failed DBus call [%s]", error->message);
+
+ /* Scan is not in progress */
+ if (g_strrstr(error->message, "Already exists"))
+ ret = WMESHD_ERROR_NONE;
+
+ g_error_free(error);
+ }
+
+ return ret;
+}
+
+static void _on_scan_result_destroy(gpointer data)
+{
+ wmesh_scan_result_s *scan_item = (wmesh_scan_result_s *)data;
+
+ if (scan_item) {
+ g_free(scan_item->mesh_id);
+ g_free(scan_item->bssid);
+ g_free(scan_item->object_path);
+ }
+ g_free(scan_item);
+}
+
+static void _on_peer_info_destroy(gpointer data)
+{
+ wmesh_peer_info_s *peer = (wmesh_peer_info_s *)data;
+
+ if (peer)
+ g_free(peer->address);
+ g_free(peer);
+}
+
+static void _get_joined_network(wmesh_service *service, GVariant *variant)
+{
+ GVariantIter *peer = NULL;
+ GVariantIter *property = NULL;
+ gchar *key = NULL;
+ GVariant *val = NULL;
+ gsize len = 0;
+ GVariant *child;
+ const gchar* obj_path = NULL;
+ const gchar* buf = NULL;
+
+ g_variant_get(variant, "(a(oa{sv}))", &peer);
+ while ((child = g_variant_iter_next_value(peer))) {
+ wmesh_network_info_s *joined_info = NULL;
+ gboolean valid_state = TRUE;
+
+ g_variant_get(child, "(oa{sv})", &obj_path, &property);
+ WMESH_LOGD(" Object: [%s]", obj_path);
+ if (NULL == obj_path) {
+ WMESH_LOGE("Null object");
+ continue;
+ }
+
+ /* Create an information structure for joined network */
+ joined_info = g_try_new0(wmesh_network_info_s, 1);
+ if (NULL == joined_info) {
+ WMESH_LOGE("Failed to allocate !");
+ return;
+ }
+
+ while (g_variant_iter_loop(property, "{sv}", &key, &val)) {
+ if (strcasecmp(key, "Name") == 0) {
+ buf = g_variant_get_string(val, &len);
+ joined_info->mesh_id = g_strdup(buf);
+ } else if (strcasecmp(key, "BSSID") == 0) {
+ buf = g_variant_get_string(val, &len);
+ joined_info->bssid = g_strdup(buf);
+ } else if (strcasecmp(key, "State") == 0) {
+ buf = g_variant_get_string(val, &len);
+ WMESH_LOGD(" State : %s", buf);
+
+ /* Skip ignorable state */
+ if (g_strcmp0(buf, "idle") == 0
+ || g_strcmp0(buf, "disconnect") == 0
+ || g_strcmp0(buf, "failure") == 0) {
+ valid_state = FALSE;
+ break;
+ } else if (g_strcmp0(buf, "association") == 0) {
+ joined_info->state = WMESHD_CONNECTION_STATE_ASSOCIATION;
+ } else if (g_strcmp0(buf, "configuration") == 0) {
+ joined_info->state = WMESHD_CONNECTION_STATE_CONFIGURATION;
+ } else if (g_strcmp0(buf, "ready") == 0 || g_strcmp0(buf, "online") == 0) {
+ joined_info->state = WMESHD_CONNECTION_STATE_CONNECTED;
+ }
+ } else if (strcasecmp(key, "Security") == 0) {
+ buf = g_variant_get_string(val, &len);
+ if (g_strcmp0("sae", buf) == 0)
+ joined_info->security = WMESHD_SECURITY_SAE;
+ else
+ joined_info->security = WMESHD_SECURITY_NONE;
+ } else if (strcasecmp(key, "Frequency") == 0) {
+ joined_info->channel = __frequency_to_channel(g_variant_get_uint16(val));
+ }
+ }
+
+ /* Skip ignorable state */
+ if (FALSE == valid_state) {
+ g_free(joined_info->mesh_id);
+ g_free(joined_info->bssid);
+ continue;
+ }
+
+ WMESH_LOGD(" Mesh ID : %s", joined_info->mesh_id);
+ WMESH_LOGD(" BSSID : %s", joined_info->bssid);
+ WMESH_LOGD(" Channel : %d", joined_info->channel);
+ WMESH_LOGD(" Security : %s",
+ (WMESHD_SECURITY_SAE == joined_info->security) ? "SAE" : "NONE");
+ service->joined_network = joined_info;
+
+ g_variant_iter_free(property);
+
+ /* If found, stop loop iteration */
+ break;
+ }
+ g_variant_iter_free(peer);
+}
+
+static void _get_mesh_peers(wmesh_service *service, GVariant *variant)
+{
+ GVariantIter *peer = NULL;
+ GVariantIter *property = NULL;
+ gchar *key = NULL;
+ GVariant *val = NULL;
+ gsize len = 0;
+ GVariant *child;
+ const gchar* obj_path = NULL;
+
+ g_variant_get(variant, "(a(oa{sv}))", &peer);
+ while ((child = g_variant_iter_next_value(peer))) {
+ wmesh_scan_result_s *scan_info = NULL;
+
+ scan_info = g_try_new0(wmesh_scan_result_s, 1);
+ if (NULL == scan_info) {
+ WMESH_LOGE("Failed to allocate !");
+ return;
+ }
+
+ g_variant_get(child, "(oa{sv})", &obj_path, &property);
+ if (NULL == obj_path) {
+ WMESH_LOGE("Null object");
+ g_free(scan_info);
+ continue;
+ }
+ WMESH_LOGD(" Obj path : [%s]", obj_path);
+ scan_info->object_path = g_strdup(obj_path);
+
+ while (g_variant_iter_loop(property, "{sv}", &key, &val)) {
+ if (strcasecmp(key, "Name") == 0) {
+ const char *buf = g_variant_get_string(val, &len);
+ scan_info->mesh_id = g_strdup(buf);
+ WMESH_LOGD(" Mesh ID : %s", scan_info->mesh_id);
+ } else if (strcasecmp(key, "BSSID") == 0) {
+ const char *buf = g_variant_get_string(val, &len);
+ scan_info->bssid = g_strdup(buf);
+ WMESH_LOGD(" BSSID : %s", scan_info->bssid);
+ } else if (strcasecmp(key, "State") == 0) {
+ const char *buf = g_variant_get_string(val, &len);
+ WMESH_LOGD(" State : %s", buf);
+
+ if (g_strcmp0(buf, "idle") == 0
+ || g_strcmp0(buf, "disconnect") == 0
+ || g_strcmp0(buf, "failure") == 0) {
+ scan_info->state = WMESHD_CONNECTION_STATE_DISCONNECTED;
+ } else if (g_strcmp0(buf, "association") == 0) {
+ scan_info->state = WMESHD_CONNECTION_STATE_ASSOCIATION;
+ } else if (g_strcmp0(buf, "configuration") == 0) {
+ scan_info->state = WMESHD_CONNECTION_STATE_CONFIGURATION;
+ } else if (g_strcmp0(buf, "ready") == 0 || g_strcmp0(buf, "online") == 0) {
+ scan_info->state = WMESHD_CONNECTION_STATE_CONNECTED;
+ }
+ } else if (strcasecmp(key, "Security") == 0) {
+ const char *buf = g_variant_get_string(val, &len);
+ WMESH_LOGD(" Security : %s", buf);
+ if (g_strcmp0("sae", buf) == 0)
+ scan_info->security = WMESHD_SECURITY_SAE;
+ else
+ scan_info->security = WMESHD_SECURITY_NONE;
+ } else if (strcasecmp(key, "Frequency") == 0) {
+ scan_info->channel = __frequency_to_channel(g_variant_get_uint16(val));
+ WMESH_LOGD(" Channel : %d", scan_info->channel);
+ } else if (strcasecmp(key, "Favorite") == 0) {
+ const char *buf = g_variant_get_string(val, &len);
+ WMESH_LOGD(" Favorite : %s", buf);
+ } else if (strcasecmp(key, "Strength") == 0) {
+ scan_info->rssi = (gint)g_variant_get_byte(val);
+ WMESH_LOGD(" RSSI : %d", scan_info->rssi);
+ }
+ }
+ /* Last element */
+ service->scanned_mesh_network =
+ g_list_prepend(service->scanned_mesh_network, scan_info);
+
+ g_variant_iter_free(property);
+ }
+ g_variant_iter_free(peer);
+}
+
+static void _get_connected_mesh_peers(wmesh_service *service, GVariant *variant)
+{
+ GVariantIter *peer = NULL;
+ GVariant *val = NULL;
+ gsize len = 0;
+ GVariant *child;
+ GVariant *dict = NULL;
+
+ g_variant_get(variant, "(a(a{sv}))", &peer);
+ while ((child = g_variant_iter_next_value(peer))) {
+ wmesh_peer_info_s *peer_info = NULL;
+
+ peer_info = g_try_new0(wmesh_peer_info_s, 1);
+ if (NULL == peer_info) {
+ WMESH_LOGE("Failed to allocate !");
+ return;
+ }
+
+ /* a{sv} <- (a{sv}) */
+ dict = g_variant_get_child_value(child, 0);
+ val = g_variant_lookup_value(dict, "PeerAddress", NULL);
+ if (NULL != val) {
+ const char *buf = g_variant_get_string(val, &len);
+ peer_info->address = g_strdup(buf);
+ WMESH_LOGD(" Address : %s", peer_info->address);
+ g_variant_unref(val);
+ } else {
+ WMESH_LOGE("Unable to get address !");
+ g_free(peer_info);
+ continue;
+ }
+
+ service->connected_mesh_peers =
+ g_list_prepend(service->connected_mesh_peers, peer_info);
+ }
+ g_variant_iter_free(peer);
+}
+
+int wmesh_gdbus_get_mesh_networks(wmesh_service *service)
+{
+ GVariant *variant = NULL;
+ GError *error = NULL;
+
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("connection", service->connection,
+ WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("_gproxy_connman",
+ _gproxy_connman, WMESHD_ERROR_IO_ERROR);
+
+ variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetMeshPeers",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+ if (variant) {
+ WMESH_LOGD("Successfully requested. [GetMeshPeers]");
+
+ if (service->scanned_mesh_network) {
+ g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy);
+ service->scanned_mesh_network = NULL;
+ }
+
+ _get_mesh_peers(service, variant);
+
+ /* List item is saved with reversed order for efficiency. */
+ service->scanned_mesh_network =
+ g_list_reverse(service->scanned_mesh_network);
+ } else if (error) {
+ WMESH_LOGE("Failed DBus call [%s]", error->message);
+ g_error_free(error);
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_gdbus_get_joined_mesh_network(wmesh_service *service)
+{
+ GVariant *variant = NULL;
+ GError *error = NULL;
+
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("connection", service->connection,
+ WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("_gproxy_connman",
+ _gproxy_connman, WMESHD_ERROR_IO_ERROR);
+
+ variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetMeshPeers",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+ if (variant) {
+ WMESH_LOGD("Successfully requested. [GetMeshPeers]");
+
+ if (service->joined_network) {
+ g_free(service->joined_network->mesh_id);
+ g_free(service->joined_network->bssid);
+ g_free(service->joined_network);
+ service->joined_network = NULL;
+ }
+
+ _get_joined_network(service, variant);
+ } else if (error) {
+ WMESH_LOGE("Failed DBus call [%s]", error->message);
+ g_error_free(error);
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_gdbus_get_connected_peers(wmesh_service *service)
+{
+ GVariant *variant = NULL;
+ GError *error = NULL;
+
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("connection", service->connection,
+ WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("_gproxy_connman",
+ _gproxy_connman, WMESHD_ERROR_IO_ERROR);
+
+ variant = g_dbus_proxy_call_sync(_gproxy_connman, "GetConnectedMeshPeers",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+ if (variant) {
+ WMESH_LOGD("Successfully requested. [GetConnectedMeshPeers]");
+
+ if (service->connected_mesh_peers) {
+ g_list_free_full(service->connected_mesh_peers, _on_peer_info_destroy);
+ service->connected_mesh_peers = NULL;
+ }
+
+ _get_connected_mesh_peers(service, variant);
+
+ /* List item is saved with reversed order for efficiency. */
+ service->connected_mesh_peers =
+ g_list_reverse(service->connected_mesh_peers);
+ } else if (error) {
+ WMESH_LOGE("Failed DBus call [%s]", error->message);
+ g_error_free(error);
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+static void _get_mesh_property(GVariant *variant, wmesh_network_info_s *result)
+{
+ GVariantIter *property = NULL;
+ gchar *key = NULL;
+ GVariant *val = NULL;
+ gsize len = 0;
+
+ WMESH_LOGD("Type [%s]", g_variant_get_type_string(variant));
+
+ g_variant_get(variant, "(a{sv})", &property);
+
+ while (g_variant_iter_loop(property, "{sv}", &key, &val)) {
+ if (strcasecmp(key, "Name") == 0) {
+ const char *buf = g_variant_get_string(val, &len);
+ result->mesh_id = g_strdup(buf);
+ WMESH_LOGD(" Mesh ID : %s", result->mesh_id);
+ } else if (strcasecmp(key, "BSSID") == 0) {
+ const char *buf = g_variant_get_string(val, &len);
+ result->bssid = g_strdup(buf);
+ WMESH_LOGD(" BSSID : %s", result->bssid);
+ } else if (strcasecmp(key, "State") == 0) {
+ const char *buf = g_variant_get_string(val, &len);
+ WMESH_LOGD(" State : %s", buf);
+
+ if (g_strcmp0(buf, "idle") == 0
+ || g_strcmp0(buf, "disconnect") == 0
+ || g_strcmp0(buf, "failure") == 0) {
+ result->state = WMESHD_CONNECTION_STATE_DISCONNECTED;
+ } else if (g_strcmp0(buf, "association") == 0) {
+ result->state = WMESHD_CONNECTION_STATE_ASSOCIATION;
+ } else if (g_strcmp0(buf, "configuration") == 0) {
+ result->state = WMESHD_CONNECTION_STATE_CONFIGURATION;
+ } else if (g_strcmp0(buf, "ready") == 0 || g_strcmp0(buf, "online") == 0) {
+ result->state = WMESHD_CONNECTION_STATE_CONNECTED;
+ }
+ } else if (strcasecmp(key, "Security") == 0) {
+ const char *buf = g_variant_get_string(val, &len);
+ WMESH_LOGD(" Security : %s", buf);
+ if (g_strcmp0("sae", buf) == 0)
+ result->security = WMESHD_SECURITY_SAE;
+ else
+ result->security = WMESHD_SECURITY_NONE;
+ } else if (strcasecmp(key, "Frequency") == 0) {
+ result->channel = __frequency_to_channel(g_variant_get_uint16(val));
+ WMESH_LOGD(" Channel : %d", result->channel);
+ } else if (strcasecmp(key, "Favorite") == 0) {
+ const char *buf = g_variant_get_string(val, &len);
+ WMESH_LOGD(" Favorite : %s", buf);
+ } else if (strcasecmp(key, "Strength") == 0) {
+ gint rssi = (gint)g_variant_get_byte(val);
+ WMESH_LOGD(" RSSI : %d", rssi);
+ }
+ }
+ g_variant_iter_free(property);
+}
+
+static int _wmesh_gdbus_get_mesh_network_property(wmesh_service *service,
+ const gchar* object_path, wmesh_network_info_s *result)
+{
+ GVariant *variant = NULL;
+ GError *error = NULL;
+
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("connection", service->connection,
+ WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("result", result, WMESHD_ERROR_INVALID_PARAMETER);
+
+ variant = g_dbus_connection_call_sync(service->connection,
+ CONNMAN_SERVER_NAME,
+ object_path,
+ CONNMAN_INTERFACE_MESH,
+ "GetProperties",
+ NULL, NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+ if (variant) {
+ WMESH_LOGD("Successfully requested. [GetProperties]");
+
+ /* Get properties */
+ _get_mesh_property(variant, result);
+ } else if (error) {
+ LOGE("Failed DBus call [%s]", error->message);
+ g_error_free(error);
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_gdbus_create_network(wmesh_service *service, gchar *mesh_id,
+ gint channel, wmeshd_security_type_e sec)
+{
+ GVariant *variant = NULL;
+ GError *error = NULL;
+ GVariant *var_dict = NULL;
+ GVariantBuilder builder;
+ const gchar* security = (WMESHD_SECURITY_SAE == sec) ? "sae" : "none";
+
+ enum nl80211_band band = (channel <= 14) ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
+ gushort freq = __channel_to_frequency(channel, band);
+
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("connection", service->connection,
+ WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("_gproxy_connman_technology",
+ _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
+
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
+ g_variant_builder_open(&builder, G_VARIANT_TYPE("a{sv}"));
+
+ g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
+ g_variant_builder_add(&builder, "s", "Name");
+ g_variant_builder_add(&builder, "v", g_variant_new_string(mesh_id));
+ g_variant_builder_close(&builder); /* {sv} */
+
+ g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
+ g_variant_builder_add(&builder, "s", "Frequency");
+ g_variant_builder_add(&builder, "v", g_variant_new_uint16(freq));
+ g_variant_builder_close(&builder); /* {sv} */
+
+ g_variant_builder_open(&builder, G_VARIANT_TYPE("{sv}"));
+ g_variant_builder_add(&builder, "s", "Security");
+ g_variant_builder_add(&builder, "v", g_variant_new_string(security));
+ g_variant_builder_close(&builder); /* {sv} */
+
+ g_variant_builder_close(&builder); /* a{sv} */
+
+ var_dict = g_variant_builder_end(&builder);
+
+ variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
+ g_variant_new("(sv)", "MeshCreateNetwork", var_dict),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+ if (variant) {
+ WMESH_LOGD("Successfully requested. [MeshCreateNetwork]");
+ } else if (error) {
+ WMESH_LOGE("Failed DBus call [%s]", error->message);
+ g_error_free(error);
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_gdbus_set_passphrase(wmesh_service *service, wmesh_scan_result_s *info, gchar *passphrase)
+{
+ GVariant *variant = NULL;
+ GError *error = NULL;
+
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("passphrase", passphrase, WMESHD_ERROR_INVALID_PARAMETER);
+
+ variant = g_dbus_connection_call_sync(service->connection,
+ CONNMAN_SERVER_NAME,
+ info->object_path,
+ CONNMAN_INTERFACE_MESH,
+ "SetProperty",
+ g_variant_new("(sv)", "Passphrase", g_variant_new_string(passphrase)),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+ if (variant) {
+ WMESH_LOGD("Successfully requested. [SetProperty]");
+ } else if (error) {
+ LOGE("Failed DBus call [%s]", error->message);
+ g_error_free(error);
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+#if 0
+static void on_response_connect_network(GObject *source_object,
+ GAsyncResult *res, gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ GError *error = NULL;
+ GVariant *variant = NULL;
+
+ NOTUSED(user_data);
+
+ variant = g_dbus_connection_call_finish(
+ G_DBUS_CONNECTION(source_object), res, &error);
+ if (variant) {
+ WMESH_LOGD("Successfully requested. [Connect]");
+
+ /* TODO: Unregister property change event */
+ } else if (error) {
+ ret = WMESHD_ERROR_IO_ERROR;
+ LOGE("Failed DBus call [%s]", error->message);
+
+ if (g_strrstr(error->message, "Already exists"))
+ ret = WMESHD_ERROR_ALREADY_REGISTERED;
+ else if (g_strrstr(error->message, "In progress"))
+ ret = WMESHD_ERROR_IN_PROGRESS;
+ else
+ ret = WMESHD_ERROR_IO_ERROR;
+
+ g_error_free(error);
+ }
+}
+#endif
+
+int wmesh_gdbus_connect_network(wmesh_service *service, wmesh_scan_result_s *info)
+{
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("info", info, WMESHD_ERROR_INVALID_PARAMETER);
+
+ g_dbus_connection_call(service->connection,
+ CONNMAN_SERVER_NAME,
+ info->object_path,
+ CONNMAN_INTERFACE_MESH,
+ "Connect",
+ NULL, NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL, /* G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED */
+ NULL, NULL);
+ WMESH_LOGD("Successfully requested. [Connect]");
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_gdbus_disconnect_network(wmesh_service *service, wmesh_scan_result_s *info)
+{
+ GVariant *variant = NULL;
+ GError *error = NULL;
+
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("info", info, WMESHD_ERROR_INVALID_PARAMETER);
+
+ variant = g_dbus_connection_call_sync(service->connection,
+ CONNMAN_SERVER_NAME,
+ info->object_path,
+ CONNMAN_INTERFACE_MESH,
+ "Disconnect",
+ NULL, NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+ if (variant) {
+ WMESH_LOGD("Successfully requested. [Disconnect]");
+ } else if (error) {
+ LOGE("Failed DBus call [%s]", error->message);
+ g_error_free(error);
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_gdbus_remove_network(wmesh_service *service, wmesh_scan_result_s *info)
+{
+ GVariant *variant = NULL;
+ GError *error = NULL;
+
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("info", info, WMESHD_ERROR_INVALID_PARAMETER);
+
+ variant = g_dbus_connection_call_sync(service->connection,
+ CONNMAN_SERVER_NAME,
+ info->object_path,
+ CONNMAN_INTERFACE_MESH,
+ "Remove",
+ NULL, NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+ if (variant) {
+ WMESH_LOGD("Successfully requested. [Remove]");
+ } else if (error) {
+ LOGE("Failed DBus call [%s]", error->message);
+ g_error_free(error);
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+
+int wmesh_gdbus_enable_ethernet_interface(wmesh_service *service, bool state)
+{
+ int ret = WMESHD_ERROR_NONE;
+ GVariant *variant = NULL;
+ GError *error = NULL;
+ wmesh_interface_s *info = NULL;
+
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("connection", service->connection,
+ WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("_gproxy_connman_technology",
+ _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
+
+ info = service->interface_info;
+ wmeshd_check_null_ret_error("info", info, WMESHD_ERROR_INVALID_PARAMETER);
+
+ variant = g_dbus_proxy_call_sync(_gproxy_connman_ethernet, "SetProperty",
+ g_variant_new("(sv)", "Powered", g_variant_new_boolean(state)),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+ if (variant) {
+ WMESH_LOGD("Successfully requested. [Powered]");
+ } else if (error) {
+ ret = WMESHD_ERROR_IO_ERROR;
+ WMESH_LOGE("Failed DBus call [%s]", error->message);
+
+ /* Interface not exists (Not created yet) */
+ if (g_strrstr(error->message, "No such device"))
+ ret = WMESHD_ERROR_NONE;
+ g_error_free(error);
+ }
+
+ return ret;
+}
+
+int wmesh_gdbus_set_mesh_gate(wmesh_service *service)
+{
+ int ret = WMESHD_ERROR_NONE;
+ GVariant *variant = NULL;
+ GError *error = NULL;
+ GVariant *var_dict = NULL;
+ GVariantDict dict;
+ wmesh_interface_s *info = NULL;
+
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("connection", service->connection,
+ WMESHD_ERROR_INVALID_PARAMETER);
+ wmeshd_check_null_ret_error("_gproxy_connman_technology",
+ _gproxy_connman_technology, WMESHD_ERROR_IO_ERROR);
+
+ info = service->interface_info;
+
+ g_variant_dict_init(&dict, NULL);
+ g_variant_dict_insert(&dict, "GateAnnounce", "b", info->gate_announce);
+ g_variant_dict_insert(&dict, "HWMPRootMode", "q", info->hwmp_root_mode);
+ g_variant_dict_insert(&dict, "STP", "q", info->stp);
+ var_dict = g_variant_dict_end(&dict);
+
+ variant = g_dbus_proxy_call_sync(_gproxy_connman_technology, "MeshCommands",
+ g_variant_new("(sv)", "SetMeshGate", var_dict),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+ if (variant) {
+ WMESH_LOGD("Successfully requested. [SetMeshGate]");
+ } else if (error) {
+ ret = WMESHD_ERROR_IO_ERROR;
+ WMESH_LOGE("Failed DBus call [%s]", error->message);
+
+ /* Interface not exists */
+ if (g_strrstr(error->message, "No such device"))
+ ret = WMESHD_ERROR_INVALID_PARAMETER;
+ g_error_free(error);
+ }
+
+ return ret;
+}
+
--- /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 <glib.h>
+#include <gio/gio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+
+#include <errno.h>
+
+#include "wmesh.h"
+#include "wmesh-log.h"
+#include "wmesh-util.h"
+#include "wmesh-service.h"
+#include "wmesh-interface.h"
+
+#define IPV4_MAX_LENGTH 16
+#define BUF_LENGTH 256
+
+#define MESH_DEFAULT_BASE_INTERFACE "wlan0"
+#define MESH_DEFAULT_MESH_INTERFACE "mesh0"
+#define MESH_DEFAULT_BRIDGE_INTERFACE "br0"
+#define MESH_DEFAULT_EXTERNAL_INTERFACE "eth0"
+#define MESH_DEFAULT_SOFTAP_INTERFACE "wlan1"
+
+typedef enum {
+ ETHERNET_CABLE_DETACHED = 0,
+ ETHERNET_CABLE_ATTACHED
+} cable_state_e;
+
+int wmesh_interface_set(const char *interface, const char* ip_addr,
+ wmesh_set_interface_type_e type)
+{
+ int sock = 0;
+ struct ifreq ifr;
+ int ret = 0;
+
+ char ip[IPV4_MAX_LENGTH] = {0,};
+ char buf[BUF_LENGTH] = {0,};
+
+ if (interface == NULL) {
+ WMESH_LOGE("Invalid interface name !");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock < 0) {
+ WMESH_LOGE("Cannot open network interface socket");
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ WMESH_LOGD("Initialize interface [%s]...", interface);
+ snprintf(ifr.ifr_name, IFNAMSIZ, "%s", interface);
+
+ /* Set IP Address */
+ if (NULL != ip_addr) {
+ struct sockaddr_in sai;
+ memset(&sai, 0, sizeof(struct sockaddr_in));
+ sai.sin_family = AF_INET;
+ sai.sin_port = 0;
+ snprintf(ip, IPV4_MAX_LENGTH, "%s", ip_addr);
+
+ WMESH_LOGD("Setting IP address: [%s]\n", ip);
+ if (!inet_aton(ip, &sai.sin_addr)) {
+ WMESH_LOGE("Failed to convert ip address");
+ close(sock);
+ return WMESHD_ERROR_OPERATION_FAILED;
+ }
+
+ memcpy(&ifr.ifr_addr, &sai, sizeof(sai));
+
+ ret = ioctl(sock, SIOCSIFADDR, &ifr);
+ if (ret < 0) {
+ (void) strerror_r(errno, buf, BUF_LENGTH);
+ WMESH_LOGE("Failed to set IP[%s] for interface[%s] : %s",
+ ip, ifr.ifr_name, buf);
+ }
+ }
+
+ /* Get status flag */
+ if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
+ (void) strerror_r(errno, buf, BUF_LENGTH);
+ WMESH_LOGE("Failed to get interface[%s] status : %s",
+ ifr.ifr_name, buf);
+ }
+ snprintf(ifr.ifr_name, IFNAMSIZ, "%s", interface);
+
+ /* Set status flag */
+ if (WMESH_INTERFACE_UP == type) {
+ ifr.ifr_flags |= (IFF_UP);
+ if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
+ (void) strerror_r(errno, buf, BUF_LENGTH);
+ WMESH_LOGE("Failed to change interface[%s] status UP : %s",
+ ifr.ifr_name, buf);
+ }
+ } else if (WMESH_INTERFACE_DOWN == type) {
+ ifr.ifr_flags &= (~IFF_UP);
+ if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
+ (void) strerror_r(errno, buf, BUF_LENGTH);
+ WMESH_LOGE("Failed to change interface[%s] status DOWN : %s",
+ ifr.ifr_name, buf);
+ }
+ } else {
+ WMESH_LOGD("Do not change up/down status");
+ }
+
+ close(sock);
+ return WMESHD_ERROR_NONE;
+}
+
+#if 0
+/* Returns interface name in sequence order which is exists */
+static char* _get_interface_exists_in_seq(const char* prefix)
+{
+ char *res = NULL;
+ char buf[32];
+ int ret;
+ int i = 0;
+ const int IF_INDEX_MAX = 9;
+
+ for (i = 0; i <= IF_INDEX_MAX; i++) {
+ snprintf(buf, sizeof(buf), "/sys/class/net/%s%d", prefix, i);
+
+ ret = access(buf, F_OK);
+ if (ret >= 0) {
+ /* This name is exists. use it */
+ snprintf(buf, sizeof(buf), "%s%d", prefix, i);
+ res = g_strdup(buf);
+ WMESH_LOGD(" use [%s]", res);
+ break;
+ }
+ }
+
+ return res;
+}
+
+/* Returns interface name in sequence order which is exists */
+static char* _get_interface_not_exists_in_seq(const char* prefix)
+{
+ char *res = NULL;
+ char buf[32];
+ int ret;
+ int i = 0;
+ const int IF_INDEX_MAX = 9;
+
+ for (i = 0; i <= IF_INDEX_MAX; i++) {
+ snprintf(buf, sizeof(buf), "/sys/class/net/%s%d", prefix, i);
+
+ ret = access(buf, F_OK);
+ if (ret < 0) {
+ /* This name is not exists. use it */
+ snprintf(buf, sizeof(buf), "%s%d", prefix, i);
+ res = g_strdup(buf);
+ WMESH_LOGD(" use [%s]", res);
+ break;
+ }
+ }
+
+ return res;
+}
+#endif
+
+static bool _check_interface_exists(const char* if_name)
+{
+ int ret;
+ char buf[32];
+ int i = 0;
+ const int IF_INDEX_MAX = 9;
+
+ for (i = 0; i <= IF_INDEX_MAX; i++) {
+ snprintf(buf, sizeof(buf), "/sys/class/net/%s", if_name);
+
+ ret = access(buf, F_OK);
+ if (ret >= 0) {
+ /* This name is exists. */
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Check if interface is bridged */
+static bool _check_bridge_interface_exists(const char* bridge, const char* if_name)
+{
+ int ret;
+ char buf[32];
+ int i = 0;
+ const int IF_INDEX_MAX = 9;
+
+ for (i = 0; i <= IF_INDEX_MAX; i++) {
+ snprintf(buf, sizeof(buf), "/sys/class/net/%s/brif/%s", bridge, if_name);
+
+ ret = access(buf, F_OK);
+ if (ret >= 0) {
+ /* This name is exists. */
+ return true;
+ }
+ }
+
+ return false;
+}
+
+char* wmesh_interface_get_address(const char* if_name)
+{
+ FILE *pf;
+ char buf[32] = { 0, };
+ char *result = NULL;
+
+ snprintf(buf, sizeof(buf), "/sys/class/net/%s/address", if_name);
+ pf = fopen(buf, "r");
+ if (NULL != pf) {
+ fgets(buf, 31, pf);
+ WMESH_LOGD("Interface[%s] address[%s]", if_name, buf);
+
+ if (strlen(buf) > 0)
+ result = g_strdup(buf);
+
+ fclose(pf);
+ }
+
+ return result;
+}
+
+int wmesh_interface_initialize(wmesh_interface_s *info)
+{
+ if (NULL == info) {
+ WMESH_LOGE("Invalid parameter");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ info->bridge_interface = g_strdup(MESH_DEFAULT_BRIDGE_INTERFACE);
+ if (NULL == info->bridge_interface) {
+ WMESH_LOGE("Failed to get bridge interface !");
+ return WMESHD_ERROR_OPERATION_FAILED;
+ }
+
+ info->base_interface = g_strdup(MESH_DEFAULT_BASE_INTERFACE);
+ if (NULL == info->bridge_interface) {
+ WMESH_LOGE("Failed to get base interface !");
+ return WMESHD_ERROR_OPERATION_FAILED;
+ }
+
+ info->mesh_interface = g_strdup(MESH_DEFAULT_MESH_INTERFACE);
+ if (NULL == info->bridge_interface) {
+ WMESH_LOGE("Failed to get mesh interface !");
+ return WMESHD_ERROR_OPERATION_FAILED;
+ }
+
+ info->softap_interface = g_strdup(MESH_DEFAULT_SOFTAP_INTERFACE);
+ info->external_interface = g_strdup(MESH_DEFAULT_EXTERNAL_INTERFACE);
+
+ WMESH_LOGD("Interface configuration for mesh network :");
+ WMESH_LOGD(" Base : [%s]", info->base_interface);
+ WMESH_LOGD(" Mesh : [%s]", info->mesh_interface);
+ WMESH_LOGD(" Bridge : [%s]", info->bridge_interface);
+ WMESH_LOGD(" SoftAP : [%s]", info->softap_interface);
+ WMESH_LOGD(" External: [%s]", info->external_interface);
+
+ return WMESHD_ERROR_NONE;
+}
+
+static int _check_ethernet_cable_plugin_status(const char* interface,
+ cable_state_e *status)
+{
+ FILE *fd = NULL;
+ int ret = -1;
+ int rv = 0;
+ char error_buf[256] = {0, };
+ char file_path[256] = {0, };
+
+ snprintf(file_path, 256, "/sys/class/net/%s/carrier", interface);
+
+ if (0 == access(file_path, F_OK)) {
+ fd = fopen(file_path, "r");
+ if (fd == NULL) {
+ WMESH_LOGE("Error! Could not open /sys/class/net/%s/carrier file",
+ interface);
+ return WMESHD_ERROR_IO_ERROR;
+ }
+ } else {
+ WMESH_LOGE("Error! Could not access /sys/class/net/%s/carrier file",
+ interface);
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ errno = 0;
+ rv = fscanf(fd, "%d", &ret);
+ if (rv < 0) {
+ strerror_r(errno, error_buf, 256);
+ WMESH_LOGE("Error! Failed to read from file, rv:[%d], error:[%s]",
+ rv, error_buf);
+ fclose(fd);
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ if (ret == 1) {
+ WMESH_LOGD("/sys/class/net/%s/carrier : [%d]", interface, ret);
+ *status = ETHERNET_CABLE_ATTACHED;
+ } else if (ret == 0) {
+ WMESH_LOGD("/sys/class/net/%s/carrier : [%d]", interface, ret);
+ *status = ETHERNET_CABLE_DETACHED;
+ }
+
+ fclose(fd);
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_interface_check_external_exists(const char* external_interface, bool *state)
+{
+ /* TODO: Current logic checks only ethernet interface.
+ This logic should consider wireless interface if can */
+ int ret = WMESHD_ERROR_NONE;
+ cable_state_e cable_state = ETHERNET_CABLE_DETACHED;
+
+ if (NULL == external_interface || NULL == state)
+ return WMESHD_ERROR_INVALID_PARAMETER;
+
+ bool ex = _check_interface_exists(external_interface);
+ if (FALSE == ex) {
+ WMESH_LOGE("External interface[%s] was not found.", external_interface);
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ /* If external interface seems Ethernet, check cable state */
+ if (g_str_has_prefix(external_interface, "eth")) {
+ ret = _check_ethernet_cable_plugin_status(external_interface, &cable_state);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to get Ethernet cable state");
+ return WMESHD_ERROR_OPERATION_FAILED;
+ }
+ }
+
+ *state = FALSE;
+ if (ETHERNET_CABLE_ATTACHED == cable_state)
+ *state = TRUE;
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_interface_check(const char* interface)
+{
+ bool ex = FALSE;
+
+ if (NULL == interface || strlen(interface) == 0)
+ return WMESHD_ERROR_INVALID_PARAMETER;
+
+ ex = _check_interface_exists(interface);
+ if (FALSE == ex) {
+ WMESH_LOGE("Interface[%s] was not found.", interface);
+ return WMESHD_ERROR_NO_DATA;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_interface_check_bridge_interface_exists(const char* bridge, const char* interface)
+{
+ bool ex = FALSE;
+
+ if (NULL == bridge || NULL == interface ||
+ strlen(bridge) == 0 || strlen(interface) == 0)
+ return WMESHD_ERROR_INVALID_PARAMETER;
+
+ ex = _check_bridge_interface_exists(bridge, interface);
+ if (FALSE == ex) {
+ WMESH_LOGE("Interface[%s] was not found.", interface);
+ return WMESHD_ERROR_NO_DATA;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
--- /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 <glib.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <net/if.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+#include <netlink/netlink.h>
+
+#include "wmesh.h"
+#include "wmesh-log.h"
+#include "wmesh-util.h"
+#include "wmesh-netlink.h"
+#include "wmesh-request.h"
+
+#include <linux/nl80211.h>
+//#include "nl80211.h"
+
+#define MESH_PARAM_HWMP_ROOTMODE "mesh_hwmp_rootmode"
+#define MESH_PARAM_GATE_ANNOUNCE "mesh_gate_announcements"
+#define MAX_MAC_ADDR_LEN 18
+#define ETH_ALEN 6
+
+#define BIT(x) (1ULL<<(x))
+
+typedef enum {
+ MESH_NL_CALLBACK_FINISHED = 0,
+ MESH_NL_CALLBACK_TRYING,
+} mesh_nl_callback_state_e;
+
+typedef struct {
+ int nl80211_id;
+ int callback_state;
+ guint event_source;
+
+ struct nl_sock *nl_socket;
+ struct nl_msg *msg;
+ struct nl_cb *cb;
+ struct nl_cb *s_cb;
+
+ bool error_occured;
+ GList **station_list;
+ GList **mpath_list;
+} mesh_nl_state;
+
+typedef struct {
+ const char *group;
+ int id;
+} multicast_group_id_args;
+
+enum plink_state {
+ LISTEN,
+ OPN_SNT,
+ OPN_RCVD,
+ CNF_RCVD,
+ ESTAB,
+ HOLDING,
+ BLOCKED
+};
+
+/* For event handler */
+static mesh_nl_state *event_state = NULL;
+
+static int __initialize_nl80211(mesh_nl_state *state)
+{
+ int err = WMESHD_ERROR_NONE;
+
+ state->nl_socket = nl_socket_alloc();
+ if (!state->nl_socket) {
+ WMESH_LOGE("Failed to allocate netlink socket.");
+ return WMESHD_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (genl_connect(state->nl_socket)) {
+ WMESH_LOGE("Failed to connect to generic netlink.");
+ err = WMESHD_ERROR_OPERATION_FAILED;
+ goto DESTROY;
+ }
+
+ nl_socket_set_buffer_size(state->nl_socket, 8192, 8192);
+
+ state->nl80211_id = genl_ctrl_resolve(state->nl_socket, "nl80211");
+ if (state->nl80211_id < 0) {
+ WMESH_LOGE("nl80211 not found.");
+ err = WMESHD_ERROR_NO_DATA;
+ goto DESTROY;
+ }
+
+ return 0;
+
+DESTROY:
+ nl_socket_free(state->nl_socket);
+ return err;
+}
+
+static void __clean_nl80211(mesh_nl_state *state)
+{
+ if (!state)
+ return;
+
+ if (state->nl_socket) {
+ nl_socket_free(state->nl_socket);
+ state->nl_socket = NULL;
+ state->nl80211_id = -1;
+ }
+}
+
+static int __get_device_index_from_string(const char* if_name, int *index)
+{
+ int device_index = 0;
+
+ if (NULL == if_name) {
+ WMESH_LOGE("Invalid parameter");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ device_index = if_nametoindex(if_name);
+ if (device_index == 0) {
+ WMESH_LOGE("No interface index found [%s]", if_name);
+ return WMESHD_ERROR_NO_DATA;
+ }
+ *index = device_index;
+
+ return WMESHD_ERROR_NONE;
+}
+
+static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
+{
+ mesh_nl_state *state = (mesh_nl_state *)arg;
+ char buf[256] = { 0, };
+
+ NOTUSED(nla);
+
+ state->callback_state = MESH_NL_CALLBACK_FINISHED;
+ state->error_occured = TRUE;
+ strerror_r(err->error, buf, 255);
+
+ WMESH_LOGD("error_handler");
+ WMESH_LOGE(" %s (%d)", buf, err->error);
+
+ return NL_STOP;
+}
+
+static int finish_handler(struct nl_msg *msg, void *arg)
+{
+ mesh_nl_state *state = (mesh_nl_state *)arg;
+
+ state->callback_state = MESH_NL_CALLBACK_FINISHED;
+
+ WMESH_LOGD("finish_handler");
+ NOTUSED(msg);
+
+ return NL_SKIP;
+}
+
+static int ack_handler(struct nl_msg *msg, void *arg)
+{
+ mesh_nl_state *state = (mesh_nl_state *)arg;
+
+ state->callback_state = MESH_NL_CALLBACK_FINISHED;
+
+ WMESH_LOGD("ack_handler");
+ NOTUSED(msg);
+
+ return NL_STOP;
+}
+
+static int ack_simple_handler(struct nl_msg *msg, void *arg)
+{
+ int *ret = arg;
+
+ (void) msg;
+ *ret = 0;
+
+ WMESH_LOGD("ack_simple_handler");
+
+ return NL_STOP;
+}
+
+static int family_handler(struct nl_msg *msg, void *arg)
+{
+ multicast_group_id_args *group = (multicast_group_id_args *)arg;
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct nlattr *tb[CTRL_ATTR_MAX + 1];
+ struct nlattr *mcast_group;
+ int rem_mcast_group;
+
+ WMESH_LOGD("family_handler");
+
+ nla_parse(tb, CTRL_ATTR_MAX,
+ genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+ if (!tb[CTRL_ATTR_MCAST_GROUPS])
+ return NL_SKIP;
+
+ nla_for_each_nested(mcast_group, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcast_group) {
+ struct nlattr *tb_mcast_group[CTRL_ATTR_MCAST_GRP_MAX + 1];
+
+ nla_parse(tb_mcast_group, CTRL_ATTR_MCAST_GRP_MAX,
+ nla_data(mcast_group), nla_len(mcast_group), NULL);
+
+ if (!tb_mcast_group[CTRL_ATTR_MCAST_GRP_NAME] ||
+ !tb_mcast_group[CTRL_ATTR_MCAST_GRP_ID])
+ continue;
+
+ if (strncmp(nla_data(tb_mcast_group[CTRL_ATTR_MCAST_GRP_NAME]),
+ group->group,
+ nla_len(tb_mcast_group[CTRL_ATTR_MCAST_GRP_NAME])))
+ continue;
+
+ group->id = nla_get_u32(tb_mcast_group[CTRL_ATTR_MCAST_GRP_ID]);
+ WMESH_LOGD("mcast group id [%d]", group->id);
+ break;
+ }
+
+ return NL_SKIP;
+}
+
+static int __nl_get_multicast_id(struct nl_sock *sock, const char *family, const char *group)
+{
+ struct nl_msg *msg;
+ struct nl_cb *cb;
+ int ret, ctrlid;
+ multicast_group_id_args group_args = {
+ .group = group,
+ .id = -ENOENT,
+ };
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -ENOMEM;
+
+ cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!cb) {
+ ret = -ENOMEM;
+ goto FAILURE;
+ }
+
+ ctrlid = genl_ctrl_resolve(sock, "nlctrl");
+
+ genlmsg_put(msg, 0, 0, ctrlid, 0,
+ 0, CTRL_CMD_GETFAMILY, 0);
+
+ ret = -ENOBUFS;
+ NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);
+
+ ret = nl_send_auto(sock, msg);
+ if (ret < 0) {
+ WMESH_LOGE("Failed to nl_send_auto");
+ goto out;
+ }
+
+ ret = 1;
+ nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &ret);
+ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_simple_handler, &ret);
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, family_handler, &group_args);
+
+ while (ret > 0)
+ nl_recvmsgs(sock, cb);
+
+ if (ret == 0)
+ ret = group_args.id;
+
+ WMESH_LOGD("mcid : [%d]", ret);
+
+ nla_put_failure:
+ out:
+ nl_cb_put(cb);
+
+ FAILURE:
+ nlmsg_free(msg);
+ return ret;
+}
+
+static int __prepare_listen_events(mesh_nl_state *state)
+{
+ int mcid, ret;
+
+ /* Configuration multicast group */
+ mcid = __nl_get_multicast_id(state->nl_socket, "nl80211", "config");
+ if (mcid < 0) {
+ WMESH_LOGE("Failed to get nl80211 config");
+ return mcid;
+ }
+ WMESH_LOGD("Mesh multicast id (config): [%d]", mcid);
+
+ ret = nl_socket_add_membership(state->nl_socket, mcid);
+ if (ret) {
+ WMESH_LOGE("Failed to nl_socket_add_membership");
+ return ret;
+ }
+
+ /* Scan multicast group */
+ mcid = __nl_get_multicast_id(state->nl_socket, "nl80211", "scan");
+ if (mcid >= 0) {
+ ret = nl_socket_add_membership(state->nl_socket, mcid);
+ if (ret) {
+ WMESH_LOGE("Failed to nl_socket_add_membership");
+ return ret;
+ }
+ }
+ WMESH_LOGD("Mesh multicast id (scan): [%d]", mcid);
+
+ /* Regulatory multicast group */
+ mcid = __nl_get_multicast_id(state->nl_socket, "nl80211", "regulatory");
+ if (mcid >= 0) {
+ ret = nl_socket_add_membership(state->nl_socket, mcid);
+ if (ret) {
+ WMESH_LOGE("Failed to nl_socket_add_membership");
+ return ret;
+ }
+ }
+ WMESH_LOGD("Mesh multicast id (regulatory): [%d]", mcid);
+
+ /* MLME multicast group */
+ mcid = __nl_get_multicast_id(state->nl_socket, "nl80211", "mlme");
+ if (mcid >= 0) {
+ ret = nl_socket_add_membership(state->nl_socket, mcid);
+ if (ret) {
+ WMESH_LOGE("Failed to nl_socket_add_membership");
+ return ret;
+ }
+ }
+ WMESH_LOGD("Mesh multicast id (mlme): [%d]", mcid);
+
+ mcid = __nl_get_multicast_id(state->nl_socket, "nl80211", "vendor");
+ if (mcid >= 0) {
+ ret = nl_socket_add_membership(state->nl_socket, mcid);
+ if (ret) {
+ WMESH_LOGE("Failed to nl_socket_add_membership");
+ return ret;
+ }
+ }
+ WMESH_LOGD("Mesh multicast id (vendor): [%d]", mcid);
+
+ return 0;
+}
+
+static mesh_nl_state *_create_mesh_nl_state()
+{
+ mesh_nl_state *state = g_new0(mesh_nl_state, 1);
+
+ state->nl80211_id = -1;
+ state->callback_state = MESH_NL_CALLBACK_TRYING;
+ state->error_occured = FALSE;
+
+ return state;
+}
+
+static void _delete_mesh_nl_state(mesh_nl_state **state)
+{
+ if (NULL == state || NULL == *state)
+ return;
+
+ g_free(*state);
+ *state = NULL;
+}
+
+static int valid_handler(struct nl_msg *msg, void *arg)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ mesh_nl_state *state = (mesh_nl_state *)arg;
+ WMESH_LOGD("valid_handler");
+
+ if (gnlh->cmd == NL80211_CMD_SCAN_ABORTED) {
+ WMESH_LOGD(" Got NL80211_CMD_SCAN_ABORTED.");
+ state->callback_state = MESH_NL_CALLBACK_FINISHED;
+
+ /* Notify scan done status */
+ wmesh_notify_scan_done();
+ } else if (gnlh->cmd == NL80211_CMD_NEW_SCAN_RESULTS) {
+ WMESH_LOGD(" Got NL80211_CMD_NEW_SCAN_RESULTS.");
+ state->callback_state = MESH_NL_CALLBACK_FINISHED;
+
+ /* Notify scan done status */
+ wmesh_notify_scan_done();
+ } else {
+ WMESH_LOGD(" Got [%d]", gnlh->cmd);
+ }
+
+ return NL_SKIP;
+}
+
+static int no_seq_check(struct nl_msg *msg, void *arg)
+{
+ NOTUSED(msg);
+ NOTUSED(arg);
+
+ return NL_OK;
+}
+
+static void __clean_netlink_message(mesh_nl_state *state)
+{
+ if (!state)
+ return;
+
+ if (state->cb)
+ nl_cb_put(state->cb);
+ if (state->s_cb)
+ nl_cb_put(state->s_cb);
+ if (state->msg)
+ nlmsg_free(state->msg);
+
+ state->cb = NULL;
+ state->s_cb = NULL;
+ state->msg = NULL;
+
+ WMESH_LOGD("message and callback cleaned");
+}
+
+static int __initialize_netlink_message(mesh_nl_state *state)
+{
+ int err = WMESHD_ERROR_NONE;
+
+ if (NULL == state) {
+ WMESH_LOGE("Invalid parameter !");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ /* Create netlink message */
+ state->msg = nlmsg_alloc();
+ if (NULL == state->msg) {
+ WMESH_LOGE("Failed to allocate netlink message");
+ return WMESHD_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* NL_CB_DEFAULT */
+ state->cb = nl_cb_alloc(NL_CB_DEFAULT);
+ state->s_cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!state->cb) {
+ WMESH_LOGE("Failed to allocate netlink callback");
+ err = WMESHD_ERROR_OUT_OF_MEMORY;
+ goto DESTROY;
+ }
+
+ /* Set socket callback */
+ nl_socket_set_cb(state->nl_socket, state->s_cb);
+
+ /* Set callbacks */
+ nl_cb_err(state->cb, NL_CB_CUSTOM, error_handler, state);
+ nl_cb_set(state->cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, state);
+ nl_cb_set(state->cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, state);
+ nl_cb_set(state->cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, state);
+
+ WMESH_LOGD("netlink socket initialized");
+
+ return WMESHD_ERROR_NONE;
+
+DESTROY:
+ __clean_netlink_message(state);
+
+ return err;
+}
+
+static gboolean _on_socket_event_io_received(GIOChannel *source,
+ GIOCondition condition, gpointer data)
+{
+ mesh_nl_state *state = (mesh_nl_state *)data;
+ int test = 0;
+
+ NOTUSED(source);
+ NOTUSED(condition);
+
+ WMESH_LOGD("[Event] I/O received");
+
+ while (nl_recvmsgs_report(state->nl_socket, state->cb) > 0)
+ WMESH_LOGD(" count [%02d]", ++test);
+
+ /* Do not remove I/O source */
+ return TRUE;
+}
+
+static void _on_remove_event_io_handler()
+{
+ if (event_state) {
+ g_source_remove(event_state->event_source);
+
+ __clean_netlink_message(event_state);
+ __clean_nl80211(event_state);
+ _delete_mesh_nl_state(&event_state);
+ }
+}
+
+static void mac_addr_n2a(char *mac_addr, unsigned char *arg)
+{
+ /* 11:22:33:44:55:66 (Len:17) */
+ snprintf(mac_addr, MAX_MAC_ADDR_LEN,
+ "%02X:%02X:%02X:%02X:%02X:%02X",
+ arg[0], arg[1], arg[2], arg[3], arg[4], arg[5]);
+}
+#if defined(NL80211_STA_INFO_CHAIN_SIGNAL) || defined(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)
+static char *get_chain_signal(struct nlattr *attr_list)
+{
+ struct nlattr *attr;
+ static char buf[64];
+ char *cur = buf;
+ int i = 0, rem;
+ const char *prefix;
+
+ if (!attr_list)
+ return (char *)"";
+
+ nla_for_each_nested(attr, attr_list, rem) {
+ if (i++ > 0)
+ prefix = ", ";
+ else
+ prefix = "[";
+
+ cur += snprintf(cur, sizeof(buf) - (cur - buf), "%s%d", prefix,
+ (int8_t) nla_get_u8(attr));
+ }
+
+ if (i)
+ snprintf(cur, sizeof(buf) - (cur - buf), "] ");
+
+ return buf;
+}
+#endif /* NL80211_STA_INFO_CHAIN_SIGNAL || NL80211_STA_INFO_CHAIN_SIGNAL_AVG */
+
+static int parse_bitrate(struct nlattr *bitrate_attr, char *buf, int buflen)
+{
+ int rate = 0;
+ int pos = 0;
+ char str_rate[32] = { 0, };
+ char str_buf[128] = { 0, };
+ struct nlattr *rate_info[NL80211_RATE_INFO_MAX + 1];
+ static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
+ [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
+ [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_BITRATE32] = { .type = NLA_U32 },
+ };
+
+ if (nla_parse_nested(rate_info, NL80211_RATE_INFO_MAX, bitrate_attr, rate_policy)) {
+ if (buf)
+ snprintf(buf, buflen, "failed to parse nested rate attributes!");
+ return 0;
+ }
+
+ if (rate_info[NL80211_RATE_INFO_MCS])
+ pos += snprintf(str_buf + pos, 128 - pos,
+ " MCS %d", nla_get_u8(rate_info[NL80211_RATE_INFO_MCS]));
+ if (rate_info[NL80211_RATE_INFO_40_MHZ_WIDTH])
+ pos += snprintf(str_buf + pos, 128 - pos, " 40MHz");
+ if (rate_info[NL80211_RATE_INFO_SHORT_GI])
+ pos += snprintf(str_buf + pos, 128 - pos, " short GI");
+ if (rate_info[NL80211_RATE_INFO_VHT_MCS])
+ pos += snprintf(str_buf + pos, 128 - pos,
+ " VHT-MCS %d", nla_get_u8(rate_info[NL80211_RATE_INFO_VHT_MCS]));
+ if (rate_info[NL80211_RATE_INFO_VHT_NSS])
+ pos += snprintf(str_buf + pos, 128 - pos,
+ " VHT-NSS %d", nla_get_u8(rate_info[NL80211_RATE_INFO_VHT_NSS]));
+ if (rate_info[NL80211_RATE_INFO_80_MHZ_WIDTH])
+ pos += snprintf(str_buf + pos, 128 - pos, " 80MHz");
+ if (rate_info[NL80211_RATE_INFO_80P80_MHZ_WIDTH])
+ pos += snprintf(str_buf + pos, 128 - pos, " 80P80MHz");
+ if (rate_info[NL80211_RATE_INFO_160_MHZ_WIDTH])
+ pos += snprintf(str_buf + pos, 128 - pos, " 160MHz");
+
+ if (rate_info[NL80211_RATE_INFO_BITRATE32])
+ rate = nla_get_u32(rate_info[NL80211_RATE_INFO_BITRATE32]);
+ else if (rate_info[NL80211_RATE_INFO_BITRATE])
+ rate = nla_get_u16(rate_info[NL80211_RATE_INFO_BITRATE]);
+ if (rate > 0)
+ snprintf(str_rate, 32, "%d.%d MBit/s", rate / 10, rate % 10);
+
+ if (buf)
+ snprintf(buf, buflen, "%s%s", str_rate, str_buf);
+
+ return rate;
+}
+
+static void parse_bss_param(struct nlattr *bss_param_attr, wmesh_station_info_s *station_info)
+{
+ struct nlattr *bss_param_info[NL80211_STA_BSS_PARAM_MAX + 1], *info;
+ static struct nla_policy bss_poilcy[NL80211_STA_BSS_PARAM_MAX + 1] = {
+ [NL80211_STA_BSS_PARAM_CTS_PROT] = { .type = NLA_FLAG },
+ [NL80211_STA_BSS_PARAM_SHORT_PREAMBLE] = { .type = NLA_FLAG },
+ [NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME] = { .type = NLA_FLAG },
+ [NL80211_STA_BSS_PARAM_DTIM_PERIOD] = { .type = NLA_U8 },
+ [NL80211_STA_BSS_PARAM_BEACON_INTERVAL] = { .type = NLA_U16 },
+ };
+
+ if (nla_parse_nested(bss_param_info, NL80211_STA_BSS_PARAM_MAX, bss_param_attr, bss_poilcy))
+ WMESH_LOGE("failed to parse nested bss param attributes!");
+
+ info = bss_param_info[NL80211_STA_BSS_PARAM_DTIM_PERIOD];
+ if (info) {
+ station_info->dtim_period = nla_get_u8(info);
+ WMESH_LOGD(" DTIM period:\t%u", station_info->dtim_period);
+ }
+ info = bss_param_info[NL80211_STA_BSS_PARAM_BEACON_INTERVAL];
+ if (info) {
+ station_info->beacon_interval = nla_get_u16(info);
+ WMESH_LOGD(" beacon interval:%u", station_info->beacon_interval);
+ }
+ info = bss_param_info[NL80211_STA_BSS_PARAM_CTS_PROT];
+ if (info) {
+ WMESH_LOGD(" CTS protection:");
+ if (nla_get_u16(info)) {
+ WMESH_LOGD(" yes");
+ station_info->cts_protection = TRUE;
+ } else {
+ WMESH_LOGD(" no");
+ station_info->cts_protection = FALSE;
+ }
+ }
+ info = bss_param_info[NL80211_STA_BSS_PARAM_SHORT_PREAMBLE];
+ if (info) {
+ WMESH_LOGD(" short preamble:");
+ if (nla_get_u16(info)) {
+ WMESH_LOGD(" yes");
+ station_info->short_preamble = TRUE;
+ } else {
+ WMESH_LOGD(" no");
+ station_info->short_preamble = FALSE;
+ }
+ }
+ info = bss_param_info[NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME];
+ if (info) {
+ WMESH_LOGD(" short slot time:");
+ if (nla_get_u16(info)) {
+ WMESH_LOGD(" yes");
+ station_info->short_slot_time = TRUE;
+ } else {
+ WMESH_LOGD(" no");
+ station_info->short_slot_time = FALSE;
+ }
+ }
+}
+
+static void print_power_mode(struct nlattr *a)
+{
+ enum nl80211_mesh_power_mode pm = nla_get_u32(a);
+
+ switch (pm) {
+ case NL80211_MESH_POWER_ACTIVE:
+ WMESH_LOGD("ACTIVE");
+ break;
+ case NL80211_MESH_POWER_LIGHT_SLEEP:
+ WMESH_LOGD("LIGHT SLEEP");
+ break;
+ case NL80211_MESH_POWER_DEEP_SLEEP:
+ WMESH_LOGD("DEEP SLEEP");
+ break;
+ default:
+ WMESH_LOGD("UNKNOWN");
+ break;
+ }
+}
+
+static int _on_receive_station_info(struct nl_msg *msg, void *arg)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct nlattr *sta_info[NL80211_STA_INFO_MAX + 1];
+ struct nlattr *attr_info[NL80211_ATTR_MAX + 1];
+ struct nl80211_sta_flag_update *sta_flags;
+ static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
+ [NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_LLID] = { .type = NLA_U16 },
+ [NL80211_STA_INFO_PLID] = { .type = NLA_U16 },
+ [NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 },
+ [NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
+ [NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
+ [NL80211_STA_INFO_RX_PACKETS] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_TX_PACKETS] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_TX_RETRIES] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_TX_FAILED] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_NESTED },
+ [NL80211_STA_INFO_BSS_PARAM] = { .type = NLA_NESTED },
+ [NL80211_STA_INFO_STA_FLAGS] = { .minlen = sizeof(struct nl80211_sta_flag_update) },
+ [NL80211_STA_INFO_BEACON_LOSS] = { .type = NLA_U32},
+ [NL80211_STA_INFO_T_OFFSET] = { .type = NLA_U64 },
+ [NL80211_STA_INFO_LOCAL_PM] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_PEER_PM] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_NONPEER_PM] = { .type = NLA_U32 },
+ [NL80211_STA_INFO_RX_BYTES64] = { .type = NLA_U64 },
+ [NL80211_STA_INFO_TX_BYTES64] = { .type = NLA_U64 },
+#ifdef NL80211_STA_INFO_CHAIN_SIGNAL
+ [NL80211_STA_INFO_CHAIN_SIGNAL] = { .type = NLA_NESTED },
+#endif /* NL80211_STA_INFO_CHAIN_SIGNAL */
+
+#ifdef NL80211_STA_INFO_CHAIN_SIGNAL_AVG
+ [NL80211_STA_INFO_CHAIN_SIGNAL_AVG] = { .type = NLA_NESTED },
+#endif /* NL80211_STA_INFO_CHAIN_SIGNAL_AVG */
+
+#ifdef NL80211_STA_INFO_RX_DROP_MISC
+ [NL80211_STA_INFO_RX_DROP_MISC] = { .type = NLA_U64 },
+#endif /* NL80211_STA_INFO_RX_DROP_MISC */
+
+#ifdef NL80211_STA_INFO_RX_DURATION
+ [NL80211_STA_INFO_BEACON_RX] = { .type = NLA_U64 },
+#endif /* NL80211_STA_INFO_RX_DURATION */
+
+#ifdef NL80211_STA_INFO_TID_STATS
+ [NL80211_STA_INFO_TID_STATS] = { .type = NLA_NESTED },
+#endif /* NL80211_STA_INFO_TID_STATS */
+
+#ifdef NL80211_STA_INFO_RX_DURATION
+ [NL80211_STA_INFO_RX_DURATION] = { .type = NLA_U64 },
+#endif /* NL80211_STA_INFO_RX_DURATION */
+ };
+ char mac_addr[MAX_MAC_ADDR_LEN], dev[IF_NAMESIZE];
+#ifdef NL80211_STA_INFO_CHAIN_SIGNAL
+ char *chain;
+#endif /* NL80211_STA_INFO_CHAIN_SIGNAL */
+ char *attr_mac = NULL;
+ mesh_nl_state *state = (mesh_nl_state *)arg;
+ wmesh_station_info_s *station_info = NULL;
+
+ nla_parse(attr_info, NL80211_ATTR_MAX,
+ genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
+
+ if (!attr_info[NL80211_ATTR_STA_INFO]) {
+ WMESH_LOGE("[Station] missing station stats !");
+ return NL_SKIP;
+ }
+
+ if (nla_parse_nested(sta_info, NL80211_STA_INFO_MAX,
+ attr_info[NL80211_ATTR_STA_INFO], stats_policy)) {
+ WMESH_LOGE("[Station] Failed to parse nested attributes!");
+ return NL_SKIP;
+ }
+
+ /* Allocation */
+ station_info = g_try_new0(wmesh_station_info_s, 1);
+ if (NULL == station_info) {
+ WMESH_LOGE("Failed to allocate station info !");
+ return NL_SKIP;
+ }
+
+ /* BSSID */
+ attr_mac = nla_data(attr_info[NL80211_ATTR_MAC]);
+ snprintf(mac_addr, MAX_MAC_ADDR_LEN, "%02X:%02X:%02X:%02X:%02X:%02X",
+ attr_mac[0], attr_mac[1], attr_mac[2],
+ attr_mac[3], attr_mac[4], attr_mac[5]);
+ if_indextoname(nla_get_u32(attr_info[NL80211_ATTR_IFINDEX]), dev);
+ station_info->bssid = g_strdup(mac_addr);
+ WMESH_LOGD("Station %s [dev %s]", station_info->bssid, dev);
+
+ /* Inactive time */
+ if (0 != sta_info[NL80211_STA_INFO_INACTIVE_TIME]) {
+ station_info->inactive_time =
+ nla_get_u32(sta_info[NL80211_STA_INFO_INACTIVE_TIME]);
+ WMESH_LOGE(" inactive time:\t%u ms", station_info->inactive_time);
+ }
+
+ /* RX Bytes */
+ if (0 != sta_info[NL80211_STA_INFO_RX_BYTES]) {
+ station_info->rx_bytes =
+ nla_get_u32(sta_info[NL80211_STA_INFO_RX_BYTES]);
+ WMESH_LOGD(" rx bytes:\t%u", station_info->rx_bytes);
+ } else if (0 != sta_info[NL80211_STA_INFO_RX_BYTES64]) {
+ station_info->rx_bytes =
+ (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_RX_BYTES64]);
+ WMESH_LOGE(" rx bytes:\t%llu", station_info->rx_bytes);
+ }
+
+ /* RX Packets */
+ if (0 != sta_info[NL80211_STA_INFO_RX_PACKETS]) {
+ station_info->rx_packets =
+ nla_get_u32(sta_info[NL80211_STA_INFO_RX_PACKETS]);
+ WMESH_LOGD(" rx packets:\t%u", station_info->rx_packets);
+ }
+
+ /* TX Bytes */
+ if (0 != sta_info[NL80211_STA_INFO_TX_BYTES]) {
+ station_info->tx_bytes =
+ nla_get_u32(sta_info[NL80211_STA_INFO_TX_BYTES]);
+ WMESH_LOGD(" tx bytes:\t%u", station_info->tx_bytes);
+ } else if (0 != sta_info[NL80211_STA_INFO_TX_BYTES64]) {
+ station_info->tx_bytes =
+ (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_TX_BYTES64]);
+ WMESH_LOGD(" tx bytes:\t%llu", station_info->rx_packets);
+ }
+
+ /* LLID, PLID */
+ if (0 != sta_info[NL80211_STA_INFO_LLID]) {
+ station_info->llid = nla_get_u16(sta_info[NL80211_STA_INFO_LLID]);
+ WMESH_LOGD(" mesh llid:\t%d", station_info->llid);
+ }
+ if (0 != sta_info[NL80211_STA_INFO_PLID]) {
+ station_info->llid = nla_get_u16(sta_info[NL80211_STA_INFO_PLID]);
+ WMESH_LOGD(" mesh plid:\t%d", station_info->plid);
+ }
+
+ /* Plink state */
+ if (0 != sta_info[NL80211_STA_INFO_PLINK_STATE]) {
+ char state_name[10];
+ station_info->mesh_plink =
+ nla_get_u8(sta_info[NL80211_STA_INFO_PLINK_STATE]);
+ switch (station_info->mesh_plink) {
+ case LISTEN:
+ snprintf(state_name, 10, "%s", "LISTEN");
+ break;
+ case OPN_SNT:
+ snprintf(state_name, 10, "%s", "OPN_SNT");
+ break;
+ case OPN_RCVD:
+ snprintf(state_name, 10, "%s", "OPN_RCVD");
+ break;
+ case CNF_RCVD:
+ snprintf(state_name, 10, "%s", "CNF_RCVD");
+ break;
+ case ESTAB:
+ snprintf(state_name, 10, "%s", "ESTAB");
+ break;
+ case HOLDING:
+ snprintf(state_name, 10, "%s", "HOLDING");
+ break;
+ case BLOCKED:
+ snprintf(state_name, 10, "%s", "BLOCKED");
+ break;
+ default:
+ snprintf(state_name, 10, "%s", "UNKNOWN");
+ break;
+ }
+ WMESH_LOGD(" mesh plink:\t%s", state_name);
+ }
+#ifdef NL80211_STA_INFO_CHAIN_SIGNAL
+ /* RSSI Signal */
+ chain = get_chain_signal(sta_info[NL80211_STA_INFO_CHAIN_SIGNAL]);
+ if (0 != sta_info[NL80211_STA_INFO_SIGNAL]) {
+ station_info->rssi =
+ (int8_t)nla_get_u8(sta_info[NL80211_STA_INFO_SIGNAL]);
+ WMESH_LOGD(" signal: \t%d %sdBm", station_info->rssi, chain);
+ }
+#endif /* NL80211_STA_INFO_CHAIN_SIGNAL */
+ /* TX Bitrate */
+ if (0 != sta_info[NL80211_STA_INFO_TX_BITRATE]) {
+ char buf[100];
+ station_info->tx_bitrate =
+ parse_bitrate(sta_info[NL80211_STA_INFO_TX_BITRATE], buf, sizeof(buf));
+ WMESH_LOGD(" tx bitrate:\t%s", buf);
+ }
+
+ if (0 != sta_info[NL80211_STA_INFO_TX_PACKETS]) {
+ station_info->tx_packets =
+ nla_get_u32(sta_info[NL80211_STA_INFO_TX_PACKETS]);
+ WMESH_LOGD(" tx packets:\t%u", station_info->tx_packets);
+ }
+ if (0 != sta_info[NL80211_STA_INFO_TX_RETRIES]) {
+ station_info->tx_retries =
+ nla_get_u32(sta_info[NL80211_STA_INFO_TX_RETRIES]);
+ WMESH_LOGD(" tx retries:\t%u", station_info->tx_retries);
+ }
+ if (0 != sta_info[NL80211_STA_INFO_TX_FAILED]) {
+ station_info->tx_failed =
+ nla_get_u32(sta_info[NL80211_STA_INFO_TX_FAILED]);
+ WMESH_LOGD(" tx failed:\t%u", station_info->tx_failed);
+ }
+#ifdef NL80211_STA_INFO_CHAIN_SIGNAL_AVG
+ /* Signal average */
+ chain = get_chain_signal(sta_info[NL80211_STA_INFO_CHAIN_SIGNAL_AVG]);
+ if (0 != sta_info[NL80211_STA_INFO_SIGNAL_AVG]) {
+ station_info->rssi_avg =
+ (int8_t)nla_get_u8(sta_info[NL80211_STA_INFO_SIGNAL_AVG]);
+ WMESH_LOGD(" signal avg:\t%d %sdBm", station_info->rssi_avg, chain);
+ }
+#endif /* NL80211_STA_INFO_CHAIN_SIGNAL_AVG */
+ if (0 != sta_info[NL80211_STA_INFO_RX_BITRATE]) {
+ char buf[100];
+ station_info->rx_bitrate =
+ parse_bitrate(sta_info[NL80211_STA_INFO_RX_BITRATE], buf, sizeof(buf));
+ WMESH_LOGD(" rx bitrate:\t%s", buf);
+ }
+
+ if (0 != sta_info[NL80211_STA_INFO_BSS_PARAM])
+ parse_bss_param(sta_info[NL80211_STA_INFO_BSS_PARAM], station_info);
+
+ if (0 != sta_info[NL80211_STA_INFO_CONNECTED_TIME]) {
+ station_info->connected_time =
+ nla_get_u32(sta_info[NL80211_STA_INFO_CONNECTED_TIME]);
+ WMESH_LOGD(" connected time:\t%u seconds", station_info->connected_time);
+ }
+
+ if (0 != sta_info[NL80211_STA_INFO_STA_FLAGS]) {
+ sta_flags = (struct nl80211_sta_flag_update *)
+ nla_data(sta_info[NL80211_STA_INFO_STA_FLAGS]);
+
+ if (sta_flags->mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
+ WMESH_LOGD(" authorized:");
+ if (sta_flags->set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
+ WMESH_LOGD(" yes");
+ station_info->authorized = TRUE;
+ } else {
+ WMESH_LOGD(" no");
+ station_info->authorized = FALSE;
+ }
+ }
+
+ if (sta_flags->mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
+ WMESH_LOGD(" authenticated:");
+ if (sta_flags->set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
+ WMESH_LOGD(" yes");
+ station_info->authenticated = TRUE;
+ } else {
+ WMESH_LOGD(" no");
+ station_info->authenticated = FALSE;
+ }
+ }
+
+ if (sta_flags->mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) {
+ WMESH_LOGD(" associated:");
+ if (sta_flags->set & BIT(NL80211_STA_FLAG_ASSOCIATED)) {
+ WMESH_LOGD(" yes");
+ station_info->associated = TRUE;
+ } else {
+ WMESH_LOGD(" no");
+ station_info->associated = FALSE;
+ }
+ }
+
+ if (sta_flags->mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
+ WMESH_LOGD(" preamble:");
+ if (sta_flags->set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
+ WMESH_LOGD(" short");
+ station_info->preamble = TRUE;
+ } else {
+ WMESH_LOGD(" long");
+ station_info->preamble = FALSE;
+ }
+ }
+
+ if (sta_flags->mask & BIT(NL80211_STA_FLAG_WME)) {
+ WMESH_LOGD(" WMM/WME:");
+ if (sta_flags->set & BIT(NL80211_STA_FLAG_WME)) {
+ WMESH_LOGD(" yes");
+ station_info->wme = TRUE;
+ } else {
+ WMESH_LOGD(" no");
+ station_info->wme = FALSE;
+ }
+ }
+
+ if (sta_flags->mask & BIT(NL80211_STA_FLAG_MFP)) {
+ WMESH_LOGD(" MFP:");
+ if (sta_flags->set & BIT(NL80211_STA_FLAG_MFP)) {
+ WMESH_LOGD(" yes");
+ station_info->mfp = TRUE;
+ } else {
+ WMESH_LOGD(" no");
+ station_info->mfp = FALSE;
+ }
+ }
+
+ if (sta_flags->mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
+ WMESH_LOGD(" TDLS peer:");
+ if (sta_flags->set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
+ WMESH_LOGD(" yes");
+ station_info->tdls_peer = TRUE;
+ } else {
+ WMESH_LOGD(" no");
+ station_info->tdls_peer = FALSE;
+ }
+ }
+ }
+
+ if (0 != sta_info[NL80211_STA_INFO_BEACON_LOSS]) {
+ station_info->beacon_loss =
+ nla_get_u32(sta_info[NL80211_STA_INFO_BEACON_LOSS]);
+ WMESH_LOGD(" beacon loss:\t%u", station_info->beacon_loss);
+ }
+
+ if (0 != sta_info[NL80211_STA_INFO_T_OFFSET]) {
+ station_info->t_offset =
+ (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_T_OFFSET]);
+ WMESH_LOGD(" Toffset:\t%llu us", station_info->t_offset);
+ }
+
+ if (0 != sta_info[NL80211_STA_INFO_LOCAL_PM]) {
+ station_info->local_ps_mode =
+ nla_get_u32(sta_info[NL80211_STA_INFO_LOCAL_PM]);
+ WMESH_LOGD(" mesh local PS mode:\t");
+ print_power_mode(sta_info[NL80211_STA_INFO_LOCAL_PM]);
+ }
+ if (0 != sta_info[NL80211_STA_INFO_PEER_PM]) {
+ station_info->peer_ps_mode =
+ nla_get_u32(sta_info[NL80211_STA_INFO_PEER_PM]);
+ WMESH_LOGD(" mesh peer PS mode:\t");
+ print_power_mode(sta_info[NL80211_STA_INFO_PEER_PM]);
+ }
+ if (0 != sta_info[NL80211_STA_INFO_NONPEER_PM]) {
+ station_info->non_peer_ps_mode =
+ nla_get_u32(sta_info[NL80211_STA_INFO_NONPEER_PM]);
+ WMESH_LOGD(" mesh non-peer PS mode:\t");
+ print_power_mode(sta_info[NL80211_STA_INFO_NONPEER_PM]);
+ }
+#ifdef NL80211_STA_INFO_RX_DROP_MISC
+ if (0 != sta_info[NL80211_STA_INFO_RX_DROP_MISC]) {
+ station_info->rx_drop_misc =
+ (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_RX_DROP_MISC]);
+ WMESH_LOGD(" rx drop misc:\t%llu", station_info->rx_drop_misc);
+ }
+#endif /* NL80211_STA_INFO_RX_DROP_MISC */
+
+#ifdef NL80211_STA_INFO_BEACON_RX
+ if (0 != sta_info[NL80211_STA_INFO_BEACON_RX]) {
+ station_info->beacon_rx =
+ (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_BEACON_RX]);
+ WMESH_LOGD(" beacon rx:\t%llu", station_info->beacon_rx);
+ }
+#endif /* NL80211_STA_INFO_BEACON_RX */
+
+#ifdef NL80211_STA_INFO_BEACON_SIGNAL_AVG
+ if (0 != sta_info[NL80211_STA_INFO_BEACON_SIGNAL_AVG]) {
+ station_info->beacon_signal_avg =
+ nla_get_u8(sta_info[NL80211_STA_INFO_BEACON_SIGNAL_AVG]);
+ WMESH_LOGD(" beacon signal avg:\t%d dBm", station_info->beacon_signal_avg);
+ }
+#endif /* NL80211_STA_INFO_BEACON_SIGNAL_AVG */
+
+#ifdef NL80211_STA_INFO_RX_DURATION
+ if (0 != sta_info[NL80211_STA_INFO_RX_DURATION]) {
+ station_info->rx_duration =
+ (unsigned long long)nla_get_u64(sta_info[NL80211_STA_INFO_RX_DURATION]);
+ WMESH_LOGD(" rx duration:\t%lld us", station_info->rx_duration);
+ }
+#endif /* NL80211_STA_INFO_RX_DURATION */
+ WMESH_LOGD("");
+ *(state->station_list) = g_list_prepend(*(state->station_list), station_info);
+
+ return NL_SKIP;
+}
+
+static int _on_receive_mpath_info(struct nl_msg *msg, void *arg)
+{
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct nlattr *pinfo[NL80211_MPATH_INFO_MAX + 1];
+ char dst[20], next_hop[20], dev[20];
+ static struct nla_policy mpath_policy[NL80211_MPATH_INFO_MAX + 1] = {
+ [NL80211_MPATH_INFO_FRAME_QLEN] = { .type = NLA_U32 },
+ [NL80211_MPATH_INFO_SN] = { .type = NLA_U32 },
+ [NL80211_MPATH_INFO_METRIC] = { .type = NLA_U32 },
+ [NL80211_MPATH_INFO_EXPTIME] = { .type = NLA_U32 },
+ [NL80211_MPATH_INFO_DISCOVERY_TIMEOUT] = { .type = NLA_U32 },
+ [NL80211_MPATH_INFO_DISCOVERY_RETRIES] = { .type = NLA_U8 },
+ [NL80211_MPATH_INFO_FLAGS] = { .type = NLA_U8 },
+ };
+
+ mesh_nl_state *state = (mesh_nl_state *)arg;
+ wmesh_mpath_info_s *mpath_info = NULL;
+
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+
+ /*
+ * TODO: validate the interface and mac address!
+ * Otherwise, there's a race condition as soon as
+ * the kernel starts sending mpath notifications.
+ */
+
+ if (!tb[NL80211_ATTR_MPATH_INFO]) {
+ WMESH_LOGE("missing mesh path info!");
+ return NL_SKIP;
+ }
+ if (nla_parse_nested(pinfo, NL80211_MPATH_INFO_MAX,
+ tb[NL80211_ATTR_MPATH_INFO],
+ mpath_policy)) {
+ WMESH_LOGE("failed to parse nested attributes!");
+ return NL_SKIP;
+ }
+
+ mpath_info = g_try_new0(wmesh_mpath_info_s, 1);
+ if (NULL == mpath_info) {
+ WMESH_LOGE("Failed to allocate mesh path info !");
+ return NL_SKIP;
+ }
+
+ mac_addr_n2a(dst, nla_data(tb[NL80211_ATTR_MAC]));
+ mpath_info->dest_addr = g_strdup(dst);
+ WMESH_LOGD("Destination Address : %s", mpath_info->dest_addr);
+
+ mac_addr_n2a(next_hop, nla_data(tb[NL80211_ATTR_MPATH_NEXT_HOP]));
+ mpath_info->next_hop = g_strdup(next_hop);
+ WMESH_LOGD("Next hop Address : %s", mpath_info->next_hop);
+
+ if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
+ mpath_info->interface = g_strdup(dev);
+ WMESH_LOGD("Interface : %s", mpath_info->interface);
+
+ if (pinfo[NL80211_MPATH_INFO_SN]) {
+ mpath_info->sn = nla_get_u32(pinfo[NL80211_MPATH_INFO_SN]);
+ WMESH_LOGD("SN : %u", mpath_info->sn);
+ }
+ if (pinfo[NL80211_MPATH_INFO_METRIC]) {
+ mpath_info->metric = nla_get_u32(pinfo[NL80211_MPATH_INFO_METRIC]);
+ WMESH_LOGD("Metric : %u", mpath_info->metric);
+ }
+ if (pinfo[NL80211_MPATH_INFO_FRAME_QLEN]) {
+ mpath_info->qlen = nla_get_u32(pinfo[NL80211_MPATH_INFO_FRAME_QLEN]);
+ WMESH_LOGD("QLEN : %u", mpath_info->qlen);
+ }
+ if (pinfo[NL80211_MPATH_INFO_EXPTIME]) {
+ mpath_info->exptime = nla_get_u32(pinfo[NL80211_MPATH_INFO_EXPTIME]);
+ WMESH_LOGD("ExpTime : %u", mpath_info->exptime);
+ }
+ if (pinfo[NL80211_MPATH_INFO_DISCOVERY_TIMEOUT]) {
+ mpath_info->discovery_timeout =
+ nla_get_u32(pinfo[NL80211_MPATH_INFO_DISCOVERY_TIMEOUT]);
+ WMESH_LOGD("Discovery Timeout : %u", mpath_info->discovery_timeout);
+ }
+ if (pinfo[NL80211_MPATH_INFO_DISCOVERY_RETRIES]) {
+ mpath_info->discovery_retries =
+ nla_get_u8(pinfo[NL80211_MPATH_INFO_DISCOVERY_RETRIES]);
+ WMESH_LOGD("Discovery Retries : %u", mpath_info->discovery_retries);
+ }
+ if (pinfo[NL80211_MPATH_INFO_FLAGS]) {
+ mpath_info->flags = nla_get_u8(pinfo[NL80211_MPATH_INFO_FLAGS]);
+ WMESH_LOGD("Flags : 0x%x", mpath_info->flags);
+ }
+
+ WMESH_LOGD("");
+ *(state->mpath_list) = g_list_prepend(*(state->mpath_list), mpath_info);
+
+ return NL_SKIP;
+}
+
+static int _on_receive_mesh_event(struct nl_msg *msg, void *arg)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ char ifname[16] = { 0, };
+ char macbuf[MAX_MAC_ADDR_LEN];
+
+ NOTUSED(arg);
+
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
+
+ if (tb[NL80211_ATTR_IFINDEX]) {
+ if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), ifname);
+ WMESH_LOGD("%s: ", ifname);
+ }
+
+ switch (gnlh->cmd) {
+ case NL80211_CMD_NEW_STATION:
+ mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
+ WMESH_LOGD("[%s] new station [%s]", ifname, macbuf);
+ break;
+ case NL80211_CMD_DEL_STATION:
+ mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
+ WMESH_LOGD("[%s] del station [%s]", ifname, macbuf);
+ break;
+ case NL80211_CMD_NEW_MPATH:
+ mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
+ WMESH_LOGD("[%s] new mpath [%s]", ifname, macbuf);
+
+ wmesh_notify_station_joined((const char*)macbuf);
+ break;
+ case NL80211_CMD_DEL_MPATH:
+ mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
+ WMESH_LOGD("[%s] del mpath [%s]", ifname, macbuf);
+
+ wmesh_notify_station_left((const char*)macbuf);
+ break;
+ default:
+ WMESH_LOGD("event [%d] is not handled", gnlh->cmd);
+ break;
+ }
+
+ return NL_SKIP;
+}
+
+static int _send_nl_set_mesh_parameter(const char* mesh_if_name,
+ const char* param_name, unsigned int value)
+{
+ mesh_nl_state state = {
+ .nl80211_id = -1,
+ .callback_state = MESH_NL_CALLBACK_TRYING,
+ .event_source = 0,
+ .nl_socket = NULL,
+ .msg = NULL,
+ .cb = NULL,
+ .s_cb = NULL,
+ .error_occured = FALSE,
+ };
+ struct nlattr *container;
+
+ int err = WMESHD_ERROR_NONE;
+ int device_index = 0;
+ int ret;
+ int test = 0;
+
+ ret = __initialize_nl80211(&state);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to initialize nl80211");
+ return ret;
+ }
+
+ ret = __initialize_netlink_message(&state);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to initialize netlink message");
+ goto DESTROY;
+ }
+
+ /* Set command into message */
+ genlmsg_put(state.msg, 0, 0, state.nl80211_id, 0,
+ 0, NL80211_CMD_SET_MESH_PARAMS, 0);
+
+ /* Add attributes into message */
+ ret = __get_device_index_from_string(mesh_if_name, &device_index);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to get mesh device index");
+ err = ret;
+ goto DESTROY;
+ }
+ NLA_PUT_U32(state.msg, NL80211_ATTR_IFINDEX, device_index);
+
+ container = nla_nest_start(state.msg, NL80211_ATTR_MESH_PARAMS);
+ if (!container) {
+ WMESH_LOGE("Failed to initialize netlink message");
+ goto DESTROY;
+ }
+
+ /* Logic need to be changed if additional parameter is required */
+ if (g_strcmp0(MESH_PARAM_HWMP_ROOTMODE, param_name) == 0) {
+ WMESH_LOGD(" [mesh_hwmp_rootmode] : [%d]", value);
+ NLA_PUT_U8(state.msg, NL80211_MESHCONF_HWMP_ROOTMODE,
+ (uint8_t)value);
+ } else if (g_strcmp0(MESH_PARAM_GATE_ANNOUNCE, param_name) == 0) {
+ WMESH_LOGD(" [mesh_gate_announcements] : [%d]", value);
+ NLA_PUT_U8(state.msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
+ (uint8_t)value);
+ } else {
+ WMESH_LOGE("Parameter [%s] is not required !", param_name);
+ nla_nest_end(state.msg, container);
+ goto DESTROY;
+ }
+ nla_nest_end(state.msg, container);
+
+ /* Send message into kernel */
+ ret = nl_send_auto(state.nl_socket, state.msg);
+ if (ret < 0) {
+ WMESH_LOGE("Failed to nl_send_auto() [%s](%d)",
+ nl_geterror(ret), ret);
+ err = WMESHD_ERROR_OPERATION_FAILED;
+ goto DESTROY;
+ }
+
+ /* sync response */
+ state.callback_state = MESH_NL_CALLBACK_TRYING;
+ while (state.callback_state == MESH_NL_CALLBACK_TRYING) {
+ WMESH_LOGD(" count [%02d]", ++test);
+ nl_recvmsgs(state.nl_socket, state.cb);
+ }
+
+DESTROY:
+ __clean_netlink_message(&state);
+ __clean_nl80211(&state);
+
+ return err;
+
+nla_put_failure:
+ WMESH_LOGE("Failed to message build");
+ __clean_netlink_message(&state);
+ __clean_nl80211(&state);
+
+ return WMESHD_ERROR_OPERATION_FAILED;
+}
+
+static int _send_nl_get_station_info(const char* if_name, GList **station_list)
+{
+ mesh_nl_state state = {
+ .nl80211_id = -1,
+ .callback_state = MESH_NL_CALLBACK_TRYING,
+ .event_source = 0,
+ .nl_socket = NULL,
+ .msg = NULL,
+ .cb = NULL,
+ .s_cb = NULL,
+ .station_list = station_list
+ };
+ int err = WMESHD_ERROR_NONE;
+ int device_index = 0;
+ int ret;
+ int test = 0;
+
+ ret = __initialize_nl80211(&state);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to initialize nl80211");
+ return ret;
+ }
+
+ ret = __initialize_netlink_message(&state);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to initialize netlink message");
+ goto DESTROY;
+ }
+
+ /* Set command into message */
+ genlmsg_put(state.msg, 0, 0, state.nl80211_id, 0,
+ NLM_F_DUMP, NL80211_CMD_GET_STATION, 0);
+
+ /* Add attributes into message */
+ WMESH_LOGD("Dump station list with interface [%s]", if_name);
+ ret = __get_device_index_from_string(if_name, &device_index);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to get mesh interface device index");
+ err = ret;
+ goto DESTROY;
+ }
+ NLA_PUT_U32(state.msg, NL80211_ATTR_IFINDEX, device_index);
+
+ /* Register valid callback to dump result */
+ nl_cb_set(state.cb, NL_CB_VALID, NL_CB_CUSTOM,
+ _on_receive_station_info, &state);
+
+ /* Send message into kernel */
+ ret = nl_send_auto(state.nl_socket, state.msg);
+ if (ret < 0) {
+ WMESH_LOGE("Failed to nl_send_auto() [%s](%d)",
+ nl_geterror(ret), ret);
+ err = WMESHD_ERROR_OPERATION_FAILED;
+ goto DESTROY;
+ }
+
+ /* sync response */
+ state.callback_state = MESH_NL_CALLBACK_TRYING;
+ while (state.callback_state == MESH_NL_CALLBACK_TRYING) {
+ WMESH_LOGD(" count [%02d]", ++test);
+ nl_recvmsgs(state.nl_socket, state.cb);
+ }
+ WMESH_LOGD("Finished");
+
+DESTROY:
+ __clean_netlink_message(&state);
+ __clean_nl80211(&state);
+
+ return err;
+
+nla_put_failure:
+ WMESH_LOGE("Failed to message build");
+ __clean_netlink_message(&state);
+ __clean_nl80211(&state);
+
+ return WMESHD_ERROR_OPERATION_FAILED;
+}
+
+static int _send_nl_del_station_info(const char* if_name, char* peer)
+{
+ mesh_nl_state state = {
+ .nl80211_id = -1,
+ .callback_state = MESH_NL_CALLBACK_FINISHED,
+ .event_source = 0,
+ .nl_socket = NULL,
+ .msg = NULL,
+ .cb = NULL,
+ .s_cb = NULL,
+ .station_list = NULL,
+ };
+ int err = WMESHD_ERROR_NONE;
+ int device_index = 0;
+ int ret;
+
+ ret = __initialize_nl80211(&state);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to initialize nl80211");
+ return ret;
+ }
+
+ ret = __initialize_netlink_message(&state);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to initialize netlink message");
+ goto DESTROY;
+ }
+
+ /* Set command into message */
+ genlmsg_put(state.msg, 0, 0, state.nl80211_id, 0,
+ NLM_F_DUMP, NL80211_CMD_DEL_STATION, 0);
+
+ /* Add attributes into message */
+ WMESH_LOGD("Delete a station [%s] with interface [%s]", peer, if_name);
+ ret = __get_device_index_from_string(if_name, &device_index);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to get mesh interface device index");
+ err = ret;
+ goto DESTROY;
+ }
+ NLA_PUT_U32(state.msg, NL80211_ATTR_IFINDEX, device_index);
+ NLA_PUT(state.msg, NL80211_ATTR_MAC, ETH_ALEN, peer);
+
+ /* Send message into kernel */
+ ret = nl_send_auto(state.nl_socket, state.msg);
+ if (ret < 0) {
+ WMESH_LOGE("Failed to nl_send_auto() [%s](%d)",
+ nl_geterror(ret), ret);
+ err = WMESHD_ERROR_OPERATION_FAILED;
+ goto DESTROY;
+ }
+
+DESTROY:
+ __clean_netlink_message(&state);
+ __clean_nl80211(&state);
+
+ return err;
+
+nla_put_failure:
+ WMESH_LOGE("Failed to message build");
+ __clean_netlink_message(&state);
+ __clean_nl80211(&state);
+
+ return WMESHD_ERROR_OPERATION_FAILED;
+}
+
+static int _send_nl_get_mpath_info(const char* if_name, GList **mpath_list)
+{
+ mesh_nl_state state = {
+ .nl80211_id = -1,
+ .callback_state = MESH_NL_CALLBACK_TRYING,
+ .event_source = 0,
+ .nl_socket = NULL,
+ .msg = NULL,
+ .cb = NULL,
+ .s_cb = NULL,
+ .mpath_list = mpath_list
+ };
+ int err = WMESHD_ERROR_NONE;
+ int device_index = 0;
+ int ret;
+ int test = 0;
+
+ ret = __initialize_nl80211(&state);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to initialize nl80211");
+ return ret;
+ }
+
+ ret = __initialize_netlink_message(&state);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to initialize netlink message");
+ goto DESTROY;
+ }
+
+ /* Set command into message */
+ genlmsg_put(state.msg, 0, 0, state.nl80211_id, 0,
+ NLM_F_DUMP, NL80211_CMD_GET_MPATH, 0);
+
+ /* Add attributes into message */
+ WMESH_LOGD("Dump station list with interface [%s]", if_name);
+ ret = __get_device_index_from_string(if_name, &device_index);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to get mesh interface device index");
+ err = ret;
+ goto DESTROY;
+ }
+ NLA_PUT_U32(state.msg, NL80211_ATTR_IFINDEX, device_index);
+
+ /* Register valid callback to dump result */
+ nl_cb_set(state.cb, NL_CB_VALID, NL_CB_CUSTOM,
+ _on_receive_mpath_info, &state);
+
+ /* Send message into kernel */
+ ret = nl_send_auto(state.nl_socket, state.msg);
+ if (ret < 0) {
+ WMESH_LOGE("Failed to nl_send_auto() [%s](%d)",
+ nl_geterror(ret), ret);
+ err = WMESHD_ERROR_OPERATION_FAILED;
+ goto DESTROY;
+ }
+
+ /* sync response */
+ state.callback_state = MESH_NL_CALLBACK_TRYING;
+ while (state.callback_state == MESH_NL_CALLBACK_TRYING) {
+ WMESH_LOGD(" count [%02d]", ++test);
+ nl_recvmsgs(state.nl_socket, state.cb);
+ }
+ WMESH_LOGD("Finished");
+
+DESTROY:
+ __clean_netlink_message(&state);
+ __clean_nl80211(&state);
+
+ return err;
+
+nla_put_failure:
+ WMESH_LOGE("Failed to message build");
+ __clean_netlink_message(&state);
+ __clean_nl80211(&state);
+
+ return WMESHD_ERROR_OPERATION_FAILED;
+}
+
+static int _send_nl_register_event_handler()
+{
+ int err = WMESHD_ERROR_NONE;
+ int ret;
+ GIOChannel *recv_channel = NULL;
+
+ if (event_state) {
+ WMESH_LOGE("Already event handler registered !");
+ return WMESHD_ERROR_IN_PROGRESS;
+ }
+
+ event_state = _create_mesh_nl_state("");
+
+ ret = __initialize_nl80211(event_state);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to initialize nl80211");
+ return ret;
+ }
+
+ /* Subscribe multicast group should be proceed before scanning */
+ ret = __prepare_listen_events(event_state);
+ if (ret) {
+ WMESH_LOGE("__prepare_listen_events : [%d]", ret);
+ goto DESTROY;
+ }
+
+ ret = __initialize_netlink_message(event_state);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to initialize netlink message");
+ goto DESTROY;
+ }
+
+ /* Set command into message */
+ genlmsg_put(event_state->msg, 0, 0, event_state->nl80211_id, 0, 0, 0, 0);
+
+ /* Set callbacks for event handler */
+ nl_cb_set(event_state->cb, NL_CB_VALID, NL_CB_CUSTOM,
+ _on_receive_mesh_event, event_state);
+ /* No sequence checking for multicast messages. */
+ nl_cb_set(event_state->cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
+
+ WMESH_LOGD("Register event handler");
+
+ /* Change socket type to non-blocking */
+ ret = nl_socket_set_nonblocking(event_state->nl_socket);
+ if (ret < 0)
+ WMESH_LOGE("Failed to non-blocking socket [%s](%d)", nl_geterror(ret), ret);
+
+ /* Register I/O callback to wait asynchronously */
+ if (FALSE == event_state->error_occured) {
+ recv_channel = g_io_channel_unix_new(nl_socket_get_fd(event_state->nl_socket));
+ event_state->event_source = g_io_add_watch(recv_channel,
+ (G_IO_IN | G_IO_ERR), _on_socket_event_io_received, event_state);
+ g_io_channel_unref(recv_channel);
+ } else {
+ WMESH_LOGE("Error responded. Failed to register event callback !!");
+ goto DESTROY;
+ }
+
+ /* Resource should be free on I/O callback */
+ return WMESHD_ERROR_NONE;
+
+DESTROY:
+ __clean_netlink_message(event_state);
+ __clean_nl80211(event_state);
+ _delete_mesh_nl_state(&event_state);
+
+ return err;
+}
+
+int wmesh_netlink_set_mesh_parameter(const char* mesh_if_name,
+ const char* param_name, unsigned int value)
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ if (NULL == mesh_if_name || strlen(mesh_if_name) > IFNAMSIZ) {
+ WMESH_LOGE("Invalid parameter [%p]", mesh_if_name);
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("Set mesh[%s] param [%s] value [%d]",
+ mesh_if_name, param_name, value);
+ ret = _send_nl_set_mesh_parameter(mesh_if_name, param_name, value);
+
+ return ret;
+}
+
+int wmesh_netlink_get_station_info(const char* mesh_if_name, GList **station_list)
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ if (NULL == mesh_if_name || strlen(mesh_if_name) > IFNAMSIZ) {
+ WMESH_LOGE("Invalid parameter [%p]", mesh_if_name);
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+ if (NULL == station_list) {
+ WMESH_LOGE("Invalid parameter [%p]", station_list);
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("Get connected stations");
+ ret = _send_nl_get_station_info(mesh_if_name, station_list);
+
+ return ret;
+}
+
+int wmesh_netlink_del_station_info(const char* mesh_if_name, char *peer)
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ if (NULL == mesh_if_name || strlen(mesh_if_name) > IFNAMSIZ) {
+ WMESH_LOGE("Invalid parameter [%p]", mesh_if_name);
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+ if (NULL == peer) {
+ WMESH_LOGE("Invalid parameter [%p]", peer);
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("Del connected station : [%s]", peer);
+ ret = _send_nl_del_station_info(mesh_if_name, peer);
+
+ return ret;
+}
+
+int wmesh_netlink_get_mpath_info(const char* mesh_if_name, GList **mpath_list)
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ if (NULL == mesh_if_name || strlen(mesh_if_name) > IFNAMSIZ) {
+ WMESH_LOGE("Invalid parameter [%p]", mesh_if_name);
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+ if (NULL == mpath_list) {
+ WMESH_LOGE("Invalid parameter [%p]", mpath_list);
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("Get current mpath info");
+ ret = _send_nl_get_mpath_info(mesh_if_name, mpath_list);
+
+ return ret;
+}
+
+int wmesh_netlink_register_event_handler()
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ WMESH_LOGD("Register mesh event handler");
+ ret = _send_nl_register_event_handler();
+
+ return ret;
+}
+
+int wmesh_netlink_unregister_event_handler()
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ WMESH_LOGD("Unregister mesh event handler");
+
+ _on_remove_event_io_handler();
+
+ return ret;
+}
--- /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 <glib.h>
+
+#include "wmesh.h"
+#include "wmesh-log.h"
+#include "wmesh-util.h"
+#include "wmesh-gdbus.h"
+#include "wmesh-request.h"
+#include "wmesh-netlink.h"
+#include "wmesh-interface.h"
+#include "wmesh-peer-monitor.h"
+
+#define MESH_MONITORING_TIME 5
+#define MESH_MAXIMUM_BEACON_LOST_COUNT 10
+
+static void _on_station_list_destroy(gpointer data)
+{
+ wmesh_station_info_s *info = (wmesh_station_info_s*)data;
+
+ if (info) {
+ g_free(info->bssid);
+ g_free(info);
+ }
+}
+#if 0
+static void _on_mpath_list_destroy(gpointer data)
+{
+ wmesh_mpath_info_s *info = (wmesh_mpath_info_s*)data;
+
+ if (info) {
+ g_free(info->dest_addr);
+ g_free(info->next_hop);
+ g_free(info->interface);
+ g_free(info);
+ }
+}
+#endif
+
+static int _get_station_info(void *pdata)
+{
+ int is_new;
+ int ret = WMESHD_ERROR_NONE;
+
+ GList *iter = NULL;
+ GList *sta_list = NULL;
+ GList *cmp_iter = NULL;
+
+ wmesh_service *service = (wmesh_service *)pdata;
+ wmesh_interface_s *info = service->interface_info;
+
+ ret = wmesh_request_get_station_info(info->mesh_interface, &sta_list);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to wmesh_request_get_station_info");
+ return ret;
+ }
+
+ iter = service->station_list;
+ while (iter) {
+ wmesh_station_info_s *item = (wmesh_station_info_s*)iter->data;
+ WMESH_LOGD("[%s]", item->bssid);
+ iter = g_list_next(iter);
+ }
+
+ iter = sta_list;
+ while (iter) {
+ wmesh_station_info_s *item = (wmesh_station_info_s*)iter->data;
+
+ /* Found this in th existing station infomation list. */
+ if (item->inactive_time > item->beacon_interval * MESH_MAXIMUM_BEACON_LOST_COUNT) {
+ /* Remove this node from station list in kernel */
+ wmesh_netlink_del_station_info(info->mesh_interface, item->bssid);
+ /* Remove current linked list */
+ iter = g_list_remove(iter, item);
+ /* Send existing node disjoined */
+ WMESH_LOGE("[%s] disjoined", item->bssid);
+
+ }
+
+ is_new = TRUE;
+ cmp_iter = service->station_list;
+ while (cmp_iter) {
+ wmesh_station_info_s *cmp_item = (wmesh_station_info_s*)cmp_iter->data;
+ if (0 == strncmp(item->bssid, cmp_item->bssid, sizeof("11:22:33:44:55:66"))) {
+ is_new = FALSE;
+ break;
+ }
+ cmp_iter = g_list_next(cmp_iter);
+ }
+
+ if (is_new) {
+ /* Send new station joined event */
+ WMESH_LOGE("[%s] joined", item->bssid);
+ }
+
+ iter = g_list_next(iter);
+ }
+
+ /* Clear mesh station list */
+ g_list_free_full(service->station_list, _on_station_list_destroy);
+ /* Copy new mesh station list */
+ service->station_list = sta_list;
+
+ iter = service->station_list;
+ while (iter) {
+ wmesh_station_info_s *item2 = (wmesh_station_info_s*)iter->data;
+ WMESH_LOGE("[%s]", item2->bssid);
+ iter = g_list_next(iter);
+ }
+
+ return ret;
+}
+#if 0
+static gboolean _get_mpath_info(void *pdata)
+{
+ int ret = WMESHD_ERROR_NONE;
+ GVariantBuilder builder;
+ GVariant* mpath_data;
+ GList *iter = NULL;
+
+ wmesh_service *service = (wmesh_service *)pdata;
+ wmesh_interface_s *info = service->interface_info;
+
+ /* Clear mesh path list */
+ g_list_free_full(service->mpath_list, _on_mpath_list_destroy);
+ service->mpath_list = NULL;
+
+ ret = wmesh_request_get_mpath_info(info->mesh_interface, &service->mpath_list);
+ if (WMESHD_ERROR_NONE == ret) {
+ /*
+ * Example) sh-3.2# iw mesh0 mpath dump
+ * DEST ADDR NEXT HOP IFACE SN METRIC QLEN EXPTIME DTIM DRET FLAGS
+ * 7c:dd:90:62:37:cf 7c:dd:90:62:37:cf mesh0 221 152 0 10 100 0 0x5
+ */
+ /* Get mesh path information and make variant data */
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
+
+ iter = service->mpath_list;
+ while (iter != NULL) {
+ wmesh_mpath_info_s *item = (wmesh_mpath_info_s*)iter->data;
+
+ g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add(&builder, "{sv}", "DEST_ADDR",
+ g_variant_new_string(item->dest_addr));
+ g_variant_builder_add(&builder, "{sv}", "NEXT_HOP",
+ g_variant_new_string(item->next_hop));
+ g_variant_builder_add(&builder, "{sv}", "IFACE",
+ g_variant_new_string(item->interface));
+ g_variant_builder_add(&builder, "{sv}", "SN",
+ g_variant_new_uint32(item->sn));
+ g_variant_builder_add(&builder, "{sv}", "METRIC",
+ g_variant_new_uint32(item->metric));
+ g_variant_builder_add(&builder, "{sv}", "QLEN",
+ g_variant_new_uint32(item->qlen));
+ g_variant_builder_add(&builder, "{sv}", "EXPTIME",
+ g_variant_new_uint32(item->exptime));
+ g_variant_builder_add(&builder, "{sv}", "DTIM",
+ g_variant_new_uint32(item->discovery_timeout));
+ g_variant_builder_add(&builder, "{sv}", "DRET",
+ g_variant_new_byte(item->discovery_retries));
+ g_variant_builder_add(&builder, "{sv}", "FLAGS",
+ g_variant_new_byte(item->flags));
+ g_variant_builder_close(&builder);
+
+ iter = g_list_next(iter);
+ }
+
+ mpath_data = g_variant_builder_end(&builder);
+ g_object_unref(mpath_data);
+ } else
+ WMESH_LOGE("Failed to wmesh_request_get_mpath_info");
+
+ return ret;
+}
+#endif
+static gboolean _on_mesh_monitor_cb(gpointer pdata)
+{
+ int ret;
+ bool state;
+ wmesh_service *service = (wmesh_service *)pdata;
+ if (service) {
+ wmesh_interface_s *info = service->interface_info;
+ if (info) {
+ /* Exceptionally, checking external interface processes here. */
+ ret = wmesh_interface_check_external_exists(info->external_interface, &state);
+ WMESH_LOGD("Status : %d %d %d", ret, info->can_be_gate, state);
+ if (WMESHD_ERROR_NONE == ret) {
+ if (info->can_be_gate != state) {
+ wmesh_gdbus_enable_ethernet_interface(service, state);
+#if 0
+ /* Detect external network state (i.e. Ethernet)
+ and decide to make gate enabled */
+ if (state)
+ wmesh_request_set_mesh_gate(info->bridge_interface,
+ info->mesh_interface, info->external_interface);
+ else
+ wmesh_request_unset_mesh_gate(info->bridge_interface,
+ info->mesh_interface, info->external_interface);
+#endif
+ WMESH_LOGD("External interface state has been changed : [%d]", state);
+ info->can_be_gate = state;
+ }
+ } else {
+ /* In error case, we call enable etheret again for OdroidU3 */
+ wmesh_gdbus_enable_ethernet_interface(service, true);
+ }
+#if 0
+ _get_mpath_info(service);
+#endif
+ _get_station_info(service);
+ }
+ }
+
+ return G_SOURCE_CONTINUE;
+}
+
+int wmesh_start_monitor_service(void *pdata)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)pdata;
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+
+ if (service->monitor_timer)
+ wmesh_stop_monitor_service(pdata);
+
+ service->monitor_timer = g_timeout_add_seconds(MESH_MONITORING_TIME, _on_mesh_monitor_cb, service);
+
+ WMESH_LOGD("Peer Monitoring Service Started");
+
+ return ret;
+}
+
+int wmesh_stop_monitor_service(void *pdata)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)pdata;
+ wmeshd_check_null_ret_error("service", service, WMESHD_ERROR_INVALID_PARAMETER);
+
+ if (service->monitor_timer) {
+ g_source_remove(service->monitor_timer);
+ service->monitor_timer = 0;
+ }
+
+ WMESH_LOGD("Peer Monitoring Service Stopped");
+ return ret;
+}
--- /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 <stdlib.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "wmesh.h"
+#include "wmesh-log.h"
+#include "wmesh-util.h"
+#include "wmesh-service-interface.h"
+#include "wmesh-generated-code.h"
+
+#include "wmesh-bridge.h"
+#include "wmesh-netlink.h"
+#include "wmesh-interface.h"
+#include "wmesh-request.h"
+#include "wmesh-softap.h"
+#include "wmesh-gdbus.h"
+
+int wmesh_request_set_mesh_gate(const char* bridge_interface,
+ const char* mesh_interface, const char* external_interface)
+{
+ int ret = WMESHD_ERROR_NONE;
+ bool state = FALSE;
+
+ ret = wmesh_interface_check_external_exists(external_interface, &state);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to get external interface state !");
+ return WMESHD_ERROR_OPERATION_FAILED;
+ }
+ WMESH_LOGD(" Ethernet cable state [%s]",
+ (state) ? "Connected" : "Disconnected");
+
+ /* Turn STP on */
+ ret = wmesh_bridge_set_stp(bridge_interface, TRUE);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to turn STP on !");
+ return ret;
+ }
+
+ /* Set mesh parameters */
+ ret = wmesh_netlink_set_mesh_parameter(mesh_interface,
+ "mesh_hwmp_rootmode", 4);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to set [mesh_hwmp_rootmode] : 4");
+
+ ret = wmesh_netlink_set_mesh_parameter(mesh_interface,
+ "mesh_gate_announcements", 1);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to set [mesh_gate_announcements] : 1");
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_unset_mesh_gate(const char* bridge_interface,
+ const char* mesh_interface, const char* external_interface)
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ NOTUSED(external_interface);
+
+ /* Set mesh parameters */
+ ret = wmesh_netlink_set_mesh_parameter(mesh_interface,
+ "mesh_hwmp_rootmode", 0);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to set [mesh_hwmp_rootmode] : 0");
+
+ ret = wmesh_netlink_set_mesh_parameter(mesh_interface,
+ "mesh_gate_announcements", 0);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to set [mesh_gate_announcements] : 0");
+
+ /* Turn STP off */
+ ret = wmesh_bridge_set_stp(bridge_interface, FALSE);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to turn STP off!");
+ return ret;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_add_bridge_interface(const char* bridge_interface,
+ const char* interface)
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ if (NULL == bridge_interface || NULL == interface) {
+ WMESH_LOGE("Invalid parameters");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("Adding interface[%s] into bridge[%s]...", interface, bridge_interface);
+
+ /* Add external interface into bridge */
+ ret = wmesh_bridge_add_interface(bridge_interface, interface);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to add interface !");
+ return ret;
+ }
+
+ /* Make external interface down */
+ ret = wmesh_interface_set(interface, NULL, WMESH_INTERFACE_DOWN);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to change external interface state");
+ return ret;
+ }
+
+ /* Make external interface up with cleared IP */
+ ret = wmesh_interface_set(interface, "0.0.0.0", WMESH_INTERFACE_UP);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to change external interface state");
+ return ret;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_remove_bridge_interface(const char* bridge_interface,
+ const char* interface)
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ if (NULL == bridge_interface || NULL == interface) {
+ WMESH_LOGE("Invalid parameters");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("Removing interface[%s] from bridge[%s]...", interface, bridge_interface);
+
+ ret = wmesh_interface_check_bridge_interface_exists(bridge_interface, interface);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGD("Interface is not exist in bridge");
+ return WMESHD_ERROR_NONE;
+ }
+
+ /* Remove external interface into bridge */
+ ret = wmesh_bridge_del_interface(bridge_interface, interface);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to remove interface !");
+ return ret;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_set_softap_config(const char* softap_interface,
+ const char *ssid, const char* mode, int channel, int visibility,
+ int max_sta, int security, const char* passphrase)
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ WMESH_LOGD("Setting configuration for SoftAP");
+
+ ret = wmesh_softap_set_configuration(softap_interface, ssid, mode, channel,
+ visibility, max_sta, security, passphrase);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to set Configuration for SoftAP");
+ return ret;
+ }
+
+ return ret;
+}
+
+int wmesh_request_enable_softap(
+ const char* bridge_interface, const char* softap_interface)
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ WMESH_LOGD("Request to turn SoftAP on");
+ ret = wmesh_softap_enable_softap(softap_interface);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to wmesh_softap_enable_softap");
+ return ret;
+ }
+
+ /* Add softAP interface into bridge */
+ ret = wmesh_request_add_bridge_interface(bridge_interface, softap_interface);
+ if (WMESHD_ERROR_NONE != ret) {
+ wmesh_softap_disable_softap();
+ return ret;
+ }
+
+ return ret;
+}
+
+int wmesh_request_disable_softap(
+ const char* bridge_interface, const char* softap_interface)
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ WMESH_LOGD("Request to turn SoftAP off");
+ ret = wmesh_softap_disable_softap();
+
+ /* Remove softAP interface from bridge */
+ ret = wmesh_request_remove_bridge_interface(bridge_interface, softap_interface);
+ if (WMESHD_ERROR_NONE != ret)
+ return ret;
+
+ return ret;
+}
+
+int wmesh_request_get_station_info(const char* mesh_interface, GList **station_list)
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ WMESH_LOGD("Request to get station info");
+
+ /* Get station info */
+ ret = wmesh_netlink_get_station_info(mesh_interface, station_list);
+ if (WMESHD_ERROR_NONE != ret)
+ return ret;
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_get_mpath_info(const char* mesh_interface, GList **mpath_list)
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ WMESH_LOGD("Request to get mpath info");
+
+ /* Get MPath info */
+ ret = wmesh_netlink_get_mpath_info(mesh_interface, mpath_list);
+ if (WMESHD_ERROR_NONE != ret)
+ return ret;
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_register_event_handler()
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ WMESH_LOGD("Request to register mesh event handler");
+
+ /* Get MPath info */
+ ret = wmesh_netlink_register_event_handler();
+ if (WMESHD_ERROR_NONE != ret)
+ return ret;
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_unregister_event_handler()
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ WMESH_LOGD("Request to unregister mesh event handler");
+
+ /* Get MPath info */
+ ret = wmesh_netlink_unregister_event_handler();
+ if (WMESHD_ERROR_NONE != ret)
+ return ret;
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_enable_network(wmesh_service *service)
+{
+ int ret;
+ wmesh_interface_s *info = NULL;
+
+ if (NULL == service) {
+ WMESH_LOGE("Invalid parameter");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("[IPC] Enable mesh network");
+
+ /* Check if mesh interface exists */
+ info = service->interface_info;
+ ret = wmesh_interface_check(info->mesh_interface);
+ if (WMESHD_ERROR_NONE == ret) {
+ /* Interface already exists */
+ return WMESHD_ERROR_NONE;
+ }
+
+ ret = wmesh_gdbus_create_mesh_interface(service);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to create mesh network");
+ return ret;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_disable_network(wmesh_service *service)
+{
+ int ret;
+ if (NULL == service) {
+ WMESH_LOGE("Invalid parameter");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("[IPC] Disable mesh network");
+
+ ret = wmesh_gdbus_remove_mesh_interface(service);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to disable mesh network");
+ return ret;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_scan(wmesh_service *service)
+{
+ int ret;
+ if (NULL == service) {
+ WMESH_LOGE("Invalid parameter");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("[IPC] Request scan for mesh network");
+
+ ret = wmesh_gdbus_mesh_scan(service);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to request scan for mesh network");
+ return ret;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_specific_scan(wmesh_service *service, gchar *mesh_id, gint channel)
+{
+ int ret;
+ if (NULL == service) {
+ WMESH_LOGE("Invalid parameter");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("[IPC] Request specific scan for mesh network");
+
+ ret = wmesh_gdbus_mesh_specific_scan(service, mesh_id, channel);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to request specific scan for mesh network");
+ return ret;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_cancel_scan(wmesh_service *service)
+{
+ int ret;
+ if (NULL == service) {
+ WMESH_LOGE("Invalid parameter");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("[IPC] Cancel scan for mesh network");
+
+ ret = wmesh_gdbus_mesh_cancel_scan(service);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to cancel scan for mesh network");
+ return ret;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_get_networks(wmesh_service *service)
+{
+ int ret;
+ if (NULL == service) {
+ WMESH_LOGE("Invalid parameter");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("[IPC] Get mesh networks");
+
+ ret = wmesh_gdbus_get_mesh_networks(service);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to get mesh networks !");
+ return ret;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+static int _select_matched_network(GList *scanned_network,
+ const char *mesh_id, int mesh_channel, wmeshd_security_type_e sec,
+ wmesh_scan_result_s **info)
+{
+ int ret = WMESHD_ERROR_NONE;
+ GList *iter = NULL;
+ wmesh_scan_result_s *item = NULL;
+ gboolean found = FALSE;
+
+ wmeshd_check_null_ret_error("scanned_network", scanned_network,
+ WMESHD_ERROR_INVALID_PARAMETER);
+
+ iter = scanned_network;
+ while (iter != NULL) {
+ item = (wmesh_scan_result_s*)iter->data;
+
+ if (g_strcmp0(mesh_id, item->mesh_id) == 0) {
+ if (item->channel == mesh_channel && item->security == sec) {
+ *info = item;
+ found = TRUE;
+ break;
+ }
+ }
+ iter = g_list_next(iter);
+ }
+
+ if (FALSE == found)
+ return WMESHD_ERROR_NO_DATA;
+
+ return ret;
+}
+
+int wmesh_request_get_joined_network(wmesh_service *service)
+{
+ int ret;
+
+ if (NULL == service) {
+ WMESH_LOGE("Invalid parameter");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("[IPC] Get joined mesh network");
+
+ ret = wmesh_gdbus_get_joined_mesh_network(service);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to get joined mesh network");
+ return ret;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_get_connected_peers(wmesh_service *service)
+{
+ int ret;
+
+ if (NULL == service) {
+ WMESH_LOGE("Invalid parameter");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("[IPC] Get connected mesh peers");
+
+ ret = wmesh_gdbus_get_connected_peers(service);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to get connected mesh peers");
+ return ret;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_create_mesh_network(wmesh_service *service, gchar *mesh_id,
+ gint channel, wmeshd_security_type_e sec)
+{
+ int ret;
+
+ if (NULL == service) {
+ WMESH_LOGE("Invalid parameter");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("[IPC] Create a new mesh network");
+
+ ret = wmesh_gdbus_create_network(service, mesh_id, channel, sec);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to create mesh network");
+ return ret;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_connect_mesh_network(wmesh_service *service, gchar *mesh_id,
+ gint channel, wmeshd_security_type_e sec, gchar *passphrase)
+{
+ int ret;
+ wmesh_scan_result_s *info = NULL;
+
+ if (NULL == service) {
+ WMESH_LOGE("Invalid parameter");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("[IPC] Connect mesh network");
+
+ /* Get mesh_id and channel from saved network */
+ ret = _select_matched_network(service->scanned_mesh_network,
+ mesh_id, channel, sec, &info);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to mesh_network_get_first_mesh_network");
+ return ret;
+ }
+
+ /* Set passphrase */
+ if (WMESHD_SECURITY_NONE != sec) {
+ if (NULL != passphrase) {
+ ret = wmesh_gdbus_set_passphrase(service, info, passphrase);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to set passphrase for mesh network");
+ return ret;
+ }
+ } else {
+ WMESH_LOGE("Passphrase is required !");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+ }
+
+ ret = wmesh_gdbus_connect_network(service, info);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to connect mesh network");
+ return ret;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_disconnect_mesh_network(wmesh_service *service,
+ gchar *mesh_id, gint channel, wmeshd_security_type_e sec)
+{
+ int ret;
+ wmesh_scan_result_s *info = NULL;
+
+ if (NULL == service) {
+ WMESH_LOGE("Invalid parameter");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("[IPC] Disconnect mesh network");
+
+ /* Get mesh_id and channel from saved network */
+ ret = _select_matched_network(service->scanned_mesh_network,
+ mesh_id, channel, sec, &info);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to _select_matched_network");
+ return ret;
+ }
+
+ ret = wmesh_gdbus_disconnect_network(service, info);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to disconnect mesh network");
+ return ret;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_request_remove_mesh_network(wmesh_service *service,
+ gchar *mesh_id, gint channel, wmeshd_security_type_e sec)
+{
+ int ret;
+ wmesh_scan_result_s *info = NULL;
+
+ if (NULL == service) {
+ WMESH_LOGE("Invalid parameter");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ WMESH_LOGD("[IPC] Remove mesh network");
+
+ /* Get mesh_id and channel from saved network */
+ ret = _select_matched_network(service->scanned_mesh_network,
+ mesh_id, channel, sec, &info);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to _select_matched_network");
+ return ret;
+ }
+
+ ret = wmesh_gdbus_remove_network(service, info);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to remove mesh network");
+ return ret;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+/* Notifications */
+void wmesh_notify_scan_done()
+{
+ NetWmesh *object = wmeshd_dbus_get_object();
+
+ net_wmesh_emit_scan_done(object);
+}
+
+void wmesh_notify_connection_state(const char* mesh_id, const char* bssid,
+ int channel, wmeshd_security_type_e sec, wmeshd_connection_state_e state)
+{
+ NetWmesh *object = wmeshd_dbus_get_object();
+
+ net_wmesh_emit_connection_state(object, mesh_id, bssid, channel, (int)sec, (int)state);
+}
+
+void wmesh_notify_station_joined(const char* bssid)
+{
+ NetWmesh *object = wmeshd_dbus_get_object();
+
+ net_wmesh_emit_sta_joined(object, bssid);
+}
+
+void wmesh_notify_station_left(const char* bssid)
+{
+ NetWmesh *object = wmeshd_dbus_get_object();
+
+ net_wmesh_emit_sta_left(object, bssid);
+}
--- /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 <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+#include <wifi-manager.h>
+
+#include "wmesh.h"
+#include "wmesh-log.h"
+#include "wmesh-util.h"
+#include "wmesh-gdbus.h"
+#include "wmesh-service.h"
+#include "wmesh-peer-monitor.h"
+#include "wmesh-service-interface.h"
+#include "wmesh-generated-code.h"
+
+#include "wmesh-request.h"
+#include "wmesh-interface.h"
+
+static NetWmesh *meshd_dbus_object;
+static Manager *meshd_activator_dbus_object;
+
+/* global list to care resource handle for each client */
+static GList *meshd_dbus_client_list;
+static GMutex meshd_dbus_client_list_mutex;
+
+typedef struct _meshd_dbus_client_s {
+ gchar *bus_name;
+} meshd_dbus_client_s;
+
+#define CASE_TO_STR(x) case x: return #x;
+
+static const char* wifi_error_to_string(wifi_manager_error_e err)
+{
+ switch (err) {
+ /* CHECK: List all enum values here */
+ CASE_TO_STR(WIFI_MANAGER_ERROR_NONE)
+ CASE_TO_STR(WIFI_MANAGER_ERROR_INVALID_PARAMETER)
+ CASE_TO_STR(WIFI_MANAGER_ERROR_OUT_OF_MEMORY)
+ CASE_TO_STR(WIFI_MANAGER_ERROR_INVALID_OPERATION)
+ CASE_TO_STR(WIFI_MANAGER_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED)
+ CASE_TO_STR(WIFI_MANAGER_ERROR_OPERATION_FAILED)
+ CASE_TO_STR(WIFI_MANAGER_ERROR_NO_CONNECTION)
+ CASE_TO_STR(WIFI_MANAGER_ERROR_NOW_IN_PROGRESS)
+ CASE_TO_STR(WIFI_MANAGER_ERROR_ALREADY_EXISTS)
+ CASE_TO_STR(WIFI_MANAGER_ERROR_OPERATION_ABORTED)
+ CASE_TO_STR(WIFI_MANAGER_ERROR_DHCP_FAILED)
+ CASE_TO_STR(WIFI_MANAGER_ERROR_INVALID_KEY)
+ CASE_TO_STR(WIFI_MANAGER_ERROR_NO_REPLY)
+ CASE_TO_STR(WIFI_MANAGER_ERROR_SECURITY_RESTRICTED)
+ CASE_TO_STR(WIFI_MANAGER_ERROR_ALREADY_INITIALIZED)
+ CASE_TO_STR(WIFI_MANAGER_ERROR_PERMISSION_DENIED)
+ CASE_TO_STR(WIFI_MANAGER_ERROR_NOT_SUPPORTED)
+ default :
+ return "WIFI_MANAGER_ERROR_UNKNOWN";
+ }
+}
+
+NetWmesh* wmeshd_dbus_get_object()
+{
+ return meshd_dbus_object;
+}
+
+int64_t wmeshd_dbus_generate_signal_number()
+{
+ static int64_t i = 0;
+
+ return i++;
+}
+
+static int _wmeshd_dbus_client_list_cleanup(GList *client_list)
+{
+ meshd_dbus_client_s *client;
+
+ wmeshd_check_null_ret_error("client_list", client_list, FALSE);
+
+ client = client_list->data;
+
+ free(client->bus_name);
+ client->bus_name = NULL;
+ free(client);
+ g_list_free(client_list);
+
+ return WMESHD_ERROR_NONE;
+}
+
+static int _wmeshd_dbus_client_list_compare_bus_name(const void *a, const void *b)
+{
+ const meshd_dbus_client_s *client = a;
+
+ return g_strcmp0(client->bus_name, b);
+}
+
+static inline GList* _wmeshd_dbus_client_list_find_client(const gchar *owner)
+{
+ return g_list_find_custom(meshd_dbus_client_list, owner,
+ _wmeshd_dbus_client_list_compare_bus_name);
+}
+
+static void _wmeshd_dbus_name_owner_changed_cb(GDBusConnection *conn,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ int ret;
+ GList *client = NULL;
+ gchar *name, *old_owner, *new_owner;
+
+ NOTUSED(conn);
+ NOTUSED(sender_name);
+ NOTUSED(object_path);
+ NOTUSED(interface_name);
+ NOTUSED(signal_name);
+ NOTUSED(user_data);
+
+ g_variant_get(parameters, "(&s&s&s)", &name, &old_owner, &new_owner);
+
+ if (0 == strlen(new_owner)) {
+ g_mutex_lock(&meshd_dbus_client_list_mutex);
+ client = _wmeshd_dbus_client_list_find_client(old_owner);
+ if (client) { /* found bus name in our bus list */
+ WMESH_LOGD("bus(%s) stopped", old_owner);
+ meshd_dbus_client_list = g_list_remove_link(meshd_dbus_client_list, client);
+ }
+ g_mutex_unlock(&meshd_dbus_client_list_mutex);
+
+ if (client) {
+ ret = _wmeshd_dbus_client_list_cleanup(client);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("_wmeshd_dbus_client_list_cleanup() Fail(%d)", ret);
+ }
+ }
+}
+
+static int _wmeshd_dbus_subscribe_name_owner_changed(GDBusConnection *conn)
+{
+ unsigned int id;
+
+ id = g_dbus_connection_signal_subscribe(conn,
+ "org.freedesktop.DBus", /* bus name */
+ "org.freedesktop.DBus", /* interface */
+ "NameOwnerChanged", /* member */
+ "/org/freedesktop/DBus", /* path */
+ NULL, /* arg0 */
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ _wmeshd_dbus_name_owner_changed_cb,
+ NULL,
+ NULL);
+ if (0 == id) {
+ WMESH_LOGE("g_dbus_connection_signal_subscribe() Fail");
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+static gboolean _wmeshd_dbus_handle_enable(Manager *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmesh_interface_s *info = service->interface_info;
+
+ wifi_manager_h wifi_handle = NULL;
+ bool wifi_activated = false;
+
+ /* Initialize Wi-Fi driver */
+ ret = wifi_manager_initialize(&wifi_handle);
+ if (WIFI_MANAGER_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to get wifi manager handle ! [%s(%X)]",
+ wifi_error_to_string(ret), ret);
+
+ wifi_manager_is_activated(wifi_handle, &wifi_activated);
+ if (false == wifi_activated) {
+ ret = wifi_manager_activate(wifi_handle, NULL, NULL);
+ if (WIFI_MANAGER_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to activate wifi ! [%s(%X)]",
+ wifi_error_to_string(ret), ret);
+ }
+ wifi_manager_deinitialize(wifi_handle);
+
+ if (service->mesh_activated) {
+ /* Already activated */
+ manager_complete_enable(object, invocation, WMESHD_ERROR_NONE);
+ goto FINISH;
+ }
+
+ /* Do API response first */
+ manager_complete_enable(object, invocation, ret);
+ service->mesh_activated = TRUE;
+
+ wmeshd_check_null_ret_error("info", info, FALSE);
+
+ /* Register event handler first */
+ ret = wmesh_request_register_event_handler();
+ if (WMESHD_ERROR_IN_PROGRESS == ret) {
+ WMESH_LOGE("Currently set netlink event handler !! [%d]", ret);
+ ret = WMESHD_ERROR_NONE;
+ } else if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to register mesh event handler !! [%d]", ret);
+ }
+
+ ret = wmesh_interface_initialize(service->interface_info);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to wmesh_interface_initialize [%d]", ret);
+ goto FINISH;
+ }
+
+FINISH:
+ net_wmesh_emit_mesh_enabled(wmeshd_dbus_get_object(), ret);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_disable(Manager *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmesh_interface_s *info = service->interface_info;
+
+ wmeshd_check_null_ret_error("info", info, FALSE);
+
+ /* Make response first */
+ manager_complete_disable(object, invocation, ret);
+
+ ret = wmesh_request_unregister_event_handler();
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to unregister mesh event handler !! [%d]", ret);
+
+ /* Terminate daemon */
+ wmeshd_service_exit(service);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_scan(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmesh_interface_s *info = service->interface_info;
+
+ wmeshd_check_null_ret_error("info", info, FALSE);
+
+ ret = wmesh_request_scan(service);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to wmesh_request_scan !");
+
+ net_wmesh_complete_scan(object, invocation, ret);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_specific_scan(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gchar *mesh_id,
+ gint channel,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmesh_interface_s *info = service->interface_info;
+
+ wmeshd_check_null_ret_error("info", info, FALSE);
+
+ ret = wmesh_request_specific_scan(service, mesh_id, channel);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to wmesh_request_specific_scan !");
+
+ net_wmesh_complete_specific_scan(object, invocation, ret);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_cancel_scan(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+
+ ret = wmesh_request_cancel_scan(service);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to wmesh_request_cancel_scan");
+
+ net_wmesh_complete_cancel_scan(object, invocation, ret);
+
+ return TRUE;
+}
+
+static void _on_scan_result_destroy(gpointer data)
+{
+ wmesh_scan_result_s *scan_item = (wmesh_scan_result_s *)data;
+
+ if (scan_item) {
+ g_free(scan_item->mesh_id);
+ g_free(scan_item->bssid);
+ g_free(scan_item->object_path);
+ }
+ g_free(scan_item);
+}
+
+static void _on_peer_info_destroy(gpointer data)
+{
+ wmesh_peer_info_s *peer = (wmesh_peer_info_s *)data;
+ if (peer)
+ g_free(peer->address);
+ g_free(peer);
+}
+
+static void _on_station_list_destroy(gpointer data)
+{
+ wmesh_station_info_s *info = (wmesh_station_info_s*)data;
+
+ if (info) {
+ g_free(info->bssid);
+ g_free(info);
+ }
+}
+
+static void _on_mpath_list_destroy(gpointer data)
+{
+ wmesh_mpath_info_s *info = (wmesh_mpath_info_s*)data;
+
+ if (info) {
+ g_free(info->dest_addr);
+ g_free(info->next_hop);
+ g_free(info->interface);
+ g_free(info);
+ }
+}
+
+static gboolean _wmeshd_dbus_handle_get_found_mesh_networks(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+
+ GVariantBuilder builder;
+ GVariant* networks;
+ GList *iter = NULL;
+ wmesh_scan_result_s *scan_item = NULL;
+
+ WMESH_LOGD("Request to get scanned mesh network list");
+
+ ret = wmesh_request_get_networks(service);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to wmesh_request_get_networks");
+
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
+
+ /* scanned_mesh_network would be filled above request */
+ iter = service->scanned_mesh_network;
+ while (iter != NULL) {
+ scan_item = (wmesh_scan_result_s*)iter->data;
+
+ g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add(&builder, "{sv}", "mesh_id",
+ g_variant_new_string(scan_item->mesh_id));
+ g_variant_builder_add(&builder, "{sv}", "bssid",
+ g_variant_new_string(scan_item->bssid));
+ g_variant_builder_add(&builder, "{sv}", "rssi",
+ g_variant_new_int32(scan_item->rssi));
+ g_variant_builder_add(&builder, "{sv}", "channel",
+ g_variant_new_uint32(scan_item->channel));
+ g_variant_builder_add(&builder, "{sv}", "data_rate",
+ g_variant_new_int32(scan_item->data_rate));
+ g_variant_builder_add(&builder, "{sv}", "security",
+ g_variant_new_uint32((int)scan_item->security));
+ g_variant_builder_add(&builder, "{sv}", "state",
+ g_variant_new_uint32(scan_item->state));
+ g_variant_builder_close(&builder);
+
+ iter = g_list_next(iter);
+ }
+
+ networks = g_variant_builder_end(&builder);
+
+ net_wmesh_complete_get_found_mesh_networks(object, invocation, networks, ret);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_enable_mesh(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+
+ /* It handles creating virtual network and bridge */
+ ret = wmesh_request_enable_network(service);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to wmesh_request_enable_network [%d]", ret);
+
+ wmesh_start_monitor_service(service);
+
+ net_wmesh_complete_enable_mesh(object, invocation, ret);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_disable_mesh(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmesh_interface_s *info = service->interface_info;
+
+ wmeshd_check_null_ret_error("info", info, FALSE);
+
+ if (FALSE == service->mesh_activated) {
+ WMESH_LOGD("Mesh network is not activated yet");
+ ret = WMESHD_ERROR_OPERATION_FAILED;
+ net_wmesh_complete_disable_mesh(object, invocation, ret);
+ return TRUE;
+ }
+
+ ret = wmesh_request_disable_network(service);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to disable mesh network !");
+
+ /* Stop Mesh Node Monitoring Service */
+ wmesh_stop_monitor_service(service);
+ /* Make response */
+ net_wmesh_complete_disable_mesh(object, invocation, ret);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_is_joined(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ gboolean state = FALSE;
+ wmesh_service *service = (wmesh_service *)user_data;
+
+ ret = wmesh_request_get_joined_network(service);
+ if (WMESHD_ERROR_NONE == ret) {
+ if (service->joined_network)
+ state = TRUE;
+ }
+
+ net_wmesh_complete_is_joined(object, invocation, state, ret);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_get_joined_mesh_network(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmesh_network_info_s *joined = NULL;
+
+ ret = wmesh_request_get_joined_network(service);
+ if (WMESHD_ERROR_NONE == ret) {
+ joined = service->joined_network;
+ if (joined) {
+ net_wmesh_complete_get_joined_mesh_network(object, invocation,
+ joined->mesh_id, joined->bssid,
+ joined->channel, (int)joined->security,
+ joined->state, ret);
+ } else {
+ net_wmesh_complete_get_joined_mesh_network(object, invocation,
+ "", "", 0, 0, 0, WMESHD_ERROR_NO_DATA);
+ }
+ } else {
+ net_wmesh_complete_get_joined_mesh_network(object, invocation,
+ "", "", 0, 0, 0, ret);
+ }
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_get_connected_peers(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+
+ GVariantBuilder builder;
+ GVariant* peer_list;
+ GList *iter = NULL;
+ wmesh_peer_info_s *peer = NULL;
+
+ WMESH_LOGD("Request to get connected peers");
+
+ ret = wmesh_request_get_connected_peers(service);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to wmesh_request_get_connected_peers");
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
+
+ iter = service->connected_mesh_peers;
+ while (iter != NULL) {
+ peer = (wmesh_peer_info_s*)iter->data;
+
+ g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add(&builder, "{sv}", "Address",
+ g_variant_new_string(peer->address));
+ g_variant_builder_close(&builder);
+
+ iter = g_list_next(iter);
+ }
+
+ peer_list = g_variant_builder_end(&builder);
+
+ net_wmesh_complete_get_connected_peers(object, invocation, peer_list, ret);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_set_gate(NetWmesh *object,
+ GDBusMethodInvocation *invocation, gint16 gate_announce, guint hwmp_root_mode,
+ gboolean stp, gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmesh_interface_s *info = service->interface_info;
+
+ WMESH_LOGD("gate_announce = %d", gate_announce);
+ WMESH_LOGD("HWMP_Root_Mode = %d", hwmp_root_mode);
+ WMESH_LOGD("STP = %d", stp);
+
+ info->gate_announce = gate_announce;
+ info->hwmp_root_mode = hwmp_root_mode;
+ info->stp = stp;
+
+ /* Set STP and gate_announce for connmand */
+ ret = wmesh_gdbus_set_mesh_gate(service);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to wmesh_gdbus_set_mesh_gate [%d]", ret);
+
+ /* Set STP and gate_announce right now */
+ ret = wmesh_request_set_mesh_gate(info->bridge_interface,
+ info->mesh_interface, info->external_interface);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to wmesh_gdbus_set_mesh_gate [%d]", ret);
+
+
+ net_wmesh_complete_set_gate(object, invocation, ret);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_unset_gate(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmesh_interface_s *info = service->interface_info;
+
+ info->gate_announce = 0;
+ info->hwmp_root_mode = 0;
+ info->stp = 0;
+
+ /* Set STP and gate_announce for connmand */
+ ret = wmesh_gdbus_set_mesh_gate(service);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to wmesh_gdbus_set_mesh_gate [%d]", ret);
+
+ /* Unset STP and Gate Annouce right now */
+ ret = wmesh_request_unset_mesh_gate(info->bridge_interface,
+ info->mesh_interface, info->external_interface);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to wmesh_request_unset_mesh_gate [%d]", ret);
+
+ net_wmesh_complete_unset_gate(object, invocation, ret);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_set_softap(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gchar *ssid, gchar *passphrase,
+ gchar *mode, gint channel, gint visibility, gint max_sta,
+ gint security, gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmesh_interface_s *info = service->interface_info;
+
+ WMESH_LOGD("SSID : %s", ssid);
+ WMESH_LOGD("mode : %s", mode);
+ WMESH_LOGD("channel : %d", channel);
+ WMESH_LOGD("visibility: %d", visibility);
+ WMESH_LOGD("max_sta : %d", max_sta);
+ WMESH_LOGD("security : %d", security);
+
+ /* Save softAP information */
+ ret = wmesh_request_set_softap_config(info->softap_interface,
+ ssid, mode, channel, visibility, max_sta,
+ security, passphrase);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to wmesh_request_set_softap_config [%d]", ret);
+
+ net_wmesh_complete_set_softap(object, invocation, ret);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_enable_softap(NetWmesh *object,
+ GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmesh_interface_s *info = service->interface_info;
+
+ /* Check softAP interface and execute it */
+ ret = wmesh_request_enable_softap(info->bridge_interface, info->softap_interface);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to wmesh_request_enable_softap [%d]", ret);
+
+ net_wmesh_complete_enable_softap(object, invocation, ret);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_disable_softap(NetWmesh *object,
+ GDBusMethodInvocation *invocation, gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmesh_interface_s *info = service->interface_info;
+
+ /* Destroy softAP */
+ ret = wmesh_request_disable_softap(info->bridge_interface, info->softap_interface);
+ if (WMESHD_ERROR_NONE != ret)
+ WMESH_LOGE("Failed to wmesh_request_disable_softap [%d]", ret);
+
+ net_wmesh_complete_disable_softap(object, invocation, ret);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_create_mesh_network(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gchar *mesh_id, gint channel, gint security,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmeshd_security_type_e sec = (1 == security) ? WMESHD_SECURITY_SAE : WMESHD_SECURITY_NONE;
+
+ ret = wmesh_request_create_mesh_network(service, mesh_id, channel, sec);
+
+ net_wmesh_complete_create_mesh_network(object, invocation, ret);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_connect_mesh_network(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gchar *mesh_id, gint channel, gint security, gchar *passphrase,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmeshd_security_type_e sec = (1 == security) ? WMESHD_SECURITY_SAE : WMESHD_SECURITY_NONE;
+
+ ret = wmesh_request_connect_mesh_network(service, mesh_id, channel, sec, passphrase);
+
+ net_wmesh_complete_connect_mesh_network(object, invocation, ret);
+
+ return TRUE;
+}
+static gboolean _wmeshd_dbus_handle_disconnect_mesh_network(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gchar *mesh_id, gint channel, gint security,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmeshd_security_type_e sec = (1 == security) ? WMESHD_SECURITY_SAE : WMESHD_SECURITY_NONE;
+
+ ret = wmesh_request_disconnect_mesh_network(service, mesh_id, channel, sec);
+
+ net_wmesh_complete_disconnect_mesh_network(object, invocation, ret);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_forget_mesh_network(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gchar *mesh_id, gint channel, gint security,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmeshd_security_type_e sec = (1 == security) ? WMESHD_SECURITY_SAE : WMESHD_SECURITY_NONE;
+
+ ret = wmesh_request_remove_mesh_network(service, mesh_id, channel, sec);
+
+ net_wmesh_complete_forget_mesh_network(object, invocation, ret);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_set_interfaces(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gchar *mesh, gchar *gate, gchar *softap,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmesh_interface_s *info = service->interface_info;
+
+ g_free(info->mesh_interface);
+ info->mesh_interface = g_strdup(mesh);
+
+ g_free(info->external_interface);
+ info->external_interface = g_strdup(gate);
+
+ g_free(info->softap_interface);
+ info->softap_interface = g_strdup(softap);
+
+ WMESH_LOGD("Interface configuration for mesh network :");
+ WMESH_LOGD(" Base : [%s]", info->base_interface);
+ WMESH_LOGD(" Mesh : [%s]", info->mesh_interface);
+ WMESH_LOGD(" Bridge : [%s]", info->bridge_interface);
+ WMESH_LOGD(" SoftAP : [%s]", info->softap_interface);
+ WMESH_LOGD(" External: [%s]", info->external_interface);
+
+ net_wmesh_complete_set_interfaces(object, invocation, ret);
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_get_station_info(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ GVariantBuilder builder;
+ GVariant* station;
+ GList *iter = NULL;
+
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmesh_interface_s *info = service->interface_info;
+
+ /* Clear mesh station list */
+ g_list_free_full(service->station_list, _on_station_list_destroy);
+ service->station_list = NULL;
+
+ ret = wmesh_request_get_station_info(
+ info->mesh_interface, &service->station_list);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to wmesh_request_get_station_info");
+
+ g_dbus_method_invocation_return_error(invocation,
+ G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Request Failed");
+ } else {
+ /*
+ * sh-3.2# iw mesh0 station dump
+ * Station 7c:dd:90:62:37:cf (on mesh0)
+ * inactive time: 1685 ms
+ * rx bytes: 34174
+ * rx packets: 1181
+ * tx bytes: 6877
+ * tx packets: 76
+ * tx retries: 0
+ * tx failed: 0
+ * beacon loss: 0
+ * signal: -64 dBm
+ * signal avg: -63 dBm
+ * tx bitrate: 54.0 MBit/s
+ * rx bitrate: 5.5 MBit/s
+ * mesh llid: 51731
+ * mesh plid: 35432
+ * mesh plink: ESTAB
+ * mesh local PS mode: ACTIVE
+ * mesh peer PS mode: ACTIVE
+ * mesh non-peer PS mode: ACTIVE
+ * authorized: yes
+ * authenticated: yes
+ * associated: yes
+ * preamble: long
+ * WMM/WME: yes
+ * MFP: no
+ * TDLS peer: no
+ * DTIM period: 0
+ * beacon interval:1000
+ * short slot time:yes
+ * connected time: 256 seconds
+ */
+ /* Get station information and make variant data */
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
+
+ iter = service->station_list;
+ while (iter != NULL) {
+ wmesh_station_info_s *item = (wmesh_station_info_s*)iter->data;
+
+ g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add(&builder, "{sv}", "bssid",
+ g_variant_new_string(item->bssid));
+ g_variant_builder_add(&builder, "{sv}", "inactive_time",
+ g_variant_new_uint32(item->inactive_time));
+ g_variant_builder_add(&builder, "{sv}", "rx_bytes",
+ g_variant_new_uint64(item->rx_bytes));
+ g_variant_builder_add(&builder, "{sv}", "rx_packets",
+ g_variant_new_uint32(item->rx_packets));
+ g_variant_builder_add(&builder, "{sv}", "tx_bytes",
+ g_variant_new_uint64(item->tx_bytes));
+ g_variant_builder_add(&builder, "{sv}", "tx_packets",
+ g_variant_new_uint32(item->tx_packets));
+ g_variant_builder_add(&builder, "{sv}", "tx_retries",
+ g_variant_new_uint32(item->tx_retries));
+ g_variant_builder_add(&builder, "{sv}", "tx_failed",
+ g_variant_new_uint32(item->tx_failed));
+ g_variant_builder_add(&builder, "{sv}", "beacon_loss",
+ g_variant_new_uint32(item->beacon_loss));
+ g_variant_builder_add(&builder, "{sv}", "beacon_rx",
+ g_variant_new_uint64(item->beacon_rx));
+ g_variant_builder_add(&builder, "{sv}", "rx_drop_misc",
+ g_variant_new_uint64(item->rx_drop_misc));
+ g_variant_builder_add(&builder, "{sv}", "signal",
+ g_variant_new_int32(item->rssi));
+ g_variant_builder_add(&builder, "{sv}", "signal_avg",
+ g_variant_new_int32(item->rssi_avg));
+ g_variant_builder_add(&builder, "{sv}", "tx_bitrate",
+ g_variant_new_uint32(item->tx_bitrate)); /* 10 times */
+ g_variant_builder_add(&builder, "{sv}", "rx_bitrate",
+ g_variant_new_uint32(item->rx_bitrate)); /* 10 times */
+ g_variant_builder_add(&builder, "{sv}", "mesh_llid",
+ g_variant_new_uint16(item->llid));
+ g_variant_builder_add(&builder, "{sv}", "mesh_plid",
+ g_variant_new_uint16(item->plid));
+ g_variant_builder_add(&builder, "{sv}", "mesh_plink",
+ g_variant_new_byte(item->mesh_plink)); /* 0 : DISCON, 1 : ESTAB */
+ g_variant_builder_add(&builder, "{sv}", "local_ps_mode",
+ g_variant_new_uint32(item->local_ps_mode)); /* 0 : INACTIVE, 1 : ACTIVE */
+ g_variant_builder_add(&builder, "{sv}", "peer_ps_mode",
+ g_variant_new_uint32(item->peer_ps_mode)); /* 0 : INACTIVE, 1 : ACTIVE */
+ g_variant_builder_add(&builder, "{sv}", "non_peer_ps_mode",
+ g_variant_new_uint32(item->non_peer_ps_mode)); /* 0 : INACTIVE, 1 : ACTIVE */
+ g_variant_builder_add(&builder, "{sv}", "authorized",
+ g_variant_new_boolean(item->authorized));
+ g_variant_builder_add(&builder, "{sv}", "associated",
+ g_variant_new_boolean(item->associated));
+ g_variant_builder_add(&builder, "{sv}", "preamble",
+ g_variant_new_boolean(item->preamble));
+ g_variant_builder_add(&builder, "{sv}", "WMM_WME",
+ g_variant_new_boolean(item->wme));
+ g_variant_builder_add(&builder, "{sv}", "MFP",
+ g_variant_new_boolean(item->mfp));
+ g_variant_builder_add(&builder, "{sv}", "TDLS_peer",
+ g_variant_new_boolean(item->tdls_peer));
+ g_variant_builder_add(&builder, "{sv}", "DTIM_period",
+ g_variant_new_byte(item->dtim_period));
+ g_variant_builder_add(&builder, "{sv}", "beacon_interval",
+ g_variant_new_uint16(item->beacon_interval));
+ g_variant_builder_add(&builder, "{sv}", "short_slot_time",
+ g_variant_new_boolean(item->short_slot_time));
+ g_variant_builder_add(&builder, "{sv}", "connected_time",
+ g_variant_new_uint32(item->connected_time));
+ g_variant_builder_close(&builder);
+
+ iter = g_list_next(iter);
+ }
+
+ station = g_variant_builder_end(&builder);
+ net_wmesh_complete_get_station_info(object, invocation, station, ret);
+
+ g_object_unref(station);
+ }
+
+ return TRUE;
+}
+
+static gboolean _wmeshd_dbus_handle_get_mpath_info(NetWmesh *object,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ int ret = WMESHD_ERROR_NONE;
+ GVariantBuilder builder;
+ GVariant* mpath_data;
+ GList *iter = NULL;
+
+ wmesh_service *service = (wmesh_service *)user_data;
+ wmesh_interface_s *info = service->interface_info;
+
+ /* Clear mesh path list */
+ g_list_free_full(service->mpath_list, _on_mpath_list_destroy);
+ service->mpath_list = NULL;
+
+ ret = wmesh_request_get_mpath_info(
+ info->mesh_interface, &service->mpath_list);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("Failed to wmesh_request_get_mpath_info");
+
+ g_dbus_method_invocation_return_error(invocation,
+ G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Request Failed");
+ } else {
+ /*
+ * Example) sh-3.2# iw mesh0 mpath dump
+ * DEST ADDR NEXT HOP IFACE SN METRIC QLEN EXPTIME DTIM DRET FLAGS
+ * 7c:dd:90:62:37:cf 7c:dd:90:62:37:cf mesh0 221 152 0 10 100 0 0x5
+ */
+ /* Get mesh path information and make variant data */
+ g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
+
+ iter = service->mpath_list;
+ while (iter != NULL) {
+ wmesh_mpath_info_s *item = (wmesh_mpath_info_s*)iter->data;
+
+ g_variant_builder_open(&builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add(&builder, "{sv}", "DEST_ADDR",
+ g_variant_new_string(item->dest_addr));
+ g_variant_builder_add(&builder, "{sv}", "NEXT_HOP",
+ g_variant_new_string(item->next_hop));
+ g_variant_builder_add(&builder, "{sv}", "IFACE",
+ g_variant_new_string(item->interface));
+ g_variant_builder_add(&builder, "{sv}", "SN",
+ g_variant_new_uint32(item->sn));
+ g_variant_builder_add(&builder, "{sv}", "METRIC",
+ g_variant_new_uint32(item->metric));
+ g_variant_builder_add(&builder, "{sv}", "QLEN",
+ g_variant_new_uint32(item->qlen));
+ g_variant_builder_add(&builder, "{sv}", "EXPTIME",
+ g_variant_new_uint32(item->exptime));
+ g_variant_builder_add(&builder, "{sv}", "DTIM",
+ g_variant_new_uint32(item->discovery_timeout));
+ g_variant_builder_add(&builder, "{sv}", "DRET",
+ g_variant_new_byte(item->discovery_retries));
+ g_variant_builder_add(&builder, "{sv}", "FLAGS",
+ g_variant_new_byte(item->flags));
+ g_variant_builder_close(&builder);
+
+ iter = g_list_next(iter);
+ }
+
+ mpath_data = g_variant_builder_end(&builder);
+ net_wmesh_complete_get_mpath_info(object, invocation, mpath_data, ret);
+
+ g_object_unref(mpath_data);
+ }
+
+ return TRUE;
+}
+
+static void _wmeshd_dbus_on_activator_bus_acquired(GDBusConnection *conn,
+ const gchar *name, gpointer user_data)
+{
+ gboolean ret;
+ GError *error = NULL;
+ wmesh_service *service = (wmesh_service *)user_data;
+
+ NOTUSED(name);
+
+ meshd_activator_dbus_object = manager_skeleton_new();
+ if (NULL == meshd_activator_dbus_object) {
+ WMESH_LOGE("manager_skeleton_new() Fail");
+ return;
+ }
+
+ g_signal_connect(meshd_activator_dbus_object, "handle-enable",
+ G_CALLBACK(_wmeshd_dbus_handle_enable), service);
+ g_signal_connect(meshd_activator_dbus_object, "handle-disable",
+ G_CALLBACK(_wmeshd_dbus_handle_disable), service);
+
+ ret = g_dbus_interface_skeleton_export(
+ G_DBUS_INTERFACE_SKELETON(meshd_activator_dbus_object),
+ conn, WMESH_DBUS_MANAGER_OBJPATH, &error);
+ if (FALSE == ret) {
+ WMESH_LOGE("g_dbus_interface_skeleton_export() Fail(%s)", error->message);
+ g_error_free(error);
+ }
+}
+
+static void _wmeshd_dbus_on_bus_acquired(GDBusConnection *conn, const gchar *name,
+ gpointer user_data)
+{
+ gboolean ret;
+ GError *error = NULL;
+ wmesh_service *service = (wmesh_service *)user_data;
+
+ NOTUSED(name);
+
+ meshd_dbus_object = net_wmesh_skeleton_new();
+ if (NULL == meshd_dbus_object) {
+ WMESH_LOGE("net_wmesh_skeleton_new() Fail");
+ return;
+ }
+
+ g_signal_connect(meshd_dbus_object, "handle-scan",
+ G_CALLBACK(_wmeshd_dbus_handle_scan), service);
+ g_signal_connect(meshd_dbus_object, "handle-specific-scan",
+ G_CALLBACK(_wmeshd_dbus_handle_specific_scan), service);
+ g_signal_connect(meshd_dbus_object, "handle-cancel-scan",
+ G_CALLBACK(_wmeshd_dbus_handle_cancel_scan), service);
+ g_signal_connect(meshd_dbus_object, "handle-get-found-mesh-networks",
+ G_CALLBACK(_wmeshd_dbus_handle_get_found_mesh_networks), service);
+ g_signal_connect(meshd_dbus_object, "handle-enable-mesh",
+ G_CALLBACK(_wmeshd_dbus_handle_enable_mesh), service);
+ g_signal_connect(meshd_dbus_object, "handle-disable-mesh",
+ G_CALLBACK(_wmeshd_dbus_handle_disable_mesh), service);
+ g_signal_connect(meshd_dbus_object, "handle-is-joined",
+ G_CALLBACK(_wmeshd_dbus_handle_is_joined), service);
+ g_signal_connect(meshd_dbus_object, "handle-get-joined-mesh-network",
+ G_CALLBACK(_wmeshd_dbus_handle_get_joined_mesh_network), service);
+ g_signal_connect(meshd_dbus_object, "handle-get-connected-peers",
+ G_CALLBACK(_wmeshd_dbus_handle_get_connected_peers), service);
+ g_signal_connect(meshd_dbus_object, "handle-set-gate",
+ G_CALLBACK(_wmeshd_dbus_handle_set_gate), service);
+ g_signal_connect(meshd_dbus_object, "handle-unset-gate",
+ G_CALLBACK(_wmeshd_dbus_handle_unset_gate), service);
+ g_signal_connect(meshd_dbus_object, "handle-set-softap",
+ G_CALLBACK(_wmeshd_dbus_handle_set_softap), service);
+ g_signal_connect(meshd_dbus_object, "handle-enable-softap",
+ G_CALLBACK(_wmeshd_dbus_handle_enable_softap), service);
+ g_signal_connect(meshd_dbus_object, "handle-disable-softap",
+ G_CALLBACK(_wmeshd_dbus_handle_disable_softap), service);
+ g_signal_connect(meshd_dbus_object, "handle-create-mesh-network",
+ G_CALLBACK(_wmeshd_dbus_handle_create_mesh_network), service);
+ g_signal_connect(meshd_dbus_object, "handle-connect-mesh-network",
+ G_CALLBACK(_wmeshd_dbus_handle_connect_mesh_network), service);
+ g_signal_connect(meshd_dbus_object, "handle-disconnect-mesh-network",
+ G_CALLBACK(_wmeshd_dbus_handle_disconnect_mesh_network), service);
+ g_signal_connect(meshd_dbus_object, "handle-forget-mesh-network",
+ G_CALLBACK(_wmeshd_dbus_handle_forget_mesh_network), service);
+ g_signal_connect(meshd_dbus_object, "handle-set-interfaces",
+ G_CALLBACK(_wmeshd_dbus_handle_set_interfaces), service);
+ g_signal_connect(meshd_dbus_object, "handle-get-station-info",
+ G_CALLBACK(_wmeshd_dbus_handle_get_station_info), service);
+ g_signal_connect(meshd_dbus_object, "handle-get-mpath-info",
+ G_CALLBACK(_wmeshd_dbus_handle_get_mpath_info), service);
+
+ ret = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(meshd_dbus_object),
+ conn, WMESH_DBUS_OBJPATH, &error);
+ if (FALSE == ret) {
+ WMESH_LOGE("g_dbus_interface_skeleton_export() Fail(%s)", error->message);
+ g_error_free(error);
+ }
+
+ ret = _wmeshd_dbus_subscribe_name_owner_changed(conn);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("_wmeshd_dbus_subscribe_name_owner_changed() Fail(%d)", ret);
+ return;
+ }
+}
+
+static void _wmeshd_dbus_on_name_lost(GDBusConnection *conn, const gchar *name,
+ gpointer user_data)
+{
+ NOTUSED(conn);
+ NOTUSED(user_data);
+
+ WMESH_LOGD("Lost the name %s", name);
+}
+
+static void _wmeshd_dbus_on_name_acquired(GDBusConnection *conn, const gchar *name,
+ gpointer user_data)
+{
+ NOTUSED(conn);
+ NOTUSED(user_data);
+
+ WMESH_LOGD("Acquired the name %s", name);
+}
+
+static gboolean _wmeshd_dbus_interface_init(wmesh_service *service)
+{
+ guint id;
+ guint activation_dbus_id;
+ wmeshd_check_null_ret_error("service", service, FALSE);
+
+ id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
+ WMESH_DBUS_INTERFACE,
+ G_BUS_NAME_OWNER_FLAGS_REPLACE,
+ _wmeshd_dbus_on_bus_acquired,
+ _wmeshd_dbus_on_name_acquired,
+ _wmeshd_dbus_on_name_lost,
+ service,
+ NULL);
+ if (0 == id) {
+ WMESH_LOGE("g_bus_own_name() Fail");
+ return FALSE;
+ }
+
+ /* Get D-Bus owner to activate mesh service daemon */
+ activation_dbus_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
+ WMESH_DBUS_INTERFACE".manager",
+ G_BUS_NAME_OWNER_FLAGS_REPLACE,
+ _wmeshd_dbus_on_activator_bus_acquired,
+ NULL,
+ NULL,
+ service,
+ NULL);
+
+ service->dbus_id = id;
+ service->activation_dbus_id = activation_dbus_id;
+ service->interface_info = g_new0(wmesh_interface_s, 1);
+ service->scanned_mesh_network = NULL;
+
+ /* Initialize DBus sendor logic */
+ wmeshd_dbus_start(service);
+
+ return TRUE;
+}
+
+static void _wmeshd_dbus_deinit(wmesh_service *service)
+{
+ wmesh_interface_s *info = NULL;
+ wmeshd_check_null_ret("service", service);
+
+ /* De-Initialize DBus sendor logic */
+ wmeshd_dbus_stop(service);
+
+ g_bus_unown_name(service->dbus_id);
+ g_bus_unown_name(service->activation_dbus_id);
+
+ info = service->interface_info;
+ wmeshd_check_null_ret("info", info);
+ if (info->bridge_interface)
+ g_free(info->bridge_interface);
+ if (info->base_interface)
+ g_free(info->base_interface);
+ if (info->mesh_interface)
+ g_free(info->mesh_interface);
+ if (info->softap_interface)
+ g_free(info->softap_interface);
+ if (info->external_interface)
+ g_free(info->external_interface);
+
+ if (service->joined_network) {
+ g_free(service->joined_network->mesh_id);
+ g_free(service->joined_network->bssid);
+ g_free(service->joined_network);
+ service->joined_network = NULL;
+ }
+
+ /* Clear scan list */
+ if (service->scanned_mesh_network)
+ g_list_free_full(service->scanned_mesh_network, _on_scan_result_destroy);
+ service->scanned_mesh_network = NULL;
+
+ /* Clear connected peers list */
+ if (service->connected_mesh_peers)
+ g_list_free_full(service->connected_mesh_peers, _on_peer_info_destroy);
+ service->connected_mesh_peers = NULL;
+
+ /* Clear mesh path list */
+ if (service->mpath_list)
+ g_list_free_full(service->mpath_list, _on_mpath_list_destroy);
+ service->mpath_list = NULL;
+
+ /* Clear mesh station list */
+ if (service->station_list)
+ g_list_free_full(service->station_list, _on_station_list_destroy);
+ service->station_list = NULL;
+
+ g_free(service->interface_info);
+ service->interface_info = NULL;
+}
+
+/**< Mesh service interface initialization */
+gboolean wmeshd_service_interface_init(wmesh_service *service)
+{
+ guint ret;
+ wmeshd_check_null_ret_error("service", service, FALSE);
+
+ /* Initialize dbus interface */
+ ret = _wmeshd_dbus_interface_init(service);
+ if (FALSE == ret) {
+ WMESH_LOGE("_wmeshd_dbus_interface_init failed!!!");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**< Mesh service interface de-initialization */
+void wmeshd_service_interface_deinit(wmesh_service *service)
+{
+ wmeshd_check_null_ret("service", service);
+
+ /* De-initialize dbus interface */
+ _wmeshd_dbus_deinit(service);
+}
--- /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 <glib.h>
+
+#include "wmesh.h"
+#include "wmesh-log.h"
+#include "wmesh-util.h"
+#include "wmesh-service.h"
+
+wmesh_service *wmeshd_service_new()
+{
+ wmesh_service *service;
+
+ service = g_malloc0(sizeof(struct _wmesh_service));
+
+ /* Create g-main loop */
+ service->main_loop = g_main_loop_new(NULL, FALSE);
+ if (G_UNLIKELY(NULL == service->main_loop)) {
+ WMESH_LOGE("g-main loop creation failed!!!");
+ g_free(service);
+ return NULL;
+ }
+
+ return service;
+}
+
+void wmeshd_service_free(wmesh_service *service)
+{
+ wmeshd_check_null_ret("service", service);
+
+ /* Unref 'g-main loop' */
+ if (service->main_loop)
+ g_main_loop_unref(service->main_loop);
+
+ g_free(service);
+}
+
+gboolean wmeshd_service_run(wmesh_service *service)
+{
+ wmeshd_check_null_ret_error("service", service, FALSE);
+ wmeshd_check_null_ret_error("service->main_loop", service->main_loop, FALSE);
+
+ g_main_loop_run(service->main_loop);
+
+ return TRUE;
+}
+
+gboolean wmeshd_service_exit(wmesh_service *service)
+{
+ wmeshd_check_null_ret_error("service", service, FALSE);
+ wmeshd_check_null_ret_error("service->main_loop", service->main_loop, FALSE);
+
+ g_main_loop_quit(service->main_loop);
+
+ return TRUE;
+}
--- /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 <glib.h>
+#include <tzplatform_config.h>
+#include <openssl/evp.h>
+#include <openssl/sha.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "wmesh.h"
+#include "wmesh-log.h"
+#include "wmesh-util.h"
+#include "wmesh-service.h"
+#include "wmesh-softap.h"
+
+#define MOBILE_AP_WIFI_KEY_MAX_LEN 64 /**< Maximum length of wifi hash key */
+
+#define HOSTAPD_VENDOR_ELEMENTS_WIFI_AP "DD050016321000" /* Specific application mode AP (e.g. GroupPlay) */
+#define HOSTAPD_CONF "interface=%s\n" \
+ "driver=nl80211\n" \
+ "ctrl_interface=%s\n" \
+ "ssid=%s\n" \
+ "channel=%d\n" \
+ "ignore_broadcast_ssid=%d\n" \
+ "hw_mode=%s\n" \
+ "max_num_sta=%d\n" \
+ "macaddr_acl=%d\n" \
+ "accept_mac_file=%s\n" \
+ "deny_mac_file=%s\n" \
+ "ieee80211n=1\n"
+#define HOSTAPD_CONF_LEN 1024
+#define HOSTAPD_BIN "/usr/sbin/hostapd"
+#define HOSTAPD_DEBUG_FILE "/var/log/mesh_hostapd.log"
+#define HOSTAPD_ENTROPY_FILE tzplatform_mkpath(TZ_SYS_VAR, "/lib/misc/hostapd.bin")
+#define HOSTAPD_MESH_CONF_FILE tzplatform_mkpath(TZ_SYS_VAR, "/lib/mesh/mesh_hostapd.conf")
+#define HOSTAPD_CTRL_INTF_DIR tzplatform_mkpath(TZ_SYS_RUN, "/hostapd")
+#define HOSTAPD_PID_FILE tzplatform_mkpath(TZ_SYS_RUN, "/.mesh_hostapd.pid")
+#define HOSTAPD_ALLOWED_LIST tzplatform_mkpath(TZ_SYS_VAR, "/lib/hostapd/hostapd.accept")
+#define HOSTAPD_BLOCKED_LIST tzplatform_mkpath(TZ_SYS_VAR, "/lib/hostapd/hostapd.deny")
+#define HOSTAPD_RETRY_MAX 5
+#define HOSTAPD_RETRY_DELAY 500000 /* us */
+
+#define MH_CTRL_INTF "/tmp/mesh_hostapd_wpa_ctrl"
+
+#define PSK_ITERATION_COUNT 4096
+#define MAX_BUF_SIZE (256u)
+
+static int hostapd_ctrl_fd = 0;
+
+static int __get_psk_hexascii(const char *pass, const unsigned char *salt,
+ char *psk, unsigned int psk_len)
+{
+ int i = 0;
+ int d_16 = 0;
+ int r_16 = 0;
+ unsigned char buf[SHA256_DIGEST_LENGTH] = {0, };
+
+ if (pass == NULL || salt == NULL || psk == NULL
+ || psk_len < (SHA256_DIGEST_LENGTH * 2 + 1)) {
+ WMESH_LOGE("Invalid parameter");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ if (!PKCS5_PBKDF2_HMAC_SHA1(pass, strlen(pass),
+ salt, strlen((const char *)salt),
+ PSK_ITERATION_COUNT, sizeof(buf), buf)) {
+ WMESH_LOGE("Getting psk is failed");
+ return WMESHD_ERROR_OPERATION_FAILED;
+ }
+
+ for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
+ d_16 = buf[i] >> 4;
+ r_16 = buf[i] & 0xf;
+
+ psk[i << 1] = d_16 < 10 ? d_16 + '0' : d_16 - 10 + 'a';
+ psk[(i << 1) + 1] = r_16 < 10 ? r_16 + '0' : r_16 - 10 + 'a';
+ }
+ psk[i << 1] = '\0';
+
+ return WMESHD_ERROR_NONE;
+}
+
+static int __config_hostapd(const char *softap_interface, const char *ssid,
+ const char *security, const char *passphrase, const char* mode,
+ int channel, int visibility, int mac_filter, int max_sta)
+{
+ char *conf = NULL;
+ char *old_conf;
+ char buf[HOSTAPD_CONF_LEN] = "";
+ FILE *fp = NULL;
+ int ret;
+ char key[MOBILE_AP_WIFI_KEY_MAX_LEN + 1];
+ char *hw_mode = NULL;
+
+ if (mode == NULL)
+ hw_mode = g_strdup("g");
+ else
+ hw_mode = g_strdup(mode);
+
+ /* Default conf. */
+ snprintf(buf, sizeof(buf), HOSTAPD_CONF,
+ softap_interface,
+ HOSTAPD_CTRL_INTF_DIR,
+ ssid,
+ channel,
+ (visibility ? 0 : 2),
+ hw_mode,
+ max_sta,
+ mac_filter,
+ HOSTAPD_ALLOWED_LIST,
+ HOSTAPD_BLOCKED_LIST);
+ conf = g_strdup(buf);
+
+ free(hw_mode);
+
+ /* Vendor elements conf. */
+ snprintf(buf, sizeof(buf),
+ "vendor_elements=%s\n", HOSTAPD_VENDOR_ELEMENTS_WIFI_AP);
+ old_conf = conf;
+ conf = g_strconcat(old_conf, buf, NULL);
+ g_free(old_conf);
+
+ /* Security conf. */
+ if (security != NULL && g_strcmp0(security, "wpa2-psk") == 0) {
+ ret = __get_psk_hexascii(passphrase,
+ (const unsigned char *)ssid, key, sizeof(key));
+ if (ret != WMESHD_ERROR_NONE) {
+ g_free(conf);
+ WMESH_LOGE("hex conversion failed");
+ return WMESHD_ERROR_OPERATION_FAILED;
+ }
+ snprintf(buf, sizeof(buf),
+ "wpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n", key);
+
+ old_conf = conf;
+ conf = g_strconcat(old_conf, buf, NULL);
+ g_free(old_conf);
+ } else {
+ WMESH_LOGD("Open connection [%s]", security);
+ }
+
+ fp = fopen(HOSTAPD_MESH_CONF_FILE, "w");
+ if (NULL == fp) {
+ WMESH_LOGE("Could not create the file.");
+ g_free(conf);
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ if (conf) {
+ fputs(conf, fp);
+ g_free(conf);
+ }
+ fclose(fp);
+
+ return WMESHD_ERROR_NONE;
+}
+
+static int __open_hostapd_intf(const char* softap_interface, int *fd,
+ const char *intf)
+{
+ int retry = 0;
+ char ctrl_intf[255] = {0, };
+ struct sockaddr_un src;
+ struct sockaddr_un dest;
+ struct stat stat_buf;
+
+ if (fd == NULL || intf == NULL) {
+ WMESH_LOGE("fd is NULL");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ *fd = socket(PF_UNIX, SOCK_DGRAM, 0);
+ if (*fd < 0) {
+ WMESH_LOGE("socket is failed");
+ return WMESHD_ERROR_OPERATION_FAILED;
+ }
+
+ src.sun_family = AF_UNIX;
+ g_strlcpy(src.sun_path, intf, sizeof(src.sun_path));
+
+ if (stat(src.sun_path, &stat_buf) == 0)
+ unlink(src.sun_path);
+
+ if (bind(*fd, (struct sockaddr *)&src, sizeof(src)) < 0) {
+ WMESH_LOGE("bind is failed");
+ close(*fd);
+ *fd = -1;
+ unlink(src.sun_path);
+ return WMESHD_ERROR_OPERATION_FAILED;
+ }
+
+ snprintf(ctrl_intf, sizeof(ctrl_intf), "%s/%s",
+ HOSTAPD_CTRL_INTF_DIR, softap_interface);
+ dest.sun_family = AF_UNIX;
+ g_strlcpy(dest.sun_path, ctrl_intf, sizeof(dest.sun_path));
+
+ while (connect(*fd, (struct sockaddr *)&dest, sizeof(dest)) < 0) {
+ if (++retry >= HOSTAPD_RETRY_MAX)
+ goto FAIL;
+ usleep(HOSTAPD_RETRY_DELAY);
+ }
+ WMESH_LOGD("Successfully open interface[%s] to hostapd", intf);
+
+ return WMESHD_ERROR_NONE;
+
+FAIL:
+ WMESH_LOGE("Cannot make connection to hostapd");
+ close(*fd);
+ *fd = -1;
+ unlink(src.sun_path);
+
+ return WMESHD_ERROR_OPERATION_FAILED;
+}
+
+static int __close_hostapd_intf(int *fd)
+{
+ if (fd == NULL) {
+ WMESH_LOGE("fd is NULL");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ if (*fd > 0)
+ close(*fd);
+ *fd = -1;
+
+ return WMESHD_ERROR_NONE;
+}
+
+static int __get_pid_of_hostapd(pid_t *pid)
+{
+ FILE *fd = NULL;
+ int ret = -1;
+ int rv = 0;
+ char error_buf[256] = {0, };
+ char file_path[256] = {0, };
+
+ snprintf(file_path, 256, "%s", HOSTAPD_PID_FILE);
+
+ if (0 == access(file_path, F_OK)) {
+ fd = fopen(file_path, "r");
+ if (fd == NULL) {
+ WMESH_LOGE("Error! Could not open pid file");
+ return WMESHD_ERROR_IO_ERROR;
+ }
+ } else {
+ WMESH_LOGE("Error! Could not access pid file");
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ errno = 0;
+ rv = fscanf(fd, "%d", &ret);
+ if (rv < 0) {
+ strerror_r(errno, error_buf, 256);
+ WMESH_LOGE("Error! Failed to read from file, rv:[%d], error:[%s]",
+ rv, error_buf);
+ fclose(fd);
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ *pid = (pid_t)ret;
+ WMESH_LOGD(" PID: [%d]", ret);
+
+ fclose(fd);
+ return WMESHD_ERROR_NONE;
+}
+
+static int __terminate_hostapd()
+{
+ int ret;
+ pid_t hostapd_pid = 0;
+
+ /* Get pid */
+ ret = __get_pid_of_hostapd(&hostapd_pid);
+ if (WMESHD_ERROR_NONE != ret) {
+ WMESH_LOGE("There is no hostapd");
+ return WMESHD_ERROR_NONE;
+ }
+
+ if (hostapd_pid == 0) {
+ WMESH_LOGE("There is no hostapd");
+ return WMESHD_ERROR_NONE;
+ }
+
+ ret = __close_hostapd_intf(&hostapd_ctrl_fd);
+ if (ret != WMESHD_ERROR_NONE)
+ WMESH_LOGE("__close_hostapd_intf is failed");
+
+ kill(hostapd_pid, SIGTERM);
+
+ return WMESHD_ERROR_NONE;
+}
+
+static int __execute_hostapd()
+{
+ pid_t pid = 0;
+ int status;
+ int ret = WMESHD_ERROR_NONE;
+
+ ret = __get_pid_of_hostapd(&pid);
+ if (0 != pid) {
+ WMESH_LOGE("hostapd is running already");
+ return WMESHD_ERROR_NONE;
+ }
+
+ pid = fork();
+ if (pid < 0) {
+ WMESH_LOGE("fork failed");
+ return WMESHD_ERROR_IO_ERROR;
+ }
+
+ if (pid == 0) {
+ if (execl(HOSTAPD_BIN, HOSTAPD_BIN, "-e", HOSTAPD_ENTROPY_FILE,
+ HOSTAPD_MESH_CONF_FILE,
+ "-f", HOSTAPD_DEBUG_FILE,
+ "-P", HOSTAPD_PID_FILE,
+ "-ddd", "-B",
+ (char *)NULL)) {
+ WMESH_LOGE("execl failed");
+ }
+
+ WMESH_LOGE("Should not get here!");
+ exit(1);
+ } else {
+ /* Reap child */
+ waitpid(pid, &status, 0);
+ WMESH_LOGD(" child [%d] reaped with status(%d)", pid, status);
+ }
+
+ return WMESHD_ERROR_NONE;
+}
+
+int wmesh_softap_set_configuration(const char* softap_interface,
+ const char *ssid, const char* mode, int channel, int visibility,
+ int max_sta, int security, const char* passphrase)
+{
+ int ret = WMESHD_ERROR_NONE;
+ const char *sec = (security == 0) ? NULL : "wpa2-psk";
+ int mac_filter = 0;
+
+ ret = __config_hostapd(softap_interface, ssid, sec, passphrase,
+ mode, channel, visibility, mac_filter, max_sta);
+
+ return ret;
+}
+
+int wmesh_softap_enable_softap(const char* softap_interface)
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ if (NULL == softap_interface) {
+ WMESH_LOGE("Invalid parameter");
+ return WMESHD_ERROR_INVALID_PARAMETER;
+ }
+
+ ret = __execute_hostapd();
+ if (ret != WMESHD_ERROR_NONE) {
+ WMESH_LOGE("__execute_hostapd is failed");
+ return WMESHD_ERROR_OPERATION_FAILED;
+ }
+
+ ret = __open_hostapd_intf(softap_interface,
+ &hostapd_ctrl_fd, MH_CTRL_INTF);
+ if (ret != WMESHD_ERROR_NONE) {
+ WMESH_LOGE("__open_hostapd_intf is failed");
+ __terminate_hostapd();
+ }
+
+ return ret;
+}
+
+int wmesh_softap_disable_softap()
+{
+ int ret = WMESHD_ERROR_NONE;
+
+ ret = __terminate_hostapd();
+ if (ret != WMESHD_ERROR_NONE) {
+ WMESH_LOGE("__execute_hostapd is failed");
+ return WMESHD_ERROR_OPERATION_FAILED;
+ }
+
+ return ret;
+}
--- /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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include "wmesh.h"
+#include "wmesh-log.h"
+#include "wmesh-util.h"
+#include "wmesh-service.h"
+#include "wmesh-service-interface.h"
+
+/**< mesh service */
+wmesh_service *meshsvc;
+
+int main(int argc, char *argv[])
+{
+ wmesh_service *service = NULL;
+ int ret_code = 0;
+ gboolean ret;
+
+ __WMESH_LOG_FUNC_ENTER__;
+
+#if !GLIB_CHECK_VERSION(2, 32, 0)
+ if (!g_thread_supported())
+ g_thread_init(NULL);
+#endif
+
+#if !GLIB_CHECK_VERSION(2, 36, 0)
+ g_type_init();
+#endif
+ NOTUSED(argc);
+ NOTUSED(argv);
+
+ WMESH_LOGI("service mainloop start");
+
+ /* Create mesh service */
+ meshsvc = service = wmeshd_service_new();
+
+ /* Initialize mesh service interface layer */
+ ret = wmeshd_service_interface_init(service);
+ if (G_UNLIKELY(FALSE == ret)) {
+ WMESH_LOGE("wmeshd_service_interface_init failed!");
+ goto END;
+ }
+
+ /* Run mesh service */
+ ret = wmeshd_service_run(service);
+ if (G_UNLIKELY(FALSE == ret)) {
+ WMESH_LOGE("Run service failed!");
+ ret_code = EXIT_FAILURE;
+ }
+
+END:
+ /* Free mesh service */
+ wmeshd_service_interface_deinit(service);
+ wmeshd_service_free(service);
+ meshsvc = NULL;
+
+ __WMESH_LOG_FUNC_EXIT__;
+ return 0;
+}
+
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>