Libinfo-517.200.9.tar.gz
[apple/libinfo.git] / nis.subproj / ypmatch_cache.c
1 /*
2 * Copyright (c) 1999-2018 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@theos.com>
26 * All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by Theo de Raadt.
39 * 4. The name of the author may not be used to endorse or promote products
40 * derived from this software without specific prior written permission.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
43 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
44 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
46 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * SUCH DAMAGE.
53 */
54
55 #if defined(LIBC_SCCS) && !defined(lint)
56 static char *rcsid = "$OpenBSD: ypmatch_cache.c,v 1.6 1996/12/03 08:20:06 deraadt Exp $";
57 #endif /* LIBC_SCCS and not lint */
58
59 #include "libinfo_common.h"
60
61 #include <sys/param.h>
62 #include <sys/types.h>
63 #include <sys/socket.h>
64 #include <sys/file.h>
65 #include <sys/uio.h>
66 #include <errno.h>
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #include <unistd.h>
71 #include <rpc/rpc.h>
72 #include <rpc/xdr.h>
73 #include <rpcsvc/yp.h>
74 #include <rpcsvc/ypclnt.h>
75 /* #define YPMATCHCACHE */
76 #include "ypinternal.h"
77
78 int _yplib_cache = 5;
79
80 #ifdef YPMATCHCACHE
81 static bool_t
82 ypmatch_add(map, key, keylen, val, vallen)
83 const char *map;
84 const char *key;
85 u_int keylen;
86 char *val;
87 u_int vallen;
88 {
89 struct ypmatch_ent *ep;
90 time_t t;
91
92 (void)time(&t);
93
94 for (ep = ypmc; ep; ep = ep->next)
95 if (ep->expire_t < t)
96 break;
97 if (ep == NULL) {
98 if ((ep = malloc(sizeof *ep)) == NULL)
99 return 0;
100 (void)memset(ep, 0, sizeof *ep);
101 if (ypmc)
102 ep->next = ypmc;
103 ypmc = ep;
104 }
105
106 if (ep->key) {
107 free(ep->key);
108 ep->key = NULL;
109 }
110 if (ep->val) {
111 free(ep->val);
112 ep->val = NULL;
113 }
114
115 if ((ep->key = malloc(keylen)) == NULL)
116 return 0;
117
118 if ((ep->val = malloc(vallen)) == NULL) {
119 free(ep->key);
120 ep->key = NULL;
121 return 0;
122 }
123
124 ep->keylen = keylen;
125 ep->vallen = vallen;
126
127 (void)memcpy(ep->key, key, ep->keylen);
128 (void)memcpy(ep->val, val, ep->vallen);
129
130 if (ep->map) {
131 if (strcmp(ep->map, map)) {
132 free(ep->map);
133 if ((ep->map = strdup(map)) == NULL)
134 return 0;
135 }
136 } else {
137 if ((ep->map = strdup(map)) == NULL)
138 return 0;
139 }
140
141 ep->expire_t = t + _yplib_cache;
142 return 1;
143 }
144
145 static bool_t
146 ypmatch_find(map, key, keylen, val, vallen)
147 const char *map;
148 const char *key;
149 u_int keylen;
150 char **val;
151 u_int *vallen;
152 {
153 struct ypmatch_ent *ep;
154 time_t t;
155
156 if (ypmc == NULL)
157 return 0;
158
159 (void) time(&t);
160
161 for (ep = ypmc; ep; ep = ep->next) {
162 if (ep->keylen != keylen)
163 continue;
164 if (strcmp(ep->map, map))
165 continue;
166 if (memcmp(ep->key, key, keylen))
167 continue;
168 if (t > ep->expire_t)
169 continue;
170
171 *val = ep->val;
172 *vallen = ep->vallen;
173 return 1;
174 }
175 return 0;
176 }
177 #endif
178
179 LIBINFO_EXPORT
180 int
181 yp_match(indomain, inmap, inkey, inkeylen, outval, outvallen)
182 const char *indomain;
183 const char *inmap;
184 const char *inkey;
185 int inkeylen;
186 char **outval;
187 int *outvallen;
188 {
189 struct dom_binding *ysd;
190 struct ypresp_val yprv;
191 struct timeval tv;
192 struct ypreq_key yprk;
193 int tries = 0, r;
194 static int proto = YP_BIND_UDP;
195
196 if (indomain == NULL || *indomain == '\0' ||
197 strlen(indomain) > YPMAXDOMAIN || inmap == NULL ||
198 *inmap == '\0' || strlen(inmap) > YPMAXMAP ||
199 inkey == NULL || inkeylen == 0)
200 return YPERR_BADARGS;
201
202 *outval = NULL;
203 *outvallen = 0;
204
205 again:
206 if (_yp_dobind(indomain, &ysd) != 0)
207 return YPERR_DOMAIN;
208
209 #ifdef YPMATCHCACHE
210 if (!strcmp(_yp_domain, indomain) && ypmatch_find(inmap, inkey,
211 inkeylen, &yprv.val.valdat_val, &yprv.val.valdat_len)) {
212 *outvallen = yprv.val.valdat_len;
213 if ((*outval = malloc(*outvallen + 1)) == NULL) {
214 _yp_unbind(ysd);
215 return YPERR_YPERR;
216 }
217 (void)memcpy(*outval, yprv.val.valdat_val, *outvallen);
218 (*outval)[*outvallen] = '\0';
219 _yp_unbind(ysd);
220 return 0;
221 }
222 #endif
223
224 tv.tv_sec = _yplib_timeout;
225 tv.tv_usec = 0;
226
227 yprk.domain = (char *)indomain;
228 yprk.map = (char *)inmap;
229 yprk.key.keydat_val = (char *) inkey;
230 yprk.key.keydat_len = inkeylen;
231
232 memset(&yprv, 0, sizeof yprv);
233
234 r = clnt_call(ysd->dom_client, YPPROC_MATCH, (xdrproc_t)xdr_ypreq_key, &yprk, (xdrproc_t)xdr_ypresp_val, &yprv, tv);
235 if (r != RPC_SUCCESS)
236 {
237 /* call failed - switch protocols and try again */
238 if (tries++) clnt_perror(ysd->dom_client, "yp_match: clnt_call");
239
240 if (proto == YP_BIND_UDP) proto = YP_BIND_TCP;
241 else proto = YP_BIND_UDP;
242 ysd->dom_vers = proto;
243
244 goto again;
245 }
246
247 if (!(r = ypprot_err(yprv.stat))) {
248 *outvallen = yprv.val.valdat_len;
249 if ((*outval = malloc(*outvallen + 1)) == NULL) {
250 r = YPERR_YPERR;
251 goto out;
252 }
253 (void)memcpy(*outval, yprv.val.valdat_val, *outvallen);
254 (*outval)[*outvallen] = '\0';
255 #ifdef YPMATCHCACHE
256 if (strcmp(_yp_domain, indomain) == 0)
257 if (!ypmatch_add(inmap, inkey, inkeylen,
258 *outval, *outvallen))
259 r = YPERR_RESRC;
260 #endif
261 }
262 out:
263 xdr_free((xdrproc_t)xdr_ypresp_val, (char *) &yprv);
264 _yp_unbind(ysd);
265 return r;
266 }
267
268 LIBINFO_EXPORT
269 int
270 yp_next(indomain, inmap, inkey, inkeylen, outkey, outkeylen, outval, outvallen)
271 const char *indomain;
272 const char *inmap;
273 const char *inkey;
274 int inkeylen;
275 char **outkey;
276 int *outkeylen;
277 char **outval;
278 int *outvallen;
279 {
280 struct ypresp_key_val yprkv;
281 struct ypreq_key yprk;
282 struct dom_binding *ysd;
283 struct timeval tv;
284 int tries = 0, r;
285 static int proto = YP_BIND_UDP;
286
287 if (indomain == NULL || *indomain == '\0' ||
288 strlen(indomain) > YPMAXDOMAIN || inmap == NULL ||
289 *inmap == '\0' || strlen(inmap) > YPMAXMAP)
290 return YPERR_BADARGS;
291
292 *outkey = *outval = NULL;
293 *outkeylen = *outvallen = 0;
294
295 again:
296 if (_yp_dobind(indomain, &ysd) != 0)
297 return YPERR_DOMAIN;
298
299 tv.tv_sec = _yplib_timeout;
300 tv.tv_usec = 0;
301
302 yprk.domain = (char *)indomain;
303 yprk.map = (char *)inmap;
304 yprk.key.keydat_val = (char *)inkey;
305 yprk.key.keydat_len = inkeylen;
306 (void)memset(&yprkv, 0, sizeof yprkv);
307
308 r = clnt_call(ysd->dom_client, YPPROC_NEXT, (xdrproc_t)xdr_ypreq_key, &yprk, (xdrproc_t)xdr_ypresp_key_val, &yprkv, tv);
309 if (r != RPC_SUCCESS)
310 {
311 /* call failed - switch protocols and try again */
312 if (tries++) clnt_perror(ysd->dom_client, "yp_next: clnt_call");
313
314 if (proto == YP_BIND_UDP) proto = YP_BIND_TCP;
315 else proto = YP_BIND_UDP;
316 ysd->dom_vers = proto;
317
318 goto again;
319 }
320
321 if (!(r = ypprot_err(yprkv.stat))) {
322 *outkeylen = yprkv.key.keydat_len;
323 if ((*outkey = malloc(*outkeylen + 1)) == NULL)
324 r = YPERR_RESRC;
325 else {
326 (void)memcpy(*outkey, yprkv.key.keydat_val, *outkeylen);
327 (*outkey)[*outkeylen] = '\0';
328 }
329 *outvallen = yprkv.val.valdat_len;
330 if ((*outval = malloc(*outvallen + 1)) == NULL)
331 r = YPERR_RESRC;
332 else {
333 (void)memcpy(*outval, yprkv.val.valdat_val, *outvallen);
334 (*outval)[*outvallen] = '\0';
335 }
336 }
337 xdr_free((xdrproc_t)xdr_ypresp_key_val, (char *) &yprkv);
338 _yp_unbind(ysd);
339 return r;
340 }