/*
* Copyright (c) 2002-2004 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*/
#include "sm/generic.h"
SM_RCSID("@(#)$Id: t-dnstsk-0.c,v 1.31 2007/06/23 04:48:44 ca Exp $")
#include "sm/assert.h"
#include "sm/magic.h"
#include "sm/error.h"
#include "sm/memops.h"
#include "sm/test.h"
#include "sm/evthr.h"
#include "sm/dns.h"
#include "sm/dns-int.h"
#include "sm/dnstsk.h"
#include <stdio.h>
/*
** Should be protected by a mutex...
** Moreover, this triggers too early if multiple callbacks are used.
*/
static bool terminate = false;
static int Verbose = 0;
static uint MaxCount = 50;
/* Test program options */
#define T_OPT_USE_TCP 0x0001
#define T_OPT_TWICE 0x0002
#define T_OPT_MX 0x0004
#define T_OPT_A 0x0008
#define T_OPT_DEBUG 0x1000
static sm_ret_T
fcts(sm_evthr_task_P tsk)
{
static uint count = 0;
struct timeval sleept, delay;
++count;
if (Verbose > 1 && (count % 10 == 0))
fprintf(stderr, "fcts: count=%u, ", count);
if (terminate || count > MaxCount)
return EVTHR_DEL|EVTHR_TERM;
sm_memzero(&sleept, sizeof(sleept));
gettimeofday(&sleept, NULL);
delay.tv_sec = 0;
delay.tv_usec = 1000;
timeradd(&sleept, &delay, &tsk->evthr_t_sleep);
return EVTHR_SLPQ;
}
static sm_ret_T
callback(dns_res_P dns_res, void *ctx)
{
dns_type_T type;
dns_rese_P dns_rese;
SM_TEST(dns_res != NULL);
if (Verbose > 1)
fprintf(stderr, "callback: got %p, ", dns_res);
if (NULL == dns_res) {
terminate = true;
return SM_FAILURE;
}
if (sm_is_err(dns_res->dnsres_ret)) {
fprintf(stderr, "error: ret=%x\n", dns_res->dnsres_ret);
terminate = true;
return SM_FAILURE;
}
if (Verbose == 0) {
terminate = true;
return SM_SUCCESS;
}
fprintf(stderr, "dnsres: entries=%u\n", dns_res->dnsres_entries);
fprintf(stderr, "dnsres: max=%u\n", dns_res->dnsres_maxentries);
for (dns_rese = DRESL_FIRST(dns_res);
dns_rese != DRESL_END(dns_res);
dns_rese = DRESL_NEXT(dns_rese))
{
type = dns_rese->dnsrese_type;
fprintf(stderr, "ttl=%u\n", dns_rese->dnsrese_ttl);
switch (type)
{
case T_MX:
fprintf(stderr, "pref=%u\n", dns_rese->dnsrese_pref);
fprintf(stderr, "weight=%u\n",
dns_rese->dnsrese_weight);
fprintf(stderr, "value=%s\n\n",
sm_cstr_data(dns_rese->dnsrese_val.dnsresu_name));
break;
case T_A:
fprintf(stderr, "IPv4=%x\n",
dns_rese->dnsrese_val.dnsresu_a);
break;
case T_CNAME:
fprintf(stderr, "CNAME=%s\n\n",
sm_cstr_data(dns_rese->dnsrese_val.dnsresu_name));
break;
default:
fprintf(stderr, "unknown type=%d\n", type);
break;
}
}
terminate = true;
return SM_SUCCESS;
}
/*
** XXX Change this to take a list of hosts? (argv[])
*/
static void
testdns(char *host, uint flags, uint32_t ipv4)
{
sm_ret_T ret;
int n;
#if 0
dns_rslv_ctx_P dns_rslv_ctx;
#endif /* 0 */
dns_mgr_ctx_P dns_mgr_ctx;
#if 0
dns_mxe_P dns_mxe;
dns_mx_P dns_mx;
#endif /* 0 */
sm_evthr_ctx_P evthr_ctx;
sm_evthr_task_P task, task3;
dns_tsk_P dns_tsk;
sm_cstr_P query;
dns_type_T type;
struct timeval sleept;
if (host == NULL || *host == '\0')
return;
dns_tsk = NULL;
evthr_ctx = NULL;
task = task3 = NULL;
dns_mgr_ctx = NULL;
query = sm_cstr_scpyn0((const uchar *) host, strlen(host));
SM_TEST(query != NULL);
if (NULL == query)
return;
sm_memzero(&sleept, sizeof(sleept));
ret = thr_init();
SM_TEST(sm_is_success(ret));
if (sm_is_err(ret))
goto errq;
ret = evthr_init(&evthr_ctx, 1, 6, 10);
SM_TEST(sm_is_success(ret));
if (sm_is_err(ret))
goto errt1;
SM_TEST(evthr_ctx != NULL);
ret = dns_rslv_new(strlen(host)
#if 0
, &dns_rslv_ctx
#endif /* 0 */
);
SM_TEST(SM_SUCCESS == ret);
if (sm_is_err(ret))
goto errt;
if (flags & T_OPT_DEBUG)
_res.options |= RES_DEBUG;
#if 0
SM_TEST(dns_rslv_ctx != NULL);
if (NULL == dns_rslv_ctx)
goto errt;
#endif /* 0 */
ret = dns_mgr_ctx_new(0, DNS_TIMEOUT, 0, 0, &dns_mgr_ctx);
SM_TEST(SM_SUCCESS == ret);
if (sm_is_err(ret))
goto err0;
SM_TEST(dns_mgr_ctx != NULL);
if (NULL == dns_mgr_ctx)
goto err0;
ret = dns_tsk_new(dns_mgr_ctx,
(flags & T_OPT_USE_TCP) ? DNS_TSK_FL_USETCP : 0,
ipv4, &dns_tsk);
SM_TEST(SM_SUCCESS == ret);
if (sm_is_err(ret)) {
fprintf(stderr, "dns_tsk_new: ret=%x\n", ret);
goto err1;
}
SM_TEST(dns_tsk != NULL);
if (NULL == dns_tsk)
goto err1;
ret = dns_tsk_start(dns_mgr_ctx, evthr_ctx);
SM_TEST(sm_is_success(ret));
if (sm_is_err(ret))
goto err1;
type = T_A;
if (flags & T_OPT_MX) {
type = T_MX;
ret = dns_req_add(dns_mgr_ctx, query, type, 0, callback, (void *) NULL);
SM_TEST(sm_is_success(ret));
if (sm_is_err(ret))
goto err1;
}
if (flags & T_OPT_A) {
type = T_A;
ret = dns_req_add(dns_mgr_ctx, query, type, 0, callback, (void *) NULL);
SM_TEST(sm_is_success(ret));
if (sm_is_err(ret))
goto err1;
}
/* test: add the same query again... */
if (flags & T_OPT_TWICE) {
ret = dns_req_add(dns_mgr_ctx, query, type, 0, callback, (void *) NULL);
SM_TEST(sm_is_success(ret));
if (sm_is_err(ret))
goto err1;
}
n = gettimeofday(&sleept, NULL);
SM_TEST(n == 0);
sleept.tv_usec += 1000;
ret = evthr_task_new(evthr_ctx, &task3, EVTHR_EV_SL, -1, &sleept,
fcts, (void *) NULL);
SM_TEST(sm_is_success(ret));
SM_TEST(task3 != NULL);
#if 0
ret = dnstskwr(dns_tsk);
ret = dns_receive(dns_tsk);
#endif /* 0 */
ret = evthr_loop(evthr_ctx);
SM_TEST(sm_is_success(ret));
/* need to get result... */
err1:
ret = dns_mgr_ctx_del(dns_mgr_ctx);
SM_TEST(SM_SUCCESS == ret);
err0:
#if 0
ret = dns_rslv_free(dns_rslv_ctx);
SM_TEST(SM_SUCCESS == ret);
#endif /* 0 */
errt:
ret = evthr_stop(evthr_ctx);
SM_TEST(sm_is_success(ret));
errt1:
ret = thr_stop();
SM_TEST(sm_is_success(ret));
errq:
SM_CSTR_FREE(query);
return;
}
static void
usage(const char *prg)
{
fprintf(stderr, "Usage: %s [options] names\n", prg);
fprintf(stderr, "Options:\n"
"-a query for A record\n"
"-d query twice\n"
"-D turn on debugging\n"
"-i ip use ip address for nameserver [127.0.0.1]\n"
"-m do not query for MX record\n"
"-T use TCP instead of UDP\n"
"-V increase verbosity\n"
);
}
int
main(int argc, char *argv[])
{
int r, i;
uint flags;
uint32_t ipv4;
flags = T_OPT_MX;
ipv4 = htonl(LOCALHOST_IP);
while ((r = getopt(argc, argv, "adDi:mt:TV")) != -1)
{
switch (r)
{
case 'a':
flags |= T_OPT_A;
break;
case 'd':
flags |= T_OPT_TWICE;
break;
case 'D':
flags |= T_OPT_DEBUG;
break;
case 'i':
ipv4 = inet_addr(optarg);
break;
case 'm':
flags &= ~T_OPT_MX;
break;
case 't':
i = atoi(optarg);
if (i <= 0)
return 1;
MaxCount = (uint) i;
break;
case 'T':
flags |= T_OPT_USE_TCP;
break;
case 'V':
Verbose++;
break;
default:
usage(argv[0]);
return 1;
}
}
sm_test_begin(argc, argv, "test getmxrr");
for (r = optind; r < argc; r++)
testdns(argv[r], flags, ipv4);
return sm_test_end();
}
syntax highlighted by Code2HTML, v. 0.9.1