statistics.cc.pre 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. // Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <auth/statistics.h>
  15. #include <auth/statistics_items.h>
  16. #include <auth/auth_log.h>
  17. #include <dns/opcode.h>
  18. #include <dns/rcode.h>
  19. #include <cc/data.h>
  20. #include <cc/session.h>
  21. #include <algorithm>
  22. #include <cctype>
  23. #include <cassert>
  24. #include <string>
  25. #include <sstream>
  26. #include <iostream>
  27. #include <unistd.h>
  28. #include <sys/types.h>
  29. #include <sys/socket.h>
  30. #include <netinet/in.h>
  31. #include <netdb.h>
  32. using namespace isc::dns;
  33. using namespace isc::auth;
  34. using namespace isc::statistics;
  35. using namespace isc::auth::statistics;
  36. namespace {
  37. void
  38. fillNodes(const Counter& counter,
  39. const struct isc::auth::statistics::CounterSpec type_tree[],
  40. isc::auth::statistics::Counters::ItemTreePtr& trees)
  41. {
  42. using namespace isc::data;
  43. for (int i = 0; type_tree[i].name != NULL; ++i) {
  44. if (type_tree[i].sub_counters != NULL) {
  45. isc::auth::statistics::Counters::ItemTreePtr sub_counters =
  46. Element::createMap();
  47. trees->set(type_tree[i].name, sub_counters);
  48. fillNodes(counter, type_tree[i].sub_counters, sub_counters);
  49. } else {
  50. trees->set(type_tree[i].name,
  51. Element::create(static_cast<long int>(
  52. counter.get(type_tree[i].counter_id)))
  53. );
  54. }
  55. }
  56. }
  57. // ### STATISTICS ITEMS DEFINITION ###
  58. } // anonymous namespace
  59. namespace isc {
  60. namespace auth {
  61. namespace statistics {
  62. // Note: opcode in this array must be start with 0 and be sequential
  63. const int opcode_to_msgcounter[] = {
  64. MSG_OPCODE_QUERY, // Opcode = 0: Query
  65. MSG_OPCODE_IQUERY, // Opcode = 1: Iquery
  66. MSG_OPCODE_STATUS, // Opcode = 2: STATUS
  67. MSG_OPCODE_OTHER, // Opcode = 3: (Unassigned)
  68. MSG_OPCODE_NOTIFY, // Opcode = 4: Notify
  69. MSG_OPCODE_UPDATE, // Opcode = 5: Update
  70. MSG_OPCODE_OTHER, // Opcode = 6: (Unassigned)
  71. MSG_OPCODE_OTHER, // Opcode = 7: (Unassigned)
  72. MSG_OPCODE_OTHER, // Opcode = 8: (Unassigned)
  73. MSG_OPCODE_OTHER, // Opcode = 9: (Unassigned)
  74. MSG_OPCODE_OTHER, // Opcode = 10: (Unassigned)
  75. MSG_OPCODE_OTHER, // Opcode = 11: (Unassigned)
  76. MSG_OPCODE_OTHER, // Opcode = 12: (Unassigned)
  77. MSG_OPCODE_OTHER, // Opcode = 13: (Unassigned)
  78. MSG_OPCODE_OTHER, // Opcode = 14: (Unassigned)
  79. MSG_OPCODE_OTHER // Opcode = 15: (Unassigned)
  80. };
  81. const size_t num_opcode_to_msgcounter =
  82. sizeof(opcode_to_msgcounter) / sizeof(opcode_to_msgcounter[0]);
  83. // Note: rcode in this array must be start with 0 and be sequential
  84. const int rcode_to_msgcounter[] = {
  85. MSG_RCODE_NOERROR, // Rcode = 0: NoError
  86. MSG_RCODE_FORMERR, // Rcode = 1: FormErr
  87. MSG_RCODE_SERVFAIL, // Rcode = 2: ServFail
  88. MSG_RCODE_NXDOMAIN, // Rcode = 3: NXDomain
  89. MSG_RCODE_NOTIMP, // Rcode = 4: NotImp
  90. MSG_RCODE_REFUSED, // Rcode = 5: Refused
  91. MSG_RCODE_YXDOMAIN, // Rcode = 6: YXDomain
  92. MSG_RCODE_YXRRSET, // Rcode = 7: YXRRSet
  93. MSG_RCODE_NXRRSET, // Rcode = 8: NXRRSet
  94. MSG_RCODE_NOTAUTH, // Rcode = 9: NotAuth
  95. MSG_RCODE_NOTZONE, // Rcode = 10: NotZone
  96. MSG_RCODE_OTHER, // Rcode = 11: (Unassigned)
  97. MSG_RCODE_OTHER, // Rcode = 12: (Unassigned)
  98. MSG_RCODE_OTHER, // Rcode = 13: (Unassigned)
  99. MSG_RCODE_OTHER, // Rcode = 14: (Unassigned)
  100. MSG_RCODE_OTHER, // Rcode = 15: (Unassigned)
  101. MSG_RCODE_BADVERS // Rcode = 16: BADVERS
  102. };
  103. const size_t num_rcode_to_msgcounter =
  104. sizeof(rcode_to_msgcounter) / sizeof(rcode_to_msgcounter[0]);
  105. Counters::Counters() :
  106. server_msg_counter_(MSG_COUNTER_TYPES)
  107. {}
  108. void
  109. Counters::incRequest(const MessageAttributes& msgattrs) {
  110. // protocols carrying request
  111. if (msgattrs.getRequestIPVersion() == AF_INET) {
  112. server_msg_counter_.inc(MSG_REQUEST_IPV4);
  113. } else if (msgattrs.getRequestIPVersion() == AF_INET6) {
  114. server_msg_counter_.inc(MSG_REQUEST_IPV6);
  115. }
  116. if (msgattrs.getRequestTransportProtocol() == IPPROTO_UDP) {
  117. server_msg_counter_.inc(MSG_REQUEST_UDP);
  118. } else if (msgattrs.getRequestTransportProtocol() == IPPROTO_TCP) {
  119. server_msg_counter_.inc(MSG_REQUEST_TCP);
  120. }
  121. // request TSIG
  122. if (msgattrs.getRequestSigTSIG()) {
  123. server_msg_counter_.inc(MSG_REQUEST_TSIG);
  124. }
  125. if (msgattrs.getRequestSigSIG0()) {
  126. server_msg_counter_.inc(MSG_REQUEST_SIG0);
  127. }
  128. if (msgattrs.getRequestSigBadSig()) {
  129. server_msg_counter_.inc(MSG_REQUEST_BADSIG);
  130. // If signature validation is failed, no other query attributes are
  131. // reliable. Skip processing of the rest of query counters.
  132. return;
  133. }
  134. // request EDNS
  135. if (msgattrs.getRequestEDNS0()) {
  136. server_msg_counter_.inc(MSG_REQUEST_EDNS0);
  137. }
  138. if (msgattrs.getRequestEDNSBadVer()) {
  139. server_msg_counter_.inc(MSG_REQUEST_BADEDNSVER);
  140. }
  141. // request DNSSEC
  142. if (msgattrs.getRequestDO()) {
  143. server_msg_counter_.inc(MSG_REQUEST_DNSSEC_OK);
  144. }
  145. // OPCODE
  146. server_msg_counter_.inc(opcode_to_msgcounter[msgattrs.getRequestOpCode()]);
  147. }
  148. void
  149. Counters::incResponse(const MessageAttributes& msgattrs,
  150. const Message& response)
  151. {
  152. // responded
  153. server_msg_counter_.inc(MSG_RESPONSE);
  154. // response truncated
  155. if (msgattrs.getResponseTruncated()) {
  156. server_msg_counter_.inc(MSG_RESPONSE_TRUNCATED);
  157. }
  158. // response EDNS
  159. ConstEDNSPtr response_edns = response.getEDNS();
  160. if (response_edns && response_edns->getVersion() == 0) {
  161. server_msg_counter_.inc(MSG_RESPONSE_EDNS0);
  162. }
  163. // response TSIG
  164. if (msgattrs.getRequestSigTSIG()) {
  165. // assume response is TSIG signed if request is TSIG signed
  166. server_msg_counter_.inc(MSG_RESPONSE_TSIG);
  167. }
  168. // response SIG(0) is currently not implemented
  169. // RCODE
  170. const unsigned int rcode = response.getRcode().getCode();
  171. const unsigned int rcode_type =
  172. rcode < num_rcode_to_msgcounter ?
  173. rcode_to_msgcounter[rcode] : MSG_RCODE_OTHER;
  174. server_msg_counter_.inc(rcode_type);
  175. // compound attributes
  176. const unsigned int answer_rrs =
  177. response.getRRCount(Message::SECTION_ANSWER);
  178. const bool is_aa_set = response.getHeaderFlag(Message::HEADERFLAG_AA);
  179. if (is_aa_set) {
  180. // QryAuthAns
  181. server_msg_counter_.inc(MSG_QRYAUTHANS);
  182. } else {
  183. // QryNoAuthAns
  184. server_msg_counter_.inc(MSG_QRYNOAUTHANS);
  185. }
  186. if (rcode == Rcode::NOERROR_CODE) {
  187. if (answer_rrs > 0) {
  188. // QrySuccess
  189. server_msg_counter_.inc(MSG_QRYSUCCESS);
  190. } else {
  191. if (is_aa_set) {
  192. // QryNxrrset
  193. server_msg_counter_.inc(MSG_QRYNXRRSET);
  194. } else {
  195. // QryReferral
  196. server_msg_counter_.inc(MSG_QRYREFERRAL);
  197. }
  198. }
  199. } else if (rcode == Rcode::REFUSED_CODE) {
  200. // AuthRej
  201. server_msg_counter_.inc(MSG_QRYREJECT);
  202. }
  203. }
  204. void
  205. Counters::inc(const MessageAttributes& msgattrs, const Message& response,
  206. const bool done)
  207. {
  208. // increment request counters
  209. incRequest(msgattrs);
  210. if (done) {
  211. // increment response counters if answer was sent
  212. incResponse(msgattrs, response);
  213. }
  214. }
  215. Counters::ItemTreePtr
  216. Counters::get() const {
  217. using namespace isc::data;
  218. Counters::ItemTreePtr item_tree = Element::createMap();
  219. Counters::ItemTreePtr zones = Element::createMap();
  220. item_tree->set("zones", zones);
  221. Counters::ItemTreePtr server = Element::createMap();
  222. fillNodes(server_msg_counter_, msg_counter_tree, server);
  223. zones->set("_SERVER_", server);
  224. return (item_tree);
  225. }
  226. } // namespace statistics
  227. } // namespace auth
  228. } // namespace isc