s3-param use Auto define for lm_announce default
[kai/samba-autobuild/.git] / source3 / winbindd / winbindd_dual.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Winbind child daemons
5
6    Copyright (C) Andrew Tridgell 2002
7    Copyright (C) Volker Lendecke 2004,2005
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 /*
24  * We fork a child per domain to be able to act non-blocking in the main
25  * winbind daemon. A domain controller thousands of miles away being being
26  * slow replying with a 10.000 user list should not hold up netlogon calls
27  * that can be handled locally.
28  */
29
30 #include "includes.h"
31 #include "winbindd.h"
32 #include "nsswitch/wb_reqtrans.h"
33 #include "secrets.h"
34 #include "../lib/util/select.h"
35 #include "../libcli/security/security.h"
36 #include "system/select.h"
37 #include "messages.h"
38 #include "../lib/util/tevent_unix.h"
39
40 #undef DBGC_CLASS
41 #define DBGC_CLASS DBGC_WINBIND
42
43 extern bool override_logfile;
44 extern struct winbindd_methods cache_methods;
45
46 static struct winbindd_child *winbindd_children = NULL;
47
48 /* Read some data from a client connection */
49
50 static NTSTATUS child_read_request(struct winbindd_cli_state *state)
51 {
52         NTSTATUS status;
53
54         /* Read data */
55
56         status = read_data(state->sock, (char *)state->request,
57                            sizeof(*state->request));
58
59         if (!NT_STATUS_IS_OK(status)) {
60                 DEBUG(3, ("child_read_request: read_data failed: %s\n",
61                           nt_errstr(status)));
62                 return status;
63         }
64
65         if (state->request->extra_len == 0) {
66                 state->request->extra_data.data = NULL;
67                 return NT_STATUS_OK;
68         }
69
70         DEBUG(10, ("Need to read %d extra bytes\n", (int)state->request->extra_len));
71
72         state->request->extra_data.data =
73                 SMB_MALLOC_ARRAY(char, state->request->extra_len + 1);
74
75         if (state->request->extra_data.data == NULL) {
76                 DEBUG(0, ("malloc failed\n"));
77                 return NT_STATUS_NO_MEMORY;
78         }
79
80         /* Ensure null termination */
81         state->request->extra_data.data[state->request->extra_len] = '\0';
82
83         status= read_data(state->sock, state->request->extra_data.data,
84                           state->request->extra_len);
85
86         if (!NT_STATUS_IS_OK(status)) {
87                 DEBUG(0, ("Could not read extra data: %s\n",
88                           nt_errstr(status)));
89         }
90         return status;
91 }
92
93 /*
94  * Do winbind child async request. This is not simply wb_simple_trans. We have
95  * to do the queueing ourselves because while a request is queued, the child
96  * might have crashed, and we have to re-fork it in the _trigger function.
97  */
98
99 struct wb_child_request_state {
100         struct tevent_context *ev;
101         struct winbindd_child *child;
102         struct winbindd_request *request;
103         struct winbindd_response *response;
104 };
105
106 static bool fork_domain_child(struct winbindd_child *child);
107
108 static void wb_child_request_trigger(struct tevent_req *req,
109                                             void *private_data);
110 static void wb_child_request_done(struct tevent_req *subreq);
111
112 struct tevent_req *wb_child_request_send(TALLOC_CTX *mem_ctx,
113                                          struct tevent_context *ev,
114                                          struct winbindd_child *child,
115                                          struct winbindd_request *request)
116 {
117         struct tevent_req *req;
118         struct wb_child_request_state *state;
119
120         req = tevent_req_create(mem_ctx, &state,
121                                 struct wb_child_request_state);
122         if (req == NULL) {
123                 return NULL;
124         }
125
126         state->ev = ev;
127         state->child = child;
128         state->request = request;
129
130         if (!tevent_queue_add(child->queue, ev, req,
131                               wb_child_request_trigger, NULL)) {
132                 tevent_req_oom(req);
133                 return tevent_req_post(req, ev);
134         }
135         return req;
136 }
137
138 static void wb_child_request_trigger(struct tevent_req *req,
139                                      void *private_data)
140 {
141         struct wb_child_request_state *state = tevent_req_data(
142                 req, struct wb_child_request_state);
143         struct tevent_req *subreq;
144
145         if ((state->child->sock == -1) && (!fork_domain_child(state->child))) {
146                 tevent_req_error(req, errno);
147                 return;
148         }
149
150         subreq = wb_simple_trans_send(state, winbind_event_context(), NULL,
151                                       state->child->sock, state->request);
152         if (tevent_req_nomem(subreq, req)) {
153                 return;
154         }
155         tevent_req_set_callback(subreq, wb_child_request_done, req);
156         tevent_req_set_endtime(req, state->ev, timeval_current_ofs(300, 0));
157 }
158
159 static void wb_child_request_done(struct tevent_req *subreq)
160 {
161         struct tevent_req *req = tevent_req_callback_data(
162                 subreq, struct tevent_req);
163         struct wb_child_request_state *state = tevent_req_data(
164                 req, struct wb_child_request_state);
165         int ret, err;
166
167         ret = wb_simple_trans_recv(subreq, state, &state->response, &err);
168         TALLOC_FREE(subreq);
169         if (ret == -1) {
170                 /*
171                  * The basic parent/child communication broke, close
172                  * our socket
173                  */
174                 close(state->child->sock);
175                 state->child->sock = -1;
176                 DLIST_REMOVE(winbindd_children, state->child);
177                 tevent_req_error(req, err);
178                 return;
179         }
180         tevent_req_done(req);
181 }
182
183 int wb_child_request_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
184                           struct winbindd_response **presponse, int *err)
185 {
186         struct wb_child_request_state *state = tevent_req_data(
187                 req, struct wb_child_request_state);
188
189         if (tevent_req_is_unix_error(req, err)) {
190                 return -1;
191         }
192         *presponse = talloc_move(mem_ctx, &state->response);
193         return 0;
194 }
195
196 static bool winbindd_child_busy(struct winbindd_child *child)
197 {
198         return tevent_queue_length(child->queue) > 0;
199 }
200
201 static struct winbindd_child *find_idle_child(struct winbindd_domain *domain)
202 {
203         int i;
204
205         for (i=0; i<lp_winbind_max_domain_connections(); i++) {
206                 if (!winbindd_child_busy(&domain->children[i])) {
207                         return &domain->children[i];
208                 }
209         }
210
211         return NULL;
212 }
213
214 struct winbindd_child *choose_domain_child(struct winbindd_domain *domain)
215 {
216         struct winbindd_child *result;
217
218         result = find_idle_child(domain);
219         if (result != NULL) {
220                 return result;
221         }
222         return &domain->children[rand() % lp_winbind_max_domain_connections()];
223 }
224
225 struct dcerpc_binding_handle *dom_child_handle(struct winbindd_domain *domain)
226 {
227         struct winbindd_child *child;
228
229         child = choose_domain_child(domain);
230         return child->binding_handle;
231 }
232
233 struct wb_domain_request_state {
234         struct tevent_context *ev;
235         struct winbindd_domain *domain;
236         struct winbindd_child *child;
237         struct winbindd_request *request;
238         struct winbindd_request *init_req;
239         struct winbindd_response *response;
240 };
241
242 static void wb_domain_request_gotdc(struct tevent_req *subreq);
243 static void wb_domain_request_initialized(struct tevent_req *subreq);
244 static void wb_domain_request_done(struct tevent_req *subreq);
245
246 struct tevent_req *wb_domain_request_send(TALLOC_CTX *mem_ctx,
247                                           struct tevent_context *ev,
248                                           struct winbindd_domain *domain,
249                                           struct winbindd_request *request)
250 {
251         struct tevent_req *req, *subreq;
252         struct wb_domain_request_state *state;
253
254         req = tevent_req_create(mem_ctx, &state,
255                                 struct wb_domain_request_state);
256         if (req == NULL) {
257                 return NULL;
258         }
259
260         state->child = choose_domain_child(domain);
261
262         if (domain->initialized) {
263                 subreq = wb_child_request_send(state, ev, state->child,
264                                                request);
265                 if (tevent_req_nomem(subreq, req)) {
266                         return tevent_req_post(req, ev);
267                 }
268                 tevent_req_set_callback(subreq, wb_domain_request_done, req);
269                 return req;
270         }
271
272         state->domain = domain;
273         state->ev = ev;
274         state->request = request;
275
276         state->init_req = talloc_zero(state, struct winbindd_request);
277         if (tevent_req_nomem(state->init_req, req)) {
278                 return tevent_req_post(req, ev);
279         }
280
281         if (IS_DC || domain->primary || domain->internal) {
282                 /* The primary domain has to find the DC name itself */
283                 state->init_req->cmd = WINBINDD_INIT_CONNECTION;
284                 fstrcpy(state->init_req->domain_name, domain->name);
285                 state->init_req->data.init_conn.is_primary = domain->primary;
286                 fstrcpy(state->init_req->data.init_conn.dcname, "");
287
288                 subreq = wb_child_request_send(state, ev, state->child,
289                                                state->init_req);
290                 if (tevent_req_nomem(subreq, req)) {
291                         return tevent_req_post(req, ev);
292                 }
293                 tevent_req_set_callback(subreq, wb_domain_request_initialized,
294                                         req);
295                 return req;
296         }
297
298         /*
299          * Ask our DC for a DC name
300          */
301         domain = find_our_domain();
302
303         /* This is *not* the primary domain, let's ask our DC about a DC
304          * name */
305
306         state->init_req->cmd = WINBINDD_GETDCNAME;
307         fstrcpy(state->init_req->domain_name, domain->name);
308
309         subreq = wb_child_request_send(state, ev, state->child, request);
310         if (tevent_req_nomem(subreq, req)) {
311                 return tevent_req_post(req, ev);
312         }
313         tevent_req_set_callback(subreq, wb_domain_request_gotdc, req);
314         return req;
315 }
316
317 static void wb_domain_request_gotdc(struct tevent_req *subreq)
318 {
319         struct tevent_req *req = tevent_req_callback_data(
320                 subreq, struct tevent_req);
321         struct wb_domain_request_state *state = tevent_req_data(
322                 req, struct wb_domain_request_state);
323         struct winbindd_response *response;
324         int ret, err;
325
326         ret = wb_child_request_recv(subreq, talloc_tos(), &response, &err);
327         TALLOC_FREE(subreq);
328         if (ret == -1) {
329                 tevent_req_error(req, err);
330                 return;
331         }
332         state->init_req->cmd = WINBINDD_INIT_CONNECTION;
333         fstrcpy(state->init_req->domain_name, state->domain->name);
334         state->init_req->data.init_conn.is_primary = False;
335         fstrcpy(state->init_req->data.init_conn.dcname,
336                 response->data.dc_name);
337
338         TALLOC_FREE(response);
339
340         subreq = wb_child_request_send(state, state->ev, state->child,
341                                        state->init_req);
342         if (tevent_req_nomem(subreq, req)) {
343                 return;
344         }
345         tevent_req_set_callback(subreq, wb_domain_request_initialized, req);
346 }
347
348 static void wb_domain_request_initialized(struct tevent_req *subreq)
349 {
350         struct tevent_req *req = tevent_req_callback_data(
351                 subreq, struct tevent_req);
352         struct wb_domain_request_state *state = tevent_req_data(
353                 req, struct wb_domain_request_state);
354         struct winbindd_response *response;
355         int ret, err;
356
357         ret = wb_child_request_recv(subreq, talloc_tos(), &response, &err);
358         TALLOC_FREE(subreq);
359         if (ret == -1) {
360                 tevent_req_error(req, err);
361                 return;
362         }
363
364         if (!string_to_sid(&state->domain->sid,
365                            response->data.domain_info.sid)) {
366                 DEBUG(1,("init_child_recv: Could not convert sid %s "
367                         "from string\n", response->data.domain_info.sid));
368                 tevent_req_error(req, EINVAL);
369                 return;
370         }
371         fstrcpy(state->domain->name, response->data.domain_info.name);
372         fstrcpy(state->domain->alt_name, response->data.domain_info.alt_name);
373         state->domain->native_mode = response->data.domain_info.native_mode;
374         state->domain->active_directory =
375                 response->data.domain_info.active_directory;
376         state->domain->initialized = true;
377
378         TALLOC_FREE(response);
379
380         subreq = wb_child_request_send(state, state->ev, state->child,
381                                        state->request);
382         if (tevent_req_nomem(subreq, req)) {
383                 return;
384         }
385         tevent_req_set_callback(subreq, wb_domain_request_done, req);
386 }
387
388 static void wb_domain_request_done(struct tevent_req *subreq)
389 {
390         struct tevent_req *req = tevent_req_callback_data(
391                 subreq, struct tevent_req);
392         struct wb_domain_request_state *state = tevent_req_data(
393                 req, struct wb_domain_request_state);
394         int ret, err;
395
396         ret = wb_child_request_recv(subreq, talloc_tos(), &state->response,
397                                     &err);
398         TALLOC_FREE(subreq);
399         if (ret == -1) {
400                 tevent_req_error(req, err);
401                 return;
402         }
403         tevent_req_done(req);
404 }
405
406 int wb_domain_request_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
407                            struct winbindd_response **presponse, int *err)
408 {
409         struct wb_domain_request_state *state = tevent_req_data(
410                 req, struct wb_domain_request_state);
411
412         if (tevent_req_is_unix_error(req, err)) {
413                 return -1;
414         }
415         *presponse = talloc_move(mem_ctx, &state->response);
416         return 0;
417 }
418
419 static void child_process_request(struct winbindd_child *child,
420                                   struct winbindd_cli_state *state)
421 {
422         struct winbindd_domain *domain = child->domain;
423         const struct winbindd_child_dispatch_table *table = child->table;
424
425         /* Free response data - we may be interrupted and receive another
426            command before being able to send this data off. */
427
428         state->response->result = WINBINDD_ERROR;
429         state->response->length = sizeof(struct winbindd_response);
430
431         /* as all requests in the child are sync, we can use talloc_tos() */
432         state->mem_ctx = talloc_tos();
433
434         /* Process command */
435
436         for (; table->name; table++) {
437                 if (state->request->cmd == table->struct_cmd) {
438                         DEBUG(10,("child_process_request: request fn %s\n",
439                                   table->name));
440                         state->response->result = table->struct_fn(domain, state);
441                         return;
442                 }
443         }
444
445         DEBUG(1, ("child_process_request: unknown request fn number %d\n",
446                   (int)state->request->cmd));
447         state->response->result = WINBINDD_ERROR;
448 }
449
450 void setup_child(struct winbindd_domain *domain, struct winbindd_child *child,
451                  const struct winbindd_child_dispatch_table *table,
452                  const char *logprefix,
453                  const char *logname)
454 {
455         if (logprefix && logname) {
456                 char *logbase = NULL;
457
458                 if (*lp_logfile()) {
459                         char *end = NULL;
460
461                         if (asprintf(&logbase, "%s", lp_logfile()) < 0) {
462                                 smb_panic("Internal error: asprintf failed");
463                         }
464
465                         if ((end = strrchr_m(logbase, '/'))) {
466                                 *end = '\0';
467                         }
468                 } else {
469                         if (asprintf(&logbase, "%s", get_dyn_LOGFILEBASE()) < 0) {
470                                 smb_panic("Internal error: asprintf failed");
471                         }
472                 }
473
474                 if (asprintf(&child->logfilename, "%s/%s-%s",
475                              logbase, logprefix, logname) < 0) {
476                         SAFE_FREE(logbase);
477                         smb_panic("Internal error: asprintf failed");
478                 }
479
480                 SAFE_FREE(logbase);
481         } else {
482                 smb_panic("Internal error: logprefix == NULL && "
483                           "logname == NULL");
484         }
485
486         child->sock = -1;
487         child->domain = domain;
488         child->table = table;
489         child->queue = tevent_queue_create(NULL, "winbind_child");
490         SMB_ASSERT(child->queue != NULL);
491         child->binding_handle = wbint_binding_handle(NULL, domain, child);
492         SMB_ASSERT(child->binding_handle != NULL);
493 }
494
495 void winbind_child_died(pid_t pid)
496 {
497         struct winbindd_child *child;
498
499         for (child = winbindd_children; child != NULL; child = child->next) {
500                 if (child->pid == pid) {
501                         break;
502                 }
503         }
504
505         if (child == NULL) {
506                 DEBUG(5, ("Already reaped child %u died\n", (unsigned int)pid));
507                 return;
508         }
509
510         /* This will be re-added in fork_domain_child() */
511
512         DLIST_REMOVE(winbindd_children, child);
513         child->pid = 0;
514
515         if (child->sock != -1) {
516                 close(child->sock);
517                 child->sock = -1;
518         }
519 }
520
521 /* Ensure any negative cache entries with the netbios or realm names are removed. */
522
523 void winbindd_flush_negative_conn_cache(struct winbindd_domain *domain)
524 {
525         flush_negative_conn_cache_for_domain(domain->name);
526         if (*domain->alt_name) {
527                 flush_negative_conn_cache_for_domain(domain->alt_name);
528         }
529 }
530
531 /* 
532  * Parent winbindd process sets its own debug level first and then
533  * sends a message to all the winbindd children to adjust their debug
534  * level to that of parents.
535  */
536
537 void winbind_msg_debug(struct messaging_context *msg_ctx,
538                          void *private_data,
539                          uint32_t msg_type,
540                          struct server_id server_id,
541                          DATA_BLOB *data)
542 {
543         struct winbindd_child *child;
544
545         DEBUG(10,("winbind_msg_debug: got debug message.\n"));
546
547         debug_message(msg_ctx, private_data, MSG_DEBUG, server_id, data);
548
549         for (child = winbindd_children; child != NULL; child = child->next) {
550
551                 DEBUG(10,("winbind_msg_debug: sending message to pid %u.\n",
552                         (unsigned int)child->pid));
553
554                 messaging_send_buf(msg_ctx, pid_to_procid(child->pid),
555                            MSG_DEBUG,
556                            data->data,
557                            strlen((char *) data->data) + 1);
558         }
559 }
560
561 /* Set our domains as offline and forward the offline message to our children. */
562
563 void winbind_msg_offline(struct messaging_context *msg_ctx,
564                          void *private_data,
565                          uint32_t msg_type,
566                          struct server_id server_id,
567                          DATA_BLOB *data)
568 {
569         struct winbindd_child *child;
570         struct winbindd_domain *domain;
571
572         DEBUG(10,("winbind_msg_offline: got offline message.\n"));
573
574         if (!lp_winbind_offline_logon()) {
575                 DEBUG(10,("winbind_msg_offline: rejecting offline message.\n"));
576                 return;
577         }
578
579         /* Set our global state as offline. */
580         if (!set_global_winbindd_state_offline()) {
581                 DEBUG(10,("winbind_msg_offline: offline request failed.\n"));
582                 return;
583         }
584
585         /* Set all our domains as offline. */
586         for (domain = domain_list(); domain; domain = domain->next) {
587                 if (domain->internal) {
588                         continue;
589                 }
590                 DEBUG(5,("winbind_msg_offline: marking %s offline.\n", domain->name));
591                 set_domain_offline(domain);
592         }
593
594         for (child = winbindd_children; child != NULL; child = child->next) {
595                 /* Don't send message to internal children.  We've already
596                    done so above. */
597                 if (!child->domain || winbindd_internal_child(child)) {
598                         continue;
599                 }
600
601                 /* Or internal domains (this should not be possible....) */
602                 if (child->domain->internal) {
603                         continue;
604                 }
605
606                 /* Each winbindd child should only process requests for one domain - make sure
607                    we only set it online / offline for that domain. */
608
609                 DEBUG(10,("winbind_msg_offline: sending message to pid %u for domain %s.\n",
610                         (unsigned int)child->pid, domain->name ));
611
612                 messaging_send_buf(msg_ctx, pid_to_procid(child->pid),
613                                    MSG_WINBIND_OFFLINE,
614                                    (uint8 *)child->domain->name,
615                                    strlen(child->domain->name)+1);
616         }
617 }
618
619 /* Set our domains as online and forward the online message to our children. */
620
621 void winbind_msg_online(struct messaging_context *msg_ctx,
622                         void *private_data,
623                         uint32_t msg_type,
624                         struct server_id server_id,
625                         DATA_BLOB *data)
626 {
627         struct winbindd_child *child;
628         struct winbindd_domain *domain;
629
630         DEBUG(10,("winbind_msg_online: got online message.\n"));
631
632         if (!lp_winbind_offline_logon()) {
633                 DEBUG(10,("winbind_msg_online: rejecting online message.\n"));
634                 return;
635         }
636
637         /* Set our global state as online. */
638         set_global_winbindd_state_online();
639
640         smb_nscd_flush_user_cache();
641         smb_nscd_flush_group_cache();
642
643         /* Set all our domains as online. */
644         for (domain = domain_list(); domain; domain = domain->next) {
645                 if (domain->internal) {
646                         continue;
647                 }
648                 DEBUG(5,("winbind_msg_online: requesting %s to go online.\n", domain->name));
649
650                 winbindd_flush_negative_conn_cache(domain);
651                 set_domain_online_request(domain);
652
653                 /* Send an online message to the idmap child when our
654                    primary domain comes back online */
655
656                 if ( domain->primary ) {
657                         struct winbindd_child *idmap = idmap_child();
658
659                         if ( idmap->pid != 0 ) {
660                                 messaging_send_buf(msg_ctx,
661                                                    pid_to_procid(idmap->pid), 
662                                                    MSG_WINBIND_ONLINE,
663                                                    (uint8 *)domain->name,
664                                                    strlen(domain->name)+1);
665                         }
666                 }
667         }
668
669         for (child = winbindd_children; child != NULL; child = child->next) {
670                 /* Don't send message to internal childs. */
671                 if (!child->domain || winbindd_internal_child(child)) {
672                         continue;
673                 }
674
675                 /* Or internal domains (this should not be possible....) */
676                 if (child->domain->internal) {
677                         continue;
678                 }
679
680                 /* Each winbindd child should only process requests for one domain - make sure
681                    we only set it online / offline for that domain. */
682
683                 DEBUG(10,("winbind_msg_online: sending message to pid %u for domain %s.\n",
684                         (unsigned int)child->pid, child->domain->name ));
685
686                 messaging_send_buf(msg_ctx, pid_to_procid(child->pid),
687                                    MSG_WINBIND_ONLINE,
688                                    (uint8 *)child->domain->name,
689                                    strlen(child->domain->name)+1);
690         }
691 }
692
693 static const char *collect_onlinestatus(TALLOC_CTX *mem_ctx)
694 {
695         struct winbindd_domain *domain;
696         char *buf = NULL;
697
698         if ((buf = talloc_asprintf(mem_ctx, "global:%s ", 
699                                    get_global_winbindd_state_offline() ? 
700                                    "Offline":"Online")) == NULL) {
701                 return NULL;
702         }
703
704         for (domain = domain_list(); domain; domain = domain->next) {
705                 if ((buf = talloc_asprintf_append_buffer(buf, "%s:%s ", 
706                                                   domain->name, 
707                                                   domain->online ?
708                                                   "Online":"Offline")) == NULL) {
709                         return NULL;
710                 }
711         }
712
713         buf = talloc_asprintf_append_buffer(buf, "\n");
714
715         DEBUG(5,("collect_onlinestatus: %s", buf));
716
717         return buf;
718 }
719
720 void winbind_msg_onlinestatus(struct messaging_context *msg_ctx,
721                               void *private_data,
722                               uint32_t msg_type,
723                               struct server_id server_id,
724                               DATA_BLOB *data)
725 {
726         TALLOC_CTX *mem_ctx;
727         const char *message;
728         struct server_id *sender;
729
730         DEBUG(5,("winbind_msg_onlinestatus received.\n"));
731
732         if (!data->data) {
733                 return;
734         }
735
736         sender = (struct server_id *)data->data;
737
738         mem_ctx = talloc_init("winbind_msg_onlinestatus");
739         if (mem_ctx == NULL) {
740                 return;
741         }
742
743         message = collect_onlinestatus(mem_ctx);
744         if (message == NULL) {
745                 talloc_destroy(mem_ctx);
746                 return;
747         }
748
749         messaging_send_buf(msg_ctx, *sender, MSG_WINBIND_ONLINESTATUS, 
750                            (const uint8 *)message, strlen(message) + 1);
751
752         talloc_destroy(mem_ctx);
753 }
754
755 void winbind_msg_dump_event_list(struct messaging_context *msg_ctx,
756                                  void *private_data,
757                                  uint32_t msg_type,
758                                  struct server_id server_id,
759                                  DATA_BLOB *data)
760 {
761         struct winbindd_child *child;
762
763         DEBUG(10,("winbind_msg_dump_event_list received\n"));
764
765         dump_event_list(winbind_event_context());
766
767         for (child = winbindd_children; child != NULL; child = child->next) {
768
769                 DEBUG(10,("winbind_msg_dump_event_list: sending message to pid %u\n",
770                         (unsigned int)child->pid));
771
772                 messaging_send_buf(msg_ctx, pid_to_procid(child->pid),
773                                    MSG_DUMP_EVENT_LIST,
774                                    NULL, 0);
775         }
776
777 }
778
779 void winbind_msg_dump_domain_list(struct messaging_context *msg_ctx,
780                                   void *private_data,
781                                   uint32_t msg_type,
782                                   struct server_id server_id,
783                                   DATA_BLOB *data)
784 {
785         TALLOC_CTX *mem_ctx;
786         const char *message = NULL;
787         struct server_id *sender = NULL;
788         const char *domain = NULL;
789         char *s = NULL;
790         NTSTATUS status;
791         struct winbindd_domain *dom = NULL;
792
793         DEBUG(5,("winbind_msg_dump_domain_list received.\n"));
794
795         if (!data || !data->data) {
796                 return;
797         }
798
799         if (data->length < sizeof(struct server_id)) {
800                 return;
801         }
802
803         mem_ctx = talloc_init("winbind_msg_dump_domain_list");
804         if (!mem_ctx) {
805                 return;
806         }
807
808         sender = (struct server_id *)data->data;
809         if (data->length > sizeof(struct server_id)) {
810                 domain = (const char *)data->data+sizeof(struct server_id);
811         }
812
813         if (domain) {
814
815                 DEBUG(5,("winbind_msg_dump_domain_list for domain: %s\n",
816                         domain));
817
818                 message = NDR_PRINT_STRUCT_STRING(mem_ctx, winbindd_domain,
819                                                   find_domain_from_name_noinit(domain));
820                 if (!message) {
821                         talloc_destroy(mem_ctx);
822                         return;
823                 }
824
825                 messaging_send_buf(msg_ctx, *sender,
826                                    MSG_WINBIND_DUMP_DOMAIN_LIST,
827                                    (const uint8_t *)message, strlen(message) + 1);
828
829                 talloc_destroy(mem_ctx);
830
831                 return;
832         }
833
834         DEBUG(5,("winbind_msg_dump_domain_list all domains\n"));
835
836         for (dom = domain_list(); dom; dom=dom->next) {
837                 message = NDR_PRINT_STRUCT_STRING(mem_ctx, winbindd_domain, dom);
838                 if (!message) {
839                         talloc_destroy(mem_ctx);
840                         return;
841                 }
842
843                 s = talloc_asprintf_append(s, "%s\n", message);
844                 if (!s) {
845                         talloc_destroy(mem_ctx);
846                         return;
847                 }
848         }
849
850         status = messaging_send_buf(msg_ctx, *sender,
851                                     MSG_WINBIND_DUMP_DOMAIN_LIST,
852                                     (uint8_t *)s, strlen(s) + 1);
853         if (!NT_STATUS_IS_OK(status)) {
854                 DEBUG(0,("failed to send message: %s\n",
855                 nt_errstr(status)));
856         }
857
858         talloc_destroy(mem_ctx);
859 }
860
861 static void account_lockout_policy_handler(struct event_context *ctx,
862                                            struct timed_event *te,
863                                            struct timeval now,
864                                            void *private_data)
865 {
866         struct winbindd_child *child =
867                 (struct winbindd_child *)private_data;
868         TALLOC_CTX *mem_ctx = NULL;
869         struct winbindd_methods *methods;
870         struct samr_DomInfo12 lockout_policy;
871         NTSTATUS result;
872
873         DEBUG(10,("account_lockout_policy_handler called\n"));
874
875         TALLOC_FREE(child->lockout_policy_event);
876
877         if ( !winbindd_can_contact_domain( child->domain ) ) {
878                 DEBUG(10,("account_lockout_policy_handler: Removing myself since I "
879                           "do not have an incoming trust to domain %s\n", 
880                           child->domain->name));
881
882                 return;         
883         }
884
885         methods = child->domain->methods;
886
887         mem_ctx = talloc_init("account_lockout_policy_handler ctx");
888         if (!mem_ctx) {
889                 result = NT_STATUS_NO_MEMORY;
890         } else {
891                 result = methods->lockout_policy(child->domain, mem_ctx, &lockout_policy);
892         }
893         TALLOC_FREE(mem_ctx);
894
895         if (!NT_STATUS_IS_OK(result)) {
896                 DEBUG(10,("account_lockout_policy_handler: lockout_policy failed error %s\n",
897                          nt_errstr(result)));
898         }
899
900         child->lockout_policy_event = event_add_timed(winbind_event_context(), NULL,
901                                                       timeval_current_ofs(3600, 0),
902                                                       account_lockout_policy_handler,
903                                                       child);
904 }
905
906 static time_t get_machine_password_timeout(void)
907 {
908         /* until we have gpo support use lp setting */
909         return lp_machine_password_timeout();
910 }
911
912 static bool calculate_next_machine_pwd_change(const char *domain,
913                                               struct timeval *t)
914 {
915         time_t pass_last_set_time;
916         time_t timeout;
917         time_t next_change;
918         struct timeval tv;
919         char *pw;
920
921         pw = secrets_fetch_machine_password(domain,
922                                             &pass_last_set_time,
923                                             NULL);
924
925         if (pw == NULL) {
926                 DEBUG(0,("cannot fetch own machine password ????"));
927                 return false;
928         }
929
930         SAFE_FREE(pw);
931
932         timeout = get_machine_password_timeout();
933         if (timeout == 0) {
934                 DEBUG(10,("machine password never expires\n"));
935                 return false;
936         }
937
938         tv.tv_sec = pass_last_set_time;
939         DEBUG(10, ("password last changed %s\n",
940                    timeval_string(talloc_tos(), &tv, false)));
941         tv.tv_sec += timeout;
942         DEBUGADD(10, ("password valid until %s\n",
943                       timeval_string(talloc_tos(), &tv, false)));
944
945         if (time(NULL) < (pass_last_set_time + timeout)) {
946                 next_change = pass_last_set_time + timeout;
947                 DEBUG(10,("machine password still valid until: %s\n",
948                         http_timestring(talloc_tos(), next_change)));
949                 *t = timeval_set(next_change, 0);
950
951                 if (lp_clustering()) {
952                         uint8_t randbuf;
953                         /*
954                          * When having a cluster, we have several
955                          * winbinds racing for the password change. In
956                          * the machine_password_change_handler()
957                          * function we check if someone else was
958                          * faster when the event triggers. We add a
959                          * 255-second random delay here, so that we
960                          * don't run to change the password at the
961                          * exact same moment.
962                          */
963                         generate_random_buffer(&randbuf, sizeof(randbuf));
964                         DEBUG(10, ("adding %d seconds randomness\n",
965                                    (int)randbuf));
966                         t->tv_sec += randbuf;
967                 }
968                 return true;
969         }
970
971         DEBUG(10,("machine password expired, needs immediate change\n"));
972
973         *t = timeval_zero();
974
975         return true;
976 }
977
978 static void machine_password_change_handler(struct event_context *ctx,
979                                             struct timed_event *te,
980                                             struct timeval now,
981                                             void *private_data)
982 {
983         struct winbindd_child *child =
984                 (struct winbindd_child *)private_data;
985         struct rpc_pipe_client *netlogon_pipe = NULL;
986         TALLOC_CTX *frame;
987         NTSTATUS result;
988         struct timeval next_change;
989
990         DEBUG(10,("machine_password_change_handler called\n"));
991
992         TALLOC_FREE(child->machine_password_change_event);
993
994         if (!calculate_next_machine_pwd_change(child->domain->name,
995                                                &next_change)) {
996                 DEBUG(10, ("calculate_next_machine_pwd_change failed\n"));
997                 return;
998         }
999
1000         DEBUG(10, ("calculate_next_machine_pwd_change returned %s\n",
1001                    timeval_string(talloc_tos(), &next_change, false)));
1002
1003         if (!timeval_expired(&next_change)) {
1004                 DEBUG(10, ("Someone else has already changed the pw\n"));
1005                 goto done;
1006         }
1007
1008         if (!winbindd_can_contact_domain(child->domain)) {
1009                 DEBUG(10,("machine_password_change_handler: Removing myself since I "
1010                           "do not have an incoming trust to domain %s\n",
1011                           child->domain->name));
1012                 return;
1013         }
1014
1015         result = cm_connect_netlogon(child->domain, &netlogon_pipe);
1016         if (!NT_STATUS_IS_OK(result)) {
1017                 DEBUG(10,("machine_password_change_handler: "
1018                         "failed to connect netlogon pipe: %s\n",
1019                          nt_errstr(result)));
1020                 return;
1021         }
1022
1023         frame = talloc_stackframe();
1024
1025         result = trust_pw_find_change_and_store_it(netlogon_pipe,
1026                                                    frame,
1027                                                    child->domain->name);
1028         TALLOC_FREE(frame);
1029
1030         DEBUG(10, ("machine_password_change_handler: "
1031                    "trust_pw_find_change_and_store_it returned %s\n",
1032                    nt_errstr(result)));
1033
1034         if (NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) ) {
1035                 DEBUG(3,("machine_password_change_handler: password set returned "
1036                          "ACCESS_DENIED.  Maybe the trust account "
1037                          "password was changed and we didn't know it. "
1038                          "Killing connections to domain %s\n",
1039                          child->domain->name));
1040                 TALLOC_FREE(child->domain->conn.netlogon_pipe);
1041         }
1042
1043         if (!calculate_next_machine_pwd_change(child->domain->name,
1044                                                &next_change)) {
1045                 DEBUG(10, ("calculate_next_machine_pwd_change failed\n"));
1046                 return;
1047         }
1048
1049         DEBUG(10, ("calculate_next_machine_pwd_change returned %s\n",
1050                    timeval_string(talloc_tos(), &next_change, false)));
1051
1052         if (!NT_STATUS_IS_OK(result)) {
1053                 struct timeval tmp;
1054                 /*
1055                  * In case of failure, give the DC a minute to recover
1056                  */
1057                 tmp = timeval_current_ofs(60, 0);
1058                 next_change = timeval_max(&next_change, &tmp);
1059         }
1060
1061 done:
1062         child->machine_password_change_event = event_add_timed(winbind_event_context(), NULL,
1063                                                               next_change,
1064                                                               machine_password_change_handler,
1065                                                               child);
1066 }
1067
1068 /* Deal with a request to go offline. */
1069
1070 static void child_msg_offline(struct messaging_context *msg,
1071                               void *private_data,
1072                               uint32_t msg_type,
1073                               struct server_id server_id,
1074                               DATA_BLOB *data)
1075 {
1076         struct winbindd_domain *domain;
1077         struct winbindd_domain *primary_domain = NULL;
1078         const char *domainname = (const char *)data->data;
1079
1080         if (data->data == NULL || data->length == 0) {
1081                 return;
1082         }
1083
1084         DEBUG(5,("child_msg_offline received for domain %s.\n", domainname));
1085
1086         if (!lp_winbind_offline_logon()) {
1087                 DEBUG(10,("child_msg_offline: rejecting offline message.\n"));
1088                 return;
1089         }
1090
1091         primary_domain = find_our_domain();
1092
1093         /* Mark the requested domain offline. */
1094
1095         for (domain = domain_list(); domain; domain = domain->next) {
1096                 if (domain->internal) {
1097                         continue;
1098                 }
1099                 if (strequal(domain->name, domainname)) {
1100                         DEBUG(5,("child_msg_offline: marking %s offline.\n", domain->name));
1101                         set_domain_offline(domain);
1102                         /* we are in the trusted domain, set the primary domain 
1103                          * offline too */
1104                         if (domain != primary_domain) {
1105                                 set_domain_offline(primary_domain);
1106                         }
1107                 }
1108         }
1109 }
1110
1111 /* Deal with a request to go online. */
1112
1113 static void child_msg_online(struct messaging_context *msg,
1114                              void *private_data,
1115                              uint32_t msg_type,
1116                              struct server_id server_id,
1117                              DATA_BLOB *data)
1118 {
1119         struct winbindd_domain *domain;
1120         struct winbindd_domain *primary_domain = NULL;
1121         const char *domainname = (const char *)data->data;
1122
1123         if (data->data == NULL || data->length == 0) {
1124                 return;
1125         }
1126
1127         DEBUG(5,("child_msg_online received for domain %s.\n", domainname));
1128
1129         if (!lp_winbind_offline_logon()) {
1130                 DEBUG(10,("child_msg_online: rejecting online message.\n"));
1131                 return;
1132         }
1133
1134         primary_domain = find_our_domain();
1135
1136         /* Set our global state as online. */
1137         set_global_winbindd_state_online();
1138
1139         /* Try and mark everything online - delete any negative cache entries
1140            to force a reconnect now. */
1141
1142         for (domain = domain_list(); domain; domain = domain->next) {
1143                 if (domain->internal) {
1144                         continue;
1145                 }
1146                 if (strequal(domain->name, domainname)) {
1147                         DEBUG(5,("child_msg_online: requesting %s to go online.\n", domain->name));
1148                         winbindd_flush_negative_conn_cache(domain);
1149                         set_domain_online_request(domain);
1150
1151                         /* we can be in trusted domain, which will contact primary domain
1152                          * we have to bring primary domain online in trusted domain process
1153                          * see, winbindd_dual_pam_auth() --> winbindd_dual_pam_auth_samlogon()
1154                          * --> contact_domain = find_our_domain()
1155                          * */
1156                         if (domain != primary_domain) {
1157                                 winbindd_flush_negative_conn_cache(primary_domain);
1158                                 set_domain_online_request(primary_domain);
1159                         }
1160                 }
1161         }
1162 }
1163
1164 static void child_msg_dump_event_list(struct messaging_context *msg,
1165                                       void *private_data,
1166                                       uint32_t msg_type,
1167                                       struct server_id server_id,
1168                                       DATA_BLOB *data)
1169 {
1170         DEBUG(5,("child_msg_dump_event_list received\n"));
1171
1172         dump_event_list(winbind_event_context());
1173 }
1174
1175 NTSTATUS winbindd_reinit_after_fork(const struct winbindd_child *myself,
1176                                     const char *logfilename)
1177 {
1178         struct winbindd_domain *domain;
1179         struct winbindd_child *cl;
1180         NTSTATUS status;
1181
1182         status = reinit_after_fork(
1183                 winbind_messaging_context(),
1184                 winbind_event_context(),
1185                 procid_self(),
1186                 true);
1187         if (!NT_STATUS_IS_OK(status)) {
1188                 DEBUG(0,("reinit_after_fork() failed\n"));
1189                 return status;
1190         }
1191
1192         close_conns_after_fork();
1193
1194         if (!override_logfile && logfilename) {
1195                 lp_set_logfile(logfilename);
1196                 reopen_logs();
1197         }
1198
1199         if (!winbindd_setup_sig_term_handler(false))
1200                 return NT_STATUS_NO_MEMORY;
1201         if (!winbindd_setup_sig_hup_handler(override_logfile ? NULL :
1202                                             logfilename))
1203                 return NT_STATUS_NO_MEMORY;
1204
1205         /* Stop zombies in children */
1206         CatchChild();
1207
1208         /* Don't handle the same messages as our parent. */
1209         messaging_deregister(winbind_messaging_context(),
1210                              MSG_SMB_CONF_UPDATED, NULL);
1211         messaging_deregister(winbind_messaging_context(),
1212                              MSG_SHUTDOWN, NULL);
1213         messaging_deregister(winbind_messaging_context(),
1214                              MSG_WINBIND_OFFLINE, NULL);
1215         messaging_deregister(winbind_messaging_context(),
1216                              MSG_WINBIND_ONLINE, NULL);
1217         messaging_deregister(winbind_messaging_context(),
1218                              MSG_WINBIND_ONLINESTATUS, NULL);
1219         messaging_deregister(winbind_messaging_context(),
1220                              MSG_DUMP_EVENT_LIST, NULL);
1221         messaging_deregister(winbind_messaging_context(),
1222                              MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
1223         messaging_deregister(winbind_messaging_context(),
1224                              MSG_DEBUG, NULL);
1225
1226         /* We have destroyed all events in the winbindd_event_context
1227          * in reinit_after_fork(), so clean out all possible pending
1228          * event pointers. */
1229
1230         /* Deal with check_online_events. */
1231
1232         for (domain = domain_list(); domain; domain = domain->next) {
1233                 TALLOC_FREE(domain->check_online_event);
1234         }
1235
1236         /* Ensure we're not handling a credential cache event inherited
1237          * from our parent. */
1238
1239         ccache_remove_all_after_fork();
1240
1241         /* Destroy all possible events in child list. */
1242         for (cl = winbindd_children; cl != NULL; cl = cl->next) {
1243                 TALLOC_FREE(cl->lockout_policy_event);
1244                 TALLOC_FREE(cl->machine_password_change_event);
1245
1246                 /* Children should never be able to send
1247                  * each other messages, all messages must
1248                  * go through the parent.
1249                  */
1250                 cl->pid = (pid_t)0;
1251
1252                 /*
1253                  * Close service sockets to all other children
1254                  */
1255                 if ((cl != myself) && (cl->sock != -1)) {
1256                         close(cl->sock);
1257                         cl->sock = -1;
1258                 }
1259         }
1260         /*
1261          * This is a little tricky, children must not
1262          * send an MSG_WINBIND_ONLINE message to idmap_child().
1263          * If we are in a child of our primary domain or
1264          * in the process created by fork_child_dc_connect(),
1265          * and the primary domain cannot go online,
1266          * fork_child_dc_connection() sends MSG_WINBIND_ONLINE
1267          * periodically to idmap_child().
1268          *
1269          * The sequence is, fork_child_dc_connect() ---> getdcs() --->
1270          * get_dc_name_via_netlogon() ---> cm_connect_netlogon()
1271          * ---> init_dc_connection() ---> cm_open_connection --->
1272          * set_domain_online(), sends MSG_WINBIND_ONLINE to
1273          * idmap_child(). Disallow children sending messages
1274          * to each other, all messages must go through the parent.
1275          */
1276         cl = idmap_child();
1277         cl->pid = (pid_t)0;
1278
1279         return NT_STATUS_OK;
1280 }
1281
1282 /*
1283  * In a child there will be only one domain, reference that here.
1284  */
1285 static struct winbindd_domain *child_domain;
1286
1287 struct winbindd_domain *wb_child_domain(void)
1288 {
1289         return child_domain;
1290 }
1291
1292 static bool fork_domain_child(struct winbindd_child *child)
1293 {
1294         int fdpair[2];
1295         struct winbindd_cli_state state;
1296         struct winbindd_request request;
1297         struct winbindd_response response;
1298         struct winbindd_domain *primary_domain = NULL;
1299         NTSTATUS status;
1300         ssize_t nwritten;
1301
1302         if (child->domain) {
1303                 DEBUG(10, ("fork_domain_child called for domain '%s'\n",
1304                            child->domain->name));
1305         } else {
1306                 DEBUG(10, ("fork_domain_child called without domain.\n"));
1307         }
1308
1309         if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) != 0) {
1310                 DEBUG(0, ("Could not open child pipe: %s\n",
1311                           strerror(errno)));
1312                 return False;
1313         }
1314
1315         ZERO_STRUCT(state);
1316         state.pid = sys_getpid();
1317         state.request = &request;
1318         state.response = &response;
1319
1320         child->pid = sys_fork();
1321
1322         if (child->pid == -1) {
1323                 DEBUG(0, ("Could not fork: %s\n", strerror(errno)));
1324                 return False;
1325         }
1326
1327         if (child->pid != 0) {
1328                 /* Parent */
1329                 ssize_t nread;
1330
1331                 close(fdpair[0]);
1332
1333                 nread = sys_read(fdpair[1], &status, sizeof(status));
1334                 if (nread != sizeof(status)) {
1335                         DEBUG(1, ("fork_domain_child: Could not read child status: "
1336                                   "nread=%d, error=%s\n", (int)nread,
1337                                   strerror(errno)));
1338                         close(fdpair[1]);
1339                         return false;
1340                 }
1341                 if (!NT_STATUS_IS_OK(status)) {
1342                         DEBUG(1, ("fork_domain_child: Child status is %s\n",
1343                                   nt_errstr(status)));
1344                         close(fdpair[1]);
1345                         return false;
1346                 }
1347
1348                 child->next = child->prev = NULL;
1349                 DLIST_ADD(winbindd_children, child);
1350                 child->sock = fdpair[1];
1351                 return True;
1352         }
1353
1354         /* Child */
1355         child_domain = child->domain;
1356
1357         DEBUG(10, ("Child process %d\n", (int)sys_getpid()));
1358
1359         state.sock = fdpair[0];
1360         close(fdpair[1]);
1361
1362         status = winbindd_reinit_after_fork(child, child->logfilename);
1363
1364         nwritten = sys_write(state.sock, &status, sizeof(status));
1365         if (nwritten != sizeof(status)) {
1366                 DEBUG(1, ("fork_domain_child: Could not write status: "
1367                           "nwritten=%d, error=%s\n", (int)nwritten,
1368                           strerror(errno)));
1369                 _exit(0);
1370         }
1371         if (!NT_STATUS_IS_OK(status)) {
1372                 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
1373                           nt_errstr(status)));
1374                 _exit(0);
1375         }
1376
1377         /* Handle online/offline messages. */
1378         messaging_register(winbind_messaging_context(), NULL,
1379                            MSG_WINBIND_OFFLINE, child_msg_offline);
1380         messaging_register(winbind_messaging_context(), NULL,
1381                            MSG_WINBIND_ONLINE, child_msg_online);
1382         messaging_register(winbind_messaging_context(), NULL,
1383                            MSG_DUMP_EVENT_LIST, child_msg_dump_event_list);
1384         messaging_register(winbind_messaging_context(), NULL,
1385                            MSG_DEBUG, debug_message);
1386         messaging_register(winbind_messaging_context(), NULL,
1387                            MSG_WINBIND_IP_DROPPED,
1388                            winbind_msg_ip_dropped);
1389
1390
1391         primary_domain = find_our_domain();
1392
1393         if (primary_domain == NULL) {
1394                 smb_panic("no primary domain found");
1395         }
1396
1397         /* It doesn't matter if we allow cache login,
1398          * try to bring domain online after fork. */
1399         if ( child->domain ) {
1400                 child->domain->startup = True;
1401                 child->domain->startup_time = time_mono(NULL);
1402                 /* we can be in primary domain or in trusted domain
1403                  * If we are in trusted domain, set the primary domain
1404                  * in start-up mode */
1405                 if (!(child->domain->internal)) {
1406                         set_domain_online_request(child->domain);
1407                         if (!(child->domain->primary)) {
1408                                 primary_domain->startup = True;
1409                                 primary_domain->startup_time = time_mono(NULL);
1410                                 set_domain_online_request(primary_domain);
1411                         }
1412                 }
1413         }
1414
1415         /*
1416          * We are in idmap child, make sure that we set the
1417          * check_online_event to bring primary domain online.
1418          */
1419         if (child == idmap_child()) {
1420                 set_domain_online_request(primary_domain);
1421         }
1422
1423         /* We might be in the idmap child...*/
1424         if (child->domain && !(child->domain->internal) &&
1425             lp_winbind_offline_logon()) {
1426
1427                 set_domain_online_request(child->domain);
1428
1429                 if (primary_domain && (primary_domain != child->domain)) {
1430                         /* We need to talk to the primary
1431                          * domain as well as the trusted
1432                          * domain inside a trusted domain
1433                          * child.
1434                          * See the code in :
1435                          * set_dc_type_and_flags_trustinfo()
1436                          * for details.
1437                          */
1438                         set_domain_online_request(primary_domain);
1439                 }
1440
1441                 child->lockout_policy_event = event_add_timed(
1442                         winbind_event_context(), NULL, timeval_zero(),
1443                         account_lockout_policy_handler,
1444                         child);
1445         }
1446
1447         if (child->domain && child->domain->primary &&
1448             !USE_KERBEROS_KEYTAB &&
1449             lp_server_role() == ROLE_DOMAIN_MEMBER) {
1450
1451                 struct timeval next_change;
1452
1453                 if (calculate_next_machine_pwd_change(child->domain->name,
1454                                                        &next_change)) {
1455                         child->machine_password_change_event = event_add_timed(
1456                                 winbind_event_context(), NULL, next_change,
1457                                 machine_password_change_handler,
1458                                 child);
1459                 }
1460         }
1461
1462         while (1) {
1463
1464                 int ret;
1465                 struct pollfd *pfds;
1466                 int num_pfds;
1467                 int timeout;
1468                 struct timeval t;
1469                 struct timeval *tp;
1470                 TALLOC_CTX *frame = talloc_stackframe();
1471                 struct iovec iov[2];
1472                 int iov_count;
1473
1474                 if (run_events_poll(winbind_event_context(), 0, NULL, 0)) {
1475                         TALLOC_FREE(frame);
1476                         continue;
1477                 }
1478
1479                 if (child->domain && child->domain->startup &&
1480                                 (time_mono(NULL) > child->domain->startup_time + 30)) {
1481                         /* No longer in "startup" mode. */
1482                         DEBUG(10,("fork_domain_child: domain %s no longer in 'startup' mode.\n",
1483                                 child->domain->name ));
1484                         child->domain->startup = False;
1485                 }
1486
1487                 pfds = talloc_zero(talloc_tos(), struct pollfd);
1488                 if (pfds == NULL) {
1489                         DEBUG(1, ("talloc failed\n"));
1490                         _exit(1);
1491                 }
1492
1493                 pfds->fd = state.sock;
1494                 pfds->events = POLLIN|POLLHUP;
1495                 num_pfds = 1;
1496
1497                 timeout = INT_MAX;
1498
1499                 if (!event_add_to_poll_args(
1500                             winbind_event_context(), talloc_tos(),
1501                             &pfds, &num_pfds, &timeout)) {
1502                         DEBUG(1, ("event_add_to_poll_args failed\n"));
1503                         _exit(1);
1504                 }
1505                 tp = get_timed_events_timeout(winbind_event_context(), &t);
1506                 if (tp) {
1507                         DEBUG(11,("select will use timeout of %u.%u seconds\n",
1508                                 (unsigned int)tp->tv_sec, (unsigned int)tp->tv_usec ));
1509                 }
1510
1511                 ret = sys_poll(pfds, num_pfds, timeout);
1512
1513                 if (run_events_poll(winbind_event_context(), ret,
1514                                     pfds, num_pfds)) {
1515                         /* We got a signal - continue. */
1516                         TALLOC_FREE(frame);
1517                         continue;
1518                 }
1519
1520                 TALLOC_FREE(pfds);
1521
1522                 if (ret == 0) {
1523                         DEBUG(11,("nothing is ready yet, continue\n"));
1524                         TALLOC_FREE(frame);
1525                         continue;
1526                 }
1527
1528                 if (ret == -1 && errno == EINTR) {
1529                         /* We got a signal - continue. */
1530                         TALLOC_FREE(frame);
1531                         continue;
1532                 }
1533
1534                 if (ret == -1 && errno != EINTR) {
1535                         DEBUG(0,("poll error occured\n"));
1536                         TALLOC_FREE(frame);
1537                         perror("poll");
1538                         _exit(1);
1539                 }
1540
1541                 /* fetch a request from the main daemon */
1542                 status = child_read_request(&state);
1543
1544                 if (!NT_STATUS_IS_OK(status)) {
1545                         /* we lost contact with our parent */
1546                         _exit(0);
1547                 }
1548
1549                 DEBUG(4,("child daemon request %d\n", (int)state.request->cmd));
1550
1551                 ZERO_STRUCTP(state.response);
1552                 state.request->null_term = '\0';
1553                 state.mem_ctx = frame;
1554                 child_process_request(child, &state);
1555
1556                 DEBUG(4, ("Finished processing child request %d\n",
1557                           (int)state.request->cmd));
1558
1559                 SAFE_FREE(state.request->extra_data.data);
1560
1561                 iov[0].iov_base = (void *)state.response;
1562                 iov[0].iov_len = sizeof(struct winbindd_response);
1563                 iov_count = 1;
1564
1565                 if (state.response->length > sizeof(struct winbindd_response)) {
1566                         iov[1].iov_base =
1567                                 (void *)state.response->extra_data.data;
1568                         iov[1].iov_len = state.response->length-iov[0].iov_len;
1569                         iov_count = 2;
1570                 }
1571
1572                 DEBUG(10, ("Writing %d bytes to parent\n",
1573                            (int)state.response->length));
1574
1575                 if (write_data_iov(state.sock, iov, iov_count) !=
1576                     state.response->length) {
1577                         DEBUG(0, ("Could not write result\n"));
1578                         exit(1);
1579                 }
1580                 TALLOC_FREE(frame);
1581         }
1582 }
1583
1584 void winbind_msg_ip_dropped_parent(struct messaging_context *msg_ctx,
1585                                    void *private_data,
1586                                    uint32_t msg_type,
1587                                    struct server_id server_id,
1588                                    DATA_BLOB *data)
1589 {
1590         struct winbindd_child *child;
1591
1592         winbind_msg_ip_dropped(msg_ctx, private_data, msg_type,
1593                                server_id, data);
1594
1595
1596         for (child = winbindd_children; child != NULL; child = child->next) {
1597                 messaging_send_buf(msg_ctx, pid_to_procid(child->pid),
1598                                    msg_type, data->data, data->length);
1599         }
1600 }