Line data Source code
1 : /* 2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved. 3 : */ 4 : 5 : #include "base/logging.h" 6 : #include "base/task_trigger.h" 7 : #include <pugixml/pugixml.hpp> 8 : #include "agent/agent_xmpp_channel.h" 9 : 10 : #include "xml/xml_pugi.h" 11 : #include "xmpp/xmpp_connection.h" 12 : #include "xmpp/xmpp_server.h" 13 : #include "cmn/dns.h" 14 : #include "mgr/dns_mgr.h" 15 : #include "mgr/dns_oper.h" 16 : #include "bind/bind_util.h" 17 : #include "bind/bind_resolver.h" 18 : #include "bind/named_config.h" 19 : #include "bind/xmpp_dns_agent.h" 20 : #include "sandesh/sandesh_trace.h" 21 : #include "cmn/dns_types.h" 22 : 23 0 : DnsAgentXmppChannel:: DnsAgentXmppChannel(XmppChannel *channel, 24 0 : DnsAgentXmppChannelManager *mgr) 25 0 : : channel_(channel), mgr_(mgr) { 26 0 : channel_->RegisterReceive(xmps::DNS, 27 : boost::bind(&DnsAgentXmppChannel::ReceiveReq, this, _1)); 28 : 29 0 : } 30 : 31 0 : DnsAgentXmppChannel::~DnsAgentXmppChannel() { 32 0 : channel_->UnRegisterWriteReady(xmps::DNS); 33 0 : channel_->UnRegisterReceive(xmps::DNS); 34 0 : } 35 : 36 0 : void DnsAgentXmppChannel::Close() { 37 0 : UpdateDnsRecords(BindUtil::DELETE_UPDATE); 38 0 : if (mgr_) 39 0 : mgr_->RemoveChannel(channel_); 40 0 : } 41 : 42 0 : void DnsAgentXmppChannel::ReceiveReq(const XmppStanza::XmppMessage *msg) { 43 0 : if (msg && msg->type == XmppStanza::IQ_STANZA) { 44 0 : XmlBase *impl = msg->dom.get(); 45 0 : XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl); 46 0 : pugi::xml_node node = pugi->FindNode("dns"); 47 : DnsAgentXmpp::XmppType type; 48 0 : std::string source_name = msg->from; 49 : uint32_t xid; 50 : uint16_t code; 51 0 : std::unique_ptr<DnsUpdateData> rcv_data(new DnsUpdateData()); 52 0 : DnsUpdateData *data = rcv_data.get(); 53 0 : if (DnsAgentXmpp::DnsAgentXmppDecode(node, type, xid, code, data, source_name)) { 54 0 : if (type == DnsAgentXmpp::Update) { 55 0 : HandleAgentUpdate(std::move(rcv_data)); 56 : } 57 : } 58 0 : } 59 0 : } 60 : 61 0 : void DnsAgentXmppChannel::HandleAgentUpdate( 62 : std::unique_ptr<DnsUpdateData> rcv_data) { 63 0 : DnsUpdateData *data = rcv_data.get(); 64 0 : if (data->virtual_dns.empty() || data->zone.empty()) { 65 : // if key is not present, ignore the update 66 0 : return; 67 : } 68 0 : DataSet::iterator it = update_data_.find(data); 69 0 : if (it != update_data_.end()) { 70 0 : DnsUpdateData *xmpp_data = *it; 71 0 : for (DnsItems::iterator iter = data->items.begin(); 72 0 : iter != data->items.end();) { 73 : bool change; 74 0 : BindUtil::Operation op = BindUtil::ADD_UPDATE; 75 0 : if ((*iter).IsDelete()) { 76 0 : change = xmpp_data->DelItem(*iter); 77 0 : op = BindUtil::DELETE_UPDATE; 78 : } else { 79 0 : change = xmpp_data->AddItem(*iter, true); 80 0 : if (!change) { 81 0 : op = BindUtil::CHANGE_UPDATE; 82 0 : change = true; 83 : } 84 : } 85 : 86 0 : if (!change) { 87 0 : data->items.erase(iter++); 88 : } else { 89 : boost::shared_ptr<DnsAgentXmppChannelManager::RecordRequest> 90 : req(new DnsAgentXmppChannelManager::RecordRequest( 91 0 : op, GetDnsRecordName(data->virtual_dns, *iter), 92 0 : data->virtual_dns, *iter)); 93 0 : mgr_->EnqueueRecord(req); 94 0 : ++iter; 95 0 : } 96 : } 97 0 : if (!xmpp_data->items.size()) { 98 0 : update_data_.erase(xmpp_data); 99 0 : delete xmpp_data; 100 : } 101 : } else { 102 0 : for (DnsItems::iterator iter = data->items.begin(); 103 0 : iter != data->items.end();) { 104 0 : if ((*iter).IsDelete()) 105 0 : data->items.erase(iter++); 106 : else { 107 : boost::shared_ptr<DnsAgentXmppChannelManager::RecordRequest> 108 : req(new DnsAgentXmppChannelManager::RecordRequest( 109 : BindUtil::ADD_UPDATE, 110 0 : GetDnsRecordName(data->virtual_dns, *iter), 111 0 : data->virtual_dns, *iter)); 112 0 : mgr_->EnqueueRecord(req); 113 0 : ++iter; 114 0 : } 115 : } 116 0 : update_data_.insert(data); 117 0 : rcv_data.release(); 118 : } 119 : } 120 : 121 0 : void DnsAgentXmppChannel::UpdateDnsRecords(BindUtil::Operation op) { 122 0 : for (DataSet::iterator it = update_data_.begin(); 123 0 : it != update_data_.end(); ++it) { 124 0 : for (DnsItems::const_iterator item = (*it)->items.begin(); 125 0 : item != (*it)->items.end(); ++item) { 126 : boost::shared_ptr<DnsAgentXmppChannelManager::RecordRequest> 127 : req(new DnsAgentXmppChannelManager::RecordRequest( 128 0 : op, GetDnsRecordName((*it)->virtual_dns, *item), 129 0 : (*it)->virtual_dns, *item)); 130 0 : mgr_->EnqueueRecord(req); 131 0 : } 132 : } 133 0 : } 134 : 135 0 : std::string DnsAgentXmppChannel::GetDnsRecordName(std::string &vdns_name, 136 : const DnsItem &item) { 137 0 : std::stringstream str; 138 0 : str << vdns_name << ":" << item.type << ":" << item.name << ":" << item.data; 139 0 : return str.str(); 140 0 : } 141 : 142 0 : void DnsAgentXmppChannel::GetAgentDnsData(AgentDnsData &data) { 143 0 : data.set_agent(channel_->connection()->endpoint().address().to_string()); 144 0 : std::vector<AgentDnsDataItem> items; 145 0 : for (DataSet::iterator it = update_data_.begin(); 146 0 : it != update_data_.end(); ++it) { 147 0 : AgentDnsDataItem item; 148 0 : item.set_virtual_dns((*it)->virtual_dns); 149 0 : item.set_zone((*it)->zone); 150 0 : std::vector<VirtualDnsRecordTraceData> records; 151 0 : for (DnsItems::iterator iter = (*it)->items.begin(); 152 0 : iter != (*it)->items.end(); ++iter) { 153 0 : VirtualDnsRecordTraceData record; 154 0 : record.rec_name = (*iter).name; 155 0 : record.rec_type = BindUtil::DnsType((*iter).type); 156 0 : record.rec_class = "IN"; 157 0 : record.rec_data = (*iter).data; 158 0 : record.rec_ttl = (*iter).ttl; 159 0 : record.source = "Agent"; 160 0 : record.installed = "yes"; 161 0 : record.rec_source_name = (*iter).source_name; 162 0 : record.rec_vm_uuid = (*iter).vm_uuid; 163 0 : records.push_back(record); 164 0 : } 165 0 : item.set_records(records); 166 0 : items.push_back(item); 167 0 : } 168 0 : data.set_agent_data(items); 169 0 : } 170 : 171 0 : DnsAgentXmppChannelManager::DnsAgentXmppChannelManager( 172 0 : XmppServer *server) 173 0 : : server_(server), 174 0 : work_queue_(TaskScheduler::GetInstance()->GetTaskId("dns::Config"), 0, 175 : boost::bind(&DnsAgentXmppChannelManager::ProcessRecord, 176 0 : this, _1)) { 177 0 : if (server_) { 178 0 : server_->RegisterConnectionEvent(xmps::DNS, 179 : boost::bind(&DnsAgentXmppChannelManager::HandleXmppChannelEvent, 180 : this, _1, _2)); 181 : } 182 0 : } 183 : 184 0 : DnsAgentXmppChannelManager::~DnsAgentXmppChannelManager() { 185 0 : if (server_) 186 0 : server_->UnRegisterConnectionEvent(xmps::DNS); 187 0 : channel_map_.clear(); 188 0 : work_queue_.Shutdown(); 189 0 : } 190 : 191 0 : bool DnsAgentXmppChannelManager::ProcessRecord( 192 : boost::shared_ptr<RecordRequest> req) { 193 0 : Dns::GetDnsManager()->ProcessAgentUpdate(req->op, req->record_name, 194 0 : req->vdns_name, req->item); 195 0 : return true; 196 : } 197 : 198 0 : void DnsAgentXmppChannelManager::EnqueueRecord( 199 : boost::shared_ptr<RecordRequest> req) { 200 0 : work_queue_.Enqueue(req); 201 0 : } 202 : 203 0 : void DnsAgentXmppChannelManager::RemoveChannel(XmppChannel *ch) { 204 0 : channel_map_.erase(ch); 205 0 : } 206 : 207 : DnsAgentXmppChannel * 208 0 : DnsAgentXmppChannelManager::DnsAgentXmppChannelManager::FindChannel( 209 : const XmppChannel *ch) { 210 0 : std::scoped_lock lock(mutex_); 211 0 : ChannelMap::iterator it = channel_map_.find(ch); 212 0 : if (it == channel_map_.end()) 213 0 : return NULL; 214 0 : return it->second; 215 0 : } 216 : 217 : void 218 0 : DnsAgentXmppChannelManager::HandleXmppChannelEvent(XmppChannel *channel, 219 : xmps::PeerState state) { 220 0 : std::scoped_lock lock(mutex_); 221 0 : ChannelMap::iterator it = channel_map_.find(channel); 222 : 223 0 : if (state == xmps::READY) { 224 0 : if (it == channel_map_.end()) { 225 : DnsAgentXmppChannel *agent_xmpp_channel = 226 0 : new DnsAgentXmppChannel(channel, this); 227 0 : channel_map_.insert(std::make_pair(channel, agent_xmpp_channel)); 228 : ConfigClientManager *config_manager = 229 0 : Dns::GetDnsManager()->get_config_manager(); 230 0 : if (config_manager && !config_manager->GetEndOfRibComputed()) { 231 0 : DNS_XMPP_TRACE(DnsXmppTrace, "Peer:" + channel->PeerAddress() + 232 : " Close due to EndofRib not computed"); 233 0 : channel->Close(); 234 : } 235 : } 236 0 : } else if (state == xmps::NOT_READY) { 237 0 : if (it != channel_map_.end()) { 238 0 : DnsAgentXmppChannel *agent_xmpp_channel = (*it).second; 239 0 : agent_xmpp_channel->Close(); 240 0 : delete agent_xmpp_channel; 241 : } else { 242 0 : DNS_XMPP_TRACE(DnsXmppTrace, 243 : "Peer not found on channel not ready event"); 244 : } 245 : } 246 0 : } 247 : 248 0 : uint8_t DnsAgentXmppChannelManager::ChannelToDscp(const XmppChannel *xc) const { 249 0 : const XmppConnection *conn = xc->connection(); 250 0 : if (conn) { 251 0 : const XmppSession *sess = conn->session(); 252 0 : if (sess) { 253 0 : return sess->GetDscpValue(); 254 : } 255 : } 256 0 : return 0; 257 : } 258 : 259 0 : void DnsAgentXmppChannelManager::GetAgentData(std::vector<AgentData> &list) { 260 0 : std::scoped_lock lock(mutex_); 261 0 : for (ChannelMap::iterator iter = channel_map_.begin(); 262 0 : iter != channel_map_.end(); ++iter) { 263 0 : const XmppChannel *channel = iter->first; 264 0 : AgentData agent_data; 265 0 : agent_data.set_peer(channel->ToString()); 266 0 : agent_data.set_peer_address( 267 0 : channel->connection()->endpoint().address().to_string()); 268 0 : agent_data.set_local_address( 269 0 : channel->connection()->local_endpoint().address().to_string()); 270 0 : agent_data.set_state(channel->StateName()); 271 0 : agent_data.set_last_event(channel->LastEvent()); 272 0 : agent_data.set_last_state(channel->LastStateName()); 273 0 : agent_data.set_last_state_at(channel->LastStateChangeAt()); 274 0 : agent_data.set_dscp(ChannelToDscp(channel)); 275 0 : list.push_back(agent_data); 276 0 : } 277 0 : } 278 : 279 0 : void DnsAgentXmppChannelManager::GetAgentDnsData(std::vector<AgentDnsData> &dt) { 280 0 : std::scoped_lock lock(mutex_); 281 0 : for (ChannelMap::iterator iter = channel_map_.begin(); 282 0 : iter != channel_map_.end(); ++iter) { 283 0 : DnsAgentXmppChannel *ch = iter->second; 284 0 : AgentDnsData data; 285 0 : ch->GetAgentDnsData(data); 286 0 : dt.push_back(data); 287 0 : } 288 0 : } 289 : 290 0 : void ShowAgentList::HandleRequest() const { 291 0 : DnsAgentListResponse *resp = new DnsAgentListResponse(); 292 0 : resp->set_context(context()); 293 : 294 0 : std::vector<AgentData> agent_list_sandesh; 295 0 : Dns::GetAgentXmppChannelManager()->GetAgentData(agent_list_sandesh); 296 : 297 0 : resp->set_agent(agent_list_sandesh); 298 0 : resp->Response(); 299 0 : } 300 : 301 0 : void ShowAgentXmppDnsData::HandleRequest() const { 302 0 : AgentXmppDnsDataResponse *resp = new AgentXmppDnsDataResponse(); 303 0 : resp->set_context(context()); 304 : 305 0 : std::vector<AgentDnsData> agent_data; 306 0 : Dns::GetAgentXmppChannelManager()->GetAgentDnsData(agent_data); 307 : 308 0 : resp->set_data(agent_data); 309 0 : resp->Response(); 310 0 : }