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