mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
r4728: split up server_services into:
- stream_socket services the smb, ldap and rpc service which sets up a srtam socket end then waits for connections and - task services which this you can create a seperate task that do something (this is also going through the process_model subsystem so with -M standard a new process for this created with -M thread a new thread ... I'll add datagram services later when we whave support for datagram sockets in lib/socket/ see the next commit as an example for service_task's metze
This commit is contained in:
parent
05c3d1c4a6
commit
d5fa02746c
@ -34,21 +34,22 @@ static void ldapsrv_terminate_connection(struct ldapsrv_connection *ldap_conn, c
|
||||
server_terminate_connection(ldap_conn->connection, reason);
|
||||
}
|
||||
|
||||
static const struct server_stream_ops *ldapsrv_get_stream_ops(void);
|
||||
|
||||
/*
|
||||
add a socket address to the list of events, one event per port
|
||||
*/
|
||||
static void add_socket(struct server_service *service,
|
||||
const struct model_ops *model_ops,
|
||||
static void add_socket(struct server_service *service,
|
||||
struct ipv4_addr *ifip)
|
||||
{
|
||||
struct server_socket *srv_sock;
|
||||
struct server_stream_socket *stream_socket;
|
||||
uint16_t port = 389;
|
||||
char *ip_str = talloc_strdup(service, sys_inet_ntoa(*ifip));
|
||||
|
||||
srv_sock = service_setup_socket(service, model_ops, "ipv4", ip_str, &port);
|
||||
stream_socket = service_setup_stream_socket(service, ldapsrv_get_stream_ops(), "ipv4", ip_str, &port);
|
||||
|
||||
port = 3268;
|
||||
srv_sock = service_setup_socket(service, model_ops, "ipv4", ip_str, &port);
|
||||
stream_socket = service_setup_stream_socket(service, ldapsrv_get_stream_ops(), "ipv4", ip_str, &port);
|
||||
|
||||
talloc_free(ip_str);
|
||||
}
|
||||
@ -56,8 +57,7 @@ static void add_socket(struct server_service *service,
|
||||
/****************************************************************************
|
||||
Open the socket communication.
|
||||
****************************************************************************/
|
||||
static void ldapsrv_init(struct server_service *service,
|
||||
const struct model_ops *model_ops)
|
||||
static void ldapsrv_init(struct server_service *service)
|
||||
{
|
||||
struct ldapsrv_service *ldap_service;
|
||||
struct ldapsrv_partition *part;
|
||||
@ -97,7 +97,7 @@ static void ldapsrv_init(struct server_service *service,
|
||||
ldap_service->default_partition = part;
|
||||
DLIST_ADD_END(ldap_service->partitions, part, struct ldapsrv_partition *);
|
||||
|
||||
service->private_data = ldap_service;
|
||||
service->service.private_data = ldap_service;
|
||||
|
||||
if (lp_interfaces() && lp_bind_interfaces_only()) {
|
||||
int num_interfaces = iface_count();
|
||||
@ -116,14 +116,14 @@ static void ldapsrv_init(struct server_service *service,
|
||||
continue;
|
||||
}
|
||||
|
||||
add_socket(service, model_ops, ifip);
|
||||
add_socket(service, ifip);
|
||||
}
|
||||
} else {
|
||||
struct ipv4_addr ifip;
|
||||
|
||||
/* Just bind to lp_socket_address() (usually 0.0.0.0) */
|
||||
ifip = interpret_addr2(lp_socket_address());
|
||||
add_socket(service, model_ops, &ifip);
|
||||
add_socket(service, &ifip);
|
||||
}
|
||||
}
|
||||
|
||||
@ -423,7 +423,7 @@ NTSTATUS ldapsrv_flush_responses(struct ldapsrv_connection *conn)
|
||||
static void ldapsrv_recv(struct server_connection *conn, struct timeval t,
|
||||
uint16_t flags)
|
||||
{
|
||||
struct ldapsrv_connection *ldap_conn = conn->private_data;
|
||||
struct ldapsrv_connection *ldap_conn = conn->connection.private_data;
|
||||
uint8_t *buf;
|
||||
size_t buf_length, msg_length;
|
||||
DATA_BLOB blob;
|
||||
@ -519,7 +519,7 @@ static void ldapsrv_recv(struct server_connection *conn, struct timeval t,
|
||||
static void ldapsrv_send(struct server_connection *conn, struct timeval t,
|
||||
uint16_t flags)
|
||||
{
|
||||
struct ldapsrv_connection *ldap_conn = conn->private_data;
|
||||
struct ldapsrv_connection *ldap_conn = conn->connection.private_data;
|
||||
|
||||
DEBUG(10,("ldapsrv_send\n"));
|
||||
|
||||
@ -535,20 +535,6 @@ static void ldapsrv_send(struct server_connection *conn, struct timeval t,
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
called when connection is idle
|
||||
*/
|
||||
static void ldapsrv_idle(struct server_connection *conn, struct timeval t)
|
||||
{
|
||||
DEBUG(10,("ldapsrv_idle: not implemented!\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
static void ldapsrv_close(struct server_connection *conn, const char *reason)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
initialise a server_context from a open socket and register a event handler
|
||||
for reading from that socket
|
||||
@ -566,31 +552,31 @@ static void ldapsrv_accept(struct server_connection *conn)
|
||||
|
||||
ZERO_STRUCTP(ldap_conn);
|
||||
ldap_conn->connection = conn;
|
||||
ldap_conn->service = talloc_reference(ldap_conn, conn->service->private_data);
|
||||
ldap_conn->service = talloc_reference(ldap_conn, conn->stream_socket->service);
|
||||
|
||||
conn->private_data = ldap_conn;
|
||||
conn->connection.private_data = ldap_conn;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
called on a fatal error that should cause this server to terminate
|
||||
*/
|
||||
static void ldapsrv_exit(struct server_service *service, const char *reason)
|
||||
static const struct server_stream_ops ldap_stream_ops = {
|
||||
.name = "ldap",
|
||||
.socket_init = NULL,
|
||||
.accept_connection = ldapsrv_accept,
|
||||
.recv_handler = ldapsrv_recv,
|
||||
.send_handler = ldapsrv_send,
|
||||
.idle_handler = NULL,
|
||||
.close_connection = NULL
|
||||
};
|
||||
|
||||
static const struct server_stream_ops *ldapsrv_get_stream_ops(void)
|
||||
{
|
||||
DEBUG(10,("ldapsrv_exit\n"));
|
||||
return;
|
||||
return &ldap_stream_ops;
|
||||
}
|
||||
|
||||
static const struct server_service_ops ldap_server_ops = {
|
||||
.name = "ldap",
|
||||
.service_init = ldapsrv_init,
|
||||
.accept_connection = ldapsrv_accept,
|
||||
.recv_handler = ldapsrv_recv,
|
||||
.send_handler = ldapsrv_send,
|
||||
.idle_handler = ldapsrv_idle,
|
||||
.close_connection = ldapsrv_close,
|
||||
.service_exit = ldapsrv_exit,
|
||||
.service_init = ldapsrv_init
|
||||
};
|
||||
|
||||
const struct server_service_ops *ldapsrv_get_ops(void)
|
||||
|
@ -134,7 +134,7 @@ static int pvfs_wait_destructor(void *ptr)
|
||||
|
||||
pwait->private = private;
|
||||
pwait->handler = fn;
|
||||
pwait->msg_ctx = pvfs->tcon->smb_conn->connection->messaging_ctx;
|
||||
pwait->msg_ctx = pvfs->tcon->smb_conn->connection->messaging.ctx;
|
||||
pwait->ev = req->tcon->smb_conn->connection->event.ctx;
|
||||
pwait->msg_type = msg_type;
|
||||
pwait->req = talloc_reference(pwait, req);
|
||||
|
@ -130,16 +130,16 @@ static NTSTATUS pvfs_connect(struct ntvfs_module_context *ntvfs,
|
||||
ntvfs->private_data = pvfs;
|
||||
|
||||
pvfs->brl_context = brl_init(pvfs,
|
||||
pvfs->tcon->smb_conn->connection->server_id,
|
||||
pvfs->tcon->smb_conn->connection->connection.id,
|
||||
pvfs->tcon->service,
|
||||
pvfs->tcon->smb_conn->connection->messaging_ctx);
|
||||
pvfs->tcon->smb_conn->connection->messaging.ctx);
|
||||
if (pvfs->brl_context == NULL) {
|
||||
return NT_STATUS_INTERNAL_DB_CORRUPTION;
|
||||
}
|
||||
|
||||
pvfs->odb_context = odb_init(pvfs,
|
||||
pvfs->tcon->smb_conn->connection->server_id,
|
||||
pvfs->tcon->smb_conn->connection->messaging_ctx);
|
||||
pvfs->tcon->smb_conn->connection->connection.id,
|
||||
pvfs->tcon->smb_conn->connection->messaging.ctx);
|
||||
if (pvfs->odb_context == NULL) {
|
||||
return NT_STATUS_INTERNAL_DB_CORRUPTION;
|
||||
}
|
||||
|
@ -1220,7 +1220,7 @@ NTSTATUS dcesrv_init_ipc_context(TALLOC_CTX *mem_ctx, struct dcesrv_context **_d
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static void dcesrv_init(struct server_service *service, const struct model_ops *model_ops)
|
||||
static void dcesrv_init(struct server_service *service)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcesrv_context *dce_ctx;
|
||||
@ -1235,7 +1235,9 @@ static void dcesrv_init(struct server_service *service, const struct model_ops *
|
||||
return;
|
||||
}
|
||||
|
||||
dcesrv_sock_init(service, model_ops, dce_ctx);
|
||||
service->service.private_data = dce_ctx;
|
||||
|
||||
dcesrv_sock_init(service);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1257,18 +1259,6 @@ static void dcesrv_send(struct server_connection *srv_conn,
|
||||
dcesrv_sock_send(srv_conn, t, flags);
|
||||
}
|
||||
|
||||
static void dcesrv_close(struct server_connection *srv_conn, const char *reason)
|
||||
{
|
||||
dcesrv_sock_close(srv_conn, reason);
|
||||
return;
|
||||
}
|
||||
|
||||
static void dcesrv_exit(struct server_service *service, const char *reason)
|
||||
{
|
||||
dcesrv_sock_exit(service, reason);
|
||||
return;
|
||||
}
|
||||
|
||||
/* the list of currently registered DCERPC endpoint servers.
|
||||
*/
|
||||
static struct ep_server {
|
||||
@ -1350,15 +1340,24 @@ const struct dcesrv_critical_sizes *dcerpc_module_version(void)
|
||||
return &critical_sizes;
|
||||
}
|
||||
|
||||
static const struct server_service_ops dcesrv_ops = {
|
||||
static const struct server_stream_ops dcesrv_stream_ops = {
|
||||
.name = "rpc",
|
||||
.service_init = dcesrv_init,
|
||||
.socket_init = NULL,
|
||||
.accept_connection = dcesrv_accept,
|
||||
.recv_handler = dcesrv_recv,
|
||||
.send_handler = dcesrv_send,
|
||||
.idle_handler = NULL,
|
||||
.close_connection = dcesrv_close,
|
||||
.service_exit = dcesrv_exit,
|
||||
.close_connection = NULL
|
||||
};
|
||||
|
||||
const struct server_stream_ops *dcesrv_get_stream_ops(void)
|
||||
{
|
||||
return &dcesrv_stream_ops;
|
||||
}
|
||||
|
||||
static const struct server_service_ops dcesrv_ops = {
|
||||
.name = "rpc",
|
||||
.service_init = dcesrv_init,
|
||||
};
|
||||
|
||||
const struct server_service_ops *dcesrv_get_ops(void)
|
||||
|
@ -53,24 +53,22 @@ static void dcesrv_terminate_connection(struct dcesrv_connection *dce_conn, cons
|
||||
server_terminate_connection(dce_conn->srv_conn, reason);
|
||||
}
|
||||
|
||||
static void add_socket_rpc_unix(struct server_service *service,
|
||||
const struct model_ops *model_ops,
|
||||
struct dcesrv_context *dce_ctx,
|
||||
struct dcesrv_endpoint *e)
|
||||
static void add_socket_rpc_unix(struct server_service *service, struct dcesrv_endpoint *e)
|
||||
{
|
||||
struct server_socket *sock;
|
||||
struct dcesrv_context *dce_ctx = service->service.private_data;
|
||||
struct server_stream_socket *stream_socket;
|
||||
struct dcesrv_socket_context *dcesrv_sock;
|
||||
uint16_t port = 1;
|
||||
|
||||
sock = service_setup_socket(service,model_ops, "unix", e->ep_description.endpoint, &port);
|
||||
if (!sock) {
|
||||
DEBUG(0,("service_setup_socket(path=%s) failed\n",e->ep_description.endpoint));
|
||||
stream_socket = service_setup_stream_socket(service, dcesrv_get_stream_ops(), "unix", e->ep_description.endpoint, &port);
|
||||
if (!stream_socket) {
|
||||
DEBUG(0,("service_setup_stream_socket(path=%s) failed\n",e->ep_description.endpoint));
|
||||
return;
|
||||
}
|
||||
|
||||
dcesrv_sock = talloc_p(sock, struct dcesrv_socket_context);
|
||||
dcesrv_sock = talloc_p(stream_socket, struct dcesrv_socket_context);
|
||||
if (!dcesrv_sock) {
|
||||
DEBUG(0,("talloc_p(sock->mem_ctx, struct dcesrv_socket_context) failed\n"));
|
||||
DEBUG(0,("talloc_p(stream_socket, struct dcesrv_socket_context) failed\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -78,15 +76,13 @@ static void add_socket_rpc_unix(struct server_service *service,
|
||||
dcesrv_sock->endpoint = e;
|
||||
dcesrv_sock->dcesrv_ctx = dce_ctx;
|
||||
|
||||
sock->private_data = dcesrv_sock;
|
||||
stream_socket->stream.private_data = dcesrv_sock;
|
||||
}
|
||||
|
||||
static void add_socket_rpc_ncalrpc(struct server_service *service,
|
||||
const struct model_ops *model_ops,
|
||||
struct dcesrv_context *dce_ctx,
|
||||
struct dcesrv_endpoint *e)
|
||||
static void add_socket_rpc_ncalrpc(struct server_service *service, struct dcesrv_endpoint *e)
|
||||
{
|
||||
struct server_socket *sock;
|
||||
struct dcesrv_context *dce_ctx = service->service.private_data;
|
||||
struct server_stream_socket *stream_socket;
|
||||
struct dcesrv_socket_context *dcesrv_sock;
|
||||
uint16_t port = 1;
|
||||
char *full_path;
|
||||
@ -100,15 +96,15 @@ static void add_socket_rpc_ncalrpc(struct server_service *service,
|
||||
|
||||
full_path = talloc_asprintf(dce_ctx, "%s/%s", lp_ncalrpc_dir(), e->ep_description.endpoint);
|
||||
|
||||
sock = service_setup_socket(service,model_ops, "unix", full_path, &port);
|
||||
if (!sock) {
|
||||
DEBUG(0,("service_setup_socket(identifier=%s,path=%s) failed\n",e->ep_description.endpoint, full_path));
|
||||
stream_socket = service_setup_stream_socket(service, dcesrv_get_stream_ops(), "unix", full_path, &port);
|
||||
if (!stream_socket) {
|
||||
DEBUG(0,("service_setup_stream_socket(identifier=%s,path=%s) failed\n",e->ep_description.endpoint, full_path));
|
||||
return;
|
||||
}
|
||||
|
||||
dcesrv_sock = talloc_p(sock, struct dcesrv_socket_context);
|
||||
dcesrv_sock = talloc_p(stream_socket, struct dcesrv_socket_context);
|
||||
if (!dcesrv_sock) {
|
||||
DEBUG(0,("talloc_p(sock->mem_ctx, struct dcesrv_socket_context) failed\n"));
|
||||
DEBUG(0,("talloc_p(stream_socket, struct dcesrv_socket_context) failed\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -116,7 +112,7 @@ static void add_socket_rpc_ncalrpc(struct server_service *service,
|
||||
dcesrv_sock->endpoint = e;
|
||||
dcesrv_sock->dcesrv_ctx = dce_ctx;
|
||||
|
||||
sock->private_data = dcesrv_sock;
|
||||
stream_socket->stream.private_data = dcesrv_sock;
|
||||
|
||||
return;
|
||||
}
|
||||
@ -125,12 +121,11 @@ static void add_socket_rpc_ncalrpc(struct server_service *service,
|
||||
add a socket address to the list of events, one event per dcerpc endpoint
|
||||
*/
|
||||
static void add_socket_rpc_tcp_iface(struct server_service *service,
|
||||
const struct model_ops *model_ops,
|
||||
struct dcesrv_context *dce_ctx,
|
||||
struct dcesrv_endpoint *e,
|
||||
struct ipv4_addr *ifip)
|
||||
{
|
||||
struct server_socket *sock;
|
||||
struct dcesrv_context *dce_ctx = service->service.private_data;
|
||||
struct server_stream_socket *stream_socket;
|
||||
struct dcesrv_socket_context *dcesrv_sock;
|
||||
uint16_t port = 0;
|
||||
char *ip_str = talloc_strdup(service, sys_inet_ntoa(*ifip));
|
||||
@ -138,9 +133,9 @@ static void add_socket_rpc_tcp_iface(struct server_service *service,
|
||||
if (e->ep_description.endpoint)
|
||||
port = atoi(e->ep_description.endpoint);
|
||||
|
||||
sock = service_setup_socket(service,model_ops, "ipv4", ip_str, &port);
|
||||
if (!sock) {
|
||||
DEBUG(0,("service_setup_socket(port=%u) failed\n",port));
|
||||
stream_socket = service_setup_stream_socket(service, dcesrv_get_stream_ops(), "ipv4", ip_str, &port);
|
||||
if (!stream_socket) {
|
||||
DEBUG(0,("service_setup_stream_socket(address=%s,port=%u) failed\n", ip_str, port));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -148,9 +143,9 @@ static void add_socket_rpc_tcp_iface(struct server_service *service,
|
||||
e->ep_description.endpoint = talloc_asprintf(dce_ctx, "%d", port);
|
||||
}
|
||||
|
||||
dcesrv_sock = talloc_p(sock, struct dcesrv_socket_context);
|
||||
dcesrv_sock = talloc_p(stream_socket, struct dcesrv_socket_context);
|
||||
if (!dcesrv_sock) {
|
||||
DEBUG(0,("talloc_p(sock->mem_ctx, struct dcesrv_socket_context) failed\n"));
|
||||
DEBUG(0,("talloc_p(stream_socket, struct dcesrv_socket_context) failed\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -158,17 +153,14 @@ static void add_socket_rpc_tcp_iface(struct server_service *service,
|
||||
dcesrv_sock->endpoint = e;
|
||||
dcesrv_sock->dcesrv_ctx = dce_ctx;
|
||||
|
||||
sock->private_data = dcesrv_sock;
|
||||
stream_socket->stream.private_data = dcesrv_sock;
|
||||
|
||||
talloc_free(ip_str);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void add_socket_rpc_tcp(struct server_service *service,
|
||||
const struct model_ops *model_ops,
|
||||
struct dcesrv_context *dce_ctx,
|
||||
struct dcesrv_endpoint *e)
|
||||
static void add_socket_rpc_tcp(struct server_service *service, struct dcesrv_endpoint *e)
|
||||
{
|
||||
/* Add TCP/IP sockets */
|
||||
if (lp_interfaces() && lp_bind_interfaces_only()) {
|
||||
@ -179,12 +171,12 @@ static void add_socket_rpc_tcp(struct server_service *service,
|
||||
if (ifip == NULL) {
|
||||
continue;
|
||||
}
|
||||
add_socket_rpc_tcp_iface(service, model_ops, dce_ctx, e, ifip);
|
||||
add_socket_rpc_tcp_iface(service, e, ifip);
|
||||
}
|
||||
} else {
|
||||
struct ipv4_addr ifip;
|
||||
ifip = interpret_addr2(lp_socket_address());
|
||||
add_socket_rpc_tcp_iface(service, model_ops, dce_ctx, e, &ifip);
|
||||
add_socket_rpc_tcp_iface(service, e, &ifip);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -193,8 +185,9 @@ static void add_socket_rpc_tcp(struct server_service *service,
|
||||
/****************************************************************************
|
||||
Open the listening sockets for RPC over NCACN_IP_TCP/NCALRPC/NCACN_UNIX_STREAM
|
||||
****************************************************************************/
|
||||
void dcesrv_sock_init(struct server_service *service, const struct model_ops *model_ops, struct dcesrv_context *dce_ctx)
|
||||
void dcesrv_sock_init(struct server_service *service)
|
||||
{
|
||||
struct dcesrv_context *dce_ctx = service->service.private_data;
|
||||
struct dcesrv_endpoint *e;
|
||||
|
||||
DEBUG(1,("dcesrv_sock_init\n"));
|
||||
@ -207,15 +200,15 @@ void dcesrv_sock_init(struct server_service *service, const struct model_ops *mo
|
||||
for (e=dce_ctx->endpoint_list;e;e=e->next) {
|
||||
switch (e->ep_description.transport) {
|
||||
case NCACN_UNIX_STREAM:
|
||||
add_socket_rpc_unix(service, model_ops, dce_ctx, e);
|
||||
add_socket_rpc_unix(service, e);
|
||||
break;
|
||||
|
||||
case NCALRPC:
|
||||
add_socket_rpc_ncalrpc(service, model_ops, dce_ctx, e);
|
||||
add_socket_rpc_ncalrpc(service, e);
|
||||
break;
|
||||
|
||||
case NCACN_IP_TCP:
|
||||
add_socket_rpc_tcp(service, model_ops, dce_ctx, e);
|
||||
add_socket_rpc_tcp(service, e);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -229,7 +222,7 @@ void dcesrv_sock_init(struct server_service *service, const struct model_ops *mo
|
||||
void dcesrv_sock_accept(struct server_connection *srv_conn)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcesrv_socket_context *dcesrv_sock = srv_conn->server_socket->private_data;
|
||||
struct dcesrv_socket_context *dcesrv_sock = srv_conn->stream_socket->stream.private_data;
|
||||
struct dcesrv_connection *dcesrv_conn = NULL;
|
||||
|
||||
DEBUG(5,("dcesrv_sock_accept\n"));
|
||||
@ -245,7 +238,7 @@ void dcesrv_sock_accept(struct server_connection *srv_conn)
|
||||
return;
|
||||
}
|
||||
|
||||
srv_conn->private_data = dcesrv_conn;
|
||||
srv_conn->connection.private_data = dcesrv_conn;
|
||||
|
||||
return;
|
||||
}
|
||||
@ -253,7 +246,7 @@ void dcesrv_sock_accept(struct server_connection *srv_conn)
|
||||
void dcesrv_sock_recv(struct server_connection *conn, struct timeval t, uint16_t flags)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct dcesrv_connection *dce_conn = conn->private_data;
|
||||
struct dcesrv_connection *dce_conn = conn->connection.private_data;
|
||||
DATA_BLOB tmp_blob;
|
||||
size_t nread;
|
||||
|
||||
@ -292,7 +285,7 @@ void dcesrv_sock_recv(struct server_connection *conn, struct timeval t, uint16_t
|
||||
|
||||
void dcesrv_sock_send(struct server_connection *conn, struct timeval t, uint16_t flags)
|
||||
{
|
||||
struct dcesrv_connection *dce_conn = conn->private_data;
|
||||
struct dcesrv_connection *dce_conn = conn->connection.private_data;
|
||||
NTSTATUS status;
|
||||
|
||||
DEBUG(10,("dcesrv_sock_send\n"));
|
||||
@ -309,20 +302,3 @@ void dcesrv_sock_send(struct server_connection *conn, struct timeval t, uint16_t
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void dcesrv_sock_close(struct server_connection *conn, const char *reason)
|
||||
{
|
||||
struct dcesrv_connection *dce_conn = conn->private_data;
|
||||
|
||||
DEBUG(5,("dcesrv_sock_close: %s\n",reason));
|
||||
|
||||
talloc_free(dce_conn);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void dcesrv_sock_exit(struct server_service *service, const char *reason)
|
||||
{
|
||||
DEBUG(1,("dcesrv_sock_exit: %s\n",reason));
|
||||
return;
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ static void reply_lanman1(struct smbsrv_request *req, uint16_t choice)
|
||||
SSVAL(req->out.vwv, VWV(3), lp_maxmux());
|
||||
SSVAL(req->out.vwv, VWV(4), 1);
|
||||
SSVAL(req->out.vwv, VWV(5), raw);
|
||||
SIVAL(req->out.vwv, VWV(6), req->smb_conn->pid);
|
||||
SIVAL(req->out.vwv, VWV(6), req->smb_conn->connection->connection.id);
|
||||
srv_push_dos_date(req->smb_conn, req->out.vwv, VWV(8), t);
|
||||
SSVAL(req->out.vwv, VWV(10), req->smb_conn->negotiate.zone_offset/60);
|
||||
SIVAL(req->out.vwv, VWV(11), 0); /* reserved */
|
||||
@ -198,7 +198,7 @@ static void reply_lanman2(struct smbsrv_request *req, uint16_t choice)
|
||||
SSVAL(req->out.vwv, VWV(3), lp_maxmux());
|
||||
SSVAL(req->out.vwv, VWV(4), 1);
|
||||
SSVAL(req->out.vwv, VWV(5), raw);
|
||||
SIVAL(req->out.vwv, VWV(6), req->smb_conn->pid);
|
||||
SIVAL(req->out.vwv, VWV(6), req->smb_conn->connection->connection.id);
|
||||
srv_push_dos_date(req->smb_conn, req->out.vwv, VWV(8), t);
|
||||
SSVAL(req->out.vwv, VWV(10), req->smb_conn->negotiate.zone_offset/60);
|
||||
SIVAL(req->out.vwv, VWV(11), 0);
|
||||
@ -310,7 +310,7 @@ static void reply_nt1(struct smbsrv_request *req, uint16_t choice)
|
||||
SSVAL(req->out.vwv+1, VWV(2), 1); /* num vcs */
|
||||
SIVAL(req->out.vwv+1, VWV(3), req->smb_conn->negotiate.max_recv);
|
||||
SIVAL(req->out.vwv+1, VWV(5), 0x10000); /* raw size. full 64k */
|
||||
SIVAL(req->out.vwv+1, VWV(7), req->smb_conn->pid); /* session key */
|
||||
SIVAL(req->out.vwv+1, VWV(7), req->smb_conn->connection->connection.id); /* session key */
|
||||
SIVAL(req->out.vwv+1, VWV(9), capabilities);
|
||||
push_nttime(req->out.vwv+1, VWV(11), nttime);
|
||||
SSVALS(req->out.vwv+1,VWV(15), req->smb_conn->negotiate.zone_offset/60);
|
||||
|
@ -47,8 +47,6 @@ struct smbsrv_request *init_smb_request(struct smbsrv_connection *smb_conn)
|
||||
{
|
||||
struct smbsrv_request *req;
|
||||
|
||||
smb_conn->pkt_count++;
|
||||
|
||||
req = talloc_p(smb_conn, struct smbsrv_request);
|
||||
if (!req) {
|
||||
return NULL;
|
||||
|
@ -72,54 +72,6 @@ static int find_service(const char *service)
|
||||
|
||||
iService = lp_servicenumber(service);
|
||||
|
||||
/* If we still don't have a service, attempt to add it as a printer. */
|
||||
if (iService == -1) {
|
||||
int iPrinterService;
|
||||
|
||||
if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) >= 0) {
|
||||
const char *pszTemp;
|
||||
|
||||
DEBUG(3,("checking whether %s is a valid printer name...\n", service));
|
||||
pszTemp = lp_printcapname();
|
||||
if ((pszTemp != NULL) && pcap_printername_ok(service, pszTemp)) {
|
||||
DEBUG(3,("%s is a valid printer name\n", service));
|
||||
DEBUG(3,("adding %s as a printer service\n", service));
|
||||
lp_add_printer(service, iPrinterService);
|
||||
iService = lp_servicenumber(service);
|
||||
if (iService < 0)
|
||||
DEBUG(0,("failed to add %s as a printer service!\n", service));
|
||||
} else {
|
||||
DEBUG(3,("%s is not a valid printer name\n", service));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for default vfs service? Unsure whether to implement this */
|
||||
if (iService == -1) {
|
||||
}
|
||||
|
||||
/* just possibly it's a default service? */
|
||||
if (iService == -1) {
|
||||
const char *pdefservice = lp_defaultservice();
|
||||
if (pdefservice && *pdefservice &&
|
||||
!strequal(pdefservice,service) &&
|
||||
!strstr(service,"..")) {
|
||||
/*
|
||||
* We need to do a local copy here as lp_defaultservice()
|
||||
* returns one of the rotating lp_string buffers that
|
||||
* could get overwritten by the recursive find_service() call
|
||||
* below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
|
||||
*/
|
||||
pstring defservice;
|
||||
pstrcpy(defservice, pdefservice);
|
||||
iService = find_service(defservice);
|
||||
if (iService >= 0) {
|
||||
/* REWRITE: all_string_sub(service, "_","/",0); */
|
||||
iService = lp_add_service(service, iService);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (iService >= 0 && !VALID_SNUM(iService)) {
|
||||
DEBUG(0,("Invalid snum %d for %s\n",iService, service));
|
||||
iService = -1;
|
||||
|
@ -506,7 +506,7 @@ static void switch_message(int type, struct smbsrv_request *req)
|
||||
session_tag = req->session->vuid;
|
||||
}
|
||||
|
||||
DEBUG(3,("switch message %s (task_id %d)\n",smb_fn_name(type), smb_conn->connection->service->model_ops->get_id(req)));
|
||||
DEBUG(3,("switch message %s (task_id %d)\n",smb_fn_name(type), req->smb_conn->connection->connection.id));
|
||||
|
||||
/* does this protocol need a valid tree connection? */
|
||||
if ((flags & AS_USER) && !req->tcon) {
|
||||
@ -649,21 +649,12 @@ void smbsrv_terminate_connection(struct smbsrv_connection *smb_conn, const char
|
||||
server_terminate_connection(smb_conn->connection, reason);
|
||||
}
|
||||
|
||||
/*
|
||||
called on a fatal error that should cause this server to terminate
|
||||
*/
|
||||
static void smbsrv_exit(struct server_service *service, const char *reason)
|
||||
{
|
||||
DEBUG(1,("smbsrv_exit\n"));
|
||||
return;
|
||||
}
|
||||
static const struct server_stream_ops *smbsrv_stream_ops(void);
|
||||
|
||||
/*
|
||||
add a socket address to the list of events, one event per port
|
||||
*/
|
||||
static void smb_add_socket(struct server_service *service,
|
||||
const struct model_ops *model_ops,
|
||||
struct socket_context *socket_ctx,
|
||||
static void smb_add_socket(struct server_service *service,
|
||||
struct ipv4_addr *ifip)
|
||||
{
|
||||
const char **ports = lp_smb_ports();
|
||||
@ -673,7 +664,7 @@ static void smb_add_socket(struct server_service *service,
|
||||
for (i=0;ports[i];i++) {
|
||||
uint16_t port = atoi(ports[i]);
|
||||
if (port == 0) continue;
|
||||
service_setup_socket(service, model_ops, "ipv4", ip_str, &port);
|
||||
service_setup_stream_socket(service, smbsrv_stream_ops(), "ipv4", ip_str, &port);
|
||||
}
|
||||
|
||||
talloc_free(ip_str);
|
||||
@ -682,7 +673,7 @@ static void smb_add_socket(struct server_service *service,
|
||||
/****************************************************************************
|
||||
Open the socket communication.
|
||||
****************************************************************************/
|
||||
static void smbsrv_init(struct server_service *service, const struct model_ops *model_ops)
|
||||
static void smbsrv_init(struct server_service *service)
|
||||
{
|
||||
DEBUG(1,("smbsrv_init\n"));
|
||||
|
||||
@ -702,13 +693,13 @@ static void smbsrv_init(struct server_service *service, const struct model_ops *
|
||||
continue;
|
||||
}
|
||||
|
||||
smb_add_socket(service, model_ops, NULL, ifip);
|
||||
smb_add_socket(service, ifip);
|
||||
}
|
||||
} else {
|
||||
struct ipv4_addr ifip;
|
||||
/* Just bind to lp_socket_address() (usually 0.0.0.0) */
|
||||
ifip = interpret_addr2(lp_socket_address());
|
||||
smb_add_socket(service, model_ops, NULL, &ifip);
|
||||
smb_add_socket(service, &ifip);
|
||||
}
|
||||
}
|
||||
|
||||
@ -717,7 +708,7 @@ static void smbsrv_init(struct server_service *service, const struct model_ops *
|
||||
*/
|
||||
static void smbsrv_recv(struct server_connection *conn, struct timeval t, uint16_t flags)
|
||||
{
|
||||
struct smbsrv_connection *smb_conn = conn->private_data;
|
||||
struct smbsrv_connection *smb_conn = conn->connection.private_data;
|
||||
NTSTATUS status;
|
||||
|
||||
DEBUG(10,("smbsrv_recv\n"));
|
||||
@ -738,7 +729,7 @@ static void smbsrv_recv(struct server_connection *conn, struct timeval t, uint16
|
||||
*/
|
||||
static void smbsrv_send(struct server_connection *conn, struct timeval t, uint16_t flags)
|
||||
{
|
||||
struct smbsrv_connection *smb_conn = conn->private_data;
|
||||
struct smbsrv_connection *smb_conn = conn->connection.private_data;
|
||||
|
||||
while (smb_conn->pending_send) {
|
||||
struct smbsrv_request *req = smb_conn->pending_send;
|
||||
@ -776,19 +767,9 @@ static void smbsrv_send(struct server_connection *conn, struct timeval t, uint16
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
called when connection is idle
|
||||
*/
|
||||
static void smbsrv_idle(struct server_connection *conn, struct timeval t)
|
||||
{
|
||||
DEBUG(10,("smbsrv_idle: not implemented!\n"));
|
||||
conn->event.idle->next_event = timeval_add(&t, 5, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
static void smbsrv_close(struct server_connection *conn, const char *reason)
|
||||
{
|
||||
struct smbsrv_connection *smb_conn = conn->private_data;
|
||||
struct smbsrv_connection *smb_conn = conn->connection.private_data;
|
||||
|
||||
DEBUG(5,("smbsrv_close: %s\n",reason));
|
||||
|
||||
@ -818,7 +799,7 @@ void smbd_process_async(struct smbsrv_connection *smb_conn)
|
||||
initialise a server_context from a open socket and register a event handler
|
||||
for reading from that socket
|
||||
*/
|
||||
void smbsrv_accept(struct server_connection *conn)
|
||||
static void smbsrv_accept(struct server_connection *conn)
|
||||
{
|
||||
struct smbsrv_connection *smb_conn;
|
||||
|
||||
@ -827,10 +808,6 @@ void smbsrv_accept(struct server_connection *conn)
|
||||
smb_conn = talloc_zero_p(conn, struct smbsrv_connection);
|
||||
if (!smb_conn) return;
|
||||
|
||||
smb_conn->pid = getpid();
|
||||
|
||||
sub_set_context(&smb_conn->substitute);
|
||||
|
||||
/* now initialise a few default values associated with this smb socket */
|
||||
smb_conn->negotiate.max_send = 0xFFFF;
|
||||
|
||||
@ -848,20 +825,29 @@ void smbsrv_accept(struct server_connection *conn)
|
||||
|
||||
smb_conn->connection = conn;
|
||||
|
||||
conn->private_data = smb_conn;
|
||||
conn->connection.private_data = smb_conn;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static const struct server_service_ops smb_server_ops = {
|
||||
static const struct server_stream_ops smb_stream_ops = {
|
||||
.name = "smb",
|
||||
.service_init = smbsrv_init,
|
||||
.socket_init = NULL,
|
||||
.accept_connection = smbsrv_accept,
|
||||
.recv_handler = smbsrv_recv,
|
||||
.send_handler = smbsrv_send,
|
||||
.idle_handler = smbsrv_idle,
|
||||
.close_connection = smbsrv_close,
|
||||
.service_exit = smbsrv_exit,
|
||||
.idle_handler = NULL,
|
||||
.close_connection = smbsrv_close
|
||||
};
|
||||
|
||||
static const struct server_stream_ops *smbsrv_stream_ops(void)
|
||||
{
|
||||
return &smb_stream_ops;
|
||||
}
|
||||
|
||||
static const struct server_service_ops smb_server_ops = {
|
||||
.name = "smb",
|
||||
.service_init = smbsrv_init,
|
||||
};
|
||||
|
||||
const struct server_service_ops *smbsrv_get_ops(void)
|
||||
|
@ -150,7 +150,7 @@ struct substitute_context {
|
||||
struct smbsrv_connection {
|
||||
/* a count of the number of packets we have received. We
|
||||
* actually only care about zero/non-zero at this stage */
|
||||
unsigned pkt_count;
|
||||
//unsigned pkt_count;
|
||||
|
||||
/* context that has been negotiated between the client and server */
|
||||
struct {
|
||||
@ -213,6 +213,7 @@ struct smbsrv_connection {
|
||||
} tree;
|
||||
|
||||
/* the context associated with open files on an smb socket */
|
||||
#if 0
|
||||
struct {
|
||||
struct files_struct *files; /* open files */
|
||||
|
||||
@ -228,7 +229,7 @@ struct smbsrv_connection {
|
||||
/* limit for maximum open files */
|
||||
int real_max_open_files;
|
||||
} file;
|
||||
|
||||
#endif
|
||||
/* context associated with currently valid session setups */
|
||||
struct {
|
||||
/* this holds info on session vuids that are already validated for this VC */
|
||||
@ -237,11 +238,6 @@ struct smbsrv_connection {
|
||||
int num_validated_vuids;
|
||||
} sessions;
|
||||
|
||||
/* this holds long term state specific to the printing subsystem */
|
||||
struct {
|
||||
struct notify_queue *notify_queue_head;
|
||||
} print;
|
||||
|
||||
/* the server_context holds a linked list of pending requests,
|
||||
* this is used for blocking locks and requests blocked due to oplock
|
||||
* break requests */
|
||||
@ -251,7 +247,7 @@ struct smbsrv_connection {
|
||||
/* the request itself - needs to be freed */
|
||||
struct smbsrv_request *request;
|
||||
} *requests;
|
||||
|
||||
#if 0
|
||||
/* the timers context contains info on when we last did various
|
||||
* functions */
|
||||
struct {
|
||||
@ -264,13 +260,10 @@ struct smbsrv_connection {
|
||||
/* when we last checked the smb.conf for auto-reload */
|
||||
time_t last_smb_conf_reload;
|
||||
} timers;
|
||||
|
||||
#endif
|
||||
struct smb_signing_context signing;
|
||||
|
||||
struct substitute_context substitute;
|
||||
|
||||
/* the pid of the process handling this session */
|
||||
pid_t pid;
|
||||
// struct substitute_context substitute;
|
||||
|
||||
struct server_connection *connection;
|
||||
|
||||
|
@ -50,24 +50,15 @@ REQUIRED_SUBSYSTEMS = \
|
||||
# End SUBSYSTEM SERVER
|
||||
#######################
|
||||
|
||||
#######################
|
||||
# Start SUBSYSTEM SERVER
|
||||
[SUBSYSTEM::SERVER]
|
||||
INIT_OBJ_FILES = \
|
||||
smbd/server.o
|
||||
ADD_OBJ_FILES = \
|
||||
smbd/rewrite.o
|
||||
REQUIRED_SUBSYSTEMS = \
|
||||
PROCESS_MODEL \
|
||||
SERVER_SERVICE
|
||||
# End SUBSYSTEM SERVER
|
||||
#######################
|
||||
|
||||
#################################
|
||||
# Start BINARY smbd
|
||||
[BINARY::smbd]
|
||||
OBJ_FILES = \
|
||||
smbd/server.o \
|
||||
smbd/rewrite.o
|
||||
REQUIRED_SUBSYSTEMS = \
|
||||
SERVER \
|
||||
PROCESS_MODEL \
|
||||
SERVER_SERVICE \
|
||||
CONFIG \
|
||||
LIBCMDLINE \
|
||||
LIBBASIC
|
||||
|
@ -27,7 +27,7 @@
|
||||
/*
|
||||
setup the events for the chosen process model
|
||||
*/
|
||||
const struct model_ops *process_model_startup(const char *model)
|
||||
const struct model_ops *process_model_startup(struct server_context *srv_ctx, const char *model)
|
||||
{
|
||||
const struct model_ops *ops;
|
||||
|
||||
@ -37,7 +37,7 @@ const struct model_ops *process_model_startup(const char *model)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
ops->model_startup();
|
||||
ops->model_init(srv_ctx);
|
||||
|
||||
return ops;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
process model manager - main loop
|
||||
Copyright (C) Andrew Tridgell 1992-2003
|
||||
Copyright (C) James J Myers 2003 <myersjj@samba.org>
|
||||
Copyright (C) Stefan (metze) Metzmacher 2004
|
||||
Copyright (C) Stefan (metze) Metzmacher 2004-2005
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -37,21 +37,23 @@ struct model_ops {
|
||||
const char *name;
|
||||
|
||||
/* called at startup when the model is selected */
|
||||
void (*model_startup)(void);
|
||||
void (*model_init)(struct server_context *srv_ctx);
|
||||
/* called at th eend of the main server process */
|
||||
void (*model_exit)(struct server_context *srv_ctx, const char *reason);
|
||||
|
||||
|
||||
/* function to accept new connection */
|
||||
void (*accept_connection)(struct event_context *, struct fd_event *,
|
||||
struct timeval t, uint16_t);
|
||||
|
||||
/* function to terminate a connection */
|
||||
void (*terminate_connection)(struct server_connection *srv_conn,
|
||||
const char *reason);
|
||||
|
||||
/* function to exit server */
|
||||
void (*exit_server)(struct server_context *srv_ctx, const char *reason);
|
||||
|
||||
/* returns process or thread id */
|
||||
int (*get_id)(struct smbsrv_request *req);
|
||||
/* function to create a new task event_context */
|
||||
void (*create_task)(struct server_task *task);
|
||||
/* function to exit this task */
|
||||
void (*terminate_task)(struct server_task *task, const char *reason);
|
||||
};
|
||||
|
||||
/* this structure is used by modules to determine the size of some critical types */
|
||||
|
@ -30,9 +30,15 @@
|
||||
/*
|
||||
called when the process model is selected
|
||||
*/
|
||||
static void single_start_server(void)
|
||||
static void single_model_init(struct server_context *server)
|
||||
{
|
||||
smbd_process_init();
|
||||
}
|
||||
|
||||
static void single_model_exit(struct server_context *server, const char *reason)
|
||||
{
|
||||
DEBUG(1,("single_exit_server: reason[%s]\n",reason));
|
||||
talloc_free(server);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -43,18 +49,18 @@ static void single_accept_connection(struct event_context *ev, struct fd_event *
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct socket_context *sock;
|
||||
struct server_socket *server_socket = srv_fde->private;
|
||||
struct server_stream_socket *stream_socket = srv_fde->private;
|
||||
struct server_connection *conn;
|
||||
|
||||
/* accept an incoming connection. */
|
||||
status = socket_accept(server_socket->socket, &sock);
|
||||
status = socket_accept(stream_socket->socket, &sock);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0,("accept_connection_single: accept: %s\n",
|
||||
nt_errstr(status)));
|
||||
return;
|
||||
}
|
||||
|
||||
conn = server_setup_connection(ev, server_socket, sock, t, socket_get_fd(sock));
|
||||
conn = server_setup_connection(ev, stream_socket, sock, t, socket_get_fd(sock));
|
||||
if (!conn) {
|
||||
DEBUG(10,("server_setup_connection failed\n"));
|
||||
return;
|
||||
@ -62,8 +68,6 @@ static void single_accept_connection(struct event_context *ev, struct fd_event *
|
||||
|
||||
talloc_steal(conn, sock);
|
||||
|
||||
DLIST_ADD(server_socket->connection_list,conn);
|
||||
|
||||
/* return to event handling */
|
||||
return;
|
||||
}
|
||||
@ -80,38 +84,57 @@ static void single_terminate_connection(struct server_connection *conn, const ch
|
||||
}
|
||||
}
|
||||
|
||||
static int single_get_id(struct smbsrv_request *req)
|
||||
/*
|
||||
called to create a new event context for a new task
|
||||
*/
|
||||
static void single_create_task(struct server_task *task)
|
||||
{
|
||||
return (int)req->smb_conn->pid;
|
||||
task->task.id = (uint32_t)task;
|
||||
task->event.ctx = task->service->server->event.ctx;
|
||||
|
||||
/* setup to receive internal messages on this connection */
|
||||
task->messaging.ctx = messaging_init(task, task->task.id, task->event.ctx);
|
||||
if (!task->messaging.ctx) {
|
||||
server_terminate_task(task, "messaging_init() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
task->task.ops->task_init(task);
|
||||
return;
|
||||
}
|
||||
|
||||
static void single_exit_server(struct server_context *srv_ctx, const char *reason)
|
||||
/*
|
||||
called to exit from a server_task
|
||||
*/
|
||||
static void single_terminate_task(struct server_task *task, const char *reason)
|
||||
{
|
||||
DEBUG(1,("single_exit_server: reason[%s]\n",reason));
|
||||
talloc_free(task);
|
||||
return;
|
||||
}
|
||||
|
||||
static const struct model_ops single_ops = {
|
||||
.name = "single",
|
||||
|
||||
.model_init = single_model_init,
|
||||
.model_exit = single_model_exit,
|
||||
|
||||
.accept_connection = single_accept_connection,
|
||||
.terminate_connection = single_terminate_connection,
|
||||
|
||||
.create_task = single_create_task,
|
||||
.terminate_task = single_terminate_task
|
||||
};
|
||||
|
||||
/*
|
||||
initialise the single process model, registering ourselves with the process model subsystem
|
||||
*/
|
||||
NTSTATUS process_model_single_init(void)
|
||||
{
|
||||
NTSTATUS ret;
|
||||
struct model_ops ops;
|
||||
|
||||
ZERO_STRUCT(ops);
|
||||
|
||||
/* fill in our name */
|
||||
ops.name = "single";
|
||||
|
||||
/* fill in all the operations */
|
||||
ops.model_startup = single_start_server;
|
||||
ops.accept_connection = single_accept_connection;
|
||||
ops.terminate_connection = single_terminate_connection;
|
||||
ops.exit_server = single_exit_server;
|
||||
ops.get_id = single_get_id;
|
||||
|
||||
/* register ourselves with the PROCESS_MODEL subsystem. */
|
||||
ret = register_process_model(&ops);
|
||||
ret = register_process_model(&single_ops);
|
||||
if (!NT_STATUS_IS_OK(ret)) {
|
||||
DEBUG(0,("Failed to register process_model 'single'!\n"));
|
||||
return ret;
|
||||
|
@ -29,10 +29,16 @@
|
||||
/*
|
||||
called when the process model is selected
|
||||
*/
|
||||
static void standard_model_startup(void)
|
||||
static void standard_model_init(struct server_context *server)
|
||||
{
|
||||
signal(SIGCHLD, SIG_IGN);
|
||||
smbd_process_init();
|
||||
}
|
||||
|
||||
static void standard_model_exit(struct server_context *server, const char *reason)
|
||||
{
|
||||
DEBUG(1,("standard_model_exit: reason[%s]\n",reason));
|
||||
talloc_free(server);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -43,12 +49,12 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct socket_context *sock;
|
||||
struct server_socket *server_socket = srv_fde->private;
|
||||
struct server_stream_socket *stream_socket = srv_fde->private;
|
||||
struct server_connection *conn;
|
||||
pid_t pid;
|
||||
|
||||
/* accept an incoming connection. */
|
||||
status = socket_accept(server_socket->socket, &sock);
|
||||
status = socket_accept(stream_socket->socket, &sock);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0,("standard_accept_connection: accept: %s\n",
|
||||
nt_errstr(status)));
|
||||
@ -68,7 +74,7 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event
|
||||
/* Child code ... */
|
||||
|
||||
/* close all the listening sockets */
|
||||
service_close_listening_sockets(server_socket->service->srv_ctx);
|
||||
event_remove_fd_all_handler(ev, server_accept_handler);
|
||||
|
||||
/* we don't care if the dup fails, as its only a select()
|
||||
speed optimisation */
|
||||
@ -83,16 +89,15 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event
|
||||
|
||||
set_need_random_reseed();
|
||||
|
||||
conn = server_setup_connection(ev, server_socket, sock, t, getpid());
|
||||
conn = server_setup_connection(ev, stream_socket, sock, t, getpid());
|
||||
if (!conn) {
|
||||
DEBUG(0,("server_setup_connection(ev, server_socket, sock, t) failed\n"));
|
||||
exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
talloc_steal(conn, sock);
|
||||
|
||||
DLIST_ADD(server_socket->connection_list,conn);
|
||||
|
||||
/* return to the event loop */
|
||||
}
|
||||
|
||||
@ -103,7 +108,7 @@ static void standard_terminate_connection(struct server_connection *conn, const
|
||||
DEBUG(2,("standard_terminate_connection: reason[%s]\n",reason));
|
||||
|
||||
if (conn) {
|
||||
talloc_free(conn->service->srv_ctx);
|
||||
talloc_free(conn->stream_socket->service->server);
|
||||
}
|
||||
|
||||
/* this init_iconv() has the effect of freeing the iconv context memory,
|
||||
@ -117,38 +122,94 @@ static void standard_terminate_connection(struct server_connection *conn, const
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int standard_get_id(struct smbsrv_request *req)
|
||||
/*
|
||||
called to create a new event context for a new task
|
||||
*/
|
||||
static void standard_create_task(struct server_task *task)
|
||||
{
|
||||
return (int)req->smb_conn->pid;
|
||||
pid_t pid;
|
||||
|
||||
pid = fork();
|
||||
|
||||
if (pid != 0) {
|
||||
/* parent or error code ... */
|
||||
talloc_free(task);
|
||||
/* go back to the event loop */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Child code ... */
|
||||
|
||||
/* close all the listening sockets */
|
||||
event_remove_fd_all_handler(task->service->server->event.ctx, server_accept_handler);
|
||||
|
||||
/* tdb needs special fork handling */
|
||||
if (tdb_reopen_all() == -1) {
|
||||
DEBUG(0,("standard_accept_connection: tdb_reopen_all failed.\n"));
|
||||
}
|
||||
|
||||
/* Ensure that the forked children do not expose identical random streams */
|
||||
|
||||
set_need_random_reseed();
|
||||
|
||||
task->task.id = (uint32)getpid();
|
||||
task->event.ctx = task->service->server->event.ctx;
|
||||
|
||||
/* setup to receive internal messages on this connection */
|
||||
task->messaging.ctx = messaging_init(task, task->task.id, task->event.ctx);
|
||||
if (!task->messaging.ctx) {
|
||||
server_terminate_task(task, "messaging_init() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
task->task.ops->task_init(task);
|
||||
|
||||
server_terminate_task(task, "exit");
|
||||
return;
|
||||
}
|
||||
|
||||
static void standard_exit_server(struct server_context *srv_ctx, const char *reason)
|
||||
/*
|
||||
called to destroy a new event context for a new task
|
||||
*/
|
||||
static void standard_terminate_task(struct server_task *task, const char *reason)
|
||||
{
|
||||
DEBUG(1,("standard_exit_server: reason[%s]\n",reason));
|
||||
DEBUG(2,("standard_terminate_task: reason[%s]\n",reason));
|
||||
|
||||
talloc_free(task);
|
||||
|
||||
/* this init_iconv() has the effect of freeing the iconv context memory,
|
||||
which makes leak checking easier */
|
||||
init_iconv();
|
||||
|
||||
/* the secrets db should really hang off the connection structure */
|
||||
secrets_shutdown();
|
||||
|
||||
/* terminate this process */
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static const struct model_ops standard_ops = {
|
||||
.name = "standard",
|
||||
|
||||
.model_init = standard_model_init,
|
||||
.model_exit = standard_model_exit,
|
||||
|
||||
.accept_connection = standard_accept_connection,
|
||||
.terminate_connection = standard_terminate_connection,
|
||||
|
||||
.create_task = standard_create_task,
|
||||
.terminate_task = standard_terminate_task
|
||||
};
|
||||
|
||||
/*
|
||||
initialise the standard process model, registering ourselves with the process model subsystem
|
||||
*/
|
||||
NTSTATUS process_model_standard_init(void)
|
||||
{
|
||||
NTSTATUS ret;
|
||||
struct model_ops ops;
|
||||
|
||||
ZERO_STRUCT(ops);
|
||||
|
||||
/* fill in our name */
|
||||
ops.name = "standard";
|
||||
|
||||
/* fill in all the operations */
|
||||
ops.model_startup = standard_model_startup;
|
||||
ops.accept_connection = standard_accept_connection;
|
||||
ops.terminate_connection = standard_terminate_connection;
|
||||
ops.exit_server = standard_exit_server;
|
||||
ops.get_id = standard_get_id;
|
||||
|
||||
/* register ourselves with the PROCESS_MODEL subsystem. */
|
||||
ret = register_process_model(&ops);
|
||||
ret = register_process_model(&standard_ops);
|
||||
if (!NT_STATUS_IS_OK(ret)) {
|
||||
DEBUG(0,("Failed to register process_model 'standard'!\n"));
|
||||
return ret;
|
||||
|
@ -33,9 +33,12 @@
|
||||
|
||||
static void *thread_connection_fn(void *thread_parm)
|
||||
{
|
||||
struct event_context *ev = thread_parm;
|
||||
struct server_connection *conn = thread_parm;
|
||||
|
||||
conn->connection.id = pthread_self();
|
||||
|
||||
/* wait for action */
|
||||
event_loop_wait(ev);
|
||||
event_loop_wait(conn->event.ctx);
|
||||
|
||||
#if 0
|
||||
pthread_cleanup_pop(1); /* will invoke terminate_mt_connection() */
|
||||
@ -43,11 +46,6 @@ static void *thread_connection_fn(void *thread_parm)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int thread_get_id(struct smbsrv_request *req)
|
||||
{
|
||||
return (int)pthread_self();
|
||||
}
|
||||
|
||||
/*
|
||||
called when a listening socket becomes readable
|
||||
*/
|
||||
@ -59,15 +57,15 @@ static void thread_accept_connection(struct event_context *ev, struct fd_event *
|
||||
int rc;
|
||||
pthread_t thread_id;
|
||||
pthread_attr_t thread_attr;
|
||||
struct server_socket *server_socket = srv_fde->private;
|
||||
struct server_stream_socket *stream_socket = srv_fde->private;
|
||||
struct server_connection *conn;
|
||||
|
||||
/* accept an incoming connection. */
|
||||
status = socket_accept(server_socket->socket, &sock);
|
||||
status = socket_accept(stream_socket->socket, &sock);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* create new detached thread for this connection. The new
|
||||
thread gets a new event_context with a single fd_event for
|
||||
receiving from the new socket. We set that thread running
|
||||
@ -75,13 +73,13 @@ static void thread_accept_connection(struct event_context *ev, struct fd_event *
|
||||
main event_context is continued.
|
||||
*/
|
||||
|
||||
ev = event_context_init(server_socket);
|
||||
ev = event_context_init(stream_socket);
|
||||
if (!ev) {
|
||||
socket_destroy(sock);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
conn = server_setup_connection(ev, server_socket, sock, t, pthread_self());
|
||||
conn = server_setup_connection(ev, stream_socket, sock, t, -1);
|
||||
if (!conn) {
|
||||
event_context_destroy(ev);
|
||||
socket_destroy(sock);
|
||||
@ -91,16 +89,9 @@ static void thread_accept_connection(struct event_context *ev, struct fd_event *
|
||||
talloc_steal(conn, ev);
|
||||
talloc_steal(conn, sock);
|
||||
|
||||
/* TODO: is this MUTEX_LOCK in the right place here?
|
||||
* --metze
|
||||
*/
|
||||
MUTEX_LOCK_BY_ID(MUTEX_SMBD);
|
||||
DLIST_ADD(server_socket->connection_list,conn);
|
||||
MUTEX_UNLOCK_BY_ID(MUTEX_SMBD);
|
||||
|
||||
pthread_attr_init(&thread_attr);
|
||||
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
|
||||
rc = pthread_create(&thread_id, &thread_attr, thread_connection_fn, ev);
|
||||
rc = pthread_create(&thread_id, &thread_attr, thread_connection_fn, conn);
|
||||
pthread_attr_destroy(&thread_attr);
|
||||
if (rc == 0) {
|
||||
DEBUG(4,("accept_connection_thread: created thread_id=%lu for fd=%d\n",
|
||||
@ -414,7 +405,7 @@ static void thread_fault_handler(int sig)
|
||||
/*
|
||||
called when the process model is selected
|
||||
*/
|
||||
static void thread_model_startup(void)
|
||||
static void thread_model_init(struct server_context *server)
|
||||
{
|
||||
struct mutex_ops m_ops;
|
||||
struct debug_ops d_ops;
|
||||
@ -422,8 +413,6 @@ static void thread_model_startup(void)
|
||||
ZERO_STRUCT(m_ops);
|
||||
ZERO_STRUCT(d_ops);
|
||||
|
||||
smbd_process_init();
|
||||
|
||||
/* register mutex/rwlock handlers */
|
||||
m_ops.mutex_init = thread_mutex_init;
|
||||
m_ops.mutex_lock = thread_mutex_lock;
|
||||
@ -448,33 +437,100 @@ static void thread_model_startup(void)
|
||||
register_debug_handlers("thread", &d_ops);
|
||||
}
|
||||
|
||||
static void thread_exit_server(struct server_context *srv_ctx, const char *reason)
|
||||
static void thread_model_exit(struct server_context *server, const char *reason)
|
||||
{
|
||||
DEBUG(1,("thread_exit_server: reason[%s]\n",reason));
|
||||
DEBUG(1,("thread_model_exit: reason[%s]\n",reason));
|
||||
talloc_free(server);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void *thread_task_fn(void *thread_parm)
|
||||
{
|
||||
struct server_task *task = thread_parm;
|
||||
|
||||
task->task.id = pthread_self();
|
||||
|
||||
task->event.ctx = event_context_init(task);
|
||||
if (!task->event.ctx) {
|
||||
server_terminate_task(task, "event_context_init() failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
task->messaging.ctx = messaging_init(task, task->task.id, task->event.ctx);
|
||||
if (!task->messaging.ctx) {
|
||||
server_terminate_task(task, "messaging_init() failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
task->task.ops->task_init(task);
|
||||
|
||||
/* wait for action */
|
||||
event_loop_wait(task->event.ctx);
|
||||
|
||||
server_terminate_task(task, "exit");
|
||||
#if 0
|
||||
pthread_cleanup_pop(1); /* will invoke terminate_mt_connection() */
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
called to create a new event context for a new task
|
||||
*/
|
||||
static void thread_create_task(struct server_task *task)
|
||||
{
|
||||
int rc;
|
||||
pthread_t thread_id;
|
||||
pthread_attr_t thread_attr;
|
||||
|
||||
pthread_attr_init(&thread_attr);
|
||||
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
|
||||
rc = pthread_create(&thread_id, &thread_attr, thread_task_fn, task);
|
||||
pthread_attr_destroy(&thread_attr);
|
||||
if (rc == 0) {
|
||||
DEBUG(4,("thread_create_task: created thread_id=%lu for task='%s'\n",
|
||||
(unsigned long int)thread_id, task->task.ops->name));
|
||||
} else {
|
||||
DEBUG(0,("thread_create_task: thread create failed for task='%s', rc=%d\n", task->task.ops->name, rc));
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
called to destroy a new event context for a new task
|
||||
*/
|
||||
static void thread_terminate_task(struct server_task *task, const char *reason)
|
||||
{
|
||||
DEBUG(2,("thread_terminate_task: reason[%s]\n",reason));
|
||||
|
||||
talloc_free(task);
|
||||
|
||||
/* terminate this thread */
|
||||
pthread_exit(NULL); /* thread cleanup routine will do actual cleanup */
|
||||
}
|
||||
|
||||
static const struct model_ops thread_ops = {
|
||||
.name = "thread",
|
||||
|
||||
.model_init = thread_model_init,
|
||||
.model_exit = thread_model_exit,
|
||||
|
||||
.accept_connection = thread_accept_connection,
|
||||
.terminate_connection = thread_terminate_connection,
|
||||
|
||||
.create_task = thread_create_task,
|
||||
.terminate_task = thread_terminate_task
|
||||
};
|
||||
|
||||
/*
|
||||
initialise the thread process model, registering ourselves with the model subsystem
|
||||
*/
|
||||
NTSTATUS process_model_thread_init(void)
|
||||
{
|
||||
NTSTATUS ret;
|
||||
struct model_ops ops;
|
||||
|
||||
ZERO_STRUCT(ops);
|
||||
|
||||
/* fill in our name */
|
||||
ops.name = "thread";
|
||||
|
||||
/* fill in all the operations */
|
||||
ops.model_startup = thread_model_startup;
|
||||
ops.accept_connection = thread_accept_connection;
|
||||
ops.terminate_connection = thread_terminate_connection;
|
||||
ops.exit_server = thread_exit_server;
|
||||
ops.get_id = thread_get_id;
|
||||
|
||||
/* register ourselves with the PROCESS_MODEL subsystem. */
|
||||
ret = register_process_model(&ops);
|
||||
ret = register_process_model(&thread_ops);
|
||||
if (!NT_STATUS_IS_OK(ret)) {
|
||||
DEBUG(0,("Failed to register process_model 'thread'!\n"));
|
||||
return ret;
|
||||
|
@ -1,14 +1,6 @@
|
||||
#include "includes.h"
|
||||
#include "dynconfig.h"
|
||||
|
||||
/*
|
||||
|
||||
this is a set of temporary stub functions used during the core smbd rewrite.
|
||||
This file will need to go away before the rewrite is complete
|
||||
*/
|
||||
|
||||
BOOL pcap_printername_ok(const char *service, const char *foo)
|
||||
{ return True; }
|
||||
|
||||
/*
|
||||
* initialize an smb process. Guaranteed to be called only once per
|
||||
|
@ -24,12 +24,6 @@
|
||||
#include "includes.h"
|
||||
#include "lib/cmdline/popt_common.h"
|
||||
|
||||
static void exit_server(const char *reason)
|
||||
{
|
||||
DEBUG(3,("Server exit (%s)\n", (reason ? reason : "")));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
main server.
|
||||
****************************************************************************/
|
||||
@ -41,10 +35,10 @@ static int binary_smbd_main(int argc,const char *argv[])
|
||||
BOOL log_stdout = False;
|
||||
int opt;
|
||||
poptContext pc;
|
||||
struct server_context *srv_ctx;
|
||||
struct server_context *server;
|
||||
const char *model = "standard";
|
||||
struct poptOption long_options[] = {
|
||||
POPT_AUTOHELP
|
||||
POPT_AUTOHELP
|
||||
POPT_COMMON_SAMBA
|
||||
{"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon (default)" , NULL },
|
||||
{"interactive", 'i', POPT_ARG_VAL, &interactive, True, "Run interactive (not a daemon)", NULL},
|
||||
@ -52,6 +46,7 @@ static int binary_smbd_main(int argc,const char *argv[])
|
||||
{"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout", NULL },
|
||||
{"port", 'p', POPT_ARG_STRING, NULL, 0, "Listen on the specified ports", "PORTS"},
|
||||
{"model", 'M', POPT_ARG_STRING, &model, True, "Select process model", "MODEL"},
|
||||
POPT_COMMON_VERSION
|
||||
POPT_TABLEEND
|
||||
};
|
||||
|
||||
@ -77,7 +72,7 @@ static int binary_smbd_main(int argc,const char *argv[])
|
||||
}
|
||||
setup_logging(argv[0], log_stdout?DEBUG_STDOUT:DEBUG_FILE);
|
||||
|
||||
fault_setup((void (*)(void *))exit_server);
|
||||
fault_setup(NULL);
|
||||
|
||||
/* we are never interested in SIGPIPE */
|
||||
BlockSignals(True,SIGPIPE);
|
||||
@ -105,7 +100,7 @@ static int binary_smbd_main(int argc,const char *argv[])
|
||||
reopen_logs();
|
||||
|
||||
DEBUG(0,("smbd version %s started.\n", SAMBA_VERSION_STRING));
|
||||
DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2004\n"));
|
||||
DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2005\n"));
|
||||
|
||||
if (sizeof(uint16_t) < 2 || sizeof(uint32_t) < 4 || sizeof(uint64_t) < 8) {
|
||||
DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
|
||||
@ -142,15 +137,21 @@ static int binary_smbd_main(int argc,const char *argv[])
|
||||
|
||||
init_subsystems();
|
||||
|
||||
smbd_process_init();
|
||||
|
||||
DEBUG(0,("Using %s process model\n", model));
|
||||
srv_ctx = server_service_startup(model);
|
||||
if (!srv_ctx) {
|
||||
server = server_service_startup(model, lp_server_services());
|
||||
if (!server) {
|
||||
DEBUG(0,("Starting Services failed.\n"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* wait for events */
|
||||
return event_loop_wait(srv_ctx->events);
|
||||
event_loop_wait(server->event.ctx);
|
||||
|
||||
server_service_shutdown(server, "exit");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
|
@ -25,8 +25,15 @@ struct server_service;
|
||||
struct event_context;
|
||||
|
||||
struct server_context {
|
||||
struct {
|
||||
struct event_context *ctx;
|
||||
} event;
|
||||
|
||||
struct {
|
||||
const struct model_ops *ops;
|
||||
} model;
|
||||
|
||||
struct server_service *service_list;
|
||||
struct event_context *events;
|
||||
};
|
||||
|
||||
/* size of listen() backlog in smbd */
|
||||
|
@ -27,38 +27,33 @@
|
||||
#include "dlinklist.h"
|
||||
#include "process_model.h"
|
||||
|
||||
struct server_context *server_service_startup(const char *model)
|
||||
struct server_context *server_service_startup(const char *model, const char **server_services)
|
||||
{
|
||||
int i;
|
||||
const char **server_services = lp_server_services();
|
||||
struct server_context *srv_ctx;
|
||||
const struct model_ops *model_ops;
|
||||
struct server_context *server;
|
||||
|
||||
if (!server_services) {
|
||||
DEBUG(0,("process_model_startup: no endpoint servers configured\n"));
|
||||
DEBUG(0,("server_service_startup: no endpoint servers configured\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
model_ops = process_model_startup(model);
|
||||
if (!model_ops) {
|
||||
server = talloc_zero(NULL, struct server_context);
|
||||
if (!server) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
server->model.ops = process_model_startup(server, model);
|
||||
if (!server->model.ops) {
|
||||
DEBUG(0,("process_model_startup('%s') failed\n", model));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
srv_ctx = talloc_p(NULL, struct server_context);
|
||||
if (!srv_ctx) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZERO_STRUCTP(srv_ctx);
|
||||
|
||||
srv_ctx->events = event_context_init(srv_ctx);
|
||||
if (!srv_ctx->events) {
|
||||
server->event.ctx = event_context_init(server);
|
||||
if (!server->event.ctx) {
|
||||
DEBUG(0,("event_context_init() failed\n"));
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
for (i=0;server_services[i];i++) {
|
||||
const struct server_service_ops *service_ops;
|
||||
struct server_service *service;
|
||||
@ -69,63 +64,64 @@ struct server_context *server_service_startup(const char *model)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
service = talloc_p(srv_ctx, struct server_service);
|
||||
service = talloc_zero(server, struct server_service);
|
||||
if (!service) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZERO_STRUCTP(service);
|
||||
service->ops = service_ops;
|
||||
service->model_ops = model_ops;
|
||||
service->srv_ctx = srv_ctx;
|
||||
|
||||
/* TODO: service_init() should return a result */
|
||||
service->ops->service_init(service, model_ops);
|
||||
service->service.ops = service_ops;
|
||||
service->server = server;
|
||||
|
||||
DLIST_ADD(srv_ctx->service_list, service);
|
||||
/* TODO: service_init() should return a result */
|
||||
service->service.ops->service_init(service);
|
||||
|
||||
DLIST_ADD(server->service_list, service);
|
||||
}
|
||||
|
||||
return srv_ctx;
|
||||
return server;
|
||||
}
|
||||
|
||||
void server_service_shutdown(struct server_context *server, const char *reason)
|
||||
{
|
||||
server->model.ops->model_exit(server, reason);
|
||||
}
|
||||
|
||||
/*
|
||||
setup a listen stream socket
|
||||
if you pass *port == 0, then a port > 1024 is used
|
||||
*/
|
||||
struct server_socket *service_setup_socket(struct server_service *service,
|
||||
const struct model_ops *model_ops,
|
||||
const char *family,
|
||||
const char *sock_addr,
|
||||
uint16_t *port)
|
||||
struct server_stream_socket *service_setup_stream_socket(struct server_service *service,
|
||||
const struct server_stream_ops *stream_ops,
|
||||
const char *family,
|
||||
const char *sock_addr,
|
||||
uint16_t *port)
|
||||
{
|
||||
NTSTATUS status;
|
||||
struct server_socket *srv_sock;
|
||||
struct socket_context *socket_ctx;
|
||||
struct server_stream_socket *stream_socket;
|
||||
struct socket_context *sock;
|
||||
struct fd_event fde;
|
||||
int i;
|
||||
|
||||
status = socket_create(family, SOCKET_TYPE_STREAM, &socket_ctx, 0);
|
||||
status = socket_create(family, SOCKET_TYPE_STREAM, &sock, 0);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0,("Failed to open socket on %s:%u - %s\n",
|
||||
sock_addr, *port, nt_errstr(status)));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
talloc_steal(service, socket_ctx);
|
||||
|
||||
/* ready to listen */
|
||||
status = socket_set_option(socket_ctx, "SO_KEEPALIVE SO_REUSEADDR=1", NULL);
|
||||
status = socket_set_option(sock, "SO_KEEPALIVE SO_REUSEADDR=1", NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0,("socket_set_option(socket_ctx, SO_KEEPALIVE, NULL): %s\n",
|
||||
nt_errstr(status)));
|
||||
socket_destroy(socket_ctx);
|
||||
socket_destroy(sock);
|
||||
return NULL;
|
||||
}
|
||||
status = socket_set_option(socket_ctx, lp_socket_options(), NULL);
|
||||
status = socket_set_option(sock, lp_socket_options(), NULL);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0,("socket_set_option(socket_ctx, lp_socket_options(), NULL): %s\n",
|
||||
nt_errstr(status)));
|
||||
socket_destroy(socket_ctx);
|
||||
socket_destroy(sock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -133,64 +129,70 @@ struct server_socket *service_setup_socket(struct server_service *service,
|
||||
|
||||
if (*port == 0) {
|
||||
for (i=SERVER_TCP_LOW_PORT;i<= SERVER_TCP_HIGH_PORT;i++) {
|
||||
status = socket_listen(socket_ctx, sock_addr, i, SERVER_LISTEN_BACKLOG, 0);
|
||||
status = socket_listen(sock, sock_addr, i, SERVER_LISTEN_BACKLOG, 0);
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
*port = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
status = socket_listen(socket_ctx, sock_addr, *port, SERVER_LISTEN_BACKLOG, 0);
|
||||
status = socket_listen(sock, sock_addr, *port, SERVER_LISTEN_BACKLOG, 0);
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(0,("Failed to listen on %s:%u - %s\n",
|
||||
sock_addr, *port, nt_errstr(status)));
|
||||
socket_destroy(socket_ctx);
|
||||
socket_destroy(sock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
srv_sock = talloc_p(service, struct server_socket);
|
||||
if (!srv_sock) {
|
||||
DEBUG(0,("talloc_p(mem_ctx, struct server_socket) failed\n"));
|
||||
socket_destroy(socket_ctx);
|
||||
stream_socket = talloc_zero(service, struct server_stream_socket);
|
||||
if (!stream_socket) {
|
||||
DEBUG(0,("talloc_p(mem_ctx, struct server_stream_socket) failed\n"));
|
||||
socket_destroy(sock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* we are only interested in read events on the listen socket */
|
||||
fde.fd = socket_get_fd(socket_ctx);
|
||||
fde.fd = socket_get_fd(sock);
|
||||
fde.flags = EVENT_FD_READ;
|
||||
fde.private = srv_sock;
|
||||
fde.handler = model_ops->accept_connection;
|
||||
fde.private = stream_socket;
|
||||
fde.handler = server_accept_handler;
|
||||
|
||||
ZERO_STRUCTP(srv_sock);
|
||||
srv_sock->service = service;
|
||||
srv_sock->socket = socket_ctx;
|
||||
srv_sock->event.ctx = service->srv_ctx->events;
|
||||
srv_sock->event.fde = event_add_fd(srv_sock->event.ctx, &fde);
|
||||
if (!srv_sock->event.fde) {
|
||||
DEBUG(0,("event_add_fd(srv_sock->event.ctx, &fde) failed\n"));
|
||||
socket_destroy(socket_ctx);
|
||||
stream_socket->stream.ops = stream_ops;
|
||||
stream_socket->service = service;
|
||||
stream_socket->socket = sock;
|
||||
stream_socket->event.ctx = service->server->event.ctx;
|
||||
stream_socket->event.fde = event_add_fd(stream_socket->event.ctx, &fde);
|
||||
if (!stream_socket->event.fde) {
|
||||
DEBUG(0,("event_add_fd(stream_socket->event.ctx, &fde) failed\n"));
|
||||
socket_destroy(sock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DLIST_ADD(service->socket_list, srv_sock);
|
||||
talloc_steal(stream_socket, sock);
|
||||
|
||||
return srv_sock;
|
||||
if (stream_socket->stream.ops->socket_init) {
|
||||
stream_socket->stream.ops->socket_init(stream_socket);
|
||||
}
|
||||
|
||||
return stream_socket;
|
||||
}
|
||||
|
||||
/*
|
||||
destructor that handles necessary event context changes
|
||||
*/
|
||||
static int server_destructor(void *ptr)
|
||||
static int server_connection_destructor(void *ptr)
|
||||
{
|
||||
struct server_connection *conn = ptr;
|
||||
|
||||
if (conn->service) {
|
||||
conn->service->ops->close_connection(conn, "shutdown");
|
||||
}
|
||||
|
||||
socket_destroy(conn->socket);
|
||||
if (conn->stream_socket &&
|
||||
conn->stream_socket->stream.ops->close_connection) {
|
||||
/* don't remove this! the stream service needs to free it's data
|
||||
* before we destroy the server_connection
|
||||
*/
|
||||
conn->stream_socket->stream.ops->close_connection(conn, "shutdown");
|
||||
}
|
||||
|
||||
if (conn->event.fde) {
|
||||
event_remove_fd(conn->event.ctx, conn->event.fde);
|
||||
@ -201,13 +203,11 @@ static int server_destructor(void *ptr)
|
||||
conn->event.idle = NULL;
|
||||
}
|
||||
|
||||
DLIST_REMOVE(conn->server_socket->connection_list, conn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct server_connection *server_setup_connection(struct event_context *ev,
|
||||
struct server_socket *server_socket,
|
||||
struct server_stream_socket *stream_socket,
|
||||
struct socket_context *sock,
|
||||
struct timeval t,
|
||||
servid_t server_id)
|
||||
@ -216,7 +216,7 @@ struct server_connection *server_setup_connection(struct event_context *ev,
|
||||
struct timed_event idle;
|
||||
struct server_connection *srv_conn;
|
||||
|
||||
srv_conn = talloc_p(server_socket, struct server_connection);
|
||||
srv_conn = talloc_p(stream_socket, struct server_connection);
|
||||
if (!srv_conn) {
|
||||
DEBUG(0,("talloc_p(mem_ctx, struct server_connection) failed\n"));
|
||||
return NULL;
|
||||
@ -238,20 +238,19 @@ struct server_connection *server_setup_connection(struct event_context *ev,
|
||||
srv_conn->event.idle = &idle;
|
||||
srv_conn->event.idle_time = timeval_set(SERVER_DEFAULT_IDLE_TIME, 0);
|
||||
|
||||
srv_conn->server_socket = server_socket;
|
||||
srv_conn->service = server_socket->service;
|
||||
srv_conn->stream_socket = stream_socket;
|
||||
srv_conn->socket = sock;
|
||||
srv_conn->server_id = server_id;
|
||||
srv_conn->connection.id = server_id;
|
||||
|
||||
/* create a server context and add it to out event
|
||||
handling */
|
||||
server_socket->service->ops->accept_connection(srv_conn);
|
||||
stream_socket->stream.ops->accept_connection(srv_conn);
|
||||
|
||||
/* accpect_connection() of the service may changed idle.next_event */
|
||||
srv_conn->event.fde = event_add_fd(ev,&fde);
|
||||
srv_conn->event.idle = event_add_timed(ev,&idle);
|
||||
|
||||
talloc_set_destructor(srv_conn, server_destructor);
|
||||
talloc_set_destructor(srv_conn, server_connection_destructor);
|
||||
|
||||
if (!socket_check_access(sock, "smbd", lp_hostsallow(-1), lp_hostsdeny(-1))) {
|
||||
server_terminate_connection(srv_conn, "denied by access rules");
|
||||
@ -259,7 +258,11 @@ struct server_connection *server_setup_connection(struct event_context *ev,
|
||||
}
|
||||
|
||||
/* setup to receive internal messages on this connection */
|
||||
srv_conn->messaging_ctx = messaging_init(srv_conn, srv_conn->server_id, ev);
|
||||
srv_conn->messaging.ctx = messaging_init(srv_conn, srv_conn->connection.id, ev);
|
||||
if (!srv_conn->messaging.ctx) {
|
||||
server_terminate_connection(srv_conn, "messaging_init() failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return srv_conn;
|
||||
}
|
||||
@ -270,7 +273,15 @@ struct server_connection *server_setup_connection(struct event_context *ev,
|
||||
void server_terminate_connection(struct server_connection *srv_conn, const char *reason)
|
||||
{
|
||||
DEBUG(2,("server_terminate_connection\n"));
|
||||
srv_conn->service->model_ops->terminate_connection(srv_conn, reason);
|
||||
srv_conn->stream_socket->service->server->model.ops->terminate_connection(srv_conn, reason);
|
||||
}
|
||||
|
||||
void server_accept_handler(struct event_context *ev, struct fd_event *fde,
|
||||
struct timeval t, uint16_t flags)
|
||||
{
|
||||
struct server_stream_socket *stream_socket = fde->private;
|
||||
|
||||
stream_socket->service->server->model.ops->accept_connection(ev, fde, t, flags);
|
||||
}
|
||||
|
||||
void server_io_handler(struct event_context *ev, struct fd_event *fde,
|
||||
@ -281,12 +292,12 @@ void server_io_handler(struct event_context *ev, struct fd_event *fde,
|
||||
conn->event.idle->next_event = timeval_sum(&t, &conn->event.idle_time);
|
||||
|
||||
if (flags & EVENT_FD_WRITE) {
|
||||
conn->service->ops->send_handler(conn, t, flags);
|
||||
conn->stream_socket->stream.ops->send_handler(conn, t, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags & EVENT_FD_READ) {
|
||||
conn->service->ops->recv_handler(conn, t, flags);
|
||||
conn->stream_socket->stream.ops->recv_handler(conn, t, flags);
|
||||
}
|
||||
|
||||
}
|
||||
@ -296,13 +307,34 @@ void server_idle_handler(struct event_context *ev, struct timed_event *idle,
|
||||
{
|
||||
struct server_connection *conn = idle->private;
|
||||
|
||||
conn->event.idle->next_event = timeval_sum(&t, &conn->event.idle_time);
|
||||
|
||||
/* Not all services provide an idle handler */
|
||||
if (conn->service->ops->idle_handler) {
|
||||
conn->service->ops->idle_handler(conn, t);
|
||||
if (conn->stream_socket->stream.ops->idle_handler) {
|
||||
conn->event.idle->next_event = timeval_sum(&t, &conn->event.idle_time);
|
||||
conn->stream_socket->stream.ops->idle_handler(conn, t);
|
||||
}
|
||||
}
|
||||
|
||||
void server_terminate_task(struct server_task *task, const char *reason)
|
||||
{
|
||||
task->service->server->model.ops->terminate_task(task, reason);
|
||||
return;
|
||||
}
|
||||
|
||||
void server_run_task(struct server_service *service, const struct server_task_ops *ops)
|
||||
{
|
||||
struct server_task *task;
|
||||
|
||||
task = talloc_zero(service, struct server_task);
|
||||
if (!task) {
|
||||
return;
|
||||
}
|
||||
task->service = service;
|
||||
task->task.ops = ops;
|
||||
|
||||
service->server->model.ops->create_task(task);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
return the operations structure for a named backend of the specified type
|
||||
*/
|
||||
@ -325,25 +357,6 @@ NTSTATUS register_server_service_ops(const void *_ops)
|
||||
return NT_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/*
|
||||
close all listening sockets. This is called by process models that fork, to
|
||||
ensure that the listen sockets from the parent are closed
|
||||
*/
|
||||
void service_close_listening_sockets(struct server_context *srv_ctx)
|
||||
{
|
||||
struct server_service *svc;
|
||||
for (svc=srv_ctx->service_list;svc;svc=svc->next) {
|
||||
struct server_socket *sock;
|
||||
for (sock=svc->socket_list;sock;sock=sock->next) {
|
||||
event_remove_fd(sock->event.ctx, sock->event.fde);
|
||||
sock->event.fde = NULL;
|
||||
socket_destroy(sock->socket);
|
||||
sock->socket = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
cleanup temporary files. This is the new alternative to
|
||||
TDB_CLEAR_IF_FIRST. Unfortunately TDB_CLEAR_IF_FIRST is not
|
||||
|
@ -42,7 +42,17 @@ struct server_service_ops {
|
||||
const char *name;
|
||||
|
||||
/* called at startup when the server_service is selected */
|
||||
void (*service_init)(struct server_service *service, const struct model_ops *ops);
|
||||
void (*service_init)(struct server_service *service);
|
||||
};
|
||||
|
||||
struct server_stream_socket;
|
||||
|
||||
struct server_stream_ops {
|
||||
/* the name of the server_service */
|
||||
const char *name;
|
||||
|
||||
/* called at startup when the server_service is selected */
|
||||
void (*socket_init)(struct server_stream_socket *socket);
|
||||
|
||||
/* function to accept new connection */
|
||||
void (*accept_connection)(struct server_connection *);
|
||||
@ -56,16 +66,16 @@ struct server_service_ops {
|
||||
|
||||
/* function to close a connection */
|
||||
void (*close_connection)(struct server_connection *, const char *reason);
|
||||
|
||||
/* function to exit server */
|
||||
void (*service_exit)(struct server_service *srv_ctx, const char *reason);
|
||||
};
|
||||
|
||||
struct socket_context;
|
||||
|
||||
struct server_socket {
|
||||
struct server_socket *next,*prev;
|
||||
void *private_data;
|
||||
struct server_stream_socket {
|
||||
struct server_stream_socket *next,*prev;
|
||||
struct {
|
||||
const struct server_stream_ops *ops;
|
||||
void *private_data;
|
||||
} stream;
|
||||
|
||||
struct {
|
||||
struct event_context *ctx;
|
||||
@ -75,20 +85,16 @@ struct server_socket {
|
||||
struct socket_context *socket;
|
||||
|
||||
struct server_service *service;
|
||||
|
||||
struct server_connection *connection_list;
|
||||
};
|
||||
|
||||
struct server_service {
|
||||
struct server_service *next,*prev;
|
||||
void *private_data;
|
||||
const struct server_service_ops *ops;
|
||||
struct {
|
||||
const struct server_service_ops *ops;
|
||||
void *private_data;
|
||||
} service;
|
||||
|
||||
const struct model_ops *model_ops;
|
||||
|
||||
struct server_socket *socket_list;
|
||||
|
||||
struct server_context *srv_ctx;
|
||||
struct server_context *server;
|
||||
};
|
||||
|
||||
/* the concept of whether two operations are on the same server
|
||||
@ -106,7 +112,10 @@ typedef uint32_t servid_t;
|
||||
|
||||
struct server_connection {
|
||||
struct server_connection *next,*prev;
|
||||
void *private_data;
|
||||
struct {
|
||||
void *private_data;
|
||||
servid_t id;
|
||||
} connection;
|
||||
|
||||
struct {
|
||||
struct event_context *ctx;
|
||||
@ -115,15 +124,42 @@ struct server_connection {
|
||||
struct timeval idle_time;
|
||||
} event;
|
||||
|
||||
servid_t server_id;
|
||||
|
||||
struct socket_context *socket;
|
||||
|
||||
struct server_socket *server_socket;
|
||||
struct server_stream_socket *stream_socket;
|
||||
|
||||
struct {
|
||||
struct messaging_context *ctx;
|
||||
} messaging;
|
||||
};
|
||||
|
||||
struct server_task;
|
||||
|
||||
struct server_task_ops {
|
||||
/* the name of the server_task */
|
||||
const char *name;
|
||||
|
||||
/* called at startup when the server_task is selected */
|
||||
void (*task_init)(struct server_task *task);
|
||||
};
|
||||
|
||||
struct server_task {
|
||||
struct server_task *next,*prev;
|
||||
struct {
|
||||
const struct server_task_ops *ops;
|
||||
void *private_data;
|
||||
servid_t id;
|
||||
} task;
|
||||
|
||||
struct {
|
||||
struct event_context *ctx;
|
||||
} event;
|
||||
|
||||
struct {
|
||||
struct messaging_context *ctx;
|
||||
} messaging;
|
||||
|
||||
struct server_service *service;
|
||||
|
||||
struct messaging_context *messaging_ctx;
|
||||
};
|
||||
|
||||
#endif /* _SERVER_SERVICE_H */
|
||||
|
Loading…
Reference in New Issue
Block a user