update from main archive 960107
[glibc.git] / nss / digits_dots.c
blobb86f66cf4d9a0b0655170d0033b5378e08fa0e12
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]) || name[0] == ':')
164 const char *cp;
165 char *hostname;
166 struct hostent *host;
167 typedef unsigned char host_addr_t [16];
168 host_addr_t *host_addr;
169 typedef char *host_addr_list_t [2];
170 host_addr_list_t *host_aliases;
171 host_addr_list_t *h_addr_ptrs;
172 size_t size_needed;
173 int addr_size;
174 #ifndef HAVE_AF
175 int af = -1;
176 #endif
178 switch (af)
180 case AF_INET:
181 addr_size = INADDRSZ;
182 break;
184 case AF_INET6:
185 addr_size = IN6ADDRSZ;
186 break;
188 default:
189 af = (_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET;
190 addr_size = (af == AF_INET6 ) ? IN6ADDRSZ : INADDRSZ;
191 break;
194 size_needed = (sizeof (*host) + sizeof (*host_addr)
195 + sizeof (*host_aliases) + sizeof (*h_addr_ptrs)
196 + strlen (name) + 1);
198 #ifdef HAVE_LOOKUP_BUFFER
199 if (buflen < size_needed)
201 __set_errno (ERANGE);
202 goto done;
204 #else
205 if (buffer_size < size_needed)
207 char *new_buf;
208 buffer_size = size_needed;
209 new_buf = realloc (buffer, buffer_size);
211 if (new_buf == NULL)
213 save = errno;
214 free (buffer);
215 __set_errno (save);
216 buffer = NULL;
217 buffer_size = 0;
218 result = (struct hostent *) NULL;
219 goto done;
221 buffer = new_buf;
223 #endif /* HAVE_LOOKUP_BUFFER */
225 memset (buffer, 0, size_needed);
227 host = (struct hostent *) buffer;
228 host_addr = (host_addr_t *) ((char *) host + sizeof (*host));
229 host_aliases = (host_addr_list_t *)
230 ((char *) host_addr + sizeof (*host_addr));
231 h_addr_ptrs = (host_addr_list_t *)
232 ((char *) host_aliases + sizeof (*host_aliases));
233 hostname = (char *) h_addr_ptrs + sizeof (*h_addr_ptrs);
235 for (cp = name;; ++cp)
237 if (!*cp)
239 if (*--cp == '.') break;
241 /* All-IPv6-legal, no dot at the end. Fake up a
242 hostent as if we'd actually done a lookup. */
243 if (inet_pton (af, name, host_addr) <= 0)
245 __set_h_errno (HOST_NOT_FOUND);
246 #ifndef HAVE_LOOKUP_BUFFER
247 result = (struct hostent *) NULL;
248 #endif
249 goto done;
252 strcpy (hostname, name);
253 host->h_name = hostname;
254 host->h_aliases = *host_aliases;
255 (*host_aliases)[0] = NULL;
256 (*h_addr_ptrs)[0] = (char *) host_addr;
257 (*h_addr_ptrs)[1] = (char *) 0;
258 host->h_addr_list = *h_addr_ptrs;
259 host->h_addrtype = af;
260 host->h_length = addr_size;
261 __set_h_errno (NETDB_SUCCESS);
262 #ifdef HAVE_LOOKUP_BUFFER
263 status = NSS_STATUS_SUCCESS;
264 #else
265 result = host;
266 #endif
267 goto done;
270 if (!isxdigit (*cp) && *cp != ':' && *cp != '.') break;