• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "lnn_log.h"
34 #include "lnn_network_manager.h"
35 #include "securec.h"
36 #include "softbus_adapter_errcode.h"
37 #include "softbus_adapter_mem.h"
38 #include "softbus_adapter_socket.h"
39 #include "softbus_adapter_thread.h"
40 #include "softbus_base_listener.h"
41 #include "softbus_socket.h"
42 #include "softbus_def.h"
43 #include "softbus_error_code.h"
44 #include "lnn_init_monitor.h"
45 
46 #undef NLMSG_OK
47 #define NLMSG_OK(nlh, len)                                                                               \
48     (((len) >= (int32_t)(sizeof(struct nlmsghdr))) && (((nlh)->nlmsg_len) >= sizeof(struct nlmsghdr)) && \
49         ((int32_t)((nlh)->nlmsg_len) <= (len)))
50 
51 #define DEFAULT_NETLINK_RECVBUF (32 * 1024)
52 
53 static int32_t g_netlinkFd = -1;
54 
CreateNetlinkSocket(void)55 static int32_t CreateNetlinkSocket(void)
56 {
57     int32_t sockFd;
58     struct sockaddr_nl nladdr;
59     int32_t sz = DEFAULT_NETLINK_RECVBUF;
60 
61     int32_t ret = SoftBusSocketCreate(SOFTBUS_PF_NETLINK, SOFTBUS_SOCK_DGRAM | SOFTBUS_SOCK_CLOEXEC,
62         NETLINK_ROUTE, &sockFd);
63     if (ret != SOFTBUS_ADAPTER_OK) {
64         LNN_LOGE(LNN_BUILDER, "open netlink socket failed");
65         return SOFTBUS_NETWORK_CREATE_SOCKET_FAILED;
66     }
67     if (SoftBusSocketSetOpt(sockFd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0 &&
68         SoftBusSocketSetOpt(sockFd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_RCVBUF, &sz, sizeof(sz)) < 0) {
69         LNN_LOGE(LNN_BUILDER, "set socket SO_RCVBUF option failed");
70         SoftBusSocketClose(sockFd);
71         return SOFTBUS_NETWORK_SET_SOCKET_OPTION_FAILED;
72     }
73     if (memset_s(&nladdr, sizeof(nladdr), 0, sizeof(nladdr)) != EOK) {
74         LNN_LOGE(LNN_BUILDER, "init sockaddr_nl failed");
75         SoftBusSocketClose(sockFd);
76         return SOFTBUS_MEM_ERR;
77     }
78     nladdr.nl_family = SOFTBUS_AF_NETLINK;
79     // Kernel will assign a unique nl_pid if set to zero.
80     nladdr.nl_pid = 0;
81     nladdr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
82     if (SoftBusSocketBind(sockFd, (SoftBusSockAddr *)&nladdr, sizeof(nladdr)) < 0) {
83         LNN_LOGE(LNN_BUILDER, "bind netlink socket failed");
84         SoftBusSocketClose(sockFd);
85         return SOFTBUS_NETWORK_BIND_SOCKET_FAILED;
86     }
87     return sockFd;
88 }
89 
ParseRtAttr(struct rtattr ** tb,int max,struct rtattr * attr,int len)90 static void ParseRtAttr(struct rtattr **tb, int max, struct rtattr *attr, int len)
91 {
92     struct rtattr *attr1 = attr;
93     for (; RTA_OK(attr1, len); attr1 = RTA_NEXT(attr1, len)) {
94         if (attr1->rta_type <= max) {
95             tb[attr1->rta_type] = attr1;
96         }
97     }
98 }
99 
NotifyIpUpdated(const char * ifName,struct nlmsghdr * nlh)100 static void NotifyIpUpdated(const char *ifName, struct nlmsghdr *nlh)
101 {
102     if (ifName == NULL || nlh == NULL) {
103         LNN_LOGE(LNN_BUILDER, "invalid param");
104         return;
105     }
106 
107     if (nlh->nlmsg_type == RTM_NEWADDR) {
108         LnnNotifyNetlinkStateChangeEvent(SOFTBUS_NETMANAGER_IFNAME_IP_UPDATED, ifName);
109     }
110 }
111 
ProcessAddrEvent(struct nlmsghdr * nlh)112 static void ProcessAddrEvent(struct nlmsghdr *nlh)
113 {
114     if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg))) {
115         LNN_LOGE(LNN_BUILDER, "Wrong len");
116         return;
117     }
118     struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA(nlh);
119     LnnNetIfType type = LNN_NETIF_TYPE_ETH;
120     char ifnameBuffer[NET_IF_NAME_LEN];
121     char *ifName = if_indextoname(ifa->ifa_index, ifnameBuffer);
122     if (ifName == NULL) {
123         LNN_LOGE(LNN_BUILDER, "invalid iface index");
124         return;
125     }
126     NotifyIpUpdated(ifName, nlh);
127     if (LnnGetNetIfTypeByName(ifName, &type) != SOFTBUS_OK) {
128         LNN_LOGE(LNN_BUILDER, "LnnGetNetIfTypeByName error");
129         return;
130     }
131     static uint32_t callCount = 0;
132     if (type == LNN_NETIF_TYPE_ETH || type == LNN_NETIF_TYPE_WLAN) {
133         LNN_LOGI(LNN_BUILDER, "network addr changed, ifName=%{public}s, netifType=%{public}d, callCount=%{public}u",
134             ifName, type, callCount++);
135         LnnNotifyAddressChangedEvent(ifName);
136     }
137 }
138 
NotifyLinkUp(const char * ifName,struct nlmsghdr * nlh,struct ifinfomsg * ifinfo)139 static void NotifyLinkUp(const char *ifName, struct nlmsghdr *nlh, struct ifinfomsg *ifinfo)
140 {
141     if (ifName == NULL || nlh == NULL || ifinfo == NULL) {
142         LNN_LOGE(LNN_BUILDER, "invalid param");
143         return;
144     }
145     if (nlh->nlmsg_type == RTM_NEWLINK && (ifinfo->ifi_flags & IFF_LOWER_UP)) {
146         LnnNotifyNetlinkStateChangeEvent(SOFTBUS_NETMANAGER_IFNAME_LINK_UP, ifName);
147     }
148 }
149 
ProcessLinkEvent(struct nlmsghdr * nlh)150 static void ProcessLinkEvent(struct nlmsghdr *nlh)
151 {
152     int len;
153     struct rtattr *tb[IFLA_MAX + 1] = {NULL};
154     struct ifinfomsg *ifinfo = (struct ifinfomsg *)NLMSG_DATA(nlh);
155     LnnNetIfType type = LNN_NETIF_TYPE_ETH;
156 
157     len = (int32_t)nlh->nlmsg_len - NLMSG_SPACE(sizeof(*ifinfo));
158     ParseRtAttr(tb, IFLA_MAX, IFLA_RTA(ifinfo), len);
159 
160     if (tb[IFLA_IFNAME] == NULL) {
161         LNN_LOGE(LNN_BUILDER, "netlink msg is invalid");
162         return;
163     }
164     NotifyLinkUp((const char *)RTA_DATA(tb[IFLA_IFNAME]), nlh, ifinfo);
165     if (LnnGetNetIfTypeByName((const char *)RTA_DATA(tb[IFLA_IFNAME]), &type) != SOFTBUS_OK) {
166         return;
167     }
168     static uint32_t callCount = 0;
169     if (type == LNN_NETIF_TYPE_ETH || type == LNN_NETIF_TYPE_WLAN) {
170         LNN_LOGI(LNN_BUILDER, "link status changed, IFLA_IFNAME=%{public}s, netifType=%{public}d, callCount=%{public}u",
171             (const char *)RTA_DATA(tb[IFLA_IFNAME]), type, callCount++);
172         LnnNotifyAddressChangedEvent((const char *)RTA_DATA(tb[IFLA_IFNAME]));
173     }
174 }
175 
NetlinkOnDataEvent(ListenerModule module,int32_t events,int32_t fd)176 static int32_t NetlinkOnDataEvent(ListenerModule module, int32_t events, int32_t fd)
177 {
178     if (module != NETLINK || events != SOFTBUS_SOCKET_IN || fd < 0) {
179         LNN_LOGE(LNN_BUILDER, "listening fail, moudle=%{public}d, events=%{public}d", module, events);
180         return SOFTBUS_INVALID_PARAM;
181     }
182     uint8_t *buffer = (uint8_t *)SoftBusCalloc(DEFAULT_NETLINK_RECVBUF * sizeof(uint8_t));
183     if (buffer == NULL) {
184         LNN_LOGE(LNN_BUILDER, "malloc fail.");
185         return SOFTBUS_MALLOC_ERR;
186     }
187     struct nlmsghdr *nlh = NULL;
188     int32_t len = SoftBusSocketRecv(fd, buffer, DEFAULT_NETLINK_RECVBUF, 0);
189     if (len < 0 || len == SOFTBUS_ADAPTER_SOCKET_EINTR || len < (int32_t)sizeof(struct nlmsghdr)) {
190         LNN_LOGE(LNN_BUILDER, "recv netlink socket error");
191         SoftBusFree(buffer);
192         return SOFTBUS_SOCKET_EXCEPTION;
193     }
194     nlh = (struct nlmsghdr *)buffer;
195     while (NLMSG_OK(nlh, len) && nlh->nlmsg_type != NLMSG_DONE) {
196         LNN_LOGD(LNN_BUILDER, "nlmsg_type=%{public}d", nlh->nlmsg_type);
197         switch (nlh->nlmsg_type) {
198             case RTM_NEWADDR:
199             case RTM_DELADDR:
200                 ProcessAddrEvent(nlh);
201                 break;
202             case RTM_NEWLINK:
203             case RTM_DELLINK:
204                 ProcessLinkEvent(nlh);
205                 break;
206             default:
207                 break;
208         }
209         nlh = NLMSG_NEXT(nlh, len);
210     }
211     SoftBusFree(buffer);
212     return SOFTBUS_OK;
213 }
214 
NetlinkOnConnectEvent(ListenerModule module,int32_t cfd,const ConnectOption * clientAddr)215 static int32_t NetlinkOnConnectEvent(ListenerModule module, int32_t cfd, const ConnectOption *clientAddr)
216 {
217     (void)module;
218     (void)cfd;
219     (void)clientAddr;
220     LNN_LOGD(LNN_BUILDER, "ignore this event");
221     return SOFTBUS_OK;
222 }
223 
LnnInitNetlinkMonitorImpl(void)224 int32_t LnnInitNetlinkMonitorImpl(void)
225 {
226     SoftbusBaseListener listener = {
227         .onConnectEvent = NetlinkOnConnectEvent,
228         .onDataEvent = NetlinkOnDataEvent,
229     };
230     int32_t ret = StartBaseClient(NETLINK, &listener);
231     if (ret != SOFTBUS_OK) {
232         LNN_LOGE(LNN_BUILDER, "listening fail, moudle=%{public}d ", NETLINK);
233         return ret;
234     }
235     int32_t sockFd = CreateNetlinkSocket();
236     if (sockFd < 0) {
237         LNN_LOGE(LNN_BUILDER, "create netlink socket failed");
238         return SOFTBUS_NETWORK_CREATE_SOCKET_FAILED;
239     }
240     g_netlinkFd = sockFd;
241     ret = AddTrigger(NETLINK, sockFd, READ_TRIGGER);
242     if (ret != SOFTBUS_OK) {
243         LNN_LOGE(LNN_BUILDER, "AddTrigger fail.");
244         SoftBusSocketClose(sockFd);
245         return ret;
246     }
247     return SOFTBUS_OK;
248 }
249 
LnnInitNetlinkMonitorImplNotify(void)250 int32_t LnnInitNetlinkMonitorImplNotify(void)
251 {
252     int32_t ret = LnnInitNetlinkMonitorImpl();
253     if (ret != SOFTBUS_OK) {
254         LnnInitModuleStatusSet(INIT_DEPS_NETLINK, DEPS_STATUS_FAILED);
255         LnnInitModuleReturnSet(INIT_DEPS_NETLINK, ret);
256         return ret;
257     }
258     LnnInitModuleStatusSet(INIT_DEPS_NETLINK, DEPS_STATUS_SUCCESS);
259     return SOFTBUS_OK;
260 }
261 
LnnDeInitNetlinkMonitorImpl(void)262 void LnnDeInitNetlinkMonitorImpl(void)
263 {
264     if (g_netlinkFd > 0) {
265         SoftBusSocketClose(g_netlinkFd);
266     }
267 }