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 struct ypresp_all_data
623 unsigned long status
;
625 int (*foreach
) (int status
, char *key
, int keylen
,
626 char *val
, int vallen
, char *data
);
630 __xdr_ypresp_all (XDR
*xdrs
, struct ypresp_all_data
*objp
)
634 struct ypresp_all resp
;
636 memset (&resp
, '\0', sizeof (struct ypresp_all
));
637 if (!xdr_ypresp_all (xdrs
, &resp
))
639 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
640 objp
->status
= YP_YPERR
;
645 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
646 objp
->status
= YP_NOMORE
;
650 switch (resp
.ypresp_all_u
.val
.stat
)
654 char key
[resp
.ypresp_all_u
.val
.key
.keydat_len
+ 1];
655 char val
[resp
.ypresp_all_u
.val
.val
.valdat_len
+ 1];
656 int keylen
= resp
.ypresp_all_u
.val
.key
.keydat_len
;
657 int vallen
= resp
.ypresp_all_u
.val
.val
.valdat_len
;
659 /* We are not allowed to modify the key and val data.
660 But we are allowed to add data behind the buffer,
661 if we don't modify the length. So add an extra NUL
662 character to avoid trouble with broken code. */
663 objp
->status
= YP_TRUE
;
664 memcpy (key
, resp
.ypresp_all_u
.val
.key
.keydat_val
, keylen
);
666 memcpy (val
, resp
.ypresp_all_u
.val
.val
.valdat_val
, vallen
);
668 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
669 if ((*objp
->foreach
) (objp
->status
, key
, keylen
,
670 val
, vallen
, objp
->data
))
675 objp
->status
= resp
.ypresp_all_u
.val
.stat
;
676 xdr_free ((xdrproc_t
) xdr_ypresp_all
, (char *) &resp
);
677 /* Sun says we don't need to make this call, but must return
678 immediatly. Since Solaris makes this call, we will call
679 the callback function, too. */
680 (*objp
->foreach
) (objp
->status
, NULL
, 0, NULL
, 0, objp
->data
);
687 yp_all (const char *indomain
, const char *inmap
,
688 const struct ypall_callback
*incallback
)
690 struct ypreq_nokey req
;
691 dom_binding
*ydb
= NULL
;
693 enum clnt_stat result
;
694 struct sockaddr_in clnt_sin
;
696 struct ypresp_all_data data
;
698 int saved_errno
= errno
;
700 if (indomain
== NULL
|| indomain
[0] == '\0' ||
701 inmap
== NULL
|| inmap
== '\0')
702 return YPERR_BADARGS
;
707 while (try < MAXTRIES
&& res
!= YPERR_SUCCESS
)
709 if (__yp_bind (indomain
, &ydb
) != 0)
711 __set_errno (saved_errno
);
715 clnt_sock
= RPC_ANYSOCK
;
716 clnt_sin
= ydb
->dom_server_addr
;
717 clnt_sin
.sin_port
= 0;
719 /* We don't need the UDP connection anymore. */
723 clnt
= clnttcp_create (&clnt_sin
, YPPROG
, YPVERS
, &clnt_sock
, 0, 0);
726 __set_errno (saved_errno
);
729 req
.domain
= (char *) indomain
;
730 req
.map
= (char *) inmap
;
732 data
.foreach
= incallback
->foreach
;
733 data
.data
= (void *) incallback
->data
;
735 result
= clnt_call (clnt
, YPPROC_ALL
, (xdrproc_t
) xdr_ypreq_nokey
,
736 (caddr_t
) &req
, (xdrproc_t
) __xdr_ypresp_all
,
737 (caddr_t
) &data
, RPCTIMEOUT
);
739 if (result
!= RPC_SUCCESS
)
741 /* Print the error message only on the last try */
742 if (try == MAXTRIES
- 1)
743 clnt_perror (clnt
, "yp_all: clnt_call");
751 if (res
== YPERR_SUCCESS
&& data
.status
!= YP_NOMORE
)
753 __set_errno (saved_errno
);
754 return ypprot_err (data
.status
);
759 __set_errno (saved_errno
);
765 yp_maplist (const char *indomain
, struct ypmaplist
**outmaplist
)
767 struct ypresp_maplist resp
;
768 enum clnt_stat result
;
770 if (indomain
== NULL
|| indomain
[0] == '\0')
771 return YPERR_BADARGS
;
773 memset (&resp
, '\0', sizeof (resp
));
775 result
= do_ypcall (indomain
, YPPROC_MAPLIST
, (xdrproc_t
) xdr_domainname
,
776 (caddr_t
) & indomain
, (xdrproc_t
) xdr_ypresp_maplist
, (caddr_t
) & resp
);
778 if (result
!= YPERR_SUCCESS
)
780 if (resp
.stat
!= YP_TRUE
)
781 return ypprot_err (resp
.stat
);
783 *outmaplist
= resp
.maps
;
784 /* We give the list not free, this will be done by ypserv
785 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
787 return YPERR_SUCCESS
;
791 yperr_string (const int error
)
798 return _("Request arguments bad");
800 return _("RPC failure on NIS operation");
802 return _("Can't bind to server which serves this domain");
804 return _("No such map in server's domain");
806 return _("No such key in map");
808 return _("Internal NIS error");
810 return _("Local resource allocation failure");
812 return _("No more records in map database");
814 return _("Can't communicate with portmapper");
816 return _("Can't communicate with ypbind");
818 return _("Can't communicate with ypserv");
820 return _("Local domain name not set");
822 return _("NIS map database is bad");
824 return _("NIS client/server version mismatch - can't supply service");
826 return _("Permission denied");
828 return _("Database is busy");
830 return _("Unknown NIS error code");
834 ypprot_err (const int code
)
839 return YPERR_SUCCESS
;
857 return YPERR_BADARGS
;
865 ypbinderr_string (const int error
)
872 return _("Internal ypbind error");
873 case YPBIND_ERR_NOSERV
:
874 return _("Domain not bound");
875 case YPBIND_ERR_RESC
:
876 return _("System resource allocation failure");
878 return _("Unknown ypbind error");
886 yp_update (char *domain
, char *map
, unsigned ypop
,
887 char *key
, int keylen
, char *data
, int datalen
)
891 ypupdate_args update_args
;
892 ypdelete_args delete_args
;
895 xdrproc_t xdr_argument
;
899 struct sockaddr saddr
;
900 char servername
[MAXNETNAMELEN
+ 1];
903 if (!domain
|| !map
|| !key
|| (ypop
!= YPOP_DELETE
&& !data
))
904 return YPERR_BADARGS
;
906 args
.update_args
.mapname
= map
;
907 args
.update_args
.key
.yp_buf_len
= keylen
;
908 args
.update_args
.key
.yp_buf_val
= key
;
909 args
.update_args
.datum
.yp_buf_len
= datalen
;
910 args
.update_args
.datum
.yp_buf_val
= data
;
912 if ((r
= yp_master (domain
, map
, &master
)) != 0)
915 if (!host2netname (servername
, master
, domain
))
917 fputs (_("yp_update: cannot convert host to netname\n"), stderr
);
921 if ((clnt
= clnt_create (master
, YPU_PROG
, YPU_VERS
, "tcp")) == NULL
)
923 clnt_pcreateerror ("yp_update: clnt_create");
927 if (!clnt_control (clnt
, CLGET_SERVER_ADDR
, (char *) &saddr
))
929 fputs (_("yp_update: cannot get server address\n"), stderr
);
938 xdr_argument
= (xdrproc_t
) xdr_ypupdate_args
;
941 xdr_argument
= (xdrproc_t
) xdr_ypdelete_args
;
944 return YPERR_BADARGS
;
948 clnt
->cl_auth
= authdes_create (servername
, WINDOW
, &saddr
, NULL
);
950 if (clnt
->cl_auth
== NULL
)
951 clnt
->cl_auth
= authunix_create_default ();
954 r
= clnt_call (clnt
, ypop
, xdr_argument
, (caddr_t
) &args
,
955 (xdrproc_t
) xdr_u_int
, (caddr_t
) &res
, RPCTIMEOUT
);
957 if (r
== RPC_AUTHERROR
)
959 if (clnt
->cl_auth
->ah_cred
.oa_flavor
== AUTH_DES
)
961 clnt
->cl_auth
= authunix_create_default ();
967 if (r
!= RPC_SUCCESS
)
969 clnt_perror (clnt
, "yp_update: clnt_call");