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