]> git.ipfire.org Git - thirdparty/man-pages.git/blame - man3/getaddrinfo_a.3
man*/: ffix (un-bracket tables)
[thirdparty/man-pages.git] / 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>
68e4db0a 22.PP
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 );
68e4db0a 27.PP
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.
847e0d88 38.PP
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.
54.PP
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:
51f5698d 69.PP
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
847e0d88 80.PP
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).
847e0d88 109.PP
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
121.BR sigevent (7).
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
134.BR sigevent (7)
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
150.BR sigevent (7)
151for details.
152.PP
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 .
847e0d88 161.PP
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).
191.PP
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.
847e0d88 196.PP
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.
847e0d88 206.PP
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.
240.PP
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.
256.PP
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.
847e0d88 268.PP
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.
281.PP
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
847e0d88 303.sp 1
3113c7f3 304.SH STANDARDS
4131356c
AC
305GNU.
306.SH HISTORY
307glibc 2.2.3.
308.PP
e11d63b9
PB
309The interface of
310.BR getaddrinfo_a ()
311was modeled after the
312.BR lio_listio (3)
313interface.
a14af333 314.SH EXAMPLES
e11d63b9
PB
315Two examples are provided: a simple example that resolves
316several requests in parallel synchronously, and a complex example
317showing some of the asynchronous capabilities.
c634028a 318.SS Synchronous example
e11d63b9
PB
319The program below simply resolves several hostnames in parallel,
320giving a speed-up compared to resolving the hostnames sequentially using
321.BR getaddrinfo (3).
322The program might be used like this:
e646a1ba 323.PP
e11d63b9 324.in +4n
e646a1ba 325.EX
7f516900 326$ \fB./a.out mirrors.kernel.org enoent.linuxfoundation.org gnu.org\fP
6de1d3a9 327mirrors.kernel.org: 139.178.88.99
e11d63b9 328enoent.linuxfoundation.org: Name or service not known
a2feb3e1 329gnu.org: 209.51.188.116
b8302363 330.EE
e11d63b9
PB
331.in
332.PP
333Here is the program source code
207050fa 334.PP
b0b6ab4e 335.\" SRC BEGIN (sync.c)
207050fa 336.EX
e11d63b9
PB
337#define _GNU_SOURCE
338#include <netdb.h>
339#include <stdio.h>
340#include <stdlib.h>
341#include <string.h>
fe5dba13 342\&
e11d63b9
PB
343int
344main(int argc, char *argv[])
345{
88893a77 346 int ret;
e11d63b9
PB
347 struct gaicb *reqs[argc \- 1];
348 char host[NI_MAXHOST];
349 struct addrinfo *res;
fe5dba13 350\&
e11d63b9 351 if (argc < 2) {
d1a71985 352 fprintf(stderr, "Usage: %s HOST...\en", argv[0]);
e11d63b9
PB
353 exit(EXIT_FAILURE);
354 }
fe5dba13 355\&
b42296e4 356 for (size_t i = 0; i < argc \- 1; i++) {
e11d63b9
PB
357 reqs[i] = malloc(sizeof(*reqs[0]));
358 if (reqs[i] == NULL) {
359 perror("malloc");
360 exit(EXIT_FAILURE);
361 }
362 memset(reqs[i], 0, sizeof(*reqs[0]));
363 reqs[i]\->ar_name = argv[i + 1];
364 }
fe5dba13 365\&
e11d63b9
PB
366 ret = getaddrinfo_a(GAI_WAIT, reqs, argc \- 1, NULL);
367 if (ret != 0) {
d1a71985 368 fprintf(stderr, "getaddrinfo_a() failed: %s\en",
e11d63b9
PB
369 gai_strerror(ret));
370 exit(EXIT_FAILURE);
371 }
fe5dba13 372\&
b42296e4 373 for (size_t i = 0; i < argc \- 1; i++) {
e11d63b9
PB
374 printf("%s: ", reqs[i]\->ar_name);
375 ret = gai_error(reqs[i]);
376 if (ret == 0) {
377 res = reqs[i]\->ar_result;
fe5dba13 378\&
e11d63b9 379 ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
d917c31d
AC
380 host, sizeof(host),
381 NULL, 0, NI_NUMERICHOST);
e11d63b9 382 if (ret != 0) {
d1a71985 383 fprintf(stderr, "getnameinfo() failed: %s\en",
e11d63b9
PB
384 gai_strerror(ret));
385 exit(EXIT_FAILURE);
386 }
387 puts(host);
fe5dba13 388\&
e11d63b9
PB
389 } else {
390 puts(gai_strerror(ret));
391 }
392 }
393 exit(EXIT_SUCCESS);
394}
207050fa 395.EE
b0b6ab4e 396.\" SRC END
c634028a 397.SS Asynchronous example
e11d63b9
PB
398This example shows a simple interactive
399.BR getaddrinfo_a ()
400front-end.
401The notification facility is not demonstrated.
402.PP
b084fc29 403An example session might look like this:
e646a1ba 404.PP
e11d63b9 405.in +4n
e646a1ba 406.EX
e11d63b9 407$ \fB./a.out\fP
7f516900 408> a mirrors.kernel.org enoent.linuxfoundation.org gnu.org
e11d63b9 409> c 2
a2feb3e1 410[2] gnu.org: Request not canceled
e11d63b9 411> w 0 1
6de1d3a9 412[00] mirrors.kernel.org: Finished
e11d63b9 413> l
6de1d3a9 414[00] mirrors.kernel.org: 139.178.88.99
e11d63b9 415[01] enoent.linuxfoundation.org: Processing request in progress
a2feb3e1 416[02] gnu.org: 209.51.188.116
e11d63b9 417> l
6de1d3a9 418[00] mirrors.kernel.org: 139.178.88.99
e11d63b9 419[01] enoent.linuxfoundation.org: Name or service not known
a2feb3e1 420[02] gnu.org: 209.51.188.116
b8302363 421.EE
e11d63b9
PB
422.in
423.PP
71af708f 424The program source is as follows:
847e0d88 425.PP
b0b6ab4e 426.\" SRC BEGIN (async.c)
207050fa 427.EX
e11d63b9
PB
428#define _GNU_SOURCE
429#include <netdb.h>
430#include <stdio.h>
431#include <stdlib.h>
432#include <string.h>
fe5dba13 433\&
e11d63b9 434static struct gaicb **reqs = NULL;
b42296e4 435static size_t nreqs = 0;
fe5dba13 436\&
e11d63b9
PB
437static char *
438getcmd(void)
439{
440 static char buf[256];
fe5dba13 441\&
e11d63b9
PB
442 fputs("> ", stdout); fflush(stdout);
443 if (fgets(buf, sizeof(buf), stdin) == NULL)
444 return NULL;
fe5dba13 445\&
b957f81f 446 if (buf[strlen(buf) \- 1] == \[aq]\en\[aq])
e11d63b9 447 buf[strlen(buf) \- 1] = 0;
fe5dba13 448\&
e11d63b9
PB
449 return buf;
450}
fe5dba13 451\&
c6beb8a1 452/* Add requests for specified hostnames. */
e11d63b9
PB
453static void
454add_requests(void)
455{
b42296e4 456 size_t nreqs_base = nreqs;
e11d63b9
PB
457 char *host;
458 int ret;
fe5dba13 459\&
e11d63b9
PB
460 while ((host = strtok(NULL, " "))) {
461 nreqs++;
26499b04 462 reqs = realloc(reqs, sizeof(reqs[0]) * nreqs);
fe5dba13 463\&
e11d63b9
PB
464 reqs[nreqs \- 1] = calloc(1, sizeof(*reqs[0]));
465 reqs[nreqs \- 1]\->ar_name = strdup(host);
466 }
fe5dba13 467\&
e11d63b9 468 /* Queue nreqs_base..nreqs requests. */
fe5dba13 469\&
e11d63b9
PB
470 ret = getaddrinfo_a(GAI_NOWAIT, &reqs[nreqs_base],
471 nreqs \- nreqs_base, NULL);
472 if (ret) {
d1a71985 473 fprintf(stderr, "getaddrinfo_a() failed: %s\en",
e11d63b9
PB
474 gai_strerror(ret));
475 exit(EXIT_FAILURE);
476 }
477}
fe5dba13 478\&
c6beb8a1 479/* Wait until at least one of specified requests completes. */
e11d63b9
PB
480static void
481wait_requests(void)
482{
483 char *id;
b42296e4
AC
484 int ret;
485 size_t n;
e11d63b9
PB
486 struct gaicb const **wait_reqs = calloc(nreqs, sizeof(*wait_reqs));
487 /* NULL elements are ignored by gai_suspend(). */
fe5dba13 488\&
e11d63b9
PB
489 while ((id = strtok(NULL, " ")) != NULL) {
490 n = atoi(id);
fe5dba13 491\&
e11d63b9 492 if (n >= nreqs) {
d1a71985 493 printf("Bad request number: %s\en", id);
e11d63b9
PB
494 return;
495 }
fe5dba13 496\&
e11d63b9
PB
497 wait_reqs[n] = reqs[n];
498 }
fe5dba13 499\&
e11d63b9
PB
500 ret = gai_suspend(wait_reqs, nreqs, NULL);
501 if (ret) {
d1a71985 502 printf("gai_suspend(): %s\en", gai_strerror(ret));
e11d63b9
PB
503 return;
504 }
fe5dba13 505\&
b42296e4 506 for (size_t i = 0; i < nreqs; i++) {
e11d63b9
PB
507 if (wait_reqs[i] == NULL)
508 continue;
fe5dba13 509\&
e11d63b9
PB
510 ret = gai_error(reqs[i]);
511 if (ret == EAI_INPROGRESS)
512 continue;
fe5dba13 513\&
b42296e4 514 printf("[%02zu] %s: %s\en", i, reqs[i]\->ar_name,
e11d63b9
PB
515 ret == 0 ? "Finished" : gai_strerror(ret));
516 }
517}
fe5dba13 518\&
c6beb8a1 519/* Cancel specified requests. */
e11d63b9
PB
520static void
521cancel_requests(void)
522{
523 char *id;
b42296e4
AC
524 int ret;
525 size_t n;
fe5dba13 526\&
e11d63b9
PB
527 while ((id = strtok(NULL, " ")) != NULL) {
528 n = atoi(id);
fe5dba13 529\&
e11d63b9 530 if (n >= nreqs) {
d1a71985 531 printf("Bad request number: %s\en", id);
e11d63b9
PB
532 return;
533 }
fe5dba13 534\&
e11d63b9 535 ret = gai_cancel(reqs[n]);
d1a71985 536 printf("[%s] %s: %s\en", id, reqs[atoi(id)]\->ar_name,
e11d63b9
PB
537 gai_strerror(ret));
538 }
539}
fe5dba13 540\&
c6beb8a1 541/* List all requests. */
e11d63b9
PB
542static void
543list_requests(void)
544{
ec8b0003 545 int ret;
e11d63b9
PB
546 char host[NI_MAXHOST];
547 struct addrinfo *res;
fe5dba13 548\&
b42296e4
AC
549 for (size_t i = 0; i < nreqs; i++) {
550 printf("[%02zu] %s: ", i, reqs[i]\->ar_name);
e11d63b9 551 ret = gai_error(reqs[i]);
fe5dba13 552\&
e11d63b9
PB
553 if (!ret) {
554 res = reqs[i]\->ar_result;
fe5dba13 555\&
e11d63b9
PB
556 ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
557 host, sizeof(host),
558 NULL, 0, NI_NUMERICHOST);
559 if (ret) {
d1a71985 560 fprintf(stderr, "getnameinfo() failed: %s\en",
e11d63b9
PB
561 gai_strerror(ret));
562 exit(EXIT_FAILURE);
563 }
564 puts(host);
565 } else {
566 puts(gai_strerror(ret));
567 }
568 }
569}
fe5dba13 570\&
e11d63b9 571int
b32ffdf2 572main(void)
e11d63b9
PB
573{
574 char *cmdline;
575 char *cmd;
fe5dba13 576\&
e11d63b9
PB
577 while ((cmdline = getcmd()) != NULL) {
578 cmd = strtok(cmdline, " ");
fe5dba13 579\&
e11d63b9
PB
580 if (cmd == NULL) {
581 list_requests();
582 } else {
583 switch (cmd[0]) {
b957f81f 584 case \[aq]a\[aq]:
e11d63b9
PB
585 add_requests();
586 break;
b957f81f 587 case \[aq]w\[aq]:
e11d63b9
PB
588 wait_requests();
589 break;
b957f81f 590 case \[aq]c\[aq]:
e11d63b9
PB
591 cancel_requests();
592 break;
b957f81f 593 case \[aq]l\[aq]:
e11d63b9
PB
594 list_requests();
595 break;
596 default:
d1a71985 597 fprintf(stderr, "Bad command: %c\en", cmd[0]);
e11d63b9
PB
598 break;
599 }
600 }
601 }
602 exit(EXIT_SUCCESS);
603}
207050fa 604.EE
b0b6ab4e 605.\" SRC END
47297adb 606.SH SEE ALSO
e11d63b9
PB
607.BR getaddrinfo (3),
608.BR inet (3),
609.BR lio_listio (3),
610.BR hostname (7),
611.BR ip (7),
612.BR sigevent (7)