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 }