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
, 1) == -1)
78 perror ("fcntl: F_SETFD");
84 yp_bind_file (const char *domain
, dom_binding
*ysd
)
86 struct ypbind_resp ypbr
;
87 char path
[sizeof (BINDINGDIR
) + strlen (domain
) + 10];
92 sprintf (path
, "%s/%s.%d", BINDINGDIR
, domain
, YPBINDVERS
);
93 fd
= open (path
, O_RDONLY
);
96 /* We have a binding file and could save a RPC call */
97 vec
[0].iov_base
= &port
;
98 vec
[0].iov_len
= sizeof (port
);
99 vec
[1].iov_base
= &ypbr
;
100 vec
[1].iov_len
= sizeof (ypbr
);
102 if (readv (fd
, vec
, 2) == sizeof (port
) + sizeof (ypbr
))
103 yp_bind_client_create (domain
, ysd
, &ypbr
);
111 yp_bind_ypbindprog (const char *domain
, dom_binding
*ysd
)
113 struct sockaddr_in clnt_saddr
;
114 struct ypbind_resp ypbr
;
118 memset (&clnt_saddr
, '\0', sizeof clnt_saddr
);
119 clnt_saddr
.sin_family
= AF_INET
;
120 clnt_saddr
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
121 clnt_sock
= RPC_ANYSOCK
;
122 client
= clnttcp_create (&clnt_saddr
, YPBINDPROG
, YPBINDVERS
,
127 /* Check the port number -- should be < IPPORT_RESERVED.
128 If not, it's possible someone has registered a bogus
129 ypbind with the portmapper and is trying to trick us. */
130 if (ntohs (clnt_saddr
.sin_port
) >= IPPORT_RESERVED
)
132 clnt_destroy (client
);
136 if (clnt_call (client
, YPBINDPROC_DOMAIN
,
137 (xdrproc_t
) xdr_domainname
, (caddr_t
) &domain
,
138 (xdrproc_t
) xdr_ypbind_resp
,
139 (caddr_t
) &ypbr
, RPCTIMEOUT
) != RPC_SUCCESS
)
141 clnt_destroy (client
);
145 clnt_destroy (client
);
147 if (ypbr
.ypbind_status
!= YPBIND_SUCC_VAL
)
149 fprintf (stderr
, _("YPBINDPROC_DOMAIN: %s\n"),
150 ypbinderr_string (ypbr
.ypbind_resp_u
.ypbind_error
));
153 memset (&ysd
->dom_server_addr
, '\0', sizeof ysd
->dom_server_addr
);
155 yp_bind_client_create (domain
, ysd
, &ypbr
);
157 return YPERR_SUCCESS
;
161 __yp_bind (const char *domain
, dom_binding
**ypdb
)
163 dom_binding
*ysd
= NULL
;
166 if (domain
== NULL
|| domain
[0] == '\0')
167 return YPERR_BADARGS
;
172 if (strcmp (domain
, ysd
->dom_domain
) == 0)
174 ysd
= ysd
->dom_pnext
;
180 ysd
= (dom_binding
*) calloc (1, sizeof *ysd
);
181 if (__builtin_expect (ysd
== NULL
, 0))
186 /* Try binding dir at first if we have no binding */
187 if (ysd
->dom_client
== NULL
)
188 yp_bind_file (domain
, ysd
);
189 #endif /* USE_BINDINGDIR */
191 if (ysd
->dom_client
== NULL
)
193 int retval
= yp_bind_ypbindprog (domain
, ysd
);
194 if (retval
!= YPERR_SUCCESS
)
202 if (ysd
->dom_client
== NULL
)
211 ysd
->dom_pnext
= *ypdb
;
215 return YPERR_SUCCESS
;
219 __yp_unbind (dom_binding
*ydb
)
221 clnt_destroy (ydb
->dom_client
);
226 yp_bind (const char *indomain
)
230 __libc_lock_lock (ypbindlist_lock
);
232 status
= __yp_bind (indomain
, &__ypbindlist
);
234 __libc_lock_unlock (ypbindlist_lock
);
240 yp_unbind_locked (const char *indomain
)
242 dom_binding
*ydbptr
, *ydbptr2
;
245 ydbptr
= __ypbindlist
;
247 while (ydbptr
!= NULL
)
249 if (strcmp (ydbptr
->dom_domain
, indomain
) == 0)
255 __ypbindlist
= __ypbindlist
->dom_pnext
;
257 ydbptr2
= ydbptr
->dom_pnext
;
262 ydbptr
= ydbptr
->dom_pnext
;
267 yp_unbind (const char *indomain
)
269 __libc_lock_lock (ypbindlist_lock
);
271 yp_unbind_locked (indomain
);
273 __libc_lock_unlock (ypbindlist_lock
);
279 __ypclnt_call (const char *domain
, u_long prog
, xdrproc_t xargs
,
280 caddr_t req
, xdrproc_t xres
, caddr_t resp
, dom_binding
**ydb
,
283 enum clnt_stat result
;
285 result
= clnt_call ((*ydb
)->dom_client
, prog
,
286 xargs
, req
, xres
, resp
, RPCTIMEOUT
);
288 if (result
!= RPC_SUCCESS
)
290 /* We don't print an error message, if we try our old,
291 cached data. Only print this for data, which should work. */
293 clnt_perror ((*ydb
)->dom_client
, "do_ypcall: clnt_call");
298 return YPERR_SUCCESS
;
302 do_ypcall (const char *domain
, u_long prog
, xdrproc_t xargs
,
303 caddr_t req
, xdrproc_t xres
, caddr_t resp
)
307 int saved_errno
= errno
;
309 status
= YPERR_YPERR
;
311 __libc_lock_lock (ypbindlist_lock
);
312 if (__ypbindlist
!= NULL
)
317 if (strcmp (domain
, ydb
->dom_domain
) == 0)
319 ydb
= ydb
->dom_pnext
;
323 if (__yp_bind (domain
, &ydb
) == 0)
325 /* Call server, print no error message, do not unbind. */
326 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
328 if (status
== YPERR_SUCCESS
)
330 __set_errno (saved_errno
);
334 /* We use ypbindlist, and the old cached data is
335 invalid. unbind now and create a new binding */
336 yp_unbind_locked (domain
);
339 __libc_lock_unlock (ypbindlist_lock
);
341 /* First try with cached data failed. Now try to get
342 current data from the system. */
344 if (__yp_bind (domain
, &ydb
) == 0)
346 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
352 /* If we support binding dir data, we have a third chance:
354 if (status
!= YPERR_SUCCESS
)
356 ydb
= calloc (1, sizeof (dom_binding
));
357 if (yp_bind_ypbindprog (domain
, ydb
) == YPERR_SUCCESS
)
359 status
= __ypclnt_call (domain
, prog
, xargs
, req
, xres
,
368 __set_errno (saved_errno
);
374 __libc_lock_define_initialized (static, domainname_lock
)
377 yp_get_default_domain (char **outdomain
)
379 int result
= YPERR_SUCCESS
;;
382 __libc_lock_lock (domainname_lock
);
384 if (__ypdomainname
[0] == '\0')
386 if (getdomainname (__ypdomainname
, NIS_MAXNAMELEN
))
387 result
= YPERR_NODOM
;
388 else if (strcmp (__ypdomainname
, "(none)") == 0)
390 /* If domainname is not set, some systems will return "(none)" */
391 __ypdomainname
[0] = '\0';
392 result
= YPERR_NODOM
;
395 *outdomain
= __ypdomainname
;
398 *outdomain
= __ypdomainname
;
400 __libc_lock_unlock (domainname_lock
);
406 __yp_check (char **domain
)
410 if (__ypdomainname
[0] == '\0')
411 if (yp_get_default_domain (&unused
))
415 *domain
= __ypdomainname
;
417 if (yp_bind (__ypdomainname
) == 0)
423 yp_match (const char *indomain
, const char *inmap
, const char *inkey
,
424 const int inkeylen
, char **outval
, int *outvallen
)
428 enum clnt_stat result
;
430 if (indomain
== NULL
|| indomain
[0] == '\0' ||
431 inmap
== NULL
|| inmap
[0] == '\0' ||
432 inkey
== NULL
|| inkey
[0] == '\0' || inkeylen
<= 0)
433 return YPERR_BADARGS
;
435 req
.domain
= (char *) indomain
;
436 req
.map
= (char *) inmap
;
437 req
.key
.keydat_val
= (char *) inkey
;
438 req
.key
.keydat_len
= inkeylen
;
442 memset (&resp
, '\0', sizeof (resp
));
444 result
= do_ypcall (indomain
, YPPROC_MATCH
, (xdrproc_t
) xdr_ypreq_key
,
445 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_val
,
448 if (result
!= YPERR_SUCCESS
)
450 if (resp
.stat
!= YP_TRUE
)
451 return ypprot_err (resp
.stat
);
453 *outvallen
= resp
.val
.valdat_len
;
454 *outval
= malloc (*outvallen
+ 1);
455 if (__builtin_expect (*outval
== NULL
, 0))
457 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
458 (*outval
)[*outvallen
] = '\0';
460 xdr_free ((xdrproc_t
) xdr_ypresp_val
, (char *) &resp
);
462 return YPERR_SUCCESS
;
466 yp_first (const char *indomain
, const char *inmap
, char **outkey
,
467 int *outkeylen
, char **outval
, int *outvallen
)
471 enum clnt_stat result
;
473 if (indomain
== NULL
|| indomain
[0] == '\0' ||
474 inmap
== NULL
|| inmap
[0] == '\0')
475 return YPERR_BADARGS
;
477 req
.domain
= (char *) indomain
;
478 req
.map
= (char *) inmap
;
480 *outkey
= *outval
= NULL
;
481 *outkeylen
= *outvallen
= 0;
482 memset (&resp
, '\0', sizeof (resp
));
484 result
= do_ypcall (indomain
, YPPROC_FIRST
, (xdrproc_t
) xdr_ypreq_nokey
,
485 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_key_val
,
488 if (result
!= RPC_SUCCESS
)
490 if (resp
.stat
!= YP_TRUE
)
491 return ypprot_err (resp
.stat
);
493 *outkeylen
= resp
.key
.keydat_len
;
494 *outkey
= malloc (*outkeylen
+ 1);
495 if (__builtin_expect (*outkey
== NULL
, 0))
497 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
498 (*outkey
)[*outkeylen
] = '\0';
499 *outvallen
= resp
.val
.valdat_len
;
500 *outval
= malloc (*outvallen
+ 1);
501 if (__builtin_expect (*outval
== NULL
, 0))
503 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
504 (*outval
)[*outvallen
] = '\0';
506 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
508 return YPERR_SUCCESS
;
512 yp_next (const char *indomain
, const char *inmap
, const char *inkey
,
513 const int inkeylen
, char **outkey
, int *outkeylen
, char **outval
,
518 enum clnt_stat result
;
520 if (indomain
== NULL
|| indomain
[0] == '\0' ||
521 inmap
== NULL
|| inmap
[0] == '\0' ||
522 inkeylen
<= 0 || inkey
== NULL
|| inkey
[0] == '\0')
523 return YPERR_BADARGS
;
525 req
.domain
= (char *) indomain
;
526 req
.map
= (char *) inmap
;
527 req
.key
.keydat_val
= (char *) inkey
;
528 req
.key
.keydat_len
= inkeylen
;
530 *outkey
= *outval
= NULL
;
531 *outkeylen
= *outvallen
= 0;
532 memset (&resp
, '\0', sizeof (resp
));
534 result
= do_ypcall (indomain
, YPPROC_NEXT
, (xdrproc_t
) xdr_ypreq_key
,
535 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_key_val
,
538 if (result
!= YPERR_SUCCESS
)
540 if (resp
.stat
!= YP_TRUE
)
541 return ypprot_err (resp
.stat
);
543 *outkeylen
= resp
.key
.keydat_len
;
544 *outkey
= malloc (*outkeylen
+ 1);
545 if (__builtin_expect (*outkey
== NULL
, 0))
547 memcpy (*outkey
, resp
.key
.keydat_val
, *outkeylen
);
548 (*outkey
)[*outkeylen
] = '\0';
549 *outvallen
= resp
.val
.valdat_len
;
550 *outval
= malloc (*outvallen
+ 1);
551 if (__builtin_expect (*outval
== NULL
, 0))
553 memcpy (*outval
, resp
.val
.valdat_val
, *outvallen
);
554 (*outval
)[*outvallen
] = '\0';
556 xdr_free ((xdrproc_t
) xdr_ypresp_key_val
, (char *) &resp
);
558 return YPERR_SUCCESS
;
562 yp_master (const char *indomain
, const char *inmap
, char **outname
)
566 enum clnt_stat result
;
568 if (indomain
== NULL
|| indomain
[0] == '\0' ||
569 inmap
== NULL
|| inmap
[0] == '\0')
570 return YPERR_BADARGS
;
572 req
.domain
= (char *) indomain
;
573 req
.map
= (char *) inmap
;
575 memset (&resp
, '\0', sizeof (ypresp_master
));
577 result
= do_ypcall (indomain
, YPPROC_MASTER
, (xdrproc_t
) xdr_ypreq_nokey
,
578 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_master
, (caddr_t
) & resp
);
580 if (result
!= YPERR_SUCCESS
)
582 if (resp
.stat
!= YP_TRUE
)
583 return ypprot_err (resp
.stat
);
585 *outname
= strdup (resp
.peer
);
586 xdr_free ((xdrproc_t
) xdr_ypresp_master
, (char *) &resp
);
588 return *outname
== NULL
? YPERR_YPERR
: YPERR_SUCCESS
;
592 yp_order (const char *indomain
, const char *inmap
, unsigned int *outorder
)
594 struct ypreq_nokey req
;
595 struct ypresp_order resp
;
596 enum clnt_stat result
;
598 if (indomain
== NULL
|| indomain
[0] == '\0' ||
599 inmap
== NULL
|| inmap
== '\0')
600 return YPERR_BADARGS
;
602 req
.domain
= (char *) indomain
;
603 req
.map
= (char *) inmap
;
605 memset (&resp
, '\0', sizeof (resp
));
607 result
= do_ypcall (indomain
, YPPROC_ORDER
, (xdrproc_t
) xdr_ypreq_nokey
,
608 (caddr_t
) & req
, (xdrproc_t
) xdr_ypresp_order
, (caddr_t
) & resp
);
610 if (result
!= YPERR_SUCCESS
)
612 if (resp
.stat
!= YP_TRUE
)
613 return ypprot_err (resp
.stat
);
615 *outorder
= resp
.ordernum
;
616 xdr_free ((xdrproc_t
) xdr_ypresp_order
, (char *) &resp
);
618 return YPERR_SUCCESS
;
621 static void *ypall_data
;
622 static int (*ypall_foreach
) (int status
, char *key
, int keylen
,
623 char *val
, int vallen
, char *data
);
626 __xdr_ypresp_all (XDR
*xdrs
, u_long
*objp
)
630 struct ypresp_all resp
;
632 memset (&resp
, '\0', sizeof (struct ypresp_all
));
633 if (!xdr_ypresp_all (xdrs
, &resp
))
635 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
641 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
646 switch (resp
.ypresp_all_u
.val
.stat
)
650 char key
[resp
.ypresp_all_u
.val
.key
.keydat_len
+ 1];
651 char val
[resp
.ypresp_all_u
.val
.val
.valdat_len
+ 1];
652 int keylen
= resp
.ypresp_all_u
.val
.key
.keydat_len
;
653 int vallen
= resp
.ypresp_all_u
.val
.val
.valdat_len
;
655 /* We are not allowed to modify the key and val data.
656 But we are allowed to add data behind the buffer,
657 if we don't modify the length. So add an extra NUL
658 character to avoid trouble with broken code. */
660 memcpy (key
, resp
.ypresp_all_u
.val
.key
.keydat_val
, keylen
);
662 memcpy (val
, resp
.ypresp_all_u
.val
.val
.valdat_val
, vallen
);
664 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
665 if ((*ypall_foreach
) (*objp
, key
, keylen
,
666 val
, vallen
, ypall_data
))
671 *objp
= resp
.ypresp_all_u
.val
.stat
;
672 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
673 /* Sun says we don't need to make this call, but must return
674 immediatly. Since Solaris makes this call, we will call
675 the callback function, too. */
676 (*ypall_foreach
) (*objp
, NULL
, 0, NULL
, 0, ypall_data
);
683 yp_all (const char *indomain
, const char *inmap
,
684 const struct ypall_callback
*incallback
)
686 struct ypreq_nokey req
;
687 dom_binding
*ydb
= NULL
;
689 enum clnt_stat result
;
690 struct sockaddr_in clnt_sin
;
692 unsigned long status
;
694 int saved_errno
= errno
;
696 if (indomain
== NULL
|| indomain
[0] == '\0' ||
697 inmap
== NULL
|| inmap
== '\0')
698 return YPERR_BADARGS
;
703 while (try < MAXTRIES
&& res
!= YPERR_SUCCESS
)
705 if (__yp_bind (indomain
, &ydb
) != 0)
707 __set_errno (saved_errno
);
711 clnt_sock
= RPC_ANYSOCK
;
712 clnt_sin
= ydb
->dom_server_addr
;
713 clnt_sin
.sin_port
= 0;
715 /* We don't need the UDP connection anymore. */
719 clnt
= clnttcp_create (&clnt_sin
, YPPROG
, YPVERS
, &clnt_sock
, 0, 0);
722 __set_errno (saved_errno
);
725 req
.domain
= (char *) indomain
;
726 req
.map
= (char *) inmap
;
728 ypall_foreach
= incallback
->foreach
;
729 ypall_data
= (void *) incallback
->data
;
731 result
= clnt_call (clnt
, YPPROC_ALL
, (xdrproc_t
) xdr_ypreq_nokey
,
732 (caddr_t
) &req
, (xdrproc_t
) __xdr_ypresp_all
,
733 (caddr_t
) &status
, RPCTIMEOUT
);
735 if (result
!= RPC_SUCCESS
)
737 /* Print the error message only on the last try */
738 if (try == MAXTRIES
- 1)
739 clnt_perror (clnt
, "yp_all: clnt_call");
747 if (res
== YPERR_SUCCESS
&& status
!= YP_NOMORE
)
749 __set_errno (saved_errno
);
750 return ypprot_err (status
);
755 __set_errno (saved_errno
);
761 yp_maplist (const char *indomain
, struct ypmaplist
**outmaplist
)
763 struct ypresp_maplist resp
;
764 enum clnt_stat result
;
766 if (indomain
== NULL
|| indomain
[0] == '\0')
767 return YPERR_BADARGS
;
769 memset (&resp
, '\0', sizeof (resp
));
771 result
= do_ypcall (indomain
, YPPROC_MAPLIST
, (xdrproc_t
) xdr_domainname
,
772 (caddr_t
) & indomain
, (xdrproc_t
) xdr_ypresp_maplist
, (caddr_t
) & resp
);
774 if (result
!= YPERR_SUCCESS
)
776 if (resp
.stat
!= YP_TRUE
)
777 return ypprot_err (resp
.stat
);
779 *outmaplist
= resp
.maps
;
780 /* We give the list not free, this will be done by ypserv
781 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
783 return YPERR_SUCCESS
;
787 yperr_string (const int error
)
794 return _("Request arguments bad");
796 return _("RPC failure on NIS operation");
798 return _("Can't bind to server which serves this domain");
800 return _("No such map in server's domain");
802 return _("No such key in map");
804 return _("Internal NIS error");
806 return _("Local resource allocation failure");
808 return _("No more records in map database");
810 return _("Can't communicate with portmapper");
812 return _("Can't communicate with ypbind");
814 return _("Can't communicate with ypserv");
816 return _("Local domain name not set");
818 return _("NIS map database is bad");
820 return _("NIS client/server version mismatch - can't supply service");
822 return _("Permission denied");
824 return _("Database is busy");
826 return _("Unknown NIS error code");
830 ypprot_err (const int code
)
835 return YPERR_SUCCESS
;
853 return YPERR_BADARGS
;
861 ypbinderr_string (const int error
)
868 return _("Internal ypbind error");
869 case YPBIND_ERR_NOSERV
:
870 return _("Domain not bound");
871 case YPBIND_ERR_RESC
:
872 return _("System resource allocation failure");
874 return _("Unknown ypbind error");
882 yp_update (char *domain
, char *map
, unsigned ypop
,
883 char *key
, int keylen
, char *data
, int datalen
)
887 ypupdate_args update_args
;
888 ypdelete_args delete_args
;
891 xdrproc_t xdr_argument
;
895 struct sockaddr saddr
;
896 char servername
[MAXNETNAMELEN
+ 1];
899 if (!domain
|| !map
|| !key
|| (ypop
!= YPOP_DELETE
&& !data
))
900 return YPERR_BADARGS
;
902 args
.update_args
.mapname
= map
;
903 args
.update_args
.key
.yp_buf_len
= keylen
;
904 args
.update_args
.key
.yp_buf_val
= key
;
905 args
.update_args
.datum
.yp_buf_len
= datalen
;
906 args
.update_args
.datum
.yp_buf_val
= data
;
908 if ((r
= yp_master (domain
, map
, &master
)) != 0)
911 if (!host2netname (servername
, master
, domain
))
913 fputs (_("yp_update: cannot convert host to netname\n"), stderr
);
917 if ((clnt
= clnt_create (master
, YPU_PROG
, YPU_VERS
, "tcp")) == NULL
)
919 clnt_pcreateerror ("yp_update: clnt_create");
923 if (!clnt_control (clnt
, CLGET_SERVER_ADDR
, (char *) &saddr
))
925 fputs (_("yp_update: cannot get server address\n"), stderr
);
934 xdr_argument
= (xdrproc_t
) xdr_ypupdate_args
;
937 xdr_argument
= (xdrproc_t
) xdr_ypdelete_args
;
940 return YPERR_BADARGS
;
944 clnt
->cl_auth
= authdes_create (servername
, WINDOW
, &saddr
, NULL
);
946 if (clnt
->cl_auth
== NULL
)
947 clnt
->cl_auth
= authunix_create_default ();
950 r
= clnt_call (clnt
, ypop
, xdr_argument
, (caddr_t
) &args
,
951 (xdrproc_t
) xdr_u_int
, (caddr_t
) &res
, RPCTIMEOUT
);
953 if (r
== RPC_AUTHERROR
)
955 if (clnt
->cl_auth
->ah_cred
.oa_flavor
== AUTH_DES
)
957 clnt
->cl_auth
= authunix_create_default ();
963 if (r
!= RPC_SUCCESS
)
965 clnt_perror (clnt
, "yp_update: clnt_call");