Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : */
4 :
5 : #include "base/util.h"
6 : #include "base/logging.h"
7 : #include "xmpp/xmpp_init.h"
8 : #include <pugixml/pugixml.hpp>
9 : #include "xml/xml_pugi.h"
10 : #include "bind/bind_util.h"
11 : #include "bind/xmpp_dns_agent.h"
12 :
13 : SandeshTraceBufferPtr AgentXmppTraceBuf(SandeshTraceBufferCreate("Xmpp", 500));
14 :
15 : std::size_t
16 0 : DnsAgentXmpp::DnsAgentXmppEncode(XmppChannel *channel,
17 : XmppType type,
18 : uint32_t trans_id,
19 : uint32_t response_code,
20 : DnsUpdateData *xmpp_data,
21 : uint8_t *data) {
22 0 : if (!channel)
23 0 : return 0;
24 :
25 0 : std::unique_ptr<XmlBase> impl(XmppStanza::AllocXmppXmlImpl());
26 0 : XmlPugi *pugi = reinterpret_cast<XmlPugi *>(impl.get());
27 : std::string iq_type =
28 : (type == DnsQuery) ? "get" :
29 0 : (type == Update) ? "set" : "result";
30 :
31 0 : pugi->AddNode("iq", "");
32 0 : pugi->AddAttribute("type", iq_type);
33 0 : pugi->AddAttribute("from", channel->FromString());
34 0 : std::string to(channel->ToString());
35 0 : to += "/";
36 0 : to += XmppInit::kDnsPeer;
37 0 : pugi->AddAttribute("to", to);
38 0 : std::stringstream id;
39 0 : id << trans_id;
40 0 : pugi->AddAttribute("id", id.str());
41 :
42 0 : pugi->AddChildNode("dns", "");
43 0 : pugi->AddAttribute("transid", id.str());
44 :
45 0 : std::stringstream code;
46 0 : code << response_code;
47 0 : pugi::xml_node node;
48 0 : switch (type) {
49 0 : case Update:
50 0 : pugi->AddChildNode("update", "");
51 0 : node = pugi->FindNode("update");
52 0 : break;
53 :
54 0 : case UpdateResponse:
55 0 : pugi->AddChildNode("response", "");
56 0 : pugi->AddAttribute("code", code.str());
57 0 : pugi->AddChildNode("update", "");
58 0 : node = pugi->FindNode("update");
59 0 : break;
60 :
61 0 : case DnsQuery:
62 0 : pugi->AddChildNode("query", "");
63 0 : node = pugi->FindNode("query");
64 0 : break;
65 :
66 0 : case DnsQueryResponse:
67 0 : pugi->AddChildNode("response", "");
68 0 : pugi->AddAttribute("code", code.str());
69 0 : pugi->AddChildNode("query", "");
70 0 : node = pugi->FindNode("query");
71 0 : break;
72 :
73 0 : default:
74 0 : assert(0);
75 : }
76 :
77 0 : EncodeDnsData(&node, xmpp_data);
78 0 : return XmppProto::EncodeMessage(impl.get(), data, sizeof(data));
79 0 : }
80 :
81 : void
82 0 : DnsAgentXmpp::EncodeDnsData(pugi::xml_node *node, DnsUpdateData *xmpp_data) {
83 0 : pugi::xml_node node_c;
84 :
85 0 : node_c = node->append_child("virtual-dns");
86 0 : node_c.text().set(xmpp_data->virtual_dns.c_str());
87 :
88 0 : node_c = node->append_child("zone");
89 0 : node_c.text().set(xmpp_data->zone.c_str());
90 :
91 0 : for (DnsItems::iterator item = xmpp_data->items.begin();
92 0 : item != xmpp_data->items.end(); ++item) {
93 0 : node_c = node->append_child("entry");
94 0 : EncodeDnsItem(&node_c, *item);
95 : }
96 0 : }
97 :
98 : void
99 0 : DnsAgentXmpp::EncodeDnsItem(pugi::xml_node *node, DnsItem &item) {
100 0 : pugi::xml_node node_c;
101 :
102 0 : node_c = node->append_child("class");
103 0 : node_c.text().set(item.eclass);
104 :
105 0 : node_c = node->append_child("type");
106 0 : node_c.text().set(item.type);
107 :
108 0 : node_c = node->append_child("name");
109 0 : node_c.text().set(item.name.c_str());
110 :
111 0 : if (item.data != "") {
112 0 : node_c = node->append_child("data");
113 0 : node_c.text().set(item.data.c_str());
114 : }
115 :
116 0 : if (item.ttl != (uint32_t) -1) {
117 0 : node_c = node->append_child("ttl");
118 0 : node_c.text().set(item.ttl);
119 : }
120 :
121 0 : if (item.priority != (uint16_t) -1) {
122 0 : node_c = node->append_child("priority");
123 0 : node_c.text().set(item.priority);
124 : }
125 0 : }
126 :
127 : bool
128 0 : DnsAgentXmpp::DnsAgentXmppDecode(const pugi::xml_node dns,
129 : XmppType &type, uint32_t &xid,
130 : uint16_t &resp_code, DnsUpdateData *data, std::string source_name) {
131 0 : std::stringstream id(dns.attribute("transid").value());
132 0 : id >> xid;
133 :
134 0 : pugi::xml_node resp = dns.first_child();
135 0 : if (strcmp(resp.name(), "response") == 0) {
136 0 : std::stringstream code(resp.attribute("code").value());
137 0 : code >> resp_code;
138 0 : return DecodeDns(resp.first_child(), type, true, data, source_name);
139 0 : } else
140 0 : return DecodeDns(resp, type, false, data, source_name);
141 0 : }
142 :
143 : bool
144 0 : DnsAgentXmpp::DecodeDns(const pugi::xml_node node,
145 : XmppType &type,
146 : bool is_resp,
147 : DnsUpdateData *data, std::string source_name) {
148 0 : if (strcmp(node.name(), "update") == 0) {
149 0 : type = is_resp ? UpdateResponse : Update;
150 0 : return DecodeDnsItems(node, data, source_name);
151 0 : } else if (strcmp(node.name(), "query") == 0) {
152 0 : type = is_resp ? DnsQueryResponse : DnsQuery;
153 0 : return DecodeDnsItems(node, data, source_name);
154 : }
155 :
156 0 : DNS_XMPP_TRACE(DnsXmppTrace, "Dns XMPP response : unknown tag : " <<
157 : node.name());
158 0 : return false;
159 : }
160 :
161 : bool
162 0 : DnsAgentXmpp::DecodeDnsItems(const pugi::xml_node dnsdata,
163 : DnsUpdateData *data, std::string source_name) {
164 0 : for (pugi::xml_node node = dnsdata.first_child(); node;
165 0 : node = node.next_sibling()) {
166 0 : if (strcmp(node.name(), "virtual-dns") == 0) {
167 0 : data->virtual_dns = node.child_value();
168 0 : } else if (strcmp(node.name(), "zone") == 0) {
169 0 : data->zone = node.child_value();
170 0 : } else if (strcmp(node.name(), "entry") == 0) {
171 0 : DnsItem item;
172 0 : for (pugi::xml_node entry = node.first_child(); entry;
173 0 : entry = entry.next_sibling()) {
174 0 : if (strcmp(entry.name(), "class") == 0) {
175 0 : std::stringstream cl(entry.child_value());
176 0 : cl >> item.eclass;
177 0 : } else if (strcmp(entry.name(), "type") == 0) {
178 0 : std::stringstream type(entry.child_value());
179 0 : type >> item.type;
180 0 : } else if (strcmp(entry.name(), "name") == 0) {
181 0 : item.name = entry.child_value();
182 0 : } else if (strcmp(entry.name(), "data") == 0) {
183 0 : item.data = entry.child_value();
184 0 : } else if (strcmp(entry.name(), "ttl") == 0) {
185 0 : std::stringstream ttl(entry.child_value());
186 0 : ttl >> item.ttl;
187 0 : } else if (strcmp(entry.name(), "priority") == 0) {
188 0 : std::stringstream prio(entry.child_value());
189 0 : prio >> item.priority;
190 0 : } else {
191 0 : DNS_XMPP_TRACE(DnsXmppTrace,
192 : "Dns XMPP response : unknown tag : " <<
193 : node.name());
194 0 : return false;
195 : }
196 : }
197 0 : item.source_name = source_name;
198 0 : data->items.push_back(item);
199 0 : } else {
200 0 : DNS_XMPP_TRACE(DnsXmppTrace, "Dns XMPP response : unknown tag : " <<
201 : node.name());
202 0 : return false;
203 : }
204 : }
205 :
206 0 : return true;
207 : }
|