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_network_manager.h"
34 #include "securec.h"
35 #include "softbus_adapter_errcode.h"
36 #include "softbus_adapter_mem.h"
37 #include "softbus_adapter_socket.h"
38 #include "softbus_adapter_thread.h"
39 #include "softbus_def.h"
40 #include "softbus_errcode.h"
41 #include "softbus_log.h"
42
43 #undef NLMSG_OK
44 #define NLMSG_OK(nlh, len) \
45 (((len) >= (int32_t)(sizeof(struct nlmsghdr))) && (((nlh)->nlmsg_len) >= sizeof(struct nlmsghdr)) && \
46 ((int32_t)((nlh)->nlmsg_len) <= (len)))
47
48 #define DEFAULT_NETLINK_RECVBUF (32 * 1024)
49
CreateNetlinkSocket(void)50 static int32_t CreateNetlinkSocket(void)
51 {
52 int32_t sockFd;
53 struct sockaddr_nl nladdr;
54 int32_t sz = DEFAULT_NETLINK_RECVBUF;
55
56 int32_t ret = SoftBusSocketCreate(SOFTBUS_PF_NETLINK, SOFTBUS_SOCK_DGRAM | SOFTBUS_SOCK_CLOEXEC,
57 NETLINK_ROUTE, &sockFd);
58 if (ret != SOFTBUS_ADAPTER_OK) {
59 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "open netlink socket failed");
60 return SOFTBUS_ERR;
61 }
62 if (SoftBusSocketSetOpt(sockFd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0 &&
63 SoftBusSocketSetOpt(sockFd, SOFTBUS_SOL_SOCKET, SOFTBUS_SO_RCVBUF, &sz, sizeof(sz)) < 0) {
64 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "set uevent socket SO_RCVBUF option failed");
65 SoftBusSocketClose(sockFd);
66 return SOFTBUS_ERR;
67 }
68 if (memset_s(&nladdr, sizeof(nladdr), 0, sizeof(nladdr)) != EOK) {
69 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "init sockaddr_nl failed");
70 SoftBusSocketClose(sockFd);
71 return SOFTBUS_ERR;
72 }
73 nladdr.nl_family = SOFTBUS_AF_NETLINK;
74 // Kernel will assign a unique nl_pid if set to zero.
75 nladdr.nl_pid = 0;
76 nladdr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
77 if (SoftBusSocketBind(sockFd, (SoftBusSockAddr *)&nladdr, sizeof(nladdr)) < 0) {
78 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "bind netlink socket failed");
79 SoftBusSocketClose(sockFd);
80 return SOFTBUS_ERR;
81 }
82 return sockFd;
83 }
84
ParseRtAttr(struct rtattr ** tb,int max,struct rtattr * attr,int len)85 static void ParseRtAttr(struct rtattr **tb, int max, struct rtattr *attr, int len)
86 {
87 struct rtattr *attr1 = attr;
88 for (; RTA_OK(attr1, len); attr1 = RTA_NEXT(attr1, len)) {
89 if (attr1->rta_type <= max) {
90 tb[attr1->rta_type] = attr1;
91 }
92 }
93 }
94
ProcessAddrEvent(struct nlmsghdr * nlh)95 static void ProcessAddrEvent(struct nlmsghdr *nlh)
96 {
97 if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg))) {
98 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "Wrong len");
99 return;
100 }
101 struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA(nlh);
102 LnnNetIfType type = LNN_NETIF_TYPE_ETH;
103 char ifnameBuffer[NET_IF_NAME_LEN];
104 char *ifName = if_indextoname(ifa->ifa_index, ifnameBuffer);
105 if (ifName == NULL) {
106 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "invalid iface index");
107 return;
108 }
109 if (LnnGetNetIfTypeByName(ifName, &type) != SOFTBUS_OK) {
110 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "ProcessAddrEvent LnnGetNetIfTypeByName error");
111 return;
112 }
113 if (type == LNN_NETIF_TYPE_ETH || type == LNN_NETIF_TYPE_WLAN) {
114 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "network addr changed, type:%d", type);
115 LnnNotifyAddressChangedEvent(ifName);
116 }
117 }
118
ProcessLinkEvent(struct nlmsghdr * nlh)119 static void ProcessLinkEvent(struct nlmsghdr *nlh)
120 {
121 int len;
122 struct rtattr *tb[IFLA_MAX + 1] = {NULL};
123 struct ifinfomsg *ifinfo = (struct ifinfomsg *)NLMSG_DATA(nlh);
124 LnnNetIfType type = LNN_NETIF_TYPE_ETH;
125
126 len = (int32_t)nlh->nlmsg_len - NLMSG_SPACE(sizeof(*ifinfo));
127 ParseRtAttr(tb, IFLA_MAX, IFLA_RTA(ifinfo), len);
128
129 if (tb[IFLA_IFNAME] == NULL) {
130 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "netlink msg is invalid");
131 return;
132 }
133
134 if (LnnGetNetIfTypeByName((const char *)RTA_DATA(tb[IFLA_IFNAME]), &type) != SOFTBUS_OK) {
135 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "ProcessAddrEvent LnnGetNetIfTypeByName error");
136 return;
137 }
138 if (type == LNN_NETIF_TYPE_ETH || type == LNN_NETIF_TYPE_WLAN) {
139 SoftBusLog(
140 SOFTBUS_LOG_LNN, SOFTBUS_LOG_WARN, "%s:link status changed, type:%d", RTA_DATA(tb[IFLA_IFNAME]), type);
141 LnnNotifyAddressChangedEvent((const char *)RTA_DATA(tb[IFLA_IFNAME]));
142 }
143 }
144
NetlinkMonitorThread(void * para)145 NO_SANITIZE("cfi") static void *NetlinkMonitorThread(void *para)
146 {
147 struct nlmsghdr *nlh = NULL;
148 (void)para;
149 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_INFO, "netlink monitor thread start");
150 int32_t sockFd = CreateNetlinkSocket();
151 if (sockFd < 0) {
152 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "create netlink socket failed");
153 return NULL;
154 }
155 uint8_t *buffer = (uint8_t *)SoftBusCalloc(DEFAULT_NETLINK_RECVBUF * sizeof(uint8_t));
156 if (buffer == NULL) {
157 SoftBusSocketClose(sockFd);
158 return NULL;
159 }
160 while (true) {
161 (void)memset_s(buffer, DEFAULT_NETLINK_RECVBUF, 0, DEFAULT_NETLINK_RECVBUF);
162 int32_t len = SoftBusSocketRecv(sockFd, buffer, DEFAULT_NETLINK_RECVBUF, 0);
163 if (len < 0 && len == SOFTBUS_ADAPTER_SOCKET_EINTR) {
164 continue;
165 }
166 if (len < 0) {
167 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "recv netlink socket error");
168 break;
169 }
170 if (len < (int32_t)sizeof(struct nlmsghdr)) {
171 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "recv buffer not enough");
172 continue;
173 }
174 nlh = (struct nlmsghdr *)buffer;
175 while (NLMSG_OK(nlh, len) && nlh->nlmsg_type != NLMSG_DONE) {
176 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_INFO, "nlmsg_type: %d", nlh->nlmsg_type);
177 switch (nlh->nlmsg_type) {
178 case RTM_NEWADDR:
179 case RTM_DELADDR:
180 ProcessAddrEvent(nlh);
181 break;
182 case RTM_NEWLINK:
183 case RTM_DELLINK:
184 ProcessLinkEvent(nlh);
185 break;
186 default:
187 break;
188 }
189 nlh = NLMSG_NEXT(nlh, len);
190 }
191 }
192 SoftBusSocketClose(sockFd);
193 SoftBusFree(buffer);
194 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_INFO, "netlink monitor thread exit");
195 return NULL;
196 }
197
LnnInitNetlinkMonitorImpl(void)198 int32_t LnnInitNetlinkMonitorImpl(void)
199 {
200 SoftBusThread tid;
201 if (SoftBusThreadCreate(&tid, NULL, NetlinkMonitorThread, NULL) != 0) {
202 SoftBusLog(SOFTBUS_LOG_LNN, SOFTBUS_LOG_ERROR, "create ip change monitor thread failed");
203 return SOFTBUS_ERR;
204 }
205 return SOFTBUS_OK;
206 }