Update.
[glibc.git] / nss / digits_dots.c
blob944b328a1a1dd44c8602ed76872602907925d74d
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 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 *host_aliases;
32 host_addr_list_t *h_addr_ptrs;
33 size_t size_needed;
34 int addr_size;
35 #ifndef HAVE_AF
36 int af = -1;
37 #endif
39 switch (af)
41 case AF_INET:
42 addr_size = INADDRSZ;
43 break;
45 case AF_INET6:
46 addr_size = IN6ADDRSZ;
47 break;
49 default:
50 af = (_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET;
51 addr_size = af == AF_INET6 ? IN6ADDRSZ : INADDRSZ;
52 break;
55 size_needed = (sizeof (*host_addr)
56 + sizeof (*host_aliases) + sizeof (*h_addr_ptrs)
57 + strlen (name) + 1);
59 #ifdef HAVE_LOOKUP_BUFFER
60 if (buflen < size_needed)
62 __set_errno (ERANGE);
63 goto done;
65 #else
66 if (buffer_size < size_needed)
68 char *new_buf;
69 buffer_size = size_needed;
70 new_buf = realloc (buffer, buffer_size);
72 if (new_buf == NULL)
74 save = errno;
75 free (buffer);
76 buffer = NULL;
77 buffer_size = 0;
78 __set_errno (save);
79 result = (struct hostent *) NULL;
80 goto done;
82 buffer = new_buf;
84 #endif /* HAVE_LOOKUP_BUFFER */
86 memset (buffer, 0, size_needed);
88 host_addr = (host_addr_t *) buffer;
89 host_aliases = (host_addr_list_t *)
90 ((char *) host_addr + sizeof (*host_addr));
91 h_addr_ptrs = (host_addr_list_t *)
92 ((char *) host_aliases + sizeof (*host_aliases));
93 hostname = (char *) h_addr_ptrs + sizeof (*h_addr_ptrs);
95 if (isdigit (name[0]))
97 for (cp = name;; ++cp)
99 if (!*cp)
101 if (*--cp == '.') break;
103 /* All-numeric, no dot at the end. Fake up a hostent as if
104 we'd actually done a lookup. What if someone types
105 255.255.255.255? The test below will succeed
106 spuriously... ??? */
107 if (inet_pton (af, name, host_addr) <= 0)
109 __set_h_errno (HOST_NOT_FOUND);
110 #ifndef HAVE_LOOKUP_BUFFER
111 result = (struct hostent *) NULL;
112 #endif
113 goto done;
116 resbuf.h_name = strcpy (hostname, name);
117 resbuf.h_aliases = *host_aliases;
118 (*host_aliases)[0] = NULL;
119 (*h_addr_ptrs)[0] = (char *)host_addr;
120 (*h_addr_ptrs)[1] = (char *)0;
121 resbuf.h_addr_list = *h_addr_ptrs;
122 if (_res.options & RES_USE_INET6 && af == AF_INET)
124 /* We need to change the IP v4 address into the
125 IP v6 address. */
126 char tmp[INADDRSZ], *p = (char *) host_addr;
127 int i;
129 /* Save a copy of the IP v4 address. */
130 memcpy (tmp, host_addr, INADDRSZ);
131 /* Mark this ipv6 addr as a mapped ipv4. */
132 for (i = 0; i < 10; i++)
133 *p++ = 0x00;
134 *p++ = 0xff;
135 *p++ = 0xff;
136 /* Copy the IP v4 address. */
137 memcpy (p, tmp, INADDRSZ);
138 resbuf.h_addrtype = AF_INET6;
139 resbuf.h_length = IN6ADDRSZ;
141 else
143 resbuf.h_addrtype = af;
144 resbuf.h_length = addr_size;
146 __set_h_errno (NETDB_SUCCESS);
147 #ifdef HAVE_LOOKUP_BUFFER
148 status = NSS_STATUS_SUCCESS;
149 #else
150 result = &resbuf;
151 #endif
152 goto done;
155 if (!isdigit (*cp) && *cp != '.') break;
159 if ((isxdigit (name[0]) && strchr (name, ':') != NULL)
160 || name[0] == ':')
162 const char *cp;
163 char *hostname;
164 typedef unsigned char host_addr_t [16];
165 host_addr_t *host_addr;
166 typedef char *host_addr_list_t [2];
167 host_addr_list_t *host_aliases;
168 host_addr_list_t *h_addr_ptrs;
169 size_t size_needed;
170 int addr_size;
171 #ifndef HAVE_AF
172 int af = -1;
173 #endif
175 switch (af)
177 case AF_INET:
178 addr_size = INADDRSZ;
179 break;
181 case AF_INET6:
182 addr_size = IN6ADDRSZ;
183 break;
185 default:
186 af = (_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET;
187 addr_size = (af == AF_INET6 ) ? IN6ADDRSZ : INADDRSZ;
188 break;
191 size_needed = (sizeof (*host_addr)
192 + sizeof (*host_aliases) + sizeof (*h_addr_ptrs)
193 + strlen (name) + 1);
195 #ifdef HAVE_LOOKUP_BUFFER
196 if (buflen < size_needed)
198 __set_errno (ERANGE);
199 goto done;
201 #else
202 if (buffer_size < size_needed)
204 char *new_buf;
205 buffer_size = size_needed;
206 new_buf = realloc (buffer, buffer_size);
208 if (new_buf == NULL)
210 save = errno;
211 free (buffer);
212 __set_errno (save);
213 buffer = NULL;
214 buffer_size = 0;
215 result = (struct hostent *) NULL;
216 goto done;
218 buffer = new_buf;
220 #endif /* HAVE_LOOKUP_BUFFER */
222 memset (buffer, 0, size_needed);
224 host_addr = (host_addr_t *) buffer;
225 host_aliases = (host_addr_list_t *)
226 ((char *) host_addr + sizeof (*host_addr));
227 h_addr_ptrs = (host_addr_list_t *)
228 ((char *) host_aliases + sizeof (*host_aliases));
229 hostname = (char *) h_addr_ptrs + sizeof (*h_addr_ptrs);
231 for (cp = name;; ++cp)
233 if (!*cp)
235 if (*--cp == '.')
236 break;
238 /* All-IPv6-legal, no dot at the end. Fake up a
239 hostent as if we'd actually done a lookup. */
240 if (inet_pton (af, name, host_addr) <= 0)
242 __set_h_errno (HOST_NOT_FOUND);
243 #ifndef HAVE_LOOKUP_BUFFER
244 result = (struct hostent *) NULL;
245 #endif
246 goto done;
249 resbuf.h_name = strcpy (hostname, name);
250 resbuf.h_aliases = *host_aliases;
251 (*host_aliases)[0] = NULL;
252 (*h_addr_ptrs)[0] = (char *) host_addr;
253 (*h_addr_ptrs)[1] = (char *) 0;
254 resbuf.h_addr_list = *h_addr_ptrs;
255 resbuf.h_addrtype = af;
256 resbuf.h_length = addr_size;
257 __set_h_errno (NETDB_SUCCESS);
258 #ifdef HAVE_LOOKUP_BUFFER
259 status = NSS_STATUS_SUCCESS;
260 #else
261 result = &resbuf;
262 #endif
263 goto done;
266 if (!isxdigit (*cp) && *cp != ':' && *cp != '.') break;