• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 "mdns_socket_listener.h"
17 
18 #include <cassert>
19 #include <cerrno>
20 #include <cstdlib>
21 #include <cstring>
22 #include <iostream>
23 
24 #include <arpa/inet.h>
25 #include <fcntl.h>
26 #include <ifaddrs.h>
27 #include <net/if.h>
28 #include <netinet/in.h>
29 #include <sys/select.h>
30 #include <sys/socket.h>
31 #include <sys/time.h>
32 #include <sys/types.h>
33 #include <unistd.h>
34 
35 #include "netmgr_ext_log_wrapper.h"
36 
37 namespace OHOS {
38 namespace NetManagerStandard {
39 
40 namespace {
41 
42 constexpr uint32_t MDNS_MULTICAST_INADDR = (224U << 24) | 251U;
43 constexpr in6_addr MDNS_MULTICAST_IN6ADDR = {
44     {{0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFB}}};
45 
46 constexpr const char *CONTROL_TAG_REFRESH = "R";
47 
48 constexpr uint16_t MDNS_PORT = 5353;
49 constexpr size_t RECV_BUFFER = 2000;
50 constexpr int WAIT_THREAD_MS = 5;
51 constexpr size_t MDNS_MAX_SOCKET = 16;
52 static constexpr size_t REFRESH_BUFFER_LEN = 2;
53 
IfaceIsSupported(ifaddrs * ifa)54 inline bool IfaceIsSupported(ifaddrs *ifa)
55 {
56     return ifa->ifa_addr && ((ifa->ifa_flags & IFF_UP) && (ifa->ifa_flags & IFF_MULTICAST)) &&
57            (!(ifa->ifa_flags & IFF_LOOPBACK) && !(ifa->ifa_flags & IFF_POINTOPOINT));
58 }
59 
InetAddrV4IsLoopback(const in_addr * addr)60 inline bool InetAddrV4IsLoopback(const in_addr *addr)
61 {
62     return addr->s_addr == htonl(INADDR_LOOPBACK);
63 }
64 
InetAddrV6IsLoopback(const in6_addr * addr6)65 inline bool InetAddrV6IsLoopback(const in6_addr *addr6)
66 {
67     return IN6_IS_ADDR_LOOPBACK(addr6);
68 }
69 
InitFdFlags(int sock)70 int InitFdFlags(int sock)
71 {
72     const int flags = fcntl(sock, F_GETFL, 0);
73     if (flags == -1) {
74         return -1;
75     }
76     if (fcntl(sock, F_SETFL, static_cast<uint32_t>(flags) | O_NONBLOCK) == -1) {
77         return -1;
78     }
79     return 0;
80 }
81 
InitReusedSocket(int sock)82 int InitReusedSocket(int sock)
83 {
84     const int enable = 1;
85     if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char *>(&enable), sizeof(enable)) != 0) {
86         return -1;
87     }
88     if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, reinterpret_cast<const char *>(&enable), sizeof(enable)) != 0) {
89         return -1;
90     }
91     return sock;
92 }
93 
InitSocketV4(int sock,ifaddrs * ifa,int port)94 int InitSocketV4(int sock, ifaddrs *ifa, int port)
95 {
96     const int one = 1;
97     const int maxtll = 255;
98 
99     if (sock < 0) {
100         return -1;
101     }
102     if (port != 0 && InitReusedSocket(sock) < 0) {
103         return -1;
104     }
105 
106     bool allOK =
107         (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, reinterpret_cast<const char *>(&one), sizeof(one)) == 0) &&
108         (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, reinterpret_cast<const char *>(&one), sizeof(one)) == 0) &&
109         (setsockopt(sock, IPPROTO_IP, IP_TTL, reinterpret_cast<const char *>(&maxtll), sizeof(maxtll)) == 0) &&
110         (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, reinterpret_cast<const char *>(&maxtll), sizeof(maxtll)) == 0);
111     if (!allOK) {
112         return -1;
113     }
114 
115     sockaddr_in sockAddr{};
116 
117     ip_mreq mreq{};
118     mreq.imr_multiaddr.s_addr = htonl(MDNS_MULTICAST_INADDR);
119     mreq.imr_interface = ifa ? reinterpret_cast<sockaddr_in *>(ifa->ifa_addr)->sin_addr : in_addr{INADDR_ANY};
120     allOK =
121         (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, reinterpret_cast<const char *>(&mreq), sizeof(mreq)) == 0) &&
122         (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, reinterpret_cast<const char *>(&mreq.imr_interface),
123                     sizeof(in_addr)) == 0);
124     if (!allOK) {
125         return -1;
126     }
127 
128     sockAddr.sin_family = AF_INET;
129     sockAddr.sin_addr.s_addr = INADDR_ANY;
130     sockAddr.sin_port = htons(port);
131 
132     if (bind(sock, reinterpret_cast<sockaddr *>(&sockAddr), sizeof(sockaddr_in)) != 0) {
133         NETMGR_EXT_LOG_E("bind failed, errno:[%{public}d]", errno);
134         return -1;
135     }
136 
137     return InitFdFlags(sock);
138 }
139 
InitSocketV6(int sock,ifaddrs * ifa,int port)140 int InitSocketV6(int sock, ifaddrs *ifa, int port)
141 {
142     const int one = 1;
143     const int max = 255;
144 
145     if (sock < 0) {
146         return -1;
147     }
148     if (port != 0 && InitReusedSocket(sock) < 0) {
149         return -1;
150     }
151 
152     bool allOK =
153         (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, reinterpret_cast<const char *>(&one), sizeof(one)) == 0) &&
154         (setsockopt(sock, IPPROTO_IPV6, IPV6_2292PKTINFO, reinterpret_cast<const char *>(&one), sizeof(one)) == 0) &&
155         (setsockopt(sock, IPPROTO_IPV6, IPV6_2292HOPLIMIT, reinterpret_cast<const char *>(&one), sizeof(one)) == 0) &&
156         (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<const char *>(&one), sizeof(one)) == 0) &&
157         (setsockopt(sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, reinterpret_cast<const char *>(&max), sizeof(max)) == 0) &&
158         (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, reinterpret_cast<const char *>(&max), sizeof(max)) == 0);
159     if (!allOK) {
160         return -1;
161     }
162 
163     sockaddr_in6 sockAddr{};
164 
165     unsigned int ifaceIndex = ifa ? if_nametoindex(ifa->ifa_name) : 0;
166     ipv6_mreq mreq{};
167     mreq.ipv6mr_multiaddr = MDNS_MULTICAST_IN6ADDR;
168     mreq.ipv6mr_interface = ifaceIndex;
169     allOK =
170         (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, reinterpret_cast<const char *>(&mreq), sizeof(mreq)) == 0) &&
171         (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, reinterpret_cast<const char *>(&ifaceIndex),
172                     sizeof(ifaceIndex)) == 0);
173     if (!allOK) {
174         return -1;
175     }
176 
177     sockAddr.sin6_family = AF_INET6;
178     sockAddr.sin6_addr = in6addr_any;
179     sockAddr.sin6_port = htons(port);
180     sockAddr.sin6_flowinfo = 0;
181     sockAddr.sin6_scope_id = 0;
182 
183     if (bind(sock, reinterpret_cast<sockaddr *>(&sockAddr), sizeof(sockaddr_in6)) != 0) {
184         NETMGR_EXT_LOG_E("bind failed, errno:[%{public}d]", errno);
185         return -1;
186     }
187 
188     return InitFdFlags(sock);
189 }
190 
191 } // namespace
192 
MDnsSocketListener()193 MDnsSocketListener::MDnsSocketListener()
194 {
195     if (socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ctrlPair_) != 0) {
196         NETMGR_EXT_LOG_F("bind failed, errno:[%{public}d]", errno);
197     }
198 }
199 
~MDnsSocketListener()200 MDnsSocketListener::~MDnsSocketListener()
201 {
202     Stop();
203 }
204 
Start()205 void MDnsSocketListener::Start()
206 {
207     if (std::this_thread::get_id() == thread_.get_id()) {
208         return;
209     }
210     if (!runningFlag_) {
211         runningFlag_ = true;
212         thread_ = std::thread([this]() { Run(); });
213         std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_THREAD_MS));
214     }
215 }
216 
Stop()217 void MDnsSocketListener::Stop()
218 {
219     if (std::this_thread::get_id() == thread_.get_id()) {
220         return;
221     }
222     if (runningFlag_) {
223         runningFlag_ = false;
224         TriggerRefresh();
225         if (thread_.joinable()) {
226             thread_.join();
227         }
228     }
229 }
230 
OpenSocketForEachIface(bool ipv6Support,bool lo)231 void MDnsSocketListener::OpenSocketForEachIface(bool ipv6Support, bool lo)
232 {
233     ifaddrs *ifaddr = nullptr;
234     ifaddrs *loaddr = nullptr;
235 
236     if (getifaddrs(&ifaddr) < 0) {
237         NETMGR_EXT_LOG_F("getifaddrs failed, errno=[%{public}d]", errno);
238         return;
239     }
240 
241     for (ifaddrs *ifa = ifaddr; ifa != nullptr && socks_.size() < MDNS_MAX_SOCKET; ifa = ifa->ifa_next) {
242         if (ifa->ifa_addr == nullptr) {
243             continue;
244         }
245         if ((ifa->ifa_flags & IFF_LOOPBACK) && ifa->ifa_addr->sa_family == AF_INET) {
246             loaddr = ifa;
247         }
248         if (!IfaceIsSupported(ifa)) {
249             continue;
250         }
251         if (ifa->ifa_addr == nullptr) {
252             continue;
253         }
254         if (ifa->ifa_addr->sa_family == AF_INET &&
255             !InetAddrV4IsLoopback(&reinterpret_cast<sockaddr_in *>(ifa->ifa_addr)->sin_addr)) {
256             OpenSocketV4(ifa);
257         } else if (ipv6Support && ifa->ifa_addr->sa_family == AF_INET6 &&
258                    !InetAddrV6IsLoopback(&reinterpret_cast<sockaddr_in6 *>(ifa->ifa_addr)->sin6_addr) &&
259                    !reinterpret_cast<sockaddr_in6 *>(ifa->ifa_addr)->sin6_scope_id) {
260             OpenSocketV6(ifa);
261         }
262     }
263 
264     if (lo && socks_.size() == 0 && loaddr && loaddr->ifa_addr) {
265         OpenSocketV4(loaddr);
266     }
267 
268     freeifaddrs(ifaddr);
269 
270     if (socks_.size() == 0) {
271         NETMGR_EXT_LOG_F("no available iface found");
272     }
273 }
274 
OpenSocketV4(ifaddrs * ifa)275 void MDnsSocketListener::OpenSocketV4(ifaddrs *ifa)
276 {
277     sockaddr_in *saddr = reinterpret_cast<sockaddr_in *>(ifa->ifa_addr);
278     int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
279     if (sock < 0) {
280         NETMGR_EXT_LOG_E("socket create failed, errno:[%{public}d]", errno);
281         return;
282     }
283     if (InitSocketV4(sock, ifa, MDNS_PORT)) {
284         NETMGR_EXT_LOG_E("InitSocketV4 failed, errno=[%{public}d]", errno);
285         close(sock);
286     } else {
287         socks_.emplace_back(sock);
288         iface_[sock] = ifa->ifa_name;
289         reinterpret_cast<sockaddr_in *>(&saddr_[sock])->sin_family = AF_INET;
290         reinterpret_cast<sockaddr_in *>(&saddr_[sock])->sin_addr = saddr->sin_addr;
291     }
292     NETMGR_EXT_LOG_I("iface found, ifa_name=[%{public}s]", ifa->ifa_name);
293 }
294 
OpenSocketV6(ifaddrs * ifa)295 void MDnsSocketListener::OpenSocketV6(ifaddrs *ifa)
296 {
297     sockaddr_in6 *saddr = reinterpret_cast<sockaddr_in6 *>(ifa->ifa_addr);
298     int sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
299     if (sock < 0) {
300         NETMGR_EXT_LOG_E("socket create failed, errno:[%{public}d]", errno);
301         return;
302     }
303     if (InitSocketV6(sock, ifa, MDNS_PORT)) {
304         NETMGR_EXT_LOG_E("InitSocketV6 failed, errno=[%{public}d]", errno);
305         close(sock);
306     } else {
307         socks_.emplace_back(sock);
308         iface_[sock] = ifa->ifa_name;
309         reinterpret_cast<sockaddr_in6 *>(&saddr_[sock])->sin6_family = AF_INET6;
310         reinterpret_cast<sockaddr_in6 *>(&saddr_[sock])->sin6_addr = saddr->sin6_addr;
311     }
312     NETMGR_EXT_LOG_I("iface found, ifa_name=[%{public}s]", ifa->ifa_name);
313 }
314 
OpenSocketForDefault(bool ipv6Support)315 void MDnsSocketListener::OpenSocketForDefault(bool ipv6Support)
316 {
317     int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
318     if (socks_.size() < MDNS_MAX_SOCKET && InitSocketV4(sock, nullptr, MDNS_PORT)) {
319         close(sock);
320     } else {
321         socks_.emplace_back(sock);
322     }
323     if (!ipv6Support) {
324         return;
325     }
326     int sock6 = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
327     if (socks_.size() < MDNS_MAX_SOCKET && InitSocketV6(sock6, nullptr, MDNS_PORT)) {
328         close(sock6);
329     } else {
330         socks_.emplace_back(sock6);
331     }
332 }
333 
CloseAllSocket()334 void MDnsSocketListener::CloseAllSocket()
335 {
336     for (size_t i = 0; i < socks_.size() && i < MDNS_MAX_SOCKET; ++i) {
337         close(socks_[i]);
338     }
339     socks_.clear();
340     iface_.clear();
341 }
342 
Run()343 void MDnsSocketListener::Run()
344 {
345     while (runningFlag_) {
346         fd_set rfds;
347         FD_ZERO(&rfds);
348         FD_SET(ctrlPair_[0], &rfds);
349         int nfds = ctrlPair_[0] + 1;
350         for (size_t i = 0; i < socks_.size(); ++i) {
351             FD_SET(socks_[i], &rfds);
352             nfds = std::max(nfds, socks_[i] + 1);
353         }
354         timeval timeout{.tv_sec = 1, .tv_usec = 0};
355         int res = select(nfds, &rfds, 0, 0, &timeout);
356         if (res <= 0) {
357             continue;
358         }
359         for (size_t i = 0; i < socks_.size() && i < MDNS_MAX_SOCKET; ++i) {
360             bool isFreshNeed = FD_ISSET(ctrlPair_[0], &rfds) && CanRefresh() && static_cast<bool>(refresh_);
361             if (isFreshNeed) {
362                 refresh_(ctrlPair_[0]);
363             }
364             if (FD_ISSET(socks_[i], &rfds)) {
365                 ReceiveInSock(socks_[i]);
366             }
367         }
368     }
369     NETMGR_EXT_LOG_W("listener stopped");
370 }
371 
ReceiveInSock(int sock)372 void MDnsSocketListener::ReceiveInSock(int sock)
373 {
374     sockaddr_storage addr{};
375     sockaddr *saddr = (sockaddr *)&addr;
376     socklen_t addrlen = sizeof(addr);
377     MDnsPayload payload(RECV_BUFFER);
378     msghdr msg{};
379     iovec iov[1];
380     cmsghdr *cmptr;
381     union {
382         cmsghdr cm;
383         char control[CMSG_SPACE(sizeof(in6_pktinfo))];
384     } control_un;
385     msg.msg_control = control_un.control;
386     msg.msg_controllen = sizeof(control_un.control);
387     msg.msg_flags = 0;
388     msg.msg_name = saddr;
389     msg.msg_namelen = addrlen;
390     iov[0].iov_base = payload.data();
391     iov[0].iov_len = payload.size();
392     msg.msg_iov = iov;
393     msg.msg_iovlen = 1;
394 
395     ssize_t recvLen = recvmsg(sock, &msg, 0);
396     if (recvLen <= 0) {
397         NETMGR_EXT_LOG_E("recvmsg return: [%{public}zd], errno:[%{public}d]", recvLen, errno);
398         return;
399     }
400 
401     int ifIndex = -1;
402     for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != nullptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) {
403         if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO) {
404             ifIndex = reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmptr))->ipi_ifindex;
405         }
406         if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == IPV6_2292PKTINFO) {
407             ifIndex = static_cast<int>(reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmptr))->ipi6_ifindex);
408         }
409     }
410 
411     char ifName[IFNAMSIZ];
412     if (if_indextoname(static_cast<unsigned>(ifIndex), ifName) == nullptr) {
413         NETMGR_EXT_LOG_E("if_indextoname failed, errno:[%{public}d]", errno);
414     }
415     if (ifName == iface_[sock] && recvLen > 0 && recv_) {
416         payload.resize(static_cast<size_t>(recvLen));
417         recv_(sock, payload);
418     }
419 }
420 
TriggerRefresh()421 void MDnsSocketListener::TriggerRefresh()
422 {
423     write(ctrlPair_[1], CONTROL_TAG_REFRESH, 1);
424 }
425 
CanRefresh()426 bool MDnsSocketListener::CanRefresh()
427 {
428     char buf[REFRESH_BUFFER_LEN] = {};
429     read(ctrlPair_[0], buf, 1);
430     return (std::string_view(buf, REFRESH_BUFFER_LEN) == CONTROL_TAG_REFRESH);
431 }
432 
Multicast(int sock,const MDnsPayload & payload)433 ssize_t MDnsSocketListener::Multicast(int sock, const MDnsPayload &payload)
434 {
435     const sockaddr *saddrIf = GetSockAddr(sock);
436     if (saddrIf == nullptr) {
437         return -1;
438     }
439 
440     if (saddrIf->sa_family == AF_INET) {
441         in_addr addr;
442         addr.s_addr = htonl(MDNS_MULTICAST_INADDR);
443         sockaddr_in saddr{.sin_family = AF_INET, .sin_port = htons(MDNS_PORT), .sin_addr = addr};
444         return sendto(sock, payload.data(), payload.size(), 0, reinterpret_cast<const sockaddr *>(&saddr),
445                       sizeof(saddr));
446     }
447     if (saddrIf->sa_family == AF_INET6) {
448         sockaddr_in6 saddr{.sin6_family = AF_INET6, .sin6_port = htons(MDNS_PORT), .sin6_addr = MDNS_MULTICAST_IN6ADDR};
449         return sendto(sock, payload.data(), payload.size(), 0, reinterpret_cast<const sockaddr *>(&saddr),
450                       sizeof(saddr));
451     }
452     return -1;
453 }
454 
Unicast(int sock,sockaddr * saddr,const MDnsPayload & payload)455 ssize_t MDnsSocketListener::Unicast(int sock, sockaddr *saddr, const MDnsPayload &payload)
456 {
457     socklen_t saddrLen = 0;
458     if (saddr->sa_family == AF_INET) {
459         saddrLen = sizeof(sockaddr_in);
460     } else if (saddr->sa_family == AF_INET6) {
461         saddrLen = sizeof(sockaddr_in6);
462     } else {
463         return -1;
464     }
465     return sendto(sock, payload.data(), payload.size(), 0, saddr, saddrLen);
466 }
467 
MulticastAll(const MDnsPayload & payload)468 ssize_t MDnsSocketListener::MulticastAll(const MDnsPayload &payload)
469 {
470     ssize_t total = 0;
471     for (size_t i = 0; i < socks_.size() && i < MDNS_MAX_SOCKET; ++i) {
472         ssize_t sendLen = Multicast(socks_[i], payload);
473         NETMGR_EXT_LOG_D("sendto return: [%{public}zd]", sendLen);
474         if (sendLen == -1) {
475             return sendLen;
476         }
477         total += sendLen;
478     }
479     return total;
480 }
481 
GetSockets() const482 const std::vector<int> &MDnsSocketListener::GetSockets() const
483 {
484     return socks_;
485 }
486 
SetReceiveHandler(const ReceiveHandler & callback)487 void MDnsSocketListener::SetReceiveHandler(const ReceiveHandler &callback)
488 {
489     recv_ = callback;
490 }
491 
SetRefreshHandler(const SendHandler & callback)492 void MDnsSocketListener::SetRefreshHandler(const SendHandler &callback)
493 {
494     refresh_ = callback;
495 }
496 
GetIface(int sock) const497 std::string_view MDnsSocketListener::GetIface(int sock) const
498 {
499     auto i = iface_.find(sock);
500     return i == iface_.end() ? std::string_view{} : i->second;
501 }
502 
GetSockAddr(int sock) const503 const sockaddr *MDnsSocketListener::GetSockAddr(int sock) const
504 {
505     auto i = saddr_.find(sock);
506     return i == saddr_.end() ? nullptr : reinterpret_cast<const sockaddr *>(&(i->second));
507 }
508 } // namespace NetManagerStandard
509 } // namespace OHOS
510