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 <atomic.h>
22: #include <errno.h>
23: #include <stdbool.h>
24: #include "nsswitch.h"
25: #include "sysdep.h"
26: #ifdef USE_NSCD
27: # include <nscd/nscd_proto.h>
28: #endif
29: #ifdef NEED__RES_HCONF
30: # include <resolv/res_hconf.h>
31: #endif
32: #ifdef NEED__RES
33: # include <resolv.h>
34: #endif
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64: #define REENTRANT_NAME APPEND_R (FUNCTION_NAME)
65: #define APPEND_R(name) APPEND_R1 (name)
66: #define APPEND_R1(name) name##_r
67: #define INTERNAL(name) INTERNAL1 (name)
68: #define INTERNAL1(name) __##name
69: #define NEW(name) NEW1 (name)
70: #define NEW1(name) __new_##name
71:
72: #ifdef USE_NSCD
73: # define NSCD_NAME ADD_NSCD (REENTRANT_NAME)
74: # define ADD_NSCD(name) ADD_NSCD1 (name)
75: # define ADD_NSCD1(name) __nscd_##name
76: # define NOT_USENSCD_NAME ADD_NOT_NSCDUSE (DATABASE_NAME)
77: # define ADD_NOT_NSCDUSE(name) ADD_NOT_NSCDUSE1 (name)
78: # define ADD_NOT_NSCDUSE1(name) __nss_not_use_nscd_##name
79: #endif
80:
81: #define FUNCTION_NAME_STRING STRINGIZE (FUNCTION_NAME)
82: #define REENTRANT_NAME_STRING STRINGIZE (REENTRANT_NAME)
83: #define DATABASE_NAME_STRING STRINGIZE (DATABASE_NAME)
84: #define STRINGIZE(name) STRINGIZE1 (name)
85: #define STRINGIZE1(name) #name
86:
87: #ifndef DB_LOOKUP_FCT
88: # define DB_LOOKUP_FCT CONCAT3_1 (__nss_, DATABASE_NAME, _lookup)
89: # define CONCAT3_1(Pre, Name, Post) CONCAT3_2 (Pre, Name, Post)
90: # define CONCAT3_2(Pre, Name, Post) Pre##Name##Post
91: #endif
92:
93:
94: #ifdef NEED_H_ERRNO
95: # define H_ERRNO_PARM , int *h_errnop
96: # define H_ERRNO_VAR , h_errnop
97: # define H_ERRNO_VAR_P h_errnop
98: #else
99: # define H_ERRNO_PARM
100: # define H_ERRNO_VAR
101: # define H_ERRNO_VAR_P NULL
102: #endif
103:
104: #ifdef HAVE_AF
105: # define AF_VAL af
106: #else
107: # define AF_VAL AF_INET
108: #endif
109:
110:
111: typedef enum nss_status (*lookup_function) (ADD_PARAMS, LOOKUP_TYPE *, char *,
112: size_t, int * H_ERRNO_PARM);
113:
114:
115: extern int DB_LOOKUP_FCT (service_user **nip, const char *name, void **fctp)
116: internal_function;
117: libc_hidden_proto (DB_LOOKUP_FCT)
118:
119:
120: int
121: INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
122: size_t buflen, LOOKUP_TYPE **result H_ERRNO_PARM)
123: {
124: static bool startp_initialized;
125: static service_user *startp;
126: static lookup_function start_fct;
127: service_user *nip;
128: union
129: {
130: lookup_function l;
131: void *ptr;
132: } fct;
133:
134: int no_more;
135: enum nss_status status = NSS_STATUS_UNAVAIL;
136: #ifdef USE_NSCD
137: int nscd_status;
138: #endif
139: #ifdef NEED_H_ERRNO
140: bool any_service = false;
141: #endif
142:
143: #ifdef PREPROCESS
144: PREPROCESS;
145: #endif
146:
147: #ifdef HANDLE_DIGITS_DOTS
148: switch (__nss_hostname_digits_dots (name, resbuf, &buffer, NULL,
149: buflen, result, &status, AF_VAL,
150: H_ERRNO_VAR_P))
151: {
152: case -1:
153: return errno;
154: case 1:
155: goto done;
156: }
157: #endif
158:
159: #ifdef USE_NSCD
160: if (NOT_USENSCD_NAME > 0 && ++NOT_USENSCD_NAME > NSS_NSCD_RETRY)
161: NOT_USENSCD_NAME = 0;
162:
163: if (!NOT_USENSCD_NAME)
164: {
165: nscd_status = NSCD_NAME (ADD_VARIABLES, resbuf, buffer, buflen, result
166: H_ERRNO_VAR);
167: if (nscd_status >= 0)
168: return nscd_status;
169: }
170: #endif
171:
172: if (! startp_initialized)
173: {
174: no_more = DB_LOOKUP_FCT (&nip, REENTRANT_NAME_STRING, &fct.ptr);
175: if (no_more)
176: {
177: void *tmp_ptr = (service_user *) -1l;
178: PTR_MANGLE (tmp_ptr);
179: startp = tmp_ptr;
180: }
181: else
182: {
183: #ifdef NEED__RES
184:
185:
186: if (__res_maybe_init (&_res, 0) == -1)
187: {
188: *h_errnop = NETDB_INTERNAL;
189: *result = NULL;
190: return errno;
191: }
192: #endif
193: #ifdef NEED__RES_HCONF
194: if (!_res_hconf.initialized)
195: _res_hconf_init ();
196: #endif
197:
198: void *tmp_ptr = fct.l;
199: PTR_MANGLE (tmp_ptr);
200: start_fct = tmp_ptr;
201: tmp_ptr = nip;
202: PTR_MANGLE (tmp_ptr);
203: startp = tmp_ptr;
204: }
205:
206:
207:
208: atomic_write_barrier ();
209: startp_initialized = true;
210: }
211: else
212: {
213: fct.l = start_fct;
214: PTR_DEMANGLE (fct.l);
215: nip = startp;
216: PTR_DEMANGLE (nip);
217: no_more = nip == (service_user *) -1l;
218: }
219:
220: while (no_more == 0)
221: {
222: #ifdef NEED_H_ERRNO
223: any_service = true;
224: #endif
225:
226: status = DL_CALL_FCT (fct.l, (ADD_VARIABLES, resbuf, buffer, buflen,
227: &errno H_ERRNO_VAR));
228:
229:
230:
231:
232:
233:
234: if (status == NSS_STATUS_TRYAGAIN
235: #ifdef NEED_H_ERRNO
236: && *h_errnop == NETDB_INTERNAL
237: #endif
238: && errno == ERANGE)
239: break;
240:
241: no_more = __nss_next (&nip, REENTRANT_NAME_STRING,
242: &fct.ptr, status, 0);
243: }
244:
245: #ifdef HANDLE_DIGITS_DOTS
246: done:
247: #endif
248: *result = status == NSS_STATUS_SUCCESS ? resbuf : NULL;
249: #ifdef NEED_H_ERRNO
250: if (status != NSS_STATUS_SUCCESS && ! any_service)
251:
252: *h_errnop = NO_RECOVERY;
253: #endif
254: #ifdef POSTPROCESS
255: POSTPROCESS;
256: #endif
257:
258: int res;
259: if (status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND)
260: res = 0;
261:
262: else if (errno == ERANGE && status != NSS_STATUS_TRYAGAIN)
263: res = EINVAL;
264: #ifdef NEED_H_ERRNO
265:
266: else if (status == NSS_STATUS_TRYAGAIN && *h_errnop != NETDB_INTERNAL)
267: res = EAGAIN;
268: #endif
269: else
270: return errno;
271:
272: __set_errno (res);
273: return res;
274: }
275:
276:
277: #include <shlib-compat.h>
278: #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1_2)
279: #define OLD(name) OLD1 (name)
280: #define OLD1(name) __old_##name
281:
282: int
283: attribute_compat_text_section
284: OLD (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
285: size_t buflen, LOOKUP_TYPE **result H_ERRNO_PARM)
286: {
287: int ret = INTERNAL (REENTRANT_NAME) (ADD_VARIABLES, resbuf, buffer,
288: buflen, result H_ERRNO_VAR);
289:
290: if (ret != 0 || result == NULL)
291: ret = -1;
292:
293: return ret;
294: }
295:
296: #define do_symbol_version(real, name, version) \
297: compat_symbol (libc, real, name, version)
298: do_symbol_version (OLD (REENTRANT_NAME), REENTRANT_NAME, GLIBC_2_0);
299: #endif
300:
301:
302:
303:
304: strong_alias (INTERNAL (REENTRANT_NAME), NEW (REENTRANT_NAME));
305:
306: #define do_default_symbol_version(real, name, version) \
307: versioned_symbol (libc, real, name, version)
308: do_default_symbol_version (NEW (REENTRANT_NAME),
309: REENTRANT_NAME, GLIBC_2_1_2);
310:
311: static_link_warning (REENTRANT_NAME)