1*86d7f5d3SJohn Marino /*-
2*86d7f5d3SJohn Marino * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
3*86d7f5d3SJohn Marino * All rights reserved.
4*86d7f5d3SJohn Marino *
5*86d7f5d3SJohn Marino * Redistribution and use in source and binary forms, with or without
6*86d7f5d3SJohn Marino * modification, are permitted provided that the following conditions
7*86d7f5d3SJohn Marino * are met:
8*86d7f5d3SJohn Marino * 1. Redistributions of source code must retain the above copyright
9*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer.
10*86d7f5d3SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
11*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer in the
12*86d7f5d3SJohn Marino * documentation and/or other materials provided with the distribution.
13*86d7f5d3SJohn Marino *
14*86d7f5d3SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*86d7f5d3SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*86d7f5d3SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*86d7f5d3SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*86d7f5d3SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*86d7f5d3SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*86d7f5d3SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*86d7f5d3SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*86d7f5d3SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*86d7f5d3SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*86d7f5d3SJohn Marino * SUCH DAMAGE.
25*86d7f5d3SJohn Marino *
26*86d7f5d3SJohn Marino * $FreeBSD: src/usr.sbin/nscd/query.c,v 1.5 2008/10/12 00:44:27 delphij Exp $
27*86d7f5d3SJohn Marino */
28*86d7f5d3SJohn Marino
29*86d7f5d3SJohn Marino #include <sys/types.h>
30*86d7f5d3SJohn Marino #include <sys/socket.h>
31*86d7f5d3SJohn Marino #include <sys/time.h>
32*86d7f5d3SJohn Marino #include <sys/event.h>
33*86d7f5d3SJohn Marino #include <sys/uio.h>
34*86d7f5d3SJohn Marino #include <assert.h>
35*86d7f5d3SJohn Marino #include <errno.h>
36*86d7f5d3SJohn Marino #include <nsswitch.h>
37*86d7f5d3SJohn Marino #include <stdio.h>
38*86d7f5d3SJohn Marino #include <stdlib.h>
39*86d7f5d3SJohn Marino #include <string.h>
40*86d7f5d3SJohn Marino #include "config.h"
41*86d7f5d3SJohn Marino #include "debug.h"
42*86d7f5d3SJohn Marino #include "query.h"
43*86d7f5d3SJohn Marino #include "log.h"
44*86d7f5d3SJohn Marino #include "mp_ws_query.h"
45*86d7f5d3SJohn Marino #include "mp_rs_query.h"
46*86d7f5d3SJohn Marino #include "singletons.h"
47*86d7f5d3SJohn Marino
48*86d7f5d3SJohn Marino static const char negative_data[1] = { 0 };
49*86d7f5d3SJohn Marino
50*86d7f5d3SJohn Marino extern void get_time_func(struct timeval *);
51*86d7f5d3SJohn Marino
52*86d7f5d3SJohn Marino static void clear_config_entry(struct configuration_entry *);
53*86d7f5d3SJohn Marino static void clear_config_entry_part(struct configuration_entry *,
54*86d7f5d3SJohn Marino const char *, size_t);
55*86d7f5d3SJohn Marino
56*86d7f5d3SJohn Marino static int on_query_startup(struct query_state *);
57*86d7f5d3SJohn Marino static void on_query_destroy(struct query_state *);
58*86d7f5d3SJohn Marino
59*86d7f5d3SJohn Marino static int on_read_request_read1(struct query_state *);
60*86d7f5d3SJohn Marino static int on_read_request_read2(struct query_state *);
61*86d7f5d3SJohn Marino static int on_read_request_process(struct query_state *);
62*86d7f5d3SJohn Marino static int on_read_response_write1(struct query_state *);
63*86d7f5d3SJohn Marino static int on_read_response_write2(struct query_state *);
64*86d7f5d3SJohn Marino
65*86d7f5d3SJohn Marino static int on_rw_mapper(struct query_state *);
66*86d7f5d3SJohn Marino
67*86d7f5d3SJohn Marino static int on_transform_request_read1(struct query_state *);
68*86d7f5d3SJohn Marino static int on_transform_request_read2(struct query_state *);
69*86d7f5d3SJohn Marino static int on_transform_request_process(struct query_state *);
70*86d7f5d3SJohn Marino static int on_transform_response_write1(struct query_state *);
71*86d7f5d3SJohn Marino
72*86d7f5d3SJohn Marino static int on_write_request_read1(struct query_state *);
73*86d7f5d3SJohn Marino static int on_write_request_read2(struct query_state *);
74*86d7f5d3SJohn Marino static int on_negative_write_request_process(struct query_state *);
75*86d7f5d3SJohn Marino static int on_write_request_process(struct query_state *);
76*86d7f5d3SJohn Marino static int on_write_response_write1(struct query_state *);
77*86d7f5d3SJohn Marino
78*86d7f5d3SJohn Marino /*
79*86d7f5d3SJohn Marino * Clears the specified configuration entry (clears the cache for positive and
80*86d7f5d3SJohn Marino * and negative entries) and also for all multipart entries.
81*86d7f5d3SJohn Marino */
82*86d7f5d3SJohn Marino static void
clear_config_entry(struct configuration_entry * config_entry)83*86d7f5d3SJohn Marino clear_config_entry(struct configuration_entry *config_entry)
84*86d7f5d3SJohn Marino {
85*86d7f5d3SJohn Marino size_t i;
86*86d7f5d3SJohn Marino
87*86d7f5d3SJohn Marino TRACE_IN(clear_config_entry);
88*86d7f5d3SJohn Marino configuration_lock_entry(config_entry, CELT_POSITIVE);
89*86d7f5d3SJohn Marino if (config_entry->positive_cache_entry != NULL)
90*86d7f5d3SJohn Marino transform_cache_entry(
91*86d7f5d3SJohn Marino config_entry->positive_cache_entry,
92*86d7f5d3SJohn Marino CTT_CLEAR);
93*86d7f5d3SJohn Marino configuration_unlock_entry(config_entry, CELT_POSITIVE);
94*86d7f5d3SJohn Marino
95*86d7f5d3SJohn Marino configuration_lock_entry(config_entry, CELT_NEGATIVE);
96*86d7f5d3SJohn Marino if (config_entry->negative_cache_entry != NULL)
97*86d7f5d3SJohn Marino transform_cache_entry(
98*86d7f5d3SJohn Marino config_entry->negative_cache_entry,
99*86d7f5d3SJohn Marino CTT_CLEAR);
100*86d7f5d3SJohn Marino configuration_unlock_entry(config_entry, CELT_NEGATIVE);
101*86d7f5d3SJohn Marino
102*86d7f5d3SJohn Marino configuration_lock_entry(config_entry, CELT_MULTIPART);
103*86d7f5d3SJohn Marino for (i = 0; i < config_entry->mp_cache_entries_size; ++i)
104*86d7f5d3SJohn Marino transform_cache_entry(
105*86d7f5d3SJohn Marino config_entry->mp_cache_entries[i],
106*86d7f5d3SJohn Marino CTT_CLEAR);
107*86d7f5d3SJohn Marino configuration_unlock_entry(config_entry, CELT_MULTIPART);
108*86d7f5d3SJohn Marino
109*86d7f5d3SJohn Marino TRACE_OUT(clear_config_entry);
110*86d7f5d3SJohn Marino }
111*86d7f5d3SJohn Marino
112*86d7f5d3SJohn Marino /*
113*86d7f5d3SJohn Marino * Clears the specified configuration entry by deleting only the elements,
114*86d7f5d3SJohn Marino * that are owned by the user with specified eid_str.
115*86d7f5d3SJohn Marino */
116*86d7f5d3SJohn Marino static void
clear_config_entry_part(struct configuration_entry * config_entry,const char * eid_str,size_t eid_str_length)117*86d7f5d3SJohn Marino clear_config_entry_part(struct configuration_entry *config_entry,
118*86d7f5d3SJohn Marino const char *eid_str, size_t eid_str_length)
119*86d7f5d3SJohn Marino {
120*86d7f5d3SJohn Marino cache_entry *start, *finish, *mp_entry;
121*86d7f5d3SJohn Marino TRACE_IN(clear_config_entry_part);
122*86d7f5d3SJohn Marino configuration_lock_entry(config_entry, CELT_POSITIVE);
123*86d7f5d3SJohn Marino if (config_entry->positive_cache_entry != NULL)
124*86d7f5d3SJohn Marino transform_cache_entry_part(
125*86d7f5d3SJohn Marino config_entry->positive_cache_entry,
126*86d7f5d3SJohn Marino CTT_CLEAR, eid_str, eid_str_length, KPPT_LEFT);
127*86d7f5d3SJohn Marino configuration_unlock_entry(config_entry, CELT_POSITIVE);
128*86d7f5d3SJohn Marino
129*86d7f5d3SJohn Marino configuration_lock_entry(config_entry, CELT_NEGATIVE);
130*86d7f5d3SJohn Marino if (config_entry->negative_cache_entry != NULL)
131*86d7f5d3SJohn Marino transform_cache_entry_part(
132*86d7f5d3SJohn Marino config_entry->negative_cache_entry,
133*86d7f5d3SJohn Marino CTT_CLEAR, eid_str, eid_str_length, KPPT_LEFT);
134*86d7f5d3SJohn Marino configuration_unlock_entry(config_entry, CELT_NEGATIVE);
135*86d7f5d3SJohn Marino
136*86d7f5d3SJohn Marino configuration_lock_entry(config_entry, CELT_MULTIPART);
137*86d7f5d3SJohn Marino if (configuration_entry_find_mp_cache_entries(config_entry,
138*86d7f5d3SJohn Marino eid_str, &start, &finish) == 0) {
139*86d7f5d3SJohn Marino for (mp_entry = start; mp_entry != finish; ++mp_entry)
140*86d7f5d3SJohn Marino transform_cache_entry(*mp_entry, CTT_CLEAR);
141*86d7f5d3SJohn Marino }
142*86d7f5d3SJohn Marino configuration_unlock_entry(config_entry, CELT_MULTIPART);
143*86d7f5d3SJohn Marino
144*86d7f5d3SJohn Marino TRACE_OUT(clear_config_entry_part);
145*86d7f5d3SJohn Marino }
146*86d7f5d3SJohn Marino
147*86d7f5d3SJohn Marino /*
148*86d7f5d3SJohn Marino * This function is assigned to the query_state structue on its creation.
149*86d7f5d3SJohn Marino * It's main purpose is to receive credentials from the client.
150*86d7f5d3SJohn Marino */
151*86d7f5d3SJohn Marino static int
on_query_startup(struct query_state * qstate)152*86d7f5d3SJohn Marino on_query_startup(struct query_state *qstate)
153*86d7f5d3SJohn Marino {
154*86d7f5d3SJohn Marino struct msghdr cred_hdr;
155*86d7f5d3SJohn Marino struct iovec iov;
156*86d7f5d3SJohn Marino struct cmsgcred *cred;
157*86d7f5d3SJohn Marino int elem_type;
158*86d7f5d3SJohn Marino
159*86d7f5d3SJohn Marino struct {
160*86d7f5d3SJohn Marino struct cmsghdr hdr;
161*86d7f5d3SJohn Marino char cred[CMSG_SPACE(sizeof(struct cmsgcred))];
162*86d7f5d3SJohn Marino } cmsg;
163*86d7f5d3SJohn Marino
164*86d7f5d3SJohn Marino TRACE_IN(on_query_startup);
165*86d7f5d3SJohn Marino assert(qstate != NULL);
166*86d7f5d3SJohn Marino
167*86d7f5d3SJohn Marino memset(&cred_hdr, 0, sizeof(struct msghdr));
168*86d7f5d3SJohn Marino cred_hdr.msg_iov = &iov;
169*86d7f5d3SJohn Marino cred_hdr.msg_iovlen = 1;
170*86d7f5d3SJohn Marino cred_hdr.msg_control = (caddr_t)&cmsg;
171*86d7f5d3SJohn Marino cred_hdr.msg_controllen = CMSG_LEN(sizeof(struct cmsgcred));
172*86d7f5d3SJohn Marino
173*86d7f5d3SJohn Marino memset(&iov, 0, sizeof(struct iovec));
174*86d7f5d3SJohn Marino iov.iov_base = &elem_type;
175*86d7f5d3SJohn Marino iov.iov_len = sizeof(int);
176*86d7f5d3SJohn Marino
177*86d7f5d3SJohn Marino if (recvmsg(qstate->sockfd, &cred_hdr, 0) == -1) {
178*86d7f5d3SJohn Marino TRACE_OUT(on_query_startup);
179*86d7f5d3SJohn Marino return (-1);
180*86d7f5d3SJohn Marino }
181*86d7f5d3SJohn Marino
182*86d7f5d3SJohn Marino if (cmsg.hdr.cmsg_len < CMSG_LEN(sizeof(struct cmsgcred))
183*86d7f5d3SJohn Marino || cmsg.hdr.cmsg_level != SOL_SOCKET
184*86d7f5d3SJohn Marino || cmsg.hdr.cmsg_type != SCM_CREDS) {
185*86d7f5d3SJohn Marino TRACE_OUT(on_query_startup);
186*86d7f5d3SJohn Marino return (-1);
187*86d7f5d3SJohn Marino }
188*86d7f5d3SJohn Marino
189*86d7f5d3SJohn Marino cred = (struct cmsgcred *)CMSG_DATA(&cmsg);
190*86d7f5d3SJohn Marino qstate->uid = cred->cmcred_uid;
191*86d7f5d3SJohn Marino qstate->gid = cred->cmcred_gid;
192*86d7f5d3SJohn Marino
193*86d7f5d3SJohn Marino #if defined(NS_NSCD_EID_CHECKING) || defined(NS_STRICT_NSCD_EID_CHECKING)
194*86d7f5d3SJohn Marino /*
195*86d7f5d3SJohn Marino * This check is probably a bit redundant - per-user cache is always separated
196*86d7f5d3SJohn Marino * by the euid/egid pair
197*86d7f5d3SJohn Marino */
198*86d7f5d3SJohn Marino if (check_query_eids(qstate) != 0) {
199*86d7f5d3SJohn Marino #ifdef NS_STRICT_NSCD_EID_CHECKING
200*86d7f5d3SJohn Marino TRACE_OUT(on_query_startup);
201*86d7f5d3SJohn Marino return (-1);
202*86d7f5d3SJohn Marino #else
203*86d7f5d3SJohn Marino if ((elem_type != CET_READ_REQUEST) &&
204*86d7f5d3SJohn Marino (elem_type != CET_MP_READ_SESSION_REQUEST) &&
205*86d7f5d3SJohn Marino (elem_type != CET_WRITE_REQUEST) &&
206*86d7f5d3SJohn Marino (elem_type != CET_MP_WRITE_SESSION_REQUEST)) {
207*86d7f5d3SJohn Marino TRACE_OUT(on_query_startup);
208*86d7f5d3SJohn Marino return (-1);
209*86d7f5d3SJohn Marino }
210*86d7f5d3SJohn Marino #endif
211*86d7f5d3SJohn Marino }
212*86d7f5d3SJohn Marino #endif
213*86d7f5d3SJohn Marino
214*86d7f5d3SJohn Marino switch (elem_type) {
215*86d7f5d3SJohn Marino case CET_WRITE_REQUEST:
216*86d7f5d3SJohn Marino qstate->process_func = on_write_request_read1;
217*86d7f5d3SJohn Marino break;
218*86d7f5d3SJohn Marino case CET_READ_REQUEST:
219*86d7f5d3SJohn Marino qstate->process_func = on_read_request_read1;
220*86d7f5d3SJohn Marino break;
221*86d7f5d3SJohn Marino case CET_TRANSFORM_REQUEST:
222*86d7f5d3SJohn Marino qstate->process_func = on_transform_request_read1;
223*86d7f5d3SJohn Marino break;
224*86d7f5d3SJohn Marino case CET_MP_WRITE_SESSION_REQUEST:
225*86d7f5d3SJohn Marino qstate->process_func = on_mp_write_session_request_read1;
226*86d7f5d3SJohn Marino break;
227*86d7f5d3SJohn Marino case CET_MP_READ_SESSION_REQUEST:
228*86d7f5d3SJohn Marino qstate->process_func = on_mp_read_session_request_read1;
229*86d7f5d3SJohn Marino break;
230*86d7f5d3SJohn Marino default:
231*86d7f5d3SJohn Marino TRACE_OUT(on_query_startup);
232*86d7f5d3SJohn Marino return (-1);
233*86d7f5d3SJohn Marino }
234*86d7f5d3SJohn Marino
235*86d7f5d3SJohn Marino qstate->kevent_watermark = 0;
236*86d7f5d3SJohn Marino TRACE_OUT(on_query_startup);
237*86d7f5d3SJohn Marino return (0);
238*86d7f5d3SJohn Marino }
239*86d7f5d3SJohn Marino
240*86d7f5d3SJohn Marino /*
241*86d7f5d3SJohn Marino * on_rw_mapper is used to process multiple read/write requests during
242*86d7f5d3SJohn Marino * one connection session. It's never called in the beginning (on query_state
243*86d7f5d3SJohn Marino * creation) as it does not process the multipart requests and does not
244*86d7f5d3SJohn Marino * receive credentials
245*86d7f5d3SJohn Marino */
246*86d7f5d3SJohn Marino static int
on_rw_mapper(struct query_state * qstate)247*86d7f5d3SJohn Marino on_rw_mapper(struct query_state *qstate)
248*86d7f5d3SJohn Marino {
249*86d7f5d3SJohn Marino ssize_t result;
250*86d7f5d3SJohn Marino int elem_type;
251*86d7f5d3SJohn Marino
252*86d7f5d3SJohn Marino TRACE_IN(on_rw_mapper);
253*86d7f5d3SJohn Marino if (qstate->kevent_watermark == 0) {
254*86d7f5d3SJohn Marino qstate->kevent_watermark = sizeof(int);
255*86d7f5d3SJohn Marino } else {
256*86d7f5d3SJohn Marino result = qstate->read_func(qstate, &elem_type, sizeof(int));
257*86d7f5d3SJohn Marino if (result != sizeof(int)) {
258*86d7f5d3SJohn Marino TRACE_OUT(on_rw_mapper);
259*86d7f5d3SJohn Marino return (-1);
260*86d7f5d3SJohn Marino }
261*86d7f5d3SJohn Marino
262*86d7f5d3SJohn Marino switch (elem_type) {
263*86d7f5d3SJohn Marino case CET_WRITE_REQUEST:
264*86d7f5d3SJohn Marino qstate->kevent_watermark = sizeof(size_t);
265*86d7f5d3SJohn Marino qstate->process_func = on_write_request_read1;
266*86d7f5d3SJohn Marino break;
267*86d7f5d3SJohn Marino case CET_READ_REQUEST:
268*86d7f5d3SJohn Marino qstate->kevent_watermark = sizeof(size_t);
269*86d7f5d3SJohn Marino qstate->process_func = on_read_request_read1;
270*86d7f5d3SJohn Marino break;
271*86d7f5d3SJohn Marino default:
272*86d7f5d3SJohn Marino TRACE_OUT(on_rw_mapper);
273*86d7f5d3SJohn Marino return (-1);
274*86d7f5d3SJohn Marino break;
275*86d7f5d3SJohn Marino }
276*86d7f5d3SJohn Marino }
277*86d7f5d3SJohn Marino TRACE_OUT(on_rw_mapper);
278*86d7f5d3SJohn Marino return (0);
279*86d7f5d3SJohn Marino }
280*86d7f5d3SJohn Marino
281*86d7f5d3SJohn Marino /*
282*86d7f5d3SJohn Marino * The default query_destroy function
283*86d7f5d3SJohn Marino */
284*86d7f5d3SJohn Marino static void
on_query_destroy(struct query_state * qstate)285*86d7f5d3SJohn Marino on_query_destroy(struct query_state *qstate)
286*86d7f5d3SJohn Marino {
287*86d7f5d3SJohn Marino
288*86d7f5d3SJohn Marino TRACE_IN(on_query_destroy);
289*86d7f5d3SJohn Marino finalize_comm_element(&qstate->response);
290*86d7f5d3SJohn Marino finalize_comm_element(&qstate->request);
291*86d7f5d3SJohn Marino TRACE_OUT(on_query_destroy);
292*86d7f5d3SJohn Marino }
293*86d7f5d3SJohn Marino
294*86d7f5d3SJohn Marino /*
295*86d7f5d3SJohn Marino * The functions below are used to process write requests.
296*86d7f5d3SJohn Marino * - on_write_request_read1 and on_write_request_read2 read the request itself
297*86d7f5d3SJohn Marino * - on_write_request_process processes it (if the client requests to
298*86d7f5d3SJohn Marino * cache the negative result, the on_negative_write_request_process is used)
299*86d7f5d3SJohn Marino * - on_write_response_write1 sends the response
300*86d7f5d3SJohn Marino */
301*86d7f5d3SJohn Marino static int
on_write_request_read1(struct query_state * qstate)302*86d7f5d3SJohn Marino on_write_request_read1(struct query_state *qstate)
303*86d7f5d3SJohn Marino {
304*86d7f5d3SJohn Marino struct cache_write_request *write_request;
305*86d7f5d3SJohn Marino ssize_t result;
306*86d7f5d3SJohn Marino
307*86d7f5d3SJohn Marino TRACE_IN(on_write_request_read1);
308*86d7f5d3SJohn Marino if (qstate->kevent_watermark == 0)
309*86d7f5d3SJohn Marino qstate->kevent_watermark = sizeof(size_t) * 3;
310*86d7f5d3SJohn Marino else {
311*86d7f5d3SJohn Marino init_comm_element(&qstate->request, CET_WRITE_REQUEST);
312*86d7f5d3SJohn Marino write_request = get_cache_write_request(&qstate->request);
313*86d7f5d3SJohn Marino
314*86d7f5d3SJohn Marino result = qstate->read_func(qstate, &write_request->entry_length,
315*86d7f5d3SJohn Marino sizeof(size_t));
316*86d7f5d3SJohn Marino result += qstate->read_func(qstate,
317*86d7f5d3SJohn Marino &write_request->cache_key_size, sizeof(size_t));
318*86d7f5d3SJohn Marino result += qstate->read_func(qstate,
319*86d7f5d3SJohn Marino &write_request->data_size, sizeof(size_t));
320*86d7f5d3SJohn Marino
321*86d7f5d3SJohn Marino if (result != sizeof(size_t) * 3) {
322*86d7f5d3SJohn Marino TRACE_OUT(on_write_request_read1);
323*86d7f5d3SJohn Marino return (-1);
324*86d7f5d3SJohn Marino }
325*86d7f5d3SJohn Marino
326*86d7f5d3SJohn Marino if (BUFSIZE_INVALID(write_request->entry_length) ||
327*86d7f5d3SJohn Marino BUFSIZE_INVALID(write_request->cache_key_size) ||
328*86d7f5d3SJohn Marino (BUFSIZE_INVALID(write_request->data_size) &&
329*86d7f5d3SJohn Marino (write_request->data_size != 0))) {
330*86d7f5d3SJohn Marino TRACE_OUT(on_write_request_read1);
331*86d7f5d3SJohn Marino return (-1);
332*86d7f5d3SJohn Marino }
333*86d7f5d3SJohn Marino
334*86d7f5d3SJohn Marino write_request->entry = (char *)calloc(1,
335*86d7f5d3SJohn Marino write_request->entry_length + 1);
336*86d7f5d3SJohn Marino assert(write_request->entry != NULL);
337*86d7f5d3SJohn Marino
338*86d7f5d3SJohn Marino write_request->cache_key = (char *)calloc(1,
339*86d7f5d3SJohn Marino write_request->cache_key_size +
340*86d7f5d3SJohn Marino qstate->eid_str_length);
341*86d7f5d3SJohn Marino assert(write_request->cache_key != NULL);
342*86d7f5d3SJohn Marino memcpy(write_request->cache_key, qstate->eid_str,
343*86d7f5d3SJohn Marino qstate->eid_str_length);
344*86d7f5d3SJohn Marino
345*86d7f5d3SJohn Marino if (write_request->data_size != 0) {
346*86d7f5d3SJohn Marino write_request->data = (char *)calloc(1,
347*86d7f5d3SJohn Marino write_request->data_size);
348*86d7f5d3SJohn Marino assert(write_request->data != NULL);
349*86d7f5d3SJohn Marino }
350*86d7f5d3SJohn Marino
351*86d7f5d3SJohn Marino qstate->kevent_watermark = write_request->entry_length +
352*86d7f5d3SJohn Marino write_request->cache_key_size +
353*86d7f5d3SJohn Marino write_request->data_size;
354*86d7f5d3SJohn Marino qstate->process_func = on_write_request_read2;
355*86d7f5d3SJohn Marino }
356*86d7f5d3SJohn Marino
357*86d7f5d3SJohn Marino TRACE_OUT(on_write_request_read1);
358*86d7f5d3SJohn Marino return (0);
359*86d7f5d3SJohn Marino }
360*86d7f5d3SJohn Marino
361*86d7f5d3SJohn Marino static int
on_write_request_read2(struct query_state * qstate)362*86d7f5d3SJohn Marino on_write_request_read2(struct query_state *qstate)
363*86d7f5d3SJohn Marino {
364*86d7f5d3SJohn Marino struct cache_write_request *write_request;
365*86d7f5d3SJohn Marino ssize_t result;
366*86d7f5d3SJohn Marino
367*86d7f5d3SJohn Marino TRACE_IN(on_write_request_read2);
368*86d7f5d3SJohn Marino write_request = get_cache_write_request(&qstate->request);
369*86d7f5d3SJohn Marino
370*86d7f5d3SJohn Marino result = qstate->read_func(qstate, write_request->entry,
371*86d7f5d3SJohn Marino write_request->entry_length);
372*86d7f5d3SJohn Marino result += qstate->read_func(qstate, write_request->cache_key +
373*86d7f5d3SJohn Marino qstate->eid_str_length, write_request->cache_key_size);
374*86d7f5d3SJohn Marino if (write_request->data_size != 0)
375*86d7f5d3SJohn Marino result += qstate->read_func(qstate, write_request->data,
376*86d7f5d3SJohn Marino write_request->data_size);
377*86d7f5d3SJohn Marino
378*86d7f5d3SJohn Marino if (result != qstate->kevent_watermark) {
379*86d7f5d3SJohn Marino TRACE_OUT(on_write_request_read2);
380*86d7f5d3SJohn Marino return (-1);
381*86d7f5d3SJohn Marino }
382*86d7f5d3SJohn Marino write_request->cache_key_size += qstate->eid_str_length;
383*86d7f5d3SJohn Marino
384*86d7f5d3SJohn Marino qstate->kevent_watermark = 0;
385*86d7f5d3SJohn Marino if (write_request->data_size != 0)
386*86d7f5d3SJohn Marino qstate->process_func = on_write_request_process;
387*86d7f5d3SJohn Marino else
388*86d7f5d3SJohn Marino qstate->process_func = on_negative_write_request_process;
389*86d7f5d3SJohn Marino TRACE_OUT(on_write_request_read2);
390*86d7f5d3SJohn Marino return (0);
391*86d7f5d3SJohn Marino }
392*86d7f5d3SJohn Marino
393*86d7f5d3SJohn Marino static int
on_write_request_process(struct query_state * qstate)394*86d7f5d3SJohn Marino on_write_request_process(struct query_state *qstate)
395*86d7f5d3SJohn Marino {
396*86d7f5d3SJohn Marino struct cache_write_request *write_request;
397*86d7f5d3SJohn Marino struct cache_write_response *write_response;
398*86d7f5d3SJohn Marino cache_entry c_entry;
399*86d7f5d3SJohn Marino
400*86d7f5d3SJohn Marino TRACE_IN(on_write_request_process);
401*86d7f5d3SJohn Marino init_comm_element(&qstate->response, CET_WRITE_RESPONSE);
402*86d7f5d3SJohn Marino write_response = get_cache_write_response(&qstate->response);
403*86d7f5d3SJohn Marino write_request = get_cache_write_request(&qstate->request);
404*86d7f5d3SJohn Marino
405*86d7f5d3SJohn Marino qstate->config_entry = configuration_find_entry(
406*86d7f5d3SJohn Marino s_configuration, write_request->entry);
407*86d7f5d3SJohn Marino
408*86d7f5d3SJohn Marino if (qstate->config_entry == NULL) {
409*86d7f5d3SJohn Marino write_response->error_code = ENOENT;
410*86d7f5d3SJohn Marino
411*86d7f5d3SJohn Marino LOG_ERR_2("write_request", "can't find configuration"
412*86d7f5d3SJohn Marino " entry '%s'. aborting request", write_request->entry);
413*86d7f5d3SJohn Marino goto fin;
414*86d7f5d3SJohn Marino }
415*86d7f5d3SJohn Marino
416*86d7f5d3SJohn Marino if (qstate->config_entry->enabled == 0) {
417*86d7f5d3SJohn Marino write_response->error_code = EACCES;
418*86d7f5d3SJohn Marino
419*86d7f5d3SJohn Marino LOG_ERR_2("write_request",
420*86d7f5d3SJohn Marino "configuration entry '%s' is disabled",
421*86d7f5d3SJohn Marino write_request->entry);
422*86d7f5d3SJohn Marino goto fin;
423*86d7f5d3SJohn Marino }
424*86d7f5d3SJohn Marino
425*86d7f5d3SJohn Marino if (qstate->config_entry->perform_actual_lookups != 0) {
426*86d7f5d3SJohn Marino write_response->error_code = EOPNOTSUPP;
427*86d7f5d3SJohn Marino
428*86d7f5d3SJohn Marino LOG_ERR_2("write_request",
429*86d7f5d3SJohn Marino "entry '%s' performs lookups by itself: "
430*86d7f5d3SJohn Marino "can't write to it", write_request->entry);
431*86d7f5d3SJohn Marino goto fin;
432*86d7f5d3SJohn Marino }
433*86d7f5d3SJohn Marino
434*86d7f5d3SJohn Marino configuration_lock_rdlock(s_configuration);
435*86d7f5d3SJohn Marino c_entry = find_cache_entry(s_cache,
436*86d7f5d3SJohn Marino qstate->config_entry->positive_cache_params.entry_name);
437*86d7f5d3SJohn Marino configuration_unlock(s_configuration);
438*86d7f5d3SJohn Marino if (c_entry != NULL) {
439*86d7f5d3SJohn Marino configuration_lock_entry(qstate->config_entry, CELT_POSITIVE);
440*86d7f5d3SJohn Marino qstate->config_entry->positive_cache_entry = c_entry;
441*86d7f5d3SJohn Marino write_response->error_code = cache_write(c_entry,
442*86d7f5d3SJohn Marino write_request->cache_key,
443*86d7f5d3SJohn Marino write_request->cache_key_size,
444*86d7f5d3SJohn Marino write_request->data,
445*86d7f5d3SJohn Marino write_request->data_size);
446*86d7f5d3SJohn Marino configuration_unlock_entry(qstate->config_entry, CELT_POSITIVE);
447*86d7f5d3SJohn Marino
448*86d7f5d3SJohn Marino if ((qstate->config_entry->common_query_timeout.tv_sec != 0) ||
449*86d7f5d3SJohn Marino (qstate->config_entry->common_query_timeout.tv_usec != 0))
450*86d7f5d3SJohn Marino memcpy(&qstate->timeout,
451*86d7f5d3SJohn Marino &qstate->config_entry->common_query_timeout,
452*86d7f5d3SJohn Marino sizeof(struct timeval));
453*86d7f5d3SJohn Marino
454*86d7f5d3SJohn Marino } else
455*86d7f5d3SJohn Marino write_response->error_code = -1;
456*86d7f5d3SJohn Marino
457*86d7f5d3SJohn Marino fin:
458*86d7f5d3SJohn Marino qstate->kevent_filter = EVFILT_WRITE;
459*86d7f5d3SJohn Marino qstate->kevent_watermark = sizeof(int);
460*86d7f5d3SJohn Marino qstate->process_func = on_write_response_write1;
461*86d7f5d3SJohn Marino
462*86d7f5d3SJohn Marino TRACE_OUT(on_write_request_process);
463*86d7f5d3SJohn Marino return (0);
464*86d7f5d3SJohn Marino }
465*86d7f5d3SJohn Marino
466*86d7f5d3SJohn Marino static int
on_negative_write_request_process(struct query_state * qstate)467*86d7f5d3SJohn Marino on_negative_write_request_process(struct query_state *qstate)
468*86d7f5d3SJohn Marino {
469*86d7f5d3SJohn Marino struct cache_write_request *write_request;
470*86d7f5d3SJohn Marino struct cache_write_response *write_response;
471*86d7f5d3SJohn Marino cache_entry c_entry;
472*86d7f5d3SJohn Marino
473*86d7f5d3SJohn Marino TRACE_IN(on_negative_write_request_process);
474*86d7f5d3SJohn Marino init_comm_element(&qstate->response, CET_WRITE_RESPONSE);
475*86d7f5d3SJohn Marino write_response = get_cache_write_response(&qstate->response);
476*86d7f5d3SJohn Marino write_request = get_cache_write_request(&qstate->request);
477*86d7f5d3SJohn Marino
478*86d7f5d3SJohn Marino qstate->config_entry = configuration_find_entry(
479*86d7f5d3SJohn Marino s_configuration, write_request->entry);
480*86d7f5d3SJohn Marino
481*86d7f5d3SJohn Marino if (qstate->config_entry == NULL) {
482*86d7f5d3SJohn Marino write_response->error_code = ENOENT;
483*86d7f5d3SJohn Marino
484*86d7f5d3SJohn Marino LOG_ERR_2("negative_write_request",
485*86d7f5d3SJohn Marino "can't find configuration"
486*86d7f5d3SJohn Marino " entry '%s'. aborting request", write_request->entry);
487*86d7f5d3SJohn Marino goto fin;
488*86d7f5d3SJohn Marino }
489*86d7f5d3SJohn Marino
490*86d7f5d3SJohn Marino if (qstate->config_entry->enabled == 0) {
491*86d7f5d3SJohn Marino write_response->error_code = EACCES;
492*86d7f5d3SJohn Marino
493*86d7f5d3SJohn Marino LOG_ERR_2("negative_write_request",
494*86d7f5d3SJohn Marino "configuration entry '%s' is disabled",
495*86d7f5d3SJohn Marino write_request->entry);
496*86d7f5d3SJohn Marino goto fin;
497*86d7f5d3SJohn Marino }
498*86d7f5d3SJohn Marino
499*86d7f5d3SJohn Marino if (qstate->config_entry->perform_actual_lookups != 0) {
500*86d7f5d3SJohn Marino write_response->error_code = EOPNOTSUPP;
501*86d7f5d3SJohn Marino
502*86d7f5d3SJohn Marino LOG_ERR_2("negative_write_request",
503*86d7f5d3SJohn Marino "entry '%s' performs lookups by itself: "
504*86d7f5d3SJohn Marino "can't write to it", write_request->entry);
505*86d7f5d3SJohn Marino goto fin;
506*86d7f5d3SJohn Marino } else {
507*86d7f5d3SJohn Marino #ifdef NS_NSCD_EID_CHECKING
508*86d7f5d3SJohn Marino if (check_query_eids(qstate) != 0) {
509*86d7f5d3SJohn Marino write_response->error_code = EPERM;
510*86d7f5d3SJohn Marino goto fin;
511*86d7f5d3SJohn Marino }
512*86d7f5d3SJohn Marino #endif
513*86d7f5d3SJohn Marino }
514*86d7f5d3SJohn Marino
515*86d7f5d3SJohn Marino configuration_lock_rdlock(s_configuration);
516*86d7f5d3SJohn Marino c_entry = find_cache_entry(s_cache,
517*86d7f5d3SJohn Marino qstate->config_entry->negative_cache_params.entry_name);
518*86d7f5d3SJohn Marino configuration_unlock(s_configuration);
519*86d7f5d3SJohn Marino if (c_entry != NULL) {
520*86d7f5d3SJohn Marino configuration_lock_entry(qstate->config_entry, CELT_NEGATIVE);
521*86d7f5d3SJohn Marino qstate->config_entry->negative_cache_entry = c_entry;
522*86d7f5d3SJohn Marino write_response->error_code = cache_write(c_entry,
523*86d7f5d3SJohn Marino write_request->cache_key,
524*86d7f5d3SJohn Marino write_request->cache_key_size,
525*86d7f5d3SJohn Marino negative_data,
526*86d7f5d3SJohn Marino sizeof(negative_data));
527*86d7f5d3SJohn Marino configuration_unlock_entry(qstate->config_entry, CELT_NEGATIVE);
528*86d7f5d3SJohn Marino
529*86d7f5d3SJohn Marino if ((qstate->config_entry->common_query_timeout.tv_sec != 0) ||
530*86d7f5d3SJohn Marino (qstate->config_entry->common_query_timeout.tv_usec != 0))
531*86d7f5d3SJohn Marino memcpy(&qstate->timeout,
532*86d7f5d3SJohn Marino &qstate->config_entry->common_query_timeout,
533*86d7f5d3SJohn Marino sizeof(struct timeval));
534*86d7f5d3SJohn Marino } else
535*86d7f5d3SJohn Marino write_response->error_code = -1;
536*86d7f5d3SJohn Marino
537*86d7f5d3SJohn Marino fin:
538*86d7f5d3SJohn Marino qstate->kevent_filter = EVFILT_WRITE;
539*86d7f5d3SJohn Marino qstate->kevent_watermark = sizeof(int);
540*86d7f5d3SJohn Marino qstate->process_func = on_write_response_write1;
541*86d7f5d3SJohn Marino
542*86d7f5d3SJohn Marino TRACE_OUT(on_negative_write_request_process);
543*86d7f5d3SJohn Marino return (0);
544*86d7f5d3SJohn Marino }
545*86d7f5d3SJohn Marino
546*86d7f5d3SJohn Marino static int
on_write_response_write1(struct query_state * qstate)547*86d7f5d3SJohn Marino on_write_response_write1(struct query_state *qstate)
548*86d7f5d3SJohn Marino {
549*86d7f5d3SJohn Marino struct cache_write_response *write_response;
550*86d7f5d3SJohn Marino ssize_t result;
551*86d7f5d3SJohn Marino
552*86d7f5d3SJohn Marino TRACE_IN(on_write_response_write1);
553*86d7f5d3SJohn Marino write_response = get_cache_write_response(&qstate->response);
554*86d7f5d3SJohn Marino result = qstate->write_func(qstate, &write_response->error_code,
555*86d7f5d3SJohn Marino sizeof(int));
556*86d7f5d3SJohn Marino if (result != sizeof(int)) {
557*86d7f5d3SJohn Marino TRACE_OUT(on_write_response_write1);
558*86d7f5d3SJohn Marino return (-1);
559*86d7f5d3SJohn Marino }
560*86d7f5d3SJohn Marino
561*86d7f5d3SJohn Marino finalize_comm_element(&qstate->request);
562*86d7f5d3SJohn Marino finalize_comm_element(&qstate->response);
563*86d7f5d3SJohn Marino
564*86d7f5d3SJohn Marino qstate->kevent_watermark = sizeof(int);
565*86d7f5d3SJohn Marino qstate->kevent_filter = EVFILT_READ;
566*86d7f5d3SJohn Marino qstate->process_func = on_rw_mapper;
567*86d7f5d3SJohn Marino
568*86d7f5d3SJohn Marino TRACE_OUT(on_write_response_write1);
569*86d7f5d3SJohn Marino return (0);
570*86d7f5d3SJohn Marino }
571*86d7f5d3SJohn Marino
572*86d7f5d3SJohn Marino /*
573*86d7f5d3SJohn Marino * The functions below are used to process read requests.
574*86d7f5d3SJohn Marino * - on_read_request_read1 and on_read_request_read2 read the request itself
575*86d7f5d3SJohn Marino * - on_read_request_process processes it
576*86d7f5d3SJohn Marino * - on_read_response_write1 and on_read_response_write2 send the response
577*86d7f5d3SJohn Marino */
578*86d7f5d3SJohn Marino static int
on_read_request_read1(struct query_state * qstate)579*86d7f5d3SJohn Marino on_read_request_read1(struct query_state *qstate)
580*86d7f5d3SJohn Marino {
581*86d7f5d3SJohn Marino struct cache_read_request *read_request;
582*86d7f5d3SJohn Marino ssize_t result;
583*86d7f5d3SJohn Marino
584*86d7f5d3SJohn Marino TRACE_IN(on_read_request_read1);
585*86d7f5d3SJohn Marino if (qstate->kevent_watermark == 0)
586*86d7f5d3SJohn Marino qstate->kevent_watermark = sizeof(size_t) * 2;
587*86d7f5d3SJohn Marino else {
588*86d7f5d3SJohn Marino init_comm_element(&qstate->request, CET_READ_REQUEST);
589*86d7f5d3SJohn Marino read_request = get_cache_read_request(&qstate->request);
590*86d7f5d3SJohn Marino
591*86d7f5d3SJohn Marino result = qstate->read_func(qstate,
592*86d7f5d3SJohn Marino &read_request->entry_length, sizeof(size_t));
593*86d7f5d3SJohn Marino result += qstate->read_func(qstate,
594*86d7f5d3SJohn Marino &read_request->cache_key_size, sizeof(size_t));
595*86d7f5d3SJohn Marino
596*86d7f5d3SJohn Marino if (result != sizeof(size_t) * 2) {
597*86d7f5d3SJohn Marino TRACE_OUT(on_read_request_read1);
598*86d7f5d3SJohn Marino return (-1);
599*86d7f5d3SJohn Marino }
600*86d7f5d3SJohn Marino
601*86d7f5d3SJohn Marino if (BUFSIZE_INVALID(read_request->entry_length) ||
602*86d7f5d3SJohn Marino BUFSIZE_INVALID(read_request->cache_key_size)) {
603*86d7f5d3SJohn Marino TRACE_OUT(on_read_request_read1);
604*86d7f5d3SJohn Marino return (-1);
605*86d7f5d3SJohn Marino }
606*86d7f5d3SJohn Marino
607*86d7f5d3SJohn Marino read_request->entry = (char *)calloc(1,
608*86d7f5d3SJohn Marino read_request->entry_length + 1);
609*86d7f5d3SJohn Marino assert(read_request->entry != NULL);
610*86d7f5d3SJohn Marino
611*86d7f5d3SJohn Marino read_request->cache_key = (char *)calloc(1,
612*86d7f5d3SJohn Marino read_request->cache_key_size +
613*86d7f5d3SJohn Marino qstate->eid_str_length);
614*86d7f5d3SJohn Marino assert(read_request->cache_key != NULL);
615*86d7f5d3SJohn Marino memcpy(read_request->cache_key, qstate->eid_str,
616*86d7f5d3SJohn Marino qstate->eid_str_length);
617*86d7f5d3SJohn Marino
618*86d7f5d3SJohn Marino qstate->kevent_watermark = read_request->entry_length +
619*86d7f5d3SJohn Marino read_request->cache_key_size;
620*86d7f5d3SJohn Marino qstate->process_func = on_read_request_read2;
621*86d7f5d3SJohn Marino }
622*86d7f5d3SJohn Marino
623*86d7f5d3SJohn Marino TRACE_OUT(on_read_request_read1);
624*86d7f5d3SJohn Marino return (0);
625*86d7f5d3SJohn Marino }
626*86d7f5d3SJohn Marino
627*86d7f5d3SJohn Marino static int
on_read_request_read2(struct query_state * qstate)628*86d7f5d3SJohn Marino on_read_request_read2(struct query_state *qstate)
629*86d7f5d3SJohn Marino {
630*86d7f5d3SJohn Marino struct cache_read_request *read_request;
631*86d7f5d3SJohn Marino ssize_t result;
632*86d7f5d3SJohn Marino
633*86d7f5d3SJohn Marino TRACE_IN(on_read_request_read2);
634*86d7f5d3SJohn Marino read_request = get_cache_read_request(&qstate->request);
635*86d7f5d3SJohn Marino
636*86d7f5d3SJohn Marino result = qstate->read_func(qstate, read_request->entry,
637*86d7f5d3SJohn Marino read_request->entry_length);
638*86d7f5d3SJohn Marino result += qstate->read_func(qstate,
639*86d7f5d3SJohn Marino read_request->cache_key + qstate->eid_str_length,
640*86d7f5d3SJohn Marino read_request->cache_key_size);
641*86d7f5d3SJohn Marino
642*86d7f5d3SJohn Marino if (result != qstate->kevent_watermark) {
643*86d7f5d3SJohn Marino TRACE_OUT(on_read_request_read2);
644*86d7f5d3SJohn Marino return (-1);
645*86d7f5d3SJohn Marino }
646*86d7f5d3SJohn Marino read_request->cache_key_size += qstate->eid_str_length;
647*86d7f5d3SJohn Marino
648*86d7f5d3SJohn Marino qstate->kevent_watermark = 0;
649*86d7f5d3SJohn Marino qstate->process_func = on_read_request_process;
650*86d7f5d3SJohn Marino
651*86d7f5d3SJohn Marino TRACE_OUT(on_read_request_read2);
652*86d7f5d3SJohn Marino return (0);
653*86d7f5d3SJohn Marino }
654*86d7f5d3SJohn Marino
655*86d7f5d3SJohn Marino static int
on_read_request_process(struct query_state * qstate)656*86d7f5d3SJohn Marino on_read_request_process(struct query_state *qstate)
657*86d7f5d3SJohn Marino {
658*86d7f5d3SJohn Marino struct cache_read_request *read_request;
659*86d7f5d3SJohn Marino struct cache_read_response *read_response;
660*86d7f5d3SJohn Marino cache_entry c_entry, neg_c_entry;
661*86d7f5d3SJohn Marino
662*86d7f5d3SJohn Marino struct agent *lookup_agent;
663*86d7f5d3SJohn Marino struct common_agent *c_agent;
664*86d7f5d3SJohn Marino int res;
665*86d7f5d3SJohn Marino
666*86d7f5d3SJohn Marino TRACE_IN(on_read_request_process);
667*86d7f5d3SJohn Marino init_comm_element(&qstate->response, CET_READ_RESPONSE);
668*86d7f5d3SJohn Marino read_response = get_cache_read_response(&qstate->response);
669*86d7f5d3SJohn Marino read_request = get_cache_read_request(&qstate->request);
670*86d7f5d3SJohn Marino
671*86d7f5d3SJohn Marino qstate->config_entry = configuration_find_entry(
672*86d7f5d3SJohn Marino s_configuration, read_request->entry);
673*86d7f5d3SJohn Marino if (qstate->config_entry == NULL) {
674*86d7f5d3SJohn Marino read_response->error_code = ENOENT;
675*86d7f5d3SJohn Marino
676*86d7f5d3SJohn Marino LOG_ERR_2("read_request",
677*86d7f5d3SJohn Marino "can't find configuration "
678*86d7f5d3SJohn Marino "entry '%s'. aborting request", read_request->entry);
679*86d7f5d3SJohn Marino goto fin;
680*86d7f5d3SJohn Marino }
681*86d7f5d3SJohn Marino
682*86d7f5d3SJohn Marino if (qstate->config_entry->enabled == 0) {
683*86d7f5d3SJohn Marino read_response->error_code = EACCES;
684*86d7f5d3SJohn Marino
685*86d7f5d3SJohn Marino LOG_ERR_2("read_request",
686*86d7f5d3SJohn Marino "configuration entry '%s' is disabled",
687*86d7f5d3SJohn Marino read_request->entry);
688*86d7f5d3SJohn Marino goto fin;
689*86d7f5d3SJohn Marino }
690*86d7f5d3SJohn Marino
691*86d7f5d3SJohn Marino /*
692*86d7f5d3SJohn Marino * if we perform lookups by ourselves, then we don't need to separate
693*86d7f5d3SJohn Marino * cache entries by euid and egid
694*86d7f5d3SJohn Marino */
695*86d7f5d3SJohn Marino if (qstate->config_entry->perform_actual_lookups != 0)
696*86d7f5d3SJohn Marino memset(read_request->cache_key, 0, qstate->eid_str_length);
697*86d7f5d3SJohn Marino else {
698*86d7f5d3SJohn Marino #ifdef NS_NSCD_EID_CHECKING
699*86d7f5d3SJohn Marino if (check_query_eids(qstate) != 0) {
700*86d7f5d3SJohn Marino /* if the lookup is not self-performing, we check for clients euid/egid */
701*86d7f5d3SJohn Marino read_response->error_code = EPERM;
702*86d7f5d3SJohn Marino goto fin;
703*86d7f5d3SJohn Marino }
704*86d7f5d3SJohn Marino #endif
705*86d7f5d3SJohn Marino }
706*86d7f5d3SJohn Marino
707*86d7f5d3SJohn Marino configuration_lock_rdlock(s_configuration);
708*86d7f5d3SJohn Marino c_entry = find_cache_entry(s_cache,
709*86d7f5d3SJohn Marino qstate->config_entry->positive_cache_params.entry_name);
710*86d7f5d3SJohn Marino neg_c_entry = find_cache_entry(s_cache,
711*86d7f5d3SJohn Marino qstate->config_entry->negative_cache_params.entry_name);
712*86d7f5d3SJohn Marino configuration_unlock(s_configuration);
713*86d7f5d3SJohn Marino if ((c_entry != NULL) && (neg_c_entry != NULL)) {
714*86d7f5d3SJohn Marino configuration_lock_entry(qstate->config_entry, CELT_POSITIVE);
715*86d7f5d3SJohn Marino qstate->config_entry->positive_cache_entry = c_entry;
716*86d7f5d3SJohn Marino read_response->error_code = cache_read(c_entry,
717*86d7f5d3SJohn Marino read_request->cache_key,
718*86d7f5d3SJohn Marino read_request->cache_key_size, NULL,
719*86d7f5d3SJohn Marino &read_response->data_size);
720*86d7f5d3SJohn Marino
721*86d7f5d3SJohn Marino if (read_response->error_code == -2) {
722*86d7f5d3SJohn Marino read_response->data = (char *)malloc(
723*86d7f5d3SJohn Marino read_response->data_size);
724*86d7f5d3SJohn Marino assert(read_response != NULL);
725*86d7f5d3SJohn Marino read_response->error_code = cache_read(c_entry,
726*86d7f5d3SJohn Marino read_request->cache_key,
727*86d7f5d3SJohn Marino read_request->cache_key_size,
728*86d7f5d3SJohn Marino read_response->data,
729*86d7f5d3SJohn Marino &read_response->data_size);
730*86d7f5d3SJohn Marino }
731*86d7f5d3SJohn Marino configuration_unlock_entry(qstate->config_entry, CELT_POSITIVE);
732*86d7f5d3SJohn Marino
733*86d7f5d3SJohn Marino configuration_lock_entry(qstate->config_entry, CELT_NEGATIVE);
734*86d7f5d3SJohn Marino qstate->config_entry->negative_cache_entry = neg_c_entry;
735*86d7f5d3SJohn Marino if (read_response->error_code == -1) {
736*86d7f5d3SJohn Marino read_response->error_code = cache_read(neg_c_entry,
737*86d7f5d3SJohn Marino read_request->cache_key,
738*86d7f5d3SJohn Marino read_request->cache_key_size, NULL,
739*86d7f5d3SJohn Marino &read_response->data_size);
740*86d7f5d3SJohn Marino
741*86d7f5d3SJohn Marino if (read_response->error_code == -2) {
742*86d7f5d3SJohn Marino read_response->error_code = 0;
743*86d7f5d3SJohn Marino read_response->data = NULL;
744*86d7f5d3SJohn Marino read_response->data_size = 0;
745*86d7f5d3SJohn Marino }
746*86d7f5d3SJohn Marino }
747*86d7f5d3SJohn Marino configuration_unlock_entry(qstate->config_entry, CELT_NEGATIVE);
748*86d7f5d3SJohn Marino
749*86d7f5d3SJohn Marino if ((read_response->error_code == -1) &&
750*86d7f5d3SJohn Marino (qstate->config_entry->perform_actual_lookups != 0)) {
751*86d7f5d3SJohn Marino free(read_response->data);
752*86d7f5d3SJohn Marino read_response->data = NULL;
753*86d7f5d3SJohn Marino read_response->data_size = 0;
754*86d7f5d3SJohn Marino
755*86d7f5d3SJohn Marino lookup_agent = find_agent(s_agent_table,
756*86d7f5d3SJohn Marino read_request->entry, COMMON_AGENT);
757*86d7f5d3SJohn Marino
758*86d7f5d3SJohn Marino if ((lookup_agent != NULL) &&
759*86d7f5d3SJohn Marino (lookup_agent->type == COMMON_AGENT)) {
760*86d7f5d3SJohn Marino c_agent = (struct common_agent *)lookup_agent;
761*86d7f5d3SJohn Marino res = c_agent->lookup_func(
762*86d7f5d3SJohn Marino read_request->cache_key +
763*86d7f5d3SJohn Marino qstate->eid_str_length,
764*86d7f5d3SJohn Marino read_request->cache_key_size -
765*86d7f5d3SJohn Marino qstate->eid_str_length,
766*86d7f5d3SJohn Marino &read_response->data,
767*86d7f5d3SJohn Marino &read_response->data_size);
768*86d7f5d3SJohn Marino
769*86d7f5d3SJohn Marino if (res == NS_SUCCESS) {
770*86d7f5d3SJohn Marino read_response->error_code = 0;
771*86d7f5d3SJohn Marino configuration_lock_entry(
772*86d7f5d3SJohn Marino qstate->config_entry,
773*86d7f5d3SJohn Marino CELT_POSITIVE);
774*86d7f5d3SJohn Marino cache_write(c_entry,
775*86d7f5d3SJohn Marino read_request->cache_key,
776*86d7f5d3SJohn Marino read_request->cache_key_size,
777*86d7f5d3SJohn Marino read_response->data,
778*86d7f5d3SJohn Marino read_response->data_size);
779*86d7f5d3SJohn Marino configuration_unlock_entry(
780*86d7f5d3SJohn Marino qstate->config_entry,
781*86d7f5d3SJohn Marino CELT_POSITIVE);
782*86d7f5d3SJohn Marino } else if ((res == NS_NOTFOUND) ||
783*86d7f5d3SJohn Marino (res == NS_RETURN)) {
784*86d7f5d3SJohn Marino configuration_lock_entry(
785*86d7f5d3SJohn Marino qstate->config_entry,
786*86d7f5d3SJohn Marino CELT_NEGATIVE);
787*86d7f5d3SJohn Marino cache_write(neg_c_entry,
788*86d7f5d3SJohn Marino read_request->cache_key,
789*86d7f5d3SJohn Marino read_request->cache_key_size,
790*86d7f5d3SJohn Marino negative_data,
791*86d7f5d3SJohn Marino sizeof(negative_data));
792*86d7f5d3SJohn Marino configuration_unlock_entry(
793*86d7f5d3SJohn Marino qstate->config_entry,
794*86d7f5d3SJohn Marino CELT_NEGATIVE);
795*86d7f5d3SJohn Marino
796*86d7f5d3SJohn Marino read_response->error_code = 0;
797*86d7f5d3SJohn Marino read_response->data = NULL;
798*86d7f5d3SJohn Marino read_response->data_size = 0;
799*86d7f5d3SJohn Marino }
800*86d7f5d3SJohn Marino }
801*86d7f5d3SJohn Marino }
802*86d7f5d3SJohn Marino
803*86d7f5d3SJohn Marino if ((qstate->config_entry->common_query_timeout.tv_sec != 0) ||
804*86d7f5d3SJohn Marino (qstate->config_entry->common_query_timeout.tv_usec != 0))
805*86d7f5d3SJohn Marino memcpy(&qstate->timeout,
806*86d7f5d3SJohn Marino &qstate->config_entry->common_query_timeout,
807*86d7f5d3SJohn Marino sizeof(struct timeval));
808*86d7f5d3SJohn Marino } else
809*86d7f5d3SJohn Marino read_response->error_code = -1;
810*86d7f5d3SJohn Marino
811*86d7f5d3SJohn Marino fin:
812*86d7f5d3SJohn Marino qstate->kevent_filter = EVFILT_WRITE;
813*86d7f5d3SJohn Marino if (read_response->error_code == 0)
814*86d7f5d3SJohn Marino qstate->kevent_watermark = sizeof(int) + sizeof(size_t);
815*86d7f5d3SJohn Marino else
816*86d7f5d3SJohn Marino qstate->kevent_watermark = sizeof(int);
817*86d7f5d3SJohn Marino qstate->process_func = on_read_response_write1;
818*86d7f5d3SJohn Marino
819*86d7f5d3SJohn Marino TRACE_OUT(on_read_request_process);
820*86d7f5d3SJohn Marino return (0);
821*86d7f5d3SJohn Marino }
822*86d7f5d3SJohn Marino
823*86d7f5d3SJohn Marino static int
on_read_response_write1(struct query_state * qstate)824*86d7f5d3SJohn Marino on_read_response_write1(struct query_state *qstate)
825*86d7f5d3SJohn Marino {
826*86d7f5d3SJohn Marino struct cache_read_response *read_response;
827*86d7f5d3SJohn Marino ssize_t result;
828*86d7f5d3SJohn Marino
829*86d7f5d3SJohn Marino TRACE_IN(on_read_response_write1);
830*86d7f5d3SJohn Marino read_response = get_cache_read_response(&qstate->response);
831*86d7f5d3SJohn Marino
832*86d7f5d3SJohn Marino result = qstate->write_func(qstate, &read_response->error_code,
833*86d7f5d3SJohn Marino sizeof(int));
834*86d7f5d3SJohn Marino
835*86d7f5d3SJohn Marino if (read_response->error_code == 0) {
836*86d7f5d3SJohn Marino result += qstate->write_func(qstate, &read_response->data_size,
837*86d7f5d3SJohn Marino sizeof(size_t));
838*86d7f5d3SJohn Marino if (result != qstate->kevent_watermark) {
839*86d7f5d3SJohn Marino TRACE_OUT(on_read_response_write1);
840*86d7f5d3SJohn Marino return (-1);
841*86d7f5d3SJohn Marino }
842*86d7f5d3SJohn Marino
843*86d7f5d3SJohn Marino qstate->kevent_watermark = read_response->data_size;
844*86d7f5d3SJohn Marino qstate->process_func = on_read_response_write2;
845*86d7f5d3SJohn Marino } else {
846*86d7f5d3SJohn Marino if (result != qstate->kevent_watermark) {
847*86d7f5d3SJohn Marino TRACE_OUT(on_read_response_write1);
848*86d7f5d3SJohn Marino return (-1);
849*86d7f5d3SJohn Marino }
850*86d7f5d3SJohn Marino
851*86d7f5d3SJohn Marino qstate->kevent_watermark = 0;
852*86d7f5d3SJohn Marino qstate->process_func = NULL;
853*86d7f5d3SJohn Marino }
854*86d7f5d3SJohn Marino
855*86d7f5d3SJohn Marino TRACE_OUT(on_read_response_write1);
856*86d7f5d3SJohn Marino return (0);
857*86d7f5d3SJohn Marino }
858*86d7f5d3SJohn Marino
859*86d7f5d3SJohn Marino static int
on_read_response_write2(struct query_state * qstate)860*86d7f5d3SJohn Marino on_read_response_write2(struct query_state *qstate)
861*86d7f5d3SJohn Marino {
862*86d7f5d3SJohn Marino struct cache_read_response *read_response;
863*86d7f5d3SJohn Marino ssize_t result;
864*86d7f5d3SJohn Marino
865*86d7f5d3SJohn Marino TRACE_IN(on_read_response_write2);
866*86d7f5d3SJohn Marino read_response = get_cache_read_response(&qstate->response);
867*86d7f5d3SJohn Marino if (read_response->data_size > 0) {
868*86d7f5d3SJohn Marino result = qstate->write_func(qstate, read_response->data,
869*86d7f5d3SJohn Marino read_response->data_size);
870*86d7f5d3SJohn Marino if (result != qstate->kevent_watermark) {
871*86d7f5d3SJohn Marino TRACE_OUT(on_read_response_write2);
872*86d7f5d3SJohn Marino return (-1);
873*86d7f5d3SJohn Marino }
874*86d7f5d3SJohn Marino }
875*86d7f5d3SJohn Marino
876*86d7f5d3SJohn Marino finalize_comm_element(&qstate->request);
877*86d7f5d3SJohn Marino finalize_comm_element(&qstate->response);
878*86d7f5d3SJohn Marino
879*86d7f5d3SJohn Marino qstate->kevent_watermark = sizeof(int);
880*86d7f5d3SJohn Marino qstate->kevent_filter = EVFILT_READ;
881*86d7f5d3SJohn Marino qstate->process_func = on_rw_mapper;
882*86d7f5d3SJohn Marino TRACE_OUT(on_read_response_write2);
883*86d7f5d3SJohn Marino return (0);
884*86d7f5d3SJohn Marino }
885*86d7f5d3SJohn Marino
886*86d7f5d3SJohn Marino /*
887*86d7f5d3SJohn Marino * The functions below are used to process write requests.
888*86d7f5d3SJohn Marino * - on_transform_request_read1 and on_transform_request_read2 read the
889*86d7f5d3SJohn Marino * request itself
890*86d7f5d3SJohn Marino * - on_transform_request_process processes it
891*86d7f5d3SJohn Marino * - on_transform_response_write1 sends the response
892*86d7f5d3SJohn Marino */
893*86d7f5d3SJohn Marino static int
on_transform_request_read1(struct query_state * qstate)894*86d7f5d3SJohn Marino on_transform_request_read1(struct query_state *qstate)
895*86d7f5d3SJohn Marino {
896*86d7f5d3SJohn Marino struct cache_transform_request *transform_request;
897*86d7f5d3SJohn Marino ssize_t result;
898*86d7f5d3SJohn Marino
899*86d7f5d3SJohn Marino TRACE_IN(on_transform_request_read1);
900*86d7f5d3SJohn Marino if (qstate->kevent_watermark == 0)
901*86d7f5d3SJohn Marino qstate->kevent_watermark = sizeof(size_t) + sizeof(int);
902*86d7f5d3SJohn Marino else {
903*86d7f5d3SJohn Marino init_comm_element(&qstate->request, CET_TRANSFORM_REQUEST);
904*86d7f5d3SJohn Marino transform_request =
905*86d7f5d3SJohn Marino get_cache_transform_request(&qstate->request);
906*86d7f5d3SJohn Marino
907*86d7f5d3SJohn Marino result = qstate->read_func(qstate,
908*86d7f5d3SJohn Marino &transform_request->entry_length, sizeof(size_t));
909*86d7f5d3SJohn Marino result += qstate->read_func(qstate,
910*86d7f5d3SJohn Marino &transform_request->transformation_type, sizeof(int));
911*86d7f5d3SJohn Marino
912*86d7f5d3SJohn Marino if (result != sizeof(size_t) + sizeof(int)) {
913*86d7f5d3SJohn Marino TRACE_OUT(on_transform_request_read1);
914*86d7f5d3SJohn Marino return (-1);
915*86d7f5d3SJohn Marino }
916*86d7f5d3SJohn Marino
917*86d7f5d3SJohn Marino if ((transform_request->transformation_type != TT_USER) &&
918*86d7f5d3SJohn Marino (transform_request->transformation_type != TT_ALL)) {
919*86d7f5d3SJohn Marino TRACE_OUT(on_transform_request_read1);
920*86d7f5d3SJohn Marino return (-1);
921*86d7f5d3SJohn Marino }
922*86d7f5d3SJohn Marino
923*86d7f5d3SJohn Marino if (transform_request->entry_length != 0) {
924*86d7f5d3SJohn Marino if (BUFSIZE_INVALID(transform_request->entry_length)) {
925*86d7f5d3SJohn Marino TRACE_OUT(on_transform_request_read1);
926*86d7f5d3SJohn Marino return (-1);
927*86d7f5d3SJohn Marino }
928*86d7f5d3SJohn Marino
929*86d7f5d3SJohn Marino transform_request->entry = (char *)calloc(1,
930*86d7f5d3SJohn Marino transform_request->entry_length + 1);
931*86d7f5d3SJohn Marino assert(transform_request->entry != NULL);
932*86d7f5d3SJohn Marino
933*86d7f5d3SJohn Marino qstate->process_func = on_transform_request_read2;
934*86d7f5d3SJohn Marino } else
935*86d7f5d3SJohn Marino qstate->process_func = on_transform_request_process;
936*86d7f5d3SJohn Marino
937*86d7f5d3SJohn Marino qstate->kevent_watermark = transform_request->entry_length;
938*86d7f5d3SJohn Marino }
939*86d7f5d3SJohn Marino
940*86d7f5d3SJohn Marino TRACE_OUT(on_transform_request_read1);
941*86d7f5d3SJohn Marino return (0);
942*86d7f5d3SJohn Marino }
943*86d7f5d3SJohn Marino
944*86d7f5d3SJohn Marino static int
on_transform_request_read2(struct query_state * qstate)945*86d7f5d3SJohn Marino on_transform_request_read2(struct query_state *qstate)
946*86d7f5d3SJohn Marino {
947*86d7f5d3SJohn Marino struct cache_transform_request *transform_request;
948*86d7f5d3SJohn Marino ssize_t result;
949*86d7f5d3SJohn Marino
950*86d7f5d3SJohn Marino TRACE_IN(on_transform_request_read2);
951*86d7f5d3SJohn Marino transform_request = get_cache_transform_request(&qstate->request);
952*86d7f5d3SJohn Marino
953*86d7f5d3SJohn Marino result = qstate->read_func(qstate, transform_request->entry,
954*86d7f5d3SJohn Marino transform_request->entry_length);
955*86d7f5d3SJohn Marino
956*86d7f5d3SJohn Marino if (result != qstate->kevent_watermark) {
957*86d7f5d3SJohn Marino TRACE_OUT(on_transform_request_read2);
958*86d7f5d3SJohn Marino return (-1);
959*86d7f5d3SJohn Marino }
960*86d7f5d3SJohn Marino
961*86d7f5d3SJohn Marino qstate->kevent_watermark = 0;
962*86d7f5d3SJohn Marino qstate->process_func = on_transform_request_process;
963*86d7f5d3SJohn Marino
964*86d7f5d3SJohn Marino TRACE_OUT(on_transform_request_read2);
965*86d7f5d3SJohn Marino return (0);
966*86d7f5d3SJohn Marino }
967*86d7f5d3SJohn Marino
968*86d7f5d3SJohn Marino static int
on_transform_request_process(struct query_state * qstate)969*86d7f5d3SJohn Marino on_transform_request_process(struct query_state *qstate)
970*86d7f5d3SJohn Marino {
971*86d7f5d3SJohn Marino struct cache_transform_request *transform_request;
972*86d7f5d3SJohn Marino struct cache_transform_response *transform_response;
973*86d7f5d3SJohn Marino struct configuration_entry *config_entry;
974*86d7f5d3SJohn Marino size_t i, size;
975*86d7f5d3SJohn Marino
976*86d7f5d3SJohn Marino TRACE_IN(on_transform_request_process);
977*86d7f5d3SJohn Marino init_comm_element(&qstate->response, CET_TRANSFORM_RESPONSE);
978*86d7f5d3SJohn Marino transform_response = get_cache_transform_response(&qstate->response);
979*86d7f5d3SJohn Marino transform_request = get_cache_transform_request(&qstate->request);
980*86d7f5d3SJohn Marino
981*86d7f5d3SJohn Marino switch (transform_request->transformation_type) {
982*86d7f5d3SJohn Marino case TT_USER:
983*86d7f5d3SJohn Marino if (transform_request->entry == NULL) {
984*86d7f5d3SJohn Marino size = configuration_get_entries_size(s_configuration);
985*86d7f5d3SJohn Marino for (i = 0; i < size; ++i) {
986*86d7f5d3SJohn Marino config_entry = configuration_get_entry(
987*86d7f5d3SJohn Marino s_configuration, i);
988*86d7f5d3SJohn Marino
989*86d7f5d3SJohn Marino if (config_entry->perform_actual_lookups == 0)
990*86d7f5d3SJohn Marino clear_config_entry_part(config_entry,
991*86d7f5d3SJohn Marino qstate->eid_str, qstate->eid_str_length);
992*86d7f5d3SJohn Marino }
993*86d7f5d3SJohn Marino } else {
994*86d7f5d3SJohn Marino qstate->config_entry = configuration_find_entry(
995*86d7f5d3SJohn Marino s_configuration, transform_request->entry);
996*86d7f5d3SJohn Marino
997*86d7f5d3SJohn Marino if (qstate->config_entry == NULL) {
998*86d7f5d3SJohn Marino LOG_ERR_2("transform_request",
999*86d7f5d3SJohn Marino "can't find configuration"
1000*86d7f5d3SJohn Marino " entry '%s'. aborting request",
1001*86d7f5d3SJohn Marino transform_request->entry);
1002*86d7f5d3SJohn Marino transform_response->error_code = -1;
1003*86d7f5d3SJohn Marino goto fin;
1004*86d7f5d3SJohn Marino }
1005*86d7f5d3SJohn Marino
1006*86d7f5d3SJohn Marino if (qstate->config_entry->perform_actual_lookups != 0) {
1007*86d7f5d3SJohn Marino LOG_ERR_2("transform_request",
1008*86d7f5d3SJohn Marino "can't transform the cache entry %s"
1009*86d7f5d3SJohn Marino ", because it ised for actual lookups",
1010*86d7f5d3SJohn Marino transform_request->entry);
1011*86d7f5d3SJohn Marino transform_response->error_code = -1;
1012*86d7f5d3SJohn Marino goto fin;
1013*86d7f5d3SJohn Marino }
1014*86d7f5d3SJohn Marino
1015*86d7f5d3SJohn Marino clear_config_entry_part(qstate->config_entry,
1016*86d7f5d3SJohn Marino qstate->eid_str, qstate->eid_str_length);
1017*86d7f5d3SJohn Marino }
1018*86d7f5d3SJohn Marino break;
1019*86d7f5d3SJohn Marino case TT_ALL:
1020*86d7f5d3SJohn Marino if (qstate->euid != 0)
1021*86d7f5d3SJohn Marino transform_response->error_code = -1;
1022*86d7f5d3SJohn Marino else {
1023*86d7f5d3SJohn Marino if (transform_request->entry == NULL) {
1024*86d7f5d3SJohn Marino size = configuration_get_entries_size(
1025*86d7f5d3SJohn Marino s_configuration);
1026*86d7f5d3SJohn Marino for (i = 0; i < size; ++i) {
1027*86d7f5d3SJohn Marino clear_config_entry(
1028*86d7f5d3SJohn Marino configuration_get_entry(
1029*86d7f5d3SJohn Marino s_configuration, i));
1030*86d7f5d3SJohn Marino }
1031*86d7f5d3SJohn Marino } else {
1032*86d7f5d3SJohn Marino qstate->config_entry = configuration_find_entry(
1033*86d7f5d3SJohn Marino s_configuration,
1034*86d7f5d3SJohn Marino transform_request->entry);
1035*86d7f5d3SJohn Marino
1036*86d7f5d3SJohn Marino if (qstate->config_entry == NULL) {
1037*86d7f5d3SJohn Marino LOG_ERR_2("transform_request",
1038*86d7f5d3SJohn Marino "can't find configuration"
1039*86d7f5d3SJohn Marino " entry '%s'. aborting request",
1040*86d7f5d3SJohn Marino transform_request->entry);
1041*86d7f5d3SJohn Marino transform_response->error_code = -1;
1042*86d7f5d3SJohn Marino goto fin;
1043*86d7f5d3SJohn Marino }
1044*86d7f5d3SJohn Marino
1045*86d7f5d3SJohn Marino clear_config_entry(qstate->config_entry);
1046*86d7f5d3SJohn Marino }
1047*86d7f5d3SJohn Marino }
1048*86d7f5d3SJohn Marino break;
1049*86d7f5d3SJohn Marino default:
1050*86d7f5d3SJohn Marino transform_response->error_code = -1;
1051*86d7f5d3SJohn Marino }
1052*86d7f5d3SJohn Marino
1053*86d7f5d3SJohn Marino fin:
1054*86d7f5d3SJohn Marino qstate->kevent_watermark = 0;
1055*86d7f5d3SJohn Marino qstate->process_func = on_transform_response_write1;
1056*86d7f5d3SJohn Marino TRACE_OUT(on_transform_request_process);
1057*86d7f5d3SJohn Marino return (0);
1058*86d7f5d3SJohn Marino }
1059*86d7f5d3SJohn Marino
1060*86d7f5d3SJohn Marino static int
on_transform_response_write1(struct query_state * qstate)1061*86d7f5d3SJohn Marino on_transform_response_write1(struct query_state *qstate)
1062*86d7f5d3SJohn Marino {
1063*86d7f5d3SJohn Marino struct cache_transform_response *transform_response;
1064*86d7f5d3SJohn Marino ssize_t result;
1065*86d7f5d3SJohn Marino
1066*86d7f5d3SJohn Marino TRACE_IN(on_transform_response_write1);
1067*86d7f5d3SJohn Marino transform_response = get_cache_transform_response(&qstate->response);
1068*86d7f5d3SJohn Marino result = qstate->write_func(qstate, &transform_response->error_code,
1069*86d7f5d3SJohn Marino sizeof(int));
1070*86d7f5d3SJohn Marino if (result != sizeof(int)) {
1071*86d7f5d3SJohn Marino TRACE_OUT(on_transform_response_write1);
1072*86d7f5d3SJohn Marino return (-1);
1073*86d7f5d3SJohn Marino }
1074*86d7f5d3SJohn Marino
1075*86d7f5d3SJohn Marino finalize_comm_element(&qstate->request);
1076*86d7f5d3SJohn Marino finalize_comm_element(&qstate->response);
1077*86d7f5d3SJohn Marino
1078*86d7f5d3SJohn Marino qstate->kevent_watermark = 0;
1079*86d7f5d3SJohn Marino qstate->process_func = NULL;
1080*86d7f5d3SJohn Marino TRACE_OUT(on_transform_response_write1);
1081*86d7f5d3SJohn Marino return (0);
1082*86d7f5d3SJohn Marino }
1083*86d7f5d3SJohn Marino
1084*86d7f5d3SJohn Marino /*
1085*86d7f5d3SJohn Marino * Checks if the client's euid and egid do not differ from its uid and gid.
1086*86d7f5d3SJohn Marino * Returns 0 on success.
1087*86d7f5d3SJohn Marino */
1088*86d7f5d3SJohn Marino int
check_query_eids(struct query_state * qstate)1089*86d7f5d3SJohn Marino check_query_eids(struct query_state *qstate)
1090*86d7f5d3SJohn Marino {
1091*86d7f5d3SJohn Marino
1092*86d7f5d3SJohn Marino return ((qstate->uid != qstate->euid) || (qstate->gid != qstate->egid) ? -1 : 0);
1093*86d7f5d3SJohn Marino }
1094*86d7f5d3SJohn Marino
1095*86d7f5d3SJohn Marino /*
1096*86d7f5d3SJohn Marino * Uses the qstate fields to process an "alternate" read - when the buffer is
1097*86d7f5d3SJohn Marino * too large to be received during one socket read operation
1098*86d7f5d3SJohn Marino */
1099*86d7f5d3SJohn Marino ssize_t
query_io_buffer_read(struct query_state * qstate,void * buf,size_t nbytes)1100*86d7f5d3SJohn Marino query_io_buffer_read(struct query_state *qstate, void *buf, size_t nbytes)
1101*86d7f5d3SJohn Marino {
1102*86d7f5d3SJohn Marino ssize_t result;
1103*86d7f5d3SJohn Marino
1104*86d7f5d3SJohn Marino TRACE_IN(query_io_buffer_read);
1105*86d7f5d3SJohn Marino if ((qstate->io_buffer_size == 0) || (qstate->io_buffer == NULL))
1106*86d7f5d3SJohn Marino return (-1);
1107*86d7f5d3SJohn Marino
1108*86d7f5d3SJohn Marino if (nbytes < qstate->io_buffer + qstate->io_buffer_size -
1109*86d7f5d3SJohn Marino qstate->io_buffer_p)
1110*86d7f5d3SJohn Marino result = nbytes;
1111*86d7f5d3SJohn Marino else
1112*86d7f5d3SJohn Marino result = qstate->io_buffer + qstate->io_buffer_size -
1113*86d7f5d3SJohn Marino qstate->io_buffer_p;
1114*86d7f5d3SJohn Marino
1115*86d7f5d3SJohn Marino memcpy(buf, qstate->io_buffer_p, result);
1116*86d7f5d3SJohn Marino qstate->io_buffer_p += result;
1117*86d7f5d3SJohn Marino
1118*86d7f5d3SJohn Marino if (qstate->io_buffer_p == qstate->io_buffer + qstate->io_buffer_size) {
1119*86d7f5d3SJohn Marino free(qstate->io_buffer);
1120*86d7f5d3SJohn Marino qstate->io_buffer = NULL;
1121*86d7f5d3SJohn Marino
1122*86d7f5d3SJohn Marino qstate->write_func = query_socket_write;
1123*86d7f5d3SJohn Marino qstate->read_func = query_socket_read;
1124*86d7f5d3SJohn Marino }
1125*86d7f5d3SJohn Marino
1126*86d7f5d3SJohn Marino TRACE_OUT(query_io_buffer_read);
1127*86d7f5d3SJohn Marino return (result);
1128*86d7f5d3SJohn Marino }
1129*86d7f5d3SJohn Marino
1130*86d7f5d3SJohn Marino /*
1131*86d7f5d3SJohn Marino * Uses the qstate fields to process an "alternate" write - when the buffer is
1132*86d7f5d3SJohn Marino * too large to be sent during one socket write operation
1133*86d7f5d3SJohn Marino */
1134*86d7f5d3SJohn Marino ssize_t
query_io_buffer_write(struct query_state * qstate,const void * buf,size_t nbytes)1135*86d7f5d3SJohn Marino query_io_buffer_write(struct query_state *qstate, const void *buf,
1136*86d7f5d3SJohn Marino size_t nbytes)
1137*86d7f5d3SJohn Marino {
1138*86d7f5d3SJohn Marino ssize_t result;
1139*86d7f5d3SJohn Marino
1140*86d7f5d3SJohn Marino TRACE_IN(query_io_buffer_write);
1141*86d7f5d3SJohn Marino if ((qstate->io_buffer_size == 0) || (qstate->io_buffer == NULL))
1142*86d7f5d3SJohn Marino return (-1);
1143*86d7f5d3SJohn Marino
1144*86d7f5d3SJohn Marino if (nbytes < qstate->io_buffer + qstate->io_buffer_size -
1145*86d7f5d3SJohn Marino qstate->io_buffer_p)
1146*86d7f5d3SJohn Marino result = nbytes;
1147*86d7f5d3SJohn Marino else
1148*86d7f5d3SJohn Marino result = qstate->io_buffer + qstate->io_buffer_size -
1149*86d7f5d3SJohn Marino qstate->io_buffer_p;
1150*86d7f5d3SJohn Marino
1151*86d7f5d3SJohn Marino memcpy(qstate->io_buffer_p, buf, result);
1152*86d7f5d3SJohn Marino qstate->io_buffer_p += result;
1153*86d7f5d3SJohn Marino
1154*86d7f5d3SJohn Marino if (qstate->io_buffer_p == qstate->io_buffer + qstate->io_buffer_size) {
1155*86d7f5d3SJohn Marino qstate->use_alternate_io = 1;
1156*86d7f5d3SJohn Marino qstate->io_buffer_p = qstate->io_buffer;
1157*86d7f5d3SJohn Marino
1158*86d7f5d3SJohn Marino qstate->write_func = query_socket_write;
1159*86d7f5d3SJohn Marino qstate->read_func = query_socket_read;
1160*86d7f5d3SJohn Marino }
1161*86d7f5d3SJohn Marino
1162*86d7f5d3SJohn Marino TRACE_OUT(query_io_buffer_write);
1163*86d7f5d3SJohn Marino return (result);
1164*86d7f5d3SJohn Marino }
1165*86d7f5d3SJohn Marino
1166*86d7f5d3SJohn Marino /*
1167*86d7f5d3SJohn Marino * The default "read" function, which reads data directly from socket
1168*86d7f5d3SJohn Marino */
1169*86d7f5d3SJohn Marino ssize_t
query_socket_read(struct query_state * qstate,void * buf,size_t nbytes)1170*86d7f5d3SJohn Marino query_socket_read(struct query_state *qstate, void *buf, size_t nbytes)
1171*86d7f5d3SJohn Marino {
1172*86d7f5d3SJohn Marino ssize_t result;
1173*86d7f5d3SJohn Marino
1174*86d7f5d3SJohn Marino TRACE_IN(query_socket_read);
1175*86d7f5d3SJohn Marino if (qstate->socket_failed != 0) {
1176*86d7f5d3SJohn Marino TRACE_OUT(query_socket_read);
1177*86d7f5d3SJohn Marino return (-1);
1178*86d7f5d3SJohn Marino }
1179*86d7f5d3SJohn Marino
1180*86d7f5d3SJohn Marino result = read(qstate->sockfd, buf, nbytes);
1181*86d7f5d3SJohn Marino if ((result == -1) || (result < nbytes))
1182*86d7f5d3SJohn Marino qstate->socket_failed = 1;
1183*86d7f5d3SJohn Marino
1184*86d7f5d3SJohn Marino TRACE_OUT(query_socket_read);
1185*86d7f5d3SJohn Marino return (result);
1186*86d7f5d3SJohn Marino }
1187*86d7f5d3SJohn Marino
1188*86d7f5d3SJohn Marino /*
1189*86d7f5d3SJohn Marino * The default "write" function, which writes data directly to socket
1190*86d7f5d3SJohn Marino */
1191*86d7f5d3SJohn Marino ssize_t
query_socket_write(struct query_state * qstate,const void * buf,size_t nbytes)1192*86d7f5d3SJohn Marino query_socket_write(struct query_state *qstate, const void *buf, size_t nbytes)
1193*86d7f5d3SJohn Marino {
1194*86d7f5d3SJohn Marino ssize_t result;
1195*86d7f5d3SJohn Marino
1196*86d7f5d3SJohn Marino TRACE_IN(query_socket_write);
1197*86d7f5d3SJohn Marino if (qstate->socket_failed != 0) {
1198*86d7f5d3SJohn Marino TRACE_OUT(query_socket_write);
1199*86d7f5d3SJohn Marino return (-1);
1200*86d7f5d3SJohn Marino }
1201*86d7f5d3SJohn Marino
1202*86d7f5d3SJohn Marino result = write(qstate->sockfd, buf, nbytes);
1203*86d7f5d3SJohn Marino if ((result == -1) || (result < nbytes))
1204*86d7f5d3SJohn Marino qstate->socket_failed = 1;
1205*86d7f5d3SJohn Marino
1206*86d7f5d3SJohn Marino TRACE_OUT(query_socket_write);
1207*86d7f5d3SJohn Marino return (result);
1208*86d7f5d3SJohn Marino }
1209*86d7f5d3SJohn Marino
1210*86d7f5d3SJohn Marino /*
1211*86d7f5d3SJohn Marino * Initializes the query_state structure by filling it with the default values.
1212*86d7f5d3SJohn Marino */
1213*86d7f5d3SJohn Marino struct query_state *
init_query_state(int sockfd,size_t kevent_watermark,uid_t euid,gid_t egid)1214*86d7f5d3SJohn Marino init_query_state(int sockfd, size_t kevent_watermark, uid_t euid, gid_t egid)
1215*86d7f5d3SJohn Marino {
1216*86d7f5d3SJohn Marino struct query_state *retval;
1217*86d7f5d3SJohn Marino
1218*86d7f5d3SJohn Marino TRACE_IN(init_query_state);
1219*86d7f5d3SJohn Marino retval = (struct query_state *)calloc(1, sizeof(struct query_state));
1220*86d7f5d3SJohn Marino assert(retval != NULL);
1221*86d7f5d3SJohn Marino
1222*86d7f5d3SJohn Marino retval->sockfd = sockfd;
1223*86d7f5d3SJohn Marino retval->kevent_filter = EVFILT_READ;
1224*86d7f5d3SJohn Marino retval->kevent_watermark = kevent_watermark;
1225*86d7f5d3SJohn Marino
1226*86d7f5d3SJohn Marino retval->euid = euid;
1227*86d7f5d3SJohn Marino retval->egid = egid;
1228*86d7f5d3SJohn Marino retval->uid = retval->gid = -1;
1229*86d7f5d3SJohn Marino
1230*86d7f5d3SJohn Marino if (asprintf(&retval->eid_str, "%d_%d_", retval->euid,
1231*86d7f5d3SJohn Marino retval->egid) == -1) {
1232*86d7f5d3SJohn Marino free(retval);
1233*86d7f5d3SJohn Marino return (NULL);
1234*86d7f5d3SJohn Marino }
1235*86d7f5d3SJohn Marino retval->eid_str_length = strlen(retval->eid_str);
1236*86d7f5d3SJohn Marino
1237*86d7f5d3SJohn Marino init_comm_element(&retval->request, CET_UNDEFINED);
1238*86d7f5d3SJohn Marino init_comm_element(&retval->response, CET_UNDEFINED);
1239*86d7f5d3SJohn Marino retval->process_func = on_query_startup;
1240*86d7f5d3SJohn Marino retval->destroy_func = on_query_destroy;
1241*86d7f5d3SJohn Marino
1242*86d7f5d3SJohn Marino retval->write_func = query_socket_write;
1243*86d7f5d3SJohn Marino retval->read_func = query_socket_read;
1244*86d7f5d3SJohn Marino
1245*86d7f5d3SJohn Marino get_time_func(&retval->creation_time);
1246*86d7f5d3SJohn Marino memcpy(&retval->timeout, &s_configuration->query_timeout,
1247*86d7f5d3SJohn Marino sizeof(struct timeval));
1248*86d7f5d3SJohn Marino
1249*86d7f5d3SJohn Marino TRACE_OUT(init_query_state);
1250*86d7f5d3SJohn Marino return (retval);
1251*86d7f5d3SJohn Marino }
1252*86d7f5d3SJohn Marino
1253*86d7f5d3SJohn Marino void
destroy_query_state(struct query_state * qstate)1254*86d7f5d3SJohn Marino destroy_query_state(struct query_state *qstate)
1255*86d7f5d3SJohn Marino {
1256*86d7f5d3SJohn Marino
1257*86d7f5d3SJohn Marino TRACE_IN(destroy_query_state);
1258*86d7f5d3SJohn Marino if (qstate->eid_str != NULL)
1259*86d7f5d3SJohn Marino free(qstate->eid_str);
1260*86d7f5d3SJohn Marino
1261*86d7f5d3SJohn Marino if (qstate->io_buffer != NULL)
1262*86d7f5d3SJohn Marino free(qstate->io_buffer);
1263*86d7f5d3SJohn Marino
1264*86d7f5d3SJohn Marino qstate->destroy_func(qstate);
1265*86d7f5d3SJohn Marino free(qstate);
1266*86d7f5d3SJohn Marino TRACE_OUT(destroy_query_state);
1267*86d7f5d3SJohn Marino }
1268