Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source3/winbindd/winbindd_dual.c

    r593 r745  
    3030#include "includes.h"
    3131#include "winbindd.h"
    32 #include "../../nsswitch/libwbclient/wbc_async.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"
    3339
    3440#undef DBGC_CLASS
     
    135141        struct tevent_req *subreq;
    136142
    137         if ((state->child->pid == 0) && (!fork_domain_child(state->child))) {
     143        if ((state->child->sock == -1) && (!fork_domain_child(state->child))) {
    138144                tevent_req_error(req, errno);
    139145                return;
     
    146152        }
    147153        tevent_req_set_callback(subreq, wb_child_request_done, req);
    148 
    149         if (!tevent_req_set_endtime(req, state->ev,
    150                                     timeval_current_ofs(300, 0))) {
    151                 tevent_req_nomem(NULL, req);
    152                 return;
    153         }
     154        tevent_req_set_endtime(req, state->ev, timeval_current_ofs(300, 0));
    154155}
    155156
     
    165166        TALLOC_FREE(subreq);
    166167        if (ret == -1) {
     168                /*
     169                 * The basic parent/child communication broke, close
     170                 * our socket
     171                 */
     172                close(state->child->sock);
     173                state->child->sock = -1;
    167174                tevent_req_error(req, err);
    168175                return;
     
    182189        *presponse = talloc_move(mem_ctx, &state->response);
    183190        return 0;
     191}
     192
     193static bool winbindd_child_busy(struct winbindd_child *child)
     194{
     195        return tevent_queue_length(child->queue) > 0;
     196}
     197
     198static struct winbindd_child *find_idle_child(struct winbindd_domain *domain)
     199{
     200        int i;
     201
     202        for (i=0; i<lp_winbind_max_domain_connections(); i++) {
     203                if (!winbindd_child_busy(&domain->children[i])) {
     204                        return &domain->children[i];
     205                }
     206        }
     207
     208        return NULL;
     209}
     210
     211struct winbindd_child *choose_domain_child(struct winbindd_domain *domain)
     212{
     213        struct winbindd_child *result;
     214
     215        result = find_idle_child(domain);
     216        if (result != NULL) {
     217                return result;
     218        }
     219        return &domain->children[rand() % lp_winbind_max_domain_connections()];
     220}
     221
     222struct dcerpc_binding_handle *dom_child_handle(struct winbindd_domain *domain)
     223{
     224        struct winbindd_child *child;
     225
     226        child = choose_domain_child(domain);
     227        return child->binding_handle;
    184228}
    185229
     
    187231        struct tevent_context *ev;
    188232        struct winbindd_domain *domain;
     233        struct winbindd_child *child;
    189234        struct winbindd_request *request;
    190235        struct winbindd_request *init_req;
     
    210255        }
    211256
     257        state->child = choose_domain_child(domain);
     258
    212259        if (domain->initialized) {
    213                 subreq = wb_child_request_send(state, ev, &domain->child,
     260                subreq = wb_child_request_send(state, ev, state->child,
    214261                                               request);
    215262                if (tevent_req_nomem(subreq, req)) {
     
    233280                state->init_req->cmd = WINBINDD_INIT_CONNECTION;
    234281                fstrcpy(state->init_req->domain_name, domain->name);
    235                 state->init_req->data.init_conn.is_primary =
    236                         domain->primary ? true : false;
     282                state->init_req->data.init_conn.is_primary = domain->primary;
    237283                fstrcpy(state->init_req->data.init_conn.dcname, "");
    238284
    239                 subreq = wb_child_request_send(state, ev, &domain->child,
     285                subreq = wb_child_request_send(state, ev, state->child,
    240286                                               state->init_req);
    241287                if (tevent_req_nomem(subreq, req)) {
     
    258304        fstrcpy(state->init_req->domain_name, domain->name);
    259305
    260         subreq = wb_child_request_send(state, ev, &domain->child, request);
     306        subreq = wb_child_request_send(state, ev, state->child, request);
    261307        if (tevent_req_nomem(subreq, req)) {
    262308                return tevent_req_post(req, ev);
     
    289335        TALLOC_FREE(response);
    290336
    291         subreq = wb_child_request_send(state, state->ev, &state->domain->child,
     337        subreq = wb_child_request_send(state, state->ev, state->child,
    292338                                       state->init_req);
    293339        if (tevent_req_nomem(subreq, req)) {
     
    329375        TALLOC_FREE(response);
    330376
    331         subreq = wb_child_request_send(state, state->ev, &state->domain->child,
     377        subreq = wb_child_request_send(state, state->ev, state->child,
    332378                                       state->request);
    333379        if (tevent_req_nomem(subreq, req)) {
     
    366412        *presponse = talloc_move(mem_ctx, &state->response);
    367413        return 0;
    368 }
    369 
    370 struct domain_request_state {
    371         struct winbindd_domain *domain;
    372         struct winbindd_request *request;
    373         struct winbindd_response *response;
    374         void (*continuation)(void *private_data_data, bool success);
    375         void *private_data_data;
    376 };
    377 
    378 static void async_domain_request_done(struct tevent_req *req);
    379 
    380 void async_domain_request(TALLOC_CTX *mem_ctx,
    381                           struct winbindd_domain *domain,
    382                           struct winbindd_request *request,
    383                           struct winbindd_response *response,
    384                           void (*continuation)(void *private_data_data, bool success),
    385                           void *private_data_data)
    386 {
    387         struct tevent_req *subreq;
    388         struct domain_request_state *state;
    389 
    390         state = TALLOC_P(mem_ctx, struct domain_request_state);
    391         if (state == NULL) {
    392                 DEBUG(0, ("talloc failed\n"));
    393                 continuation(private_data_data, False);
    394                 return;
    395         }
    396 
    397         state->domain = domain;
    398         state->request = request;
    399         state->response = response;
    400         state->continuation = continuation;
    401         state->private_data_data = private_data_data;
    402 
    403         subreq = wb_domain_request_send(state, winbind_event_context(),
    404                                         domain, request);
    405         if (subreq == NULL) {
    406                 DEBUG(5, ("wb_domain_request_send failed\n"));
    407                 continuation(private_data_data, false);
    408                 return;
    409         }
    410         tevent_req_set_callback(subreq, async_domain_request_done, state);
    411 }
    412 
    413 static void async_domain_request_done(struct tevent_req *req)
    414 {
    415         struct domain_request_state *state = tevent_req_callback_data(
    416                 req, struct domain_request_state);
    417         struct winbindd_response *response;
    418         int ret, err;
    419 
    420         ret = wb_domain_request_recv(req, state, &response, &err);
    421         TALLOC_FREE(req);
    422         if (ret == -1) {
    423                 DEBUG(5, ("wb_domain_request returned %s\n", strerror(err)));
    424                 state->continuation(state->private_data_data, false);
    425                 return;
    426         }
    427         *(state->response) = *response;
    428         state->continuation(state->private_data_data, true);
    429 }
    430 
    431 static void recvfrom_child(void *private_data_data, bool success)
    432 {
    433         struct winbindd_cli_state *state =
    434                 talloc_get_type_abort(private_data_data, struct winbindd_cli_state);
    435         enum winbindd_result result = state->response->result;
    436 
    437         /* This is an optimization: The child has written directly to the
    438          * response buffer. The request itself is still in pending state,
    439          * state that in the result code. */
    440 
    441         state->response->result = WINBINDD_PENDING;
    442 
    443         if ((!success) || (result != WINBINDD_OK)) {
    444                 request_error(state);
    445                 return;
    446         }
    447 
    448         request_ok(state);
    449 }
    450 
    451 void sendto_domain(struct winbindd_cli_state *state,
    452                    struct winbindd_domain *domain)
    453 {
    454         async_domain_request(state->mem_ctx, domain,
    455                              state->request, state->response,
    456                              recvfrom_child, state);
    457414}
    458415
     
    483440        }
    484441
    485         DEBUG(1 ,("child_process_request: unknown request fn number %d\n",
     442        DEBUG(1, ("child_process_request: unknown request fn number %d\n",
    486443                  (int)state->request->cmd));
    487444        state->response->result = WINBINDD_ERROR;
     
    494451{
    495452        if (logprefix && logname) {
     453                char *logbase = NULL;
     454
     455                if (*lp_logfile()) {
     456                        char *end = NULL;
     457
     458                        if (asprintf(&logbase, "%s", lp_logfile()) < 0) {
     459                                smb_panic("Internal error: asprintf failed");
     460                        }
     461
     462                        if ((end = strrchr_m(logbase, '/'))) {
     463                                *end = '\0';
     464                        }
     465                } else {
     466                        if (asprintf(&logbase, "%s", get_dyn_LOGFILEBASE()) < 0) {
     467                                smb_panic("Internal error: asprintf failed");
     468                        }
     469                }
     470
    496471                if (asprintf(&child->logfilename, "%s/%s-%s",
    497                              get_dyn_LOGFILEBASE(), logprefix, logname) < 0) {
     472                             logbase, logprefix, logname) < 0) {
     473                        SAFE_FREE(logbase);
    498474                        smb_panic("Internal error: asprintf failed");
    499475                }
     476
     477                SAFE_FREE(logbase);
    500478        } else {
    501479                smb_panic("Internal error: logprefix == NULL && "
     
    503481        }
    504482
     483        child->sock = -1;
    505484        child->domain = domain;
    506485        child->table = table;
    507486        child->queue = tevent_queue_create(NULL, "winbind_child");
    508487        SMB_ASSERT(child->queue != NULL);
    509         child->rpccli = wbint_rpccli_create(NULL, domain, child);
    510         SMB_ASSERT(child->rpccli != NULL);
    511 }
    512 
    513 struct winbindd_child *children = NULL;
     488        child->binding_handle = wbint_binding_handle(NULL, domain, child);
     489        SMB_ASSERT(child->binding_handle != NULL);
     490}
     491
     492static struct winbindd_child *winbindd_children = NULL;
    514493
    515494void winbind_child_died(pid_t pid)
     
    517496        struct winbindd_child *child;
    518497
    519         for (child = children; child != NULL; child = child->next) {
     498        for (child = winbindd_children; child != NULL; child = child->next) {
    520499                if (child->pid == pid) {
    521500                        break;
     
    530509        /* This will be re-added in fork_domain_child() */
    531510
    532         DLIST_REMOVE(children, child);
    533 
    534         close(child->sock);
    535         child->sock = -1;
     511        DLIST_REMOVE(winbindd_children, child);
    536512        child->pid = 0;
     513
     514        if (child->sock != -1) {
     515                close(child->sock);
     516                child->sock = -1;
     517        }
    537518}
    538519
     
    565546        debug_message(msg_ctx, private_data, MSG_DEBUG, server_id, data);
    566547
    567         for (child = children; child != NULL; child = child->next) {
     548        for (child = winbindd_children; child != NULL; child = child->next) {
    568549
    569550                DEBUG(10,("winbind_msg_debug: sending message to pid %u.\n",
     
    610591        }
    611592
    612         for (child = children; child != NULL; child = child->next) {
    613                 /* Don't send message to internal childs.  We've already
     593        for (child = winbindd_children; child != NULL; child = child->next) {
     594                /* Don't send message to internal children.  We've already
    614595                   done so above. */
    615596                if (!child->domain || winbindd_internal_child(child)) {
     
    685666        }
    686667
    687         for (child = children; child != NULL; child = child->next) {
     668        for (child = winbindd_children; child != NULL; child = child->next) {
    688669                /* Don't send message to internal childs. */
    689670                if (!child->domain || winbindd_internal_child(child)) {
     
    783764        dump_event_list(winbind_event_context());
    784765
    785         for (child = children; child != NULL; child = child->next) {
     766        for (child = winbindd_children; child != NULL; child = child->next) {
    786767
    787768                DEBUG(10,("winbind_msg_dump_event_list: sending message to pid %u\n",
     
    11911172}
    11921173
    1193 bool winbindd_reinit_after_fork(const char *logfilename)
     1174NTSTATUS winbindd_reinit_after_fork(const struct winbindd_child *myself,
     1175                                    const char *logfilename)
    11941176{
    11951177        struct winbindd_domain *domain;
    11961178        struct winbindd_child *cl;
    1197 
    1198         if (!NT_STATUS_IS_OK(reinit_after_fork(winbind_messaging_context(),
    1199                                                winbind_event_context(),
    1200                                                true))) {
     1179        NTSTATUS status;
     1180
     1181        status = reinit_after_fork(
     1182                winbind_messaging_context(),
     1183                winbind_event_context(),
     1184                procid_self(),
     1185                true);
     1186        if (!NT_STATUS_IS_OK(status)) {
    12011187                DEBUG(0,("reinit_after_fork() failed\n"));
    1202                 return false;
     1188                return status;
    12031189        }
    12041190
     
    12111197
    12121198        if (!winbindd_setup_sig_term_handler(false))
    1213                 return false;
     1199                return NT_STATUS_NO_MEMORY;
    12141200        if (!winbindd_setup_sig_hup_handler(override_logfile ? NULL :
    12151201                                            logfilename))
    1216                 return false;
     1202                return NT_STATUS_NO_MEMORY;
    12171203
    12181204        /* Stop zombies in children */
     
    12531239
    12541240        /* Destroy all possible events in child list. */
    1255         for (cl = children; cl != NULL; cl = cl->next) {
     1241        for (cl = winbindd_children; cl != NULL; cl = cl->next) {
    12561242                TALLOC_FREE(cl->lockout_policy_event);
    12571243                TALLOC_FREE(cl->machine_password_change_event);
     
    12621248                 */
    12631249                cl->pid = (pid_t)0;
     1250
     1251                /*
     1252                 * Close service sockets to all other children
     1253                 */
     1254                if ((cl != myself) && (cl->sock != -1)) {
     1255                        close(cl->sock);
     1256                        cl->sock = -1;
     1257                }
    12641258        }
    12651259        /*
     
    12821276        cl->pid = (pid_t)0;
    12831277
    1284         return true;
     1278        return NT_STATUS_OK;
    12851279}
    12861280
     
    13021296        struct winbindd_response response;
    13031297        struct winbindd_domain *primary_domain = NULL;
     1298        NTSTATUS status;
     1299        ssize_t nwritten;
    13041300
    13051301        if (child->domain) {
     
    13091305                DEBUG(10, ("fork_domain_child called without domain.\n"));
    13101306        }
    1311         child_domain = child->domain;
    13121307
    13131308        if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) != 0) {
     
    13311326        if (child->pid != 0) {
    13321327                /* Parent */
     1328                ssize_t nread;
     1329
    13331330                close(fdpair[0]);
     1331
     1332                nread = read(fdpair[1], &status, sizeof(status));
     1333                if (nread != sizeof(status)) {
     1334                        DEBUG(1, ("fork_domain_child: Could not read child status: "
     1335                                  "nread=%d, error=%s\n", (int)nread,
     1336                                  strerror(errno)));
     1337                        close(fdpair[1]);
     1338                        return false;
     1339                }
     1340                if (!NT_STATUS_IS_OK(status)) {
     1341                        DEBUG(1, ("fork_domain_child: Child status is %s\n",
     1342                                  nt_errstr(status)));
     1343                        close(fdpair[1]);
     1344                        return false;
     1345                }
     1346
    13341347                child->next = child->prev = NULL;
    1335                 DLIST_ADD(children, child);
     1348                DLIST_ADD(winbindd_children, child);
    13361349                child->sock = fdpair[1];
    13371350                return True;
     
    13391352
    13401353        /* Child */
     1354        child_domain = child->domain;
    13411355
    13421356        DEBUG(10, ("Child process %d\n", (int)sys_getpid()));
     
    13451359        close(fdpair[1]);
    13461360
    1347         if (!winbindd_reinit_after_fork(child->logfilename)) {
     1361        status = winbindd_reinit_after_fork(child, child->logfilename);
     1362
     1363        nwritten = write(state.sock, &status, sizeof(status));
     1364        if (nwritten != sizeof(status)) {
     1365                DEBUG(1, ("fork_domain_child: Could not write status: "
     1366                          "nwritten=%d, error=%s\n", (int)nwritten,
     1367                          strerror(errno)));
     1368                _exit(0);
     1369        }
     1370        if (!NT_STATUS_IS_OK(status)) {
     1371                DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
     1372                          nt_errstr(status)));
    13481373                _exit(0);
    13491374        }
     
    13581383        messaging_register(winbind_messaging_context(), NULL,
    13591384                           MSG_DEBUG, debug_message);
     1385        messaging_register(winbind_messaging_context(), NULL,
     1386                           MSG_WINBIND_IP_DROPPED,
     1387                           winbind_msg_ip_dropped);
     1388
    13601389
    13611390        primary_domain = find_our_domain();
     
    13691398        if ( child->domain ) {
    13701399                child->domain->startup = True;
    1371                 child->domain->startup_time = time(NULL);
     1400                child->domain->startup_time = time_mono(NULL);
    13721401                /* we can be in primary domain or in trusted domain
    13731402                 * If we are in trusted domain, set the primary domain
     
    13771406                        if (!(child->domain->primary)) {
    13781407                                primary_domain->startup = True;
    1379                                 primary_domain->startup_time = time(NULL);
     1408                                primary_domain->startup_time = time_mono(NULL);
    13801409                                set_domain_online_request(primary_domain);
    13811410                        }
     
    14331462
    14341463                int ret;
    1435                 fd_set r_fds;
    1436                 fd_set w_fds;
    1437                 int maxfd;
     1464                struct pollfd *pfds;
     1465                int num_pfds;
     1466                int timeout;
    14381467                struct timeval t;
    14391468                struct timeval *tp;
    1440                 struct timeval now;
    14411469                TALLOC_CTX *frame = talloc_stackframe();
    14421470                struct iovec iov[2];
    14431471                int iov_count;
    1444                 NTSTATUS status;
    1445 
    1446                 if (run_events(winbind_event_context(), 0, NULL, NULL)) {
     1472
     1473                if (run_events_poll(winbind_event_context(), 0, NULL, 0)) {
    14471474                        TALLOC_FREE(frame);
    14481475                        continue;
    14491476                }
    14501477
    1451                 GetTimeOfDay(&now);
    1452 
    14531478                if (child->domain && child->domain->startup &&
    1454                                 (now.tv_sec > child->domain->startup_time + 30)) {
     1479                                (time_mono(NULL) > child->domain->startup_time + 30)) {
    14551480                        /* No longer in "startup" mode. */
    14561481                        DEBUG(10,("fork_domain_child: domain %s no longer in 'startup' mode.\n",
     
    14591484                }
    14601485
    1461                 FD_ZERO(&r_fds);
    1462                 FD_ZERO(&w_fds);
    1463 
    1464                 if (state.sock < 0 || state.sock >= FD_SETSIZE) {
    1465                         TALLOC_FREE(frame);
    1466                         perror("EBADF");
     1486                pfds = TALLOC_ZERO_P(talloc_tos(), struct pollfd);
     1487                if (pfds == NULL) {
     1488                        DEBUG(1, ("talloc failed\n"));
    14671489                        _exit(1);
    14681490                }
    14691491
    1470                 FD_SET(state.sock, &r_fds);
    1471                 maxfd = state.sock;
    1472 
    1473                 /*
    1474                  * Initialize this high as event_add_to_select_args()
    1475                  * uses a timeval_min() on this and next_event. Fix
    1476                  * from Roel van Meer <rolek@alt001.com>.
    1477                  */
    1478                 t.tv_sec = 999999;
    1479                 t.tv_usec = 0;
    1480 
    1481                 event_add_to_select_args(winbind_event_context(), &now,
    1482                                          &r_fds, &w_fds, &t, &maxfd);
     1492                pfds->fd = state.sock;
     1493                pfds->events = POLLIN|POLLHUP;
     1494                num_pfds = 1;
     1495
     1496                timeout = INT_MAX;
     1497
     1498                if (!event_add_to_poll_args(
     1499                            winbind_event_context(), talloc_tos(),
     1500                            &pfds, &num_pfds, &timeout)) {
     1501                        DEBUG(1, ("event_add_to_poll_args failed\n"));
     1502                        _exit(1);
     1503                }
    14831504                tp = get_timed_events_timeout(winbind_event_context(), &t);
    14841505                if (tp) {
     
    14871508                }
    14881509
    1489                 ret = sys_select(maxfd + 1, &r_fds, &w_fds, NULL, tp);
    1490 
    1491                 if (run_events(winbind_event_context(), ret, &r_fds, &w_fds)) {
     1510                ret = sys_poll(pfds, num_pfds, timeout);
     1511
     1512                if (run_events_poll(winbind_event_context(), ret,
     1513                                    pfds, num_pfds)) {
    14921514                        /* We got a signal - continue. */
    14931515                        TALLOC_FREE(frame);
    14941516                        continue;
    14951517                }
     1518
     1519                TALLOC_FREE(pfds);
    14961520
    14971521                if (ret == 0) {
     
    15081532
    15091533                if (ret == -1 && errno != EINTR) {
    1510                         DEBUG(0,("select error occured\n"));
     1534                        DEBUG(0,("poll error occured\n"));
    15111535                        TALLOC_FREE(frame);
    1512                         perror("select");
     1536                        perror("poll");
    15131537                        _exit(1);
    15141538                }
     
    15561580        }
    15571581}
     1582
     1583void winbind_msg_ip_dropped_parent(struct messaging_context *msg_ctx,
     1584                                   void *private_data,
     1585                                   uint32_t msg_type,
     1586                                   struct server_id server_id,
     1587                                   DATA_BLOB *data)
     1588{
     1589        struct winbindd_child *child;
     1590
     1591        winbind_msg_ip_dropped(msg_ctx, private_data, msg_type,
     1592                               server_id, data);
     1593
     1594
     1595        for (child = winbindd_children; child != NULL; child = child->next) {
     1596                messaging_send_buf(msg_ctx, pid_to_procid(child->pid),
     1597                                   msg_type, data->data, data->length);
     1598        }
     1599}
Note: See TracChangeset for help on using the changeset viewer.