]>
Commit | Line | Data |
---|---|---|
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> | |
29 | #include "nis_intern.h" | |
30 | ||
cc3fa755 UD |
31 | static struct timeval RPCTIMEOUT = {10, 0}; |
32 | static struct timeval UDPTIMEOUT = {5, 0}; | |
2d7da676 | 33 | |
3996f34b | 34 | unsigned long |
e61abf83 UD |
35 | inetstr2int (const char *str) |
36 | { | |
37 | char buffer[strlen (str) + 3]; | |
38 | size_t buflen; | |
39 | size_t i, j; | |
40 | ||
41 | buflen = stpcpy (buffer, str) - buffer; | |
42 | ||
43 | j = 0; | |
44 | for (i = 0; i < buflen; ++i) | |
45 | if (buffer[i] == '.') | |
46 | { | |
47 | ++j; | |
48 | if (j == 4) | |
49 | { | |
50 | buffer[i] = '\0'; | |
51 | break; | |
52 | } | |
53 | } | |
54 | ||
55 | return inet_addr (buffer); | |
56 | } | |
57 | ||
2d7da676 UD |
58 | static void |
59 | __bind_destroy (dir_binding *bind) | |
e61abf83 | 60 | { |
2d7da676 | 61 | if (bind->clnt != NULL) |
e61abf83 | 62 | { |
2d7da676 UD |
63 | if (bind->use_auth) |
64 | auth_destroy (bind->clnt->cl_auth); | |
65 | clnt_destroy (bind->clnt); | |
66 | } | |
67 | free (bind->server_val); | |
68 | free (bind); | |
69 | } | |
70 | ||
71 | static nis_error | |
72 | __bind_next (dir_binding *bind) | |
73 | { | |
3996f34b | 74 | u_int j; |
2d7da676 UD |
75 | |
76 | if (bind->clnt != NULL) | |
77 | { | |
78 | if (bind->use_auth) | |
79 | auth_destroy (bind->clnt->cl_auth); | |
80 | clnt_destroy (bind->clnt); | |
81 | bind->clnt = NULL; | |
82 | } | |
3996f34b UD |
83 | |
84 | if (bind->trys >= bind->server_len) | |
85 | return NIS_FAIL; | |
86 | ||
87 | for (j = bind->current_ep + 1; | |
88 | j < bind->server_val[bind->server_used].ep.ep_len; ++j) | |
89 | if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].family, | |
90 | "inet") == 0) | |
91 | if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].proto, | |
92 | "-") == 0) | |
93 | { | |
94 | bind->current_ep = j; | |
95 | return NIS_SUCCESS; | |
96 | } | |
97 | ||
98 | ++bind->trys; | |
99 | ++bind->server_used; | |
100 | if (bind->server_used >= bind->server_len) | |
101 | bind->server_used = 0; | |
102 | ||
650425ce | 103 | for (j = 0; j < bind->server_val[bind->server_used].ep.ep_len; ++j) |
3996f34b UD |
104 | if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].family, |
105 | "inet") == 0) | |
106 | if (strcmp (bind->server_val[bind->server_used].ep.ep_val[j].proto, | |
107 | "-") == 0) | |
108 | { | |
109 | bind->current_ep = j; | |
110 | return NIS_SUCCESS; | |
111 | } | |
112 | ||
113 | return NIS_FAIL; | |
2d7da676 UD |
114 | } |
115 | ||
116 | static nis_error | |
117 | __bind_connect (dir_binding *dbp) | |
118 | { | |
119 | struct sockaddr_in check; | |
120 | nis_server *serv; | |
121 | int checklen; | |
2d7da676 UD |
122 | |
123 | if (dbp == NULL) | |
124 | return NIS_FAIL; | |
125 | ||
126 | serv = &dbp->server_val[dbp->server_used]; | |
127 | ||
128 | memset (&dbp->addr, '\0', sizeof (dbp->addr)); | |
129 | dbp->addr.sin_family = AF_INET; | |
3996f34b UD |
130 | |
131 | dbp->addr.sin_addr.s_addr = | |
132 | inetstr2int (serv->ep.ep_val[dbp->current_ep].uaddr); | |
133 | ||
2d7da676 UD |
134 | if (dbp->addr.sin_addr.s_addr == 0) |
135 | return NIS_FAIL; | |
136 | ||
137 | dbp->socket = RPC_ANYSOCK; | |
138 | if (dbp->use_udp) | |
139 | dbp->clnt = clntudp_create (&dbp->addr, NIS_PROG, NIS_VERSION, | |
cc3fa755 | 140 | UDPTIMEOUT, &dbp->socket); |
2d7da676 UD |
141 | else |
142 | dbp->clnt = clnttcp_create (&dbp->addr, NIS_PROG, NIS_VERSION, | |
143 | &dbp->socket, 0, 0); | |
3996f34b | 144 | |
2d7da676 UD |
145 | if (dbp->clnt == NULL) |
146 | return NIS_RPCERROR; | |
3996f34b | 147 | |
cc3fa755 | 148 | clnt_control (dbp->clnt, CLSET_TIMEOUT, (caddr_t)&RPCTIMEOUT); |
2d7da676 UD |
149 | /* If the program exists, close the socket */ |
150 | if (fcntl (dbp->socket, F_SETFD, 1) == -1) | |
151 | perror (_("fcntl: F_SETFD")); | |
3996f34b | 152 | |
2d7da676 UD |
153 | if (dbp->use_auth) |
154 | { | |
2d7da676 | 155 | if (serv->key_type == NIS_PK_DH) |
e61abf83 | 156 | { |
2d7da676 UD |
157 | char netname[MAXNETNAMELEN+1]; |
158 | char *p; | |
3996f34b | 159 | |
2d7da676 UD |
160 | p = stpcpy (netname, "unix."); |
161 | strncpy (p, serv->name,MAXNETNAMELEN-5); | |
162 | netname[MAXNETNAMELEN] = '\0'; | |
163 | p = strchr (netname, '.'); | |
164 | *p = '@'; | |
165 | dbp->clnt->cl_auth = | |
166 | authdes_pk_create (netname, &serv->pkey, 300, NULL, NULL); | |
167 | if (!dbp->clnt->cl_auth) | |
168 | dbp->clnt->cl_auth = authunix_create_default (); | |
e61abf83 | 169 | } |
2d7da676 | 170 | else |
2d7da676 UD |
171 | dbp->clnt->cl_auth = authunix_create_default (); |
172 | dbp->use_auth = TRUE; | |
173 | } | |
3996f34b | 174 | |
2d7da676 UD |
175 | /* Get port for sanity checks later */ |
176 | checklen = sizeof (struct sockaddr_in); | |
177 | memset (&check, 0, checklen); | |
178 | if (dbp->use_udp) | |
179 | bind (dbp->socket, (struct sockaddr *)&check, checklen); | |
180 | check.sin_family = AF_INET; | |
181 | if (!getsockname (dbp->socket, (struct sockaddr *)&check, &checklen)) | |
182 | dbp->port = check.sin_port; | |
183 | ||
184 | dbp->create = time (NULL); | |
185 | ||
186 | return NIS_SUCCESS; | |
187 | } | |
26dee9c4 | 188 | |
2d7da676 | 189 | static dir_binding * |
ac9f45cf UD |
190 | __bind_create (const nis_server *serv_val, u_int serv_len, u_long flags, |
191 | cache2_info *cinfo) | |
2d7da676 UD |
192 | { |
193 | dir_binding *dbp; | |
194 | u_int i; | |
3996f34b | 195 | |
2d7da676 UD |
196 | dbp = calloc (1, sizeof (dir_binding)); |
197 | if (dbp == NULL) | |
198 | return NULL; | |
3996f34b | 199 | |
2d7da676 UD |
200 | dbp->server_len = serv_len; |
201 | dbp->server_val = calloc (1, sizeof (nis_server) * serv_len); | |
202 | if (dbp->server_val == NULL) | |
203 | { | |
204 | free (dbp); | |
205 | return NULL; | |
206 | } | |
3996f34b UD |
207 | |
208 | if (flags & USE_DGRAM) | |
209 | dbp->use_udp = TRUE; | |
210 | else | |
211 | dbp->use_udp = FALSE; | |
212 | ||
213 | if (flags & NO_AUTHINFO) | |
214 | dbp->use_auth = FALSE; | |
215 | else | |
216 | dbp->use_auth = TRUE; | |
217 | ||
218 | if (flags & MASTER_ONLY) | |
219 | dbp->master_only = TRUE; | |
220 | else | |
221 | dbp->master_only = FALSE; | |
222 | ||
223 | dbp->trys = 1; | |
224 | ||
2d7da676 UD |
225 | for (i = 0; i < serv_len; ++i) |
226 | { | |
227 | if (serv_val[i].name != NULL) | |
228 | dbp->server_val[i].name = strdup (serv_val[i].name); | |
3996f34b | 229 | |
2d7da676 UD |
230 | dbp->server_val[i].ep.ep_len = serv_val[i].ep.ep_len; |
231 | if (dbp->server_val[i].ep.ep_len > 0) | |
26dee9c4 | 232 | { |
2d7da676 | 233 | unsigned long j; |
3996f34b | 234 | |
2d7da676 UD |
235 | dbp->server_val[i].ep.ep_val = |
236 | malloc (serv_val[i].ep.ep_len * sizeof (endpoint)); | |
237 | for (j = 0; j < dbp->server_val[i].ep.ep_len; ++j) | |
26dee9c4 | 238 | { |
2d7da676 UD |
239 | if (serv_val[i].ep.ep_val[j].uaddr) |
240 | dbp->server_val[i].ep.ep_val[j].uaddr = | |
241 | strdup (serv_val[i].ep.ep_val[j].uaddr); | |
242 | else | |
243 | dbp->server_val[i].ep.ep_val[j].uaddr = NULL; | |
244 | if (serv_val[i].ep.ep_val[j].family) | |
245 | dbp->server_val[i].ep.ep_val[j].family = | |
246 | strdup (serv_val[i].ep.ep_val[j].family); | |
247 | else | |
248 | dbp->server_val[i].ep.ep_val[j].family = NULL; | |
249 | if (serv_val[i].ep.ep_val[j].proto) | |
250 | dbp->server_val[i].ep.ep_val[j].proto = | |
251 | strdup (serv_val[i].ep.ep_val[j].proto); | |
252 | else | |
253 | dbp->server_val[i].ep.ep_val[j].proto = NULL; | |
26dee9c4 | 254 | } |
26dee9c4 | 255 | } |
2d7da676 UD |
256 | else |
257 | dbp->server_val[i].ep.ep_val = NULL; | |
258 | dbp->server_val[i].key_type = serv_val[i].key_type; | |
259 | dbp->server_val[i].pkey.n_len = serv_val[i].pkey.n_len; | |
260 | if (serv_val[i].pkey.n_len > 0) | |
261 | { | |
262 | dbp->server_val[i].pkey.n_bytes = | |
263 | malloc (serv_val[i].pkey.n_len); | |
264 | if (dbp->server_val[i].pkey.n_bytes == NULL) | |
265 | return NULL; | |
266 | memcpy (dbp->server_val[i].pkey.n_bytes, serv_val[i].pkey.n_bytes, | |
267 | serv_val[i].pkey.n_len); | |
268 | } | |
269 | else | |
270 | dbp->server_val[i].pkey.n_bytes = NULL; | |
e61abf83 | 271 | } |
2d7da676 | 272 | |
ac9f45cf UD |
273 | dbp->class = -1; |
274 | if (cinfo != NULL && cinfo->server_used >= 0) | |
275 | { | |
276 | dbp->server_used = cinfo->server_used; | |
277 | dbp->current_ep = cinfo->current_ep; | |
278 | dbp->class = cinfo->class; | |
279 | } | |
280 | else if (__nis_findfastest (dbp) < 1) | |
3996f34b UD |
281 | { |
282 | __bind_destroy (dbp); | |
283 | return NULL; | |
284 | } | |
2d7da676 UD |
285 | |
286 | return dbp; | |
e61abf83 UD |
287 | } |
288 | ||
289 | nis_error | |
43b0e40f UD |
290 | __do_niscall2 (const nis_server *server, u_int server_len, u_long prog, |
291 | xdrproc_t xargs, caddr_t req, xdrproc_t xres, caddr_t resp, | |
ac9f45cf | 292 | u_long flags, nis_cb *cb, cache2_info *cinfo) |
e61abf83 | 293 | { |
2d7da676 UD |
294 | enum clnt_stat result; |
295 | nis_error retcode; | |
296 | dir_binding *dbp; | |
297 | ||
3996f34b | 298 | if (flags & MASTER_ONLY) |
2d7da676 | 299 | server_len = 1; |
3996f34b | 300 | |
ac9f45cf UD |
301 | dbp = __bind_create (server, server_len, flags, cinfo); |
302 | if (dbp == NULL) | |
a5a0310d | 303 | return NIS_NAMEUNREACHABLE; |
2d7da676 | 304 | while (__bind_connect (dbp) != NIS_SUCCESS) |
e61abf83 | 305 | { |
2d7da676 | 306 | if (__bind_next (dbp) != NIS_SUCCESS) |
e61abf83 | 307 | { |
2d7da676 UD |
308 | __bind_destroy (dbp); |
309 | return NIS_NAMEUNREACHABLE; | |
e61abf83 UD |
310 | } |
311 | } | |
312 | ||
2d7da676 | 313 | do |
43b0e40f | 314 | { |
2d7da676 | 315 | again: |
cc3fa755 | 316 | result = clnt_call (dbp->clnt, prog, xargs, req, xres, resp, RPCTIMEOUT); |
3996f34b | 317 | |
43b0e40f UD |
318 | if (result != RPC_SUCCESS) |
319 | { | |
2d7da676 UD |
320 | clnt_perror (dbp->clnt, "__do_niscall2: clnt_call"); |
321 | __bind_destroy (dbp); | |
322 | retcode = NIS_RPCERROR; | |
43b0e40f UD |
323 | } |
324 | else | |
2d7da676 UD |
325 | { |
326 | switch (prog) | |
327 | { | |
650425ce UD |
328 | case NIS_IBLIST: |
329 | if ((((nis_result *)resp)->status == NIS_CBRESULTS) && | |
330 | (cb != NULL)) | |
331 | { | |
332 | __nis_do_callback(dbp, &((nis_result *)resp)->cookie, cb); | |
333 | break; | |
334 | } | |
335 | /* Yes, this is correct. If we doesn't have to start | |
336 | a callback, look if we have to search another server */ | |
2d7da676 UD |
337 | case NIS_LOOKUP: |
338 | case NIS_ADD: | |
339 | case NIS_MODIFY: | |
340 | case NIS_REMOVE: | |
2d7da676 UD |
341 | case NIS_IBADD: |
342 | case NIS_IBMODIFY: | |
343 | case NIS_IBREMOVE: | |
344 | case NIS_IBFIRST: | |
345 | case NIS_IBNEXT: | |
650425ce UD |
346 | if ((((nis_result *)resp)->status == NIS_NOTFOUND) || |
347 | (((nis_result *)resp)->status == NIS_NOSUCHNAME) || | |
348 | (((nis_result *)resp)->status == NIS_NOT_ME)) | |
3996f34b UD |
349 | { |
350 | if (__bind_next (dbp) == NIS_SUCCESS) | |
650425ce UD |
351 | { |
352 | while (__bind_connect (dbp) != NIS_SUCCESS) | |
353 | { | |
354 | if (__bind_next (dbp) != NIS_SUCCESS) | |
355 | { | |
356 | __bind_destroy (dbp); | |
357 | return NIS_SUCCESS; | |
358 | } | |
359 | } | |
360 | } | |
361 | else | |
362 | break; /* No more servers to search in */ | |
2d7da676 | 363 | goto again; |
3996f34b | 364 | } |
a5a0310d | 365 | break; |
2d7da676 | 366 | case NIS_FINDDIRECTORY: |
650425ce UD |
367 | if ((((fd_result *)resp)->status == NIS_NOTFOUND) || |
368 | (((fd_result *)resp)->status == NIS_NOSUCHNAME) || | |
369 | (((fd_result *)resp)->status == NIS_NOT_ME)) | |
3996f34b UD |
370 | { |
371 | if (__bind_next (dbp) == NIS_SUCCESS) | |
650425ce UD |
372 | { |
373 | while (__bind_connect (dbp) != NIS_SUCCESS) | |
374 | { | |
375 | if (__bind_next (dbp) != NIS_SUCCESS) | |
376 | { | |
377 | __bind_destroy (dbp); | |
378 | return NIS_SUCCESS; | |
379 | } | |
380 | } | |
381 | } | |
382 | else | |
383 | break; /* No more servers to search in */ | |
2d7da676 | 384 | goto again; |
3996f34b | 385 | } |
2d7da676 UD |
386 | break; |
387 | case NIS_DUMPLOG: /* log_result */ | |
388 | case NIS_DUMP: | |
650425ce UD |
389 | if ((((log_result *)resp)->lr_status == NIS_NOTFOUND) || |
390 | (((log_result *)resp)->lr_status == NIS_NOSUCHNAME) || | |
391 | (((log_result *)resp)->lr_status == NIS_NOT_ME)) | |
3996f34b UD |
392 | { |
393 | if (__bind_next (dbp) == NIS_SUCCESS) | |
650425ce UD |
394 | { |
395 | while (__bind_connect (dbp) != NIS_SUCCESS) | |
396 | { | |
397 | if (__bind_next (dbp) != NIS_SUCCESS) | |
398 | { | |
399 | __bind_destroy (dbp); | |
400 | return NIS_SUCCESS; | |
401 | } | |
402 | } | |
403 | } | |
404 | else | |
405 | break; /* No more servers to search in */ | |
3996f34b UD |
406 | goto again; |
407 | } | |
2d7da676 | 408 | break; |
2d7da676 UD |
409 | default: |
410 | break; | |
411 | } | |
412 | __bind_destroy (dbp); | |
413 | retcode = NIS_SUCCESS; | |
414 | } | |
43b0e40f | 415 | } |
2d7da676 | 416 | while ((flags & HARD_LOOKUP) && retcode == NIS_RPCERROR); |
3996f34b UD |
417 | |
418 | return retcode; | |
43b0e40f UD |
419 | } |
420 | ||
421 | static directory_obj * | |
3996f34b UD |
422 | rec_dirsearch (const_nis_name name, directory_obj *dir, u_long flags, |
423 | nis_error *status) | |
43b0e40f | 424 | { |
2d7da676 UD |
425 | fd_result *fd_res; |
426 | XDR xdrs; | |
43b0e40f UD |
427 | char domain [strlen (name) + 3]; |
428 | ||
429 | nis_domain_of_r (name, domain, sizeof (domain)); | |
430 | if (strncmp (domain, "org_dir.", 8) == 0) | |
431 | { | |
432 | char tmp[strlen (name) + 3]; | |
433 | ||
434 | nis_domain_of_r (domain, tmp, sizeof (tmp)); | |
435 | strcpy (domain, tmp); | |
436 | } | |
437 | else | |
438 | if (strncmp (domain, "groups_dir.", 11) == 0) | |
439 | { | |
440 | char tmp[strlen (name) + 3]; | |
441 | ||
442 | nis_domain_of_r (domain, tmp, sizeof (tmp)); | |
443 | strcpy (domain, tmp); | |
444 | } | |
445 | else | |
446 | { | |
447 | /* We have no grous_dir or org_dir, so try the complete name */ | |
448 | strcpy (domain, name); | |
449 | } | |
450 | ||
451 | switch (nis_dir_cmp (domain, dir->do_name)) | |
452 | { | |
453 | case SAME_NAME: | |
3996f34b | 454 | *status = NIS_SUCCESS; |
43b0e40f UD |
455 | return dir; |
456 | case NOT_SEQUENTIAL: | |
457 | /* NOT_SEQUENTIAL means, go one up and try it there ! */ | |
458 | case HIGHER_NAME: | |
459 | { /* We need data from a parent domain */ | |
460 | directory_obj *obj; | |
461 | char ndomain [strlen (name) + 3]; | |
462 | ||
463 | nis_domain_of_r (dir->do_name, ndomain, sizeof (ndomain)); | |
464 | ||
465 | /* The root server of our domain is a replica of the parent | |
466 | domain ! (Now I understand why a root server must be a | |
467 | replica of the parent domain) */ | |
2d7da676 | 468 | fd_res = __nis_finddirectory (dir, ndomain); |
3996f34b | 469 | *status = fd_res->status; |
2d7da676 UD |
470 | if (fd_res->status != NIS_SUCCESS) |
471 | { | |
472 | nis_free_directory (dir); | |
af6f3906 | 473 | __free_fdresult (fd_res); |
2d7da676 UD |
474 | return NULL; |
475 | } | |
2d7da676 UD |
476 | obj = calloc(1, sizeof(directory_obj)); |
477 | xdrmem_create(&xdrs, fd_res->dir_data.dir_data_val, | |
478 | fd_res->dir_data.dir_data_len, XDR_DECODE); | |
479 | xdr_directory_obj(&xdrs, obj); | |
480 | xdr_destroy(&xdrs); | |
dfd2257a | 481 | __free_fdresult (fd_res); |
43b0e40f UD |
482 | if (obj != NULL) |
483 | { | |
484 | /* We have found a NIS+ server serving ndomain, now | |
485 | let us search for "name" */ | |
486 | nis_free_directory (dir); | |
3996f34b | 487 | return rec_dirsearch (name, obj, flags, status); |
43b0e40f UD |
488 | } |
489 | else | |
490 | { | |
491 | /* Ups, very bad. Are we already the root server ? */ | |
492 | nis_free_directory (dir); | |
493 | return NULL; | |
494 | } | |
495 | } | |
2d7da676 | 496 | break; |
43b0e40f UD |
497 | case LOWER_NAME: |
498 | { | |
499 | directory_obj *obj; | |
500 | char leaf [strlen (name) + 3]; | |
501 | char ndomain [strlen (name) + 3]; | |
714a562f | 502 | char *cp; |
3996f34b | 503 | |
43b0e40f UD |
504 | do |
505 | { | |
506 | if (strlen (domain) == 0) | |
507 | { | |
508 | nis_free_directory (dir); | |
509 | return NULL; | |
510 | } | |
511 | nis_leaf_of_r (domain, leaf, sizeof (leaf)); | |
512 | nis_domain_of_r (domain, ndomain, sizeof (ndomain)); | |
513 | strcpy (domain, ndomain); | |
514 | } | |
515 | while (nis_dir_cmp (domain, dir->do_name) != SAME_NAME); | |
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 | { |
2d7da676 | 524 | nis_free_directory (dir); |
af6f3906 | 525 | __free_fdresult (fd_res); |
2d7da676 UD |
526 | return NULL; |
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); | |
531 | xdr_directory_obj(&xdrs, obj); | |
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 | ||
553 | nis_error | |
554 | __do_niscall (const_nis_name name, u_long prog, xdrproc_t xargs, | |
650425ce UD |
555 | caddr_t req, xdrproc_t xres, caddr_t resp, u_long flags, |
556 | nis_cb *cb) | |
43b0e40f | 557 | { |
2d7da676 | 558 | nis_error retcode; |
43b0e40f | 559 | directory_obj *dir = NULL; |
2d7da676 | 560 | nis_server *server; |
43b0e40f | 561 | u_int server_len; |
ac9f45cf | 562 | cache2_info cinfo = {-1, -1, -1}; |
36a8586d | 563 | int saved_errno = errno; |
43b0e40f | 564 | |
2d7da676 UD |
565 | if (name == NULL) |
566 | return NIS_BADNAME; | |
43b0e40f | 567 | |
ac9f45cf UD |
568 | /* Search in local cache. In the moment, we ignore the fastest server */ |
569 | if (!(flags & NO_CACHE)) | |
570 | dir = __nis_cache_search (name, flags, &cinfo); | |
571 | ||
2d7da676 | 572 | if (dir == NULL) |
43b0e40f | 573 | { |
3996f34b | 574 | nis_error status; |
2d7da676 UD |
575 | dir = readColdStartFile (); |
576 | if (dir == NULL) /* No /var/nis/NIS_COLD_START->no NIS+ installed */ | |
36a8586d UD |
577 | { |
578 | __set_errno (saved_errno); | |
579 | return NIS_UNAVAIL; | |
580 | } | |
3996f34b UD |
581 | |
582 | dir = rec_dirsearch (name, dir, flags, &status); | |
43b0e40f | 583 | if (dir == NULL) |
3996f34b | 584 | return status; |
43b0e40f | 585 | } |
43b0e40f | 586 | |
3996f34b | 587 | if (flags & MASTER_ONLY) |
2d7da676 UD |
588 | { |
589 | server = dir->do_servers.do_servers_val; | |
590 | server_len = 1; | |
591 | } | |
592 | else | |
593 | { | |
594 | server = dir->do_servers.do_servers_val; | |
595 | server_len = dir->do_servers.do_servers_len; | |
596 | } | |
3996f34b UD |
597 | |
598 | ||
2d7da676 | 599 | retcode = __do_niscall2 (server, server_len, prog, xargs, req, xres, resp, |
ac9f45cf | 600 | flags, cb, &cinfo); |
3996f34b | 601 | |
2d7da676 | 602 | nis_free_directory (dir); |
43b0e40f | 603 | |
2d7da676 | 604 | return retcode; |
e61abf83 | 605 | } |