Update.
[glibc.git] / nss / digits_dots.c
blobe1baafa843e47bb74c09327ea23c3c11088e1ccb
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.
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
22 * they end in a dot.
24 if (isdigit (name[0]) || (isxdigit (name[0]) || name[0] == ':'))
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
40 switch (af)
42 case AF_INET:
43 addr_size = INADDRSZ;
44 break;
46 case AF_INET6:
47 addr_size = IN6ADDRSZ;
48 break;
50 default:
51 af = (_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET;
52 addr_size = (af == AF_INET6 ) ? IN6ADDRSZ : INADDRSZ;
53 break;
56 size_needed = (sizeof (*host) + sizeof (*host_addr)
57 + sizeof (*host_aliases) + sizeof (*h_addr_ptrs)
58 + strlen (name) + 1);
60 #ifdef HAVE_LOOKUP_BUFFER
61 if (buflen < size_needed)
63 __set_errno (ERANGE);
64 goto done;
66 #else
67 if (buffer_size < size_needed)
69 char *new_buf;
70 buffer_size = size_needed;
71 new_buf = realloc (buffer, buffer_size);
73 if (new_buf == NULL)
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;
83 buffer = new_buf;
85 #endif /* HAVE_LOOKUP_BUFFER */
87 memset (buffer, 0, size_needed);
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);
97 if (isdigit (name[0]))
99 for (cp = name;; ++cp)
101 if (!*cp)
103 if (*--cp == '.') break;
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)
111 __set_h_errno (HOST_NOT_FOUND);
112 #ifndef HAVE_LOOKUP_BUFFER
113 result = (struct hostent *) NULL;
114 #endif
115 goto done;
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)
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;
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;
144 else
146 host->h_addrtype = af;
147 host->h_length = addr_size;
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;
158 if (!isdigit (*cp) && *cp != '.') break;
162 if ((isxdigit (name[0]) && strchr (name, ':') != NULL)
163 || name[0] == ':')
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
179 switch (af)
181 case AF_INET:
182 addr_size = INADDRSZ;
183 break;
185 case AF_INET6:
186 addr_size = IN6ADDRSZ;
187 break;
189 default:
190 af = (_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET;
191 addr_size = (af == AF_INET6 ) ? IN6ADDRSZ : INADDRSZ;
192 break;
195 size_needed = (sizeof (*host) + sizeof (*host_addr)
196 + sizeof (*host_aliases) + sizeof (*h_addr_ptrs)
197 + strlen (name) + 1);
199 #ifdef HAVE_LOOKUP_BUFFER
200 if (buflen < size_needed)
202 __set_errno (ERANGE);
203 goto done;
205 #else
206 if (buffer_size < size_needed)
208 char *new_buf;
209 buffer_size = size_needed;
210 new_buf = realloc (buffer, buffer_size);
212 if (new_buf == NULL)
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;
222 buffer = new_buf;
224 #endif /* HAVE_LOOKUP_BUFFER */
226 memset (buffer, 0, size_needed);
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);
236 for (cp = name;; ++cp)
238 if (!*cp)
240 if (*--cp == '.')
241 break;
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)
247 __set_h_errno (HOST_NOT_FOUND);
248 #ifndef HAVE_LOOKUP_BUFFER
249 result = (struct hostent *) NULL;
250 #endif
251 goto done;
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;
272 if (!isxdigit (*cp) && *cp != ':' && *cp != '.') break;