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