mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
smbd: Move smbd_add_connection to smb2_process.c
Signed-off-by: David Mulder <dmulder@suse.com> Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
parent
c43c9ef3ee
commit
6f792afe43
@ -66,7 +66,7 @@ struct pending_message_list {
|
||||
|
||||
static bool smb_splice_chain(uint8_t **poutbuf, const uint8_t *andx_buf);
|
||||
|
||||
static void smbd_echo_init(struct smbXsrv_connection *xconn)
|
||||
void smbd_echo_init(struct smbXsrv_connection *xconn)
|
||||
{
|
||||
xconn->smb1.echo_handler.trusted_fd = -1;
|
||||
xconn->smb1.echo_handler.socket_lock_fd = -1;
|
||||
@ -1414,10 +1414,10 @@ static connection_struct *switch_message(uint8_t type, struct smb_request *req)
|
||||
Construct a reply to the incoming packet.
|
||||
****************************************************************************/
|
||||
|
||||
static void construct_reply(struct smbXsrv_connection *xconn,
|
||||
char *inbuf, int size, size_t unread_bytes,
|
||||
uint32_t seqnum, bool encrypted,
|
||||
struct smb_perfcount_data *deferred_pcd)
|
||||
void construct_reply(struct smbXsrv_connection *xconn,
|
||||
char *inbuf, int size, size_t unread_bytes,
|
||||
uint32_t seqnum, bool encrypted,
|
||||
struct smb_perfcount_data *deferred_pcd)
|
||||
{
|
||||
struct smbd_server_connection *sconn = xconn->client->sconn;
|
||||
struct smb_request *req;
|
||||
@ -2150,126 +2150,8 @@ static void smbd_server_connection_write_handler(
|
||||
/* TODO: make write nonblocking */
|
||||
}
|
||||
|
||||
static void smbd_smb2_server_connection_read_handler(
|
||||
struct smbXsrv_connection *xconn, int fd)
|
||||
{
|
||||
char lenbuf[NBT_HDR_SIZE];
|
||||
size_t len = 0;
|
||||
uint8_t *buffer = NULL;
|
||||
size_t bufferlen = 0;
|
||||
NTSTATUS status;
|
||||
uint8_t msg_type = 0;
|
||||
|
||||
/* Read the first 4 bytes - contains length of remainder. */
|
||||
status = read_smb_length_return_keepalive(fd, lenbuf, 0, &len);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
exit_server_cleanly("failed to receive request length");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Integer wrap check. */
|
||||
if (len + NBT_HDR_SIZE < len) {
|
||||
exit_server_cleanly("Invalid length on initial request");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The +4 here can't wrap, we've checked the length above already.
|
||||
*/
|
||||
bufferlen = len+NBT_HDR_SIZE;
|
||||
|
||||
buffer = talloc_array(talloc_tos(), uint8_t, bufferlen);
|
||||
if (buffer == NULL) {
|
||||
DBG_ERR("Could not allocate request inbuf of length %zu\n",
|
||||
bufferlen);
|
||||
exit_server_cleanly("talloc fail");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy the NBT_HDR_SIZE length. */
|
||||
memcpy(buffer, lenbuf, sizeof(lenbuf));
|
||||
|
||||
status = read_packet_remainder(fd, (char *)buffer+NBT_HDR_SIZE, 0, len);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
exit_server_cleanly("Failed to read remainder of initial request");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check the message type. */
|
||||
msg_type = PULL_LE_U8(buffer,0);
|
||||
if (msg_type == NBSSrequest) {
|
||||
/*
|
||||
* clients can send this request before
|
||||
* bootstrapping into SMB2. Cope with this
|
||||
* message only, don't allow any other strange
|
||||
* NBSS types.
|
||||
*/
|
||||
reply_special(xconn, (char *)buffer, bufferlen);
|
||||
xconn->client->sconn->num_requests++;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only a 'normal' message type allowed now. */
|
||||
if (msg_type != NBSSmessage) {
|
||||
DBG_ERR("Invalid message type %d\n", msg_type);
|
||||
exit_server_cleanly("Invalid message type for initial request");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Could this be an SMB1 negprot bootstrap into SMB2 ? */
|
||||
if (bufferlen < smb_size) {
|
||||
exit_server_cleanly("Invalid initial SMB1 or SMB2 packet");
|
||||
return;
|
||||
}
|
||||
#if defined(WITH_SMB1SERVER)
|
||||
if (valid_smb_header(buffer)) {
|
||||
/* Can *only* allow an SMB1 negprot here. */
|
||||
uint8_t cmd = PULL_LE_U8(buffer, smb_com);
|
||||
if (cmd != SMBnegprot) {
|
||||
DBG_ERR("Incorrect SMB1 command 0x%hhx, "
|
||||
"should be SMBnegprot (0x72)\n",
|
||||
cmd);
|
||||
exit_server_cleanly("Invalid initial SMB1 packet");
|
||||
}
|
||||
/* Minimal process_smb(). */
|
||||
show_msg((char *)buffer);
|
||||
construct_reply(xconn,
|
||||
(char *)buffer,
|
||||
bufferlen,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
NULL);
|
||||
xconn->client->sconn->trans_num++;
|
||||
xconn->client->sconn->num_requests++;
|
||||
return;
|
||||
|
||||
} else
|
||||
#endif
|
||||
if (!smbd_is_smb2_header(buffer, bufferlen)) {
|
||||
exit_server_cleanly("Invalid initial SMB2 packet");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Here we know we're a valid SMB2 packet. */
|
||||
|
||||
/*
|
||||
* Point at the start of the SMB2 PDU.
|
||||
* len is the length of the SMB2 PDU.
|
||||
*/
|
||||
|
||||
status = smbd_smb2_process_negprot(xconn,
|
||||
0,
|
||||
(const uint8_t *)buffer+NBT_HDR_SIZE,
|
||||
len);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
exit_server_cleanly("SMB2 negprot fail");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void smbd_smb1_server_connection_read_handler(
|
||||
struct smbXsrv_connection *xconn, int fd)
|
||||
void smbd_smb1_server_connection_read_handler(struct smbXsrv_connection *xconn,
|
||||
int fd)
|
||||
{
|
||||
uint8_t *inbuf = NULL;
|
||||
size_t inbuf_len = 0;
|
||||
@ -2333,44 +2215,6 @@ process:
|
||||
seqnum, encrypted, NULL);
|
||||
}
|
||||
|
||||
static void smbd_server_connection_handler(struct tevent_context *ev,
|
||||
struct tevent_fd *fde,
|
||||
uint16_t flags,
|
||||
void *private_data)
|
||||
{
|
||||
struct smbXsrv_connection *xconn =
|
||||
talloc_get_type_abort(private_data,
|
||||
struct smbXsrv_connection);
|
||||
|
||||
if (!NT_STATUS_IS_OK(xconn->transport.status)) {
|
||||
/*
|
||||
* we're not supposed to do any io
|
||||
*/
|
||||
TEVENT_FD_NOT_READABLE(xconn->transport.fde);
|
||||
TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags & TEVENT_FD_WRITE) {
|
||||
smbd_server_connection_write_handler(xconn);
|
||||
return;
|
||||
}
|
||||
if (flags & TEVENT_FD_READ) {
|
||||
#if defined(WITH_SMB1SERVER)
|
||||
if (lp_server_min_protocol() > PROTOCOL_NT1) {
|
||||
#endif
|
||||
smbd_smb2_server_connection_read_handler(xconn,
|
||||
xconn->transport.sock);
|
||||
#if defined(WITH_SMB1SERVER)
|
||||
} else {
|
||||
smbd_smb1_server_connection_read_handler(xconn,
|
||||
xconn->transport.sock);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void smbd_server_echo_handler(struct tevent_context *ev,
|
||||
struct tevent_fd *fde,
|
||||
uint16_t flags,
|
||||
@ -2400,180 +2244,6 @@ static void smbd_server_echo_handler(struct tevent_context *ev,
|
||||
}
|
||||
}
|
||||
|
||||
struct smbd_release_ip_state {
|
||||
struct smbXsrv_connection *xconn;
|
||||
struct tevent_immediate *im;
|
||||
char addr[INET6_ADDRSTRLEN];
|
||||
};
|
||||
|
||||
static void smbd_release_ip_immediate(struct tevent_context *ctx,
|
||||
struct tevent_immediate *im,
|
||||
void *private_data)
|
||||
{
|
||||
struct smbd_release_ip_state *state =
|
||||
talloc_get_type_abort(private_data,
|
||||
struct smbd_release_ip_state);
|
||||
struct smbXsrv_connection *xconn = state->xconn;
|
||||
|
||||
if (!NT_STATUS_EQUAL(xconn->transport.status, NT_STATUS_ADDRESS_CLOSED)) {
|
||||
/*
|
||||
* smbd_server_connection_terminate() already triggered ?
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
smbd_server_connection_terminate(xconn, "CTDB_SRVID_RELEASE_IP");
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
received when we should release a specific IP
|
||||
****************************************************************************/
|
||||
static int release_ip(struct tevent_context *ev,
|
||||
uint32_t src_vnn, uint32_t dst_vnn,
|
||||
uint64_t dst_srvid,
|
||||
const uint8_t *msg, size_t msglen,
|
||||
void *private_data)
|
||||
{
|
||||
struct smbd_release_ip_state *state =
|
||||
talloc_get_type_abort(private_data,
|
||||
struct smbd_release_ip_state);
|
||||
struct smbXsrv_connection *xconn = state->xconn;
|
||||
const char *ip;
|
||||
const char *addr = state->addr;
|
||||
const char *p = addr;
|
||||
|
||||
if (msglen == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (msg[msglen-1] != '\0') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ip = (const char *)msg;
|
||||
|
||||
if (!NT_STATUS_IS_OK(xconn->transport.status)) {
|
||||
/* avoid recursion */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strncmp("::ffff:", addr, 7) == 0) {
|
||||
p = addr + 7;
|
||||
}
|
||||
|
||||
DEBUG(10, ("Got release IP message for %s, "
|
||||
"our address is %s\n", ip, p));
|
||||
|
||||
if ((strcmp(p, ip) == 0) || ((p != addr) && strcmp(addr, ip) == 0)) {
|
||||
DEBUG(0,("Got release IP message for our IP %s - exiting immediately\n",
|
||||
ip));
|
||||
/*
|
||||
* With SMB2 we should do a clean disconnect,
|
||||
* the previous_session_id in the session setup
|
||||
* will cleanup the old session, tcons and opens.
|
||||
*
|
||||
* A clean disconnect is needed in order to support
|
||||
* durable handles.
|
||||
*
|
||||
* Note: typically this is never triggered
|
||||
* as we got a TCP RST (triggered by ctdb event scripts)
|
||||
* before we get CTDB_SRVID_RELEASE_IP.
|
||||
*
|
||||
* We used to call _exit(1) here, but as this was mostly never
|
||||
* triggered and has implication on our process model,
|
||||
* we can just use smbd_server_connection_terminate()
|
||||
* (also for SMB1).
|
||||
*
|
||||
* We don't call smbd_server_connection_terminate() directly
|
||||
* as we might be called from within ctdbd_migrate(),
|
||||
* we need to defer our action to the next event loop
|
||||
*/
|
||||
tevent_schedule_immediate(state->im,
|
||||
xconn->client->raw_ev_ctx,
|
||||
smbd_release_ip_immediate,
|
||||
state);
|
||||
|
||||
/*
|
||||
* Make sure we don't get any io on the connection.
|
||||
*/
|
||||
xconn->transport.status = NT_STATUS_ADDRESS_CLOSED;
|
||||
return EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int match_cluster_movable_ip(uint32_t total_ip_count,
|
||||
const struct sockaddr_storage *ip,
|
||||
bool is_movable_ip,
|
||||
void *private_data)
|
||||
{
|
||||
const struct sockaddr_storage *srv = private_data;
|
||||
struct samba_sockaddr pub_ip = {
|
||||
.u = {
|
||||
.ss = *ip,
|
||||
},
|
||||
};
|
||||
struct samba_sockaddr srv_ip = {
|
||||
.u = {
|
||||
.ss = *srv,
|
||||
},
|
||||
};
|
||||
|
||||
if (is_movable_ip && sockaddr_equal(&pub_ip.u.sa, &srv_ip.u.sa)) {
|
||||
return EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static NTSTATUS smbd_register_ips(struct smbXsrv_connection *xconn,
|
||||
struct sockaddr_storage *srv,
|
||||
struct sockaddr_storage *clnt)
|
||||
{
|
||||
struct smbd_release_ip_state *state;
|
||||
struct ctdbd_connection *cconn;
|
||||
int ret;
|
||||
|
||||
cconn = messaging_ctdb_connection();
|
||||
if (cconn == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
state = talloc_zero(xconn, struct smbd_release_ip_state);
|
||||
if (state == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
state->xconn = xconn;
|
||||
state->im = tevent_create_immediate(state);
|
||||
if (state->im == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
if (print_sockaddr(state->addr, sizeof(state->addr), srv) == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (xconn->client->server_multi_channel_enabled) {
|
||||
ret = ctdbd_public_ip_foreach(cconn,
|
||||
match_cluster_movable_ip,
|
||||
srv);
|
||||
if (ret == EADDRNOTAVAIL) {
|
||||
xconn->has_cluster_movable_ip = true;
|
||||
DBG_DEBUG("cluster movable IP on %s\n",
|
||||
smbXsrv_connection_dbg(xconn));
|
||||
} else if (ret != 0) {
|
||||
DBG_ERR("failed to iterate cluster IPs: %s\n",
|
||||
strerror(ret));
|
||||
return NT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ctdbd_register_ips(cconn, srv, clnt, release_ip, state);
|
||||
if (ret != 0) {
|
||||
return map_nt_error_from_unix(ret);
|
||||
}
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static void msg_kill_client_ip(struct messaging_context *msg_ctx,
|
||||
void *private_data, uint32_t msg_type,
|
||||
struct server_id server_id, DATA_BLOB *data)
|
||||
@ -3411,223 +3081,6 @@ static void smbd_tevent_trace_callback(enum tevent_trace_point point,
|
||||
errno = 0;
|
||||
}
|
||||
|
||||
static int smbXsrv_connection_destructor(struct smbXsrv_connection *xconn)
|
||||
{
|
||||
DBG_DEBUG("xconn[%s]\n", smbXsrv_connection_dbg(xconn));
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS smbd_add_connection(struct smbXsrv_client *client, int sock_fd,
|
||||
NTTIME now, struct smbXsrv_connection **_xconn)
|
||||
{
|
||||
TALLOC_CTX *frame = talloc_stackframe();
|
||||
struct smbXsrv_connection *xconn;
|
||||
struct sockaddr_storage ss_srv;
|
||||
void *sp_srv = (void *)&ss_srv;
|
||||
struct sockaddr *sa_srv = (struct sockaddr *)sp_srv;
|
||||
struct sockaddr_storage ss_clnt;
|
||||
void *sp_clnt = (void *)&ss_clnt;
|
||||
struct sockaddr *sa_clnt = (struct sockaddr *)sp_clnt;
|
||||
socklen_t sa_socklen;
|
||||
struct tsocket_address *local_address = NULL;
|
||||
struct tsocket_address *remote_address = NULL;
|
||||
const char *remaddr = NULL;
|
||||
char *p;
|
||||
const char *rhost = NULL;
|
||||
int ret;
|
||||
int tmp;
|
||||
|
||||
*_xconn = NULL;
|
||||
|
||||
DO_PROFILE_INC(connect);
|
||||
|
||||
xconn = talloc_zero(client, struct smbXsrv_connection);
|
||||
if (xconn == NULL) {
|
||||
DEBUG(0,("talloc_zero(struct smbXsrv_connection)\n"));
|
||||
TALLOC_FREE(frame);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
talloc_set_destructor(xconn, smbXsrv_connection_destructor);
|
||||
talloc_steal(frame, xconn);
|
||||
xconn->client = client;
|
||||
xconn->connect_time = now;
|
||||
if (client->next_channel_id != 0) {
|
||||
xconn->channel_id = client->next_channel_id++;
|
||||
}
|
||||
|
||||
xconn->transport.sock = sock_fd;
|
||||
#if defined(WITH_SMB1SERVER)
|
||||
smbd_echo_init(xconn);
|
||||
#endif
|
||||
xconn->protocol = PROTOCOL_NONE;
|
||||
|
||||
/* Ensure child is set to blocking mode */
|
||||
set_blocking(sock_fd,True);
|
||||
|
||||
set_socket_options(sock_fd, "SO_KEEPALIVE");
|
||||
set_socket_options(sock_fd, lp_socket_options());
|
||||
|
||||
sa_socklen = sizeof(ss_clnt);
|
||||
ret = getpeername(sock_fd, sa_clnt, &sa_socklen);
|
||||
if (ret != 0) {
|
||||
int saved_errno = errno;
|
||||
int level = (errno == ENOTCONN)?2:0;
|
||||
DEBUG(level,("getpeername() failed - %s\n",
|
||||
strerror(saved_errno)));
|
||||
TALLOC_FREE(frame);
|
||||
return map_nt_error_from_unix_common(saved_errno);
|
||||
}
|
||||
ret = tsocket_address_bsd_from_sockaddr(xconn,
|
||||
sa_clnt, sa_socklen,
|
||||
&remote_address);
|
||||
if (ret != 0) {
|
||||
int saved_errno = errno;
|
||||
DEBUG(0,("%s: tsocket_address_bsd_from_sockaddr remote failed - %s\n",
|
||||
__location__, strerror(saved_errno)));
|
||||
TALLOC_FREE(frame);
|
||||
return map_nt_error_from_unix_common(saved_errno);
|
||||
}
|
||||
|
||||
sa_socklen = sizeof(ss_srv);
|
||||
ret = getsockname(sock_fd, sa_srv, &sa_socklen);
|
||||
if (ret != 0) {
|
||||
int saved_errno = errno;
|
||||
int level = (errno == ENOTCONN)?2:0;
|
||||
DEBUG(level,("getsockname() failed - %s\n",
|
||||
strerror(saved_errno)));
|
||||
TALLOC_FREE(frame);
|
||||
return map_nt_error_from_unix_common(saved_errno);
|
||||
}
|
||||
ret = tsocket_address_bsd_from_sockaddr(xconn,
|
||||
sa_srv, sa_socklen,
|
||||
&local_address);
|
||||
if (ret != 0) {
|
||||
int saved_errno = errno;
|
||||
DEBUG(0,("%s: tsocket_address_bsd_from_sockaddr remote failed - %s\n",
|
||||
__location__, strerror(saved_errno)));
|
||||
TALLOC_FREE(frame);
|
||||
return map_nt_error_from_unix_common(saved_errno);
|
||||
}
|
||||
|
||||
if (tsocket_address_is_inet(remote_address, "ip")) {
|
||||
remaddr = tsocket_address_inet_addr_string(remote_address,
|
||||
talloc_tos());
|
||||
if (remaddr == NULL) {
|
||||
DEBUG(0,("%s: tsocket_address_inet_addr_string remote failed - %s\n",
|
||||
__location__, strerror(errno)));
|
||||
TALLOC_FREE(frame);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
} else {
|
||||
remaddr = "0.0.0.0";
|
||||
}
|
||||
|
||||
/*
|
||||
* Before the first packet, check the global hosts allow/ hosts deny
|
||||
* parameters before doing any parsing of packets passed to us by the
|
||||
* client. This prevents attacks on our parsing code from hosts not in
|
||||
* the hosts allow list.
|
||||
*/
|
||||
|
||||
ret = get_remote_hostname(remote_address,
|
||||
&p, talloc_tos());
|
||||
if (ret < 0) {
|
||||
int saved_errno = errno;
|
||||
DEBUG(0,("%s: get_remote_hostname failed - %s\n",
|
||||
__location__, strerror(saved_errno)));
|
||||
TALLOC_FREE(frame);
|
||||
return map_nt_error_from_unix_common(saved_errno);
|
||||
}
|
||||
rhost = p;
|
||||
if (strequal(rhost, "UNKNOWN")) {
|
||||
rhost = remaddr;
|
||||
}
|
||||
|
||||
xconn->local_address = local_address;
|
||||
xconn->remote_address = remote_address;
|
||||
xconn->remote_hostname = talloc_strdup(xconn, rhost);
|
||||
if (xconn->remote_hostname == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (!srv_init_signing(xconn)) {
|
||||
DEBUG(0, ("Failed to init smb_signing\n"));
|
||||
TALLOC_FREE(frame);
|
||||
return NT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if (!allow_access(lp_hosts_deny(-1), lp_hosts_allow(-1),
|
||||
xconn->remote_hostname,
|
||||
remaddr)) {
|
||||
DEBUG( 1, ("Connection denied from %s to %s\n",
|
||||
tsocket_address_string(remote_address, talloc_tos()),
|
||||
tsocket_address_string(local_address, talloc_tos())));
|
||||
|
||||
/*
|
||||
* We return a valid xconn
|
||||
* so that the caller can return an error message
|
||||
* to the client
|
||||
*/
|
||||
DLIST_ADD_END(client->connections, xconn);
|
||||
talloc_steal(client, xconn);
|
||||
|
||||
*_xconn = xconn;
|
||||
TALLOC_FREE(frame);
|
||||
return NT_STATUS_NETWORK_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
DEBUG(10, ("Connection allowed from %s to %s\n",
|
||||
tsocket_address_string(remote_address, talloc_tos()),
|
||||
tsocket_address_string(local_address, talloc_tos())));
|
||||
|
||||
if (lp_clustering()) {
|
||||
/*
|
||||
* We need to tell ctdb about our client's TCP
|
||||
* connection, so that for failover ctdbd can send
|
||||
* tickle acks, triggering a reconnection by the
|
||||
* client.
|
||||
*/
|
||||
NTSTATUS status;
|
||||
|
||||
status = smbd_register_ips(xconn, &ss_srv, &ss_clnt);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0, ("ctdbd_register_ips failed: %s\n",
|
||||
nt_errstr(status)));
|
||||
}
|
||||
}
|
||||
|
||||
tmp = lp_max_xmit();
|
||||
tmp = MAX(tmp, SMB_BUFFER_SIZE_MIN);
|
||||
tmp = MIN(tmp, SMB_BUFFER_SIZE_MAX);
|
||||
|
||||
#if defined(WITH_SMB1SERVER)
|
||||
xconn->smb1.negprot.max_recv = tmp;
|
||||
|
||||
xconn->smb1.sessions.done_sesssetup = false;
|
||||
xconn->smb1.sessions.max_send = SMB_BUFFER_SIZE_MAX;
|
||||
#endif
|
||||
|
||||
xconn->transport.fde = tevent_add_fd(client->raw_ev_ctx,
|
||||
xconn,
|
||||
sock_fd,
|
||||
TEVENT_FD_READ,
|
||||
smbd_server_connection_handler,
|
||||
xconn);
|
||||
if (!xconn->transport.fde) {
|
||||
TALLOC_FREE(frame);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
tevent_fd_set_auto_close(xconn->transport.fde);
|
||||
|
||||
/* for now we only have one connection */
|
||||
DLIST_ADD_END(client->connections, xconn);
|
||||
talloc_steal(client, xconn);
|
||||
|
||||
*_xconn = xconn;
|
||||
TALLOC_FREE(frame);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Process commands from the client
|
||||
****************************************************************************/
|
||||
|
@ -892,6 +892,13 @@ void process_smb1(struct smbXsrv_connection *xconn,
|
||||
uint32_t seqnum, bool encrypted,
|
||||
struct smb_perfcount_data *deferred_pcd);
|
||||
bool valid_smb_header(const uint8_t *inbuf);
|
||||
void smbd_echo_init(struct smbXsrv_connection *xconn);
|
||||
void construct_reply(struct smbXsrv_connection *xconn,
|
||||
char *inbuf, int size, size_t unread_bytes,
|
||||
uint32_t seqnum, bool encrypted,
|
||||
struct smb_perfcount_data *deferred_pcd);
|
||||
void smbd_smb1_server_connection_read_handler(struct smbXsrv_connection *xconn,
|
||||
int fd);
|
||||
|
||||
/* The following definitions come from smbd/smb2_process.c */
|
||||
|
||||
|
@ -731,3 +731,556 @@ const char *smbXsrv_connection_dbg(const struct smbXsrv_connection *xconn)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void smbd_server_connection_write_handler(
|
||||
struct smbXsrv_connection *xconn)
|
||||
{
|
||||
/* TODO: make write nonblocking */
|
||||
}
|
||||
|
||||
static void smbd_smb2_server_connection_read_handler(
|
||||
struct smbXsrv_connection *xconn, int fd)
|
||||
{
|
||||
char lenbuf[NBT_HDR_SIZE];
|
||||
size_t len = 0;
|
||||
uint8_t *buffer = NULL;
|
||||
size_t bufferlen = 0;
|
||||
NTSTATUS status;
|
||||
uint8_t msg_type = 0;
|
||||
|
||||
/* Read the first 4 bytes - contains length of remainder. */
|
||||
status = read_smb_length_return_keepalive(fd, lenbuf, 0, &len);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
exit_server_cleanly("failed to receive request length");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Integer wrap check. */
|
||||
if (len + NBT_HDR_SIZE < len) {
|
||||
exit_server_cleanly("Invalid length on initial request");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The +4 here can't wrap, we've checked the length above already.
|
||||
*/
|
||||
bufferlen = len+NBT_HDR_SIZE;
|
||||
|
||||
buffer = talloc_array(talloc_tos(), uint8_t, bufferlen);
|
||||
if (buffer == NULL) {
|
||||
DBG_ERR("Could not allocate request inbuf of length %zu\n",
|
||||
bufferlen);
|
||||
exit_server_cleanly("talloc fail");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy the NBT_HDR_SIZE length. */
|
||||
memcpy(buffer, lenbuf, sizeof(lenbuf));
|
||||
|
||||
status = read_packet_remainder(fd, (char *)buffer+NBT_HDR_SIZE, 0, len);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
exit_server_cleanly("Failed to read remainder of initial request");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check the message type. */
|
||||
msg_type = PULL_LE_U8(buffer,0);
|
||||
if (msg_type == NBSSrequest) {
|
||||
/*
|
||||
* clients can send this request before
|
||||
* bootstrapping into SMB2. Cope with this
|
||||
* message only, don't allow any other strange
|
||||
* NBSS types.
|
||||
*/
|
||||
reply_special(xconn, (char *)buffer, bufferlen);
|
||||
xconn->client->sconn->num_requests++;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only a 'normal' message type allowed now. */
|
||||
if (msg_type != NBSSmessage) {
|
||||
DBG_ERR("Invalid message type %d\n", msg_type);
|
||||
exit_server_cleanly("Invalid message type for initial request");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Could this be an SMB1 negprot bootstrap into SMB2 ? */
|
||||
if (bufferlen < smb_size) {
|
||||
exit_server_cleanly("Invalid initial SMB1 or SMB2 packet");
|
||||
return;
|
||||
}
|
||||
#if defined(WITH_SMB1SERVER)
|
||||
if (valid_smb_header(buffer)) {
|
||||
/* Can *only* allow an SMB1 negprot here. */
|
||||
uint8_t cmd = PULL_LE_U8(buffer, smb_com);
|
||||
if (cmd != SMBnegprot) {
|
||||
DBG_ERR("Incorrect SMB1 command 0x%hhx, "
|
||||
"should be SMBnegprot (0x72)\n",
|
||||
cmd);
|
||||
exit_server_cleanly("Invalid initial SMB1 packet");
|
||||
}
|
||||
/* Minimal process_smb(). */
|
||||
show_msg((char *)buffer);
|
||||
construct_reply(xconn,
|
||||
(char *)buffer,
|
||||
bufferlen,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
NULL);
|
||||
xconn->client->sconn->trans_num++;
|
||||
xconn->client->sconn->num_requests++;
|
||||
return;
|
||||
|
||||
} else
|
||||
#endif
|
||||
if (!smbd_is_smb2_header(buffer, bufferlen)) {
|
||||
exit_server_cleanly("Invalid initial SMB2 packet");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Here we know we're a valid SMB2 packet. */
|
||||
|
||||
/*
|
||||
* Point at the start of the SMB2 PDU.
|
||||
* len is the length of the SMB2 PDU.
|
||||
*/
|
||||
|
||||
status = smbd_smb2_process_negprot(xconn,
|
||||
0,
|
||||
(const uint8_t *)buffer+NBT_HDR_SIZE,
|
||||
len);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
exit_server_cleanly("SMB2 negprot fail");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void smbd_server_connection_handler(struct tevent_context *ev,
|
||||
struct tevent_fd *fde,
|
||||
uint16_t flags,
|
||||
void *private_data)
|
||||
{
|
||||
struct smbXsrv_connection *xconn =
|
||||
talloc_get_type_abort(private_data,
|
||||
struct smbXsrv_connection);
|
||||
|
||||
if (!NT_STATUS_IS_OK(xconn->transport.status)) {
|
||||
/*
|
||||
* we're not supposed to do any io
|
||||
*/
|
||||
TEVENT_FD_NOT_READABLE(xconn->transport.fde);
|
||||
TEVENT_FD_NOT_WRITEABLE(xconn->transport.fde);
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags & TEVENT_FD_WRITE) {
|
||||
smbd_server_connection_write_handler(xconn);
|
||||
return;
|
||||
}
|
||||
if (flags & TEVENT_FD_READ) {
|
||||
#if defined(WITH_SMB1SERVER)
|
||||
if (lp_server_min_protocol() > PROTOCOL_NT1) {
|
||||
#endif
|
||||
smbd_smb2_server_connection_read_handler(xconn,
|
||||
xconn->transport.sock);
|
||||
#if defined(WITH_SMB1SERVER)
|
||||
} else {
|
||||
smbd_smb1_server_connection_read_handler(xconn,
|
||||
xconn->transport.sock);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
struct smbd_release_ip_state {
|
||||
struct smbXsrv_connection *xconn;
|
||||
struct tevent_immediate *im;
|
||||
char addr[INET6_ADDRSTRLEN];
|
||||
};
|
||||
|
||||
static void smbd_release_ip_immediate(struct tevent_context *ctx,
|
||||
struct tevent_immediate *im,
|
||||
void *private_data)
|
||||
{
|
||||
struct smbd_release_ip_state *state =
|
||||
talloc_get_type_abort(private_data,
|
||||
struct smbd_release_ip_state);
|
||||
struct smbXsrv_connection *xconn = state->xconn;
|
||||
|
||||
if (!NT_STATUS_EQUAL(xconn->transport.status, NT_STATUS_ADDRESS_CLOSED)) {
|
||||
/*
|
||||
* smbd_server_connection_terminate() already triggered ?
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
smbd_server_connection_terminate(xconn, "CTDB_SRVID_RELEASE_IP");
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
received when we should release a specific IP
|
||||
****************************************************************************/
|
||||
static int release_ip(struct tevent_context *ev,
|
||||
uint32_t src_vnn, uint32_t dst_vnn,
|
||||
uint64_t dst_srvid,
|
||||
const uint8_t *msg, size_t msglen,
|
||||
void *private_data)
|
||||
{
|
||||
struct smbd_release_ip_state *state =
|
||||
talloc_get_type_abort(private_data,
|
||||
struct smbd_release_ip_state);
|
||||
struct smbXsrv_connection *xconn = state->xconn;
|
||||
const char *ip;
|
||||
const char *addr = state->addr;
|
||||
const char *p = addr;
|
||||
|
||||
if (msglen == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (msg[msglen-1] != '\0') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ip = (const char *)msg;
|
||||
|
||||
if (!NT_STATUS_IS_OK(xconn->transport.status)) {
|
||||
/* avoid recursion */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strncmp("::ffff:", addr, 7) == 0) {
|
||||
p = addr + 7;
|
||||
}
|
||||
|
||||
DEBUG(10, ("Got release IP message for %s, "
|
||||
"our address is %s\n", ip, p));
|
||||
|
||||
if ((strcmp(p, ip) == 0) || ((p != addr) && strcmp(addr, ip) == 0)) {
|
||||
DEBUG(0,("Got release IP message for our IP %s - exiting immediately\n",
|
||||
ip));
|
||||
/*
|
||||
* With SMB2 we should do a clean disconnect,
|
||||
* the previous_session_id in the session setup
|
||||
* will cleanup the old session, tcons and opens.
|
||||
*
|
||||
* A clean disconnect is needed in order to support
|
||||
* durable handles.
|
||||
*
|
||||
* Note: typically this is never triggered
|
||||
* as we got a TCP RST (triggered by ctdb event scripts)
|
||||
* before we get CTDB_SRVID_RELEASE_IP.
|
||||
*
|
||||
* We used to call _exit(1) here, but as this was mostly never
|
||||
* triggered and has implication on our process model,
|
||||
* we can just use smbd_server_connection_terminate()
|
||||
* (also for SMB1).
|
||||
*
|
||||
* We don't call smbd_server_connection_terminate() directly
|
||||
* as we might be called from within ctdbd_migrate(),
|
||||
* we need to defer our action to the next event loop
|
||||
*/
|
||||
tevent_schedule_immediate(state->im,
|
||||
xconn->client->raw_ev_ctx,
|
||||
smbd_release_ip_immediate,
|
||||
state);
|
||||
|
||||
/*
|
||||
* Make sure we don't get any io on the connection.
|
||||
*/
|
||||
xconn->transport.status = NT_STATUS_ADDRESS_CLOSED;
|
||||
return EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int match_cluster_movable_ip(uint32_t total_ip_count,
|
||||
const struct sockaddr_storage *ip,
|
||||
bool is_movable_ip,
|
||||
void *private_data)
|
||||
{
|
||||
const struct sockaddr_storage *srv = private_data;
|
||||
struct samba_sockaddr pub_ip = {
|
||||
.u = {
|
||||
.ss = *ip,
|
||||
},
|
||||
};
|
||||
struct samba_sockaddr srv_ip = {
|
||||
.u = {
|
||||
.ss = *srv,
|
||||
},
|
||||
};
|
||||
|
||||
if (is_movable_ip && sockaddr_equal(&pub_ip.u.sa, &srv_ip.u.sa)) {
|
||||
return EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static NTSTATUS smbd_register_ips(struct smbXsrv_connection *xconn,
|
||||
struct sockaddr_storage *srv,
|
||||
struct sockaddr_storage *clnt)
|
||||
{
|
||||
struct smbd_release_ip_state *state;
|
||||
struct ctdbd_connection *cconn;
|
||||
int ret;
|
||||
|
||||
cconn = messaging_ctdb_connection();
|
||||
if (cconn == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
state = talloc_zero(xconn, struct smbd_release_ip_state);
|
||||
if (state == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
state->xconn = xconn;
|
||||
state->im = tevent_create_immediate(state);
|
||||
if (state->im == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
if (print_sockaddr(state->addr, sizeof(state->addr), srv) == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (xconn->client->server_multi_channel_enabled) {
|
||||
ret = ctdbd_public_ip_foreach(cconn,
|
||||
match_cluster_movable_ip,
|
||||
srv);
|
||||
if (ret == EADDRNOTAVAIL) {
|
||||
xconn->has_cluster_movable_ip = true;
|
||||
DBG_DEBUG("cluster movable IP on %s\n",
|
||||
smbXsrv_connection_dbg(xconn));
|
||||
} else if (ret != 0) {
|
||||
DBG_ERR("failed to iterate cluster IPs: %s\n",
|
||||
strerror(ret));
|
||||
return NT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ctdbd_register_ips(cconn, srv, clnt, release_ip, state);
|
||||
if (ret != 0) {
|
||||
return map_nt_error_from_unix(ret);
|
||||
}
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static int smbXsrv_connection_destructor(struct smbXsrv_connection *xconn)
|
||||
{
|
||||
DBG_DEBUG("xconn[%s]\n", smbXsrv_connection_dbg(xconn));
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS smbd_add_connection(struct smbXsrv_client *client, int sock_fd,
|
||||
NTTIME now, struct smbXsrv_connection **_xconn)
|
||||
{
|
||||
TALLOC_CTX *frame = talloc_stackframe();
|
||||
struct smbXsrv_connection *xconn;
|
||||
struct sockaddr_storage ss_srv;
|
||||
void *sp_srv = (void *)&ss_srv;
|
||||
struct sockaddr *sa_srv = (struct sockaddr *)sp_srv;
|
||||
struct sockaddr_storage ss_clnt;
|
||||
void *sp_clnt = (void *)&ss_clnt;
|
||||
struct sockaddr *sa_clnt = (struct sockaddr *)sp_clnt;
|
||||
socklen_t sa_socklen;
|
||||
struct tsocket_address *local_address = NULL;
|
||||
struct tsocket_address *remote_address = NULL;
|
||||
const char *remaddr = NULL;
|
||||
char *p;
|
||||
const char *rhost = NULL;
|
||||
int ret;
|
||||
int tmp;
|
||||
|
||||
*_xconn = NULL;
|
||||
|
||||
DO_PROFILE_INC(connect);
|
||||
|
||||
xconn = talloc_zero(client, struct smbXsrv_connection);
|
||||
if (xconn == NULL) {
|
||||
DEBUG(0,("talloc_zero(struct smbXsrv_connection)\n"));
|
||||
TALLOC_FREE(frame);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
talloc_set_destructor(xconn, smbXsrv_connection_destructor);
|
||||
talloc_steal(frame, xconn);
|
||||
xconn->client = client;
|
||||
xconn->connect_time = now;
|
||||
if (client->next_channel_id != 0) {
|
||||
xconn->channel_id = client->next_channel_id++;
|
||||
}
|
||||
|
||||
xconn->transport.sock = sock_fd;
|
||||
#if defined(WITH_SMB1SERVER)
|
||||
smbd_echo_init(xconn);
|
||||
#endif
|
||||
xconn->protocol = PROTOCOL_NONE;
|
||||
|
||||
/* Ensure child is set to blocking mode */
|
||||
set_blocking(sock_fd,True);
|
||||
|
||||
set_socket_options(sock_fd, "SO_KEEPALIVE");
|
||||
set_socket_options(sock_fd, lp_socket_options());
|
||||
|
||||
sa_socklen = sizeof(ss_clnt);
|
||||
ret = getpeername(sock_fd, sa_clnt, &sa_socklen);
|
||||
if (ret != 0) {
|
||||
int saved_errno = errno;
|
||||
int level = (errno == ENOTCONN)?2:0;
|
||||
DEBUG(level,("getpeername() failed - %s\n",
|
||||
strerror(saved_errno)));
|
||||
TALLOC_FREE(frame);
|
||||
return map_nt_error_from_unix_common(saved_errno);
|
||||
}
|
||||
ret = tsocket_address_bsd_from_sockaddr(xconn,
|
||||
sa_clnt, sa_socklen,
|
||||
&remote_address);
|
||||
if (ret != 0) {
|
||||
int saved_errno = errno;
|
||||
DEBUG(0,("%s: tsocket_address_bsd_from_sockaddr remote failed - %s\n",
|
||||
__location__, strerror(saved_errno)));
|
||||
TALLOC_FREE(frame);
|
||||
return map_nt_error_from_unix_common(saved_errno);
|
||||
}
|
||||
|
||||
sa_socklen = sizeof(ss_srv);
|
||||
ret = getsockname(sock_fd, sa_srv, &sa_socklen);
|
||||
if (ret != 0) {
|
||||
int saved_errno = errno;
|
||||
int level = (errno == ENOTCONN)?2:0;
|
||||
DEBUG(level,("getsockname() failed - %s\n",
|
||||
strerror(saved_errno)));
|
||||
TALLOC_FREE(frame);
|
||||
return map_nt_error_from_unix_common(saved_errno);
|
||||
}
|
||||
ret = tsocket_address_bsd_from_sockaddr(xconn,
|
||||
sa_srv, sa_socklen,
|
||||
&local_address);
|
||||
if (ret != 0) {
|
||||
int saved_errno = errno;
|
||||
DEBUG(0,("%s: tsocket_address_bsd_from_sockaddr remote failed - %s\n",
|
||||
__location__, strerror(saved_errno)));
|
||||
TALLOC_FREE(frame);
|
||||
return map_nt_error_from_unix_common(saved_errno);
|
||||
}
|
||||
|
||||
if (tsocket_address_is_inet(remote_address, "ip")) {
|
||||
remaddr = tsocket_address_inet_addr_string(remote_address,
|
||||
talloc_tos());
|
||||
if (remaddr == NULL) {
|
||||
DEBUG(0,("%s: tsocket_address_inet_addr_string remote failed - %s\n",
|
||||
__location__, strerror(errno)));
|
||||
TALLOC_FREE(frame);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
} else {
|
||||
remaddr = "0.0.0.0";
|
||||
}
|
||||
|
||||
/*
|
||||
* Before the first packet, check the global hosts allow/ hosts deny
|
||||
* parameters before doing any parsing of packets passed to us by the
|
||||
* client. This prevents attacks on our parsing code from hosts not in
|
||||
* the hosts allow list.
|
||||
*/
|
||||
|
||||
ret = get_remote_hostname(remote_address,
|
||||
&p, talloc_tos());
|
||||
if (ret < 0) {
|
||||
int saved_errno = errno;
|
||||
DEBUG(0,("%s: get_remote_hostname failed - %s\n",
|
||||
__location__, strerror(saved_errno)));
|
||||
TALLOC_FREE(frame);
|
||||
return map_nt_error_from_unix_common(saved_errno);
|
||||
}
|
||||
rhost = p;
|
||||
if (strequal(rhost, "UNKNOWN")) {
|
||||
rhost = remaddr;
|
||||
}
|
||||
|
||||
xconn->local_address = local_address;
|
||||
xconn->remote_address = remote_address;
|
||||
xconn->remote_hostname = talloc_strdup(xconn, rhost);
|
||||
if (xconn->remote_hostname == NULL) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (!srv_init_signing(xconn)) {
|
||||
DEBUG(0, ("Failed to init smb_signing\n"));
|
||||
TALLOC_FREE(frame);
|
||||
return NT_STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if (!allow_access(lp_hosts_deny(-1), lp_hosts_allow(-1),
|
||||
xconn->remote_hostname,
|
||||
remaddr)) {
|
||||
DEBUG( 1, ("Connection denied from %s to %s\n",
|
||||
tsocket_address_string(remote_address, talloc_tos()),
|
||||
tsocket_address_string(local_address, talloc_tos())));
|
||||
|
||||
/*
|
||||
* We return a valid xconn
|
||||
* so that the caller can return an error message
|
||||
* to the client
|
||||
*/
|
||||
DLIST_ADD_END(client->connections, xconn);
|
||||
talloc_steal(client, xconn);
|
||||
|
||||
*_xconn = xconn;
|
||||
TALLOC_FREE(frame);
|
||||
return NT_STATUS_NETWORK_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
DEBUG(10, ("Connection allowed from %s to %s\n",
|
||||
tsocket_address_string(remote_address, talloc_tos()),
|
||||
tsocket_address_string(local_address, talloc_tos())));
|
||||
|
||||
if (lp_clustering()) {
|
||||
/*
|
||||
* We need to tell ctdb about our client's TCP
|
||||
* connection, so that for failover ctdbd can send
|
||||
* tickle acks, triggering a reconnection by the
|
||||
* client.
|
||||
*/
|
||||
NTSTATUS status;
|
||||
|
||||
status = smbd_register_ips(xconn, &ss_srv, &ss_clnt);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0, ("ctdbd_register_ips failed: %s\n",
|
||||
nt_errstr(status)));
|
||||
}
|
||||
}
|
||||
|
||||
tmp = lp_max_xmit();
|
||||
tmp = MAX(tmp, SMB_BUFFER_SIZE_MIN);
|
||||
tmp = MIN(tmp, SMB_BUFFER_SIZE_MAX);
|
||||
|
||||
#if defined(WITH_SMB1SERVER)
|
||||
xconn->smb1.negprot.max_recv = tmp;
|
||||
|
||||
xconn->smb1.sessions.done_sesssetup = false;
|
||||
xconn->smb1.sessions.max_send = SMB_BUFFER_SIZE_MAX;
|
||||
#endif
|
||||
|
||||
xconn->transport.fde = tevent_add_fd(client->raw_ev_ctx,
|
||||
xconn,
|
||||
sock_fd,
|
||||
TEVENT_FD_READ,
|
||||
smbd_server_connection_handler,
|
||||
xconn);
|
||||
if (!xconn->transport.fde) {
|
||||
TALLOC_FREE(frame);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
tevent_fd_set_auto_close(xconn->transport.fde);
|
||||
|
||||
/* for now we only have one connection */
|
||||
DLIST_ADD_END(client->connections, xconn);
|
||||
talloc_steal(client, xconn);
|
||||
|
||||
*_xconn = xconn;
|
||||
TALLOC_FREE(frame);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user