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