1 /* Convert struct addrinfo values to a string.
2 Copyright (C) 2016-2018 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 #include <support/format_nss.h>
21 #include <arpa/inet.h>
25 #include <support/support.h>
26 #include <support/xmemstream.h>
29 socket_address_length (int family
)
34 return sizeof (struct sockaddr_in
);
36 return sizeof (struct sockaddr_in6
);
43 format_ai_flags_1 (FILE *out
, struct addrinfo
*ai
, int flag
, const char *name
,
46 if ((ai
->ai_flags
& flag
) != 0)
47 fprintf (out
, " %s", name
);
48 *flags_printed
|= flag
;
52 format_ai_flags (FILE *out
, struct addrinfo
*ai
)
57 if (ai
->ai_flags
!= 0)
59 fprintf (out
, "flags:");
60 int flags_printed
= 0;
61 #define FLAG(flag) format_ai_flags_1 (out, ai, flag, #flag, &flags_printed)
64 FLAG (AI_NUMERICHOST
);
70 FLAG (AI_IDN_ALLOW_UNASSIGNED
);
71 FLAG (AI_IDN_USE_STD3_ASCII_RULES
);
72 FLAG (AI_NUMERICSERV
);
74 int remaining
= ai
->ai_flags
& ~flags_printed
;
76 fprintf (out
, " %08x", remaining
);
80 /* Report flag mismatches within the list. */
81 int flags
= ai
->ai_flags
;
86 if (ai
->ai_flags
!= flags
)
87 fprintf (out
, "error: flags at %d: 0x%x expected, 0x%x actual\n",
88 index
, flags
, ai
->ai_flags
);
95 format_ai_canonname (FILE *out
, struct addrinfo
*ai
)
99 if (ai
->ai_canonname
!= NULL
)
100 fprintf (out
, "canonname: %s\n", ai
->ai_canonname
);
102 /* Report incorrectly set ai_canonname fields on subsequent list
108 if (ai
->ai_canonname
!= NULL
)
109 fprintf (out
, "error: canonname set at %d: %s\n",
110 index
, ai
->ai_canonname
);
117 format_ai_one (FILE *out
, struct addrinfo
*ai
)
121 const char *type_str
;
123 const char *proto_str
;
126 switch (ai
->ai_socktype
)
138 snprintf (type_buf
, sizeof (type_buf
), "%d", ai
->ai_socktype
);
143 switch (ai
->ai_protocol
)
155 snprintf (proto_buf
, sizeof (proto_buf
), "%d", ai
->ai_protocol
);
156 proto_str
= proto_buf
;
158 fprintf (out
, "address: %s/%s", type_str
, proto_str
);
162 if (ai
->ai_addrlen
!= socket_address_length (ai
->ai_family
))
164 char *family
= support_format_address_family (ai
->ai_family
);
165 fprintf (out
, "error: invalid address length %d for %s\n",
166 ai
->ai_addrlen
, family
);
175 switch (ai
->ai_family
)
179 struct sockaddr_in
*sin
= (struct sockaddr_in
*) ai
->ai_addr
;
180 ret
= inet_ntop (AF_INET
, &sin
->sin_addr
, buf
, sizeof (buf
));
181 port
= sin
->sin_port
;
186 struct sockaddr_in6
*sin
= (struct sockaddr_in6
*) ai
->ai_addr
;
187 ret
= inet_ntop (AF_INET6
, &sin
->sin6_addr
, buf
, sizeof (buf
));
188 port
= sin
->sin6_port
;
192 errno
= EAFNOSUPPORT
;
196 fprintf (out
, "error: inet_top failed: %m\n");
198 fprintf (out
, " %s %u\n", buf
, ntohs (port
));
202 /* Format all the addresses in one address family. */
204 format_ai_family (FILE *out
, struct addrinfo
*ai
, int family
)
208 if (ai
->ai_family
== family
)
209 format_ai_one (out
, ai
);
215 support_format_addrinfo (struct addrinfo
*ai
, int ret
)
217 int errno_copy
= errno
;
219 struct xmemstream mem
;
220 xopen_memstream (&mem
);
223 fprintf (mem
.out
, "error: %s\n", gai_strerror (ret
));
224 if (ret
== EAI_SYSTEM
)
227 fprintf (mem
.out
, "error: %m\n");
232 format_ai_flags (mem
.out
, ai
);
233 format_ai_canonname (mem
.out
, ai
);
234 format_ai_family (mem
.out
, ai
, AF_INET
);
235 format_ai_family (mem
.out
, ai
, AF_INET6
);
238 xfclose_memstream (&mem
);