From: ian Date: Wed, 1 Dec 2004 00:22:06 +0000 (+0000) Subject: adns compiles and does not work X-Git-Tag: debian/1.1.1~116 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-tcl.git;a=commitdiff_plain;h=cc93324adf9022c227322bc691103b56c2a70b68 adns compiles and does not work --- diff --git a/adns/adns.c b/adns/adns.c index c18ccad..34ca06c 100644 --- a/adns/adns.c +++ b/adns/adns.c @@ -3,9 +3,9 @@ /* * adns lookup TYPE DOMAIN [QUERY-OPTIONS] => [list RDATA] * if no or dontknow, throws an exception, with errorCode one of - * ADNS NO 300 nxdomain {No such domain} - * ADNS NO 301 nodata {No such data} - * ADNS FAILED ERROR-CODE ERROR-NAME ERROR-STRING + * ADNS permfail 300 nxdomain {No such domain} + * ADNS permfail 301 nodata {No such data} + * ADNS tempfail ERROR-CODE ERROR-NAME ERROR-STRING * where * ERROR-CODE is the numerical adns status value * ERROR-NAME is the symbolic adns status value (in lowercase) @@ -56,65 +56,29 @@ #include "tables.h" #include "hbytes.h" -IdDataTable adnstcl_resolvers= { "adns-res" }; -IdDataTable adnstcl_queries= { "adns-q" }; - -typedef struct { - int ix; /* first! */ - Tcl_Interp *interp; fixme what about interpreter deletion - adns_state *ads; - int maxfd; - fd_set handling[3]; -} Resolver; - -typedef struct { - int ix; /* first! */ - adns_query *aqu; - Tcl_Obj *on_yes, *on_no, *on_fail, *xargs; -} Query; - -static adns_state *adnstcl_default; -static int default_auto; +/*---------- important types and forward declarations ----------*/ -#define RRTYPE_EXACTLY(t) { #t, adns_r_##t } -#define RRTYPE_RAW(t) { #t, adns_r_##t##_raw } -#define RRTYPE_PLUS(t) { #t "+", adns_r_##t } -#define RRTYPE_MINUS(t) { #t "-", adns_r_##t##_raw } - -const AdnsTclRRTypeInfo adnstclrrtypeinfos[]= { - RRTYPE_EXACTLY(a), - RRTYPE_EXACTLY(cname), - RRTYPE_EXACTLY(hinfo), - RRTYPE_EXACTLY(addr), - - RRTYPE_RAW(ns), - RRTYPE_RAW(mx), - - RRTYPE_EXACTLY(soa), - RRTYPE_EXACTLY(ptr), - RRTYPE_EXACTLY(rp), +typedef struct Resolver Resolver; +typedef struct OptionInfo OptionInfo; +static void asynch_check(Resolver *res); +static void asynch_sethandlers(Resolver *res, int shutdown); - RRTYPE_MINUS(soa), - RRTYPE_MINUS(ptr), - RRTYPE_MINUS(rp), - { 0 } -}; +/*---------- common resolver/query option processing ----------*/ typedef struct { /* this struct type is used to hold both resolver and query options */ /* common to resolver and query: */ - unsigned long *aflags; - unsigned long *sflags; + unsigned long aflags; + unsigned long sflags; /* resolver: */ FILE *errfile; Tcl_Obj *errcallback; const char *config_string; /* query: */ - adns_state *resolver; + Resolver *resolver; const char *reverseany; } OptionParse; -typedef struct OptionInfo OptionInfo; struct OptionInfo { const char *name; int (*fn)(Tcl_Interp *ip, const OptionInfo *oi, Tcl_Obj *arg, @@ -129,53 +93,18 @@ enum { }; static int oiufn_f(const OptionInfo *oi, unsigned long *flags) { - flags &= ~oi->flags_remove; - flags |= oi->flsgs_add; + *flags &= ~oi->flags_remove; + *flags |= oi->flags_add; + return TCL_OK; } static int oifn_fa(Tcl_Interp *ip, const OptionInfo *oi, Tcl_Obj *arg, - OptionParse *op) { oiufn_f(oi,op->aflags); } + OptionParse *op) { return oiufn_f(oi,&op->aflags); } static int oifn_fs(Tcl_Interp *ip, const OptionInfo *oi, Tcl_Obj *arg, - OptionParse *op) { oiufn_f(oi,op->sflags); } - -static int oifn_errfile(Tcl_Interp *ip, const OptionInfo *oi, - Tcl_Obj *arg, OptionParse *op) { - int rc; - const char *str; - - rc= pat_string(ip,arg,&str); if (rc) return rc; - if (!strcmp(str,"stderr")) op.errfile= stderr; - else if (!strcmp(str,"stdout")) op.errfile= stdout; - else return staticerr(ip,"-errfile argument must be stderr or stdout",0); - - op.aflags &= ~adns_if_noerrprint; - op.errcallback= 0; - return TCL_OK; -} - -static int oifn_errcallback(Tcl_Interp *ip, const OptionInfo *oi, - Tcl_Obj *arg, OptionParse *op) { - op.errcallback= arg; - op.aflags &= ~adns_if_noeerpring; - op.errfile= 0; - return TCL_OK; -} - -static int oifn_config(Tcl_Interp *ip, const OptionInfo *oi, - Tcl_Obj *arg, OptionParse *op) { - return pat_string(ip,arg,&op.config_string); -} - -static int oifn_resolver(Tcl_Interp *ip, const OptionInfo *oi, - Tcl_Obj *arg, OptionParse *op) { - void *val_v; - rc= pat_iddata(ip,arg,&val_v,adnstcl_resolvers); - if (rc) return rc; - op.resolver= val_v; -} + OptionParse *op) { return oiufn_f(oi,&op->sflags); } static int oifn_reverse_any(Tcl_Interp *ip, const OptionInfo *oi, Tcl_Obj *arg, OptionParse *op) { - return pat_string(ip,arg,&op.reverseany); + return pat_string(ip,arg,&op->reverseany); } #define OIFA1(t,f,r) { "-" #f, oifn_fa, 0, adns_##t##_##f, r } @@ -183,44 +112,20 @@ static int oifn_reverse_any(Tcl_Interp *ip, const OptionInfo *oi, #define OIFS(f) { "-" #f, oifn_fs, 0, oisf_##f, 0 } #define OICA(o) { "-" #o, oifn_##o, 1 } -static const OptionInfo resolver_optioninfos[]= { - OIFA1(if,noenv, 0), - OIFA1(if,debug, adns_if_noerrprint), - OIFA1(if,logpid, adns_if_noerrprint), - OIFA1(if,noerrprint, adns_if_debug), - OIFA2(if,checkc,entex), - OIFA2(if,checkc,freq), - OIFS(makedefault), - OICA(errprint), - OICA(errcallback), - OICA(config), - { 0 } -}; - -static const OptionInfo query_optioninfos[]= { - OIFA1(if,search,0), - OIFA1(if,usevc,0), - OIFA2(if,quoteok,query), - OIFA2(if,quoteok,anshost), - OIFA2(if,quotefail,cname), - OIFA2(if,cname,loose), - OIFA2(if,cname,forbid), - OICA(resolver), - OIFS(reverse), - { "-reverse-any", oifn_reverse_any, 1 }, - { 0 } -}; - static int parse_options(Tcl_Interp *ip, int objc, Tcl_Obj *const *objv, const OptionInfo opttable[], OptionParse *op) { const OptionInfo *oi; + const void *oi_v; Tcl_Obj *arg; - + int rc; + + objc--; objv++; for (;;) { if (!objc--) break; - - rc= pat_enum(ip,*objv++, &oi,opttable, sizeof(OptionInfo)); + rc= pat_enum(ip, *objv++, &oi_v, opttable, sizeof(OptionInfo), + "query or resolver option"); if (rc) return rc; + oi= oi_v; if (oi->takesarg) { if (!objc--) { @@ -237,79 +142,84 @@ static int parse_options(Tcl_Interp *ip, int objc, Tcl_Obj *const *objv, return TCL_OK; } -int do_adns_destroy_resolver(ClientData cd, Tcl_Interp *ip, void *res_v) { - adns_state *res= res_v; +/*---------- resolver management ----------*/ - if (res == adnstcl_default) { - adnstcl_default= 0; - default_auto= 0; - } - adns_finish(res); fixme what about outstanding qs - return TCL_OK; -} +IdDataTable adnstcl_resolvers= { "adns-res" }; -static void asynch_check(Resolver *res); +struct Resolver { + int ix; /* first! */ + Tcl_Interp *interp; + adns_state ads; + Tcl_TimerToken timertoken; + int maxfd; + fd_set handling[3]; +}; -static void asynch_timerhandler(void *res_v) { - Resolver *res= res_v; - res->timertoken= 0; - adns_processtimeouts(res->ads,0); - checkqueries_updatehandlers(res); -} +static int oifn_errfile(Tcl_Interp *ip, const OptionInfo *oi, + Tcl_Obj *arg, OptionParse *op) { + int rc; + const char *str; + + rc= pat_string(ip,arg,&str); if (rc) return rc; + if (!strcmp(str,"stderr")) op->errfile= stderr; + else if (!strcmp(str,"stdout")) op->errfile= stdout; + else return staticerr(ip,"-errfile argument must be stderr or stdout",0); -static void asynch_filehandler(void *res_v, int mask) { - Resolver *res= res_v; - ec= adns_processany(res->ads); - if (ec) adns_globalsystemfailure(res->ads); - checkqueries_updatehandlers(res); + op->aflags &= ~adns_if_noerrprint; + op->errcallback= 0; + return TCL_OK; } -static void asynch_sethandlers(Resolver *res, int shutdown) { - fd_set want[3]; - int maxfd; - struct timeval tvbuf, *timeout; - - for (i=0; i<3; i++) FD_ZERO(&want[i]); - maxfd= 0; - timeout= 0; - - if (!shutdown) - adns_beforeselect(res->ads,&maxfd,&want[0],&want[1],&want[2], - &timeout,&tv_buf,0); +static int oifn_errcallback(Tcl_Interp *ip, const OptionInfo *oi, + Tcl_Obj *arg, OptionParse *op) { + op->errcallback= arg; + op->aflags &= ~adns_if_noerrprint; + op->errfile= 0; + return TCL_OK; +} - for (fd= 0; fd < maxfd || fd < res->maxfd; fd++) - for (i=0; i<3; i++) - if (!!FD_ISSET(fd, &res->handling[i]) - != !!FD_ISSET(fd, &want[i])) { - int mask=0; - if (FD->ISSET(fd, &want[0])) mask |= TCL_READABLE; - if (FD->ISSET(fd, &want[1])) mask |= TCL_WRITABLE; - if (FD->ISSET(fd, &want[2])) mask |= TCL_EXCEPTION; - if (mask) Tcl_CreateFileHandler(fd,mask,filehandler,res); - else Tcl_DeleteFileHandler(fd); - } +static int oifn_config(Tcl_Interp *ip, const OptionInfo *oi, + Tcl_Obj *arg, OptionParse *op) { + return pat_string(ip,arg,&op->config_string); +} - Tcl_DeleteTimerHandler(res->timertoken); +static const OptionInfo resolver_optioninfos[]= { + OIFA1(if,noenv, 0), + OIFA1(if,debug, adns_if_noerrprint), + OIFA1(if,logpid, adns_if_noerrprint), + OIFA1(if,noerrprint, adns_if_debug), + OIFA2(if,checkc,entex), + OIFA2(if,checkc,freq), + OIFS(makedefault), + OICA(errfile), + OICA(errcallback), + OICA(config), + { 0 } +}; - if (timeout) { - int milliseconds; +static void adnslogfn_callback(adns_state ads, void *logfndata, + const char *fmt, va_list al) { + abort(); /* fixme implement adns_logcallbackfn */ +} - if (timeout->tv_sec >= INT_MAX/1000 - 1) - milliseconds= INT_MAX; - else - milliseconds= timeout->tv_sec * 1000 + - (timeout->tv_usec + 999) / 1000; - - res->timertoken= Tcl_CreateTimerHandler(milliseconds,timerhandler,res); - } +int do_adns_destroy_resolver(ClientData cd, Tcl_Interp *ip, void *res_v) { + Resolver *res= res_v; + tabledataid_disposing(res,&adnstcl_resolvers); + if (res->ads) adns_finish(res->ads); + asynch_sethandlers(res,1); + TFREE(res); + /* fixme what about outstanding queries */ + /* fixme what about the default resolver */ + /* fixme what if the tcl interpreter gets deleted */ + return TCL_OK; } int do_adns_new_resolver(ClientData cd, Tcl_Interp *ip, int objc, Tcl_Obj *const *objv, void **result) { OptionParse op; - adns_state *ads=0; Resolver *res=0; + int rc, i, ec; op.aflags= adns_if_noautosys; op.sflags= 0; @@ -320,42 +230,105 @@ int do_adns_new_resolver(ClientData cd, Tcl_Interp *ip, if (rc) goto x_rc; res= TALLOC(sizeof(*res)); assert(res); - res->maxfd= 0; - for (i=0; i<3; i++) FD_ZERO(&res->handling); + res->ix= -1; res->interp= ip; + res->ads= 0; + res->timertoken= 0; + res->maxfd= 0; + for (i=0; i<3; i++) FD_ZERO(&res->handling[i]); if (op.aflags & adns_if_noerrprint) { op.errfile= 0; op.errcallback= 0; } - ec= adns_init_logfn(&ads, op.aflags, op.configstring, + ec= adns_init_logfn(&res->ads, op.aflags, op.config_string, op.errcallback ? adnslogfn_callback : 0, - op.errcallback ? op.errcallback : op.errfile); + op.errcallback ? (void*)op.errcallback + : (void*)op.errfile); if (ec) { rc= posixerr(ip,ec,"create adns resolver"); goto x_rc; } - res->ads= ads; if (op.errcallback) Tcl_IncrRefCount(op.errcallback); - rc= update_handlers(&res); if (rc) goto x_rc; - *result= res; return TCL_OK; + + x_rc: + if (res) { + if (res->ads) adns_finish(res->ads); + TFREE(res); + } + return rc; +} + +/*---------- query, query option and answers - common stuff ----------*/ + +#define RRTYPE_EXACTLY(t) { #t, adns_r_##t } +#define RRTYPE_RAW(t) { #t, adns_r_##t##_raw } +#define RRTYPE_PLUS(t) { #t "+", adns_r_##t } +#define RRTYPE_MINUS(t) { #t "-", adns_r_##t##_raw } + +const AdnsTclRRTypeInfo adnstclrrtypeinfos[]= { + RRTYPE_EXACTLY(a), + RRTYPE_EXACTLY(cname), + RRTYPE_EXACTLY(hinfo), + RRTYPE_EXACTLY(addr), + + RRTYPE_RAW(ns), + RRTYPE_RAW(mx), + + RRTYPE_EXACTLY(soa), + RRTYPE_EXACTLY(ptr), + RRTYPE_EXACTLY(rp), + + RRTYPE_MINUS(soa), + RRTYPE_MINUS(ptr), + RRTYPE_MINUS(rp), + { 0 } +}; + +static int oifn_resolver(Tcl_Interp *ip, const OptionInfo *oi, + Tcl_Obj *arg, OptionParse *op) { + void *val_v; + int rc; + + rc= pat_iddata(ip,arg,&val_v,&adnstcl_resolvers); + if (rc) return rc; + op->resolver= val_v; + return TCL_OK; } -static int query_submit(Tcl_Interp *ip, int objc, Tcl_Obj *const *objv, - const char *domain) { +static const OptionInfo query_optioninfos[]= { + OIFA1(qf,search,0), + OIFA1(qf,usevc,0), + OIFA2(qf,quoteok,query), + OIFA2(qf,quoteok,anshost), + OIFA2(qf,quotefail,cname), + OIFA2(qf,cname,loose), + OIFA2(qf,cname,forbid), + OICA(resolver), + OIFS(reverse), + { "-reverse-any", oifn_reverse_any, 1 }, + { 0 } +}; + +static int query_submit(Tcl_Interp *ip, + const AdnsTclRRTypeInfo *type, const char *domain, + int queryopts_objc, Tcl_Obj *const *queryopts_objv, + adns_query *aqu_r, OptionParse *op) { struct sockaddr sa; static const int aftry[]= { AF_INET, AF_INET6 }; + int rc, r, ec; + adns_state ads; - op.aflags= adns_qf_owner; - op.sflags= 0; - op.resolver= 0; - rc= parse_options(ip,objc,objv,query_optioninfos,&op); + op->aflags= adns_qf_owner; + op->sflags= 0; + op->resolver= 0; + rc= parse_options(ip, queryopts_objc,queryopts_objv, query_optioninfos,op); if (rc) return rc; - if (op.reverseany || (op.sflags & oisf_reverse)) { + if (op->reverseany || (op->sflags & oisf_reverse)) { const int *af; for (af=aftry; af < af + sizeof(af)/sizeof(*af); af++) { memset(&sa,0,sizeof(sa)); @@ -363,25 +336,21 @@ static int query_submit(Tcl_Interp *ip, int objc, Tcl_Obj *const *objv, r= inet_pton(*af,domain,&sa); if (!r) goto af_found; } - return staticerr(ip,ec,"invalid address for adns reverse submit",""); + return staticerr(ip,"invalid address for adns reverse submit",""); + af_found:; } - if (!op.resolver) { - if (!adnstcl_default) { - ec= adns_init(&adnstcl_default,adns_if_noautosys,0); - if (ec) return posixerr(ip,ec,"create default adns resolver"); - } - default_auto= 1; - op.resolver= adnstcl_default; - } + ads= op->resolver->ads; - if (op.reverseany) { - ec= adns_submit_reverse_any(op.resolver, &sa, op.reverseany, rrtype, - op.aflags, 0, &query); - } else if (op.sflags & oisf_reverse) { - ec= adns_submit_reverse(op.resolver, &sa, rrtype, op.aflags, 0, &query); + if (op->reverseany) { + ec= adns_submit_reverse_any(ads, &sa, op->reverseany, + type->number, op->aflags, 0, aqu_r); + } else if (op->sflags & oisf_reverse) { + ec= adns_submit_reverse(ads, &sa, + type->number, op->aflags, 0, aqu_r); } else { - ec= adns_submit(op.resolver, domain, rrtype, op.aflags, 0, &query); + ec= adns_submit(ads, domain, + type->number, op->aflags, 0, aqu_r); } if (ec) return posixerr(ip,ec,"submit adns query"); @@ -389,46 +358,176 @@ static int query_submit(Tcl_Interp *ip, int objc, Tcl_Obj *const *objv, return TCL_OK; } -int do_adns_lookup(ClientData cd, Tcl_Interp *ip, - const AdnsTclRRTypeInfo *rrtype, - const char *domain, - int objc, Tcl_Obj *const *objv, - Tcl_Obj **result) { - OptionParse op; - - rc= query_submit(ip,domain,objc,objv,&op, ); if (rc) return rc; +#define RESULTSTATUS_LLEN 4 +#define RESULTLIST_LLEN 7 - ec= adns_wait(op.resolver,&query,&answer,0); - if (ec) return posixerr(ip,ec,"wait for adns lookup"); - - ...; +static void make_resultstatus(Tcl_Interp *ip, adns_status status, + Tcl_Obj *results[RESULTSTATUS_LLEN]) { + results[0]= ret_string(ip, adns_errtypeabbrev(status)); + results[1]= ret_int(ip, status); + results[2]= ret_string(ip, adns_errabbrev(status)); + results[3]= ret_string(ip, adns_strerror(status)); } -#define RESULTS_LLEN 7 -static void make_results(Tcl_Interp *ip, adns_answer *answer, - Tcl_Obj results[RESULTS_LLEN]) { - Tcl_Obj *rdata; +static Tcl_Obj *make_resultrdata(Tcl_Interp *ip, adns_answer *answer) { + Tcl_Obj **rdata; + int i, rrsz; + adns_status st; + char *datap, *rdatastring; - results[0]= ret_string(ip, adns_errtypeabbrev(answer->status)); - results[1]= ret_int(ip, answer->status); - results[2]= ret_string(ip, adns_errabbrev(answer->status)); - results[3]= ret_string(ip, adns_strstatus(answer->status)); - results[4]= ret_string(ip, answer->owner); - results[5]= ret_string(ip, answer->cname ? answer->cname : ""); - rdata= TALLOC(sizeof(*rdata) * answer->nrrs); for (i=0, datap=answer->rrs.untyped; - inrrs; i++, datap += rrsz) { + inrrs; + i++, datap += rrsz) { st= adns_rr_info(answer->type, 0,0, &rrsz, datap, &rdatastring); assert(!st); rdata[i]= ret_string(ip, rdatastring); free(rdatastring); } - results[6]= Tcl_NewListObj(RESULTS_LLEN,rdata); TFREE(rdata); + return Tcl_NewListObj(answer->nrrs, rdata); +} + +static void make_resultlist(Tcl_Interp *ip, adns_answer *answer, + Tcl_Obj *results[RESULTLIST_LLEN]) { + + make_resultstatus(ip, answer->status, results); + assert(RESULTSTATUS_LLEN==4); + results[4]= ret_string(ip, answer->owner); + results[5]= ret_string(ip, answer->cname ? answer->cname : ""); + results[6]= make_resultrdata(ip, answer); +} + +/*---------- synchronous query handling ----------*/ + +static int synch(Tcl_Interp *ip, const AdnsTclRRTypeInfo *rrtype, + const char *domain, + int objc, Tcl_Obj *const *objv, adns_answer **answer_r) { + adns_query aqu; + OptionParse op; + Resolver *res; + int rc, ec; + + rc= query_submit(ip,rrtype,domain,objc,objv,&aqu,&op); + if (rc) return rc; + + res= op.resolver; + ec= adns_wait(res->ads,&aqu,answer_r,0); + assert(!ec); + + asynch_check(res); + return TCL_OK; +} + +int do_adns_lookup(ClientData cd, Tcl_Interp *ip, + const AdnsTclRRTypeInfo *rrtype, + const char *domain, + int objc, Tcl_Obj *const *objv, + Tcl_Obj **result) { + int rc; + adns_answer *answer; + + rc= synch(ip,rrtype,domain,objc,objv,&answer); if (rc) return rc; + + if (answer->status) { + Tcl_Obj *problem[RESULTSTATUS_LLEN]; + make_resultstatus(ip, answer->status, problem); + *result= Tcl_NewListObj(RESULTSTATUS_LLEN, problem); + } else { + *result= make_resultrdata(ip, answer); + } + free(answer); + return TCL_OK; +} + +int do_adns_synch(ClientData cd, Tcl_Interp *ip, + const AdnsTclRRTypeInfo *rrtype, + const char *domain, + int objc, Tcl_Obj *const *objv, + Tcl_Obj **result) { + int rc; + adns_answer *answer; + Tcl_Obj *results[RESULTLIST_LLEN]; + + rc= synch(ip,rrtype,domain,objc,objv,&answer); if (rc) return rc; + make_resultlist(ip,answer,results); + free(answer); + *result= Tcl_NewListObj(RESULTLIST_LLEN, results); + return TCL_OK; } + +/*---------- asynchronous query handling ----------*/ + +typedef struct { + int ix; /* first! */ + Resolver *res; + adns_query aqu; + ScriptToInvoke on_yes, on_no, on_fail; + Tcl_Obj *xargs; +} Query; + +IdDataTable adnstcl_queries= { "adns" }; + +static void asynch_timerhandler(void *res_v) { + Resolver *res= res_v; + res->timertoken= 0; + adns_processtimeouts(res->ads,0); + asynch_check(res); +} + +static void asynch_filehandler(void *res_v, int mask) { + Resolver *res= res_v; + int ec; + ec= adns_processany(res->ads); + if (ec) adns_globalsystemfailure(res->ads); + asynch_check(res); +} + +static void asynch_sethandlers(Resolver *res, int shutdown) { + fd_set want[3]; + int maxfd; + struct timeval tv_buf, *timeout; + int i, fd; + + timeout= 0; + maxfd= 0; + for (i=0; i<3; i++) FD_ZERO(&want[i]); + + if (!shutdown) + adns_beforeselect(res->ads,&maxfd,&want[0],&want[1],&want[2], + &timeout,&tv_buf,0); + + for (fd= 0; fd < maxfd || fd < res->maxfd; fd++) + for (i=0; i<3; i++) + if (!!FD_ISSET(fd, &res->handling[i]) + != !!FD_ISSET(fd, &want[i])) { + int mask=0; + if (FD_ISSET(fd, &want[0])) mask |= TCL_READABLE; + if (FD_ISSET(fd, &want[1])) mask |= TCL_WRITABLE; + if (FD_ISSET(fd, &want[2])) mask |= TCL_EXCEPTION; + if (mask) Tcl_CreateFileHandler(fd,mask,asynch_filehandler,res); + else Tcl_DeleteFileHandler(fd); + } + + Tcl_DeleteTimerHandler(res->timertoken); + + if (timeout) { + int milliseconds; + + if (timeout->tv_sec >= INT_MAX/1000 - 1) + milliseconds= INT_MAX; + else + milliseconds= timeout->tv_sec * 1000 + + (timeout->tv_usec + 999) / 1000; + + res->timertoken= + Tcl_CreateTimerHandler(milliseconds,asynch_timerhandler,res); + } +} + static void asynch_query_dispose(Query *query) { + tabledataid_disposing(query, &adnstcl_queries); scriptinv_cancel(&query->on_yes); scriptinv_cancel(&query->on_no); scriptinv_cancel(&query->on_fail); @@ -439,26 +538,30 @@ static void asynch_query_dispose(Query *query) { static void asynch_check(Resolver *res) { Tcl_Interp *interp= res->interp; - adns_query *aqu; + adns_query aqu; adns_answer *answer; - Query *qu; + void *query_v; + Query *query; ScriptToInvoke *si; - Tcl_Obj results[RESULTS_LLEN]; + int ec; + Tcl_Obj *results[RESULTLIST_LLEN]; for (;;) { - ec= adns_check(res->ads, &aqu, &answer, &qu); + ec= adns_check(res->ads, &aqu, &answer, &query_v); if (ec==ESRCH || ec==EAGAIN) break; assert(!ec); + query= query_v; - qu->aqu= 0; + query->aqu= 0; + tabledataid_disposing(query, &adnstcl_queries); si= (!answer->status ? si= &query->on_yes : answer->status > adns_s_max_tempfail ? &query->on_no : &query->on_fail); - adnstcl_queries[qu->ix].a= 0; - make_results(ip, answer, results); - scriptinv_invoke(si, RESULTS_LLEN, results); + make_resultlist(interp, answer, results); + free(answer); + scriptinv_invoke(si, RESULTLIST_LLEN, results); asynch_query_dispose(query); } @@ -466,22 +569,27 @@ static void asynch_check(Resolver *res) { } int do_adns_asynch(ClientData cd, Tcl_Interp *ip, - const AdnsTclRRTypeInfo *rrtype, const char *domain, Tcl_Obj *on_yes, Tcl_Obj *on_no, Tcl_Obj *on_fail, Tcl_Obj *xargs, + const AdnsTclRRTypeInfo *rrtype, const char *domain, int objc, Tcl_Obj *const *objv, void **result) { Query *query; - adns_query *aqu; + int rc; + Resolver *res=0; + OptionParse op; query= TALLOC(sizeof(*query)); + query->ix= -1; query->aqu= 0; scriptinv_init(&query->on_yes); scriptinv_init(&query->on_no); scriptinv_init(&query->on_fail); query->xargs= 0; - rc= query_submit(ip,rrtype,domain, ...); if (rc) goto x_rc; - query->aqu= aqu; + rc= query_submit(ip,rrtype,domain,objc,objv,&query->aqu,&op); + if (rc) goto x_rc; + + res= op.resolver; rc= scriptinv_set(&query->on_yes, ip,on_yes); if (rc) goto x_rc; rc= scriptinv_set(&query->on_no, ip,on_no); if (rc) goto x_rc; @@ -493,13 +601,16 @@ int do_adns_asynch(ClientData cd, Tcl_Interp *ip, return TCL_OK; x_rc: - asynch_cancel(query); + if (query) asynch_query_dispose(query); + if (res) asynch_sethandlers(res,0); return rc; } int do_adns_asynch_cancel(ClientData cd, Tcl_Interp *ip, void *query_v) { - adns_query *qu; + Query *query= query_v; + Resolver *res= query->res; + asynch_query_dispose(query); + asynch_sethandlers(res,0); + return TCL_OK; } - -int do_adns_synch(ClientData cd, Tcl_Interp *ip, const AdnsTclRRTypeInfo *rrtype, const char *domain, int objc, Tcl_Obj *const *objv, adns_answer **result); diff --git a/base/hook.c b/base/hook.c index 2d59baa..b65741f 100644 --- a/base/hook.c +++ b/base/hook.c @@ -386,6 +386,12 @@ int do_toplevel_ulong(ClientData cd, Tcl_Interp *ip, return subcmd->func(0,ip,objc,objv); } +int do_toplevel_adns(ClientData cd, Tcl_Interp *ip, + const Adns_SubCommand *subcmd, + int objc, Tcl_Obj *const *objv) { + return subcmd->func(0,ip,objc,objv); +} + #define URANDOM "/dev/urandom" int get_urandom(Tcl_Interp *ip, Byte *buffer, int l) { diff --git a/base/tables-examples.tct b/base/tables-examples.tct index 9165827..696583a 100644 --- a/base/tables-examples.tct +++ b/base/tables-examples.tct @@ -19,6 +19,10 @@ Type ulong: uint32_t @ Type long: long @ Type string: const char *@ +Type adnsresults: adns_answer *@ +Init adnsresults @=0; +Fini adnsresults free(@); + Type charfrom(const char *opts, const char *what): int H-Include "hbytes.h" @@ -36,6 +40,37 @@ Table toplevel TopLevel_Command ulong subcmd enum(ULong_SubCommand,"ulong subcommand") ... obj + adns + subcmd enum(Adns_SubCommand,"adns subcommand") + ... obj + +Table adns Adns_SubCommand + lookup + rrtype enum(AdnsTclRRTypeInfo, "rrtype") + domain string + ... obj + => obj + synch + rrtype enum(AdnsTclRRTypeInfo, "rrtype") + domain string + ... obj + => obj + asynch + on_yes obj + on_no obj + on_fail obj + xargs obj + rrtype enum(AdnsTclRRTypeInfo, "rrtype") + domain string + ... obj + => iddata(&adnstcl_queries) + asynch-cancel + query iddata(&adnstcl_queries) + new-resolver + ... obj + => iddata(&adnstcl_resolvers) + destroy-resolver + res iddata(&adnstcl_resolvers) Table maskmap MaskMap_SubCommand lookup diff --git a/base/troglodyte-Makefile b/base/troglodyte-Makefile index 9eff482..ea2c10c 100644 --- a/base/troglodyte-Makefile +++ b/base/troglodyte-Makefile @@ -30,7 +30,7 @@ TARGETS= hbytes.so autocode.tcl autococo.tcl CC_CRYPTO= $(CC) $(CFLAGS) $(CPPFLAGS) -O3 CPPFLAGS= -I../plocal/include $(TCL_MEM_DEBUG) $(CMDLINE_CPPFLAGS) LDFLAGS= -L../plocal/lib -LDLIBS= -lnettle +LDLIBS= -lnettle -ladns CFLAGS= -g -Wall -Wmissing-prototypes -Wstrict-prototypes -Werror \ $(OPTIMISE) OPTIMISE= -O2 diff --git a/hbytes/hook.c b/hbytes/hook.c index 2d59baa..b65741f 100644 --- a/hbytes/hook.c +++ b/hbytes/hook.c @@ -386,6 +386,12 @@ int do_toplevel_ulong(ClientData cd, Tcl_Interp *ip, return subcmd->func(0,ip,objc,objv); } +int do_toplevel_adns(ClientData cd, Tcl_Interp *ip, + const Adns_SubCommand *subcmd, + int objc, Tcl_Obj *const *objv) { + return subcmd->func(0,ip,objc,objv); +} + #define URANDOM "/dev/urandom" int get_urandom(Tcl_Interp *ip, Byte *buffer, int l) {