]>
Commit | Line | Data |
---|---|---|
03fb6eb0 A |
1 | /* |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
ad21edcc A |
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. | |
03fb6eb0 A |
13 | * |
14 | * The Original Code and all software distributed under the License are | |
ad21edcc | 15 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
03fb6eb0 A |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
ad21edcc A |
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. | |
03fb6eb0 A |
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 <sys/param.h> | |
60 | #include <sys/types.h> | |
61 | #include <sys/socket.h> | |
62 | #include <sys/file.h> | |
63 | #include <sys/uio.h> | |
64 | #include <errno.h> | |
65 | #include <stdio.h> | |
66 | #include <stdlib.h> | |
67 | #include <string.h> | |
68 | #include <unistd.h> | |
69 | #include <rpc/rpc.h> | |
70 | #include <rpc/xdr.h> | |
71 | #include <rpcsvc/yp.h> | |
72 | #include <rpcsvc/ypclnt.h> | |
73 | /* #define YPMATCHCACHE */ | |
74 | #include "ypinternal.h" | |
75 | ||
76 | int _yplib_cache = 5; | |
77 | ||
78 | #ifdef YPMATCHCACHE | |
79 | static bool_t | |
80 | ypmatch_add(map, key, keylen, val, vallen) | |
81 | const char *map; | |
82 | const char *key; | |
83 | u_int keylen; | |
84 | char *val; | |
85 | u_int vallen; | |
86 | { | |
87 | struct ypmatch_ent *ep; | |
88 | time_t t; | |
89 | ||
90 | (void)time(&t); | |
91 | ||
92 | for (ep = ypmc; ep; ep = ep->next) | |
93 | if (ep->expire_t < t) | |
94 | break; | |
95 | if (ep == NULL) { | |
96 | if ((ep = malloc(sizeof *ep)) == NULL) | |
97 | return 0; | |
98 | (void)memset(ep, 0, sizeof *ep); | |
99 | if (ypmc) | |
100 | ep->next = ypmc; | |
101 | ypmc = ep; | |
102 | } | |
103 | ||
104 | if (ep->key) { | |
105 | free(ep->key); | |
106 | ep->key = NULL; | |
107 | } | |
108 | if (ep->val) { | |
109 | free(ep->val); | |
110 | ep->val = NULL; | |
111 | } | |
112 | ||
113 | if ((ep->key = malloc(keylen)) == NULL) | |
114 | return 0; | |
115 | ||
116 | if ((ep->val = malloc(vallen)) == NULL) { | |
117 | free(ep->key); | |
118 | ep->key = NULL; | |
119 | return 0; | |
120 | } | |
121 | ||
122 | ep->keylen = keylen; | |
123 | ep->vallen = vallen; | |
124 | ||
125 | (void)memcpy(ep->key, key, ep->keylen); | |
126 | (void)memcpy(ep->val, val, ep->vallen); | |
127 | ||
128 | if (ep->map) { | |
129 | if (strcmp(ep->map, map)) { | |
130 | free(ep->map); | |
131 | if ((ep->map = strdup(map)) == NULL) | |
132 | return 0; | |
133 | } | |
134 | } else { | |
135 | if ((ep->map = strdup(map)) == NULL) | |
136 | return 0; | |
137 | } | |
138 | ||
139 | ep->expire_t = t + _yplib_cache; | |
140 | return 1; | |
141 | } | |
142 | ||
143 | static bool_t | |
144 | ypmatch_find(map, key, keylen, val, vallen) | |
145 | const char *map; | |
146 | const char *key; | |
147 | u_int keylen; | |
148 | char **val; | |
149 | u_int *vallen; | |
150 | { | |
151 | struct ypmatch_ent *ep; | |
152 | time_t t; | |
153 | ||
154 | if (ypmc == NULL) | |
155 | return 0; | |
156 | ||
157 | (void) time(&t); | |
158 | ||
159 | for (ep = ypmc; ep; ep = ep->next) { | |
160 | if (ep->keylen != keylen) | |
161 | continue; | |
162 | if (strcmp(ep->map, map)) | |
163 | continue; | |
164 | if (memcmp(ep->key, key, keylen)) | |
165 | continue; | |
166 | if (t > ep->expire_t) | |
167 | continue; | |
168 | ||
169 | *val = ep->val; | |
170 | *vallen = ep->vallen; | |
171 | return 1; | |
172 | } | |
173 | return 0; | |
174 | } | |
175 | #endif | |
176 | ||
177 | int | |
178 | yp_match(indomain, inmap, inkey, inkeylen, outval, outvallen) | |
179 | const char *indomain; | |
180 | const char *inmap; | |
181 | const char *inkey; | |
182 | int inkeylen; | |
183 | char **outval; | |
184 | int *outvallen; | |
185 | { | |
186 | struct dom_binding *ysd; | |
187 | struct ypresp_val yprv; | |
188 | struct timeval tv; | |
189 | struct ypreq_key yprk; | |
190 | int tries = 0, r; | |
b3dd680f | 191 | static int proto = YP_BIND_UDP; |
03fb6eb0 A |
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 | ||
b3dd680f A |
231 | r = clnt_call(ysd->dom_client, YPPROC_MATCH, (xdrproc_t)xdr_ypreq_key, &yprk, (xdrproc_t)xdr_ypresp_val, &yprv, tv); |
232 | if (r != RPC_SUCCESS) | |
233 | { | |
234 | /* call failed - switch protocols and try again */ | |
235 | if (tries++) clnt_perror(ysd->dom_client, "yp_match: clnt_call"); | |
236 | ||
237 | if (proto == YP_BIND_UDP) proto = YP_BIND_TCP; | |
238 | else proto = YP_BIND_UDP; | |
239 | ysd->dom_vers = proto; | |
240 | ||
03fb6eb0 A |
241 | goto again; |
242 | } | |
b3dd680f | 243 | |
03fb6eb0 A |
244 | if (!(r = ypprot_err(yprv.stat))) { |
245 | *outvallen = yprv.val.valdat_len; | |
246 | if ((*outval = malloc(*outvallen + 1)) == NULL) { | |
247 | r = YPERR_YPERR; | |
248 | goto out; | |
249 | } | |
250 | (void)memcpy(*outval, yprv.val.valdat_val, *outvallen); | |
251 | (*outval)[*outvallen] = '\0'; | |
252 | #ifdef YPMATCHCACHE | |
253 | if (strcmp(_yp_domain, indomain) == 0) | |
254 | if (!ypmatch_add(inmap, inkey, inkeylen, | |
255 | *outval, *outvallen)) | |
256 | r = YPERR_RESRC; | |
257 | #endif | |
258 | } | |
259 | out: | |
b3dd680f | 260 | xdr_free((xdrproc_t)xdr_ypresp_val, (char *) &yprv); |
03fb6eb0 A |
261 | _yp_unbind(ysd); |
262 | return r; | |
263 | } | |
264 | ||
265 | int | |
266 | yp_next(indomain, inmap, inkey, inkeylen, outkey, outkeylen, outval, outvallen) | |
267 | const char *indomain; | |
268 | const char *inmap; | |
269 | const char *inkey; | |
270 | int inkeylen; | |
271 | char **outkey; | |
272 | int *outkeylen; | |
273 | char **outval; | |
274 | int *outvallen; | |
275 | { | |
276 | struct ypresp_key_val yprkv; | |
277 | struct ypreq_key yprk; | |
278 | struct dom_binding *ysd; | |
279 | struct timeval tv; | |
280 | int tries = 0, r; | |
b3dd680f | 281 | static int proto = YP_BIND_UDP; |
03fb6eb0 A |
282 | |
283 | if (indomain == NULL || *indomain == '\0' || | |
284 | strlen(indomain) > YPMAXDOMAIN || inmap == NULL || | |
285 | *inmap == '\0' || strlen(inmap) > YPMAXMAP) | |
286 | return YPERR_BADARGS; | |
287 | ||
288 | *outkey = *outval = NULL; | |
289 | *outkeylen = *outvallen = 0; | |
290 | ||
291 | again: | |
292 | if (_yp_dobind(indomain, &ysd) != 0) | |
293 | return YPERR_DOMAIN; | |
294 | ||
295 | tv.tv_sec = _yplib_timeout; | |
296 | tv.tv_usec = 0; | |
297 | ||
298 | yprk.domain = (char *)indomain; | |
299 | yprk.map = (char *)inmap; | |
300 | yprk.key.keydat_val = (char *)inkey; | |
301 | yprk.key.keydat_len = inkeylen; | |
302 | (void)memset(&yprkv, 0, sizeof yprkv); | |
303 | ||
b3dd680f A |
304 | r = clnt_call(ysd->dom_client, YPPROC_NEXT, (xdrproc_t)xdr_ypreq_key, &yprk, (xdrproc_t)xdr_ypresp_key_val, &yprkv, tv); |
305 | if (r != RPC_SUCCESS) | |
306 | { | |
307 | /* call failed - switch protocols and try again */ | |
308 | if (tries++) clnt_perror(ysd->dom_client, "yp_next: clnt_call"); | |
309 | ||
310 | if (proto == YP_BIND_UDP) proto = YP_BIND_TCP; | |
311 | else proto = YP_BIND_UDP; | |
312 | ysd->dom_vers = proto; | |
313 | ||
03fb6eb0 A |
314 | goto again; |
315 | } | |
b3dd680f | 316 | |
03fb6eb0 A |
317 | if (!(r = ypprot_err(yprkv.stat))) { |
318 | *outkeylen = yprkv.key.keydat_len; | |
319 | if ((*outkey = malloc(*outkeylen + 1)) == NULL) | |
320 | r = YPERR_RESRC; | |
321 | else { | |
322 | (void)memcpy(*outkey, yprkv.key.keydat_val, *outkeylen); | |
323 | (*outkey)[*outkeylen] = '\0'; | |
324 | } | |
325 | *outvallen = yprkv.val.valdat_len; | |
326 | if ((*outval = malloc(*outvallen + 1)) == NULL) | |
327 | r = YPERR_RESRC; | |
328 | else { | |
329 | (void)memcpy(*outval, yprkv.val.valdat_val, *outvallen); | |
330 | (*outval)[*outvallen] = '\0'; | |
331 | } | |
332 | } | |
b3dd680f | 333 | xdr_free((xdrproc_t)xdr_ypresp_key_val, (char *) &yprkv); |
03fb6eb0 A |
334 | _yp_unbind(ysd); |
335 | return r; | |
336 | } |