Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include <sys/types.h>
6 : #include "base/address_util.h"
7 : #include "init/agent_init.h"
8 : #include "oper/interface_common.h"
9 : #include "services/dns_proto.h"
10 : #include "bind/bind_resolver.h"
11 : #include "cmn/agent_cmn.h"
12 : #include "init/agent_param.h"
13 : #include "ifmap/ifmap_link.h"
14 : #include "ifmap/ifmap_table.h"
15 : #include "pkt/pkt_init.h"
16 : #include "controller/controller_dns.h"
17 : #include "oper/global_qos_config.h"
18 : #include "oper/vn.h"
19 : #include "oper/route_common.h"
20 : #include <fstream>
21 :
22 : const Ip4Address DnsProto::ip4_unspec_(0);
23 : const Ip6Address DnsProto::ip6_unspec_ = Ip6Address::from_string("::");
24 :
25 0 : void DnsProto::IoShutdown() {
26 0 : BindResolver::Shutdown();
27 :
28 0 : for (DnsBindQueryMap::iterator it = dns_query_map_.begin();
29 0 : it != dns_query_map_.end(); ) {
30 0 : DnsBindQueryMap::iterator next = it++;
31 0 : delete it->second;
32 0 : it = next;
33 : }
34 :
35 0 : curr_vm_requests_.clear();
36 : // Following tables should be deleted when all VMs are gone
37 0 : assert(update_set_.empty());
38 0 : assert(all_vms_.empty());
39 0 : }
40 :
41 0 : void DnsProto::ConfigInit() {
42 0 : BuildDefaultServerList();
43 0 : default_slist_timer_->Start(kDnsDefaultSlistInterval,
44 : boost::bind(&DnsProto::BuildDefaultServerList,
45 : this));
46 0 : std::vector<BindResolver::DnsServer> dns_servers;
47 0 : for (int i = 0; i < MAX_XMPP_SERVERS; i++) {
48 0 : std::string server = agent()->dns_server(i);
49 0 : if (server != "")
50 0 : dns_servers.push_back(BindResolver::DnsServer(
51 0 : server, agent()->dns_server_port(i)));
52 0 : }
53 0 : GlobalQosConfig* qos = NULL;
54 0 : uint8_t dscp = 0;
55 0 : if (agent_->oper_db()) {
56 0 : qos = agent_->oper_db()->global_qos_config();
57 : }
58 0 : if (qos && qos->control_dscp() != GlobalQosConfig::kInvalidDscp) {
59 0 : dscp = qos->dns_dscp();
60 : }
61 0 : BindResolver::Init(*agent()->event_manager()->io_service(), dns_servers,
62 0 : agent()->params()->dns_client_port(),
63 : boost::bind(&DnsProto::SendDnsIpc, this, _1, _2), dscp);
64 0 : }
65 :
66 0 : DnsProto::DnsProto(Agent *agent, boost::asio::io_context &io) :
67 : Proto(agent, "Agent::Services", PktHandler::DNS, io),
68 0 : xid_(0), timeout_(agent->params()->dns_timeout()),
69 0 : max_retries_(agent->params()->dns_max_retries()) {
70 : // limit the number of entries in the workqueue
71 0 : work_queue_.SetSize(agent->params()->services_queue_limit());
72 0 : work_queue_.SetBounded(true);
73 0 : def_server_list_.clear();
74 0 : default_slist_timer_ = TimerManager::CreateTimer(io, "DnsDefSlistTimer",
75 : TaskScheduler::GetInstance()->
76 : GetTaskId("Agent::Services"), PktHandler::DNS);
77 :
78 0 : lid_ = agent->interface_table()->Register(
79 : boost::bind(&DnsProto::InterfaceNotify, this, _2));
80 0 : Vnlid_ = agent->vn_table()->Register(
81 : boost::bind(&DnsProto::VnNotify, this, _2));
82 0 : if (agent->tsn_enabled()) {
83 0 : vrf_table_listener_id_ =
84 0 : agent->vrf_table()->Register(boost::bind(&DnsProto::VrfNotify,
85 : this, _2));
86 : }
87 0 : agent->domain_config_table()->RegisterIpamCb(
88 : boost::bind(&DnsProto::IpamNotify, this, _1));
89 0 : agent->domain_config_table()->RegisterVdnsCb(
90 : boost::bind(&DnsProto::VdnsNotify, this, _1));
91 : agent->interface_table()->set_update_floatingip_cb
92 0 : (boost::bind(&DnsProto::UpdateFloatingIp, this, _1, _2, _3, _4));
93 :
94 : AgentDnsXmppChannel::set_dns_message_handler_cb
95 0 : (boost::bind(&DnsProto::SendDnsUpdateIpc, this, _1, _2, _3, _4));
96 : AgentDnsXmppChannel::set_dns_xmpp_event_handler_cb
97 0 : (boost::bind(&DnsProto::SendDnsUpdateIpc, this, _1));
98 0 : }
99 :
100 0 : DnsProto::~DnsProto() {
101 0 : }
102 :
103 0 : void DnsProto::Shutdown() {
104 0 : agent_->interface_table()->Unregister(lid_);
105 0 : agent_->vn_table()->Unregister(Vnlid_);
106 0 : if (agent_->tsn_enabled()) {
107 0 : agent_->vrf_table()->Unregister(vrf_table_listener_id_);
108 : }
109 0 : default_slist_timer_->Cancel();
110 0 : TimerManager::DeleteTimer(default_slist_timer_);
111 0 : }
112 :
113 0 : bool DnsProto::BuildDefaultServerList() {
114 0 : def_server_list_ = BuildDefaultServerListImpl(); // assign new contents
115 0 : return true;
116 : }
117 :
118 0 : std::vector<IpAddress> DnsProto::GetDefaultServerList() {
119 0 : return def_server_list_;
120 : }
121 :
122 0 : ProtoHandler *DnsProto::AllocProtoHandler(boost::shared_ptr<PktInfo> info,
123 : boost::asio::io_context &io) {
124 0 : return new DnsHandler(agent(), info, io);
125 : }
126 :
127 0 : void DnsProto::InterfaceNotify(DBEntryBase *entry) {
128 0 : Interface *itf = static_cast<Interface *>(entry);
129 0 : if (itf->type() != Interface::VM_INTERFACE)
130 0 : return;
131 :
132 0 : const VmInterface *vmitf = static_cast<VmInterface *>(entry);
133 0 : if (entry->IsDeleted()) {
134 0 : SendDnsUpdateIpc(NULL, DnsAgentXmpp::Update, vmitf, false);
135 0 : SendDnsUpdateIpc(NULL, DnsAgentXmpp::Update, vmitf, true);
136 0 : all_vms_.erase(vmitf);
137 0 : DNS_BIND_TRACE(DnsBindTrace, "Vm Interface deleted : " <<
138 : vmitf->vm_name());
139 : // remove floating ip entries from fip list
140 0 : const VmInterface::FloatingIpList &fip = vmitf->floating_ip_list();
141 0 : for (VmInterface::FloatingIpSet::iterator it = fip.list_.begin(),
142 0 : next = fip.list_.begin(); it != fip.list_.end(); it = next) {
143 0 : ++next;
144 0 : UpdateFloatingIp(vmitf, it->vn_.get(), it->floating_ip_,true);
145 : }
146 : } else {
147 0 : autogen::VirtualDnsType vdns_type;
148 0 : std::string vdns_name;
149 0 : GetVdnsData(vmitf->vn(), vmitf->primary_ip_addr(),
150 : vmitf->primary_ip6_addr(),
151 : vdns_name, vdns_type);
152 0 : VmDataMap::iterator it = all_vms_.find(vmitf);
153 0 : if (it == all_vms_.end()) {
154 0 : if (!UpdateDnsEntry(vmitf, vmitf->vn(), vmitf->vm_name(), vdns_name,
155 : vmitf->primary_ip_addr(), vmitf->primary_ip6_addr(),
156 : false, false))
157 0 : vdns_name = "";
158 0 : IpVdnsMap vmdata;
159 0 : vmdata.insert(IpVdnsPair(vmitf->primary_ip_addr().to_ulong(), vdns_name));
160 0 : all_vms_.insert(VmDataPair(vmitf, vmdata));
161 0 : DNS_BIND_TRACE(DnsBindTrace, "Vm Interface added : " <<
162 : vmitf->vm_name());
163 0 : } else {
164 0 : CheckForUpdate(it->second, vmitf, vmitf->vn(),
165 : vmitf->primary_ip_addr(), vmitf->primary_ip6_addr(),
166 : vdns_name, vdns_type);
167 : }
168 :
169 : // floating ip activate & de-activate are updated via the callback to
170 : // UpdateFloatingIp; If tenant name is also required in the fip name,
171 : // it may not be available during activate if the vm interface doesnt
172 : // have vn at that time. Invoke Update here to handle that case.
173 0 : if (vmitf->vn()) {
174 0 : const VmInterface::FloatingIpList &fip = vmitf->floating_ip_list();
175 0 : for (VmInterface::FloatingIpSet::iterator it = fip.list_.begin();
176 0 : it != fip.list_.end(); ++it) {
177 0 : if (it->Installed()) {
178 0 : UpdateFloatingIp(vmitf, it->vn_.get(),
179 0 : it->floating_ip_, false);
180 : }
181 : }
182 : }
183 0 : }
184 : }
185 :
186 0 : void DnsProto::VnNotify(DBEntryBase *entry) {
187 0 : const VnEntry *vn = static_cast<const VnEntry *>(entry);
188 0 : if (vn->IsDeleted()) {
189 : // remove floating ip entries from this vn in floating ip list
190 : // Ip4Address is the smallest address
191 0 : IpAddress ip_key = Ip4Address(0);
192 0 : DnsFipEntryPtr key(new DnsFipEntry(vn, ip_key, NULL));
193 0 : DnsFipSet::iterator it = fip_list_.upper_bound(key);
194 0 : while (it != fip_list_.end()) {
195 0 : DnsFipEntry *entry = (*it).get();
196 0 : if (entry->vn_ != vn) {
197 0 : break;
198 : }
199 0 : ++it;
200 0 : UpdateFloatingIp(entry->interface_, entry->vn_,
201 0 : entry->floating_ip_, true);
202 : }
203 0 : return;
204 0 : }
205 0 : if (vn->GetVnIpam().size() == 0)
206 0 : return;
207 0 : DNS_BIND_TRACE(DnsBindTrace, "Vn Notify : " << vn->GetName());
208 0 : for (VmDataMap::iterator it = all_vms_.begin(); it != all_vms_.end(); ++it) {
209 0 : if (it->first->vn() == vn) {
210 0 : std::string vdns_name;
211 0 : autogen::VirtualDnsType vdns_type;
212 0 : GetVdnsData(vn, it->first->primary_ip_addr(),
213 0 : it->first->primary_ip6_addr(),
214 : vdns_name, vdns_type);
215 0 : CheckForUpdate(it->second, it->first, it->first->vn(),
216 0 : it->first->primary_ip_addr(),
217 0 : it->first->primary_ip6_addr(),
218 : vdns_name, vdns_type);
219 0 : }
220 : }
221 0 : IpAddress ip_key = Ip4Address(0);
222 0 : DnsFipEntryPtr key(new DnsFipEntry(vn, ip_key, NULL));
223 0 : DnsFipSet::iterator it = fip_list_.upper_bound(key);
224 0 : while (it != fip_list_.end()) {
225 0 : std::string fip_vdns_name;
226 0 : DnsFipEntry *entry = (*it).get();
227 0 : if (entry->vn_ != vn) {
228 0 : break;
229 : }
230 0 : autogen::VirtualDnsType fip_vdns_type;
231 0 : Ip4Address ip4 = ip4_unspec_;
232 0 : Ip6Address ip6 = ip6_unspec_;
233 0 : if (entry->floating_ip_.is_v4()) {
234 0 : ip4 = entry->floating_ip_.to_v4();
235 : }
236 0 : if (entry->floating_ip_.is_v6()) {
237 0 : ip6 = entry->floating_ip_.to_v6();
238 : }
239 0 : GetVdnsData(entry->vn_, ip4, ip6,
240 : fip_vdns_name, fip_vdns_type);
241 0 : CheckForFipUpdate(entry, fip_vdns_name, fip_vdns_type);
242 0 : ++it;
243 0 : }
244 0 : }
245 :
246 0 : void DnsProto::VrfNotify(DBEntryBase *entry) {
247 0 : VrfEntry *vrf = static_cast<VrfEntry *>(entry);
248 0 : if (vrf->GetName() == agent_->fabric_vrf_name())
249 0 : return;
250 0 : MacAddress address(agent_->vhost_interface()->mac());
251 :
252 0 : if (entry->IsDeleted()) {
253 0 : BridgeAgentRouteTable::Delete(agent_->local_peer(), vrf->GetName(),
254 : address, -1);
255 0 : return;
256 : }
257 :
258 0 : if (vrf->vn()) {
259 0 : BridgeAgentRouteTable::AddBridgeReceiveRoute(agent_->local_peer(),
260 : vrf->GetName(),
261 : address,
262 : vrf->vn()->GetName(),
263 : "pkt0", true);
264 : }
265 : }
266 :
267 0 : void DnsProto::IpamNotify(IFMapNode *node) {
268 0 : if (node->IsDeleted())
269 0 : return;
270 0 : DNS_BIND_TRACE(DnsBindTrace, "Ipam Notify : " << node->name());
271 0 : ProcessNotify(node->name(), node->IsDeleted(), true);
272 : }
273 :
274 0 : void DnsProto::VdnsNotify(IFMapNode *node) {
275 0 : DNS_BIND_TRACE(DnsBindTrace, "Vdns Notify : " << node->name());
276 : // Update any existing records prior to checking for new ones
277 0 : if (!node->IsDeleted()) {
278 : autogen::VirtualDns *virtual_dns =
279 0 : static_cast <autogen::VirtualDns *> (node->GetObject());
280 0 : autogen::VirtualDnsType vdns_type = virtual_dns->data();
281 0 : std::string name = node->name();
282 0 : MoveVDnsEntry(NULL, name, name, vdns_type, false);
283 0 : }
284 0 : ProcessNotify(node->name(), node->IsDeleted(), false);
285 0 : }
286 :
287 0 : void DnsProto::ProcessNotify(std::string name, bool is_deleted, bool is_ipam) {
288 0 : for (VmDataMap::iterator it = all_vms_.begin(); it != all_vms_.end(); ++it) {
289 0 : std::string vdns_name;
290 0 : autogen::VirtualDnsType vdns_type;
291 0 : GetVdnsData(it->first->vn(), it->first->primary_ip_addr(),
292 0 : it->first->primary_ip6_addr(), vdns_name, vdns_type);
293 : // in case of VDNS delete, clear the name
294 0 : if (!is_ipam && is_deleted && vdns_name == name)
295 0 : vdns_name.clear();
296 0 : CheckForUpdate(it->second, it->first, it->first->vn(),
297 0 : it->first->primary_ip_addr(),
298 0 : it->first->primary_ip6_addr(),
299 : vdns_name, vdns_type);
300 0 : }
301 0 : DnsFipSet::iterator it = fip_list_.begin();
302 0 : while (it != fip_list_.end()) {
303 0 : std::string fip_vdns_name;
304 0 : DnsFipEntry *entry = (*it).get();
305 0 : autogen::VirtualDnsType fip_vdns_type;
306 0 : Ip4Address ip4 = ip4_unspec_;
307 0 : Ip6Address ip6 = ip6_unspec_;
308 0 : if (entry->floating_ip_.is_v4()) {
309 0 : ip4 = entry->floating_ip_.to_v4();
310 : }
311 0 : if (entry->floating_ip_.is_v6()) {
312 0 : ip6 = entry->floating_ip_.to_v6();
313 : }
314 0 : GetVdnsData(entry->vn_, ip4, ip6,
315 : fip_vdns_name, fip_vdns_type);
316 0 : CheckForFipUpdate(entry, fip_vdns_name, fip_vdns_type);
317 0 : ++it;
318 0 : }
319 0 : }
320 :
321 0 : void DnsProto::CheckForUpdate(IpVdnsMap &ipvdns, const VmInterface *vmitf,
322 : const VnEntry *vn, const Ip4Address &ip,
323 : const Ip6Address &ip6, std::string &vdns_name,
324 : const autogen::VirtualDnsType &vdns_type) {
325 0 : IpVdnsMap::iterator vmdata_it = ipvdns.find(ip.to_ulong());
326 0 : if (vmdata_it == ipvdns.end()) {
327 0 : if (UpdateDnsEntry(vmitf, vn, vmitf->vm_name(),
328 : vdns_name, ip, ip6, false, false))
329 0 : ipvdns.insert(IpVdnsPair(ip.to_ulong(), vdns_name));
330 : else
331 0 : ipvdns.insert(IpVdnsPair(ip.to_ulong(), ""));
332 0 : return;
333 : }
334 0 : if (vmdata_it->second.empty() && vmdata_it->second != vdns_name) {
335 0 : if (UpdateDnsEntry(vmitf, vn, vmitf->vm_name(),
336 : vdns_name, ip, ip6, false, false))
337 0 : vmdata_it->second = vdns_name;
338 0 : } else if (vmdata_it->second != vdns_name) {
339 0 : if (MoveVDnsEntry(vmitf, vdns_name, vmdata_it->second,
340 : vdns_type, false))
341 0 : vmdata_it->second = vdns_name;
342 : }
343 : }
344 :
345 0 : void DnsProto::CheckForFipUpdate(DnsFipEntry *entry, std::string &vdns_name,
346 : const autogen::VirtualDnsType &vdns_type) {
347 0 : if (entry->vdns_name_.empty() && entry->vdns_name_ != vdns_name) {
348 0 : std::string fip_name;
349 0 : if (!GetFipName(entry->interface_, vdns_type,
350 0 : entry->floating_ip_, fip_name))
351 0 : vdns_name = "";
352 :
353 0 : Ip4Address ip4 = ip4_unspec_;
354 0 : Ip6Address ip6 = ip6_unspec_;
355 0 : if (entry->floating_ip_.is_v4()) {
356 0 : ip4 = entry->floating_ip_.to_v4();
357 : }
358 0 : if (entry->floating_ip_.is_v6()) {
359 0 : ip6 = entry->floating_ip_.to_v6();
360 : }
361 0 : if (UpdateDnsEntry(entry->interface_, entry->vn_, fip_name,
362 : vdns_name, ip4, ip6, true, false)) {
363 0 : entry->vdns_name_.assign(vdns_name);
364 0 : entry->fip_name_ = fip_name;
365 : }
366 0 : } else if (entry->vdns_name_ != vdns_name) {
367 0 : if (MoveVDnsEntry(entry->interface_, vdns_name, entry->vdns_name_,
368 : vdns_type, true)) {
369 0 : entry->vdns_name_.assign(vdns_name);
370 : }
371 : }
372 0 : }
373 :
374 : // Send A & PTR record entries
375 0 : bool DnsProto::SendUpdateDnsEntry(const VmInterface *vmitf,
376 : const std::string &name,
377 : const Ip4Address &ip, uint32_t plen,
378 : const Ip6Address &ip6, uint32_t plen6,
379 : const std::string &vdns_name,
380 : const autogen::VirtualDnsType &vdns_type,
381 : bool is_floating, bool is_delete) {
382 0 : if (!name.size() || !vdns_type.dynamic_records_from_client) {
383 0 : DNS_BIND_TRACE(DnsBindTrace, "Not adding DNS entry; Name = " <<
384 : name << "Dynamic records allowed = " <<
385 : (vdns_type.dynamic_records_from_client ? "yes" : "no"));
386 0 : return false;
387 : }
388 :
389 0 : DnsUpdateData *data = new DnsUpdateData();
390 0 : data->virtual_dns = vdns_name;
391 0 : data->zone = vdns_type.domain_name;
392 :
393 : // Add a DNS record
394 0 : DnsItem item;
395 0 : if (!ip.is_unspecified()) {
396 0 : item.eclass = is_delete ? DNS_CLASS_NONE : DNS_CLASS_IN;
397 0 : item.type = DNS_A_RECORD;
398 0 : item.ttl = is_delete ? 0 : vdns_type.default_ttl_seconds;
399 0 : item.name = name;
400 0 : boost::system::error_code ec;
401 0 : item.data = ip.to_string(ec);
402 0 : data->items.push_back(item);
403 : }
404 :
405 0 : DnsItem ip6_item;
406 0 : if (!ip6.is_unspecified()) {
407 0 : ip6_item.eclass = is_delete ? DNS_CLASS_NONE : DNS_CLASS_IN;
408 0 : ip6_item.type = DNS_AAAA_RECORD;
409 0 : ip6_item.ttl = is_delete ? 0 : vdns_type.default_ttl_seconds;
410 0 : ip6_item.name = name;
411 0 : boost::system::error_code ec;
412 0 : ip6_item.data = ip6.to_string(ec);
413 0 : data->items.push_back(ip6_item);
414 : }
415 :
416 0 : if (data->items.size()) {
417 0 : DNS_BIND_TRACE(DnsBindTrace,
418 : "DNS update sent for : " << item.ToString() <<
419 : " IPv6 : " << ip6_item.ToString() <<
420 : " VDNS : " << data->virtual_dns <<
421 : " Zone : " << data->zone);
422 0 : SendDnsUpdateIpc(data, DnsAgentXmpp::Update, vmitf, is_floating);
423 : } else {
424 0 : DNS_BIND_TRACE(DnsBindTrace, "Not adding DNS entry; Name = " <<
425 : name << "Address unspecified");
426 0 : return false;
427 : }
428 :
429 : // Add a PTR record as well
430 0 : DnsUpdateData *ptr_data = new DnsUpdateData();
431 0 : ptr_data->virtual_dns = vdns_name;
432 0 : BindUtil::GetReverseZone(ip, plen, ptr_data->zone);
433 :
434 0 : item.type = DNS_PTR_RECORD;
435 0 : item.data.swap(item.name);
436 0 : item.name = BindUtil::GetPtrNameFromAddr(ip);
437 0 : ptr_data->items.push_back(item);
438 :
439 0 : DNS_BIND_TRACE(DnsBindTrace, "DNS update sent for : " << item.ToString() <<
440 : " VDNS : " << ptr_data->virtual_dns <<
441 : " Zone : " << ptr_data->zone);
442 0 : SendDnsUpdateIpc(ptr_data, DnsAgentXmpp::Update, vmitf, is_floating);
443 :
444 : // Add a PTR record for IPv6, if present
445 0 : if (!ip6.is_unspecified()) {
446 0 : DnsUpdateData *ptr6_data = new DnsUpdateData();
447 0 : ptr6_data->virtual_dns = vdns_name;
448 0 : BindUtil::GetReverseZone(ip6, plen6, ptr6_data->zone);
449 :
450 0 : ip6_item.type = DNS_PTR_RECORD;
451 0 : ip6_item.data.swap(ip6_item.name);
452 :
453 0 : ip6_item.name = BindUtil::GetPtrNameFromAddr(ip6);
454 0 : ptr6_data->items.push_back(ip6_item);
455 :
456 0 : DNS_BIND_TRACE(DnsBindTrace, "DNS update sent for : " << ip6_item.ToString() <<
457 : " VDNS : " << ptr6_data->virtual_dns <<
458 : " Zone : " << ptr6_data->zone);
459 0 : SendDnsUpdateIpc(ptr6_data, DnsAgentXmpp::Update, vmitf, is_floating);
460 : }
461 :
462 0 : return true;
463 0 : }
464 :
465 : // Update the floating ip entries
466 0 : bool DnsProto::UpdateFloatingIp(const VmInterface *vmitf, const VnEntry *vn,
467 : const IpAddress &ip, bool is_deleted) {
468 0 : Ip4Address ip4 = ip4_unspec_;
469 0 : Ip6Address ip6 = ip6_unspec_;
470 0 : if (ip.is_v6()) {
471 0 : ip6 = ip.to_v6();
472 : }
473 0 : if (ip.is_v4()) {
474 0 : ip4 = ip.to_v4();
475 : }
476 0 : bool is_floating = true;
477 0 : std::string vdns_name;
478 0 : autogen::VirtualDnsType vdns_type;
479 0 : GetVdnsData(vn, ip4, ip6, vdns_name, vdns_type);
480 0 : DnsFipEntryPtr key(new DnsFipEntry(vn, ip, vmitf));
481 0 : DnsFipSet::iterator it = fip_list_.find(key);
482 0 : if (it == fip_list_.end()) {
483 0 : if (is_deleted)
484 0 : return true;
485 0 : std::string fip_name;
486 0 : if (!GetFipName(vmitf, vdns_type, ip, fip_name))
487 0 : vdns_name = "";
488 0 : if (!UpdateDnsEntry(vmitf, vn, fip_name,
489 : vdns_name, ip4, ip6, is_floating, false))
490 0 : vdns_name = "";
491 0 : key.get()->vdns_name_ = vdns_name;
492 0 : key.get()->fip_name_ = fip_name;
493 0 : fip_list_.insert(key);
494 0 : } else {
495 0 : if (is_deleted) {
496 0 : std::string fip_name;
497 0 : UpdateDnsEntry(vmitf, vn, (*it)->fip_name_,
498 0 : (*it)->vdns_name_, ip4, ip6, is_floating, true);
499 0 : fip_list_.erase(key);
500 0 : } else {
501 0 : DnsFipEntry *entry = (*it).get();
502 0 : CheckForFipUpdate(entry, vdns_name, vdns_type);
503 : }
504 : }
505 0 : return true;
506 0 : }
507 :
508 0 : bool DnsProto::UpdateDnsEntry(const VmInterface *vmitf, const VnEntry *vn,
509 : const std::string &vm_name,
510 : const std::string &vdns_name,
511 : const Ip4Address &ip,
512 : const Ip6Address &ip6,
513 : bool is_floating, bool is_deleted) {
514 0 : if (!vdns_name.empty()) {
515 0 : uint32_t plen = 0;
516 0 : const std::vector<VnIpam> &ipam = vn->GetVnIpam();
517 : unsigned int i;
518 0 : if (!ip.is_unspecified()) {
519 0 : for (i = 0; i < ipam.size(); ++i) {
520 0 : if (ipam[i].IsV4() &&
521 0 : IsIp4SubnetMember(ip, ipam[i].ip_prefix.to_v4(), ipam[i].plen)) {
522 0 : plen = ipam[i].plen;
523 0 : break;
524 : }
525 : }
526 0 : if (i == ipam.size()) {
527 0 : DNS_BIND_TRACE(DnsBindTrace, "UpdateDnsEntry for VM <" <<
528 : vm_name << "> not done for vn <" <<
529 : vn->GetName() << "> IPAM doesnt have Ipv4 subnet; " <<
530 : ((is_deleted)? "delete" : "update"));
531 0 : return false;
532 : }
533 : }
534 :
535 0 : uint32_t plen6 = 0;
536 0 : if (!ip6.is_unspecified()) {
537 0 : for (i = 0; i < ipam.size(); ++i) {
538 0 : if (ipam[i].IsV6() &&
539 0 : IsIp6SubnetMember(ip6, ipam[i].ip_prefix.to_v6(), ipam[i].plen)) {
540 0 : plen6 = ipam[i].plen;
541 0 : break;
542 : }
543 : }
544 0 : if (i == ipam.size()) {
545 0 : DNS_BIND_TRACE(DnsBindTrace, "UpdateDnsEntry for VM <" <<
546 : vm_name << "> not done for vn <" <<
547 : vn->GetName() << "> IPAM doesnt have Ipv6 subnet; " <<
548 : ((is_deleted)? "delete" : "update"));
549 0 : return false;
550 : }
551 : }
552 :
553 0 : autogen::VirtualDnsType vdns_type;
554 0 : if (agent_->domain_config_table()->GetVDns(vdns_name, &vdns_type)) {
555 0 : return SendUpdateDnsEntry(vmitf, vm_name, ip, plen, ip6, plen6,
556 : vdns_name, vdns_type, is_floating,
557 0 : is_deleted);
558 : } else {
559 0 : DNS_BIND_TRACE(DnsBindTrace, "UpdateDnsEntry for VM <" <<
560 : vm_name << "> entry not " <<
561 : ((is_deleted)? "deleted; " : "updated; ") <<
562 : "VDNS info for " << vdns_name << " not present");
563 0 : return false;
564 : }
565 0 : }
566 :
567 0 : return true;
568 : }
569 :
570 : // Move DNS entries for a VM from one VDNS to another
571 0 : bool DnsProto::MoveVDnsEntry(const VmInterface *vmitf,
572 : std::string &new_vdns_name,
573 : std::string &old_vdns_name,
574 : const autogen::VirtualDnsType &vdns_type,
575 : bool is_floating) {
576 0 : std::string name = (vmitf ? vmitf->vm_name() : "All Vms");
577 0 : DNS_BIND_TRACE(DnsBindTrace, "VDNS modify for VM <" << name <<
578 : " old VDNS : " << old_vdns_name <<
579 : " new VDNS : " << new_vdns_name <<
580 : " ttl : " << vdns_type.default_ttl_seconds <<
581 : " floating : " << (is_floating ? "yes" : "no"));
582 0 : SendDnsUpdateIpc(vmitf, new_vdns_name,
583 0 : old_vdns_name, vdns_type.domain_name,
584 0 : (uint32_t)vdns_type.default_ttl_seconds, is_floating);
585 0 : return true;
586 0 : }
587 :
588 0 : bool DnsProto::GetVdnsData(const VnEntry *vn, const Ip4Address &v4_addr,
589 : const Ip6Address &v6_addr, std::string &vdns_name,
590 : autogen::VirtualDnsType &vdns_type) {
591 0 : if (!vn)
592 0 : return false;
593 :
594 0 : autogen::IpamType ipam_type;
595 0 : if ((!v4_addr.to_ulong() ||
596 0 : !vn->GetIpamVdnsData(v4_addr, &ipam_type, &vdns_type)) &&
597 0 : (v6_addr.is_unspecified() ||
598 0 : !vn->GetIpamVdnsData(v6_addr, &ipam_type, &vdns_type))) {
599 0 : DNS_BIND_TRACE(DnsBindTrace, "Unable to retrieve VDNS data; VN : " <<
600 : vn->GetName() << " IPv4 : " << v4_addr.to_string() <<
601 : " IPv6 : " << v6_addr.to_string());
602 0 : return false;
603 : }
604 :
605 0 : vdns_name = ipam_type.ipam_dns_server.virtual_dns_server_name;
606 0 : return true;
607 0 : }
608 :
609 0 : bool DnsProto::GetFipName(const VmInterface *vmitf,
610 : const autogen::VirtualDnsType &vdns_type,
611 : const IpAddress &ip, std::string &fip_name) const {
612 : std::string fip_name_notation =
613 0 : boost::to_lower_copy(vdns_type.floating_ip_record);
614 :
615 0 : std::string name;
616 0 : if (fip_name_notation == "" ||
617 0 : fip_name_notation == "dashed-ip" ||
618 0 : fip_name_notation == "dashed-ip-tenant-name") {
619 0 : name = ip.to_string();
620 0 : boost::replace_all(name, ".", "-");
621 : } else {
622 0 : name = vmitf->vm_name();
623 : }
624 :
625 0 : if (fip_name_notation == "" ||
626 0 : fip_name_notation == "dashed-ip-tenant-name" ||
627 0 : fip_name_notation == "vm-name-tenant-name") {
628 0 : if (!vmitf->vn())
629 0 : return false;
630 0 : name += "." + vmitf->vn()->GetProject();
631 : }
632 :
633 0 : fip_name = name;
634 0 : return true;
635 0 : }
636 :
637 0 : uint16_t DnsProto::GetTransId() {
638 0 : return (++xid_ == 0 ? ++xid_ : xid_);
639 : }
640 :
641 0 : void DnsProto::SendDnsIpc(uint8_t *pkt, std::size_t length) {
642 0 : DnsIpc *ipc = new DnsIpc(pkt, length, 0, NULL, DnsProto::DNS_BIND_RESPONSE);
643 0 : agent_->pkt()->pkt_handler()->SendMessage(PktHandler::DNS, ipc);
644 0 : }
645 :
646 0 : void DnsProto::SendDnsIpc(InterTaskMessage cmd, uint16_t xid, uint8_t *msg,
647 : DnsHandler *handler) {
648 0 : DnsIpc *ipc = new DnsIpc(msg, 0, xid, handler, cmd);
649 0 : agent_->pkt()->pkt_handler()->SendMessage(PktHandler::DNS, ipc);
650 0 : }
651 :
652 0 : void DnsProto::SendDnsUpdateIpc(DnsUpdateData *data,
653 : DnsAgentXmpp::XmppType type,
654 : const VmInterface *vm, bool floating) {
655 0 : DnsUpdateIpc *ipc = new DnsUpdateIpc(type, data, vm, floating);
656 0 : agent_->pkt()->pkt_handler()->SendMessage(PktHandler::DNS, ipc);
657 0 : }
658 :
659 0 : void DnsProto::SendDnsUpdateIpc(const VmInterface *vm,
660 : const std::string &new_vdns,
661 : const std::string &old_vdns,
662 : const std::string &new_dom,
663 : uint32_t ttl, bool is_floating) {
664 : DnsUpdateIpc *ipc = new DnsUpdateIpc(vm, new_vdns, old_vdns, new_dom,
665 0 : ttl, is_floating);
666 0 : agent_->pkt()->pkt_handler()->SendMessage(PktHandler::DNS, ipc);
667 0 : }
668 :
669 0 : void DnsProto::SendDnsUpdateIpc(AgentDnsXmppChannel *channel) {
670 0 : DnsUpdateAllIpc *ipc = new DnsUpdateAllIpc(channel);
671 0 : agent_->pkt()->pkt_handler()->SendMessage(PktHandler::DNS, ipc);
672 0 : }
673 :
674 0 : void DnsProto::AddDnsQuery(uint16_t xid, DnsHandler *handler) {
675 0 : dns_query_map_.insert(DnsBindQueryPair(xid, handler));
676 0 : }
677 :
678 0 : void DnsProto::DelDnsQuery(uint16_t xid) {
679 0 : dns_query_map_.erase(xid);
680 0 : }
681 :
682 0 : bool DnsProto::IsDnsQueryInProgress(uint16_t xid) {
683 0 : return dns_query_map_.find(xid) != dns_query_map_.end();
684 : }
685 :
686 0 : bool DnsProto::IsDnsHandlerInUse(DnsHandler *handler) {
687 0 : for (DnsBindQueryMap::iterator it = dns_query_map_.begin();
688 0 : it != dns_query_map_.end(); it++) {
689 0 : if (it->second == handler) {
690 0 : return true;
691 : }
692 : }
693 0 : return false;
694 : }
695 :
696 0 : void DnsProto::DelDnsQueryHandler(DnsHandler *handler) {
697 0 : for (DnsBindQueryMap::iterator it = dns_query_map_.begin();
698 0 : it != dns_query_map_.end();) {
699 0 : if (it->second == handler) {
700 0 : dns_query_map_.erase(it++);
701 0 : continue;
702 : }
703 0 : ++it;
704 : }
705 0 : }
706 :
707 0 : DnsHandler *DnsProto::GetDnsQueryHandler(uint16_t xid) {
708 0 : DnsBindQueryMap::iterator it = dns_query_map_.find(xid);
709 0 : if (it != dns_query_map_.end())
710 0 : return it->second;
711 0 : return NULL;
712 : }
713 :
714 0 : void DnsProto::AddDnsQueryIndex(uint16_t xid, int16_t srv_idx) {
715 0 : dns_query_index_map_.insert(DnsBindQueryIndexPair(xid, srv_idx));
716 0 : }
717 :
718 0 : void DnsProto::DelDnsQueryIndex(uint16_t xid) {
719 0 : dns_query_index_map_.erase(xid);
720 0 : }
721 :
722 0 : int16_t DnsProto::GetDnsQueryServerIndex(uint16_t xid) {
723 0 : DnsBindQueryIndexMap::iterator it = dns_query_index_map_.find(xid);
724 0 : if (it != dns_query_index_map_.end())
725 0 : return it->second;
726 0 : return -1;
727 : }
728 :
729 :
730 0 : void DnsProto::AddVmRequest(DnsHandler::QueryKey *key) {
731 0 : curr_vm_requests_.insert(*key);
732 0 : }
733 :
734 0 : void DnsProto::DelVmRequest(DnsHandler::QueryKey *key) {
735 0 : curr_vm_requests_.erase(*key);
736 0 : }
737 :
738 0 : bool DnsProto::IsVmRequestDuplicate(DnsHandler::QueryKey *key) {
739 0 : return curr_vm_requests_.find(*key) != curr_vm_requests_.end();
740 : }
741 :
742 0 : DnsProto::DnsFipEntry::DnsFipEntry(const VnEntry *vn, const IpAddress &fip,
743 0 : const VmInterface *itf)
744 0 : : vn_(vn), floating_ip_(fip), interface_(itf) {
745 0 : }
746 :
747 0 : DnsProto::DnsFipEntry::~DnsFipEntry() {
748 0 : }
749 :
750 0 : bool DnsProto::DnsFipEntryCmp::operator() (const DnsFipEntryPtr &lhs,
751 : const DnsFipEntryPtr &rhs) const {
752 0 : return lhs->IsLess(rhs.get());
753 : }
754 :
755 0 : bool DnsProto::DnsFipEntry::IsLess(const DnsFipEntry *rhs) const {
756 0 : if (vn_ != rhs->vn_) {
757 0 : return vn_ < rhs->vn_;
758 : }
759 0 : if (floating_ip_ != rhs->floating_ip_) {
760 0 : return floating_ip_ < rhs->floating_ip_;
761 : }
762 0 : return interface_ < rhs->interface_;
763 : }
|