summaryrefslogtreecommitdiff
path: root/source4/rpc_server/dcerpc_tcp.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2003-12-13 23:25:15 +0000
committerAndrew Tridgell <tridge@samba.org>2003-12-13 23:25:15 +0000
commitd262b8c3c79b2fbb0bf8c330d765f89210948a26 (patch)
tree0492a6fa66101b94f5dc368480c2ab027e4f8b77 /source4/rpc_server/dcerpc_tcp.c
parent8d79eb52f104d023122de3965592b4ea36adbb2b (diff)
downloadsamba-d262b8c3c79b2fbb0bf8c330d765f89210948a26.tar.gz
samba-d262b8c3c79b2fbb0bf8c330d765f89210948a26.tar.bz2
samba-d262b8c3c79b2fbb0bf8c330d765f89210948a26.zip
completed the linkage between the endpoint mapper and the dcerpc
server endpoints. We can now successfully setup listening endpoints on high ports, then use our endpoint mapper redirect incoming clients to the right port. also greatly cleanup the rpc over tcp session handling. (This used to be commit 593bc29bbe0e46d356d001160e8a3332a88f2fa8)
Diffstat (limited to 'source4/rpc_server/dcerpc_tcp.c')
-rw-r--r--source4/rpc_server/dcerpc_tcp.c189
1 files changed, 113 insertions, 76 deletions
diff --git a/source4/rpc_server/dcerpc_tcp.c b/source4/rpc_server/dcerpc_tcp.c
index 1f8230eb1c..8ea0605fb7 100644
--- a/source4/rpc_server/dcerpc_tcp.c
+++ b/source4/rpc_server/dcerpc_tcp.c
@@ -22,11 +22,36 @@
#include "includes.h"
-struct rpc_listen {
- struct dce_endpoint *e;
- struct model_ops *model_ops;
+struct rpc_server_context {
+ struct dcesrv_endpoint *endpoint;
+ const struct dcesrv_endpoint_ops *endpoint_ops;
+ const struct model_ops *model_ops;
+ struct dcesrv_state *dce;
+ struct dcesrv_context dcesrv_context;
+ int socket_fd;
+ struct event_context *events;
};
+/*
+ a callback from the process model termination routine
+*/
+void rpc_server_terminate(void *rr)
+{
+ struct rpc_server_context *r = rr;
+
+ dcesrv_endpoint_disconnect(r->dce);
+ close(r->socket_fd);
+ event_remove_fd_all(r->events, r->socket_fd);
+ free(r);
+}
+
+/*
+ called when a rpc session needs to be shutdown
+*/
+static void terminate_rpc_session(struct rpc_server_context *r, const char *reason)
+{
+ r->model_ops->terminate_rpc_connection(r, reason);
+}
/*
called when a RPC socket becomes writable
@@ -34,22 +59,26 @@ struct rpc_listen {
static void dcerpc_write_handler(struct event_context *ev, struct fd_event *fde,
time_t t, uint16 flags)
{
- struct dcesrv_state *dce = fde->private;
+ struct rpc_server_context *r = fde->private;
DATA_BLOB blob;
NTSTATUS status;
- blob = data_blob(NULL, 3);
+ blob = data_blob(NULL, 0x4000);
if (!blob.data) {
- smb_panic("out of memory in rpc write handler");
+ terminate_rpc_session(r, "out of memory");
+ return;
}
- status = dcesrv_output(dce, &blob);
- if (!NT_STATUS_IS_OK(status)) {
- fde->flags &= ~EVENT_FD_WRITE;
- } else {
+ status = dcesrv_output(r->dce, &blob);
+
+ if (NT_STATUS_IS_OK(status)) {
write_data(fde->fd, blob.data, blob.length);
}
+ if (!r->dce->call_list || !r->dce->call_list->replies) {
+ fde->flags &= ~EVENT_FD_WRITE;
+ }
+
data_blob_free(&blob);
}
@@ -59,31 +88,32 @@ static void dcerpc_write_handler(struct event_context *ev, struct fd_event *fde,
static void dcerpc_read_handler(struct event_context *ev, struct fd_event *fde,
time_t t, uint16 flags)
{
- struct dcesrv_state *dce = fde->private;
+ struct rpc_server_context *r = fde->private;
DATA_BLOB blob;
ssize_t ret;
- blob = data_blob(NULL, 3);
+ blob = data_blob(NULL, 0x4000);
if (!blob.data) {
- smb_panic("out of memory in rpc read handler");
+ terminate_rpc_session(r, "out of memory");
+ return;
}
ret = read(fde->fd, blob.data, blob.length);
- if (ret == 0) {
- smb_panic("need a shutdown routine");
- }
- if (ret == -1 && errno != EINTR) {
- smb_panic("need a shutdown routine");
+ if (ret == 0 || (ret == -1 && errno != EINTR)) {
+ terminate_rpc_session(r, "eof on socket");
+ return;
}
if (ret == -1) {
return;
}
- dcesrv_input(dce, &blob);
+ dcesrv_input(r->dce, &blob);
data_blob_free(&blob);
- fde->flags |= EVENT_FD_WRITE;
+ if (r->dce->call_list && r->dce->call_list->replies) {
+ fde->flags |= EVENT_FD_WRITE;
+ }
}
@@ -93,7 +123,7 @@ static void dcerpc_read_handler(struct event_context *ev, struct fd_event *fde,
called when a RPC socket becomes readable
*/
static void dcerpc_io_handler(struct event_context *ev, struct fd_event *fde,
- time_t t, uint16 flags)
+ time_t t, uint16 flags)
{
if (flags & EVENT_FD_WRITE) {
dcerpc_write_handler(ev, fde, t, flags);
@@ -110,25 +140,20 @@ static void dcerpc_io_handler(struct event_context *ev, struct fd_event *fde,
*/
void init_rpc_session(struct event_context *ev, void *private, int fd)
{
- struct dcesrv_context context;
- struct dcesrv_state *dce;
struct fd_event fde;
- struct rpc_listen *r = private;
- struct dcesrv_endpoint endpoint;
+ struct rpc_server_context *r = private;
- set_socket_options(fd,"SO_KEEPALIVE");
- set_socket_options(fd, lp_socket_options());
+ r = memdup(r, sizeof(struct rpc_server_context));
- context.endpoint_list = NULL;
- dcesrv_init(&context);
+ r->events = ev;
+ r->socket_fd = fd;
- endpoint.type = ENDPOINT_TCP;
- endpoint.info.tcp_port = 0;
+ set_socket_options(fd,"SO_KEEPALIVE");
+ set_socket_options(fd, lp_socket_options());
- dcesrv_endpoint_connect_ops(&context, &endpoint, r->e->endpoint_ops, &dce);
+ dcesrv_endpoint_connect_ops(&r->dcesrv_context, r->endpoint, r->endpoint_ops, &r->dce);
- dce->dce = talloc_p(dce->mem_ctx, struct dcesrv_context);
- *dce->dce = context;
+ r->dce->dce = &r->dcesrv_context;
set_blocking(fd, False);
@@ -136,7 +161,7 @@ void init_rpc_session(struct event_context *ev, void *private, int fd)
only interested in reading from the socket */
fde.fd = fd;
fde.handler = dcerpc_io_handler;
- fde.private = dce;
+ fde.private = r;
fde.flags = EVENT_FD_READ;
event_add_fd(ev, &fde);
@@ -148,38 +173,58 @@ void init_rpc_session(struct event_context *ev, void *private, int fd)
*/
static void setup_listen_rpc(struct event_context *events,
struct model_ops *model_ops,
- struct in_addr *ifip, unsigned port,
- struct dce_endpoint *e)
+ struct in_addr *ifip, uint32 *port,
+ struct rpc_server_context *r,
+ const struct dcesrv_endpoint_ops *endpoint_ops)
{
struct fd_event fde;
- struct rpc_listen *r;
+ int i;
+
+ if (*port == 0) {
+ fde.fd = -1;
+ for (i=DCERPC_TCP_LOW_PORT;i<= DCERPC_TCP_HIGH_PORT;i++) {
+ fde.fd = open_socket_in(SOCK_STREAM, i, 0, ifip->s_addr, True);
+ if (fde.fd != -1) break;
+ }
+ if (fde.fd != -1) {
+ *port = i;
+ }
+ } else {
+ fde.fd = open_socket_in(SOCK_STREAM, *port, 0, ifip->s_addr, True);
+ }
- fde.fd = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True);
if (fde.fd == -1) {
DEBUG(0,("Failed to open socket on %s:%u - %s\n",
- inet_ntoa(*ifip), port, strerror(errno)));
+ inet_ntoa(*ifip), *port, strerror(errno)));
return;
}
+ /* each listening socket has separate state, so must use a different context */
+ r = memdup(r, sizeof(struct rpc_server_context));
+ if (!r) {
+ smb_panic("out of memory");
+ }
+
+ r->endpoint_ops = endpoint_ops;
+
+ r->endpoint = malloc(sizeof(struct dcesrv_endpoint));
+ if (!r->endpoint) {
+ smb_panic("out of memory");
+ }
+ r->endpoint->type = ENDPOINT_TCP;
+ r->endpoint->info.tcp_port = *port;
+
/* ready to listen */
set_socket_options(fde.fd, "SO_KEEPALIVE");
set_socket_options(fde.fd, lp_socket_options());
if (listen(fde.fd, SMBD_LISTEN_BACKLOG) == -1) {
DEBUG(0,("Failed to listen on %s:%d - %s\n",
- inet_ntoa(*ifip), port, strerror(errno)));
+ inet_ntoa(*ifip), *port, strerror(errno)));
close(fde.fd);
return;
}
- r = malloc(sizeof(*r));
- if (!r) {
- return;
- }
-
- r->e = e;
- r->model_ops = model_ops;
-
/* we are only interested in read events on the listen socket */
fde.flags = EVENT_FD_READ;
fde.private = r;
@@ -195,37 +240,29 @@ static void add_socket_rpc(struct event_context *events,
struct model_ops *model_ops,
struct in_addr *ifip)
{
- struct dcesrv_context dce;
- TALLOC_CTX *mem_ctx;
-
- mem_ctx = talloc_init("add_socket_rpc");
- if (!mem_ctx) {
- smb_panic("out of memory in add_socket_rpc");
+ struct dce_endpoint *e;
+ struct rpc_server_context *r;
+
+ r = malloc(sizeof(struct rpc_server_context));
+ if (!r) {
+ smb_panic("out of memory");
}
+
+ r->dcesrv_context.endpoint_list = NULL;
+ dcesrv_init(&r->dcesrv_context);
+ r->endpoint = NULL;
+ r->model_ops = model_ops;
+ r->dce = NULL;
+ r->socket_fd = -1;
+ r->events = NULL;
- dce.endpoint_list = NULL;
-
- dcesrv_init(&dce);
-
- while (dce.endpoint_list) {
- struct dce_endpoint *e = dce.endpoint_list;
- struct dcesrv_ep_iface *ifaces;
- int count, i;
-
- count = e->endpoint_ops->lookup_endpoints(mem_ctx, &ifaces);
- for (i=0;i<count;i++) {
- if (ifaces[i].endpoint.type == ENDPOINT_TCP) {
- setup_listen_rpc(events, model_ops, ifip,
- ifaces[i].endpoint.info.tcp_port,
- e);
- break;
- }
+ for (e=r->dcesrv_context.endpoint_list;e;e=e->next) {
+ if (e->endpoint.type == ENDPOINT_TCP) {
+ setup_listen_rpc(events, model_ops, ifip,
+ &e->endpoint.info.tcp_port,
+ r, e->endpoint_ops);
}
-
- DLIST_REMOVE(dce.endpoint_list, e);
}
-
- talloc_destroy(mem_ctx);
}
/****************************************************************************