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