/*
 * 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 <http://www.gnu.org/licenses/>.
 */

#include <config.h>

#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif

#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif

#ifdef HAVE_STRING_H
#include <string.h>
#endif

#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif

#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif

#include "protocol.h"

/**
 *  Simple DNS test.
 *
 *  The nameserver is queried for NS record of DNS root.
 *
 *  @author Martin Pala, <martinp@tildeslash.com>
 *
 *  @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;
    
}



syntax highlighted by Code2HTML, v. 0.9.1