Trying to understand epmapper registration

Andreas Schneider asn at
Sat Mar 3 04:38:37 MST 2012

On Saturday 03 March 2012 21:44:55 Andrew Bartlett wrote:
> > Do you mean the table with the GUID, endpoint names, and on which
> > endpoints it should be available? I don't really get what you're talking
> > about and what the problem is :)
> I'm sorry, clearly I have not been specific enough.  To continue using
> dssetup as my example, here is the relevant fucntion in master:
> static bool rpc_setup_dssetup(struct tevent_context *ev_ctx,
> 			      struct messaging_context *msg_ctx,
> 			      const struct dcerpc_binding_vector *v)
> {
> 	const struct ndr_interface_table *t = &ndr_table_dssetup;
> 	const char *pipe_name = "dssetup";
> 	struct dcerpc_binding_vector *v2;
> 	enum rpc_service_mode_e epm_mode = rpc_epmapper_mode();
> 	NTSTATUS status;
> 	bool ok;
> 	status = rpc_dssetup_init(NULL);
> 	if (!NT_STATUS_IS_OK(status)) {
> 		return false;
> 	}
> 	if (epm_mode != RPC_SERVICE_MODE_DISABLED) {
> 		v2 = dcerpc_binding_vector_dup(talloc_tos(), v);
> 		if (v2 == NULL) {
> 			return false;
> 		}
> 		status = dcerpc_binding_vector_replace_iface(t, v2);
> 		if (!NT_STATUS_IS_OK(status)) {
> 			return false;
> 		}
> 		status = dcerpc_binding_vector_add_np_default(t, v2);
> 		if (!NT_STATUS_IS_OK(status)) {
> 			return false;
> 		}
> 		ok = setup_dcerpc_ncalrpc_socket(ev_ctx,
> 						 msg_ctx,
> 						 pipe_name,
> 						 NULL);
> 		if (!ok) {
> 			return false;
> 		}
> 		status = dcerpc_binding_vector_add_unix(t, v2, pipe_name);
> 		if (!NT_STATUS_IS_OK(status)) {
> 			return false;
> 		}
> 		status = rpc_ep_register(ev_ctx,
> 					 msg_ctx,
> 					 t,
> 					 v2);
> 		if (!NT_STATUS_IS_OK(status)) {
> 			return false;
> 		}
> 	}
> 	return true;
> }
> The function does:
>  - copies in the TCP/IP port bindings

Only if it is enabled and this is normally not the case cause smbd can't 
handle rpc tcpip connection. This is why we developed the prefork stuff and 
have lsasd.

This is normally and emtpy structure.

>  - registers ncacn_np pipes based on the IDL interface table
>  - registers the ncaclrpc pipe
> My question is:  Is there a reason why this is not entirely table
> driven, based on this IDL interface table:

No, I think there is no reason.

> [
> 	uuid("3919286a-b10c-11d0-9ba8-00c04fd92ef5"),
> 	version(0.0),
> 	endpoint("ncacn_np:[\\pipe\\lsarpc]", "ncacn_np:[\\pipe\\lsass]",
> "ncacn_ip_tcp:", "ncalrpc:"),
> 	pointer_default(unique),
> 	helpstring("Active Directory Setup")
> ] interface dssetup
> (this is used by dcerpc_binding_vector_add_np_default already).
> I'm not trying to poke blame or suggest that hard-coding it was not the
> most expedient option available at the time.  I'm just trying to
> understand the why behind the code we have so far, as it seems I will be
> needing to undertake some significant works in this area.  It helps to
> understand not just the actions, but the intentions of those who have
> been before me.  Naturally, I'll also keep you in the loop as I do the
> work.

It made it easier to do it somehow manually than relying on the IDL table for 
the service. For RPC over TCPIP we only open one port. Copying it and 
replacing the GUID was the easiest way to implement it. If you want to always 
rely on the idl then you can do that, but then you always have to pass all 
options like ip address and ports to the functions even if you don't need it. 

As it is now it was the simplest way to pass around a structure with all ip 
address and port combination we can have.

I someone specifies ip addresses to listen on you need to open a random port 
on all of them and register each service for all of them on the endpoint 
mapper. So it was the easiest to setup the endpoint mapper structure and pass 
it down and only replace the GUID. I didn't want to introduce yet another 
structure to pass around the information.

Maybe we should create more abstract functions for registering and have a 
public library which can be used by openchange to register their endpoints.

> > We need(ed) to call rpc_spoolss_init() or if you connect over a named pipe
> > to smbd, then smbd will tell the client that it doesn't know the rpc
> > protocol and drop the connection. This registration is (was) needed to
> > accept the connection and forward it over the named pipe proxy to the
> > correct service, spoolssd.
> > 
> > Maybe this has changed and isn't needed anymore. It was needed by the time
> > I was doing the work. I think we need to try it and maybe make sure it
> > isn't requried anymore.
> I'll do that.  We should be able to put our RPC services into one of two
> categories:  Services that are embedded in the forked smbd SMB child
> process, and external services (the rest).  We should not need to
> register external services except to the epmapper, and just fail
> gracefully if we cannot find the socket.

I agree. Maybe it is already working in the meantime. We just need to move the 
rpc_<service>_init() calls into the embedded case.

> > > Given the support for automatically removing registrations when
> > > processes shut down, I imagined it would need to be registred from the
> > > same process.
> > 
> > Do you talk about registered endpoints in smbd or rpc_<rpc>_init() now?
> I'm sorry, I was confused by the rpc_setup_lsarpc() call, being called
> from main() -> dcesrv_ep_setup -> rpc_setup_lsarpc().  However, it is
> guarded and the registration only applies in embedded mode.
> The rpc_lsarpc_init() function appears to be called from both that and
> setup_lsasd().  I don't know if that matters.

As you explained above it should only be called in smbd if it is embedded. The 
rpc_lsarpc_init() call was required to get the proxy connection to the 
external daemon working.

> > We should differentiate between registering the process on epmd or make
> > smbd aware of handling the connection for dssetup and forwarding it. If
> > you mean the letter than we need to make sure that this will work.
> If possible, I would like to make 'smbd' essentially unaware of external
> rpc pipes, just working on what sockets exist in the ncaclrpc/np
> directory.  Then epmd (wherever it is implemented) can deal with
> registrations.

I would like to have epmd in its own deamon and be started like smbd from 
s3fs. This was it could be used by s4 and s3/lsasd. I'm also fine if we create 
a library and fork it from s3/s4.

	-- andreas

Andreas Schneider                   GPG-ID: F33E3FC6                asn at

More information about the samba-technical mailing list