]> sourceware.org Git - glibc.git/blame - nis/ypclnt.c
Update.
[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
109 sprintf (path, "%s/%s.%ld", BINDINGDIR, domain, YPBINDVERS);
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
602__xdr_ypresp_all (XDR * xdrs, u_long * objp)
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
UD
692 {
693 __set_errno (saved_errno);
694 return YPERR_PMAP;
695 }
68dbb3a6
UD
696 req.domain = (char *) indomain;
697 req.map = (char *) inmap;
6259ec0d
UD
698
699 ypall_foreach = incallback->foreach;
700 ypall_data = (void *) incallback->data;
701
3e5f5557
UD
702 result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey,
703 (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
cc3fa755 704 (caddr_t) &status, RPCTIMEOUT);
6259ec0d
UD
705
706 if (result != RPC_SUCCESS)
707 {
d111572f
UD
708 clnt_perror (clnt, "yp_all: clnt_call");
709 res = YPERR_RPC;
6259ec0d
UD
710 }
711 else
d111572f
UD
712 res = YPERR_SUCCESS;
713
714 clnt_destroy (clnt);
6259ec0d 715
6259ec0d 716 if (status != YP_NOMORE)
a788b6c2
UD
717 {
718 __set_errno (saved_errno);
719 return ypprot_err (status);
720 }
721 ++try;
6259ec0d
UD
722 }
723
a788b6c2
UD
724 __set_errno (saved_errno);
725
d111572f 726 return res;
6259ec0d
UD
727}
728
729int
730yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
731{
732 struct ypresp_maplist resp;
d111572f 733 enum clnt_stat result;
6259ec0d
UD
734
735 if (indomain == NULL || indomain[0] == '\0')
736 return YPERR_BADARGS;
737
738 memset (&resp, '\0', sizeof (resp));
739
740 result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
741 (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
742
4bca4c17
UD
743 if (result != YPERR_SUCCESS)
744 return result;
6259ec0d
UD
745 if (resp.stat != YP_TRUE)
746 return ypprot_err (resp.stat);
747
748 *outmaplist = resp.maps;
749 /* We give the list not free, this will be done by ypserv
750 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
751
752 return YPERR_SUCCESS;
753}
754
755const char *
756yperr_string (const int error)
757{
758 switch (error)
759 {
760 case YPERR_SUCCESS:
761 return _("Success");
762 case YPERR_BADARGS:
763 return _("Request arguments bad");
764 case YPERR_RPC:
765 return _("RPC failure on NIS operation");
766 case YPERR_DOMAIN:
767 return _("Can't bind to server which serves this domain");
768 case YPERR_MAP:
769 return _("No such map in server's domain");
770 case YPERR_KEY:
771 return _("No such key in map");
772 case YPERR_YPERR:
773 return _("Internal NIS error");
774 case YPERR_RESRC:
775 return _("Local resource allocation failure");
776 case YPERR_NOMORE:
777 return _("No more records in map database");
778 case YPERR_PMAP:
779 return _("Can't communicate with portmapper");
780 case YPERR_YPBIND:
781 return _("Can't communicate with ypbind");
782 case YPERR_YPSERV:
783 return _("Can't communicate with ypserv");
784 case YPERR_NODOM:
785 return _("Local domain name not set");
786 case YPERR_BADDB:
bd355af0 787 return _("NIS map database is bad");
6259ec0d
UD
788 case YPERR_VERS:
789 return _("NIS client/server version mismatch - can't supply service");
790 case YPERR_ACCESS:
791 return _("Permission denied");
792 case YPERR_BUSY:
793 return _("Database is busy");
794 }
795 return _("Unknown NIS error code");
796}
797
798int
799ypprot_err (const int code)
800{
801 switch (code)
802 {
803 case YP_TRUE:
804 return YPERR_SUCCESS;
805 case YP_NOMORE:
806 return YPERR_NOMORE;
807 case YP_FALSE:
808 return YPERR_YPERR;
809 case YP_NOMAP:
810 return YPERR_MAP;
811 case YP_NODOM:
812 return YPERR_DOMAIN;
813 case YP_NOKEY:
814 return YPERR_KEY;
815 case YP_BADOP:
816 return YPERR_YPERR;
817 case YP_BADDB:
818 return YPERR_BADDB;
819 case YP_YPERR:
820 return YPERR_YPERR;
821 case YP_BADARGS:
822 return YPERR_BADARGS;
823 case YP_VERS:
824 return YPERR_VERS;
825 }
826 return YPERR_YPERR;
827}
828
829const char *
830ypbinderr_string (const int error)
831{
832 switch (error)
833 {
834 case 0:
835 return _("Success");
836 case YPBIND_ERR_ERR:
837 return _("Internal ypbind error");
838 case YPBIND_ERR_NOSERV:
839 return _("Domain not bound");
840 case YPBIND_ERR_RESC:
841 return _("System resource allocation failure");
842 default:
843 return _("Unknown ypbind error");
844 }
845}
846
847
848#define WINDOW 60
849
850int
851yp_update (char *domain, char *map, unsigned ypop,
852 char *key, int keylen, char *data, int datalen)
853{
6259ec0d
UD
854 union
855 {
856 ypupdate_args update_args;
857 ypdelete_args delete_args;
858 }
859 args;
860 xdrproc_t xdr_argument;
861 unsigned res = 0;
862 CLIENT *clnt;
863 char *master;
864 struct sockaddr saddr;
865 char servername[MAXNETNAMELEN + 1];
866 int r;
867
868 if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
869 return YPERR_BADARGS;
870
871 args.update_args.mapname = map;
872 args.update_args.key.yp_buf_len = keylen;
873 args.update_args.key.yp_buf_val = key;
874 args.update_args.datum.yp_buf_len = datalen;
875 args.update_args.datum.yp_buf_val = data;
876
877 if ((r = yp_master (domain, map, &master)) != 0)
878 return r;
879
880 if (!host2netname (servername, master, domain))
881 {
882 fputs (_("yp_update: cannot convert host to netname\n"), stderr);
883 return YPERR_YPERR;
884 }
885
886 if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
887 {
888 clnt_pcreateerror ("yp_update: clnt_create");
889 return YPERR_RPC;
890 }
891
892 if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
893 {
894 fputs (_("yp_update: cannot get server address\n"), stderr);
895 return YPERR_RPC;
896 }
897
898 switch (ypop)
899 {
900 case YPOP_CHANGE:
901 case YPOP_INSERT:
902 case YPOP_STORE:
903 xdr_argument = (xdrproc_t) xdr_ypupdate_args;
904 break;
905 case YPOP_DELETE:
906 xdr_argument = (xdrproc_t) xdr_ypdelete_args;
907 break;
908 default:
909 return YPERR_BADARGS;
910 break;
911 }
912
913 clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
914
915 if (clnt->cl_auth == NULL)
916 clnt->cl_auth = authunix_create_default ();
917
918again:
26dee9c4 919 r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args,
cc3fa755 920 (xdrproc_t) xdr_u_int, (caddr_t) &res, RPCTIMEOUT);
6259ec0d
UD
921
922 if (r == RPC_AUTHERROR)
923 {
924 if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
925 {
926 clnt->cl_auth = authunix_create_default ();
927 goto again;
928 }
929 else
930 return YPERR_ACCESS;
931 }
932 if (r != RPC_SUCCESS)
933 {
934 clnt_perror (clnt, "yp_update: clnt_call");
935 return YPERR_RPC;
936 }
937 return res;
6259ec0d 938}
This page took 0.140266 seconds and 5 git commands to generate.