• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.5.8/source3/winbindd/
1/*
2   Unix SMB/CIFS implementation.
3   async implementation of WINBINDD_SHOW_SEQUENCE
4   Copyright (C) Volker Lendecke 2009
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 3 of the License, or
9   (at your option) any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#include "includes.h"
21#include "winbindd.h"
22
23struct winbindd_show_sequence_state {
24	bool one_domain;
25	/* One domain */
26	uint32_t seqnum;
27
28	/* All domains */
29	int num_domains;
30	NTSTATUS *stati;
31	struct winbindd_domain **domains;
32	uint32_t *seqnums;
33};
34
35static void winbindd_show_sequence_done_one(struct tevent_req *subreq);
36static void winbindd_show_sequence_done_all(struct tevent_req *subreq);
37
38struct tevent_req *winbindd_show_sequence_send(TALLOC_CTX *mem_ctx,
39					       struct tevent_context *ev,
40					       struct winbindd_cli_state *cli,
41					       struct winbindd_request *request)
42{
43	struct tevent_req *req, *subreq;
44	struct winbindd_show_sequence_state *state;
45
46	req = tevent_req_create(mem_ctx, &state,
47				struct winbindd_show_sequence_state);
48	if (req == NULL) {
49		return NULL;
50	}
51	state->one_domain = false;
52	state->domains = NULL;
53	state->stati = NULL;
54	state->seqnums = NULL;
55
56	/* Ensure null termination */
57	request->domain_name[sizeof(request->domain_name)-1]='\0';
58
59	DEBUG(3, ("show_sequence %s\n", request->domain_name));
60
61	if (request->domain_name[0] != '\0') {
62		struct winbindd_domain *domain;
63
64		state->one_domain = true;
65
66		domain = find_domain_from_name_noinit(
67			request->domain_name);
68		if (domain == NULL) {
69			tevent_req_nterror(req, NT_STATUS_NO_SUCH_DOMAIN);
70			return tevent_req_post(req, ev);
71		}
72
73		subreq = wb_seqnum_send(state, ev, domain);
74		if (tevent_req_nomem(subreq, req)) {
75			return tevent_req_post(req, ev);
76		}
77		tevent_req_set_callback(
78			subreq, winbindd_show_sequence_done_one, req);
79		return req;
80	}
81
82	subreq = wb_seqnums_send(state, ev);
83	if (tevent_req_nomem(subreq, req)) {
84		return tevent_req_post(req, ev);
85	}
86	tevent_req_set_callback(subreq, winbindd_show_sequence_done_all, req);
87	return req;
88}
89
90static void winbindd_show_sequence_done_one(struct tevent_req *subreq)
91{
92	struct tevent_req *req = tevent_req_callback_data(
93		subreq, struct tevent_req);
94	struct winbindd_show_sequence_state *state = tevent_req_data(
95		req, struct winbindd_show_sequence_state);
96	NTSTATUS status;
97
98	status = wb_seqnum_recv(subreq, &state->seqnum);
99	TALLOC_FREE(subreq);
100	if (!NT_STATUS_IS_OK(status)) {
101		tevent_req_nterror(req, status);
102		return;
103	}
104	tevent_req_done(req);
105}
106
107static void winbindd_show_sequence_done_all(struct tevent_req *subreq)
108{
109	struct tevent_req *req = tevent_req_callback_data(
110		subreq, struct tevent_req);
111	struct winbindd_show_sequence_state *state = tevent_req_data(
112		req, struct winbindd_show_sequence_state);
113	NTSTATUS status;
114
115	status = wb_seqnums_recv(subreq, state, &state->num_domains,
116				 &state->domains, &state->stati,
117				 &state->seqnums);
118	TALLOC_FREE(subreq);
119	if (!NT_STATUS_IS_OK(status)) {
120		tevent_req_nterror(req, status);
121		return;
122	}
123	tevent_req_done(req);
124}
125
126NTSTATUS winbindd_show_sequence_recv(struct tevent_req *req,
127				     struct winbindd_response *response)
128{
129	struct winbindd_show_sequence_state *state = tevent_req_data(
130		req, struct winbindd_show_sequence_state);
131	NTSTATUS status;
132	char *extra_data;
133	int i;
134
135	if (tevent_req_is_nterror(req, &status)) {
136		return status;
137	}
138
139	if (state->one_domain) {
140		response->data.sequence_number = state->seqnum;
141		return NT_STATUS_OK;
142	}
143
144	extra_data = talloc_strdup(response, "");
145	if (extra_data == NULL) {
146		return NT_STATUS_NO_MEMORY;
147	}
148
149	for (i=0; i<state->num_domains; i++) {
150		if (!NT_STATUS_IS_OK(state->stati[i])
151		    || (state->seqnums[i] == DOM_SEQUENCE_NONE)) {
152			extra_data = talloc_asprintf_append_buffer(
153				extra_data, "%s : DISCONNECTED\n",
154				state->domains[i]->name);
155		} else {
156			extra_data = talloc_asprintf_append_buffer(
157				extra_data, "%s : %d\n",
158				state->domains[i]->name,
159				(int)state->seqnums[i]);
160		}
161		if (extra_data == NULL) {
162			return NT_STATUS_NO_MEMORY;
163		}
164	}
165
166	response->extra_data.data = extra_data;
167	response->length += talloc_get_size(extra_data);
168	return NT_STATUS_OK;
169}
170