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 <stdint.h>
7 : #include "base/os.h"
8 : #include "vr_defs.h"
9 : #include "base/address_util.h"
10 : #include "oper/interface_common.h"
11 : #include "services/dns_proto.h"
12 : #include "services/dhcp_proto.h"
13 : #include "bind/bind_resolver.h"
14 : #include "cmn/agent_cmn.h"
15 : #include "controller/controller_dns.h"
16 : #include "base/timer.h"
17 : #include "oper/operdb_init.h"
18 : #include "oper/global_vrouter.h"
19 : #include "oper/vn.h"
20 :
21 338 : DnsHandler::DnsHandler(Agent *agent, boost::shared_ptr<PktInfo> info,
22 338 : boost::asio::io_context &io)
23 338 : : ProtoHandler(agent, info, io), resp_ptr_(NULL), dns_resp_size_(0),
24 338 : xid_(-1), action_(NONE), rkey_(NULL),
25 676 : query_name_update_(false), pend_req_(0), default_method_(false),
26 338 : curr_index_(0) {
27 338 : dns_ = (dnshdr *) pkt_info_->data;
28 338 : }
29 :
30 676 : DnsHandler::~DnsHandler() {
31 338 : for (ResolvList::iterator it = resolv_list_.begin();
32 338 : it != resolv_list_.end(); ++it) {
33 0 : delete *it;
34 : }
35 338 : if (rkey_) {
36 0 : delete rkey_;
37 : }
38 :
39 338 : uint8_t count = 0;
40 338 : while (count < dns_resolvers_.size()) {
41 0 : if (dns_resolvers_[count]) {
42 0 : dns_resolvers_[count]->timer_->Cancel();
43 0 : TimerManager::DeleteTimer(dns_resolvers_[count]->timer_);
44 0 : delete dns_resolvers_[count];
45 : }
46 0 : count++;
47 : }
48 338 : count = 0;
49 338 : while (count < def_dns_resolvers_.size()) {
50 0 : if (def_dns_resolvers_[count]) {
51 0 : def_dns_resolvers_[count]->timer_->Cancel();
52 0 : TimerManager::DeleteTimer(def_dns_resolvers_[count]->timer_);
53 0 : delete def_dns_resolvers_[count];
54 : }
55 0 : count++;
56 : }
57 :
58 338 : dns_resolvers_.clear();
59 338 : def_dns_resolvers_.clear();
60 676 : }
61 :
62 :
63 0 : void DnsHandler::BuildDnsResolvers() {
64 :
65 0 : uint8_t count = 0;
66 0 : uint8_t resolvers_count = Agent::GetInstance()->GetDnslist().size();
67 0 : dns_resolvers_.resize(resolvers_count);
68 :
69 0 : std::vector<string>dns_servers;
70 0 : while (count < resolvers_count) {
71 :
72 0 : boost::split(dns_servers, Agent::GetInstance()->GetDnslist()[count],
73 0 : boost::is_any_of(":"));
74 0 : DnsResolverInfo *resolver = new DnsResolverInfo();
75 :
76 0 : boost::system::error_code ec;
77 0 : resolver->ep_.address(AddressFromString(dns_servers[0], &ec));
78 0 : assert(ec.value() == 0);
79 0 : uint16_t dns_port = DNS_SERVER_PORT;
80 0 : if (dns_servers.size() > 1)
81 0 : dns_port = strtoul(dns_servers[1].c_str(), NULL, 10);
82 0 : resolver->ep_.port(dns_port);
83 0 : resolver->retries_ = 0;
84 0 : std::stringstream ss;
85 0 : ss << "DnsHandlerTimer " << count;
86 0 : resolver->timer_ = TimerManager::CreateTimer(
87 0 : *(agent()->event_manager()->io_service()), ss.str(),
88 : TaskScheduler::GetInstance()->GetTaskId("Agent::Services"),
89 : PktHandler::DNS);
90 0 : dns_resolvers_[count] = resolver;
91 :
92 0 : count++;
93 0 : }
94 0 : }
95 :
96 0 : void DnsHandler::BuildDefaultDnsResolvers() {
97 0 : uint8_t count = 0;
98 0 : DnsProto *dns_proto = agent()->GetDnsProto();
99 0 : std::vector<IpAddress> const &def_slist = dns_proto->GetDefaultServerList();
100 0 : def_dns_resolvers_.resize(def_slist.size());
101 0 : while (count < def_slist.size()) {
102 0 : DnsResolverInfo *resolver = new DnsResolverInfo();
103 :
104 0 : resolver->ep_.address(def_slist[count]);
105 0 : resolver->ep_.port(DNS_SERVER_PORT);
106 0 : resolver->retries_ = 0;
107 0 : std::stringstream ss;
108 0 : ss << "DefDnsHandlerTimer " << count;
109 0 : resolver->timer_ = TimerManager::CreateTimer(
110 0 : *(agent()->event_manager()->io_service()), ss.str(),
111 : TaskScheduler::GetInstance()->GetTaskId("Agent::Services"),
112 : PktHandler::DNS);
113 0 : def_dns_resolvers_[count] = resolver;
114 0 : count++;
115 0 : }
116 0 : }
117 :
118 338 : bool DnsHandler::Run() {
119 338 : switch(pkt_info_->type) {
120 338 : case PktType::MESSAGE:
121 338 : return HandleMessage();
122 :
123 0 : default:
124 0 : return HandleRequest();
125 : }
126 : }
127 :
128 0 : bool DnsHandler::HandleRequest() {
129 0 : DnsProto *dns_proto = agent()->GetDnsProto();
130 0 : dns_proto->IncrStatsReq();
131 :
132 0 : uint16_t ret = DNS_ERR_NO_ERROR;
133 : const Interface *itf =
134 0 : agent()->interface_table()->FindInterface(GetInterfaceIndex());
135 0 : if (!itf || (itf->type() != Interface::VM_INTERFACE) ||
136 0 : dns_->flags.req) {
137 0 : dns_proto->IncrStatsDrop();
138 0 : DNS_BIND_TRACE(DnsBindError, "Received Invalid DNS request - dropping"
139 : << "; itf = " << itf << "; flags.req = "
140 : << dns_->flags.req << "; src addr = "
141 : << pkt_info_->ip->ip_src.s_addr <<";");
142 0 : return true;
143 : }
144 :
145 0 : const VmInterface *vmitf = static_cast<const VmInterface *>(itf);
146 0 : if (!vmitf->layer3_forwarding()) {
147 0 : DNS_BIND_TRACE(DnsBindError, "DNS request on VM port with disabled"
148 : "ipv4 service: " << itf);
149 0 : dns_proto->IncrStatsDrop();
150 0 : return true;
151 : }
152 : // Handle requests (req == 0), queries (op code == 0), updates, non auth
153 0 : if ((dns_->flags.op && dns_->flags.op != DNS_OPCODE_UPDATE) ||
154 0 : (dns_->flags.cd)) {
155 0 : DNS_BIND_TRACE(DnsBindError, "Unimplemented DNS request"
156 : << "; flags.op = " << dns_->flags.op << "; flags.cd = "
157 : << dns_->flags.cd << ";");
158 0 : ret = DNS_ERR_NO_IMPLEMENT;
159 0 : goto error;
160 : }
161 :
162 0 : if (!vmitf->vn() ||
163 0 : (pkt_info_->ip_saddr.is_v4() &&
164 0 : !vmitf->vn()->GetIpamData(vmitf->primary_ip_addr(),
165 0 : &ipam_name_, &ipam_type_)) ||
166 0 : (pkt_info_->ip_saddr.is_v6() &&
167 0 : !vmitf->vn()->GetIpamData(vmitf->primary_ip6_addr(),
168 : &ipam_name_, &ipam_type_))) {
169 0 : DNS_BIND_TRACE(DnsBindError, "Unable to find Ipam data; interface = "
170 : << vmitf->name());
171 0 : ret = DNS_ERR_SERVER_FAIL;
172 0 : goto error;
173 : }
174 :
175 0 : if (ipam_type_.ipam_dns_method == "default-dns-server" ||
176 0 : ipam_type_.ipam_dns_method == "") {
177 0 : BuildDefaultDnsResolvers();
178 0 : if (dns_->flags.op == DNS_OPCODE_UPDATE) {
179 0 : DNS_BIND_TRACE(DnsBindError, "Default DNS request : Update received, ignoring");
180 0 : ret = DNS_ERR_NO_IMPLEMENT;
181 0 : goto error;
182 : }
183 0 : GetDomainName(vmitf, &domain_name_);
184 0 : default_method_ = true;
185 0 : return HandleDefaultDnsRequest(vmitf);
186 0 : } else if (ipam_type_.ipam_dns_method == "virtual-dns-server") {
187 0 : BuildDnsResolvers();
188 0 : if (!agent()->domain_config_table()->GetVDns(ipam_type_.ipam_dns_server.
189 0 : virtual_dns_server_name, &vdns_type_)) {
190 0 : DNS_BIND_TRACE(DnsBindError, "Unable to find domain; interface = "
191 : << vmitf->vm_name());
192 0 : ret = DNS_ERR_SERVER_FAIL;
193 0 : goto error;
194 : }
195 0 : domain_name_ = vdns_type_.domain_name;
196 0 : default_method_ = false;
197 0 : return HandleVirtualDnsRequest(vmitf);
198 0 : } else if (ipam_type_.ipam_dns_method == "none") {
199 0 : DNS_BIND_TRACE(DnsBindError, "No DNS support for the VM : "
200 : << "ipam_dns_method set to none, ignoring request");
201 0 : ret = DNS_ERR_SERVER_FAIL;
202 0 : goto error;
203 : }
204 :
205 0 : ret = DNS_ERR_SERVER_FAIL;
206 0 : error:
207 0 : BindUtil::BuildDnsHeader(dns_, ntohs(dns_->xid), DNS_QUERY_RESPONSE,
208 : DNS_OPCODE_QUERY, 0, 1, ret,
209 0 : ntohs(dns_->ques_rrcount));
210 0 : SendDnsResponse();
211 0 : return true;
212 : }
213 :
214 0 : bool DnsHandler::HandleDefaultDnsRequest(const VmInterface *vmitf) {
215 0 : std::scoped_lock lock(mutex_);
216 0 : uint16_t ret = DNS_ERR_NO_ERROR;
217 0 : DnsProto *dns_proto = agent()->GetDnsProto();
218 0 : rkey_ = new QueryKey(vmitf, dns_->xid);
219 0 : if (dns_proto->IsVmRequestDuplicate(rkey_)) {
220 0 : DNS_BIND_TRACE(DnsBindTrace,
221 : "Retry DNS query from VM - dropping; interface = "
222 : << vmitf->vm_name() << " xid = " << dns_->xid);
223 0 : dns_proto->IncrStatsRetransmitReq();
224 0 : return true;
225 : }
226 0 : dns_proto->AddVmRequest(rkey_);
227 :
228 0 : if (BindUtil::ParseDnsQuery((uint8_t *)dns_,
229 0 : pkt_info_->GetUdpPayloadLength(),
230 0 : &dns_resp_size_, items_) == false) {
231 0 : DNS_BIND_TRACE(DnsBindTrace, "Default DNS query parsing failed; "
232 : "interface = " << vmitf->vm_name() << " xid = " <<
233 : dns_->xid);
234 0 : return true;
235 : }
236 :
237 0 : resp_ptr_ = (uint8_t *)dns_ + dns_resp_size_;
238 0 : BindUtil::BuildDnsHeader(dns_, ntohs(dns_->xid), DNS_QUERY_RESPONSE,
239 : DNS_OPCODE_QUERY, 0, 1, DNS_ERR_NO_ERROR,
240 0 : ntohs(dns_->ques_rrcount));
241 0 : ResolveAllLinkLocalRequests();
242 0 : if (!items_.size()) {
243 : // no pending resolution, send response
244 0 : dns_->ans_rrcount = htons(dns_->ans_rrcount);
245 0 : DefaultDnsSendResponse();
246 0 : dns_proto->DelVmRequest(rkey_);
247 0 : return true;
248 : }
249 :
250 0 : if (!def_dns_resolvers_.size()) {
251 0 : DNS_BIND_TRACE(DnsBindTrace, "No DNS resolvers for Default DNS query"
252 : " with xid = " << dns_->xid << ";interface = "
253 : << vmitf->vm_name());
254 0 : ret = DNS_ERR_SERVER_FAIL;
255 0 : goto fail;
256 : }
257 :
258 0 : DNS_BIND_TRACE(DnsBindTrace, "Default DNS query received; "
259 : "interface = " << vmitf->vm_name() << " xid = " <<
260 : dns_->xid << " " << DnsItemsToString(items_));
261 :
262 0 : action_ = DnsHandler::DNS_QUERY;
263 0 : curr_index_ = 0;
264 0 : if (SendToDefaultServer()) {
265 0 : return false;
266 : }
267 :
268 0 : DNS_BIND_TRACE(DnsBindTrace, "Unable to send DNS query to resolvers;"
269 : " xid = " << dns_->xid << "; interface = "
270 : << vmitf->vm_name());
271 0 : ret = DNS_ERR_SERVER_FAIL;
272 0 : fail:
273 0 : BindUtil::BuildDnsHeader(dns_, ntohs(dns_->xid), DNS_QUERY_RESPONSE,
274 : DNS_OPCODE_QUERY, 0, 1, ret,
275 0 : ntohs(dns_->ques_rrcount));
276 0 : SendDnsResponse();
277 0 : dns_proto->DelVmRequest(rkey_);
278 0 : return true;
279 0 : }
280 :
281 0 : void DnsHandler::DefaultDnsSendResponse() {
282 0 : agent()->GetDnsProto()->DelVmRequest(rkey_);
283 0 : if (dns_->flags.ret) {
284 0 : DNS_BIND_TRACE(DnsBindError, "Query failed : " <<
285 : BindUtil::DnsResponseCode(dns_->flags.ret) <<
286 : " xid = " << dns_->xid << " " <<
287 : DnsItemsToString(items_) <<
288 : DnsItemsToString(linklocal_items_));
289 : } else {
290 0 : DNS_BIND_TRACE(DnsBindTrace, "Query successful : xid = " <<
291 : dns_->xid << " " << DnsItemsToString(items_) <<
292 : DnsItemsToString(linklocal_items_));
293 : }
294 0 : SendDnsResponse();
295 0 : }
296 :
297 0 : bool DnsHandler::HandleVirtualDnsRequest(const VmInterface *vmitf) {
298 0 : rkey_ = new QueryKey(vmitf, dns_->xid);
299 0 : DnsProto *dns_proto = agent()->GetDnsProto();
300 0 : if (dns_proto->IsVmRequestDuplicate(rkey_)) {
301 0 : DNS_BIND_TRACE(DnsBindTrace,
302 : "Retry DNS query from VM - dropping; interface = " <<
303 : vmitf->vm_name() << " xid = " << dns_->xid << " " <<
304 : DnsItemsToString(items_) <<
305 : DnsItemsToString(linklocal_items_));
306 0 : dns_proto->IncrStatsRetransmitReq();
307 0 : return true;
308 : }
309 0 : dns_proto->AddVmRequest(rkey_);
310 :
311 0 : BindUtil::RemoveSpecialChars(ipam_type_.ipam_dns_server.
312 0 : virtual_dns_server_name);
313 :
314 0 : uint16_t ret = DNS_ERR_NO_ERROR;
315 0 : switch (dns_->flags.op) {
316 0 : case DNS_OPCODE_QUERY: {
317 0 : if (BindUtil::ParseDnsQuery((uint8_t *)dns_,
318 0 : pkt_info_->GetUdpPayloadLength(),
319 0 : &dns_resp_size_, items_) == false) {
320 0 : DNS_BIND_TRACE(DnsBindTrace, "vDNS query parsing failed; "
321 : "interface = " << vmitf->vm_name() << " xid = " <<
322 : dns_->xid);
323 0 : break;
324 : }
325 0 : resp_ptr_ = (uint8_t *)dns_ + dns_resp_size_;
326 0 : BindUtil::BuildDnsHeader(dns_, ntohs(dns_->xid), DNS_QUERY_RESPONSE,
327 : DNS_OPCODE_QUERY, 0, 1, ret,
328 0 : ntohs(dns_->ques_rrcount));
329 : // Check for linklocal service name resolution
330 0 : ResolveAllLinkLocalRequests();
331 0 : if (!items_.size()) {
332 : // no pending resolution, send response
333 0 : dns_->ans_rrcount = htons(dns_->ans_rrcount);
334 0 : SendDnsResponse();
335 0 : break;
336 : }
337 0 : UpdateQueryNames();
338 :
339 0 : uint8_t count = 0;
340 0 : bool query_success = false;
341 :
342 0 : action_ = DnsHandler::DNS_QUERY;
343 0 : while (count < dns_resolvers_.size()) {
344 0 : if (dns_resolvers_[count]) {
345 0 : uint16_t xid = dns_proto->GetTransId();
346 0 : if (SendDnsQuery(dns_resolvers_[count], xid) == true) {
347 0 : dns_proto->AddDnsQueryIndex(xid, count);
348 0 : query_success = true;
349 : }
350 : }
351 0 : count++;
352 : }
353 0 : if (query_success) {
354 : // atleast one query sent succesful, do not delete request yet.
355 0 : return false;
356 : }
357 0 : break;
358 : }
359 :
360 0 : case DNS_OPCODE_UPDATE: {
361 0 : if (vdns_type_.dynamic_records_from_client) {
362 0 : DnsUpdateData *update_data = new DnsUpdateData();
363 : DnsProto::DnsUpdateIpc *update =
364 : new DnsProto::DnsUpdateIpc(DnsAgentXmpp::Update,
365 0 : update_data, vmitf, false);
366 0 : if (BindUtil::ParseDnsUpdate((uint8_t *)dns_,
367 0 : pkt_info_->GetUdpPayloadLength(),
368 : *update_data)) {
369 : update_data->virtual_dns = ipam_type_.ipam_dns_server.
370 0 : virtual_dns_server_name;
371 0 : Update(update);
372 : } else {
373 0 : delete update;
374 0 : ret = DNS_ERR_NO_IMPLEMENT;
375 : }
376 : } else {
377 0 : DNS_BIND_TRACE(DnsBindTrace, "Client not allowed to update "
378 : "dynamic records : " << vmitf->vm_name() << " ;Ignoring "
379 : "update for " << DnsItemsToString(items_));
380 0 : ret = DNS_ERR_NOT_AUTH;
381 : }
382 0 : BindUtil::BuildDnsHeader(dns_, ntohs(dns_->xid), DNS_QUERY_RESPONSE,
383 : DNS_OPCODE_UPDATE, 0, 1, ret,
384 0 : ntohs(dns_->ques_rrcount));
385 0 : SendDnsResponse();
386 0 : break;
387 : }
388 :
389 0 : default: {
390 0 : DNS_BIND_TRACE(DnsBindTrace, "Unsupported op : " << dns_->flags.op
391 : << "from vm : " << vmitf->vm_name());
392 0 : break;
393 : }
394 : }
395 :
396 0 : dns_proto->DelVmRequest(rkey_);
397 0 : return true;
398 : }
399 :
400 0 : bool DnsHandler::SendDnsQuery(DnsResolverInfo *resolver,
401 : uint16_t xid) {
402 0 : uint8_t *pkt = NULL;
403 0 : std::size_t len = 0;
404 0 : DnsProto *dns_proto = agent()->GetDnsProto();
405 0 : bool in_progress = dns_proto->IsDnsQueryInProgress(xid);
406 0 : if (in_progress) {
407 0 : if (resolver->retries_ >= dns_proto->max_retries()) {
408 0 : DNS_BIND_TRACE(DnsBindTrace,
409 : "Max retries reached for query; xid = " << xid <<
410 : " " << DnsItemsToString(items_));
411 0 : goto cleanup;
412 : } else {
413 0 : resolver->retries_++;
414 : }
415 : } else {
416 0 : dns_proto->AddDnsQuery(xid, this);
417 : }
418 :
419 0 : pkt = new uint8_t[BindResolver::max_pkt_size];
420 0 : if (!default_method_) {
421 0 : len = BindUtil::BuildDnsQuery(pkt, xid,
422 0 : ipam_type_.ipam_dns_server.virtual_dns_server_name, items_);
423 : } else {
424 0 : len = BindUtil::BuildDnsQuery(pkt, xid, "", items_);
425 : }
426 0 : if (BindResolver::Resolver()->DnsSend(pkt, resolver->ep_, len)) {
427 0 : DNS_BIND_TRACE(DnsBindTrace, "DNS query sent to named server : " <<
428 : resolver->ep_.address().to_string() << "; xid =" <<
429 : xid << " " << DnsItemsToString(items_));
430 0 : resolver->timer_->Cancel();
431 0 : resolver->timer_->Start(dns_proto->timeout(),
432 : boost::bind(&DnsHandler::TimerExpiry, this, xid));
433 0 : return true;
434 : }
435 :
436 0 : cleanup:
437 0 : dns_proto->IncrStatsDrop();
438 0 : dns_proto->DelDnsQuery(xid);
439 0 : dns_proto->DelDnsQueryIndex(xid);
440 0 : return false;
441 : }
442 :
443 : // Check the request against configured link local services and
444 : // update DnsItems, if found
445 0 : bool DnsHandler::ResolveLinkLocalRequest(DnsItems::iterator &item,
446 : DnsItems *linklocal_items) const {
447 0 : GlobalVrouter *global_vrouter = agent_->oper_db()->global_vrouter();
448 :
449 0 : switch (item->type) {
450 :
451 0 : case DNS_A_RECORD: {
452 0 : std::string base_name;
453 0 : GetBaseName(item->name, &base_name);
454 0 : std::set<IpAddress> service_ips;
455 0 : if (global_vrouter->FindLinkLocalService(item->name, &service_ips) ||
456 0 : (!base_name.empty() &&
457 0 : global_vrouter->FindLinkLocalService(base_name, &service_ips))) {
458 0 : for (std::set<IpAddress>::iterator it = service_ips.begin();
459 0 : it != service_ips.end(); ++it) {
460 0 : item->data = it->to_string();
461 0 : linklocal_items->push_back(*item);
462 : }
463 : }
464 0 : break;
465 0 : }
466 :
467 0 : case DNS_PTR_RECORD: {
468 0 : std::set<std::string> service_names;
469 0 : boost::asio::ip::address addr;
470 0 : if (!BindUtil::GetAddrFromPtrName(item->name, addr) ||
471 0 : !addr.is_v4()) {
472 : // TODO: Support link-local services on IPv6 links.
473 0 : break;
474 : }
475 0 : if (global_vrouter->FindLinkLocalService(
476 0 : addr.to_v4(), &service_names)) {
477 0 : for (std::set<std::string>::iterator it = service_names.begin();
478 0 : it != service_names.end(); ++it) {
479 0 : item->data = *it;
480 0 : linklocal_items->push_back(*item);
481 : }
482 : }
483 0 : break;
484 0 : }
485 :
486 0 : case DNS_AAAA_RECORD:
487 0 : break;
488 :
489 0 : default:
490 0 : break;
491 :
492 : }
493 :
494 0 : return (linklocal_items->size() > 0);
495 : }
496 :
497 : // Resolve link local service name requests locally
498 0 : bool DnsHandler::ResolveAllLinkLocalRequests() {
499 0 : bool linklocal_request = false;
500 0 : for (DnsItems::iterator it = items_.begin(); it != items_.end(); ) {
501 0 : DnsItems linklocal_items;
502 0 : if (ResolveLinkLocalRequest(it, &linklocal_items)) {
503 0 : linklocal_request = true;
504 0 : for (DnsItems::iterator llit = linklocal_items.begin();
505 0 : llit != linklocal_items.end(); ++llit) {
506 0 : resp_ptr_ = BindUtil::AddAnswerSection(resp_ptr_, *llit,
507 0 : dns_resp_size_);
508 0 : dns_->ans_rrcount++;
509 : }
510 : // storing the link local items in a different list
511 0 : linklocal_items_.splice(linklocal_items_.begin(), linklocal_items);
512 0 : items_.erase(it++);
513 : } else {
514 0 : it++;
515 : }
516 0 : }
517 0 : return linklocal_request;
518 : }
519 :
520 338 : bool DnsHandler::HandleMessage() {
521 338 : switch (pkt_info_->ipc->cmd) {
522 0 : case DnsProto::DNS_DEFAULT_RESPONSE:
523 0 : return HandleDefaultDnsResponse();
524 :
525 0 : case DnsProto::DNS_BIND_RESPONSE:
526 0 : return HandleBindResponse();
527 :
528 0 : case DnsProto::DNS_TIMER_EXPIRED:
529 0 : return HandleRetryExpiry();
530 :
531 338 : case DnsProto::DNS_XMPP_SEND_UPDATE:
532 338 : return HandleUpdate();
533 :
534 0 : case DnsProto::DNS_XMPP_MODIFY_VDNS:
535 0 : return HandleModifyVdns();
536 :
537 0 : case DnsProto::DNS_XMPP_UPDATE_RESPONSE:
538 0 : return HandleUpdateResponse();
539 :
540 0 : case DnsProto::DNS_XMPP_SEND_UPDATE_ALL:
541 0 : return UpdateAll();
542 :
543 0 : default:
544 0 : DNS_BIND_TRACE(DnsBindError, "Invalid internal DNS message : " <<
545 : pkt_info_->ipc->cmd);
546 0 : return true;
547 : }
548 : }
549 :
550 0 : bool DnsHandler::HandleDefaultDnsResponse() {
551 0 : DnsProto::DnsIpc *ipc = static_cast<DnsProto::DnsIpc *>(pkt_info_->ipc);
552 0 : ipc->handler->DefaultDnsSendResponse();
553 0 : delete ipc;
554 0 : return true;
555 : }
556 :
557 0 : bool DnsHandler::HandleBindResponse() {
558 0 : DnsProto::DnsIpc *ipc = static_cast<DnsProto::DnsIpc *>(pkt_info_->ipc);
559 0 : uint16_t xid = ntohs(*(uint16_t *)ipc->resp);
560 0 : DnsProto *dns_proto = agent()->GetDnsProto();
561 0 : DnsHandler *handler = dns_proto->GetDnsQueryHandler(xid);
562 0 : bool valid_response = false;
563 0 : if (handler) {
564 : dns_flags flags;
565 0 : DnsItems ques, ans, auth, add;
566 0 : if (BindUtil::ParseDnsResponse(ipc->resp, ipc->length, xid, flags,
567 : ques, ans, auth, add)) {
568 0 : switch(handler->action_) {
569 0 : case DnsHandler::DNS_QUERY:
570 0 : if (flags.ret) {
571 0 : DNS_BIND_TRACE(DnsBindError, "Query failed : " <<
572 : BindUtil::DnsResponseCode(flags.ret) <<
573 : " xid = " << xid << " " <<
574 : DnsItemsToString(items_) <<
575 : DnsItemsToString(linklocal_items_));
576 : } else {
577 0 : valid_response = true;
578 0 : handler->Resolve(flags, ques, ans, auth, add);
579 0 : DNS_BIND_TRACE(DnsBindTrace,
580 : "Query successful : xid = " <<
581 : xid << " " << DnsItemsToString(ans) <<
582 : DnsItemsToString(linklocal_items_));
583 : }
584 0 : break;
585 :
586 0 : default:
587 0 : DNS_BIND_TRACE(DnsBindTrace,
588 : "Invalid DNS action: xid = " << xid);
589 0 : break;
590 : }
591 : } else {
592 0 : DNS_BIND_TRACE(DnsBindTrace,
593 : "Received invalid BIND response: xid = " << xid);
594 : }
595 :
596 0 : dns_proto->DelDnsQuery(xid);
597 0 : dns_proto->DelDnsQueryIndex(xid);
598 :
599 0 : if (valid_response) {
600 0 : dns_proto->DelDnsQueryHandler(handler);
601 : /* Delete Request on first valid Response from named Server */
602 0 : dns_proto->DelVmRequest(handler->rkey_);
603 0 : delete handler;
604 : } else {
605 0 : if (!handler->DefaultMethodInUse()) {
606 0 : if (!dns_proto->IsDnsHandlerInUse(handler)) {
607 0 : HandleInvalidBindResponse(handler, flags, ques, ans, auth,
608 : add, xid);
609 : }
610 : } else {
611 0 : if (NeedRetryForNextServer(flags.ret)) {
612 : /* Try sending query to next available server */
613 0 : handler->IncrCurrIndex();
614 0 : if (!handler->SendToDefaultServer()) {
615 : /* Sending query to next server failed, send invalid
616 : * response to client
617 : */
618 0 : HandleInvalidBindResponse(handler, flags, ques, ans,
619 : auth, add, xid);
620 : }
621 : } else {
622 : /* Retry is not required, send invalid response to client */
623 0 : HandleInvalidBindResponse(handler, flags, ques, ans, auth,
624 : add, xid);
625 : }
626 : }
627 : }
628 0 : } else {
629 0 : DNS_BIND_TRACE(DnsBindError, "Invalid or Response ignored xid " << xid <<
630 : " received from DNS server - dropping");
631 0 : dns_proto->DelDnsQueryIndex(xid);
632 : }
633 :
634 0 : delete ipc;
635 0 : return true;
636 : }
637 :
638 0 : void DnsHandler::HandleInvalidBindResponse(DnsHandler *handler, dns_flags flags,
639 : const DnsItems &ques, DnsItems &ans,
640 : DnsItems &auth, DnsItems &add,
641 : uint16_t xid) {
642 0 : DnsProto *dns_proto = agent()->GetDnsProto();
643 0 : if (flags.ret) {
644 : /* Send last invalid response to requesting VM */
645 0 : handler->Resolve(flags, ques, ans, auth, add);
646 0 : DNS_BIND_TRACE(DnsBindTrace,
647 : "Send invalid BIND response: xid = " << xid);
648 : } else {
649 0 : DNS_BIND_TRACE(DnsBindTrace,
650 : "No response sent: xid = " << xid);
651 : }
652 : /* Delete Request on last invalid Response from named Server */
653 0 : dns_proto->DelVmRequest(handler->rkey_);
654 0 : delete handler;
655 0 : }
656 :
657 0 : bool DnsHandler::NeedRetryForNextServer(uint16_t code) {
658 : /*
659 : * Try next server for following response codes: server_failure(2),
660 : * Non-existent domain(3), Not implemented(4), Query refused(5),
661 : * Not Authorized(9)
662 : */
663 0 : if ((code > 1 && code < 6) || code == 9) {
664 0 : return true;
665 : }
666 0 : return false;
667 : }
668 :
669 0 : bool DnsHandler::SendToDefaultServer() {
670 0 : if (curr_index() > last_index()) {
671 0 : return false;
672 : }
673 0 : DnsProto *dns_proto = agent()->GetDnsProto();
674 0 : uint16_t xid = dns_proto->GetTransId();
675 : DnsResolverInfo *resolver;
676 0 : while (curr_index() <= last_index()) {
677 0 : resolver = def_dns_resolvers_[curr_index()];
678 0 : if (!SendDnsQuery(resolver, xid)) {
679 0 : IncrCurrIndex();
680 : } else {
681 : /* Query sent succesfully */
682 0 : return true;
683 : }
684 : }
685 0 : return false;
686 : }
687 :
688 0 : bool DnsHandler::HandleRetryExpiry() {
689 0 : DnsProto::DnsIpc *ipc = static_cast<DnsProto::DnsIpc *>(pkt_info_->ipc);
690 0 : DnsProto *dns_proto = agent()->GetDnsProto();
691 0 : uint16_t xid = ipc->xid;
692 0 : DnsHandler *handler = dns_proto->GetDnsQueryHandler(xid);
693 0 : if (handler) {
694 : DnsResolverInfo *resolver;
695 0 : if (handler->DefaultMethodInUse()) {
696 0 : resolver = handler->def_dns_resolvers_[handler->curr_index()];
697 0 : if (!handler->SendDnsQuery(resolver, xid)) {
698 : // Try sending query to next available server
699 0 : handler->IncrCurrIndex();
700 0 : if (!handler->SendToDefaultServer()) {
701 0 : dns_proto->DelVmRequest(handler->rkey_);
702 0 : delete handler;
703 : }
704 : }
705 : } else {
706 0 : uint16_t idx = dns_proto->GetDnsQueryServerIndex(ipc->xid);
707 0 : resolver = handler->dns_resolvers_[idx];
708 0 : if (!handler->SendDnsQuery(resolver, xid)) {
709 0 : if (!dns_proto->IsDnsHandlerInUse(handler)) {
710 0 : dns_proto->DelVmRequest(handler->rkey_);
711 0 : delete handler;
712 : }
713 : }
714 : }
715 : }
716 0 : delete ipc;
717 0 : return true;
718 : }
719 :
720 0 : bool DnsHandler::HandleUpdateResponse() {
721 : DnsProto::DnsUpdateIpc *ipc =
722 0 : static_cast<DnsProto::DnsUpdateIpc *>(pkt_info_->ipc);
723 0 : delete ipc;
724 0 : return true;
725 : }
726 :
727 338 : bool DnsHandler::HandleUpdate() {
728 : DnsProto::DnsUpdateIpc *ipc =
729 338 : static_cast<DnsProto::DnsUpdateIpc *>(pkt_info_->ipc);
730 338 : if (!ipc->xmpp_data) {
731 338 : DelUpdate(ipc);
732 : } else {
733 0 : Update(ipc);
734 : }
735 338 : return true;
736 : }
737 :
738 0 : bool DnsHandler::HandleModifyVdns() {
739 : DnsProto::DnsUpdateIpc *ipc =
740 0 : static_cast<DnsProto::DnsUpdateIpc *>(pkt_info_->ipc);
741 0 : DnsProto *dns_proto = agent()->GetDnsProto();
742 0 : std::vector<DnsProto::DnsUpdateIpc *> change_list;
743 0 : const DnsProto::DnsUpdateSet &update_set = dns_proto->update_set();
744 0 : for (DnsProto::DnsUpdateSet::const_iterator it = update_set.begin();
745 0 : it != update_set.end(); ++it) {
746 0 : if ((ipc->itf &&
747 0 : ((*it)->itf != ipc->itf || (*it)->floatingIp != ipc->floatingIp)) ||
748 0 : !((*it)->xmpp_data) || (*it)->xmpp_data->virtual_dns != ipc->old_vdns)
749 0 : continue;
750 :
751 0 : change_list.push_back(*it);
752 : // if the server ttl changes, we only readd with the new values
753 0 : if (!ipc->itf && ipc->new_vdns == ipc->old_vdns)
754 0 : continue;
755 :
756 0 : for (DnsItems::iterator item = (*it)->xmpp_data->items.begin();
757 0 : item != (*it)->xmpp_data->items.end(); ++item) {
758 : // in case of delete, set the class to NONE and ttl to 0
759 0 : (*item).eclass = DNS_CLASS_NONE;
760 0 : (*item).ttl = 0;
761 : }
762 0 : for (int i = 0; i < MAX_XMPP_SERVERS; i++) {
763 0 : AgentDnsXmppChannel *channel = agent()->dns_xmpp_channel(i);
764 0 : SendXmppUpdate(channel, (*it)->xmpp_data);
765 : }
766 : }
767 0 : for (unsigned int i = 0; i < change_list.size(); i++) {
768 0 : dns_proto->DelUpdateRequest(change_list[i]);
769 0 : if (ipc->new_vdns.empty())
770 0 : delete change_list[i];
771 : }
772 0 : if (ipc->new_vdns.empty())
773 0 : goto done;
774 0 : for (unsigned int i = 0; i < change_list.size(); i++) {
775 0 : change_list[i]->xmpp_data->virtual_dns = ipc->new_vdns;
776 0 : std::string &zone = change_list[i]->xmpp_data->zone;
777 0 : if (zone.find(".in-addr.arpa") == std::string::npos &&
778 0 : zone.find(".ip6.arpa") == std::string::npos)
779 0 : zone = ipc->new_domain;
780 0 : for (DnsItems::iterator item = change_list[i]->xmpp_data->items.begin();
781 0 : item != change_list[i]->xmpp_data->items.end(); ++item) {
782 0 : (*item).eclass = DNS_CLASS_IN;
783 0 : (*item).ttl = ipc->ttl;
784 : }
785 0 : Update(change_list[i]);
786 : }
787 :
788 0 : done:
789 0 : delete ipc;
790 0 : return true;
791 0 : }
792 :
793 0 : bool DnsHandler::UpdateAll() {
794 : DnsProto::DnsUpdateAllIpc *ipc =
795 0 : static_cast<DnsProto::DnsUpdateAllIpc *>(pkt_info_->ipc);
796 : const DnsProto::DnsUpdateSet &update_set =
797 0 : agent()->GetDnsProto()->update_set();
798 0 : for (DnsProto::DnsUpdateSet::const_iterator it = update_set.begin();
799 0 : it != update_set.end(); ++it) {
800 0 : SendXmppUpdate(ipc->channel, (*it)->xmpp_data);
801 : }
802 :
803 0 : delete ipc;
804 0 : return true;
805 : }
806 :
807 0 : void DnsHandler::SendXmppUpdate(AgentDnsXmppChannel *channel,
808 : DnsUpdateData *xmpp_data) {
809 0 : if (channel && agent_->is_dns_xmpp_channel(channel)) {
810 : // Split the request in case we have more data items
811 0 : DnsItems done, store;
812 0 : DnsItems::iterator first, last;
813 :
814 0 : uint32_t size = xmpp_data->items.size();
815 0 : store.swap(xmpp_data->items);
816 0 : for (uint32_t i = 0; i <= size / max_items_per_xmpp_msg; i++) {
817 0 : if (!store.size())
818 0 : break;
819 :
820 0 : first = last = store.begin();
821 0 : if (store.size() > max_items_per_xmpp_msg)
822 0 : std::advance(last, max_items_per_xmpp_msg);
823 : else
824 0 : last = store.end();
825 0 : xmpp_data->items.splice(xmpp_data->items.begin(), store, first, last);
826 :
827 : uint8_t data[DnsAgentXmpp::max_dns_xmpp_msg_len];
828 0 : xid_ = agent()->GetDnsProto()->GetTransId();
829 0 : std::size_t len = 0;
830 0 : if ((len = DnsAgentXmpp::DnsAgentXmppEncode(channel->GetXmppChannel(),
831 : DnsAgentXmpp::Update,
832 0 : xid_, 0, xmpp_data,
833 0 : data)) > 0) {
834 0 : channel->SendMsg(data, len);
835 : }
836 :
837 0 : done.splice(done.end(), xmpp_data->items, xmpp_data->items.begin(),
838 0 : xmpp_data->items.end());
839 : }
840 0 : xmpp_data->items.swap(done);
841 0 : }
842 0 : }
843 :
844 : void
845 0 : DnsHandler::Resolve(dns_flags flags, const DnsItems &ques, DnsItems &ans,
846 : DnsItems &auth, DnsItems &add) {
847 0 : for (DnsItems::iterator it = ans.begin(); it != ans.end(); ++it) {
848 0 : bool name_update_required = true;
849 : // Do not update dns response msg offset, for default dns case
850 0 : if (!DefaultMethodInUse()) {
851 : // find the matching entry in the request
852 0 : for (DnsItems::const_iterator item = items_.begin();
853 0 : item != items_.end(); ++item) {
854 0 : if (it->name == item->name && it->eclass == item->eclass) {
855 0 : it->name_plen = item->name_plen;
856 0 : it->name_offset = item->offset;
857 0 : name_update_required = false;
858 0 : break;
859 : }
860 : }
861 : }
862 0 : UpdateOffsets(*it, name_update_required);
863 0 : resp_ptr_ = BindUtil::AddAnswerSection(resp_ptr_, *it, dns_resp_size_);
864 0 : dns_->ans_rrcount++;
865 : }
866 :
867 0 : for (DnsItems::iterator it = auth.begin(); it != auth.end(); ++it) {
868 0 : UpdateOffsets(*it, true);
869 0 : UpdateGWAddress(*it);
870 0 : resp_ptr_ = BindUtil::AddAnswerSection(resp_ptr_, *it, dns_resp_size_);
871 0 : dns_->auth_rrcount++;
872 : }
873 :
874 0 : for (DnsItems::iterator it = add.begin(); it != add.end(); ++it) {
875 0 : UpdateOffsets(*it, true);
876 0 : UpdateGWAddress(*it);
877 0 : resp_ptr_ = BindUtil::AddAnswerSection(resp_ptr_, *it, dns_resp_size_);
878 0 : dns_->add_rrcount++;
879 : }
880 :
881 0 : dns_->flags.ret = flags.ret;
882 0 : dns_->flags.auth = flags.auth;
883 0 : dns_->flags.ad = flags.ad;
884 0 : dns_->flags.ra = flags.ra;
885 0 : dns_->ans_rrcount = htons(dns_->ans_rrcount);
886 0 : dns_->auth_rrcount = htons(dns_->auth_rrcount);
887 0 : dns_->add_rrcount = htons(dns_->add_rrcount);
888 0 : SendDnsResponse();
889 0 : }
890 :
891 0 : void DnsHandler::SendDnsResponse() {
892 0 : PktInfo in_pkt_info = *pkt_info_.get();
893 :
894 0 : uint16_t buff_len = in_pkt_info.packet_buffer()->buffer_len();
895 0 : pkt_info_->AllocPacketBuffer(agent(), PktHandler::DNS, buff_len, 0);
896 0 : char *buff = (char *)pkt_info_->packet_buffer()->data();
897 0 : memset(buff, 0, buff_len);
898 0 : pkt_info_->vrf = in_pkt_info.vrf;
899 :
900 0 : uint16_t eth_type = ETHERTYPE_IP;
901 0 : if (in_pkt_info.ip == NULL)
902 0 : eth_type = ETHERTYPE_IPV6;
903 :
904 0 : MacAddress dest_mac(in_pkt_info.eth->ether_shost);
905 0 : pkt_info_->eth = (struct ether_header *)(buff);
906 0 : uint16_t eth_len = 0;
907 0 : eth_len += EthHdr(buff, buff_len, in_pkt_info.GetAgentHdr().ifindex,
908 : agent()->vhost_interface()->mac(), dest_mac, eth_type);
909 :
910 0 : uint16_t data_len = dns_resp_size_;
911 : // fill in the response
912 0 : if (in_pkt_info.ip) {
913 : // IPv4 request
914 0 : in_addr_t src_ip = in_pkt_info.ip->ip_dst.s_addr;
915 0 : in_addr_t dest_ip = in_pkt_info.ip->ip_src.s_addr;
916 :
917 0 : pkt_info_->ip = (struct ip *)(buff + eth_len);
918 0 : pkt_info_->transp.udp = (struct udphdr *)
919 0 : ((uint8_t *)pkt_info_->ip + sizeof(struct ip));
920 :
921 0 : data_len += sizeof(udphdr);
922 0 : UdpHdr(data_len, src_ip, DNS_SERVER_PORT,
923 0 : dest_ip, ntohs(in_pkt_info.transp.udp->uh_sport));
924 0 : data_len += sizeof(struct ip);
925 0 : IpHdr(data_len, src_ip, dest_ip, IPPROTO_UDP,
926 : DEFAULT_IP_ID, DEFAULT_IP_TTL);
927 :
928 : } else {
929 : // IPv6 request
930 0 : Ip6Address src_ip = in_pkt_info.ip_daddr.to_v6();
931 0 : Ip6Address dest_ip = in_pkt_info.ip_saddr.to_v6();
932 :
933 0 : pkt_info_->ip6 = (struct ip6_hdr *)(buff + eth_len);
934 0 : pkt_info_->transp.udp = (struct udphdr *)
935 0 : ((uint8_t *)pkt_info_->ip6 + sizeof(struct ip6_hdr));
936 :
937 0 : data_len += sizeof(udphdr);
938 0 : UdpHdr(data_len, src_ip.to_bytes().data(),
939 0 : DNS_SERVER_PORT, dest_ip.to_bytes().data(),
940 0 : ntohs(in_pkt_info.transp.udp->uh_sport), IPPROTO_UDP);
941 :
942 0 : data_len += sizeof(struct ip6_hdr);
943 0 : Ip6Hdr(pkt_info_->ip6, data_len, IPPROTO_UDP, 64,
944 0 : src_ip.to_bytes().data(), dest_ip.to_bytes().data());
945 : }
946 :
947 0 : memcpy(((char *)pkt_info_->transp.udp + sizeof(udphdr)),
948 0 : ((char *)in_pkt_info.transp.udp + sizeof(udphdr)),
949 0 : dns_resp_size_);
950 :
951 0 : dns_resp_size_ += data_len + eth_len;
952 0 : pkt_info_->set_len(dns_resp_size_);
953 :
954 : PacketInterfaceKey key(
955 0 : boost::uuids::nil_uuid(), agent()->pkt_interface_name());
956 0 : Interface *pkt_itf = static_cast<Interface *>
957 0 : (agent()->interface_table()->FindActiveEntry(&key));
958 0 : if (pkt_itf) {
959 0 : UpdateStats();
960 : uint32_t interface =
961 0 : (pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ?
962 0 : pkt_info_->agent_hdr.cmd_param : GetInterfaceIndex();
963 : uint16_t command =
964 0 : (pkt_info_->agent_hdr.cmd == AgentHdr::TRAP_TOR_CONTROL_PKT) ?
965 0 : (uint16_t)AgentHdr::TX_ROUTE : AgentHdr::TX_SWITCH;
966 0 : Send(interface, pkt_info_->vrf, command, PktHandler::DNS);
967 : } else {
968 0 : agent()->GetDnsProto()->IncrStatsDrop();
969 : }
970 0 : }
971 :
972 0 : void DnsHandler::UpdateQueryNames() {
973 0 : for (DnsItems::iterator it = items_.begin(); it != items_.end(); ++it) {
974 : // do not append domain for empty string (request to root ns)
975 0 : if (it->name.size() == 0) {
976 0 : return;
977 : }
978 :
979 : // do not append domain in case of NS query
980 0 : if (it->type == DNS_NS_RECORD) {
981 0 : return;
982 : }
983 :
984 0 : if (it->name.find('.', 0) == std::string::npos) {
985 0 : it->name.append(".");
986 0 : it->name.append(vdns_type_.domain_name);
987 0 : query_name_update_ = true;
988 : }
989 : }
990 : }
991 :
992 : // In case we added domain name to the queries, the response to the VM
993 : // should not have the domain name. Update the offsets in the DnsItems
994 : // accordingly.
995 0 : void DnsHandler::UpdateOffsets(DnsItem &item, bool name_update_required) {
996 0 : if (!query_name_update_)
997 0 : return;
998 :
999 0 : uint16_t msg_offset = (resp_ptr_ - (uint8_t *)dns_) | 0xC000;
1000 0 : if (name_update_required) {
1001 0 : name_encoder_.AddName(item.name, msg_offset, item.name_plen,
1002 0 : item.name_offset);
1003 : }
1004 0 : msg_offset += BindUtil::DataLength(item.name_plen, item.name_offset,
1005 0 : item.name.size()) + 10;
1006 0 : if (item.type == DNS_TYPE_SOA) {
1007 0 : name_encoder_.AddName(item.soa.primary_ns, msg_offset, item.soa.ns_plen,
1008 0 : item.soa.ns_offset);
1009 0 : msg_offset += BindUtil::DataLength(item.soa.ns_plen, item.soa.ns_offset,
1010 0 : item.soa.primary_ns.size());
1011 0 : name_encoder_.AddName(item.soa.mailbox, msg_offset,
1012 0 : item.soa.mailbox_plen, item.soa.mailbox_offset);
1013 : } else {
1014 0 : name_encoder_.AddName(item.data, msg_offset,
1015 0 : item.data_plen, item.data_offset);
1016 : }
1017 : }
1018 :
1019 0 : void DnsHandler::UpdateGWAddress(DnsItem &item) {
1020 0 : boost::system::error_code ec;
1021 0 : if ((item.type == DNS_A_RECORD || item.type == DNS_AAAA_RECORD) &&
1022 0 : (item.data == agent()->dns_server(0) ||
1023 0 : item.data == agent()->dns_server(1))) {
1024 0 : item.data = pkt_info_->ip_daddr.to_string(ec);
1025 : }
1026 0 : }
1027 :
1028 0 : void DnsHandler::Update(InterTaskMsg *msg) {
1029 0 : DnsProto::DnsUpdateIpc *update = static_cast<DnsProto::DnsUpdateIpc *>(msg);
1030 0 : bool free_update = true;
1031 0 : DnsProto *dns_proto = agent()->GetDnsProto();
1032 0 : DnsProto::DnsUpdateIpc *update_req = dns_proto->FindUpdateRequest(update);
1033 0 : if (update_req) {
1034 0 : DnsUpdateData *data = update_req->xmpp_data;
1035 0 : for (DnsItems::iterator item = update->xmpp_data->items.begin();
1036 0 : item != update->xmpp_data->items.end();) {
1037 0 : if ((*item).IsDelete()) {
1038 0 : if (!data->DelItem(*item))
1039 0 : update->xmpp_data->items.erase(item++);
1040 : else
1041 0 : ++item;
1042 : } else {
1043 0 : if (!data->AddItem(*item))
1044 0 : update->xmpp_data->items.erase(item++);
1045 : else
1046 0 : ++item;
1047 : }
1048 : }
1049 0 : if (!data->items.size()) {
1050 0 : dns_proto->DelUpdateRequest(update_req);
1051 0 : delete update_req;
1052 : }
1053 0 : if (!update->xmpp_data->items.size())
1054 0 : goto done;
1055 : } else {
1056 0 : dns_proto->AddUpdateRequest(update);
1057 0 : free_update = false;
1058 : }
1059 :
1060 0 : for (int i = 0; i < MAX_XMPP_SERVERS; i++) {
1061 0 : AgentDnsXmppChannel *channel = agent()->dns_xmpp_channel(i);
1062 0 : SendXmppUpdate(channel, update->xmpp_data);
1063 : }
1064 :
1065 0 : done:
1066 0 : if (free_update)
1067 0 : delete update;
1068 0 : }
1069 :
1070 338 : void DnsHandler::DelUpdate(InterTaskMsg *msg) {
1071 338 : DnsProto::DnsUpdateIpc *update = static_cast<DnsProto::DnsUpdateIpc *>(msg);
1072 338 : DnsProto *dns_proto = agent()->GetDnsProto();
1073 338 : DnsProto::DnsUpdateIpc *update_req = dns_proto->FindUpdateRequest(update);
1074 338 : while (update_req) {
1075 0 : for (DnsItems::iterator item = update_req->xmpp_data->items.begin();
1076 0 : item != update_req->xmpp_data->items.end(); ++item) {
1077 : // in case of delete, set the class to NONE and ttl to 0
1078 0 : (*item).eclass = DNS_CLASS_NONE;
1079 0 : (*item).ttl = 0;
1080 : }
1081 0 : for (int i = 0; i < MAX_XMPP_SERVERS; i++) {
1082 : AgentDnsXmppChannel *channel =
1083 0 : agent()->dns_xmpp_channel(i);
1084 0 : SendXmppUpdate(channel, update_req->xmpp_data);
1085 : }
1086 0 : dns_proto->DelUpdateRequest(update_req);
1087 0 : delete update_req;
1088 0 : update_req = dns_proto->FindUpdateRequest(update);
1089 : }
1090 338 : delete update;
1091 338 : }
1092 :
1093 0 : void DnsHandler::UpdateStats() {
1094 0 : DnsProto *dns_proto = agent()->GetDnsProto();
1095 0 : switch (dns_->flags.ret) {
1096 0 : case DNS_ERR_NO_ERROR:
1097 0 : dns_proto->IncrStatsRes();
1098 0 : break;
1099 :
1100 0 : case DNS_ERR_NO_IMPLEMENT:
1101 0 : dns_proto->IncrStatsUnsupp();
1102 0 : break;
1103 :
1104 0 : case DNS_ERR_FORMAT_ERROR:
1105 : case DNS_ERR_NO_SUCH_NAME:
1106 : case DNS_ERR_SERVER_FAIL:
1107 : case DNS_ERR_NOT_AUTH:
1108 : default:
1109 0 : dns_proto->IncrStatsFail();
1110 0 : break;
1111 : }
1112 0 : }
1113 :
1114 0 : bool DnsHandler::TimerExpiry(uint16_t xid) {
1115 0 : agent()->GetDnsProto()->SendDnsIpc(DnsProto::DNS_TIMER_EXPIRED, xid,
1116 : NULL, NULL);
1117 0 : return false;
1118 : }
1119 :
1120 0 : void DnsHandler::GetDomainName(const VmInterface *vm_itf,
1121 : std::string *domain_name) const {
1122 0 : std::vector<autogen::DhcpOptionType> options;
1123 0 : if (vm_itf->GetInterfaceDhcpOptions(&options)) {
1124 0 : if (GetDomainNameFromDhcp(options, domain_name))
1125 0 : return;
1126 : }
1127 :
1128 0 : if (pkt_info_->ip_saddr.is_v4()) {
1129 0 : if (vm_itf->GetSubnetDhcpOptions(&options, false) ||
1130 0 : vm_itf->GetIpamDhcpOptions(&options, false)) {
1131 0 : GetDomainNameFromDhcp(options, domain_name);
1132 0 : return;
1133 : }
1134 : }
1135 :
1136 0 : if (pkt_info_->ip_saddr.is_v6()) {
1137 0 : if (vm_itf->GetSubnetDhcpOptions(&options, true) ||
1138 0 : vm_itf->GetIpamDhcpOptions(&options, true)) {
1139 0 : GetDomainNameFromDhcp(options, domain_name);
1140 0 : return;
1141 : }
1142 : }
1143 0 : }
1144 :
1145 0 : bool DnsHandler::GetDomainNameFromDhcp(
1146 : std::vector<autogen::DhcpOptionType> &options,
1147 : std::string *domain_name) const {
1148 0 : for (unsigned int i = 0; i < options.size(); ++i) {
1149 : uint32_t option_type;
1150 0 : std::stringstream str(options[i].dhcp_option_name);
1151 0 : str >> option_type;
1152 0 : if (option_type == DHCP_OPTION_DOMAIN_NAME) {
1153 0 : *domain_name = options[i].dhcp_option_value;
1154 0 : return true;
1155 : }
1156 0 : }
1157 0 : return false;
1158 : }
1159 :
1160 : // remove domain name suffix from given name, if present
1161 0 : void DnsHandler::GetBaseName(const std::string &name, std::string *base) const {
1162 0 : if (domain_name_.empty())
1163 0 : return;
1164 :
1165 0 : std::size_t pos = name.find(domain_name_, 1);
1166 0 : while (pos != std::string::npos) {
1167 0 : std::string base_name = name.substr(0, pos - 1);
1168 0 : if (name == base_name + "." + domain_name_ ||
1169 0 : name == base_name + "." + domain_name_ + ".") {
1170 0 : *base = base_name;
1171 0 : return;
1172 : }
1173 0 : pos = name.find(domain_name_, pos + 1);
1174 0 : }
1175 : }
1176 :
1177 0 : std::string DnsHandler::DnsItemsToString(DnsItems &items) const {
1178 0 : std::string str;
1179 0 : for (DnsItems::const_iterator it = items.begin(); it != items.end(); ++it) {
1180 0 : str.append(it->ToString());
1181 0 : str.append(" ");
1182 : }
1183 0 : return str;
1184 0 : }
|