]> git.ipfire.org Git - thirdparty/glibc.git/blob - nis/nss_nis/nis-rpc.c
Make sunrpc code usable again
[thirdparty/glibc.git] / nis / nss_nis / nis-rpc.c
1 /* Copyright (C) 1996-1998,2000,2002,2003,2004,2006
2 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
19
20 #include <nss.h>
21 #include <netdb.h>
22 #include <ctype.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <bits/libc-lock.h>
26 #include <rpcsvc/yp.h>
27 #include <rpcsvc/ypclnt.h>
28
29 #include "nss-nis.h"
30
31 /* Get the declaration of the parser function. */
32 #define ENTNAME rpcent
33 #define EXTERN_PARSER
34 #include <nss/nss_files/files-parse.c>
35
36 __libc_lock_define_initialized (static, lock)
37
38 static intern_t intern;
39
40
41 static void
42 internal_nis_endrpcent (intern_t *intern)
43 {
44 struct response_t *curr = intern->next;
45
46 while (curr != NULL)
47 {
48 struct response_t *last = curr;
49 curr = curr->next;
50 free (last);
51 }
52
53 intern->next = intern->start = NULL;
54 }
55
56 static enum nss_status
57 internal_nis_setrpcent (intern_t *intern)
58 {
59 char *domainname;
60 struct ypall_callback ypcb;
61 enum nss_status status;
62
63 if (yp_get_default_domain (&domainname))
64 return NSS_STATUS_UNAVAIL;
65
66 internal_nis_endrpcent (intern);
67
68 ypcb.foreach = _nis_saveit;
69 ypcb.data = (char *) intern;
70 status = yperr2nss (yp_all (domainname, "rpc.bynumber", &ypcb));
71
72 /* Mark the last buffer as full. */
73 if (intern->next != NULL)
74 intern->next->size = intern->offset;
75
76 intern->next = intern->start;
77 intern->offset = 0;
78
79 return status;
80 }
81
82 enum nss_status
83 _nss_nis_setrpcent (int stayopen)
84 {
85 enum nss_status status;
86
87 __libc_lock_lock (lock);
88
89 status = internal_nis_setrpcent (&intern);
90
91 __libc_lock_unlock (lock);
92
93 return status;
94 }
95
96 enum nss_status
97 _nss_nis_endrpcent (void)
98 {
99 __libc_lock_lock (lock);
100
101 internal_nis_endrpcent (&intern);
102
103 __libc_lock_unlock (lock);
104
105 return NSS_STATUS_SUCCESS;
106 }
107
108 static enum nss_status
109 internal_nis_getrpcent_r (struct rpcent *rpc, char *buffer, size_t buflen,
110 int *errnop, intern_t *intern)
111 {
112 struct parser_data *pdata = (void *) buffer;
113 int parse_res;
114 char *p;
115
116 if (intern->start == NULL)
117 internal_nis_setrpcent (intern);
118
119 if (intern->next == NULL)
120 /* Not one entry in the map. */
121 return NSS_STATUS_NOTFOUND;
122
123 /* Get the next entry until we found a correct one. */
124 do
125 {
126 struct response_t *bucket = intern->next;
127
128 if (__builtin_expect (intern->offset >= bucket->size, 0))
129 {
130 if (bucket->next == NULL)
131 return NSS_STATUS_NOTFOUND;
132
133 /* We look at all the content in the current bucket. Go on
134 to the next. */
135 bucket = intern->next = bucket->next;
136 intern->offset = 0;
137 }
138
139 for (p = &bucket->mem[intern->offset]; isspace (*p); ++p)
140 ++intern->offset;
141
142 size_t len = strlen (p) + 1;
143 if (__builtin_expect (len > buflen, 0))
144 {
145 *errnop = ERANGE;
146 return NSS_STATUS_TRYAGAIN;
147 }
148
149 /* We unfortunately have to copy the data in the user-provided
150 buffer because that buffer might be around for a very long
151 time and the servent structure must remain valid. If we would
152 rely on the BUCKET memory the next 'setservent' or 'endservent'
153 call would destroy it.
154
155 The important thing is that it is a single NUL-terminated
156 string. This is what the parsing routine expects. */
157 p = memcpy (buffer, &bucket->mem[intern->offset], len);
158
159 parse_res = _nss_files_parse_rpcent (p, rpc, pdata, buflen, errnop);
160 if (__builtin_expect (parse_res == -1, 0))
161 return NSS_STATUS_TRYAGAIN;
162
163 intern->offset += len;
164 }
165 while (!parse_res);
166
167 return NSS_STATUS_SUCCESS;
168 }
169
170 enum nss_status
171 _nss_nis_getrpcent_r (struct rpcent *rpc, char *buffer, size_t buflen,
172 int *errnop)
173 {
174 enum nss_status status;
175
176 __libc_lock_lock (lock);
177
178 status = internal_nis_getrpcent_r (rpc, buffer, buflen, errnop, &intern);
179
180 __libc_lock_unlock (lock);
181
182 return status;
183 }
184
185 enum nss_status
186 _nss_nis_getrpcbyname_r (const char *name, struct rpcent *rpc,
187 char *buffer, size_t buflen, int *errnop)
188 {
189 if (name == NULL)
190 {
191 *errnop = EINVAL;
192 return NSS_STATUS_UNAVAIL;
193 }
194
195 intern_t data = { NULL, NULL, 0 };
196 enum nss_status status = internal_nis_setrpcent (&data);
197 if (__builtin_expect (status != NSS_STATUS_SUCCESS, 0))
198 return status;
199
200 int found = 0;
201 while (!found &&
202 ((status = internal_nis_getrpcent_r (rpc, buffer, buflen, errnop,
203 &data)) == NSS_STATUS_SUCCESS))
204 {
205 if (strcmp (rpc->r_name, name) == 0)
206 found = 1;
207 else
208 {
209 int i = 0;
210
211 while (rpc->r_aliases[i] != NULL)
212 {
213 if (strcmp (rpc->r_aliases[i], name) == 0)
214 {
215 found = 1;
216 break;
217 }
218 else
219 ++i;
220 }
221 }
222 }
223
224 internal_nis_endrpcent (&data);
225
226 if (__builtin_expect (!found && status == NSS_STATUS_SUCCESS, 0))
227 return NSS_STATUS_NOTFOUND;
228
229 return status;
230 }
231
232 enum nss_status
233 _nss_nis_getrpcbynumber_r (int number, struct rpcent *rpc,
234 char *buffer, size_t buflen, int *errnop)
235 {
236 char *domain;
237 if (__builtin_expect (yp_get_default_domain (&domain), 0))
238 return NSS_STATUS_UNAVAIL;
239
240 char buf[32];
241 int nlen = snprintf (buf, sizeof (buf), "%d", number);
242
243 char *result;
244 int len;
245 int yperr = yp_match (domain, "rpc.bynumber", buf, nlen, &result, &len);
246
247 if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
248 {
249 enum nss_status retval = yperr2nss (yperr);
250
251 if (retval == NSS_STATUS_TRYAGAIN)
252 *errnop = errno;
253 return retval;
254 }
255
256 if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
257 {
258 free (result);
259 *errnop = ERANGE;
260 return NSS_STATUS_TRYAGAIN;
261 }
262
263 char *p = strncpy (buffer, result, len);
264 buffer[len] = '\0';
265 while (isspace (*p))
266 ++p;
267 free (result);
268
269 int parse_res = _nss_files_parse_rpcent (p, rpc, (void *) buffer, buflen,
270 errnop);
271 if (__builtin_expect (parse_res < 1, 0))
272 {
273 if (parse_res == -1)
274 return NSS_STATUS_TRYAGAIN;
275 else
276 return NSS_STATUS_NOTFOUND;
277 }
278 else
279 return NSS_STATUS_SUCCESS;
280 }