]> git.ipfire.org Git - thirdparty/glibc.git/blame - nis/nss_nis/nis-service.c
Update.
[thirdparty/glibc.git] / nis / nss_nis / nis-service.c
CommitLineData
34816665 1/* Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc.
6259ec0d 2 This file is part of the GNU C Library.
d6f6ffa1 3 Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
6259ec0d
UD
4
5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
6259ec0d
UD
9
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
41bdb6e2 13 Lesser General Public License for more details.
6259ec0d 14
41bdb6e2
AJ
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
6259ec0d
UD
19
20#include <nss.h>
21#include <netdb.h>
22#include <ctype.h>
23#include <errno.h>
24#include <string.h>
5107cf1d 25#include <bits/libc-lock.h>
6259ec0d
UD
26#include <rpcsvc/yp.h>
27#include <rpcsvc/ypclnt.h>
28
29#include "nss-nis.h"
30
f8b87ef0 31
5713a71e
UD
32/* Get the declaration of the parser function. */
33#define ENTNAME servent
34#define EXTERN_PARSER
35#include <nss/nss_files/files-parse.c>
f8b87ef0 36
6259ec0d
UD
37__libc_lock_define_initialized (static, lock)
38
f166d865
UD
39struct response_t
40{
41 char *val;
42 struct response_t *next;
43};
44
6259ec0d
UD
45struct intern_t
46{
f166d865
UD
47 struct response_t *start;
48 struct response_t *next;
6259ec0d
UD
49};
50typedef struct intern_t intern_t;
51
0d8733c4 52static intern_t intern = { NULL, NULL };
f166d865
UD
53
54static int
0d8733c4 55saveit (int instatus, char *inkey, int inkeylen, char *inval,
f166d865
UD
56 int invallen, char *indata)
57{
0d8733c4 58 intern_t *intern = (intern_t *) indata;
f166d865
UD
59
60 if (instatus != YP_TRUE)
61 return instatus;
62
63 if (inkey && inkeylen > 0 && inval && invallen > 0)
64 {
65 if (intern->start == NULL)
66 {
67 intern->start = malloc (sizeof (struct response_t));
3b965a7d
UD
68 if (intern->start == NULL)
69 return YP_FALSE; /* We have no error code for out of memory */
f166d865
UD
70 intern->next = intern->start;
71 }
72 else
73 {
74 intern->next->next = malloc (sizeof (struct response_t));
3b965a7d
UD
75 if (intern->next->next == NULL)
76 return YP_FALSE; /* We have no error code for out of memory */
f166d865
UD
77 intern->next = intern->next->next;
78 }
79 intern->next->next = NULL;
80 intern->next->val = malloc (invallen + 1);
3b965a7d
UD
81 if (intern->next->val == NULL)
82 return YP_FALSE; /* We have no error code for out of memory */
f166d865
UD
83 strncpy (intern->next->val, inval, invallen);
84 intern->next->val[invallen] = '\0';
85 }
0d8733c4 86
f166d865
UD
87 return 0;
88}
6259ec0d
UD
89
90static enum nss_status
f166d865 91internal_nis_setservent (intern_t *intern)
6259ec0d 92{
f166d865
UD
93 char *domainname;
94 struct ypall_callback ypcb;
0d8733c4
UD
95 enum nss_status status;
96
f166d865
UD
97 if (yp_get_default_domain (&domainname))
98 return NSS_STATUS_UNAVAIL;
0d8733c4 99
f166d865 100 while (intern->start != NULL)
6259ec0d 101 {
f166d865
UD
102 if (intern->start->val != NULL)
103 free (intern->start->val);
104 intern->next = intern->start;
105 intern->start = intern->start->next;
106 free (intern->next);
6259ec0d 107 }
f166d865
UD
108 intern->start = NULL;
109
110 ypcb.foreach = saveit;
0d8733c4
UD
111 ypcb.data = (char *) intern;
112 status = yperr2nss (yp_all (domainname, "services.byname", &ypcb));
f166d865
UD
113 intern->next = intern->start;
114
0d8733c4 115 return status;
6259ec0d
UD
116}
117enum nss_status
51eecc4a 118_nss_nis_setservent (int stayopen)
6259ec0d
UD
119{
120 enum nss_status status;
121
122 __libc_lock_lock (lock);
123
124 status = internal_nis_setservent (&intern);
125
126 __libc_lock_unlock (lock);
127
128 return status;
129}
130
131static enum nss_status
132internal_nis_endservent (intern_t * intern)
133{
f166d865 134 while (intern->start != NULL)
6259ec0d 135 {
f166d865
UD
136 if (intern->start->val != NULL)
137 free (intern->start->val);
138 intern->next = intern->start;
139 intern->start = intern->start->next;
140 free (intern->next);
6259ec0d 141 }
f166d865 142 intern->start = NULL;
0d8733c4 143
6259ec0d
UD
144 return NSS_STATUS_SUCCESS;
145}
146
147enum nss_status
148_nss_nis_endservent (void)
149{
150 enum nss_status status;
151
152 __libc_lock_lock (lock);
153
154 status = internal_nis_endservent (&intern);
155
156 __libc_lock_unlock (lock);
157
158 return status;
159}
160
161static enum nss_status
162internal_nis_getservent_r (struct servent *serv, char *buffer,
d71b808a 163 size_t buflen, int *errnop, intern_t *data)
6259ec0d 164{
5713a71e 165 struct parser_data *pdata = (void *) buffer;
f166d865 166 int parse_res;
6259ec0d
UD
167 char *p;
168
f166d865
UD
169 if (data->start == NULL)
170 internal_nis_setservent (data);
0d8733c4 171
6259ec0d
UD
172 /* Get the next entry until we found a correct one. */
173 do
174 {
f166d865 175 if (data->next == NULL)
34816665
UD
176 return NSS_STATUS_NOTFOUND;
177
9756dfe1 178 p = strncpy (buffer, data->next->val, buflen);
b85697f6 179 while (isspace (*p))
6259ec0d 180 ++p;
0d8733c4 181
5713a71e 182 parse_res = _nss_files_parse_servent (p, serv, pdata, buflen, errnop);
d71b808a 183 if (parse_res == -1)
6259ec0d 184 return NSS_STATUS_TRYAGAIN;
60c96635 185 data->next = data->next->next;
6259ec0d
UD
186 }
187 while (!parse_res);
188
189 return NSS_STATUS_SUCCESS;
190}
191
192enum nss_status
d71b808a
UD
193_nss_nis_getservent_r (struct servent *serv, char *buffer, size_t buflen,
194 int *errnop)
6259ec0d
UD
195{
196 enum nss_status status;
197
198 __libc_lock_lock (lock);
199
d71b808a 200 status = internal_nis_getservent_r (serv, buffer, buflen, errnop, &intern);
6259ec0d
UD
201
202 __libc_lock_unlock (lock);
203
204 return status;
205}
206
207enum nss_status
51eecc4a 208_nss_nis_getservbyname_r (const char *name, const char *protocol,
d71b808a
UD
209 struct servent *serv, char *buffer, size_t buflen,
210 int *errnop)
6259ec0d 211{
0d8733c4 212 intern_t data = { NULL, NULL };
6259ec0d
UD
213 enum nss_status status;
214 int found;
215
e61abf83 216 if (name == NULL)
6259ec0d 217 {
ac9f45cf 218 *errnop = EINVAL;
6259ec0d
UD
219 return NSS_STATUS_UNAVAIL;
220 }
221
b85697f6
UD
222 /* If the protocol is given, we could try if our NIS server knows
223 about services.byservicename map. If yes, we only need one query */
224 if (protocol != NULL)
225 {
226 char key[strlen (name) + strlen (protocol) + 2];
227 char *cp, *domain, *result;
228 size_t keylen, len;
ed40d9c0 229 int int_len;
b85697f6
UD
230
231 /* If this fails, the other solution will also fail. */
232 if (yp_get_default_domain (&domain))
233 return NSS_STATUS_UNAVAIL;
234
235 /* key is: "name/protocol" */
236 cp = stpcpy (key, name);
237 *cp++ = '/';
238 stpcpy (cp, protocol);
239 keylen = strlen (key);
240 status = yperr2nss (yp_match (domain, "services.byservicename", key,
ed40d9c0
UD
241 keylen, &result, &int_len));
242 len = int_len;
b85697f6
UD
243
244 /* If we found the key, it's ok and parse the result. If not,
245 fall through and parse the complete table. */
246 if (status == NSS_STATUS_SUCCESS)
247 {
248 struct parser_data *pdata = (void *) buffer;
249 int parse_res;
250 char *p;
251
252 if ((size_t) (len + 1) > buflen)
253 {
254 free (result);
255 *errnop = ERANGE;
256 return NSS_STATUS_TRYAGAIN;
257 }
258
259 p = strncpy (buffer, result, len);
260 buffer[len] = '\0';
261 while (isspace (*p))
262 ++p;
263 free (result);
264 parse_res = _nss_files_parse_servent (p, serv, pdata,
265 buflen, errnop);
266 if (parse_res < 0)
267 {
268 if (parse_res == -1)
269 return NSS_STATUS_TRYAGAIN;
270 else
34816665 271 return NSS_STATUS_NOTFOUND;
b85697f6
UD
272 }
273 else
274 return NSS_STATUS_SUCCESS;
275 }
276 }
277
6259ec0d
UD
278 status = internal_nis_setservent (&data);
279 if (status != NSS_STATUS_SUCCESS)
280 return status;
281
282 found = 0;
283 while (!found &&
d71b808a
UD
284 ((status = internal_nis_getservent_r (serv, buffer, buflen, errnop,
285 &data)) == NSS_STATUS_SUCCESS))
6259ec0d 286 {
e61abf83 287 if (protocol == NULL || strcmp (serv->s_proto, protocol) == 0)
f166d865
UD
288 {
289 char **cp;
0d8733c4 290
f166d865
UD
291 if (strcmp (serv->s_name, name) == 0)
292 found = 1;
293 else
294 for (cp = serv->s_aliases; *cp; cp++)
0d8733c4 295 if (strcmp (name, *cp) == 0)
f166d865
UD
296 found = 1;
297 }
6259ec0d 298 }
0d8733c4 299
6259ec0d
UD
300 internal_nis_endservent (&data);
301
302 if (!found && status == NSS_STATUS_SUCCESS)
34816665 303 return NSS_STATUS_NOTFOUND;
6259ec0d
UD
304 else
305 return status;
306}
307
308enum nss_status
51eecc4a
AJ
309_nss_nis_getservbyport_r (int port, const char *protocol,
310 struct servent *serv, char *buffer,
311 size_t buflen, int *errnop)
6259ec0d 312{
0d8733c4 313 intern_t data = { NULL, NULL };
6259ec0d
UD
314 enum nss_status status;
315 int found;
316
b85697f6
UD
317 /* If the protocol is given, we only need one query */
318 if (protocol != NULL)
6259ec0d 319 {
b85697f6
UD
320 char key[100 + strlen (protocol) + 2];
321 char *domain, *result;
322 size_t keylen, len;
c7e41631 323 int int_len;
b85697f6
UD
324
325 /* If this fails, the other solution will also fail. */
326 if (yp_get_default_domain (&domain))
327 return NSS_STATUS_UNAVAIL;
328
329 /* key is: "port/protocol" */
330 keylen = snprintf (key, sizeof (key), "%d/%s", port, protocol);
331 status = yperr2nss (yp_match (domain, "services.byname", key,
c7e41631
UD
332 keylen, &result, &int_len));
333 len = int_len;
b85697f6
UD
334
335 /* If we found the key, it's ok and parse the result. If not,
336 fall through and parse the complete table. */
337 if (status == NSS_STATUS_SUCCESS)
338 {
339 struct parser_data *pdata = (void *) buffer;
340 int parse_res;
341 char *p;
342
343 if ((size_t) (len + 1) > buflen)
344 {
345 free (result);
346 *errnop = ERANGE;
347 return NSS_STATUS_TRYAGAIN;
348 }
349
350 p = strncpy (buffer, result, len);
351 buffer[len] = '\0';
352 while (isspace (*p))
353 ++p;
354 free (result);
355 parse_res = _nss_files_parse_servent (p, serv, pdata,
356 buflen, errnop);
357 if (parse_res < 0)
358 {
359 if (parse_res == -1)
360 return NSS_STATUS_TRYAGAIN;
361 else
34816665 362 return NSS_STATUS_NOTFOUND;
b85697f6
UD
363 }
364 else
365 return NSS_STATUS_SUCCESS;
366 }
6259ec0d
UD
367 }
368
369 status = internal_nis_setservent (&data);
370 if (status != NSS_STATUS_SUCCESS)
371 return status;
372
373 found = 0;
374 while (!found &&
d71b808a
UD
375 ((status = internal_nis_getservent_r (serv, buffer, buflen, errnop,
376 &data)) == NSS_STATUS_SUCCESS))
b85697f6
UD
377 if (serv->s_port == port &&
378 (protocol == NULL || strcmp (serv->s_proto, protocol) == 0))
d71b808a 379 found = 1;
6259ec0d
UD
380
381 internal_nis_endservent (&data);
382
383 if (!found && status == NSS_STATUS_SUCCESS)
34816665 384 return NSS_STATUS_NOTFOUND;
6259ec0d
UD
385 else
386 return status;
387}