Line data Source code
1 : /*
2 : Authors:
3 : Pavel Březina <pbrezina@redhat.com>
4 :
5 : Copyright (C) 2011 Red Hat
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <errno.h>
22 : #include <tevent.h>
23 : #include <talloc.h>
24 :
25 : #include "util/util.h"
26 : #include "providers/ldap/sdap.h"
27 : #include "providers/ldap/sdap_id_op.h"
28 : #include "providers/ldap/sdap_sudo.h"
29 :
30 : struct sdap_sudo_timer_state {
31 : struct tevent_context *ev;
32 : struct sdap_sudo_ctx *sudo_ctx;
33 : time_t timeout; /* relative time how many seconds wait before
34 : canceling fn request */
35 : sdap_sudo_timer_fn_t fn; /* request executed on 'when' */
36 :
37 : struct tevent_req *subreq;
38 : struct tevent_timer *timer_timeout;
39 : };
40 :
41 : static void sdap_sudo_timer(struct tevent_context *ev,
42 : struct tevent_timer *tt,
43 : struct timeval tv, void *pvt);
44 :
45 : static void sdap_sudo_timer_done(struct tevent_req *subreq);
46 :
47 : static void sdap_sudo_timer_timeout(struct tevent_context *ev,
48 : struct tevent_timer *tt,
49 : struct timeval tv, void *pvt);
50 :
51 0 : struct tevent_req * sdap_sudo_timer_send(TALLOC_CTX *mem_ctx,
52 : struct tevent_context *ev,
53 : struct sdap_sudo_ctx *sudo_ctx,
54 : struct timeval when,
55 : time_t timeout,
56 : sdap_sudo_timer_fn_t fn)
57 : {
58 0 : struct tevent_req *req = NULL;
59 0 : struct tevent_timer *timer = NULL;
60 0 : struct sdap_sudo_timer_state *state = NULL;
61 : int ret;
62 :
63 : /* create request */
64 0 : req = tevent_req_create(mem_ctx, &state, struct sdap_sudo_timer_state);
65 0 : if (req == NULL) {
66 0 : DEBUG(SSSDBG_FATAL_FAILURE, "tevent_req_create() failed\n");
67 0 : return NULL;
68 : }
69 :
70 0 : state->ev = ev;
71 0 : state->sudo_ctx = sudo_ctx;
72 0 : state->timeout = timeout;
73 0 : state->fn = fn;
74 :
75 : /* set timer */
76 0 : timer = tevent_add_timer(ev, req, when, sdap_sudo_timer, req);
77 0 : if (timer == NULL) {
78 0 : DEBUG(SSSDBG_FATAL_FAILURE, "tevent_add_timer() failed\n");
79 0 : ret = ENOMEM;
80 0 : goto immediately;
81 : }
82 :
83 0 : return req;
84 :
85 : immediately:
86 0 : if (ret == EOK) {
87 0 : tevent_req_done(req);
88 : } else {
89 0 : tevent_req_error(req, ret);
90 : }
91 0 : tevent_req_post(req, ev);
92 :
93 0 : return req;
94 : }
95 :
96 0 : int sdap_sudo_timer_recv(TALLOC_CTX *mem_ctx,
97 : struct tevent_req *req,
98 : struct tevent_req **_subreq)
99 : {
100 0 : struct sdap_sudo_timer_state *state = NULL;
101 :
102 0 : state = tevent_req_data(req, struct sdap_sudo_timer_state);
103 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
104 :
105 0 : *_subreq = talloc_steal(mem_ctx, state->subreq);
106 :
107 0 : return EOK;
108 : }
109 :
110 0 : static void sdap_sudo_timer(struct tevent_context *ev,
111 : struct tevent_timer *tt,
112 : struct timeval tv, void *pvt)
113 : {
114 0 : struct tevent_req *req = NULL;
115 0 : struct sdap_sudo_timer_state *state = NULL;
116 :
117 0 : req = talloc_get_type(pvt, struct tevent_req);
118 0 : state = tevent_req_data(req, struct sdap_sudo_timer_state);
119 :
120 : /* issue request */
121 0 : state->subreq = state->fn(state, state->sudo_ctx);
122 0 : if (state->subreq == NULL) {
123 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to issue timed request!\n");
124 0 : tevent_req_error(req, ENOMEM);
125 0 : return;
126 : }
127 :
128 0 : tevent_req_set_callback(state->subreq, sdap_sudo_timer_done, req);
129 :
130 : /* schedule timeout */
131 0 : tv = tevent_timeval_current_ofs(state->timeout, 0);
132 0 : state->timer_timeout = tevent_add_timer(state->ev, state->subreq, tv,
133 : sdap_sudo_timer_timeout, req);
134 0 : if (state->timer_timeout == NULL) {
135 : /* If we can't guarantee a timeout, we
136 : * need to cancel the request, to avoid
137 : * the possibility of starting another
138 : * concurrently
139 : */
140 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set timeout, "
141 : "canceling request!\n");
142 0 : talloc_zfree(state->subreq);
143 0 : tevent_req_error(req, ENOMEM);
144 : }
145 : }
146 :
147 0 : static void sdap_sudo_timer_done(struct tevent_req *subreq)
148 : {
149 0 : struct tevent_req *req = NULL;
150 0 : struct sdap_sudo_timer_state *state = NULL;
151 :
152 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
153 : /* do not free subreq, it is returned in recv */
154 :
155 : /* cancel timeout */
156 0 : state = tevent_req_data(req, struct sdap_sudo_timer_state);
157 0 : talloc_zfree(state->timer_timeout);
158 :
159 0 : tevent_req_done(req);
160 0 : }
161 :
162 0 : static void sdap_sudo_timer_timeout(struct tevent_context *ev,
163 : struct tevent_timer *tt,
164 : struct timeval tv, void *pvt)
165 : {
166 0 : struct tevent_req *req = NULL;
167 0 : struct sdap_sudo_timer_state *state = NULL;
168 :
169 0 : req = talloc_get_type(pvt, struct tevent_req);
170 0 : state = tevent_req_data(req, struct sdap_sudo_timer_state);
171 :
172 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Request timed out. Is timeout too small?"
173 : " (%lds)!\n", state->timeout);
174 :
175 0 : talloc_zfree(state->subreq);
176 :
177 0 : tevent_req_error(req, EAGAIN);
178 0 : }
|