/*
 * Copyright (C) 2000, 2001  Nominum, Inc.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/*
 * Copyright (C) 2004 - 2006 Nominum, Inc.
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose with or without fee is hereby granted,
 * provided that the above copyright notice and this permission notice
 * appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <netinet/in.h>
#include <math.h>
#include <errno.h>
#include <signal.h>

#include <isc/base64.h>
#include <isc/buffer.h>
#include <isc/file.h>
#include <isc/hmacmd5.h>
#include <isc/lex.h>
#include <isc/list.h>
#include <isc/mem.h>
#include <isc/netaddr.h>
#include <isc/sockaddr.h>
#include <isc/parseint.h>
#include <isc/region.h>
#include <isc/result.h>
#include <isc/sockaddr.h>
#include <isc/string.h>
#include <isc/util.h>

#include <dns/callbacks.h>
#include <dns/compress.h>
#include <dns/fixedname.h>
#include <dns/message.h>
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
#include <dns/rdatatype.h>
#include <dns/result.h>
#include <dns/ttl.h>

#include <bind9/getaddresses.h>

#include "version.h"

/*
 * Configuration defaults
 */

#define DEF_SERVER_TO_QUERY		"127.0.0.1"
#define DEF_SERVER_PORT			53
#define DEF_BUFFER_SIZE			32		/* in k */

/*
 * Other constants / definitions
 */

#define COMMENT_CHAR			';'
#define MAX_INPUT_LEN			512
#define EDNSLEN				11
#define MAX_UDP_PACKET			512
#define MAX_EDNS_PACKET			4096
#define MAX_RECV_PACKET			4096

#define TSIG_HMACMD5_NAME		"\010hmac-md5\007sig-alg\003reg\003int"

#define WHITESPACE			" \t\n"

/*
 * Data type definitions
 */

struct query_status;

typedef ISC_LIST(struct query_status) query_list;

struct query_status {
	struct timeval sent_timestamp;
	char *desc;
	/*
	 * This link links the query into the list of outstanding
	 * queries or the list of available query IDs.
	 */
	ISC_LINK(struct query_status) link;
	/*
	 * The list this query is on.
	 */
	query_list *list;
};

/*
 * Configuration options (global)
 */

#ifdef DEFINE_GLOBALS
#define EXTERN
#define INIT(value) = value
#else
#define EXTERN extern
#define INIT(value)
#endif

EXTERN isc_boolean_t print_arguments INIT(ISC_FALSE);
EXTERN isc_uint32_t socket_bufsize INIT(DEF_BUFFER_SIZE);

EXTERN int family INIT(AF_UNSPEC);
EXTERN const char *datafile_name;			/* init NULL */

EXTERN const char *server_name INIT(DEF_SERVER_TO_QUERY);
EXTERN in_port_t server_port INIT(DEF_SERVER_PORT);
EXTERN isc_sockaddr_t server_addr;
EXTERN char server_addr_str[ISC_NETADDR_FORMATSIZE];

EXTERN isc_boolean_t edns INIT(ISC_FALSE);
EXTERN isc_boolean_t dnssec INIT(ISC_FALSE);

EXTERN isc_boolean_t verbose INIT(ISC_FALSE);

EXTERN char *tsigkeyarg;				/* init NULL */

EXTERN isc_boolean_t update_mode INIT(ISC_FALSE);

/*
 * Other global stuff
 */

EXTERN const char *progname;

EXTERN unsigned char outpacket_buffer[MAX_EDNS_PACKET];
EXTERN unsigned char inpacket_buffer[MAX_RECV_PACKET];

EXTERN isc_uint64_t total_request_size;
EXTERN isc_uint64_t total_response_size;

EXTERN FILE *datafile;					/* init NULL */

EXTERN unsigned int num_queries_sent;			/* init 0 */
EXTERN unsigned int num_queries_outstanding;		/* init 0 */

EXTERN struct timeval time_now;				/* init {0,0} */
EXTERN struct timeval time_of_program_start;		/* init {0,0} */
EXTERN struct timeval time_of_end_of_run;		/* init {0,0} */

EXTERN isc_mem_t *mctx;					/* init NULL */
EXTERN isc_lex_t *lexer;				/* init NULL */
EXTERN dns_compress_t compress;

EXTERN isc_region_t tsigalg;
EXTERN dns_fixedname_t tsigfname;
EXTERN dns_name_t *tsigname;				/* init NULL */
EXTERN unsigned char tsigdata[256];
EXTERN isc_buffer_t tsigsecret;

extern const char *rcode_strings[];

#define NQIDS 65536

/*
 * Information about outstanding queries, indexed by query ID.
 */
EXTERN struct query_status status[NQIDS];

/*
 * The list of outstanding queries.
 */
EXTERN query_list outstanding_list;

/*
 * The list of unused query IDs
 */
EXTERN query_list instanding_list;

EXTERN int query_socket INIT(-1);

/*
 * Function prototypes
 */
isc_result_t parse_args(int argc, char **argv, const char *progopts);
void show_usage(void);
void show_usage_prog(void);
void show_options_prog(void);
void show_usage_common(void);
void show_options_common(void);
isc_boolean_t register_response(unsigned int id, unsigned int rcode);
isc_result_t handle_prog_opt(int c);
isc_result_t parse_udouble(double *dp, const char *string);
double difftv(const struct timeval *tv1, const struct timeval *tv2);
void update_current_time(void);
isc_result_t setup(int argc, char **argv, const char *progopts);
isc_result_t get_input_line(char *line, int n);
isc_result_t process_line(char *query_desc);
isc_boolean_t try_process_response(int sockfd);
void cleanup(void);
void maybe_print_args(int argc, char **argv);


syntax highlighted by Code2HTML, v. 0.9.1