r4231: commiting changes to 3.0.10
[Samba.git] / source / nsswitch / winbindd_dual.c
blob587507ee29046c65960e87e07fc16e8b8538a957
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind background daemon
6 Copyright (C) Andrew Tridgell 2002
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 2 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 the idea of the optional dual daemon mode is ot prevent slow domain
25 responses from clagging up the rest of the system. When in dual
26 daemon mode winbindd always responds to requests from cache if the
27 request is in cache, and if the cached answer is stale then it asks
28 the "dual daemon" to update the cache for that request
32 #include "includes.h"
33 #include "winbindd.h"
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_WINBIND
38 extern BOOL opt_dual_daemon;
39 BOOL background_process = False;
40 int dual_daemon_pipe = -1;
43 /* a list of requests ready to be sent to the dual daemon */
44 struct dual_list {
45 struct dual_list *next;
46 char *data;
47 int length;
48 int offset;
51 static struct dual_list *dual_list;
52 static struct dual_list *dual_list_end;
55 setup a select() including the dual daemon pipe
57 int dual_select_setup(fd_set *fds, int maxfd)
59 if (dual_daemon_pipe == -1 ||
60 !dual_list) {
61 return maxfd;
64 FD_SET(dual_daemon_pipe, fds);
65 if (dual_daemon_pipe > maxfd) {
66 maxfd = dual_daemon_pipe;
68 return maxfd;
73 a hook called from the main winbindd select() loop to handle writes
74 to the dual daemon pipe
76 void dual_select(fd_set *fds)
78 int n;
80 if (dual_daemon_pipe == -1 ||
81 !dual_list ||
82 !FD_ISSET(dual_daemon_pipe, fds)) {
83 return;
86 n = sys_write(dual_daemon_pipe,
87 &dual_list->data[dual_list->offset],
88 dual_list->length - dual_list->offset);
90 if (n <= 0) {
91 /* the pipe is dead! fall back to normal operation */
92 dual_daemon_pipe = -1;
93 return;
96 dual_list->offset += n;
98 if (dual_list->offset == dual_list->length) {
99 struct dual_list *next;
100 next = dual_list->next;
101 free(dual_list->data);
102 free(dual_list);
103 dual_list = next;
104 if (!dual_list) {
105 dual_list_end = NULL;
111 send a request to the background daemon
112 this is called for stale cached entries
114 void dual_send_request(struct winbindd_cli_state *state)
116 struct dual_list *list;
118 if (!background_process) return;
120 list = SMB_MALLOC_P(struct dual_list);
121 if (!list) return;
123 list->next = NULL;
124 list->data = memdup(&state->request, sizeof(state->request));
125 list->length = sizeof(state->request);
126 list->offset = 0;
128 if (!dual_list_end) {
129 dual_list = list;
130 dual_list_end = list;
131 } else {
132 dual_list_end->next = list;
133 dual_list_end = list;
136 background_process = False;
141 the main dual daemon
143 void do_dual_daemon(void)
145 int fdpair[2];
146 struct winbindd_cli_state state;
148 if (pipe(fdpair) != 0) {
149 return;
152 ZERO_STRUCT(state);
153 state.pid = getpid();
155 dual_daemon_pipe = fdpair[1];
156 state.sock = fdpair[0];
158 if (sys_fork() != 0) {
159 close(fdpair[0]);
160 return;
162 close(fdpair[1]);
164 /* tdb needs special fork handling */
165 if (tdb_reopen_all() == -1) {
166 DEBUG(0,("tdb_reopen_all failed.\n"));
167 _exit(0);
170 dual_daemon_pipe = -1;
171 opt_dual_daemon = False;
173 while (1) {
174 /* free up any talloc memory */
175 lp_talloc_free();
176 main_loop_talloc_free();
178 /* fetch a request from the main daemon */
179 winbind_client_read(&state);
181 if (state.finished) {
182 /* we lost contact with our parent */
183 exit(0);
186 /* process full rquests */
187 if (state.read_buf_len == sizeof(state.request)) {
188 DEBUG(4,("dual daemon request %d\n", (int)state.request.cmd));
190 /* special handling for the stateful requests */
191 switch (state.request.cmd) {
192 case WINBINDD_GETPWENT:
193 winbindd_setpwent(&state);
194 break;
196 case WINBINDD_GETGRENT:
197 case WINBINDD_GETGRLST:
198 winbindd_setgrent(&state);
199 break;
200 default:
201 break;
204 winbind_process_packet(&state);
205 SAFE_FREE(state.response.extra_data);
207 free_getent_state(state.getpwent_state);
208 free_getent_state(state.getgrent_state);
209 state.getpwent_state = NULL;
210 state.getgrent_state = NULL;