1 /*
2 ** Copyright 1998 - 2011 Double Precision, Inc.
3 ** See COPYING for distribution information.
4 */
5 
6 #ifndef	rfc1035_h
7 #define	rfc1035_h
8 
9 
10 
11 #if	HAVE_CONFIG_H
12 #include "rfc1035/config.h"
13 #endif
14 
15 #include	"random128/random128.h"
16 #include	"md5/md5.h"
17 
18 #include	<stdio.h>
19 #include	<sys/types.h>
20 #include	<sys/socket.h>
21 #if HAVE_NETINET_IN_H
22 #include	<netinet/in.h>
23 #endif
24 #if HAVE_STDINT_H
25 #include	<stdint.h>
26 #endif
27 #ifdef  __cplusplus
28 extern "C" {
29 #endif
30 
31 #if RFC1035_IPV6
32 typedef struct in6_addr	RFC1035_ADDR;
33 typedef struct sockaddr_in6 RFC1035_SOCKADDR;
34 typedef struct sockaddr_storage RFC1035_NETADDR;
35 #define RFC1035_ADDRANY		in6addr_any
36 #else
37 typedef	struct in_addr	RFC1035_ADDR;
38 typedef struct sockaddr_in	RFC1035_SOCKADDR;
39 typedef struct sockaddr		RFC1035_NETADDR;
40 
41 extern struct in_addr rfc1035_addr_any;
42 #define RFC1035_ADDRANY		rfc1035_addr_any
43 #endif
44 
45 #define RFC1035_TYPE_A		1
46 #define RFC1035_TYPE_NS		2
47 #define RFC1035_TYPE_MD		3
48 #define RFC1035_TYPE_MF		4
49 #define RFC1035_TYPE_CNAME	5
50 #define RFC1035_TYPE_SOA	6
51 #define RFC1035_TYPE_MB		7
52 #define RFC1035_TYPE_MG		8
53 #define RFC1035_TYPE_MR		9
54 #define RFC1035_TYPE_NULL	10
55 #define RFC1035_TYPE_WKS	11
56 #define RFC1035_TYPE_PTR	12
57 #define RFC1035_TYPE_HINFO	13
58 #define RFC1035_TYPE_MINFO	14
59 #define RFC1035_TYPE_MX		15
60 #define RFC1035_TYPE_TXT	16
61 
62 #define	RFC1035_TYPE_AAAA	28	/* RFC 1886. Even if we don't have
63 					IPv6 */
64 
65 #define RFC1035_TYPE_OPT	41
66 #define RFC1035_TYPE_RRSIG	46
67 
68 #define	RFC1035_TYPE_AXFR	252
69 #define	RFC1035_TYPE_MAILB	253
70 #define	RFC1035_TYPE_MAILA	254
71 #define	RFC1035_TYPE_ANY	255
72 
73 void rfc1035_type_itostr(int, void (*)(const char *, void *), void *);
74 int rfc1035_type_strtoi(const char *);
75 
76 #define	RFC1035_CLASS_IN	1
77 #define	RFC1035_CLASS_CSNET	2
78 #define	RFC1035_CLASS_CHAOS	3
79 #define	RFC1035_CLASS_HESIOD	4
80 #define	RFC1035_CLASS_ANY	255
81 
82 const char *rfc1035_class_itostr(int);
83 int rfc1035_class_strtoi(const char *);
84 
85 #define	RFC1035_OPCODE_QUERY	0
86 #define	RFC1035_OPCODE_IQUERY	1
87 #define	RFC1035_OPCODE_STATUS	2
88 
89 const char *rfc1035_opcode_itostr(int);
90 int rfc1035_opcode_strtoi(const char *);
91 
92 #define RFC1035_RCODE_NOERROR	0
93 #define	RFC1035_RCODE_FORMAT	1
94 #define	RFC1035_RCODE_SERVFAIL	2
95 #define	RFC1035_RCODE_NXDOMAIN	3
96 #define	RFC1035_RCODE_UNIMPLEMENTED	4
97 #define	RFC1035_RCODE_REFUSED	5
98 
99 const char *rfc1035_rcode_itostr(int);
100 int rfc1035_rcode_strtoi(const char *);
101 
102 struct rfc1035_query {
103 	const char *name;
104 	unsigned qtype, qclass;
105 	} ;
106 
107 struct rfc1035_reply;	/* Defined below */
108 struct rfc1035_rr;	/* Defined below */
109 
110 /*
111 ** The init family of functions perform various initializations.  Calling them
112 ** is optional, as librfc1035.a will use defaults if not specified.
113 */
114 
115 #define	RFC1035_MAXNS	10
116 #define	RFC1035_DEFAULT_INITIAL_TIMEOUT	5
117 #define	RFC1035_DEFAULT_MAXIMUM_BACKOFF	3
118 
119 		/* Resolver state */
120 struct rfc1035_res {
121 
122 	RFC1035_ADDR nameservers[RFC1035_MAXNS];
123 	int rfc1035_nnameservers;
124 
125 	char *rfc1035_defaultdomain;
126 	int norecursive; /* Do not set the recursive flag, for specialized apps */
127 	int dnssec_payload_size; /* Enable dnssec requests */
128 
129 	unsigned rfc1035_good_ns;
130 	unsigned rfc1035_timeout_initial;	/* Initial timeout */
131 	unsigned rfc1035_timeout_backoff;	/* Maximum exponential backoff */
132 
133 	random128binbuf randseed;
134 	MD5_DIGEST	randbuf;
135 	unsigned randptr;
136 	} ;
137 
138 extern struct rfc1035_res rfc1035_default_resolver;
139 
140 void rfc1035_init_timeout(struct rfc1035_res *, unsigned, unsigned);
141 					/*
142 					** Specify timeout in seconds,
143 					** and maximum exponential backoff.
144 					*/
145 void rfc1035_init_ns(struct rfc1035_res *, const RFC1035_ADDR *, unsigned);
146 		/* Specify nameservers to query (max 10) */
147 
148 void rfc1035_init_norecursive(struct rfc1035_res *, int);
149 	/* Set the no-recursive flag, if you don't want the NS to do recursive queries on your behalf */
150 
151 void rfc1035_init_dnssec_enable(struct rfc1035_res *, int);
152 	/* Enable/disable dnssec/edns0 */
153 
154 void rfc1035_init_edns_payload(struct rfc1035_res *, int);
155 	/* Set edns0 payload size */
156 
157 void rfc1035_init_resolv(struct rfc1035_res *);
158 	/* Read /etc/resolv.conf for nameservers */
159 
160 void rfc1035_destroy_resolv(struct rfc1035_res *);
161 	/* Destroy the resolver object */
162 
163 	/*
164 	** Most people will only need to call rfc1035_resolve or
165 	** rfc1035_resolve_cname.  The return value from _resolve functions
166 	** should be interpreted as follows:
167 	**     NULL - internal failure (treat it as a soft DNS error)
168 	**     ptr->rcode = RFC1035_RCODE_NOERROR - success
169 	**     ptr->rcode = RFC1035_RCODE_NXDOMAIN - hard DNS error
170 	**     ptr->rcode = RFC1035_RCODE_TEMPFAIL - soft DNS error
171 	**     ptr->rcode = any other value - log abnormal result,
172 	**                  handle as soft DNS error
173 	*/
174 
175 struct rfc1035_reply *rfc1035_resolve(
176 	struct rfc1035_res *,	/* Pointer to a resolver structure */
177 	int,		/* Opcode, see above. */
178 	const char *,	/* Query name */
179 	unsigned,	/* Query type, see above. */
180 	unsigned);	/* Query class, see above. */
181 
182 	/*
183 	** Multiple queries.  Most servers don't support this.
184 	*/
185 
186 struct rfc1035_reply *rfc1035_resolve_multiple(
187 	struct rfc1035_res *,	/* Pointer to a resolver structure */
188 	int,	/* opcode */
189 	const struct rfc1035_query *,	/* Array of queries */
190 	unsigned);			/* Array size */
191 
192 /*
193 ** rfc1035_resolve_cname is like _resolve, but starts with the default
194 ** servers, and automatically reissues the query if the received response
195 ** is a CNAME.  If successful, it returns an INDEX into the allrrs array
196 ** containing the first answer.  To get the next answers, call
197 ** rfc1035_replysearch_all with return value+1.  If not succesfull, -1
198 ** is returned.
199 **
200 ** Note - if the returned index points to a CNAME, this is because a CNAME
201 ** pointed to another CNAME -- it's BAD!
202 **
203 ** It takes a POINTER to the 'id' counter, which is incremented if a
204 ** second query needs to be issued.
205 **
206 ** If takes a POINTER to the rfc1035_reply structure, which will be either
207 ** null on exit, or point to the reply received.  The pointer MAY be not null
208 ** even if the return value is -1.
209 **
210 ** Suggested logic:
211 **    Return value >= 0, succesfull query.
212 **    Return value <= -1, ptr is not null, and rcode = RFC1035_RCODE_NXDOMAIN,
213 **        hard DNS error.
214 **    Return value <= -1, ptr is not null, and rcode = RFC1035_RCODE_TEMPFAIL,
215 **        soft DNS error.
216 **    Other situations: log the abnormal result, handle as soft DNS error.
217 */
218 
219 #define	RFC1035_ERR_CNAME_RECURSIVE	-2
220 	/* Specific error code for a recursive CNAME record - prohibited */
221 
222 int rfc1035_resolve_cname(
223 		struct rfc1035_res *,	/* Pointer to a resolver structure */
224 		char *,			/* RFC1035_MAXNAMESIZE buffer with
225 					** the name to query */
226 		unsigned,		/* Query type */
227 		unsigned,		/* Query class */
228 		struct rfc1035_reply **, /* Ptr set to reply received */
229 		int); /* Extended flags: */
230 
231 #define RFC1035_X_RANDOMIZE 1    /* Randomize query results */
232 
233 /*
234 ** rfc1035_resolve_cname_multiple is a version of rfc1035_resolve_cname
235 ** that accepts an array of qtypes, and issues a query for each qtype.
236 **
237 ** qtypes points to a 0-terminated list of RRs.
238 */
239 int rfc1035_resolve_cname_multiple(struct rfc1035_res *res,
240 				   char *namebuf,
241 				   /* RFC1035_MAXNAMESIZE buffer with
242 				   ** the name to query */
243 				   unsigned char *qtypes,
244 				   unsigned qclass,
245 				   struct rfc1035_reply **ptr,
246 				   int x_flags);
247 
248 
249 	/*
250 	** Always call replyfree when done.
251 	*/
252 
253 void rfc1035_replyfree(struct rfc1035_reply *);
254 
255 	/*
256 	** !!!ALL!!! the const char * pointers in rfc1035_reply are NOT
257 	** standard C strings, but DNS-compressed strings.  Call
258 	** replyhostname to translate those to C strings.
259 	*/
260 
261 const char *rfc1035_replyhostname(
262 	const struct rfc1035_reply *,	/* The reply */
263 	const char *,	/* The const char ptr */
264 
265 	char *);	/* Buffer where to put hostname.  All strings are
266 			** guaranteed to fit into RFC1035_MAXNAMESIZE+1 byte
267 			** buffer.
268 			** replyhostname returns this pointer.
269 			*/
270 
271 /* Some value added code, look up A and PTR records. */
272 
273 int rfc1035_a(struct rfc1035_res *,
274 	const char *,		/* Host name */
275 	RFC1035_ADDR **,		/* We allocate array of IP addresses */
276 	unsigned *);			/* We return # of IP addresses here */
277 
278 int rfc1035_ptr(struct rfc1035_res *,
279 	const RFC1035_ADDR *,	/* Query PTR for this address */
280 	char *);		/* Result - RFC1035_MAXNAMESIZE+1 buf */
281 
282 int rfc1035_ptr_x(struct rfc1035_res *res, const RFC1035_ADDR *addr,
283 		  void (*cb_func)(const char *, void *),
284 		  void *cb_arg); /* Invoke a callback function instead
285 				 ** (multiple callbacks possible)
286 				 */
287 
288 /* ---------------------- */
289 
290 	/* Replyuncompress is a lower-level function taking a pointer to
291 	** the const char *.  When it returns, the const char * is advanced
292 	** past the end of the compressed string in the DNS data.
293 	** replyuncompress returns its third argument, or NULL if there was
294 	** an error. */
295 
296 const char *rfc1035_replyuncompress(const char **,
297 	const struct rfc1035_reply *, char *);
298 
299 #define	RFC1035_MAXNAMESIZE	255
300 
301 
302 	/*
303 	** Compare two hostnames.  Return 0 if they match, non-zero if they
304 	** don't.
305 	*/
306 
307 int rfc1035_hostnamecmp(const char *, const char *);
308 
309 	/*
310 	** After we receive a reply, search for the answer there.  Returns
311 	** an index in the respective section, or -1 if not found.
312 	** If we find a CNAME, we return a pointer to it instead, so make
313 	** sure to check for that!
314 	*/
315 
316 int rfc1035_replysearch_an(
317 	const struct rfc1035_res *,	/* The resolver */
318 	const struct rfc1035_reply *,	/* The reply */
319 	const char *, 			/* Hostname to search */
320 	unsigned,			/* Type */
321 	unsigned,			/* Class */
322 	int);				/* Starting position, 1st time use 0 */
323 
324 int rfc1035_replysearch_ns(
325 	const struct rfc1035_res *,	/* The resolver */
326 	const struct rfc1035_reply *,	/* The reply */
327 	const char *, 			/* Hostname to search */
328 	unsigned,			/* Type */
329 	unsigned,			/* Class */
330 	int);				/* Starting position, 1st time use 0 */
331 
332 int rfc1035_replysearch_all(
333 	const struct rfc1035_res *,	/* The resolver */
334 	const struct rfc1035_reply *,	/* The reply */
335 	const char *, 			/* Hostname to search */
336 	unsigned,			/* Type */
337 	unsigned,			/* Class */
338 	int);				/* Starting position, 1st time use 0 */
339 
340 /*
341 ** Low level functions follow.
342 */
343 
344 	/*
345 	** rfc1035_mkquery() constructs a query to be sent.  The query is
346 	** composed by REPEATEDLY running the caller-provided function,
347 	** which will be called REPEATEDLY to build the query, part by part.
348 	*/
349 
350 int rfc1035_mkquery(struct rfc1035_res *,	/* resolver structure */
351 			unsigned,	/* opcode */
352 
353 #define	RFC1035_RESOLVE_RECURSIVE 1	/* Ask nameserver to do the recursion */
354 
355 			const struct rfc1035_query *,	/* questions */
356 			unsigned,	/* Number of questions */
357 			void (*)(const char *, unsigned, void *),
358 					/* Function - called repetitively
359 					** to build the query */
360 			void *);	/* Third arg to function */
361 
362 /**************************************************************************/
363 /* Low level input/output functions.  Most people won't need to use these */
364 /**************************************************************************/
365 
366 int rfc1035_open_udp(int *af);		/* Create a UDP socket */
367 
368 int rfc1035_send_udp(int,	/* File descriptor from rfc1035_open */
369 		const struct sockaddr *, int, /* Send to this name server */
370 		const char *,	/* The query */
371 		unsigned);	/* Query length */
372 	/*
373 	** Returns 0, or non-zero if failed.
374 	*/
375 
376 int rfc1035_wait_reply(int,	/* File descriptor from rfc1035_open */
377 	unsigned);	/* Number of seconds to wait, use 0 for default */
378 	/* Returns 0 when reply is waiting, non-0 if timeout expired */
379 
380 int rfc1035_wait_query(int,	/* File descriptor from rfc1035_open */
381 	unsigned);	/* Number of seconds to wait, use 0 for default */
382 	/* Like reply, but we select for writing */
383 
384 char *rfc1035_query_udp(struct rfc1035_res *,
385 	int,	/* file descriptor */
386 	const struct sockaddr *, int,	/* Attempt number */
387 	const char *,		/* query */
388 	unsigned,		/* query length */
389 	int *,			/* # of bytes received */
390 	unsigned);		/* # of seconds to wait for response */
391 
392 	/*
393 	** Jumbo function: sends the indicated query via UDP, waits for
394 	** a validated reply.  Returns pointer to dynamically allocated
395 	** memory with the reply.  Returns NULL if there was an error.
396 	** errno will be set to EAGAIN if the response timed out
397 	** (if the UDP stack returns an error, we fake an EAGAIN).
398 	** After getting EAGAIN, attempt number should be incremented,
399 	** and we should try again.
400 	** Fake ETIMEDOUT is returned if no more attempts are possible.
401 	*/
402 
403 int rfc1035_open_tcp(struct rfc1035_res *, const RFC1035_ADDR *);
404 				/*
405 				** Create a TCP socket for this attempt #,
406 				** returns negative for a failure, and sets
407 				** errno.
408 				*/
409 
410 	/*
411 	** Attempt to transmit the indicated query on this TCP socket.
412 	** Return 0 for successfull transmission.
413 	*/
414 
415 int rfc1035_send_tcp(int,	/* file descriptor */
416 		const char *,	/* query */
417 		unsigned);	/* query length */
418 
419 	/*
420 	** Attempt to receive a reply on this TCP socket.
421 	** Returns pointer to dynamically malloced memory, or null if error.
422 	*/
423 
424 char *rfc1035_recv_tcp(struct rfc1035_res *,
425 		int,	/* file descriptor */
426 		int *,		/* * initialized to contain msg length */
427 		unsigned);	/* # of seconds to wait for a response */
428 
429 char *rfc1035_query_tcp(struct rfc1035_res *,
430 	int,	/* file descriptor */
431 	const char *,		/* query */
432 	unsigned,		/* query length */
433 	int *,			/* * initialized to contain msg length */
434 	unsigned);		/* # of seconds to wait for response */
435 
436 /*************************************************/
437 /* Parse a raw response into a useful structure. */
438 /*************************************************/
439 
440 struct rfc1035_rr {
441 	const char *rrname;  /* NOT a null term str, a ptr into the raw resp */
442 	unsigned rrtype, rrclass;
443 	RFC1035_UINT32  ttl;
444 	unsigned rdlength;
445 	const char    *rdata;	/* Raw data, parsed record follows: */
446 
447 	union {
448 		struct {
449 			const char *hinfo_str;
450 			const char *os_str;
451 			} hinfo;
452 
453 		struct in_addr inaddr;		/* A */
454 #if RFC1035_IPV6
455 		struct in6_addr in6addr;	/* AAAA */
456 #endif
457 
458 		const char *domainname;
459 				/* CNAME, MB, MD, MF, MG, MR, NS, PTR */
460 
461 		struct {
462 			const char *rmailbx_label;
463 			const char *emailbx_label;
464 			} minfo;
465 
466 		struct {
467 			unsigned preference;
468 			const char *mx_label;
469 			} mx;
470 
471 		struct {
472 			const char *mname_label;
473 			const char *rname_label;
474 			RFC1035_UINT32 serial;
475 			RFC1035_UINT32 refresh;
476 			RFC1035_UINT32 retry;
477 			RFC1035_UINT32 expire;
478 			RFC1035_UINT32 minimum;
479 			} soa;
480 
481 		struct {
482 			RFC1035_UINT16 type_covered;
483 			unsigned char algorithm;
484 			unsigned char labels;
485 			RFC1035_UINT16 original_ttl;
486 			RFC1035_UINT32 signature_expiration;
487 			RFC1035_UINT32 signature_inception;
488 			RFC1035_UINT16 key_tag;
489 			const char *signer_name;
490 			const char *signature;
491 			RFC1035_UINT16 signature_len;
492 		} rrsig;
493 
494 		/* As are just represented by rdata/rdlength */
495 		/* TXTs are parsed directly from rdata/rdlength */
496 		/* WKS are parsed directly */
497 
498 		} rr;
499 	} ;
500 
501 struct rfc1035_reply {
502 	struct	rfc1035_reply	*next;	/* AXFRs have a linked list here */
503 
504 	const	char	*reply;	/* The raw reply, for convenience's sake */
505 	unsigned	replylen;	/* The length of the reply */
506 	char		*mallocedbuf;	/* If not NULL, dynamically allocated
507 					** memory that holds the reply.
508 					*/
509 
510 	RFC1035_NETADDR server_addr;	/* Replying server */
511 
512 	unsigned char qr;
513 	unsigned char opcode;
514 	unsigned char aa;
515 	unsigned char tc;
516 	unsigned char rd;
517 	unsigned char ra;
518 	unsigned char ad;
519 	unsigned char cd;
520 	unsigned char rcode;
521 	unsigned qdcount;
522 	unsigned ancount;
523 	unsigned nscount;
524 	unsigned arcount;
525 
526 	struct rfc1035_query *qdptr;	/* sizeof qdcount */
527 	struct rfc1035_rr *anptr;
528 	struct rfc1035_rr *nsptr;
529 	struct rfc1035_rr *arptr;
530 
531 	struct rfc1035_rr **allrrs;	/* Pointers to all RR records,
532 					** add ancount+nscount+arcount for
533 					** the size of the array */
534 	} ;
535 
536 struct rfc1035_reply *rfc1035_replyparse(const char *, unsigned);
537 void rfc1035_rr_rand_an(struct rfc1035_reply *rr);
538 void rfc1035_rr_rand_ns(struct rfc1035_reply *rr);
539 void rfc1035_rr_rand_ar(struct rfc1035_reply *rr);
540 void rfc1035_rr_rand(struct rfc1035_reply *rr);
541 
542 void rfc1035_dump(struct rfc1035_reply *, FILE *);
543 
544 const char *rfc1035_fmttime(unsigned long, char *);
545 #define	RFC1035_MAXTIMEBUFSIZE	40
546 
547 char *rfc1035_dumprrdata(struct rfc1035_reply *, struct rfc1035_rr *);
548 
549 int rfc1035_rr_gettxt(struct rfc1035_rr *,
550 		      int,
551 		      char buf[256]);
552 
553 /*
554 ** I ignore any possible bugs in the resolver functions, and roll my own,
555 ** for IPv4.
556 */
557 
558 void rfc1035_ntoa_ipv4(const struct in_addr *in, char *buf);
559 int rfc1035_aton_ipv4(const char *p, struct in_addr *in4);
560 
561 #if RFC1035_IPV6
562 void rfc1035_ipv6to4(struct in_addr *, const struct in6_addr *);
563 void rfc1035_ipv4to6(struct in6_addr *, const struct in_addr *);
564 #endif
565 
566 /*
567 ** Extract network address from a socket address.
568 */
569 
570 int rfc1035_sockaddrip(const RFC1035_NETADDR *,	/* Socket address buffer */
571 		int,				/* Length of address */
572 		RFC1035_ADDR *);		/* Address saved here */
573 
574 int rfc1035_sockaddrport(const RFC1035_NETADDR *, /* Socket address buffer */
575 		int,				/* Length of address */
576 		int *);				/* Port saved here */
577 
578 #if RFC1035_IPV6
579 #define	RFC1035_NTOABUFSIZE	INET6_ADDRSTRLEN
580 #else
581 #define	RFC1035_NTOABUFSIZE	16
582 #endif
583 
584 void rfc1035_ntoa(const RFC1035_ADDR *, char *);
585 int rfc1035_aton(const char *, RFC1035_ADDR *);
586 
587 /*
588 ** New function that compares two addresses -- handles both IPv4 and IPv6:
589 */
590 
591 int rfc1035_same_ip(const void *, int, const void *, int);
592 
593 int     rfc1035_bindsource(int sockfd,	/* Socket fd */
594 	const struct sockaddr *addr,	/* Buffer to socket address */
595 	int addrlen);			/* Size of socket address */
596 
597 /*
598 ** First try to create an IPv6 socket, then, if we fail, an IPv4 socket.
599 */
600 
601 int	rfc1035_mksocket(int sock_type,		/* socket type to create */
602 			int sock_protocol,	/* socket protocol to create */
603 			int *af);	/* If succeed, address family created */
604 
605 /*
606 ** Take the destination address, and create a socket address structure
607 ** suitable for connecting to this address.
608 */
609 
610 int	rfc1035_mkaddress(int af,		/* AF_INET or AF_INET6 */
611 
612 	/* buf is initiailized to the sender's ip address. */
613 
614 	RFC1035_NETADDR *buf,		/* Buffer for the created address */
615 	const RFC1035_ADDR *addr,	/* Network address */
616 	int port,			/* Network port (network byte order) */
617 	const struct sockaddr **ptr,	/* Will point to buf */
618 	int *len);			/* Will be size of socket address */
619 
620 /*
621 ** A convenient interface to the SIOCGIFCONF ioctl.
622 */
623 
624 struct rfc1035_ifconf {
625 	struct rfc1035_ifconf *next;
626 	char *ifname;
627 	RFC1035_ADDR ifaddr;
628 };
629 
630 struct rfc1035_ifconf *rfc1035_ifconf(int *errflag);
631 void rfc1035_ifconf_free(struct rfc1035_ifconf *ifconf_list);
632 
633 /*
634 ** Outstanding UDP queries.
635 */
636 
637 	/* common query buffer */
638 
639 struct querybuf {
640 	char qbuf[512];
641 	unsigned qbuflen;
642 	} ;
643 
644 struct rfc1035_udp_query_response;
645 
646 	/* How many queries, and the queries */
647 
648 struct rfc1035_udp_query_responses {
649 	int n_queries;
650 	struct rfc1035_udp_query_response *queries;
651 };
652 
653 	/* Each query, and response already receives so far, if any. */
654 
655 struct rfc1035_udp_query_response {
656 	const char *query;
657 	unsigned querylen;
658 	char *response;
659 	unsigned resplen;
660 };
661 
662 /*
663 ** Allocate a new rfc1035_udp_query_responses.
664 ** Copies each query into the rfc1035_udp_query_response, each response is
665 ** initialized to null.
666 */
667 
668 struct rfc1035_udp_query_responses *
669 rfc1035_udp_query_response_alloc(const char **queries,
670 				 const unsigned *querylens,
671 				 int n_queries);
672 
673 struct rfc1035_udp_query_responses *
674 rfc1035_udp_query_response_alloc_bis(struct querybuf *queries,
675 				 int n_queries);
676 
677 /*
678 ** Send all queries via UDPs, wait for responses.
679 **
680 ** Returns non-0 if all queries are received, 0 if not. EAGAIN indicates
681 ** a timeout, and this can be called again with the same
682 ** rfc1035_udp_query_responses object; this resends all queries for which
683 ** no response was received, and this will wait for the remaining responses.
684 */
685 int rfc1035_udp_query_multi(struct rfc1035_res *res,
686 			    /* Socket: */
687 			    int fd,
688 			    /* Where to send it to */
689 			    const struct sockaddr *sin, int sin_len,
690 			    /* The queries */
691 			    struct rfc1035_udp_query_responses *qr,
692 
693 			    /* How long to wait for responses, in seconds. */
694 			    unsigned w);
695 
696 /*
697 ** Deallocate rfc1035_udp_query_responses. Each non-NULL response pointer
698 ** gets free()d.
699 */
700 
701 void rfc1035_udp_query_response_free(struct rfc1035_udp_query_responses *);
702 
703 
704 #ifdef  __cplusplus
705 }
706 #endif
707 
708 #endif
709