• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }