1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <errno.h>
21: #include <string.h>
22: #include <not-cancel.h>
23: #include <stdio-common/_itoa.h>
24:
25: #include "nscd-client.h"
26: #include "nscd_proto.h"
27:
28:
29: int __nss_not_use_nscd_services;
30:
31:
32: static int nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
33: request_type type, struct servent *resultbuf,
34: char *buf, size_t buflen, struct servent **result);
35:
36:
37: int
38: __nscd_getservbyname_r (const char *name, const char *proto,
39: struct servent *result_buf, char *buf, size_t buflen,
40: struct servent **result)
41: {
42: return nscd_getserv_r (name, strlen (name), proto, GETSERVBYNAME, result_buf,
43: buf, buflen, result);
44: }
45:
46:
47: int
48: __nscd_getservbyport_r (int port, const char *proto,
49: struct servent *result_buf, char *buf, size_t buflen,
50: struct servent **result)
51: {
52: char portstr[3 * sizeof (int) + 2];
53: portstr[sizeof (portstr) - 1] = '\0';
54: char *cp = _itoa_word (port, portstr + sizeof (portstr) - 1, 10, 0);
55:
56: return nscd_getserv_r (portstr, portstr + sizeof (portstr) - cp, proto,
57: GETSERVBYPORT, result_buf, buf, buflen, result);
58: }
59:
60:
61: libc_locked_map_ptr (, __serv_map_handle) attribute_hidden;
62:
63:
64:
65: libc_freeres_fn (serv_map_free)
66: {
67: if (__serv_map_handle.mapped != NO_MAPPING)
68: {
69: void *p = __serv_map_handle.mapped;
70: __serv_map_handle.mapped = NO_MAPPING;
71: free (p);
72: }
73: }
74:
75:
76: static int
77: nscd_getserv_r (const char *crit, size_t critlen, const char *proto,
78: request_type type, struct servent *resultbuf,
79: char *buf, size_t buflen, struct servent **result)
80: {
81: int gc_cycle;
82: int nretries = 0;
83:
84:
85:
86: struct mapped_database *mapped;
87: mapped = __nscd_get_map_ref (GETFDSERV, "services", &__serv_map_handle,
88: &gc_cycle);
89: size_t protolen = proto == NULL ? 0 : strlen (proto);
90: size_t keylen = critlen + 1 + protolen + 1;
91: char *key = alloca (keylen);
92: memcpy (__mempcpy (__mempcpy (key, crit, critlen),
93: "/", 1), proto ?: "", protolen + 1);
94:
95: retry:;
96: const char *s_name = NULL;
97: const char *s_proto = NULL;
98: const uint32_t *aliases_len = NULL;
99: const char *aliases_list = NULL;
100: int retval = -1;
101: const char *recend = (const char *) ~UINTMAX_C (0);
102: int sock = -1;
103: serv_response_header serv_resp;
104:
105: if (mapped != NO_MAPPING)
106: {
107: struct datahead *found = __nscd_cache_search (type, key, keylen, mapped);
108:
109: if (found != NULL)
110: {
111: s_name = (char *) (&found->data[0].servdata + 1);
112: serv_resp = found->data[0].servdata;
113: s_proto = s_name + serv_resp.s_name_len;
114: aliases_len = (uint32_t *) (s_proto + serv_resp.s_proto_len);
115: aliases_list = ((char *) aliases_len
116: + serv_resp.s_aliases_cnt * sizeof (uint32_t));
117: recend = (const char *) found->data + found->recsize;
118:
119:
120: if (mapped->head->gc_cycle != gc_cycle)
121: {
122: retval = -2;
123: goto out;
124: }
125: if (__builtin_expect ((const char *) aliases_len
126: + serv_resp.s_aliases_cnt * sizeof (uint32_t)
127: > recend, 0))
128: goto out;
129:
130: #ifndef _STRING_ARCH_unaligned
131:
132:
133:
134:
135: if (((uintptr_t) aliases_len & (__alignof__ (*aliases_len) - 1))
136: != 0)
137: {
138: uint32_t *tmp = alloca (serv_resp.s_aliases_cnt
139: * sizeof (uint32_t));
140: aliases_len = memcpy (tmp, aliases_len,
141: serv_resp.s_aliases_cnt
142: * sizeof (uint32_t));
143: }
144: #endif
145: }
146: }
147:
148: if (s_name == NULL)
149: {
150: sock = __nscd_open_socket (key, keylen, type, &serv_resp,
151: sizeof (serv_resp));
152: if (sock == -1)
153: {
154: __nss_not_use_nscd_services = 1;
155: goto out;
156: }
157: }
158:
159:
160: *result = NULL;
161:
162: if (__builtin_expect (serv_resp.found == -1, 0))
163: {
164:
165: __nss_not_use_nscd_services = 1;
166: goto out_close;
167: }
168:
169: if (serv_resp.found == 1)
170: {
171: char *cp = buf;
172: uintptr_t align1;
173: uintptr_t align2;
174: size_t total_len;
175: ssize_t cnt;
176: int n;
177:
178:
179:
180:
181: align1 = ((__alignof__ (char *) - (cp - ((char *) 0)))
182: & (__alignof__ (char *) - 1));
183: align2 = ((__alignof__ (char *) - ((cp + align1 + serv_resp.s_name_len
184: + serv_resp.s_proto_len)
185: - ((char *) 0)))
186: & (__alignof__ (char *) - 1));
187: if (buflen < (align1 + serv_resp.s_name_len + serv_resp.s_proto_len
188: + align2
189: + (serv_resp.s_aliases_cnt + 1) * sizeof (char *)))
190: {
191: no_room:
192: __set_errno (ERANGE);
193: retval = ERANGE;
194: goto out_close;
195: }
196: cp += align1;
197:
198:
199: resultbuf->s_aliases = (char **) cp;
200: cp += (serv_resp.s_aliases_cnt + 1) * sizeof (char *);
201:
202: resultbuf->s_name = cp;
203: cp += serv_resp.s_name_len;
204: resultbuf->s_proto = cp;
205: cp += serv_resp.s_proto_len + align2;
206: resultbuf->s_port = serv_resp.s_port;
207:
208: if (s_name == NULL)
209: {
210: struct iovec vec[2];
211:
212: vec[0].iov_base = resultbuf->s_name;
213: vec[0].iov_len = serv_resp.s_name_len + serv_resp.s_proto_len;
214: total_len = vec[0].iov_len;
215: n = 1;
216:
217: if (serv_resp.s_aliases_cnt > 0)
218: {
219: aliases_len = alloca (serv_resp.s_aliases_cnt
220: * sizeof (uint32_t));
221: vec[n].iov_base = (void *) aliases_len;
222: vec[n].iov_len = serv_resp.s_aliases_cnt * sizeof (uint32_t);
223:
224: total_len += serv_resp.s_aliases_cnt * sizeof (uint32_t);
225: ++n;
226: }
227:
228: if ((size_t) __readvall (sock, vec, n) != total_len)
229: goto out_close;
230: }
231: else
232: memcpy (resultbuf->s_name, s_name,
233: serv_resp.s_name_len + serv_resp.s_proto_len);
234:
235:
236: total_len = 0;
237: for (cnt = 0; cnt < serv_resp.s_aliases_cnt; ++cnt)
238: {
239: resultbuf->s_aliases[cnt] = cp;
240: cp += aliases_len[cnt];
241: total_len += aliases_len[cnt];
242: }
243: resultbuf->s_aliases[cnt] = NULL;
244:
245: if (__builtin_expect ((const char *) aliases_list + total_len > recend,
246: 0))
247: {
248:
249:
250: if (aliases_list != NULL && mapped->head->gc_cycle != gc_cycle)
251: retval = -2;
252: goto out_close;
253: }
254:
255:
256: if (__builtin_expect (cp > buf + buflen, 0))
257: {
258:
259:
260: if (aliases_list != NULL && mapped->head->gc_cycle != gc_cycle)
261: {
262: retval = -2;
263: goto out_close;
264: }
265: goto no_room;
266: }
267:
268:
269: if (aliases_list == NULL)
270: {
271: if (total_len == 0
272: || ((size_t) __readall (sock, resultbuf->s_aliases[0], total_len)
273: == total_len))
274: {
275: retval = 0;
276: *result = resultbuf;
277: }
278: }
279: else
280: {
281: memcpy (resultbuf->s_aliases[0], aliases_list, total_len);
282:
283:
284: if (resultbuf->s_name[serv_resp.s_name_len - 1] != '\0'
285: || resultbuf->s_proto[serv_resp.s_proto_len - 1] != '\0'
286: || ({for (cnt = 0; cnt < serv_resp.s_aliases_cnt; ++cnt)
287: if (resultbuf->s_aliases[cnt][aliases_len[cnt] - 1]
288: != '\0')
289: break;
290: cnt < serv_resp.s_aliases_cnt; }))
291: {
292:
293: if (mapped->head->gc_cycle != gc_cycle)
294: retval = -2;
295: goto out_close;
296: }
297:
298: retval = 0;
299: *result = resultbuf;
300: }
301: }
302: else
303: {
304:
305: __set_errno (0);
306:
307: retval = 0;
308: }
309:
310: out_close:
311: if (sock != -1)
312: close_not_cancel_no_status (sock);
313: out:
314: if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0)
315: {
316:
317:
318:
319: if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1)
320: {
321:
322: if (atomic_decrement_val (&mapped->counter) == 0)
323: __nscd_unmap (mapped);
324: mapped = NO_MAPPING;
325: }
326:
327: if (retval != -1)
328: goto retry;
329: }
330:
331: return retval;
332: }