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