1 /* Copyright (C) 1996-2001, 2002, 2003, 2004, 2005, 2006
2 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 #include <rpcsvc/nis.h>
28 #include <rpcsvc/yp.h>
29 #include <rpcsvc/ypclnt.h>
30 #include <rpcsvc/ypupd.h>
32 #include <bits/libc-lock.h>
34 /* This should only be defined on systems with a BSD compatible ypbind */
36 # define BINDINGDIR "/var/yp/binding"
41 struct dom_binding
*dom_pnext
;
42 char dom_domain
[YPMAXDOMAIN
+ 1];
43 struct sockaddr_in dom_server_addr
;
47 typedef struct dom_binding dom_binding
;
49 static const struct timeval RPCTIMEOUT
= {25, 0};
50 static const struct timeval UDPTIMEOUT
= {5, 0};
51 static int const MAXTRIES
= 2;
52 static char ypdomainname
[NIS_MAXNAMELEN
+ 1];
53 __libc_lock_define_initialized (static, ypbindlist_lock
)
54 static dom_binding
*ypbindlist
= NULL
;
58 yp_bind_client_create (const char *domain
, dom_binding
*ysd
,
59 struct ypbind_resp
*ypbr
)
61 ysd
->dom_server_addr
.sin_family
= AF_INET
;
62 memcpy (&ysd
->dom_server_addr
.sin_port
,
63 ypbr
->ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_port
,
64 sizeof (ysd
->dom_server_addr
.sin_port
));
65 memcpy (&ysd
->dom_server_addr
.sin_addr
.s_addr
,
66 ypbr
->ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_addr
,
67 sizeof (ysd
->dom_server_addr
.sin_addr
.s_addr
));
68 strncpy (ysd
->dom_domain
, domain
, YPMAXDOMAIN
);
69 ysd
->dom_domain
[YPMAXDOMAIN
] = '\0';
71 ysd
->dom_socket
= RPC_ANYSOCK
;
72 ysd
->dom_client
= clntudp_create (&ysd
->dom_server_addr
, YPPROG
, YPVERS
,
73 UDPTIMEOUT
, &ysd
->dom_socket
);
75 if (ysd
->dom_client
!= NULL
)
77 /* If the program exits, close the socket */
78 if (fcntl (ysd
->dom_socket
, F_SETFD
, FD_CLOEXEC
) == -1)
79 perror ("fcntl: F_SETFD");
85 yp_bind_file (const char *domain
, dom_binding
*ysd
)
87 char path
[sizeof (BINDINGDIR
) + strlen (domain
) + 3 * sizeof (unsigned) + 3];
89 snprintf (path
, sizeof (path
), "%s/%s.%u", BINDINGDIR
, domain
, YPBINDVERS
);
90 int fd
= open (path
, O_RDONLY
);
93 /* We have a binding file and could save a RPC call. The file
94 contains a port number and the YPBIND_RESP record. The port
95 number (16 bits) can be ignored. */
96 struct ypbind_resp ypbr
;
98 if (pread (fd
, &ypbr
, sizeof (ypbr
), 2) == sizeof (ypbr
))
99 yp_bind_client_create (domain
, ysd
, &ypbr
);
107 yp_bind_ypbindprog (const char *domain
, dom_binding
*ysd
)
109 struct sockaddr_in clnt_saddr
;
110 struct ypbind_resp ypbr
;
114 clnt_saddr
.sin_family
= AF_INET
;
115 clnt_saddr
.sin_port
= 0;
116 clnt_saddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
117 clnt_sock
= RPC_ANYSOCK
;
118 client
= clnttcp_create (&clnt_saddr
, YPBINDPROG
, YPBINDVERS
,
123 /* Check the port number -- should be < IPPORT_RESERVED.
124 If not, it's possible someone has registered a bogus
125 ypbind with the portmapper and is trying to trick us. */
126 if (ntohs (clnt_saddr
.sin_port
) >= IPPORT_RESERVED
)
128 clnt_destroy (client
);
132 if (clnt_call (client
, YPBINDPROC_DOMAIN
,
133 (xdrproc_t
) xdr_domainname
, (caddr_t
) &domain
,
134 (xdrproc_t
) xdr_ypbind_resp
,
135 (caddr_t
) &ypbr
, RPCTIMEOUT
) != RPC_SUCCESS
)
137 clnt_destroy (client
);
141 clnt_destroy (client
);
143 if (ypbr
.ypbind_status
!= YPBIND_SUCC_VAL
)
145 fprintf (stderr
, "YPBINDPROC_DOMAIN: %s\n",
146 ypbinderr_string (ypbr
.ypbind_resp_u
.ypbind_error
));
149 memset (&ysd
->dom_server_addr
, '\0', sizeof ysd
->dom_server_addr
);
151 yp_bind_client_create (domain
, ysd
, &ypbr
);
153 return YPERR_SUCCESS
;
157 __yp_bind (const char *domain
, dom_binding
**ypdb
)
159 dom_binding
*ysd
= NULL
;
162 if (domain
== NULL
|| domain
[0] == '\0')
163 return YPERR_BADARGS
;
168 if (strcmp (domain
, ysd
->dom_domain
) == 0)
170 ysd
= ysd
->dom_pnext
;
176 ysd
= (dom_binding
*) calloc (1, sizeof *ysd
);
177 if (__builtin_expect (ysd
== NULL
, 0))
182 /* Try binding dir at first if we have no binding */
183 if (ysd
->dom_client
== NULL
)
184 yp_bind_file (domain
, ysd
);
185 #endif /* USE_BINDINGDIR */
187 if (ysd
->dom_client
== NULL
)
189 int retval
= yp_bind_ypbindprog (domain
, ysd
);
190 if (retval
!= YPERR_SUCCESS
)
198 if (ysd
->dom_client
== NULL
)
207 ysd
->dom_pnext
= *ypdb
;
211 return YPERR_SUCCESS
;
215 __yp_unbind (dom_binding
*ydb
)
217 clnt_destroy (ydb
->dom_client
);
222 yp_bind (const char *indomain
)
226 __libc_lock_lock (ypbindlist_lock
);
228 status
= __yp_bind (indomain
, &ypbindlist
);
230 __libc_lock_unlock (ypbindlist_lock
);
234 libnsl_hidden_def (yp_bind
)
237 yp_unbind_locked (const char *indomain
)
239 dom_binding
*ydbptr
, *ydbptr2
;
244 while (ydbptr
!= NULL
)
246 if (strcmp (ydbptr
->dom_domain
, indomain
) == 0)
252 ypbindlist
= ypbindlist
->dom_pnext
;
254 ydbptr2
= ydbptr
->dom_pnext
;
259 ydbptr
= ydbptr
->dom_pnext
;
264 yp_unbind (const char *indomain
)
266 __libc_lock_lock (ypbindlist_lock
);
268 yp_unbind_locked (indomain
);
270 __libc_lock_unlock (ypbindlist_lock
);
276 __ypclnt_call (const char *domain
, u_long prog
, xdrproc_t xargs
,
277 caddr_t req
, xdrproc_t xres
, caddr_t resp
, dom_binding
**ydb
,
280 enum clnt_stat result
;
282 result
= clnt_call ((*ydb
)->dom_client
, prog
,
283 xargs
, req
, xres
, resp
, RPCTIMEOUT
);
285 if (result
!= RPC_SUCCESS
)
287 /* We don't print an error message, if we try our old,
288 cached data. Only print this for data, which should work. */
290 clnt_perror ((*ydb
)->dom_client
, "do_ypcall: clnt_call");
295 return YPERR_SUCCESS
;
299 do_ypcall (const char *domain
, u_long prog
, xdrproc_t xargs
,
300 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
304 int saved_errno
= errno
;
306 status
= YPERR_YPERR
;
308 __libc_lock_lock (ypbindlist_lock
);
312 if (strcmp (domain
, ydb
->dom_domain
) == 0)
314 if (__yp_bind (domain
, &ydb
) == 0)
316 /* Call server, print no error message, do not unbind. */
317 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
319 if (status
== YPERR_SUCCESS
)
321 __libc_lock_unlock (ypbindlist_lock
);
322 __set_errno (saved_errno
);
326 /* We use ypbindlist, and the old cached data is
327 invalid. unbind now and create a new binding */
328 yp_unbind_locked (domain
);
332 ydb
= ydb
->dom_pnext
;
334 __libc_lock_unlock (ypbindlist_lock
);
336 /* First try with cached data failed. Now try to get
337 current data from the system. */
339 if (__yp_bind (domain
, &ydb
) == 0)
341 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
347 /* If we support binding dir data, we have a third chance:
349 if (status
!= YPERR_SUCCESS
)
351 ydb
= calloc (1, sizeof (dom_binding
));
352 if (ydb
!= NULL
&& yp_bind_ypbindprog (domain
, ydb
) == YPERR_SUCCESS
)
354 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
363 __set_errno (saved_errno
);
368 /* Like do_ypcall, but translate the status value if necessary. */
370 do_ypcall_tr (const char *domain
, u_long prog
, xdrproc_t xargs
,
371 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
373 int status
= do_ypcall (domain
, prog
, xargs
, req
, xres
, resp
);
374 if (status
== YPERR_SUCCESS
)
375 /* We cast to ypresp_val although the pointer could also be of
376 type ypresp_key_val or ypresp_master or ypresp_order or
377 ypresp_maplist. But the stat element is in a common prefix so
378 this does not matter. */
379 status
= ypprot_err (((struct ypresp_val
*) resp
)->stat
);
384 __libc_lock_define_initialized (static, domainname_lock
)
387 yp_get_default_domain (char **outdomain
)
389 int result
= YPERR_SUCCESS
;;
392 __libc_lock_lock (domainname_lock
);
394 if (ypdomainname
[0] == '\0')
396 if (getdomainname (ypdomainname
, NIS_MAXNAMELEN
))
397 result
= YPERR_NODOM
;
398 else if (strcmp (ypdomainname
, "(none)") == 0)
400 /* If domainname is not set, some systems will return "(none)" */
401 ypdomainname
[0] = '\0';
402 result
= YPERR_NODOM
;
405 *outdomain
= ypdomainname
;
408 *outdomain
= ypdomainname
;
410 __libc_lock_unlock (domainname_lock
);
414 libnsl_hidden_def (yp_get_default_domain
)
417 __yp_check (char **domain
)
421 if (ypdomainname
[0] == '\0')
422 if (yp_get_default_domain (&unused
))
426 *domain
= ypdomainname
;
428 if (yp_bind (ypdomainname
) == 0)
434 yp_match (const char *indomain
, const char *inmap
, const char *inkey
,
435 const int inkeylen
, char **outval
, int *outvallen
)
439 enum clnt_stat result
;
441 if (indomain
== NULL
|| indomain
[0] == '\0' ||
442 inmap
== NULL
|| inmap
[0] == '\0' ||
443 inkey
== NULL
|| inkey
[0] == '\0' || inkeylen
<= 0)
444 return YPERR_BADARGS
;
446 req
.domain
= (char *) indomain
;
447 req
.map
= (char *) inmap
;
448 req
.key
.keydat_val
= (char *) inkey
;
449 req
.key
.keydat_len
= inkeylen
;
453 memset (&resp
, '\0', sizeof (resp
));
455 result
= do_ypcall_tr (indomain
, YPPROC_MATCH
, (xdrproc_t
) xdr_ypreq_key
,
456 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_val
,
459 if (result
!= YPERR_SUCCESS
)
462 *outvallen
= resp
.val
.valdat_len
;
463 *outval
= malloc (*outvallen
+ 1);
464 int status
= YPERR_RESRC
;
465 if (__builtin_expect (*outval
!= NULL
, 1))
467 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
468 (*outval
)[*outvallen
] = '\0';
469 status
= YPERR_SUCCESS
;
472 xdr_free ((xdrproc_t
) xdr_ypresp_val
, (char *) &resp
);
478 yp_first (const char *indomain
, const char *inmap
, char **outkey
,
479 int *outkeylen
, char **outval
, int *outvallen
)
483 enum clnt_stat result
;
485 if (indomain
== NULL
|| indomain
[0] == '\0' ||
486 inmap
== NULL
|| inmap
[0] == '\0')
487 return YPERR_BADARGS
;
489 req
.domain
= (char *) indomain
;
490 req
.map
= (char *) inmap
;
492 *outkey
= *outval
= NULL
;
493 *outkeylen
= *outvallen
= 0;
494 memset (&resp
, '\0', sizeof (resp
));
496 result
= do_ypcall (indomain
, YPPROC_FIRST
, (xdrproc_t
) xdr_ypreq_nokey
,
497 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
500 if (result
!= RPC_SUCCESS
)
502 if (resp
.stat
!= YP_TRUE
)
503 return ypprot_err (resp
.stat
);
506 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
507 && (*outval
= malloc (resp
.val
.valdat_len
510 *outkeylen
= resp
.key
.keydat_len
;
511 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
512 (*outkey
)[*outkeylen
] = '\0';
514 *outvallen
= resp
.val
.valdat_len
;
515 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
516 (*outval
)[*outvallen
] = '\0';
518 status
= YPERR_SUCCESS
;
523 status
= YPERR_RESRC
;
526 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
532 yp_next (const char *indomain
, const char *inmap
, const char *inkey
,
533 const int inkeylen
, char **outkey
, int *outkeylen
, char **outval
,
538 enum clnt_stat result
;
540 if (indomain
== NULL
|| indomain
[0] == '\0' ||
541 inmap
== NULL
|| inmap
[0] == '\0' ||
542 inkeylen
<= 0 || inkey
== NULL
|| inkey
[0] == '\0')
543 return YPERR_BADARGS
;
545 req
.domain
= (char *) indomain
;
546 req
.map
= (char *) inmap
;
547 req
.key
.keydat_val
= (char *) inkey
;
548 req
.key
.keydat_len
= inkeylen
;
550 *outkey
= *outval
= NULL
;
551 *outkeylen
= *outvallen
= 0;
552 memset (&resp
, '\0', sizeof (resp
));
554 result
= do_ypcall_tr (indomain
, YPPROC_NEXT
, (xdrproc_t
) xdr_ypreq_key
,
555 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
558 if (result
!= YPERR_SUCCESS
)
562 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
563 && (*outval
= malloc (resp
.val
.valdat_len
566 *outkeylen
= resp
.key
.keydat_len
;
567 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
568 (*outkey
)[*outkeylen
] = '\0';
570 *outvallen
= resp
.val
.valdat_len
;
571 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
572 (*outval
)[*outvallen
] = '\0';
574 status
= YPERR_SUCCESS
;
579 status
= YPERR_RESRC
;
582 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
588 yp_master (const char *indomain
, const char *inmap
, char **outname
)
592 enum clnt_stat result
;
594 if (indomain
== NULL
|| indomain
[0] == '\0' ||
595 inmap
== NULL
|| inmap
[0] == '\0')
596 return YPERR_BADARGS
;
598 req
.domain
= (char *) indomain
;
599 req
.map
= (char *) inmap
;
601 memset (&resp
, '\0', sizeof (ypresp_master
));
603 result
= do_ypcall_tr (indomain
, YPPROC_MASTER
, (xdrproc_t
) xdr_ypreq_nokey
,
604 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_master
,
607 if (result
!= YPERR_SUCCESS
)
610 *outname
= strdup (resp
.peer
);
611 xdr_free ((xdrproc_t
) xdr_ypresp_master
, (char *) &resp
);
613 return *outname
== NULL
? YPERR_YPERR
: YPERR_SUCCESS
;
615 libnsl_hidden_def (yp_master
)
618 yp_order (const char *indomain
, const char *inmap
, unsigned int *outorder
)
620 struct ypreq_nokey req
;
621 struct ypresp_order resp
;
622 enum clnt_stat result
;
624 if (indomain
== NULL
|| indomain
[0] == '\0' ||
625 inmap
== NULL
|| inmap
[0] == '\0')
626 return YPERR_BADARGS
;
628 req
.domain
= (char *) indomain
;
629 req
.map
= (char *) inmap
;
631 memset (&resp
, '\0', sizeof (resp
));
633 result
= do_ypcall_tr (indomain
, YPPROC_ORDER
, (xdrproc_t
) xdr_ypreq_nokey
,
634 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_order
,
637 if (result
!= YPERR_SUCCESS
)
640 *outorder
= resp
.ordernum
;
641 xdr_free ((xdrproc_t
) xdr_ypresp_order
, (char *) &resp
);
646 struct ypresp_all_data
648 unsigned long status
;
650 int (*foreach
) (int status
, char *key
, int keylen
,
651 char *val
, int vallen
, char *data
);
655 __xdr_ypresp_all (XDR
*xdrs
, struct ypresp_all_data
*objp
)
659 struct ypresp_all resp
;
661 memset (&resp
, '\0', sizeof (struct ypresp_all
));
662 if (!xdr_ypresp_all (xdrs
, &resp
))
664 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
665 objp
->status
= YP_YPERR
;
670 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
671 objp
->status
= YP_NOMORE
;
675 switch (resp
.ypresp_all_u
.val
.stat
)
679 char key
[resp
.ypresp_all_u
.val
.key
.keydat_len
+ 1];
680 char val
[resp
.ypresp_all_u
.val
.val
.valdat_len
+ 1];
681 int keylen
= resp
.ypresp_all_u
.val
.key
.keydat_len
;
682 int vallen
= resp
.ypresp_all_u
.val
.val
.valdat_len
;
684 /* We are not allowed to modify the key and val data.
685 But we are allowed to add data behind the buffer,
686 if we don't modify the length. So add an extra NUL
687 character to avoid trouble with broken code. */
688 objp
->status
= YP_TRUE
;
689 *((char *) __mempcpy (key
, resp
.ypresp_all_u
.val
.key
.keydat_val
,
691 *((char *) __mempcpy (val
, resp
.ypresp_all_u
.val
.val
.valdat_val
,
693 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
694 if ((*objp
->foreach
) (objp
->status
, key
, keylen
,
695 val
, vallen
, objp
->data
))
700 objp
->status
= resp
.ypresp_all_u
.val
.stat
;
701 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
702 /* Sun says we don't need to make this call, but must return
703 immediately. Since Solaris makes this call, we will call
704 the callback function, too. */
705 (*objp
->foreach
) (objp
->status
, NULL
, 0, NULL
, 0, objp
->data
);
712 yp_all (const char *indomain
, const char *inmap
,
713 const struct ypall_callback
*incallback
)
715 struct ypreq_nokey req
;
716 dom_binding
*ydb
= NULL
;
718 enum clnt_stat result
;
719 struct sockaddr_in clnt_sin
;
721 struct ypresp_all_data data
;
723 int saved_errno
= errno
;
725 if (indomain
== NULL
|| indomain
[0] == '\0'
726 || inmap
== NULL
|| inmap
[0] == '\0')
727 return YPERR_BADARGS
;
732 while (try < MAXTRIES
&& res
!= YPERR_SUCCESS
)
734 if (__yp_bind (indomain
, &ydb
) != 0)
736 __set_errno (saved_errno
);
740 clnt_sock
= RPC_ANYSOCK
;
741 clnt_sin
= ydb
->dom_server_addr
;
742 clnt_sin
.sin_port
= 0;
744 /* We don't need the UDP connection anymore. */
748 clnt
= clnttcp_create (&clnt_sin
, YPPROG
, YPVERS
, &clnt_sock
, 0, 0);
751 __set_errno (saved_errno
);
754 req
.domain
= (char *) indomain
;
755 req
.map
= (char *) inmap
;
757 data
.foreach
= incallback
->foreach
;
758 data
.data
= (void *) incallback
->data
;
760 result
= clnt_call (clnt
, YPPROC_ALL
, (xdrproc_t
) xdr_ypreq_nokey
,
761 (caddr_t
) &req
, (xdrproc_t
) __xdr_ypresp_all
,
762 (caddr_t
) &data
, RPCTIMEOUT
);
764 if (__builtin_expect (result
!= RPC_SUCCESS
, 0))
766 /* Print the error message only on the last try. */
767 if (try == MAXTRIES
- 1)
768 clnt_perror (clnt
, "yp_all: clnt_call");
776 if (res
== YPERR_SUCCESS
&& data
.status
!= YP_NOMORE
)
778 __set_errno (saved_errno
);
779 return ypprot_err (data
.status
);
784 __set_errno (saved_errno
);
791 yp_maplist (const char *indomain
, struct ypmaplist
**outmaplist
)
793 struct ypresp_maplist resp
;
794 enum clnt_stat result
;
796 if (indomain
== NULL
|| indomain
[0] == '\0')
797 return YPERR_BADARGS
;
799 memset (&resp
, '\0', sizeof (resp
));
801 result
= do_ypcall_tr (indomain
, YPPROC_MAPLIST
, (xdrproc_t
) xdr_domainname
,
802 (caddr_t
) &indomain
, (xdrproc_t
) xdr_ypresp_maplist
,
805 if (__builtin_expect (result
== YPERR_SUCCESS
, 1))
807 *outmaplist
= resp
.maps
;
808 /* We don't free the list, this will be done by ypserv
809 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
816 yperr_string (const int error
)
825 str
= N_("Request arguments bad");
828 str
= N_("RPC failure on NIS operation");
831 str
= N_("Can't bind to server which serves this domain");
834 str
= N_("No such map in server's domain");
837 str
= N_("No such key in map");
840 str
= N_("Internal NIS error");
843 str
= N_("Local resource allocation failure");
846 str
= N_("No more records in map database");
849 str
= N_("Can't communicate with portmapper");
852 str
= N_("Can't communicate with ypbind");
855 str
= N_("Can't communicate with ypserv");
858 str
= N_("Local domain name not set");
861 str
= N_("NIS map database is bad");
864 str
= N_("NIS client/server version mismatch - can't supply service");
867 str
= N_("Permission denied");
870 str
= N_("Database is busy");
873 str
= N_("Unknown NIS error code");
879 static const int8_t yp_2_yperr
[] =
881 #define YP2YPERR(yp, yperr) [YP_##yp - YP_VERS] = YPERR_##yperr
882 YP2YPERR (TRUE
, SUCCESS
),
883 YP2YPERR (NOMORE
, NOMORE
),
884 YP2YPERR (FALSE
, YPERR
),
885 YP2YPERR (NOMAP
, MAP
),
886 YP2YPERR (NODOM
, DOMAIN
),
887 YP2YPERR (NOKEY
, KEY
),
888 YP2YPERR (BADOP
, YPERR
),
889 YP2YPERR (BADDB
, BADDB
),
890 YP2YPERR (YPERR
, YPERR
),
891 YP2YPERR (BADARGS
, BADARGS
),
892 YP2YPERR (VERS
, VERS
)
895 ypprot_err (const int code
)
897 if (code
< YP_VERS
|| code
> YP_NOMORE
)
899 return yp_2_yperr
[code
- YP_VERS
];
901 libnsl_hidden_def (ypprot_err
)
904 ypbinderr_string (const int error
)
913 str
= N_("Internal ypbind error");
915 case YPBIND_ERR_NOSERV
:
916 str
= N_("Domain not bound");
918 case YPBIND_ERR_RESC
:
919 str
= N_("System resource allocation failure");
922 str
= N_("Unknown ypbind error");
927 libnsl_hidden_def (ypbinderr_string
)
932 yp_update (char *domain
, char *map
, unsigned ypop
,
933 char *key
, int keylen
, char *data
, int datalen
)
937 ypupdate_args update_args
;
938 ypdelete_args delete_args
;
941 xdrproc_t xdr_argument
;
945 struct sockaddr saddr
;
946 char servername
[MAXNETNAMELEN
+ 1];
949 if (!domain
|| !map
|| !key
|| (ypop
!= YPOP_DELETE
&& !data
))
950 return YPERR_BADARGS
;
952 args
.update_args
.mapname
= map
;
953 args
.update_args
.key
.yp_buf_len
= keylen
;
954 args
.update_args
.key
.yp_buf_val
= key
;
955 args
.update_args
.datum
.yp_buf_len
= datalen
;
956 args
.update_args
.datum
.yp_buf_val
= data
;
958 if ((r
= yp_master (domain
, map
, &master
)) != YPERR_SUCCESS
)
961 if (!host2netname (servername
, master
, domain
))
963 fputs (_("yp_update: cannot convert host to netname\n"), stderr
);
968 clnt
= clnt_create (master
, YPU_PROG
, YPU_VERS
, "tcp");
970 /* We do not need the string anymore. */
975 clnt_pcreateerror ("yp_update: clnt_create");
979 if (!clnt_control (clnt
, CLGET_SERVER_ADDR
, (char *) &saddr
))
981 fputs (_("yp_update: cannot get server address\n"), stderr
);
990 xdr_argument
= (xdrproc_t
) xdr_ypupdate_args
;
993 xdr_argument
= (xdrproc_t
) xdr_ypdelete_args
;
996 return YPERR_BADARGS
;
1000 clnt
->cl_auth
= authdes_create (servername
, WINDOW
, &saddr
, NULL
);
1002 if (clnt
->cl_auth
== NULL
)
1003 clnt
->cl_auth
= authunix_create_default ();
1006 r
= clnt_call (clnt
, ypop
, xdr_argument
, (caddr_t
) &args
,
1007 (xdrproc_t
) xdr_u_int
, (caddr_t
) &res
, RPCTIMEOUT
);
1009 if (r
== RPC_AUTHERROR
)
1011 if (clnt
->cl_auth
->ah_cred
.oa_flavor
== AUTH_DES
)
1013 auth_destroy (clnt
->cl_auth
);
1014 clnt
->cl_auth
= authunix_create_default ();
1018 return YPERR_ACCESS
;
1020 if (r
!= RPC_SUCCESS
)
1022 clnt_perror (clnt
, "yp_update: clnt_call");