]> git.ipfire.org Git - thirdparty/glibc.git/blame - nis/nis_call.c
Update.
[thirdparty/glibc.git] / nis / nis_call.c
CommitLineData
ac9f45cf 1/* Copyright (C) 1997, 1998 Free Software Foundation, Inc.
e61abf83
UD
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
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 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
19
36a8586d 20#include <errno.h>
2d7da676 21#include <fcntl.h>
e61abf83
UD
22#include <string.h>
23#include <rpc/rpc.h>
24#include <rpc/auth.h>
25#include <rpcsvc/nis.h>
26#include <sys/socket.h>
27#include <netinet/in.h>
28#include <arpa/inet.h>
91eee4dd
UD
29
30#include "nis_xdr.h"
e61abf83
UD
31#include "nis_intern.h"
32
cc3fa755
UD
33static struct timeval RPCTIMEOUT = {10, 0};
34static struct timeval UDPTIMEOUT = {5, 0};
2d7da676 35
26a60f90
UD
36extern u_short __pmap_getnisport (struct sockaddr_in *address, u_long program,
37 u_long version, u_int protocol);
38
3996f34b 39unsigned long
e61abf83
UD
40inetstr2int (const char *str)
41{
42 char buffer[strlen (str) + 3];
43 size_t buflen;
44 size_t i, j;
45
46 buflen = stpcpy (buffer, str) - buffer;
47
48 j = 0;
49 for (i = 0; i < buflen; ++i)
50 if (buffer[i] == '.')
51 {
52 ++j;
53 if (j == 4)
54 {
55 buffer[i] = '\0';
56 break;
57 }
58 }
59
60 return inet_addr (buffer);
61}
62
2d7da676
UD
63static void
64__bind_destroy (dir_binding *bind)
e61abf83 65{
2d7da676 66 if (bind->clnt != NULL)
e61abf83 67 {
2d7da676
UD
68 if (bind->use_auth)
69 auth_destroy (bind->clnt->cl_auth);
70 clnt_destroy (bind->clnt);
71 }
72 free (bind->server_val);
73 free (bind);
74}
75
76static nis_error
77__bind_next (dir_binding *bind)
78{
3996f34b 79 u_int j;
2d7da676
UD
80
81 if (bind->clnt != NULL)
82 {
83 if (bind->use_auth)
84 auth_destroy (bind->clnt->cl_auth);
85 clnt_destroy (bind->clnt);
86 bind->clnt = NULL;
87 }
3996f34b
UD
88
89 if (bind->trys >= bind->server_len)
90 return NIS_FAIL;
91
92 for (j = bind->current_ep + 1;
93 j < bind->server_val[bind->server_used].ep.ep_len; ++j)
94 if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].family,
95 "inet") == 0)
96 if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].proto,
97 "-") == 0)
98 {
99 bind->current_ep = j;
100 return NIS_SUCCESS;
101 }
102
103 ++bind->trys;
104 ++bind->server_used;
105 if (bind->server_used >= bind->server_len)
106 bind->server_used = 0;
107
650425ce 108 for (j = 0; j < bind->server_val[bind->server_used].ep.ep_len; ++j)
3996f34b
UD
109 if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].family,
110 "inet") == 0)
111 if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].proto,
112 "-") == 0)
113 {
114 bind->current_ep = j;
115 return NIS_SUCCESS;
116 }
117
118 return NIS_FAIL;
2d7da676
UD
119}
120
121static nis_error
122__bind_connect (dir_binding *dbp)
123{
124 struct sockaddr_in check;
125 nis_server *serv;
126 int checklen;
2d7da676
UD
127
128 if (dbp == NULL)
129 return NIS_FAIL;
130
131 serv = &dbp->server_val[dbp->server_used];
132
133 memset (&dbp->addr, '\0', sizeof (dbp->addr));
134 dbp->addr.sin_family = AF_INET;
3996f34b
UD
135
136 dbp->addr.sin_addr.s_addr =
137 inetstr2int (serv->ep.ep_val[dbp->current_ep].uaddr);
138
2d7da676
UD
139 if (dbp->addr.sin_addr.s_addr == 0)
140 return NIS_FAIL;
141
26a60f90
UD
142 /* Check, if the host is online and rpc.nisd is running. Much faster
143 then the clnt*_create functions: */
144 if (__pmap_getnisport (&dbp->addr, NIS_PROG, NIS_VERSION, IPPROTO_UDP) == 0)
145 return NIS_RPCERROR;
146
2d7da676
UD
147 dbp->socket = RPC_ANYSOCK;
148 if (dbp->use_udp)
149 dbp->clnt = clntudp_create (&dbp->addr, NIS_PROG, NIS_VERSION,
cc3fa755 150 UDPTIMEOUT, &dbp->socket);
2d7da676
UD
151 else
152 dbp->clnt = clnttcp_create (&dbp->addr, NIS_PROG, NIS_VERSION,
153 &dbp->socket, 0, 0);
3996f34b 154
2d7da676
UD
155 if (dbp->clnt == NULL)
156 return NIS_RPCERROR;
3996f34b 157
cc3fa755 158 clnt_control (dbp->clnt, CLSET_TIMEOUT, (caddr_t)&RPCTIMEOUT);
2d7da676
UD
159 /* If the program exists, close the socket */
160 if (fcntl (dbp->socket, F_SETFD, 1) == -1)
161 perror (_("fcntl: F_SETFD"));
3996f34b 162
2d7da676
UD
163 if (dbp->use_auth)
164 {
26a60f90 165 if (serv->key_type == NIS_PK_DH && key_secretkey_is_set ())
e61abf83 166 {
2d7da676
UD
167 char netname[MAXNETNAMELEN+1];
168 char *p;
3996f34b 169
2d7da676
UD
170 p = stpcpy (netname, "unix.");
171 strncpy (p, serv->name,MAXNETNAMELEN-5);
172 netname[MAXNETNAMELEN] = '\0';
173 p = strchr (netname, '.');
174 *p = '@';
175 dbp->clnt->cl_auth =
176 authdes_pk_create (netname, &serv->pkey, 300, NULL, NULL);
177 if (!dbp->clnt->cl_auth)
178 dbp->clnt->cl_auth = authunix_create_default ();
e61abf83 179 }
2d7da676 180 else
2d7da676
UD
181 dbp->clnt->cl_auth = authunix_create_default ();
182 dbp->use_auth = TRUE;
183 }
3996f34b 184
2d7da676
UD
185 /* Get port for sanity checks later */
186 checklen = sizeof (struct sockaddr_in);
187 memset (&check, 0, checklen);
188 if (dbp->use_udp)
189 bind (dbp->socket, (struct sockaddr *)&check, checklen);
190 check.sin_family = AF_INET;
191 if (!getsockname (dbp->socket, (struct sockaddr *)&check, &checklen))
192 dbp->port = check.sin_port;
193
194 dbp->create = time (NULL);
195
196 return NIS_SUCCESS;
197}
26dee9c4 198
2d7da676 199static dir_binding *
ac9f45cf
UD
200__bind_create (const nis_server *serv_val, u_int serv_len, u_long flags,
201 cache2_info *cinfo)
2d7da676
UD
202{
203 dir_binding *dbp;
204 u_int i;
3996f34b 205
2d7da676
UD
206 dbp = calloc (1, sizeof (dir_binding));
207 if (dbp == NULL)
208 return NULL;
3996f34b 209
2d7da676
UD
210 dbp->server_len = serv_len;
211 dbp->server_val = calloc (1, sizeof (nis_server) * serv_len);
212 if (dbp->server_val == NULL)
213 {
214 free (dbp);
215 return NULL;
216 }
3996f34b
UD
217
218 if (flags & USE_DGRAM)
219 dbp->use_udp = TRUE;
220 else
221 dbp->use_udp = FALSE;
222
223 if (flags & NO_AUTHINFO)
224 dbp->use_auth = FALSE;
225 else
226 dbp->use_auth = TRUE;
227
228 if (flags & MASTER_ONLY)
229 dbp->master_only = TRUE;
230 else
231 dbp->master_only = FALSE;
232
26a60f90 233 /* We try the first server */
3996f34b
UD
234 dbp->trys = 1;
235
2d7da676
UD
236 for (i = 0; i < serv_len; ++i)
237 {
238 if (serv_val[i].name != NULL)
239 dbp->server_val[i].name = strdup (serv_val[i].name);
3996f34b 240
2d7da676
UD
241 dbp->server_val[i].ep.ep_len = serv_val[i].ep.ep_len;
242 if (dbp->server_val[i].ep.ep_len > 0)
26dee9c4 243 {
2d7da676 244 unsigned long j;
3996f34b 245
2d7da676
UD
246 dbp->server_val[i].ep.ep_val =
247 malloc (serv_val[i].ep.ep_len * sizeof (endpoint));
248 for (j = 0; j < dbp->server_val[i].ep.ep_len; ++j)
26dee9c4 249 {
2d7da676
UD
250 if (serv_val[i].ep.ep_val[j].uaddr)
251 dbp->server_val[i].ep.ep_val[j].uaddr =
252 strdup (serv_val[i].ep.ep_val[j].uaddr);
253 else
254 dbp->server_val[i].ep.ep_val[j].uaddr = NULL;
255 if (serv_val[i].ep.ep_val[j].family)
256 dbp->server_val[i].ep.ep_val[j].family =
257 strdup (serv_val[i].ep.ep_val[j].family);
258 else
259 dbp->server_val[i].ep.ep_val[j].family = NULL;
260 if (serv_val[i].ep.ep_val[j].proto)
261 dbp->server_val[i].ep.ep_val[j].proto =
262 strdup (serv_val[i].ep.ep_val[j].proto);
263 else
264 dbp->server_val[i].ep.ep_val[j].proto = NULL;
26dee9c4 265 }
26dee9c4 266 }
2d7da676
UD
267 else
268 dbp->server_val[i].ep.ep_val = NULL;
269 dbp->server_val[i].key_type = serv_val[i].key_type;
270 dbp->server_val[i].pkey.n_len = serv_val[i].pkey.n_len;
271 if (serv_val[i].pkey.n_len > 0)
272 {
273 dbp->server_val[i].pkey.n_bytes =
274 malloc (serv_val[i].pkey.n_len);
275 if (dbp->server_val[i].pkey.n_bytes == NULL)
276 return NULL;
277 memcpy (dbp->server_val[i].pkey.n_bytes, serv_val[i].pkey.n_bytes,
278 serv_val[i].pkey.n_len);
279 }
280 else
281 dbp->server_val[i].pkey.n_bytes = NULL;
e61abf83 282 }
2d7da676 283
ac9f45cf
UD
284 dbp->class = -1;
285 if (cinfo != NULL && cinfo->server_used >= 0)
286 {
287 dbp->server_used = cinfo->server_used;
288 dbp->current_ep = cinfo->current_ep;
289 dbp->class = cinfo->class;
290 }
291 else if (__nis_findfastest (dbp) < 1)
3996f34b
UD
292 {
293 __bind_destroy (dbp);
294 return NULL;
295 }
2d7da676
UD
296
297 return dbp;
e61abf83
UD
298}
299
300nis_error
43b0e40f
UD
301__do_niscall2 (const nis_server *server, u_int server_len, u_long prog,
302 xdrproc_t xargs, caddr_t req, xdrproc_t xres, caddr_t resp,
ac9f45cf 303 u_long flags, nis_cb *cb, cache2_info *cinfo)
e61abf83 304{
2d7da676
UD
305 enum clnt_stat result;
306 nis_error retcode;
307 dir_binding *dbp;
308
3996f34b 309 if (flags & MASTER_ONLY)
2d7da676 310 server_len = 1;
3996f34b 311
ac9f45cf
UD
312 dbp = __bind_create (server, server_len, flags, cinfo);
313 if (dbp == NULL)
a5a0310d 314 return NIS_NAMEUNREACHABLE;
2d7da676 315 while (__bind_connect (dbp) != NIS_SUCCESS)
e61abf83 316 {
2d7da676 317 if (__bind_next (dbp) != NIS_SUCCESS)
e61abf83 318 {
2d7da676
UD
319 __bind_destroy (dbp);
320 return NIS_NAMEUNREACHABLE;
e61abf83
UD
321 }
322 }
323
2d7da676 324 do
43b0e40f 325 {
2d7da676 326 again:
cc3fa755 327 result = clnt_call (dbp->clnt, prog, xargs, req, xres, resp, RPCTIMEOUT);
3996f34b 328
43b0e40f
UD
329 if (result != RPC_SUCCESS)
330 {
2d7da676
UD
331 __bind_destroy (dbp);
332 retcode = NIS_RPCERROR;
43b0e40f
UD
333 }
334 else
2d7da676
UD
335 {
336 switch (prog)
337 {
650425ce
UD
338 case NIS_IBLIST:
339 if ((((nis_result *)resp)->status == NIS_CBRESULTS) &&
340 (cb != NULL))
341 {
342 __nis_do_callback(dbp, &((nis_result *)resp)->cookie, cb);
343 break;
344 }
345 /* Yes, this is correct. If we doesn't have to start
346 a callback, look if we have to search another server */
2d7da676
UD
347 case NIS_LOOKUP:
348 case NIS_ADD:
349 case NIS_MODIFY:
350 case NIS_REMOVE:
2d7da676
UD
351 case NIS_IBADD:
352 case NIS_IBMODIFY:
353 case NIS_IBREMOVE:
354 case NIS_IBFIRST:
355 case NIS_IBNEXT:
650425ce
UD
356 if ((((nis_result *)resp)->status == NIS_NOTFOUND) ||
357 (((nis_result *)resp)->status == NIS_NOSUCHNAME) ||
358 (((nis_result *)resp)->status == NIS_NOT_ME))
3996f34b
UD
359 {
360 if (__bind_next (dbp) == NIS_SUCCESS)
650425ce
UD
361 {
362 while (__bind_connect (dbp) != NIS_SUCCESS)
363 {
364 if (__bind_next (dbp) != NIS_SUCCESS)
365 {
366 __bind_destroy (dbp);
367 return NIS_SUCCESS;
368 }
369 }
370 }
371 else
372 break; /* No more servers to search in */
2d7da676 373 goto again;
3996f34b 374 }
a5a0310d 375 break;
2d7da676 376 case NIS_FINDDIRECTORY:
650425ce
UD
377 if ((((fd_result *)resp)->status == NIS_NOTFOUND) ||
378 (((fd_result *)resp)->status == NIS_NOSUCHNAME) ||
379 (((fd_result *)resp)->status == NIS_NOT_ME))
3996f34b
UD
380 {
381 if (__bind_next (dbp) == NIS_SUCCESS)
650425ce
UD
382 {
383 while (__bind_connect (dbp) != NIS_SUCCESS)
384 {
385 if (__bind_next (dbp) != NIS_SUCCESS)
386 {
387 __bind_destroy (dbp);
388 return NIS_SUCCESS;
389 }
390 }
391 }
392 else
393 break; /* No more servers to search in */
2d7da676 394 goto again;
3996f34b 395 }
2d7da676
UD
396 break;
397 case NIS_DUMPLOG: /* log_result */
398 case NIS_DUMP:
650425ce
UD
399 if ((((log_result *)resp)->lr_status == NIS_NOTFOUND) ||
400 (((log_result *)resp)->lr_status == NIS_NOSUCHNAME) ||
401 (((log_result *)resp)->lr_status == NIS_NOT_ME))
3996f34b
UD
402 {
403 if (__bind_next (dbp) == NIS_SUCCESS)
650425ce
UD
404 {
405 while (__bind_connect (dbp) != NIS_SUCCESS)
406 {
407 if (__bind_next (dbp) != NIS_SUCCESS)
408 {
409 __bind_destroy (dbp);
410 return NIS_SUCCESS;
411 }
412 }
413 }
414 else
415 break; /* No more servers to search in */
3996f34b
UD
416 goto again;
417 }
2d7da676 418 break;
2d7da676
UD
419 default:
420 break;
421 }
422 __bind_destroy (dbp);
423 retcode = NIS_SUCCESS;
424 }
43b0e40f 425 }
2d7da676 426 while ((flags & HARD_LOOKUP) && retcode == NIS_RPCERROR);
3996f34b
UD
427
428 return retcode;
43b0e40f
UD
429}
430
431static directory_obj *
3996f34b
UD
432rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags,
433 nis_error *status)
43b0e40f 434{
2d7da676
UD
435 fd_result *fd_res;
436 XDR xdrs;
43b0e40f 437
26a60f90 438 switch (nis_dir_cmp (name, dir->do_name))
43b0e40f
UD
439 {
440 case SAME_NAME:
3996f34b 441 *status = NIS_SUCCESS;
43b0e40f
UD
442 return dir;
443 case NOT_SEQUENTIAL:
444 /* NOT_SEQUENTIAL means, go one up and try it there ! */
445 case HIGHER_NAME:
446 { /* We need data from a parent domain */
447 directory_obj *obj;
448 char ndomain [strlen (name) + 3];
449
450 nis_domain_of_r (dir->do_name, ndomain, sizeof (ndomain));
451
452 /* The root server of our domain is a replica of the parent
453 domain ! (Now I understand why a root server must be a
454 replica of the parent domain) */
2d7da676 455 fd_res = __nis_finddirectory (dir, ndomain);
3996f34b 456 *status = fd_res->status;
2d7da676
UD
457 if (fd_res->status != NIS_SUCCESS)
458 {
26a60f90 459 /* Try the current directory obj, maybe it works */
af6f3906 460 __free_fdresult (fd_res);
26a60f90 461 return dir;
2d7da676 462 }
2d7da676
UD
463 obj = calloc(1, sizeof(directory_obj));
464 xdrmem_create(&xdrs, fd_res->dir_data.dir_data_val,
465 fd_res->dir_data.dir_data_len, XDR_DECODE);
91eee4dd 466 _xdr_directory_obj(&xdrs, obj);
2d7da676 467 xdr_destroy(&xdrs);
dfd2257a 468 __free_fdresult (fd_res);
43b0e40f
UD
469 if (obj != NULL)
470 {
471 /* We have found a NIS+ server serving ndomain, now
472 let us search for "name" */
473 nis_free_directory (dir);
3996f34b 474 return rec_dirsearch (name, obj, flags, status);
43b0e40f
UD
475 }
476 else
477 {
478 /* Ups, very bad. Are we already the root server ? */
479 nis_free_directory (dir);
480 return NULL;
481 }
482 }
2d7da676 483 break;
43b0e40f
UD
484 case LOWER_NAME:
485 {
486 directory_obj *obj;
a53bad16
UD
487 size_t namelen = strlen (name);
488 char leaf [namelen + 3];
489 char domain [namelen + 3];
490 char ndomain [namelen + 3];
714a562f 491 char *cp;
26a60f90
UD
492 u_int run = 0;
493
494 strcpy (domain, name);
3996f34b 495
43b0e40f
UD
496 do
497 {
a53bad16 498 if (domain[0] == '\0')
43b0e40f
UD
499 {
500 nis_free_directory (dir);
501 return NULL;
502 }
503 nis_leaf_of_r (domain, leaf, sizeof (leaf));
504 nis_domain_of_r (domain, ndomain, sizeof (ndomain));
505 strcpy (domain, ndomain);
26a60f90 506 ++run;
43b0e40f
UD
507 }
508 while (nis_dir_cmp (domain, dir->do_name) != SAME_NAME);
26a60f90
UD
509
510 if (run == 1)
511 {
512 /* We have found the directory above. Use it. */
513 return dir;
514 }
515
714a562f
UD
516 cp = strchr (leaf, '\0');
517 *cp++ = '.';
518 strcpy (cp, domain);
3996f34b 519
2d7da676 520 fd_res = __nis_finddirectory (dir, leaf);
3996f34b 521 *status = fd_res->status;
2d7da676 522 if (fd_res->status != NIS_SUCCESS)
43b0e40f 523 {
26a60f90 524 /* Try the current directory object, maybe it works */
af6f3906 525 __free_fdresult (fd_res);
26a60f90 526 return dir;
2d7da676 527 }
2d7da676
UD
528 obj = calloc(1, sizeof(directory_obj));
529 xdrmem_create(&xdrs, fd_res->dir_data.dir_data_val,
530 fd_res->dir_data.dir_data_len, XDR_DECODE);
91eee4dd 531 _xdr_directory_obj(&xdrs, obj);
2d7da676 532 xdr_destroy(&xdrs);
dfd2257a 533 __free_fdresult (fd_res);
2d7da676
UD
534 if (obj != NULL)
535 {
536 /* We have found a NIS+ server serving ndomain, now
537 let us search for "name" */
538 nis_free_directory (dir);
3996f34b 539 return rec_dirsearch (name, obj, flags, status);
43b0e40f
UD
540 }
541 }
2d7da676 542 break;
43b0e40f
UD
543 case BAD_NAME:
544 nis_free_directory (dir);
3996f34b 545 *status = NIS_BADNAME;
43b0e40f
UD
546 return NULL;
547 }
548 nis_free_directory (dir);
3996f34b 549 *status = NIS_FAIL;
43b0e40f
UD
550 return NULL;
551}
552
26a60f90
UD
553/* We try to query the current server for the searched object,
554 maybe he know about it ? */
555static directory_obj *
556first_shoot (const_nis_name name, directory_obj *dir, u_long flags)
557{
558 directory_obj *obj;
559 fd_result *fd_res;
560 XDR xdrs;
561 char domain [strlen (name) + 3];
562
563 if (nis_dir_cmp (name, dir->do_name) == SAME_NAME)
564 return dir;
565
566 nis_domain_of_r (name, domain, sizeof (domain));
567
568 if (nis_dir_cmp (domain, dir->do_name) == SAME_NAME)
569 return dir;
570
571 fd_res = __nis_finddirectory (dir, domain);
572 if (fd_res->status != NIS_SUCCESS)
573 {
574 __free_fdresult (fd_res);
575 return NULL;
576 }
577 obj = calloc(1, sizeof(directory_obj));
578 if (obj == NULL)
579 return NULL;
580 xdrmem_create(&xdrs, fd_res->dir_data.dir_data_val,
581 fd_res->dir_data.dir_data_len, XDR_DECODE);
91eee4dd
UD
582 _xdr_directory_obj (&xdrs, obj);
583 xdr_destroy (&xdrs);
26a60f90
UD
584 __free_fdresult (fd_res);
585 if (obj != NULL)
586 {
587 nis_free_directory (dir);
588 return obj;
589 }
590 return NULL;
591}
592
43b0e40f
UD
593nis_error
594__do_niscall (const_nis_name name, u_long prog, xdrproc_t xargs,
650425ce
UD
595 caddr_t req, xdrproc_t xres, caddr_t resp, u_long flags,
596 nis_cb *cb)
43b0e40f 597{
2d7da676 598 nis_error retcode;
43b0e40f 599 directory_obj *dir = NULL;
2d7da676 600 nis_server *server;
43b0e40f 601 u_int server_len;
ac9f45cf 602 cache2_info cinfo = {-1, -1, -1};
36a8586d 603 int saved_errno = errno;
43b0e40f 604
2d7da676
UD
605 if (name == NULL)
606 return NIS_BADNAME;
43b0e40f 607
ac9f45cf
UD
608 /* Search in local cache. In the moment, we ignore the fastest server */
609 if (!(flags & NO_CACHE))
610 dir = __nis_cache_search (name, flags, &cinfo);
611
2d7da676 612 if (dir == NULL)
43b0e40f 613 {
3996f34b 614 nis_error status;
26a60f90
UD
615 directory_obj *obj;
616
2d7da676
UD
617 dir = readColdStartFile ();
618 if (dir == NULL) /* No /var/nis/NIS_COLD_START->no NIS+ installed */
36a8586d
UD
619 {
620 __set_errno (saved_errno);
621 return NIS_UNAVAIL;
622 }
3996f34b 623
26a60f90
UD
624 /* Try at first, if servers in "dir" know our object */
625 obj = first_shoot (name, dir, flags);
626 if (obj == NULL)
a788b6c2 627 {
26a60f90
UD
628 dir = rec_dirsearch (name, dir, flags, &status);
629 if (dir == NULL)
630 {
631 __set_errno (saved_errno);
632 return status;
633 }
a788b6c2 634 }
26a60f90
UD
635 else
636 dir = obj;
43b0e40f 637 }
43b0e40f 638
3996f34b 639 if (flags & MASTER_ONLY)
2d7da676
UD
640 {
641 server = dir->do_servers.do_servers_val;
642 server_len = 1;
643 }
644 else
645 {
646 server = dir->do_servers.do_servers_val;
647 server_len = dir->do_servers.do_servers_len;
648 }
3996f34b
UD
649
650
2d7da676 651 retcode = __do_niscall2 (server, server_len, prog, xargs, req, xres, resp,
ac9f45cf 652 flags, cb, &cinfo);
3996f34b 653
2d7da676 654 nis_free_directory (dir);
43b0e40f 655
a788b6c2
UD
656 __set_errno (saved_errno);
657
2d7da676 658 return retcode;
e61abf83 659}