]> sourceware.org Git - glibc.git/blame - nis/ypclnt.c
Update.
[glibc.git] / nis / ypclnt.c
CommitLineData
66f72f03 1/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
6259ec0d 2 This file is part of the GNU C Library.
b85697f6 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
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
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
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
19
ee74a442 20#include <errno.h>
cc3fa755 21#include <fcntl.h>
6259ec0d
UD
22#include <string.h>
23#include <unistd.h>
4360eafd 24#include <libintl.h>
26dee9c4 25#include <rpc/rpc.h>
f21acc89 26#include <rpcsvc/nis.h>
6259ec0d
UD
27#include <rpcsvc/yp.h>
28#include <rpcsvc/ypclnt.h>
29#include <rpcsvc/ypupd.h>
9931ba24 30#include <sys/uio.h>
cc3fa755 31#include <bits/libc-lock.h>
6259ec0d 32
9931ba24
UD
33/* This should only be defined on systems with a BSD compatible ypbind */
34#ifndef BINDINGDIR
35# define BINDINGDIR "/var/yp/binding"
36#endif
37
6259ec0d
UD
38struct dom_binding
39 {
40 struct dom_binding *dom_pnext;
41 char dom_domain[YPMAXDOMAIN + 1];
42 struct sockaddr_in dom_server_addr;
43 int dom_socket;
44 CLIENT *dom_client;
6259ec0d
UD
45 };
46typedef struct dom_binding dom_binding;
47
cc3fa755
UD
48static struct timeval RPCTIMEOUT = {25, 0};
49static struct timeval UDPTIMEOUT = {5, 0};
66f72f03 50static int const MAXTRIES = 2;
f21acc89 51static char __ypdomainname[NIS_MAXNAMELEN + 1] = "\0";
6259ec0d
UD
52__libc_lock_define_initialized (static, ypbindlist_lock)
53static dom_binding *__ypbindlist = NULL;
54
f8b87ef0 55
6259ec0d 56static int
cc3fa755 57__yp_bind (const char *domain, dom_binding **ypdb)
6259ec0d
UD
58{
59 struct sockaddr_in clnt_saddr;
60 struct ypbind_resp ypbr;
cc3fa755 61 dom_binding *ysd = NULL;
6259ec0d
UD
62 int clnt_sock;
63 CLIENT *client;
64 int is_new = 0;
6259ec0d 65
6ff5bc68 66 if (domain == NULL || domain[0] == '\0')
6259ec0d
UD
67 return YPERR_BADARGS;
68
cc3fa755 69 if (ypdb != NULL)
6259ec0d 70 {
cc3fa755
UD
71 ysd = *ypdb;
72 while (ysd != NULL)
73 {
74 if (strcmp (domain, ysd->dom_domain) == 0)
75 break;
76 ysd = ysd->dom_pnext;
77 }
6259ec0d
UD
78 }
79
80 if (ysd == NULL)
81 {
82 is_new = 1;
bd355af0 83 ysd = (dom_binding *) calloc (1, sizeof *ysd);
6259ec0d
UD
84 }
85
9931ba24 86#if USE_BINDINGDIR
b85697f6
UD
87 if (ysd->dom_client == NULL)
88 {
89 /* Try binding dir at first if we have no binding */
90 char path[sizeof (BINDINGDIR) + strlen (domain) + 10];
91 struct iovec vec[2];
92 unsigned short port;
93 int fd;
94
95 sprintf (path, "%s/%s.%d", BINDINGDIR, domain, YPBINDVERS);
96 fd = open (path, O_RDONLY);
97 if (fd >= 0)
9931ba24 98 {
b85697f6
UD
99 /* We have a binding file and could save a RPC call */
100 vec[0].iov_base = &port;
101 vec[0].iov_len = sizeof (port);
102 vec[1].iov_base = &ypbr;
103 vec[1].iov_len = sizeof (ypbr);
104
105 if (readv (fd, vec, 2) == sizeof (port) + sizeof (ypbr))
9931ba24 106 {
b85697f6
UD
107 ysd->dom_server_addr.sin_family = AF_INET;
108 memcpy (&ysd->dom_server_addr.sin_port,
109 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
110 sizeof (ysd->dom_server_addr.sin_port));
111 memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
112 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
113 sizeof (ysd->dom_server_addr.sin_addr.s_addr));
114 strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
115 ysd->dom_domain[YPMAXDOMAIN] = '\0';
116
117 ysd->dom_socket = RPC_ANYSOCK;
118 ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG,
119 YPVERS, UDPTIMEOUT,
120 &ysd->dom_socket);
121
122 if (ysd->dom_client != NULL)
123 /* If the program exits, close the socket */
124 if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
125 perror ("fcntl: F_SETFD");
9931ba24 126 }
b85697f6 127 close (fd);
9931ba24 128 }
b85697f6 129 }
9931ba24
UD
130#endif /* USE_BINDINGDIR */
131
b85697f6
UD
132 if (ysd->dom_client == NULL)
133 {
134 memset (&clnt_saddr, '\0', sizeof clnt_saddr);
135 clnt_saddr.sin_family = AF_INET;
136 clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
137 clnt_sock = RPC_ANYSOCK;
138 client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
139 &clnt_sock, 0, 0);
140 if (client == NULL)
36a8586d 141 {
b85697f6
UD
142 if (is_new)
143 free (ysd);
144 return YPERR_YPBIND;
145 }
146 /* Check the port number -- should be < IPPORT_RESERVED.
147 If not, it's possible someone has registered a bogus
148 ypbind with the portmapper and is trying to trick us. */
149 if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED)
150 {
151 clnt_destroy (client);
152 if (is_new)
153 free (ysd);
154 return YPERR_YPBIND;
155 }
156
157 if (clnt_call (client, YPBINDPROC_DOMAIN,
158 (xdrproc_t) xdr_domainname, (caddr_t) &domain,
159 (xdrproc_t) xdr_ypbind_resp,
160 (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS)
161 {
162 clnt_destroy (client);
163 if (is_new)
164 free (ysd);
165 return YPERR_YPBIND;
166 }
167
168 clnt_destroy (client);
169
170 if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
171 {
172 fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"),
173 ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
174 if (is_new)
175 free (ysd);
176 return YPERR_DOMAIN;
177 }
178 memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
179 ysd->dom_server_addr.sin_family = AF_INET;
180 memcpy (&ysd->dom_server_addr.sin_port,
181 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
182 sizeof (ysd->dom_server_addr.sin_port));
183 memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
184 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
185 sizeof (ysd->dom_server_addr.sin_addr.s_addr));
186 strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
187 ysd->dom_domain[YPMAXDOMAIN] = '\0';
6259ec0d 188
6259ec0d
UD
189 ysd->dom_socket = RPC_ANYSOCK;
190 ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
cc3fa755 191 UDPTIMEOUT, &ysd->dom_socket);
6259ec0d 192
b85697f6
UD
193 if (ysd->dom_client != NULL)
194 /* If the program exits, close the socket */
195 if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
196 perror ("fcntl: F_SETFD");
6259ec0d 197 }
6259ec0d 198
b85697f6
UD
199 if (ysd->dom_client == NULL)
200 {
201 if (is_new)
202 free (ysd);
203 return YPERR_YPSERV;
204 }
6259ec0d 205
cc3fa755 206 if (is_new && ypdb != NULL)
6259ec0d 207 {
cc3fa755
UD
208 ysd->dom_pnext = *ypdb;
209 *ypdb = ysd;
6259ec0d
UD
210 }
211
6259ec0d
UD
212 return YPERR_SUCCESS;
213}
214
215static void
216__yp_unbind (dom_binding *ydb)
217{
218 clnt_destroy (ydb->dom_client);
219 ydb->dom_client = NULL;
b85697f6
UD
220}
221
222int
223yp_bind (const char *indomain)
224{
225 int status;
226
227 __libc_lock_lock (ypbindlist_lock);
228
229 status = __yp_bind (indomain, &__ypbindlist);
230
231 __libc_lock_unlock (ypbindlist_lock);
232
233 return status;
234}
235
236static void
237yp_unbind_locked (const char *indomain)
238{
239 dom_binding *ydbptr, *ydbptr2;
240
241 ydbptr2 = NULL;
242 ydbptr = __ypbindlist;
243
244 while (ydbptr != NULL)
245 {
246 if (strcmp (ydbptr->dom_domain, indomain) == 0)
247 {
248 dom_binding *work;
249
250 work = ydbptr;
251 if (ydbptr2 == NULL)
252 __ypbindlist = __ypbindlist->dom_pnext;
253 else
254 ydbptr2 = ydbptr->dom_pnext;
255 __yp_unbind (work);
256 free (work);
257 break;
258 }
259 ydbptr2 = ydbptr;
260 ydbptr = ydbptr->dom_pnext;
261 }
262}
263
264void
265yp_unbind (const char *indomain)
266{
267 __libc_lock_lock (ypbindlist_lock);
268
269 yp_unbind_locked (indomain);
270
271 __libc_lock_unlock (ypbindlist_lock);
272
273 return;
6259ec0d
UD
274}
275
276static int
277do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
278 caddr_t req, xdrproc_t xres, caddr_t resp)
279{
280 dom_binding *ydb = NULL;
cc3fa755 281 bool_t use_ypbindlist = FALSE;
d111572f
UD
282 int try, status;
283 enum clnt_stat result;
a788b6c2 284 int saved_errno = errno;
6259ec0d
UD
285
286 try = 0;
d111572f 287 status = YPERR_YPERR;
6259ec0d 288
cc3fa755
UD
289 __libc_lock_lock (ypbindlist_lock);
290 if (__ypbindlist != NULL)
6259ec0d 291 {
cc3fa755
UD
292 ydb = __ypbindlist;
293 while (ydb != NULL)
294 {
295 if (strcmp (domain, ydb->dom_domain) == 0)
296 break;
297 ydb = ydb->dom_pnext;
298 }
299 if (ydb != NULL)
300 use_ypbindlist = TRUE;
301 else
302 __libc_lock_unlock (ypbindlist_lock);
303 }
304 else
305 __libc_lock_unlock (ypbindlist_lock);
6259ec0d 306
a588b67d 307 while (try < MAXTRIES && status != YPERR_SUCCESS)
cc3fa755 308 {
6259ec0d
UD
309 if (__yp_bind (domain, &ydb) != 0)
310 {
cc3fa755
UD
311 if (use_ypbindlist)
312 __libc_lock_unlock (ypbindlist_lock);
a788b6c2 313 __set_errno (saved_errno);
6259ec0d
UD
314 return YPERR_DOMAIN;
315 }
316
317 result = clnt_call (ydb->dom_client, prog,
cc3fa755 318 xargs, req, xres, resp, RPCTIMEOUT);
6259ec0d
UD
319
320 if (result != RPC_SUCCESS)
321 {
b85697f6
UD
322 /* Don't print the error message on the first try. It
323 could be that we use cached data which is now invalid. */
324 if (try != 0)
325 clnt_perror (ydb->dom_client, "do_ypcall: clnt_call");
326
327 if (use_ypbindlist)
328 {
329 /* We use ypbindlist, and the old cached data is
330 invalid. unbind now and create a new binding */
331 yp_unbind_locked (domain);
332 __libc_lock_unlock (ypbindlist_lock);
333 use_ypbindlist = FALSE;
334 }
335 else
cc3fa755
UD
336 {
337 __yp_unbind (ydb);
338 free (ydb);
cc3fa755 339 }
b85697f6
UD
340
341 ydb = NULL;
66f72f03 342 status = YPERR_RPC;
6259ec0d 343 }
d111572f
UD
344 else
345 status = YPERR_SUCCESS;
346
6259ec0d
UD
347 try++;
348 }
cc3fa755
UD
349 if (use_ypbindlist)
350 {
351 __libc_lock_unlock (ypbindlist_lock);
352 use_ypbindlist = FALSE;
353 }
354 else
bd355af0
UD
355 if (ydb != NULL)
356 {
357 __yp_unbind (ydb);
358 free (ydb);
359 ydb = NULL;
360 }
6259ec0d 361
a788b6c2
UD
362 __set_errno (saved_errno);
363
d111572f 364 return status;
6259ec0d
UD
365}
366
6259ec0d
UD
367
368__libc_lock_define_initialized (static, domainname_lock)
369
370int
371yp_get_default_domain (char **outdomain)
372{
373 int result = YPERR_SUCCESS;;
374 *outdomain = NULL;
375
376 __libc_lock_lock (domainname_lock);
377
378 if (__ypdomainname[0] == '\0')
379 {
f21acc89 380 if (getdomainname (__ypdomainname, NIS_MAXNAMELEN))
6259ec0d 381 result = YPERR_NODOM;
ee74a442
UD
382 else if (strcmp (__ypdomainname, "(none)") == 0)
383 {
b85697f6 384 /* If domainname is not set, some systems will return "(none)" */
ee74a442
UD
385 __ypdomainname[0] = '\0';
386 result = YPERR_NODOM;
387 }
6259ec0d
UD
388 else
389 *outdomain = __ypdomainname;
390 }
391 else
392 *outdomain = __ypdomainname;
393
394 __libc_lock_unlock (domainname_lock);
395
396 return result;
397}
398
399int
400__yp_check (char **domain)
401{
402 char *unused;
403
404 if (__ypdomainname[0] == '\0')
405 if (yp_get_default_domain (&unused))
406 return 0;
6259ec0d
UD
407
408 if (domain)
409 *domain = __ypdomainname;
410
411 if (yp_bind (__ypdomainname) == 0)
412 return 1;
413 return 0;
414}
415
416int
417yp_match (const char *indomain, const char *inmap, const char *inkey,
418 const int inkeylen, char **outval, int *outvallen)
419{
420 ypreq_key req;
421 ypresp_val resp;
d111572f 422 enum clnt_stat result;
6259ec0d
UD
423
424 if (indomain == NULL || indomain[0] == '\0' ||
425 inmap == NULL || inmap[0] == '\0' ||
426 inkey == NULL || inkey[0] == '\0' || inkeylen <= 0)
427 return YPERR_BADARGS;
428
68dbb3a6
UD
429 req.domain = (char *) indomain;
430 req.map = (char *) inmap;
431 req.key.keydat_val = (char *) inkey;
6259ec0d
UD
432 req.key.keydat_len = inkeylen;
433
434 *outval = NULL;
435 *outvallen = 0;
436 memset (&resp, '\0', sizeof (resp));
437
438 result = do_ypcall (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
439 (caddr_t) & req, (xdrproc_t) xdr_ypresp_val,
440 (caddr_t) & resp);
441
4bca4c17
UD
442 if (result != YPERR_SUCCESS)
443 return result;
6259ec0d
UD
444 if (resp.stat != YP_TRUE)
445 return ypprot_err (resp.stat);
446
447 *outvallen = resp.val.valdat_len;
448 *outval = malloc (*outvallen + 1);
449 memcpy (*outval, resp.val.valdat_val, *outvallen);
450 (*outval)[*outvallen] = '\0';
451
452 xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
453
454 return YPERR_SUCCESS;
455}
456
457int
458yp_first (const char *indomain, const char *inmap, char **outkey,
459 int *outkeylen, char **outval, int *outvallen)
460{
461 ypreq_nokey req;
462 ypresp_key_val resp;
d111572f 463 enum clnt_stat result;
6259ec0d
UD
464
465 if (indomain == NULL || indomain[0] == '\0' ||
466 inmap == NULL || inmap[0] == '\0')
467 return YPERR_BADARGS;
468
68dbb3a6
UD
469 req.domain = (char *) indomain;
470 req.map = (char *) inmap;
6259ec0d
UD
471
472 *outkey = *outval = NULL;
473 *outkeylen = *outvallen = 0;
474 memset (&resp, '\0', sizeof (resp));
475
476 result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
477 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
478 (caddr_t) & resp);
479
480 if (result != RPC_SUCCESS)
d111572f 481 return YPERR_RPC;
6259ec0d
UD
482 if (resp.stat != YP_TRUE)
483 return ypprot_err (resp.stat);
484
485 *outkeylen = resp.key.keydat_len;
486 *outkey = malloc (*outkeylen + 1);
487 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
488 (*outkey)[*outkeylen] = '\0';
489 *outvallen = resp.val.valdat_len;
490 *outval = malloc (*outvallen + 1);
491 memcpy (*outval, resp.val.valdat_val, *outvallen);
492 (*outval)[*outvallen] = '\0';
493
494 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
495
496 return YPERR_SUCCESS;
497}
498
499int
500yp_next (const char *indomain, const char *inmap, const char *inkey,
501 const int inkeylen, char **outkey, int *outkeylen, char **outval,
502 int *outvallen)
503{
504 ypreq_key req;
505 ypresp_key_val resp;
d111572f 506 enum clnt_stat result;
6259ec0d
UD
507
508 if (indomain == NULL || indomain[0] == '\0' ||
509 inmap == NULL || inmap[0] == '\0' ||
510 inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
511 return YPERR_BADARGS;
512
68dbb3a6
UD
513 req.domain = (char *) indomain;
514 req.map = (char *) inmap;
515 req.key.keydat_val = (char *) inkey;
6259ec0d
UD
516 req.key.keydat_len = inkeylen;
517
518 *outkey = *outval = NULL;
519 *outkeylen = *outvallen = 0;
520 memset (&resp, '\0', sizeof (resp));
521
522 result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
523 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
524 (caddr_t) & resp);
525
4bca4c17
UD
526 if (result != YPERR_SUCCESS)
527 return result;
6259ec0d
UD
528 if (resp.stat != YP_TRUE)
529 return ypprot_err (resp.stat);
530
531 *outkeylen = resp.key.keydat_len;
532 *outkey = malloc (*outkeylen + 1);
533 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
534 (*outkey)[*outkeylen] = '\0';
535 *outvallen = resp.val.valdat_len;
536 *outval = malloc (*outvallen + 1);
537 memcpy (*outval, resp.val.valdat_val, *outvallen);
538 (*outval)[*outvallen] = '\0';
539
540 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
541
542 return YPERR_SUCCESS;
543}
544
545int
546yp_master (const char *indomain, const char *inmap, char **outname)
547{
548 ypreq_nokey req;
549 ypresp_master resp;
d111572f 550 enum clnt_stat result;
6259ec0d
UD
551
552 if (indomain == NULL || indomain[0] == '\0' ||
553 inmap == NULL || inmap[0] == '\0')
554 return YPERR_BADARGS;
555
68dbb3a6
UD
556 req.domain = (char *) indomain;
557 req.map = (char *) inmap;
6259ec0d
UD
558
559 memset (&resp, '\0', sizeof (ypresp_master));
560
561 result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
562 (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);
563
4bca4c17
UD
564 if (result != YPERR_SUCCESS)
565 return result;
6259ec0d
UD
566 if (resp.stat != YP_TRUE)
567 return ypprot_err (resp.stat);
568
569 *outname = strdup (resp.peer);
570 xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
571
d111572f 572 return *outname == NULL ? YPERR_YPERR : YPERR_SUCCESS;
6259ec0d
UD
573}
574
575int
576yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
577{
578 struct ypreq_nokey req;
579 struct ypresp_order resp;
d111572f 580 enum clnt_stat result;
6259ec0d
UD
581
582 if (indomain == NULL || indomain[0] == '\0' ||
583 inmap == NULL || inmap == '\0')
584 return YPERR_BADARGS;
585
68dbb3a6
UD
586 req.domain = (char *) indomain;
587 req.map = (char *) inmap;
6259ec0d
UD
588
589 memset (&resp, '\0', sizeof (resp));
590
591 result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
592 (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp);
593
4bca4c17
UD
594 if (result != YPERR_SUCCESS)
595 return result;
6259ec0d
UD
596 if (resp.stat != YP_TRUE)
597 return ypprot_err (resp.stat);
598
599 *outorder = resp.ordernum;
600 xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
601
602 return YPERR_SUCCESS;
603}
604
605static void *ypall_data;
3e5f5557
UD
606static int (*ypall_foreach) __P ((int status, char *key, int keylen,
607 char *val, int vallen, char *data));
6259ec0d
UD
608
609static bool_t
a1129917 610__xdr_ypresp_all (XDR *xdrs, u_long *objp)
6259ec0d
UD
611{
612 while (1)
613 {
614 struct ypresp_all resp;
615
616 memset (&resp, '\0', sizeof (struct ypresp_all));
617 if (!xdr_ypresp_all (xdrs, &resp))
618 {
619 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
620 *objp = YP_YPERR;
d111572f 621 return FALSE;
6259ec0d
UD
622 }
623 if (resp.more == 0)
624 {
625 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
626 *objp = YP_NOMORE;
d111572f 627 return TRUE;
6259ec0d
UD
628 }
629
630 switch (resp.ypresp_all_u.val.stat)
631 {
632 case YP_TRUE:
633 {
634 char key[resp.ypresp_all_u.val.key.keydat_len + 1];
635 char val[resp.ypresp_all_u.val.val.valdat_len + 1];
636 int keylen = resp.ypresp_all_u.val.key.keydat_len;
637 int vallen = resp.ypresp_all_u.val.val.valdat_len;
638
b85697f6
UD
639 /* We are not allowed to modify the key and val data.
640 But we are allowed to add data behind the buffer,
641 if we don't modify the length. So add an extra NUL
642 character to avoid trouble with broken code. */
6259ec0d
UD
643 *objp = YP_TRUE;
644 memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
645 key[keylen] = '\0';
646 memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
647 val[vallen] = '\0';
648 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
649 if ((*ypall_foreach) (*objp, key, keylen,
650 val, vallen, ypall_data))
651 return TRUE;
652 }
653 break;
6259ec0d
UD
654 default:
655 *objp = resp.ypresp_all_u.val.stat;
656 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
b85697f6
UD
657 /* Sun says we don't need to make this call, but must return
658 immediatly. Since Solaris makes this call, we will call
659 the callback function, too. */
660 (*ypall_foreach) (*objp, NULL, 0, NULL, 0, ypall_data);
6259ec0d
UD
661 return TRUE;
662 }
663 }
664}
665
666int
667yp_all (const char *indomain, const char *inmap,
668 const struct ypall_callback *incallback)
669{
670 struct ypreq_nokey req;
cc3fa755 671 dom_binding *ydb = NULL;
d111572f
UD
672 int try, res;
673 enum clnt_stat result;
6259ec0d
UD
674 struct sockaddr_in clnt_sin;
675 CLIENT *clnt;
676 unsigned long status;
677 int clnt_sock;
a788b6c2 678 int saved_errno = errno;
6259ec0d
UD
679
680 if (indomain == NULL || indomain[0] == '\0' ||
681 inmap == NULL || inmap == '\0')
682 return YPERR_BADARGS;
683
684 try = 0;
d111572f 685 res = YPERR_YPERR;
6259ec0d 686
d111572f 687 while (try < MAXTRIES && res != YPERR_SUCCESS)
6259ec0d 688 {
6259ec0d
UD
689 if (__yp_bind (indomain, &ydb) != 0)
690 {
a788b6c2 691 __set_errno (saved_errno);
6259ec0d
UD
692 return YPERR_DOMAIN;
693 }
694
cf26217d
UD
695 /* YPPROC_ALL get its own TCP channel to ypserv. Therefore we
696 close the socket opened by the __yp_bind call. */
697 close (ydb->dom_socket);
6259ec0d
UD
698 clnt_sock = RPC_ANYSOCK;
699 clnt_sin = ydb->dom_server_addr;
700 clnt_sin.sin_port = 0;
701 clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
702 if (clnt == NULL)
a788b6c2 703 {
999b2f6b 704 __yp_unbind (ydb);
a788b6c2
UD
705 __set_errno (saved_errno);
706 return YPERR_PMAP;
707 }
68dbb3a6
UD
708 req.domain = (char *) indomain;
709 req.map = (char *) inmap;
6259ec0d
UD
710
711 ypall_foreach = incallback->foreach;
712 ypall_data = (void *) incallback->data;
713
3e5f5557
UD
714 result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey,
715 (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
cc3fa755 716 (caddr_t) &status, RPCTIMEOUT);
6259ec0d
UD
717
718 if (result != RPC_SUCCESS)
719 {
d111572f
UD
720 clnt_perror (clnt, "yp_all: clnt_call");
721 res = YPERR_RPC;
6259ec0d
UD
722 }
723 else
d111572f
UD
724 res = YPERR_SUCCESS;
725
999b2f6b 726 __yp_unbind (ydb);
d111572f 727 clnt_destroy (clnt);
6259ec0d 728
6259ec0d 729 if (status != YP_NOMORE)
a788b6c2
UD
730 {
731 __set_errno (saved_errno);
732 return ypprot_err (status);
733 }
734 ++try;
6259ec0d
UD
735 }
736
a788b6c2
UD
737 __set_errno (saved_errno);
738
d111572f 739 return res;
6259ec0d
UD
740}
741
742int
743yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
744{
745 struct ypresp_maplist resp;
d111572f 746 enum clnt_stat result;
6259ec0d
UD
747
748 if (indomain == NULL || indomain[0] == '\0')
749 return YPERR_BADARGS;
750
751 memset (&resp, '\0', sizeof (resp));
752
753 result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
754 (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
755
4bca4c17
UD
756 if (result != YPERR_SUCCESS)
757 return result;
6259ec0d
UD
758 if (resp.stat != YP_TRUE)
759 return ypprot_err (resp.stat);
760
761 *outmaplist = resp.maps;
762 /* We give the list not free, this will be done by ypserv
763 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
764
765 return YPERR_SUCCESS;
766}
767
768const char *
769yperr_string (const int error)
770{
771 switch (error)
772 {
773 case YPERR_SUCCESS:
774 return _("Success");
775 case YPERR_BADARGS:
776 return _("Request arguments bad");
777 case YPERR_RPC:
778 return _("RPC failure on NIS operation");
779 case YPERR_DOMAIN:
780 return _("Can't bind to server which serves this domain");
781 case YPERR_MAP:
782 return _("No such map in server's domain");
783 case YPERR_KEY:
784 return _("No such key in map");
785 case YPERR_YPERR:
786 return _("Internal NIS error");
787 case YPERR_RESRC:
788 return _("Local resource allocation failure");
789 case YPERR_NOMORE:
790 return _("No more records in map database");
791 case YPERR_PMAP:
792 return _("Can't communicate with portmapper");
793 case YPERR_YPBIND:
794 return _("Can't communicate with ypbind");
795 case YPERR_YPSERV:
796 return _("Can't communicate with ypserv");
797 case YPERR_NODOM:
798 return _("Local domain name not set");
799 case YPERR_BADDB:
bd355af0 800 return _("NIS map database is bad");
6259ec0d
UD
801 case YPERR_VERS:
802 return _("NIS client/server version mismatch - can't supply service");
803 case YPERR_ACCESS:
804 return _("Permission denied");
805 case YPERR_BUSY:
806 return _("Database is busy");
807 }
808 return _("Unknown NIS error code");
809}
810
811int
812ypprot_err (const int code)
813{
814 switch (code)
815 {
816 case YP_TRUE:
817 return YPERR_SUCCESS;
818 case YP_NOMORE:
819 return YPERR_NOMORE;
820 case YP_FALSE:
821 return YPERR_YPERR;
822 case YP_NOMAP:
823 return YPERR_MAP;
824 case YP_NODOM:
825 return YPERR_DOMAIN;
826 case YP_NOKEY:
827 return YPERR_KEY;
828 case YP_BADOP:
829 return YPERR_YPERR;
830 case YP_BADDB:
831 return YPERR_BADDB;
832 case YP_YPERR:
833 return YPERR_YPERR;
834 case YP_BADARGS:
835 return YPERR_BADARGS;
836 case YP_VERS:
837 return YPERR_VERS;
838 }
839 return YPERR_YPERR;
840}
841
842const char *
843ypbinderr_string (const int error)
844{
845 switch (error)
846 {
847 case 0:
848 return _("Success");
849 case YPBIND_ERR_ERR:
850 return _("Internal ypbind error");
851 case YPBIND_ERR_NOSERV:
852 return _("Domain not bound");
853 case YPBIND_ERR_RESC:
854 return _("System resource allocation failure");
855 default:
856 return _("Unknown ypbind error");
857 }
858}
859
860
861#define WINDOW 60
862
863int
864yp_update (char *domain, char *map, unsigned ypop,
865 char *key, int keylen, char *data, int datalen)
866{
6259ec0d
UD
867 union
868 {
869 ypupdate_args update_args;
870 ypdelete_args delete_args;
871 }
872 args;
873 xdrproc_t xdr_argument;
874 unsigned res = 0;
875 CLIENT *clnt;
876 char *master;
877 struct sockaddr saddr;
878 char servername[MAXNETNAMELEN + 1];
879 int r;
880
881 if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
882 return YPERR_BADARGS;
883
884 args.update_args.mapname = map;
885 args.update_args.key.yp_buf_len = keylen;
886 args.update_args.key.yp_buf_val = key;
887 args.update_args.datum.yp_buf_len = datalen;
888 args.update_args.datum.yp_buf_val = data;
889
890 if ((r = yp_master (domain, map, &master)) != 0)
891 return r;
892
893 if (!host2netname (servername, master, domain))
894 {
895 fputs (_("yp_update: cannot convert host to netname\n"), stderr);
896 return YPERR_YPERR;
897 }
898
899 if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
900 {
901 clnt_pcreateerror ("yp_update: clnt_create");
902 return YPERR_RPC;
903 }
904
905 if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
906 {
907 fputs (_("yp_update: cannot get server address\n"), stderr);
908 return YPERR_RPC;
909 }
910
911 switch (ypop)
912 {
913 case YPOP_CHANGE:
914 case YPOP_INSERT:
915 case YPOP_STORE:
916 xdr_argument = (xdrproc_t) xdr_ypupdate_args;
917 break;
918 case YPOP_DELETE:
919 xdr_argument = (xdrproc_t) xdr_ypdelete_args;
920 break;
921 default:
922 return YPERR_BADARGS;
923 break;
924 }
925
926 clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
927
928 if (clnt->cl_auth == NULL)
929 clnt->cl_auth = authunix_create_default ();
930
931again:
26dee9c4 932 r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args,
cc3fa755 933 (xdrproc_t) xdr_u_int, (caddr_t) &res, RPCTIMEOUT);
6259ec0d
UD
934
935 if (r == RPC_AUTHERROR)
936 {
937 if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
938 {
939 clnt->cl_auth = authunix_create_default ();
940 goto again;
941 }
942 else
943 return YPERR_ACCESS;
944 }
945 if (r != RPC_SUCCESS)
946 {
947 clnt_perror (clnt, "yp_update: clnt_call");
948 return YPERR_RPC;
949 }
950 return res;
6259ec0d 951}
This page took 0.255954 seconds and 5 git commands to generate.