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