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 : records.push_back(record); 163 0 : } 164 0 : item.set_records(records); 165 0 : items.push_back(item); 166 0 : } 167 0 : data.set_agent_data(items); 168 0 : } 169 : 170 0 : DnsAgentXmppChannelManager::DnsAgentXmppChannelManager( 171 0 : XmppServer *server) 172 0 : : server_(server), 173 0 : work_queue_(TaskScheduler::GetInstance()->GetTaskId("dns::Config"), 0, 174 : boost::bind(&DnsAgentXmppChannelManager::ProcessRecord, 175 0 : this, _1)) { 176 0 : if (server_) { 177 0 : server_->RegisterConnectionEvent(xmps::DNS, 178 : boost::bind(&DnsAgentXmppChannelManager::HandleXmppChannelEvent, 179 : this, _1, _2)); 180 : } 181 0 : } 182 : 183 0 : DnsAgentXmppChannelManager::~DnsAgentXmppChannelManager() { 184 0 : if (server_) 185 0 : server_->UnRegisterConnectionEvent(xmps::DNS); 186 0 : channel_map_.clear(); 187 0 : work_queue_.Shutdown(); 188 0 : } 189 : 190 0 : bool DnsAgentXmppChannelManager::ProcessRecord( 191 : boost::shared_ptr<RecordRequest> req) { 192 0 : Dns::GetDnsManager()->ProcessAgentUpdate(req->op, req->record_name, 193 0 : req->vdns_name, req->item); 194 0 : return true; 195 : } 196 : 197 0 : void DnsAgentXmppChannelManager::EnqueueRecord( 198 : boost::shared_ptr<RecordRequest> req) { 199 0 : work_queue_.Enqueue(req); 200 0 : } 201 : 202 0 : void DnsAgentXmppChannelManager::RemoveChannel(XmppChannel *ch) { 203 0 : channel_map_.erase(ch); 204 0 : } 205 : 206 : DnsAgentXmppChannel * 207 0 : DnsAgentXmppChannelManager::DnsAgentXmppChannelManager::FindChannel( 208 : const XmppChannel *ch) { 209 0 : std::scoped_lock lock(mutex_); 210 0 : ChannelMap::iterator it = channel_map_.find(ch); 211 0 : if (it == channel_map_.end()) 212 0 : return NULL; 213 0 : return it->second; 214 0 : } 215 : 216 : void 217 0 : DnsAgentXmppChannelManager::HandleXmppChannelEvent(XmppChannel *channel, 218 : xmps::PeerState state) { 219 0 : std::scoped_lock lock(mutex_); 220 0 : ChannelMap::iterator it = channel_map_.find(channel); 221 : 222 0 : if (state == xmps::READY) { 223 0 : if (it == channel_map_.end()) { 224 : DnsAgentXmppChannel *agent_xmpp_channel = 225 0 : new DnsAgentXmppChannel(channel, this); 226 0 : channel_map_.insert(std::make_pair(channel, agent_xmpp_channel)); 227 : ConfigClientManager *config_manager = 228 0 : Dns::GetDnsManager()->get_config_manager(); 229 0 : if (config_manager && !config_manager->GetEndOfRibComputed()) { 230 0 : DNS_XMPP_TRACE(DnsXmppTrace, "Peer:" + channel->PeerAddress() + 231 : " Close due to EndofRib not computed"); 232 0 : channel->Close(); 233 : } 234 : } 235 0 : } else if (state == xmps::NOT_READY) { 236 0 : if (it != channel_map_.end()) { 237 0 : DnsAgentXmppChannel *agent_xmpp_channel = (*it).second; 238 0 : agent_xmpp_channel->Close(); 239 0 : delete agent_xmpp_channel; 240 : } else { 241 0 : DNS_XMPP_TRACE(DnsXmppTrace, 242 : "Peer not found on channel not ready event"); 243 : } 244 : } 245 0 : } 246 : 247 0 : uint8_t DnsAgentXmppChannelManager::ChannelToDscp(const XmppChannel *xc) const { 248 0 : const XmppConnection *conn = xc->connection(); 249 0 : if (conn) { 250 0 : const XmppSession *sess = conn->session(); 251 0 : if (sess) { 252 0 : return sess->GetDscpValue(); 253 : } 254 : } 255 0 : return 0; 256 : } 257 : 258 0 : void DnsAgentXmppChannelManager::GetAgentData(std::vector<AgentData> &list) { 259 0 : std::scoped_lock lock(mutex_); 260 0 : for (ChannelMap::iterator iter = channel_map_.begin(); 261 0 : iter != channel_map_.end(); ++iter) { 262 0 : const XmppChannel *channel = iter->first; 263 0 : AgentData agent_data; 264 0 : agent_data.set_peer(channel->ToString()); 265 0 : agent_data.set_peer_address( 266 0 : channel->connection()->endpoint().address().to_string()); 267 0 : agent_data.set_local_address( 268 0 : channel->connection()->local_endpoint().address().to_string()); 269 0 : agent_data.set_state(channel->StateName()); 270 0 : agent_data.set_last_event(channel->LastEvent()); 271 0 : agent_data.set_last_state(channel->LastStateName()); 272 0 : agent_data.set_last_state_at(channel->LastStateChangeAt()); 273 0 : agent_data.set_dscp(ChannelToDscp(channel)); 274 0 : list.push_back(agent_data); 275 0 : } 276 0 : } 277 : 278 0 : void DnsAgentXmppChannelManager::GetAgentDnsData(std::vector<AgentDnsData> &dt) { 279 0 : std::scoped_lock lock(mutex_); 280 0 : for (ChannelMap::iterator iter = channel_map_.begin(); 281 0 : iter != channel_map_.end(); ++iter) { 282 0 : DnsAgentXmppChannel *ch = iter->second; 283 0 : AgentDnsData data; 284 0 : ch->GetAgentDnsData(data); 285 0 : dt.push_back(data); 286 0 : } 287 0 : } 288 : 289 0 : void ShowAgentList::HandleRequest() const { 290 0 : DnsAgentListResponse *resp = new DnsAgentListResponse(); 291 0 : resp->set_context(context()); 292 : 293 0 : std::vector<AgentData> agent_list_sandesh; 294 0 : Dns::GetAgentXmppChannelManager()->GetAgentData(agent_list_sandesh); 295 : 296 0 : resp->set_agent(agent_list_sandesh); 297 0 : resp->Response(); 298 0 : } 299 : 300 0 : void ShowAgentXmppDnsData::HandleRequest() const { 301 0 : AgentXmppDnsDataResponse *resp = new AgentXmppDnsDataResponse(); 302 0 : resp->set_context(context()); 303 : 304 0 : std::vector<AgentDnsData> agent_data; 305 0 : Dns::GetAgentXmppChannelManager()->GetAgentDnsData(agent_data); 306 : 307 0 : resp->set_data(agent_data); 308 0 : resp->Response(); 309 0 : }