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