goto done;
}
- if (ntohs(peeraddr_in->sin_port) == 139) {
- struct nmb_name calling;
- struct nmb_name called;
-
- make_nmb_name(&calling, global_myname(), 0x0);
- make_nmb_name(&called, "*SMBSERVER", 0x20);
-
- if (!cli_session_request(*cli, &calling, &called)) {
- DEBUG(8, ("cli_session_request failed for %s\n",
- controller));
- result = NT_STATUS_UNSUCCESSFUL;
- goto done;
- }
- }
-
result = cli_negprot(*cli);
if (!NT_STATUS_IS_OK(result)) {
struct sockaddr_storage *addrs = NULL;
int num_addrs = 0;
- int i, fd_index;
+ int i;
+ size_t fd_index;
+
+ NTSTATUS status;
*fd = -1;
&addrs, &num_addrs)) {
return False;
}
-
- if (!add_string_to_array(mem_ctx, dcs[i].name,
- &dcnames, &num_dcnames)) {
- return False;
- }
- if (!add_sockaddr_to_array(mem_ctx, &dcs[i].ss, 139,
- &addrs, &num_addrs)) {
- return False;
- }
}
if ((num_dcnames == 0) || (num_dcnames != num_addrs))
if ((addrs == NULL) || (dcnames == NULL))
return False;
- /* 5 second timeout. */
- if (!open_any_socket_out(addrs, num_addrs, 5000, &fd_index, fd) ) {
+ status = smbsock_any_connect(addrs, dcnames, num_addrs,
+ fd, &fd_index, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
for (i=0; i<num_dcs; i++) {
char ab[INET6_ADDRSTRLEN];
print_sockaddr(ab, sizeof(ab), &dcs[i].ss);
- DEBUG(10, ("find_new_dc: open_any_socket_out failed for "
+ DEBUG(10, ("find_new_dc: smbsock_any_connect failed for "
"domain %s address %s. Error was %s\n",
- domain->name, ab, strerror(errno) ));
+ domain->name, ab, nt_errstr(status) ));
winbind_add_failed_connection_entry(domain,
dcs[i].name, NT_STATUS_UNSUCCESSFUL);
}
goto again;
}
+static char *current_dc_key(TALLOC_CTX *mem_ctx, const char *domain_name)
+{
+ return talloc_asprintf_strupper_m(mem_ctx, "CURRENT_DCNAME/%s",
+ domain_name);
+}
+
+static void store_current_dc_in_gencache(const char *domain_name,
+ const char *dc_name,
+ struct cli_state *cli)
+{
+ char addr[INET6_ADDRSTRLEN];
+ char *key, *value;
+
+ if (cli == NULL) {
+ return;
+ }
+ if (cli->fd == -1) {
+ return;
+ }
+ get_peer_addr(cli->fd, addr, sizeof(addr));
+
+ key = current_dc_key(talloc_tos(), domain_name);
+ if (key == NULL) {
+ goto done;
+ }
+
+ value = talloc_asprintf(talloc_tos(), "%s %s", addr, dc_name);
+ if (value == NULL) {
+ goto done;
+ }
+
+ gencache_set(key, value, 0x7ffffffff);
+done:
+ TALLOC_FREE(value);
+ TALLOC_FREE(key);
+}
+
+bool fetch_current_dc_from_gencache(TALLOC_CTX *mem_ctx,
+ const char *domain_name,
+ char **p_dc_name, char **p_dc_ip)
+{
+ char *key, *value, *p;
+ bool ret = false;
+ char *dc_name = NULL;
+ char *dc_ip = NULL;
+
+ key = current_dc_key(talloc_tos(), domain_name);
+ if (key == NULL) {
+ goto done;
+ }
+ if (!gencache_get(key, &value, NULL)) {
+ goto done;
+ }
+ p = strchr(value, ' ');
+ if (p == NULL) {
+ goto done;
+ }
+ dc_ip = talloc_strndup(mem_ctx, value, p - value);
+ if (dc_ip == NULL) {
+ goto done;
+ }
+ dc_name = talloc_strdup(mem_ctx, p+1);
+ if (dc_name == NULL) {
+ goto done;
+ }
+
+ if (p_dc_ip != NULL) {
+ *p_dc_ip = dc_ip;
+ dc_ip = NULL;
+ }
+ if (p_dc_name != NULL) {
+ *p_dc_name = dc_name;
+ dc_name = NULL;
+ }
+ ret = true;
+done:
+ TALLOC_FREE(dc_name);
+ TALLOC_FREE(dc_ip);
+ TALLOC_FREE(key);
+ return ret;
+}
+
static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
struct winbindd_cm_conn *new_conn)
{
&& NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
&& (resolve_name(domain->dcname, &domain->dcaddr, 0x20)))
{
- struct sockaddr_storage *addrs = NULL;
- int num_addrs = 0;
- int dummy = 0;
-
- if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 445, &addrs, &num_addrs)) {
- set_domain_offline(domain);
- talloc_destroy(mem_ctx);
- return NT_STATUS_NO_MEMORY;
- }
- if (!add_sockaddr_to_array(mem_ctx, &domain->dcaddr, 139, &addrs, &num_addrs)) {
- set_domain_offline(domain);
- talloc_destroy(mem_ctx);
- return NT_STATUS_NO_MEMORY;
- }
+ NTSTATUS status;
- /* 5 second timeout. */
- if (!open_any_socket_out(addrs, num_addrs, 5000, &dummy, &fd)) {
+ status = smbsock_connect(&domain->dcaddr, NULL, NULL,
+ &fd, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
fd = -1;
}
}
set_global_winbindd_state_online();
}
set_domain_online(domain);
+
+ /*
+ * Much as I hate global state, this seems to be the point
+ * where we can be certain that we have a proper connection to
+ * a DC. wbinfo --dc-info needs that information, store it in
+ * gencache with a looong timeout. This will need revisiting
+ * once we start to connect to multiple DCs, wbcDcInfo is
+ * already prepared for that.
+ */
+ store_current_dc_in_gencache(domain->name, domain->dcname,
+ new_conn->cli);
} else {
/* Ensure we setup the retry handler. */
set_domain_offline(domain);
*cli = conn->netlogon_pipe;
return NT_STATUS_OK;
}
+
+void winbind_msg_ip_dropped(struct messaging_context *msg_ctx,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id server_id,
+ DATA_BLOB *data)
+{
+ struct winbindd_domain *domain;
+
+ if ((data == NULL)
+ || (data->data == NULL)
+ || (data->length == 0)
+ || (data->data[data->length-1] != '\0')
+ || !is_ipaddress((char *)data->data)) {
+ DEBUG(1, ("invalid msg_ip_dropped message\n"));
+ return;
+ }
+ for (domain = domain_list(); domain != NULL; domain = domain->next) {
+ char sockaddr[INET6_ADDRSTRLEN];
+ if (domain->conn.cli == NULL) {
+ continue;
+ }
+ if (domain->conn.cli->fd == -1) {
+ continue;
+ }
+ client_socket_addr(domain->conn.cli->fd, sockaddr,
+ sizeof(sockaddr));
+ if (strequal(sockaddr, (char *)data->data)) {
+ close(domain->conn.cli->fd);
+ domain->conn.cli->fd = -1;
+ }
+ }
+}
+
+extern struct winbindd_child *children;
+
+void winbind_msg_ip_dropped_parent(struct messaging_context *msg_ctx,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id server_id,
+ DATA_BLOB *data)
+{
+ struct winbindd_child *child;
+
+ winbind_msg_ip_dropped(msg_ctx, private_data, msg_type,
+ server_id, data);
+
+
+ for (child = children; child != NULL; child = child->next) {
+ messaging_send_buf(msg_ctx, pid_to_procid(child->pid),
+ msg_type, data->data, data->length);
+ }
+}