In this lab, you will learn and use getaddrinfo()
for
looking up the IPv4 addresses of a domain name aka host name. You will
also finish with freeaddrinfo()
for freeing the data
structure created by getaddrinfo()
.
getaddrinfo()
getaddrinfo()
takes many parameters because it can do
many things; the man page can be overwhelming at first sight. On the
bright side, it offers to completely compute all parameters you need for
socket()
, bind()
, and
connect()
.
You should read the man page, but here is an orientation:
int getaddrinfo(const char *host,
const char *service,
const struct addrinfo *hints,
struct addrinfo **res);
host
: The domain name, e.g.,
"mathlab.utsc.utoronto.ca"
service
: If you intend a port number, this can be
the string form of that number, e.g., "80"
for port number
80. Why string? Because many common port numbers have names, e.g., 80 is
the standard/default port for http, and you can give "http"
here. (See /etc/services for common ports and names.)
getaddrinfo()
wants this because it offers to fill in
the port-number field in sockaddr_in
(or
sockaddr_in6
) for you later.
hints
: Pointer to your own
struct addrinfo
you have filled in for limiting the search,
e.g., IPv4-only, stream-only. (See below.)
res
: getaddrinfo()
wants to give you a
linked list containing the answers because in general there can be
multiple answers. (struct addrinfo
is a list node.) It
wants to store the head pointer in your variable. So you provide the
address of your variable here to receive the head pointer.
The return int
is 0 if no error, or one of the
EAI_*
error codes if error (see man page).
In hints
, the following 4 fields in
struct addrinfo
are relevant, and the other fields should
be set to 0 (if number field) or NULL (if pointer field):
ai_family
: AF_INET
if you want
IPv4-only, AF_INET6
if IPv6-only, AF_UNSPEC
if
you accept both.
ai_socktype
: SOCK_STREAM
if stream-only
(this course), SOCK_DGRAM
if datagram-only, 0 if you accept
both.
ai_protocol
: 0 in this course for stream-only.
(Similar to the protocol parameter of socket()
.)
ai_flags
: Moar customizations. You may just use 0
for this lab. See the man page or the textbook for the full
menu.
In the struct addrinfo
you receive via
res
:
ai_family
, ai_socktype
,
ai_protocol
: have actual resolved values you can pass to
socket()
.
ai_addr
, ai_addrlen
: pointer to
struct sockaddr
and size, so you can pass to
bind()
or connect()
. In this lab, you give
ai_addr
to print_inet4_addr()
(provided in the
starter code).
ai_canonname
: Not used in this lab. (See the man
page.)
ai_next
: pointer to the next
struct addrinfo
node.
Your job is to complete getaddr.c to call getaddrinfo()
and then use the provided print_inet4_addr()
to print out
all IPv4 addresses found.
After that, use freeaddrinfo()
to free the linked list.
I will use valgrind to check this!
Optional: If getaddrinfo()
returns a non-zero number,
learn and use gai_strerror()
for the corresponding error
message, print it to stderr, and exit.
Sample runs and outputs, assuming your executable is ./getaddr :
$ ./getaddr mathlab.utsc.utoronto.ca
142.1.96.164
$ ./getaddr ageofempires.com | sort
20.112.250.133
20.231.239.246
20.236.44.162
20.70.246.20
20.76.201.171
The ageofempires.com example shows a case of multiple answers.
Although the order can be different every time, piping to
sort
should yield a reproducible result, as shown.