| .\" Copyright (c) 2007, 2008 Michael Kerrisk <mtk.manpages@gmail.com> |
| .\" and Copyright (c) 2006 Ulrich Drepper <drepper@redhat.com> |
| .\" A few pieces of an earlier version remain: |
| .\" Copyright 2000, Sam Varshavchik <mrsam@courier-mta.com> |
| .\" |
| .\" %%%LICENSE_START(VERBATIM) |
| .\" Permission is granted to make and distribute verbatim copies of this |
| .\" manual provided the copyright notice and this permission notice are |
| .\" preserved on all copies. |
| .\" |
| .\" Permission is granted to copy and distribute modified versions of this |
| .\" manual under the conditions for verbatim copying, provided that the |
| .\" entire resulting derived work is distributed under the terms of a |
| .\" permission notice identical to this one. |
| .\" |
| .\" Since the Linux kernel and libraries are constantly changing, this |
| .\" manual page may be incorrect or out-of-date. The author(s) assume no |
| .\" responsibility for errors or omissions, or for damages resulting from |
| .\" the use of the information contained herein. The author(s) may not |
| .\" have taken the same level of care in the production of this manual, |
| .\" which is licensed free of charge, as they might when working |
| .\" professionally. |
| .\" |
| .\" Formatted or processed versions of this manual, if unaccompanied by |
| .\" the source, must acknowledge the copyright and authors of this work. |
| .\" %%%LICENSE_END |
| .\" |
| .\" References: RFC 2553 |
| .\" |
| .\" 2005-08-09, mtk, added AI_ALL, AI_ADDRCONFIG, AI_V4MAPPED, |
| .\" and AI_NUMERICSERV. |
| .\" 2006-11-25, Ulrich Drepper <drepper@redhat.com> |
| .\" Add text describing Internationalized Domain Name extensions. |
| .\" 2007-06-08, mtk: added example programs |
| .\" 2008-02-26, mtk; clarify discussion of NULL 'hints' argument; other |
| .\" minor rewrites. |
| .\" 2008-06-18, mtk: many parts rewritten |
| .\" 2008-12-04, Petr Baudis <pasky@suse.cz> |
| .\" Describe results ordering and reference /etc/gai.conf. |
| .\" |
| .\" FIXME . glibc's 2.9 NEWS file documents DCCP and UDP-lite support |
| .\" and is SCTP support now also there? |
| .\" |
| .TH GETADDRINFO 3 2016-03-15 "GNU" "Linux Programmer's Manual" |
| .SH NAME |
| getaddrinfo, freeaddrinfo, gai_strerror \- network address and |
| service translation |
| .SH SYNOPSIS |
| .nf |
| .B #include <sys/types.h> |
| .B #include <sys/socket.h> |
| .B #include <netdb.h> |
| .sp |
| .BI "int getaddrinfo(const char *" "node" ", const char *" "service" , |
| .BI " const struct addrinfo *" "hints" , |
| .BI " struct addrinfo **" "res" ); |
| .sp |
| .BI "void freeaddrinfo(struct addrinfo *" "res" ); |
| .sp |
| .BI "const char *gai_strerror(int " "errcode" ); |
| .fi |
| .sp |
| .in -4n |
| Feature Test Macro Requirements for glibc (see |
| .BR feature_test_macros (7)): |
| .ad l |
| .in |
| .sp |
| .BR getaddrinfo (), |
| .BR freeaddrinfo (), |
| .BR gai_strerror (): |
| Since glibc 2.22: _POSIX_C_SOURCE >= 201112L |
| Glibc 2.21 and earlier: _POSIX_C_SOURCE |
| .ad b |
| .SH DESCRIPTION |
| Given |
| .I node |
| and |
| .IR service , |
| which identify an Internet host and a service, |
| .BR getaddrinfo () |
| returns one or more |
| .I addrinfo |
| structures, each of which contains an Internet address |
| that can be specified in a call to |
| .BR bind (2) |
| or |
| .BR connect (2). |
| The |
| .BR getaddrinfo () |
| function combines the functionality provided by the |
| .\" .BR getipnodebyname (3), |
| .\" .BR getipnodebyaddr (3), |
| .BR gethostbyname (3) |
| and |
| .BR getservbyname (3) |
| functions into a single interface, but unlike the latter functions, |
| .BR getaddrinfo () |
| is reentrant and allows programs to eliminate IPv4-versus-IPv6 dependencies. |
| .PP |
| The |
| .I addrinfo |
| structure used by |
| .BR getaddrinfo () |
| contains the following fields: |
| .sp |
| .in +4n |
| .nf |
| struct addrinfo { |
| int ai_flags; |
| int ai_family; |
| int ai_socktype; |
| int ai_protocol; |
| socklen_t ai_addrlen; |
| struct sockaddr *ai_addr; |
| char *ai_canonname; |
| struct addrinfo *ai_next; |
| }; |
| .fi |
| .in |
| .PP |
| The |
| .I hints |
| argument points to an |
| .I addrinfo |
| structure that specifies criteria for selecting the socket address |
| structures returned in the list pointed to by |
| .IR res . |
| If |
| .I hints |
| is not NULL it points to an |
| .I addrinfo |
| structure whose |
| .IR ai_family , |
| .IR ai_socktype , |
| and |
| .I ai_protocol |
| specify criteria that limit the set of socket addresses returned by |
| .BR getaddrinfo (), |
| as follows: |
| .TP 12 |
| .I ai_family |
| This field specifies the desired address family for the returned addresses. |
| Valid values for this field include |
| .BR AF_INET |
| and |
| .BR AF_INET6 . |
| The value |
| .B AF_UNSPEC |
| indicates that |
| .BR getaddrinfo () |
| should return socket addresses for any address family |
| (either IPv4 or IPv6, for example) that can be used with |
| .I node |
| and |
| .IR service . |
| .TP |
| .I ai_socktype |
| This field specifies the preferred socket type, for example |
| .BR SOCK_STREAM |
| or |
| .BR SOCK_DGRAM . |
| Specifying 0 in this field indicates that socket addresses of any type |
| can be returned by |
| .BR getaddrinfo (). |
| .TP |
| .I ai_protocol |
| This field specifies the protocol for the returned socket addresses. |
| Specifying 0 in this field indicates that socket addresses with |
| any protocol can be returned by |
| .BR getaddrinfo (). |
| .TP |
| .I ai_flags |
| This field specifies additional options, described below. |
| Multiple flags are specified by bitwise OR-ing them together. |
| .PP |
| All the other fields in the structure pointed to by |
| .I hints |
| must contain either 0 or a null pointer, as appropriate. |
| .PP |
| Specifying |
| .I hints |
| as NULL is equivalent to setting |
| .I ai_socktype |
| and |
| .I ai_protocol |
| to 0; |
| .I ai_family |
| to |
| .BR AF_UNSPEC ; |
| and |
| .I ai_flags |
| to |
| .BR "(AI_V4MAPPED\ |\ AI_ADDRCONFIG)" . |
| (POSIX specifies different defaults for |
| .IR ai_flags ; |
| see NOTES.) |
| .I node |
| specifies either a numerical network address |
| (for IPv4, numbers-and-dots notation as supported by |
| .BR inet_aton (3); |
| for IPv6, hexadecimal string format as supported by |
| .BR inet_pton (3)), |
| or a network hostname, whose network addresses are looked up and resolved. |
| If |
| .I hints.ai_flags |
| contains the |
| .B AI_NUMERICHOST |
| flag, then |
| .I node |
| must be a numerical network address. |
| The |
| .B AI_NUMERICHOST |
| flag suppresses any potentially lengthy network host address lookups. |
| .PP |
| If the |
| .B AI_PASSIVE |
| flag is specified in |
| .IR hints.ai_flags , |
| and |
| .I node |
| is NULL, |
| then the returned socket addresses will be suitable for |
| .BR bind (2)ing |
| a socket that will |
| .BR accept (2) |
| connections. |
| The returned socket address will contain the "wildcard address" |
| .RB ( INADDR_ANY |
| for IPv4 addresses, |
| .BR IN6ADDR_ANY_INIT |
| for IPv6 address). |
| The wildcard address is used by applications (typically servers) |
| that intend to accept connections on any of the host's network addresses. |
| If |
| .I node |
| is not NULL, then the |
| .B AI_PASSIVE |
| flag is ignored. |
| .PP |
| If the |
| .B AI_PASSIVE |
| flag is not set in |
| .IR hints.ai_flags , |
| then the returned socket addresses will be suitable for use with |
| .BR connect (2), |
| .BR sendto (2), |
| or |
| .BR sendmsg (2). |
| If |
| .I node |
| is NULL, |
| then the network address will be set to the loopback interface address |
| .RB ( INADDR_LOOPBACK |
| for IPv4 addresses, |
| .BR IN6ADDR_LOOPBACK_INIT |
| for IPv6 address); |
| this is used by applications that intend to communicate |
| with peers running on the same host. |
| .PP |
| .I service |
| sets the port in each returned address structure. |
| If this argument is a service name (see |
| .BR services (5)), |
| it is translated to the corresponding port number. |
| This argument can also be specified as a decimal number, |
| which is simply converted to binary. |
| If |
| .I service |
| is NULL, then the port number of the returned socket addresses |
| will be left uninitialized. |
| If |
| .B AI_NUMERICSERV |
| is specified in |
| .I hints.ai_flags |
| and |
| .I service |
| is not NULL, then |
| .I service |
| must point to a string containing a numeric port number. |
| This flag is used to inhibit the invocation of a name resolution service |
| in cases where it is known not to be required. |
| .PP |
| Either |
| .I node |
| or |
| .IR service , |
| but not both, may be NULL. |
| .PP |
| The |
| .BR getaddrinfo () |
| function allocates and initializes a linked list of |
| .I addrinfo |
| structures, one for each network address that matches |
| .I node |
| and |
| .IR service , |
| subject to any restrictions imposed by |
| .IR hints , |
| and returns a pointer to the start of the list in |
| .IR res . |
| The items in the linked list are linked by the |
| .I ai_next |
| field. |
| |
| There are several reasons why |
| the linked list may have more than one |
| .I addrinfo |
| structure, including: the network host is multihomed, accessible |
| over multiple protocols (e.g., both |
| .BR AF_INET |
| and |
| .BR AF_INET6 ); |
| or the same service is available from multiple socket types (one |
| .B SOCK_STREAM |
| address and another |
| .B SOCK_DGRAM |
| address, for example). |
| Normally, the application should try |
| using the addresses in the order in which they are returned. |
| The sorting function used within |
| .BR getaddrinfo () |
| is defined in RFC\ 3484; the order can be tweaked for a particular |
| system by editing |
| .IR /etc/gai.conf |
| (available since glibc 2.5). |
| .PP |
| If |
| .I hints.ai_flags |
| includes the |
| .B AI_CANONNAME |
| flag, then the |
| .I ai_canonname |
| field of the first of the |
| .I addrinfo |
| structures in the returned list is set to point to the |
| official name of the host. |
| .\" In glibc prior to 2.3.4, the ai_canonname of each addrinfo |
| .\" structure was set pointing to the canonical name; that was |
| .\" more than POSIX.1-2001 specified, or other implementations provided. |
| .\" MTK, Aug 05 |
| |
| The remaining fields of each returned |
| .I addrinfo |
| structure are initialized as follows: |
| .IP * 2 |
| The |
| .IR ai_family , |
| .IR ai_socktype , |
| and |
| .I ai_protocol |
| fields return the socket creation parameters (i.e., these fields have |
| the same meaning as the corresponding arguments of |
| .BR socket (2)). |
| For example, |
| .I ai_family |
| might return |
| .B AF_INET |
| or |
| .BR AF_INET6 ; |
| .I ai_socktype |
| might return |
| .B SOCK_DGRAM |
| or |
| .BR SOCK_STREAM ; |
| and |
| .I ai_protocol |
| returns the protocol for the socket. |
| .IP * |
| A pointer to the socket address is placed in the |
| .I ai_addr |
| field, and the length of the socket address, in bytes, |
| is placed in the |
| .I ai_addrlen |
| field. |
| .PP |
| If |
| .I hints.ai_flags |
| includes the |
| .B AI_ADDRCONFIG |
| flag, then IPv4 addresses are returned in the list pointed to by |
| .I res |
| only if the local system has at least one |
| IPv4 address configured, and IPv6 addresses are returned |
| only if the local system has at least one IPv6 address configured. |
| The loopback address is not considered for this case as valid |
| as a configured address. |
| This flag is useful on, for example, |
| IPv4-only systems, to ensure that |
| .BR getaddrinfo () |
| does not return IPv6 socket addresses that would always fail in |
| .BR connect (2) |
| or |
| .BR bind (2). |
| .PP |
| If |
| .I hints.ai_flags |
| specifies the |
| .B AI_V4MAPPED |
| flag, and |
| .I hints.ai_family |
| was specified as |
| .BR AF_INET6 , |
| and no matching IPv6 addresses could be found, |
| then return IPv4-mapped IPv6 addresses in the list pointed to by |
| .IR res . |
| If both |
| .B AI_V4MAPPED |
| and |
| .B AI_ALL |
| are specified in |
| .IR hints.ai_flags , |
| then return both IPv6 and IPv4-mapped IPv6 addresses |
| in the list pointed to by |
| .IR res . |
| .B AI_ALL |
| is ignored if |
| .B AI_V4MAPPED |
| is not also specified. |
| .PP |
| The |
| .BR freeaddrinfo () |
| function frees the memory that was allocated |
| for the dynamically allocated linked list |
| .IR res . |
| .SS Extensions to getaddrinfo() for Internationalized Domain Names |
| .PP |
| Starting with glibc 2.3.4, |
| .BR getaddrinfo () |
| has been extended to selectively allow the incoming and outgoing |
| hostnames to be transparently converted to and from the |
| Internationalized Domain Name (IDN) format (see RFC 3490, |
| .IR "Internationalizing Domain Names in Applications (IDNA)" ). |
| Four new flags are defined: |
| .TP |
| .B AI_IDN |
| If this flag is specified, then the node name given in |
| .I node |
| is converted to IDN format if necessary. |
| The source encoding is that of the current locale. |
| |
| If the input name contains non-ASCII characters, then the IDN encoding |
| is used. |
| Those parts of the node name (delimited by dots) that contain |
| non-ASCII characters are encoded using ASCII Compatible Encoding (ACE) |
| before being passed to the name resolution functions. |
| .\" Implementation Detail: |
| .\" To minimize effects on system performance the implementation might |
| .\" want to check whether the input string contains any non-ASCII |
| .\" characters. If there are none the IDN step can be skipped completely. |
| .\" On systems which allow not-ASCII safe encodings for a locale this |
| .\" might be a problem. |
| .TP |
| .B AI_CANONIDN |
| After a successful name lookup, and if the |
| .B AI_CANONNAME |
| flag was specified, |
| .BR getaddrinfo () |
| will return the canonical name of the |
| node corresponding to the |
| .I addrinfo |
| structure value passed back. |
| The return value is an exact copy of the value returned by the name |
| resolution function. |
| |
| If the name is encoded using ACE, then it will contain the |
| .I xn\-\- |
| prefix for one or more components of the name. |
| To convert these components into a readable form the |
| .B AI_CANONIDN |
| flag can be passed in addition to |
| .BR AI_CANONNAME . |
| The resulting string is encoded using the current locale's encoding. |
| .\" |
| .\"Implementation Detail: |
| .\"If no component of the returned name starts with xn\-\- the IDN |
| .\"step can be skipped, therefore avoiding unnecessary slowdowns. |
| .TP |
| .BR AI_IDN_ALLOW_UNASSIGNED ", " AI_IDN_USE_STD3_ASCII_RULES |
| Setting these flags will enable the |
| IDNA_ALLOW_UNASSIGNED (allow unassigned Unicode code points) and |
| IDNA_USE_STD3_ASCII_RULES (check output to make sure it is a STD3 |
| conforming hostname) |
| flags respectively to be used in the IDNA handling. |
| .SH RETURN VALUE |
| .\" FIXME glibc defines the following additional errors, some which |
| .\" can probably be returned by getaddrinfo(); they need to |
| .\" be documented. |
| .\" #ifdef __USE_GNU |
| .\" #define EAI_INPROGRESS -100 /* Processing request in progress. */ |
| .\" #define EAI_CANCELED -101 /* Request canceled. */ |
| .\" #define EAI_NOTCANCELED -102 /* Request not canceled. */ |
| .\" #define EAI_ALLDONE -103 /* All requests done. */ |
| .\" #define EAI_INTR -104 /* Interrupted by a signal. */ |
| .\" #define EAI_IDN_ENCODE -105 /* IDN encoding failed. */ |
| .\" #endif |
| .BR getaddrinfo () |
| returns 0 if it succeeds, or one of the following nonzero error codes: |
| .TP |
| .B EAI_ADDRFAMILY |
| .\" Not in SUSv3 |
| The specified network host does not have any network addresses in the |
| requested address family. |
| .TP |
| .B EAI_AGAIN |
| The name server returned a temporary failure indication. |
| Try again later. |
| .TP |
| .B EAI_BADFLAGS |
| .I hints.ai_flags |
| contains invalid flags; or, |
| .I hints.ai_flags |
| included |
| .B AI_CANONNAME |
| and |
| .I name |
| was NULL. |
| .TP |
| .B EAI_FAIL |
| The name server returned a permanent failure indication. |
| .TP |
| .B EAI_FAMILY |
| The requested address family is not supported. |
| .TP |
| .B EAI_MEMORY |
| Out of memory. |
| .TP |
| .B EAI_NODATA |
| .\" Not in SUSv3 |
| The specified network host exists, but does not have any |
| network addresses defined. |
| .TP |
| .B EAI_NONAME |
| The |
| .I node |
| or |
| .I service |
| is not known; or both |
| .I node |
| and |
| .I service |
| are NULL; or |
| .B AI_NUMERICSERV |
| was specified in |
| .I hints.ai_flags |
| and |
| .I service |
| was not a numeric port-number string. |
| .TP |
| .B EAI_SERVICE |
| The requested service is not available for the requested socket type. |
| It may be available through another socket type. |
| For example, this error could occur if |
| .I service |
| was "shell" (a service available only on stream sockets), and either |
| .I hints.ai_protocol |
| was |
| .BR IPPROTO_UDP , |
| or |
| .I hints.ai_socktype |
| was |
| .BR SOCK_DGRAM ; |
| or the error could occur if |
| .I service |
| was not NULL, and |
| .I hints.ai_socktype |
| was |
| .BR SOCK_RAW |
| (a socket type that does not support the concept of services). |
| .TP |
| .B EAI_SOCKTYPE |
| The requested socket type is not supported. |
| This could occur, for example, if |
| .I hints.ai_socktype |
| and |
| .I hints.ai_protocol |
| are inconsistent (e.g., |
| .BR SOCK_DGRAM |
| and |
| .BR IPPROTO_TCP , |
| respectively). |
| .TP |
| .B EAI_SYSTEM |
| Other system error, check |
| .I errno |
| for details. |
| .PP |
| The |
| .BR gai_strerror () |
| function translates these error codes to a human readable string, |
| suitable for error reporting. |
| .SH FILES |
| .I /etc/gai.conf |
| .SH ATTRIBUTES |
| For an explanation of the terms used in this section, see |
| .BR attributes (7). |
| .TS |
| allbox; |
| lbw15 lb lb |
| l l l. |
| Interface Attribute Value |
| T{ |
| .BR getaddrinfo () |
| T} Thread safety MT-Safe env locale |
| T{ |
| .BR freeaddrinfo (), |
| .BR gai_strerror () |
| T} Thread safety MT-Safe |
| .TE |
| |
| .SH CONFORMING TO |
| POSIX.1-2001, POSIX.1-2008. |
| The |
| .BR getaddrinfo () |
| function is documented in RFC\ 2553. |
| .SH NOTES |
| .BR getaddrinfo () |
| supports the |
| .IB address % scope-id |
| notation for specifying the IPv6 scope-ID. |
| |
| .BR AI_ADDRCONFIG , |
| .BR AI_ALL , |
| and |
| .B AI_V4MAPPED |
| are available since glibc 2.3.3. |
| .B AI_NUMERICSERV |
| is available since glibc 2.3.4. |
| |
| According to POSIX.1, specifying |
| .\" POSIX.1-2001, POSIX.1-2008 |
| .I hints |
| as NULL should cause |
| .I ai_flags |
| to be assumed as 0. |
| The GNU C library instead assumes a value of |
| .BR "(AI_V4MAPPED\ |\ AI_ADDRCONFIG)" |
| for this case, |
| since this value is considered an improvement on the specification. |
| .SH EXAMPLE |
| .\" getnameinfo.3 refers to this example |
| .\" socket.2 refers to this example |
| .\" bind.2 refers to this example |
| .\" connect.2 refers to this example |
| .\" recvfrom.2 refers to this example |
| .\" sendto.2 refers to this example |
| The following programs demonstrate the use of |
| .BR getaddrinfo (), |
| .BR gai_strerror (), |
| .BR freeaddrinfo (), |
| and |
| .BR getnameinfo (3). |
| The programs are an echo server and client for UDP datagrams. |
| .SS Server program |
| \& |
| .nf |
| #include <sys/types.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <sys/socket.h> |
| #include <netdb.h> |
| |
| #define BUF_SIZE 500 |
| |
| int |
| main(int argc, char *argv[]) |
| { |
| struct addrinfo hints; |
| struct addrinfo *result, *rp; |
| int sfd, s; |
| struct sockaddr_storage peer_addr; |
| socklen_t peer_addr_len; |
| ssize_t nread; |
| char buf[BUF_SIZE]; |
| |
| if (argc != 2) { |
| fprintf(stderr, "Usage: %s port\\n", argv[0]); |
| exit(EXIT_FAILURE); |
| } |
| |
| memset(&hints, 0, sizeof(struct addrinfo)); |
| hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ |
| hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ |
| hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ |
| hints.ai_protocol = 0; /* Any protocol */ |
| hints.ai_canonname = NULL; |
| hints.ai_addr = NULL; |
| hints.ai_next = NULL; |
| |
| s = getaddrinfo(NULL, argv[1], &hints, &result); |
| if (s != 0) { |
| fprintf(stderr, "getaddrinfo: %s\\n", gai_strerror(s)); |
| exit(EXIT_FAILURE); |
| } |
| |
| /* getaddrinfo() returns a list of address structures. |
| Try each address until we successfully bind(2). |
| If socket(2) (or bind(2)) fails, we (close the socket |
| and) try the next address. */ |
| |
| for (rp = result; rp != NULL; rp = rp\->ai_next) { |
| sfd = socket(rp\->ai_family, rp\->ai_socktype, |
| rp\->ai_protocol); |
| if (sfd == \-1) |
| continue; |
| |
| if (bind(sfd, rp\->ai_addr, rp\->ai_addrlen) == 0) |
| break; /* Success */ |
| |
| close(sfd); |
| } |
| |
| if (rp == NULL) { /* No address succeeded */ |
| fprintf(stderr, "Could not bind\\n"); |
| exit(EXIT_FAILURE); |
| } |
| |
| freeaddrinfo(result); /* No longer needed */ |
| |
| /* Read datagrams and echo them back to sender */ |
| |
| for (;;) { |
| peer_addr_len = sizeof(struct sockaddr_storage); |
| nread = recvfrom(sfd, buf, BUF_SIZE, 0, |
| (struct sockaddr *) &peer_addr, &peer_addr_len); |
| if (nread == \-1) |
| continue; /* Ignore failed request */ |
| |
| char host[NI_MAXHOST], service[NI_MAXSERV]; |
| |
| s = getnameinfo((struct sockaddr *) &peer_addr, |
| peer_addr_len, host, NI_MAXHOST, |
| service, NI_MAXSERV, NI_NUMERICSERV); |
| if (s == 0) |
| printf("Received %zd bytes from %s:%s\\n", |
| nread, host, service); |
| else |
| fprintf(stderr, "getnameinfo: %s\\n", gai_strerror(s)); |
| |
| if (sendto(sfd, buf, nread, 0, |
| (struct sockaddr *) &peer_addr, |
| peer_addr_len) != nread) |
| fprintf(stderr, "Error sending response\\n"); |
| } |
| } |
| .fi |
| .SS Client program |
| \& |
| .nf |
| #include <sys/types.h> |
| #include <sys/socket.h> |
| #include <netdb.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <string.h> |
| |
| #define BUF_SIZE 500 |
| |
| int |
| main(int argc, char *argv[]) |
| { |
| struct addrinfo hints; |
| struct addrinfo *result, *rp; |
| int sfd, s, j; |
| size_t len; |
| ssize_t nread; |
| char buf[BUF_SIZE]; |
| |
| if (argc < 3) { |
| fprintf(stderr, "Usage: %s host port msg...\\n", argv[0]); |
| exit(EXIT_FAILURE); |
| } |
| |
| /* Obtain address(es) matching host/port */ |
| |
| memset(&hints, 0, sizeof(struct addrinfo)); |
| hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ |
| hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ |
| hints.ai_flags = 0; |
| hints.ai_protocol = 0; /* Any protocol */ |
| |
| s = getaddrinfo(argv[1], argv[2], &hints, &result); |
| if (s != 0) { |
| fprintf(stderr, "getaddrinfo: %s\\n", gai_strerror(s)); |
| exit(EXIT_FAILURE); |
| } |
| |
| /* getaddrinfo() returns a list of address structures. |
| Try each address until we successfully connect(2). |
| If socket(2) (or connect(2)) fails, we (close the socket |
| and) try the next address. */ |
| |
| for (rp = result; rp != NULL; rp = rp\->ai_next) { |
| sfd = socket(rp\->ai_family, rp\->ai_socktype, |
| rp\->ai_protocol); |
| if (sfd == \-1) |
| continue; |
| |
| if (connect(sfd, rp\->ai_addr, rp\->ai_addrlen) != \-1) |
| break; /* Success */ |
| |
| close(sfd); |
| } |
| |
| if (rp == NULL) { /* No address succeeded */ |
| fprintf(stderr, "Could not connect\\n"); |
| exit(EXIT_FAILURE); |
| } |
| |
| freeaddrinfo(result); /* No longer needed */ |
| |
| /* Send remaining command\-line arguments as separate |
| datagrams, and read responses from server */ |
| |
| for (j = 3; j < argc; j++) { |
| len = strlen(argv[j]) + 1; |
| /* +1 for terminating null byte */ |
| |
| if (len + 1 > BUF_SIZE) { |
| fprintf(stderr, |
| "Ignoring long message in argument %d\\n", j); |
| continue; |
| } |
| |
| if (write(sfd, argv[j], len) != len) { |
| fprintf(stderr, "partial/failed write\\n"); |
| exit(EXIT_FAILURE); |
| } |
| |
| nread = read(sfd, buf, BUF_SIZE); |
| if (nread == \-1) { |
| perror("read"); |
| exit(EXIT_FAILURE); |
| } |
| |
| printf("Received %zd bytes: %s\\n", nread, buf); |
| } |
| |
| exit(EXIT_SUCCESS); |
| } |
| .fi |
| .SH SEE ALSO |
| .\" .BR getipnodebyaddr (3), |
| .\" .BR getipnodebyname (3), |
| .BR getaddrinfo_a (3), |
| .BR gethostbyname (3), |
| .BR getnameinfo (3), |
| .BR inet (3), |
| .BR gai.conf (5), |
| .BR hostname (7), |
| .BR ip (7) |