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