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