diff --git a/source3/smbd/server.c b/source3/smbd/server.c index aba980e9375..e2d6c8c0be1 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -1284,6 +1284,13 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent, messaging_register(msg_ctx, NULL, MSG_SMB_NOTIFY_STARTED, smb_parent_send_to_children); + if (lp_interfaces() && lp_bind_interfaces_only()) { + messaging_register(msg_ctx, + NULL, + MSG_SMB_IP_DROPPED, + smb_parent_send_to_children); + } + #ifdef DEVELOPER messaging_register(msg_ctx, NULL, MSG_SMB_INJECT_FAULT, msg_inject_fault); @@ -1640,6 +1647,7 @@ static void smbd_init_addrchange(TALLOC_CTX *mem_ctx, } static void smbd_close_socket_for_ip(struct smbd_parent_context *parent, + struct messaging_context *msg_ctx, struct sockaddr_storage *addr) { struct smbd_open_socket *s = NULL; @@ -1655,12 +1663,25 @@ static void smbd_close_socket_for_ip(struct smbd_parent_context *parent, if (sockaddr_equal((struct sockaddr *)&a, (struct sockaddr *)addr)) { char addrstr[INET6_ADDRSTRLEN]; + DATA_BLOB blob; + NTSTATUS status; DLIST_REMOVE(parent->sockets, s); TALLOC_FREE(s); print_sockaddr(addrstr, sizeof(addrstr), addr); DBG_NOTICE("smbd: Closed listening socket for %s\n", addrstr); + + blob = data_blob_const(addrstr, strlen(addrstr)+1); + status = messaging_send(msg_ctx, + messaging_server_id(msg_ctx), + MSG_SMB_IP_DROPPED, + &blob); + if (!NT_STATUS_IS_OK(status)) { + DBG_NOTICE( + "messaging_send failed: %s - ignoring\n", + nt_errstr(status)); + } return; } } @@ -1693,7 +1714,7 @@ static void smbd_addr_changed(struct tevent_req *req) "on if_index %u\n", addrstr, if_index); - smbd_close_socket_for_ip(state->parent, &addr); + smbd_close_socket_for_ip(state->parent, state->msg_ctx, &addr); goto rearm; } diff --git a/source3/smbd/smb2_process.c b/source3/smbd/smb2_process.c index 482c448e81b..4a6cda39a2f 100644 --- a/source3/smbd/smb2_process.c +++ b/source3/smbd/smb2_process.c @@ -1565,6 +1565,38 @@ static void msg_kill_client_ip(struct messaging_context *msg_ctx, TALLOC_FREE(client_ip); } +static void msg_kill_client_with_server_ip(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + struct smbd_server_connection *sconn = talloc_get_type_abort( + private_data, struct smbd_server_connection); + const char *ip = (char *) data->data; + char *server_ip = NULL; + TALLOC_CTX *ctx = NULL; + + DBG_NOTICE("Got kill request for source IP %s\n", ip); + ctx = talloc_stackframe(); + + server_ip = tsocket_address_inet_addr_string(sconn->local_address, ctx); + if (server_ip == NULL) { + goto out_free; + } + + if (strequal(ip, server_ip)) { + DBG_NOTICE( + "Got ip dropped message for %s - exiting immediately\n", + ip); + TALLOC_FREE(ctx); + exit_server_cleanly("Forced disconnect for client"); + } + +out_free: + TALLOC_FREE(ctx); +} + /* * Do the recurring check if we're idle */ @@ -2019,6 +2051,12 @@ void smbd_process(struct tevent_context *ev_ctx, messaging_register(sconn->msg_ctx, NULL, MSG_DEBUG, debug_message); + messaging_deregister(sconn->msg_ctx, MSG_SMB_IP_DROPPED, NULL); + messaging_register(sconn->msg_ctx, + sconn, + MSG_SMB_IP_DROPPED, + msg_kill_client_with_server_ip); + #if defined(WITH_SMB1SERVER) if ((lp_keepalive() != 0) && !(event_add_idle(ev_ctx,