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