]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3:rpc_client: remember the local/remote ipv4 or ipv6 addresses
authorStefan Metzmacher <metze@samba.org>
Tue, 1 Oct 2024 10:52:15 +0000 (12:52 +0200)
committerJule Anger <janger@samba.org>
Thu, 12 Jun 2025 11:27:15 +0000 (11:27 +0000)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
(cherry picked from commit b6123197d13b5350b8fc88e9c8d59f0f05c3aed6)

source3/rpc_client/cli_pipe.c

index d512dde386f6e11f41828a5eafef9a4988767734..188b7fe283859db91a2ecaeee7c9747704783951 100644 (file)
@@ -80,6 +80,7 @@ static NTSTATUS rpc_client_association_create(TALLOC_CTX *mem_ctx,
 {
        struct rpc_client_association *assoc = NULL;
        struct dcerpc_binding *bd = NULL;
+       char addrstr[INET6_ADDRSTRLEN] = { 0, };
        NTSTATUS status;
 
        assoc = talloc_zero(mem_ctx, struct rpc_client_association);
@@ -106,12 +107,29 @@ static NTSTATUS rpc_client_association_create(TALLOC_CTX *mem_ctx,
                TALLOC_FREE(assoc);
                return status;
        }
-       status = dcerpc_binding_set_string_option(bd,
-                                                 "host",
-                                                 target_hostname);
-       if (!NT_STATUS_IS_OK(status)) {
-               TALLOC_FREE(assoc);
-               return status;
+       switch (addr->u.sa.sa_family) {
+       case AF_INET:
+       case AF_INET6:
+               print_sockaddr(addrstr,
+                              sizeof(addrstr),
+                              &addr->u.ss);
+               status = dcerpc_binding_set_string_option(bd,
+                                                         "host",
+                                                         addrstr);
+               if (!NT_STATUS_IS_OK(status)) {
+                       TALLOC_FREE(assoc);
+                       return status;
+               }
+               break;
+       default:
+               status = dcerpc_binding_set_string_option(bd,
+                                                         "host",
+                                                         target_hostname);
+               if (!NT_STATUS_IS_OK(status)) {
+                       TALLOC_FREE(assoc);
+                       return status;
+               }
+               break;
        }
        status = dcerpc_binding_set_string_option(bd,
                                                  "target_hostname",
@@ -143,6 +161,7 @@ static NTSTATUS rpc_client_association_create(TALLOC_CTX *mem_ctx,
 struct rpc_client_connection {
        DATA_BLOB transport_session_key;
        struct rpc_cli_transport *transport;
+       struct samba_sockaddr localaddr;
 
        struct {
                uint16_t max_xmit_frag;
@@ -2749,6 +2768,7 @@ struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
        struct dcerpc_binding_handle *h = NULL;
        struct rpccli_bh_state *hs = NULL;
        struct dcerpc_binding *b = NULL;
+       char localaddr[INET6_ADDRSTRLEN] = { 0, };
        uint32_t a_flags = 0;
        uint32_t c_flags = 0;
        NTSTATUS status;
@@ -2838,6 +2858,22 @@ struct dcerpc_binding_handle *rpccli_bh_create(struct rpc_pipe_client *c,
                return NULL;
        }
 
+       switch (c->conn->localaddr.u.sa.sa_family) {
+       case AF_INET:
+       case AF_INET6:
+               print_sockaddr(localaddr,
+                              sizeof(localaddr),
+                              &c->conn->localaddr.u.ss);
+               status = dcerpc_binding_set_string_option(b,
+                                                         "localaddress",
+                                                         localaddr);
+               if (!NT_STATUS_IS_OK(status)) {
+                       TALLOC_FREE(h);
+                       return NULL;
+               }
+               break;
+       }
+
        hs->binding = b;
 
        return h;
@@ -3061,6 +3097,7 @@ static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx,
        uint16_t port;
        NTSTATUS status;
        int fd;
+       int ret;
 
        transport = dcerpc_binding_get_transport(assoc->binding);
        if (transport != NCACN_IP_TCP) {
@@ -3092,6 +3129,15 @@ static NTSTATUS rpc_pipe_open_tcp_port(TALLOC_CTX *mem_ctx,
        }
        set_socket_options(fd, lp_socket_options());
 
+       conn->localaddr.sa_socklen = sizeof(conn->localaddr.u.ss);
+       ret = getsockname(fd, &conn->localaddr.u.sa, &conn->localaddr.sa_socklen);
+       if (ret != 0) {
+               status = map_nt_error_from_unix_common(errno);
+               close(fd);
+               TALLOC_FREE(conn);
+               return status;
+       }
+
        status = rpc_transport_sock_init(conn, fd, &conn->transport);
        if (!NT_STATUS_IS_OK(status)) {
                close(fd);
@@ -3700,6 +3746,7 @@ static struct tevent_req *rpc_client_connection_np_send(
        struct rpc_client_connection_np_state *state = NULL;
        enum dcerpc_transport_t transport;
        const char *endpoint = NULL;
+       const struct sockaddr_storage *local_sockaddr = NULL;
        struct smbXcli_session *session = NULL;
        NTSTATUS status;
 
@@ -3730,6 +3777,9 @@ static struct tevent_req *rpc_client_connection_np_send(
                return tevent_req_post(req, ev);
        }
 
+       local_sockaddr = smbXcli_conn_local_sockaddr(cli->conn);
+       state->conn->localaddr.u.ss = *local_sockaddr;
+
        if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
                session = cli->smb2.session;
        } else {