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