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_protocol_impl.h"
17
18 #include <arpa/inet.h>
19 #include <iostream>
20 #include <numeric>
21 #include <random>
22 #include <unistd.h>
23
24 #include "mdns_packet_parser.h"
25 #include "netmgr_ext_log_wrapper.h"
26
27 namespace OHOS {
28 namespace NetManagerStandard {
29
30 namespace {
31
32 constexpr uint32_t DEFAULT_TTL = 120;
33 constexpr uint16_t MDNS_FLUSH_CACHE_BIT = 0x8000;
34
35 constexpr int PHASE_PTR = 1;
36 constexpr int PHASE_SRV = 2;
37 constexpr int PHASE_DOMAIN = 3;
38
AddrToString(const std::any & addr)39 std::string AddrToString(const std::any &addr)
40 {
41 char buf[INET6_ADDRSTRLEN] = {0};
42 if (std::any_cast<in_addr>(&addr)) {
43 if (inet_ntop(AF_INET, std::any_cast<in_addr>(&addr), buf, sizeof(buf)) == nullptr) {
44 return std::string{};
45 }
46 } else if (std::any_cast<in6_addr>(&addr)) {
47 if (inet_ntop(AF_INET6, std::any_cast<in6_addr>(&addr), buf, sizeof(buf)) == nullptr) {
48 return std::string{};
49 }
50 } else {
51 return std::string{};
52 }
53 return std::string(buf);
54 }
55
56 } // namespace
57
MDnsProtocolImpl()58 MDnsProtocolImpl::MDnsProtocolImpl()
59 {
60 Init();
61 }
62
Init()63 void MDnsProtocolImpl::Init()
64 {
65 listener_.CloseAllSocket();
66 if (config_.configAllIface) {
67 listener_.OpenSocketForEachIface(config_.ipv6Support, config_.configLo);
68 } else {
69 listener_.OpenSocketForDefault(config_.ipv6Support);
70 }
71 listener_.SetReceiveHandler(
72 [this](int sock, const MDnsPayload &payload) { return this->ReceivePacket(sock, payload); });
73 listener_.SetRefreshHandler([this](int sock) { return this->OnRefresh(sock); });
74 }
75
SetConfig(const MDnsConfig & config)76 void MDnsProtocolImpl::SetConfig(const MDnsConfig &config)
77 {
78 config_ = config;
79 }
80
GetConfig() const81 const MDnsConfig &MDnsProtocolImpl::GetConfig() const
82 {
83 return config_;
84 }
85
SetHandler(const Handler & handler)86 void MDnsProtocolImpl::SetHandler(const Handler &handler)
87 {
88 handler_ = handler;
89 }
90
Decorated(const std::string & name) const91 std::string MDnsProtocolImpl::Decorated(const std::string &name) const
92 {
93 return name + config_.topDomain;
94 }
95
ExtractInstance(const Result & info) const96 std::string MDnsProtocolImpl::ExtractInstance(const Result &info) const
97 {
98 return Decorated(info.serviceName + MDNS_DOMAIN_SPLITER_STR + info.serviceType);
99 }
100
Register(const Result & info)101 int32_t MDnsProtocolImpl::Register(const Result &info)
102 {
103 if (!(IsNameValid(info.serviceName) && IsTypeValid(info.serviceType) && IsPortValid(info.port))) {
104 return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
105 }
106 std::string name = ExtractInstance(info);
107 if (!IsDomainValid(name)) {
108 return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
109 }
110 {
111 std::lock_guard<std::recursive_mutex> guard(mutex_);
112 if (srvMap_.find(name) != srvMap_.end()) {
113 return NET_MDNS_ERR_SERVICE_INSTANCE_DUPLICATE;
114 }
115 srvMap_.emplace(name, info);
116 }
117
118 listener_.Start();
119 return Announce(info, false);
120 }
121
Discovery(const std::string & serviceType)122 int32_t MDnsProtocolImpl::Discovery(const std::string &serviceType)
123 {
124 if (!IsTypeValid(serviceType)) {
125 return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
126 }
127 std::string name = Decorated(serviceType);
128 if (!IsDomainValid(name)) {
129 return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
130 }
131 {
132 std::lock_guard<std::recursive_mutex> guard(mutex_);
133 ++reqMap_[name];
134 }
135 MDnsPayloadParser parser;
136 MDnsMessage msg{};
137 msg.questions.emplace_back(DNSProto::Question{
138 .name = name,
139 .qtype = DNSProto::RRTYPE_PTR,
140 .qclass = DNSProto::RRCLASS_IN,
141 });
142 msg.header.qdcount = msg.questions.size();
143
144 listener_.Start();
145 ssize_t size = listener_.MulticastAll(parser.ToBytes(msg));
146
147 return size > 0 ? NETMANAGER_EXT_SUCCESS : NET_MDNS_ERR_SEND;
148 }
149
HandleResolveInstanceLater(const Result & result)150 void MDnsProtocolImpl::HandleResolveInstanceLater(const Result &result)
151 {
152 cacheMap_[result.domain];
153 ResolveFromNet(result.domain);
154 RunTaskLater(
155 [r = result, this]() mutable {
156 if (cacheMap_.find(r.domain) == cacheMap_.end() || cacheMap_[r.domain].addr.empty()) {
157 NETMGR_EXT_LOG_D("instance %{public}s, domain: %{public}s not found", r.serviceName.c_str(),
158 r.domain.c_str());
159 return false;
160 }
161 r.ipv6 = cacheMap_[r.domain].ipv6;
162 r.addr = cacheMap_[r.domain].addr;
163 handler_(r, NETMANAGER_EXT_SUCCESS);
164 return true;
165 },
166 false);
167 }
168
ResolveInstanceFromCache(const std::string & name)169 bool MDnsProtocolImpl::ResolveInstanceFromCache(const std::string &name)
170 {
171 std::lock_guard<std::recursive_mutex> guard(mutex_);
172 if (cacheMap_.find(name) != cacheMap_.end() && !cacheMap_[name].domain.empty()) {
173 Result r = cacheMap_[name];
174 if (cacheMap_.find(r.domain) != cacheMap_.end() && !cacheMap_[r.domain].addr.empty()) {
175 r.ipv6 = cacheMap_[r.domain].ipv6;
176 r.addr = cacheMap_[r.domain].addr;
177 RunTaskLater([r, this]() {
178 handler_(r, NETMANAGER_EXT_SUCCESS);
179 return true;
180 });
181 } else {
182 HandleResolveInstanceLater(r);
183 }
184 return true;
185 }
186 return false;
187 }
188
ResolveInstanceFromNet(const std::string & name)189 bool MDnsProtocolImpl::ResolveInstanceFromNet(const std::string &name)
190 {
191 MDnsPayloadParser parser;
192 MDnsMessage msg{};
193 msg.questions.emplace_back(DNSProto::Question{
194 .name = name,
195 .qtype = DNSProto::RRTYPE_SRV,
196 .qclass = DNSProto::RRCLASS_IN,
197 });
198 msg.questions.emplace_back(DNSProto::Question{
199 .name = name,
200 .qtype = DNSProto::RRTYPE_TXT,
201 .qclass = DNSProto::RRCLASS_IN,
202 });
203 msg.header.qdcount = msg.questions.size();
204
205 listener_.Start();
206 ssize_t size = listener_.MulticastAll(parser.ToBytes(msg));
207
208 return size > 0;
209 }
210
ResolveFromCache(const std::string & domain)211 bool MDnsProtocolImpl::ResolveFromCache(const std::string &domain)
212 {
213 if (cacheMap_.find(domain) != cacheMap_.end() && !cacheMap_[domain].addr.empty()) {
214 RunTaskLater([r = cacheMap_[domain], this]() {
215 handler_(r, NETMANAGER_EXT_SUCCESS);
216 return true;
217 });
218 return true;
219 }
220 return false;
221 }
222
ResolveFromNet(const std::string & domain)223 bool MDnsProtocolImpl::ResolveFromNet(const std::string &domain)
224 {
225 MDnsPayloadParser parser;
226 MDnsMessage msg{};
227 msg.questions.emplace_back(DNSProto::Question{
228 .name = domain,
229 .qtype = DNSProto::RRTYPE_A,
230 .qclass = DNSProto::RRCLASS_IN,
231 });
232 msg.questions.emplace_back(DNSProto::Question{
233 .name = domain,
234 .qtype = DNSProto::RRTYPE_AAAA,
235 .qclass = DNSProto::RRCLASS_IN,
236 });
237 msg.header.qdcount = msg.questions.size();
238
239 listener_.Start();
240 ssize_t size = listener_.MulticastAll(parser.ToBytes(msg));
241
242 return size > 0;
243 }
244
ResolveInstance(const std::string & instance)245 int32_t MDnsProtocolImpl::ResolveInstance(const std::string &instance)
246 {
247 if (!IsInstanceValid(instance)) {
248 return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
249 }
250 std::string name = Decorated(instance);
251 if (!IsDomainValid(name)) {
252 return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
253 }
254 std::lock_guard<std::recursive_mutex> guard(mutex_);
255 if (ResolveInstanceFromCache(name)) {
256 return NETMANAGER_EXT_SUCCESS;
257 }
258 ++reqMap_[name];
259 return ResolveInstanceFromNet(name) ? NETMANAGER_EXT_SUCCESS : NET_MDNS_ERR_SEND;
260 }
261
Resolve(const std::string & domain)262 int32_t MDnsProtocolImpl::Resolve(const std::string &domain)
263 {
264 if (!IsDomainValid(domain)) {
265 return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
266 }
267 std::string name = domain;
268 if (!IsDomainValid(name)) {
269 return NET_MDNS_ERR_ILLEGAL_ARGUMENT;
270 }
271 std::lock_guard<std::recursive_mutex> guard(mutex_);
272 if (ResolveFromCache(name)) {
273 return NETMANAGER_EXT_SUCCESS;
274 }
275 ++reqMap_[name];
276 return ResolveFromNet(name) ? NETMANAGER_EXT_SUCCESS : NET_MDNS_ERR_SEND;
277 }
278
UnRegister(const std::string & key)279 int32_t MDnsProtocolImpl::UnRegister(const std::string &key)
280 {
281 std::string name = Decorated(key);
282 std::lock_guard<std::recursive_mutex> guard(mutex_);
283 if (srvMap_.find(name) != srvMap_.end()) {
284 Announce(srvMap_[name], true);
285 srvMap_.erase(name);
286 return NETMANAGER_EXT_SUCCESS;
287 }
288 return NET_MDNS_ERR_SERVICE_INSTANCE_NOT_FOUND;
289 }
290
StopDiscovery(const std::string & key)291 int32_t MDnsProtocolImpl::StopDiscovery(const std::string &key)
292 {
293 return Stop(Decorated(key));
294 }
295
StopResolveInstance(const std::string & key)296 int32_t MDnsProtocolImpl::StopResolveInstance(const std::string &key)
297 {
298 return Stop(Decorated(key));
299 }
300
StopResolve(const std::string & key)301 int32_t MDnsProtocolImpl::StopResolve(const std::string &key)
302 {
303 return Stop(key);
304 }
305
Stop(const std::string & key)306 int32_t MDnsProtocolImpl::Stop(const std::string &key)
307 {
308 std::lock_guard<std::recursive_mutex> guard(mutex_);
309 if (reqMap_.find(key) != reqMap_.end() && reqMap_[key] > 0) {
310 --reqMap_[key];
311 }
312 return NETMANAGER_EXT_SUCCESS;
313 }
314
Announce(const Result & info,bool off)315 int32_t MDnsProtocolImpl::Announce(const Result &info, bool off)
316 {
317 MDnsMessage response{};
318 response.header.flags = DNSProto::MDNS_ANSWER_FLAGS;
319 std::string name = Decorated(info.serviceName + MDNS_DOMAIN_SPLITER_STR + info.serviceType);
320 response.answers.emplace_back(DNSProto::ResourceRecord{.name = Decorated(info.serviceType),
321 .rtype = static_cast<uint16_t>(DNSProto::RRTYPE_PTR),
322 .rclass = DNSProto::RRCLASS_IN | MDNS_FLUSH_CACHE_BIT,
323 .ttl = off ? 0U : DEFAULT_TTL,
324 .rdata = name});
325 response.answers.emplace_back(DNSProto::ResourceRecord{.name = name,
326 .rtype = static_cast<uint16_t>(DNSProto::RRTYPE_SRV),
327 .rclass = DNSProto::RRCLASS_IN | MDNS_FLUSH_CACHE_BIT,
328 .ttl = off ? 0U : DEFAULT_TTL,
329 .rdata = DNSProto::RDataSrv{
330 .priority = 0,
331 .weight = 0,
332 .port = static_cast<uint16_t>(info.port),
333 .name = GetHostDomain(),
334 }});
335 response.answers.emplace_back(DNSProto::ResourceRecord{.name = name,
336 .rtype = static_cast<uint16_t>(DNSProto::RRTYPE_TXT),
337 .rclass = DNSProto::RRCLASS_IN | MDNS_FLUSH_CACHE_BIT,
338 .ttl = off ? 0U : DEFAULT_TTL,
339 .rdata = info.txt});
340 MDnsPayloadParser parser;
341 ssize_t size = listener_.MulticastAll(parser.ToBytes(response));
342 return size > 0 ? NETMANAGER_EXT_SUCCESS : NET_MDNS_ERR_SEND;
343 }
344
ReceivePacket(int sock,const MDnsPayload & payload)345 void MDnsProtocolImpl::ReceivePacket(int sock, const MDnsPayload &payload)
346 {
347 if (payload.size() == 0) {
348 NETMGR_EXT_LOG_W("empty payload received");
349 return;
350 }
351 MDnsPayloadParser parser;
352 MDnsMessage msg = parser.FromBytes(payload);
353 if (parser.GetError() != 0) {
354 NETMGR_EXT_LOG_W("payload parse failed");
355 return;
356 }
357 if ((msg.header.flags & DNSProto::HEADER_FLAGS_QR_MASK) == 0) {
358 ProcessQuestion(sock, msg);
359 } else {
360 ProcessAnswer(sock, msg);
361 }
362 }
363
OnRefresh(int sock)364 void MDnsProtocolImpl::OnRefresh(int sock)
365 {
366 std::lock_guard<std::recursive_mutex> guard(mutex_);
367 std::queue<Task> tmp;
368 while (taskQueue_.size() > 0) {
369 auto func = taskQueue_.front();
370 taskQueue_.pop();
371 if (!func()) {
372 tmp.push(func);
373 }
374 }
375 tmp.swap(taskQueue_);
376 }
377
AppendRecord(std::vector<DNSProto::ResourceRecord> & rrlist,DNSProto::RRType type,const std::string & name,const std::any & rdata)378 void MDnsProtocolImpl::AppendRecord(std::vector<DNSProto::ResourceRecord> &rrlist, DNSProto::RRType type,
379 const std::string &name, const std::any &rdata)
380 {
381 rrlist.emplace_back(DNSProto::ResourceRecord{.name = name,
382 .rtype = static_cast<uint16_t>(type),
383 .rclass = DNSProto::RRCLASS_IN | MDNS_FLUSH_CACHE_BIT,
384 .ttl = DEFAULT_TTL,
385 .rdata = rdata});
386 }
387
ProcessQuestion(int sock,const MDnsMessage & msg)388 void MDnsProtocolImpl::ProcessQuestion(int sock, const MDnsMessage &msg)
389 {
390 const sockaddr *saddrIf = listener_.GetSockAddr(sock);
391 if (saddrIf == nullptr) {
392 return;
393 }
394 std::any anyAddr;
395 DNSProto::RRType anyAddrType;
396 if (saddrIf->sa_family == AF_INET6) {
397 anyAddr = reinterpret_cast<const sockaddr_in6 *>(saddrIf)->sin6_addr;
398 anyAddrType = DNSProto::RRTYPE_AAAA;
399 } else {
400 anyAddr = reinterpret_cast<const sockaddr_in *>(saddrIf)->sin_addr;
401 anyAddrType = DNSProto::RRTYPE_A;
402 }
403 int phase = 0;
404 MDnsMessage response{};
405 response.header.flags = DNSProto::MDNS_ANSWER_FLAGS;
406 for (size_t i = 0; i < msg.header.qdcount; ++i) {
407 ProcessQuestionRecord(anyAddr, anyAddrType, msg.questions[i], phase, response);
408 }
409 if (phase < PHASE_DOMAIN) {
410 AppendRecord(response.additional, anyAddrType, GetHostDomain(), anyAddr);
411 }
412 if (phase != 0 && response.answers.size() > 0) {
413 listener_.Multicast(sock, MDnsPayloadParser().ToBytes(response));
414 }
415 }
416
ProcessQuestionRecord(const std::any & anyAddr,const DNSProto::RRType & anyAddrType,const DNSProto::Question & qu,int & phase,MDnsMessage & response)417 void MDnsProtocolImpl::ProcessQuestionRecord(const std::any &anyAddr, const DNSProto::RRType &anyAddrType,
418 const DNSProto::Question &qu, int &phase, MDnsMessage &response)
419 {
420 std::lock_guard<std::recursive_mutex> guard(mutex_);
421 std::string name = qu.name;
422 if (qu.qtype == DNSProto::RRTYPE_ANY || qu.qtype == DNSProto::RRTYPE_PTR) {
423 std::for_each(srvMap_.begin(), srvMap_.end(), [&](const auto &elem) -> void {
424 if (EndsWith(elem.first, name)) {
425 AppendRecord(response.answers, DNSProto::RRTYPE_PTR, name, elem.first);
426 AppendRecord(response.additional, DNSProto::RRTYPE_SRV, elem.first,
427 DNSProto::RDataSrv{
428 .priority = 0,
429 .weight = 0,
430 .port = static_cast<uint16_t>(elem.second.port),
431 .name = GetHostDomain(),
432 });
433 AppendRecord(response.additional, DNSProto::RRTYPE_TXT, elem.first, elem.second.txt);
434 }
435 });
436 phase = std::max(phase, PHASE_PTR);
437 }
438 if (qu.qtype == DNSProto::RRTYPE_ANY || qu.qtype == DNSProto::RRTYPE_SRV) {
439 auto iter = srvMap_.find(name);
440 if (iter == srvMap_.end()) {
441 return;
442 }
443 AppendRecord(response.answers, DNSProto::RRTYPE_SRV, name,
444 DNSProto::RDataSrv{
445 .priority = 0,
446 .weight = 0,
447 .port = static_cast<uint16_t>(iter->second.port),
448 .name = GetHostDomain(),
449 });
450 phase = std::max(phase, PHASE_SRV);
451 }
452 if (qu.qtype == DNSProto::RRTYPE_ANY || qu.qtype == DNSProto::RRTYPE_TXT) {
453 auto iter = srvMap_.find(name);
454 if (iter == srvMap_.end()) {
455 return;
456 }
457 AppendRecord(response.answers, DNSProto::RRTYPE_TXT, name, iter->second.txt);
458 phase = std::max(phase, PHASE_SRV);
459 }
460 if (qu.qtype == DNSProto::RRTYPE_ANY || qu.qtype == DNSProto::RRTYPE_A || qu.qtype == DNSProto::RRTYPE_AAAA) {
461 if (name != GetHostDomain() || (qu.qtype != DNSProto::RRTYPE_ANY && anyAddrType != qu.qtype)) {
462 return;
463 }
464 AppendRecord(response.answers, anyAddrType, name, anyAddr);
465 phase = std::max(phase, PHASE_DOMAIN);
466 }
467 }
468
ProcessAnswer(int sock,const MDnsMessage & msg)469 void MDnsProtocolImpl::ProcessAnswer(int sock, const MDnsMessage &msg)
470 {
471 const sockaddr *saddrIf = listener_.GetSockAddr(sock);
472 if (saddrIf == nullptr) {
473 return;
474 }
475 bool v6 = (saddrIf->sa_family == AF_INET6);
476
477 std::vector<Result> matches;
478 std::set<std::string> changed;
479 for (size_t i = 0; i < msg.answers.size(); ++i) {
480 ProcessAnswerRecord(v6, msg.answers[i], &matches, changed);
481 }
482
483 for (size_t i = 0; i < msg.additional.size(); ++i) {
484 ProcessAnswerRecord(v6, msg.additional[i], nullptr, changed);
485 }
486
487 for (size_t i = 0; i < msg.additional.size(); ++i) {
488 ProcessAnswerRecord(v6, msg.additional[i], nullptr, changed);
489 }
490
491 for (auto i = matches.begin(); i != matches.end() && handler_ != nullptr; ++i) {
492 handler_(*i, NETMANAGER_EXT_SUCCESS);
493 }
494
495 for (auto i = changed.begin(); i != changed.end() && handler_ != nullptr; ++i) {
496 if (cacheMap_.find(*i) == cacheMap_.end()) {
497 continue;
498 }
499 cacheMap_[*i].iface = listener_.GetIface(sock);
500 if (cacheMap_[*i].type == INSTANCE_RESOLVED && ResolveInstanceFromCache(*i)) {
501 continue;
502 }
503 handler_(cacheMap_[*i], NETMANAGER_EXT_SUCCESS);
504 }
505 }
506
ProcessPtrRecord(bool v6,const DNSProto::ResourceRecord & rr,std::vector<Result> * matches)507 void MDnsProtocolImpl::ProcessPtrRecord(bool v6, const DNSProto::ResourceRecord &rr, std::vector<Result> *matches)
508 {
509 const std::string *data = std::any_cast<std::string>(&rr.rdata);
510 if (data == nullptr) {
511 return;
512 }
513 Result result;
514 ExtractNameAndType(*data, result.serviceName, result.serviceType);
515 if (std::find_if(matches->begin(), matches->end(), [&](const auto &elem) {
516 return elem.serviceName == result.serviceName && elem.serviceType == result.serviceType;
517 }) == matches->end()) {
518 result.type = (rr.ttl == 0) ? SERVICE_LOST : SERVICE_FOUND;
519 matches->emplace_back(std::move(result));
520 if (rr.ttl == 0) {
521 cacheMap_.erase(*data);
522 } else {
523 cacheMap_[*data];
524 }
525 }
526 }
527
ProcessAnswerRecord(bool v6,const DNSProto::ResourceRecord & rr,std::vector<Result> * matches,std::set<std::string> & changed)528 void MDnsProtocolImpl::ProcessAnswerRecord(bool v6, const DNSProto::ResourceRecord &rr, std::vector<Result> *matches,
529 std::set<std::string> &changed)
530 {
531 std::lock_guard<std::recursive_mutex> guard(mutex_);
532 std::string name = rr.name;
533 bool isReq = reqMap_.find(name) != reqMap_.end() && reqMap_[name] > 0;
534 if (!isReq && cacheMap_.find(name) == cacheMap_.end()) {
535 return;
536 }
537 if (rr.rtype == DNSProto::RRTYPE_PTR && matches) {
538 ProcessPtrRecord(v6, rr, matches);
539 } else if (rr.rtype == DNSProto::RRTYPE_SRV) {
540 const DNSProto::RDataSrv *srv = std::any_cast<DNSProto::RDataSrv>(&rr.rdata);
541 if (rr.ttl == 0) {
542 return cacheMap_[name].domain.clear();
543 }
544 if (srv == nullptr) {
545 return;
546 }
547 Result &result = cacheMap_[name];
548 result.type = INSTANCE_RESOLVED;
549 ExtractNameAndType(name, result.serviceName, result.serviceType);
550 result.domain = srv->name;
551 result.port = srv->port;
552 cacheMap_[srv->name];
553 if (isReq) {
554 changed.emplace(name);
555 }
556 } else if (rr.rtype == DNSProto::RRTYPE_TXT) {
557 const TxtRecordEncoded *txt = std::any_cast<TxtRecordEncoded>(&rr.rdata);
558 if (rr.ttl == 0 || txt == nullptr) {
559 return;
560 }
561 Result &result = cacheMap_[name];
562 result.txt = *txt;
563 } else if (rr.rtype == DNSProto::RRTYPE_A || rr.rtype == DNSProto::RRTYPE_AAAA) {
564 if (v6 != (rr.rtype == DNSProto::RRTYPE_AAAA)) {
565 return;
566 }
567 if (rr.ttl == 0) {
568 return cacheMap_[name].domain.clear();
569 }
570 Result &result = cacheMap_[name];
571 result.type = DOMAIN_RESOLVED;
572 result.domain = name;
573 result.ipv6 = (rr.rtype == DNSProto::RRTYPE_AAAA);
574 result.addr = AddrToString(rr.rdata);
575 if (isReq) {
576 changed.emplace(name);
577 }
578 } else {
579 NETMGR_EXT_LOG_D("Unknown packet received, type=[%{public}d]", rr.rtype);
580 }
581 }
582
GetHostDomain()583 std::string MDnsProtocolImpl::GetHostDomain()
584 {
585 if (config_.hostname.empty()) {
586 char buffer[MDNS_MAX_DOMAIN_LABEL];
587 if (gethostname(buffer, sizeof(buffer)) == 0) {
588 config_.hostname = buffer;
589 static auto uid = []() {
590 std::random_device rd;
591 return rd();
592 }();
593 config_.hostname += std::to_string(uid);
594 }
595 }
596 return Decorated(config_.hostname);
597 }
598
RunTaskLater(const Task & task,bool atonce)599 void MDnsProtocolImpl::RunTaskLater(const Task &task, bool atonce)
600 {
601 {
602 std::lock_guard<std::recursive_mutex> guard(mutex_);
603 taskQueue_.push(task);
604 }
605 if (atonce) {
606 listener_.TriggerRefresh();
607 }
608 }
609
610 } // namespace NetManagerStandard
611 } // namespace OHOS
612