21 boost::asio::io_context &io)
22 :
ProtoHandler(agent, info, io), resp_ptr_(NULL), dns_resp_size_(0),
23 xid_(-1), action_(
NONE), rkey_(NULL),
24 query_name_update_(false), pend_req_(0), default_method_(false),
68 std::vector<string>dns_servers;
69 while (count < resolvers_count) {
72 boost::is_any_of(
":"));
75 boost::system::error_code ec;
77 assert(ec.value() == 0);
79 if (dns_servers.size() > 1)
80 dns_port = strtoul(dns_servers[1].c_str(), NULL, 10);
81 resolver->
ep_.port(dns_port);
84 ss <<
"DnsHandlerTimer " << count;
86 *(
agent()->event_manager()->io_service()), ss.str(),
100 while (count < def_slist.size()) {
103 resolver->
ep_.address(def_slist[count]);
106 std::stringstream ss;
107 ss <<
"DefDnsHandlerTimer " << count;
109 *(
agent()->event_manager()->io_service()), ss.str(),
137 DNS_BIND_TRACE(DnsBindError,
"Received Invalid DNS request - dropping"
138 <<
"; itf = " << itf <<
"; flags.req = "
146 DNS_BIND_TRACE(DnsBindError,
"DNS request on VM port with disabled"
147 "ipv4 service: " << itf);
155 <<
"; flags.op = " <<
dns_->
flags.
op <<
"; flags.cd = "
168 DNS_BIND_TRACE(DnsBindError,
"Unable to find Ipam data; interface = "
174 if (
ipam_type_.ipam_dns_method ==
"default-dns-server" ||
178 DNS_BIND_TRACE(DnsBindError,
"Default DNS request : Update received, ignoring");
185 }
else if (
ipam_type_.ipam_dns_method ==
"virtual-dns-server") {
187 if (!
agent()->domain_config_table()->GetVDns(
ipam_type_.ipam_dns_server.
189 DNS_BIND_TRACE(DnsBindError,
"Unable to find domain; interface = "
197 }
else if (
ipam_type_.ipam_dns_method ==
"none") {
199 <<
"ipam_dns_method set to none, ignoring request");
214 tbb::mutex::scoped_lock lock(
mutex_);
220 "Retry DNS query from VM - dropping; interface = "
231 "interface = " << vmitf->
vm_name() <<
" xid = " <<
250 DNS_BIND_TRACE(DnsBindTrace,
"No DNS resolvers for Default DNS query"
251 " with xid = " <<
dns_->
xid <<
";interface = "
258 "interface = " << vmitf->
vm_name() <<
" xid = " <<
267 DNS_BIND_TRACE(DnsBindTrace,
"Unable to send DNS query to resolvers;"
268 " xid = " <<
dns_->
xid <<
"; interface = "
285 " xid = " <<
dns_->
xid <<
" " <<
301 "Retry DNS query from VM - dropping; interface = " <<
311 virtual_dns_server_name);
320 "interface = " << vmitf->
vm_name() <<
" xid = " <<
339 bool query_success =
false;
347 query_success =
true;
364 update_data, vmitf,
false);
369 virtual_dns_server_name;
377 "dynamic records : " << vmitf->
vm_name() <<
" ;Ignoring "
390 <<
"from vm : " << vmitf->
vm_name());
408 "Max retries reached for query; xid = " << xid <<
426 DNS_BIND_TRACE(DnsBindTrace,
"DNS query sent to named server : " <<
427 resolver->
ep_.address().to_string() <<
"; xid =" <<
448 switch (item->type) {
451 std::string base_name;
453 std::set<IpAddress> service_ips;
455 (!base_name.empty() &&
457 for (std::set<IpAddress>::iterator it = service_ips.begin();
458 it != service_ips.end(); ++it) {
459 item->data = it->to_string();
460 linklocal_items->push_back(*item);
467 std::set<std::string> service_names;
468 boost::asio::ip::address addr;
475 addr.to_v4(), &service_names)) {
476 for (std::set<std::string>::iterator it = service_names.begin();
477 it != service_names.end(); ++it) {
479 linklocal_items->push_back(*item);
493 return (linklocal_items->size() > 0);
498 bool linklocal_request =
false;
499 for (DnsItems::iterator it =
items_.begin(); it !=
items_.end(); ) {
502 linklocal_request =
true;
503 for (DnsItems::iterator llit = linklocal_items.begin();
504 llit != linklocal_items.end(); ++llit) {
516 return linklocal_request;
558 uint16_t xid = ntohs(*(uint16_t *)ipc->
resp);
561 bool valid_response =
false;
566 ques, ans, auth, add)) {
572 " xid = " << xid <<
" " <<
576 valid_response =
true;
577 handler->
Resolve(flags, ques, ans, auth, add);
579 "Query successful : xid = " <<
587 "Invalid DNS action: xid = " << xid);
592 "Received invalid BIND response: xid = " << xid);
598 if (valid_response) {
628 DNS_BIND_TRACE(DnsBindError,
"Invalid or Response ignored xid " << xid <<
629 " received from DNS server - dropping");
644 handler->
Resolve(flags, ques, ans, auth, add);
646 "Send invalid BIND response: xid = " << xid);
649 "No response sent: xid = " << xid);
662 if ((code > 1 && code < 6) || code == 9) {
690 uint16_t xid = ipc->
xid;
741 std::vector<DnsProto::DnsUpdateIpc *> change_list;
743 for (DnsProto::DnsUpdateSet::const_iterator it = update_set.begin();
744 it != update_set.end(); ++it) {
746 ((*it)->itf != ipc->
itf || (*it)->floatingIp != ipc->
floatingIp)) ||
747 !((*it)->xmpp_data) || (*it)->xmpp_data->virtual_dns != ipc->
old_vdns)
750 change_list.push_back(*it);
755 for (DnsItems::iterator item = (*it)->xmpp_data->items.begin();
756 item != (*it)->xmpp_data->items.end(); ++item) {
766 for (
unsigned int i = 0; i < change_list.size(); i++) {
769 delete change_list[i];
773 for (
unsigned int i = 0; i < change_list.size(); i++) {
774 change_list[i]->xmpp_data->virtual_dns = ipc->
new_vdns;
775 std::string &zone = change_list[i]->xmpp_data->zone;
776 if (zone.find(
".in-addr.arpa") == std::string::npos &&
777 zone.find(
".ip6.arpa") == std::string::npos)
779 for (DnsItems::iterator item = change_list[i]->xmpp_data->items.begin();
780 item != change_list[i]->xmpp_data->items.end(); ++item) {
782 (*item).ttl = ipc->
ttl;
797 for (DnsProto::DnsUpdateSet::const_iterator it = update_set.begin();
798 it != update_set.end(); ++it) {
811 DnsItems::iterator first, last;
813 uint32_t size = xmpp_data->
items.size();
814 store.swap(xmpp_data->
items);
819 first = last = store.begin();
824 xmpp_data->
items.splice(xmpp_data->
items.begin(), store, first, last);
836 done.splice(done.end(), xmpp_data->items, xmpp_data->items.begin(),
837 xmpp_data->items.end());
839 xmpp_data->
items.swap(done);
846 for (DnsItems::iterator it = ans.begin(); it != ans.end(); ++it) {
847 bool name_update_required =
true;
851 for (DnsItems::const_iterator item =
items_.begin();
852 item !=
items_.end(); ++item) {
853 if (it->name == item->name && it->eclass == item->eclass) {
854 it->name_plen = item->name_plen;
855 it->name_offset = item->offset;
856 name_update_required =
false;
866 for (DnsItems::iterator it = auth.begin(); it != auth.end(); ++it) {
873 for (DnsItems::iterator it = add.begin(); it != add.end(); ++it) {
895 char *buff = (
char *)
pkt_info_->packet_buffer()->data();
896 memset(buff, 0, buff_len);
899 uint16_t eth_type = ETHERTYPE_IP;
900 if (in_pkt_info.
ip == NULL)
901 eth_type = ETHERTYPE_IPV6;
904 pkt_info_->eth = (
struct ether_header *)(buff);
905 uint16_t eth_len = 0;
911 if (in_pkt_info.
ip) {
913 in_addr_t src_ip = in_pkt_info.
ip->ip_dst.s_addr;
914 in_addr_t dest_ip = in_pkt_info.
ip->ip_src.s_addr;
916 pkt_info_->ip = (
struct ip *)(buff + eth_len);
917 pkt_info_->transp.udp = (
struct udphdr *)
918 ((uint8_t *)
pkt_info_->ip +
sizeof(
struct ip));
920 data_len +=
sizeof(udphdr);
922 dest_ip, ntohs(in_pkt_info.
transp.
udp->uh_sport));
923 data_len +=
sizeof(
struct ip);
924 IpHdr(data_len, src_ip, dest_ip, IPPROTO_UDP,
932 pkt_info_->ip6 = (
struct ip6_hdr *)(buff + eth_len);
933 pkt_info_->transp.udp = (
struct udphdr *)
934 ((uint8_t *)
pkt_info_->ip6 +
sizeof(
struct ip6_hdr));
936 data_len +=
sizeof(udphdr);
937 UdpHdr(data_len, src_ip.to_bytes().data(),
939 ntohs(in_pkt_info.
transp.
udp->uh_sport), IPPROTO_UDP);
941 data_len +=
sizeof(
struct ip6_hdr);
943 src_ip.to_bytes().data(), dest_ip.to_bytes().data());
946 memcpy(((
char *)
pkt_info_->transp.udp +
sizeof(udphdr)),
947 ((
char *)in_pkt_info.
transp.
udp +
sizeof(udphdr)),
954 boost::uuids::nil_uuid(),
agent()->pkt_interface_name());
972 for (DnsItems::iterator it =
items_.begin(); it !=
items_.end(); ++it) {
974 if (it->name.size() == 0) {
983 if (it->name.find(
'.', 0) == std::string::npos) {
984 it->name.append(
".");
998 uint16_t msg_offset = (
resp_ptr_ - (uint8_t *)
dns_) | 0xC000;
999 if (name_update_required) {
1004 item.
name.size()) + 10;
1019 boost::system::error_code ec;
1029 bool free_update =
true;
1036 if ((*item).IsDelete()) {
1048 if (!data->
items.size()) {
1056 free_update =
false;
1073 while (update_req) {
1074 for (DnsItems::iterator item = update_req->
xmpp_data->
items.begin();
1120 std::string *domain_name)
const {
1121 std::vector<autogen::DhcpOptionType>
options;
1145 std::vector<autogen::DhcpOptionType> &
options,
1146 std::string *domain_name)
const {
1147 for (
unsigned int i = 0; i < options.size(); ++i) {
1148 uint32_t option_type;
1149 std::stringstream str(options[i].dhcp_option_name);
1152 *domain_name = options[i].dhcp_option_value;
1165 while (pos != std::string::npos) {
1166 std::string base_name = name.substr(0, pos - 1);
1178 for (DnsItems::const_iterator it = items.begin(); it != items.end(); ++it) {
1179 str.append(it->ToString());
bool GetIpamDhcpOptions(std::vector< autogen::DhcpOptionType > *options, bool ipv6) const
PacketBuffer * packet_buffer() const
void BuildDefaultDnsResolvers()
void DelVmRequest(DnsHandler::QueryKey *key)
#define DNS_BIND_TRACE(obj, arg)
DnsItems linklocal_items_
void UpdateGWAddress(DnsItem &item)
void GetDomainName(const VmInterface *vm_itf, std::string *domain_name) const
static Agent * GetInstance()
DnsUpdateData * xmpp_data
std::string DnsItemsToString(DnsItems &items) const
void GetBaseName(const std::string &name, std::string *base) const
bool HandleDefaultDnsResponse()
bool GetSubnetDhcpOptions(std::vector< autogen::DhcpOptionType > *options, bool ipv6) const
int16_t GetDnsQueryServerIndex(uint16_t xid)
boost::asio::ip::udp::endpoint ep_
static int BuildDnsQuery(uint8_t *buf, uint16_t xid, const std::string &domain, const DnsItems &items)
bool is_dns_xmpp_channel(AgentDnsXmppChannel *channel)
std::vector< string > & GetDnslist()
void DelDnsQuery(uint16_t xid)
const Interface * vhost_interface() const
void DelUpdate(InterTaskMsg *msg)
static const uint16_t max_dns_xmpp_msg_len
bool GetInterfaceDhcpOptions(std::vector< autogen::DhcpOptionType > *options) const
virtual bool SendMsg(uint8_t *msg, std::size_t len)
void DelUpdateRequest(DnsUpdateIpc *ipc)
std::list< DnsItem > DnsItems
void DelDnsQueryIndex(uint16_t xid)
#define DNS_ERR_NO_SUCH_NAME
AgentDBEntry * FindActiveEntry(const DBEntry *key)
InterfaceTable * interface_table() const
struct ether_header * eth
#define DNS_ERR_FORMAT_ERROR
static const int max_pkt_size
void DelDnsQueryHandler(DnsHandler *handler)
bool NeedRetryForNextServer(uint16_t code)
const MacAddress & mac() const
void IncrStatsRetransmitReq()
uint32_t max_retries() const
std::vector< DnsResolverInfo * > dns_resolvers_
bool SendDnsQuery(DnsResolverInfo *resolver, uint16_t xid)
static uint8_t * AddAnswerSection(uint8_t *ptr, const DnsItem &item, uint16_t &length)
autogen::VirtualDnsType vdns_type_
void SendXmppUpdate(AgentDnsXmppChannel *channel, DnsUpdateData *xmpp_data)
void AddName(std::string &name, uint16_t curr_msg_offset, uint16_t &name_plen, uint16_t &name_offset)
void AddDnsQueryIndex(uint16_t xid, int16_t srv_idx)
void AddUpdateRequest(DnsUpdateIpc *ipc)
boost::shared_ptr< PktInfo > pkt_info_
static const std::string & DnsResponseCode(uint16_t code)
int GetTaskId(const std::string &name)
bool FindLinkLocalService(const std::string &service_name, IpAddress *service_ip, uint16_t *service_port, std::string *fabric_hostname, Ip4Address *fabric_ip, uint16_t *fabric_port) const
Get link local service configuration info, for a given service name.
static bool ParseDnsResponse(uint8_t *dns, uint16_t dnslen, uint16_t &xid, dns_flags &flags, DnsItems &ques, DnsItems &ans, DnsItems &auth, DnsItems &add)
static void RemoveSpecialChars(std::string &name)
bool DefaultMethodInUse()
AgentDnsXmppChannel * dns_xmpp_channel(uint8_t idx) const
DnsHandler(Agent *agent, boost::shared_ptr< PktInfo > info, boost::asio::io_context &io)
autogen::IpamType ipam_type_
bool IsDnsQueryInProgress(uint16_t xid)
int EthHdr(const MacAddress &src, const MacAddress &dest, const uint16_t proto)
bool IsDnsHandlerInUse(DnsHandler *handler)
GlobalVrouter * global_vrouter() const
static bool ParseDnsUpdate(uint8_t *dns, uint16_t dnslen, DnsUpdateData &data)
std::set< DnsUpdateIpc *, UpdateCompare > DnsUpdateSet
void SendDnsIpc(uint8_t *pkt, std::size_t length)
uint32_t GetInterfaceIndex() const
static bool ParseDnsQuery(uint8_t *dns, uint16_t dnslen, uint16_t *parsed_length, DnsItems &items)
static TaskScheduler * GetInstance()
void UpdateOffsets(DnsItem &item, bool name_update_required)
boost::asio::ip::address_v6 Ip6Address
void Send(uint32_t itf, uint32_t vrf, uint16_t, PktHandler::PktModuleName)
uint16_t buffer_len() const
bool layer3_forwarding() const
void AddDnsQuery(uint16_t xid, DnsHandler *handler)
static BindResolver * Resolver()
void DefaultDnsSendResponse()
static uint16_t DataLength(uint16_t plen, uint16_t offset, uint16_t size)
DnsHandler * GetDnsQueryHandler(uint16_t xid)
DnsNameEncoder name_encoder_
const VnEntry * vn() const
bool AddItem(DnsItem &item, bool replace=false) const
bool HandleUpdateResponse()
bool ResolveLinkLocalRequest(DnsItems::iterator &item, DnsItems *linklocal_items) const
static Timer * CreateTimer(boost::asio::io_context &service, const std::string &name, int task_id=Timer::GetTimerTaskId(), int task_instance=Timer::GetTimerInstanceId(), bool delete_on_completion=false)
void Update(InterTaskMsg *msg)
void Ip6Hdr(ip6_hdr *ip, uint16_t plen, uint8_t next_header, uint8_t hlim, uint8_t *src, uint8_t *dest)
void AddVmRequest(DnsHandler::QueryKey *key)
DefaultServerList GetDefaultServerList()
bool ResolveAllLinkLocalRequests()
std::vector< DnsResolverInfo * > def_dns_resolvers_
const DnsUpdateSet & update_set() const
const Ip4Address & primary_ip_addr() const
static std::size_t DnsAgentXmppEncode(XmppChannel *channel, XmppType type, uint32_t trans_id, uint32_t resp_code, DnsUpdateData *xmpp_data, uint8_t *data)
const AgentHdr & GetAgentHdr() const
IpAddress AddressFromString(const std::string &ip_address_str, boost::system::error_code *ec)
#define DNS_ERR_NO_IMPLEMENT
const std::string & vm_name() const
bool GetDomainNameFromDhcp(std::vector< autogen::DhcpOptionType > &options, std::string *domain_name) const
static bool GetAddrFromPtrName(std::string &ptr_name, IpAddress &mask)
bool DelItem(DnsItem &item) const
void UdpHdr(uint16_t len, in_addr_t src, uint16_t src_port, in_addr_t dest, uint16_t dest_port)
DnsProto * GetDnsProto() const
void Resolve(dns_flags flags, const DnsItems &ques, DnsItems &ans, DnsItems &auth, DnsItems &add)
const Ip6Address & primary_ip6_addr() const
bool Start(int time, Handler handler, ErrorHandler error_handler=NULL)
bool SendToDefaultServer()
bool HandleVirtualDnsRequest(const VmInterface *vmitf)
static const uint32_t max_items_per_xmpp_msg
static void BuildDnsHeader(dnshdr *dns, uint16_t xid, DnsReq req, DnsOpcode op, bool rd, bool ra, uint8_t ret, uint16_t ques_count)
const Interface * FindInterface(size_t index) const
AgentDnsXmppChannel * channel
const std::string & name() const
bool HandleDefaultDnsRequest(const VmInterface *vmitf)
#define DNS_ERR_SERVER_FAIL
#define DHCP_OPTION_DOMAIN_NAME
XmppChannel * GetXmppChannel()
bool TimerExpiry(uint16_t xid)
DnsUpdateIpc * FindUpdateRequest(DnsUpdateIpc *ipc)
bool HandleBindResponse()
void IpHdr(uint16_t len, in_addr_t src, in_addr_t dest, uint8_t protocol, uint16_t id, uint8_t ttl)
static bool DeleteTimer(Timer *Timer)
bool GetIpamData(const IpAddress &vm_addr, std::string *ipam_name, autogen::IpamType *ipam_type) const
bool IsVmRequestDuplicate(DnsHandler::QueryKey *key)
void HandleInvalidBindResponse(DnsHandler *handler, dns_flags flags, const DnsItems &ques, DnsItems &ans, DnsItems &auth, DnsItems &add, uint16_t xid)