]>
Commit | Line | Data |
---|---|---|
0d8733c4 | 1 | /* Copyright (C) 1996, 1997 Free Software Foundation, Inc. |
6259ec0d UD |
2 | This file is part of the GNU C Library. |
3 | Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. | |
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 | ||
20 | #include <string.h> | |
21 | #include <unistd.h> | |
22 | #include <fcntl.h> | |
5107cf1d | 23 | #include <bits/libc-lock.h> |
26dee9c4 | 24 | #include <rpc/rpc.h> |
6259ec0d UD |
25 | #include <rpcsvc/yp.h> |
26 | #include <rpcsvc/ypclnt.h> | |
27 | #include <rpcsvc/ypupd.h> | |
28 | ||
29 | struct dom_binding | |
30 | { | |
31 | struct dom_binding *dom_pnext; | |
32 | char dom_domain[YPMAXDOMAIN + 1]; | |
33 | struct sockaddr_in dom_server_addr; | |
34 | int dom_socket; | |
35 | CLIENT *dom_client; | |
36 | long int dom_vers; | |
37 | }; | |
38 | typedef struct dom_binding dom_binding; | |
39 | ||
40 | static struct timeval TIMEOUT = {25, 0}; | |
41 | static int const MAXTRIES = 5; | |
42 | static char __ypdomainname[MAXHOSTNAMELEN + 1] = "\0"; | |
43 | __libc_lock_define_initialized (static, ypbindlist_lock) | |
44 | static dom_binding *__ypbindlist = NULL; | |
45 | ||
f8b87ef0 | 46 | |
6259ec0d | 47 | static int |
f8b87ef0 | 48 | __yp_bind (const char *domain, dom_binding ** ypdb) |
6259ec0d UD |
49 | { |
50 | struct sockaddr_in clnt_saddr; | |
51 | struct ypbind_resp ypbr; | |
52 | dom_binding *ysd; | |
53 | int clnt_sock; | |
54 | CLIENT *client; | |
55 | int is_new = 0; | |
56 | int try; | |
57 | ||
58 | if (ypdb != NULL) | |
59 | *ypdb = NULL; | |
60 | ||
61 | if ((domain == NULL) || (strlen (domain) == 0)) | |
62 | return YPERR_BADARGS; | |
63 | ||
64 | ysd = __ypbindlist; | |
65 | while (ysd != NULL) | |
66 | { | |
67 | if (strcmp (domain, ysd->dom_domain) == 0) | |
68 | break; | |
69 | ysd = ysd->dom_pnext; | |
70 | } | |
71 | ||
72 | if (ysd == NULL) | |
73 | { | |
74 | is_new = 1; | |
75 | ysd = (dom_binding *) malloc (sizeof *ysd); | |
76 | memset (ysd, '\0', sizeof *ysd); | |
77 | ysd->dom_socket = -1; | |
78 | ysd->dom_vers = -1; | |
79 | } | |
80 | ||
81 | try = 0; | |
82 | ||
83 | do | |
84 | { | |
85 | try++; | |
86 | if (try > MAXTRIES) | |
87 | { | |
88 | if (is_new) | |
89 | free (ysd); | |
90 | return YPERR_YPBIND; | |
91 | } | |
92 | ||
93 | if (ysd->dom_vers == -1) | |
94 | { | |
95 | if(ysd->dom_client) | |
96 | { | |
97 | clnt_destroy(ysd->dom_client); | |
98 | ysd->dom_client = NULL; | |
99 | ysd->dom_socket = -1; | |
100 | } | |
101 | memset (&clnt_saddr, '\0', sizeof clnt_saddr); | |
102 | clnt_saddr.sin_family = AF_INET; | |
103 | clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); | |
104 | clnt_sock = RPC_ANYSOCK; | |
105 | client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS, | |
106 | &clnt_sock, 0, 0); | |
107 | if (client == NULL) | |
108 | { | |
109 | if (is_new) | |
110 | free (ysd); | |
111 | return YPERR_YPBIND; | |
112 | } | |
113 | /* | |
114 | ** Check the port number -- should be < IPPORT_RESERVED. | |
115 | ** If not, it's possible someone has registered a bogus | |
116 | ** ypbind with the portmapper and is trying to trick us. | |
117 | */ | |
118 | if (ntohs(clnt_saddr.sin_port) >= IPPORT_RESERVED) | |
119 | { | |
120 | clnt_destroy(client); | |
121 | if (is_new) | |
122 | free(ysd); | |
123 | return(YPERR_YPBIND); | |
124 | } | |
125 | ||
126 | if (clnt_call (client, YPBINDPROC_DOMAIN, | |
3e5f5557 | 127 | (xdrproc_t) xdr_domainname, (caddr_t) &domain, |
6259ec0d | 128 | (xdrproc_t) xdr_ypbind_resp, |
3e5f5557 | 129 | (caddr_t) &ypbr, TIMEOUT) != RPC_SUCCESS) |
6259ec0d UD |
130 | { |
131 | clnt_destroy (client); | |
132 | if (is_new) | |
133 | free (ysd); | |
134 | return YPERR_YPBIND; | |
135 | } | |
136 | ||
137 | clnt_destroy (client); | |
138 | if (ypbr.ypbind_status != YPBIND_SUCC_VAL) | |
139 | { | |
140 | switch (ypbr.ypbind_resp_u.ypbind_error) | |
141 | { | |
142 | case YPBIND_ERR_ERR: | |
143 | fputs (_("YPBINDPROC_DOMAIN: Internal error\n"), stderr); | |
144 | break; | |
145 | case YPBIND_ERR_NOSERV: | |
146 | fprintf (stderr, | |
147 | _("YPBINDPROC_DOMAIN: No server for domain %s\n"), | |
148 | domain); | |
149 | break; | |
150 | case YPBIND_ERR_RESC: | |
151 | fputs (_("YPBINDPROC_DOMAIN: Resource allocation failure\n"), | |
152 | stderr); | |
153 | break; | |
154 | default: | |
155 | fputs (_("YPBINDPROC_DOMAIN: Unknown error\n"), stderr); | |
156 | break; | |
157 | } | |
158 | if (is_new) | |
159 | free (ysd); | |
160 | return YPERR_DOMAIN; | |
161 | } | |
162 | memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr); | |
163 | ysd->dom_server_addr.sin_family = AF_INET; | |
164 | memcpy (&ysd->dom_server_addr.sin_port, | |
165 | ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, | |
166 | sizeof (ysd->dom_server_addr.sin_port)); | |
167 | memcpy (&ysd->dom_server_addr.sin_addr.s_addr, | |
168 | ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, | |
169 | sizeof (ysd->dom_server_addr.sin_addr.s_addr)); | |
170 | ysd->dom_vers = YPVERS; | |
0d8733c4 UD |
171 | strncpy (ysd->dom_domain, domain, YPMAXDOMAIN); |
172 | ysd->dom_domain[YPMAXDOMAIN] = '\0'; | |
6259ec0d UD |
173 | } |
174 | ||
175 | if (ysd->dom_client) | |
176 | clnt_destroy (ysd->dom_client); | |
177 | ysd->dom_socket = RPC_ANYSOCK; | |
178 | ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS, | |
179 | TIMEOUT, &ysd->dom_socket); | |
180 | if (ysd->dom_client == NULL) | |
181 | ysd->dom_vers = -1; | |
182 | ||
183 | } | |
184 | while (ysd->dom_client == NULL); | |
185 | ||
186 | /* If the program exists, close the socket */ | |
187 | if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1) | |
188 | perror (_("fcntl: F_SETFD")); | |
189 | ||
190 | if (is_new) | |
191 | { | |
192 | ysd->dom_pnext = __ypbindlist; | |
193 | __ypbindlist = ysd; | |
194 | } | |
195 | ||
196 | if (NULL != ypdb) | |
197 | *ypdb = ysd; | |
198 | ||
199 | return YPERR_SUCCESS; | |
200 | } | |
201 | ||
202 | static void | |
203 | __yp_unbind (dom_binding *ydb) | |
204 | { | |
205 | clnt_destroy (ydb->dom_client); | |
206 | ydb->dom_client = NULL; | |
207 | ydb->dom_socket = -1; | |
208 | } | |
209 | ||
210 | static int | |
211 | do_ypcall (const char *domain, u_long prog, xdrproc_t xargs, | |
212 | caddr_t req, xdrproc_t xres, caddr_t resp) | |
213 | { | |
214 | dom_binding *ydb = NULL; | |
215 | int try, result; | |
216 | ||
217 | try = 0; | |
218 | result = YPERR_YPERR; | |
219 | ||
220 | while (try < MAXTRIES && result != RPC_SUCCESS) | |
221 | { | |
222 | __libc_lock_lock (ypbindlist_lock); | |
223 | ||
224 | if (__yp_bind (domain, &ydb) != 0) | |
225 | { | |
226 | __libc_lock_unlock (ypbindlist_lock); | |
227 | return YPERR_DOMAIN; | |
228 | } | |
229 | ||
230 | result = clnt_call (ydb->dom_client, prog, | |
231 | xargs, req, xres, resp, TIMEOUT); | |
232 | ||
233 | if (result != RPC_SUCCESS) | |
234 | { | |
235 | clnt_perror (ydb->dom_client, "do_ypcall: clnt_call"); | |
236 | ydb->dom_vers = -1; | |
237 | __yp_unbind (ydb); | |
238 | result = YPERR_RPC; | |
239 | } | |
240 | ||
241 | __libc_lock_unlock (ypbindlist_lock); | |
242 | ||
243 | try++; | |
244 | } | |
245 | ||
246 | return result; | |
247 | } | |
248 | ||
249 | int | |
250 | yp_bind (const char *indomain) | |
251 | { | |
252 | int status; | |
253 | ||
254 | __libc_lock_lock (ypbindlist_lock); | |
255 | ||
256 | status = __yp_bind (indomain, NULL); | |
257 | ||
258 | __libc_lock_unlock (ypbindlist_lock); | |
259 | ||
260 | return status; | |
261 | } | |
262 | ||
263 | void | |
264 | yp_unbind (const char *indomain) | |
265 | { | |
266 | dom_binding *ydbptr, *ydbptr2; | |
267 | ||
268 | __libc_lock_lock (ypbindlist_lock); | |
269 | ||
270 | ydbptr2 = NULL; | |
271 | ydbptr = __ypbindlist; | |
272 | while (ydbptr != NULL) | |
273 | { | |
274 | if (strcmp (ydbptr->dom_domain, indomain) == 0) | |
275 | { | |
276 | dom_binding *work; | |
277 | ||
278 | work = ydbptr; | |
279 | if (ydbptr2 == NULL) | |
280 | __ypbindlist = __ypbindlist->dom_pnext; | |
281 | else | |
282 | ydbptr2 = ydbptr->dom_pnext; | |
283 | __yp_unbind (work); | |
284 | free (work); | |
285 | break; | |
286 | } | |
287 | ydbptr2 = ydbptr; | |
288 | ydbptr = ydbptr->dom_pnext; | |
289 | } | |
290 | ||
291 | __libc_lock_unlock (ypbindlist_lock); | |
292 | ||
293 | return; | |
294 | } | |
295 | ||
296 | __libc_lock_define_initialized (static, domainname_lock) | |
297 | ||
298 | int | |
299 | yp_get_default_domain (char **outdomain) | |
300 | { | |
301 | int result = YPERR_SUCCESS;; | |
302 | *outdomain = NULL; | |
303 | ||
304 | __libc_lock_lock (domainname_lock); | |
305 | ||
306 | if (__ypdomainname[0] == '\0') | |
307 | { | |
308 | if (getdomainname (__ypdomainname, MAXHOSTNAMELEN)) | |
309 | result = YPERR_NODOM; | |
310 | else | |
311 | *outdomain = __ypdomainname; | |
312 | } | |
313 | else | |
314 | *outdomain = __ypdomainname; | |
315 | ||
316 | __libc_lock_unlock (domainname_lock); | |
317 | ||
318 | return result; | |
319 | } | |
320 | ||
321 | int | |
322 | __yp_check (char **domain) | |
323 | { | |
324 | char *unused; | |
325 | ||
326 | if (__ypdomainname[0] == '\0') | |
327 | if (yp_get_default_domain (&unused)) | |
328 | return 0; | |
329 | else if (strcmp (__ypdomainname, "(none)") == 0) | |
330 | return 0; | |
331 | ||
332 | if (domain) | |
333 | *domain = __ypdomainname; | |
334 | ||
335 | if (yp_bind (__ypdomainname) == 0) | |
336 | return 1; | |
337 | return 0; | |
338 | } | |
339 | ||
340 | int | |
341 | yp_match (const char *indomain, const char *inmap, const char *inkey, | |
342 | const int inkeylen, char **outval, int *outvallen) | |
343 | { | |
344 | ypreq_key req; | |
345 | ypresp_val resp; | |
346 | int result; | |
347 | ||
348 | if (indomain == NULL || indomain[0] == '\0' || | |
349 | inmap == NULL || inmap[0] == '\0' || | |
350 | inkey == NULL || inkey[0] == '\0' || inkeylen <= 0) | |
351 | return YPERR_BADARGS; | |
352 | ||
68dbb3a6 UD |
353 | req.domain = (char *) indomain; |
354 | req.map = (char *) inmap; | |
355 | req.key.keydat_val = (char *) inkey; | |
6259ec0d UD |
356 | req.key.keydat_len = inkeylen; |
357 | ||
358 | *outval = NULL; | |
359 | *outvallen = 0; | |
360 | memset (&resp, '\0', sizeof (resp)); | |
361 | ||
362 | result = do_ypcall (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key, | |
363 | (caddr_t) & req, (xdrproc_t) xdr_ypresp_val, | |
364 | (caddr_t) & resp); | |
365 | ||
366 | if (result != RPC_SUCCESS) | |
367 | return result; | |
368 | if (resp.stat != YP_TRUE) | |
369 | return ypprot_err (resp.stat); | |
370 | ||
371 | *outvallen = resp.val.valdat_len; | |
372 | *outval = malloc (*outvallen + 1); | |
373 | memcpy (*outval, resp.val.valdat_val, *outvallen); | |
374 | (*outval)[*outvallen] = '\0'; | |
375 | ||
376 | xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp); | |
377 | ||
378 | return YPERR_SUCCESS; | |
379 | } | |
380 | ||
381 | int | |
382 | yp_first (const char *indomain, const char *inmap, char **outkey, | |
383 | int *outkeylen, char **outval, int *outvallen) | |
384 | { | |
385 | ypreq_nokey req; | |
386 | ypresp_key_val resp; | |
387 | int result; | |
388 | ||
389 | if (indomain == NULL || indomain[0] == '\0' || | |
390 | inmap == NULL || inmap[0] == '\0') | |
391 | return YPERR_BADARGS; | |
392 | ||
68dbb3a6 UD |
393 | req.domain = (char *) indomain; |
394 | req.map = (char *) inmap; | |
6259ec0d UD |
395 | |
396 | *outkey = *outval = NULL; | |
397 | *outkeylen = *outvallen = 0; | |
398 | memset (&resp, '\0', sizeof (resp)); | |
399 | ||
400 | result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey, | |
401 | (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val, | |
402 | (caddr_t) & resp); | |
403 | ||
404 | if (result != RPC_SUCCESS) | |
405 | return result; | |
406 | if (resp.stat != YP_TRUE) | |
407 | return ypprot_err (resp.stat); | |
408 | ||
409 | *outkeylen = resp.key.keydat_len; | |
410 | *outkey = malloc (*outkeylen + 1); | |
411 | memcpy (*outkey, resp.key.keydat_val, *outkeylen); | |
412 | (*outkey)[*outkeylen] = '\0'; | |
413 | *outvallen = resp.val.valdat_len; | |
414 | *outval = malloc (*outvallen + 1); | |
415 | memcpy (*outval, resp.val.valdat_val, *outvallen); | |
416 | (*outval)[*outvallen] = '\0'; | |
417 | ||
418 | xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp); | |
419 | ||
420 | return YPERR_SUCCESS; | |
421 | } | |
422 | ||
423 | int | |
424 | yp_next (const char *indomain, const char *inmap, const char *inkey, | |
425 | const int inkeylen, char **outkey, int *outkeylen, char **outval, | |
426 | int *outvallen) | |
427 | { | |
428 | ypreq_key req; | |
429 | ypresp_key_val resp; | |
430 | int result; | |
431 | ||
432 | if (indomain == NULL || indomain[0] == '\0' || | |
433 | inmap == NULL || inmap[0] == '\0' || | |
434 | inkeylen <= 0 || inkey == NULL || inkey[0] == '\0') | |
435 | return YPERR_BADARGS; | |
436 | ||
68dbb3a6 UD |
437 | req.domain = (char *) indomain; |
438 | req.map = (char *) inmap; | |
439 | req.key.keydat_val = (char *) inkey; | |
6259ec0d UD |
440 | req.key.keydat_len = inkeylen; |
441 | ||
442 | *outkey = *outval = NULL; | |
443 | *outkeylen = *outvallen = 0; | |
444 | memset (&resp, '\0', sizeof (resp)); | |
445 | ||
446 | result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key, | |
447 | (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val, | |
448 | (caddr_t) & resp); | |
449 | ||
450 | if (result != RPC_SUCCESS) | |
451 | return result; | |
452 | if (resp.stat != YP_TRUE) | |
453 | return ypprot_err (resp.stat); | |
454 | ||
455 | *outkeylen = resp.key.keydat_len; | |
456 | *outkey = malloc (*outkeylen + 1); | |
457 | memcpy (*outkey, resp.key.keydat_val, *outkeylen); | |
458 | (*outkey)[*outkeylen] = '\0'; | |
459 | *outvallen = resp.val.valdat_len; | |
460 | *outval = malloc (*outvallen + 1); | |
461 | memcpy (*outval, resp.val.valdat_val, *outvallen); | |
462 | (*outval)[*outvallen] = '\0'; | |
463 | ||
464 | xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp); | |
465 | ||
466 | return YPERR_SUCCESS; | |
467 | } | |
468 | ||
469 | int | |
470 | yp_master (const char *indomain, const char *inmap, char **outname) | |
471 | { | |
472 | ypreq_nokey req; | |
473 | ypresp_master resp; | |
474 | int result; | |
475 | ||
476 | if (indomain == NULL || indomain[0] == '\0' || | |
477 | inmap == NULL || inmap[0] == '\0') | |
478 | return YPERR_BADARGS; | |
479 | ||
68dbb3a6 UD |
480 | req.domain = (char *) indomain; |
481 | req.map = (char *) inmap; | |
6259ec0d UD |
482 | |
483 | memset (&resp, '\0', sizeof (ypresp_master)); | |
484 | ||
485 | result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey, | |
486 | (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp); | |
487 | ||
488 | if (result != RPC_SUCCESS) | |
489 | return result; | |
490 | if (resp.stat != YP_TRUE) | |
491 | return ypprot_err (resp.stat); | |
492 | ||
493 | *outname = strdup (resp.peer); | |
494 | xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp); | |
495 | ||
496 | return YPERR_SUCCESS; | |
497 | } | |
498 | ||
499 | int | |
500 | yp_order (const char *indomain, const char *inmap, unsigned int *outorder) | |
501 | { | |
502 | struct ypreq_nokey req; | |
503 | struct ypresp_order resp; | |
504 | int result; | |
505 | ||
506 | if (indomain == NULL || indomain[0] == '\0' || | |
507 | inmap == NULL || inmap == '\0') | |
508 | return YPERR_BADARGS; | |
509 | ||
68dbb3a6 UD |
510 | req.domain = (char *) indomain; |
511 | req.map = (char *) inmap; | |
6259ec0d UD |
512 | |
513 | memset (&resp, '\0', sizeof (resp)); | |
514 | ||
515 | result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey, | |
516 | (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp); | |
517 | ||
518 | if (result != RPC_SUCCESS) | |
519 | return result; | |
520 | if (resp.stat != YP_TRUE) | |
521 | return ypprot_err (resp.stat); | |
522 | ||
523 | *outorder = resp.ordernum; | |
524 | xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp); | |
525 | ||
526 | return YPERR_SUCCESS; | |
527 | } | |
528 | ||
529 | static void *ypall_data; | |
3e5f5557 UD |
530 | static int (*ypall_foreach) __P ((int status, char *key, int keylen, |
531 | char *val, int vallen, char *data)); | |
6259ec0d UD |
532 | |
533 | static bool_t | |
534 | __xdr_ypresp_all (XDR * xdrs, u_long * objp) | |
535 | { | |
536 | while (1) | |
537 | { | |
538 | struct ypresp_all resp; | |
539 | ||
540 | memset (&resp, '\0', sizeof (struct ypresp_all)); | |
541 | if (!xdr_ypresp_all (xdrs, &resp)) | |
542 | { | |
543 | xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); | |
544 | *objp = YP_YPERR; | |
545 | return (FALSE); | |
546 | } | |
547 | if (resp.more == 0) | |
548 | { | |
549 | xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); | |
550 | *objp = YP_NOMORE; | |
551 | return (FALSE); | |
552 | } | |
553 | ||
554 | switch (resp.ypresp_all_u.val.stat) | |
555 | { | |
556 | case YP_TRUE: | |
557 | { | |
558 | char key[resp.ypresp_all_u.val.key.keydat_len + 1]; | |
559 | char val[resp.ypresp_all_u.val.val.valdat_len + 1]; | |
560 | int keylen = resp.ypresp_all_u.val.key.keydat_len; | |
561 | int vallen = resp.ypresp_all_u.val.val.valdat_len; | |
562 | ||
563 | *objp = YP_TRUE; | |
564 | memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen); | |
565 | key[keylen] = '\0'; | |
566 | memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen); | |
567 | val[vallen] = '\0'; | |
568 | xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); | |
569 | if ((*ypall_foreach) (*objp, key, keylen, | |
570 | val, vallen, ypall_data)) | |
571 | return TRUE; | |
572 | } | |
573 | break; | |
574 | case YP_NOMORE: | |
575 | *objp = YP_NOMORE; | |
576 | xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); | |
577 | return TRUE; | |
578 | break; | |
579 | default: | |
580 | *objp = resp.ypresp_all_u.val.stat; | |
581 | xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); | |
582 | return TRUE; | |
583 | } | |
584 | } | |
585 | } | |
586 | ||
587 | int | |
588 | yp_all (const char *indomain, const char *inmap, | |
589 | const struct ypall_callback *incallback) | |
590 | { | |
591 | struct ypreq_nokey req; | |
592 | dom_binding *ydb; | |
593 | int try, result; | |
594 | struct sockaddr_in clnt_sin; | |
595 | CLIENT *clnt; | |
596 | unsigned long status; | |
597 | int clnt_sock; | |
598 | ||
599 | if (indomain == NULL || indomain[0] == '\0' || | |
600 | inmap == NULL || inmap == '\0') | |
601 | return YPERR_BADARGS; | |
602 | ||
603 | try = 0; | |
604 | result = YPERR_YPERR; | |
605 | ||
606 | while (try < MAXTRIES && result != RPC_SUCCESS) | |
607 | { | |
608 | __libc_lock_lock (ypbindlist_lock); | |
609 | ||
610 | if (__yp_bind (indomain, &ydb) != 0) | |
611 | { | |
612 | __libc_lock_unlock (ypbindlist_lock); | |
613 | return YPERR_DOMAIN; | |
614 | } | |
615 | ||
616 | /* YPPROC_ALL get its own TCP channel to ypserv */ | |
617 | clnt_sock = RPC_ANYSOCK; | |
618 | clnt_sin = ydb->dom_server_addr; | |
619 | clnt_sin.sin_port = 0; | |
620 | clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0); | |
621 | if (clnt == NULL) | |
622 | { | |
623 | puts ("yp_all: clnttcp_create failed"); | |
624 | __libc_lock_unlock (ypbindlist_lock); | |
625 | return YPERR_PMAP; | |
626 | } | |
68dbb3a6 UD |
627 | req.domain = (char *) indomain; |
628 | req.map = (char *) inmap; | |
6259ec0d UD |
629 | |
630 | ypall_foreach = incallback->foreach; | |
631 | ypall_data = (void *) incallback->data; | |
632 | ||
3e5f5557 UD |
633 | result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey, |
634 | (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all, | |
635 | (caddr_t) &status, TIMEOUT); | |
6259ec0d UD |
636 | |
637 | if (result != RPC_SUCCESS) | |
638 | { | |
639 | clnt_perror (ydb->dom_client, "yp_all: clnt_call"); | |
640 | clnt_destroy (clnt); | |
641 | __yp_unbind (ydb); | |
642 | result = YPERR_RPC; | |
643 | } | |
644 | else | |
645 | { | |
646 | clnt_destroy (clnt); | |
647 | result = YPERR_SUCCESS; | |
648 | } | |
649 | ||
650 | __libc_lock_unlock (ypbindlist_lock); | |
651 | ||
652 | if (status != YP_NOMORE) | |
653 | return ypprot_err (status); | |
654 | try++; | |
655 | } | |
656 | ||
657 | return result; | |
658 | } | |
659 | ||
660 | int | |
661 | yp_maplist (const char *indomain, struct ypmaplist **outmaplist) | |
662 | { | |
663 | struct ypresp_maplist resp; | |
664 | int result; | |
665 | ||
666 | if (indomain == NULL || indomain[0] == '\0') | |
667 | return YPERR_BADARGS; | |
668 | ||
669 | memset (&resp, '\0', sizeof (resp)); | |
670 | ||
671 | result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname, | |
672 | (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp); | |
673 | ||
674 | if (result != RPC_SUCCESS) | |
675 | return result; | |
676 | if (resp.stat != YP_TRUE) | |
677 | return ypprot_err (resp.stat); | |
678 | ||
679 | *outmaplist = resp.maps; | |
680 | /* We give the list not free, this will be done by ypserv | |
681 | xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */ | |
682 | ||
683 | return YPERR_SUCCESS; | |
684 | } | |
685 | ||
686 | const char * | |
687 | yperr_string (const int error) | |
688 | { | |
689 | switch (error) | |
690 | { | |
691 | case YPERR_SUCCESS: | |
692 | return _("Success"); | |
693 | case YPERR_BADARGS: | |
694 | return _("Request arguments bad"); | |
695 | case YPERR_RPC: | |
696 | return _("RPC failure on NIS operation"); | |
697 | case YPERR_DOMAIN: | |
698 | return _("Can't bind to server which serves this domain"); | |
699 | case YPERR_MAP: | |
700 | return _("No such map in server's domain"); | |
701 | case YPERR_KEY: | |
702 | return _("No such key in map"); | |
703 | case YPERR_YPERR: | |
704 | return _("Internal NIS error"); | |
705 | case YPERR_RESRC: | |
706 | return _("Local resource allocation failure"); | |
707 | case YPERR_NOMORE: | |
708 | return _("No more records in map database"); | |
709 | case YPERR_PMAP: | |
710 | return _("Can't communicate with portmapper"); | |
711 | case YPERR_YPBIND: | |
712 | return _("Can't communicate with ypbind"); | |
713 | case YPERR_YPSERV: | |
714 | return _("Can't communicate with ypserv"); | |
715 | case YPERR_NODOM: | |
716 | return _("Local domain name not set"); | |
717 | case YPERR_BADDB: | |
718 | return _("NIS map data base is bad"); | |
719 | case YPERR_VERS: | |
720 | return _("NIS client/server version mismatch - can't supply service"); | |
721 | case YPERR_ACCESS: | |
722 | return _("Permission denied"); | |
723 | case YPERR_BUSY: | |
724 | return _("Database is busy"); | |
725 | } | |
726 | return _("Unknown NIS error code"); | |
727 | } | |
728 | ||
729 | int | |
730 | ypprot_err (const int code) | |
731 | { | |
732 | switch (code) | |
733 | { | |
734 | case YP_TRUE: | |
735 | return YPERR_SUCCESS; | |
736 | case YP_NOMORE: | |
737 | return YPERR_NOMORE; | |
738 | case YP_FALSE: | |
739 | return YPERR_YPERR; | |
740 | case YP_NOMAP: | |
741 | return YPERR_MAP; | |
742 | case YP_NODOM: | |
743 | return YPERR_DOMAIN; | |
744 | case YP_NOKEY: | |
745 | return YPERR_KEY; | |
746 | case YP_BADOP: | |
747 | return YPERR_YPERR; | |
748 | case YP_BADDB: | |
749 | return YPERR_BADDB; | |
750 | case YP_YPERR: | |
751 | return YPERR_YPERR; | |
752 | case YP_BADARGS: | |
753 | return YPERR_BADARGS; | |
754 | case YP_VERS: | |
755 | return YPERR_VERS; | |
756 | } | |
757 | return YPERR_YPERR; | |
758 | } | |
759 | ||
760 | const char * | |
761 | ypbinderr_string (const int error) | |
762 | { | |
763 | switch (error) | |
764 | { | |
765 | case 0: | |
766 | return _("Success"); | |
767 | case YPBIND_ERR_ERR: | |
768 | return _("Internal ypbind error"); | |
769 | case YPBIND_ERR_NOSERV: | |
770 | return _("Domain not bound"); | |
771 | case YPBIND_ERR_RESC: | |
772 | return _("System resource allocation failure"); | |
773 | default: | |
774 | return _("Unknown ypbind error"); | |
775 | } | |
776 | } | |
777 | ||
778 | ||
779 | #define WINDOW 60 | |
780 | ||
781 | int | |
782 | yp_update (char *domain, char *map, unsigned ypop, | |
783 | char *key, int keylen, char *data, int datalen) | |
784 | { | |
26dee9c4 | 785 | #if defined (HAVE_SECURE_RPC) |
6259ec0d UD |
786 | union |
787 | { | |
788 | ypupdate_args update_args; | |
789 | ypdelete_args delete_args; | |
790 | } | |
791 | args; | |
792 | xdrproc_t xdr_argument; | |
793 | unsigned res = 0; | |
794 | CLIENT *clnt; | |
795 | char *master; | |
796 | struct sockaddr saddr; | |
797 | char servername[MAXNETNAMELEN + 1]; | |
798 | int r; | |
799 | ||
800 | if (!domain || !map || !key || (ypop != YPOP_DELETE && !data)) | |
801 | return YPERR_BADARGS; | |
802 | ||
803 | args.update_args.mapname = map; | |
804 | args.update_args.key.yp_buf_len = keylen; | |
805 | args.update_args.key.yp_buf_val = key; | |
806 | args.update_args.datum.yp_buf_len = datalen; | |
807 | args.update_args.datum.yp_buf_val = data; | |
808 | ||
809 | if ((r = yp_master (domain, map, &master)) != 0) | |
810 | return r; | |
811 | ||
812 | if (!host2netname (servername, master, domain)) | |
813 | { | |
814 | fputs (_("yp_update: cannot convert host to netname\n"), stderr); | |
815 | return YPERR_YPERR; | |
816 | } | |
817 | ||
818 | if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL) | |
819 | { | |
820 | clnt_pcreateerror ("yp_update: clnt_create"); | |
821 | return YPERR_RPC; | |
822 | } | |
823 | ||
824 | if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr)) | |
825 | { | |
826 | fputs (_("yp_update: cannot get server address\n"), stderr); | |
827 | return YPERR_RPC; | |
828 | } | |
829 | ||
830 | switch (ypop) | |
831 | { | |
832 | case YPOP_CHANGE: | |
833 | case YPOP_INSERT: | |
834 | case YPOP_STORE: | |
835 | xdr_argument = (xdrproc_t) xdr_ypupdate_args; | |
836 | break; | |
837 | case YPOP_DELETE: | |
838 | xdr_argument = (xdrproc_t) xdr_ypdelete_args; | |
839 | break; | |
840 | default: | |
841 | return YPERR_BADARGS; | |
842 | break; | |
843 | } | |
844 | ||
845 | clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL); | |
846 | ||
847 | if (clnt->cl_auth == NULL) | |
848 | clnt->cl_auth = authunix_create_default (); | |
849 | ||
850 | again: | |
26dee9c4 UD |
851 | r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args, |
852 | (xdrproc_t) xdr_u_int, (caddr_t) &res, TIMEOUT); | |
6259ec0d UD |
853 | |
854 | if (r == RPC_AUTHERROR) | |
855 | { | |
856 | if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES) | |
857 | { | |
858 | clnt->cl_auth = authunix_create_default (); | |
859 | goto again; | |
860 | } | |
861 | else | |
862 | return YPERR_ACCESS; | |
863 | } | |
864 | if (r != RPC_SUCCESS) | |
865 | { | |
866 | clnt_perror (clnt, "yp_update: clnt_call"); | |
867 | return YPERR_RPC; | |
868 | } | |
869 | return res; | |
870 | #else | |
871 | return YPERR_YPERR; | |
872 | #endif | |
873 | } |