1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
|
GETADDRINFO(3) BSD Library Functions Manual GETADDRINFO(3)
NAME
getaddrinfo, freeaddrinfo, gai_strerror -- nodename-to-address translation in protocol-inde-
pendent manner
LIBRARY
Standard C Library (libc, -lc)
SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int
getaddrinfo(const char *nodename, const char *servname, const struct addrinfo *hints,
struct addrinfo **res);
void
freeaddrinfo(struct addrinfo *ai);
char *
gai_strerror(int ecode);
DESCRIPTION
The getaddrinfo() function is defined for protocol-independent nodename-to-address transla-
tion. It performs the functionality of gethostbyname(3) and getservbyname(3), but in a more
sophisticated manner.
The addrinfo structure is defined as a result of including the <netdb.h> header:
struct addrinfo {
int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
int ai_family; /* PF_xxx */
int ai_socktype; /* SOCK_xxx */
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
size_t ai_addrlen; /* length of ai_addr */
char *ai_canonname; /* canonical name for nodename */
struct sockaddr *ai_addr; /* binary address */
struct addrinfo *ai_next; /* next structure in linked list */
};
The nodename and servname arguments are pointers to null-terminated strings or NULL. One or
both of these two arguments must be a non-NULL pointer. In the normal client scenario, both
the nodename and servname are specified. In the normal server scenario, only the servname
is specified. A non-NULL nodename string can be either a node name or a numeric host ad-
dress string (i.e., a dotted-decimal IPv4 address or an IPv6 hex address). A non-NULL
servname string can be either a service name or a decimal port number.
The caller can optionally pass an addrinfo structure, pointed to by the third argument, to
provide hints concerning the type of socket that the caller supports. In this hints struc-
ture all members other than ai_flags, ai_family, ai_socktype, and ai_protocol must be zero
or a NULL pointer. A value of PF_UNSPEC for ai_family means the caller will accept any pro-
tocol family. A value of 0 for ai_socktype means the caller will accept any socket type. A
value of 0 for ai_protocol means the caller will accept any protocol. For example, if the
caller handles only TCP and not UDP, then the ai_socktype member of the hints structure
should be set to SOCK_STREAM when getaddrinfo() is called. If the caller handles only IPv4
and not IPv6, then the ai_family member of the hints structure should be set to PF_INET when
getaddrinfo() is called. If the third argument to getaddrinfo() is a NULL pointer, this is
the same as if the caller had filled in an addrinfo structure initialized to zero with
ai_family set to PF_UNSPEC.
Upon successful return a pointer to a linked list of one or more addrinfo structures is re-
turned through the final argument. The caller can process each addrinfo structure in this
list by following the ai_next pointer, until a NULL pointer is encountered. In each re-
turned addrinfo structure the three members ai_family, ai_socktype, and ai_protocol are the
corresponding arguments for a call to the socket() function. In each addrinfo structure the
ai_addr member points to a filled-in socket address structure whose length is specified by
the ai_addrlen member.
If the AI_PASSIVE bit is set in the ai_flags member of the hints structure, then the caller
plans to use the returned socket address structure in a call to bind(). In this case, if
the nodename argument is a NULL pointer, then the IP address portion of the socket address
structure will be set to INADDR_ANY for an IPv4 address or IN6ADDR_ANY_INIT for an IPv6 ad-
dress.
If the AI_PASSIVE bit is not set in the ai_flags member of the hints structure, then the re-
turned socket address structure will be ready for a call to connect() (for a connection-ori-
ented protocol) or either connect(), sendto(), or sendmsg() (for a connectionless protocol).
In this case, if the nodename argument is a NULL pointer, then the IP address portion of the
socket address structure will be set to the loopback address.
If the AI_CANONNAME bit is set in the ai_flags member of the hints structure, then upon suc-
cessful return the ai_canonname member of the first addrinfo structure in the linked list
will point to a null-terminated string containing the canonical name of the specified
nodename.
If the AI_NUMERICHOST bit is set in the ai_flags member of the hints structure, then a
non-NULL nodename string must be a numeric host address string. Otherwise an error of
EAI_NONAME is returned. This flag prevents any type of name resolution service (e.g., the
DNS) from being called.
The arguments to getaddrinfo() must be sufficiently consistent and unambiguous. Here are
some problem cases you may encounter:
+o getaddrinfo() will fail if the members in the hints structure are not consistent. For
example, for internet address families, getaddrinfo() will fail if you specify
SOCK_STREAM to ai_socktype while you specify IPPROTO_UDP to ai_protocol.
+o If you specify a servname which is defined only for certain ai_socktype, getaddrinfo()
will fail because the arguments are not consistent. For example, getaddrinfo() will re-
turn an error if you ask for "tftp" service on SOCK_STREAM.
+o For internet address families, if you specify servname while you set ai_socktype to
SOCK_RAW, getaddrinfo() will fail, because service names are not defined for the inter-
net SOCK_RAW space.
+o If you specify numeric servname, while leaving ai_socktype and ai_protocol unspecified,
getaddrinfo() will fail. This is because the numeric servname does not identify any
socket type, and getaddrinfo() is not allowed to glob the argument in such case.
All of the information returned by getaddrinfo() is dynamically allocated: the addrinfo
structures, the socket address structures, and canonical node name strings pointed to by the
addrinfo structures. To return this information to the system the function freeaddrinfo()
is called. The addrinfo structure pointed to by the ai argument is freed, along with any
dynamic storage pointed to by the structure. This operation is repeated until a NULL
ai_next pointer is encountered.
To aid applications in printing error messages based on the EAI_xxx codes returned by
getaddrinfo(), gai_strerror() is defined. The argument is one of the EAI_xxx values defined
earlier and the return value points to a string describing the error. If the argument is
not one of the EAI_xxx values, the function still returns a pointer to a string whose con-
tents indicate an unknown error.
EXTENSIONS
This implementation supports numeric IPv6 address notation with the experimental scope iden-
tifier. By appending a percent sign and scope identifier to the address, you can specify
the value of the sin6_scope_id field of the socket address. This makes management of scoped
address easier, and allows cut-and-paste input of scoped addresses.
At the moment the code supports only link-local addresses in this format. The scope identi-
fier is hardcoded to name of hardware interface associated with the link, (such as ne0).
For example, "fe80::1%ne0", which means "fe80::1 on the link associated with the ne0
interface".
This implementation is still very experimental and non-standard. The current implementation
assumes a one-to-one relationship between interfaces and links, which is not necessarily
true according to the specification.
EXAMPLES
The following code tries to connect to "www.kame.net" service "http". via stream socket.
It loops through all the addresses available, regardless of the address family. If the des-
tination resolves to an IPv4 address, it will use an AF_INET socket. Similarly, if it re-
solves to IPv6, an AF_INET6 socket is used. Observe that there is no hardcoded reference to
particular address family. The code works even if getaddrinfo() returns addresses that are
not IPv4/v6.
struct addrinfo hints, *res, *res0;
int error;
int s;
const char *cause = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo("www.kame.net", "http", &hints, &res0);
if (error) {
errx(1, "%s", gai_strerror(error));
/*NOTREACHED*/
}
s = -1;
cause = "no addresses";
errno = EADDRNOTAVAIL;
for (res = res0; res; res = res->ai_next) {
s = socket(res->ai_family, res->ai_socktype,
res->ai_protocol);
if (s < 0) {
cause = "socket";
continue;
}
if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
cause = "connect";
close(s);
s = -1;
continue;
}
break; /* okay we got one */
}
if (s < 0) {
err(1, cause);
/*NOTREACHED*/
}
freeaddrinfo(res0);
The following example tries to open a wildcard listening socket onto service "http", for all
the address families available.
struct addrinfo hints, *res, *res0;
int error;
int s[MAXSOCK];
int nsock;
const char *cause = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
error = getaddrinfo(NULL, "http", &hints, &res0);
if (error) {
errx(1, "%s", gai_strerror(error));
/*NOTREACHED*/
}
nsock = 0;
for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) {
s[nsock] = socket(res->ai_family, res->ai_socktype,
res->ai_protocol);
if (s[nsock] < 0) {
cause = "socket";
continue;
}
if (bind(s[nsock], res->ai_addr, res->ai_addrlen) < 0) {
cause = "bind";
close(s[nsock]);
continue;
}
if (listen(s[nsock], SOMAXCONN) < 0) {
cause = "listen";
close(s[nsock]);
continue;
}
nsock++;
}
if (nsock == 0) {
err(1, cause);
/*NOTREACHED*/
}
freeaddrinfo(res0);
FILES
/etc/hosts
/etc/nsswitch.conf
/etc/resolv.conf
DIAGNOSTICS
Error return status from getaddrinfo() is zero on success and non-zero on errors. Non-zero
error codes are defined in <netdb.h>, and as follows:
EAI_ADDRFAMILY Address family for nodename not supported.
EAI_AGAIN Temporary failure in name resolution.
EAI_BADFLAGS Invalid value for ai_flags.
EAI_FAIL Non-recoverable failure in name resolution.
EAI_FAMILY ai_family not supported.
EAI_MEMORY Memory allocation failure.
EAI_NODATA No address associated with nodename.
EAI_NONAME nodename nor servname provided, or not known.
EAI_SERVICE servname not supported for ai_socktype.
EAI_SOCKTYPE ai_socktype not supported.
EAI_SYSTEM System error returned in errno.
EAI_BADHINTS Invalid value for hints.
EAI_PROTOCOL Resolved protocol is unknown.
EAI_MAX Unknown error.
If called with an appropriate argument, gai_strerror() returns a pointer to a string de-
scribing the given error code. If the argument is not one of the EAI_xxx values, the func-
tion still returns a pointer to a string whose contents indicate an unknown error.
SEE ALSO
gethostbyname(3), getnameinfo(3), getservbyname(3), hosts(5), resolv.conf(5), services(5),
hostname(7), named(8)
R. Gilligan, S. Thomson, J. Bound, and W. Stevens, Basic Socket Interface Extensions for
IPv6, RFC2553, March 1999.
Tatsuya Jinmei and Atsushi Onoe, An Extension of Format for IPv6 Scoped Addresses, internet
draft, draft-ietf-ipngwg-scopedaddr-format-02.txt, work in progress material.
Craig Metz, "Protocol Independence Using the Sockets API", Proceedings of the freenix track:
2000 USENIX annual technical conference, June 2000.
HISTORY
The implementation first appeared in WIDE Hydrangea IPv6 protocol stack kit.
STANDARDS
The getaddrinfo() function is defined in IEEE Std 1003.1g-2000 ("POSIX.1"), and documented
in "Basic Socket Interface Extensions for IPv6" (RFC2553).
BUGS
The current implementation is not thread-safe.
The text was shamelessly copied from RFC2553.
BSD May 25, 1995 BSD
|