yplib.c revision 1.19 1 1.19 jtc /* $NetBSD: yplib.c,v 1.19 1996/05/14 13:36:51 jtc Exp $ */
2 1.14 cgd
3 1.3 deraadt /*
4 1.8 deraadt * Copyright (c) 1992, 1993 Theo de Raadt <deraadt (at) fsa.ca>
5 1.3 deraadt * All rights reserved.
6 1.3 deraadt *
7 1.3 deraadt * Redistribution and use in source and binary forms, with or without
8 1.3 deraadt * modification, are permitted provided that the following conditions
9 1.3 deraadt * are met:
10 1.3 deraadt * 1. Redistributions of source code must retain the above copyright
11 1.3 deraadt * notice, this list of conditions and the following disclaimer.
12 1.3 deraadt * 2. Redistributions in binary form must reproduce the above copyright
13 1.3 deraadt * notice, this list of conditions and the following disclaimer in the
14 1.3 deraadt * documentation and/or other materials provided with the distribution.
15 1.8 deraadt * 3. All advertising materials mentioning features or use of this software
16 1.8 deraadt * must display the following acknowledgement:
17 1.8 deraadt * This product includes software developed by Theo de Raadt.
18 1.8 deraadt * 4. The name of the author may not be used to endorse or promote products
19 1.8 deraadt * derived from this software without specific prior written permission.
20 1.3 deraadt *
21 1.3 deraadt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
22 1.3 deraadt * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 1.3 deraadt * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 1.3 deraadt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
25 1.3 deraadt * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 1.3 deraadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 1.3 deraadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 1.3 deraadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 1.3 deraadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 1.3 deraadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 1.3 deraadt * SUCH DAMAGE.
32 1.3 deraadt */
33 1.3 deraadt
34 1.17 jtc #if defined(LIBC_SCCS) && !defined(lint)
35 1.19 jtc static char rcsid[] = "$NetBSD: yplib.c,v 1.19 1996/05/14 13:36:51 jtc Exp $";
36 1.3 deraadt #endif
37 1.3 deraadt
38 1.1 deraadt #include <sys/param.h>
39 1.1 deraadt #include <sys/types.h>
40 1.1 deraadt #include <sys/socket.h>
41 1.1 deraadt #include <sys/file.h>
42 1.7 deraadt #include <sys/uio.h>
43 1.1 deraadt #include <errno.h>
44 1.1 deraadt #include <stdio.h>
45 1.9 jtc #include <stdlib.h>
46 1.1 deraadt #include <string.h>
47 1.9 jtc #include <unistd.h>
48 1.1 deraadt #include <rpc/rpc.h>
49 1.1 deraadt #include <rpc/xdr.h>
50 1.1 deraadt #include <rpcsvc/yp_prot.h>
51 1.1 deraadt #include <rpcsvc/ypclnt.h>
52 1.1 deraadt
53 1.13 deraadt #define BINDINGDIR "/var/yp/binding"
54 1.13 deraadt #define YPBINDLOCK "/var/run/ypbind.lock"
55 1.1 deraadt #define YPMATCHCACHE
56 1.1 deraadt
57 1.16 christos int (*ypresp_allfn) __P((u_long, char *, int, char *, int, void *));
58 1.1 deraadt void *ypresp_data;
59 1.1 deraadt
60 1.1 deraadt struct dom_binding *_ypbindlist;
61 1.1 deraadt static char _yp_domain[MAXHOSTNAMELEN];
62 1.1 deraadt int _yplib_timeout = 10;
63 1.1 deraadt
64 1.16 christos static bool_t ypmatch_add __P((const char *, const char *, int, char *, int));
65 1.16 christos static bool_t ypmatch_find __P((const char *, const char *, int, const char **,
66 1.16 christos int *));
67 1.16 christos static void _yp_unbind __P((struct dom_binding *));
68 1.16 christos
69 1.1 deraadt #ifdef YPMATCHCACHE
70 1.1 deraadt int _yplib_cache = 5;
71 1.1 deraadt
72 1.1 deraadt static struct ypmatch_ent {
73 1.16 christos struct ypmatch_ent *next;
74 1.16 christos char *map, *key;
75 1.16 christos char *val;
76 1.16 christos int keylen, vallen;
77 1.16 christos time_t expire_t;
78 1.1 deraadt } *ypmc;
79 1.1 deraadt
80 1.16 christos static bool_t
81 1.1 deraadt ypmatch_add(map, key, keylen, val, vallen)
82 1.16 christos const char *map;
83 1.16 christos const char *key;
84 1.16 christos int keylen;
85 1.16 christos char *val;
86 1.16 christos int vallen;
87 1.1 deraadt {
88 1.1 deraadt struct ypmatch_ent *ep;
89 1.1 deraadt time_t t;
90 1.1 deraadt
91 1.16 christos (void)time(&t);
92 1.1 deraadt
93 1.16 christos for (ep = ypmc; ep; ep = ep->next)
94 1.16 christos if (ep->expire_t < t)
95 1.1 deraadt break;
96 1.16 christos if (ep == NULL) {
97 1.16 christos if ((ep = malloc(sizeof *ep)) == NULL)
98 1.16 christos return 0;
99 1.16 christos (void)memset(ep, 0, sizeof *ep);
100 1.16 christos if (ypmc)
101 1.1 deraadt ep->next = ypmc;
102 1.1 deraadt ypmc = ep;
103 1.1 deraadt }
104 1.1 deraadt
105 1.16 christos if (ep->key) {
106 1.1 deraadt free(ep->key);
107 1.16 christos ep->key = NULL;
108 1.16 christos }
109 1.16 christos if (ep->val) {
110 1.1 deraadt free(ep->val);
111 1.16 christos ep->val = NULL;
112 1.16 christos }
113 1.1 deraadt
114 1.16 christos if ((ep->key = malloc(keylen)) == NULL)
115 1.16 christos return 0;
116 1.1 deraadt
117 1.16 christos if ((ep->val = malloc(vallen)) == NULL) {
118 1.1 deraadt free(ep->key);
119 1.1 deraadt ep->key = NULL;
120 1.16 christos return 0;
121 1.1 deraadt }
122 1.16 christos
123 1.1 deraadt ep->keylen = keylen;
124 1.1 deraadt ep->vallen = vallen;
125 1.1 deraadt
126 1.16 christos (void)memcpy(ep->key, key, ep->keylen);
127 1.16 christos (void)memcpy(ep->val, val, ep->vallen);
128 1.1 deraadt
129 1.16 christos if (ep->map) {
130 1.16 christos if (strcmp(ep->map, map)) {
131 1.1 deraadt free(ep->map);
132 1.16 christos if ((ep->map = strdup(map)) == NULL)
133 1.16 christos return 0;
134 1.1 deraadt }
135 1.1 deraadt } else {
136 1.16 christos if ((ep->map = strdup(map)) == NULL)
137 1.16 christos return 0;
138 1.1 deraadt }
139 1.1 deraadt
140 1.1 deraadt ep->expire_t = t + _yplib_cache;
141 1.16 christos return 1;
142 1.1 deraadt }
143 1.1 deraadt
144 1.1 deraadt static bool_t
145 1.1 deraadt ypmatch_find(map, key, keylen, val, vallen)
146 1.16 christos const char *map;
147 1.16 christos const char *key;
148 1.16 christos int keylen;
149 1.16 christos const char **val;
150 1.16 christos int *vallen;
151 1.1 deraadt {
152 1.1 deraadt struct ypmatch_ent *ep;
153 1.16 christos time_t t;
154 1.1 deraadt
155 1.16 christos if (ypmc == NULL)
156 1.1 deraadt return 0;
157 1.1 deraadt
158 1.16 christos (void) time(&t);
159 1.1 deraadt
160 1.16 christos for (ep = ypmc; ep; ep = ep->next) {
161 1.16 christos if (ep->keylen != keylen)
162 1.1 deraadt continue;
163 1.16 christos if (strcmp(ep->map, map))
164 1.1 deraadt continue;
165 1.16 christos if (memcmp(ep->key, key, keylen))
166 1.1 deraadt continue;
167 1.16 christos if (t > ep->expire_t)
168 1.1 deraadt continue;
169 1.1 deraadt
170 1.1 deraadt *val = ep->val;
171 1.1 deraadt *vallen = ep->vallen;
172 1.1 deraadt return 1;
173 1.1 deraadt }
174 1.1 deraadt return 0;
175 1.1 deraadt }
176 1.1 deraadt #endif
177 1.1 deraadt
178 1.1 deraadt int
179 1.1 deraadt _yp_dobind(dom, ypdb)
180 1.16 christos const char *dom;
181 1.16 christos struct dom_binding **ypdb;
182 1.1 deraadt {
183 1.16 christos static int pid = -1;
184 1.16 christos char path[MAXPATHLEN];
185 1.1 deraadt struct dom_binding *ysd, *ysd2;
186 1.1 deraadt struct ypbind_resp ypbr;
187 1.16 christos struct timeval tv;
188 1.1 deraadt struct sockaddr_in clnt_sin;
189 1.16 christos int clnt_sock, fd, gpid;
190 1.16 christos CLIENT *client;
191 1.16 christos int new = 0, r;
192 1.16 christos int count = 0;
193 1.1 deraadt
194 1.13 deraadt /*
195 1.13 deraadt * test if YP is running or not
196 1.13 deraadt */
197 1.16 christos if ((fd = open(YPBINDLOCK, O_RDONLY)) == -1)
198 1.13 deraadt return YPERR_YPBIND;
199 1.16 christos if (!(flock(fd, LOCK_EX | LOCK_NB) == -1 && errno == EWOULDBLOCK)) {
200 1.16 christos (void)close(fd);
201 1.13 deraadt return YPERR_YPBIND;
202 1.13 deraadt }
203 1.16 christos (void)close(fd);
204 1.13 deraadt
205 1.1 deraadt gpid = getpid();
206 1.16 christos if (!(pid == -1 || pid == gpid)) {
207 1.1 deraadt ysd = _ypbindlist;
208 1.16 christos while (ysd) {
209 1.16 christos if (ysd->dom_client)
210 1.1 deraadt clnt_destroy(ysd->dom_client);
211 1.1 deraadt ysd2 = ysd->dom_pnext;
212 1.1 deraadt free(ysd);
213 1.1 deraadt ysd = ysd2;
214 1.1 deraadt }
215 1.1 deraadt _ypbindlist = NULL;
216 1.1 deraadt }
217 1.1 deraadt pid = gpid;
218 1.1 deraadt
219 1.16 christos if (ypdb != NULL)
220 1.1 deraadt *ypdb = NULL;
221 1.1 deraadt
222 1.16 christos if (dom == NULL || strlen(dom) == 0)
223 1.1 deraadt return YPERR_BADARGS;
224 1.1 deraadt
225 1.16 christos for (ysd = _ypbindlist; ysd; ysd = ysd->dom_pnext)
226 1.16 christos if (strcmp(dom, ysd->dom_domain) == 0)
227 1.1 deraadt break;
228 1.16 christos if (ysd == NULL) {
229 1.16 christos if ((ysd = malloc(sizeof *ysd)) == NULL)
230 1.16 christos return YPERR_YPERR;
231 1.16 christos (void)memset(ysd, 0, sizeof *ysd);
232 1.1 deraadt ysd->dom_socket = -1;
233 1.1 deraadt ysd->dom_vers = 0;
234 1.1 deraadt new = 1;
235 1.1 deraadt }
236 1.1 deraadt again:
237 1.16 christos if (ysd->dom_vers == 0) {
238 1.16 christos (void) snprintf(path, sizeof(path), "%s/%s.%d",
239 1.16 christos BINDINGDIR, dom, 2);
240 1.16 christos if ((fd = open(path, O_RDONLY)) == -1) {
241 1.16 christos /*
242 1.16 christos * no binding file, YP is dead, or not yet fully
243 1.16 christos * alive.
244 1.16 christos */
245 1.11 deraadt goto trynet;
246 1.1 deraadt }
247 1.16 christos if (flock(fd, LOCK_EX | LOCK_NB) == -1 &&
248 1.16 christos errno == EWOULDBLOCK) {
249 1.16 christos struct iovec iov[2];
250 1.7 deraadt struct ypbind_resp ybr;
251 1.16 christos u_short ypb_port;
252 1.16 christos struct ypbind_binding *bn;
253 1.7 deraadt
254 1.16 christos iov[0].iov_base = (caddr_t) & ypb_port;
255 1.7 deraadt iov[0].iov_len = sizeof ypb_port;
256 1.16 christos iov[1].iov_base = (caddr_t) & ybr;
257 1.7 deraadt iov[1].iov_len = sizeof ybr;
258 1.7 deraadt
259 1.7 deraadt r = readv(fd, iov, 2);
260 1.16 christos if (r != iov[0].iov_len + iov[1].iov_len) {
261 1.16 christos (void)close(fd);
262 1.1 deraadt ysd->dom_vers = -1;
263 1.1 deraadt goto again;
264 1.1 deraadt }
265 1.16 christos (void)memset(&ysd->dom_server_addr, 0,
266 1.16 christos sizeof ysd->dom_server_addr);
267 1.16 christos ysd->dom_server_addr.sin_len =
268 1.16 christos sizeof(struct sockaddr_in);
269 1.7 deraadt ysd->dom_server_addr.sin_family = AF_INET;
270 1.16 christos bn = &ybr.ypbind_respbody.ypbind_bindinfo;
271 1.15 mycroft ysd->dom_server_addr.sin_port =
272 1.16 christos bn->ypbind_binding_port;
273 1.16 christos
274 1.7 deraadt ysd->dom_server_addr.sin_addr =
275 1.16 christos bn->ypbind_binding_addr;
276 1.7 deraadt
277 1.1 deraadt ysd->dom_server_port = ysd->dom_server_addr.sin_port;
278 1.16 christos (void)close(fd);
279 1.1 deraadt goto gotit;
280 1.1 deraadt } else {
281 1.1 deraadt /* no lock on binding file, YP is dead. */
282 1.16 christos (void)close(fd);
283 1.16 christos if (new)
284 1.1 deraadt free(ysd);
285 1.1 deraadt return YPERR_YPBIND;
286 1.1 deraadt }
287 1.1 deraadt }
288 1.11 deraadt trynet:
289 1.16 christos if (ysd->dom_vers == -1 || ysd->dom_vers == 0) {
290 1.16 christos struct ypbind_binding *bn;
291 1.16 christos (void)memset(&clnt_sin, 0, sizeof clnt_sin);
292 1.15 mycroft clnt_sin.sin_len = sizeof(struct sockaddr_in);
293 1.1 deraadt clnt_sin.sin_family = AF_INET;
294 1.1 deraadt clnt_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
295 1.1 deraadt
296 1.1 deraadt clnt_sock = RPC_ANYSOCK;
297 1.16 christos client = clnttcp_create(&clnt_sin, YPBINDPROG, YPBINDVERS,
298 1.16 christos &clnt_sock, 0, 0);
299 1.16 christos if (client == NULL) {
300 1.1 deraadt clnt_pcreateerror("clnttcp_create");
301 1.16 christos if (new)
302 1.1 deraadt free(ysd);
303 1.1 deraadt return YPERR_YPBIND;
304 1.1 deraadt }
305 1.1 deraadt tv.tv_sec = _yplib_timeout;
306 1.1 deraadt tv.tv_usec = 0;
307 1.16 christos r = clnt_call(client, YPBINDPROC_DOMAIN, xdr_domainname,
308 1.16 christos dom, xdr_ypbind_resp, &ypbr, tv);
309 1.16 christos if (r != RPC_SUCCESS) {
310 1.16 christos if (new == 0 || count)
311 1.12 deraadt fprintf(stderr,
312 1.16 christos "YP server for domain %s not responding, still trying\n",
313 1.16 christos dom);
314 1.12 deraadt count++;
315 1.1 deraadt clnt_destroy(client);
316 1.1 deraadt ysd->dom_vers = -1;
317 1.1 deraadt goto again;
318 1.1 deraadt }
319 1.1 deraadt clnt_destroy(client);
320 1.1 deraadt
321 1.16 christos (void)memset(&ysd->dom_server_addr, 0,
322 1.16 christos sizeof ysd->dom_server_addr);
323 1.15 mycroft ysd->dom_server_addr.sin_len = sizeof(struct sockaddr_in);
324 1.1 deraadt ysd->dom_server_addr.sin_family = AF_INET;
325 1.16 christos bn = &ypbr.ypbind_respbody.ypbind_bindinfo;
326 1.1 deraadt ysd->dom_server_addr.sin_port =
327 1.16 christos bn->ypbind_binding_port;
328 1.1 deraadt ysd->dom_server_addr.sin_addr.s_addr =
329 1.16 christos bn->ypbind_binding_addr.s_addr;
330 1.1 deraadt ysd->dom_server_port =
331 1.16 christos bn->ypbind_binding_port;
332 1.1 deraadt gotit:
333 1.1 deraadt ysd->dom_vers = YPVERS;
334 1.16 christos (void)strcpy(ysd->dom_domain, dom);
335 1.1 deraadt }
336 1.16 christos tv.tv_sec = _yplib_timeout / 2;
337 1.1 deraadt tv.tv_usec = 0;
338 1.16 christos if (ysd->dom_client)
339 1.1 deraadt clnt_destroy(ysd->dom_client);
340 1.1 deraadt ysd->dom_socket = RPC_ANYSOCK;
341 1.1 deraadt ysd->dom_client = clntudp_create(&ysd->dom_server_addr,
342 1.16 christos YPPROG, YPVERS, tv, &ysd->dom_socket);
343 1.16 christos if (ysd->dom_client == NULL) {
344 1.1 deraadt clnt_pcreateerror("clntudp_create");
345 1.1 deraadt ysd->dom_vers = -1;
346 1.1 deraadt goto again;
347 1.1 deraadt }
348 1.16 christos if (fcntl(ysd->dom_socket, F_SETFD, 1) == -1)
349 1.1 deraadt perror("fcntl: F_SETFD");
350 1.1 deraadt
351 1.16 christos if (new) {
352 1.1 deraadt ysd->dom_pnext = _ypbindlist;
353 1.1 deraadt _ypbindlist = ysd;
354 1.1 deraadt }
355 1.16 christos if (ypdb != NULL)
356 1.1 deraadt *ypdb = ysd;
357 1.1 deraadt return 0;
358 1.1 deraadt }
359 1.1 deraadt
360 1.1 deraadt static void
361 1.1 deraadt _yp_unbind(ypb)
362 1.16 christos struct dom_binding *ypb;
363 1.1 deraadt {
364 1.1 deraadt clnt_destroy(ypb->dom_client);
365 1.1 deraadt ypb->dom_client = NULL;
366 1.1 deraadt ypb->dom_socket = -1;
367 1.1 deraadt }
368 1.1 deraadt
369 1.1 deraadt int
370 1.1 deraadt yp_bind(dom)
371 1.16 christos const char *dom;
372 1.1 deraadt {
373 1.1 deraadt return _yp_dobind(dom, NULL);
374 1.1 deraadt }
375 1.1 deraadt
376 1.1 deraadt void
377 1.1 deraadt yp_unbind(dom)
378 1.16 christos const char *dom;
379 1.1 deraadt {
380 1.1 deraadt struct dom_binding *ypb, *ypbp;
381 1.1 deraadt
382 1.1 deraadt ypbp = NULL;
383 1.16 christos for (ypb = _ypbindlist; ypb; ypb = ypb->dom_pnext) {
384 1.16 christos if (strcmp(dom, ypb->dom_domain) == 0) {
385 1.1 deraadt clnt_destroy(ypb->dom_client);
386 1.16 christos if (ypbp)
387 1.1 deraadt ypbp->dom_pnext = ypb->dom_pnext;
388 1.1 deraadt else
389 1.1 deraadt _ypbindlist = ypb->dom_pnext;
390 1.1 deraadt free(ypb);
391 1.1 deraadt return;
392 1.1 deraadt }
393 1.1 deraadt ypbp = ypb;
394 1.1 deraadt }
395 1.1 deraadt return;
396 1.1 deraadt }
397 1.1 deraadt
398 1.1 deraadt int
399 1.1 deraadt yp_match(indomain, inmap, inkey, inkeylen, outval, outvallen)
400 1.16 christos const char *indomain;
401 1.16 christos const char *inmap;
402 1.16 christos const char *inkey;
403 1.16 christos int inkeylen;
404 1.16 christos char **outval;
405 1.16 christos int *outvallen;
406 1.1 deraadt {
407 1.1 deraadt struct dom_binding *ysd;
408 1.1 deraadt struct ypresp_val yprv;
409 1.16 christos struct timeval tv;
410 1.1 deraadt struct ypreq_key yprk;
411 1.16 christos int r;
412 1.1 deraadt
413 1.1 deraadt *outval = NULL;
414 1.1 deraadt *outvallen = 0;
415 1.1 deraadt
416 1.1 deraadt again:
417 1.16 christos if (_yp_dobind(indomain, &ysd) != 0)
418 1.1 deraadt return YPERR_DOMAIN;
419 1.1 deraadt
420 1.1 deraadt #ifdef YPMATCHCACHE
421 1.16 christos if (!strcmp(_yp_domain, indomain) && ypmatch_find(inmap, inkey,
422 1.16 christos inkeylen, &yprv.valdat.dptr, &yprv.valdat.dsize)) {
423 1.1 deraadt *outvallen = yprv.valdat.dsize;
424 1.16 christos if ((*outval = malloc(*outvallen + 1)) == NULL)
425 1.16 christos return YPERR_YPERR;
426 1.16 christos (void)memcpy(*outval, yprv.valdat.dptr, *outvallen);
427 1.1 deraadt (*outval)[*outvallen] = '\0';
428 1.1 deraadt return 0;
429 1.1 deraadt }
430 1.1 deraadt #endif
431 1.1 deraadt
432 1.1 deraadt tv.tv_sec = _yplib_timeout;
433 1.1 deraadt tv.tv_usec = 0;
434 1.1 deraadt
435 1.1 deraadt yprk.domain = indomain;
436 1.1 deraadt yprk.map = inmap;
437 1.16 christos yprk.keydat.dptr = (char *) inkey;
438 1.1 deraadt yprk.keydat.dsize = inkeylen;
439 1.1 deraadt
440 1.9 jtc memset(&yprv, 0, sizeof yprv);
441 1.1 deraadt
442 1.1 deraadt r = clnt_call(ysd->dom_client, YPPROC_MATCH,
443 1.16 christos xdr_ypreq_key, &yprk, xdr_ypresp_val, &yprv, tv);
444 1.16 christos if (r != RPC_SUCCESS) {
445 1.1 deraadt clnt_perror(ysd->dom_client, "yp_match: clnt_call");
446 1.1 deraadt ysd->dom_vers = -1;
447 1.1 deraadt goto again;
448 1.1 deraadt }
449 1.16 christos if (!(r = ypprot_err(yprv.status))) {
450 1.1 deraadt *outvallen = yprv.valdat.dsize;
451 1.16 christos if ((*outval = malloc(*outvallen + 1)) == NULL)
452 1.16 christos return YPERR_YPERR;
453 1.16 christos (void)memcpy(*outval, yprv.valdat.dptr, *outvallen);
454 1.1 deraadt (*outval)[*outvallen] = '\0';
455 1.1 deraadt #ifdef YPMATCHCACHE
456 1.16 christos if (strcmp(_yp_domain, indomain) == 0)
457 1.16 christos if (!ypmatch_add(inmap, inkey, inkeylen,
458 1.16 christos *outval, *outvallen))
459 1.16 christos r = RPC_SYSTEMERROR;
460 1.1 deraadt #endif
461 1.1 deraadt }
462 1.16 christos xdr_free(xdr_ypresp_val, (char *) &yprv);
463 1.1 deraadt _yp_unbind(ysd);
464 1.1 deraadt return r;
465 1.1 deraadt }
466 1.1 deraadt
467 1.1 deraadt int
468 1.1 deraadt yp_get_default_domain(domp)
469 1.16 christos char **domp;
470 1.1 deraadt {
471 1.1 deraadt *domp = NULL;
472 1.16 christos if (_yp_domain[0] == '\0')
473 1.16 christos if (getdomainname(_yp_domain, sizeof _yp_domain))
474 1.1 deraadt return YPERR_NODOM;
475 1.1 deraadt *domp = _yp_domain;
476 1.1 deraadt return 0;
477 1.1 deraadt }
478 1.1 deraadt
479 1.1 deraadt int
480 1.1 deraadt yp_first(indomain, inmap, outkey, outkeylen, outval, outvallen)
481 1.16 christos const char *indomain;
482 1.16 christos const char *inmap;
483 1.16 christos char **outkey;
484 1.16 christos int *outkeylen;
485 1.16 christos char **outval;
486 1.16 christos int *outvallen;
487 1.1 deraadt {
488 1.1 deraadt struct ypresp_key_val yprkv;
489 1.1 deraadt struct ypreq_nokey yprnk;
490 1.1 deraadt struct dom_binding *ysd;
491 1.16 christos struct timeval tv;
492 1.16 christos int r;
493 1.1 deraadt
494 1.1 deraadt *outkey = *outval = NULL;
495 1.1 deraadt *outkeylen = *outvallen = 0;
496 1.1 deraadt
497 1.1 deraadt again:
498 1.16 christos if (_yp_dobind(indomain, &ysd) != 0)
499 1.1 deraadt return YPERR_DOMAIN;
500 1.1 deraadt
501 1.1 deraadt tv.tv_sec = _yplib_timeout;
502 1.1 deraadt tv.tv_usec = 0;
503 1.1 deraadt
504 1.1 deraadt yprnk.domain = indomain;
505 1.1 deraadt yprnk.map = inmap;
506 1.16 christos (void)memset(&yprkv, 0, sizeof yprkv);
507 1.1 deraadt
508 1.1 deraadt r = clnt_call(ysd->dom_client, YPPROC_FIRST,
509 1.16 christos xdr_ypreq_nokey, &yprnk, xdr_ypresp_key_val, &yprkv, tv);
510 1.16 christos if (r != RPC_SUCCESS) {
511 1.1 deraadt clnt_perror(ysd->dom_client, "yp_first: clnt_call");
512 1.1 deraadt ysd->dom_vers = -1;
513 1.1 deraadt goto again;
514 1.1 deraadt }
515 1.16 christos if (!(r = ypprot_err(yprkv.status))) {
516 1.1 deraadt *outkeylen = yprkv.keydat.dsize;
517 1.16 christos if ((*outkey = malloc(*outkeylen + 1)) == NULL)
518 1.16 christos r = RPC_SYSTEMERROR;
519 1.16 christos else {
520 1.16 christos (void)memcpy(*outkey, yprkv.keydat.dptr, *outkeylen);
521 1.16 christos (*outkey)[*outkeylen] = '\0';
522 1.16 christos }
523 1.1 deraadt *outvallen = yprkv.valdat.dsize;
524 1.16 christos if ((*outval = malloc(*outvallen + 1)) == NULL)
525 1.16 christos r = RPC_SYSTEMERROR;
526 1.16 christos else {
527 1.16 christos (void)memcpy(*outval, yprkv.valdat.dptr, *outvallen);
528 1.16 christos (*outval)[*outvallen] = '\0';
529 1.16 christos }
530 1.1 deraadt }
531 1.16 christos xdr_free(xdr_ypresp_key_val, (char *) &yprkv);
532 1.1 deraadt _yp_unbind(ysd);
533 1.1 deraadt return r;
534 1.1 deraadt }
535 1.1 deraadt
536 1.1 deraadt int
537 1.1 deraadt yp_next(indomain, inmap, inkey, inkeylen, outkey, outkeylen, outval, outvallen)
538 1.16 christos const char *indomain;
539 1.16 christos const char *inmap;
540 1.16 christos const char *inkey;
541 1.16 christos int inkeylen;
542 1.16 christos char **outkey;
543 1.16 christos int *outkeylen;
544 1.16 christos char **outval;
545 1.16 christos int *outvallen;
546 1.1 deraadt {
547 1.1 deraadt struct ypresp_key_val yprkv;
548 1.1 deraadt struct ypreq_key yprk;
549 1.1 deraadt struct dom_binding *ysd;
550 1.16 christos struct timeval tv;
551 1.16 christos int r;
552 1.1 deraadt
553 1.1 deraadt *outkey = *outval = NULL;
554 1.1 deraadt *outkeylen = *outvallen = 0;
555 1.1 deraadt
556 1.1 deraadt again:
557 1.16 christos if (_yp_dobind(indomain, &ysd) != 0)
558 1.1 deraadt return YPERR_DOMAIN;
559 1.1 deraadt
560 1.1 deraadt tv.tv_sec = _yplib_timeout;
561 1.1 deraadt tv.tv_usec = 0;
562 1.1 deraadt
563 1.1 deraadt yprk.domain = indomain;
564 1.1 deraadt yprk.map = inmap;
565 1.1 deraadt yprk.keydat.dptr = inkey;
566 1.1 deraadt yprk.keydat.dsize = inkeylen;
567 1.16 christos (void)memset(&yprkv, 0, sizeof yprkv);
568 1.1 deraadt
569 1.1 deraadt r = clnt_call(ysd->dom_client, YPPROC_NEXT,
570 1.16 christos xdr_ypreq_key, &yprk, xdr_ypresp_key_val, &yprkv, tv);
571 1.16 christos if (r != RPC_SUCCESS) {
572 1.1 deraadt clnt_perror(ysd->dom_client, "yp_next: clnt_call");
573 1.1 deraadt ysd->dom_vers = -1;
574 1.1 deraadt goto again;
575 1.1 deraadt }
576 1.16 christos if (!(r = ypprot_err(yprkv.status))) {
577 1.1 deraadt *outkeylen = yprkv.keydat.dsize;
578 1.16 christos if ((*outkey = malloc(*outkeylen + 1)) == NULL)
579 1.16 christos r = RPC_SYSTEMERROR;
580 1.16 christos else {
581 1.16 christos (void)memcpy(*outkey, yprkv.keydat.dptr, *outkeylen);
582 1.16 christos (*outkey)[*outkeylen] = '\0';
583 1.16 christos }
584 1.1 deraadt *outvallen = yprkv.valdat.dsize;
585 1.16 christos if ((*outval = malloc(*outvallen + 1)) == NULL)
586 1.16 christos r = RPC_SYSTEMERROR;
587 1.16 christos else {
588 1.16 christos (void)memcpy(*outval, yprkv.valdat.dptr, *outvallen);
589 1.16 christos (*outval)[*outvallen] = '\0';
590 1.16 christos }
591 1.1 deraadt }
592 1.16 christos xdr_free(xdr_ypresp_key_val, (char *) &yprkv);
593 1.1 deraadt _yp_unbind(ysd);
594 1.1 deraadt return r;
595 1.1 deraadt }
596 1.1 deraadt
597 1.1 deraadt int
598 1.1 deraadt yp_all(indomain, inmap, incallback)
599 1.16 christos const char *indomain;
600 1.16 christos const char *inmap;
601 1.16 christos struct ypall_callback *incallback;
602 1.1 deraadt {
603 1.1 deraadt struct ypreq_nokey yprnk;
604 1.1 deraadt struct dom_binding *ysd;
605 1.16 christos struct timeval tv;
606 1.1 deraadt struct sockaddr_in clnt_sin;
607 1.16 christos CLIENT *clnt;
608 1.16 christos u_long status;
609 1.16 christos int clnt_sock;
610 1.1 deraadt
611 1.16 christos if (_yp_dobind(indomain, &ysd) != 0)
612 1.1 deraadt return YPERR_DOMAIN;
613 1.1 deraadt
614 1.1 deraadt tv.tv_sec = _yplib_timeout;
615 1.1 deraadt tv.tv_usec = 0;
616 1.1 deraadt clnt_sock = RPC_ANYSOCK;
617 1.1 deraadt clnt_sin = ysd->dom_server_addr;
618 1.1 deraadt clnt_sin.sin_port = 0;
619 1.1 deraadt clnt = clnttcp_create(&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
620 1.16 christos if (clnt == NULL) {
621 1.1 deraadt printf("clnttcp_create failed\n");
622 1.1 deraadt return YPERR_PMAP;
623 1.1 deraadt }
624 1.1 deraadt yprnk.domain = indomain;
625 1.1 deraadt yprnk.map = inmap;
626 1.1 deraadt ypresp_allfn = incallback->foreach;
627 1.16 christos ypresp_data = (void *) incallback->data;
628 1.1 deraadt
629 1.1 deraadt (void) clnt_call(clnt, YPPROC_ALL,
630 1.16 christos xdr_ypreq_nokey, &yprnk, xdr_ypresp_all_seq, &status, tv);
631 1.1 deraadt clnt_destroy(clnt);
632 1.16 christos /* not really needed... */
633 1.16 christos xdr_free(xdr_ypresp_all_seq, (char *) &status);
634 1.1 deraadt _yp_unbind(ysd);
635 1.1 deraadt
636 1.16 christos if (status != YP_FALSE)
637 1.1 deraadt return ypprot_err(status);
638 1.1 deraadt return 0;
639 1.1 deraadt }
640 1.1 deraadt
641 1.1 deraadt int
642 1.1 deraadt yp_order(indomain, inmap, outorder)
643 1.16 christos const char *indomain;
644 1.16 christos const char *inmap;
645 1.16 christos int *outorder;
646 1.1 deraadt {
647 1.16 christos struct dom_binding *ysd;
648 1.1 deraadt struct ypresp_order ypro;
649 1.1 deraadt struct ypreq_nokey yprnk;
650 1.16 christos struct timeval tv;
651 1.16 christos int r;
652 1.1 deraadt
653 1.1 deraadt again:
654 1.16 christos if (_yp_dobind(indomain, &ysd) != 0)
655 1.1 deraadt return YPERR_DOMAIN;
656 1.1 deraadt
657 1.1 deraadt tv.tv_sec = _yplib_timeout;
658 1.1 deraadt tv.tv_usec = 0;
659 1.1 deraadt
660 1.1 deraadt yprnk.domain = indomain;
661 1.1 deraadt yprnk.map = inmap;
662 1.1 deraadt
663 1.16 christos (void)memset(&ypro, 0, sizeof ypro);
664 1.1 deraadt
665 1.1 deraadt r = clnt_call(ysd->dom_client, YPPROC_ORDER,
666 1.16 christos xdr_ypreq_nokey, &yprnk, xdr_ypresp_order, &ypro, tv);
667 1.16 christos if (r != RPC_SUCCESS) {
668 1.18 christos clnt_perror(ysd->dom_client, "yp_order: clnt_call");
669 1.18 christos if (r == RPC_PROCUNAVAIL) {
670 1.18 christos /* Case of NIS+ server in NIS compat mode */
671 1.18 christos r = YPERR_YPERR;
672 1.18 christos goto bail;
673 1.18 christos }
674 1.1 deraadt ysd->dom_vers = -1;
675 1.1 deraadt goto again;
676 1.1 deraadt }
677 1.1 deraadt *outorder = ypro.ordernum;
678 1.16 christos xdr_free(xdr_ypresp_order, (char *) &ypro);
679 1.18 christos r = ypprot_err(ypro.status);
680 1.18 christos bail:
681 1.1 deraadt _yp_unbind(ysd);
682 1.18 christos return r;
683 1.1 deraadt }
684 1.1 deraadt
685 1.5 deraadt int
686 1.1 deraadt yp_master(indomain, inmap, outname)
687 1.16 christos const char *indomain;
688 1.16 christos const char *inmap;
689 1.16 christos char **outname;
690 1.1 deraadt {
691 1.1 deraadt struct dom_binding *ysd;
692 1.1 deraadt struct ypresp_master yprm;
693 1.1 deraadt struct ypreq_nokey yprnk;
694 1.16 christos struct timeval tv;
695 1.16 christos int r;
696 1.1 deraadt
697 1.1 deraadt again:
698 1.16 christos if (_yp_dobind(indomain, &ysd) != 0)
699 1.1 deraadt return YPERR_DOMAIN;
700 1.1 deraadt
701 1.1 deraadt tv.tv_sec = _yplib_timeout;
702 1.1 deraadt tv.tv_usec = 0;
703 1.1 deraadt
704 1.1 deraadt yprnk.domain = indomain;
705 1.1 deraadt yprnk.map = inmap;
706 1.1 deraadt
707 1.16 christos (void)memset(&yprm, 0, sizeof yprm);
708 1.1 deraadt
709 1.1 deraadt r = clnt_call(ysd->dom_client, YPPROC_MASTER,
710 1.16 christos xdr_ypreq_nokey, &yprnk, xdr_ypresp_master, &yprm, tv);
711 1.16 christos if (r != RPC_SUCCESS) {
712 1.1 deraadt clnt_perror(ysd->dom_client, "yp_master: clnt_call");
713 1.1 deraadt ysd->dom_vers = -1;
714 1.1 deraadt goto again;
715 1.1 deraadt }
716 1.16 christos if (!(r = ypprot_err(yprm.status))) {
717 1.16 christos if ((*outname = strdup(yprm.master)) == NULL)
718 1.16 christos r = RPC_SYSTEMERROR;
719 1.1 deraadt }
720 1.16 christos xdr_free(xdr_ypresp_master, (char *) &yprm);
721 1.1 deraadt _yp_unbind(ysd);
722 1.1 deraadt return r;
723 1.1 deraadt }
724 1.1 deraadt
725 1.16 christos int
726 1.1 deraadt yp_maplist(indomain, outmaplist)
727 1.16 christos const char *indomain;
728 1.16 christos struct ypmaplist **outmaplist;
729 1.1 deraadt {
730 1.1 deraadt struct dom_binding *ysd;
731 1.1 deraadt struct ypresp_maplist ypml;
732 1.16 christos struct timeval tv;
733 1.16 christos int r;
734 1.1 deraadt
735 1.1 deraadt again:
736 1.16 christos if (_yp_dobind(indomain, &ysd) != 0)
737 1.1 deraadt return YPERR_DOMAIN;
738 1.1 deraadt
739 1.1 deraadt tv.tv_sec = _yplib_timeout;
740 1.1 deraadt tv.tv_usec = 0;
741 1.1 deraadt
742 1.9 jtc memset(&ypml, 0, sizeof ypml);
743 1.1 deraadt
744 1.1 deraadt r = clnt_call(ysd->dom_client, YPPROC_MAPLIST,
745 1.16 christos xdr_domainname, indomain, xdr_ypresp_maplist, &ypml, tv);
746 1.1 deraadt if (r != RPC_SUCCESS) {
747 1.1 deraadt clnt_perror(ysd->dom_client, "yp_maplist: clnt_call");
748 1.1 deraadt ysd->dom_vers = -1;
749 1.1 deraadt goto again;
750 1.1 deraadt }
751 1.1 deraadt *outmaplist = ypml.list;
752 1.16 christos /* NO: xdr_free(xdr_ypresp_maplist, &ypml); */
753 1.1 deraadt _yp_unbind(ysd);
754 1.1 deraadt return ypprot_err(ypml.status);
755 1.1 deraadt }
756 1.1 deraadt
757 1.1 deraadt int
758 1.1 deraadt ypprot_err(incode)
759 1.16 christos unsigned int incode;
760 1.1 deraadt {
761 1.16 christos switch (incode) {
762 1.1 deraadt case YP_TRUE:
763 1.1 deraadt return 0;
764 1.1 deraadt case YP_FALSE:
765 1.1 deraadt return YPERR_YPBIND;
766 1.1 deraadt case YP_NOMORE:
767 1.1 deraadt return YPERR_NOMORE;
768 1.1 deraadt case YP_NOMAP:
769 1.1 deraadt return YPERR_MAP;
770 1.1 deraadt case YP_NODOM:
771 1.1 deraadt return YPERR_NODOM;
772 1.1 deraadt case YP_NOKEY:
773 1.1 deraadt return YPERR_KEY;
774 1.1 deraadt case YP_BADOP:
775 1.1 deraadt return YPERR_YPERR;
776 1.1 deraadt case YP_BADDB:
777 1.1 deraadt return YPERR_BADDB;
778 1.1 deraadt case YP_YPERR:
779 1.1 deraadt return YPERR_YPERR;
780 1.1 deraadt case YP_BADARGS:
781 1.1 deraadt return YPERR_BADARGS;
782 1.1 deraadt case YP_VERS:
783 1.1 deraadt return YPERR_VERS;
784 1.1 deraadt }
785 1.1 deraadt return YPERR_YPERR;
786 1.1 deraadt }
787 1.1 deraadt
788 1.1 deraadt int
789 1.1 deraadt _yp_check(dom)
790 1.16 christos char **dom;
791 1.1 deraadt {
792 1.16 christos char *unused;
793 1.1 deraadt
794 1.16 christos if (_yp_domain[0] == '\0')
795 1.16 christos if (yp_get_default_domain(&unused))
796 1.1 deraadt return 0;
797 1.1 deraadt
798 1.16 christos if (dom)
799 1.1 deraadt *dom = _yp_domain;
800 1.1 deraadt
801 1.16 christos if (yp_bind(_yp_domain) == 0)
802 1.1 deraadt return 1;
803 1.1 deraadt return 0;
804 1.1 deraadt }
805