Skip to content

Commit a88404c

Browse files
ejohnstownphilljj
authored andcommitted
Drop a forward the peer refused twice
A cancel refusal leaves the forward standing, since the peer keeps a listener it would not drop. There is no listener to keep when the setup was refused too, so FwdRemoteSettle() unwinds a registration nothing establishes and nothing is still owed an answer on, rather than leaving it unconfirmed and unmatchable until the session ends. - A cancel refusal unlinks an unconfirmed forward with no setup queued - Test refuses a want-reply setup and the cancel behind it, and checks the registration is gone
1 parent f612689 commit a88404c

2 files changed

Lines changed: 36 additions & 1 deletion

File tree

src/internal.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4097,7 +4097,11 @@ static void FwdRemoteSettle(WOLFSSH* ssh, WOLFSSH_FWD_REMOTE* entry,
40974097
if (isCancel) {
40984098
if (!success) {
40994099
/* The peer kept the listener, so the forward stands and matching
4100-
* resumes unless a later cancel is outstanding. */
4100+
* resumes unless a later cancel is outstanding. An unconfirmed
4101+
* forward has no listener to keep, though: its setup was refused
4102+
* too, and with none still queued nothing will ever bind it. */
4103+
if (!entry->confirmed && !FwdReplyHasSetup(ssh, entry))
4104+
FwdRemoteUnlink(ssh, ssh->ctx->heap, entry);
41014105
return;
41024106
}
41034107

tests/regress.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4051,6 +4051,36 @@ static void TestForwardedTcpipCancelBeforeSetupReply(void)
40514051
FreeChannelOpenHarness(&harness);
40524052
}
40534053

4054+
/* The same overlap with both requests refused. The setup bound no listener,
4055+
* so the cancel's refusal is only the peer saying it has none to drop, and
4056+
* nothing is left to hold the registration open. */
4057+
static void TestForwardedTcpipSetupAndCancelBothRefusedDrops(void)
4058+
{
4059+
ChannelOpenHarness harness;
4060+
4061+
InitFwdRemoteHarness(&harness);
4062+
4063+
AssertIntEQ(wolfSSH_FwdRemoteSetup(harness.ssh, "127.0.0.1", 8080, 1),
4064+
WS_SUCCESS);
4065+
AssertIntEQ(wolfSSH_FwdRemoteCancel(harness.ssh, "127.0.0.1", 8080, 1),
4066+
WS_SUCCESS);
4067+
4068+
/* The setup is refused, but the queued cancel still names the forward, so
4069+
* it is held for that answer. */
4070+
FeedRequestFailure(&harness);
4071+
AssertNotNull(harness.ssh->fwdRemoteList);
4072+
4073+
/* The cancel is refused too. Nothing establishes the forward and nothing
4074+
* is owed an answer on it, so it goes rather than sitting unmatchable
4075+
* until the session ends. */
4076+
FeedRequestFailure(&harness);
4077+
AssertNull(harness.ssh->fwdRemoteList);
4078+
4079+
AssertForwardedOpenRefused(&harness, "127.0.0.1", 8080);
4080+
4081+
FreeChannelOpenHarness(&harness);
4082+
}
4083+
40544084
/* The same overlap, but with a second forward outstanding behind it. The
40554085
* cancelled forward's reply must not be spent on the one still waiting. */
40564086
static void TestForwardedTcpipCancelBeforeSetupReplyKeepsOther(void)
@@ -10800,6 +10830,7 @@ int main(int argc, char** argv)
1080010830
TestForwardedTcpipUnmatchedCancelKeepsForward();
1080110831
TestForwardedTcpipCancelBeforeSetupReply();
1080210832
TestForwardedTcpipCancelBeforeSetupReplyKeepsOther();
10833+
TestForwardedTcpipSetupAndCancelBothRefusedDrops();
1080310834
TestForwardedTcpipDuplicateSetupIsOneForward();
1080410835
TestForwardedTcpipDuplicateSetupRefusalKeepsForward();
1080510836
TestForwardedTcpipDuplicateSetupLaterSuccessBinds();

0 commit comments

Comments
 (0)