1 /* Copyright (C) 2004-2021 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
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 <https://www.gnu.org/licenses/>. */
24 #include <arpa/nameser.h>
26 #include <resolv/resolv_context.h>
27 #include <resolv/resolv-internal.h>
31 # define MAXPACKET PACKETSZ
33 # define MAXPACKET 65536
37 /* We need this time later. */
38 typedef union querybuf
41 unsigned char buf
[MAXPACKET
];
45 static const short int qtypes
[] = { ns_t_a
, ns_t_aaaa
};
46 #define nqtypes (sizeof (qtypes) / sizeof (qtypes[0]))
50 _nss_dns_getcanonname_r (const char *name
, char *buffer
, size_t buflen
,
51 char **result
,int *errnop
, int *h_errnop
)
53 /* Just an alibi buffer, res_nquery will allocate a real buffer for
55 unsigned char buf
[20];
60 } ansp
= { .ptr
= buf
};
61 enum nss_status status
= NSS_STATUS_UNAVAIL
;
63 struct resolv_context
*ctx
= __resolv_context_get ();
67 *h_errnop
= NETDB_INTERNAL
;
68 return NSS_STATUS_UNAVAIL
;
71 for (int i
= 0; i
< nqtypes
; ++i
)
73 int r
= __res_context_query (ctx
, name
, ns_c_in
, qtypes
[i
],
74 buf
, sizeof (buf
), &ansp
.ptr
, NULL
, NULL
,
78 /* We need to decode the response. Just one question record.
79 And if we got no answers we bail out, too. */
80 if (ansp
.buf
->hdr
.qdcount
!= htons (1))
83 /* Number of answers. */
84 unsigned int ancount
= ntohs (ansp
.buf
->hdr
.ancount
);
86 /* Beginning and end of the buffer with query, answer, and the
88 unsigned char *ptr
= &ansp
.buf
->buf
[sizeof (HEADER
)];
89 unsigned char *endptr
= ansp
.ptr
+ r
;
91 /* Skip over the query. This is the name, type, and class. */
92 int s
= __libc_dn_skipname (ptr
, endptr
);
96 status
= NSS_STATUS_UNAVAIL
;
100 /* Skip over the name and the two 16-bit values containing type
102 ptr
+= s
+ 2 * sizeof (uint16_t);
104 while (ancount
-- > 0)
106 /* Now the reply. First again the name from the query,
107 then type, class, TTL, and the length of the RDATA.
108 We remember the name start. */
109 unsigned char *namestart
= ptr
;
110 s
= __libc_dn_skipname (ptr
, endptr
);
116 /* Check that there are enough bytes for the RR
118 if (endptr
- ptr
< 10)
121 /* Check whether type and class match. */
123 NS_GET16 (type
, ptr
);
124 if (type
== qtypes
[i
])
126 /* We found the record. */
127 s
= __libc_dn_expand (ansp
.buf
->buf
, endptr
, namestart
,
131 if (errno
!= EMSGSIZE
)
134 /* The buffer is too small. */
136 status
= NSS_STATUS_TRYAGAIN
;
137 h_errno
= NETDB_INTERNAL
;
143 status
= NSS_STATUS_SUCCESS
;
149 if (type
!= ns_t_cname
)
153 NS_GET16 (rrclass
, ptr
);
154 if (rrclass
!= ns_c_in
)
158 ptr
+= sizeof (uint32_t);
160 /* Skip over RDATA length and RDATA itself. */
162 NS_GET16 (rdatalen
, ptr
);
164 /* Not enough room for RDATA. */
165 if (endptr
- ptr
< rdatalen
)
171 /* Restore original buffer before retry. */
184 __resolv_context_put (ctx
);
187 libc_hidden_def (_nss_dns_getcanonname_r
)