@@ -379,6 +379,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct
gaih_addrtuple **pat,
{
enum nss_status status = check_name (name, herrnop);
char tmp[NS_MAXDNAME];
+
if (status != NSS_STATUS_SUCCESS)
return status;
struct resolv_context *ctx = __resolv_context_get ();
@@ -413,25 +414,43 @@ _nss_dns_gethostbyname4_r (const char *name,
struct gaih_addrtuple **pat,
int olderr = errno;
int n;
- if ((ctx->resp->options & RES_NOAAAA) == 0)
- {
- n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA,
- dns_packet_buffer, sizeof (dns_packet_buffer),
- &alt_dns_packet_buffer, &ans2p, &nans2p,
- &resplen2, &ans2p_malloced);
- if (n >= 0)
- status = gaih_getanswer (alt_dns_packet_buffer, n, ans2p, resplen2,
- &abuf, pat, errnop, herrnop, ttlp);
- }
- else
+ switch (ctx->resp->options & (RES_NOAAAA|RES_IPV4|RES_IPV6))
{
- n = __res_context_search (ctx, name, C_IN, T_A,
- dns_packet_buffer, sizeof (dns_packet_buffer),
- &alt_dns_packet_buffer, NULL, NULL, NULL, NULL);
- if (n >= 0)
- status = gaih_getanswer_noaaaa (alt_dns_packet_buffer, n,
- &abuf, pat, errnop, herrnop, ttlp);
- }
+ case RES_IPV4:
+ case RES_IPV4|RES_NOAAAA:
+ case RES_NOAAAA:
+ case RES_IPV6|RES_NOAAAA: /*< this combination should never be used. */
+ case RES_IPV4|RES_IPV6|RES_NOAAAA: /*< this does not make sense. */
+ n = __res_context_search (ctx, name, C_IN, T_A,
+ dns_packet_buffer, sizeof (dns_packet_buffer),
+ NULL, NULL, NULL, NULL, NULL);
+ if (n >= 0)
+ status = gaih_getanswer_noaaaa (alt_dns_packet_buffer, n,
+ &abuf, pat, errnop, herrnop, ttlp);
+ break;
+
+ case RES_IPV6:
+ n = __res_context_search (ctx, name, C_IN, T_AAAA,
+ dns_packet_buffer, sizeof (dns_packet_buffer),
+ NULL, NULL, NULL, NULL, NULL);
+ if (n >= 0) /* oh we want AAAA, but not A here. code is the same. */
+ status = gaih_getanswer_noaaaa (alt_dns_packet_buffer, n,
+ &abuf, pat, errnop, herrnop, ttlp);
+ break;
+
+ case 0:
+ case RES_IPV4|RES_IPV6:
+ default:
+ n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA,
+ dns_packet_buffer, sizeof (dns_packet_buffer),
+ &alt_dns_packet_buffer, &ans2p, &nans2p,
+ &resplen2, &ans2p_malloced);
+ if (n >= 0)
+ status = gaih_getanswer (alt_dns_packet_buffer, n, ans2p, resplen2,
+ &abuf, pat, errnop, herrnop, ttlp);
+ break;
+ }
+
if (n < 0)
{
switch (errno)
@@ -613,6 +613,8 @@ p_option(u_long option) {
case RES_NORELOAD: return "no-reload";
case RES_TRUSTAD: return "trust-ad";
case RES_NOAAAA: return "no-aaaa";
+ case RES_IPV4: return "ipv4";
+ case RES_IPV6: return "ipv6";
/* XXX nonreentrant */
default: sprintf(nbuf, "?0x%lx?", (u_long)option);
return (nbuf);
@@ -696,6 +696,8 @@ res_setoptions (struct resolv_conf_parser *parser,
const char *options)
{ STRnLEN ("trust-ad"), RES_TRUSTAD },
{ STRnLEN ("no-aaaa"), RES_NOAAAA },
{ STRnLEN ("strict-error"), RES_STRICTERR },
+ { STRnLEN ("ipv4"), RES_IPV4 },
+ { STRnLEN ("ipv6"), RES_IPV6 },
};
#define noptions (sizeof (options) / sizeof (options[0]))
bool negate_option = *cp == '-';
@@ -134,6 +134,8 @@ struct res_sym {
#define RES_TRUSTAD 0x04000000 /* Request AD bit, keep it in responses. */
#define RES_NOAAAA 0x08000000 /* Suppress AAAA queries. */
#define RES_STRICTERR 0x10000000 /* Report more DNS errors as errors. */
+#define RES_IPV4 0x20000000 /* Query A records on PF_UNSPEC hints. */
+#define RES_IPV6 0x40000000 /* Query AAAA records on PF_UNSPEC hints. */
#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH)
b/resolv/tst-resolv-res_init-skeleton.c
@@ -130,6 +130,8 @@ print_resp (FILE *fp, res_state resp)
print_option_flag (fp, &options, RES_TRUSTAD, "trust-ad");
print_option_flag (fp, &options, RES_NOAAAA, "no-aaaa");
print_option_flag (fp, &options, RES_STRICTERR, "strict-error");
+ print_option_flag (fp, &options, RES_IPV4, "ipv4");
+ print_option_flag (fp, &options, RES_IPV6, "ipv6");
fputc ('\n', fp);
if (options != 0)
fprintf (fp, "; error: unresolved option bits: 0x%x\n", options);