1 /* Copyright (C) 1996-2016 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
25 #include <rpcsvc/nis.h>
26 #include <rpcsvc/yp.h>
27 #include <rpcsvc/ypclnt.h>
28 #include <rpcsvc/ypupd.h>
29 #include <sys/socket.h>
31 #include <libc-lock.h>
33 /* This should only be defined on systems with a BSD compatible ypbind */
35 # define BINDINGDIR "/var/yp/binding"
40 struct dom_binding
*dom_pnext
;
41 char dom_domain
[YPMAXDOMAIN
+ 1];
42 struct sockaddr_in dom_server_addr
;
46 typedef struct dom_binding dom_binding
;
48 static const struct timeval RPCTIMEOUT
= {25, 0};
49 static const struct timeval UDPTIMEOUT
= {5, 0};
50 static int const MAXTRIES
= 2;
51 static char ypdomainname
[NIS_MAXNAMELEN
+ 1];
52 __libc_lock_define_initialized (static, ypbindlist_lock
)
53 static dom_binding
*ypbindlist
= NULL
;
57 yp_bind_client_create (const char *domain
, dom_binding
*ysd
,
58 struct ypbind_resp
*ypbr
)
60 ysd
->dom_server_addr
.sin_family
= AF_INET
;
61 memcpy (&ysd
->dom_server_addr
.sin_port
,
62 ypbr
->ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_port
,
63 sizeof (ysd
->dom_server_addr
.sin_port
));
64 memcpy (&ysd
->dom_server_addr
.sin_addr
.s_addr
,
65 ypbr
->ypbind_resp_u
.ypbind_bindinfo
.ypbind_binding_addr
,
66 sizeof (ysd
->dom_server_addr
.sin_addr
.s_addr
));
67 strncpy (ysd
->dom_domain
, domain
, YPMAXDOMAIN
);
68 ysd
->dom_domain
[YPMAXDOMAIN
] = '\0';
70 ysd
->dom_socket
= RPC_ANYSOCK
;
71 ysd
->dom_client
= __libc_clntudp_bufcreate (&ysd
->dom_server_addr
, YPPROG
,
74 UDPMSGSIZE
, UDPMSGSIZE
,
80 yp_bind_file (const char *domain
, dom_binding
*ysd
)
82 char path
[sizeof (BINDINGDIR
) + strlen (domain
) + 3 * sizeof (unsigned) + 3];
84 snprintf (path
, sizeof (path
), "%s/%s.%u", BINDINGDIR
, domain
, YPBINDVERS
);
85 int fd
= open (path
, O_RDONLY
);
88 /* We have a binding file and could save a RPC call. The file
89 contains a port number and the YPBIND_RESP record. The port
90 number (16 bits) can be ignored. */
91 struct ypbind_resp ypbr
;
93 if (pread (fd
, &ypbr
, sizeof (ypbr
), 2) == sizeof (ypbr
))
94 yp_bind_client_create (domain
, ysd
, &ypbr
);
102 yp_bind_ypbindprog (const char *domain
, dom_binding
*ysd
)
104 struct sockaddr_in clnt_saddr
;
105 struct ypbind_resp ypbr
;
109 clnt_saddr
.sin_family
= AF_INET
;
110 clnt_saddr
.sin_port
= 0;
111 clnt_saddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
112 clnt_sock
= RPC_ANYSOCK
;
113 client
= clnttcp_create (&clnt_saddr
, YPBINDPROG
, YPBINDVERS
,
118 /* Check the port number -- should be < IPPORT_RESERVED.
119 If not, it's possible someone has registered a bogus
120 ypbind with the portmapper and is trying to trick us. */
121 if (ntohs (clnt_saddr
.sin_port
) >= IPPORT_RESERVED
)
123 clnt_destroy (client
);
127 if (clnt_call (client
, YPBINDPROC_DOMAIN
,
128 (xdrproc_t
) xdr_domainname
, (caddr_t
) &domain
,
129 (xdrproc_t
) xdr_ypbind_resp
,
130 (caddr_t
) &ypbr
, RPCTIMEOUT
) != RPC_SUCCESS
)
132 clnt_destroy (client
);
136 clnt_destroy (client
);
138 if (ypbr
.ypbind_status
!= YPBIND_SUCC_VAL
)
140 fprintf (stderr
, "YPBINDPROC_DOMAIN: %s\n",
141 ypbinderr_string (ypbr
.ypbind_resp_u
.ypbind_error
));
144 memset (&ysd
->dom_server_addr
, '\0', sizeof ysd
->dom_server_addr
);
146 yp_bind_client_create (domain
, ysd
, &ypbr
);
148 return YPERR_SUCCESS
;
152 __yp_bind (const char *domain
, dom_binding
**ypdb
)
154 dom_binding
*ysd
= NULL
;
157 if (domain
== NULL
|| domain
[0] == '\0')
158 return YPERR_BADARGS
;
163 if (strcmp (domain
, ysd
->dom_domain
) == 0)
165 ysd
= ysd
->dom_pnext
;
171 ysd
= (dom_binding
*) calloc (1, sizeof *ysd
);
172 if (__glibc_unlikely (ysd
== NULL
))
177 /* Try binding dir at first if we have no binding */
178 if (ysd
->dom_client
== NULL
)
179 yp_bind_file (domain
, ysd
);
180 #endif /* USE_BINDINGDIR */
182 if (ysd
->dom_client
== NULL
)
184 int retval
= yp_bind_ypbindprog (domain
, ysd
);
185 if (retval
!= YPERR_SUCCESS
)
193 if (ysd
->dom_client
== NULL
)
202 ysd
->dom_pnext
= *ypdb
;
206 return YPERR_SUCCESS
;
210 __yp_unbind (dom_binding
*ydb
)
212 clnt_destroy (ydb
->dom_client
);
217 yp_bind (const char *indomain
)
221 __libc_lock_lock (ypbindlist_lock
);
223 status
= __yp_bind (indomain
, &ypbindlist
);
225 __libc_lock_unlock (ypbindlist_lock
);
229 libnsl_hidden_def (yp_bind
)
232 yp_unbind_locked (const char *indomain
)
234 dom_binding
*ydbptr
, *ydbptr2
;
239 while (ydbptr
!= NULL
)
241 if (strcmp (ydbptr
->dom_domain
, indomain
) == 0)
247 ypbindlist
= ypbindlist
->dom_pnext
;
249 ydbptr2
= ydbptr
->dom_pnext
;
254 ydbptr
= ydbptr
->dom_pnext
;
259 yp_unbind (const char *indomain
)
261 __libc_lock_lock (ypbindlist_lock
);
263 yp_unbind_locked (indomain
);
265 __libc_lock_unlock (ypbindlist_lock
);
271 __ypclnt_call (const char *domain
, u_long prog
, xdrproc_t xargs
,
272 caddr_t req
, xdrproc_t xres
, caddr_t resp
, dom_binding
**ydb
,
275 enum clnt_stat result
;
277 result
= clnt_call ((*ydb
)->dom_client
, prog
,
278 xargs
, req
, xres
, resp
, RPCTIMEOUT
);
280 if (result
!= RPC_SUCCESS
)
282 /* We don't print an error message, if we try our old,
283 cached data. Only print this for data, which should work. */
285 clnt_perror ((*ydb
)->dom_client
, "do_ypcall: clnt_call");
290 return YPERR_SUCCESS
;
294 do_ypcall (const char *domain
, u_long prog
, xdrproc_t xargs
,
295 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
299 int saved_errno
= errno
;
301 status
= YPERR_YPERR
;
303 __libc_lock_lock (ypbindlist_lock
);
307 if (strcmp (domain
, ydb
->dom_domain
) == 0)
309 if (__yp_bind (domain
, &ydb
) == 0)
311 /* Call server, print no error message, do not unbind. */
312 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
314 if (status
== YPERR_SUCCESS
)
316 __libc_lock_unlock (ypbindlist_lock
);
317 __set_errno (saved_errno
);
321 /* We use ypbindlist, and the old cached data is
322 invalid. unbind now and create a new binding */
323 yp_unbind_locked (domain
);
327 ydb
= ydb
->dom_pnext
;
329 __libc_lock_unlock (ypbindlist_lock
);
331 /* First try with cached data failed. Now try to get
332 current data from the system. */
334 if (__yp_bind (domain
, &ydb
) == 0)
336 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
342 /* If we support binding dir data, we have a third chance:
344 if (status
!= YPERR_SUCCESS
)
346 ydb
= calloc (1, sizeof (dom_binding
));
347 if (ydb
!= NULL
&& yp_bind_ypbindprog (domain
, ydb
) == YPERR_SUCCESS
)
349 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
358 __set_errno (saved_errno
);
363 /* Like do_ypcall, but translate the status value if necessary. */
365 do_ypcall_tr (const char *domain
, u_long prog
, xdrproc_t xargs
,
366 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
368 int status
= do_ypcall (domain
, prog
, xargs
, req
, xres
, resp
);
369 if (status
== YPERR_SUCCESS
)
370 /* We cast to ypresp_val although the pointer could also be of
371 type ypresp_key_val or ypresp_master or ypresp_order or
372 ypresp_maplist. But the stat element is in a common prefix so
373 this does not matter. */
374 status
= ypprot_err (((struct ypresp_val
*) resp
)->stat
);
379 __libc_lock_define_initialized (static, domainname_lock
)
382 yp_get_default_domain (char **outdomain
)
384 int result
= YPERR_SUCCESS
;;
387 __libc_lock_lock (domainname_lock
);
389 if (ypdomainname
[0] == '\0')
391 if (getdomainname (ypdomainname
, NIS_MAXNAMELEN
))
392 result
= YPERR_NODOM
;
393 else if (strcmp (ypdomainname
, "(none)") == 0)
395 /* If domainname is not set, some systems will return "(none)" */
396 ypdomainname
[0] = '\0';
397 result
= YPERR_NODOM
;
400 *outdomain
= ypdomainname
;
403 *outdomain
= ypdomainname
;
405 __libc_lock_unlock (domainname_lock
);
409 libnsl_hidden_def (yp_get_default_domain
)
412 __yp_check (char **domain
)
416 if (ypdomainname
[0] == '\0')
417 if (yp_get_default_domain (&unused
))
421 *domain
= ypdomainname
;
423 if (yp_bind (ypdomainname
) == 0)
429 yp_match (const char *indomain
, const char *inmap
, const char *inkey
,
430 const int inkeylen
, char **outval
, int *outvallen
)
434 enum clnt_stat result
;
436 if (indomain
== NULL
|| indomain
[0] == '\0' ||
437 inmap
== NULL
|| inmap
[0] == '\0' ||
438 inkey
== NULL
|| inkey
[0] == '\0' || inkeylen
<= 0)
439 return YPERR_BADARGS
;
441 req
.domain
= (char *) indomain
;
442 req
.map
= (char *) inmap
;
443 req
.key
.keydat_val
= (char *) inkey
;
444 req
.key
.keydat_len
= inkeylen
;
448 memset (&resp
, '\0', sizeof (resp
));
450 result
= do_ypcall_tr (indomain
, YPPROC_MATCH
, (xdrproc_t
) xdr_ypreq_key
,
451 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_val
,
454 if (result
!= YPERR_SUCCESS
)
457 *outvallen
= resp
.val
.valdat_len
;
458 *outval
= malloc (*outvallen
+ 1);
459 int status
= YPERR_RESRC
;
460 if (__glibc_likely (*outval
!= NULL
))
462 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
463 (*outval
)[*outvallen
] = '\0';
464 status
= YPERR_SUCCESS
;
467 xdr_free ((xdrproc_t
) xdr_ypresp_val
, (char *) &resp
);
473 yp_first (const char *indomain
, const char *inmap
, char **outkey
,
474 int *outkeylen
, char **outval
, int *outvallen
)
478 enum clnt_stat result
;
480 if (indomain
== NULL
|| indomain
[0] == '\0' ||
481 inmap
== NULL
|| inmap
[0] == '\0')
482 return YPERR_BADARGS
;
484 req
.domain
= (char *) indomain
;
485 req
.map
= (char *) inmap
;
487 *outkey
= *outval
= NULL
;
488 *outkeylen
= *outvallen
= 0;
489 memset (&resp
, '\0', sizeof (resp
));
491 result
= do_ypcall (indomain
, YPPROC_FIRST
, (xdrproc_t
) xdr_ypreq_nokey
,
492 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
495 if (result
!= RPC_SUCCESS
)
497 if (resp
.stat
!= YP_TRUE
)
498 return ypprot_err (resp
.stat
);
501 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
502 && (*outval
= malloc (resp
.val
.valdat_len
505 *outkeylen
= resp
.key
.keydat_len
;
506 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
507 (*outkey
)[*outkeylen
] = '\0';
509 *outvallen
= resp
.val
.valdat_len
;
510 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
511 (*outval
)[*outvallen
] = '\0';
513 status
= YPERR_SUCCESS
;
518 status
= YPERR_RESRC
;
521 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
527 yp_next (const char *indomain
, const char *inmap
, const char *inkey
,
528 const int inkeylen
, char **outkey
, int *outkeylen
, char **outval
,
533 enum clnt_stat result
;
535 if (indomain
== NULL
|| indomain
[0] == '\0' ||
536 inmap
== NULL
|| inmap
[0] == '\0' ||
537 inkeylen
<= 0 || inkey
== NULL
|| inkey
[0] == '\0')
538 return YPERR_BADARGS
;
540 req
.domain
= (char *) indomain
;
541 req
.map
= (char *) inmap
;
542 req
.key
.keydat_val
= (char *) inkey
;
543 req
.key
.keydat_len
= inkeylen
;
545 *outkey
= *outval
= NULL
;
546 *outkeylen
= *outvallen
= 0;
547 memset (&resp
, '\0', sizeof (resp
));
549 result
= do_ypcall_tr (indomain
, YPPROC_NEXT
, (xdrproc_t
) xdr_ypreq_key
,
550 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_key_val
,
553 if (result
!= YPERR_SUCCESS
)
557 if (__builtin_expect ((*outkey
= malloc (resp
.key
.keydat_len
+ 1)) != NULL
558 && (*outval
= malloc (resp
.val
.valdat_len
561 *outkeylen
= resp
.key
.keydat_len
;
562 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
563 (*outkey
)[*outkeylen
] = '\0';
565 *outvallen
= resp
.val
.valdat_len
;
566 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
567 (*outval
)[*outvallen
] = '\0';
569 status
= YPERR_SUCCESS
;
574 status
= YPERR_RESRC
;
577 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
583 yp_master (const char *indomain
, const char *inmap
, char **outname
)
587 enum clnt_stat result
;
589 if (indomain
== NULL
|| indomain
[0] == '\0' ||
590 inmap
== NULL
|| inmap
[0] == '\0')
591 return YPERR_BADARGS
;
593 req
.domain
= (char *) indomain
;
594 req
.map
= (char *) inmap
;
596 memset (&resp
, '\0', sizeof (ypresp_master
));
598 result
= do_ypcall_tr (indomain
, YPPROC_MASTER
, (xdrproc_t
) xdr_ypreq_nokey
,
599 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_master
,
602 if (result
!= YPERR_SUCCESS
)
605 *outname
= strdup (resp
.peer
);
606 xdr_free ((xdrproc_t
) xdr_ypresp_master
, (char *) &resp
);
608 return *outname
== NULL
? YPERR_YPERR
: YPERR_SUCCESS
;
610 libnsl_hidden_def (yp_master
)
613 yp_order (const char *indomain
, const char *inmap
, unsigned int *outorder
)
615 struct ypreq_nokey req
;
616 struct ypresp_order resp
;
617 enum clnt_stat result
;
619 if (indomain
== NULL
|| indomain
[0] == '\0' ||
620 inmap
== NULL
|| inmap
[0] == '\0')
621 return YPERR_BADARGS
;
623 req
.domain
= (char *) indomain
;
624 req
.map
= (char *) inmap
;
626 memset (&resp
, '\0', sizeof (resp
));
628 result
= do_ypcall_tr (indomain
, YPPROC_ORDER
, (xdrproc_t
) xdr_ypreq_nokey
,
629 (caddr_t
) &req
, (xdrproc_t
) xdr_ypresp_order
,
632 if (result
!= YPERR_SUCCESS
)
635 *outorder
= resp
.ordernum
;
636 xdr_free ((xdrproc_t
) xdr_ypresp_order
, (char *) &resp
);
641 struct ypresp_all_data
643 unsigned long status
;
645 int (*foreach
) (int status
, char *key
, int keylen
,
646 char *val
, int vallen
, char *data
);
650 __xdr_ypresp_all (XDR
*xdrs
, struct ypresp_all_data
*objp
)
654 struct ypresp_all resp
;
656 memset (&resp
, '\0', sizeof (struct ypresp_all
));
657 if (!xdr_ypresp_all (xdrs
, &resp
))
659 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
660 objp
->status
= YP_YPERR
;
665 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
666 objp
->status
= YP_NOMORE
;
670 switch (resp
.ypresp_all_u
.val
.stat
)
674 char key
[resp
.ypresp_all_u
.val
.key
.keydat_len
+ 1];
675 char val
[resp
.ypresp_all_u
.val
.val
.valdat_len
+ 1];
676 int keylen
= resp
.ypresp_all_u
.val
.key
.keydat_len
;
677 int vallen
= resp
.ypresp_all_u
.val
.val
.valdat_len
;
679 /* We are not allowed to modify the key and val data.
680 But we are allowed to add data behind the buffer,
681 if we don't modify the length. So add an extra NUL
682 character to avoid trouble with broken code. */
683 objp
->status
= YP_TRUE
;
684 *((char *) __mempcpy (key
, resp
.ypresp_all_u
.val
.key
.keydat_val
,
686 *((char *) __mempcpy (val
, resp
.ypresp_all_u
.val
.val
.valdat_val
,
688 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
689 if ((*objp
->foreach
) (objp
->status
, key
, keylen
,
690 val
, vallen
, objp
->data
))
695 objp
->status
= resp
.ypresp_all_u
.val
.stat
;
696 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
697 /* Sun says we don't need to make this call, but must return
698 immediately. Since Solaris makes this call, we will call
699 the callback function, too. */
700 (*objp
->foreach
) (objp
->status
, NULL
, 0, NULL
, 0, objp
->data
);
707 yp_all (const char *indomain
, const char *inmap
,
708 const struct ypall_callback
*incallback
)
710 struct ypreq_nokey req
;
711 dom_binding
*ydb
= NULL
;
713 enum clnt_stat result
;
714 struct sockaddr_in clnt_sin
;
716 struct ypresp_all_data data
;
718 int saved_errno
= errno
;
720 if (indomain
== NULL
|| indomain
[0] == '\0'
721 || inmap
== NULL
|| inmap
[0] == '\0')
722 return YPERR_BADARGS
;
727 while (try < MAXTRIES
&& res
!= YPERR_SUCCESS
)
729 if (__yp_bind (indomain
, &ydb
) != 0)
731 __set_errno (saved_errno
);
735 clnt_sock
= RPC_ANYSOCK
;
736 clnt_sin
= ydb
->dom_server_addr
;
737 clnt_sin
.sin_port
= 0;
739 /* We don't need the UDP connection anymore. */
743 clnt
= clnttcp_create (&clnt_sin
, YPPROG
, YPVERS
, &clnt_sock
, 0, 0);
746 __set_errno (saved_errno
);
749 req
.domain
= (char *) indomain
;
750 req
.map
= (char *) inmap
;
752 data
.foreach
= incallback
->foreach
;
753 data
.data
= (void *) incallback
->data
;
755 result
= clnt_call (clnt
, YPPROC_ALL
, (xdrproc_t
) xdr_ypreq_nokey
,
756 (caddr_t
) &req
, (xdrproc_t
) __xdr_ypresp_all
,
757 (caddr_t
) &data
, RPCTIMEOUT
);
759 if (__glibc_unlikely (result
!= RPC_SUCCESS
))
761 /* Print the error message only on the last try. */
762 if (try == MAXTRIES
- 1)
763 clnt_perror (clnt
, "yp_all: clnt_call");
771 if (res
== YPERR_SUCCESS
&& data
.status
!= YP_NOMORE
)
773 __set_errno (saved_errno
);
774 return ypprot_err (data
.status
);
779 __set_errno (saved_errno
);
786 yp_maplist (const char *indomain
, struct ypmaplist
**outmaplist
)
788 struct ypresp_maplist resp
;
789 enum clnt_stat result
;
791 if (indomain
== NULL
|| indomain
[0] == '\0')
792 return YPERR_BADARGS
;
794 memset (&resp
, '\0', sizeof (resp
));
796 result
= do_ypcall_tr (indomain
, YPPROC_MAPLIST
, (xdrproc_t
) xdr_domainname
,
797 (caddr_t
) &indomain
, (xdrproc_t
) xdr_ypresp_maplist
,
800 if (__glibc_likely (result
== YPERR_SUCCESS
))
802 *outmaplist
= resp
.maps
;
803 /* We don't free the list, this will be done by ypserv
804 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
811 yperr_string (const int error
)
820 str
= N_("Request arguments bad");
823 str
= N_("RPC failure on NIS operation");
826 str
= N_("Can't bind to server which serves this domain");
829 str
= N_("No such map in server's domain");
832 str
= N_("No such key in map");
835 str
= N_("Internal NIS error");
838 str
= N_("Local resource allocation failure");
841 str
= N_("No more records in map database");
844 str
= N_("Can't communicate with portmapper");
847 str
= N_("Can't communicate with ypbind");
850 str
= N_("Can't communicate with ypserv");
853 str
= N_("Local domain name not set");
856 str
= N_("NIS map database is bad");
859 str
= N_("NIS client/server version mismatch - can't supply service");
862 str
= N_("Permission denied");
865 str
= N_("Database is busy");
868 str
= N_("Unknown NIS error code");
874 static const int8_t yp_2_yperr
[] =
876 #define YP2YPERR(yp, yperr) [YP_##yp - YP_VERS] = YPERR_##yperr
877 YP2YPERR (TRUE
, SUCCESS
),
878 YP2YPERR (NOMORE
, NOMORE
),
879 YP2YPERR (FALSE
, YPERR
),
880 YP2YPERR (NOMAP
, MAP
),
881 YP2YPERR (NODOM
, DOMAIN
),
882 YP2YPERR (NOKEY
, KEY
),
883 YP2YPERR (BADOP
, YPERR
),
884 YP2YPERR (BADDB
, BADDB
),
885 YP2YPERR (YPERR
, YPERR
),
886 YP2YPERR (BADARGS
, BADARGS
),
887 YP2YPERR (VERS
, VERS
)
890 ypprot_err (const int code
)
892 if (code
< YP_VERS
|| code
> YP_NOMORE
)
894 return yp_2_yperr
[code
- YP_VERS
];
896 libnsl_hidden_def (ypprot_err
)
899 ypbinderr_string (const int error
)
908 str
= N_("Internal ypbind error");
910 case YPBIND_ERR_NOSERV
:
911 str
= N_("Domain not bound");
913 case YPBIND_ERR_RESC
:
914 str
= N_("System resource allocation failure");
917 str
= N_("Unknown ypbind error");
922 libnsl_hidden_def (ypbinderr_string
)
927 yp_update (char *domain
, char *map
, unsigned ypop
,
928 char *key
, int keylen
, char *data
, int datalen
)
932 ypupdate_args update_args
;
933 ypdelete_args delete_args
;
936 xdrproc_t xdr_argument
;
940 struct sockaddr saddr
;
941 char servername
[MAXNETNAMELEN
+ 1];
944 if (!domain
|| !map
|| !key
|| (ypop
!= YPOP_DELETE
&& !data
))
945 return YPERR_BADARGS
;
947 args
.update_args
.mapname
= map
;
948 args
.update_args
.key
.yp_buf_len
= keylen
;
949 args
.update_args
.key
.yp_buf_val
= key
;
950 args
.update_args
.datum
.yp_buf_len
= datalen
;
951 args
.update_args
.datum
.yp_buf_val
= data
;
953 if ((r
= yp_master (domain
, map
, &master
)) != YPERR_SUCCESS
)
956 if (!host2netname (servername
, master
, domain
))
958 fputs (_("yp_update: cannot convert host to netname\n"), stderr
);
963 clnt
= clnt_create (master
, YPU_PROG
, YPU_VERS
, "tcp");
965 /* We do not need the string anymore. */
970 clnt_pcreateerror ("yp_update: clnt_create");
974 if (!clnt_control (clnt
, CLGET_SERVER_ADDR
, (char *) &saddr
))
976 fputs (_("yp_update: cannot get server address\n"), stderr
);
985 xdr_argument
= (xdrproc_t
) xdr_ypupdate_args
;
988 xdr_argument
= (xdrproc_t
) xdr_ypdelete_args
;
991 return YPERR_BADARGS
;
995 clnt
->cl_auth
= authdes_create (servername
, WINDOW
, &saddr
, NULL
);
997 if (clnt
->cl_auth
== NULL
)
998 clnt
->cl_auth
= authunix_create_default ();
1001 r
= clnt_call (clnt
, ypop
, xdr_argument
, (caddr_t
) &args
,
1002 (xdrproc_t
) xdr_u_int
, (caddr_t
) &res
, RPCTIMEOUT
);
1004 if (r
== RPC_AUTHERROR
)
1006 if (clnt
->cl_auth
->ah_cred
.oa_flavor
== AUTH_DES
)
1008 auth_destroy (clnt
->cl_auth
);
1009 clnt
->cl_auth
= authunix_create_default ();
1013 return YPERR_ACCESS
;
1015 if (r
!= RPC_SUCCESS
)
1017 clnt_perror (clnt
, "yp_update: clnt_call");