Changeset 745 for trunk/server/source3/winbindd/winbindd_dual.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source3/winbindd/winbindd_dual.c
r593 r745 30 30 #include "includes.h" 31 31 #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" 33 39 34 40 #undef DBGC_CLASS … … 135 141 struct tevent_req *subreq; 136 142 137 if ((state->child-> pid == 0) && (!fork_domain_child(state->child))) {143 if ((state->child->sock == -1) && (!fork_domain_child(state->child))) { 138 144 tevent_req_error(req, errno); 139 145 return; … … 146 152 } 147 153 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)); 154 155 } 155 156 … … 165 166 TALLOC_FREE(subreq); 166 167 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; 167 174 tevent_req_error(req, err); 168 175 return; … … 182 189 *presponse = talloc_move(mem_ctx, &state->response); 183 190 return 0; 191 } 192 193 static bool winbindd_child_busy(struct winbindd_child *child) 194 { 195 return tevent_queue_length(child->queue) > 0; 196 } 197 198 static 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 211 struct 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 222 struct 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; 184 228 } 185 229 … … 187 231 struct tevent_context *ev; 188 232 struct winbindd_domain *domain; 233 struct winbindd_child *child; 189 234 struct winbindd_request *request; 190 235 struct winbindd_request *init_req; … … 210 255 } 211 256 257 state->child = choose_domain_child(domain); 258 212 259 if (domain->initialized) { 213 subreq = wb_child_request_send(state, ev, &domain->child,260 subreq = wb_child_request_send(state, ev, state->child, 214 261 request); 215 262 if (tevent_req_nomem(subreq, req)) { … … 233 280 state->init_req->cmd = WINBINDD_INIT_CONNECTION; 234 281 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; 237 283 fstrcpy(state->init_req->data.init_conn.dcname, ""); 238 284 239 subreq = wb_child_request_send(state, ev, &domain->child,285 subreq = wb_child_request_send(state, ev, state->child, 240 286 state->init_req); 241 287 if (tevent_req_nomem(subreq, req)) { … … 258 304 fstrcpy(state->init_req->domain_name, domain->name); 259 305 260 subreq = wb_child_request_send(state, ev, &domain->child, request);306 subreq = wb_child_request_send(state, ev, state->child, request); 261 307 if (tevent_req_nomem(subreq, req)) { 262 308 return tevent_req_post(req, ev); … … 289 335 TALLOC_FREE(response); 290 336 291 subreq = wb_child_request_send(state, state->ev, &state->domain->child,337 subreq = wb_child_request_send(state, state->ev, state->child, 292 338 state->init_req); 293 339 if (tevent_req_nomem(subreq, req)) { … … 329 375 TALLOC_FREE(response); 330 376 331 subreq = wb_child_request_send(state, state->ev, &state->domain->child,377 subreq = wb_child_request_send(state, state->ev, state->child, 332 378 state->request); 333 379 if (tevent_req_nomem(subreq, req)) { … … 366 412 *presponse = talloc_move(mem_ctx, &state->response); 367 413 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 the438 * 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);457 414 } 458 415 … … 483 440 } 484 441 485 DEBUG(1 ,("child_process_request: unknown request fn number %d\n",442 DEBUG(1, ("child_process_request: unknown request fn number %d\n", 486 443 (int)state->request->cmd)); 487 444 state->response->result = WINBINDD_ERROR; … … 494 451 { 495 452 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 496 471 if (asprintf(&child->logfilename, "%s/%s-%s", 497 get_dyn_LOGFILEBASE(), logprefix, logname) < 0) { 472 logbase, logprefix, logname) < 0) { 473 SAFE_FREE(logbase); 498 474 smb_panic("Internal error: asprintf failed"); 499 475 } 476 477 SAFE_FREE(logbase); 500 478 } else { 501 479 smb_panic("Internal error: logprefix == NULL && " … … 503 481 } 504 482 483 child->sock = -1; 505 484 child->domain = domain; 506 485 child->table = table; 507 486 child->queue = tevent_queue_create(NULL, "winbind_child"); 508 487 SMB_ASSERT(child->queue != NULL); 509 child-> rpccli = wbint_rpccli_create(NULL, domain, child);510 SMB_ASSERT(child-> rpccli!= NULL);511 } 512 513 st ruct winbindd_child *children = NULL;488 child->binding_handle = wbint_binding_handle(NULL, domain, child); 489 SMB_ASSERT(child->binding_handle != NULL); 490 } 491 492 static struct winbindd_child *winbindd_children = NULL; 514 493 515 494 void winbind_child_died(pid_t pid) … … 517 496 struct winbindd_child *child; 518 497 519 for (child = children; child != NULL; child = child->next) {498 for (child = winbindd_children; child != NULL; child = child->next) { 520 499 if (child->pid == pid) { 521 500 break; … … 530 509 /* This will be re-added in fork_domain_child() */ 531 510 532 DLIST_REMOVE(children, child); 533 534 close(child->sock); 535 child->sock = -1; 511 DLIST_REMOVE(winbindd_children, child); 536 512 child->pid = 0; 513 514 if (child->sock != -1) { 515 close(child->sock); 516 child->sock = -1; 517 } 537 518 } 538 519 … … 565 546 debug_message(msg_ctx, private_data, MSG_DEBUG, server_id, data); 566 547 567 for (child = children; child != NULL; child = child->next) {548 for (child = winbindd_children; child != NULL; child = child->next) { 568 549 569 550 DEBUG(10,("winbind_msg_debug: sending message to pid %u.\n", … … 610 591 } 611 592 612 for (child = children; child != NULL; child = child->next) {613 /* Don't send message to internal child s. We've already593 for (child = winbindd_children; child != NULL; child = child->next) { 594 /* Don't send message to internal children. We've already 614 595 done so above. */ 615 596 if (!child->domain || winbindd_internal_child(child)) { … … 685 666 } 686 667 687 for (child = children; child != NULL; child = child->next) {668 for (child = winbindd_children; child != NULL; child = child->next) { 688 669 /* Don't send message to internal childs. */ 689 670 if (!child->domain || winbindd_internal_child(child)) { … … 783 764 dump_event_list(winbind_event_context()); 784 765 785 for (child = children; child != NULL; child = child->next) {766 for (child = winbindd_children; child != NULL; child = child->next) { 786 767 787 768 DEBUG(10,("winbind_msg_dump_event_list: sending message to pid %u\n", … … 1191 1172 } 1192 1173 1193 bool winbindd_reinit_after_fork(const char *logfilename) 1174 NTSTATUS winbindd_reinit_after_fork(const struct winbindd_child *myself, 1175 const char *logfilename) 1194 1176 { 1195 1177 struct winbindd_domain *domain; 1196 1178 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)) { 1201 1187 DEBUG(0,("reinit_after_fork() failed\n")); 1202 return false;1188 return status; 1203 1189 } 1204 1190 … … 1211 1197 1212 1198 if (!winbindd_setup_sig_term_handler(false)) 1213 return false;1199 return NT_STATUS_NO_MEMORY; 1214 1200 if (!winbindd_setup_sig_hup_handler(override_logfile ? NULL : 1215 1201 logfilename)) 1216 return false;1202 return NT_STATUS_NO_MEMORY; 1217 1203 1218 1204 /* Stop zombies in children */ … … 1253 1239 1254 1240 /* 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) { 1256 1242 TALLOC_FREE(cl->lockout_policy_event); 1257 1243 TALLOC_FREE(cl->machine_password_change_event); … … 1262 1248 */ 1263 1249 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 } 1264 1258 } 1265 1259 /* … … 1282 1276 cl->pid = (pid_t)0; 1283 1277 1284 return true;1278 return NT_STATUS_OK; 1285 1279 } 1286 1280 … … 1302 1296 struct winbindd_response response; 1303 1297 struct winbindd_domain *primary_domain = NULL; 1298 NTSTATUS status; 1299 ssize_t nwritten; 1304 1300 1305 1301 if (child->domain) { … … 1309 1305 DEBUG(10, ("fork_domain_child called without domain.\n")); 1310 1306 } 1311 child_domain = child->domain;1312 1307 1313 1308 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) != 0) { … … 1331 1326 if (child->pid != 0) { 1332 1327 /* Parent */ 1328 ssize_t nread; 1329 1333 1330 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 1334 1347 child->next = child->prev = NULL; 1335 DLIST_ADD( children, child);1348 DLIST_ADD(winbindd_children, child); 1336 1349 child->sock = fdpair[1]; 1337 1350 return True; … … 1339 1352 1340 1353 /* Child */ 1354 child_domain = child->domain; 1341 1355 1342 1356 DEBUG(10, ("Child process %d\n", (int)sys_getpid())); … … 1345 1359 close(fdpair[1]); 1346 1360 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))); 1348 1373 _exit(0); 1349 1374 } … … 1358 1383 messaging_register(winbind_messaging_context(), NULL, 1359 1384 MSG_DEBUG, debug_message); 1385 messaging_register(winbind_messaging_context(), NULL, 1386 MSG_WINBIND_IP_DROPPED, 1387 winbind_msg_ip_dropped); 1388 1360 1389 1361 1390 primary_domain = find_our_domain(); … … 1369 1398 if ( child->domain ) { 1370 1399 child->domain->startup = True; 1371 child->domain->startup_time = time (NULL);1400 child->domain->startup_time = time_mono(NULL); 1372 1401 /* we can be in primary domain or in trusted domain 1373 1402 * If we are in trusted domain, set the primary domain … … 1377 1406 if (!(child->domain->primary)) { 1378 1407 primary_domain->startup = True; 1379 primary_domain->startup_time = time (NULL);1408 primary_domain->startup_time = time_mono(NULL); 1380 1409 set_domain_online_request(primary_domain); 1381 1410 } … … 1433 1462 1434 1463 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; 1438 1467 struct timeval t; 1439 1468 struct timeval *tp; 1440 struct timeval now;1441 1469 TALLOC_CTX *frame = talloc_stackframe(); 1442 1470 struct iovec iov[2]; 1443 1471 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)) { 1447 1474 TALLOC_FREE(frame); 1448 1475 continue; 1449 1476 } 1450 1477 1451 GetTimeOfDay(&now);1452 1453 1478 if (child->domain && child->domain->startup && 1454 ( now.tv_sec> child->domain->startup_time + 30)) {1479 (time_mono(NULL) > child->domain->startup_time + 30)) { 1455 1480 /* No longer in "startup" mode. */ 1456 1481 DEBUG(10,("fork_domain_child: domain %s no longer in 'startup' mode.\n", … … 1459 1484 } 1460 1485 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")); 1467 1489 _exit(1); 1468 1490 } 1469 1491 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 } 1483 1504 tp = get_timed_events_timeout(winbind_event_context(), &t); 1484 1505 if (tp) { … … 1487 1508 } 1488 1509 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)) { 1492 1514 /* We got a signal - continue. */ 1493 1515 TALLOC_FREE(frame); 1494 1516 continue; 1495 1517 } 1518 1519 TALLOC_FREE(pfds); 1496 1520 1497 1521 if (ret == 0) { … … 1508 1532 1509 1533 if (ret == -1 && errno != EINTR) { 1510 DEBUG(0,(" selecterror occured\n"));1534 DEBUG(0,("poll error occured\n")); 1511 1535 TALLOC_FREE(frame); 1512 perror(" select");1536 perror("poll"); 1513 1537 _exit(1); 1514 1538 } … … 1556 1580 } 1557 1581 } 1582 1583 void 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.