Changeset eafba4c159b528b48fd4bb166e310408712691bb

Show
Ignore:
Timestamp:
06/20/14 02:59:59 (4 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1403233199 -0400
git-parent:

[dfb4d35b71291f626f02b4f9e3a4d1c72b091bea]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1403233199 -0400
Message:

Upgrade libudns 0.4

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/Makefile.objs.in

    rb6cd323 reafba4c  
    33        udns/udns_XtoX.o udns/udns_rr_a.o udns/udns_rr_ptr.o udns/udns_rr_mx.o \ 
    44        udns/udns_rr_txt.o udns/udns_bl.o udns/udns_rr_srv.o \ 
    5         udns/udns_rr_naptr.o udns/udns_codes.o 
     5        udns/udns_rr_naptr.o udns/udns_codes.o udns/udns_jran.o 
    66JSON_LIB_OBJS=json-lib/arraylist.o json-lib/debug.o json-lib/json_object.o \ 
    77        json-lib/json_tokener.o json-lib/json_util.o json-lib/linkhash.o \ 
  • src/udns/COPYING.LGPL

    r5a9b91b reafba4c  
    1                  GNU LESSER GENERAL PUBLIC LICENSE 
    2                       Version 2.1, February 1999 
     1                  GNU LESSER GENERAL PUBLIC LICENSE 
     2                       Version 2.1, February 1999 
    33 
    44 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 
    5      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
     5 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA 
    66 Everyone is permitted to copy and distribute verbatim copies 
    77 of this license document, but changing it is not allowed. 
     
    1111 the version number 2.1.] 
    1212 
    13                            Preamble 
     13                            Preamble 
    1414 
    1515  The licenses for most software are designed to take away your 
     
    113113be combined with the library in order to run. 
    114114  
    115                  GNU LESSER GENERAL PUBLIC LICENSE 
     115                  GNU LESSER GENERAL PUBLIC LICENSE 
    116116   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 
    117117 
     
    147147writing it).  Whether that is true depends on what the Library does 
    148148and what the program that uses the Library does. 
    149    
     149 
    150150  1. You may copy and distribute verbatim copies of the Library's 
    151151complete source code as you receive it, in any medium, provided that 
     
    433433and reuse of software generally. 
    434434 
    435                            NO WARRANTY 
     435                            NO WARRANTY 
    436436 
    437437  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 
     
    456456DAMAGES. 
    457457 
    458                     END OF TERMS AND CONDITIONS 
     458                     END OF TERMS AND CONDITIONS 
    459459  
    460460           How to Apply These Terms to Your New Libraries 
     
    486486    You should have received a copy of the GNU Lesser General Public 
    487487    License along with this library; if not, write to the Free Software 
    488     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
     488    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA 
    489489 
    490490Also add information on how to contact you by electronic and paper mail. 
     
    501501 
    502502That's all there is to it! 
    503  
    504  
  • src/udns/Makefile.in

    r4c7aa25 reafba4c  
    2424        udns_misc.c udns_XtoX.c \ 
    2525        udns_rr_a.c udns_rr_ptr.c udns_rr_mx.c udns_rr_txt.c udns_bl.c \ 
    26         udns_rr_srv.c udns_rr_naptr.c udns_codes.c 
     26        udns_rr_srv.c udns_rr_naptr.c udns_codes.c udns_jran.c 
    2727USRCS  = dnsget.c rblcheck.c ex-rdns.c 
    2828DEB    = debian/copyright debian/changelog debian/control debian/rules 
     
    171171udns_dn.o udns_dn.lo: udns_dn.c udns.h 
    172172udns_dntosp.o udns_dntosp.lo: udns_dntosp.c udns.h 
     173udns_jran.o udns_jran.lo: udns_jran.c udns.h 
    173174udns_parse.o udns_parse.lo: udns_parse.c udns.h 
    174175udns_resolver.o udns_resolver.lo: udns_resolver.c udns_config.h udns.h 
  • src/udns/NEWS

    r5a9b91b reafba4c  
    1 $Id: NEWS,v 1.11 2007/01/15 21:19:08 mjt Exp $ 
     1NEWS 
     2User-visible changes in udns library.  Recent changes on top. 
    23 
    3 User-visible changes in udns library.  Recent changes on top. 
     40.4 (Jan 2014) 
     5 
     6 - bugfix: fix a bug in new list code introduced in 0.3 
     7 - portability: use $(LD)/$(LDFLAGS)/$(LIBS) 
     8 
     90.3 (Jan 2014) 
     10 
     11 - bugfix: refactor double-linked list implementation in udns_resolver.c 
     12   (internal to the library) to be more strict-aliasing-friendly, because 
     13   old code were miscompiled by gcc. 
     14 
     15 - bugfix: forgotten strdup() in rblcheck 
     16 
     170.2 (Dec 2011) 
     18 
     19 - bugfix: SRV RR handling: fix domain name parsing and crash in case 
     20   if no port is specified on input for SRV record query 
     21 
     22 - (trivial api) dns_set_opts() now returns number of unrecognized  
     23   options instead of always returning 0 
     24 
     25 - dnsget: combine -f and -o options in dnsget (and stop documenting -f), 
     26   and report unknown/invalid -o options (and error out) 
     27 
     28 - dnsget: pretty-print SSHFP RRs 
     29 
     30 0.1 (Dec 2010) 
     31 
     32 - bugfix: udns_new(old) - when actually cloning another context - 
     33   makes the new context referencing memory from old, which leads 
     34   to crashes when old is modified later 
     35 
     36 - use random queue IDs (the 16bit qID) in queries instead of sequentional 
     37   ones, based on simple pseudo-random RNG by Bob Jenkins (udns_jran.[ch]). 
     38   Some people believe that this improves security (CVE-2008-1447).  I'm 
     39   still not convinced (see comments in udns_resolver.c), but it isn't 
     40   difficult to add after all. 
     41 
     42 - deprecate dns_random16() function which was declared in udns.h 
     43   (not anymore) but never documented.  In order to keep ABI compatible 
     44   it is still exported. 
     45 
     46 - library has a way now to set query flags (DNS_SET_DO; DNS_SET_CD). 
     47 
     48 - dnsget now prints non-printable chars in all strings in DNS RRs using 
     49   decimal escape sequences (\%03u) instead of hexadecimal (\%02x) when 
     50   before - other DNS software does it like this. 
     51 
     52 - recognize a few more record types in dnsget, notable some DNSSEC RRs; 
     53   add -f option for dnsget to set query flags. 
     54 
     55 - udns is not a Debian native package anymore (was a wrong idea) 
    456 
    5570.0.9 (16 Jan 2007) 
     
    759 - incompat: minor API changes in dns_init() &friends.  dns_init() 
    860   now requires extra `struct dns_ctx *' argument.  Not bumped 
    9    soversion yet - I only expect one "release" with this change, 
    10    0.1 will have more changes and will increment so version 
     61   soversion yet - I only expect one "release" with this change. 
    1162 
    1263 - many small bugfixes, here and there 
  • src/udns/NOTES

    r5a9b91b reafba4c  
    7676network, where a bad guy can generate alot of packets in a short time. 
    7777 
    78 Choosing of DNS QueryID 
    79 ~~~~~~~~~~~~~~~~~~~~~~~ 
    80  
    81 Currently, udns uses sequential number for query IDs.  Which simplifies 
    82 attacks even more (c.f. the previous item about single UDP port), making 
    83 them nearly trivial.  The library should use random number for query ID. 
    84 But there's no portable way to get random numbers, even on various flavors 
    85 of Unix.  It's possible to use low bits from tv_nsec field returned by 
    86 gettimeofday() (current time, nanoseconds), but I wrote the library in 
    87 a way to avoid making system calls where possible, because many syscalls 
    88 means many context switches and slow processes as a result.  Maybe use some 
    89 application-supplied callback to get random values will be a better way, 
    90 defaulting to gettimeofday() method. 
    91  
    92 Note that a single query - even if (re)sent to different nameservers, several 
    93 times (due to no reply received in time), uses the same qID assigned when it 
    94 was first dispatched.  So we have: single UDP socket (fixed port number), 
    95 sequential (= trivially predictable) qIDs, and long lifetime of those qIDs. 
    96 This all makes (local) attacks against the library really trivial. 
    97  
    98 See also comments in udns_resolver.c, udns_newid(). 
    99  
    100 And note that at least some other stub resolvers out there (like c-ares 
    101 for example) also uses sequential qID. 
     78Spoofing of replies (Kaminsky attack, CVE-2008-1447) 
     79~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     80 
     81While udns uses random numbers for query IDs, it uses single UDP port for 
     82all queries (see previous item).  And even if it used random UDP port for 
     83each query, the attack described in CVE-2008-1447 is still quite trivial. 
     84This is not specific to udns library unfortunately - it is inherent property 
     85of the protocol.  Udns is designed to work in a LAN, it needs full recursive 
     86resolver nearby, and modern LAN usually uses high-bandwidth equipment which 
     87makes the Kaminsky attack trivial.  The problem is that even with qID (16 
     88bits) and random UDP port (about 20 bits available to a regular process) 
     89combined still can not hold enough randomness, so on a fast network it is 
     90still easy to flood the target with fake replies and hit the "right" reply 
     91before real reply comes.  So random qIDs don't add much protection anyway, 
     92even if this feature is implemented in udns, and using all available 
     93techniques wont solve it either. 
     94 
     95See also long comment in udns_resolver.c, udns_newid(). 
    10296 
    10397Assumptions about RRs returned 
     
    154148~~~~~~~~~~~~~~~~~~~ 
    155149 
    156 At least one thing I want to change for 0.1 version is a way how queries are 
    157 submitted and how replies are handled. 
     150At least one thing I want to change for some future version is a way how 
     151queries are submitted and how replies are handled. 
    158152 
    159153I want to made dns_query object to be owned by an application.  So that instead 
     
    195189default NULL.  But with such "nesting" of query initializers, it becomes 
    196190trivial. 
     191 
     192This change (the way how queries gets submitted) will NOT break API/ABI 
     193compatibility with old versions, since the new submitting API works in 
     194parallel with current (and current will use the new one as building 
     195blocks, instead of doing all work at once). 
    197196 
    198197Another way to do the same is to manipulate query object right after a 
     
    213212call a parsing routine again. 
    214213 
     214This, in theory, also can be done without breaking current API/ABI, but in 
     215that case we'll again need a parallel set of routines (parsing included), 
     216which makes the library more complicated with too many ways of doing the 
     217same thing.  Still, code reuse is at good level. 
     218 
    215219Another modification I plan to include is to have an ability to work in 
    216220terms of domain names (DNs) as used with on-wire DNS packets, not only 
  • src/udns/TODO

    r5a9b91b reafba4c  
    1 $Id: TODO,v 1.13 2007/01/15 21:19:08 mjt Exp $ 
     1TODO 
    22 
    33The following is mostly an internal, not user-visible stuff. 
     
    66  so that it'll look like this: 
    77   struct dns_query *q; 
    8    q = udns_query_alloc(ctx); 
    9    udns_query_set(q, options, domain_name, flags, ...); 
    10    udns_query_submit(ctx, q); 
    11  or 
    12    udns_query_resolve(ctx, q); 
     8   q = dns_query_alloc(ctx); 
     9   dns_query_set(q, options, domain_name, flags, ...); 
     10   dns_query_submit(ctx, q); 
     11  For more information see NOTES file, section "Planned API changes". 
    1312 
    1413* allow NULL callbacks?  Or provide separate resolver 
     
    4140* allow TCP queue? 
    4241 
    43 * And oh, qID should really be random.  Or... not. 
    44   See notes in udns_resolver.c, dns_newid(). 
    45  
    4642* more accurate error reporting.  Currently, udns always returns TEMPFAIL, 
    4743  but don't specify why it happened (ENOMEM, timeout, etc). 
     
    6258 
    6359* sortlist support? 
    64  
    65 * windows port?  Oh no please!..  At least, I can't do it myself 
    66   because of the lack of platform. 
    67   Ok ok, the Windows port is in progress.  Christian Prahauser 
    68   from cosy.sbg.ac.at is helping with that. 
    69   Other folks done some more work in this area. 
  • src/udns/dnsget.1

    r5a9b91b reafba4c  
    1 .\" $Id: dnsget.1,v 1.3 2005/04/20 00:55:34 mjt Exp $ 
    2 .\" dnsget manpage 
     1.\" dnsget.1: dnsget manpage 
    32.\" 
    4 .\" Copyright (C) 2005  Michael Tokarev <mjt@corpit.ru> 
     3.\" Copyright (C) 2005-2014  Michael Tokarev <mjt+udns@tls.msk.ru> 
    54.\" This file is part of UDNS library, an async DNS stub resolver. 
    65.\" 
     
    2019.\" Suite 330, Boston, MA  02111-1307  USA 
    2120 
    22 .TH dnsget 1 "Apr 2005" "User Utilities" 
     21.TH dnsget 1 "Jan 2014" "User Utilities" 
    2322 
    2423.SH NAME 
     
    3332.IR type \|] 
    3433.RB [\| \-o 
    35 .IR option : value \
     34.IR opt , opt ,...
    3635.IR name \|.\|.\|. 
    3736 
     
    128127 
    129128.TP 
    130 \fB\-o \fIoption\fR:\fIvalue\fR 
    131 Set resolver option \fIoption\fR to the value \fIvalue\fR 
    132 (may be specified several times).  The same as setting 
     129\fB\-o \fIopt\fR,\fIopt\fR,... 
     130(may be specified several times). 
     131Set resolver options (in a form \fIoption\fR:\fIvalue\fR) as if they 
     132were set in 
    133133.RB $ RES_OPTIONS 
    134 environment variable.  The following options are recognized
     134environment variable, or set query flags
    135135.RS 
    136136.TP 
     
    148148\fBport\fR:\fInum\fR 
    149149Use given UDP port number \fInum\fR instead of the default port 53 (domain). 
     150.TP 
     151\fBaa\fR 
     152set AA (auth only) query bit. 
     153.TP 
     154\fBnord\fR 
     155do not set RD (recursion desired) query bit (set by default). 
     156.TP 
     157\fBdnssec\fR or \fBdo\fR 
     158set DNSSEC OK (DO) query flag (\fBdnsget\fR does not verify DNSSEC signatures, 
     159only displays them; this is set in EDNS RR). 
     160.TP 
     161\fBcd\fR 
     162set CD (checking disabled) query bit. 
    150163.RE 
    151164 
  • src/udns/dnsget.c

    r5a9b91b reafba4c  
    1 /* $Id: dnsget.c,v 1.31 2007/01/08 01:14:44 mjt Exp $ 
     1/* dnsget.c 
    22   simple host/dig-like application using UDNS library 
    33 
     
    122122  const unsigned char *e = c + n; 
    123123  if (verbose > 0) while(c < e) { 
    124     if (*c < ' ' || *c >= 127) printf("\\%02x", *c); 
     124    if (*c < ' ' || *c >= 127) printf("\\%03u", *c); 
    125125    else if (*c == '\\' || *c == '"') printf("\\%c", *c); 
    126126    else putchar(*c); 
     
    188188    if (verbose > 1) { 
    189189      if (!p->dnsp_rrl && !rr->dnsrr_dn[0] && rr->dnsrr_typ == DNS_T_OPT) { 
    190         printf(";EDNS0 OPT record (UDPsize: %d): %d bytes\n", 
    191                rr->dnsrr_cls, rr->dnsrr_dsz); 
     190        printf(";EDNS%d OPT record (UDPsize: %d, ERcode: %d, Flags: 0x%02x): %d bytes\n", 
     191               (rr->dnsrr_ttl>>16) & 0xff,      /* version */ 
     192               rr->dnsrr_cls,                   /* udp size */ 
     193               (rr->dnsrr_ttl>>24) & 0xff,      /* extended rcode */ 
     194               rr->dnsrr_ttl & 0xffff,          /* flags */ 
     195               rr->dnsrr_dsz); 
    192196        return; 
    193197      } 
     
    302306    break; 
    303307 
    304   case DNS_T_KEY: /* flags(2) proto(1) algo(1) pubkey */ 
     308  case DNS_T_KEY: 
     309  case DNS_T_DNSKEY: 
     310    /* flags(2) proto(1) algo(1) pubkey */ 
     311  case DNS_T_DS: 
     312  case DNS_T_DLV: 
     313    /* ktag(2) proto(1) algo(1) pubkey */ 
    305314    c = dptr; 
    306315    if (c + 2 + 1 + 1 > dend) goto xperr; 
     
    314323 
    315324  case DNS_T_SIG: 
     325  case DNS_T_RRSIG: 
    316326    /* type(2) algo(1) labels(1) ottl(4) sexp(4) sinc(4) tag(2) sdn sig */ 
    317327    c = dptr; 
    318328    c += 2 + 1 + 1 + 4 + 4 + 4 + 2; 
    319329    if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0) goto xperr; 
    320     printf("%d %u %u %u ", 
    321            dns_get16(dptr), dptr[2], dptr[3], dns_get32(dptr+4)); 
     330    printf("%s %u %u %u ", 
     331           dns_typename(dns_get16(dptr)), dptr[2], dptr[3], dns_get32(dptr+4)); 
    322332    printdate(dns_get32(dptr+8)); 
    323333    putchar(' '); 
     
    327337    break; 
    328338 
     339  case DNS_T_SSHFP: /* algo(1), fp type(1), fp... */ 
     340    if (dend < dptr + 3) goto xperr; 
     341    printf("%u %u ", dptr[0], dptr[1]); /* algo, fp type */ 
     342    printhex(dptr + 2, dend); 
     343    break; 
     344 
    329345#if 0   /* unused RR types? */ 
    330   case DNS_T_DS: 
    331     c = dptr; 
    332     if (c + 2 + 2 >= dend) goto xperr; 
    333     printf("%u %u %u ", dns_get16(c), c[2], c[3]); 
    334     printhex(c + 4, dend); 
    335     break; 
    336  
    337   case DNS_T_NSEC: 
     346  case DNS_T_NSEC: /* nextDN bitmaps */ 
    338347    c = dptr; 
    339348    if (dns_getdn(pkt, &c, end, dn, DNS_MAXDN) <= 0) goto xperr; 
     
    451460         dns_rcodename(dns_rcode(pkt)), dns_qid(pkt), r); 
    452461  if (dns_qr(pkt)) printf(" qr"); 
     462  if (dns_aa(pkt)) printf(" aa"); 
     463  if (dns_tc(pkt)) printf(" tc"); 
    453464  if (dns_rd(pkt)) printf(" rd"); 
    454465  if (dns_ra(pkt)) printf(" ra"); 
    455   if (dns_aa(pkt)) printf(" aa"); 
    456   if (dns_tc(pkt)) printf(" tc"); 
     466  /* if (dns_z(pkt))  printf(" z"); only one reserved bit left */ 
     467  if (dns_ad(pkt)) printf(" ad"); 
     468  if (dns_cd(pkt)) printf(" cd"); 
    457469  numqd = dns_numqd(pkt); 
    458470  printf("; QUERY: %d, ANSWER: %d, AUTHORITY: %d, ADDITIONAL: %d\n", 
     
    560572  enum dns_type qtyp = 0; 
    561573  struct dns_ctx *nctx = NULL; 
     574  int flags = 0; 
    562575 
    563576  if (!(progname = strrchr(argv[0], '/'))) progname = argv[0]; 
     
    573586   */ 
    574587 
    575   while((i = getopt(argc, argv, "vqt:c:an:o:h")) != EOF) switch(i) { 
     588  while((i = getopt(argc, argv, "vqt:c:an:o:f:h")) != EOF) switch(i) { 
    576589  case 'v': ++verbose; break; 
    577590  case 'q': --verbose; break; 
     
    600613    break; 
    601614  case 'o': 
    602     if (dns_set_opts(NULL, optarg) != 0) 
    603       die(0, "invalid option string: `%s'", optarg); 
    604     break; 
     615  case 'f': { 
     616    char *opt; 
     617    const char *const delim = " \t,;"; 
     618    for(opt = strtok(optarg, delim); opt != NULL; opt = strtok(NULL, delim)) { 
     619      if (dns_set_opts(NULL, optarg) == 0) 
     620        ; 
     621      else if (strcmp(opt, "aa") == 0) flags |= DNS_AAONLY; 
     622      else if (strcmp(optarg, "nord") == 0) flags |= DNS_NORD; 
     623      else if (strcmp(optarg, "dnssec") == 0) flags |= DNS_SET_DO; 
     624      else if (strcmp(optarg, "do")     == 0) flags |= DNS_SET_DO; 
     625      else if (strcmp(optarg, "cd") == 0) flags |= DNS_SET_CD; 
     626      else 
     627        die(0, "invalid option: `%s'", opt); 
     628    } 
     629    break; 
     630  } 
    605631  case 'h': 
    606632    printf( 
     
    616642" -n ns - use given nameserver(s) instead of default\n" 
    617643"  (may be specified multiple times)\n" 
    618 " -o option:value - set resovler option (the same as setting $RES_OPTIONS):\n" 
    619 "  timeout:sec  - initial query timeout\n" 
    620 "  attempts:num - number of attempt to resovle a query\n" 
    621 "  ndots:num    - if name has more than num dots, lookup it before search\n" 
    622 "  port:num     - port number for queries instead of default 53\n" 
    623 "  udpbuf:num   - size of UDP buffer (use EDNS0 if >512)\n" 
    624 "  (may be specified more than once)\n" 
     644" -o opt,opt,... (comma- or space-separated list,\n" 
     645"                 may be specified more than once):\n" 
     646"  set resovler options (the same as setting $RES_OPTIONS):\n" 
     647"   timeout:sec  - initial query timeout\n" 
     648"   attempts:num - number of attempt to resovle a query\n" 
     649"   ndots:num    - if name has more than num dots, lookup it before search\n" 
     650"   port:num     - port number for queries instead of default 53\n" 
     651"   udpbuf:num   - size of UDP buffer (use EDNS0 if >512)\n" 
     652"  or query flags:\n" 
     653"   aa,nord,dnssec,do,cd - set query flag (auth-only, no recursion,\n" 
     654"     enable DNSSEC (DNSSEC Ok), check disabled)\n" 
    625655      , progname, dns_version(), progname); 
    626656    return 0; 
     
    680710    dns_set_dbgfn(NULL, dbgcb); 
    681711 
     712  if (flags) 
     713    dns_set_opt(NULL, DNS_OPT_FLAGS, flags); 
     714 
    682715  for (i = 0; i < argc; ++i) { 
    683716    char *name = argv[i]; 
  • src/udns/ex-rdns.c

    r5a9b91b reafba4c  
    1 /* $Id: ex-rdns.c,v 1.8 2007/01/07 22:46:47 mjt Exp $ 
     1/* ex-rdns.c 
    22   parallel rDNS resolver example - read IP addresses from stdin, 
    33   write domain names to stdout 
     
    5757 
    5858int main(int argc, char **argv) { 
    59   int c, t
     59  int c
    6060  time_t now; 
    6161  int maxq = 10; 
     
    104104    } 
    105105    if (curq) { 
    106       t = dns_timeouts(0, -1, now); 
    107       t = poll(&pfd, 1, c * 1000); 
     106      c = dns_timeouts(0, -1, now); 
     107      c = poll(&pfd, 1, c < 0 ? -1 : c * 1000); 
    108108      now = time(NULL); 
    109       if (t) dns_ioevent(0, now); 
     109      if (c) 
     110        dns_ioevent(0, now); 
    110111    } 
    111112  } 
  • src/udns/getopt.c

    r5a9b91b reafba4c  
    1 /* $Id: getopt.c,v 1.2 2007/01/07 23:19:19 mjt Exp $ 
     1/* getopt.c 
    22 * Simple getopt() implementation. 
    33 * 
  • src/udns/inet_XtoX.c

    r5a9b91b reafba4c  
    1 /* $Id: inet_XtoX.c,v 1.1 2006/12/04 01:55:39 mjt Exp $ 
     1/* inet_XtoX.c 
    22 * Simple implementation of the following functions: 
    33 *  inet_ntop(), inet_ntoa(), inet_pton(), inet_aton(). 
  • src/udns/rblcheck.1

    r5a9b91b reafba4c  
    1 .\" $Id: rblcheck.1,v 1.1 2005/04/24 23:14:23 mjt Exp $ 
     1.\" rblcheck.1 
    22.\" rblckeck manpage 
    33.\" 
  • src/udns/rblcheck.c

    r5a9b91b reafba4c  
    1 /* $Id: rblcheck.c,v 1.14 2007/01/10 02:52:51 mjt Exp $ 
     1/* rblcheck.c 
    22   dnsbl (rbl) checker application 
    33 
     
    4545#endif 
    4646 
    47 static const char *version = "udns-rblcheck 0.2"; 
     47static const char *version = "udns-rblcheck 0.4"; 
    4848static char *progname; 
    4949 
     
    122122    while(*e && *e != ' ' && *e != '\t' && *e != '\n') 
    123123      ++e; 
    124     *e = '\0'; 
     124    *e++ = '\0'; 
     125    p = memcpy(ecalloc(e - p, 1), p, e - p); // strdup 
    125126    addzone(p); 
    126127  } 
  • src/udns/udns.3

    r5a9b91b reafba4c  
    1 .\" $Id: udns.3,v 1.32 2007/01/15 21:19:08 mjt Exp $ 
     1.\" udns.3 
    22.\" udns library manpage 
    33.\" 
    4 .\" Copyright (C) 2005  Michael Tokarev <mjt@corpit.ru> 
     4.\" Copyright (C) 2005-2014  Michael Tokarev <mjt+udns@tls.msk.ru> 
    55.\" This file is part of UDNS library, an async DNS stub resolver. 
    66.\" 
     
    2020.\" Suite 330, Boston, MA  02111-1307  USA 
    2121 
    22 .TH udns 3 "Jan 2007" "Library Functions" 
     22.TH udns 3 "Jan 2014" "Library Functions" 
    2323 
    2424.SH NAME 
     
    185185When initializing resolver context, the library uses information from 
    186186system file /etc/resolv.conf (see \fBresolv.conf\fR(5)), consults 
    187 environment variables \fB$LOCALDOMAIN\fR, \fB$DNSCACHEIP\fR, 
     187environment variables \fB$LOCALDOMAIN\fR, \fB$NSCACHEIP\fR, 
    188188\fB$NAMESERVERS\fR and \fB$RES_OPTIONS\fR, and local host name to obtain 
    189189list of local nameservers, domain name search list and various resolver 
     
    253253set resolver context options from \fIopts\fR string, in the same way as 
    254254processing \fBoptions\fR statement in resolv.conf and \fB$RES_OPTIONS\fR 
    255 environment variable. 
     255environment variable.  Return number of unrecognized/invalid options 
     256found (all recognized and valid options gets processed). 
    256257.RE 
    257258.PP 
     
    350351.nf 
    351352typedef void \fBdns_utm_fn\fR(\fIctx\fR, int \fItimeout\fR, void *\fIdata\fR) 
    352 void \fBdns_set_cbck\fR(\fIctx\fR, dns_utm_fn *\fIutmfn\fR, void *\fIdata\fR) 
     353void \fBdns_set_tmcbck\fR(\fIctx\fR, dns_utm_fn *\fIutmfn\fR, void *\fIdata\fR) 
    353354.fi 
    354355.RS 
     
    368369.IP "\fIctx\fR == NULL" 
    369370delete user timer, at context free time or when an application changes 
    370 user timer request routine using \fBdns_set_cbck\fR(); 
     371user timer request routine using \fBdns_set_tmcbck\fR(); 
    371372.IP "\fIctx\fR != NULL, \fItimeout\fR < 0" 
    372373don't fire timer anymore, when there are no active requests; 
     
    377378.PP 
    378379The \fIdata\fR argument passed to the routine will be the same 
    379 as passed to \fBdns_set_cbck\fR(). 
    380 .PP 
    381 When a timer expires, an application should call \fBdns_tmeouts\fR() 
     380as passed to \fBdns_set_tmcbck\fR(). 
     381.PP 
     382When a timer expires, an application should call \fBdns_timeouts\fR() 
    382383routine (see below).  Non-callback timer usage is provided too. 
    383384.RE 
     
    846847  int \fBpreference\fR;         /* preference of this record */ 
    847848  char *\fBflags\fR;            /* application-specific flags */ 
    848   char *\fBservices\fR;         /* service parameters */ 
     849  char *\fBservice\fR;          /* service parameter */ 
    849850  char *\fBregexp\fR;           /* substitutional regular expression */ 
    850851  char *\fBreplacement\fR;      /* replacement string */ 
     
    13451346.SH AUTHOR 
    13461347.PP 
    1347 The \fBudns\fR library has been written by Michael Tokarev, mjt@corpit.ru. 
     1348The \fBudns\fR library has been written by Michael Tokarev, mjt+udns@tls.msk.ru. 
    13481349 
    13491350.SH VERSION 
    13501351.PP 
    1351 This manual page corresponds to udns version 0.0.9, released Jan-2007
     1352This manual page corresponds to udns version 0.4, released Jan-2014
  • src/udns/udns.h

    rc478b72 reafba4c  
    1 /* $Id: udns.h,v 1.51 2007/01/15 21:19:08 mjt Exp $ 
     1/* udns.h 
    22   header file for the UDNS library. 
    33 
     
    2424#ifndef UDNS_VERSION    /* include guard */ 
    2525 
    26 #define UDNS_VERSION "0.0.9
     26#define UDNS_VERSION "0.4
    2727 
    2828#ifdef WINDOWS 
     
    131131  DNS_T_OPT             = 41,   /* EDNS0 option (meta-RR) */ 
    132132  DNS_T_DS              = 43,   /* DNSSEC */ 
     133  DNS_T_SSHFP           = 44, 
     134  DNS_T_IPSECKEY        = 45, 
     135  DNS_T_RRSIG           = 46,   /* DNSSEC */ 
    133136  DNS_T_NSEC            = 47,   /* DNSSEC */ 
     137  DNS_T_DNSKEY          = 48, 
     138  DNS_T_DHCID           = 49, 
     139  DNS_T_NSEC3           = 50, 
     140  DNS_T_NSEC3PARAMS     = 51, 
     141  DNS_T_TALINK          = 58, /* draft-ietf-dnsop-trust-history */ 
     142  DNS_T_SPF             = 99, 
     143  DNS_T_UINFO           = 100, 
     144  DNS_T_UID             = 101, 
     145  DNS_T_GID             = 102, 
     146  DNS_T_UNSPEC          = 103, 
    134147  DNS_T_TSIG            = 250,  /* Transaction signature. */ 
    135148  DNS_T_IXFR            = 251,  /* Incremental zone transfer. */ 
     
    139152  DNS_T_ANY             = 255,  /* Wildcard match. */ 
    140153  DNS_T_ZXFR            = 256,  /* BIND-specific, nonstandard. */ 
     154  DNS_T_DLV             = 32769, /* RFC 4431, 5074, DNSSEC Lookaside Validation */ 
    141155  DNS_T_MAX             = 65536 
    142156}; 
     
    234248}; 
    235249 
    236 static inline unsigned dns_get16(dnscc_t *s) { 
     250static __inline unsigned dns_get16(dnscc_t *s) { 
    237251  return ((unsigned)s[0]<<8) | s[1]; 
    238252} 
    239 static inline unsigned dns_get32(dnscc_t *s) { 
     253static __inline unsigned dns_get32(dnscc_t *s) { 
    240254  return ((unsigned)s[0]<<24) | ((unsigned)s[1]<<16) 
    241255        | ((unsigned)s[2]<<8) | s[3]; 
    242256} 
    243 static inline dnsc_t *dns_put16(dnsc_t *d, unsigned n) { 
     257static __inline dnsc_t *dns_put16(dnsc_t *d, unsigned n) { 
    244258  *d++ = (dnsc_t)((n >> 8) & 255); *d++ = (dnsc_t)(n & 255); return d; 
    245259} 
    246 static inline dnsc_t *dns_put32(dnsc_t *d, unsigned n) { 
     260static __inline dnsc_t *dns_put32(dnsc_t *d, unsigned n) { 
    247261  *d++ = (dnsc_t)((n >> 24) & 255); *d++ = (dnsc_t)((n >> 16) & 255); 
    248262  *d++ = (dnsc_t)((n >>  8) & 255); *d++ = (dnsc_t)(n & 255); 
    249263  return d; 
    250264} 
    251  
    252 /* return pseudo-random 16bits number */ 
    253 UDNS_API unsigned dns_random16(void); 
    254265 
    255266/* DNS Header layout */ 
     
    276287  DNS_HF2_RA    = 0x80, /* recursion available */ 
    277288#define dns_ra(pkt)     ((pkt)[DNS_H_F2]&DNS_HF2_RA) 
    278   DNS_HF2_Z     = 0x70, /* reserved */ 
     289  DNS_HF2_Z     = 0x40, /* reserved */ 
     290  DNS_HF2_AD    = 0x20, /* DNSSEC: authentic data */ 
     291#define dns_ad(pkt)     ((pkt)[DNS_H_F2]&DNS_HF2_AD) 
     292  DNS_HF2_CD    = 0x10, /* DNSSEC: checking disabled */ 
     293#define dns_cd(pkt)     ((pkt)[DNS_H_F2]&DNS_HF2_CD) 
    279294  DNS_HF2_RCODE = 0x0f, /* response code, DNS_R_XXX above */ 
    280295#define dns_rcode(pkt)  ((pkt)[DNS_H_F2]&DNS_HF2_RCODE) 
     
    300315#define dns_numar(pkt)  dns_get16((pkt)+10) 
    301316#define dns_payload(pkt) ((pkt)+DNS_HSIZE) 
     317  /* EDNS0 (OPT RR) flags (Ext. Flags) */ 
     318  DNS_EF1_DO    = 0x80, /* DNSSEC OK */ 
    302319}; 
    303320 
     
    407424  DNS_NORD      = 0x00020000,   /* request no recursion */ 
    408425  DNS_AAONLY    = 0x00040000,   /* set AA flag in queries */ 
     426  DNS_SET_DO    = 0x00080000,   /* set EDNS0 "DO" bit (DNSSEC OK) */ 
     427  DNS_SET_CD    = 0x00100000,   /* set CD bit (DNSSEC: checking disabled) */ 
    409428}; 
    410429 
     
    742761UDNS_API const char *dns_strerror(int errnum); 
    743762 
     763/* simple pseudo-random number generator, code by Bob Jenkins */ 
     764 
     765struct udns_jranctx {   /* the context */ 
     766  unsigned a, b, c, d; 
     767}; 
     768 
     769/* initialize the RNG with a given seed */ 
     770UDNS_API void 
     771udns_jraninit(struct udns_jranctx *x, unsigned seed); 
     772 
     773/* return next random number.  32bits on most platforms so far. */ 
     774UDNS_API unsigned 
     775udns_jranval(struct udns_jranctx *x); 
     776 
    744777#ifdef __cplusplus 
    745778} /* extern "C" */ 
  • src/udns/udns_XtoX.c

    r5a9b91b reafba4c  
    1 /* $Id: udns_XtoX.c,v 1.1 2007/01/07 22:20:39 mjt Exp $ 
     1/* udns_XtoX.c 
    22   udns_ntop() and udns_pton() routines, which are either 
    33     - wrappers for inet_ntop() and inet_pton() or 
  • src/udns/udns_bl.c

    r5a9b91b reafba4c  
    1 /* $Id: udns_bl.c,v 1.10 2005/09/12 10:55:21 mjt Exp $ 
     1/* udns_bl.c 
    22   DNSBL stuff 
    33 
  • src/udns/udns_dn.c

    r6519887 reafba4c  
    1 /* $Id: udns_dn.c,v 1.7 2006/11/28 22:45:20 mjt Exp $ 
     1/* udns_dn.c 
    22   domain names manipulation routines 
    33 
     
    2727unsigned dns_dnlen(dnscc_t *dn) { 
    2828  register dnscc_t *d = dn; 
    29   unsigned l = 0; 
    30   while(*d && l < DNS_MAXDN) { 
    31     l += 1 + *d; 
     29  while(*d) 
    3230    d += 1 + *d; 
    33   } 
    3431  return (unsigned)(d - dn) + 1; 
    3532} 
     
    9087        if (np == (dnscc_t *)name && np + 1 == ne) { 
    9188          /* special case for root dn, aka `.' */ 
    92           /* ++np; 
    93              ... incrementing a variable that isn't subsequently looked at */ 
     89          ++np; 
    9490          break; 
    9591        } 
     
    139135    return -1;                          /* label too long */ 
    140136  if ((llab[-1] = (dnsc_t)c) != 0) { 
    141     if (dp >= de) 
    142       return -1; 
    143137    *dp++ = 0; 
    144138    if (isabs) 
     
    155149dnsc_t * 
    156150dns_a4todn_(const struct in_addr *addr, dnsc_t *dn, dnsc_t *dne) { 
    157   dnsc_t *p; 
    158   unsigned n; 
    159   dnscc_t *s = ((dnscc_t *)addr) + 4; 
    160   while(--s >= (dnscc_t *)addr) { 
    161     n = *s; 
    162     p = dn + 1; 
     151  const unsigned char *s = ((const unsigned char *)addr) + 4; 
     152  while(s > (const unsigned char *)addr) { 
     153    unsigned n = *--s; 
     154    dnsc_t *p = dn + 1; 
    163155    if (n > 99) { 
    164156      if (p + 2 > dne) return 0; 
     
    213205dnsc_t * 
    214206dns_a6todn_(const struct in6_addr *addr, dnsc_t *dn, dnsc_t *dne) { 
    215   unsigned n; 
    216   dnscc_t *s = ((dnscc_t *)addr) + 16; 
     207  const unsigned char *s = ((const unsigned char *)addr) + 16; 
    217208  if (dn + 64 > dne) return 0; 
    218   while(--s >= (dnscc_t *)addr) { 
     209  while(s > (const unsigned char *)addr) { 
     210    unsigned n = *--s & 0x0f; 
    219211    *dn++ = 1; 
    220     n = *s & 0x0f; 
    221212    *dn++ = n > 9 ? n + 'a' - 10 : n + '0'; 
    222213    *dn++ = 1; 
  • src/udns/udns_dntosp.c

    r5a9b91b reafba4c  
    1 /* $Id: udns_dntosp.c,v 1.5 2005/04/19 21:48:09 mjt Exp $ 
     1/* udns_dntosp.c 
    22   dns_dntosp() = convert DN to asciiz string using static buffer 
    33 
  • src/udns/udns_init.c

    rdd70a5f reafba4c  
    1 /* $Id: udns_init.c,v 1.6 2007/01/08 00:41:38 mjt Exp $ 
     1/* udns_init.c 
    22   resolver initialisation stuff 
    33 
     
    3737#include <string.h> 
    3838#include "udns.h" 
    39  
    40 extern int NE_O_CLOEXEC; 
    4139 
    4240#define ISSPACE(x) (x == ' ' || x == '\t' || x == '\r' || x == '\n') 
     
    150148 
    151149  /* read resolv.conf... */ 
    152   { int fd = open("/etc/resolv.conf", O_RDONLY|NE_O_CLOEXEC); 
     150  { int fd = open("/etc/resolv.conf", O_RDONLY); 
    153151    if (fd >= 0) { 
    154152      int l = read(fd, buf, sizeof(buf) - 1); 
  • src/udns/udns_misc.c

    r5a9b91b reafba4c  
    1 /* $Id: udns_misc.c,v 1.8 2005/04/05 22:51:32 mjt Exp $ 
     1/* udns_misc.c 
    22   miscellaneous routines 
    33 
  • src/udns/udns_parse.c

    r6519887 reafba4c  
    1 /* $Id: udns_parse.c,v 1.14 2005/09/12 10:55:21 mjt Exp $ 
     1/* udns_parse.c 
    22   raw DNS packet parsing routines 
    33 
     
    5656    c = *pp++;                  /* length of the label */ 
    5757    if (!c) {                   /* empty label: terminate */ 
    58       if (dp >= de)           /* can't fit terminator */ 
     58      if (dn >= de)           /* can't fit terminator */ 
    5959        goto noroom; 
    6060      *dp++ = 0; 
  • src/udns/udns_resolver.c

    rdd70a5f reafba4c  
    1 /* $Id: udns_resolver.c,v 1.98 2007/01/10 13:32:33 mjt Exp $ 
     1/* udns_resolver.c 
    22   resolver stuff (main module) 
    33 
     
    5656#include "udns.h" 
    5757 
    58 extern int NE_SOCK_CLOEXEC; 
    59  
    6058#ifndef EAFNOSUPPORT 
    6159# define EAFNOSUPPORT EINVAL 
     
    6563#endif 
    6664 
    67 struct dns_qlink
    68   struct dns_query *next, *prev
     65struct dns_qlist
     66  struct dns_query *head, *tail
    6967}; 
    7068 
    7169struct dns_query { 
    72   struct dns_qlink dnsq_link;           /* list entry (should be first) */ 
     70  struct dns_query *dnsq_next;          /* double-linked list */ 
     71  struct dns_query *dnsq_prev; 
    7372  unsigned dnsq_origdnl0;               /* original query DN len w/o last 0 */ 
    7473  unsigned dnsq_flags;                  /* control flags for this query */ 
     
    9493/* working with dns_query lists */ 
    9594 
    96 static inline void qlist_init(struct dns_qlink *list) { 
    97   list->next = list->prev = (struct dns_query *)list; 
    98 
    99  
    100 static inline int qlist_isempty(const struct dns_qlink *list) { 
    101   return list->next == (const struct dns_query *)list ? 1 : 0; 
    102 
    103  
    104 static inline struct dns_query *qlist_first(struct dns_qlink *list) { 
    105   return list->next == (struct dns_query *)list ? 0 : list->next; 
    106 
    107  
    108 static inline void qlist_remove(struct dns_query *q) { 
    109   q->dnsq_link.next->dnsq_link.prev = q->dnsq_link.prev; 
    110   q->dnsq_link.prev->dnsq_link.next = q->dnsq_link.next; 
    111 
    112  
    113 /* insert q between prev and next */ 
    114 static inline void 
    115 qlist_insert(struct dns_query *q, 
    116              struct dns_query *prev, struct dns_query *next) { 
    117   q->dnsq_link.next = next; 
    118   q->dnsq_link.prev = prev; 
    119   prev->dnsq_link.next = next->dnsq_link.prev = q; 
    120 
    121  
    122 static inline void 
    123 qlist_insert_after(struct dns_query *q, struct dns_query *prev) { 
    124   qlist_insert(q, prev, prev->dnsq_link.next); 
    125 
    126  
    127 static inline void 
    128 qlist_insert_before(struct dns_query *q, struct dns_query *next) { 
    129   qlist_insert(q, next->dnsq_link.prev, next); 
    130 
    131  
    132 static inline void 
    133 qlist_add_tail(struct dns_query *q, struct dns_qlink *top) { 
    134   qlist_insert_before(q, (struct dns_query *)top); 
    135 
    136  
    137 static inline void 
    138 qlist_add_head(struct dns_query *q, struct dns_qlink *top) { 
    139   qlist_insert_after(q, (struct dns_query *)top); 
    140 
    141  
    142 #define QLIST_FIRST(list, direction) ((list)->direction) 
    143 #define QLIST_ISLAST(list, q) ((q) == (struct dns_query*)(list)) 
    144 #define QLIST_NEXT(q, direction) ((q)->dnsq_link.direction) 
    145  
    146 #define QLIST_FOR_EACH(list, q, direction) \ 
    147   for(q = QLIST_FIRST(list, direction); \ 
    148       !QLIST_ISLAST(list, q); q = QLIST_NEXT(q, direction)) 
     95static __inline void qlist_init(struct dns_qlist *list) { 
     96  list->head = list->tail = NULL; 
     97
     98 
     99static __inline void qlist_remove(struct dns_qlist *list, struct dns_query *q) { 
     100   if (q->dnsq_prev) q->dnsq_prev->dnsq_next = q->dnsq_next; 
     101   else list->head = q->dnsq_next; 
     102   if (q->dnsq_next) q->dnsq_next->dnsq_prev = q->dnsq_prev; 
     103   else list->tail = q->dnsq_prev; 
     104
     105 
     106static __inline void 
     107qlist_add_head(struct dns_qlist *list, struct dns_query *q) { 
     108  q->dnsq_next = list->head; 
     109  if (list->head) list->head->dnsq_prev = q; 
     110  else list->tail = q; 
     111  list->head = q; 
     112  q->dnsq_prev = NULL; 
     113
     114 
     115static __inline void 
     116qlist_insert_after(struct dns_qlist *list, 
     117                   struct dns_query *q, struct dns_query *prev) { 
     118  if ((q->dnsq_prev = prev) != NULL) { 
     119    if ((q->dnsq_next = prev->dnsq_next) != NULL) 
     120      q->dnsq_next->dnsq_prev = q; 
     121    else 
     122      list->tail = q; 
     123    prev->dnsq_next = q; 
     124  } 
     125  else 
     126    qlist_add_head(list, q); 
     127
    149128 
    150129union sockaddr_ns { 
     
    185164 
    186165  /* dynamic data */ 
    187   unsigned dnsc_nextid;         /* next queue ID to use */ 
     166  struct udns_jranctx dnsc_jran;        /* random number generator state */ 
     167  unsigned dnsc_nextid;                 /* next queue ID to use if !0 */ 
    188168  int dnsc_udpsock;                     /* UDP socket */ 
    189   struct dns_qlink dnsc_qactive;      /* active list sorted by deadline */ 
     169  struct dns_qlist dnsc_qactive;      /* active list sorted by deadline */ 
    190170  int dnsc_nactive;                     /* number entries in dnsc_qactive */ 
    191171  dnsc_t *dnsc_pbuf;                    /* packet buffer (udpbuf size) */ 
     
    231211  int nactive = 0; 
    232212  const struct dns_query *q; 
    233   QLIST_FOR_EACH(&ctx->dnsc_qactive, q, next) { 
     213  for(q = ctx->dnsc_qactive.head; q; q = q->dnsq_next) { 
    234214    assert(q->dnsq_ctx == ctx); 
    235     assert(q->dnsq_link.next->dnsq_link.prev == q); 
    236     assert(q->dnsq_link.prev->dnsq_link.next == q); 
     215    assert(q == (q->dnsq_next ? 
     216                 q->dnsq_next->dnsq_prev : ctx->dnsc_qactive.tail)); 
     217    assert(q == (q->dnsq_prev ? 
     218                 q->dnsq_prev->dnsq_next : ctx->dnsc_qactive.head)); 
    237219    ++nactive; 
    238220  } 
     
    290272int dns_set_opts(struct dns_ctx *ctx, const char *opts) { 
    291273  unsigned i, v; 
     274  int err = 0; 
    292275  SETCTXINACTIVE(ctx); 
    293276  for(;;) { 
    294277    while(ISSPACE(*opts)) ++opts; 
    295278    if (!*opts) break; 
    296     for(i = 0; i < sizeof(dns_opts)/sizeof(dns_opts[0]); ++i) { 
     279    for(i = 0; ; ++i) { 
     280      if (i >= sizeof(dns_opts)/sizeof(dns_opts[0])) { ++err; break; } 
    297281      v = strlen(dns_opts[i].name); 
    298282      if (strncmp(dns_opts[i].name, opts, v) != 0 || 
     
    301285      opts += v + 1; 
    302286      v = 0; 
    303       if (*opts < '0' || *opts > '9') break; 
     287      if (*opts < '0' || *opts > '9') { ++err; break; } 
    304288      do v = v * 10 + (*opts++ - '0'); 
    305289      while (*opts >= '0' && *opts <= '9'); 
     
    311295    while(*opts && !ISSPACE(*opts)) ++opts; 
    312296  } 
    313   return 0
     297  return err
    314298} 
    315299 
     
    374358  time_t deadline; 
    375359  int timeout; 
    376   q = qlist_first(&ctx->dnsc_qactive)
     360  q = ctx->dnsc_qactive.head
    377361  if (!q) 
    378362    deadline = -1, timeout = -1; 
     
    387371} 
    388372 
    389 static inline void 
     373static __inline void 
    390374dns_request_utm(struct dns_ctx *ctx, time_t now) { 
    391375  if (ctx->dnsc_utmfn) 
     
    408392} 
    409393 
    410 unsigned dns_random16(void) { 
     394static unsigned dns_nonrandom_32(void) { 
    411395#ifdef WINDOWS 
    412396  FILETIME ft; 
    413397  GetSystemTimeAsFileTime(&ft); 
    414 #define x (ft.dwLowDateTime) 
     398  return ft.dwLowDateTime; 
    415399#else 
    416400  struct timeval tv; 
    417401  gettimeofday(&tv, NULL); 
    418 #define x (tv.tv_usec) 
    419 #endif 
    420   return ((unsigned)x ^ ((unsigned)x >> 16)) & 0xffff; 
    421 #undef x 
     402  return tv.tv_usec; 
     403#endif 
     404
     405 
     406/* This is historic deprecated API */ 
     407UDNS_API unsigned dns_random16(void); 
     408unsigned dns_random16(void) { 
     409  unsigned x = dns_nonrandom_32(); 
     410  return (x ^ (x >> 16)) & 0xffff; 
     411
     412 
     413static void dns_init_rng(struct dns_ctx *ctx) { 
     414  udns_jraninit(&ctx->dnsc_jran, dns_nonrandom_32()); 
     415  ctx->dnsc_nextid = 0; 
    422416} 
    423417 
    424418void dns_close(struct dns_ctx *ctx) { 
    425   struct dns_query *q
     419  struct dns_query *q, *p
    426420  SETCTX(ctx); 
    427421  if (CTXINITED(ctx)) { 
     
    432426      free(ctx->dnsc_pbuf); 
    433427    ctx->dnsc_pbuf = NULL; 
    434     while((q = qlist_first(&ctx->dnsc_qactive)) != NULL) { 
    435       qlist_remove(q); 
    436       free(q); 
    437     } 
     428    q = ctx->dnsc_qactive.head; 
     429    while((p = q) != NULL) { 
     430      q = q->dnsq_next; 
     431      free(p); 
     432    } 
     433    qlist_init(&ctx->dnsc_qactive); 
    438434    ctx->dnsc_nactive = 0; 
    439435    dns_drop_utm(ctx); 
     
    453449  ctx->dnsc_srchend = ctx->dnsc_srchbuf; 
    454450  qlist_init(&ctx->dnsc_qactive); 
    455   ctx->dnsc_nextid = dns_random16(); 
     451  dns_init_rng(ctx); 
    456452  ctx->dnsc_flags = DNS_INITED; 
    457453} 
     
    470466  ctx->dnsc_pbuf = NULL; 
    471467  ctx->dnsc_qstatus = 0; 
     468  ctx->dnsc_srchend = ctx->dnsc_srchbuf + 
     469    (copy->dnsc_srchend - copy->dnsc_srchbuf); 
    472470  ctx->dnsc_utmfn = NULL; 
    473471  ctx->dnsc_utmctx = NULL; 
    474   ctx->dnsc_nextid = dns_random16(); 
     472  dns_init_rng(ctx); 
    475473  return ctx; 
    476474} 
     
    532530      if (sns->sa.sa_family == AF_INET) { 
    533531        sin6.sin6_port = sns->sin.sin_port; 
    534         memcpy(&((struct in_addr*)&sin6.sin6_addr)[3], 
    535                &sns->sin.sin_addr, sizeof(struct in_addr)); 
     532        memcpy(sin6.sin6_addr.s6_addr + 4*3, &sns->sin.sin_addr, 4); 
    536533        sns->sin6 = sin6; 
    537534      } 
     
    543540 
    544541  if (have_inet6) 
    545     sock = socket(PF_INET6, NE_SOCK_CLOEXEC|SOCK_DGRAM, IPPROTO_UDP); 
     542    sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); 
    546543  else 
    547     sock = socket(PF_INET, NE_SOCK_CLOEXEC|SOCK_DGRAM, IPPROTO_UDP); 
     544    sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 
    548545#else /* !HAVE_IPv6 */ 
    549   sock = socket(PF_INET, NE_SOCK_CLOEXEC|SOCK_DGRAM, IPPROTO_UDP); 
     546  sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 
    550547  ctx->dnsc_salen = sizeof(struct sockaddr_in); 
    551548#endif /* HAVE_IPv6 */ 
     
    617614  assert(ctx->dnsc_nactive > 0); 
    618615  --ctx->dnsc_nactive; 
    619   qlist_remove(q); 
     616  qlist_remove(&ctx->dnsc_qactive, q); 
    620617  /* force the query to be unconnected */ 
    621618  /*memset(q, 0, sizeof(*q));*/ 
     
    693690   * DNSSEC) suffers from this same problem. 
    694691   * 
    695    * So, instead of trying to be more secure (which actually is not - false 
    696    * sense of security is - I think - is worse than no security), I'm trying 
    697    * to be more robust here (by preventing qID reuse, which helps in normal 
    698    * conditions).  And use sequential qID generation scheme
     692   * Here, I use a pseudo-random number generator for qIDs, instead of a 
     693   * simpler sequential IDs.  This is _not_ more secure than sequential 
     694   * ID, but some found random IDs more enjoyeable for some reason.  So 
     695   * here it goes
    699696   */ 
    700   dns_put16(q->dnsq_id, ctx->dnsc_nextid++); 
     697 
     698  /* Use random number and check if it's unique. 
     699   * If it's not, try again up to 5 times. 
     700   */ 
     701  unsigned loop; 
     702  dnsc_t c0, c1; 
     703  for(loop = 0; loop < 5; ++loop) { 
     704    const struct dns_query *c; 
     705    if (!ctx->dnsc_nextid) 
     706      ctx->dnsc_nextid = udns_jranval(&ctx->dnsc_jran); 
     707    c0 = ctx->dnsc_nextid & 0xff; 
     708    c1 = (ctx->dnsc_nextid >> 8) & 0xff; 
     709    ctx->dnsc_nextid >>= 16; 
     710    for(c = ctx->dnsc_qactive.head; c; c = c->dnsq_next) 
     711      if (c->dnsq_id[0] == c0 && c->dnsq_id[1] == c1) 
     712        break; /* found such entry, try again */ 
     713    if (!c) 
     714      break; 
     715  } 
     716  q->dnsq_id[0] = c0; q->dnsq_id[1] = c1; 
     717 
    701718  /* reset all parameters relevant for previous query lifetime */ 
    702719  q->dnsq_try = 0; 
     
    758775    if (!(q->dnsq_flags & DNS_NORD)) p[DNS_H_F1] |= DNS_HF1_RD; 
    759776    if (q->dnsq_flags & DNS_AAONLY) p[DNS_H_F1] |= DNS_HF1_AA; 
     777    if (q->dnsq_flags & DNS_SET_CD) p[DNS_H_F2] |= DNS_HF2_CD; 
    760778    p[DNS_H_QDCNT2] = 1; 
    761779    memcpy(p + DNS_H_QID, q->dnsq_id, 2); 
     
    765783    /* query type and class */ 
    766784    memcpy(p, q->dnsq_typcls, 4); p += 4; 
    767     /* add EDNS0 size record */ 
    768     if (ctx->dnsc_udpbuf > DNS_MAXPACKET && 
    769         !(q->dnsq_servnEDNS0 & (1 << servi))) { 
     785    /* add EDNS0 record. DO flag requires it */ 
     786    if (q->dnsq_flags & DNS_SET_DO || 
     787        (ctx->dnsc_udpbuf > DNS_MAXPACKET && 
     788         !(q->dnsq_servnEDNS0 & (1 << servi)))) { 
    770789      *p++ = 0;                 /* empty (root) DN */ 
    771790      p = dns_put16(p, DNS_T_OPT); 
    772791      p = dns_put16(p, ctx->dnsc_udpbuf); 
    773792      /* EDNS0 RCODE & VERSION; rest of the TTL field; RDLEN */ 
    774       memset(p, 0, 2+2+2); p += 2+2+2; 
     793      memset(p, 0, 2+2+2); 
     794      if (q->dnsq_flags & DNS_SET_DO) p[2] |= DNS_EF1_DO; 
     795      p += 2+2+2; 
    775796      ctx->dnsc_pbuf[DNS_H_ARCNT2] = 1; 
    776797    } 
     
    802823 
    803824  /* move the query to the proper place, according to the new deadline */ 
    804   qlist_remove(q); 
     825  qlist_remove(&ctx->dnsc_qactive, q); 
    805826  { /* insert from the tail */ 
    806827    struct dns_query *p; 
    807     QLIST_FOR_EACH(&ctx->dnsc_qactive, p, prev) 
     828    for(p = ctx->dnsc_qactive.tail; p; p = p->dnsq_prev) 
    808829      if (p->dnsq_deadline <= q->dnsq_deadline) 
    809830        break; 
    810     qlist_insert_after(q, p); 
     831    qlist_insert_after(&ctx->dnsc_qactive, q, p); 
    811832  } 
    812833 
     
    847868static void dns_dummy_cb(struct dns_ctx *ctx, void *result, void *data) { 
    848869  if (result) free(result); 
     870  data = ctx = 0;       /* used */ 
    849871} 
    850872 
     
    898920  } 
    899921 
    900   qlist_add_head(q, &ctx->dnsc_qactive); 
     922  /* q->dnsq_deadline is set to 0 (calloc above): the new query is 
     923   * "already expired" when first inserted into queue, so it's safe 
     924   * to insert it into the head of the list.  Next call to dns_timeouts() 
     925   * will actually send it. 
     926   */ 
     927  qlist_add_head(&ctx->dnsc_qactive, q); 
    901928  ++ctx->dnsc_nactive; 
    902929  dns_request_utm(ctx, 0); 
     
    952979again: /* receive the reply */ 
    953980 
    954   if (!CTXOPEN(ctx)) 
    955     return; 
    956981  slen = sizeof(sns); 
    957982  r = recvfrom(ctx->dnsc_udpsock, (void*)pbuf, ctx->dnsc_udpbuf, 
     
    9891014 
    9901015  /* find the matching query, by qID */ 
    991   for (q = QLIST_FIRST(&ctx->dnsc_qactive, next);; q = QLIST_NEXT(q, next)) { 
    992     if (QLIST_ISLAST(&ctx->dnsc_qactive, q)) { 
     1016  for (q = ctx->dnsc_qactive.head; ; q = q->dnsq_next) { 
     1017    if (!q) { 
    9931018      /* no more requests: old reply? */ 
    9941019      DNS_DBG(ctx, -5/*no matching query*/, &sns.sa, slen, pbuf, r); 
     
    11891214   */ 
    11901215 
    1191   q = qlist_first(&ctx->dnsc_qactive)
     1216  q = ctx->dnsc_qactive.head
    11921217  if (!q) 
    11931218    return maxwait; 
     
    12051230      dns_send(ctx, q, now); 
    12061231    } 
    1207   } while((q = qlist_first(&ctx->dnsc_qactive)) != NULL); 
     1232  } while((q = ctx->dnsc_qactive.head) != NULL); 
    12081233 
    12091234  dns_request_utm(ctx, now); /* update timer with new deadline */ 
     
    12911316  if (q->dnsq_cbck == dns_resolve_cb) 
    12921317    return (ctx->dnsc_qstatus = DNS_E_BADQUERY); 
    1293   qlist_remove(q); 
     1318  qlist_remove(&ctx->dnsc_qactive, q); 
    12941319  --ctx->dnsc_nactive; 
    12951320  dns_request_utm(ctx, 0); 
  • src/udns/udns_rr_a.c

    r5a9b91b reafba4c  
    1 /* $Id: udns_rr_a.c,v 1.16 2007/01/09 04:44:51 mjt Exp $ 
     1/* udns_rr_a.c 
    22   parse/query A/AAAA IN records 
    33 
  • src/udns/udns_rr_mx.c

    r5a9b91b reafba4c  
    1 /* $Id: udns_rr_mx.c,v 1.13 2005/04/20 06:44:34 mjt Exp $ 
     1/* udns_rr_mx.c 
    22   parse/query MX IN records 
    33 
  • src/udns/udns_rr_naptr.c

    r5a9b91b reafba4c  
    1 /* $Id: udns_rr_naptr.c,v 1.1 2006/11/28 22:58:04 mjt Exp $ 
     1/* udns_rr_naptr.c 
    22   parse/query NAPTR IN records 
    33 
  • src/udns/udns_rr_ptr.c

    rc69f955 reafba4c  
    1 /* $Id: udns_rr_ptr.c,v 1.15 2005/09/12 11:21:06 mjt Exp $ 
     1/* udns_rr_ptr.c 
    22   parse/query PTR records 
    33 
     
    6565  c = 0; 
    6666  dns_rewind(&p, qdn); 
    67   while(dns_nextrr(&p, &rr) > 0) { 
     67  while((r = dns_nextrr(&p, &rr)) > 0) { 
    6868    ret->dnsptr_ptr[c] = sp; 
    6969    cur = rr.dnsrr_dptr; 
  • src/udns/udns_rr_srv.c

    r5a9b91b reafba4c  
    1 /* $Id: udns_rr_srv.c,v 1.2 2005/09/12 12:26:22 mjt Exp $ 
     1/* udns_rr_srv.c 
    22   parse/query SRV IN (rfc2782) records 
    33 
     
    8888 * Return 0 or the label length. 
    8989 * Routing assumes dn holds enouth space for a single DN label. */ 
    90 static unsigned add_sname(dnsc_t *dn, const char *sn) { 
    91   unsigned l; 
    92   l = dns_ptodn(sn, 0, dn + 1, DNS_MAXLABEL-1, NULL); 
     90static int add_sname(dnsc_t *dn, const char *sn) { 
     91  int l = dns_ptodn(sn, 0, dn + 1, DNS_MAXLABEL-1, NULL); 
    9392  if (l <= 1 || l - 2 != dn[1]) 
    9493    /* Should we really check if sn is exactly one label?  Do we care? */ 
     
    9998} 
    10099 
    101 /* Construct a domain name for SRV query from the given name, service and 
    102  * protocol (service may be NULL in which case protocol isn't used). 
    103  * Return negative value on error (malformed query), 
    104  * or addition query flag(s) to use. 
     100/* Construct a domain name for SRV query from the given name, service and proto. 
     101 * The code allows any combinations of srv and proto (both are non-NULL, 
     102 * both NULL, or either one is non-NULL).  Whenever it makes any sense or not 
     103 * is left as an exercise to programmer. 
     104 * Return negative value on error (malformed query) or addition query flag(s). 
    105105 */ 
    106106static int 
    107107build_srv_dn(dnsc_t *dn, const char *name, const char *srv, const char *proto) 
    108108{ 
    109   unsigned p = 0, l; 
    110   int isabs; 
     109  int p = 0, l, isabs; 
    111110  if (srv) { 
    112111    l = add_sname(dn + p, srv); 
     
    114113      return -1; 
    115114    p += l; 
     115  } 
     116  if (proto) { 
    116117    l = add_sname(dn + p, proto); 
    117118    if (!l) 
     
    120121  } 
    121122  l = dns_ptodn(name, 0, dn + p, DNS_MAXDN - p, &isabs); 
    122   if (!l
     123  if (l < 0
    123124    return -1; 
    124125  return isabs ? DNS_NOSRCH : 0; 
  • src/udns/udns_rr_txt.c

    r5a9b91b reafba4c  
    1 /* $Id: udns_rr_txt.c,v 1.15 2006/11/28 22:45:20 mjt Exp $ 
     1/* udns_rr_txt.c 
    22   parse/query TXT records 
    33