GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libc/yp/ypmatch_cache.c Lines: 0 75 0.0 %
Date: 2017-11-13 Branches: 0 42 0.0 %

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