1 /* Copyright (C) 1997, 1999 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by H.J. Lu <hjl@gnu.ai.mit.edu>, 1997.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 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 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
21 * disallow names consisting only of digits/dots, unless
24 if (isdigit (name
[0]) || (isxdigit (name
[0]) || name
[0] == ':'))
28 typedef unsigned char host_addr_t
[16];
29 host_addr_t
*host_addr
;
30 typedef char *host_addr_list_t
[2];
31 host_addr_list_t
*h_addr_ptrs
;
49 addr_size
= IN6ADDRSZ
;
54 /* This must not happen. */
55 *h_errnop
= HOST_NOT_FOUND
;
58 af
= (_res
.options
& RES_USE_INET6
) ? AF_INET6
: AF_INET
;
59 addr_size
= af
== AF_INET6
? IN6ADDRSZ
: INADDRSZ
;
64 size_needed
= (sizeof (*host_addr
)
65 + sizeof (*h_addr_ptrs
) + strlen (name
) + 1);
67 #ifdef HAVE_LOOKUP_BUFFER
68 if (buflen
< size_needed
)
71 *h_errnop
= TRY_AGAIN
;
77 if (buffer_size
< size_needed
)
80 buffer_size
= size_needed
;
81 new_buf
= realloc (buffer
, buffer_size
);
91 *h_errnop
= TRY_AGAIN
;
93 result
= (struct hostent
*) NULL
;
98 #endif /* HAVE_LOOKUP_BUFFER */
100 memset (buffer
, 0, size_needed
);
102 host_addr
= (host_addr_t
*) buffer
;
103 h_addr_ptrs
= (host_addr_list_t
*)
104 ((char *) host_addr
+ sizeof (*host_addr
));
105 hostname
= (char *) h_addr_ptrs
+ sizeof (*h_addr_ptrs
);
107 if (isdigit (name
[0]))
109 for (cp
= name
;; ++cp
)
118 /* All-numeric, no dot at the end. Fake up a hostent as if
119 we'd actually done a lookup. What if someone types
120 255.255.255.255? The test below will succeed
123 ok
= inet_aton (name
, (struct in_addr
*) host_addr
);
126 assert (af
== AF_INET6
);
127 ok
= (inet_pton (af
, name
, host_addr
) > 0);
131 *h_errnop
= HOST_NOT_FOUND
;
132 #ifndef HAVE_LOOKUP_BUFFER
133 result
= (struct hostent
*) NULL
;
138 resbuf
.h_name
= strcpy (hostname
, name
);
139 resbuf
.h_aliases
= NULL
;
140 (*h_addr_ptrs
)[0] = (char *)host_addr
;
141 (*h_addr_ptrs
)[1] = (char *)0;
142 resbuf
.h_addr_list
= *h_addr_ptrs
;
147 af
== AF_INET
&& (_res
.options
& RES_USE_INET6
)
152 if ((flags
& AI_V4MAPPED
) == 0)
154 /* That's bad. The user hasn't specified that she
155 allows IPv4 numeric addresses. */
157 *h_errnop
= HOST_NOT_FOUND
;
163 /* We need to change the IP v4 address into the
165 char tmp
[INADDRSZ
], *p
= (char *) host_addr
;
168 /* Save a copy of the IP v4 address. */
169 memcpy (tmp
, host_addr
, INADDRSZ
);
170 /* Mark this ipv6 addr as a mapped ipv4. */
171 for (i
= 0; i
< 10; i
++)
175 /* Copy the IP v4 address. */
176 memcpy (p
, tmp
, INADDRSZ
);
177 resbuf
.h_addrtype
= AF_INET6
;
178 resbuf
.h_length
= IN6ADDRSZ
;
183 resbuf
.h_addrtype
= af
;
184 resbuf
.h_length
= addr_size
;
186 *h_errnop
= NETDB_SUCCESS
;
187 #ifdef HAVE_LOOKUP_BUFFER
188 status
= NSS_STATUS_SUCCESS
;
195 if (!isdigit (*cp
) && *cp
!= '.') break;
199 if ((isxdigit (name
[0]) && strchr (name
, ':') != NULL
)
204 typedef unsigned char host_addr_t
[16];
205 host_addr_t
*host_addr
;
206 typedef char *host_addr_list_t
[2];
207 host_addr_list_t
*h_addr_ptrs
;
221 af
= (_res
.options
& RES_USE_INET6
) ? AF_INET6
: AF_INET
;
224 addr_size
= IN6ADDRSZ
;
230 /* This is not possible. We cannot represent an IPv6 address
231 in an `struct in_addr' variable. */
232 *h_errnop
= HOST_NOT_FOUND
;
237 addr_size
= IN6ADDRSZ
;
241 size_needed
= (sizeof (*host_addr
)
242 + sizeof (*h_addr_ptrs
) + strlen (name
) + 1);
244 #ifdef HAVE_LOOKUP_BUFFER
245 if (buflen
< size_needed
)
248 *h_errnop
= TRY_AGAIN
;
250 __set_errno (ERANGE
);
254 if (buffer_size
< size_needed
)
257 buffer_size
= size_needed
;
258 new_buf
= realloc (buffer
, buffer_size
);
267 result
= (struct hostent
*) NULL
;
272 #endif /* HAVE_LOOKUP_BUFFER */
274 memset (buffer
, 0, size_needed
);
276 host_addr
= (host_addr_t
*) buffer
;
277 h_addr_ptrs
= (host_addr_list_t
*)
278 ((char *) host_addr
+ sizeof (*host_addr
));
279 hostname
= (char *) h_addr_ptrs
+ sizeof (*h_addr_ptrs
);
281 for (cp
= name
;; ++cp
)
288 /* All-IPv6-legal, no dot at the end. Fake up a
289 hostent as if we'd actually done a lookup. */
290 if (inet_pton (AF_INET6
, name
, host_addr
) <= 0)
292 *h_errnop
= HOST_NOT_FOUND
;
293 #ifndef HAVE_LOOKUP_BUFFER
294 result
= (struct hostent
*) NULL
;
299 resbuf
.h_name
= strcpy (hostname
, name
);
300 resbuf
.h_aliases
= NULL
;
301 (*h_addr_ptrs
)[0] = (char *) host_addr
;
302 (*h_addr_ptrs
)[1] = (char *) 0;
303 resbuf
.h_addr_list
= *h_addr_ptrs
;
304 resbuf
.h_addrtype
= AF_INET6
;
305 resbuf
.h_length
= addr_size
;
306 *h_errnop
= NETDB_SUCCESS
;
307 #ifdef HAVE_LOOKUP_BUFFER
308 status
= NSS_STATUS_SUCCESS
;
315 if (!isxdigit (*cp
) && *cp
!= ':' && *cp
!= '.') break;