LCOV - code coverage report
Current view: top level - vnsw/agent/services - dns_proto.cc (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 0 478 0.0 %
Date: 2026-10-19 02:12:28 Functions: 0 46 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14