Include files for missing prototypes, remove buggy declaration of prototypes.
[kopensolaris-gnu/glibc.git] / nss / digits_dots.c
1 /* Copyright (C) 1997, 1999, 2000 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.
4
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.
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    Library General Public License for more details.
14
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.  */
19
20 #ifdef USE_NSCD
21 # define inet_aton __inet_aton
22 #endif
23
24   /*
25    * disallow names consisting only of digits/dots, unless
26    * they end in a dot.
27    */
28   if (isdigit (name[0]) || (isxdigit (name[0]) || name[0] == ':'))
29     {
30       const char *cp;
31       char *hostname;
32       typedef unsigned char host_addr_t[16];
33       host_addr_t *host_addr;
34       typedef char *host_addr_list_t[2];
35       host_addr_list_t *h_addr_ptrs;
36       char **h_alias_ptr;
37       size_t size_needed;
38       int addr_size;
39 #ifdef HAVE_TYPE
40       int af = type;
41 #else
42 # ifndef HAVE_AF
43       int af = -1;
44 # endif
45 #endif
46
47       switch (af)
48         {
49         case AF_INET:
50           addr_size = INADDRSZ;
51           break;
52
53         case AF_INET6:
54           addr_size = IN6ADDRSZ;
55           break;
56
57         default:
58 #ifdef HAVE_TYPE
59           /* This must not happen.  */
60           *h_errnop = HOST_NOT_FOUND;
61           goto done;
62 #else
63           af = (_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET;
64           addr_size = af == AF_INET6 ? IN6ADDRSZ : INADDRSZ;
65           break;
66 #endif
67         }
68
69       size_needed = (sizeof (*host_addr)
70                      + sizeof (*h_addr_ptrs) + strlen (name) + 1);
71
72 #ifdef HAVE_LOOKUP_BUFFER
73       if (buflen < size_needed)
74         {
75 # ifdef NEED_H_ERRNO
76           *h_errnop = TRY_AGAIN;
77 # endif
78           __set_errno (ERANGE);
79           goto done;
80         }
81 #else
82       if (buffer_size < size_needed)
83         {
84           char *new_buf;
85           buffer_size = size_needed;
86           new_buf = realloc (buffer, buffer_size);
87
88           if (new_buf == NULL)
89             {
90               save = errno;
91               free (buffer);
92               buffer = NULL;
93               buffer_size = 0;
94               __set_errno (save);
95 # ifdef NEED_H_ERRNO
96               *h_errnop = TRY_AGAIN;
97 # endif
98               result = (struct hostent *) NULL;
99               goto done;
100             }
101           buffer = new_buf;
102         }
103 #endif /* HAVE_LOOKUP_BUFFER */
104
105       memset (buffer, 0, size_needed);
106
107       host_addr = (host_addr_t *) buffer;
108       h_addr_ptrs = (host_addr_list_t *)
109         ((char *) host_addr + sizeof (*host_addr));
110       h_alias_ptr = (char **) ((char *) h_addr_ptrs + sizeof (*h_addr_ptrs));
111       hostname = (char *) h_alias_ptr + sizeof (*h_alias_ptr);
112
113       if (isdigit (name[0]))
114         {
115           for (cp = name;; ++cp)
116             {
117               if (!*cp)
118                 {
119                   int ok;
120
121                   if (*--cp == '.')
122                     break;
123
124                   /* All-numeric, no dot at the end. Fake up a hostent as if
125                      we'd actually done a lookup.  What if someone types
126                      255.255.255.255?  The test below will succeed
127                      spuriously... ???  */
128                   if (af == AF_INET)
129                     ok = __inet_aton (name, (struct in_addr *) host_addr);
130                   else
131                     {
132                       assert (af == AF_INET6);
133                       ok = (inet_pton (af, name, host_addr) > 0);
134                     }
135                   if (! ok)
136                     {
137                       *h_errnop = HOST_NOT_FOUND;
138 #ifndef HAVE_LOOKUP_BUFFER
139                       result = (struct hostent *) NULL;
140 #endif
141                       goto done;
142                     }
143
144                   resbuf.h_name = strcpy (hostname, name);
145                   h_alias_ptr[0] = NULL;
146                   resbuf.h_aliases = h_alias_ptr;
147                   (*h_addr_ptrs)[0] = (char *)host_addr;
148                   (*h_addr_ptrs)[1] = (char *)0;
149                   resbuf.h_addr_list = *h_addr_ptrs;
150                   if (
151 #ifdef HAVE_TYPE
152                       type == AF_INET6
153 #else
154                       af == AF_INET && (_res.options & RES_USE_INET6)
155 #endif
156                       )
157                     {
158 #ifdef HAVE_TYPE
159                       if ((flags & AI_V4MAPPED) == 0)
160                         {
161                           /* That's bad.  The user hasn't specified that she
162                              allows IPv4 numeric addresses.  */
163                           result = NULL;
164                           *h_errnop = HOST_NOT_FOUND;
165                           goto done;
166                         }
167                       else
168 #endif
169                         {
170                           /* We need to change the IP v4 address into the
171                              IP v6 address.  */
172                           char tmp[INADDRSZ], *p = (char *) host_addr;
173                           int i;
174
175                           /* Save a copy of the IP v4 address. */
176                           memcpy (tmp, host_addr, INADDRSZ);
177                           /* Mark this ipv6 addr as a mapped ipv4. */
178                           for (i = 0; i < 10; i++)
179                             *p++ = 0x00;
180                           *p++ = 0xff;
181                           *p++ = 0xff;
182                           /* Copy the IP v4 address. */
183                           memcpy (p, tmp, INADDRSZ);
184                           resbuf.h_addrtype = AF_INET6;
185                           resbuf.h_length = IN6ADDRSZ;
186                         }
187                     }
188                   else
189                     {
190                       resbuf.h_addrtype = af;
191                       resbuf.h_length = addr_size;
192                     }
193                   *h_errnop = NETDB_SUCCESS;
194 #ifdef HAVE_LOOKUP_BUFFER
195                   status = NSS_STATUS_SUCCESS;
196 #else
197                   result = &resbuf;
198 #endif
199                   goto done;
200                 }
201
202               if (!isdigit (*cp) && *cp != '.') break;
203             }
204         }
205
206       if ((isxdigit (name[0]) && strchr (name, ':') != NULL)
207           || name[0] == ':')
208         {
209           const char *cp;
210           char *hostname;
211           typedef unsigned char host_addr_t [16];
212           host_addr_t *host_addr;
213           typedef char *host_addr_list_t [2];
214           host_addr_list_t *h_addr_ptrs;
215           size_t size_needed;
216           int addr_size;
217 #ifdef HAVE_TYPE
218           int af = type;
219 #else
220 # ifndef HAVE_AF
221           int af = -1;
222 # endif
223 #endif
224
225           switch (af)
226             {
227             default:
228               af = (_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET;
229               if (af == AF_INET6)
230                 {
231                   addr_size = IN6ADDRSZ;
232                   break;
233                 }
234               /* FALLTHROUGH */
235
236             case AF_INET:
237               /* This is not possible.  We cannot represent an IPv6 address
238                  in an `struct in_addr' variable.  */
239               *h_errnop = HOST_NOT_FOUND;
240               result = NULL;
241               goto done;
242
243             case AF_INET6:
244               addr_size = IN6ADDRSZ;
245               break;
246             }
247
248           size_needed = (sizeof (*host_addr)
249                          + sizeof (*h_addr_ptrs) + strlen (name) + 1);
250
251 #ifdef HAVE_LOOKUP_BUFFER
252           if (buflen < size_needed)
253             {
254 # ifdef NEED_H_ERRNO
255               *h_errnop = TRY_AGAIN;
256 # endif
257               __set_errno (ERANGE);
258               goto done;
259             }
260 #else
261           if (buffer_size < size_needed)
262             {
263               char *new_buf;
264               buffer_size = size_needed;
265               new_buf = realloc (buffer, buffer_size);
266
267               if (new_buf == NULL)
268                 {
269                   save = errno;
270                   free (buffer);
271                   __set_errno (save);
272                   buffer = NULL;
273                   buffer_size = 0;
274                   result = (struct hostent *) NULL;
275                   goto done;
276                 }
277               buffer = new_buf;
278             }
279 #endif /* HAVE_LOOKUP_BUFFER */
280
281           memset (buffer, 0, size_needed);
282
283           host_addr = (host_addr_t *) buffer;
284           h_addr_ptrs = (host_addr_list_t *)
285             ((char *) host_addr + sizeof (*host_addr));
286           hostname = (char *) h_addr_ptrs + sizeof (*h_addr_ptrs);
287
288           for (cp = name;; ++cp)
289             {
290               if (!*cp)
291                 {
292                   if (*--cp == '.')
293                     break;
294
295                   /* All-IPv6-legal, no dot at the end. Fake up a
296                      hostent as if we'd actually done a lookup.  */
297                   if (inet_pton (AF_INET6, name, host_addr) <= 0)
298                     {
299                       *h_errnop = HOST_NOT_FOUND;
300 #ifndef HAVE_LOOKUP_BUFFER
301                       result = (struct hostent *) NULL;
302 #endif
303                       goto done;
304                     }
305
306                   resbuf.h_name = strcpy (hostname, name);
307                   h_alias_ptr[0] = NULL;
308                   resbuf.h_aliases = h_alias_ptr;
309                   (*h_addr_ptrs)[0] = (char *) host_addr;
310                   (*h_addr_ptrs)[1] = (char *) 0;
311                   resbuf.h_addr_list = *h_addr_ptrs;
312                   resbuf.h_addrtype = AF_INET6;
313                   resbuf.h_length = addr_size;
314                   *h_errnop = NETDB_SUCCESS;
315 #ifdef HAVE_LOOKUP_BUFFER
316                   status = NSS_STATUS_SUCCESS;
317 #else
318                   result = &resbuf;
319 #endif
320                   goto done;
321                 }
322
323               if (!isxdigit (*cp) && *cp != ':' && *cp != '.') break;
324             }
325         }
326     }