1<?php 2 3/** 4 * Observium 5 * 6 * This file is part of Observium. 7 * 8 * @package observium 9 * @subpackage poller 10 * @copyright (C) 2006-2013 Adam Armstrong, (C) 2013-2019 Observium Limited 11 * 12 */ 13 14if (!empty($agent_data['app']['bind']['global'])) 15{ 16 $app_id = discover_app($device, 'bind'); 17 18 // Prepare data arrays 19 // ------------------- 20 $rrtypes = array('SOA', 'ANY', 'A', 'AAAA', 'NS', 'MX', 'CNAME', 'DNAME', 'TXT', 'SPF', 'SRV', 'SSHFP', 'TLSA', 'IPSECKEY', 'PTR', 'DNSKEY', 'RRSIG', 'NSEC', 'NSEC3', 'NSEC3PARAM', 'DS', 'DLV', 'IXFR', 'AXFR'); 21 22 // Requests incoming 23 $req_in = array( 24 'QUERY' => 0, 25 'STATUS' => 0, 26 'NOTIFY' => 0, 27 'UPDATE' => 0, 28 ); 29 30 // Query incoming 31 $query_in = array(); 32 foreach ($rrtypes as $rrtype) 33 { 34 $query_in[$rrtype] = 0; 35 } 36 37 // Query outgoing 38 $query_out = array(); 39 40 // Name server statistics 41 $ns_stats_field_mapping = array( 42 "IPv4 requests received" => 'Requestv4', 43 "IPv6 requests received" => 'Requestv6', 44 "requests with EDNS(0) received" => 'ReqEdns0', 45 "requests with unsupported EDNS version received" => 'ReqBadEDNSVer', 46 "requests with TSIG received" => 'ReqTSIG', 47 "requests with SIG(0) received" => 'ReqSIG0', 48 "requests with invalid signature" => 'ReqBadSIG', 49 "TCP requests received" => 'ReqTCP', 50 "auth queries rejected" => 'AuthQryRej', 51 "recursive queries rejected" => 'RecQryRej', 52 "transfer requests rejected" => 'XfrRej', 53 "update requests rejected" => 'UpdateRej', 54 "responses sent" => 'Response', 55 "truncated responses sent" => 'TruncatedResp', 56 "responses with EDNS(0) sent" => 'RespEDNS0', 57 "responses with TSIG sent" => 'RespTSIG', 58 "responses with SIG(0) sent" => 'RespSIG0', 59 "queries resulted in successful answer" => 'QrySuccess', 60 "queries resulted in authoritative answer" => 'QryAuthAns', 61 "queries resulted in non authoritative answer" => 'QryNoauthAns', 62 "queries resulted in referral answer" => 'QryReferral', 63 "queries resulted in nxrrset" => 'QryNxrrset', 64 "queries resulted in SERVFAIL" => 'QrySERVFAIL', 65 "queries resulted in FORMERR" => 'QryFORMERR', 66 "queries resulted in NXDOMAIN" => 'QryNXDOMAIN', 67 "queries caused recursion" => 'QryRecursion', 68 "duplicate queries received" => 'QryDuplicate', 69 "queries dropped" => 'QryDropped', 70 "other query failures" => 'QryFailure', 71 "requested transfers completed" => 'XfrReqDone', 72 "update requests forwarded" => 'UpdateReqFwd', 73 "update responses forwarded" => 'UpdateRespFwd', 74 "update forward failed" => 'UpdateFwdFail', 75 "updates completed" => 'UpdateDone', 76 "updates failed" => 'UpdateFail', 77 "updates rejected due to prerequisite failure" => 'UpdateBadPrereq', 78 "response policy zone rewrites" => 'RPZRewrites', 79 ); 80 81 $ns_stats_fields = array_values($ns_stats_field_mapping); 82 array_sort($ns_stats_fields, 'Requestv4'); 83 84 $ns_stats = array(); 85 foreach ($ns_stats_fields as $field) 86 { 87 $ns_stats[$field] = 0; 88 } 89 90 // Zone maintenance 91 $zone_maint_field_mapping = array( 92 "IPv4 notifies sent" => 'NotifyOutv4', 93 "IPv6 notifies sent" => 'NotifyOutv6', 94 "IPv4 notifies received" => 'NotifyInv4', 95 "IPv6 notifies received" => 'NotifyInv6', 96 "notifies rejected" => 'NotifyRej', 97 "IPv4 SOA queries sent" => 'SOAOutv4', 98 "IPv6 SOA queries sent" => 'SOAOutv6', 99 "IPv4 AXFR requested" => 'AXFRReqv4', 100 "IPv6 AXFR requested" => 'AXFRReqv6', 101 "IPv4 IXFR requested" => 'IXFRReqv4', 102 "IPv6 IXFR requested" => 'IXFRReqv6', 103 "transfer requests succeeded" => 'XfrSuccess', 104 "transfer requests failed" => 'XfrFail', 105 ); 106 107 $zone_maint_fields = array_values($zone_maint_field_mapping); 108 array_sort($zone_maint_fields, 'NotifyOutv4'); 109 110 $zone_maint = array(); 111 foreach ($zone_maint_fields as $field) 112 { 113 $zone_maint[$field] = 0; 114 } 115 116 // Resolver 117 $resolver_field_mapping = array( 118 "IPv4 queries sent" => 'Queryv4', 119 "IPv6 queries sent" => 'Queryv6', 120 "IPv4 responses received" => 'Responsev4', 121 "IPv6 responses received" => 'Responsev6', 122 "NXDOMAIN received" => 'NXDOMAIN', 123 "SERVFAIL received" => 'SERVFAIL', 124 "FORMERR received" => 'FORMERR', 125 "other errors received" => 'OtherError', 126 "EDNS(0) query failures" => 'EDNS0Fail', 127 "mismatch responses received" => 'Mismatch', 128 "truncated responses received" => 'Truncated', 129 "lame delegations received" => 'Lame', 130 "query retries" => 'Retry', 131 "queries aborted due to quota" => 'QueryAbort', 132 "failures in opening query sockets" => 'QuerySockFail', 133 "query timeouts" => 'QueryTimeout', 134 "IPv4 NS address fetches" => 'GlueFetchv4', 135 "IPv6 NS address fetches" => 'GlueFetchv6', 136 "IPv4 NS address fetch failed" => 'GlueFetchv4Fail', 137 "IPv6 NS address fetch failed" => 'GlueFetchv6Fail', 138 "DNSSEC validation attempted" => 'ValAttempt', 139 "DNSSEC validation succeeded" => 'ValOk', 140 "DNSSEC NX validation succeeded" => 'ValNegOk', 141 "DNSSEC validation failed" => 'ValFail', 142 "queries with RTT < 10ms" => 'QryRTT10', 143 "queries with RTT 10-100ms" => 'QryRTT100', 144 "queries with RTT 100-500ms" => 'QryRTT500', 145 "queries with RTT 500-800ms" => 'QryRTT800', 146 "queries with RTT 800-1600ms" => 'QryRTT1600', 147 "queries with RTT > 1600ms" => 'QryRTT1600plus', 148 ); 149 150 $resolver_fields = array_values($resolver_field_mapping); 151 array_sort($resolver_fields, 'Queryv4'); 152 153 $resolver = array(); 154 155 // Cache 156 $cache = array(); 157 158 // Store the data in arrays 159 // ------------------------ 160 $lines = explode("\n", $agent_data['app']['bind']['global']); 161 foreach ($lines as $line) { 162 // Line format is "key:value" 163 list ($key, $value) = explode(':', $line); 164 165 // Keys consist of "section,subkey" 166 list ($section, $subkey) = explode(',', $key, 2); 167 168 // The subkey depends on the section 169 if ($section == 'req-in') 170 { 171 // Subkey is the opcode 172 $req_in[$subkey] = (int) $value; 173 } 174 elseif ($section == 'query-in') 175 { 176 // Subkey is the RRType 177 $query_in[$subkey] = (int) $value; 178 } 179 elseif ($section == 'ns-stats') 180 { 181 // Subkey is description 182 if (isset($ns_stats_field_mapping[$subkey])) 183 { 184 $subkey = $ns_stats_field_mapping[$subkey]; 185 } 186 $ns_stats[$subkey] = (int) $value; 187 } 188 elseif ($section == 'zone-maint') 189 { 190 // Subkey is description 191 if (isset($zone_maint_field_mapping[$subkey])) 192 { 193 $subkey = $zone_maint_field_mapping[$subkey]; 194 } 195 $zone_maint[$subkey] = (int) $value; 196 } 197 } 198 199 // Done with the global stuff 200 unset($agent_data['app']['bind']['global']); 201 202 // The rest is views 203 foreach ($agent_data['app']['bind'] as $view => $view_data) 204 { 205 $lines = explode("\n", $agent_data['app']['bind'][$view]); 206 foreach ($lines as $line) { 207 // Line format is "key:value" 208 list ($key, $value) = explode(':', $line); 209 210 // Keys consist of "section,subkey" 211 list ($section, $subkey) = explode(',', $key, 2); 212 213 // The subkey depends on the section 214 if ($section == 'query-out') 215 { 216 // Create the view if it doesn't exist yet 217 if (!isset($query_out[$view])) 218 { 219 foreach ($rrtypes as $rrtype) 220 { 221 $query_out[$view][$rrtype] = 0; 222 } 223 } 224 225 // Subkey is the RRType 226 $query_out[$view][$subkey] = (int) $value; 227 } 228 elseif ($section == 'resolver') 229 { 230 // Create the view if it doesn't exist yet 231 if (!isset($resolver[$view])) 232 { 233 foreach ($resolver_fields as $field) 234 { 235 $resolver[$view][$field] = 0; 236 } 237 } 238 239 // Subkey is the description 240 if (isset($resolver_field_mapping[$subkey])) 241 { 242 $subkey = $resolver_field_mapping[$subkey]; 243 } 244 $resolver[$view][$subkey] = (int) $value; 245 } 246 elseif ($section == 'cache') 247 { 248 // Create the view if it doesn't exist yet 249 if (!isset($cache[$view])) 250 { 251 foreach ($rrtypes as $rrtype) 252 { 253 // Create fields for both positive and negative cache entries 254 $cache[$view][$field] = 0; 255 $cache[$view]['!'.$field] = 0; 256 } 257 } 258 // Subkey is the RRType 259 $cache[$view][$subkey] = (int) $value; 260 } 261 } 262 } 263 264 // Use the data from the arrays to build RRDs 265 // ------------------------------------------ 266 267 // rrdcreate list of rrtypes 268 $rrdcreate_rrtypes = ""; 269 foreach ($rrtypes as $rrtype) 270 { 271 $rrdcreate_rrtypes .= " DS:$rrtype:DERIVE:600:0:7500000"; 272 } 273 274 // req-in 275 rrdtool_update_ng($device, 'bind-req-in', array( 276 'query' => $req_in['QUERY'], 277 'status' => $req_in['STATUS'], 278 'notify' => $req_in['NOTIFY'], 279 'update' => $req_in['UPDATE'], 280 ), $app_id); 281 282 // query-in 283 $rrd_filename = "app-bind-$app_id-query-in.rrd"; 284 285 rrdtool_create($device, $rrd_filename, " $rrdcreate_rrtypes "); 286 287 $rrd_data = ""; 288 foreach ($rrtypes as $rrtype) 289 { 290 $rrd_data .= ":".$query_in[$rrtype]; 291 } 292 rrdtool_update($device, $rrd_filename, "N".$rrd_data); 293 294 // ns-stats 295 $rrd_filename = "app-bind-$app_id-ns-stats.rrd"; 296 297 // rrdcreate list of fields 298 $rrdcreate_ns_stats = ""; 299 foreach ($ns_stats_fields as $field) 300 { 301 $rrdcreate_ns_stats .= " DS:$field:DERIVE:600:0:7500000"; 302 } 303 304 rrdtool_create($device, $rrd_filename, " $rrdcreate_ns_stats "); 305 306 $rrd_data = ""; 307 foreach ($ns_stats_fields as $field) 308 { 309 $rrd_data .= ":".$ns_stats[$field]; 310 } 311 rrdtool_update($device, $rrd_filename, "N".$rrd_data); 312 313 // zone-maint 314 $rrd_filename = "app-bind-$app_id-zone-maint.rrd"; 315 316 // rrdcreate list of fields 317 $rrdcreate_zone_maint = ""; 318 foreach ($zone_maint_fields as $field) 319 { 320 $rrdcreate_zone_maint .= " DS:$field:DERIVE:600:0:7500000"; 321 } 322 rrdtool_create($device, $rrd_filename, " $rrdcreate_zone_maint "); 323 324 $rrd_data = ""; 325 foreach ($zone_maint_fields as $field) 326 { 327 $rrd_data .= ":".$zone_maint[$field]; 328 } 329 rrdtool_update($device, $rrd_filename, "N".$rrd_data); 330 331 // query-out 332 foreach ($query_out as $view => $view_data) 333 { 334 $rrd_filename = "app-bind-$app_id-query-out-".$view.".rrd"; 335 336 rrdtool_create($device, $rrd_filename, " $rrdcreate_rrtypes "); 337 338 $rrd_data = ""; 339 foreach ($rrtypes as $rrtype) 340 { 341 $rrd_data .= ":".$view_data[$rrtype]; 342 } 343 rrdtool_update($device, $rrd_filename, "N".$rrd_data); 344 } 345 346 // resolver 347 foreach ($resolver as $view => $view_data) 348 { 349 $rrd_filename = "app-bind-$app_id-resolver-$view.rrd"; 350 351 // rrdcreate list of fields 352 $rrdcreate_resolver = ""; 353 foreach ($resolver_fields as $field) 354 { 355 $rrdcreate_resolver .= " DS:$field:DERIVE:600:0:7500000"; 356 } 357 rrdtool_create($device, $rrd_filename, " $rrdcreate_resolver "); 358 359 $rrd_data = ""; 360 foreach ($resolver_fields as $field) 361 { 362 $rrd_data .= ":".$view_data[$field]; 363 } 364 rrdtool_update($device, $rrd_filename, "N".$rrd_data); 365 } 366 367 // cache 368 foreach ($cache as $view => $view_data) 369 { 370 $rrd_filename = "app-bind-$app_id-cache-$view.rrd"; 371 372 $rrdcreate_cache = ""; 373 foreach ($rrtypes as $rrtype) 374 { 375 $rrdcreate_cache .= " DS:$rrtype:GAUGE:600:0:1000000"; 376 $rrdcreate_cache .= " DS:NEG_$rrtype:GAUGE:600:0:1000000"; 377 } 378 rrdtool_create($device, $rrd_filename, " $rrdcreate_cache "); 379 380 $rrd_data = ""; 381 foreach ($rrtypes as $rrtype) 382 { 383 $rrd_data .= ":".$view_data[$rrtype]; 384 $rrd_data .= ":".$view_data['!'.$rrtype]; 385 } 386 rrdtool_update($device, $rrd_filename, "N".$rrd_data); 387 } 388 389 390 // FIXME 391 update_application($app_id, array()); 392 393} 394 395// EOF 396