]> sourceware.org Git - glibc.git/blame - resolv/nss_dns/dns-canon.c
* io/tst-fchownat.c: Correctly handle _POSIX_CHOWN_RESTRICTED
[glibc.git] / resolv / nss_dns / dns-canon.c
CommitLineData
acb98cb5 1/* Copyright (C) 2004, 2006 Free Software Foundation, Inc.
28977c2c
UD
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
4
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.
9
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.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
19
20#include <errno.h>
21#include <netdb.h>
22#include <resolv.h>
23#include <stdlib.h>
24#include <arpa/nameser.h>
25#include <nsswitch.h>
26
27
28#if PACKETSZ > 65536
29# define MAXPACKET PACKETSZ
30#else
31# define MAXPACKET 65536
32#endif
33
34
35/* We need this time later. */
36typedef union querybuf
37{
38 HEADER hdr;
39 unsigned char buf[MAXPACKET];
40} querybuf;
41
42
acb98cb5
UD
43static const short int qtypes[] = { ns_t_a, ns_t_aaaa };
44#define nqtypes (sizeof (qtypes) / sizeof (qtypes[0]))
45
46
28977c2c
UD
47enum nss_status
48_nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
49 char **result,int *errnop, int *h_errnop)
50{
51 /* Just an alibi buffer, res_nquery will allocate a real buffer for
52 us. */
53 unsigned char buf[20];
54 union
55 {
56 querybuf *buf;
57 unsigned char *ptr;
58 } ansp = { .ptr = buf };
10b71c3d 59 enum nss_status status = NSS_STATUS_UNAVAIL;
28977c2c 60
3207d436 61 for (int i = 0; i < nqtypes; ++i)
28977c2c 62 {
3207d436
UD
63 int r = __libc_res_nquery (&_res, name, ns_c_in, qtypes[i],
64 buf, sizeof (buf), &ansp.ptr);
65 if (r > 0)
28977c2c 66 {
3207d436
UD
67 /* We need to decode the response. Just one question record.
68 And if we got no answers we bail out, too. */
69 if (ansp.buf->hdr.qdcount != htons (1))
70 continue;
71
72 /* Number of answers. */
73 unsigned int ancount = ntohs (ansp.buf->hdr.ancount);
74
75 /* Beginning and end of the buffer with query, answer, and the
76 rest. */
77 unsigned char *ptr = &ansp.buf->buf[sizeof (HEADER)];
78 unsigned char *endptr = ansp.ptr + r;
79
80 /* Skip over the query. This is the name, type, and class. */
81 int s = __dn_skipname (ptr, endptr);
82 if (s < 0)
83 {
84 unavail:
85 status = NSS_STATUS_UNAVAIL;
86 break;
87 }
88
89 /* Skip over the name and the two 16-bit values containing type
90 and class. */
91 ptr += s + 2 * sizeof (uint16_t);
92
93 while (ancount-- > 0)
94 {
95 /* Now the reply. First again the name from the query,
96 then type, class, TTL, and the length of the RDATA.
97 We remember the name start. */
98 unsigned char *namestart = ptr;
99 s = __dn_skipname (ptr, endptr);
100 if (s < 0)
101 goto unavail;
102
103 ptr += s;
104
105 /* Check whether type and class match. */
acb98cb5
UD
106 uint_fast16_t type;
107 NS_GET16 (type, ptr);
3207d436
UD
108 if (type == qtypes[i])
109 {
110 /* We found the record. */
111 s = __dn_expand (ansp.buf->buf, endptr, namestart,
112 buffer, buflen);
113 if (s < 0)
114 {
115 if (errno != EMSGSIZE)
116 goto unavail;
117
118 /* The buffer is too small. */
119 *errnop = ERANGE;
120 status = NSS_STATUS_TRYAGAIN;
121 h_errno = NETDB_INTERNAL;
122 }
123 else
124 {
125 /* Success. */
126 *result = buffer;
127 status = NSS_STATUS_SUCCESS;
128 }
129
130 goto out;
131 }
132
133 if (type != ns_t_cname)
134 goto unavail;
135
acb98cb5 136 if (ns_get16 (ptr) != ns_c_in)
3207d436
UD
137 goto unavail;
138
139 /* Also skip over the TTL. */
140 ptr += sizeof (uint16_t) + sizeof (uint32_t);
141
142 /* Skip over the data length and data. */
acb98cb5 143 ptr += sizeof (uint16_t) + ns_get16 (ptr);
3207d436 144 }
28977c2c
UD
145 }
146 }
3207d436
UD
147
148 out:
28977c2c
UD
149 *h_errnop = h_errno;
150
151 if (ansp.ptr != buf)
152 free (ansp.ptr);
153
154 return status;
155}
This page took 1.497103 seconds and 5 git commands to generate.