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