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