In a file copy session smbd (19 processes) & 16 connections (I think) for my test session with 5 interfaces so it seems for multichannel up to 4 connections per channel for RSS interfaces (possibly the main one is not used then from the numbers above) For multichannel each connection seems to trigger a smbd child which then handles the negprot, then tries to pass it's fd to the 'main' smbd and then exit. When a connection is processed ============================== When processing smbd_smb2_request_dispatch source3/smbd/smb2_server.c smbd_smb2_request_process_negprot is called for SMB2_OP_NEGPROT, seems it checks the client guid (by smb2srv_client_lookup_global) if it knows about it it calls smb2srv_client_connection_pass which sends the MSG_SMBXSRV_CONNECTION_PASS message (and returns NT_STATUS_OBJECTID_EXISTS to the caller) (it also calls exit_server) note: MSG_SMBXSRV_CONNECTION_PASS is the internal message type used to actually pass the fd(s). Seems messaging_filtered_read_send (source3/lib/messages.c) and associated functions implement an internal (intra smbd) messaging subsystem if it (smbd_smb2_request_process_negprot) doesn't know about the guid then it calls smbXsrv_client_update, so it is a subsequent time that smb2srv_client_connection_pass is called. Normally though the guid should be already inserted via a previous negprot (client is the copy process ?) And in my case this seems so, only one client (from smb2srv_client_lookup_global) should exist in this case smb2srv_client_connection_pass (this is called for each connection in-turn handled by the individual smbd process) calls messaging_send_iov, it sends to global->server_id where server_id contains the pid (presumably of the main smbd ?) (and other data e.g. task, vnn & unique_id) struct smbXsrv_connection_pass0 pass_info0; struct smbXsrv_connection_passB pass_blob; are additionally sent it seems with the 'MSG_SMBXSRV_CONNECTION_PASS' message smbXsrv_connection_pass0 is a wrapper for the incomming request (the smb2req->in.vector is copied (or referenced) by smbXsrv_connection_pass0.negotiate_request (data_blob) member. Additionally client_guid & smb2req->xconn->smb2.credits.seq_low are copied into that struct. smbXsrv_connection_passB is itself a container (maybe) for the smbXsrv_connection_pass0 struture( it's a posible value for the union member 'info' (with smbXsrv_connection_passB.version as descriminator) The netprot handling (that presumably would normally happen from here is continued in the 'main' smbd process when it recieves the passed fds. (see "what happens when the connection is passed" below) When a smbd starts up ====================== smbXsrv_client_create starts listening for MSG_SMBXSRV_xyz messages, creates the smbXsrv_client_table_create also smbXsrv_client_connection_pass_loop is set as callback for messaging_filtered_read_send method (basically this method is just waiting to call smbXsrv_client_connection_pass_loop for any of the messaging_rec type message. Note: smbXsrv_client_connection_pass_loop will get called only if smbXsrv_client_connection_pass_filter (which is called for the messaging_rec message) returns true. * smbXsrv_client_connection_pass_filter checks if the msg type is MSG_SMBXSRV_CONNECTION_PASS. * smbXsrv_client_connection_pass_loop * extracts the fds So although any/all smbd processes can process the callback the callback above seems to fire only in one smbd process (again presumably the 'main' smbd) - or at least it seems it (the smbd that fires) is the first smbd that processes the first negprot for the 'client' smbXsrv_client_update creates the global (based on the client info in the negprot) and updates the pid that subsequent smbd (that get connection/negprot calls) what happens when the connection is passed =========================================== smbXsrv_client_connection_pass_loop (source3/smbd/smbXsrv_client.c) is called, the struct smbXsrv_connection_passB & struct smbXsrv_connection_pass0 data is pulled from the messaging_rec message. The global client id is compared with the smbXsrv_connection_pass0.client_guid passed in the messaging_rec (MSG_SMBXSRV_CONNECTION_PASS) message. If not equal we keep listening (by calling messaging_filtered_read_send again). If equal then initial_connect_time (from global and smbXsrv_connection_pass0.initial_connect_time) are compared and again if not equal keep listening. Finally struct smbXsrv_connection *xconn is set up via smbd_add_connection (source3/smbd/process.c) This I am guessing is a function called normally by smbd (without multichannel) the fd is set up, various checks are made (e.g. is the connection allowed) 'smbd_server_connection_handler' callback is set for the (in this case) passed fd. Then smbd_smb2_first_negprot is called which afaics starts the smb2 normal message processing occurs from here. There must be more to this ? since now a single smbd is handling the request (and there is reportedly some multi-threaded handling) but haven't seen where this happens yet In the logs there seems to be some RPC activity fsctl_net_iface_info (see netinterface in librpc/idl/ioctl.idl) Probably the SMB3 spec might shed some light on this, it's obviously to do with detection and getting info on the available interfaces but need to see how it is used/implemented