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: 230 478 48.1 %
Date: 2026-11-09 02:10:49 Functions: 24 46 52.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14