]> git.ipfire.org Git - thirdparty/glibc.git/blame - inet/getnameinfo.c
Update.
[thirdparty/glibc.git] / inet / getnameinfo.c
CommitLineData
1fb05e3d
UD
1/* The Inner Net License, Version 2.00
2
3 The author(s) grant permission for redistribution and use in source and
4binary forms, with or without modification, of the software and documentation
5provided that the following conditions are met:
6
70. If you receive a version of the software that is specifically labelled
8 as not being for redistribution (check the version message and/or README),
9 you are not permitted to redistribute that version of the software in any
10 way or form.
111. All terms of the all other applicable copyrights and licenses must be
12 followed.
132. Redistributions of source code must retain the authors' copyright
14 notice(s), this list of conditions, and the following disclaimer.
153. Redistributions in binary form must reproduce the authors' copyright
16 notice(s), this list of conditions, and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
184. All advertising materials mentioning features or use of this software
19 must display the following acknowledgement with the name(s) of the
20 authors as specified in the copyright notice(s) substituted where
21 indicated:
22
23 This product includes software developed by <name(s)>, The Inner
24 Net, and other contributors.
25
265. Neither the name(s) of the author(s) nor the names of its contributors
27 may be used to endorse or promote products derived from this software
28 without specific prior written permission.
29
30THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY
31EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
32WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
33DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
34DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
37ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
39SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40
41 If these license terms cause you a real problem, contact the author. */
42
43/* This software is Copyright 1996 by Craig Metz, All Rights Reserved. */
44
1fb05e3d
UD
45#include <sys/types.h>
46#include <sys/socket.h>
47
48#include <netinet/in.h>
1fb05e3d
UD
49#include <sys/un.h>
50#include <sys/utsname.h>
1fb05e3d
UD
51#include <netdb.h>
52#include <errno.h>
53#include <string.h>
54#include <stdio.h>
55#include <unistd.h>
5a97622d 56#include <alloca.h>
5107cf1d 57#include <bits/libc-lock.h>
5a97622d 58#include <arpa/inet.h>
1fb05e3d 59
1fb05e3d 60#ifndef min
cd6ede75 61# define min(x,y) (((x) > (y)) ? (y) : (x))
1fb05e3d
UD
62#endif /* min */
63
1fb05e3d 64
40a55d20 65static char *
dfd2257a 66internal_function
cd6ede75 67nrl_domainname (void)
1fb05e3d 68{
390500b1
UD
69 static char *domain;
70 static int not_first;
1fb05e3d 71
3a07823a 72 if (! not_first)
cd6ede75
UD
73 {
74 __libc_lock_define_initialized (static, lock);
75 __libc_lock_lock (lock);
76
3a07823a 77 if (! not_first)
cd6ede75
UD
78 {
79 char *c;
80 struct hostent *h, th;
40a55d20 81 size_t tmpbuflen = 1024;
cd6ede75
UD
82 char *tmpbuf = alloca (tmpbuflen);
83 int herror;
84
390500b1 85 not_first = 1;
cd6ede75
UD
86
87 while (__gethostbyname_r ("localhost", &th, tmpbuf, tmpbuflen, &h,
88 &herror))
89 {
90 if (herror == NETDB_INTERNAL && errno == ERANGE)
91 {
92 tmpbuflen *= 2;
93 tmpbuf = alloca (tmpbuflen);
94 }
95 else
96 break;
97 }
5a97622d 98
cd6ede75
UD
99 if (h && (c = strchr (h->h_name, '.')))
100 domain = __strdup (++c);
101 else
102 {
103 /* The name contains no domain information. Use the name
104 now to get more information. */
50304ef0 105 while (__gethostname (tmpbuf, tmpbuflen))
cd6ede75
UD
106 {
107 tmpbuflen *= 2;
108 tmpbuf = alloca (tmpbuflen);
109 }
5a97622d 110
cd6ede75
UD
111 if ((c = strchr (tmpbuf, '.')))
112 domain = __strdup (++c);
113 else
114 {
115 /* We need to preserve the hostname. */
116 const char *hstname = strdupa (tmpbuf);
117
118 while (__gethostbyname_r (hstname, &th, tmpbuf, tmpbuflen,
119 &h, &herror))
120 {
121 if (herror == NETDB_INTERNAL && errno == ERANGE)
122 {
123 tmpbuflen *= 2;
124 tmpbuf = alloca (tmpbuflen);
125 }
126 else
127 break;
128 }
129
130 if (h && (c = strchr(h->h_name, '.')))
131 domain = __strdup (++c);
132 else
133 {
134 struct in_addr in_addr;
135
136 in_addr.s_addr = htonl (0x7f000001);
137
138 while (__gethostbyaddr_r ((const char *) &in_addr,
139 sizeof (struct in_addr),
140 AF_INET, &th, tmpbuf,
141 tmpbuflen, &h, &herror))
142 {
143 if (herror == NETDB_INTERNAL && errno == ERANGE)
144 {
145 tmpbuflen *= 2;
146 tmpbuf = alloca (tmpbuflen);
147 }
148 else
149 break;
150 }
151
152 if (h && (c = strchr (h->h_name, '.')))
153 domain = __strdup (++c);
154 }
155 }
5a97622d 156 }
5a97622d 157 }
1fb05e3d 158
cd6ede75 159 __libc_lock_unlock (lock);
1fb05e3d
UD
160 }
161
1fb05e3d
UD
162 return domain;
163};
164
cd6ede75
UD
165
166int
c7614ee9 167getnameinfo (const struct sockaddr *sa, socklen_t addrlen, char *host,
cd6ede75 168 size_t hostlen, char *serv, size_t servlen, int flags)
1fb05e3d
UD
169{
170 int serrno = errno;
5a97622d
UD
171 int tmpbuflen = 1024;
172 int herrno;
cd6ede75 173 char *tmpbuf = alloca (tmpbuflen);
5a97622d 174 struct hostent th;
922809a2 175 socklen_t min_addrlen = 0;
1fb05e3d 176
922809a2
UD
177 if (sa == NULL || addrlen < sizeof (sa_family_t))
178 return -1;
179
180 switch (sa->sa_family)
181 {
182 case AF_LOCAL:
183 min_addrlen = (socklen_t) (((struct sockaddr_un *) NULL)->sun_path);
184 break;
185 default:
186 min_addrlen = __libc_sa_len (sa->sa_family);
187 }
188 if (addrlen < min_addrlen)
1fb05e3d
UD
189 return -1;
190
cd6ede75
UD
191 if (host != NULL && hostlen > 0)
192 switch(sa->sa_family)
193 {
1fb05e3d 194 case AF_INET:
1fb05e3d 195 case AF_INET6:
cd6ede75
UD
196 if (!(flags & NI_NUMERICHOST))
197 {
198 struct hostent *h = NULL;
cd6ede75
UD
199 if (h == NULL)
200 {
cd6ede75
UD
201 if (sa->sa_family == AF_INET6)
202 {
203 while (__gethostbyaddr_r ((void *) &(((struct sockaddr_in6 *) sa)->sin6_addr),
204 sizeof(struct in6_addr),
205 AF_INET6, &th, tmpbuf, tmpbuflen,
206 &h, &herrno))
207 {
208 if (herrno == NETDB_INTERNAL)
209 {
210 if (errno == ERANGE)
211 {
212 tmpbuflen *= 2;
213 tmpbuf = alloca (tmpbuflen);
214 }
215 else
216 {
217 __set_h_errno (herrno);
40a55d20
UD
218 __set_errno (serrno);
219 return -1;
cd6ede75
UD
220 }
221 }
222 else
223 {
224 break;
225 }
226 }
5a97622d 227 }
cd6ede75
UD
228 else
229 {
cd6ede75
UD
230 while (__gethostbyaddr_r ((void *) &(((struct sockaddr_in *)sa)->sin_addr),
231 sizeof(struct in_addr), AF_INET,
232 &th, tmpbuf, tmpbuflen,
233 &h, &herrno))
234 {
235 if (errno == ERANGE)
236 {
237 tmpbuflen *= 2;
238 tmpbuf = alloca (tmpbuflen);
239 }
240 else
241 {
242 break;
243 }
244 }
245 }
5a97622d 246 }
1fb05e3d 247
cd6ede75
UD
248 if (h)
249 {
250 if (flags & NI_NOFQDN)
251 {
40a55d20 252 char *c;
cd6ede75
UD
253 if ((c = nrl_domainname ()) && (c = strstr(h->h_name, c))
254 && (c != h->h_name) && (*(--c) == '.'))
255 {
256 strncpy (host, h->h_name,
257 min(hostlen, (size_t) (c - h->h_name)));
6e9b72d3
UD
258 host[min(hostlen - 1, (size_t) (c - h->h_name))]
259 = '\0';
cd6ede75
UD
260 break;
261 }
262 }
263 strncpy (host, h->h_name, hostlen);
1fb05e3d 264 break;
cd6ede75
UD
265 }
266 }
1fb05e3d
UD
267
268 if (flags & NI_NAMEREQD)
40a55d20
UD
269 {
270 __set_errno (serrno);
271 return -1;
272 }
cd6ede75
UD
273 else
274 {
275 const char *c;
cd6ede75
UD
276 if (sa->sa_family == AF_INET6)
277 c = inet_ntop (AF_INET6,
278 (void *) &(((struct sockaddr_in6 *) sa)->sin6_addr),
279 host, hostlen);
280 else
cd6ede75
UD
281 c = inet_ntop (AF_INET,
282 (void *) &(((struct sockaddr_in *) sa)->sin_addr),
283 host, hostlen);
1fb05e3d 284
40a55d20
UD
285 if (c == NULL)
286 {
287 __set_errno (serrno);
288 return -1;
289 }
cd6ede75 290 }
1fb05e3d 291 break;
cd6ede75 292
1fb05e3d 293 case AF_LOCAL:
cd6ede75
UD
294 if (!(flags & NI_NUMERICHOST))
295 {
296 struct utsname utsname;
1fb05e3d 297
cd6ede75
UD
298 if (!uname (&utsname))
299 {
300 strncpy (host, utsname.nodename, hostlen);
301 break;
302 };
1fb05e3d 303 };
1fb05e3d
UD
304
305 if (flags & NI_NAMEREQD)
40a55d20
UD
306 {
307 __set_errno (serrno);
308 return -1;
309 }
1fb05e3d 310
cd6ede75 311 strncpy (host, "localhost", hostlen);
1fb05e3d 312 break;
cd6ede75 313
1fb05e3d
UD
314 default:
315 return -1;
cd6ede75 316 }
1fb05e3d
UD
317
318 if (serv && (servlen > 0))
cd6ede75
UD
319 switch(sa->sa_family)
320 {
1fb05e3d 321 case AF_INET:
1fb05e3d 322 case AF_INET6:
cd6ede75
UD
323 if (!(flags & NI_NUMERICSERV))
324 {
325 struct servent *s, ts;
326 while (__getservbyport_r (((struct sockaddr_in *) sa)->sin_port,
327 ((flags & NI_DGRAM) ? "udp" : "tcp"),
328 &ts, tmpbuf, tmpbuflen, &s))
329 {
330 if (herrno == NETDB_INTERNAL)
331 {
332 if (errno == ERANGE)
333 {
334 tmpbuflen *= 2;
40a55d20 335 tmpbuf = __alloca (tmpbuflen);
cd6ede75
UD
336 }
337 else
40a55d20
UD
338 {
339 __set_errno (serrno);
340 return -1;
341 }
cd6ede75
UD
342 }
343 else
344 {
345 break;
346 }
347 }
348 if (s)
349 {
40a55d20 350 strncpy (serv, s->s_name, servlen);
cd6ede75 351 break;
5a97622d 352 }
5a97622d 353 }
50304ef0
UD
354 __snprintf (serv, servlen, "%d",
355 ntohs (((struct sockaddr_in *) sa)->sin_port));
1fb05e3d 356 break;
cd6ede75 357
1fb05e3d 358 case AF_LOCAL:
cd6ede75 359 strncpy (serv, ((struct sockaddr_un *) sa)->sun_path, servlen);
1fb05e3d 360 break;
cd6ede75
UD
361 }
362
1fb05e3d
UD
363 if (host && (hostlen > 0))
364 host[hostlen-1] = 0;
365 if (serv && (servlen > 0))
366 serv[servlen-1] = 0;
367 errno = serrno;
368 return 0;
40a55d20 369}