|
Use the GETADDRINFO command
to resolve host or service name information.
This command translates the name of a service location
(host name) or a service name. The command returns a set of NAME strings
and associated information; this information can be used to create
a socket with which to address the specified service or to send a
datagram to the specified service. For information about the format of the NAME string, see How structures are represented.
Guideline: Use the application
to cycle through each NAME string until a successful connection is
established. An example is provided in Code example.
Format
>>-SOCKET--(--"GETADDRINFO"--,--node_service-------------------->
>--,--+-------+--,--+--------+---------------------------------->
'-flags-' '-family-'
>--,--+----------+--,--+----------+--,--+--------+--)----------><
'-socktype-' '-protocol-' '-eflags-'
Parameters - node_service
- This variable takes one of the following formats:
>>-node--,--+---------+----------------------------------------><
'-service-'
>>-+------+--,--service----------------------------------------><
'-node-'
where:- node
- The host name or IP address. If the value of the node parameter is an IP address, you also must issue the AI_NUMERICHOST
flag. The value of the node parameter can be up
to 255 bytes in length.
Scope information can be appended to the
host name, using the following format: "node%scope information"
For example, you could set the node parameter to "MYNODE%23". For more information, see z/OS® Communication
Server: IPv6 Network and Application Design Guide.
- service
- The TCP/IP service that is queried. If the value of the service parameter is a port number, you must specify the
AI_NUMERICSERV flag. The value of the service parameter
can be up to 32 bytes in length
- flags
- To specify multiple flags, code the flags parameter as a space-delimited string. The following flags are supported:
- AI_PASSIVE
- Specifies how to fill the returned socket NAME string. If this
flag is set, the returned NAME string can be used with the BIND command
to bind a socket for accepting new connection requests.
Rules: - If the AI_PASSIVE flag is specified and the node parameter is not specified, the IP address portion of the NAME string
is set to either the IPv4 address (INADDR_ANY) or to the IPv6 unspecified
address (in6addr_any).
- If the AI_PASSIVE flag is not specified, then the returned NAME
string can be used with the CONNECT or the SENDTO commands.
- If the AI_PASSIVE flag is not specified and the node parameter is not specified, the IP address portion of the NAME string
is set to the default loopback address: 127.0.0.1 (IPv4) or ::1 (IPv6).
If you issue the following command: src = socket("GETADDRINFO",,54123,"AI_PASSIVE","AF_UNSPEC")
Then the following string is returned: 0 '' AF_INET6 54123 0 ::0 0 AF_INET 54123 0.0.0.0
See example 2 in Code example for one method
of how to use this flag.
- AI_CANONNAMEOK
- Specifies that the canonical name that corresponds to the node parameter is returned. The node parameter must also be issued.
If you issue the following command: src = socket("GETADDRINFO","chile",21,"AI_CANONNAMEOK")
Then the following string is returned: 0 host.department.com AF_INET 21 10.11.103.1
- AI_NUMERICHOST
- If you specify this flag, the node parameter
must be specified as an IP address, for example, 10.11.103.1. Otherwise, the command fails with a 1 EAI_NONAME return code.
If you issue the following command: src = socket("GETADDRINFO","10.11.103.1",,"AI_NUMERICHOST")
Then the following string is returned: 0 '' AF_INET 0 10.11.103.1
- AI_NUMERICSERV
- If you specify this flag, you must specify the service parameter as a port number, for example, 1821. Otherwise, the command fails with a 1 EAI_NONAME return code.
If you issue the following command src = socket("GETADDRINFO",,23,"AI_NUMERICSERV")
Then the following string is returned. 0 '' AF_INET6 23 0 ::1 0 AF_INET 23 127.0.0.1
- AI_V4MAPPED
- If you specify this flag and the family is AF_INET6 or AF_UNSPEC,
the caller accepts IPv4-mapped IPv6 addresses.
Rules: - When the AI_ALL flag is not specified and no IPv6 addresses are
found, then a query is made for IPv4 addresses. Any IPv4 addresses
that are found are returned as IPv4-mapped IPv6 addresses.
- If the value of the family parameter is not
AF_INET6 or AF_UNSPEC, and if IPv6 is not supported on the system,
then this flag is ignored.
If you issue the following command: src = socket("GETADDRINFO","CHILE",,"AI_V4MAPPED AI_CANONNAMEOK");
Then the following string is returned: 0 host.department.com AF_INET6 0 0 ::FFFF:10.11.103.1 0
- AI_ALL
- If you specify this flag, the NAME strings that are returned depend
on the value of the family parameter.
Rules: - If this flag is specified and the value of the family parameter is AF_INET6, then the AI_V4MAPPED flag must also be set
to indicate that both IPv4-mapped IPv6 addresses and IPv6-mapped IP
addresses are acceptable.
- If value of the family parameter is AF_UNSPEC
and the system supports IPv6, then two queries are made. The first
query is for IPv6 addresses; if any are found, they are returned.
The second query is for IPv4 addresses. If the AI_V4MAPPED flag is
not specified, the IPv4 addresses are returned as IPv4 addresses.
If the AI_V4MAPPED flag is specified, theIPv4 addresses are returned
as IPv4-mapped IPv6 addresses.
- If the value of the family parameter is not
AF_INET6 or AF_UNSPEC, and if the system supports IPv6, then this
flag is ignored.
If you issue the following command: src = socket("GETADDRINFO","CHILE",,,
"AI_ALL AI_V4MAPPED AI_CANONNAMEOK",,
"AF_UNSPEC");
The following string is returned (all
on one line): 0 CHILE.department.com AF_INET6 0 0 ::FFFF:10.11.103.1 0
AF_INET6 0 0 2001:10:11:103::1 0
- AI_ADDRCONFIG
- If you specify this flag, the node is queried if the resolver
determines that one of the following conditions is true:
- The system is IPv6 enabled and has at least one IPv6 interface.
In this case, the resolver makes a query for AAAA DNS records (IPv6).
- The system is IPv4 enabled and has at least one IPv4 interface.
In this case, the resolver makes a query for A DNS records (IPv4).
The loopback address is not a valid interface for this flag.
- AI_EXTFLAGS
- If you specify this flag, the extended form of the getaddrinfo
function is requested. The extended form allows additional hints to
be passed to the resolver to determine the order of destination addresses
that are returned. This flag affects only the order of IPv6 addresses
that are returned, if any. If AI_EXTFLAGS flag is specified, the eflags parameter must be specified.
- family
- Limits the returned information to a specific address family.
The following families are supported:
- AF_UNSPEC
- Any protocol family. The value 0 is accepted also.
- AF_INET
- IPv4 families. The value 2 is accepted also.
- AF_INET6
- IPv6 families. The value 19 is accepted also.
- socktype
- Limits the returned information to a specific socket type. If
no socket type is specified, the command returns address information
for all types. The following socket types are supported:
Type name |
Decimal value |
Description |
---|
SOCK_STREAM |
1 |
Stream socket |
SOCK_DGRAM |
2 |
Datagram socket |
SOCK_RAW |
3 |
Raw-protocol interface |
Consider the following points: - If the value of the socktype parameter is set
to any value other than SOCK_STREAM, SOCK_DGRAM, or SOCK_RAW, the
GETADDRINFO command fails with a 9 EAI_SOCKTYPE return
code.
- If the value of the socktype parameter is SOCK_RAW,
the value of the service parameter must be numeric.
- If the value of the socktype parameter is set
to SOCK_STREAM or SOCK_DGRAM, then the resolver searches the services
file for a service name.
If the socktype and protocol parameters are both specified as 0, then the GETADDRINFO command
is processed in the following way: - If the value of the service parameter is null
or numeric, then any returned address information has the default socktype value of SOCK_STREAM.
- If the value of the service parameter is a
service name, for example, FTP, then the GETADDRINFO command searches
the appropriate services file twice. The first search uses SOCK_STREAM
as the protocol, and the second search uses SOCK_DGRAM as the protocol.
There is no default socket-type provision in this case.
If both the socktype and protocol parameters are specified as nonzero values, then
the values must be compatible, regardless of the value specified by
the service parameter. In this case, compatible
means one of the following combinations of parameters: - The socktype parameter is SOCK_STREAM and the protocol parameter is IPPROTO_TCP.
- The socktype parameter is SOCK_DGRAM and the protocol parameter is IPPROTO_UDP.
- The socktype parameter is SOCK_RAW, in which
case the protocol parameter can have any value.
- protocol
- Limits the returned information to a specific protocol. The value
0 indicates that the caller accepts any protocol. The following protocols
are supported:
Protocol name |
Decimal value |
Description |
---|
IPPROTO_TCP |
6 |
TCP |
IPPROTO_UDP |
16 |
UDP |
Consider the following points:
- If the socktype parameter is 0 and the protocol parameter is not 0, the only acceptable input
values for the protocol parameter are IPPROTO_TCP
and IPPROTO_UDP. If any other values are issued for the protocol parameter, the GETADDRINFO command fails with a 7 EAI_BADFLAGS return code.
- If the protocol and socktype parameters are both specified as 0, then the GETADDRINFO command
is processed in the following way:
- If the service parameter value is null or numeric,
then any returned address information assumes that the socket type
is SOCK_STREAM.
- If the service parameter is specified as a
service name, for example, FTP, then the GETADDRINFO command searches
the applicable services file twice. The first search uses the protocol
SOCK_STREAM, and the second search uses the protocol SOCK_DGRAM. There
is no default socket type provision in this case.
- If both the protocol and socktype parameters are specified as nonzero values, the values must be compatible,
regardless of the value that is specified by the service parameter. In this context, compatible means one of the following
combinations of parameters:
- The socktype parameter is SOCK_STREAM and the protocol parameter is IPPROTO_TCP.
- The socktype parameter is SOCK_DGRAM and the protocol parameter is IPPROTO_UDP.
- The socktype parameter is SOCK_RAW, in which
case the protocol parameter can have any value.
- If the lookup for the value specified by the service parameter fails (for example, the service name
does not appear in the applicable services file), then the GETADDRINFO
command fails with the 8 EAI_SERVICE return code.
- eflags
- A fullword binary field that specifies the source IPv6 address
selection preferences. If AI_EXTFLAGS flag is specified in FLAGS,
this field is required. To specify multiple eflags, code the eflags parameter as a space-delimited string.
This field
must have the value of 0 or of one or more of the following values:
- IPV6_PREFER_SRC_HOME
- Requests that resolver returns destination IPv6 addresses that
can be reached by a home IPv6 source address before it returns
destinations that can be reached by a care-of IPv6 source address.
This is the default behavior if AI_EXTFLAGS flag is not specified.
- IPV6_PREFER_SRC_COA
- Requests that resolver returns destination IPv6 addresses that
can be reached by a care-of IPv6 source address before it returns destinations that can be reached by a home IPv6 source address.
- IPV6_PREFER_SRC_PUBLIC
- Requests that resolver returns destination IPv6 addresses that
can be reached by a public IPv6 source address before it returns
destinations that can be reached by a temporary IPv6 source address.
- IPV6_PREFER_SRC_TMP
- Requests that the resolver returns destination IPv6 addresses
that can be reached by a temporary IPv6 source address before it returns destinations that can be reached by a public IPv6
source address.
- IPV6_PREFER_SRC_CGA
- Requests that resolver returns destination IPv6 addresses that
can be reached by a cryptographically generated IPv6 source address
before it returns destinations that can be reached by a non-cryptographically
generated IPv6 source address.
- IPV6_PREFER_SRC_NONCGA
- Requests that resolver returns destination IPv6 addresses that
can be reached by a non-cryptographically generated IPv6 source address
before it returns destinations that can be reached by a cryptographically
generated IPv6 source address.
- ZERO
- No preferences are specified.
Any EFLAGS specification other than the value of
0 or one of the options listed above causes an EINVALIDRXSOCKETCALL
error to be returned.
If contradictory EFLAGS, for example,
IPV6_PREFER_SRC_TMP and IPV6_PREFER_SRC_PUBLIC, are specified, the
GETADDRINFO call returns EINVALIDCOMBINATION.
Returned value The command returns a string
that contains the return code, canonical name, and a NAME string or
list of NAME strings. The return code can be 0, a REXX socket API error number, or the REXX TCP/IP error number that is set by the socket command. The return code 0 indicates that the requested socket command was completed successfully.
The following string is an example of what is returned
by the GETADDRINFO command: 0 RALEIGH.IBM.COM name1 name2 name3
In the example, 0 is the return code, RALEIGH.IBM.COM is the canonical
name, and name1 name2 name3 is a list of NAME strings.
Depending on the flags that were issued, these names can be IPv4 or
IPv6 values.
Tip: For a description of the format of
a socket name, see CONNECT or BIND.
See Socket call error return codes for additional information about the numeric error codes that are returned by this command.
The following REXX TCP/IP error numbers can be returned:- 1 EAI_NONAME
- 2 EAI_AGAIN
- 5 EAI_FAIMLY
- 6 EAI_MEMORY
- 7 EAI_BADFLAGS
- 8 EAI_SERVICE
- 9 EAI_SOCKTYPE
- 9 EBADF
- 35 EWOULDBLOCK
The following REXX socket API error numbers can be returned:- 2001 EINVALIDRXSOCKETCALL
- 2005 ESUBTASKNOTACTIVE
- 2006 ESOCKETNOTALLOCATED
LE C/C++ equivalent int getaddrinfo(const char *nodename, const char *servname,
const struct addrinfo *hints, struct addrinfo **res);
Code example/* REXX EZARXR05 */
/*
* This sample demonstrates a use of the GETADDRINFO command.
* It is possible that the GETADDRINFO command will return
* more then one name address. The program shows one
* technique that can be used to parse the information
* returned. After a successful connection has been established
* the program will sends data to a server listeneing on port
* 54777. The program then waits for a reply.
*
* HINT: The program code provided under the IOCTL command can
* be used as a server for this sample.
*
* GUIDELINE: It is generally recommended that a program loop around
* the RECV command to ensure that all data is read off
* the socket. This sample does not follow the guideline.
*/
src = socket("INITIALIZE","MYSET01",10);
if perror(src,"INITIALIZE") = 0 then do
src = socket("SOCKET","AF_INET6","SOCK_STREAM");
if perror(src,"SOCKET") \= 0 then signal ENDPROGRAM
parse var src l_retcode l_sockid
/* ****************************************************
* Issue GETADDRINFO command. Request that all IPv6 address
* information be returned, and if possible provide the
* canon name. IPV4 addresses are to be mapped to
* IPv6 mapped addresses. Names will be returned as AF_INET6
* NAMES.
* ****************************************************/
src = socket("GETADDRINFO","MVS150",54777,,
"AI_ALL AI_CANONNAMEOK AI_NUMERICSERV",
"AI_V4MAPPED","AF_INET6","SOCK_STREAM",,
"IPPROTO_TCP");
if perror(src,"GETADDRINFO") = 0 then do
parse var src l_retcode l_canonname l_names
l_LOCName = "AF_INET6 0 0 IN6ADDR_ANY 0";
src = socket("BIND", l_sockid, l_LOCname);
if perror(src,"BIND") \= 0 then signal ENDPROGRAM
/* **************************************************
* It is possible that GETADDRINFO returned multiple
* name structures. Cycle through them until a
* successful connection is achived or none are left.
* **************************************************/
l_done = "FALSE";
l_connectOK = "FALSE";
do while l_names \= '' | l_done = "FALSE"
if word(l_names,1) = "AF_INET6" then do
parse var l_names . l_port l_flow l_addr,
l_scope l_names
l_RMTname = "AF_INET6 "l_port" "l_flow" "l_addr,
||" "l_scope;
end; /* AF_INET6 */
else do
parse var l_names . l_port l_addr l_names
l_RMTname = "AF_INET "l_port" "l_addr;
end; /* AF_INET */
Say "Attempting connection using RMT NAME: ",
l_RMTname;
src = socket("CONNECT",l_sockid,l_RMTname);
if perror(src,"CONNECT") = 0 then do
Say "...Connected";
l_connectOK = "TRUE";
l_done = "TRUE";
end; /* CONNECT */
else do
l_done = "TRUE";
end;
end; /* DO LOOP */
if l_connectOK = "TRUE" then do
l_data = time() "**** **** **** **** ";
src = socket("GETSOCKNAME",l_sockid);
Say "GETSOCKNAME: "src;
src = socket("SEND",l_sockid,l_data);
if perror(src,"SEND") = 0 then do
src = socket("RECV",l_sockid);
if perror(src,"RECV") = 0 then do
parse var src . l_amtdata l_data
Say "Received " l_amtdata " bytes from ",
l_addr " on" port " l_port";
Say "The received data is: "l_data;
end; /* RECV */
end; /* SEND */
end; /* CONNECT OK */
else do /* CONNECT not OK */
say "No Connection to remote host could be",
"establisthed";
end;
end; /* GETADDRINFO */
end; /* INITIALIZE */
ENDPROGRAM:
src=socket("CLOSE",l_sockid);
src=perror(src,"CLOSE");
src=socket("TERMINATE","MYSET01");
src=perror(src,"TERMINATE");
exit 0;
/* This routine returns -1 if the first word if arg 1 is not zero */
perror: if word(arg(1),1) = 0 then return 0; else
Say arg(2) "Error : "arg(1);
return -1;
/* REXX EZARXR32 */
/*
* This example shows how to use the GETADDRINFO command
* to obtain a list of NAME constructs suitable for
* use with the BIND command using the well-known port 54123.
* The addr fields of the NAME constructs returned will be
* set to
*
* This example also shows how to use the SELECT command to
* monitor listening sockets for for new connections.
*
* In the case of 2 name constructs being returned the
* first successful bind will be used.
*
* HINT: To limit the NAME structures to a specific
* Address family change AF_UNSPEC to either
* AF_INET or AF_INET6
*
* HINT: Coding a hostname for the node paramter will result
* in the ipaddress fields of the NAME constructs to
* have a specific interface address assigned.
*
*/
l_selectlist = '';
src = socket("INITIALIZE","MYSET01");
src = socket("GETADDRINFO",,54123,"AI_PASSIVE",
"AI_CANONNAMEOK","AF_UNSPEC");
parse var src l_retcode l_canname l_names
l_bindok = "FALSE";
Say "Canonname returned is: "l_canname;
do while l_names \= ''
select
when word(l_names,1) = "AF_INET" then do
l_SockName = word(l_names,1) word(l_names,2),
word(l_names,3)
l_names = subword(l_names,4);
end;
when word(l_names,1) = "AF_INET6" then do
l_SockName = word(l_names,1) word(l_names,2),
word(l_names,3) word(l_names,4),
word(l_names,5);
l_names = subword(l_names,6);
end;
otherwise
l_sockname = "unknown";
end;
src=socket("SOCKET",word(l_sockname,1),"STREAM");
if word(src,1) = 0 then do
l_socket = word(src,2);
src = socket("BIND",l_socket1,l_sockname);
if word(src,1) = 0 then do
src = socket("LISTEN",l_socket);
if word(src,1) = 0 then do
Say "Listening on socket: "l_sockname;
l_selectlist = l_selectlist" "l_socket;
l_bindOK = "TRUE";
end;
end;
end;
end;
if l_selectlist \= 0 then do
Say "The following sockets will be monitored" l_selectlist;
l_fdset = "READ "l_selectlist" WRITE EXCEPTION";
src = socket("SELECT",l_fdset,0);
if word(src,1) = 0 & word(src,2) \= 0 then do
l_socklist = subword(src,3);
do while l_socklist \= ''
parse var l_socklist l_sockid l_socklist
src = socket("ACCEPT",l_sockid);
if word(src,1) = 0 then do
l_newsock = word(src,2);
/*
* DO SOME STUFF WITH l_newsock
*
*/
src = socket("CLOSE",l_newsock);
end;
end;
end;
src = socket("CLOSE",word(l_selectlist,1));
src = socket("CLOSE",word(l_selectlist,2));
end;
src = socket("TERMINATE","MYSET01");
exit word(src,1);
|