summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafal Szczesniak <mimir@samba.org>2006-07-13 22:13:47 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:10:09 -0500
commit434087bb4baa14df503690cc05dc418b96fabe53 (patch)
tree4b4f729d3a5def04bd445a9461858aaf836cdfc8
parent440d0487a6ad9a39630d7364eb54e46367207d05 (diff)
downloadsamba-434087bb4baa14df503690cc05dc418b96fabe53.tar.gz
samba-434087bb4baa14df503690cc05dc418b96fabe53.tar.bz2
samba-434087bb4baa14df503690cc05dc418b96fabe53.zip
r17026: Make rpc connect routine a bit smarter. Try to connect again
using different transport and possibly address type, when the first attempt fails (only if it makes any sense, of course). This may be especially useful when connecting DCs and PDCs in mixed environments. Also, add monitor messages issuing. rafal (This used to be commit d69b31230dd01efadd9c0cc6ef31c794c6165881)
-rw-r--r--source4/libnet/libnet_rpc.c93
1 files changed, 86 insertions, 7 deletions
diff --git a/source4/libnet/libnet_rpc.c b/source4/libnet/libnet_rpc.c
index fce7811138..31d2b4dbf4 100644
--- a/source4/libnet/libnet_rpc.c
+++ b/source4/libnet/libnet_rpc.c
@@ -23,13 +23,16 @@
#include "libnet/libnet.h"
#include "libcli/libcli.h"
#include "libcli/composite/composite.h"
+#include "librpc/rpc/dcerpc.h"
#include "librpc/gen_ndr/ndr_lsa_c.h"
#include "librpc/gen_ndr/ndr_samr.h"
struct rpc_connect_srv_state {
+ struct libnet_context *ctx;
struct libnet_RpcConnect r;
const char *binding;
+ enum dcerpc_transport_t trans;
};
@@ -64,15 +67,21 @@ static struct composite_context* libnet_RpcConnectSrv_send(struct libnet_context
c->private_data = s;
c->event_ctx = ctx->event_ctx;
+ s->ctx = ctx;
s->r = *r;
ZERO_STRUCT(s->r.out);
/* prepare binding string */
switch (r->level) {
case LIBNET_RPC_CONNECT_DC:
+ s->binding = talloc_asprintf(s, "ncacn_ip_tcp:%s", r->in.name);
+ s->trans = NCACN_IP_TCP;
+ break;
+
case LIBNET_RPC_CONNECT_PDC:
case LIBNET_RPC_CONNECT_SERVER:
s->binding = talloc_asprintf(s, "ncacn_np:%s", r->in.name);
+ s->trans = NCACN_NP;
break;
case LIBNET_RPC_CONNECT_BINDING:
@@ -104,13 +113,45 @@ static void continue_pipe_connect(struct composite_context *ctx)
{
struct composite_context *c;
struct rpc_connect_srv_state *s;
+ struct composite_context *pipe_connect_req;
c = talloc_get_type(ctx->async.private_data, struct composite_context);
s = talloc_get_type(c->private_data, struct rpc_connect_srv_state);
/* receive result of rpc pipe connection */
c->status = dcerpc_pipe_connect_recv(ctx, c, &s->r.out.dcerpc_pipe);
- if (!composite_is_ok(c)) return;
+
+ if (NT_STATUS_EQUAL(c->status, NT_STATUS_IO_TIMEOUT)) {
+ switch (s->r.level) {
+ case LIBNET_RPC_CONNECT_DC:
+ if (s->trans == NCACN_IP_TCP) {
+ s->binding = talloc_asprintf(s, "ncacn_np:%s", s->r.in.name);
+ s->trans = NCACN_NP;
+ }
+ break;
+
+ case LIBNET_RPC_CONNECT_SERVER:
+ if (s->trans == NCACN_NP) {
+ s->binding = talloc_asprintf(s, "ncacn_ip_tcp:%s", s->r.in.name);
+ s->trans = NCACN_IP_TCP;
+ }
+ break;
+
+ default:
+ if (!composite_is_ok(c)) return;
+ s->r.out.error_string = NULL;
+ composite_done(c);
+ }
+
+ /* connect to remote dcerpc pipe */
+ pipe_connect_req = dcerpc_pipe_connect_send(c, &s->r.out.dcerpc_pipe,
+ s->binding, s->r.in.dcerpc_iface,
+ s->ctx->cred, c->event_ctx);
+ if (composite_nomem(pipe_connect_req, c)) return;
+
+ composite_continue(c, pipe_connect_req, continue_pipe_connect, c);
+ return;
+ }
s->r.out.error_string = NULL;
composite_done(c);
@@ -166,6 +207,9 @@ struct rpc_connect_dc_state {
struct libnet_RpcConnect r2;
struct libnet_LookupDCs f;
const char *connect_name;
+
+ /* information about the progress */
+ void (*monitor_fn)(struct monitor_msg *);
};
@@ -217,6 +261,7 @@ static struct composite_context* libnet_RpcConnectDC_send(struct libnet_context
default:
break;
}
+
s->f.in.domain_name = r->in.name;
s->f.out.num_dcs = 0;
s->f.out.dcs = NULL;
@@ -239,6 +284,8 @@ static void continue_lookup_dc(struct composite_context *ctx)
struct composite_context *c;
struct rpc_connect_dc_state *s;
struct composite_context *rpc_connect_req;
+ struct monitor_msg msg;
+ struct msg_net_lookup_dc data;
c = talloc_get_type(ctx->async.private_data, struct composite_context);
s = talloc_get_type(c->private_data, struct rpc_connect_dc_state);
@@ -247,15 +294,34 @@ static void continue_lookup_dc(struct composite_context *ctx)
c->status = libnet_LookupDCs_recv(ctx, c, &s->f);
if (!composite_is_ok(c)) return;
- /* we might not have got back a name. Fall back to the IP */
- if (s->f.out.dcs[0].name) {
+ /* decide on preferred address type depending on DC type */
+ switch (s->r.level) {
+ case LIBNET_RPC_CONNECT_PDC:
s->connect_name = s->f.out.dcs[0].name;
- } else {
+ break;
+
+ case LIBNET_RPC_CONNECT_DC:
s->connect_name = s->f.out.dcs[0].address;
+ break;
+
+ default:
+ /* we shouldn't absolutely get here */
+ composite_error(c, NT_STATUS_INVALID_LEVEL);
}
+ /* prepare a monitor message and post it */
+ msg.type = net_lookup_dc;
+ msg.data = &data;
+ msg.data_size = sizeof(data);
+
+ data.domain_name = s->f.in.domain_name;
+ data.hostname = s->f.out.dcs[0].name;
+ data.address = s->f.out.dcs[0].address;
+
+ if (s->monitor_fn) s->monitor_fn(&msg);
+
/* ok, pdc has been found so do attempt to rpc connect */
- s->r2.level = LIBNET_RPC_CONNECT_SERVER;
+ s->r2.level = s->r.level;
/* this will cause yet another name resolution, but at least
* we pass the right name down the stack now */
@@ -263,7 +329,7 @@ static void continue_lookup_dc(struct composite_context *ctx)
s->r2.in.dcerpc_iface = s->r.in.dcerpc_iface;
/* send rpc connect request to the server */
- rpc_connect_req = libnet_RpcConnect_send(s->ctx, c, &s->r2);
+ rpc_connect_req = libnet_RpcConnectSrv_send(s->ctx, c, &s->r2);
if (composite_nomem(rpc_connect_req, c)) return;
composite_continue(c, rpc_connect_req, continue_rpc_connect, c);
@@ -277,11 +343,13 @@ static void continue_rpc_connect(struct composite_context *ctx)
{
struct composite_context *c;
struct rpc_connect_dc_state *s;
+ struct monitor_msg msg;
+ struct msg_net_pipe_connected data;
c = talloc_get_type(ctx->async.private_data, struct composite_context);
s = talloc_get_type(c->private_data, struct rpc_connect_dc_state);
- c->status = libnet_RpcConnect_recv(ctx, s->ctx, c, &s->r2);
+ c->status = libnet_RpcConnectSrv_recv(ctx, s->ctx, c, &s->r2);
/* error string is to be passed anyway */
s->r.out.error_string = s->r2.out.error_string;
@@ -289,6 +357,17 @@ static void continue_rpc_connect(struct composite_context *ctx)
s->r.out.dcerpc_pipe = s->r2.out.dcerpc_pipe;
+ /* prepare a monitor message and post it */
+ msg.type = net_pipe_connected;
+ msg.data = NULL;
+ msg.data_size = 0;
+
+ data.host = s->r.out.dcerpc_pipe->binding->host;
+ data.endpoint = s->r.out.dcerpc_pipe->binding->endpoint;
+ data.transport = s->r.out.dcerpc_pipe->binding->transport;
+
+ if (s->monitor_fn) s->monitor_fn(&msg);
+
composite_done(c);
}