Skip to content

Fixes #555 : IM0 record not always returned from DCE lookup request due to randomized sequence numbers #556

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions src/device/pf_cmrpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -520,9 +520,11 @@ static int pf_session_allocate (pnet_t * net, pf_session_info_t ** pp_sess)
p_sess->in_use = true;
p_sess->p_ar = NULL;
p_sess->sequence_nmb_send = 0;
p_sess->epm_sequence_nmb = 0;
p_sess->dcontrol_sequence_nmb = UINT32_MAX;
p_sess->ix = ix;
pf_scheduler_init_handle (&p_sess->resend_timeout, "rpc");
pf_scheduler_init_handle (&p_sess->epm_timeout, "rpc-lookup");

/* Set activity UUID. Will be overwritten for incoming requests. */
pf_generate_uuid (
Expand Down Expand Up @@ -570,6 +572,7 @@ static void pf_session_release (pnet_t * net, pf_session_info_t * p_sess)
}

pf_scheduler_remove_if_running (net, &p_sess->resend_timeout);
pf_scheduler_remove_if_running (net, &p_sess->epm_timeout);

LOG_DEBUG (
PF_RPC_LOG,
Expand All @@ -592,6 +595,22 @@ static void pf_session_release (pnet_t * net, pf_session_info_t * p_sess)
}
}

/**
* @internal
*
* An EPM timeout has occurred.
*
* @param net InOut: The p-net stack instance
* @param arg InOut: The session instance.
* @param current_time In: Time when the EPM timeout function was scheduled
*/
static void pf_session_epm_timeout(pnet_t * net, void * arg, uint32_t current_time)
{
struct pf_session_info * p_session = (struct pf_session_info *)arg;

pf_session_release(net, p_session);
}

/**
* @internal
* Find a session (in use) by its activity UUID.
Expand Down Expand Up @@ -3109,6 +3128,7 @@ static int pf_cmrpc_lookup_ind (
lookup_request.udpPort = p_sess->port;
ret = pf_cmrpc_lookup_request (
net,
p_sess,
p_rpc_req,
&lookup_request,
&p_sess->rpc_result,
Expand Down Expand Up @@ -4639,6 +4659,10 @@ static int pf_cmrpc_dce_packet (
&uuid_epmap_interface,
sizeof (rpc_req.object_uuid)) == 0)
{
/* Incoming EPM request will cancel timeout */
pf_scheduler_remove_if_running(net, &p_sess->epm_timeout);
pf_scheduler_reset_handle(&p_sess->epm_timeout);

rpc_res.fragment_nmb = 0;
rpc_res.flags.idempotent = false;

Expand All @@ -4653,10 +4677,16 @@ static int pf_cmrpc_dce_packet (
&p_sess->out_buf_len);
*p_close_socket = p_sess->from_me;

/* Close session after each EPM request
If future more advanced EPM usage is required, implement a
timeout for closing the session */
p_sess->kill_session = true;
// If the pf_cmrpc_lookup_ind didn't request
// the session to be killed, increment the sequence
// number and start a timeout that will kill the
// session if a request is not received soon enough
if(!p_sess->kill_session)
{
p_sess->epm_sequence_nmb++;
pf_scheduler_add(net, 5000000, pf_session_epm_timeout, (void*) p_sess, &p_sess->epm_timeout);
}

}
else
{
Expand Down
6 changes: 5 additions & 1 deletion src/device/pf_cmrpc_epm.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,15 @@ static int pf_cmrdr_add_pnio_entry (
*/
static int pf_cmrdr_inquiry_read_all_reg_ind (
pnet_t * net,
pf_session_info_t * p_sess,
const pf_rpc_header_t * p_rpc_req,
const pf_rpc_lookup_req_t * p_lookup_req,
pf_rpc_lookup_rsp_t * p_lookup_rsp,
pnet_result_t * p_read_status)
{
int ret = -1;

switch (p_rpc_req->sequence_nmb)
switch (p_sess->epm_sequence_nmb)
{
case 0:
{
Expand Down Expand Up @@ -315,6 +316,7 @@ static int pf_cmrdr_inquiry_read_all_reg_ind (
}
break;
default:
p_sess->kill_session = true;
break;
}
return ret;
Expand All @@ -335,6 +337,7 @@ static int pf_cmrdr_inquiry_read_all_reg_ind (
*/
int pf_cmrpc_lookup_request (
pnet_t * net,
pf_session_info_t * p_sess,
const pf_rpc_header_t * p_rpc_req,
const pf_rpc_lookup_req_t * p_lookup_req,
pnet_result_t * p_read_status,
Expand All @@ -361,6 +364,7 @@ int pf_cmrpc_lookup_request (
case PF_RPC_INQUIRY_READ_ALL_REGISTERED_INTERFACES:
pf_cmrdr_inquiry_read_all_reg_ind (
net,
p_sess,
p_rpc_req,
p_lookup_req,
&lookup_rsp,
Expand Down
1 change: 1 addition & 0 deletions src/device/pf_cmrpc_epm.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ extern "C" {
*/
int pf_cmrpc_lookup_request (
pnet_t * net,
pf_session_info_t * p_sess,
const pf_rpc_header_t * p_rpc_req,
const pf_rpc_lookup_req_t * p_lookup_req,
pnet_result_t * p_read_status,
Expand Down
3 changes: 3 additions & 0 deletions src/pf_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -2078,6 +2078,9 @@ typedef struct pf_session_info
uint32_t dcontrol_sequence_nmb; /* From dcontrol request */
pnet_result_t dcontrol_result;

uint32_t epm_sequence_nmb; /* Counts the sequence number for an EPM request. 0 is the 1st request, 1 is 2nd, etc. */
pf_scheduler_handle_t epm_timeout; /* Timeout EPM requests if they don't receive a response within a certain time limit */

/* This timer is used to handle ccontrol and fragment re-transmissions */
pf_scheduler_handle_t resend_timeout;
uint32_t resend_counter;
Expand Down