//============================================================================= // Copyright (c) 2000 Microsoft Corporation // Abstract: // This module implements 6to4 configuration commands. //============================================================================= #include "precomp.h" #pragma hdrstop #define KEY_ENABLE_6TO4 L"Enable6to4" #define KEY_ENABLE_RESOLUTION L"EnableResolution" #define KEY_ENABLE_ROUTING L"EnableRouting" #define KEY_ENABLE_SITELOCALS L"EnableSiteLocals" #define KEY_RESOLUTION_INTERVAL L"ResolutionInterval" #define KEY_UNDO_ON_STOP L"UndoOnStop" #define KEY_RELAY_NAME L"RelayName" PWCHAR pwszStateString[] = { TOKEN_VALUE_DEFAULT, TOKEN_VALUE_AUTOMATIC, TOKEN_VALUE_ENABLED, TOKEN_VALUE_DISABLED, }; // The guid for this context // GUID g_Ip6to4Guid = IP6TO4_GUID; // The commands supported in this context // CMD_ENTRY g_Ip6to4SetCmdTable[] = { CREATE_CMD_ENTRY(IP6TO4_SET_INTERFACE,Ip6to4HandleSetInterface), CREATE_CMD_ENTRY(IP6TO4_SET_RELAY, Ip6to4HandleSetRelay), CREATE_CMD_ENTRY(IP6TO4_SET_ROUTING, Ip6to4HandleSetRouting), CREATE_CMD_ENTRY(IP6TO4_SET_STATE, Ip6to4HandleSetState), }; CMD_ENTRY g_Ip6to4ShowCmdTable[] = { CREATE_CMD_ENTRY(IP6TO4_SHOW_INTERFACE,Ip6to4HandleShowInterface), CREATE_CMD_ENTRY(IP6TO4_SHOW_RELAY, Ip6to4HandleShowRelay), CREATE_CMD_ENTRY(IP6TO4_SHOW_ROUTING, Ip6to4HandleShowRouting), CREATE_CMD_ENTRY(IP6TO4_SHOW_STATE, Ip6to4HandleShowState), }; CMD_GROUP_ENTRY g_Ip6to4CmdGroups[] = { CREATE_CMD_GROUP_ENTRY(GROUP_SET, g_Ip6to4SetCmdTable), CREATE_CMD_GROUP_ENTRY(GROUP_SHOW, g_Ip6to4ShowCmdTable), }; ULONG g_ulIp6to4NumGroups = sizeof(g_Ip6to4CmdGroups)/sizeof(CMD_GROUP_ENTRY); CMD_ENTRY g_Ip6to4TopCmds[] = { CREATE_CMD_ENTRY(IP6TO4_RESET, Ip6to4HandleReset), }; ULONG g_ulNumIp6to4TopCmds = sizeof(g_Ip6to4TopCmds)/sizeof(CMD_ENTRY); #if 0 TOKEN_VALUE AdminStates[] = { { VAL_AUTOMATIC, TOKEN_AUTOMATIC }, { VAL_ENABLED, TOKEN_ENABLED }, { VAL_DISABLED, TOKEN_DISABLED }, { VAL_DEFAULT, TOKEN_DEFAULT }, }; #endif BOOL GetString( IN HKEY hKey, IN LPCTSTR lpName, IN PWCHAR pwszBuff, IN ULONG ulLength) { DWORD dwErr, dwType; ULONG ulSize, ulValue; if (hKey == INVALID_HANDLE_VALUE) { return FALSE; } ulSize = sizeof(ulValue); dwErr = RegQueryValueEx(hKey, lpName, NULL, &dwType, (PBYTE)pwszBuff, &ulLength); if (dwErr != ERROR_SUCCESS) { return FALSE; } if (dwType != REG_SZ) { return FALSE; } return TRUE; } ULONG GetInteger( IN HKEY hKey, IN LPCTSTR lpName, IN ULONG ulDefault) { DWORD dwErr, dwType; ULONG ulSize, ulValue; if (hKey == INVALID_HANDLE_VALUE) { return ulDefault; } ulSize = sizeof(ulValue); dwErr = RegQueryValueEx(hKey, lpName, NULL, &dwType, (PBYTE)&ulValue, &ulSize); if (dwErr != ERROR_SUCCESS) { return ulDefault; } if (dwType != REG_DWORD) { return ulDefault; } return ulValue; } DWORD SetInteger( IN HKEY hKey, IN LPCTSTR lpName, IN ULONG ulValue) { DWORD dwErr; ULONG ulOldValue; ASSERT(hKey != INVALID_HANDLE_VALUE); ulOldValue = GetInteger(hKey, lpName, VAL_DEFAULT); if (ulValue == ulOldValue) { return NO_ERROR; } if (ulValue == VAL_DEFAULT) { dwErr = RegDeleteValue(hKey, lpName); if (dwErr == ERROR_FILE_NOT_FOUND) { dwErr = NO_ERROR; } } else { dwErr = RegSetValueEx(hKey, lpName, 0, REG_DWORD, (PBYTE)&ulValue, sizeof(ulValue)); } return dwErr; } DWORD SetString( IN HKEY hKey, IN LPCTSTR lpName, IN PWCHAR pwcValue) { DWORD dwErr; ASSERT(hKey != INVALID_HANDLE_VALUE); if (!pwcValue[0] || !_wcsicmp(pwcValue, TOKEN_VALUE_DEFAULT)) { dwErr = RegDeleteValue(hKey, lpName); if (dwErr == ERROR_FILE_NOT_FOUND) { dwErr = NO_ERROR; } } else { dwErr = RegSetValueEx(hKey, lpName, 0, REG_SZ, (PBYTE)pwcValue, (DWORD) (wcslen(pwcValue)+1) * sizeof(WCHAR)); } return dwErr; } DWORD ResetKey( IN HKEY hKey, IN PWCHAR pwcSubKey) /*++ Routine Description Used to delete everything under a key without deleting the key itself. We use this where we would otherwise just use SHDeleteKey or RegDeleteKey but we need to preserve the ACL on the key itself. Arguments hKey Handle to parent of key to reset. pwcSubKey Name of key to reset. --*/ { ULONG Status, ValueNameChars; HKEY hSubKey; // // All values we care about resetting are short. // WCHAR ValueName[256]; Status = RegOpenKeyExW(hKey, pwcSubKey, 0, KEY_READ | KEY_WRITE, &hSubKey); if (Status != NO_ERROR) { return Status; } // // First delete values. // while (Status == NO_ERROR) { // // RegEnumValue takes the size in characters, including space // for the NULL, and ensures NULL termination on success. // ValueNameChars = sizeof(ValueName)/sizeof(WCHAR); Status = RegEnumValueW(hSubKey, 0, ValueName, &ValueNameChars, NULL, NULL, NULL, NULL); if (Status != NO_ERROR) { if (Status == ERROR_NO_MORE_ITEMS) { Status = NO_ERROR; } break; } Status = RegDeleteValueW(hSubKey, ValueName); } // // Now delete any subkeys. // while (Status == NO_ERROR) { // // RegEnumKeyEx takes the size in characters, including space // for the NULL, and ensures NULL termination on success. // ValueNameChars = sizeof(ValueName)/sizeof(WCHAR); Status = RegEnumKeyExW(hSubKey, 0, ValueName, &ValueNameChars, NULL, NULL, NULL, NULL); if (Status != NO_ERROR) { if (Status == ERROR_NO_MORE_ITEMS) { Status = NO_ERROR; } break; } Status = RegDeleteKey(hSubKey, ValueName); } RegCloseKey(hSubKey); return Status; } DWORD WINAPI Ip6to4StartHelper( IN CONST GUID *pguidParent, IN DWORD dwVersion) /*++ Routine Description Used to initialize the helper. Arguments pguidParent Ifmon's guid pfnRegisterContext Return Value NO_ERROR other error code --*/ { DWORD dwErr = NO_ERROR; NS_CONTEXT_ATTRIBUTES attMyAttributes; // Initialize // ZeroMemory(&attMyAttributes, sizeof(attMyAttributes)); attMyAttributes.pwszContext = L"6to4"; attMyAttributes.guidHelper = g_Ip6to4Guid; attMyAttributes.dwVersion = IP6TO4_VERSION; attMyAttributes.dwFlags = 0; attMyAttributes.pfnDumpFn = Ip6to4Dump; attMyAttributes.ulNumTopCmds= g_ulNumIp6to4TopCmds; attMyAttributes.pTopCmds = (CMD_ENTRY (*)[])&g_Ip6to4TopCmds; attMyAttributes.ulNumGroups = g_ulIp6to4NumGroups; attMyAttributes.pCmdGroups = (CMD_GROUP_ENTRY (*)[])&g_Ip6to4CmdGroups; dwErr = RegisterContext( &attMyAttributes ); if (dwErr != NO_ERROR) { return dwErr; } // // Register ISATAP context. // return IsatapStartHelper(pguidParent, dwVersion); } DWORD Ip6to4PokeService() { SC_HANDLE hService, hSCManager; SERVICE_STATUS ServiceStatus; DWORD dwErr = NO_ERROR; hSCManager = OpenSCManager(NULL, NULL, GENERIC_READ); if (hSCManager == NULL) { return GetLastError(); } hService = OpenService(hSCManager, L"6to4", SERVICE_ALL_ACCESS); if (hService == NULL) { dwErr = GetLastError(); } else { // Tell the 6to4 service to re-read its config info if (!ControlService(hService, SERVICE_CONTROL_PARAMCHANGE, &ServiceStatus)) { dwErr = GetLastError(); } CloseServiceHandle(hService); } CloseServiceHandle(hSCManager); return dwErr; } TOKEN_VALUE rgtvEnums[] = { { TOKEN_VALUE_AUTOMATIC, VAL_AUTOMATIC }, { TOKEN_VALUE_ENABLED, VAL_ENABLED }, { TOKEN_VALUE_DISABLED, VAL_DISABLED }, { TOKEN_VALUE_DEFAULT, VAL_DEFAULT }, }; #define BM_ENABLE_ROUTING 0x01 #define BM_ENABLE_SITELOCALS 0x02 DWORD Ip6to4HandleSetInterface( IN LPCWSTR pwszMachine, IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN DWORD dwFlags, IN LPCVOID pvData, OUT BOOL *pbDone ) { DWORD dwErr = NO_ERROR; HKEY hInterfaces, hIf; STATE stEnableRouting = 0; DWORD dwBitVector = 0; TAG_TYPE pttTags[] = {{TOKEN_NAME, TRUE, FALSE}, {TOKEN_ROUTING, TRUE, FALSE}}; DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)]; DWORD i; WCHAR wszInterfaceName[MAX_INTERFACE_NAME_LEN + 1] = L"\0"; DWORD dwBufferSize = sizeof(wszInterfaceName); PWCHAR wszIfFriendlyName = NULL; // Parse arguments dwErr = PreprocessCommand(g_hModule, ppwcArguments, dwCurrentIndex, dwArgCount, pttTags, sizeof(pttTags)/sizeof(TAG_TYPE), 2, sizeof(pttTags)/sizeof(TAG_TYPE), rgdwTagType ); if (dwErr isnot NO_ERROR) { return dwErr; } for (i=0; i 0)) { DisplayMessageT(DMP_IP6TO4_SET_RELAY); if (bHaveRelayName) { DisplayMessageT(DMP_STRING_ARG, TOKEN_NAME, pwszRelayName); } if (stEnableResolution != VAL_DEFAULT) { DisplayMessageT(DMP_STRING_ARG, TOKEN_STATE, pwszStateString[stEnableResolution]); } if (ulResolutionInterval > 0) { DisplayMessageT(DMP_INTEGER_ARG, TOKEN_INTERVAL, ulResolutionInterval); } DisplayMessage(g_hModule, MSG_NEWLINE); } } else { DisplayMessage(g_hModule, MSG_RELAY_NAME); if (bHaveRelayName) { DisplayMessage(g_hModule, MSG_STRING, pwszRelayName); } else { DisplayMessage(g_hModule, MSG_STRING, TOKEN_VALUE_DEFAULT); } DisplayMessage(g_hModule, MSG_RESOLUTION_STATE, pwszStateString[stEnableResolution]); DisplayMessage(g_hModule, MSG_RESOLUTION_INTERVAL); if (ulResolutionInterval) { DisplayMessage(g_hModule, MSG_MINUTES, ulResolutionInterval); } else { DisplayMessage(g_hModule, MSG_STRING, TOKEN_VALUE_DEFAULT); } } return dwErr; } DWORD Ip6to4HandleShowRelay( IN LPCWSTR pwszMachine, IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN DWORD dwFlags, IN LPCVOID pvData, OUT BOOL *pbDone ) { return ShowRelayConfig(FALSE); } DWORD Ip6to4HandleReset( IN LPCWSTR pwszMachine, IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN DWORD dwFlags, IN LPCVOID pvData, OUT BOOL *pbDone ) { DWORD dwErr; // Nuke global params dwErr = ResetKey(HKEY_LOCAL_MACHINE, KEY_GLOBAL); if ((dwErr != NO_ERROR) && (dwErr != ERROR_FILE_NOT_FOUND)) { return dwErr; } // Nuke all interface config dwErr = ResetKey(HKEY_LOCAL_MACHINE, KEY_INTERFACES); if ((dwErr != NO_ERROR) && (dwErr != ERROR_FILE_NOT_FOUND)) { return dwErr; } // Start/poke the service Ip6to4PokeService(); return ERROR_OKAY; } DWORD ShowStateConfig( IN BOOL bDump) { DWORD dwErr = NO_ERROR; HKEY hGlobal = INVALID_HANDLE_VALUE; STATE stEnable6to4; STATE stUndoOnStop; dwErr = RegOpenKeyEx( HKEY_LOCAL_MACHINE, KEY_GLOBAL, 0, KEY_READ, &hGlobal); if (dwErr != NO_ERROR) { dwErr = NO_ERROR; } stEnable6to4 = GetInteger(hGlobal, KEY_ENABLE_6TO4, VAL_DEFAULT); stUndoOnStop = GetInteger(hGlobal, KEY_UNDO_ON_STOP, VAL_DEFAULT); if (hGlobal != INVALID_HANDLE_VALUE) { RegCloseKey(hGlobal); } if (bDump) { if ((stEnable6to4 != VAL_DEFAULT) || (stUndoOnStop != VAL_DEFAULT)) { DisplayMessageT(DMP_IP6TO4_SET_STATE); if (stEnable6to4 != VAL_DEFAULT) { DisplayMessageT(DMP_STRING_ARG, TOKEN_STATE, pwszStateString[stEnable6to4]); } if (stUndoOnStop != VAL_DEFAULT) { DisplayMessageT(DMP_STRING_ARG, TOKEN_UNDO_ON_STOP, pwszStateString[stUndoOnStop]); } DisplayMessage(g_hModule, MSG_NEWLINE); } } else { DisplayMessage(g_hModule, MSG_IP6TO4_STATE, pwszStateString[stEnable6to4]); DisplayMessage(g_hModule, MSG_UNDO_ON_STOP_STATE, pwszStateString[stUndoOnStop]); } return dwErr; } DWORD Ip6to4HandleShowState( IN LPCWSTR pwszMachine, IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN DWORD dwFlags, IN LPCVOID pvData, OUT BOOL *pbDone ) { return ShowStateConfig(FALSE); } DWORD WINAPI Ip6to4Dump( IN LPCWSTR pwszRouter, IN OUT LPWSTR *ppwcArguments, IN DWORD dwArgCount, IN LPCVOID pvData ) /*++ Routine Description Used when dumping all contexts Arguments Return Value NO_ERROR --*/ { DisplayMessage( g_hModule, DMP_IP6TO4_HEADER ); DisplayMessageT(DMP_IP6TO4_PUSHD); ShowStateConfig(TRUE); ShowRelayConfig(TRUE); ShowRoutingConfig(TRUE); ShowInterfaceConfig(TRUE); DisplayMessageT(DMP_IP6TO4_POPD); DisplayMessage( g_hModule, DMP_IP6TO4_FOOTER ); return NO_ERROR; }