]>
Commit | Line | Data |
---|---|---|
8ccf22f9 | 1 | /* Copyright (C) 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008 |
509230ca | 2 | Free Software Foundation, Inc. |
6259ec0d | 3 | This file is part of the GNU C Library. |
b85697f6 | 4 | Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. |
6259ec0d UD |
5 | |
6 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
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. | |
6259ec0d UD |
10 | |
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 | |
41bdb6e2 | 14 | Lesser General Public License for more details. |
6259ec0d | 15 | |
41bdb6e2 AJ |
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 | |
19 | 02111-1307 USA. */ | |
6259ec0d | 20 | |
ee74a442 | 21 | #include <errno.h> |
cc3fa755 | 22 | #include <fcntl.h> |
6259ec0d UD |
23 | #include <string.h> |
24 | #include <unistd.h> | |
4360eafd | 25 | #include <libintl.h> |
26dee9c4 | 26 | #include <rpc/rpc.h> |
f21acc89 | 27 | #include <rpcsvc/nis.h> |
6259ec0d UD |
28 | #include <rpcsvc/yp.h> |
29 | #include <rpcsvc/ypclnt.h> | |
30 | #include <rpcsvc/ypupd.h> | |
8ccf22f9 | 31 | #include <sys/socket.h> |
9931ba24 | 32 | #include <sys/uio.h> |
cc3fa755 | 33 | #include <bits/libc-lock.h> |
6259ec0d | 34 | |
9931ba24 UD |
35 | /* This should only be defined on systems with a BSD compatible ypbind */ |
36 | #ifndef BINDINGDIR | |
37 | # define BINDINGDIR "/var/yp/binding" | |
38 | #endif | |
39 | ||
6259ec0d UD |
40 | struct dom_binding |
41 | { | |
42 | struct dom_binding *dom_pnext; | |
43 | char dom_domain[YPMAXDOMAIN + 1]; | |
44 | struct sockaddr_in dom_server_addr; | |
45 | int dom_socket; | |
46 | CLIENT *dom_client; | |
6259ec0d UD |
47 | }; |
48 | typedef struct dom_binding dom_binding; | |
49 | ||
3218d55b UD |
50 | static const struct timeval RPCTIMEOUT = {25, 0}; |
51 | static const struct timeval UDPTIMEOUT = {5, 0}; | |
66f72f03 | 52 | static int const MAXTRIES = 2; |
2c2efdc1 | 53 | static char ypdomainname[NIS_MAXNAMELEN + 1]; |
6259ec0d | 54 | __libc_lock_define_initialized (static, ypbindlist_lock) |
2c2efdc1 | 55 | static dom_binding *ypbindlist = NULL; |
6259ec0d | 56 | |
f8b87ef0 | 57 | |
57be8a82 | 58 | static void |
4c9ae37b UD |
59 | yp_bind_client_create (const char *domain, dom_binding *ysd, |
60 | struct ypbind_resp *ypbr) | |
57be8a82 RM |
61 | { |
62 | ysd->dom_server_addr.sin_family = AF_INET; | |
63 | memcpy (&ysd->dom_server_addr.sin_port, | |
64 | ypbr->ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, | |
65 | sizeof (ysd->dom_server_addr.sin_port)); | |
66 | memcpy (&ysd->dom_server_addr.sin_addr.s_addr, | |
67 | ypbr->ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, | |
68 | sizeof (ysd->dom_server_addr.sin_addr.s_addr)); | |
69 | strncpy (ysd->dom_domain, domain, YPMAXDOMAIN); | |
70 | ysd->dom_domain[YPMAXDOMAIN] = '\0'; | |
71 | ||
72 | ysd->dom_socket = RPC_ANYSOCK; | |
8ccf22f9 UD |
73 | #ifdef SOCK_CLOEXEC |
74 | # define xflags SOCK_CLOEXEC | |
75 | #else | |
76 | # define xflags 0 | |
77 | #endif | |
78 | ysd->dom_client = __libc_clntudp_bufcreate (&ysd->dom_server_addr, YPPROG, | |
79 | YPVERS, UDPTIMEOUT, | |
80 | &ysd->dom_socket, | |
81 | UDPMSGSIZE, UDPMSGSIZE, | |
82 | xflags); | |
57be8a82 RM |
83 | |
84 | if (ysd->dom_client != NULL) | |
85 | { | |
8ccf22f9 | 86 | #ifndef SOCK_CLOEXEC |
57be8a82 | 87 | /* If the program exits, close the socket */ |
3900770e | 88 | if (fcntl (ysd->dom_socket, F_SETFD, FD_CLOEXEC) == -1) |
57be8a82 | 89 | perror ("fcntl: F_SETFD"); |
8ccf22f9 | 90 | #endif |
57be8a82 RM |
91 | } |
92 | } | |
93 | ||
4c9ae37b | 94 | #if USE_BINDINGDIR |
57be8a82 | 95 | static void |
4c9ae37b | 96 | yp_bind_file (const char *domain, dom_binding *ysd) |
57be8a82 | 97 | { |
3900770e | 98 | char path[sizeof (BINDINGDIR) + strlen (domain) + 3 * sizeof (unsigned) + 3]; |
57be8a82 | 99 | |
3900770e UD |
100 | snprintf (path, sizeof (path), "%s/%s.%u", BINDINGDIR, domain, YPBINDVERS); |
101 | int fd = open (path, O_RDONLY); | |
57be8a82 RM |
102 | if (fd >= 0) |
103 | { | |
3900770e UD |
104 | /* We have a binding file and could save a RPC call. The file |
105 | contains a port number and the YPBIND_RESP record. The port | |
106 | number (16 bits) can be ignored. */ | |
107 | struct ypbind_resp ypbr; | |
57be8a82 | 108 | |
3900770e | 109 | if (pread (fd, &ypbr, sizeof (ypbr), 2) == sizeof (ypbr)) |
4c9ae37b | 110 | yp_bind_client_create (domain, ysd, &ypbr); |
57be8a82 RM |
111 | |
112 | close (fd); | |
113 | } | |
114 | } | |
4c9ae37b | 115 | #endif |
57be8a82 | 116 | |
6259ec0d | 117 | static int |
4c9ae37b | 118 | yp_bind_ypbindprog (const char *domain, dom_binding *ysd) |
6259ec0d UD |
119 | { |
120 | struct sockaddr_in clnt_saddr; | |
121 | struct ypbind_resp ypbr; | |
6259ec0d UD |
122 | int clnt_sock; |
123 | CLIENT *client; | |
57be8a82 | 124 | |
57be8a82 | 125 | clnt_saddr.sin_family = AF_INET; |
2c2efdc1 | 126 | clnt_saddr.sin_port = 0; |
57be8a82 RM |
127 | clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); |
128 | clnt_sock = RPC_ANYSOCK; | |
129 | client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS, | |
130 | &clnt_sock, 0, 0); | |
131 | if (client == NULL) | |
132 | return YPERR_YPBIND; | |
133 | ||
134 | /* Check the port number -- should be < IPPORT_RESERVED. | |
135 | If not, it's possible someone has registered a bogus | |
136 | ypbind with the portmapper and is trying to trick us. */ | |
137 | if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED) | |
138 | { | |
139 | clnt_destroy (client); | |
140 | return YPERR_YPBIND; | |
141 | } | |
142 | ||
143 | if (clnt_call (client, YPBINDPROC_DOMAIN, | |
144 | (xdrproc_t) xdr_domainname, (caddr_t) &domain, | |
145 | (xdrproc_t) xdr_ypbind_resp, | |
146 | (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS) | |
147 | { | |
148 | clnt_destroy (client); | |
149 | return YPERR_YPBIND; | |
150 | } | |
151 | ||
152 | clnt_destroy (client); | |
153 | ||
154 | if (ypbr.ypbind_status != YPBIND_SUCC_VAL) | |
155 | { | |
2c2efdc1 | 156 | fprintf (stderr, "YPBINDPROC_DOMAIN: %s\n", |
57be8a82 RM |
157 | ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error)); |
158 | return YPERR_DOMAIN; | |
159 | } | |
160 | memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr); | |
161 | ||
4c9ae37b | 162 | yp_bind_client_create (domain, ysd, &ypbr); |
57be8a82 RM |
163 | |
164 | return YPERR_SUCCESS; | |
165 | } | |
166 | ||
167 | static int | |
168 | __yp_bind (const char *domain, dom_binding **ypdb) | |
169 | { | |
170 | dom_binding *ysd = NULL; | |
6259ec0d | 171 | int is_new = 0; |
6259ec0d | 172 | |
6ff5bc68 | 173 | if (domain == NULL || domain[0] == '\0') |
6259ec0d UD |
174 | return YPERR_BADARGS; |
175 | ||
345d9208 UD |
176 | ysd = *ypdb; |
177 | while (ysd != NULL) | |
6259ec0d | 178 | { |
345d9208 UD |
179 | if (strcmp (domain, ysd->dom_domain) == 0) |
180 | break; | |
181 | ysd = ysd->dom_pnext; | |
6259ec0d UD |
182 | } |
183 | ||
184 | if (ysd == NULL) | |
185 | { | |
186 | is_new = 1; | |
bd355af0 | 187 | ysd = (dom_binding *) calloc (1, sizeof *ysd); |
54eb84d0 | 188 | if (__builtin_expect (ysd == NULL, 0)) |
3b965a7d | 189 | return YPERR_RESRC; |
6259ec0d UD |
190 | } |
191 | ||
9931ba24 | 192 | #if USE_BINDINGDIR |
3900770e | 193 | /* Try binding dir at first if we have no binding */ |
57be8a82 | 194 | if (ysd->dom_client == NULL) |
3900770e | 195 | yp_bind_file (domain, ysd); |
9931ba24 UD |
196 | #endif /* USE_BINDINGDIR */ |
197 | ||
b85697f6 UD |
198 | if (ysd->dom_client == NULL) |
199 | { | |
4c9ae37b | 200 | int retval = yp_bind_ypbindprog (domain, ysd); |
57be8a82 | 201 | if (retval != YPERR_SUCCESS) |
b85697f6 | 202 | { |
b85697f6 UD |
203 | if (is_new) |
204 | free (ysd); | |
57be8a82 | 205 | return retval; |
b85697f6 | 206 | } |
6259ec0d | 207 | } |
6259ec0d | 208 | |
b85697f6 UD |
209 | if (ysd->dom_client == NULL) |
210 | { | |
211 | if (is_new) | |
212 | free (ysd); | |
213 | return YPERR_YPSERV; | |
214 | } | |
6259ec0d | 215 | |
47ae3942 | 216 | if (is_new) |
6259ec0d | 217 | { |
345d9208 UD |
218 | ysd->dom_pnext = *ypdb; |
219 | *ypdb = ysd; | |
6259ec0d UD |
220 | } |
221 | ||
6259ec0d UD |
222 | return YPERR_SUCCESS; |
223 | } | |
224 | ||
225 | static void | |
226 | __yp_unbind (dom_binding *ydb) | |
227 | { | |
228 | clnt_destroy (ydb->dom_client); | |
345d9208 | 229 | free (ydb); |
b85697f6 UD |
230 | } |
231 | ||
232 | int | |
233 | yp_bind (const char *indomain) | |
234 | { | |
235 | int status; | |
236 | ||
237 | __libc_lock_lock (ypbindlist_lock); | |
238 | ||
2c2efdc1 | 239 | status = __yp_bind (indomain, &ypbindlist); |
b85697f6 UD |
240 | |
241 | __libc_lock_unlock (ypbindlist_lock); | |
242 | ||
243 | return status; | |
244 | } | |
7440c23e | 245 | libnsl_hidden_def (yp_bind) |
b85697f6 UD |
246 | |
247 | static void | |
248 | yp_unbind_locked (const char *indomain) | |
249 | { | |
250 | dom_binding *ydbptr, *ydbptr2; | |
251 | ||
252 | ydbptr2 = NULL; | |
2c2efdc1 | 253 | ydbptr = ypbindlist; |
b85697f6 UD |
254 | |
255 | while (ydbptr != NULL) | |
256 | { | |
257 | if (strcmp (ydbptr->dom_domain, indomain) == 0) | |
258 | { | |
259 | dom_binding *work; | |
260 | ||
261 | work = ydbptr; | |
262 | if (ydbptr2 == NULL) | |
2c2efdc1 | 263 | ypbindlist = ypbindlist->dom_pnext; |
b85697f6 UD |
264 | else |
265 | ydbptr2 = ydbptr->dom_pnext; | |
266 | __yp_unbind (work); | |
b85697f6 UD |
267 | break; |
268 | } | |
269 | ydbptr2 = ydbptr; | |
270 | ydbptr = ydbptr->dom_pnext; | |
271 | } | |
272 | } | |
273 | ||
274 | void | |
275 | yp_unbind (const char *indomain) | |
276 | { | |
277 | __libc_lock_lock (ypbindlist_lock); | |
278 | ||
279 | yp_unbind_locked (indomain); | |
280 | ||
281 | __libc_lock_unlock (ypbindlist_lock); | |
282 | ||
283 | return; | |
6259ec0d UD |
284 | } |
285 | ||
57be8a82 RM |
286 | static int |
287 | __ypclnt_call (const char *domain, u_long prog, xdrproc_t xargs, | |
288 | caddr_t req, xdrproc_t xres, caddr_t resp, dom_binding **ydb, | |
289 | int print_error) | |
290 | { | |
291 | enum clnt_stat result; | |
292 | ||
293 | result = clnt_call ((*ydb)->dom_client, prog, | |
294 | xargs, req, xres, resp, RPCTIMEOUT); | |
295 | ||
296 | if (result != RPC_SUCCESS) | |
297 | { | |
298 | /* We don't print an error message, if we try our old, | |
299 | cached data. Only print this for data, which should work. */ | |
300 | if (print_error) | |
301 | clnt_perror ((*ydb)->dom_client, "do_ypcall: clnt_call"); | |
302 | ||
303 | return YPERR_RPC; | |
304 | } | |
305 | ||
306 | return YPERR_SUCCESS; | |
307 | } | |
308 | ||
6259ec0d UD |
309 | static int |
310 | do_ypcall (const char *domain, u_long prog, xdrproc_t xargs, | |
311 | caddr_t req, xdrproc_t xres, caddr_t resp) | |
312 | { | |
57be8a82 RM |
313 | dom_binding *ydb; |
314 | int status; | |
a788b6c2 | 315 | int saved_errno = errno; |
6259ec0d | 316 | |
d111572f | 317 | status = YPERR_YPERR; |
6259ec0d | 318 | |
cc3fa755 | 319 | __libc_lock_lock (ypbindlist_lock); |
2c2efdc1 | 320 | ydb = ypbindlist; |
9435d38c | 321 | while (ydb != NULL) |
6259ec0d | 322 | { |
9435d38c | 323 | if (strcmp (domain, ydb->dom_domain) == 0) |
57be8a82 RM |
324 | { |
325 | if (__yp_bind (domain, &ydb) == 0) | |
326 | { | |
327 | /* Call server, print no error message, do not unbind. */ | |
328 | status = __ypclnt_call (domain, prog, xargs, req, xres, | |
329 | resp, &ydb, 0); | |
330 | if (status == YPERR_SUCCESS) | |
331 | { | |
9435d38c | 332 | __libc_lock_unlock (ypbindlist_lock); |
57be8a82 RM |
333 | __set_errno (saved_errno); |
334 | return status; | |
335 | } | |
336 | } | |
337 | /* We use ypbindlist, and the old cached data is | |
338 | invalid. unbind now and create a new binding */ | |
339 | yp_unbind_locked (domain); | |
9435d38c UD |
340 | |
341 | break; | |
57be8a82 | 342 | } |
9435d38c | 343 | ydb = ydb->dom_pnext; |
cc3fa755 | 344 | } |
4c9ae37b | 345 | __libc_lock_unlock (ypbindlist_lock); |
6259ec0d | 346 | |
57be8a82 RM |
347 | /* First try with cached data failed. Now try to get |
348 | current data from the system. */ | |
349 | ydb = NULL; | |
350 | if (__yp_bind (domain, &ydb) == 0) | |
cc3fa755 | 351 | { |
57be8a82 RM |
352 | status = __ypclnt_call (domain, prog, xargs, req, xres, |
353 | resp, &ydb, 1); | |
354 | __yp_unbind (ydb); | |
355 | } | |
6259ec0d | 356 | |
57be8a82 RM |
357 | #if USE_BINDINGDIR |
358 | /* If we support binding dir data, we have a third chance: | |
359 | Ask ypbind. */ | |
360 | if (status != YPERR_SUCCESS) | |
361 | { | |
362 | ydb = calloc (1, sizeof (dom_binding)); | |
2c2efdc1 | 363 | if (ydb != NULL && yp_bind_ypbindprog (domain, ydb) == YPERR_SUCCESS) |
6259ec0d | 364 | { |
57be8a82 RM |
365 | status = __ypclnt_call (domain, prog, xargs, req, xres, |
366 | resp, &ydb, 1); | |
367 | __yp_unbind (ydb); | |
6259ec0d | 368 | } |
d111572f | 369 | else |
57be8a82 | 370 | free (ydb); |
6259ec0d | 371 | } |
57be8a82 | 372 | #endif |
6259ec0d | 373 | |
a788b6c2 UD |
374 | __set_errno (saved_errno); |
375 | ||
d111572f | 376 | return status; |
6259ec0d UD |
377 | } |
378 | ||
2c2efdc1 UD |
379 | /* Like do_ypcall, but translate the status value if necessary. */ |
380 | static int | |
381 | do_ypcall_tr (const char *domain, u_long prog, xdrproc_t xargs, | |
382 | caddr_t req, xdrproc_t xres, caddr_t resp) | |
383 | { | |
384 | int status = do_ypcall (domain, prog, xargs, req, xres, resp); | |
385 | if (status == YPERR_SUCCESS) | |
386 | /* We cast to ypresp_val although the pointer could also be of | |
387 | type ypresp_key_val or ypresp_master or ypresp_order or | |
388 | ypresp_maplist. But the stat element is in a common prefix so | |
389 | this does not matter. */ | |
390 | status = ypprot_err (((struct ypresp_val *) resp)->stat); | |
391 | return status; | |
392 | } | |
393 | ||
6259ec0d UD |
394 | |
395 | __libc_lock_define_initialized (static, domainname_lock) | |
396 | ||
397 | int | |
398 | yp_get_default_domain (char **outdomain) | |
399 | { | |
400 | int result = YPERR_SUCCESS;; | |
401 | *outdomain = NULL; | |
402 | ||
403 | __libc_lock_lock (domainname_lock); | |
404 | ||
2c2efdc1 | 405 | if (ypdomainname[0] == '\0') |
6259ec0d | 406 | { |
2c2efdc1 | 407 | if (getdomainname (ypdomainname, NIS_MAXNAMELEN)) |
6259ec0d | 408 | result = YPERR_NODOM; |
2c2efdc1 | 409 | else if (strcmp (ypdomainname, "(none)") == 0) |
ee74a442 | 410 | { |
b85697f6 | 411 | /* If domainname is not set, some systems will return "(none)" */ |
2c2efdc1 | 412 | ypdomainname[0] = '\0'; |
ee74a442 UD |
413 | result = YPERR_NODOM; |
414 | } | |
6259ec0d | 415 | else |
2c2efdc1 | 416 | *outdomain = ypdomainname; |
6259ec0d UD |
417 | } |
418 | else | |
2c2efdc1 | 419 | *outdomain = ypdomainname; |
6259ec0d UD |
420 | |
421 | __libc_lock_unlock (domainname_lock); | |
422 | ||
423 | return result; | |
424 | } | |
7440c23e | 425 | libnsl_hidden_def (yp_get_default_domain) |
6259ec0d UD |
426 | |
427 | int | |
428 | __yp_check (char **domain) | |
429 | { | |
430 | char *unused; | |
431 | ||
2c2efdc1 | 432 | if (ypdomainname[0] == '\0') |
6259ec0d UD |
433 | if (yp_get_default_domain (&unused)) |
434 | return 0; | |
6259ec0d UD |
435 | |
436 | if (domain) | |
2c2efdc1 | 437 | *domain = ypdomainname; |
6259ec0d | 438 | |
2c2efdc1 | 439 | if (yp_bind (ypdomainname) == 0) |
6259ec0d UD |
440 | return 1; |
441 | return 0; | |
442 | } | |
443 | ||
444 | int | |
445 | yp_match (const char *indomain, const char *inmap, const char *inkey, | |
446 | const int inkeylen, char **outval, int *outvallen) | |
447 | { | |
448 | ypreq_key req; | |
449 | ypresp_val resp; | |
d111572f | 450 | enum clnt_stat result; |
6259ec0d UD |
451 | |
452 | if (indomain == NULL || indomain[0] == '\0' || | |
453 | inmap == NULL || inmap[0] == '\0' || | |
454 | inkey == NULL || inkey[0] == '\0' || inkeylen <= 0) | |
455 | return YPERR_BADARGS; | |
456 | ||
68dbb3a6 UD |
457 | req.domain = (char *) indomain; |
458 | req.map = (char *) inmap; | |
459 | req.key.keydat_val = (char *) inkey; | |
6259ec0d UD |
460 | req.key.keydat_len = inkeylen; |
461 | ||
462 | *outval = NULL; | |
463 | *outvallen = 0; | |
464 | memset (&resp, '\0', sizeof (resp)); | |
465 | ||
2c2efdc1 UD |
466 | result = do_ypcall_tr (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key, |
467 | (caddr_t) &req, (xdrproc_t) xdr_ypresp_val, | |
468 | (caddr_t) &resp); | |
6259ec0d | 469 | |
4bca4c17 UD |
470 | if (result != YPERR_SUCCESS) |
471 | return result; | |
6259ec0d UD |
472 | |
473 | *outvallen = resp.val.valdat_len; | |
474 | *outval = malloc (*outvallen + 1); | |
2c2efdc1 UD |
475 | int status = YPERR_RESRC; |
476 | if (__builtin_expect (*outval != NULL, 1)) | |
477 | { | |
478 | memcpy (*outval, resp.val.valdat_val, *outvallen); | |
479 | (*outval)[*outvallen] = '\0'; | |
480 | status = YPERR_SUCCESS; | |
481 | } | |
6259ec0d UD |
482 | |
483 | xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp); | |
484 | ||
2c2efdc1 | 485 | return status; |
6259ec0d UD |
486 | } |
487 | ||
488 | int | |
489 | yp_first (const char *indomain, const char *inmap, char **outkey, | |
490 | int *outkeylen, char **outval, int *outvallen) | |
491 | { | |
492 | ypreq_nokey req; | |
493 | ypresp_key_val resp; | |
d111572f | 494 | enum clnt_stat result; |
6259ec0d UD |
495 | |
496 | if (indomain == NULL || indomain[0] == '\0' || | |
497 | inmap == NULL || inmap[0] == '\0') | |
498 | return YPERR_BADARGS; | |
499 | ||
68dbb3a6 UD |
500 | req.domain = (char *) indomain; |
501 | req.map = (char *) inmap; | |
6259ec0d UD |
502 | |
503 | *outkey = *outval = NULL; | |
504 | *outkeylen = *outvallen = 0; | |
505 | memset (&resp, '\0', sizeof (resp)); | |
506 | ||
507 | result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey, | |
2c2efdc1 UD |
508 | (caddr_t) &req, (xdrproc_t) xdr_ypresp_key_val, |
509 | (caddr_t) &resp); | |
6259ec0d UD |
510 | |
511 | if (result != RPC_SUCCESS) | |
d111572f | 512 | return YPERR_RPC; |
6259ec0d UD |
513 | if (resp.stat != YP_TRUE) |
514 | return ypprot_err (resp.stat); | |
515 | ||
2c2efdc1 UD |
516 | int status; |
517 | if (__builtin_expect ((*outkey = malloc (resp.key.keydat_len + 1)) != NULL | |
518 | && (*outval = malloc (resp.val.valdat_len | |
519 | + 1)) != NULL, 1)) | |
520 | { | |
521 | *outkeylen = resp.key.keydat_len; | |
522 | memcpy (*outkey, resp.key.keydat_val, *outkeylen); | |
523 | (*outkey)[*outkeylen] = '\0'; | |
524 | ||
525 | *outvallen = resp.val.valdat_len; | |
526 | memcpy (*outval, resp.val.valdat_val, *outvallen); | |
527 | (*outval)[*outvallen] = '\0'; | |
528 | ||
529 | status = YPERR_SUCCESS; | |
530 | } | |
531 | else | |
532 | { | |
533 | free (*outkey); | |
534 | status = YPERR_RESRC; | |
535 | } | |
6259ec0d UD |
536 | |
537 | xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp); | |
538 | ||
2c2efdc1 | 539 | return status; |
6259ec0d UD |
540 | } |
541 | ||
542 | int | |
543 | yp_next (const char *indomain, const char *inmap, const char *inkey, | |
544 | const int inkeylen, char **outkey, int *outkeylen, char **outval, | |
545 | int *outvallen) | |
546 | { | |
547 | ypreq_key req; | |
548 | ypresp_key_val resp; | |
d111572f | 549 | enum clnt_stat result; |
6259ec0d UD |
550 | |
551 | if (indomain == NULL || indomain[0] == '\0' || | |
552 | inmap == NULL || inmap[0] == '\0' || | |
553 | inkeylen <= 0 || inkey == NULL || inkey[0] == '\0') | |
554 | return YPERR_BADARGS; | |
555 | ||
68dbb3a6 UD |
556 | req.domain = (char *) indomain; |
557 | req.map = (char *) inmap; | |
558 | req.key.keydat_val = (char *) inkey; | |
6259ec0d UD |
559 | req.key.keydat_len = inkeylen; |
560 | ||
561 | *outkey = *outval = NULL; | |
562 | *outkeylen = *outvallen = 0; | |
563 | memset (&resp, '\0', sizeof (resp)); | |
564 | ||
2c2efdc1 UD |
565 | result = do_ypcall_tr (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key, |
566 | (caddr_t) &req, (xdrproc_t) xdr_ypresp_key_val, | |
567 | (caddr_t) &resp); | |
6259ec0d | 568 | |
4bca4c17 UD |
569 | if (result != YPERR_SUCCESS) |
570 | return result; | |
6259ec0d | 571 | |
2c2efdc1 UD |
572 | int status; |
573 | if (__builtin_expect ((*outkey = malloc (resp.key.keydat_len + 1)) != NULL | |
574 | && (*outval = malloc (resp.val.valdat_len | |
575 | + 1)) != NULL, 1)) | |
576 | { | |
577 | *outkeylen = resp.key.keydat_len; | |
578 | memcpy (*outkey, resp.key.keydat_val, *outkeylen); | |
579 | (*outkey)[*outkeylen] = '\0'; | |
580 | ||
581 | *outvallen = resp.val.valdat_len; | |
582 | memcpy (*outval, resp.val.valdat_val, *outvallen); | |
583 | (*outval)[*outvallen] = '\0'; | |
584 | ||
585 | status = YPERR_SUCCESS; | |
586 | } | |
587 | else | |
588 | { | |
589 | free (*outkey); | |
590 | status = YPERR_RESRC; | |
591 | } | |
6259ec0d UD |
592 | |
593 | xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp); | |
594 | ||
2c2efdc1 | 595 | return status; |
6259ec0d UD |
596 | } |
597 | ||
598 | int | |
599 | yp_master (const char *indomain, const char *inmap, char **outname) | |
600 | { | |
601 | ypreq_nokey req; | |
602 | ypresp_master resp; | |
d111572f | 603 | enum clnt_stat result; |
6259ec0d UD |
604 | |
605 | if (indomain == NULL || indomain[0] == '\0' || | |
606 | inmap == NULL || inmap[0] == '\0') | |
607 | return YPERR_BADARGS; | |
608 | ||
68dbb3a6 UD |
609 | req.domain = (char *) indomain; |
610 | req.map = (char *) inmap; | |
6259ec0d UD |
611 | |
612 | memset (&resp, '\0', sizeof (ypresp_master)); | |
613 | ||
2c2efdc1 UD |
614 | result = do_ypcall_tr (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey, |
615 | (caddr_t) &req, (xdrproc_t) xdr_ypresp_master, | |
616 | (caddr_t) &resp); | |
6259ec0d | 617 | |
4bca4c17 UD |
618 | if (result != YPERR_SUCCESS) |
619 | return result; | |
6259ec0d UD |
620 | |
621 | *outname = strdup (resp.peer); | |
622 | xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp); | |
623 | ||
d111572f | 624 | return *outname == NULL ? YPERR_YPERR : YPERR_SUCCESS; |
6259ec0d | 625 | } |
7440c23e | 626 | libnsl_hidden_def (yp_master) |
6259ec0d UD |
627 | |
628 | int | |
629 | yp_order (const char *indomain, const char *inmap, unsigned int *outorder) | |
630 | { | |
631 | struct ypreq_nokey req; | |
632 | struct ypresp_order resp; | |
d111572f | 633 | enum clnt_stat result; |
6259ec0d UD |
634 | |
635 | if (indomain == NULL || indomain[0] == '\0' || | |
85f90d22 | 636 | inmap == NULL || inmap[0] == '\0') |
6259ec0d UD |
637 | return YPERR_BADARGS; |
638 | ||
68dbb3a6 UD |
639 | req.domain = (char *) indomain; |
640 | req.map = (char *) inmap; | |
6259ec0d UD |
641 | |
642 | memset (&resp, '\0', sizeof (resp)); | |
643 | ||
2c2efdc1 UD |
644 | result = do_ypcall_tr (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey, |
645 | (caddr_t) &req, (xdrproc_t) xdr_ypresp_order, | |
646 | (caddr_t) &resp); | |
6259ec0d | 647 | |
0f749099 | 648 | if (result != YPERR_SUCCESS) |
4bca4c17 | 649 | return result; |
6259ec0d UD |
650 | |
651 | *outorder = resp.ordernum; | |
652 | xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp); | |
653 | ||
2c2efdc1 | 654 | return result; |
6259ec0d UD |
655 | } |
656 | ||
ffdd5e50 UD |
657 | struct ypresp_all_data |
658 | { | |
659 | unsigned long status; | |
660 | void *data; | |
661 | int (*foreach) (int status, char *key, int keylen, | |
662 | char *val, int vallen, char *data); | |
663 | }; | |
6259ec0d UD |
664 | |
665 | static bool_t | |
ffdd5e50 | 666 | __xdr_ypresp_all (XDR *xdrs, struct ypresp_all_data *objp) |
6259ec0d UD |
667 | { |
668 | while (1) | |
669 | { | |
670 | struct ypresp_all resp; | |
671 | ||
672 | memset (&resp, '\0', sizeof (struct ypresp_all)); | |
673 | if (!xdr_ypresp_all (xdrs, &resp)) | |
674 | { | |
675 | xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); | |
ffdd5e50 | 676 | objp->status = YP_YPERR; |
d111572f | 677 | return FALSE; |
6259ec0d UD |
678 | } |
679 | if (resp.more == 0) | |
680 | { | |
681 | xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); | |
ffdd5e50 | 682 | objp->status = YP_NOMORE; |
d111572f | 683 | return TRUE; |
6259ec0d UD |
684 | } |
685 | ||
686 | switch (resp.ypresp_all_u.val.stat) | |
687 | { | |
688 | case YP_TRUE: | |
689 | { | |
690 | char key[resp.ypresp_all_u.val.key.keydat_len + 1]; | |
691 | char val[resp.ypresp_all_u.val.val.valdat_len + 1]; | |
692 | int keylen = resp.ypresp_all_u.val.key.keydat_len; | |
693 | int vallen = resp.ypresp_all_u.val.val.valdat_len; | |
694 | ||
b85697f6 UD |
695 | /* We are not allowed to modify the key and val data. |
696 | But we are allowed to add data behind the buffer, | |
697 | if we don't modify the length. So add an extra NUL | |
698 | character to avoid trouble with broken code. */ | |
ffdd5e50 | 699 | objp->status = YP_TRUE; |
91287339 UD |
700 | *((char *) __mempcpy (key, resp.ypresp_all_u.val.key.keydat_val, |
701 | keylen)) = '\0'; | |
702 | *((char *) __mempcpy (val, resp.ypresp_all_u.val.val.valdat_val, | |
703 | vallen)) = '\0'; | |
6259ec0d | 704 | xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); |
ffdd5e50 UD |
705 | if ((*objp->foreach) (objp->status, key, keylen, |
706 | val, vallen, objp->data)) | |
6259ec0d UD |
707 | return TRUE; |
708 | } | |
709 | break; | |
6259ec0d | 710 | default: |
ffdd5e50 | 711 | objp->status = resp.ypresp_all_u.val.stat; |
6259ec0d | 712 | xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); |
b85697f6 | 713 | /* Sun says we don't need to make this call, but must return |
91287339 | 714 | immediately. Since Solaris makes this call, we will call |
b85697f6 | 715 | the callback function, too. */ |
ffdd5e50 | 716 | (*objp->foreach) (objp->status, NULL, 0, NULL, 0, objp->data); |
6259ec0d UD |
717 | return TRUE; |
718 | } | |
719 | } | |
720 | } | |
721 | ||
722 | int | |
723 | yp_all (const char *indomain, const char *inmap, | |
724 | const struct ypall_callback *incallback) | |
725 | { | |
726 | struct ypreq_nokey req; | |
cc3fa755 | 727 | dom_binding *ydb = NULL; |
d111572f UD |
728 | int try, res; |
729 | enum clnt_stat result; | |
6259ec0d UD |
730 | struct sockaddr_in clnt_sin; |
731 | CLIENT *clnt; | |
ffdd5e50 | 732 | struct ypresp_all_data data; |
6259ec0d | 733 | int clnt_sock; |
a788b6c2 | 734 | int saved_errno = errno; |
6259ec0d | 735 | |
2c2efdc1 UD |
736 | if (indomain == NULL || indomain[0] == '\0' |
737 | || inmap == NULL || inmap[0] == '\0') | |
6259ec0d UD |
738 | return YPERR_BADARGS; |
739 | ||
740 | try = 0; | |
d111572f | 741 | res = YPERR_YPERR; |
6259ec0d | 742 | |
d111572f | 743 | while (try < MAXTRIES && res != YPERR_SUCCESS) |
6259ec0d | 744 | { |
6259ec0d UD |
745 | if (__yp_bind (indomain, &ydb) != 0) |
746 | { | |
a788b6c2 | 747 | __set_errno (saved_errno); |
6259ec0d UD |
748 | return YPERR_DOMAIN; |
749 | } | |
750 | ||
6259ec0d UD |
751 | clnt_sock = RPC_ANYSOCK; |
752 | clnt_sin = ydb->dom_server_addr; | |
753 | clnt_sin.sin_port = 0; | |
85939c79 UD |
754 | |
755 | /* We don't need the UDP connection anymore. */ | |
756 | __yp_unbind (ydb); | |
47ae3942 | 757 | ydb = NULL; |
85939c79 | 758 | |
6259ec0d UD |
759 | clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0); |
760 | if (clnt == NULL) | |
a788b6c2 UD |
761 | { |
762 | __set_errno (saved_errno); | |
763 | return YPERR_PMAP; | |
764 | } | |
68dbb3a6 UD |
765 | req.domain = (char *) indomain; |
766 | req.map = (char *) inmap; | |
6259ec0d | 767 | |
ffdd5e50 UD |
768 | data.foreach = incallback->foreach; |
769 | data.data = (void *) incallback->data; | |
6259ec0d | 770 | |
3e5f5557 UD |
771 | result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey, |
772 | (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all, | |
ffdd5e50 | 773 | (caddr_t) &data, RPCTIMEOUT); |
6259ec0d | 774 | |
2c2efdc1 | 775 | if (__builtin_expect (result != RPC_SUCCESS, 0)) |
6259ec0d | 776 | { |
2c2efdc1 | 777 | /* Print the error message only on the last try. */ |
c891b2df UD |
778 | if (try == MAXTRIES - 1) |
779 | clnt_perror (clnt, "yp_all: clnt_call"); | |
d111572f | 780 | res = YPERR_RPC; |
6259ec0d UD |
781 | } |
782 | else | |
d111572f UD |
783 | res = YPERR_SUCCESS; |
784 | ||
785 | clnt_destroy (clnt); | |
6259ec0d | 786 | |
ffdd5e50 | 787 | if (res == YPERR_SUCCESS && data.status != YP_NOMORE) |
a788b6c2 UD |
788 | { |
789 | __set_errno (saved_errno); | |
ffdd5e50 | 790 | return ypprot_err (data.status); |
a788b6c2 UD |
791 | } |
792 | ++try; | |
6259ec0d UD |
793 | } |
794 | ||
a788b6c2 UD |
795 | __set_errno (saved_errno); |
796 | ||
d111572f | 797 | return res; |
6259ec0d UD |
798 | } |
799 | ||
800 | int | |
2c2efdc1 | 801 | |
6259ec0d UD |
802 | yp_maplist (const char *indomain, struct ypmaplist **outmaplist) |
803 | { | |
804 | struct ypresp_maplist resp; | |
d111572f | 805 | enum clnt_stat result; |
6259ec0d UD |
806 | |
807 | if (indomain == NULL || indomain[0] == '\0') | |
808 | return YPERR_BADARGS; | |
809 | ||
810 | memset (&resp, '\0', sizeof (resp)); | |
811 | ||
2c2efdc1 UD |
812 | result = do_ypcall_tr (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname, |
813 | (caddr_t) &indomain, (xdrproc_t) xdr_ypresp_maplist, | |
814 | (caddr_t) &resp); | |
6259ec0d | 815 | |
2c2efdc1 UD |
816 | if (__builtin_expect (result == YPERR_SUCCESS, 1)) |
817 | { | |
818 | *outmaplist = resp.maps; | |
819 | /* We don't free the list, this will be done by ypserv | |
820 | xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */ | |
821 | } | |
a334319f | 822 | |
2c2efdc1 | 823 | return result; |
6259ec0d UD |
824 | } |
825 | ||
826 | const char * | |
827 | yperr_string (const int error) | |
828 | { | |
2c2efdc1 | 829 | const char *str; |
6259ec0d UD |
830 | switch (error) |
831 | { | |
832 | case YPERR_SUCCESS: | |
3e64e913 | 833 | str = N_("Success"); |
2c2efdc1 | 834 | break; |
6259ec0d | 835 | case YPERR_BADARGS: |
3e64e913 | 836 | str = N_("Request arguments bad"); |
2c2efdc1 | 837 | break; |
6259ec0d | 838 | case YPERR_RPC: |
3e64e913 | 839 | str = N_("RPC failure on NIS operation"); |
2c2efdc1 | 840 | break; |
6259ec0d | 841 | case YPERR_DOMAIN: |
3e64e913 | 842 | str = N_("Can't bind to server which serves this domain"); |
2c2efdc1 | 843 | break; |
6259ec0d | 844 | case YPERR_MAP: |
3e64e913 | 845 | str = N_("No such map in server's domain"); |
2c2efdc1 | 846 | break; |
6259ec0d | 847 | case YPERR_KEY: |
3e64e913 | 848 | str = N_("No such key in map"); |
2c2efdc1 | 849 | break; |
6259ec0d | 850 | case YPERR_YPERR: |
3e64e913 | 851 | str = N_("Internal NIS error"); |
2c2efdc1 | 852 | break; |
6259ec0d | 853 | case YPERR_RESRC: |
3e64e913 | 854 | str = N_("Local resource allocation failure"); |
2c2efdc1 | 855 | break; |
6259ec0d | 856 | case YPERR_NOMORE: |
3e64e913 | 857 | str = N_("No more records in map database"); |
2c2efdc1 | 858 | break; |
6259ec0d | 859 | case YPERR_PMAP: |
3e64e913 | 860 | str = N_("Can't communicate with portmapper"); |
2c2efdc1 | 861 | break; |
6259ec0d | 862 | case YPERR_YPBIND: |
3e64e913 | 863 | str = N_("Can't communicate with ypbind"); |
2c2efdc1 | 864 | break; |
6259ec0d | 865 | case YPERR_YPSERV: |
3e64e913 | 866 | str = N_("Can't communicate with ypserv"); |
2c2efdc1 | 867 | break; |
6259ec0d | 868 | case YPERR_NODOM: |
3e64e913 | 869 | str = N_("Local domain name not set"); |
2c2efdc1 | 870 | break; |
6259ec0d | 871 | case YPERR_BADDB: |
3e64e913 | 872 | str = N_("NIS map database is bad"); |
2c2efdc1 | 873 | break; |
6259ec0d | 874 | case YPERR_VERS: |
3e64e913 | 875 | str = N_("NIS client/server version mismatch - can't supply service"); |
2c2efdc1 | 876 | break; |
6259ec0d | 877 | case YPERR_ACCESS: |
3e64e913 | 878 | str = N_("Permission denied"); |
2c2efdc1 | 879 | break; |
6259ec0d | 880 | case YPERR_BUSY: |
3e64e913 | 881 | str = N_("Database is busy"); |
2c2efdc1 UD |
882 | break; |
883 | default: | |
3e64e913 | 884 | str = N_("Unknown NIS error code"); |
2c2efdc1 | 885 | break; |
6259ec0d | 886 | } |
2c2efdc1 | 887 | return _(str); |
6259ec0d UD |
888 | } |
889 | ||
7440c23e UD |
890 | static const int8_t yp_2_yperr[] = |
891 | { | |
892 | #define YP2YPERR(yp, yperr) [YP_##yp - YP_VERS] = YPERR_##yperr | |
509230ca UD |
893 | YP2YPERR (TRUE, SUCCESS), |
894 | YP2YPERR (NOMORE, NOMORE), | |
895 | YP2YPERR (FALSE, YPERR), | |
896 | YP2YPERR (NOMAP, MAP), | |
897 | YP2YPERR (NODOM, DOMAIN), | |
7440c23e UD |
898 | YP2YPERR (NOKEY, KEY), |
899 | YP2YPERR (BADOP, YPERR), | |
900 | YP2YPERR (BADDB, BADDB), | |
901 | YP2YPERR (YPERR, YPERR), | |
902 | YP2YPERR (BADARGS, BADARGS), | |
903 | YP2YPERR (VERS, VERS) | |
904 | }; | |
6259ec0d UD |
905 | int |
906 | ypprot_err (const int code) | |
907 | { | |
509230ca | 908 | if (code < YP_VERS || code > YP_NOMORE) |
7440c23e | 909 | return YPERR_YPERR; |
a45e13bd | 910 | return yp_2_yperr[code - YP_VERS]; |
6259ec0d | 911 | } |
7440c23e | 912 | libnsl_hidden_def (ypprot_err) |
6259ec0d UD |
913 | |
914 | const char * | |
915 | ypbinderr_string (const int error) | |
916 | { | |
2c2efdc1 | 917 | const char *str; |
6259ec0d UD |
918 | switch (error) |
919 | { | |
920 | case 0: | |
3e64e913 | 921 | str = N_("Success"); |
2c2efdc1 | 922 | break; |
6259ec0d | 923 | case YPBIND_ERR_ERR: |
3e64e913 | 924 | str = N_("Internal ypbind error"); |
2c2efdc1 | 925 | break; |
6259ec0d | 926 | case YPBIND_ERR_NOSERV: |
3e64e913 | 927 | str = N_("Domain not bound"); |
2c2efdc1 | 928 | break; |
6259ec0d | 929 | case YPBIND_ERR_RESC: |
3e64e913 | 930 | str = N_("System resource allocation failure"); |
2c2efdc1 | 931 | break; |
6259ec0d | 932 | default: |
3e64e913 | 933 | str = N_("Unknown ypbind error"); |
2c2efdc1 | 934 | break; |
6259ec0d | 935 | } |
2c2efdc1 | 936 | return _(str); |
6259ec0d | 937 | } |
7440c23e | 938 | libnsl_hidden_def (ypbinderr_string) |
6259ec0d UD |
939 | |
940 | #define WINDOW 60 | |
941 | ||
942 | int | |
943 | yp_update (char *domain, char *map, unsigned ypop, | |
944 | char *key, int keylen, char *data, int datalen) | |
945 | { | |
6259ec0d UD |
946 | union |
947 | { | |
948 | ypupdate_args update_args; | |
949 | ypdelete_args delete_args; | |
950 | } | |
951 | args; | |
952 | xdrproc_t xdr_argument; | |
953 | unsigned res = 0; | |
954 | CLIENT *clnt; | |
955 | char *master; | |
956 | struct sockaddr saddr; | |
957 | char servername[MAXNETNAMELEN + 1]; | |
958 | int r; | |
959 | ||
960 | if (!domain || !map || !key || (ypop != YPOP_DELETE && !data)) | |
961 | return YPERR_BADARGS; | |
962 | ||
963 | args.update_args.mapname = map; | |
964 | args.update_args.key.yp_buf_len = keylen; | |
965 | args.update_args.key.yp_buf_val = key; | |
966 | args.update_args.datum.yp_buf_len = datalen; | |
967 | args.update_args.datum.yp_buf_val = data; | |
968 | ||
0292b0dd | 969 | if ((r = yp_master (domain, map, &master)) != YPERR_SUCCESS) |
6259ec0d UD |
970 | return r; |
971 | ||
972 | if (!host2netname (servername, master, domain)) | |
973 | { | |
974 | fputs (_("yp_update: cannot convert host to netname\n"), stderr); | |
0292b0dd | 975 | free (master); |
6259ec0d UD |
976 | return YPERR_YPERR; |
977 | } | |
978 | ||
0292b0dd UD |
979 | clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp"); |
980 | ||
981 | /* We do not need the string anymore. */ | |
982 | free (master); | |
983 | ||
984 | if (clnt == NULL) | |
6259ec0d UD |
985 | { |
986 | clnt_pcreateerror ("yp_update: clnt_create"); | |
987 | return YPERR_RPC; | |
988 | } | |
989 | ||
990 | if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr)) | |
991 | { | |
992 | fputs (_("yp_update: cannot get server address\n"), stderr); | |
993 | return YPERR_RPC; | |
994 | } | |
995 | ||
996 | switch (ypop) | |
997 | { | |
998 | case YPOP_CHANGE: | |
999 | case YPOP_INSERT: | |
1000 | case YPOP_STORE: | |
1001 | xdr_argument = (xdrproc_t) xdr_ypupdate_args; | |
1002 | break; | |
1003 | case YPOP_DELETE: | |
1004 | xdr_argument = (xdrproc_t) xdr_ypdelete_args; | |
1005 | break; | |
1006 | default: | |
1007 | return YPERR_BADARGS; | |
1008 | break; | |
1009 | } | |
1010 | ||
1011 | clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL); | |
1012 | ||
1013 | if (clnt->cl_auth == NULL) | |
1014 | clnt->cl_auth = authunix_create_default (); | |
1015 | ||
1016 | again: | |
26dee9c4 | 1017 | r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args, |
cc3fa755 | 1018 | (xdrproc_t) xdr_u_int, (caddr_t) &res, RPCTIMEOUT); |
6259ec0d UD |
1019 | |
1020 | if (r == RPC_AUTHERROR) | |
1021 | { | |
1022 | if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES) | |
1023 | { | |
e975f14e | 1024 | auth_destroy (clnt->cl_auth); |
6259ec0d UD |
1025 | clnt->cl_auth = authunix_create_default (); |
1026 | goto again; | |
1027 | } | |
1028 | else | |
1029 | return YPERR_ACCESS; | |
1030 | } | |
1031 | if (r != RPC_SUCCESS) | |
1032 | { | |
1033 | clnt_perror (clnt, "yp_update: clnt_call"); | |
1034 | return YPERR_RPC; | |
1035 | } | |
1036 | return res; | |
6259ec0d | 1037 | } |