1 /* $NetBSD: yp_match.c,v 1.7 1997/07/07 02:00:37 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993 Theo de Raadt <deraadt@fsa.ca> 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) 35 static char rcsid[] = "$NetBSD: yp_match.c,v 1.7 1997/07/07 02:00:37 lukem Exp $"; 36 #endif 37 38 #include <stdlib.h> 39 #include <string.h> 40 #include <rpc/rpc.h> 41 #include <rpcsvc/yp_prot.h> 42 #include <rpcsvc/ypclnt.h> 43 44 #define YPMATCHCACHE 45 46 extern struct timeval _yplib_timeout; 47 extern int _yplib_nerrs; 48 extern char _yp_domain[]; 49 50 #ifdef YPMATCHCACHE 51 int _yplib_cache = 5; 52 53 static struct ypmatch_ent { 54 struct ypmatch_ent *next; 55 char *map, *key; 56 char *val; 57 int keylen, vallen; 58 time_t expire_t; 59 } *ypmc; 60 61 static bool_t 62 ypmatch_add(map, key, keylen, val, vallen) 63 const char *map; 64 const char *key; 65 int keylen; 66 char *val; 67 int vallen; 68 { 69 struct ypmatch_ent *ep; 70 time_t t; 71 72 (void)time(&t); 73 74 for (ep = ypmc; ep; ep = ep->next) 75 if (ep->expire_t < t) 76 break; 77 if (ep == NULL) { 78 if ((ep = malloc(sizeof *ep)) == NULL) 79 return 0; 80 (void)memset(ep, 0, sizeof *ep); 81 if (ypmc) 82 ep->next = ypmc; 83 ypmc = ep; 84 } 85 86 if (ep->key) { 87 free(ep->key); 88 ep->key = NULL; 89 } 90 if (ep->val) { 91 free(ep->val); 92 ep->val = NULL; 93 } 94 95 if ((ep->key = malloc(keylen)) == NULL) 96 return 0; 97 98 if ((ep->val = malloc(vallen)) == NULL) { 99 free(ep->key); 100 ep->key = NULL; 101 return 0; 102 } 103 104 ep->keylen = keylen; 105 ep->vallen = vallen; 106 107 (void)memcpy(ep->key, key, ep->keylen); 108 (void)memcpy(ep->val, val, ep->vallen); 109 110 if (ep->map) { 111 if (strcmp(ep->map, map)) { 112 free(ep->map); 113 if ((ep->map = strdup(map)) == NULL) 114 return 0; 115 } 116 } else { 117 if ((ep->map = strdup(map)) == NULL) 118 return 0; 119 } 120 121 ep->expire_t = t + _yplib_cache; 122 return 1; 123 } 124 125 static bool_t 126 ypmatch_find(map, key, keylen, val, vallen) 127 const char *map; 128 const char *key; 129 int keylen; 130 const char **val; 131 int *vallen; 132 { 133 struct ypmatch_ent *ep; 134 time_t t; 135 136 if (ypmc == NULL) 137 return 0; 138 139 (void) time(&t); 140 141 for (ep = ypmc; ep; ep = ep->next) { 142 if (ep->keylen != keylen) 143 continue; 144 if (strcmp(ep->map, map)) 145 continue; 146 if (memcmp(ep->key, key, keylen)) 147 continue; 148 if (t > ep->expire_t) 149 continue; 150 151 *val = ep->val; 152 *vallen = ep->vallen; 153 return 1; 154 } 155 return 0; 156 } 157 #endif 158 159 int 160 yp_match(indomain, inmap, inkey, inkeylen, outval, outvallen) 161 const char *indomain; 162 const char *inmap; 163 const char *inkey; 164 int inkeylen; 165 char **outval; 166 int *outvallen; 167 { 168 struct dom_binding *ysd; 169 struct ypresp_val yprv; 170 struct ypreq_key yprk; 171 int r, nerrs = 0; 172 173 if (outval == NULL) 174 return YPERR_BADARGS; 175 *outval = NULL; 176 *outvallen = 0; 177 178 if (_yp_invalid_domain(indomain)) 179 return YPERR_BADARGS; 180 if (inmap == NULL || *inmap == '\0' 181 || strlen(inmap) > YPMAXMAP) 182 return YPERR_BADARGS; 183 if (inkey == NULL || inkeylen == 0) 184 return YPERR_BADARGS; 185 186 again: 187 if (_yp_dobind(indomain, &ysd) != 0) 188 return YPERR_DOMAIN; 189 190 #ifdef YPMATCHCACHE 191 if (!strcmp(_yp_domain, indomain) && ypmatch_find(inmap, inkey, 192 inkeylen, &yprv.valdat.dptr, &yprv.valdat.dsize)) { 193 *outvallen = yprv.valdat.dsize; 194 if ((*outval = malloc(*outvallen + 1)) == NULL) 195 return YPERR_YPERR; 196 (void)memcpy(*outval, yprv.valdat.dptr, *outvallen); 197 (*outval)[*outvallen] = '\0'; 198 return 0; 199 } 200 #endif 201 202 yprk.domain = indomain; 203 yprk.map = inmap; 204 yprk.keydat.dptr = (char *) inkey; 205 yprk.keydat.dsize = inkeylen; 206 207 memset(&yprv, 0, sizeof yprv); 208 209 r = clnt_call(ysd->dom_client, YPPROC_MATCH, 210 xdr_ypreq_key, &yprk, xdr_ypresp_val, &yprv, 211 _yplib_timeout); 212 if (r != RPC_SUCCESS) { 213 if (++nerrs == _yplib_nerrs) { 214 clnt_perror(ysd->dom_client, "yp_match: clnt_call"); 215 nerrs = 0; 216 } 217 ysd->dom_vers = -1; 218 goto again; 219 } 220 if (!(r = ypprot_err(yprv.status))) { 221 *outvallen = yprv.valdat.dsize; 222 if ((*outval = malloc(*outvallen + 1)) == NULL) 223 return YPERR_YPERR; 224 (void)memcpy(*outval, yprv.valdat.dptr, *outvallen); 225 (*outval)[*outvallen] = '\0'; 226 #ifdef YPMATCHCACHE 227 if (strcmp(_yp_domain, indomain) == 0) 228 if (!ypmatch_add(inmap, inkey, inkeylen, 229 *outval, *outvallen)) 230 r = YPERR_RESRC; 231 #endif 232 } 233 xdr_free(xdr_ypresp_val, (char *) &yprv); 234 _yp_unbind(ysd); 235 if (r != 0) { 236 if (*outval) { 237 free(*outval); 238 *outval = NULL; 239 } 240 } 241 return r; 242 } 243