Skip to content

Commit

Permalink
Merge pull request #2 from firejox/features/hvsock
Browse files Browse the repository at this point in the history
Add HyperV Socket Support
  • Loading branch information
firejox authored Mar 22, 2023
2 parents 6d949d5 + 3139f82 commit a7bdfd8
Show file tree
Hide file tree
Showing 5 changed files with 541 additions and 4 deletions.
24 changes: 21 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ The WinSocat is accept two address pattern
winsocat.exe [address1] [address2]
```

The `address1` can accept `STDIO`, `TCP-LISTEN`, `TCP`, `NPIPE`, `NPIPE-LISTEN`, `EXEC`, `WSL`, `UNIX`, `UNIX-LISTEN` socket types.
The `address1` can accept `STDIO`, `TCP-LISTEN`, `TCP`, `NPIPE`, `NPIPE-LISTEN`, `EXEC`, `WSL`, `UNIX`, `UNIX-LISTEN`, `HVSOCK`, `HVSOCK-LISTEN` socket types.

The `address2` can accept `STDIO`, `TCP`, `NPIPE`, `EXEC`, `WSL`, `UNIX` socket types.
The `address2` can accept `STDIO`, `TCP`, `NPIPE`, `EXEC`, `WSL`, `UNIX`, `HVSOCK` socket types.

## Examples

Expand Down Expand Up @@ -79,4 +79,22 @@ winsocat NPIPE-LISTEN:fooPipe WSL:"socat STDIO unix-connect:foo.sock"
* WSL Unix Socket forwarding to Windows named pipe
```
socat unix-listen:foo.sock,fork EXEC:"/path/to/winsocat.exe STDIO NPIPE:fooPipe"
```
```

### HyperV Socket Support

WinSocat is also allow to interact with hyper-v socket. It requires the vmId and serviceId to connect. For example, you can use this

```
winsocat stdio hvsock:0cb41c0b-fd26-4a41-8370-dccb048e216e:00000ac9-facb-11e6-bd58-64006a7986d3
```

to connect the VSOCK socket opened by WSL2 program. This program is running under the HyperV-VM with vmId `0cb41c0b-fd26-4a41-8370-dccb048e216e`.
And it opens the VSOCK port 2761(the hex format is 0x00000ac9). According to [hyper-v on windows](https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service),
the VSOCK port on Linux will be equivalent to the serviceId `[port in hex]-facb-11e6-bd58-64006a7986d3` on windows. Hence, WinSocat provide the short representation for VSOCK.

```
winsocat stdio hvsock:0cb41c0b-fd26-4a41-8370-dccb048e216e:vsock-2761
```

This `vsock-2761` will be viewed as the serviceId `00000ac9-facb-11e6-bd58-64006a7986d3`.
82 changes: 82 additions & 0 deletions Tests/HyperVListenPiperInfoTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using Firejox.App.WinSocat;

namespace APPTest;

public class HyperVListenPiperInfoTest
{
public const string GuidZero = "00000000-0000-0000-0000-000000000000";
public const string GuidWildCard = "00000000-0000-0000-0000-000000000000";
public const string GuidBroadCast = "ffffffff-ffff-ffff-ffff-ffffffffffff";
public const string GuidChildren = "90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd";
public const string GuidLoopBack = "e0e16197-dd56-4a10-9195-5ee7a155a838";
public const string GuidParent = "a42e7cda-d03f-480c-9cc2-a4de20abb878";
public const string GuidVSock0 = "00000000-facb-11e6-bd58-64006a7986d3";
public const string GuidVSock1 = "00000001-facb-11e6-bd58-64006a7986d3";
public const string GuidVSockMax = "7fffffff-facb-11e6-bd58-64006a7986d3";

[TestCase("HVSOCK-LISTEN:00000000-0000-0000-0000-000000000000:00000000-0000-0000-0000-000000000000")]
[TestCase("HVSOCK-LISTEN:e0e16197dd564a1091955ee7a155a838:(00000000-0000-0000-0000-000000000000)")]
[TestCase("HVSOCK-LISTEN:ZERO:VSOCK-0")]
[TestCase("HVSOCK-LISTEN:PARENT:VSOCK-0")]
[TestCase("HVSOCK-LISTEN:WILDCARD:VSOCK-0")]
[TestCase("HVSOCK-LISTEN:LOOPBACK:VSOCK-0")]
[TestCase("HVSOCK-LISTEN:BROADCAST:VSOCK-0")]
[TestCase("HVSOCK-LISTEN:CHILDREN:VSOCK-0")]
public void ValidInputParseTest(string input)
{
var element = AddressElement.TryParse(input);
Assert.NotNull(HyperVListenPiperInfo.TryParse(element));
}

[TestCase("HVSOCK-LISTEN:00000000-0000-0000-0000-000000000000:00000000-0000-0000-0000-000000000000")]
[TestCase("hvsock-listen:e0e16197dd564a1091955ee7a155a838:(00000000-0000-0000-0000-000000000000)")]
[TestCase("hvsock-listen:zero:vsock-0")]
[TestCase("hvsock-listen:parent:vsock-0")]
[TestCase("hvsock-listen:wildcard:vsock-0")]
[TestCase("hvsock-listen:loopback:vsock-0")]
[TestCase("hvsock-listen:broadcast:vsock-0")]
[TestCase("hvsock-listen:children:vsock-0")]
public void CaseInsensitiveValidInputParseTest(string input)
{
var element = AddressElement.TryParse(input);
Assert.NotNull(HyperVListenPiperInfo.TryParse(element));
}

[TestCase("STDIO")]
[TestCase("TCP:127.0.0.1:80")]
[TestCase("TCP-LISTEN:127.0.0.1:80")]
[TestCase("NPIPE:fooServer:barPipe")]
[TestCase("NPIPE-LISTEN:fooPipe")]
[TestCase(@"EXEC:'C:\Foo.exe bar'")]
[TestCase("UNIX:foo.sock")]
[TestCase("UNIX-LISTEN:foo.sock")]
public void InvalidInputParseTest(string input)
{
var element = AddressElement.TryParse(input);
Assert.Null(HyperVListenPiperInfo.TryParse(element));
}

[TestCase("HVSOCK-LISTEN:00000000-0000-0000-0000-000000000000:00000000-0000-0000-0000-000000000000", ExpectedResult = "00000000-0000-0000-0000-000000000000")]
[TestCase("HVSOCK-LISTEN:e0e16197dd564a1091955ee7a155a838:(00000000-0000-0000-0000-000000000000)", ExpectedResult = "e0e16197-dd56-4a10-9195-5ee7a155a838")]
[TestCase("HVSOCK-LISTEN:ZERO:VSOCK-0", ExpectedResult = GuidZero)]
[TestCase("HVSOCK-LISTEN:WILDCARD:VSOCK-0", ExpectedResult = GuidWildCard)]
[TestCase("HVSOCK-LISTEN:BROADCAST:VSOCK-0", ExpectedResult = GuidBroadCast)]
[TestCase("HVSOCK-LISTEN:CHILDREN:VSOCK-0", ExpectedResult = GuidChildren)]
[TestCase("HVSOCK-LISTEN:PARENT:VSOCK-0", ExpectedResult = GuidParent)]
[TestCase("HVSOCK-LISTEN:LOOPBACK:VSOCK-0", ExpectedResult = GuidLoopBack)]
public string VmIdPatternMatchTest(string input)
{
var element = AddressElement.TryParse(input);
return HyperVListenPiperInfo.TryParse(element).VmId.ToString();
}

[TestCase("HVSOCK-LISTEN:00000000-0000-0000-0000-000000000000:00000000-0000-0000-0000-000000000000", ExpectedResult = "00000000-0000-0000-0000-000000000000")]
[TestCase("HVSOCK-LISTEN:90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd:e0e16197dd564a1091955ee7a155a838", ExpectedResult = "e0e16197-dd56-4a10-9195-5ee7a155a838")]
[TestCase("HVSOCK-LISTEN:ZERO:VSOCK-0", ExpectedResult = GuidVSock0)]
[TestCase("HVSOCK-LISTEN:ZERO:VSOCK-1", ExpectedResult = GuidVSock1)]
[TestCase("HVSOCK-LISTEN:ZERO:VSOCK-2147483647", ExpectedResult = GuidVSockMax)]
public string ServiceIdPatternMatchTest(string input)
{
var element = AddressElement.TryParse(input);
return HyperVListenPiperInfo.TryParse(element).ServiceId.ToString();
}}
82 changes: 82 additions & 0 deletions Tests/HyperVStreamPiperInfoTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using Firejox.App.WinSocat;
namespace APPTest;

public class HyperVStreamPiperInfoTest
{
public const string GuidZero = "00000000-0000-0000-0000-000000000000";
public const string GuidWildCard = "00000000-0000-0000-0000-000000000000";
public const string GuidBroadCast = "ffffffff-ffff-ffff-ffff-ffffffffffff";
public const string GuidChildren = "90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd";
public const string GuidLoopBack = "e0e16197-dd56-4a10-9195-5ee7a155a838";
public const string GuidParent = "a42e7cda-d03f-480c-9cc2-a4de20abb878";
public const string GuidVSock0 = "00000000-facb-11e6-bd58-64006a7986d3";
public const string GuidVSock1 = "00000001-facb-11e6-bd58-64006a7986d3";
public const string GuidVSockMax = "7fffffff-facb-11e6-bd58-64006a7986d3";

[TestCase("HVSOCK:00000000-0000-0000-0000-000000000000:00000000-0000-0000-0000-000000000000")]
[TestCase("HVSOCK:e0e16197dd564a1091955ee7a155a838:(00000000-0000-0000-0000-000000000000)")]
[TestCase("HVSOCK:ZERO:VSOCK-0")]
[TestCase("HVSOCK:PARENT:VSOCK-0")]
[TestCase("HVSOCK:WILDCARD:VSOCK-0")]
[TestCase("HVSOCK:LOOPBACK:VSOCK-0")]
[TestCase("HVSOCK:BROADCAST:VSOCK-0")]
[TestCase("HVSOCK:CHILDREN:VSOCK-0")]
public void ValidInputParseTest(string input)
{
var element = AddressElement.TryParse(input);
Assert.NotNull(HyperVStreamPiperInfo.TryParse(element));
}

[TestCase("HVSOCK:00000000-0000-0000-0000-000000000000:00000000-0000-0000-0000-000000000000")]
[TestCase("hvsock:e0e16197dd564a1091955ee7a155a838:(00000000-0000-0000-0000-000000000000)")]
[TestCase("HVSOCK:zero:vsock-0")]
[TestCase("HVSOCK:parent:vsock-0")]
[TestCase("HVSOCK:wildcard:vsock-0")]
[TestCase("HVSOCK:loopback:vsock-0")]
[TestCase("HVSOCK:broadcast:vsock-0")]
[TestCase("HVSOCK:children:vsock-0")]
public void CaseInsensitiveValidInputParseTest(string input)
{
var element = AddressElement.TryParse(input);
Assert.NotNull(HyperVStreamPiperInfo.TryParse(element));
}

[TestCase("STDIO")]
[TestCase("TCP:127.0.0.1:80")]
[TestCase("TCP-LISTEN:127.0.0.1:80")]
[TestCase("NPIPE:fooServer:barPipe")]
[TestCase("NPIPE-LISTEN:fooPipe")]
[TestCase(@"EXEC:'C:\Foo.exe bar'")]
[TestCase("UNIX:foo.sock")]
[TestCase("UNIX-LISTEN:foo.sock")]
public void InvalidInputParseTest(string input)
{
var element = AddressElement.TryParse(input);
Assert.Null(HyperVStreamPiperInfo.TryParse(element));
}

[TestCase("HVSOCK:00000000-0000-0000-0000-000000000000:00000000-0000-0000-0000-000000000000", ExpectedResult = "00000000-0000-0000-0000-000000000000")]
[TestCase("HVSOCK:e0e16197dd564a1091955ee7a155a838:(00000000-0000-0000-0000-000000000000)", ExpectedResult = "e0e16197-dd56-4a10-9195-5ee7a155a838")]
[TestCase("HVSOCK:ZERO:VSOCK-0", ExpectedResult = GuidZero)]
[TestCase("HVSOCK:WILDCARD:VSOCK-0", ExpectedResult = GuidWildCard)]
[TestCase("HVSOCK:BROADCAST:VSOCK-0", ExpectedResult = GuidBroadCast)]
[TestCase("HVSOCK:CHILDREN:VSOCK-0", ExpectedResult = GuidChildren)]
[TestCase("HVSOCK:PARENT:VSOCK-0", ExpectedResult = GuidParent)]
[TestCase("HVSOCK:LOOPBACK:VSOCK-0", ExpectedResult = GuidLoopBack)]
public string VmIdPatternMatchTest(string input)
{
var element = AddressElement.TryParse(input);
return HyperVStreamPiperInfo.TryParse(element).VmId.ToString();
}

[TestCase("HVSOCK:00000000-0000-0000-0000-000000000000:00000000-0000-0000-0000-000000000000", ExpectedResult = "00000000-0000-0000-0000-000000000000")]
[TestCase("HVSOCK:90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd:e0e16197dd564a1091955ee7a155a838", ExpectedResult = "e0e16197-dd56-4a10-9195-5ee7a155a838")]
[TestCase("HVSOCK:ZERO:VSOCK-0", ExpectedResult = GuidVSock0)]
[TestCase("HVSOCK:ZERO:VSOCK-1", ExpectedResult = GuidVSock1)]
[TestCase("HVSOCK:ZERO:VSOCK-2147483647", ExpectedResult = GuidVSockMax)]
public string ServiceIdPatternMatchTest(string input)
{
var element = AddressElement.TryParse(input);
return HyperVStreamPiperInfo.TryParse(element).ServiceId.ToString();
}
}
Loading

0 comments on commit a7bdfd8

Please sign in to comment.