ARES_SEND(3)

πŸ“¦
version 1.34.9 Β· 2 versions
, in alpine 3.22, alpine 3.23, alpine 3.24, arch rolling, centos-stream 10, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, opensuse-leap 16.0, ubuntu stonking

πŸ’– ARES_SEND πŸ’–

ok so bestie, this is the ares_send page from the c-ares library functions manual, and it's genuinely one of the most iconic ones. it's giving "start a DNS query" main character energy. sit down, grab a strawberry, we're doing this πŸ“


✨ NAME ✨

ares_send β€” Initiate a DNS query


🌸 SYNOPSIS 🌸

#include <ares.h>

typedef void (*ares_callback_dnsrec)(void *arg, ares_status_t status,
                                     size_t timeouts,
                                     const ares_dns_record_t *dnsrec);

ares_status_t ares_send_dnsrec(ares_channel_t *channel,
                               const ares_dns_record_t *dnsrec,
                               ares_callback_dnsrec callback,
                               void *arg, unsigned short *qid);

typedef void (*ares_callback)(void *arg, int status,
                              int timeouts, unsigned char *abuf,
                              int alen);

void ares_send(ares_channel_t *channel, const unsigned char *qbuf,
               int qlen, ares_callback callback, void *arg);

πŸ¦‹ DESCRIPTION πŸ¦‹

ok so first up, the ares_send_dnsrec(3) function kicks off a DNS query that was formatted using the ares_dns_record_t * data structure you made with ares_dns_record_create(3), passed in through the dnsrec parameter. and the callback you hand over in the callback parameter? it also gives you the response back using an ares_dns_record_t * data structure. cute, symmetrical, we love to see it πŸ’…

the ares_send(3) function does basically the same thing, starts a DNS query, but instead it deals in raw binary buffers with fully formatted DNS messages, passed in through the qbuf and qlen parameters. and the callback in callback hands you back the raw binary DNS response in the abuf and alen parameters. ngl bestie, this method should be considered deprecated in favor of ares_send_dnsrec(3). it's giving legacy 🫠

both functions take an initialized ares channel, identified by channel.

ares_send_dnsrec(3) can also be handed an optional output parameter, qid, which gets populated with the query id exactly as it was placed on the wire. love that for you ✨

ares_send_dnsrec(3) returns an ares_status_t response code. this is useful for knowing the query was enqueued properly. heads up though: that response code does not reflect the result of the query β€” only the result of the enqueuing of the query. don't get it twisted πŸ™ˆ

completion or failure of the query might happen immediately (like, literally before the function even returns), or it might happen later as network events get processed. either way. no cap.

⚠️ when the associated callback gets called, it's called with a channel lock, so be careful β€” keep any processing minimal or you'll stall the DNS channel. it's giving "don't block the group chat" πŸ’€

the callback may be triggered from a different thread than the one that called ares_send_dnsrec(3) or ares_send(3).

for integrators running their own event loops and not using ARES_OPT_EVENT_THREAD, you need to be careful to make sure any file descriptor lists are updated immediately within the eventloop when notified. like, immediately immediately πŸ”₯

the callback argument arg is copied from the arg parameter of ares_send_dnsrec(3) or ares_send(3).

the callback argument status tells you whether the query succeeded and, if it didn't, how it failed. it may have any of these values:

  • ARES_SUCCESS β€” The query completed. πŸ‘‘
  • ARES_EBADQUERY β€” The query buffer was poorly formed (was not long enough for a DNS header or was too long for TCP transmission).
  • ARES_ETIMEOUT β€” No name servers responded within the timeout period.
  • ARES_ECONNREFUSED β€” No name servers could be contacted.
  • ARES_ENOMEM β€” Memory was exhausted.
  • ARES_ECANCELLED β€” The query was cancelled.
  • ARES_EDESTRUCTION β€” The name service channel channel is being destroyed; the query will not be completed.
  • ARES_ENOSERVER β€” The query will not be completed because no DNS servers were configured on the channel.
  • ARES_EBADQUERY β€” Misformatted DNS query.

(yes bestie, ARES_EBADQUERY shows up twice in the original list. that's not me being messy, that's just how it is 🫢)

the callback argument timeouts reports how many times a query timed out during the execution of the given request.

if the query completed, the callback argument dnsrec for ares_send_dnsrec(3), or abuf and alen for ares_send(3), will be non-NULL. periodt ✨

the abuf buffer is owned by the c-ares library and is only valid for the duration of the callback. the callback must not modify or free it, and must not retain a reference to it after returning β€” treat it as read-only. the parameter is intentionally not declared const solely to preserve API/ABI compatibility with existing applications. that's the whole reason. iykyk πŸ’…

unless the flag ARES_FLAG_NOCHECKRESP was set at channel initialization time, ares_send_dnsrec(3) and ares_send(3) will normally ignore responses whose questions do not match the supplied questions, plus responses with reply codes of SERVFAIL, NOTIMP, and REFUSED. but unlike other query functions in the ares library, ares_send_dnsrec(3) and ares_send(3) do not inspect the header of the reply packet to determine the error status. so a callback status of ARES_SUCCESS doesn't reflect as much about the response as it would for other query functions. read that twice, bestie 😭


🌈 AVAILABILITY 🌈

ares_send_dnsrec(3) was introduced in c-ares 1.28.0. iconic behavior, honestly ⭐


πŸŽ€ SEE ALSO πŸŽ€


and that's the whole page, bestie! this one's from the c-ares library functions manual, dated 25 July 1998, and the page itself is ARES_SEND(3). go forth and enqueue your queries responsibly πŸ§šπŸ’œ