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