-
Notifications
You must be signed in to change notification settings - Fork 7.6k
Test-Connection: Fallback to hop IP Address on -Traceroute without -ResolveDestination #11335
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
Test-Connection: Fallback to hop IP Address on -Traceroute without -ResolveDestination #11335
Conversation
/cc @daxian-dbw @SteveL-MSFT I know it's late in the cycle, but I'd really rather not leave this bug in for v7 😅 so if we're able to tidy this loose end away for RC or GA that'd be much appreciated! 💖 |
get | ||
{ | ||
if (_status.Address?.ToString() == IPAddress.Any.ToString() | ||
|| _status.Address?.ToString() == IPAddress.IPv6Any.ToString()) | ||
{ | ||
// There was no response to the ping (TimedOut). | ||
return null; | ||
} | ||
|
||
if (_status.Destination == string.Empty) | ||
{ | ||
// There was a response, but the destination field is empty; use DisplayAddress. | ||
return _status.DisplayAddress; | ||
} | ||
|
||
return _status.Destination; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking the code I guess there is a bug in ProcessTraceroute()
if (ResolveDestination.IsPresent && routerName == string.Empty)
- we skip assigning the routerName
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. I left that in because I wanted to allow it to retry assigning the router name if resolve destination is present. I think I should split up that if statement, so if ResolveDestination isn't present at all it just immediately assigns the IP address.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed the ProcessTraceroute() issue by checking if routerName
is string.Empty
when creating the objects for output and instead assigning the hopAddressString
as the Destination
field instead of leaving it blank.
Huh, looks like that commit isn't showing up yet. Checked https://www.githubstatus.com/ and it looks liek they're having some issues. I'll check back tomorrow and see if it shows, I might need to push an empty commit to get things to refresh here. EDIT: It showed up, so we should be good! 🎉 |
src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs
Outdated
Show resolved
Hide resolved
#if !UNIX | ||
if (ResolveDestination.IsPresent && routerName == string.Empty) | ||
if (routerName == string.Empty | ||
|| ResolveDestination.IsPresent && routerName == hopAddressString) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need InitProcessPing() in the for
cycle if we ping the same address?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mainly for -ResolveDestination purposes, to retrieve the DNS name for the hop point. Note that it is skipped if there is already a name retrieved for that hop point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We call InitProcessPing() for the same hop in the cycle. I suggest to move the call out of the cycle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved the InitProcessPing() call to just before the loop. 👍
if (_status.Address == IPAddress.Any | ||
|| _status.Address == IPAddress.IPv6Any) | ||
{ | ||
// There was no response to the ping (TimedOut). | ||
return null; | ||
} | ||
|
||
// We have a usable IP address from this ping reply. | ||
return _status.Destination; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We initialize TraceStatus with resolvedTargetName coming from InitProcessPing(). So maybe we should do the check and assign to null in InitProcessPing() ?
// There was no response to the ping (TimedOut).
I see we use targetAddress
to initialize TraceStatus but the value is not related to ping status and timeout.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not 100% clear on what you're suggesting here. Just move this check to the constructor and set the value there?
Yes, TraceStatus isn't directly tied to PingStatus, but it does effectively "wrap" the PingStatus and surfaces some of the properties from the PingStatus while adding some extra properties to make the traceroute progress clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved this check to the constructor so we only need to check it once. 👍
@vexx32, this is the reminder you requested 24 hours. ago |
@@ -383,25 +381,14 @@ private void ProcessTraceroute(string targetNameOrAddress) | |||
#endif | |||
var hopAddressString = discoveryReply.Address.ToString(); | |||
|
|||
InitProcessPing(hopAddressString, out string routerName, out _); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should still put this in try-catch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean have an if/else? The method should be catching all errors here.
I'll add an if statement so we properly set some sort of router name based on hopAddressString
if the name can't be resolved, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the method throws if router name can not be resolved
InitProcessPing(hopAddressString, out string routerName, out _); | |
try | |
{ | |
InitProcessPing(hopAddressString, out string routerName, out _); | |
} | |
catch | |
{ | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method writes an error, but it does not throw.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested with artifact and get throw on first hop where router hasn't name. I guess it was in GetHostEntry().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still see the issue in latest artifact
PS C:\Users\1\Downloads\publish> Get-Error
Exception :
Type : System.Net.Sockets.SocketException
Message : No such host is known.
SocketErrorCode : HostNotFound
ErrorCode : 11001
NativeErrorCode : 11001
TargetSite :
Name : InternalGetHostByAddress
DeclaringType : System.Net.Dns
MemberType : Method
Module : System.Net.NameResolution.dll
StackTrace :
at System.Net.Dns.InternalGetHostByAddress(IPAddress address)
at System.Net.Dns.GetHostEntry(String hostNameOrAddress)
at Microsoft.PowerShell.Commands.TestConnectionCommand.TryResolveNameOrAddress(String targetNameOrAddress, String& r
esolvedTargetName, IPAddress& targetAddress)
at Microsoft.PowerShell.Commands.TestConnectionCommand.ProcessTraceroute(String targetNameOrAddress)
at Microsoft.PowerShell.Commands.TestConnectionCommand.ProcessRecord()
at System.Management.Automation.CommandProcessor.ProcessRecord()
Source : System.Net.NameResolution
HResult : -2147467259
CategoryInfo : NotSpecified: (:) [Test-Connection], SocketException
FullyQualifiedErrorId : System.Net.Sockets.SocketException,Microsoft.PowerShell.Commands.TestConnectionCommand
InvocationInfo :
MyCommand : Test-Connection
ScriptLineNumber : 1
OffsetInLine : 1
HistoryId : 4
Line : Test-Connection -Traceroute 1.1.1.1 -ResolveDestination
PositionMessage : At line:1 char:1
+ Test-Connection -Traceroute 1.1.1.1 -ResolveDestination
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
InvocationName : Test-Connection
CommandOrigin : Internal
ScriptStackTrace : at <ScriptBlock>, <No file>: line 1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Huh! GetHostEntry
itself throws? Thanks for following up on that. Yeah, I can sort that out. 🙂
src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs
Show resolved
Hide resolved
- When doing traceroutes, Destination is set as the router name. If no router name is available, it ends up as string.Empty. - Change Hostname property to fallback to DisplayAddress if needed.
- Previously, the Destination field of the PingStatus could be empty - Change ensures that it will always be populated with the IP address if no hostname is available. - The getter for TraceStatus.Hostname was adjusted to make better use of the underlying properties as well.
- Before this change, if ResolveDestination was not set, we did not use the method to get the hop address string. - After this change, the routerName and thus Destination field will always be set.
- Call InitProcessPing() only once per hop. - Set Hostname in TraceStatus constructor.
754f062
to
72e9e8f
Compare
src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be correct that with this change, test-connection 127.0.0.1 -traceroute
should not output any asterisks? If so, we can just test that case.
Yeah, that should work. 👍 |
src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs
Show resolved
Hide resolved
src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This resolves an issue where intermediate hops may not have DNS entries. Retaining this behaviour means we acknowledge not all nodes in the trace will necessarily be reachable. This is quite normal; many nodes may block direct ICMP requests. By catching any errors during hostname resolution, we get a more useful experience for users.
src/Microsoft.PowerShell.Commands.Management/commands/management/TestConnectionCommand.cs
Outdated
Show resolved
Hide resolved
@vexx32 Can you please look into the build failure?
|
@daxian-dbw Ah yep, that'll do it. Still getting used to working in files with nullable reference types enabled. |
I like nullable reference types more and more. |
They really help keep things locked down tight, it's lovely. I just have to remember to be a little careful when working with them. 😁 |
…`-ResolveDestination` (#11335)
🎉 Handy links: |
PR Summary
When doing traceroutes, Destination of the PingStatus is set as the router name.
If no router name is available, it ends up as string.Empty.
This PR changes the logic in
ProcessTraceroute()
to instead assign thehopAddressString
value as theDestination
field for thePingStatus
object created if there is norouterName
available.PR Context
Fixes #11334
PR Checklist
.h
,.cpp
,.cs
,.ps1
and.psm1
files have the correct copyright headerWIP:
or[ WIP ]
to the beginning of the title (theWIP
bot will keep its status check atPending
while the prefix is present) and remove the prefix when the PR is ready.