windows-nt/Source/XPSP1/NT/net/tcpip/tpipv6/ipv6mon/portproxy.c
2020-09-26 16:20:57 +08:00

714 lines
18 KiB
C

/*++
Copyright (c) 2000 Microsoft Corporation
Abstract:
Port Proxy Helper.
--*/
#include "precomp.h"
GUID g_PpGuid = PORTPROXY_GUID;
#define KEY_PORTS L"System\\CurrentControlSet\\Services\\PortProxy"
typedef enum {
V4TOV4,
V4TOV6,
V6TOV4,
V6TOV6
} PPTYPE, *PPPTYPE;
typedef struct {
PWCHAR Token;
PWCHAR ListenFamily;
PWCHAR ConnectFamily;
PWCHAR KeyString;
} PPTYPEINFO, *PPPTYPEINFO;
#define IPV4_STR L"IPv4"
#define IPV6_STR L"IPv6"
PPTYPEINFO PpTypeInfo[] = {
{ CMD_V4TOV4, IPV4_STR, IPV4_STR, KEY_PORTS L"\\" CMD_V4TOV4 },
{ CMD_V4TOV6, IPV4_STR, IPV6_STR, KEY_PORTS L"\\" CMD_V4TOV6 },
{ CMD_V6TOV4, IPV6_STR, IPV4_STR, KEY_PORTS L"\\" CMD_V6TOV4 },
{ CMD_V6TOV6, IPV6_STR, IPV6_STR, KEY_PORTS L"\\" CMD_V6TOV6 },
};
//
// Port Proxy commands.
//
FN_HANDLE_CMD PpHandleReset;
FN_HANDLE_CMD PpHandleDelV4ToV4;
FN_HANDLE_CMD PpHandleDelV4ToV6;
FN_HANDLE_CMD PpHandleDelV6ToV4;
FN_HANDLE_CMD PpHandleDelV6ToV6;
FN_HANDLE_CMD PpHandleAddSetV4ToV4;
FN_HANDLE_CMD PpHandleAddSetV4ToV6;
FN_HANDLE_CMD PpHandleAddSetV6ToV4;
FN_HANDLE_CMD PpHandleAddSetV6ToV6;
FN_HANDLE_CMD PpHandleShowAll;
FN_HANDLE_CMD PpHandleShowV4ToV4;
FN_HANDLE_CMD PpHandleShowV4ToV6;
FN_HANDLE_CMD PpHandleShowV6ToV4;
FN_HANDLE_CMD PpHandleShowV6ToV6;
CMD_ENTRY g_PpAddCmdTable[] =
{
CREATE_UNDOCUMENTED_CMD_ENTRY(PP_ADD_V4TOV4, PpHandleAddSetV4ToV4),
CREATE_UNDOCUMENTED_CMD_ENTRY(PP_ADD_V4TOV6, PpHandleAddSetV4ToV6),
CREATE_UNDOCUMENTED_CMD_ENTRY(PP_ADD_V6TOV4, PpHandleAddSetV6ToV4),
CREATE_UNDOCUMENTED_CMD_ENTRY(PP_ADD_V6TOV6, PpHandleAddSetV6ToV6),
};
CMD_ENTRY g_PpDelCmdTable[] =
{
CREATE_UNDOCUMENTED_CMD_ENTRY(PP_DEL_V4TOV4, PpHandleDelV4ToV4),
CREATE_UNDOCUMENTED_CMD_ENTRY(PP_DEL_V4TOV6, PpHandleDelV4ToV6),
CREATE_UNDOCUMENTED_CMD_ENTRY(PP_DEL_V6TOV4, PpHandleDelV6ToV4),
CREATE_UNDOCUMENTED_CMD_ENTRY(PP_DEL_V6TOV6, PpHandleDelV6ToV6),
};
CMD_ENTRY g_PpSetCmdTable[] =
{
CREATE_UNDOCUMENTED_CMD_ENTRY(PP_SET_V4TOV4, PpHandleAddSetV4ToV4),
CREATE_UNDOCUMENTED_CMD_ENTRY(PP_SET_V4TOV6, PpHandleAddSetV4ToV6),
CREATE_UNDOCUMENTED_CMD_ENTRY(PP_SET_V6TOV4, PpHandleAddSetV6ToV4),
CREATE_UNDOCUMENTED_CMD_ENTRY(PP_SET_V6TOV6, PpHandleAddSetV6ToV6),
};
CMD_ENTRY g_PpShowCmdTable[] =
{
CREATE_UNDOCUMENTED_CMD_ENTRY(PP_SHOW_ALL, PpHandleShowAll),
CREATE_UNDOCUMENTED_CMD_ENTRY(PP_SHOW_V4TOV4, PpHandleShowV4ToV4),
CREATE_UNDOCUMENTED_CMD_ENTRY(PP_SHOW_V4TOV6, PpHandleShowV4ToV6),
CREATE_UNDOCUMENTED_CMD_ENTRY(PP_SHOW_V6TOV4, PpHandleShowV6ToV4),
CREATE_UNDOCUMENTED_CMD_ENTRY(PP_SHOW_V6TOV6, PpHandleShowV6ToV6),
};
CMD_GROUP_ENTRY g_PpCmdGroups[] =
{
CREATE_CMD_GROUP_ENTRY(GROUP_ADD, g_PpAddCmdTable),
CREATE_CMD_GROUP_ENTRY(GROUP_DELETE, g_PpDelCmdTable),
CREATE_CMD_GROUP_ENTRY(GROUP_SHOW, g_PpShowCmdTable),
CREATE_CMD_GROUP_ENTRY(GROUP_SET, g_PpSetCmdTable),
};
ULONG g_ulNumPpCmdGroups = sizeof(g_PpCmdGroups)/sizeof(CMD_GROUP_ENTRY);
CMD_ENTRY g_PpTopCmds[] =
{
CREATE_CMD_ENTRY(IPV6_RESET, PpHandleReset),
};
ULONG g_ulNumPpTopCmds = sizeof(g_PpTopCmds)/sizeof(CMD_ENTRY);
DWORD
WINAPI
PpStartHelper(
IN CONST GUID *pguidParent,
IN DWORD dwParentVersion
)
{
DWORD dwErr;
NS_CONTEXT_ATTRIBUTES attMyAttributes;
ZeroMemory(&attMyAttributes, sizeof(attMyAttributes));
attMyAttributes.pwszContext = L"portproxy";
attMyAttributes.guidHelper = g_PpGuid;
attMyAttributes.dwVersion = PORTPROXY_HELPER_VERSION;
attMyAttributes.dwFlags = CMD_FLAG_LOCAL | CMD_FLAG_ONLINE;
attMyAttributes.pfnDumpFn = PpDump;
attMyAttributes.ulNumTopCmds= g_ulNumPpTopCmds;
attMyAttributes.pTopCmds = (CMD_ENTRY (*)[])&g_PpTopCmds;
attMyAttributes.ulNumGroups = g_ulNumPpCmdGroups;
attMyAttributes.pCmdGroups = (CMD_GROUP_ENTRY (*)[])&g_PpCmdGroups;
dwErr = RegisterContext( &attMyAttributes );
return dwErr;
}
VOID
ShowPorts(
IN PPTYPE Type,
IN FORMAT Format
)
{
ULONG Status, i, ListenChars, ConnectBytes, dwType;
HKEY hType, hProto;
WCHAR ListenBuffer[256], *ListenAddress, *ListenPort;
WCHAR ConnectAddress[256], *ConnectPort;
Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, PpTypeInfo[Type].KeyString, 0,
KEY_QUERY_VALUE, &hType);
if (Status != NO_ERROR) {
return;
}
Status = RegOpenKeyEx(hType, TOKEN_VALUE_TCP, 0,
KEY_QUERY_VALUE, &hProto);
if (Status == NO_ERROR) {
for (i=0; ; i++) {
ListenChars = sizeof(ListenBuffer)/sizeof(WCHAR);
ConnectBytes = sizeof(ConnectAddress);
Status = RegEnumValueW(hProto, i, ListenBuffer, &ListenChars,
NULL, &dwType, (PVOID)ConnectAddress,
&ConnectBytes);
if (Status != NO_ERROR) {
break;
}
if (dwType != REG_SZ) {
continue;
}
ListenPort = wcschr(ListenBuffer, L'/');
if (ListenPort) {
//
// Replace slash with NULL, so we have 2 strings to pass
// to getaddrinfo.
//
ListenAddress = ListenBuffer;
*ListenPort++ = L'\0';
} else {
//
// If the address data didn't include a connect address
// use "*".
//
ListenAddress = L"*";
ListenPort = ListenBuffer;
}
ConnectPort = wcschr(ConnectAddress, L'/');
if (ConnectPort) {
//
// Replace slash with NULL, so we have 2 strings to pass
// to getaddrinfo.
//
*ConnectPort++ = L'\0';
} else {
//
// If the address data didn't include a connect port
// number, use the same port as the listen port number.
//
ConnectPort = ListenPort;
}
if (Format == FORMAT_NORMAL) {
if (i==0) {
// DisplayMessage(g_hModule, MSG_PORT_PROXY_HEADER,
// PpTypeInfo[Type].ListenFamily,
// PpTypeInfo[Type].ConnectFamily);
}
// DisplayMessage(g_hModule, MSG_PORT_PROXY, ListenAddress,
// ListenPort, ConnectAddress, ConnectPort);
} else {
DisplayMessageT(DMP_ADD_PORT_PROXY, PpTypeInfo[Type].Token);
DisplayMessageT(DMP_STRING_ARG, TOKEN_LISTENPORT, ListenPort);
DisplayMessageT(DMP_STRING_ARG, TOKEN_CONNECTADDRESS, ConnectAddress);
DisplayMessageT(DMP_STRING_ARG, TOKEN_CONNECTPORT, ConnectPort);
DisplayMessageT(DMP_NEWLINE);
}
}
RegCloseKey(hProto);
}
RegCloseKey(hType);
}
ULONG
PpHandleShowV4ToV4(
IN LPCWSTR MachineName,
IN LPWSTR *Argv,
IN ULONG CurrentIndex,
IN ULONG Argc,
IN ULONG Flags,
IN LPCVOID Data,
OUT BOOL *Done
)
{
ShowPorts(V4TOV4, FORMAT_NORMAL);
return STATUS_SUCCESS;
}
ULONG
PpHandleShowV6ToV4(
IN LPCWSTR MachineName,
IN LPWSTR *Argv,
IN ULONG CurrentIndex,
IN ULONG Argc,
IN ULONG Flags,
IN LPCVOID Data,
OUT BOOL *Done
)
{
ShowPorts(V6TOV4, FORMAT_NORMAL);
return STATUS_SUCCESS;
}
ULONG
PpHandleShowV4ToV6(
IN LPCWSTR MachineName,
IN LPWSTR *Argv,
IN ULONG CurrentIndex,
IN ULONG Argc,
IN ULONG Flags,
IN LPCVOID Data,
OUT BOOL *Done
)
{
ShowPorts(V4TOV6, FORMAT_NORMAL);
return STATUS_SUCCESS;
}
ULONG
PpHandleShowV6ToV6(
IN LPCWSTR MachineName,
IN LPWSTR *Argv,
IN ULONG CurrentIndex,
IN ULONG Argc,
IN ULONG Flags,
IN LPCVOID Data,
OUT BOOL *Done
)
{
ShowPorts(V6TOV6, FORMAT_NORMAL);
return STATUS_SUCCESS;
}
ULONG
PpHandleShowAll(
IN LPCWSTR MachineName,
IN LPWSTR *Argv,
IN ULONG CurrentIndex,
IN ULONG Argc,
IN ULONG Flags,
IN LPCVOID Data,
OUT BOOL *Done
)
{
ShowPorts(V4TOV4, FORMAT_NORMAL);
ShowPorts(V4TOV6, FORMAT_NORMAL);
ShowPorts(V6TOV4, FORMAT_NORMAL);
ShowPorts(V6TOV6, FORMAT_NORMAL);
return STATUS_SUCCESS;
}
PWCHAR
PpFormValue(
IN PWCHAR Address,
IN PWCHAR Port
)
{
ULONG Length;
PWCHAR Value;
Length = wcslen(Address) + wcslen(Port) + 2;
Value = MALLOC(Length * sizeof(WCHAR));
swprintf(Value, L"%s/%s", Address, Port);
return Value;
}
TOKEN_VALUE g_ProtocolEnum[] = {{ TOKEN_VALUE_TCP, IPPROTO_TCP }};
ULONG
PpHandleAddSetPort(
IN PPTYPE Type,
IN LPWSTR *Argv,
IN ULONG CurrentIndex,
IN ULONG Argc
)
{
ULONG Status, i;
TAG_TYPE Tags[] = {{TOKEN_LISTENPORT, NS_REQ_PRESENT, FALSE},
{TOKEN_CONNECTADDRESS, NS_REQ_ZERO, FALSE},
{TOKEN_CONNECTPORT, NS_REQ_ZERO, FALSE},
{TOKEN_LISTENADDRESS, NS_REQ_ZERO, FALSE},
{TOKEN_PROTOCOL, NS_REQ_ZERO, FALSE}};
ULONG TagType[sizeof(Tags)/sizeof(TAG_TYPE)];
PWCHAR ListenAddress = NULL, ListenPort = NULL;
PWCHAR ConnectAddress = NULL, ConnectPort = NULL;
PWCHAR ProtocolString = NULL;
ULONG Protocol = IPPROTO_TCP;
PWCHAR KeyValue, KeyData;
HKEY hType, hProto;
if ((Type == V4TOV4) || (Type == V6TOV6)) {
Tags[1].dwRequired = NS_REQ_PRESENT;
}
Status = PreprocessCommand(g_hModule,
Argv,
CurrentIndex,
Argc,
Tags,
sizeof(Tags)/sizeof(TAG_TYPE),
0,
sizeof(Tags)/sizeof(TAG_TYPE),
TagType);
for (i=0; (Status == NO_ERROR) && (i < Argc-CurrentIndex); i++) {
switch (TagType[i]) {
case 0: // LISTENPORT
ListenPort = Argv[CurrentIndex + i];
break;
case 1: // CONNECTADDRESS
ConnectAddress = Argv[CurrentIndex + i];
break;
case 2: // CONNECTPORT
ConnectPort = Argv[CurrentIndex + i];
break;
case 3: // LISTENADDRESS
ListenAddress = Argv[CurrentIndex + i];
break;
case 4: // PROTOCOL
Status = MatchEnumTag(NULL,
Argv[CurrentIndex + i],
NUM_TOKENS_IN_TABLE(g_ProtocolEnum),
g_ProtocolEnum,
(PULONG)&Protocol);
if (Status != NO_ERROR) {
Status = ERROR_INVALID_PARAMETER;
}
ProtocolString = Argv[CurrentIndex + i];
break;
default:
Status = ERROR_INVALID_SYNTAX;
break;
}
}
if (Status != NO_ERROR) {
return Status;
}
if (ConnectAddress == NULL) {
ConnectAddress = L"localhost";
}
if (ListenAddress == NULL) {
ListenAddress = L"*";
}
if (ProtocolString == NULL) {
ProtocolString = TOKEN_VALUE_TCP;
}
if (ConnectPort == NULL) {
ConnectPort = ListenPort;
}
Status = RegCreateKeyEx(HKEY_LOCAL_MACHINE, PpTypeInfo[Type].KeyString, 0,
NULL, 0, KEY_ALL_ACCESS, NULL, &hType, NULL);
if (Status != NO_ERROR) {
return Status;
}
Status = RegCreateKeyEx(hType, ProtocolString, 0,
NULL, 0, KEY_ALL_ACCESS, NULL, &hProto, NULL);
if (Status != NO_ERROR) {
RegCloseKey(hType);
return Status;
}
KeyValue = PpFormValue(ListenAddress, ListenPort);
KeyData = PpFormValue(ConnectAddress, ConnectPort);
if (KeyValue && KeyData) {
Status = RegSetValueEx(hProto, KeyValue, 0, REG_SZ, (PVOID)KeyData,
wcslen(KeyData) * sizeof(WCHAR));
FREE(KeyValue);
}
RegCloseKey(hProto);
RegCloseKey(hType);
Ip6to4PokeService();
return Status;
}
ULONG
PpHandleDeletePort(
IN PPTYPE Type,
IN LPWSTR *Argv,
IN ULONG CurrentIndex,
IN ULONG Argc
)
{
ULONG Status, i;
TAG_TYPE Tags[] = {{TOKEN_LISTENPORT, NS_REQ_PRESENT, FALSE},
{TOKEN_LISTENADDRESS, NS_REQ_ZERO, FALSE},
{TOKEN_PROTOCOL, NS_REQ_ZERO, FALSE}};
ULONG TagType[sizeof(Tags)/sizeof(TAG_TYPE)];
PWCHAR ListenAddress = NULL, ListenPort = NULL;
PWCHAR ConnectAddress = NULL, ConnectPort = NULL;
ULONG Protocol;
PWCHAR ProtocolString = NULL;
HKEY hType, hProto;
PWCHAR Value;
Status = PreprocessCommand(g_hModule,
Argv,
CurrentIndex,
Argc,
Tags,
sizeof(Tags)/sizeof(TAG_TYPE),
0,
sizeof(Tags)/sizeof(TAG_TYPE),
TagType);
for (i=0; (Status == NO_ERROR) && (i < Argc-CurrentIndex); i++) {
switch (TagType[i]) {
case 0: // LISTENPORT
ListenPort = Argv[CurrentIndex + i];
break;
case 1: // LISTENADDRESS
ListenAddress = Argv[CurrentIndex + i];
break;
case 2: // PROTOCOL
Status = MatchEnumTag(NULL,
Argv[CurrentIndex + i],
NUM_TOKENS_IN_TABLE(g_ProtocolEnum),
g_ProtocolEnum,
(PULONG)&Protocol);
if (Status != NO_ERROR) {
Status = ERROR_INVALID_PARAMETER;
}
ProtocolString = Argv[CurrentIndex + i];
break;
default:
Status = ERROR_INVALID_SYNTAX;
break;
}
}
if (Status != NO_ERROR) {
return Status;
}
if (ListenAddress == NULL) {
ListenAddress = L"*";
}
if (ProtocolString == NULL) {
ProtocolString = TOKEN_VALUE_TCP;
}
Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, PpTypeInfo[Type].KeyString, 0,
KEY_ALL_ACCESS, &hType);
if (Status != NO_ERROR) {
return Status;
}
Status = RegOpenKeyEx(hType, ProtocolString, 0, KEY_ALL_ACCESS, &hProto);
if (Status != NO_ERROR) {
RegCloseKey(hType);
return Status;
}
Value = PpFormValue(ListenAddress, ListenPort);
if (Value) {
Status = RegDeleteValue(hProto, Value);
FREE(Value);
}
RegCloseKey(hProto);
RegCloseKey(hType);
Ip6to4PokeService();
return Status;
}
ULONG
PpHandleDelV4ToV4(
IN LPCWSTR MachineName,
IN LPWSTR *Argv,
IN ULONG CurrentIndex,
IN ULONG Argc,
IN ULONG Flags,
IN LPCVOID Data,
OUT BOOL *Done
)
{
return PpHandleDeletePort(V4TOV4, Argv, CurrentIndex, Argc);
}
ULONG
PpHandleDelV4ToV6(
IN LPCWSTR MachineName,
IN LPWSTR *Argv,
IN ULONG CurrentIndex,
IN ULONG Argc,
IN ULONG Flags,
IN LPCVOID Data,
OUT BOOL *Done
)
{
return PpHandleDeletePort(V4TOV6, Argv, CurrentIndex, Argc);
}
ULONG
PpHandleDelV6ToV4(
IN LPCWSTR MachineName,
IN LPWSTR *Argv,
IN ULONG CurrentIndex,
IN ULONG Argc,
IN ULONG Flags,
IN LPCVOID Data,
OUT BOOL *Done
)
{
return PpHandleDeletePort(V6TOV4, Argv, CurrentIndex, Argc);
}
ULONG
PpHandleDelV6ToV6(
IN LPCWSTR MachineName,
IN LPWSTR *Argv,
IN ULONG CurrentIndex,
IN ULONG Argc,
IN ULONG Flags,
IN LPCVOID Data,
OUT BOOL *Done
)
{
return PpHandleDeletePort(V6TOV6, Argv, CurrentIndex, Argc);
}
ULONG
PpHandleAddSetV4ToV4(
IN LPCWSTR MachineName,
IN LPWSTR *Argv,
IN ULONG CurrentIndex,
IN ULONG Argc,
IN ULONG Flags,
IN LPCVOID Data,
OUT BOOL *Done
)
{
return PpHandleAddSetPort(V4TOV4, Argv, CurrentIndex, Argc);
}
ULONG
PpHandleAddSetV4ToV6(
IN LPCWSTR MachineName,
IN LPWSTR *Argv,
IN ULONG CurrentIndex,
IN ULONG Argc,
IN ULONG Flags,
IN LPCVOID Data,
OUT BOOL *Done
)
{
return PpHandleAddSetPort(V4TOV6, Argv, CurrentIndex, Argc);
}
ULONG
PpHandleAddSetV6ToV4(
IN LPCWSTR MachineName,
IN LPWSTR *Argv,
IN ULONG CurrentIndex,
IN ULONG Argc,
IN ULONG Flags,
IN LPCVOID Data,
OUT BOOL *Done
)
{
return PpHandleAddSetPort(V6TOV4, Argv, CurrentIndex, Argc);
}
ULONG
PpHandleAddSetV6ToV6(
IN LPCWSTR MachineName,
IN LPWSTR *Argv,
IN ULONG CurrentIndex,
IN ULONG Argc,
IN ULONG Flags,
IN LPCVOID Data,
OUT BOOL *Done
)
{
return PpHandleAddSetPort(V6TOV6, Argv, CurrentIndex, Argc);
}
VOID
PpReset(
IN PPTYPE Type
)
{
HKEY hType;
ULONG Status;
Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, PpTypeInfo[Type].KeyString, 0,
KEY_ALL_ACCESS, &hType);
if (Status != NO_ERROR) {
return;
}
SHDeleteKey(hType, TOKEN_VALUE_TCP);
RegCloseKey(hType);
Ip6to4PokeService();
}
ULONG
PpHandleReset(
IN LPCWSTR MachineName,
IN LPWSTR *Argv,
IN ULONG CurrentIndex,
IN ULONG Argc,
IN ULONG Flags,
IN LPCVOID Data,
OUT BOOL *Done
)
{
PpReset(V4TOV4);
PpReset(V4TOV6);
PpReset(V6TOV4);
PpReset(V6TOV6);
return STATUS_SUCCESS;
}
DWORD
WINAPI
PpDump(
IN LPCWSTR pwszRouter,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwArgCount,
IN LPCVOID pvData
)
{
// DisplayMessage(g_hModule, DMP_PP_HEADER_COMMENTS);
DisplayMessageT(DMP_PP_PUSHD);
ShowPorts(V4TOV4, FORMAT_DUMP);
ShowPorts(V4TOV6, FORMAT_DUMP);
ShowPorts(V6TOV4, FORMAT_DUMP);
ShowPorts(V6TOV6, FORMAT_DUMP);
DisplayMessageT(DMP_PP_POPD);
// DisplayMessage(g_hModule, DMP_PP_FOOTER_COMMENTS);
return NO_ERROR;
}