1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <assert.h>
21: #include <errno.h>
22: #include <string.h>
23: #include <stdlib.h>
24: #include <ctype.h>
25: #include <wctype.h>
26: #include <resolv.h>
27: #include <netdb.h>
28: #include <arpa/inet.h>
29: #include "nsswitch.h"
30:
31: #ifdef USE_NSCD
32: # define inet_aton __inet_aton
33: # include <nscd/nscd_proto.h>
34: #endif
35:
36: int
37: __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
38: char **buffer, size_t *buffer_size,
39: size_t buflen, struct hostent **result,
40: enum nss_status *status, int af, int *h_errnop)
41: {
42: int save;
43:
44:
45:
46: if (__res_maybe_init (&_res, 0) == -1)
47: {
48: if (h_errnop)
49: *h_errnop = NETDB_INTERNAL;
50: *result = NULL;
51: return -1;
52: }
53:
54:
55:
56:
57:
58: if (isdigit (name[0]) || isxdigit (name[0]) || name[0] == ':')
59: {
60: const char *cp;
61: char *hostname;
62: typedef unsigned char host_addr_t[16];
63: host_addr_t *host_addr;
64: typedef char *host_addr_list_t[2];
65: host_addr_list_t *h_addr_ptrs;
66: char **h_alias_ptr;
67: size_t size_needed;
68: int addr_size;
69:
70: switch (af)
71: {
72: case AF_INET:
73: addr_size = INADDRSZ;
74: break;
75:
76: case AF_INET6:
77: addr_size = IN6ADDRSZ;
78: break;
79:
80: default:
81: af = (_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET;
82: addr_size = af == AF_INET6 ? IN6ADDRSZ : INADDRSZ;
83: break;
84: }
85:
86: size_needed = (sizeof (*host_addr)
87: + sizeof (*h_addr_ptrs) + strlen (name) + 1);
88:
89: if (buffer_size == NULL)
90: {
91: if (buflen < size_needed)
92: {
93: if (h_errnop != NULL)
94: *h_errnop = TRY_AGAIN;
95: __set_errno (ERANGE);
96: goto done;
97: }
98: }
99: else if (buffer_size != NULL && *buffer_size < size_needed)
100: {
101: char *new_buf;
102: *buffer_size = size_needed;
103: new_buf = (char *) realloc (*buffer, *buffer_size);
104:
105: if (new_buf == NULL)
106: {
107: save = errno;
108: free (*buffer);
109: *buffer = NULL;
110: *buffer_size = 0;
111: __set_errno (save);
112: if (h_errnop != NULL)
113: *h_errnop = TRY_AGAIN;
114: *result = NULL;
115: goto done;
116: }
117: *buffer = new_buf;
118: }
119:
120: memset (*buffer, '\0', size_needed);
121:
122: host_addr = (host_addr_t *) *buffer;
123: h_addr_ptrs = (host_addr_list_t *)
124: ((char *) host_addr + sizeof (*host_addr));
125: h_alias_ptr = (char **) ((char *) h_addr_ptrs + sizeof (*h_addr_ptrs));
126: hostname = (char *) h_alias_ptr + sizeof (*h_alias_ptr);
127:
128: if (isdigit (name[0]))
129: {
130: for (cp = name;; ++cp)
131: {
132: if (*cp == '\0')
133: {
134: int ok;
135:
136: if (*--cp == '.')
137: break;
138:
139:
140:
141:
142:
143: if (af == AF_INET)
144: ok = __inet_aton (name, (struct in_addr *) host_addr);
145: else
146: {
147: assert (af == AF_INET6);
148: ok = inet_pton (af, name, host_addr) > 0;
149: }
150: if (! ok)
151: {
152: *h_errnop = HOST_NOT_FOUND;
153: if (buffer_size)
154: *result = NULL;
155: goto done;
156: }
157:
158: resbuf->h_name = strcpy (hostname, name);
159: h_alias_ptr[0] = NULL;
160: resbuf->h_aliases = h_alias_ptr;
161: (*h_addr_ptrs)[0] = (char *) host_addr;
162: (*h_addr_ptrs)[1] = NULL;
163: resbuf->h_addr_list = *h_addr_ptrs;
164: if (af == AF_INET && (_res.options & RES_USE_INET6))
165: {
166:
167:
168: char tmp[INADDRSZ];
169: char *p = (char *) host_addr;
170: int i;
171:
172:
173: memcpy (tmp, host_addr, INADDRSZ);
174:
175: for (i = 0; i < 10; i++)
176: *p++ = 0x00;
177: *p++ = 0xff;
178: *p++ = 0xff;
179:
180: memcpy (p, tmp, INADDRSZ);
181: resbuf->h_addrtype = AF_INET6;
182: resbuf->h_length = IN6ADDRSZ;
183: }
184: else
185: {
186: resbuf->h_addrtype = af;
187: resbuf->h_length = addr_size;
188: }
189: if (h_errnop != NULL)
190: *h_errnop = NETDB_SUCCESS;
191: if (buffer_size == NULL)
192: *status = NSS_STATUS_SUCCESS;
193: else
194: *result = resbuf;
195: goto done;
196: }
197:
198: if (!isdigit (*cp) && *cp != '.')
199: break;
200: }
201: }
202:
203: if ((isxdigit (name[0]) && strchr (name, ':') != NULL) || name[0] == ':')
204: {
205: const char *cp;
206: char *hostname;
207: typedef unsigned char host_addr_t[16];
208: host_addr_t *host_addr;
209: typedef char *host_addr_list_t[2];
210: host_addr_list_t *h_addr_ptrs;
211: size_t size_needed;
212: int addr_size;
213:
214: switch (af)
215: {
216: default:
217: af = (_res.options & RES_USE_INET6) ? AF_INET6 : AF_INET;
218: if (af == AF_INET6)
219: {
220: addr_size = IN6ADDRSZ;
221: break;
222: }
223:
224:
225: case AF_INET:
226:
227:
228: *h_errnop = HOST_NOT_FOUND;
229: *result = NULL;
230: goto done;
231:
232: case AF_INET6:
233: addr_size = IN6ADDRSZ;
234: break;
235: }
236:
237: size_needed = (sizeof (*host_addr)
238: + sizeof (*h_addr_ptrs) + strlen (name) + 1);
239:
240: if (buffer_size == NULL && buflen < size_needed)
241: {
242: if (h_errnop != NULL)
243: *h_errnop = TRY_AGAIN;
244: __set_errno (ERANGE);
245: goto done;
246: }
247: else if (buffer_size != NULL && *buffer_size < size_needed)
248: {
249: char *new_buf;
250: *buffer_size = size_needed;
251: new_buf = realloc (*buffer, *buffer_size);
252:
253: if (new_buf == NULL)
254: {
255: save = errno;
256: free (*buffer);
257: __set_errno (save);
258: *buffer = NULL;
259: *buffer_size = 0;
260: *result = NULL;
261: goto done;
262: }
263: *buffer = new_buf;
264: }
265:
266: memset (*buffer, '\0', size_needed);
267:
268: host_addr = (host_addr_t *) *buffer;
269: h_addr_ptrs = (host_addr_list_t *)
270: ((char *) host_addr + sizeof (*host_addr));
271: hostname = (char *) h_addr_ptrs + sizeof (*h_addr_ptrs);
272:
273: for (cp = name;; ++cp)
274: {
275: if (!*cp)
276: {
277: if (*--cp == '.')
278: break;
279:
280:
281:
282: if (inet_pton (AF_INET6, name, host_addr) <= 0)
283: {
284: *h_errnop = HOST_NOT_FOUND;
285: if (buffer_size)
286: *result = NULL;
287: goto done;
288: }
289:
290: resbuf->h_name = strcpy (hostname, name);
291: h_alias_ptr[0] = NULL;
292: resbuf->h_aliases = h_alias_ptr;
293: (*h_addr_ptrs)[0] = (char *) host_addr;
294: (*h_addr_ptrs)[1] = (char *) 0;
295: resbuf->h_addr_list = *h_addr_ptrs;
296: resbuf->h_addrtype = AF_INET6;
297: resbuf->h_length = addr_size;
298: *h_errnop = NETDB_SUCCESS;
299: if (buffer_size == NULL)
300: *status = NSS_STATUS_SUCCESS;
301: else
302: *result = resbuf;
303: goto done;
304: }
305:
306: if (!isxdigit (*cp) && *cp != ':' && *cp != '.')
307: break;
308: }
309: }
310: }
311:
312: return 0;
313:
314: done:
315: return 1;
316: }
317: libc_hidden_def (__nss_hostname_digits_dots)