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: 153 472 32.4 %
Date: 2026-06-04 02:06:09 Functions: 19 46 41.3 %
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 "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           2 : void DnsProto::IoShutdown() {
      26           2 :     BindResolver::Shutdown();
      27             : 
      28           2 :     for (DnsBindQueryMap::iterator it = dns_query_map_.begin();
      29           2 :          it != dns_query_map_.end(); ) {
      30           0 :         DnsBindQueryMap::iterator next = it++;
      31           0 :         delete it->second;
      32           0 :         it = next;
      33             :     }
      34             : 
      35           2 :     curr_vm_requests_.clear();
      36             :     // Following tables should be deleted when all VMs are gone
      37           2 :     assert(update_set_.empty());
      38           2 :     assert(all_vms_.empty());
      39           2 : }
      40             : 
      41           2 : void DnsProto::ConfigInit() {
      42           2 :     BuildDefaultServerList();
      43           2 :     default_slist_timer_->Start(kDnsDefaultSlistInterval,
      44             :                                 boost::bind(&DnsProto::BuildDefaultServerList,
      45             :                                 this));
      46           2 :     std::vector<BindResolver::DnsServer> dns_servers;
      47           6 :     for (int i = 0; i < MAX_XMPP_SERVERS; i++) {
      48           4 :         std::string server = agent()->dns_server(i);
      49           4 :         if (server != "")
      50           2 :             dns_servers.push_back(BindResolver::DnsServer(
      51           2 :                                   server, agent()->dns_server_port(i)));
      52           4 :     }
      53           2 :     GlobalQosConfig* qos = NULL;
      54           2 :     uint8_t dscp = 0;
      55           2 :     if (agent_->oper_db()) {
      56           2 :         qos = agent_->oper_db()->global_qos_config();
      57             :     }
      58           2 :     if (qos && qos->control_dscp() != GlobalQosConfig::kInvalidDscp) {
      59           2 :         dscp = qos->dns_dscp();
      60             :     }
      61           4 :     BindResolver::Init(*agent()->event_manager()->io_service(), dns_servers,
      62           2 :                        agent()->params()->dns_client_port(),
      63             :                        boost::bind(&DnsProto::SendDnsIpc, this, _1, _2), dscp);
      64           2 : }
      65             : 
      66           2 : DnsProto::DnsProto(Agent *agent, boost::asio::io_context &io) :
      67             :     Proto(agent, "Agent::Services", PktHandler::DNS, io),
      68           2 :     xid_(0), timeout_(agent->params()->dns_timeout()),
      69           4 :     max_retries_(agent->params()->dns_max_retries()) {
      70             :     // limit the number of entries in the workqueue
      71           2 :     work_queue_.SetSize(agent->params()->services_queue_limit());
      72           2 :     work_queue_.SetBounded(true);
      73           2 :     def_server_list_.clear();
      74           2 :     default_slist_timer_ = TimerManager::CreateTimer(io, "DnsDefSlistTimer",
      75             :                            TaskScheduler::GetInstance()->
      76             :                            GetTaskId("Agent::Services"), PktHandler::DNS);
      77             : 
      78           2 :     lid_ = agent->interface_table()->Register(
      79             :                   boost::bind(&DnsProto::InterfaceNotify, this, _2));
      80           2 :     Vnlid_ = agent->vn_table()->Register(
      81             :                   boost::bind(&DnsProto::VnNotify, this, _2));
      82           2 :     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           2 :     agent->domain_config_table()->RegisterIpamCb(
      88             :                   boost::bind(&DnsProto::IpamNotify, this, _1));
      89           2 :     agent->domain_config_table()->RegisterVdnsCb(
      90             :                   boost::bind(&DnsProto::VdnsNotify, this, _1));
      91             :     agent->interface_table()->set_update_floatingip_cb
      92           2 :         (boost::bind(&DnsProto::UpdateFloatingIp, this, _1, _2, _3, _4));
      93             : 
      94             :     AgentDnsXmppChannel::set_dns_message_handler_cb
      95           2 :         (boost::bind(&DnsProto::SendDnsUpdateIpc, this, _1, _2, _3, _4));
      96             :     AgentDnsXmppChannel::set_dns_xmpp_event_handler_cb
      97           2 :         (boost::bind(&DnsProto::SendDnsUpdateIpc, this, _1));
      98           2 : }
      99             : 
     100           4 : DnsProto::~DnsProto() {
     101           4 : }
     102             : 
     103           2 : void DnsProto::Shutdown() {
     104           2 :     agent_->interface_table()->Unregister(lid_);
     105           2 :     agent_->vn_table()->Unregister(Vnlid_);
     106           2 :     if (agent_->tsn_enabled()) {
     107           0 :         agent_->vrf_table()->Unregister(vrf_table_listener_id_);
     108             :     }
     109           2 :     default_slist_timer_->Cancel();
     110           2 :     TimerManager::DeleteTimer(default_slist_timer_);
     111           2 : }
     112             : 
     113           2 : bool DnsProto::BuildDefaultServerList() {
     114           2 :     def_server_list_ = BuildDefaultServerListImpl(); // assign new contents
     115           2 :     return true;
     116             : }
     117             : 
     118           0 : std::vector<IpAddress> DnsProto::GetDefaultServerList() {
     119           0 :     return def_server_list_;
     120             : }
     121             : 
     122          60 : ProtoHandler *DnsProto::AllocProtoHandler(boost::shared_ptr<PktInfo> info,
     123             :                                           boost::asio::io_context &io) {
     124          60 :     return new DnsHandler(agent(), info, io);
     125             : }
     126             : 
     127         144 : void DnsProto::InterfaceNotify(DBEntryBase *entry) {
     128         144 :     Interface *itf = static_cast<Interface *>(entry);
     129         144 :     if (itf->type() != Interface::VM_INTERFACE)
     130          19 :         return;
     131             : 
     132         125 :     const VmInterface *vmitf = static_cast<VmInterface *>(entry);
     133         125 :     if (entry->IsDeleted()) {
     134          30 :         SendDnsUpdateIpc(NULL, DnsAgentXmpp::Update, vmitf, false);
     135          30 :         SendDnsUpdateIpc(NULL, DnsAgentXmpp::Update, vmitf, true);
     136          30 :         all_vms_.erase(vmitf);
     137          30 :         DNS_BIND_TRACE(DnsBindTrace, "Vm Interface deleted : " <<
     138             :                        vmitf->vm_name());
     139             :         // remove floating ip entries from fip list
     140          30 :         const VmInterface::FloatingIpList &fip = vmitf->floating_ip_list();
     141          60 :         for (VmInterface::FloatingIpSet::iterator it = fip.list_.begin(),
     142          60 :              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          95 :         autogen::VirtualDnsType vdns_type;
     148          95 :         std::string vdns_name;
     149          95 :         GetVdnsData(vmitf->vn(), vmitf->primary_ip_addr(),
     150             :                     vmitf->primary_ip6_addr(),
     151             :                     vdns_name, vdns_type);
     152          95 :         VmDataMap::iterator it = all_vms_.find(vmitf);
     153          95 :         if (it == all_vms_.end()) {
     154          30 :             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          30 :             IpVdnsMap vmdata;
     159          30 :             vmdata.insert(IpVdnsPair(vmitf->primary_ip_addr().to_ulong(), vdns_name));
     160          30 :             all_vms_.insert(VmDataPair(vmitf, vmdata));
     161          30 :             DNS_BIND_TRACE(DnsBindTrace, "Vm Interface added : " <<
     162             :                            vmitf->vm_name());
     163          30 :         } else {
     164          65 :             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          95 :         if (vmitf->vn()) {
     174          51 :             const VmInterface::FloatingIpList &fip = vmitf->floating_ip_list();
     175          51 :             for (VmInterface::FloatingIpSet::iterator it = fip.list_.begin();
     176          51 :                  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          95 :     }
     184             : }
     185             : 
     186          61 : void DnsProto::VnNotify(DBEntryBase *entry) {
     187          61 :     const VnEntry *vn = static_cast<const VnEntry *>(entry);
     188          61 :     if (vn->IsDeleted()) {
     189             :         // remove floating ip entries from this vn in floating ip list
     190             :         // Ip4Address is the smallest address
     191          20 :         IpAddress ip_key = Ip4Address(0);
     192          20 :         DnsFipEntryPtr key(new DnsFipEntry(vn, ip_key, NULL));
     193          20 :         DnsFipSet::iterator it = fip_list_.upper_bound(key);
     194          20 :         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          20 :         return;
     204          20 :     }
     205          41 :     if (vn->GetVnIpam().size() == 0)
     206           0 :         return;
     207          41 :     DNS_BIND_TRACE(DnsBindTrace, "Vn Notify : " << vn->GetName());
     208         119 :     for (VmDataMap::iterator it = all_vms_.begin(); it != all_vms_.end(); ++it) {
     209          78 :         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          41 :     IpAddress ip_key = Ip4Address(0);
     222          41 :     DnsFipEntryPtr key(new DnsFipEntry(vn, ip_key, NULL));
     223          41 :     DnsFipSet::iterator it = fip_list_.upper_bound(key);
     224          41 :     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          41 : }
     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          74 : void DnsProto::IpamNotify(IFMapNode *node) {
     268          74 :     if (node->IsDeleted())
     269          56 :         return;
     270          18 :     DNS_BIND_TRACE(DnsBindTrace, "Ipam Notify : " << node->name());
     271          18 :     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          18 : void DnsProto::ProcessNotify(std::string name, bool is_deleted, bool is_ipam) {
     288          36 :     for (VmDataMap::iterator it = all_vms_.begin(); it != all_vms_.end(); ++it) {
     289          18 :         std::string vdns_name;
     290          18 :         autogen::VirtualDnsType vdns_type;
     291          18 :         GetVdnsData(it->first->vn(), it->first->primary_ip_addr(),
     292          18 :                     it->first->primary_ip6_addr(), vdns_name, vdns_type);
     293             :         // in case of VDNS delete, clear the name
     294          18 :         if (!is_ipam && is_deleted && vdns_name == name)
     295           0 :             vdns_name.clear();
     296          18 :         CheckForUpdate(it->second, it->first, it->first->vn(),
     297          18 :                        it->first->primary_ip_addr(),
     298          18 :                        it->first->primary_ip6_addr(),
     299             :                        vdns_name, vdns_type);
     300          18 :     }
     301          18 :     DnsFipSet::iterator it = fip_list_.begin();
     302          18 :     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          18 : }
     320             : 
     321          83 : 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          83 :     IpVdnsMap::iterator vmdata_it = ipvdns.find(ip.to_ulong());
     326          83 :     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          83 :     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          83 :     } 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          30 : 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          30 :     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          30 :     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         113 : 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         113 :     if (!vn)
     592          62 :         return false;
     593             : 
     594          51 :     autogen::IpamType ipam_type;
     595          51 :     if ((!v4_addr.to_ulong() ||
     596         137 :          !vn->GetIpamVdnsData(v4_addr, &ipam_type, &vdns_type)) &&
     597          51 :         (v6_addr.is_unspecified() ||
     598          86 :          !vn->GetIpamVdnsData(v6_addr, &ipam_type, &vdns_type))) {
     599          51 :         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          51 :         return false;
     603             :     }
     604             : 
     605           0 :     vdns_name = ipam_type.ipam_dns_server.virtual_dns_server_name;
     606           0 :     return true;
     607          51 : }
     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          60 : void DnsProto::SendDnsUpdateIpc(DnsUpdateData *data,
     653             :                                 DnsAgentXmpp::XmppType type,
     654             :                                 const VmInterface *vm, bool floating) {
     655          60 :     DnsUpdateIpc *ipc = new DnsUpdateIpc(type, data, vm, floating);
     656          60 :     agent_->pkt()->pkt_handler()->SendMessage(PktHandler::DNS, ipc);
     657          60 : }
     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          61 : DnsProto::DnsFipEntry::DnsFipEntry(const VnEntry *vn, const IpAddress &fip,
     743          61 :                                    const VmInterface *itf)
     744          61 :     : vn_(vn), floating_ip_(fip), interface_(itf) {
     745          61 : }
     746             : 
     747         122 : DnsProto::DnsFipEntry::~DnsFipEntry() {
     748         122 : }
     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             : }

Generated by: LCOV version 1.14