]> git.ipfire.org Git - thirdparty/man-pages.git/blame - man/man3/getaddrinfo_a.3
man/, share/mk/: Move man*/ to man/
[thirdparty/man-pages.git] / man / man3 / getaddrinfo_a.3
CommitLineData
a1eaacb1 1'\" t
e11d63b9 2.\" Copyright (c) 2009 Petr Baudis <pasky@suse.cz>
bfb9c7c0 3.\" and clean-ups and additions (C) Copyright 2010 Michael Kerrisk
67c7e1d5 4.\" <mtk.manpages@gmail.com>
e11d63b9 5.\"
5fbde956 6.\" SPDX-License-Identifier: Linux-man-pages-copyleft
e11d63b9
PB
7.\"
8.\" References: http://people.redhat.com/drepper/asynchnl.pdf,
9.\" http://www.imperialviolet.org/2005/06/01/asynchronous-dns-lookups-with-glibc.html
10.\"
4c1c5274 11.TH getaddrinfo_a 3 (date) "Linux man-pages (unreleased)"
e11d63b9
PB
12.SH NAME
13getaddrinfo_a, gai_suspend, gai_error, gai_cancel \- asynchronous
14network address and service translation
af56ce56
AC
15.SH LIBRARY
16Asynchronous name lookup library
17.RI ( libanl ", " \-lanl )
e11d63b9
PB
18.SH SYNOPSIS
19.nf
b80f966b 20.BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */"
e11d63b9 21.B #include <netdb.h>
c6d039a3 22.P
79201b69
AC
23.BI "int getaddrinfo_a(int " mode ", struct gaicb *" list [restrict],
24.BI " int " nitems ", struct sigevent *restrict " sevp );
25.BI "int gai_suspend(const struct gaicb *const " list "[], int " nitems ,
26.BI " const struct timespec *" timeout );
c6d039a3 27.P
79201b69
AC
28.BI "int gai_error(struct gaicb *" req );
29.BI "int gai_cancel(struct gaicb *" req );
e11d63b9
PB
30.fi
31.SH DESCRIPTION
32The
33.BR getaddrinfo_a ()
34function performs the same task as
35.BR getaddrinfo (3),
36but allows multiple name look-ups to be performed asynchronously,
37with optional notification on completion of look-up operations.
c6d039a3 38.P
e11d63b9
PB
39The
40.I mode
41argument has one of the following values:
42.TP
43.B GAI_WAIT
af15dfab
SP
44Perform the look-ups synchronously.
45The call blocks until the look-ups have completed.
e11d63b9
PB
46.TP
47.B GAI_NOWAIT
48Perform the look-ups asynchronously.
49The call returns immediately,
50and the requests are resolved in the background.
51See the discussion of the
52.I sevp
53argument below.
c6d039a3 54.P
e11d63b9
PB
55The array
56.I list
57specifies the look-up requests to process.
58The
59.I nitems
60argument specifies the number of elements in
61.IR list .
62The requested look-up operations are started in parallel.
63NULL elements in
64.I list
65are ignored.
66Each request is described by a
67.I gaicb
68structure, defined as follows:
c6d039a3 69.P
e11d63b9 70.in +4n
b8302363 71.EX
e11d63b9
PB
72struct gaicb {
73 const char *ar_name;
74 const char *ar_service;
75 const struct addrinfo *ar_request;
76 struct addrinfo *ar_result;
77};
b8302363 78.EE
e11d63b9 79.in
c6d039a3 80.P
e11d63b9
PB
81The elements of this structure correspond to the arguments of
82.BR getaddrinfo (3).
83Thus,
84.I ar_name
85corresponds to the
86.I node
87argument and
88.I ar_service
89to the
90.I service
91argument, identifying an Internet host and a service.
92The
93.I ar_request
94element corresponds to the
95.I hints
96argument, specifying the criteria for selecting
97the returned socket address structures.
98Finally,
99.I ar_result
100corresponds to the
101.I res
102argument; you do not need to initialize this element,
103it will be automatically set when the request
104is resolved.
105The
106.I addrinfo
107structure referenced by the last two elements is described in
108.BR getaddrinfo (3).
c6d039a3 109.P
e11d63b9
PB
110When
111.I mode
112is specified as
5238ea2c 113.BR GAI_NOWAIT ,
e11d63b9
PB
114notifications about resolved requests
115can be obtained by employing the
116.I sigevent
117structure pointed to by the
118.I sevp
119argument.
120For the definition and general details of this structure, see
5b98e0e7 121.BR sigevent (3type).
e11d63b9
PB
122The
123.I sevp\->sigev_notify
124field can have the following values:
125.TP
1ae6b2c7 126.B SIGEV_NONE
e11d63b9
PB
127Don't provide any notification.
128.TP
1ae6b2c7 129.B SIGEV_SIGNAL
e11d63b9
PB
130When a look-up completes, generate the signal
131.I sigev_signo
132for the process.
133See
5b98e0e7 134.BR sigevent (3type)
e11d63b9
PB
135for general details.
136The
137.I si_code
138field of the
139.I siginfo_t
140structure will be set to
141.BR SI_ASYNCNL .
142.\" si_pid and si_uid are also set, to the values of the calling process,
143.\" which doesn't provide useful information, so we'll skip mentioning it.
144.TP
1ae6b2c7 145.B SIGEV_THREAD
e11d63b9
PB
146When a look-up completes, invoke
147.I sigev_notify_function
148as if it were the start function of a new thread.
149See
5b98e0e7 150.BR sigevent (3type)
e11d63b9 151for details.
c6d039a3 152.P
59e9285d 153For
1ae6b2c7 154.B SIGEV_SIGNAL
e11d63b9
PB
155and
156.BR SIGEV_THREAD ,
157it may be useful to point
1ae6b2c7 158.I sevp\->sigev_value.sival_ptr
e11d63b9
PB
159to
160.IR list .
c6d039a3 161.P
e11d63b9
PB
162The
163.BR gai_suspend ()
164function suspends execution of the calling thread,
165waiting for the completion of one or more requests in the array
1f2a5c64 166.IR list .
e11d63b9
PB
167The
168.I nitems
169argument specifies the size of the array
170.IR list .
171The call blocks until one of the following occurs:
cdede5cd 172.IP \[bu] 3
e11d63b9
PB
173One or more of the operations in
174.I list
175completes.
cdede5cd 176.IP \[bu]
e11d63b9 177The call is interrupted by a signal that is caught.
cdede5cd 178.IP \[bu]
e11d63b9
PB
179The time interval specified in
180.I timeout
181elapses.
182This argument specifies a timeout in seconds plus nanoseconds (see
183.BR nanosleep (2)
184for details of the
185.I timespec
186structure).
187If
188.I timeout
189is NULL, then the call blocks indefinitely
190(until one of the events above occurs).
c6d039a3 191.P
e11d63b9
PB
192No explicit indication of which request was completed is given;
193you must determine which request(s) have completed by iterating with
194.BR gai_error ()
195over the list of requests.
c6d039a3 196.P
e11d63b9
PB
197The
198.BR gai_error ()
199function returns the status of the request
200.IR req :
201either
202.B EAI_INPROGRESS
203if the request was not completed yet,
2040 if it was handled successfully,
205or an error code if the request could not be resolved.
c6d039a3 206.P
e11d63b9
PB
207The
208.BR gai_cancel ()
209function cancels the request
210.IR req .
211If the request has been canceled successfully,
212the error status of the request will be set to
819eeff4 213.B EAI_CANCELED
e11d63b9
PB
214and normal asynchronous notification will be performed.
215The request cannot be canceled if it is currently being processed;
216in that case, it will be handled as if
217.BR gai_cancel ()
218has never been called.
219If
220.I req
221is NULL, an attempt is made to cancel all outstanding requests
222that the process has made.
47297adb 223.SH RETURN VALUE
e11d63b9
PB
224The
225.BR getaddrinfo_a ()
226function returns 0 if all of the requests have been enqueued successfully,
227or one of the following nonzero error codes:
228.TP
229.B EAI_AGAIN
230The resources necessary to enqueue the look-up requests were not available.
231The application may check the error status of each
232request to determine which ones failed.
233.TP
234.B EAI_MEMORY
235Out of memory.
236.TP
237.B EAI_SYSTEM
238.I mode
239is invalid.
c6d039a3 240.P
e11d63b9
PB
241The
242.BR gai_suspend ()
243function returns 0 if at least one of the listed requests has been completed.
244Otherwise, it returns one of the following nonzero error codes:
245.TP
246.B EAI_AGAIN
247The given timeout expired before any of the requests could be completed.
248.TP
249.B EAI_ALLDONE
250There were no actual requests given to the function.
251.TP
252.B EAI_INTR
253A signal has interrupted the function.
254Note that this interruption might have been
255caused by signal notification of some completed look-up request.
c6d039a3 256.P
e11d63b9
PB
257The
258.BR gai_error ()
259function can return
260.B EAI_INPROGRESS
261for an unfinished look-up request,
2620 for a successfully completed look-up
263(as described above), one of the error codes that could be returned by
264.BR getaddrinfo (3),
265or the error code
819eeff4 266.B EAI_CANCELED
e11d63b9 267if the request has been canceled explicitly before it could be finished.
c6d039a3 268.P
e11d63b9
PB
269The
270.BR gai_cancel ()
271function can return one of these values:
272.TP
819eeff4 273.B EAI_CANCELED
e11d63b9
PB
274The request has been canceled successfully.
275.TP
819eeff4 276.B EAI_NOTCANCELED
e11d63b9
PB
277The request has not been canceled.
278.TP
279.B EAI_ALLDONE
280The request has already completed.
c6d039a3 281.P
e11d63b9
PB
282The
283.BR gai_strerror (3)
284function translates these error codes to a human readable string,
285suitable for error reporting.
9038b7f6
ZL
286.SH ATTRIBUTES
287For an explanation of the terms used in this section, see
288.BR attributes (7).
289.TS
290allbox;
c466875e 291lbx lb lb
9038b7f6
ZL
292l l l.
293Interface Attribute Value
294T{
9e54434e
BR
295.na
296.nh
9038b7f6
ZL
297.BR getaddrinfo_a (),
298.BR gai_suspend (),
299.BR gai_error (),
300.BR gai_cancel ()
301T} Thread safety MT-Safe
302.TE
3113c7f3 303.SH STANDARDS
4131356c
AC
304GNU.
305.SH HISTORY
306glibc 2.2.3.
c6d039a3 307.P
e11d63b9
PB
308The interface of
309.BR getaddrinfo_a ()
310was modeled after the
311.BR lio_listio (3)
312interface.
a14af333 313.SH EXAMPLES
e11d63b9
PB
314Two examples are provided: a simple example that resolves
315several requests in parallel synchronously, and a complex example
316showing some of the asynchronous capabilities.
c634028a 317.SS Synchronous example
e11d63b9
PB
318The program below simply resolves several hostnames in parallel,
319giving a speed-up compared to resolving the hostnames sequentially using
320.BR getaddrinfo (3).
321The program might be used like this:
c6d039a3 322.P
e11d63b9 323.in +4n
e646a1ba 324.EX
7f516900 325$ \fB./a.out mirrors.kernel.org enoent.linuxfoundation.org gnu.org\fP
6de1d3a9 326mirrors.kernel.org: 139.178.88.99
e11d63b9 327enoent.linuxfoundation.org: Name or service not known
a2feb3e1 328gnu.org: 209.51.188.116
b8302363 329.EE
e11d63b9 330.in
c6d039a3 331.P
e11d63b9 332Here is the program source code
c6d039a3 333.P
b0b6ab4e 334.\" SRC BEGIN (sync.c)
207050fa 335.EX
e11d63b9 336#define _GNU_SOURCE
6a79bd57 337#include <err.h>
e11d63b9
PB
338#include <netdb.h>
339#include <stdio.h>
340#include <stdlib.h>
341#include <string.h>
fe5dba13 342\&
5d774587
AC
343#define MALLOC(n, type) ((type *) reallocarray(NULL, n, sizeof(type)))
344\&
e11d63b9
PB
345int
346main(int argc, char *argv[])
347{
88893a77 348 int ret;
e11d63b9
PB
349 struct gaicb *reqs[argc \- 1];
350 char host[NI_MAXHOST];
351 struct addrinfo *res;
fe5dba13 352\&
e11d63b9 353 if (argc < 2) {
d1a71985 354 fprintf(stderr, "Usage: %s HOST...\en", argv[0]);
e11d63b9
PB
355 exit(EXIT_FAILURE);
356 }
fe5dba13 357\&
b42296e4 358 for (size_t i = 0; i < argc \- 1; i++) {
5d774587 359 reqs[i] = MALLOC(1, struct gaicb);
6a79bd57
AC
360 if (reqs[i] == NULL)
361 err(EXIT_FAILURE, "malloc");
362\&
e11d63b9
PB
363 memset(reqs[i], 0, sizeof(*reqs[0]));
364 reqs[i]\->ar_name = argv[i + 1];
365 }
fe5dba13 366\&
e11d63b9
PB
367 ret = getaddrinfo_a(GAI_WAIT, reqs, argc \- 1, NULL);
368 if (ret != 0) {
d1a71985 369 fprintf(stderr, "getaddrinfo_a() failed: %s\en",
e11d63b9
PB
370 gai_strerror(ret));
371 exit(EXIT_FAILURE);
372 }
fe5dba13 373\&
b42296e4 374 for (size_t i = 0; i < argc \- 1; i++) {
e11d63b9
PB
375 printf("%s: ", reqs[i]\->ar_name);
376 ret = gai_error(reqs[i]);
377 if (ret == 0) {
378 res = reqs[i]\->ar_result;
fe5dba13 379\&
e11d63b9 380 ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
d917c31d
AC
381 host, sizeof(host),
382 NULL, 0, NI_NUMERICHOST);
e11d63b9 383 if (ret != 0) {
d1a71985 384 fprintf(stderr, "getnameinfo() failed: %s\en",
e11d63b9
PB
385 gai_strerror(ret));
386 exit(EXIT_FAILURE);
387 }
388 puts(host);
fe5dba13 389\&
e11d63b9
PB
390 } else {
391 puts(gai_strerror(ret));
392 }
393 }
394 exit(EXIT_SUCCESS);
395}
207050fa 396.EE
b0b6ab4e 397.\" SRC END
c634028a 398.SS Asynchronous example
e11d63b9
PB
399This example shows a simple interactive
400.BR getaddrinfo_a ()
401front-end.
402The notification facility is not demonstrated.
c6d039a3 403.P
b084fc29 404An example session might look like this:
c6d039a3 405.P
e11d63b9 406.in +4n
e646a1ba 407.EX
e11d63b9 408$ \fB./a.out\fP
7f516900 409> a mirrors.kernel.org enoent.linuxfoundation.org gnu.org
e11d63b9 410> c 2
a2feb3e1 411[2] gnu.org: Request not canceled
e11d63b9 412> w 0 1
6de1d3a9 413[00] mirrors.kernel.org: Finished
e11d63b9 414> l
6de1d3a9 415[00] mirrors.kernel.org: 139.178.88.99
e11d63b9 416[01] enoent.linuxfoundation.org: Processing request in progress
a2feb3e1 417[02] gnu.org: 209.51.188.116
e11d63b9 418> l
6de1d3a9 419[00] mirrors.kernel.org: 139.178.88.99
e11d63b9 420[01] enoent.linuxfoundation.org: Name or service not known
a2feb3e1 421[02] gnu.org: 209.51.188.116
b8302363 422.EE
e11d63b9 423.in
c6d039a3 424.P
71af708f 425The program source is as follows:
c6d039a3 426.P
b0b6ab4e 427.\" SRC BEGIN (async.c)
207050fa 428.EX
e11d63b9 429#define _GNU_SOURCE
5d774587 430#include <assert.h>
6a79bd57 431#include <err.h>
e11d63b9
PB
432#include <netdb.h>
433#include <stdio.h>
434#include <stdlib.h>
435#include <string.h>
fe5dba13 436\&
5d774587
AC
437#define CALLOC(n, type) ((type *) calloc(n, sizeof(type)))
438\&
439#define REALLOCF(ptr, n, type) \e
440({ \e
441 static_assert(__builtin_types_compatible_p(typeof(ptr), type *)); \e
442 \e
443 (type *) reallocarrayf(ptr, n, sizeof(type)); \e
444})
445\&
e11d63b9 446static struct gaicb **reqs = NULL;
b42296e4 447static size_t nreqs = 0;
fe5dba13 448\&
5d774587
AC
449static inline void *
450reallocarrayf(void *p, size_t nmemb, size_t size)
451{
452 void *q;
453\&
454 q = reallocarray(p, nmemb, size);
455 if (q == NULL && nmemb != 0 && size != 0)
456 free(p);
457 return q;
458}
459\&
e11d63b9
PB
460static char *
461getcmd(void)
462{
463 static char buf[256];
fe5dba13 464\&
e11d63b9
PB
465 fputs("> ", stdout); fflush(stdout);
466 if (fgets(buf, sizeof(buf), stdin) == NULL)
467 return NULL;
fe5dba13 468\&
b957f81f 469 if (buf[strlen(buf) \- 1] == \[aq]\en\[aq])
e11d63b9 470 buf[strlen(buf) \- 1] = 0;
fe5dba13 471\&
e11d63b9
PB
472 return buf;
473}
fe5dba13 474\&
c6beb8a1 475/* Add requests for specified hostnames. */
e11d63b9
PB
476static void
477add_requests(void)
478{
b42296e4 479 size_t nreqs_base = nreqs;
e11d63b9
PB
480 char *host;
481 int ret;
fe5dba13 482\&
e11d63b9
PB
483 while ((host = strtok(NULL, " "))) {
484 nreqs++;
5d774587 485 reqs = REALLOCF(reqs, nreqs, struct gaicb *);
6a79bd57
AC
486 if (reqs == NULL)
487 err(EXIT_FAILURE, "reallocf");
fe5dba13 488\&
5d774587 489 reqs[nreqs \- 1] = CALLOC(1, struct gaicb);
6a79bd57
AC
490 if (reqs[nreqs \- 1] == NULL)
491 err(EXIT_FAILURE, "calloc");
492\&
e11d63b9
PB
493 reqs[nreqs \- 1]\->ar_name = strdup(host);
494 }
fe5dba13 495\&
e11d63b9 496 /* Queue nreqs_base..nreqs requests. */
fe5dba13 497\&
e11d63b9
PB
498 ret = getaddrinfo_a(GAI_NOWAIT, &reqs[nreqs_base],
499 nreqs \- nreqs_base, NULL);
500 if (ret) {
d1a71985 501 fprintf(stderr, "getaddrinfo_a() failed: %s\en",
e11d63b9
PB
502 gai_strerror(ret));
503 exit(EXIT_FAILURE);
504 }
505}
fe5dba13 506\&
c6beb8a1 507/* Wait until at least one of specified requests completes. */
e11d63b9
PB
508static void
509wait_requests(void)
510{
511 char *id;
b42296e4
AC
512 int ret;
513 size_t n;
6a79bd57
AC
514 struct gaicb const **wait_reqs;
515\&
5d774587 516 wait_reqs = CALLOC(nreqs, const struct gaicb *);
6a79bd57
AC
517 if (wait_reqs == NULL)
518 err(EXIT_FAILURE, "calloc");
519\&
e11d63b9 520 /* NULL elements are ignored by gai_suspend(). */
fe5dba13 521\&
e11d63b9
PB
522 while ((id = strtok(NULL, " ")) != NULL) {
523 n = atoi(id);
fe5dba13 524\&
e11d63b9 525 if (n >= nreqs) {
d1a71985 526 printf("Bad request number: %s\en", id);
e11d63b9
PB
527 return;
528 }
fe5dba13 529\&
e11d63b9
PB
530 wait_reqs[n] = reqs[n];
531 }
fe5dba13 532\&
e11d63b9
PB
533 ret = gai_suspend(wait_reqs, nreqs, NULL);
534 if (ret) {
d1a71985 535 printf("gai_suspend(): %s\en", gai_strerror(ret));
e11d63b9
PB
536 return;
537 }
fe5dba13 538\&
b42296e4 539 for (size_t i = 0; i < nreqs; i++) {
e11d63b9
PB
540 if (wait_reqs[i] == NULL)
541 continue;
fe5dba13 542\&
e11d63b9
PB
543 ret = gai_error(reqs[i]);
544 if (ret == EAI_INPROGRESS)
545 continue;
fe5dba13 546\&
b42296e4 547 printf("[%02zu] %s: %s\en", i, reqs[i]\->ar_name,
e11d63b9
PB
548 ret == 0 ? "Finished" : gai_strerror(ret));
549 }
550}
fe5dba13 551\&
c6beb8a1 552/* Cancel specified requests. */
e11d63b9
PB
553static void
554cancel_requests(void)
555{
556 char *id;
b42296e4
AC
557 int ret;
558 size_t n;
fe5dba13 559\&
e11d63b9
PB
560 while ((id = strtok(NULL, " ")) != NULL) {
561 n = atoi(id);
fe5dba13 562\&
e11d63b9 563 if (n >= nreqs) {
d1a71985 564 printf("Bad request number: %s\en", id);
e11d63b9
PB
565 return;
566 }
fe5dba13 567\&
e11d63b9 568 ret = gai_cancel(reqs[n]);
d1a71985 569 printf("[%s] %s: %s\en", id, reqs[atoi(id)]\->ar_name,
e11d63b9
PB
570 gai_strerror(ret));
571 }
572}
fe5dba13 573\&
c6beb8a1 574/* List all requests. */
e11d63b9
PB
575static void
576list_requests(void)
577{
ec8b0003 578 int ret;
e11d63b9
PB
579 char host[NI_MAXHOST];
580 struct addrinfo *res;
fe5dba13 581\&
b42296e4
AC
582 for (size_t i = 0; i < nreqs; i++) {
583 printf("[%02zu] %s: ", i, reqs[i]\->ar_name);
e11d63b9 584 ret = gai_error(reqs[i]);
fe5dba13 585\&
e11d63b9
PB
586 if (!ret) {
587 res = reqs[i]\->ar_result;
fe5dba13 588\&
e11d63b9
PB
589 ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
590 host, sizeof(host),
591 NULL, 0, NI_NUMERICHOST);
592 if (ret) {
d1a71985 593 fprintf(stderr, "getnameinfo() failed: %s\en",
e11d63b9
PB
594 gai_strerror(ret));
595 exit(EXIT_FAILURE);
596 }
597 puts(host);
598 } else {
599 puts(gai_strerror(ret));
600 }
601 }
602}
fe5dba13 603\&
e11d63b9 604int
b32ffdf2 605main(void)
e11d63b9
PB
606{
607 char *cmdline;
608 char *cmd;
fe5dba13 609\&
e11d63b9
PB
610 while ((cmdline = getcmd()) != NULL) {
611 cmd = strtok(cmdline, " ");
fe5dba13 612\&
e11d63b9
PB
613 if (cmd == NULL) {
614 list_requests();
615 } else {
616 switch (cmd[0]) {
b957f81f 617 case \[aq]a\[aq]:
e11d63b9
PB
618 add_requests();
619 break;
b957f81f 620 case \[aq]w\[aq]:
e11d63b9
PB
621 wait_requests();
622 break;
b957f81f 623 case \[aq]c\[aq]:
e11d63b9
PB
624 cancel_requests();
625 break;
b957f81f 626 case \[aq]l\[aq]:
e11d63b9
PB
627 list_requests();
628 break;
629 default:
d1a71985 630 fprintf(stderr, "Bad command: %c\en", cmd[0]);
e11d63b9
PB
631 break;
632 }
633 }
634 }
635 exit(EXIT_SUCCESS);
636}
207050fa 637.EE
b0b6ab4e 638.\" SRC END
47297adb 639.SH SEE ALSO
e11d63b9
PB
640.BR getaddrinfo (3),
641.BR inet (3),
642.BR lio_listio (3),
643.BR hostname (7),
644.BR ip (7),
5b98e0e7 645.BR sigevent (3type)