Fix typo.
[kopensolaris-gnu/glibc.git] / nss / digits_dots.c
1 /* Copyright (C) 1997 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   /*
21    * disallow names consisting only of digits/dots, unless
22    * they end in a dot.
23    */
24   if (isdigit (name[0]) || (isxdigit (name[0]) || name[0] == ':'))
25     {
26       const char *cp;
27       char *hostname;
28       struct hostent *host;
29       typedef unsigned char host_addr_t [16];
30       host_addr_t *host_addr;
31       typedef char *host_addr_list_t [2];
32       host_addr_list_t *host_aliases;
33       host_addr_list_t *h_addr_ptrs;
34       size_t size_needed;
35       int addr_size;
36 #ifndef HAVE_AF
37       int af = -1;
38 #endif
39
40       switch (af)
41         {
42         case AF_INET:
43           addr_size = INADDRSZ;
44           break;
45
46         case AF_INET6:
47           addr_size = IN6ADDRSZ;
48           break;
49
50         default:
51           af = (_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET;
52           addr_size = (af == AF_INET6 ) ? IN6ADDRSZ : INADDRSZ;
53           break;
54         }
55
56       size_needed = (sizeof (*host) + sizeof (*host_addr)
57                      + sizeof (*host_aliases) + sizeof (*h_addr_ptrs)
58                      + strlen (name) + 1);
59
60 #ifdef HAVE_LOOKUP_BUFFER
61       if (buflen < size_needed)
62         {
63           __set_errno (ERANGE);
64           goto done;
65         }
66 #else
67       if (buffer_size < size_needed)
68         {
69           char *new_buf;
70           buffer_size = size_needed;
71           new_buf = realloc (buffer, buffer_size);
72
73           if (new_buf == NULL)
74             {
75               save = errno;
76               free (buffer);
77               buffer = NULL;
78               buffer_size = 0;
79               __set_errno (save);
80               result = (struct hostent *) NULL;
81               goto done;
82             }
83           buffer = new_buf;
84         }
85 #endif /* HAVE_LOOKUP_BUFFER */
86
87       memset (buffer, 0, size_needed);
88
89       host = (struct hostent *) buffer;
90       host_addr = (host_addr_t *) ((char *) host + sizeof (*host));
91       host_aliases = (host_addr_list_t *)
92         ((char *) host_addr + sizeof (*host_addr));
93       h_addr_ptrs = (host_addr_list_t *)
94         ((char *) host_aliases + sizeof (*host_aliases));
95       hostname = (char *) h_addr_ptrs + sizeof (*h_addr_ptrs);
96
97       if (isdigit (name[0]))
98         {
99           for (cp = name;; ++cp)
100             {
101               if (!*cp)
102                 {
103                   if (*--cp == '.') break;
104
105         /* All-numeric, no dot at the end. Fake up a hostent as if
106            we'd actually done a lookup.  What if someone types
107            255.255.255.255?  The test below will succeed
108            spuriously... ???  */
109                   if (inet_pton (af, name, host_addr) <= 0)
110                     {
111                       __set_h_errno (HOST_NOT_FOUND);
112 #ifndef HAVE_LOOKUP_BUFFER
113                       result = (struct hostent *) NULL;
114 #endif
115                       goto done;
116                     }
117
118                   strcpy (hostname, name);
119                   host->h_name = hostname;
120                   host->h_aliases = *host_aliases;
121                   (*host_aliases)[0] = NULL;
122                   (*h_addr_ptrs)[0] = (char *)host_addr;
123                   (*h_addr_ptrs)[1] = (char *)0;
124                   host->h_addr_list = *h_addr_ptrs;
125                   if (_res.options & RES_USE_INET6 && af == AF_INET)
126                     {
127                       /* We need to change the IP v4 address into the
128                          IP v6 address.  */
129                       char tmp[INADDRSZ], *p = (char *) host_addr;
130                       int i;
131
132                       /* Save a copy of the IP v4 address. */
133                       memcpy (tmp, host_addr, INADDRSZ);
134                       /* Mark this ipv6 addr as a mapped ipv4. */
135                       for (i = 0; i < 10; i++)
136                         *p++ = 0x00;
137                       *p++ = 0xff;
138                       *p++ = 0xff;
139                       /* Copy the IP v4 address. */
140                       memcpy (p, tmp, INADDRSZ);
141                       host->h_addrtype = AF_INET6;
142                       host->h_length = IN6ADDRSZ;
143                     }
144                   else
145                     {
146                       host->h_addrtype = af;
147                       host->h_length = addr_size;
148                     }
149                   __set_h_errno (NETDB_SUCCESS);
150 #ifdef HAVE_LOOKUP_BUFFER
151                   status = NSS_STATUS_SUCCESS;
152 #else
153                   result = host;
154 #endif
155                   goto done;
156                 }
157
158               if (!isdigit (*cp) && *cp != '.') break;
159             }
160         }
161
162       if ((isxdigit (name[0]) && strchr (name, ':') != NULL)
163           || name[0] == ':')
164         {
165           const char *cp;
166           char *hostname;
167           struct hostent *host;
168           typedef unsigned char host_addr_t [16];
169           host_addr_t *host_addr;
170           typedef char *host_addr_list_t [2];
171           host_addr_list_t *host_aliases;
172           host_addr_list_t *h_addr_ptrs;
173           size_t size_needed;
174           int addr_size;
175 #ifndef HAVE_AF
176           int af = -1;
177 #endif
178
179           switch (af)
180             {
181             case AF_INET:
182               addr_size = INADDRSZ;
183               break;
184
185             case AF_INET6:
186               addr_size = IN6ADDRSZ;
187               break;
188
189             default:
190               af = (_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET;
191               addr_size = (af == AF_INET6 ) ? IN6ADDRSZ : INADDRSZ;
192               break;
193             }
194
195           size_needed = (sizeof (*host) + sizeof (*host_addr)
196                          + sizeof (*host_aliases) + sizeof (*h_addr_ptrs)
197                          + strlen (name) + 1);
198
199 #ifdef HAVE_LOOKUP_BUFFER
200           if (buflen < size_needed)
201             {
202               __set_errno (ERANGE);
203               goto done;
204             }
205 #else
206           if (buffer_size < size_needed)
207             {
208               char *new_buf;
209               buffer_size = size_needed;
210               new_buf = realloc (buffer, buffer_size);
211
212               if (new_buf == NULL)
213                 {
214                   save = errno;
215                   free (buffer);
216                   __set_errno (save);
217                   buffer = NULL;
218                   buffer_size = 0;
219                   result = (struct hostent *) NULL;
220                   goto done;
221                 }
222               buffer = new_buf;
223             }
224 #endif /* HAVE_LOOKUP_BUFFER */
225
226           memset (buffer, 0, size_needed);
227
228           host = (struct hostent *) buffer;
229           host_addr = (host_addr_t *) ((char *) host + sizeof (*host));
230           host_aliases = (host_addr_list_t *)
231             ((char *) host_addr + sizeof (*host_addr));
232           h_addr_ptrs = (host_addr_list_t *)
233             ((char *) host_aliases + sizeof (*host_aliases));
234           hostname = (char *) h_addr_ptrs + sizeof (*h_addr_ptrs);
235
236           for (cp = name;; ++cp)
237             {
238               if (!*cp)
239                 {
240                   if (*--cp == '.')
241                     break;
242
243                   /* All-IPv6-legal, no dot at the end. Fake up a
244                      hostent as if we'd actually done a lookup.  */
245                   if (inet_pton (af, name, host_addr) <= 0)
246                     {
247                       __set_h_errno (HOST_NOT_FOUND);
248 #ifndef HAVE_LOOKUP_BUFFER
249                       result = (struct hostent *) NULL;
250 #endif
251                       goto done;
252                     }
253
254                   strcpy (hostname, name);
255                   host->h_name = hostname;
256                   host->h_aliases = *host_aliases;
257                   (*host_aliases)[0] = NULL;
258                   (*h_addr_ptrs)[0] = (char *) host_addr;
259                   (*h_addr_ptrs)[1] = (char *) 0;
260                   host->h_addr_list = *h_addr_ptrs;
261                   host->h_addrtype = af;
262                   host->h_length = addr_size;
263                   __set_h_errno (NETDB_SUCCESS);
264 #ifdef HAVE_LOOKUP_BUFFER
265                   status = NSS_STATUS_SUCCESS;
266 #else
267                   result = host;
268 #endif
269                   goto done;
270                 }
271
272               if (!isxdigit (*cp) && *cp != ':' && *cp != '.') break;
273             }
274         }
275     }