3 * Copyright (c) 2020 Project CHIP Authors
4 * Copyright (c) 2018 Nest Labs, Inc.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 * Provides an implementation of the PlatformManager object
22 * for Linux platforms.
25 #include <platform/internal/CHIPDeviceLayerInternal.h>
27 #include <platform/PlatformManager.h>
28 #include <platform/internal/GenericPlatformManagerImpl_POSIX.cpp>
29 #include <support/CHIPMem.h>
30 #include <support/logging/CHIPLogging.h>
34 #include <arpa/inet.h>
35 #include <linux/netlink.h>
36 #include <linux/rtnetlink.h>
38 #include <netinet/in.h>
41 namespace DeviceLayer {
43 PlatformManagerImpl PlatformManagerImpl::sInstance;
46 static void GDBus_Thread()
48 GMainLoop * loop = g_main_loop_new(nullptr, false);
50 g_main_loop_run(loop);
51 g_main_loop_unref(loop);
55 void PlatformManagerImpl::WiFIIPChangeListener()
58 if ((sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1)
60 ChipLogError(DeviceLayer, "Failed to init netlink socket for ip addresses.");
64 struct sockaddr_nl addr;
65 memset(&addr, 0, sizeof(addr));
66 addr.nl_family = AF_NETLINK;
67 addr.nl_groups = RTMGRP_IPV4_IFADDR;
69 if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) == -1)
71 ChipLogError(DeviceLayer, "Failed to bind netlink socket for ip addresses.");
77 for (struct nlmsghdr * header = reinterpret_cast<struct nlmsghdr *>(buffer); (len = recv(sock, header, sizeof(buffer), 0)) > 0;)
79 for (struct nlmsghdr * messageHeader = header;
80 (NLMSG_OK(messageHeader, static_cast<uint32_t>(len))) && (messageHeader->nlmsg_type != NLMSG_DONE);
81 messageHeader = NLMSG_NEXT(messageHeader, len))
83 if (header->nlmsg_type == RTM_NEWADDR)
85 struct ifaddrmsg * addressMessage = (struct ifaddrmsg *) NLMSG_DATA(header);
86 struct rtattr * routeInfo = IFA_RTA(addressMessage);
87 size_t rtl = IFA_PAYLOAD(header);
89 while (rtl && RTA_OK(routeInfo, rtl))
91 if (routeInfo->rta_type == IFA_LOCAL)
94 ChipDeviceEvent event;
95 if_indextoname(addressMessage->ifa_index, name);
96 if (strcmp(name, CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME) != 0)
101 event.Type = DeviceEventType::kInternetConnectivityChange;
102 event.InternetConnectivityChange.IPv4 = kConnectivity_Established;
103 event.InternetConnectivityChange.IPv6 = kConnectivity_NoChange;
104 inet_ntop(AF_INET, RTA_DATA(routeInfo), event.InternetConnectivityChange.address,
105 sizeof(event.InternetConnectivityChange.address));
107 ChipLogDetail(DeviceLayer, "Got IP address on interface: %s IP: %s", name,
108 event.InternetConnectivityChange.address);
110 PlatformMgr().LockChipStack();
111 PlatformMgr().PostEvent(&event);
112 PlatformMgr().UnlockChipStack();
114 routeInfo = RTA_NEXT(routeInfo, rtl);
121 CHIP_ERROR PlatformManagerImpl::_InitChipStack()
126 GError * error = nullptr;
128 this->mpGDBusConnection = UniqueGDBusConnection(g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error));
130 std::thread gdbusThread(GDBus_Thread);
131 gdbusThread.detach();
134 std::thread wifiIPThread(WiFIIPChangeListener);
135 wifiIPThread.detach();
137 // Initialize the configuration system.
138 err = Internal::PosixConfig::Init();
140 // Call _InitChipStack() on the generic implementation base class
141 // to finish the initialization process.
142 err = Internal::GenericPlatformManagerImpl_POSIX<PlatformManagerImpl>::_InitChipStack();
150 GDBusConnection * PlatformManagerImpl::GetGDBusConnection()
152 return this->mpGDBusConnection.get();
156 } // namespace DeviceLayer