1 /* Copyright (C) 1996-2001, 2002, 2003, 2004 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, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 #include <rpcsvc/nis.h>
27 #include <rpcsvc/yp.h>
28 #include <rpcsvc/ypclnt.h>
29 #include <rpcsvc/ypupd.h>
31 #include <bits/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 struct timeval RPCTIMEOUT
= {25, 0};
49 static struct timeval UDPTIMEOUT
= {5, 0};
50 static int const MAXTRIES
= 2;
51 static char __ypdomainname
[NIS_MAXNAMELEN
+ 1] = "\0";
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
= clntudp_create (&ysd
->dom_server_addr
, YPPROG
, YPVERS
,
72 UDPTIMEOUT
, &ysd
->dom_socket
);
74 if (ysd
->dom_client
!= NULL
)
76 /* If the program exits, close the socket */
77 if (fcntl (ysd
->dom_socket
, F_SETFD
, FD_CLOEXEC
) == -1)
78 perror ("fcntl: F_SETFD");
84 yp_bind_file (const char *domain
, dom_binding
*ysd
)
86 char path
[sizeof (BINDINGDIR
) + strlen (domain
) + 3 * sizeof (unsigned) + 3];
88 snprintf (path
, sizeof (path
), "%s/%s.%u", BINDINGDIR
, domain
, YPBINDVERS
);
89 int fd
= open (path
, O_RDONLY
);
92 /* We have a binding file and could save a RPC call. The file
93 contains a port number and the YPBIND_RESP record. The port
94 number (16 bits) can be ignored. */
95 struct ypbind_resp ypbr
;
97 if (pread (fd
, &ypbr
, sizeof (ypbr
), 2) == sizeof (ypbr
))
98 yp_bind_client_create (domain
, ysd
, &ypbr
);
106 yp_bind_ypbindprog (const char *domain
, dom_binding
*ysd
)
108 struct sockaddr_in clnt_saddr
;
109 struct ypbind_resp ypbr
;
113 memset (&clnt_saddr
, '\0', sizeof clnt_saddr
);
114 clnt_saddr
.sin_family
= AF_INET
;
115 clnt_saddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
116 clnt_sock
= RPC_ANYSOCK
;
117 client
= clnttcp_create (&clnt_saddr
, YPBINDPROG
, YPBINDVERS
,
122 /* Check the port number -- should be < IPPORT_RESERVED.
123 If not, it's possible someone has registered a bogus
124 ypbind with the portmapper and is trying to trick us. */
125 if (ntohs (clnt_saddr
.sin_port
) >= IPPORT_RESERVED
)
127 clnt_destroy (client
);
131 if (clnt_call (client
, YPBINDPROC_DOMAIN
,
132 (xdrproc_t
) xdr_domainname
, (caddr_t
) &domain
,
133 (xdrproc_t
) xdr_ypbind_resp
,
134 (caddr_t
) &ypbr
, RPCTIMEOUT
) != RPC_SUCCESS
)
136 clnt_destroy (client
);
140 clnt_destroy (client
);
142 if (ypbr
.ypbind_status
!= YPBIND_SUCC_VAL
)
144 fprintf (stderr
, _("YPBINDPROC_DOMAIN: %s\n"),
145 ypbinderr_string (ypbr
.ypbind_resp_u
.ypbind_error
));
148 memset (&ysd
->dom_server_addr
, '\0', sizeof ysd
->dom_server_addr
);
150 yp_bind_client_create (domain
, ysd
, &ypbr
);
152 return YPERR_SUCCESS
;
156 __yp_bind (const char *domain
, dom_binding
**ypdb
)
158 dom_binding
*ysd
= NULL
;
161 if (domain
== NULL
|| domain
[0] == '\0')
162 return YPERR_BADARGS
;
167 if (strcmp (domain
, ysd
->dom_domain
) == 0)
169 ysd
= ysd
->dom_pnext
;
175 ysd
= (dom_binding
*) calloc (1, sizeof *ysd
);
176 if (__builtin_expect (ysd
== NULL
, 0))
181 /* Try binding dir at first if we have no binding */
182 if (ysd
->dom_client
== NULL
)
183 yp_bind_file (domain
, ysd
);
184 #endif /* USE_BINDINGDIR */
186 if (ysd
->dom_client
== NULL
)
188 int retval
= yp_bind_ypbindprog (domain
, ysd
);
189 if (retval
!= YPERR_SUCCESS
)
197 if (ysd
->dom_client
== NULL
)
206 ysd
->dom_pnext
= *ypdb
;
210 return YPERR_SUCCESS
;
214 __yp_unbind (dom_binding
*ydb
)
216 clnt_destroy (ydb
->dom_client
);
221 yp_bind (const char *indomain
)
225 __libc_lock_lock (ypbindlist_lock
);
227 status
= __yp_bind (indomain
, &__ypbindlist
);
229 __libc_lock_unlock (ypbindlist_lock
);
235 yp_unbind_locked (const char *indomain
)
237 dom_binding
*ydbptr
, *ydbptr2
;
240 ydbptr
= __ypbindlist
;
242 while (ydbptr
!= NULL
)
244 if (strcmp (ydbptr
->dom_domain
, indomain
) == 0)
250 __ypbindlist
= __ypbindlist
->dom_pnext
;
252 ydbptr2
= ydbptr
->dom_pnext
;
257 ydbptr
= ydbptr
->dom_pnext
;
262 yp_unbind (const char *indomain
)
264 __libc_lock_lock (ypbindlist_lock
);
266 yp_unbind_locked (indomain
);
268 __libc_lock_unlock (ypbindlist_lock
);
274 __ypclnt_call (const char *domain
, u_long prog
, xdrproc_t xargs
,
275 caddr_t req
, xdrproc_t xres
, caddr_t resp
, dom_binding
**ydb
,
278 enum clnt_stat result
;
280 result
= clnt_call ((*ydb
)->dom_client
, prog
,
281 xargs
, req
, xres
, resp
, RPCTIMEOUT
);
283 if (result
!= RPC_SUCCESS
)
285 /* We don't print an error message, if we try our old,
286 cached data. Only print this for data, which should work. */
288 clnt_perror ((*ydb
)->dom_client
, "do_ypcall: clnt_call");
293 return YPERR_SUCCESS
;
297 do_ypcall (const char *domain
, u_long prog
, xdrproc_t xargs
,
298 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
302 int saved_errno
= errno
;
304 status
= YPERR_YPERR
;
306 __libc_lock_lock (ypbindlist_lock
);
310 if (strcmp (domain
, ydb
->dom_domain
) == 0)
312 if (__yp_bind (domain
, &ydb
) == 0)
314 /* Call server, print no error message, do not unbind. */
315 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
317 if (status
== YPERR_SUCCESS
)
319 __libc_lock_unlock (ypbindlist_lock
);
320 __set_errno (saved_errno
);
324 /* We use ypbindlist, and the old cached data is
325 invalid. unbind now and create a new binding */
326 yp_unbind_locked (domain
);
330 ydb
= ydb
->dom_pnext
;
332 __libc_lock_unlock (ypbindlist_lock
);
334 /* First try with cached data failed. Now try to get
335 current data from the system. */
337 if (__yp_bind (domain
, &ydb
) == 0)
339 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
345 /* If we support binding dir data, we have a third chance:
347 if (status
!= YPERR_SUCCESS
)
349 ydb
= calloc (1, sizeof (dom_binding
));
350 if (yp_bind_ypbindprog (domain
, ydb
) == YPERR_SUCCESS
)
352 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
361 __set_errno (saved_errno
);
367 __libc_lock_define_initialized (static, domainname_lock
)
370 yp_get_default_domain (char **outdomain
)
372 int result
= YPERR_SUCCESS
;;
375 __libc_lock_lock (domainname_lock
);
377 if (__ypdomainname
[0] == '\0')
379 if (getdomainname (__ypdomainname
, NIS_MAXNAMELEN
))
380 result
= YPERR_NODOM
;
381 else if (strcmp (__ypdomainname
, "(none)") == 0)
383 /* If domainname is not set, some systems will return "(none)" */
384 __ypdomainname
[0] = '\0';
385 result
= YPERR_NODOM
;
388 *outdomain
= __ypdomainname
;
391 *outdomain
= __ypdomainname
;
393 __libc_lock_unlock (domainname_lock
);
399 __yp_check (char **domain
)
403 if (__ypdomainname
[0] == '\0')
404 if (yp_get_default_domain (&unused
))
408 *domain
= __ypdomainname
;
410 if (yp_bind (__ypdomainname
) == 0)
416 yp_match (const char *indomain
, const char *inmap
, const char *inkey
,
417 const int inkeylen
, char **outval
, int *outvallen
)
421 enum clnt_stat result
;
423 if (indomain
== NULL
|| indomain
[0] == '\0' ||
424 inmap
== NULL
|| inmap
[0] == '\0' ||
425 inkey
== NULL
|| inkey
[0] == '\0' || inkeylen
<= 0)
426 return YPERR_BADARGS
;
428 req
.domain
= (char *) indomain
;
429 req
.map
= (char *) inmap
;
430 req
.key
.keydat_val
= (char *) inkey
;
431 req
.key
.keydat_len
= inkeylen
;
435 memset (&resp
, '\0', sizeof (resp
));
437 result
= do_ypcall (indomain
, YPPROC_MATCH
, (xdrproc_t
) xdr_ypreq_key
,
438 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_val
,
441 if (result
!= YPERR_SUCCESS
)
443 if (resp
.stat
!= YP_TRUE
)
444 return ypprot_err (resp
.stat
);
446 *outvallen
= resp
.val
.valdat_len
;
447 *outval
= malloc (*outvallen
+ 1);
448 if (__builtin_expect (*outval
== NULL
, 0))
450 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
451 (*outval
)[*outvallen
] = '\0';
453 xdr_free ((xdrproc_t
) xdr_ypresp_val
, (char *) &resp
);
455 return YPERR_SUCCESS
;
459 yp_first (const char *indomain
, const char *inmap
, char **outkey
,
460 int *outkeylen
, char **outval
, int *outvallen
)
464 enum clnt_stat result
;
466 if (indomain
== NULL
|| indomain
[0] == '\0' ||
467 inmap
== NULL
|| inmap
[0] == '\0')
468 return YPERR_BADARGS
;
470 req
.domain
= (char *) indomain
;
471 req
.map
= (char *) inmap
;
473 *outkey
= *outval
= NULL
;
474 *outkeylen
= *outvallen
= 0;
475 memset (&resp
, '\0', sizeof (resp
));
477 result
= do_ypcall (indomain
, YPPROC_FIRST
, (xdrproc_t
) xdr_ypreq_nokey
,
478 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_key_val
,
481 if (result
!= RPC_SUCCESS
)
483 if (resp
.stat
!= YP_TRUE
)
484 return ypprot_err (resp
.stat
);
486 *outkeylen
= resp
.key
.keydat_len
;
487 *outkey
= malloc (*outkeylen
+ 1);
488 if (__builtin_expect (*outkey
== NULL
, 0))
490 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
491 (*outkey
)[*outkeylen
] = '\0';
492 *outvallen
= resp
.val
.valdat_len
;
493 *outval
= malloc (*outvallen
+ 1);
494 if (__builtin_expect (*outval
== NULL
, 0))
496 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
497 (*outval
)[*outvallen
] = '\0';
499 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
501 return YPERR_SUCCESS
;
505 yp_next (const char *indomain
, const char *inmap
, const char *inkey
,
506 const int inkeylen
, char **outkey
, int *outkeylen
, char **outval
,
511 enum clnt_stat result
;
513 if (indomain
== NULL
|| indomain
[0] == '\0' ||
514 inmap
== NULL
|| inmap
[0] == '\0' ||
515 inkeylen
<= 0 || inkey
== NULL
|| inkey
[0] == '\0')
516 return YPERR_BADARGS
;
518 req
.domain
= (char *) indomain
;
519 req
.map
= (char *) inmap
;
520 req
.key
.keydat_val
= (char *) inkey
;
521 req
.key
.keydat_len
= inkeylen
;
523 *outkey
= *outval
= NULL
;
524 *outkeylen
= *outvallen
= 0;
525 memset (&resp
, '\0', sizeof (resp
));
527 result
= do_ypcall (indomain
, YPPROC_NEXT
, (xdrproc_t
) xdr_ypreq_key
,
528 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_key_val
,
531 if (result
!= YPERR_SUCCESS
)
533 if (resp
.stat
!= YP_TRUE
)
534 return ypprot_err (resp
.stat
);
536 *outkeylen
= resp
.key
.keydat_len
;
537 *outkey
= malloc (*outkeylen
+ 1);
538 if (__builtin_expect (*outkey
== NULL
, 0))
540 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
541 (*outkey
)[*outkeylen
] = '\0';
542 *outvallen
= resp
.val
.valdat_len
;
543 *outval
= malloc (*outvallen
+ 1);
544 if (__builtin_expect (*outval
== NULL
, 0))
546 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
547 (*outval
)[*outvallen
] = '\0';
549 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
551 return YPERR_SUCCESS
;
555 yp_master (const char *indomain
, const char *inmap
, char **outname
)
559 enum clnt_stat result
;
561 if (indomain
== NULL
|| indomain
[0] == '\0' ||
562 inmap
== NULL
|| inmap
[0] == '\0')
563 return YPERR_BADARGS
;
565 req
.domain
= (char *) indomain
;
566 req
.map
= (char *) inmap
;
568 memset (&resp
, '\0', sizeof (ypresp_master
));
570 result
= do_ypcall (indomain
, YPPROC_MASTER
, (xdrproc_t
) xdr_ypreq_nokey
,
571 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_master
, (caddr_t
) & resp
);
573 if (result
!= YPERR_SUCCESS
)
575 if (resp
.stat
!= YP_TRUE
)
576 return ypprot_err (resp
.stat
);
578 *outname
= strdup (resp
.peer
);
579 xdr_free ((xdrproc_t
) xdr_ypresp_master
, (char *) &resp
);
581 return *outname
== NULL
? YPERR_YPERR
: YPERR_SUCCESS
;
585 yp_order (const char *indomain
, const char *inmap
, unsigned int *outorder
)
587 struct ypreq_nokey req
;
588 struct ypresp_order resp
;
589 enum clnt_stat result
;
591 if (indomain
== NULL
|| indomain
[0] == '\0' ||
592 inmap
== NULL
|| inmap
== '\0')
593 return YPERR_BADARGS
;
595 req
.domain
= (char *) indomain
;
596 req
.map
= (char *) inmap
;
598 memset (&resp
, '\0', sizeof (resp
));
600 result
= do_ypcall (indomain
, YPPROC_ORDER
, (xdrproc_t
) xdr_ypreq_nokey
,
601 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_order
, (caddr_t
) & resp
);
603 if (result
!= YPERR_SUCCESS
)
605 if (resp
.stat
!= YP_TRUE
)
606 return ypprot_err (resp
.stat
);
608 *outorder
= resp
.ordernum
;
609 xdr_free ((xdrproc_t
) xdr_ypresp_order
, (char *) &resp
);
611 return YPERR_SUCCESS
;
614 struct ypresp_all_data
616 unsigned long status
;
618 int (*foreach
) (int status
, char *key
, int keylen
,
619 char *val
, int vallen
, char *data
);
623 __xdr_ypresp_all (XDR
*xdrs
, struct ypresp_all_data
*objp
)
627 struct ypresp_all resp
;
629 memset (&resp
, '\0', sizeof (struct ypresp_all
));
630 if (!xdr_ypresp_all (xdrs
, &resp
))
632 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
633 objp
->status
= YP_YPERR
;
638 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
639 objp
->status
= YP_NOMORE
;
643 switch (resp
.ypresp_all_u
.val
.stat
)
647 char key
[resp
.ypresp_all_u
.val
.key
.keydat_len
+ 1];
648 char val
[resp
.ypresp_all_u
.val
.val
.valdat_len
+ 1];
649 int keylen
= resp
.ypresp_all_u
.val
.key
.keydat_len
;
650 int vallen
= resp
.ypresp_all_u
.val
.val
.valdat_len
;
652 /* We are not allowed to modify the key and val data.
653 But we are allowed to add data behind the buffer,
654 if we don't modify the length. So add an extra NUL
655 character to avoid trouble with broken code. */
656 objp
->status
= YP_TRUE
;
657 memcpy (key
, resp
.ypresp_all_u
.val
.key
.keydat_val
, keylen
);
659 memcpy (val
, resp
.ypresp_all_u
.val
.val
.valdat_val
, vallen
);
661 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
662 if ((*objp
->foreach
) (objp
->status
, key
, keylen
,
663 val
, vallen
, objp
->data
))
668 objp
->status
= resp
.ypresp_all_u
.val
.stat
;
669 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
670 /* Sun says we don't need to make this call, but must return
671 immediatly. Since Solaris makes this call, we will call
672 the callback function, too. */
673 (*objp
->foreach
) (objp
->status
, NULL
, 0, NULL
, 0, objp
->data
);
680 yp_all (const char *indomain
, const char *inmap
,
681 const struct ypall_callback
*incallback
)
683 struct ypreq_nokey req
;
684 dom_binding
*ydb
= NULL
;
686 enum clnt_stat result
;
687 struct sockaddr_in clnt_sin
;
689 struct ypresp_all_data data
;
691 int saved_errno
= errno
;
693 if (indomain
== NULL
|| indomain
[0] == '\0' ||
694 inmap
== NULL
|| inmap
== '\0')
695 return YPERR_BADARGS
;
700 while (try < MAXTRIES
&& res
!= YPERR_SUCCESS
)
702 if (__yp_bind (indomain
, &ydb
) != 0)
704 __set_errno (saved_errno
);
708 clnt_sock
= RPC_ANYSOCK
;
709 clnt_sin
= ydb
->dom_server_addr
;
710 clnt_sin
.sin_port
= 0;
712 /* We don't need the UDP connection anymore. */
716 clnt
= clnttcp_create (&clnt_sin
, YPPROG
, YPVERS
, &clnt_sock
, 0, 0);
719 __set_errno (saved_errno
);
722 req
.domain
= (char *) indomain
;
723 req
.map
= (char *) inmap
;
725 data
.foreach
= incallback
->foreach
;
726 data
.data
= (void *) incallback
->data
;
728 result
= clnt_call (clnt
, YPPROC_ALL
, (xdrproc_t
) xdr_ypreq_nokey
,
729 (caddr_t
) &req
, (xdrproc_t
) __xdr_ypresp_all
,
730 (caddr_t
) &data
, RPCTIMEOUT
);
732 if (result
!= RPC_SUCCESS
)
734 /* Print the error message only on the last try */
735 if (try == MAXTRIES
- 1)
736 clnt_perror (clnt
, "yp_all: clnt_call");
744 if (res
== YPERR_SUCCESS
&& data
.status
!= YP_NOMORE
)
746 __set_errno (saved_errno
);
747 return ypprot_err (data
.status
);
752 __set_errno (saved_errno
);
758 yp_maplist (const char *indomain
, struct ypmaplist
**outmaplist
)
760 struct ypresp_maplist resp
;
761 enum clnt_stat result
;
763 if (indomain
== NULL
|| indomain
[0] == '\0')
764 return YPERR_BADARGS
;
766 memset (&resp
, '\0', sizeof (resp
));
768 result
= do_ypcall (indomain
, YPPROC_MAPLIST
, (xdrproc_t
) xdr_domainname
,
769 (caddr_t
) & indomain
, (xdrproc_t
) xdr_ypresp_maplist
, (caddr_t
) & resp
);
771 if (result
!= YPERR_SUCCESS
)
773 if (resp
.stat
!= YP_TRUE
)
774 return ypprot_err (resp
.stat
);
776 *outmaplist
= resp
.maps
;
777 /* We give the list not free, this will be done by ypserv
778 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
780 return YPERR_SUCCESS
;
784 yperr_string (const int error
)
791 return _("Request arguments bad");
793 return _("RPC failure on NIS operation");
795 return _("Can't bind to server which serves this domain");
797 return _("No such map in server's domain");
799 return _("No such key in map");
801 return _("Internal NIS error");
803 return _("Local resource allocation failure");
805 return _("No more records in map database");
807 return _("Can't communicate with portmapper");
809 return _("Can't communicate with ypbind");
811 return _("Can't communicate with ypserv");
813 return _("Local domain name not set");
815 return _("NIS map database is bad");
817 return _("NIS client/server version mismatch - can't supply service");
819 return _("Permission denied");
821 return _("Database is busy");
823 return _("Unknown NIS error code");
827 ypprot_err (const int code
)
832 return YPERR_SUCCESS
;
850 return YPERR_BADARGS
;
858 ypbinderr_string (const int error
)
865 return _("Internal ypbind error");
866 case YPBIND_ERR_NOSERV
:
867 return _("Domain not bound");
868 case YPBIND_ERR_RESC
:
869 return _("System resource allocation failure");
871 return _("Unknown ypbind error");
879 yp_update (char *domain
, char *map
, unsigned ypop
,
880 char *key
, int keylen
, char *data
, int datalen
)
884 ypupdate_args update_args
;
885 ypdelete_args delete_args
;
888 xdrproc_t xdr_argument
;
892 struct sockaddr saddr
;
893 char servername
[MAXNETNAMELEN
+ 1];
896 if (!domain
|| !map
|| !key
|| (ypop
!= YPOP_DELETE
&& !data
))
897 return YPERR_BADARGS
;
899 args
.update_args
.mapname
= map
;
900 args
.update_args
.key
.yp_buf_len
= keylen
;
901 args
.update_args
.key
.yp_buf_val
= key
;
902 args
.update_args
.datum
.yp_buf_len
= datalen
;
903 args
.update_args
.datum
.yp_buf_val
= data
;
905 if ((r
= yp_master (domain
, map
, &master
)) != 0)
908 if (!host2netname (servername
, master
, domain
))
910 fputs (_("yp_update: cannot convert host to netname\n"), stderr
);
914 if ((clnt
= clnt_create (master
, YPU_PROG
, YPU_VERS
, "tcp")) == NULL
)
916 clnt_pcreateerror ("yp_update: clnt_create");
920 if (!clnt_control (clnt
, CLGET_SERVER_ADDR
, (char *) &saddr
))
922 fputs (_("yp_update: cannot get server address\n"), stderr
);
931 xdr_argument
= (xdrproc_t
) xdr_ypupdate_args
;
934 xdr_argument
= (xdrproc_t
) xdr_ypdelete_args
;
937 return YPERR_BADARGS
;
941 clnt
->cl_auth
= authdes_create (servername
, WINDOW
, &saddr
, NULL
);
943 if (clnt
->cl_auth
== NULL
)
944 clnt
->cl_auth
= authunix_create_default ();
947 r
= clnt_call (clnt
, ypop
, xdr_argument
, (caddr_t
) &args
,
948 (xdrproc_t
) xdr_u_int
, (caddr_t
) &res
, RPCTIMEOUT
);
950 if (r
== RPC_AUTHERROR
)
952 if (clnt
->cl_auth
->ah_cred
.oa_flavor
== AUTH_DES
)
954 clnt
->cl_auth
= authunix_create_default ();
960 if (r
!= RPC_SUCCESS
)
962 clnt_perror (clnt
, "yp_update: clnt_call");