1 /*
2 * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "lnn_event_monitor_impl.h"
17
18 #ifndef _GNU_SOURCE
19 #define _GNU_SOURCE
20 #endif
21
22 #ifndef __MUSL__
23 #define __MUSL__
24 #endif
25
26 #include <arpa/inet.h>
27 #include <linux/netlink.h>
28 #include <linux/rtnetlink.h>
29 #include <net/if.h>
30 #include <sys/ioctl.h>
31
32 #include "bus_center_event.h"
33 #include "bus_center_manager.h"
34 #include "lnn_log.h"
35 #include "lnn_network_manager.h"
36 #include "securec.h"
37 #include "softbus_adapter_errcode.h"
38 #include "softbus_adapter_mem.h"
39 #include "softbus_adapter_socket.h"
40 #include "softbus_adapter_thread.h"
41 #include "softbus_base_listener.h"
42 #include "softbus_socket.h"
43 #include "softbus_def.h"
44 #include "softbus_error_code.h"
45 #include "softbus_wifi_api_adapter.h"
46 #include "lnn_init_monitor.h"
47 #include "lnn_net_capability.h"
48
49 #undef NLMSG_OK
50 #define NLMSG_OK(nlh, len) \
51 (((len) >= (int32_t)(sizeof(struct nlmsghdr))) && (((nlh)->nlmsg_len) >= sizeof(struct nlmsghdr)) && \
52 ((int32_t)((nlh)->nlmsg_len) <= (len)))
53
54 #define DEFAULT_NETLINK_RECVBUF (32 * 1024)
55
56 static int32_t g_netlinkFd = -1;
57
CreateNetlinkSocket(void)58 static int32_t CreateNetlinkSocket(void)
59 {
60 int32_t sockFd;
61 struct sockaddr_nl nladdr;
62 int32_t sz = DEFAULT_NETLINK_RECVBUF;
63
64 int32_t ret = SoftBusSocketCreate(SOFTBUS_PF_NETLINK, SOFTBUS_SOCK_DGRAM | SOFTBUS_SOCK_CLOEXEC,
65 NETLINK_ROUTE, &sockFd);
66 if (ret != SOFTBUS_ADAPTER_OK) {
67 LNN_LOGE(LNN_BUILDER, "open netlink socket failed");
68 return SOFTBUS_NETWORK_CREATE_SOCKET_FAILED;
69 }
70 if (SoftBusSocketSetOpt(sockFd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0 &&
71 SoftBusSocketSetOpt(sockFd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_RCVBUF, &sz, sizeof(sz)) < 0) {
72 LNN_LOGE(LNN_BUILDER, "set socket SO_RCVBUF option failed");
73 SoftBusSocketClose(sockFd);
74 return SOFTBUS_NETWORK_SET_SOCKET_OPTION_FAILED;
75 }
76 if (memset_s(&nladdr, sizeof(nladdr), 0, sizeof(nladdr)) != EOK) {
77 LNN_LOGE(LNN_BUILDER, "init sockaddr_nl failed");
78 SoftBusSocketClose(sockFd);
79 return SOFTBUS_MEM_ERR;
80 }
81 nladdr.nl_family = SOFTBUS_AF_NETLINK;
82 // Kernel will assign a unique nl_pid if set to zero.
83 nladdr.nl_pid = 0;
84 nladdr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
85 if (SoftBusSocketBind(sockFd, (SoftBusSockAddr *)&nladdr, sizeof(nladdr)) < 0) {
86 LNN_LOGE(LNN_BUILDER, "bind netlink socket failed");
87 SoftBusSocketClose(sockFd);
88 return SOFTBUS_NETWORK_BIND_SOCKET_FAILED;
89 }
90 return sockFd;
91 }
92
ParseRtAttr(struct rtattr ** tb,int max,struct rtattr * attr,int len)93 static void ParseRtAttr(struct rtattr **tb, int max, struct rtattr *attr, int len)
94 {
95 struct rtattr *attr1 = attr;
96 for (; RTA_OK(attr1, len); attr1 = RTA_NEXT(attr1, len)) {
97 if (attr1->rta_type <= max) {
98 tb[attr1->rta_type] = attr1;
99 }
100 }
101 }
102
NotifyIpUpdated(const char * ifName,struct nlmsghdr * nlh)103 static void NotifyIpUpdated(const char *ifName, struct nlmsghdr *nlh)
104 {
105 if (ifName == NULL || nlh == NULL) {
106 LNN_LOGE(LNN_BUILDER, "invalid param");
107 return;
108 }
109
110 if (nlh->nlmsg_type == RTM_NEWADDR) {
111 LnnNotifyNetlinkStateChangeEvent(SOFTBUS_NETMANAGER_IFNAME_IP_UPDATED, ifName);
112 }
113 }
114
WifiBandSetCapability()115 static void WifiBandSetCapability()
116 {
117 uint32_t netCapability = 0;
118 if (LnnGetLocalNumU32Info(NUM_KEY_NET_CAP, &netCapability) != SOFTBUS_OK) {
119 LNN_LOGE(LNN_BUILDER, "get capability fail from local.");
120 return;
121 }
122 SoftBusBand band = SoftBusGetLinkBand();
123 if (band == BAND_24G) {
124 (void)LnnSetNetCapability(&netCapability, BIT_WIFI_24G);
125 (void)LnnClearNetCapability(&netCapability, BIT_WIFI_5G);
126 } else if (band == BAND_5G) {
127 (void)LnnSetNetCapability(&netCapability, BIT_WIFI_5G);
128 (void)LnnClearNetCapability(&netCapability, BIT_WIFI_24G);
129 } else {
130 (void)LnnSetNetCapability(&netCapability, BIT_WIFI_5G);
131 (void)LnnSetNetCapability(&netCapability, BIT_WIFI_24G);
132 }
133 (void)LnnSetNetCapability(&netCapability, BIT_WIFI);
134 (void)LnnSetNetCapability(&netCapability, BIT_WIFI_P2P);
135 LNN_LOGD(LNN_BUILDER, "netCapability==%{public}d", netCapability);
136 if (LnnSetLocalNumU32Info(NUM_KEY_NET_CAP, netCapability) != SOFTBUS_OK) {
137 LNN_LOGE(LNN_LEDGER, "set local capability fail");
138 }
139 }
140
ProcessAddrEvent(struct nlmsghdr * nlh)141 static void ProcessAddrEvent(struct nlmsghdr *nlh)
142 {
143 if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg))) {
144 LNN_LOGE(LNN_BUILDER, "Wrong len");
145 return;
146 }
147 struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA(nlh);
148 LnnNetIfType type = LNN_NETIF_TYPE_ETH;
149 char ifnameBuffer[NET_IF_NAME_LEN];
150 char *ifName = if_indextoname(ifa->ifa_index, ifnameBuffer);
151 if (ifName == NULL) {
152 LNN_LOGE(LNN_BUILDER, "invalid iface index");
153 return;
154 }
155 NotifyIpUpdated(ifName, nlh);
156 if (LnnGetNetIfTypeByName(ifName, &type) != SOFTBUS_OK) {
157 LNN_LOGE(LNN_BUILDER, "LnnGetNetIfTypeByName error");
158 return;
159 }
160 if (type == LNN_NETIF_TYPE_WLAN && nlh->nlmsg_type == RTM_NEWADDR) {
161 WifiBandSetCapability();
162 }
163 static uint32_t callCount = 0;
164 if (type == LNN_NETIF_TYPE_ETH || type == LNN_NETIF_TYPE_WLAN) {
165 LNN_LOGI(LNN_BUILDER, "network addr changed, ifName=%{public}s, netifType=%{public}d, callCount=%{public}u",
166 ifName, type, callCount++);
167 LnnNotifyAddressChangedEvent(ifName);
168 }
169 }
170
NotifyLinkUp(const char * ifName,struct nlmsghdr * nlh,struct ifinfomsg * ifinfo)171 static void NotifyLinkUp(const char *ifName, struct nlmsghdr *nlh, struct ifinfomsg *ifinfo)
172 {
173 if (ifName == NULL || nlh == NULL || ifinfo == NULL) {
174 LNN_LOGE(LNN_BUILDER, "invalid param");
175 return;
176 }
177 if (nlh->nlmsg_type == RTM_NEWLINK && (ifinfo->ifi_flags & IFF_LOWER_UP)) {
178 LnnNotifyNetlinkStateChangeEvent(SOFTBUS_NETMANAGER_IFNAME_LINK_UP, ifName);
179 }
180 }
181
ProcessLinkEvent(struct nlmsghdr * nlh)182 static void ProcessLinkEvent(struct nlmsghdr *nlh)
183 {
184 int len;
185 struct rtattr *tb[IFLA_MAX + 1] = {NULL};
186 struct ifinfomsg *ifinfo = (struct ifinfomsg *)NLMSG_DATA(nlh);
187 LnnNetIfType type = LNN_NETIF_TYPE_ETH;
188
189 len = (int32_t)nlh->nlmsg_len - NLMSG_SPACE(sizeof(*ifinfo));
190 ParseRtAttr(tb, IFLA_MAX, IFLA_RTA(ifinfo), len);
191
192 if (tb[IFLA_IFNAME] == NULL) {
193 LNN_LOGE(LNN_BUILDER, "netlink msg is invalid");
194 return;
195 }
196 NotifyLinkUp((const char *)RTA_DATA(tb[IFLA_IFNAME]), nlh, ifinfo);
197 if (LnnGetNetIfTypeByName((const char *)RTA_DATA(tb[IFLA_IFNAME]), &type) != SOFTBUS_OK) {
198 return;
199 }
200 static uint32_t callCount = 0;
201 if (type == LNN_NETIF_TYPE_ETH || type == LNN_NETIF_TYPE_WLAN) {
202 LNN_LOGI(LNN_BUILDER, "link status changed, IFLA_IFNAME=%{public}s, netifType=%{public}d, callCount=%{public}u",
203 (const char *)RTA_DATA(tb[IFLA_IFNAME]), type, callCount++);
204 LnnNotifyAddressChangedEvent((const char *)RTA_DATA(tb[IFLA_IFNAME]));
205 }
206 }
207
NetlinkOnDataEvent(ListenerModule module,int32_t events,int32_t fd)208 static int32_t NetlinkOnDataEvent(ListenerModule module, int32_t events, int32_t fd)
209 {
210 if (module != NETLINK || events != SOFTBUS_SOCKET_IN || fd < 0) {
211 LNN_LOGE(LNN_BUILDER, "listening fail, moudle=%{public}d, events=%{public}d", module, events);
212 return SOFTBUS_INVALID_PARAM;
213 }
214 uint8_t *buffer = (uint8_t *)SoftBusCalloc(DEFAULT_NETLINK_RECVBUF * sizeof(uint8_t));
215 if (buffer == NULL) {
216 LNN_LOGE(LNN_BUILDER, "malloc fail.");
217 return SOFTBUS_MALLOC_ERR;
218 }
219 struct nlmsghdr *nlh = NULL;
220 int32_t len = SoftBusSocketRecv(fd, buffer, DEFAULT_NETLINK_RECVBUF, 0);
221 if (len < 0 || len == SOFTBUS_ADAPTER_SOCKET_EINTR || len < (int32_t)sizeof(struct nlmsghdr)) {
222 LNN_LOGE(LNN_BUILDER, "recv netlink socket error");
223 SoftBusFree(buffer);
224 return SOFTBUS_SOCKET_EXCEPTION;
225 }
226 nlh = (struct nlmsghdr *)buffer;
227 while (NLMSG_OK(nlh, len) && nlh->nlmsg_type != NLMSG_DONE) {
228 LNN_LOGD(LNN_BUILDER, "nlmsg_type=%{public}d", nlh->nlmsg_type);
229 switch (nlh->nlmsg_type) {
230 case RTM_NEWADDR:
231 case RTM_DELADDR:
232 ProcessAddrEvent(nlh);
233 break;
234 case RTM_NEWLINK:
235 case RTM_DELLINK:
236 ProcessLinkEvent(nlh);
237 break;
238 default:
239 break;
240 }
241 nlh = NLMSG_NEXT(nlh, len);
242 }
243 SoftBusFree(buffer);
244 return SOFTBUS_OK;
245 }
246
NetlinkOnConnectEvent(ListenerModule module,int32_t cfd,const ConnectOption * clientAddr)247 static int32_t NetlinkOnConnectEvent(ListenerModule module, int32_t cfd, const ConnectOption *clientAddr)
248 {
249 (void)module;
250 (void)cfd;
251 (void)clientAddr;
252 LNN_LOGD(LNN_BUILDER, "ignore this event");
253 return SOFTBUS_OK;
254 }
255
LnnInitNetlinkMonitorImpl(void)256 int32_t LnnInitNetlinkMonitorImpl(void)
257 {
258 SoftbusBaseListener listener = {
259 .onConnectEvent = NetlinkOnConnectEvent,
260 .onDataEvent = NetlinkOnDataEvent,
261 };
262 int32_t ret = StartBaseClient(NETLINK, &listener);
263 if (ret != SOFTBUS_OK) {
264 LNN_LOGE(LNN_BUILDER, "listening fail, moudle=%{public}d ", NETLINK);
265 return ret;
266 }
267 int32_t sockFd = CreateNetlinkSocket();
268 if (sockFd < 0) {
269 LNN_LOGE(LNN_BUILDER, "create netlink socket failed");
270 return SOFTBUS_NETWORK_CREATE_SOCKET_FAILED;
271 }
272 g_netlinkFd = sockFd;
273 ret = AddTrigger(NETLINK, sockFd, READ_TRIGGER);
274 if (ret != SOFTBUS_OK) {
275 LNN_LOGE(LNN_BUILDER, "AddTrigger fail.");
276 SoftBusSocketClose(sockFd);
277 return ret;
278 }
279 return SOFTBUS_OK;
280 }
281
LnnInitNetlinkMonitorImplNotify(void)282 int32_t LnnInitNetlinkMonitorImplNotify(void)
283 {
284 int32_t ret = LnnInitNetlinkMonitorImpl();
285 if (ret != SOFTBUS_OK) {
286 LnnInitModuleStatusSet(INIT_DEPS_NETLINK, DEPS_STATUS_FAILED);
287 LnnInitModuleReturnSet(INIT_DEPS_NETLINK, ret);
288 return ret;
289 }
290 LnnInitModuleStatusSet(INIT_DEPS_NETLINK, DEPS_STATUS_SUCCESS);
291 return SOFTBUS_OK;
292 }
293
LnnDeInitNetlinkMonitorImpl(void)294 void LnnDeInitNetlinkMonitorImpl(void)
295 {
296 if (g_netlinkFd > 0) {
297 SoftBusSocketClose(g_netlinkFd);
298 }
299 }