e6efb9b99ab5b6c7f20735884e497bf81858aff2
[ira/wip.git] / source3 / winbindd / wb_seqnums.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    async seqnums, update the seqnums in winbindd_cache.c
5
6    Copyright (C) Volker Lendecke 2009
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "winbindd.h"
24 #include "librpc/gen_ndr/cli_wbint.h"
25
26 struct wb_seqnums_state {
27         int num_domains;
28         int num_received;
29
30         struct tevent_req **subreqs;
31         struct winbindd_domain **domains;
32         NTSTATUS *stati;
33         uint32_t *seqnums;
34 };
35
36 static void wb_seqnums_done(struct tevent_req *subreq);
37
38 struct tevent_req *wb_seqnums_send(TALLOC_CTX *mem_ctx,
39                                    struct tevent_context *ev)
40 {
41         struct tevent_req *req;
42         struct wb_seqnums_state *state;
43         struct winbindd_domain *domain;
44         int i;
45
46         req = tevent_req_create(mem_ctx, &state, struct wb_seqnums_state);
47         if (req == NULL) {
48                 return NULL;
49         }
50         state->num_received = 0;
51         state->num_domains = 0;
52
53         for (domain = domain_list(); domain != NULL; domain = domain->next) {
54                 state->num_domains += 1;
55         }
56
57         state->subreqs = talloc_array(state, struct tevent_req *,
58                                       state->num_domains);
59         state->domains = talloc_array(state, struct winbindd_domain *,
60                                       state->num_domains);
61         state->stati = talloc_array(state, NTSTATUS, state->num_domains);
62         state->seqnums = talloc_array(state, uint32_t, state->num_domains);
63
64         if ((state->subreqs == NULL) || (state->domains == NULL) ||
65             (state->stati == NULL) || (state->seqnums == NULL)) {
66                 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
67                 return tevent_req_post(req, ev);
68         }
69
70         i = 0;
71
72         for (domain = domain_list(); domain != NULL; domain = domain->next) {
73                 state->domains[i] = domain;
74                 state->subreqs[i] = wb_seqnum_send(state->subreqs, ev, domain);
75                 if (tevent_req_nomem(state->subreqs[i], req)) {
76                         /* Don't even start all the other requests */
77                         TALLOC_FREE(state->subreqs);
78                         return tevent_req_post(req, ev);
79                 }
80                 tevent_req_set_callback(state->subreqs[i], wb_seqnums_done,
81                                         req);
82                 i += 1;
83         }
84         return req;
85 }
86
87 static void wb_seqnums_done(struct tevent_req *subreq)
88 {
89         struct tevent_req *req = tevent_req_callback_data(
90                 subreq, struct tevent_req);
91         struct wb_seqnums_state *state = tevent_req_data(
92                 req, struct wb_seqnums_state);
93         NTSTATUS status;
94         uint32_t seqnum;
95         int i;
96
97         status = wb_seqnum_recv(subreq, &seqnum);
98
99         for (i=0; i<state->num_domains; i++) {
100                 if (subreq == state->subreqs[i]) {
101                         state->subreqs[i] = NULL;
102                         state->stati[i] = status;
103                         if (NT_STATUS_IS_OK(status)) {
104                                 state->seqnums[i] = seqnum;
105
106                                 /*
107                                  * This first assignment might be removed
108                                  * later
109                                  */
110                                 state->domains[i]->sequence_number = seqnum;
111
112                                 wcache_store_seqnum(state->domains[i]->name,
113                                                     state->seqnums[i],
114                                                     time(NULL));
115                         }
116                         break;
117                 }
118         }
119         TALLOC_FREE(subreq);
120
121         state->num_received += 1;
122
123         if (state->num_received >= state->num_domains) {
124                 tevent_req_done(req);
125         }
126 }
127
128 NTSTATUS wb_seqnums_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
129                          int *num_domains, struct winbindd_domain ***domains,
130                          NTSTATUS **stati, uint32_t **seqnums)
131 {
132         struct wb_seqnums_state *state = tevent_req_data(
133                 req, struct wb_seqnums_state);
134         NTSTATUS status;
135
136         if (tevent_req_is_nterror(req, &status)) {
137                 return status;
138         }
139         *num_domains = state->num_domains;
140         *domains = talloc_move(mem_ctx, &state->domains);
141         *stati = talloc_move(mem_ctx, &state->stati);
142         *seqnums = talloc_move(mem_ctx, &state->seqnums);
143         return NT_STATUS_OK;
144 }