/* * Copyright (C), 2000-2007 by the monit project group. * All Rights Reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #ifdef HAVE_STDIO_H #include #endif #ifdef HAVE_ERRNO_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif #include "protocol.h" /** * Simple DNS test. * * The nameserver is queried for NS record of DNS root. * * @author Martin Pala, * * @version \$Id: dns.c,v 1.7 2007/07/25 12:54:32 hauk Exp $ * * @file */ int check_dns(Socket_T s) { int offset_request = 0; int offset_response = 0; unsigned char buf[STRLEN]; unsigned char *response = NULL; unsigned char request[19] = { 0x00, /** Request Length field for DNS via TCP */ 0x11, 0x00, /** Transaction ID */ 0x01, 0x01, /** Flags */ 0x00, 0x00, /** Queries count */ 0x01, 0x00, /** Answer resource records count */ 0x00, 0x00, /** Authority resource records count */ 0x00, 0x00, /** Additional resource records count */ 0x00, /** Query: */ 0x00, /** Name: DNS root (empty string) */ 0x00, /** Type: NS */ 0x02, 0x00, /** Class: IN */ 0x01 }; ASSERT(s); switch(socket_get_type(s)) { case SOCK_DGRAM: offset_request = 2; /* Skip Length field in request */ offset_response = 0; break; case SOCK_STREAM: offset_request = 0; offset_response = 2; /* Skip Length field in response */ break; default: LogError("DNS: unsupported socket type -- protocol test skipped\n"); return TRUE; } if(socket_write(s, (unsigned char *)request + offset_request, sizeof(request) - offset_request) < 0) { LogError("DNS: error sending query -- %s\n", STRERROR); return FALSE; } /* Response should have at least 14 bytes */ if(socket_read(s, (unsigned char *)buf, 15) <= 14) { LogError("DNS: error receiving response -- %s\n", STRERROR); return FALSE; } response = buf + offset_response; /* Compare transaction ID (it should be the same as in our request): */ if(response[0] != 0x00 && response[1] != 0x01) { LogError("DNS: transaction ID mismatch\n"); return FALSE; } /* Compare flags: */ if((response[2] & 0x80) != 0x80) /* Response type */ { LogError("DNS: message is not response\n"); return FALSE; } if((response[3] & 0x0F) != 0x00) /* Response code */ { LogError("DNS: invalid reply code -- error occured\n"); return FALSE; } /* Compare queries count (it should be one as in our request): */ if(response[4] != 0x00 && response[5] != 0x01) { LogError("DNS: query count mismatch\n"); return FALSE; } /* Compare answer resource records count (it should not be zero): */ if(response[6] == 0x00 && response[7] == 0x00) { LogError("DNS: no answer records returned\n"); return FALSE; } return TRUE; }