s4-librpc: do not limit to the first IP when trying to do a rpc connection
authorMatthieu Patou <mat@matws.net>
Thu, 10 Nov 2011 19:59:09 +0000 (20:59 +0100)
committerMatthieu Patou <mat@samba.org>
Fri, 11 Nov 2011 19:28:11 +0000 (20:28 +0100)
The function continue_ip_resolve_name was calling resolve_name_recv which returns
only the first IP for a given hostname.
Instead we use resolve_name_multiple_recv which returns all the IP for a given
hostname. This kind of problem can occur if a host has more than 1 IP but is listenning
only on 1.

source4/librpc/rpc/dcerpc_sock.c

index d0d28bc47e2d456447dcfe38245e904eb2d2c119..a291996f8ca2206283c0b174cdde57ec3bc6e990 100644 (file)
@@ -362,7 +362,8 @@ static NTSTATUS dcerpc_pipe_open_socket_recv(struct composite_context *c)
 struct pipe_tcp_state {
        const char *server;
        const char *target_hostname;
-       const char *address;
+       const char **addresses;
+       uint32_t index;
        uint32_t port;
        struct socket_address *localaddr;
        struct socket_address *srvaddr;
@@ -382,11 +383,12 @@ static void continue_ip_resolve_name(struct composite_context *ctx)
                                                   struct pipe_tcp_state);
        struct composite_context *sock_ip_req;
 
-       c->status = resolve_name_recv(ctx, s, &s->address);
+       c->status = resolve_name_multiple_recv(ctx, s, &s->addresses);
        if (!composite_is_ok(c)) return;
 
        /* prepare server address using host ip:port and transport name */
-       s->srvaddr = socket_address_from_strings(s->conn, "ip", s->address, s->port);
+       s->srvaddr = socket_address_from_strings(s->conn, "ip", s->addresses[s->index], s->port);
+       s->index++;
        if (composite_nomem(s->srvaddr, c)) return;
 
        sock_ip_req = dcerpc_pipe_open_socket_send(c, s->conn, s->localaddr,
@@ -413,11 +415,27 @@ static void continue_ip_open_socket(struct composite_context *ctx)
        if (!NT_STATUS_IS_OK(c->status)) {
                /* something went wrong... */
                DEBUG(0, ("Failed to connect host %s (%s) on port %d - %s.\n",
-                         s->address, s->target_hostname, 
+                         s->addresses[s->index - 1], s->target_hostname,
                          s->port, nt_errstr(c->status)));
-
-               composite_error(c, c->status);
-               return;
+               if (s->addresses[s->index]) {
+                       struct composite_context *sock_ip_req;
+                       talloc_free(s->srvaddr);
+                       /* prepare server address using host ip:port and transport name */
+                       s->srvaddr = socket_address_from_strings(s->conn, "ip", s->addresses[s->index], s->port);
+                       s->index++;
+                       if (composite_nomem(s->srvaddr, c)) return;
+
+                       sock_ip_req = dcerpc_pipe_open_socket_send(c, s->conn, s->localaddr,
+                                                               s->srvaddr, s->target_hostname,
+                                                               NULL,
+                                                               NCACN_IP_TCP);
+                       composite_continue(c, sock_ip_req, continue_ip_open_socket, c);
+
+                       return;
+               } else {
+                       composite_error(c, c->status);
+                       return;
+               }
        }
 
        composite_done(c);