~bug-zappers/ubuntu/lucid/samba/bugzapping

« back to all changes in this revision

Viewing changes to source/nsswitch/winbindd_dual.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-10-15 12:31:58 UTC
  • Revision ID: james.westby@ubuntu.com-20041015123158-aokykzdqkdgy6dfx
Tags: upstream-3.0.7
ImportĀ upstreamĀ versionĀ 3.0.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/CIFS implementation.
 
3
 
 
4
   Winbind background daemon
 
5
 
 
6
   Copyright (C) Andrew Tridgell 2002
 
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 2 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, write to the Free Software
 
20
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
21
*/
 
22
 
 
23
/*
 
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
 
29
 
 
30
 */
 
31
 
 
32
#include "includes.h"
 
33
#include "winbindd.h"
 
34
 
 
35
#undef DBGC_CLASS
 
36
#define DBGC_CLASS DBGC_WINBIND
 
37
 
 
38
extern BOOL opt_dual_daemon;
 
39
BOOL background_process = False;
 
40
int dual_daemon_pipe = -1;
 
41
 
 
42
 
 
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;
 
49
};
 
50
 
 
51
static struct dual_list *dual_list;
 
52
static struct dual_list *dual_list_end;
 
53
 
 
54
/*
 
55
  setup a select() including the dual daemon pipe
 
56
 */
 
57
int dual_select_setup(fd_set *fds, int maxfd)
 
58
{
 
59
        if (dual_daemon_pipe == -1 ||
 
60
            !dual_list) {
 
61
                return maxfd;
 
62
        }
 
63
 
 
64
        FD_SET(dual_daemon_pipe, fds);
 
65
        if (dual_daemon_pipe > maxfd) {
 
66
                maxfd = dual_daemon_pipe;
 
67
        }
 
68
        return maxfd;
 
69
}
 
70
 
 
71
 
 
72
/*
 
73
  a hook called from the main winbindd select() loop to handle writes
 
74
  to the dual daemon pipe 
 
75
*/
 
76
void dual_select(fd_set *fds)
 
77
{
 
78
        int n;
 
79
 
 
80
        if (dual_daemon_pipe == -1 ||
 
81
            !dual_list ||
 
82
            !FD_ISSET(dual_daemon_pipe, fds)) {
 
83
                return;
 
84
        }
 
85
 
 
86
        n = sys_write(dual_daemon_pipe, 
 
87
                  &dual_list->data[dual_list->offset],
 
88
                  dual_list->length - dual_list->offset);
 
89
 
 
90
        if (n <= 0) {
 
91
                /* the pipe is dead! fall back to normal operation */
 
92
                dual_daemon_pipe = -1;
 
93
                return;
 
94
        }
 
95
 
 
96
        dual_list->offset += n;
 
97
 
 
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;
 
106
                }
 
107
        }
 
108
}
 
109
 
 
110
/* 
 
111
   send a request to the background daemon 
 
112
   this is called for stale cached entries
 
113
*/
 
114
void dual_send_request(struct winbindd_cli_state *state)
 
115
{
 
116
        struct dual_list *list;
 
117
 
 
118
        if (!background_process) return;
 
119
 
 
120
        list = malloc(sizeof(*list));
 
121
        if (!list) return;
 
122
 
 
123
        list->next = NULL;
 
124
        list->data = memdup(&state->request, sizeof(state->request));
 
125
        list->length = sizeof(state->request);
 
126
        list->offset = 0;
 
127
        
 
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;
 
134
        }
 
135
 
 
136
        background_process = False;
 
137
}
 
138
 
 
139
 
 
140
/* 
 
141
the main dual daemon 
 
142
*/
 
143
void do_dual_daemon(void)
 
144
{
 
145
        int fdpair[2];
 
146
        struct winbindd_cli_state state;
 
147
        
 
148
        if (pipe(fdpair) != 0) {
 
149
                return;
 
150
        }
 
151
 
 
152
        ZERO_STRUCT(state);
 
153
        state.pid = getpid();
 
154
 
 
155
        dual_daemon_pipe = fdpair[1];
 
156
        state.sock = fdpair[0];
 
157
 
 
158
        if (fork() != 0) {
 
159
                close(fdpair[0]);
 
160
                return;
 
161
        }
 
162
        close(fdpair[1]);
 
163
 
 
164
        /* tdb needs special fork handling */
 
165
        if (tdb_reopen_all() == -1) {
 
166
                DEBUG(0,("tdb_reopen_all failed.\n"));
 
167
                _exit(0);
 
168
        }
 
169
        
 
170
        dual_daemon_pipe = -1;
 
171
        opt_dual_daemon = False;
 
172
 
 
173
        while (1) {
 
174
                /* free up any talloc memory */
 
175
                lp_talloc_free();
 
176
                main_loop_talloc_free();
 
177
 
 
178
                /* fetch a request from the main daemon */
 
179
                winbind_client_read(&state);
 
180
 
 
181
                if (state.finished) {
 
182
                        /* we lost contact with our parent */
 
183
                        exit(0);
 
184
                }
 
185
 
 
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));
 
189
 
 
190
                        /* special handling for the stateful requests */
 
191
                        switch (state.request.cmd) {
 
192
                        case WINBINDD_GETPWENT:
 
193
                                winbindd_setpwent(&state);
 
194
                                break;
 
195
                                
 
196
                        case WINBINDD_GETGRENT:
 
197
                        case WINBINDD_GETGRLST:
 
198
                                winbindd_setgrent(&state);
 
199
                                break;
 
200
                        default:
 
201
                                break;
 
202
                        }
 
203
 
 
204
                        winbind_process_packet(&state);
 
205
                        SAFE_FREE(state.response.extra_data);
 
206
 
 
207
                        free_getent_state(state.getpwent_state);
 
208
                        free_getent_state(state.getgrent_state);
 
209
                        state.getpwent_state = NULL;
 
210
                        state.getgrent_state = NULL;
 
211
                }
 
212
        }
 
213
}
 
214