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