OSDN Git Service

(split) LDP_man-pages: update original to v3.34.
[linuxjm/LDP_man-pages.git] / original / 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 .\" Permission is granted to make and distribute verbatim copies of this
5 .\" manual provided the copyright notice and this permission notice are
6 .\" preserved on all copies.
7 .\"
8 .\" Permission is granted to copy and distribute modified versions of this
9 .\" manual under the conditions for verbatim copying, provided that the
10 .\" entire resulting derived work is distributed under the terms of a
11 .\" permission notice identical to this one.
12 .\"
13 .\" Since the Linux kernel and libraries are constantly changing, this
14 .\" manual page may be incorrect or out-of-date.  The author(s) assume no
15 .\" responsibility for errors or omissions, or for damages resulting from
16 .\" the use of the information contained herein.  The author(s) may not
17 .\" have taken the same level of care in the production of this manual,
18 .\" which is licensed free of charge, as they might when working
19 .\" professionally.
20 .\"
21 .\" Formatted or processed versions of this manual, if unaccompanied by
22 .\" the source, must acknowledge the copyright and authors of this work.
23 .\"
24 .\" References: http://people.redhat.com/drepper/asynchnl.pdf,
25 .\"     http://www.imperialviolet.org/2005/06/01/asynchronous-dns-lookups-with-glibc.html
26 .\"
27 .TH GETADDRINFO_A 3 2010-09-27 "GNU" "Linux Programmer's Manual"
28 .SH NAME
29 getaddrinfo_a, gai_suspend, gai_error, gai_cancel \- asynchronous
30 network address and service translation
31 .SH SYNOPSIS
32 .nf
33 .BR "#define _GNU_SOURCE" "         /* See feature_test_macros(7) */"
34 .B #include <netdb.h>
35 .sp
36 .BI "int getaddrinfo_a(int " "mode" ", struct gaicb *" "list[]" ,
37 .BI "                int " "nitems" ", struct sigevent *" "sevp" );
38 .sp
39 .BI "int gai_suspend(struct gaicb *" "list[]" ", int " "nitems" ,
40 .BI "                struct timespec *" "timeout" );
41 .sp
42 .BI "int gai_error(struct gaicb *" "req" );
43 .sp
44 .BI "int gai_cancel(struct gaicb *" "req" );
45 .sp
46 Link with \fI\-lanl\fP.
47 .fi
48 .SH DESCRIPTION
49 The
50 .BR getaddrinfo_a ()
51 function performs the same task as
52 .BR getaddrinfo (3),
53 but allows multiple name look-ups to be performed asynchronously,
54 with optional notification on completion of look-up operations.
55
56 The
57 .I mode
58 argument has one of the following values:
59 .TP
60 .B GAI_WAIT
61 Perform the look-ups synchronously.
62 The call blocks until the look-ups have completed.
63 .TP
64 .B GAI_NOWAIT
65 Perform the look-ups asynchronously.
66 The call returns immediately,
67 and the requests are resolved in the background.
68 See the discussion of the
69 .I sevp
70 argument below.
71 .PP
72 The array
73 .I list
74 specifies the look-up requests to process.
75 The
76 .I nitems
77 argument specifies the number of elements in
78 .IR list .
79 The requested look-up operations are started in parallel.
80 NULL elements in
81 .I list
82 are ignored.
83 Each request is described by a
84 .I gaicb
85 structure, defined as follows:
86 .sp
87 .in +4n
88 .nf
89 struct gaicb {
90     const char            *ar_name;
91     const char            *ar_service;
92     const struct addrinfo *ar_request;
93     struct addrinfo       *ar_result;
94 };
95 .fi
96 .in
97
98 The elements of this structure correspond to the arguments of
99 .BR getaddrinfo (3).
100 Thus,
101 .I ar_name
102 corresponds to the
103 .I node
104 argument and
105 .I ar_service
106 to the
107 .I service
108 argument, identifying an Internet host and a service.
109 The
110 .I ar_request
111 element corresponds to the
112 .I hints
113 argument, specifying the criteria for selecting
114 the returned socket address structures.
115 Finally,
116 .I ar_result
117 corresponds to the
118 .I res
119 argument; you do not need to initialize this element,
120 it will be automatically set when the request
121 is resolved.
122 The
123 .I addrinfo
124 structure referenced by the last two elements is described in
125 .BR getaddrinfo (3).
126
127 When
128 .I mode
129 is specified as
130 .BR GAI_NOWAIT ,
131 notifications about resolved requests
132 can be obtained by employing the
133 .I sigevent
134 structure pointed to by the
135 .I sevp
136 argument.
137 For the definition and general details of this structure, see
138 .BR sigevent (7).
139 The
140 .I sevp\->sigev_notify
141 field can have the following values:
142 .TP
143 .BR SIGEV_NONE
144 Don't provide any notification.
145 .TP
146 .BR SIGEV_SIGNAL
147 When a look-up completes, generate the signal
148 .I sigev_signo
149 for the process.
150 See
151 .BR sigevent (7)
152 for general details.
153 The
154 .I si_code
155 field of the
156 .I siginfo_t
157 structure will be set to
158 .BR SI_ASYNCNL .
159 .\" si_pid and si_uid are also set, to the values of the calling process,
160 .\" which doesn't provide useful information, so we'll skip mentioning it.
161 .TP
162 .BR SIGEV_THREAD
163 When a look-up completes, invoke
164 .I sigev_notify_function
165 as if it were the start function of a new thread.
166 See
167 .BR sigevent (7)
168 for details.
169 .PP
170 For
171 .BR SIGEV_SIGNAL
172 and
173 .BR SIGEV_THREAD ,
174 it may be useful to point
175 .IR sevp\->sigev_value.sival_ptr
176 to
177 .IR list .
178
179 The
180 .BR gai_suspend ()
181 function suspends execution of the calling thread,
182 waiting for the completion of one or more requests in the array
183 .IR list .
184 The
185 .I nitems
186 argument specifies the size of the array
187 .IR list .
188 The call blocks until one of the following occurs:
189 .IP * 3
190 One or more of the operations in
191 .I list
192 completes.
193 .IP *
194 The call is interrupted by a signal that is caught.
195 .IP *
196 The time interval specified in
197 .I timeout
198 elapses.
199 This argument specifies a timeout in seconds plus nanoseconds (see
200 .BR nanosleep (2)
201 for details of the
202 .I timespec
203 structure).
204 If
205 .I timeout
206 is NULL, then the call blocks indefinitely
207 (until one of the events above occurs).
208 .PP
209 No explicit indication of which request was completed is given;
210 you must determine which request(s) have completed by iterating with
211 .BR gai_error ()
212 over the list of requests.
213
214 The
215 .BR gai_error ()
216 function returns the status of the request
217 .IR req :
218 either
219 .B EAI_INPROGRESS
220 if the request was not completed yet,
221 0 if it was handled successfully,
222 or an error code if the request could not be resolved.
223
224 The
225 .BR gai_cancel ()
226 function cancels the request
227 .IR req .
228 If the request has been canceled successfully,
229 the error status of the request will be set to
230 .B EAI_CANCELLED
231 and normal asynchronous notification will be performed.
232 The request cannot be canceled if it is currently being processed;
233 in that case, it will be handled as if
234 .BR gai_cancel ()
235 has never been called.
236 If
237 .I req
238 is NULL, an attempt is made to cancel all outstanding requests
239 that the process has made.
240 .SH "RETURN VALUE"
241 The
242 .BR getaddrinfo_a ()
243 function returns 0 if all of the requests have been enqueued successfully,
244 or one of the following nonzero error codes:
245 .TP
246 .B EAI_AGAIN
247 The resources necessary to enqueue the look-up requests were not available.
248 The application may check the error status of each
249 request to determine which ones failed.
250 .TP
251 .B EAI_MEMORY
252 Out of memory.
253 .TP
254 .B EAI_SYSTEM
255 .I mode
256 is invalid.
257 .PP
258 The
259 .BR gai_suspend ()
260 function returns 0 if at least one of the listed requests has been completed.
261 Otherwise, it returns one of the following nonzero error codes:
262 .TP
263 .B EAI_AGAIN
264 The given timeout expired before any of the requests could be completed.
265 .TP
266 .B EAI_ALLDONE
267 There were no actual requests given to the function.
268 .TP
269 .B EAI_INTR
270 A signal has interrupted the function.
271 Note that this interruption might have been
272 caused by signal notification of some completed look-up request.
273 .PP
274 The
275 .BR gai_error ()
276 function can return
277 .B EAI_INPROGRESS
278 for an unfinished look-up request,
279 0 for a successfully completed look-up
280 (as described above), one of the error codes that could be returned by
281 .BR getaddrinfo (3),
282 or the error code
283 .B EAI_CANCELLED
284 if the request has been canceled explicitly before it could be finished.
285
286 The
287 .BR gai_cancel ()
288 function can return one of these values:
289 .TP
290 .B EAI_CANCELLED
291 The request has been canceled successfully.
292 .TP
293 .B EAI_NOTCANCELLED
294 The request has not been canceled.
295 .TP
296 .B EAI_ALLDONE
297 The request has already completed.
298 .PP
299 The
300 .BR gai_strerror (3)
301 function translates these error codes to a human readable string,
302 suitable for error reporting.
303 .SH "CONFORMING TO"
304 These functions are GNU extensions;
305 they first appeared in glibc in version 2.2.3.
306 .SH NOTES
307 The interface of
308 .BR getaddrinfo_a ()
309 was modeled after the
310 .BR lio_listio (3)
311 interface.
312 .SH EXAMPLE
313 Two examples are provided: a simple example that resolves
314 several requests in parallel synchronously, and a complex example
315 showing some of the asynchronous capabilities.
316 .SS Synchronous Example
317 The program below simply resolves several hostnames in parallel,
318 giving a speed-up compared to resolving the hostnames sequentially using
319 .BR getaddrinfo (3).
320 The program might be used like this:
321 .in +4n
322 .nf
323
324 $ \fB./a.out ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz\fP
325 ftp.us.kernel.org: 128.30.2.36
326 enoent.linuxfoundation.org: Name or service not known
327 gnu.cz: 87.236.197.13
328 .fi
329 .in
330 .PP
331 Here is the program source code
332 .nf
333
334 #define _GNU_SOURCE
335 #include <netdb.h>
336 #include <stdio.h>
337 #include <stdlib.h>
338 #include <string.h>
339
340 int
341 main(int argc, char *argv[])
342 {
343     int i, ret;
344     struct gaicb *reqs[argc \- 1];
345     char host[NI_MAXHOST];
346     struct addrinfo *res;
347
348     if (argc < 2) {
349         fprintf(stderr, "Usage: %s HOST...\\n", argv[0]);
350         exit(EXIT_FAILURE);
351     }
352
353     for (i = 0; i < argc \- 1; i++) {
354         reqs[i] = malloc(sizeof(*reqs[0]));
355         if (reqs[i] == NULL) {
356             perror("malloc");
357             exit(EXIT_FAILURE);
358         }
359         memset(reqs[i], 0, sizeof(*reqs[0]));
360         reqs[i]\->ar_name = argv[i + 1];
361     }
362
363     ret = getaddrinfo_a(GAI_WAIT, reqs, argc \- 1, NULL);
364     if (ret != 0) {
365         fprintf(stderr, "getaddrinfo_a() failed: %s\\n",
366                 gai_strerror(ret));
367         exit(EXIT_FAILURE);
368     }
369
370     for (i = 0; i < argc \- 1; i++) {
371         printf("%s: ", reqs[i]\->ar_name);
372         ret = gai_error(reqs[i]);
373         if (ret == 0) {
374             res = reqs[i]\->ar_result;
375
376             ret = getnameinfo(res\->ai_addr, res\->ai_addrlen,
377                     host, sizeof(host),
378                     NULL, 0, NI_NUMERICHOST);
379             if (ret != 0) {
380                 fprintf(stderr, "getnameinfo() failed: %s\\n",
381                         gai_strerror(ret));
382                 exit(EXIT_FAILURE);
383             }
384             puts(host);
385
386         } else {
387             puts(gai_strerror(ret));
388         }
389     }
390     exit(EXIT_SUCCESS);
391 }
392 .fi
393
394 .SS Asynchronous Example
395 This example shows a simple interactive
396 .BR getaddrinfo_a ()
397 front-end.
398 The notification facility is not demonstrated.
399 .PP
400 An example session might look like like this:
401 .in +4n
402 .nf
403
404 $ \fB./a.out\fP
405 > a ftp.us.kernel.org enoent.linuxfoundation.org gnu.cz
406 > c 2
407 [2] gnu.cz: Request not canceled
408 > w 0 1
409 [00] ftp.us.kernel.org: Finished
410 > l
411 [00] ftp.us.kernel.org: 216.165.129.139
412 [01] enoent.linuxfoundation.org: Processing request in progress
413 [02] gnu.cz: 87.236.197.13
414 > l
415 [00] ftp.us.kernel.org: 216.165.129.139
416 [01] enoent.linuxfoundation.org: Name or service not known
417 [02] gnu.cz: 87.236.197.13
418 .fi
419 .in
420 .PP
421 The program source goes as follows:
422
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)