[Nagiosplug-devel] check_dns
Awais Ahmad
awais at eurobell.net
Mon Feb 23 04:49:45 CET 2004
I have done this with the stable version of check_dns.c but never had
the time to carry the changes across to HEAD. The patch is attached.
Although the main resolver lib functions are available, via
GLIBC/LIBC,the response parsing routines (ns_parserr and friends) are
only visible to the resolver lib functions themselves.
I've had to roll my own.
I've tested on Debian GNU/Linux, Redhat GNU/Linux, FreeBSD current/4.X
and Solaris 7.
Awais Ahmad
On Fri, 2004-02-20 at 03:52, Karl DeBisschop wrote:
> On Thu, 2004-02-19 at 22:34, Ton Voon wrote:
>
> > I'll have a go at this change, but only after I can get check_dns to
> > use the resolver routines instead of nslookup first. Most of
> > check_dns.c looks like it is parsing for error messages in nslookup!
>
> Makes sense to me. That was the direction we wanted to go anyway, to use
> the resolver instead of parsing scripts.
>
> IIRC, the resolver is covered by POSIX, so we should have much less
> platform-specific cruft once we do that.
>
> --
> Karl
>
>
>
> -------------------------------------------------------
> SF.Net is sponsored by: Speed Start Your Linux Apps Now.
> Build and deploy apps & Web services for Linux with
> a free DVD software kit from IBM. Click Now!
> http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click
> _______________________________________________
> Nagiosplug-devel mailing list
> Nagiosplug-devel at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/nagiosplug-devel
> ::: Please include plugins version (-v) and OS when reporting any issue.
> ::: Messages without supporting info will risk being sent to /dev/null
>
-------------- next part --------------
--- check_dns.c Sat Nov 15 23:24:22 2003
+++ check_dns.c.current Mon Feb 23 12:38:28 2004
@@ -6,11 +6,12 @@
* License: GPL
* Copyright (c) 1999 Ethan Galstad (nagios at nagios.org)
*
- * Last Modified: $Date: 2003/02/21 21:46:27 $
+ * Last Modified: $Date: 2003/05/31 14:39:33 $
*
* Notes:
* - Safe popen added by Karl DeBisschop 9-11-99
* - expected-address parameter added by Alex Chaffee - 7 Oct 2002
+ * - modified to use resolver libs by Awais Ahmad - 14/11/2003
*
* Command line: (see print_usage)
*
@@ -44,19 +45,21 @@
*
*****************************************************************************/
+#include <resolv.h>
+#include <arpa/nameser.h>
+#include <netinet/in.h>
#include "common.h"
-#include "popen.h"
#include "utils.h"
+
const char *progname = "check_dns";
-#define REVISION "$Revision: 1.8 $"
+#define REVISION "$Revision: 1.8.2.3 $"
#define COPYRIGHT "2000-2002"
int process_arguments (int, char **);
int validate_arguments (void);
void print_usage (void);
void print_help (void);
-int error_scan (char *);
#define ADDRESS_LENGTH 256
char query_address[ADDRESS_LENGTH] = "";
@@ -75,186 +78,59 @@
char *address = NULL;
char *temp_buffer = NULL;
int result = STATE_UNKNOWN;
+ char queryresult[ADDRESS_LENGTH];
+
- /* Set signal handling and alarm */
- if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
- printf ("Cannot catch SIGALRM");
- return STATE_UNKNOWN;
- }
if (process_arguments (argc, argv) != OK) {
print_usage ();
return STATE_UNKNOWN;
}
- /* get the command to run */
- asprintf (&command_line, "%s %s %s", NSLOOKUP_COMMAND, query_address, dns_server);
+ /* Set signal handling and alarm */
+ if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
+ printf ("Cannot catch SIGALRM");
+ return STATE_UNKNOWN;
+ }
alarm (timeout_interval);
time (&start_time);
- if (verbose)
- printf ("%s\n", command_line);
- /* run the command */
- child_process = spopen (command_line);
- if (child_process == NULL) {
- printf ("Could not open pipe: %s\n", command_line);
- return STATE_UNKNOWN;
- }
+ if (verbose)
+ printf("Query address:%s DNS server:%s\n", query_address, dns_server);
- child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
- if (child_stderr == NULL)
- printf ("Could not open stderr for %s\n", command_line);
-
- /* scan stdout */
- while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
-
- if (verbose)
- printf ("%s\n", input_buffer);
-
- if (strstr (input_buffer, ".in-addr.arpa")) {
- if ((temp_buffer = strstr (input_buffer, "name = ")))
- address = strscpy (address, temp_buffer + 7);
- else {
- output = strscpy (output, "Unknown error (plugin)");
- result = STATE_WARNING;
- }
- }
+ result = nslookup(dns_server, query_address, &queryresult, verbose);
+
+ (void) time (&end_time);
- /* the server is responding, we just got the host name... */
- if (strstr (input_buffer, "Name:")) {
+ if (result == STATE_CRITICAL) {
- /* get the host address */
- if (!fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process))
- break;
-
- if (verbose)
- printf ("%s\n", input_buffer);
-
- if ((temp_buffer = index (input_buffer, ':'))) {
- temp_buffer++;
- /* Strip leading spaces */
- for (; *temp_buffer != '\0' && *temp_buffer == ' '; temp_buffer++)
- /* NOOP */;
- address = strscpy (address, temp_buffer);
- strip (address);
- result = STATE_OK;
- }
- else {
- output = strscpy (output, "Unknown error (plugin)");
- result = STATE_WARNING;
- }
+ terminate (STATE_CRITICAL,
+ "DNS CRITICAL - '%s'\n", strerror(errno));
- break;
- }
+ }else if (result == STATE_WARNING) {
- result = error_scan (input_buffer);
- if (result != STATE_OK) {
- output = strscpy (output, 1 + index (input_buffer, ':'));
- break;
- }
+ /* query succeeded with no result */
+ printf("DNS WARNING - Server has no records for %s\n", query_address);
- }
+ /* compare to expected address */
+ }else if (match_expected_address && strcmp(queryresult, expected_address)) {
- /* scan stderr */
- while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
- if (error_scan (input_buffer) != STATE_OK) {
- result = max_state (result, error_scan (input_buffer));
- output = strscpy (output, 1 + index (input_buffer, ':'));
- }
- }
+ result = STATE_CRITICAL;
+ printf("DNS CRITICAL - expected %s but got %s\n", expected_address, queryresult);
- /* close stderr */
- (void) fclose (child_stderr);
+ }else if (result == STATE_OK) {
- /* close stdout */
- if (spclose (child_process)) {
- result = max_state (result, STATE_WARNING);
- if (!strcmp (output, ""))
- output = strscpy (output, "nslookup returned error status");
+ printf ("DNS ok - %d seconds response time, Address is %s\n",
+ (int) (end_time - start_time), queryresult);
}
- /* compare to expected address */
- if (result == STATE_OK && match_expected_address && strcmp(address, expected_address)) {
- result = STATE_CRITICAL;
- asprintf(&output, "expected %s but got %s", expected_address, address);
- }
-
- (void) time (&end_time);
+
- if (result == STATE_OK)
- printf ("DNS ok - %d seconds response time, Address(es) is/are %s\n",
- (int) (end_time - start_time), address);
- else if (result == STATE_WARNING)
- printf ("DNS WARNING - %s\n",
- !strcmp (output, "") ? " Probably a non-existent host/domain" : output);
- else if (result == STATE_CRITICAL)
- printf ("DNS CRITICAL - %s\n",
- !strcmp (output, "") ? " Probably a non-existent host/domain" : output);
- else
- printf ("DNS problem - %s\n",
- !strcmp (output, "") ? " Probably a non-existent host/domain" : output);
return result;
}
-int
-error_scan (char *input_buffer)
-{
-
- /* the DNS lookup timed out */
- if (strstr (input_buffer,
- "Note: nslookup is deprecated and may be removed from future releases.")
- || strstr (input_buffer,
- "Consider using the `dig' or `host' programs instead. Run nslookup with")
- || strstr (input_buffer,
- "the `-sil[ent]' option to prevent this message from appearing."))
- return STATE_OK;
-
- /* the DNS lookup timed out */
- else if (strstr (input_buffer, "Timed out"))
- return STATE_WARNING;
-
- /* DNS server is not running... */
- else if (strstr (input_buffer, "No response from server"))
- return STATE_CRITICAL;
-
- /* Host name is valid, but server doesn't have records... */
- else if (strstr (input_buffer, "No records"))
- return STATE_WARNING;
-
- /* Host or domain name does not exist */
- else if (strstr (input_buffer, "Non-existent"))
- return STATE_CRITICAL;
- else if (strstr (input_buffer, "** server can't find"))
- return STATE_CRITICAL;
- else if(strstr(input_buffer,"NXDOMAIN")) /* 9.x */
- return STATE_CRITICAL;
-
- /* Connection was refused */
- else if (strstr (input_buffer, "Connection refused"))
- return STATE_CRITICAL;
-
- /* Network is unreachable */
- else if (strstr (input_buffer, "Network is unreachable"))
- return STATE_CRITICAL;
-
- /* Internal server failure */
- else if (strstr (input_buffer, "Server failure"))
- return STATE_CRITICAL;
-
- /* DNS server refused to service request */
- else if (strstr (input_buffer, "Refused"))
- return STATE_CRITICAL;
-
- /* Request error */
- else if (strstr (input_buffer, "Format error"))
- return STATE_WARNING;
-
- else
- return STATE_OK;
-
-}
/* process command-line arguments */
int
@@ -421,3 +297,106 @@
"be specified. If no DNS server is specified, the default server(s)\n"
"specified in /etc/resolv.conf will be used.\n", DEFAULT_SOCKET_TIMEOUT);
}
+
+
+
+
+int nslookup(char *target, char *question, char *result, int verbose) {
+
+ char replybuffer[ADDRESS_LENGTH*4];
+ char *eom;
+ char *pos;
+ char tmp[1024]="";
+ char name[ADDRESS_LENGTH]="";
+ char cname[ADDRESS_LENGTH]="";
+ int totalcount, count, offset, rrtype;
+ u_int16_t type;
+ u_int16_t class;
+ u_int16_t rdlength;
+ u_int32_t ttl;
+ struct in_addr target_in_addr, ipaddr, t_ipaddr;
+
+ if (res_init() != 0) {
+
+ if (verbose) printf("Call to res_init(3) failed:%s\n",
+ (char *)strerror(errno));
+ return STATE_CRITICAL;
+
+ }
+
+ inet_aton(target, &target_in_addr.s_addr);
+ /* change _res to only contain our target name server */
+ _res.nscount = 1;
+ _res.nsaddr_list[0].sin_addr = target_in_addr;
+
+ if (inet_aton(question, &ipaddr.s_addr) == 0) {
+ rrtype = T_A;
+ }else{
+ /* if this is an IP, then type is T_PTR */
+ rrtype = T_PTR;
+ /* reverse the octets */
+ t_ipaddr.s_addr = ipaddr.s_addr >> 24;
+ t_ipaddr.s_addr += (((ipaddr.s_addr >> 16) & 0xff) << 8);
+ t_ipaddr.s_addr += (((ipaddr.s_addr >> 8) & 0xff) << 16);
+ t_ipaddr.s_addr += ((ipaddr.s_addr & 0xff) << 24);
+
+ strcpy(tmp, (char *)inet_ntoa(t_ipaddr.s_addr));
+ strncat(tmp, ".in-addr.arpa", 13);
+ question=tmp;
+ }
+
+ /* zero out buffer */
+ bzero(replybuffer, sizeof(replybuffer));
+ totalcount = res_query(question, C_IN, rrtype, replybuffer,
+ sizeof(replybuffer));
+
+ if ( totalcount == -1 ) {
+ if (errno == 0 ) {
+ /* query succeeded with no result */
+ if (verbose) printf("Server has no records for %s\n", question);
+ return STATE_WARNING;
+ }
+ if (verbose) printf("Call to res_query(3) failed:%s\n",
+ (char *)strerror(errno));
+ return STATE_CRITICAL;
+
+ }
+ eom = replybuffer + totalcount;
+ count = dn_expand(replybuffer, eom,
+ replybuffer + 12, tmp, 1024);
+ offset = count + 16;
+ /* this gets us to the start of the reply */
+ count = dn_expand(replybuffer, eom,
+ replybuffer + offset, name, 1024);
+ offset += count;
+ pos = offset + replybuffer;
+ /* we are at type now*/
+ NS_GET16(type, pos);
+ NS_GET16(class, pos);
+ NS_GET32(ttl, pos);
+ NS_GET16(rdlength, pos);
+
+ if (type == T_CNAME) {
+ /* another lookup is required */
+ count = dn_expand(replybuffer, eom,
+ pos, cname, 1024);
+ return nslookup(target, cname, result, verbose);
+ }
+
+ if (type == T_PTR) {
+ count = dn_expand(replybuffer, eom,
+ pos, result, 1024);
+ }else{
+ memcpy(&t_ipaddr, (int *)pos, 4);
+ strcpy(result, (char *)inet_ntoa(t_ipaddr));
+ }
+ if (verbose) {
+
+ printf("\nName: %s\n", name);
+ printf("Type: %hu\n", type);
+ printf("TTL: %u\n", ttl);
+ printf("IP: %s\n\n", result);
+ }
+ return STATE_OK;
+}
+
More information about the Devel
mailing list