Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include <cstdio>
6 : #include <iomanip>
7 : #include <assert.h>
8 : #include <errno.h>
9 : #include <sys/types.h>
10 : #include <dirent.h>
11 : #include "base/logging.h"
12 : #include <base/contrail_ports.h>
13 : #include <bind/bind_util.h>
14 : #include <cfg/dns_config.h>
15 : #include <mgr/dns_oper.h>
16 : #include "named_config.h"
17 : #include <cmn/dns.h>
18 :
19 : using namespace std;
20 :
21 : NamedConfig *NamedConfig::singleton_;
22 : const string NamedConfig::NamedZoneFileSuffix = "zone";
23 : const string NamedConfig::NamedZoneNSPrefix = "contrail-ns";
24 : const string NamedConfig::NamedZoneMXPrefix = "contrail-mx";
25 : const char NamedConfig::pid_file_name[] = "contrail-named.pid";
26 : const char NamedConfig::sessionkey_file_name[] = "session.key";
27 :
28 0 : void NamedConfig::Init(const std::string& named_config_dir,
29 : const std::string& named_config_file,
30 : const std::string& named_log_file,
31 : const std::string& rndc_config_file,
32 : const std::string& rndc_secret,
33 : const std::string& named_max_cache_size) {
34 0 : assert(singleton_ == NULL);
35 0 : singleton_ = new NamedConfig(named_config_dir, named_config_file,
36 : named_log_file, rndc_config_file, rndc_secret,
37 0 : named_max_cache_size);
38 0 : singleton_->Reset();
39 0 : }
40 :
41 15 : void NamedConfig::Shutdown() {
42 15 : assert(singleton_);
43 15 : delete singleton_;
44 15 : }
45 :
46 : // Reset bind config
47 15 : void NamedConfig::Reset() {
48 15 : reset_flag_ = true;
49 15 : CreateRndcConf();
50 15 : UpdateNamedConf();
51 15 : DIR *dir = opendir(named_config_dir_.c_str());
52 15 : if (dir) {
53 : struct dirent *file;
54 540 : while ((file = readdir(dir)) != NULL) {
55 525 : std::string str(named_config_dir_);
56 525 : str.append(file->d_name);
57 525 : if (str.find(".zone") != std::string::npos) {
58 0 : remove(str.c_str());
59 : }
60 525 : }
61 15 : closedir(dir);
62 : }
63 15 : reset_flag_ = false;
64 15 : }
65 :
66 11 : void NamedConfig::AddView(const VirtualDnsConfig *vdns) {
67 11 : UpdateNamedConf(vdns);
68 11 : }
69 :
70 8 : void NamedConfig::ChangeView(const VirtualDnsConfig *vdns) {
71 8 : UpdateNamedConf(vdns);
72 8 : std::string old_domain = vdns->GetOldDomainName();
73 8 : if (vdns->GetDomainName() != old_domain) {
74 0 : ZoneList zones;
75 0 : zones.push_back(old_domain);
76 0 : RemoveZoneFiles(vdns, zones);
77 0 : }
78 8 : }
79 :
80 11 : void NamedConfig::DelView(const VirtualDnsConfig *vdns) {
81 11 : UpdateNamedConf(vdns);
82 11 : }
83 :
84 0 : void NamedConfig::AddAllViews() {
85 0 : all_zone_files_ = true;
86 0 : UpdateNamedConf();
87 0 : all_zone_files_ = false;
88 0 : }
89 :
90 13 : void NamedConfig::AddZone(const Subnet &subnet, const VirtualDnsConfig *vdns) {
91 13 : ZoneList zones;
92 13 : subnet.GetReverseZones(zones);
93 : // Ignore zone files which already exist
94 41 : for (unsigned int i = 0; i < zones.size();) {
95 28 : std::ifstream file(zones[i].c_str());
96 28 : if (file.is_open()) {
97 0 : if (file.good()) {
98 0 : zones.erase(zones.begin() + i);
99 0 : file.close();
100 0 : continue;
101 : }
102 0 : file.close();
103 : }
104 28 : i++;
105 28 : }
106 13 : AddZoneFiles(zones, vdns);
107 13 : UpdateNamedConf();
108 13 : }
109 :
110 29 : void NamedConfig::DelZone(const Subnet &subnet, const VirtualDnsConfig *vdns) {
111 29 : UpdateNamedConf();
112 29 : ZoneList vdns_zones, snet_zones;
113 29 : MakeZoneList(vdns, vdns_zones);
114 29 : subnet.GetReverseZones(snet_zones);
115 : // Ignore zones which are still in use
116 87 : for (unsigned int i = 0; i < snet_zones.size();) {
117 : unsigned int j;
118 218 : for (j = 0; j < vdns_zones.size(); j++) {
119 168 : if (snet_zones[i] == vdns_zones[j]) {
120 8 : snet_zones.erase(snet_zones.begin() + i);
121 8 : break;
122 : }
123 : }
124 58 : if (j == vdns_zones.size())
125 50 : i++;
126 : }
127 29 : RemoveZoneFiles(vdns, snet_zones);
128 29 : }
129 :
130 0 : void NamedConfig::UpdateNamedConf(const VirtualDnsConfig *updated_vdns) {
131 0 : CreateNamedConf(updated_vdns);
132 0 : sync();
133 :
134 0 : ifstream pyscript("/etc/contrail/dns/applynamedconfig.py");
135 0 : if (!pyscript.good()) {
136 0 : std::stringstream str;
137 0 : str << "/usr/bin/contrail-rndc -c " << rndc_config_file_ << " -p ";
138 0 : str << ContrailPorts::DnsRndc();
139 0 : str << " reconfig";
140 0 : int res = system(str.str().c_str());
141 0 : if (res) {
142 0 : LOG(WARN, "/usr/bin/contrail-rndc command failed");
143 : }
144 0 : } else {
145 0 : std::stringstream str;
146 : // execute the helper script to apply named config
147 0 : str << "python3 /etc/contrail/dns/applynamedconfig.py";
148 0 : int res = system(str.str().c_str());
149 0 : if (res) {
150 0 : LOG(ERROR, "Applying named configuration failed");
151 : }
152 0 : }
153 0 : }
154 :
155 87 : void NamedConfig::CreateNamedConf(const VirtualDnsConfig *updated_vdns) {
156 87 : GetDefaultForwarders();
157 87 : file_.open(named_config_file_.c_str());
158 :
159 87 : WriteOptionsConfig();
160 87 : WriteRndcConfig();
161 87 : WriteLoggingConfig();
162 87 : WriteViewConfig(updated_vdns);
163 :
164 87 : file_.flush();
165 87 : file_.close();
166 87 : }
167 :
168 15 : void NamedConfig::CreateRndcConf() {
169 15 : file_.open(rndc_config_file_.c_str());
170 :
171 15 : file_ << "key \"rndc-key\" {" << endl;
172 15 : file_ << " algorithm hmac-md5;" << endl;
173 15 : file_ << " secret \"" << rndc_secret_ << "\";" << endl;
174 15 : file_ << "};" << endl << endl;
175 :
176 15 : file_ << "options {" << endl;
177 15 : file_ << " default-key \"rndc-key\";" << endl;
178 15 : file_ << " default-server 127.0.0.1;" << endl;
179 15 : file_ << " default-port " << ContrailPorts::DnsRndc() << ";" << endl;
180 15 : file_ << "};" << endl << endl;
181 :
182 15 : file_.flush();
183 15 : file_.close();
184 15 : }
185 :
186 87 : void NamedConfig::WriteOptionsConfig() {
187 87 : file_ << "options {" << endl;
188 87 : file_ << " directory \"" << named_config_dir_ << "\";" << endl;
189 87 : file_ << " managed-keys-directory \"" << named_config_dir_ << "\";" << endl;
190 87 : file_ << " empty-zones-enable no;" << endl;
191 87 : file_ << " pid-file \"" << GetPidFilePath() << "\";" << endl;
192 87 : file_ << " session-keyfile \"" << GetSessionKeyFilePath() << "\";" << endl;
193 87 : file_ << " listen-on port " << Dns::GetDnsPort() << " { any; };" << endl;
194 87 : file_ << " allow-query { any; };" << endl;
195 87 : file_ << " allow-recursion { any; };" << endl;
196 87 : file_ << " allow-query-cache { any; };" << endl;
197 87 : if (!named_max_cache_size_.empty())
198 87 : file_ << " max-cache-size " << named_max_cache_size_ << ";" << endl;
199 87 : file_ << "};" << endl << endl;
200 87 : }
201 :
202 87 : void NamedConfig::WriteRndcConfig() {
203 87 : file_ << "key \"rndc-key\" {" << endl;
204 87 : file_ << " algorithm hmac-md5;" << endl;
205 87 : file_ << " secret \"" << rndc_secret_ << "\";" << endl;
206 87 : file_ << "};" << endl << endl;
207 :
208 :
209 87 : file_ << "controls {" << endl;
210 87 : file_ << " inet 127.0.0.1 port "<< ContrailPorts::DnsRndc() << endl;
211 87 : file_ << " allow { 127.0.0.1; } keys { \"rndc-key\"; };" << endl;
212 87 : file_ << "};" << endl << endl;
213 87 : }
214 :
215 87 : void NamedConfig::WriteLoggingConfig() {
216 87 : file_ << "logging {" << endl;
217 87 : file_ << " channel debug_log {" << endl;
218 87 : file_ << " file \"" << named_log_file_ << "\" versions 3 size 5m;" << endl;
219 87 : file_ << " severity debug;" << endl;
220 87 : file_ << " print-time yes;" << endl;
221 87 : file_ << " print-severity yes;" << endl;
222 87 : file_ << " print-category yes;" << endl;
223 87 : file_ << " };" << endl;
224 87 : file_ << " category default {" << endl;
225 87 : file_ << " debug_log;" << endl;
226 87 : file_ << " };" << endl;
227 87 : file_ << " category queries {" << endl;
228 87 : file_ << " debug_log;" << endl;
229 87 : file_ << " };" << endl;
230 87 : file_ << "};" << endl << endl;
231 87 : }
232 :
233 87 : void NamedConfig::WriteViewConfig(const VirtualDnsConfig *updated_vdns) {
234 87 : ZoneViewMap zone_view_map;
235 87 : if (reset_flag_) {
236 15 : WriteDefaultView(zone_view_map);
237 15 : return;
238 : }
239 :
240 72 : VirtualDnsConfig::DataMap vdns = VirtualDnsConfig::GetVirtualDnsMap();
241 306 : for (VirtualDnsConfig::DataMap::iterator it = vdns.begin(); it != vdns.end(); ++it) {
242 234 : VirtualDnsConfig *curr_vdns = it->second;
243 234 : ZoneList zones;
244 234 : MakeZoneList(curr_vdns, zones);
245 :
246 234 : if (curr_vdns->IsDeleted() || !curr_vdns->IsNotified()) {
247 17 : RemoveZoneFiles(curr_vdns, zones);
248 17 : continue;
249 : }
250 :
251 217 : std::string view_name = curr_vdns->GetViewName();
252 217 : file_ << "view \"" << view_name << "\" {" << endl;
253 :
254 217 : std::string order = curr_vdns->GetRecordOrder();
255 217 : if (!order.empty()) {
256 217 : if (order == "round-robin")
257 52 : order = "cyclic";
258 217 : file_ << " rrset-order {order " << order << ";};" << endl;
259 : }
260 :
261 217 : std::string next_dns = curr_vdns->GetNextDns();
262 217 : if (!next_dns.empty()) {
263 215 : boost::system::error_code ec;
264 : boost::asio::ip::address_v4
265 215 : next_addr(boost::asio::ip::address_v4::from_string(next_dns, ec));
266 215 : if (!ec.value()) {
267 0 : file_ << " forwarders {" << next_addr.to_string() << ";};" << endl;
268 : } else {
269 215 : file_ << " virtual-forwarder \"" << next_dns << "\";" << endl;
270 : }
271 2 : } else if (!default_forwarders_.empty()) {
272 0 : file_ << " forwarders {" << default_forwarders_ << "};" << endl;
273 : }
274 :
275 217 : bool reverse_resolution = curr_vdns->IsReverseResolutionEnabled();
276 886 : for (unsigned int i = 0; i < zones.size(); i++) {
277 669 : WriteZone(view_name, zones[i], true, reverse_resolution, next_dns);
278 : // update the zone view map, to be used to generate default view
279 669 : if (curr_vdns->IsExternalVisible())
280 347 : zone_view_map.insert(ZoneViewPair(zones[i], view_name));
281 :
282 : }
283 :
284 217 : file_ << "};" << endl << endl;
285 :
286 217 : if (curr_vdns == updated_vdns || all_zone_files_)
287 19 : AddZoneFiles(zones, curr_vdns);
288 234 : }
289 :
290 72 : WriteDefaultView(zone_view_map);
291 87 : }
292 :
293 87 : void NamedConfig::WriteDefaultView(ZoneViewMap &zone_view_map) {
294 : // Create a default view first for any requests which do not have
295 : // view name TXT record
296 87 : file_ << "view \"_default_view_\" {" << endl;
297 87 : file_ << " match-clients {any;};" << endl;
298 87 : file_ << " match-destinations {any;};" << endl;
299 87 : file_ << " match-recursive-only no;" << endl;
300 87 : if (!default_forwarders_.empty()) {
301 0 : file_ << " forwarders {" << default_forwarders_ << "};" << endl;
302 : }
303 87 : for (ZoneViewMap::iterator it = zone_view_map.begin();
304 434 : it != zone_view_map.end(); ++it) {
305 347 : WriteZone(it->second, it->first, false, false, "");
306 : }
307 87 : file_ << "};" << endl << endl;
308 87 : }
309 :
310 1016 : void NamedConfig::WriteZone(const string &vdns, const string &name,
311 : bool is_master, bool is_rr, const string &next_dns) {
312 1016 : file_ << " zone \"" << name << "\" IN {" << endl;
313 1016 : if (is_master) {
314 669 : file_ << " type master;" << endl;
315 669 : file_ << " file \"" << GetZoneFilePath(vdns, name) << "\";" << endl;
316 669 : file_ << " allow-update {127.0.0.1;};" << endl;
317 669 : if (!next_dns.empty()) {
318 666 : if (!is_rr && BindUtil::IsReverseZone(name)) {
319 218 : file_ << " forwarders { };" << endl;
320 : }
321 : } else {
322 3 : file_ << " forwarders { };" << endl;
323 : }
324 : } else {
325 347 : file_ << " type static-stub;" << endl;
326 347 : file_ << " virtual-server-name \"" << vdns << "\";" << endl;
327 347 : file_ << " server-addresses {127.0.0.1;};" << endl;
328 : }
329 1016 : file_ << " };" << endl;
330 1016 : }
331 :
332 32 : void NamedConfig::AddZoneFiles(ZoneList &zones, const VirtualDnsConfig *vdns) {
333 135 : for (unsigned int i = 0; i < zones.size(); i++) {
334 103 : CreateZoneFile(zones[i], vdns, !BindUtil::IsReverseZone(zones[i]));
335 : }
336 32 : }
337 :
338 46 : void NamedConfig::RemoveZoneFiles(const VirtualDnsConfig *vdns,
339 : ZoneList &zones) {
340 113 : for (unsigned int i = 0; i < zones.size(); i++) {
341 67 : RemoveZoneFile(vdns, zones[i]);
342 : }
343 46 : }
344 :
345 67 : void NamedConfig::RemoveZoneFile(const VirtualDnsConfig *vdns, string &zone) {
346 67 : string zfile_name = GetZoneFilePath(vdns->GetViewName(), zone);
347 67 : remove(zfile_name.c_str());
348 67 : zfile_name.append(".jnl");
349 67 : remove(zfile_name.c_str());
350 67 : }
351 :
352 0 : string NamedConfig::GetZoneFileName(const string &vdns, const string &name) {
353 0 : if (name.size() && name.at(name.size() - 1) == '.')
354 0 : return (vdns + "." + name + NamedZoneFileSuffix);
355 : else
356 0 : return (vdns + "." + name + "." + NamedZoneFileSuffix);
357 : }
358 :
359 0 : string NamedConfig::GetZoneFilePath(const string &vdns, const string &name) {
360 0 : return (named_config_dir_ + GetZoneFileName(vdns, name));
361 : }
362 :
363 87 : string NamedConfig::GetPidFilePath() {
364 87 : return (named_config_dir_ + pid_file_name);
365 : }
366 :
367 87 : string NamedConfig::GetSessionKeyFilePath() {
368 87 : return (named_config_dir_ + sessionkey_file_name);
369 : }
370 :
371 206 : string NamedConfig::GetZoneNSName(const string domain_name) {
372 412 : return (NamedZoneNSPrefix + "." + domain_name);
373 : }
374 :
375 103 : string NamedConfig::GetZoneMXName(const string domain_name) {
376 206 : return (NamedZoneMXPrefix + "." + domain_name);
377 : }
378 :
379 103 : void NamedConfig::CreateZoneFile(std::string &zone_name,
380 : const VirtualDnsConfig *vdns, bool ns) {
381 103 : ofstream zfile;
382 103 : string ns_name;
383 103 : string zone_filename = GetZoneFilePath(vdns->GetViewName(), zone_name);
384 :
385 103 : zfile.open(zone_filename.c_str());
386 103 : zfile << "$ORIGIN ." << endl;
387 103 : if (vdns->GetTtl() > 0) {
388 103 : zfile << "$TTL " << vdns->GetTtl() << endl;
389 : } else {
390 0 : zfile << "$TTL " << Defaults::GlobalTTL << endl;
391 : }
392 103 : zfile << left << setw(NameWidth) << zone_name << " IN SOA " <<
393 206 : GetZoneNSName(vdns->GetDomainName()) << " " <<
394 206 : GetZoneMXName(vdns->GetDomainName()) << " (" << endl;
395 103 : zfile << setw(NameWidth + 8) << "" << setw(NumberWidth) << Defaults::Serial << endl;
396 103 : zfile << setw(NameWidth + 8) << "" << setw(NumberWidth) << Defaults::Refresh << endl;
397 103 : zfile << setw(NameWidth + 8) << "" << setw(NumberWidth) << Defaults::Retry << endl;
398 103 : zfile << setw(NameWidth + 8) << "" << setw(NumberWidth) << Defaults::Expire << endl;
399 103 : if (vdns->GetNegativeCacheTtl() > 0 ) {
400 2 : zfile << setw(NameWidth + 8) << "" << setw(NumberWidth) << vdns->GetNegativeCacheTtl() << endl;
401 : } else {
402 101 : zfile << setw(NameWidth + 8) << "" << setw(NumberWidth) << Defaults::Minimum << endl;
403 : }
404 103 : zfile << setw(NameWidth + 8) << "" << ")" << endl;
405 : /* NS records are mandatory in zone file. They are required for the following reasons
406 : 1. Name servers returns NS RR in responses to queries, in the authority section
407 : of the DNS message.
408 : 2. Name servers use the NS records to determine where to send NOTIFY messages.
409 : */
410 : zfile << setw(NameWidth + 4) << "" << setw(TypeWidth) << " NS " <<
411 103 : setw(NameWidth) << GetZoneNSName(vdns->GetDomainName()) << endl;
412 103 : zfile << "$ORIGIN " << zone_name << endl;
413 : //Write the NS record
414 103 : if (ns)
415 19 : zfile << setw(NameWidth) << NamedZoneNSPrefix << " IN A " << Dns::GetSelfIp() << endl;
416 103 : zfile.flush();
417 103 : zfile.close();
418 103 : }
419 :
420 : // Create a list of zones for the virtual DNS
421 263 : void NamedConfig::MakeZoneList(const VirtualDnsConfig *vdns_config,
422 : ZoneList &zones) {
423 : // always take domain name in lower case, to avoid differences due to case
424 526 : std::string dns_domain = boost::to_lower_copy(vdns_config->GetDomainName());
425 263 : if (dns_domain.empty()) {
426 0 : return;
427 : }
428 :
429 : // Forward Zone
430 263 : zones.push_back(dns_domain);
431 :
432 : // Reverse zones
433 263 : MakeReverseZoneList(vdns_config, zones);
434 263 : }
435 :
436 263 : void NamedConfig::MakeReverseZoneList(const VirtualDnsConfig *vdns_config,
437 : ZoneList &zones) {
438 263 : const VirtualDnsConfig::IpamList &ipams = vdns_config->GetIpamList();
439 263 : for (VirtualDnsConfig::IpamList::const_iterator ipam_it = ipams.begin();
440 443 : ipam_it != ipams.end(); ++ipam_it) {
441 180 : if ((*ipam_it)->IsDeleted() || !(*ipam_it)->IsValid()) {
442 28 : continue;
443 : }
444 152 : const IpamConfig::VnniList &vnni_list = (*ipam_it)->GetVnniList();
445 152 : for (IpamConfig::VnniList::iterator vnni_it = vnni_list.begin();
446 387 : vnni_it != vnni_list.end(); ++vnni_it) {
447 235 : if ((*vnni_it)->IsDeleted() || !(*vnni_it)->IsValid()) {
448 22 : continue;
449 : }
450 213 : const Subnets &subnets = (*vnni_it)->GetSubnets();
451 496 : for (unsigned int i = 0; i < subnets.size(); ++i) {
452 283 : const Subnet &subnet = subnets[i];
453 283 : if (subnet.IsDeleted())
454 0 : continue;
455 283 : subnet.GetReverseZones(zones);
456 : }
457 : }
458 : }
459 :
460 : // If same subnet is used in different VNs, remove duplicates
461 263 : std::sort(zones.begin(), zones.end());
462 263 : ZoneList::iterator it = std::unique(zones.begin(), zones.end());
463 263 : zones.resize(std::distance(zones.begin(), it));
464 263 : }
465 :
466 87 : void NamedConfig::GetDefaultForwarders() {
467 87 : default_forwarders_.clear();
468 87 : std::ifstream fd;
469 87 : fd.open(GetResolveFile().c_str());
470 87 : if (!fd.is_open()) {
471 87 : return;
472 : }
473 :
474 0 : std::string line;
475 0 : while (getline(fd, line)) {
476 0 : std::size_t pos = line.find_first_of("#");
477 0 : std::stringstream ss(line.substr(0, pos));
478 0 : std::string key;
479 0 : ss >> key;
480 0 : if (key == "nameserver") {
481 0 : std::string ip;
482 0 : ss >> ip;
483 0 : boost::system::error_code ec;
484 0 : boost::asio::ip::address_v4::from_string(ip, ec);
485 0 : if (!ec.value()) {
486 0 : default_forwarders_ += ip + "; ";
487 : }
488 0 : }
489 0 : }
490 :
491 0 : fd.close();
492 87 : }
493 :
494 : ///////////////////////////////////////////////////////////////////////////////
495 :
496 15 : BindStatus::BindStatus(BindEventHandler handler)
497 15 : : named_pid_(-1), handler_(handler), change_timeout_(true) {
498 30 : status_timer_ = TimerManager::CreateTimer(
499 15 : *Dns::GetEventManager()->io_service(), "BindStatusTimer",
500 : TaskScheduler::GetInstance()->GetTaskId("dns::BindStatus"), 0);
501 15 : status_timer_->Start(kInitTimeout,
502 : boost::bind(&BindStatus::CheckBindStatus, this));
503 15 : }
504 :
505 15 : BindStatus::~BindStatus() {
506 15 : status_timer_->Cancel();
507 15 : TimerManager::DeleteTimer(status_timer_);
508 15 : }
509 :
510 : // Check if a given pid belongs to contrail-named
511 0 : bool BindStatus::IsBindPid(uint32_t pid) {
512 0 : bool ret = false;
513 0 : std::stringstream str;
514 0 : str << "/proc/" << pid << "/cmdline";
515 :
516 0 : ifstream ifile(str.str().c_str());
517 0 : if (ifile.is_open()) {
518 0 : if (ifile.good()) {
519 0 : std::string cmdline;
520 0 : cmdline.assign((istreambuf_iterator<char>(ifile)),
521 : istreambuf_iterator<char>());
522 0 : istringstream cmdstream(cmdline);
523 0 : if (cmdstream.str().find("/usr/bin/contrail-named") !=
524 : std::string::npos) {
525 0 : ret = true;
526 : }
527 0 : }
528 0 : ifile.close();
529 : }
530 :
531 0 : return ret;
532 0 : }
533 :
534 0 : bool BindStatus::CheckBindStatus() {
535 0 : uint32_t new_pid = -1;
536 0 : NamedConfig *ncfg = NamedConfig::GetNamedConfigObject();
537 0 : if (ncfg) {
538 0 : std::ifstream pid_file(ncfg->GetPidFilePath().c_str());
539 0 : if (pid_file.is_open()) {
540 0 : if (pid_file.good()) {
541 0 : pid_file >> new_pid;
542 : }
543 0 : pid_file.close();
544 : }
545 0 : }
546 :
547 0 : if (new_pid == (uint32_t) -1) {
548 0 : handler_(Down);
549 0 : } else if (!IsBindPid(new_pid)) {
550 0 : if (named_pid_ != (uint32_t) -1) {
551 0 : named_pid_ = -1;
552 0 : handler_(Down);
553 : }
554 : } else {
555 0 : if (named_pid_ != new_pid) {
556 0 : named_pid_ = new_pid;
557 0 : handler_(Up);
558 : }
559 : }
560 :
561 0 : if (change_timeout_) {
562 0 : change_timeout_ = false;
563 0 : status_timer_->Reschedule(kBindStatusTimeout);
564 : }
565 0 : return true;
566 : }
|