1 module jmap.resolv;
2 
3 /+
4 
5 *******************************************************************
6  * Test DNS SRV lookups
7  * copyright Gerald Carter <jerry@samba.org>  2006
8  *
9  * For some bizarre reason the ns_initparse(), et. al. routines
10  * are not available in the shared version of libresolv.so.
11  *
12  * To compile, run
13  *    dmd dnstest -L-lresolv
14  *
15  *******************************************************************/
16 
17 /* standard system headers */
18 
19 import std.stdio;
20 import std.string;
21 import core.sys.posix.netinet.in_;
22 import std.exception : enforce;
23 import std.experimental.logger : tracef;
24 import core.stdc.string : strerror;
25 import core.stdc.errno : errno;
26 
27 enum ns_s_max = 4;
28 extern(C) struct dst_key;
29 
30 /* resolver headers */
31 #include <sys/types.h>
32 #include <netinet/in.h>
33 #include <arpa/nameser.h>
34 #include <resolv.h>
35 
36 #include <netdb.h>
37 alias fromCString = fromStringz;
38 
39 struct RecordSRV
40 {
41     string name;
42     string address;
43 }
44 
45 
46 void main(string[] args)
47 {
48     auto records = getRecordsSRV(args[1]);
49     foreach(record;records)
50         writeln(record);
51 }
52 
53 RecordSRV[] getRecordsSRV(string hostname)
54 {
55     ns_msg h;
56     ns_rr rr;
57 
58     RecordSRV[] records;
59 
60     char[NS_PACKETSZ] buffer;
61     // send the request
62 
63     int resp_len = res_query(cast(char*) hostname.toStringz, NSClass.in_, NSType.srv, buffer.ptr, buffer.sizeof);
64     enforce(resp_len >=0, format!"Query for %s failed"(hostname));
65     writefln("resp = %s",buffer);
66     // now do the parsing
67     auto result = ns_initparse( cast(const(char)*) buffer.ptr, resp_len, &h );
68     enforce (!result, "Failed to parse response buffer");
69 
70     int numAnswerRecords = ns_msg_count(h, NSSect.an);
71     writefln("num an Records = %s",numAnswerRecords);
72 
73     foreach(recordNum; 0 .. numAnswerRecords)
74     {
75         result = ns_parserr( &h, NSSect.an, recordNum, &rr );
76         if(result)
77         {
78             stderr.writefln("ns_parserr: %s, %s" ,result,strerror(errno).fromStringz);
79             continue;
80         }
81 
82         if ( ns_rr_type(rr) == NSType.srv ) {
83             char[4096] name;
84             in_addr ip;
85 
86             //int ret = dn_expand( cast(const(char)*) ns_msg_base(h), cast(const(char)*) ns_msg_end(h), cast(const(char)*) ns_rr_rdata(rr)+6, name.ptr, name.sizeof);
87             int ret = dn_expand( cast(char*) ns_msg_base(h), cast(char*) ns_msg_end(h), cast(char*) ns_rr_rdata(rr)+6, name.ptr, name.sizeof);
88             enforce(ret >=0, format!"Failed to uncompress name (%s)"(ret));
89             tracef("%s",name);
90             records ~= RecordSRV(name.ptr.fromStringz.idup,"");
91         }
92     }
93 
94     numAnswerRecords = ns_msg_count(h, NSSect.ar);
95     writefln("num ar Records = %s",numAnswerRecords);
96 
97     foreach(recordNum; 0 .. numAnswerRecords)
98     {
99         writefln("%s",ns_rr_type(rr));
100         result = ns_parserr( &h, NSSect.ar, recordNum, &rr );
101         if(result)
102         {
103             stderr.writefln("ns_parserr: %s" ,strerror(errno).fromStringz);
104             continue;
105         }
106 
107         if ( ns_rr_type(rr) == NSType.a ) {
108             import std.conv : to;
109             char*[1024] name;
110             in_addr ip;
111             //const(char)** p = ns_rr_rdata(rr);
112             auto p = ns_rr_rdata(rr);
113             writeln("%s",p);
114             ip.s_addr = (p[3].to!int << 24) | (p[2].to!int << 16) | (p[1].to!int << 8) | p[0].to!int;
115             records ~= RecordSRV(ns_rr_name(rr).idup, inet_ntoa(ip).fromStringz.idup);
116         }
117     }
118 
119     return records;
120 }
121 
122 extern(C) @system:
123 
124 /*
125  * Copyright (c) 1983, 1987, 1989
126  *    The Regents of the University of California.  All rights reserved.
127  *
128  * Redistribution and use in source and binary forms, with or without
129  * modification, are permitted provided that the following conditions
130  * are met:
131  * 1. Redistributions of source code must retain the above copyright
132  *    notice, this list of conditions and the following disclaimer.
133  * 2. Redistributions in binary form must reproduce the above copyright
134  *    notice, this list of conditions and the following disclaimer in the
135  *    documentation and/or other materials provided with the distribution.
136  * 4. Neither the name of the University nor the names of its contributors
137  *    may be used to endorse or promote products derived from this software
138  *    without specific prior written permission.
139  *
140  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
141  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
142  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
143  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
144  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
145  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
146  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
147  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
148  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
149  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
150  * SUCH DAMAGE.
151  */
152 
153 /*
154  * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
155  *
156  * Permission to use, copy, modify, and distribute this software for any
157  * purpose with or without fee is hereby granted, provided that the above
158  * copyright notice and this permission notice appear in all copies.
159  *
160  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
161  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
162  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
163  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
164  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
165  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
166  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
167  * SOFTWARE.
168  */
169 
170 /*
171  *  @(#)resolv.h    8.1 (Berkeley) 6/2/93
172  *  $BINDId: resolv.h,v 8.31 2000/03/30 20:16:50 vixie Exp $
173  */
174 
175 /+
176 #include <sys/cdefs.h>
177 #include <sys/param.h>
178 #include <sys/types.h>
179 #include <stdio.h>
180 #include <netinet/in.h>
181 #include <arpa/nameser.h>
182 #include <bits/types/res_state.h>
183 +/
184 /*
185  * Global defines and variables for resolver stub.
186  */
187 enum LOCALDOMAINPARTS   = 2;    /* min levels in name that is "local" */
188 
189 enum ResolverCode
190 {
191     timeout = 5,                // min. seconds between retries
192     maxNDots = 15,              // should reflect bit field size
193     maxRetrans = 30,            // only for resolv.conf/RES_OPTIONS
194     maxRetry = 5,               // only for resolv.conf/RES_OPTIONS
195     defaultTries = 2,           // Default tries
196     maxTime = 65535,            // Infinity, in milliseconds
197 }
198 
199 
200 //alias nsaddr = nsaddr_list[0];        /* for backward compatibility */
201 
202 /*
203  * Revision information.  This is the release date in YYYYMMDD format.
204  * It can change every day so the right thing to do with it is use it
205  * in preprocessor commands such as "#if (__RES > 19931104)".  Do not
206  * compare for equality; rather, use it to determine whether your resolver
207  * is new enough to contain a certain feature.
208  */
209 
210 enum __RES  = 19991006;
211 
212 /*
213  * Resolver configuration file.
214  * Normally not present, but may contain the address of the
215  * inital name server(s) to query and the domain search list.
216  */
217 
218 enum _PATH_RESCONF = "/etc/resolv.conf";
219 
220 struct res_sym
221 {
222     int number;     /* Identifying number, like T_MX */
223     char** name;        /* Its symbolic name, like "MX" */
224     char** humanname;   /* Its fun name, like "mail exchanger" */
225 }
226 
227 /*
228  * Resolver options (keep these in synch with res_debug.c, please)
229  */
230 enum ResolverOption
231 {
232     init = 0x00000001,          // address initialized
233     debugMessages = 0x00000002, // print debug messages
234     aaOnly = 0x00000004,
235     useVirtualCircuit = 0x00000008,     // use virtual circuit
236     primary = 0x00000010,
237     ignoreTruncationErrors = 0x00000020,    // ignore trucation errors
238     recurse = 0x00000040,                   // recursion desired
239     defaultDomainName = 0x00000080,         // use default domain name
240     keepTCPSocketOPen = 0x00000100,         // Keep TCP socket open
241     searchUpLocalDomainTree = 0x00000200,   // search up local domain tree
242     shutOffHostAliases = 0x00001000,        // shuts off HOSTALIASES feature
243     rotateNSListAfterEachQuery = 0x00004000, // rotate ns list after each query
244     noCheckName =  0x00008000,
245     keepTSig = 0x00010000,
246     blast = 0x00020000,
247     useEDNS0 = 0x00100000,                  // Use EDNS0.
248     singleKUp = 0x00200000,                 // one outstanding request at a time
249     singleKUpReop = 0x00400000,             //  -"-, but open new socket for each request
250     useDNSSEC =  0x00800000,                // use DNSSEC using OK bit in OPT
251     notLDQuery = 0x01000000,                //  Do not look up unqualified name as a TLD
252     noReload = 0x02000000,                  // No automatic configuration reload
253     trustAD = 0x04000000,                   // Request AD bit, keep it in responses
254     default_ = ResolverOption.recurse | ResolverOption.defaultDomainName | ResolverOption.searchUpLocalDomainTree,
255 }
256 
257 /*
258  * Resolver "pfcode" values.  Used by dig.
259  */
260 enum PfCode
261 {
262  stats = 0x00000001,
263  update = 0x00000002,
264  class_ = 0x00000004,
265  cmd = 0x00000008,
266  ques = 0x00000010,
267  ans = 0x00000020,
268  auth = 0x00000040,
269  add = 0x00000080,
270  head1 = 0x00000100,
271  head2 = 0x00000200,
272  ttlID = 0x00000400,
273  headx = 0x00000800,
274  query = 0x00001000,
275  reply = 0x00002000,
276  init = 0x00004000,
277 /*          0x00008000  */
278 }
279 
280 /* Things involving an internal (static) resolver context. */
281 //__res_state* __res_state(); //
282 
283 void        fp_nquery (const(char)* *, int, FILE *);
284 void        fp_query (const(char)* *, FILE *);
285 const(char* )*  hostalias (const(char* )* );
286 void        p_query (const(char)* *);
287 void        res_close();
288 int     res_init();
289 int     res_isourserver (const sockaddr_in *);
290 int     res_mkquery (int, const(char* )* , int, int, const(char)* *, int, const(char)* *, char* *, int);
291 //int res_query(char*, int, int, char*, int);
292 int __res_query(char*, int, int, char*, int);
293 alias res_query = __res_query;
294 //extern(C) int     res_query (const(char)* , int, int, char*, int) ;
295 int     res_querydomain (const(char* )* , const(char* )* , int, int, char* *, int);
296 int     res_search (const(char* )* , int, int, char* *, int) ;
297 int     res_send (const(char)* *, int, char* *, int) ;
298 
299 
300 int     res_hnok (const(char* )* );
301 int     res_ownok (const(char* )* );
302 int     res_mailok (const(char* )* );
303 int     res_dnok (const(char* )* );
304 int     sym_ston (const res_sym *, const(char* )* , int *);
305 const(char* )*  sym_ntos (const res_sym *, int, int *);
306 const(char* )*  sym_ntop (const res_sym *, int, int *);
307 int     b64_ntop (const(char)* *, size_t, char* *, size_t);
308 int     b64_pton (char**, char**, size_t);
309 int     loc_aton (const(char* )* __ascii, char** __binary);
310 const(char* )*  loc_ntoa (const(char)* *__binary, char* *__ascii);
311 int     dn_skipname (const(char)* *, const(char)* *) ;
312 void putlong(uint, char**);
313 void putshort (ushort, char* *);
314 const(char* )*  p_class (int);
315 const(char* )*  p_time (ushort);
316 const(char* )*  p_type (int);
317 const(char* )*  p_rcode (int);
318 const(char)** p_cdnname (const(char)* *, const(char)* *, int, FILE *);
319 const(char)** p_cdname (const(char)* *, const(char)* *, FILE *);
320 const(char)** p_fqnname (const(char)* *__cp, const(char)* *__msg, int, char* *, int);
321 const(char)** p_fqname (const(char)* *, const(char)* *, FILE *);
322 const(char)** p_option (ulong __option);
323 int     dn_count_labels (const(char* )* );
324 int     dn_comp (const(char* )* , char* *, int, char* **, char* **);
325 // int  dn_expand(const(char)* msg, const(char)* eomorig, const(char)* comp_dn, char* exp_dn, int length);
326 //int   dn_expand(char* msg, char* eomorig, char* comp_dn, char* exp_dn, int length);
327 int __dn_expand(char* msg, char* eomorig, char* comp_dn, char* exp_dn, int length);
328 alias dn_expand = __dn_expand;
329 uint    res_randomid();
330 int     res_nameinquery (const(char* )* , int, int, const(char)* *, const(char)* *);
331 int     res_queriesmatch (const(char)* *, const(char)* *, const(char)* *, const(char)* *);
332 /* Things involving a resolver context. */
333 int     res_ninit (res_state);
334 void        fp_resstat (const res_state, FILE *);
335 const(char* )*  res_hostalias (const res_state, const(char* )* , char* *, size_t);
336 int res_nquery (res_state, const(char* )* , int, int, char* *, int);
337 int res_nsearch (res_state, const(char* )* , int, int, char* *, int);
338 int res_nquerydomain (res_state, const(char* )* , const(char* )* , int, int, char* *, int);
339 int res_nmkquery (res_state, int, const(char* )* , int, int, const(char)* *, int, const(char)* *, char* *, int);
340 int res_nsend (res_state, const(char)* *, int, char* *, int);
341 void    res_nclose (res_state);
342 
343 // #include <sys/types.h>
344 // #include <netinet/in.h>
345 
346 /* res_state: the global state used by the resolver stub.  */
347 enum MAXNS          =3; /* max # name servers we'll track */
348 enum MAXDFLSRCH     =3; /* # default domain levels to try */
349 enum MAXDNSRCH  =   6;  /* max # domains in search path */
350 enum MAXRESOLVSORT=     10; /* number of net to sort on */
351 
352 struct res_state
353 {
354     import std.bitmanip : bitfields;
355     int retrans;        /* retransmition time interval */
356     int retry;          /* number of times to retransmit */
357     ulong options;      /* option flags - see below. */
358     int nscount;        /* number of name servers */
359     sockaddr_in[MAXNS] nsaddr_list; /* address of name server */
360     ushort id;      /* current message id */
361     /* 2 byte hole here.  */
362     char*[MAXDNSRCH+1] dnsrch;  /* components of domain to search */
363     char[256]   defdname;       /* default domain (deprecated) */
364     ulong pfcode;       /* RES_PRF_ flags - see below. */
365 
366     mixin(bitfields!(
367                 uint, "ndots", 4,       // threshold for initial abs. query
368                 uint, "nsort", 4,       // number of elements in sort_list[]
369                 uint,"ipv6_unavail",1, // connecting to IPv6 server failed
370                 uint, "unused",23,
371     ));
372     struct SortListEntry
373     {
374         in_addr addr;
375         uint mask;
376     }
377     SortListEntry [MAXRESOLVSORT] sort_list;
378     /* 4 byte hole here on 64-bit architectures.  */
379     void * __glibc_unused_qhook;
380     void * __glibc_unused_rhook;
381     int res_h_errno;        /* last one set for this context */
382     int _vcsock;        /* PRIVATE: for res_send VC i/o */
383     uint _flags;        /* PRIVATE: see below */
384     /* 4 byte hole here on 64-bit architectures.  */
385     union U
386     {
387         char[52] pad;   /* On an i386 this means 512b total. */
388         struct Ext
389         {
390             ushort nscount;
391             ushort[MAXNS] nsmap;
392             int[MAXNS] nssocks;
393             ushort nscount6;
394             ushort nsinit;
395             sockaddr_in6*[MAXNS] nsaddrs;
396             uint[2] __glibc_reserved;
397         }
398        Ext _ext;
399     }
400    U _u;
401 };
402 
403 /*
404  * Copyright (c) 1983, 1989, 1993
405  *    The Regents of the University of California.  All rights reserved.
406  *
407  * Redistribution and use in source and binary forms, with or without
408  * modification, are permitted provided that the following conditions
409  * are met:
410  * 1. Redistributions of source code must retain the above copyright
411  *    notice, this list of conditions and the following disclaimer.
412  * 2. Redistributions in binary form must reproduce the above copyright
413  *    notice, this list of conditions and the following disclaimer in the
414  *    documentation and/or other materials provided with the distribution.
415  * 4. Neither the name of the University nor the names of its contributors
416  *    may be used to endorse or promote products derived from this software
417  *    without specific prior written permission.
418  *
419  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
420  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
421  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
422  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
423  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
424  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
425  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
426  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
427  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
428  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
429  * SUCH DAMAGE.
430  */
431 
432 /*
433  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
434  * Copyright (c) 1996-1999 by Internet Software Consortium.
435  *
436  * Permission to use, copy, modify, and distribute this software for any
437  * purpose with or without fee is hereby granted, provided that the above
438  * copyright notice and this permission notice appear in all copies.
439  *
440  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
441  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
442  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
443  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
444  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
445  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
446  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
447  * SOFTWARE.
448  */
449 
450 /+
451 #include <sys/param.h>
452 #include <sys/types.h>
453 #include <stdint.h>
454 +/
455 /*
456  * Define constants based on RFC 883, RFC 1034, RFC 1035
457  */
458 enum NS_PACKETSZ    =512;   /*%< default UDP packet size */
459 enum NS_MAXDNAME    =1025;  /*%< maximum domain name */
460 enum NS_MAXMSG  =65535;     // %< maximum message size
461 enum NS_MAXCDNAME   =255;   // %< maximum compressed domain name */
462 enum NS_MAXLABEL    =63;        //  %< maximum length of domain label */
463 enum NS_HFIXEDSZ    =12;        //  /*%< #/bytes of fixed data in header */
464 enum NS_QFIXEDSZ    =4;     //  /*%< #/bytes of fixed data in query */
465 enum NS_RRFIXEDSZ   =10;    /*%< #/bytes of fixed data in r record */
466 enum NS_INT32SZ =4; /*%< #/bytes of data in a uint32_t */
467 enum NS_INT16SZ =2; /*%< #/bytes of data in a uint16_t */
468 enum NS_INT8SZ  =1; /*%< #/bytes of data in a uint8_t */
469 enum NS_INADDRSZ    =4; /*%< IPv4 T_A */
470 enum NS_IN6ADDRSZ   =16;    /*%< IPv6 T_AAAA */
471 enum NS_CMPRSFLGS   =0xc0;  /*%< Flag bits indicating name compression. */
472 enum NS_DEFAULTPORT =53;    /*%< For both TCP and UDP. */
473 /*
474  * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord()
475  * in synch with it.
476  */
477 enum NSSect
478 {
479     qd = 0,     /*%< Query: Question. */
480     zn = 0,     /*%< Update: Zone. */
481     an = 1,     /*%< Query: Answer. */
482     pr = 1,     /*%< Update: Prerequisites. */
483     ns = 2,     /*%< Query: Name servers. */
484     ud = 2,     /*%< Update: Update. */
485     ar = 3,     /*%< Query|Update: Additional records. */
486     max = 4,
487 }
488 
489 alias ns_sect = NSSect;
490 /*%
491  * This is a message handle.  It is caller allocated and has no dynamic data.
492  * This structure is intended to be opaque to all but ns_parse.c, thus the
493  * leading _'s on the member names.  Use the accessor functions, not the _'s.
494  */
495 struct ns_msg
496 {
497     const(char)* _msg;
498     const(char)* _eom;
499     ushort _id;
500     ushort _flags;
501     ushort[ns_s_max] _counts;
502     const(char)[ns_s_max]* _sections;
503     ns_sect _sect;
504     int _rrnum;
505     const(char) *_msg_ptr;
506 }
507 
508 /* Private data structure - do not use from outside library. */
509 //struct _ns_flagdata {  int mask, shift;  };
510 //extern const struct _ns_flagdata _ns_flagdata[];
511 
512 /* Accessor macros - this is part of the public interface. */
513 auto ns_msg_id(ns_msg handle)
514 {
515     return handle._id;
516 }
517 
518 auto ns_msg_base(ns_msg handle)
519 {
520     return  handle._msg;
521 }
522 
523 auto ns_msg_end(ns_msg handle)
524 {
525     return handle._eom;
526 }
527 
528 auto ns_msg_size(ns_msg handle)
529 {
530     return handle._eom - handle._msg;
531 }
532 
533 auto ns_msg_count(Section)(ns_msg handle, Section section)
534 {
535     return handle._counts[section];
536 }
537 
538 /*%
539  * This is a parsed record.  It is caller allocated and has no dynamic data.
540  */
541 struct ns_rr
542 {
543     char[NS_MAXDNAME] name;
544     ushort type;
545     ushort rr_class;
546     uint ttl;
547     ushort rdlength;
548     const(char) *   rdata;
549 }
550 
551 /* Accessor macros - this is part of the public interface. */
552 string ns_rr_name(ns_rr rr)
553 {
554     return (rr.name[0] != '\0') ? rr.name.ptr.fromStringz.idup: ".";
555 }
556 
557 auto ns_rr_type(ns_rr rr)
558 {
559     return cast(NSType)rr.type;
560 }
561 
562 auto ns_rr_class(ns_rr rr)
563 {
564     return cast(NSClass) rr.rr_class;
565 }
566 
567 auto ns_rr_ttl(ns_rr rr)
568 {
569     return rr.ttl;
570 }
571 
572 auto ns_rr_rdlen(ns_rr rr)
573 {
574     return rr.rdlength;
575 }
576 
577 char[] ns_rr_rdata(ns_rr rr)
578 {
579     return rr.rdata[0.. rr.rdlength].dup;
580 }
581 
582 /*%
583  * These don't have to be in the same order as in the packet flags word,
584  * and they can even overlap in some cases, but they will need to be kept
585  * in synch with ns_parse.c:ns_flagdata[].
586  */
587 enum FlagCode
588 {
589     qr,     /*%< Question/Response. */
590     opcode,     /*%< Operation code. */
591     aa,     /*%< Authoritative Answer. */
592     tc,     /*%< Truncation occurred. */
593     rd,     /*%< Recursion Desired. */
594     ra,     /*%< Recursion Available. */
595     z,          /*%< MBZ. */
596     ad,     /*%< Authentic Data (DNSSEC). */
597     cd,     /*%< Checking Disabled (DNSSEC). */
598     rcode,      /*%< Response code. */
599     max
600 }
601 
602 /*%
603  * Currently defined opcodes.
604  */
605 enum OpCode
606 {
607     query = 0,      /*%< Standard query. */
608     iquery = 1, /*%< Inverse query (deprecated/unsupported). */
609     status = 2, /*%< Name server status query (unsupported). */
610                 /* Opcode 3 is undefined/reserved. */
611     notify = 4, /*%< Zone change notification. */
612     update = 5, /*%< Zone update message. */
613     max = 6
614 }
615 
616 /*%
617  * Currently defined response codes.
618  */
619 enum ResponseCode
620 {
621     noerror = 0,    /*%< No error occurred. */
622     formerr = 1,    /*%< Format error. */
623     servfail = 2,   /*%< Server failure. */
624     nxdomain = 3,   /*%< Name error. */
625     notimpl = 4,    /*%< Unimplemented. */
626     refused = 5,    /*%< Operation refused. */
627     /* these are for BIND_UPDATE */
628     yxdomain = 6,   /*%< Name exists */
629     yxrrset = 7,    /*%< RRset exists */
630     nxrrset = 8,    /*%< RRset does not exist */
631     notauth = 9,    /*%< Not authoritative for zone */
632     notzone = 10,   /*%< Zone of record different from zone section */
633     _max = 11,
634     /* The following are EDNS extended rcodes */
635     badvers = 16,
636     /* The following are TSIG errors */
637     badsig = 16,
638     badkey = 17,
639     badtime = 18
640 }
641 
642 /* BIND_UPDATE */
643 enum BindUpdateOperation
644 {
645     delete_ = 0,
646     add = 1,
647     max = 2
648 }
649 
650 /*%
651  * This structure is used for TSIG authenticated messages
652  */
653 struct ns_tsig_key
654 {
655         char[NS_MAXDNAME] name;
656         char[NS_MAXDNAME] alg;
657         char *data;
658         int len;
659 }
660 
661 /*%
662  * This structure is used for TSIG authenticated TCP messages
663  */
664 struct ns_tcp_tsig_state
665 {
666     int counter;
667     dst_key *key;
668     void *ctx;
669     char[NS_PACKETSZ] sig;
670     int siglen;
671 }
672 
673 enum NS_TSIG_FUDGE = 300;
674 enum NS_TSIG_TCP_COUNT = 100;
675 enum NS_TSIG_ALG_HMAC_MD5 = "HMAC-MD5.SIG-ALG.REG.INT";
676 
677 enum NS_TSIG_ERROR_NO_TSIG = -10;
678 enum NS_TSIG_ERROR_NO_SPACE = -11;
679 enum NS_TSIG_ERROR_FORMERR = -12;
680 
681 /*%
682  * Currently defined type values for resources and queries.
683  */
684 enum NSType
685 {
686     invalid = 0,
687     a = 1,
688     ns = 2,
689     md = 3,
690     mf = 4,
691     cname = 5,
692     soa = 6,
693     mb = 7,
694     mg = 8,
695     mr = 9,
696     null_ = 10,
697     wks = 11,
698     ptr = 12,
699     hinfo = 13,
700     minfo = 14,
701     mx = 15,
702     txt = 16,
703     rp = 17,
704     afsdb = 18,
705     x25 = 19,
706     isdn = 20,
707     rt = 21,
708     nsap = 22,
709     nsap_ptr = 23,
710     sig = 24,
711     key = 25,
712     px = 26,
713     gpos = 27,
714     aaaa = 28,
715     loc = 29,
716     nxt = 30,
717     eid = 31,
718     nimloc = 32,
719     srv = 33,
720     atma = 34,
721     naptr = 35,
722     kx = 36,
723     cert = 37,
724     a6 = 38,
725     dname = 39,
726     sink = 40,
727     opt = 41,
728     apl = 42,
729     ds = 43,
730     sshfp = 44,
731     ipseckey = 45,
732     rrsig = 46,
733     nsec = 47,
734     dnskey = 48,
735     dhcid = 49,
736     nsec3 = 50,
737     nsec3param = 51,
738     tlsa = 52,
739     smimea = 53,
740     hip = 55,
741     ninfo = 56,
742     rkey = 57,
743     talink = 58,
744     cds = 59,
745     cdnskey = 60,
746     openpgpkey = 61,
747     csync = 62,
748     spf = 99,
749     uinfo = 100,
750     uid = 101,
751     gid = 102,
752     unspec = 103,
753     nid = 104,
754     l32 = 105,
755     l64 = 106,
756     lp = 107,
757     eui48 = 108,
758     eui64 = 109,
759     tkey = 249,
760     tsig = 250,
761     ixfr = 251,
762     axfr = 252,
763     mailb = 253,
764     maila = 254,
765     any = 255,
766     uri = 256,
767     caa = 257,
768     avc = 258,
769     ta = 32768,
770     dlv = 32769,
771 
772     max = 65536
773  }
774 
775 /*%
776  * Values for class field
777  */
778 enum NSClass
779 {
780     invalid = 0,    /*%< Cookie. */
781     in_ = 1,        /*%< Internet. */
782     ns_c_2 = 2,     /*%< unallocated/unsupported. */
783     chaos = 3,      /*%< MIT Chaos-net. */
784     hesiod  = 4,        /*%< MIT Hesiod. */
785     /* Query class values which do not appear in resource records */
786     none = 254, /*%< for prereq. sections in update requests */
787     any = 255,      /*%< Wildcard match. */
788     max = 65536
789 }
790 
791 /* Certificate type values in CERT resource records.  */
792 enum NSCertType
793 {
794     pkix = 1,   /*%< PKIX (X.509v3) */
795     spki = 2,   /*%< SPKI */
796     pgp  = 3,   /*%< PGP */
797     url  = 253, /*%< URL private type */
798     oid  = 254  /*%< OID private type */
799 }
800 
801 /*%
802  * EDNS0 extended flags and option codes, host order.
803  */
804 enum NS_OPT_DNSSEC_OK        =0x8000U;
805 enum NS_OPT_NSID        =3;
806 /+
807 
808 /*%
809  * Inline versions of get/put short/long.  Pointer is advanced.
810  */
811 enum NS_GET16(s, cp) do { \
812     const(char) *t_cp = (const(char) *)(cp); \
813     (s) = ((uint16_t)t_cp[0] << 8) \
814         | ((uint16_t)t_cp[1]) \
815         ; \
816     (cp) += NS_INT16SZ; \
817 } while (0)
818 
819 enum NS_GET32(l, cp) do { \
820     const(char) *t_cp = (const(char) *)(cp); \
821     (l) = ((uint32_t)t_cp[0] << 24) \
822         | ((uint32_t)t_cp[1] << 16) \
823         | ((uint32_t)t_cp[2] << 8) \
824         | ((uint32_t)t_cp[3]) \
825         ; \
826     (cp) += NS_INT32SZ; \
827 } while (0)
828 
829 enum NS_PUT16(s, cp) do { \
830     uint16_t t_s = (uint16_t)(s); \
831     char *t_cp = (char *)(cp); \
832     *t_cp++ = t_s >> 8; \
833     *t_cp   = t_s; \
834     (cp) += NS_INT16SZ; \
835 } while (0)
836 
837 enum NS_PUT32(l, cp) do { \
838     uint32_t t_l = (uint32_t)(l); \
839     char *t_cp = (char *)(cp); \
840     *t_cp++ = t_l >> 24; \
841     *t_cp++ = t_l >> 16; \
842     *t_cp++ = t_l >> 8; \
843     *t_cp   = t_l; \
844     (cp) += NS_INT32SZ; \
845 } while (0)
846 +/
847 int     ns_msg_getflag (ns_msg, int);
848 uint    ns_get16 (const(char) *);
849 ulong   ns_get32 (const(char) *);
850 void        ns_put16 (uint, char *);
851 void        ns_put32 (ulong, char *);
852 int     ns_initparse (const(char) *, int, ns_msg *);
853 int     ns_skiprr (const(char) *, const(char) *, ns_sect, int);
854 int     ns_parserr (ns_msg*, ns_sect, int, ns_rr *);
855 int     ns_sprintrr (const ns_msg *, const ns_rr *, const(char) *, const(char) *, char *, size_t)
856     ;
857 int     ns_sprintrrf (const(char) *, size_t, const(char) *, NSClass, NSType, ulong, const(char) *, size_t, const(char) *, const(char) *, char *, size_t);
858 int     ns_format_ttl (ulong, char *, size_t);
859 int     ns_parse_ttl (const(char) *, ulong *);
860 uint32_t    ns_datetosecs (const(char) *, int *);
861 int     ns_name_ntol (const(char) *, char *, size_t)
862     ;
863 int     ns_name_ntop (const(char) *, char *, size_t);
864 int     ns_name_pton (const(char) *, char *, size_t);
865 int     ns_name_unpack (const(char) *, const(char) *,
866                 const(char) *, char *, size_t)
867     ;
868 int     ns_name_pack (const(char) *, char *, int,
869                   const(char) **, const(char) **)
870     ;
871 int     ns_name_uncompress (const(char) *,
872                     const(char) *,
873                     const(char) *,
874                     char *, size_t);
875 int     ns_name_compress (const(char) *, char *, size_t,
876                   const(char) **,
877                   const(char) **);
878 int     ns_name_skip (const(char) **, const(char) *)
879     ;
880 void        ns_name_rollback (const(char) *,
881                   const(char) **,
882                   const(char) **);
883 int     ns_samedomain (const(char) *, const(char) *);
884 int     ns_subdomain (const(char) *, const(char) *);
885 int     ns_makecanon (const(char) *, char *, size_t);
886 int     ns_samename (const(char) *, const(char) *);
887 //__END_DECLS
888 
889 // #include <arpa/nameser_compat.h>
890 +/