/* File: rasip.h The 'remoteaccess ip' sub context 3/2/99 */ #include "precomp.h" #include "rasip.h" #include #define MMAKEIPADDRESS(b1,b2,b3,b4) \ (((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4))) #define FIRST_IPADDRESS(x) ((x>>24) & 0xff) #define SECOND_IPADDRESS(x) ((x>>16) & 0xff) #define THIRD_IPADDRESS(x) ((x>>8) & 0xff) #define FOURTH_IPADDRESS(x) (x & 0xff) // The guid for this context // GUID g_RasIpGuid = RASIP_GUID; static PWCHAR g_pszServer = NULL; static DWORD g_dwBuild = 0; // The commands supported in this context // CMD_ENTRY g_RasIpSetCmdTable[] = { CREATE_CMD_ENTRY(RASIP_SET_NEGOTIATION,RasIpHandleSetNegotiation), CREATE_CMD_ENTRY(RASIP_SET_ACCESS, RasIpHandleSetAccess), CREATE_CMD_ENTRY(RASIP_SET_ASSIGNMENT, RasIpHandleSetAssignment), CREATE_CMD_ENTRY(RASIP_SET_CALLERSPEC, RasIpHandleSetCallerSpec), CREATE_CMD_ENTRY(RASIP_SET_NETBTBCAST, RasIpHandleSetNetbtBcast), }; CMD_ENTRY g_RasIpShowCmdTable[] = { CREATE_CMD_ENTRY(RASIP_SHOW_CONFIG, RasIpHandleShow), }; CMD_ENTRY g_RasIpAddCmdTable[] = { CREATE_CMD_ENTRY(RASIP_ADD_RANGE, RasIpHandleAddRange), }; CMD_ENTRY g_RasIpDelCmdTable[] = { CREATE_CMD_ENTRY(RASIP_DEL_RANGE, RasIpHandleDelRange), CREATE_CMD_ENTRY(RASIP_DEL_POOL, RasIpHandleDelPool), }; CMD_GROUP_ENTRY g_RasIpCmdGroups[] = { CREATE_CMD_GROUP_ENTRY(GROUP_SET, g_RasIpSetCmdTable), CREATE_CMD_GROUP_ENTRY(GROUP_SHOW, g_RasIpShowCmdTable), CREATE_CMD_GROUP_ENTRY(GROUP_ADD, g_RasIpAddCmdTable), CREATE_CMD_GROUP_ENTRY(GROUP_DEL, g_RasIpDelCmdTable), }; ULONG g_ulRasIpNumGroups = sizeof(g_RasIpCmdGroups)/sizeof(CMD_GROUP_ENTRY); // // Flags that control how/what info is read/written // in the RASIP_CB structure // #define RASIP_F_EnableIn 0x1 #define RASIP_F_Access 0x2 #define RASIP_F_Auto 0x4 #define RASIP_F_Pool 0x8 #define RASIP_F_Mask 0x10 #define RASIP_F_CallerSpec 0x20 #define RASIP_F_All 0xFFFF // // Reasons for the ras ip pool to be invalid // #define RASIP_REASON_BadAddress 0x1 #define RASIP_REASON_BadRange 0x3 #define RASIP_REASON_127 0x4 // // RAS pool definition // typedef struct _RAS_IPRANGE_NODE { DWORD dwFrom; DWORD dwTo; struct _RAS_IPRANGE_NODE* pNext; } RAS_IPRANGE_NODE; typedef struct _RAS_IPPOOL { DWORD dwCount; RAS_IPRANGE_NODE* pHead; RAS_IPRANGE_NODE* pTail; } RAS_IPPOOL; // // Control block for ras ip configuration // typedef struct _RASIP_CB { DWORD dwFlags; // See RASIP_F_* values BOOL bEnableIn; BOOL bAccess; BOOL bAuto; RAS_IPPOOL* pPool; BOOL bCallerSpec; } RASIP_CB; // // Ip specific registry parameters // WCHAR pszIpParams[] = L"Ip"; WCHAR pszIpAddress[] = L"IpAddress"; WCHAR pszIpMask[] = L"IpMask"; WCHAR pszIpClientSpec[] = L"AllowClientIpAddresses"; WCHAR pszIpUseDhcp[] = L"UseDhcpAddressing"; WCHAR pszIpFrom[] = L"From"; WCHAR pszIpTo[] = L"To"; WCHAR pszIpPoolSubKey[] = L"StaticAddressPool"; // // Prototypes of functions that manipulate the // RASIP_CB structures // DWORD RasIpCbCleanup( IN RASIP_CB* pConfig); DWORD RasIpCbCreateDefault( OUT RASIP_CB** ppConfig); DWORD RasIpCbOpenRegKeys( IN LPCWSTR pszServer, OUT HKEY* phKey); DWORD RasIpCbRead( IN LPCWSTR pszServer, OUT RASIP_CB* pConfig); DWORD RasIpCbWrite( IN LPCWSTR pszServer, IN RASIP_CB* pConfig); DWORD RasIpPoolReset( IN HKEY hkParams); DWORD RasIpPoolRead( IN HKEY hkParams, OUT RAS_IPPOOL** ppRanges); DWORD RasIpPoolWrite( IN HKEY hkParams, IN RAS_IPPOOL* pPool); DWORD RasIpPoolAdd( IN OUT RAS_IPPOOL* pPool, IN DWORD dwFrom, IN DWORD dwTo); DWORD RasIpPoolDel( IN OUT RAS_IPPOOL* pPool, IN DWORD dwFrom, IN DWORD dwTo); DWORD RasIpPoolCleanup( IN RAS_IPPOOL* pPool); DWORD RasIpSetNetbtBcast( DWORD dwEnable ); BOOL RasIpShowNetbtBcast( VOID ); // // Entry called by rasmontr to register this context // DWORD WINAPI RasIpStartHelper( IN CONST GUID *pguidParent, IN DWORD dwVersion) { DWORD dwErr = NO_ERROR; NS_CONTEXT_ATTRIBUTES attMyAttributes; // Initialize // ZeroMemory(&attMyAttributes, sizeof(attMyAttributes)); attMyAttributes.pwszContext = L"ip"; attMyAttributes.guidHelper = g_RasIpGuid; attMyAttributes.dwVersion = RASIP_VERSION; attMyAttributes.dwFlags = 0; attMyAttributes.ulNumTopCmds = 0; attMyAttributes.pTopCmds = NULL; attMyAttributes.ulNumGroups = g_ulRasIpNumGroups; attMyAttributes.pCmdGroups = (CMD_GROUP_ENTRY (*)[])&g_RasIpCmdGroups; attMyAttributes.pfnDumpFn = RasIpDump; dwErr = RegisterContext( &attMyAttributes ); return dwErr; } DWORD RasIpDisplayInvalidPool( IN DWORD dwReason ) { DWORD dwArg = 0; PWCHAR pszArg = NULL; switch (dwReason) { case RASIP_REASON_BadAddress: dwArg = EMSG_RASIP_BAD_ADDRESS; break; case RASIP_REASON_BadRange: dwArg = EMSG_RASIP_BAD_RANGE; break; case RASIP_REASON_127: dwArg = EMSG_RASIP_NETID_127; break; default: dwArg = EMSG_RASIP_BAD_POOL_GENERIC; break; } // Make the argument string // pszArg = MakeString(g_hModule, dwArg); if (pszArg == NULL) { DisplayError(NULL, ERROR_NOT_ENOUGH_MEMORY); return ERROR_NOT_ENOUGH_MEMORY; } // Display the error // DisplayMessage( g_hModule, EMSG_RASIP_INVALID_POOL, pszArg); // Cleanup // FreeString(pszArg); return NO_ERROR; } DWORD RasIpDisplayPool( IN RASIP_CB* pConfig, IN BOOL bReport) { DWORD dwErr = NO_ERROR, i; RAS_IPPOOL* pPool = pConfig->pPool; RAS_IPRANGE_NODE* pNode = NULL; PWCHAR pszFrom = NULL, pszTo = NULL; WCHAR pszFromBuf[128], pszToBuf[128]; if (!pPool) { return ERROR_CAN_NOT_COMPLETE; } do { pNode = pPool->pHead; for (i = 0; i < pPool->dwCount; i++, pNode = pNode->pNext) { wsprintfW( pszFromBuf, L"%d.%d.%d.%d", FIRST_IPADDRESS(pNode->dwFrom), SECOND_IPADDRESS(pNode->dwFrom), THIRD_IPADDRESS(pNode->dwFrom), FOURTH_IPADDRESS(pNode->dwFrom)); wsprintfW( pszToBuf, L"%d.%d.%d.%d", FIRST_IPADDRESS(pNode->dwTo), SECOND_IPADDRESS(pNode->dwTo), THIRD_IPADDRESS(pNode->dwTo), FOURTH_IPADDRESS(pNode->dwTo)); if (bReport) { DisplayMessage( g_hModule, MSG_RASIP_SHOW_POOL, pszFromBuf, pszToBuf); } else { pszFrom = RutlAssignmentFromTokens(g_hModule, TOKEN_FROM, pszFromBuf); pszTo = RutlAssignmentFromTokens(g_hModule, TOKEN_TO, pszToBuf); if (pszFrom == NULL || pszTo == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; } DisplayMessage( g_hModule, MSG_RASIP_ADD_RANGE_CMD, DMP_RASIP_ADD_RANGE, pszFrom, pszTo); } } } while (FALSE); // Cleanup { RutlFree(pszFrom); RutlFree(pszTo); } return dwErr; } DWORD RasIpDisplayConfig( IN BOOL bReport) { DWORD dwErr = NO_ERROR, dwReason; RASIP_CB* pConfig = NULL; PWCHAR pszPool = NULL, pszAccess = NULL, pszAuto = NULL, pszMask = NULL; PWCHAR pszEnabled = NULL, pszCaller = NULL, pszNetbtBcast = NULL; do { // Get a default config blob // dwErr = RasIpCbCreateDefault(&pConfig); BREAK_ON_DWERR( dwErr ); // Read in all of the values // pConfig->dwFlags = RASIP_F_All; dwErr = RasIpCbRead(g_pszServer, pConfig); BREAK_ON_DWERR( dwErr ); if (bReport) { pszEnabled = RutlStrDup(pConfig->bEnableIn ? TOKEN_ALLOW : TOKEN_DENY); pszAccess = RutlStrDup(pConfig->bAccess ? TOKEN_ALL : TOKEN_SERVERONLY); pszAuto = RutlStrDup(pConfig->bAuto ? TOKEN_AUTO : TOKEN_POOL); pszCaller = RutlStrDup(pConfig->bCallerSpec ? TOKEN_ALLOW : TOKEN_DENY); // Whistler bug: 359847 Netsh: move broadcastnameresolution from // routing ip to ras ip // pszNetbtBcast = RutlStrDup(RasIpShowNetbtBcast() ? TOKEN_ENABLED : TOKEN_DISABLED); DisplayMessage( g_hModule, MSG_RASIP_SERVERCONFIG, g_pszServer, pszEnabled, pszAccess, pszAuto, pszCaller, pszNetbtBcast); RasIpDisplayPool(pConfig, bReport); } else { pszEnabled = RutlAssignmentFromTokens( g_hModule, TOKEN_MODE, pConfig->bEnableIn ? TOKEN_ALLOW : TOKEN_DENY); pszAccess = RutlAssignmentFromTokens( g_hModule, TOKEN_MODE, pConfig->bAccess ? TOKEN_ALL : TOKEN_SERVERONLY); pszAuto = RutlAssignmentFromTokens( g_hModule, TOKEN_METHOD, pConfig->bAuto ? TOKEN_AUTO : TOKEN_POOL); pszCaller = RutlAssignmentFromTokens( g_hModule, TOKEN_MODE, pConfig->bCallerSpec ? TOKEN_ALLOW : TOKEN_DENY); // Whistler bug: 359847 Netsh: move broadcastnameresolution from // routing ip to ras ip // pszNetbtBcast = RutlAssignmentFromTokens( g_hModule, TOKEN_MODE, RasIpShowNetbtBcast() ? TOKEN_ENABLED : TOKEN_DISABLED); DisplayMessage( g_hModule, MSG_RASIP_SCRIPTHEADER); DisplayMessageT(DMP_RASIP_PUSHD); DisplayMessageT( DMP_RASIP_DEL_POOL); DisplayMessageT(MSG_NEWLINE); DisplayMessageT(MSG_NEWLINE); DisplayMessage( g_hModule, MSG_RASIP_SET_CMD, DMP_RASIP_SET_NEGOTIATION, pszEnabled); DisplayMessage( g_hModule, MSG_RASIP_SET_CMD, DMP_RASIP_SET_ACCESS, pszAccess); DisplayMessage( g_hModule, MSG_RASIP_SET_CMD, DMP_RASIP_SET_CALLERSPEC, pszCaller); DisplayMessage( g_hModule, MSG_RASIP_SET_CMD, DMP_RASIP_SET_NETBTBCAST, pszNetbtBcast); if (! pConfig->bAuto) { RasIpDisplayPool(pConfig, bReport); } DisplayMessage( g_hModule, MSG_RASIP_SET_CMD, DMP_RASIP_SET_ASSIGNMENT, pszAuto); DisplayMessageT(DMP_RASIP_POPD); DisplayMessage( g_hModule, MSG_RASIP_SCRIPTFOOTER); } } while (FALSE); // Cleanup { if (pConfig) { RasIpCbCleanup(pConfig); } if (pszEnabled) { RutlFree(pszEnabled); } if (pszAccess) { RutlFree(pszAccess); } if (pszAuto) { RutlFree(pszAuto); } if (pszCaller) { RutlFree(pszCaller); } if (pszNetbtBcast) { RutlFree(pszNetbtBcast); } if (pszPool) { RutlFree(pszPool); } if (pszMask) { RutlFree(pszMask); } } return dwErr; } DWORD WINAPI RasIpDump( IN LPCWSTR pwszRouter, IN OUT LPWSTR *ppwcArguments, IN DWORD dwArgCount, IN LPCVOID pvData ) { return RasIpDisplayConfig(FALSE); } // // Returns NO_ERROR if the given address is a valid IP pool. // The offending component is returned in lpdwErrReason. // See RASIP_F_* values // DWORD RasIpValidateRange( IN DWORD dwFrom, IN DWORD dwTo, OUT LPDWORD lpdwErrReason ) { DWORD dwLowIp, dwHighIp; // Initialize // *lpdwErrReason = 0; dwLowIp = MMAKEIPADDRESS(1,0,0,0); dwHighIp = MMAKEIPADDRESS(224,0,0,0); // Make sure that the netId is a valid class // if ((dwFrom < dwLowIp) || (dwFrom >= dwHighIp) || (dwTo < dwLowIp) || (dwTo >= dwHighIp)) { *lpdwErrReason = RASIP_REASON_BadAddress; return ERROR_BAD_FORMAT; } if ((FIRST_IPADDRESS(dwFrom) == 127) || (FIRST_IPADDRESS(dwTo) == 127)) { *lpdwErrReason = RASIP_REASON_127; return ERROR_BAD_FORMAT; } if (!(dwFrom <= dwTo)) { *lpdwErrReason = RASIP_REASON_BadRange; return ERROR_BAD_FORMAT; } return NO_ERROR; } DWORD RasIpConvertRangePszToDword( IN LPCWSTR pszFrom, IN LPCWSTR pszTo, OUT LPDWORD lpdwFrom, OUT LPDWORD lpdwTo) { DWORD dwFrom = 0, dwTo = 0; CHAR pszFromA[64], pszToA[64]; // Whistler bug 259799 PREFIX // if (NULL == pszFrom || NULL == pszTo) { return ERROR_INVALID_PARAMETER; } wcstombs(pszFromA, pszFrom, sizeof(pszFromA)); dwFrom = inet_addr(pszFromA); if (dwFrom == INADDR_NONE) { return ERROR_BAD_FORMAT; } wcstombs(pszToA, pszTo, sizeof(pszToA)); dwTo = inet_addr(pszToA); if (dwTo == INADDR_NONE) { return ERROR_BAD_FORMAT; } // Convert for x86 // *lpdwFrom = ntohl(dwFrom); *lpdwTo = ntohl(dwTo); return NO_ERROR; } DWORD RasIpHandleSetAccess( 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, dwValue = 0; RASIP_CB Config; TOKEN_VALUE rgEnumMode[] = { {TOKEN_ALL, TRUE}, {TOKEN_SERVERONLY, FALSE} }; RASMON_CMD_ARG pArgs[] = { { RASMONTR_CMD_TYPE_ENUM, {TOKEN_MODE, TRUE, FALSE}, rgEnumMode, sizeof(rgEnumMode)/sizeof(*rgEnumMode), NULL } }; do { // Parse the command line // dwErr = RutlParse( ppwcArguments, dwCurrentIndex, dwArgCount, pbDone, pArgs, sizeof(pArgs)/sizeof(*pArgs)); BREAK_ON_DWERR( dwErr ); dwValue = RASMON_CMD_ARG_GetDword(&pArgs[0]); // If successful, go ahead and set the info // ZeroMemory(&Config, sizeof(Config)); Config.dwFlags = RASIP_F_Access; Config.bAccess = dwValue; dwErr = RasIpCbWrite(g_pszServer, &Config); if (dwErr != NO_ERROR) { DisplayError(NULL, dwErr); break; } } while (FALSE); // Cleanup { } return dwErr; } DWORD RasIpHandleSetAssignment( 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, dwValue = 0, dwReason = 0; RASIP_CB* pConfig = NULL; TOKEN_VALUE rgEnum[] = { {TOKEN_AUTO, TRUE}, {TOKEN_POOL, FALSE} }; RASMON_CMD_ARG pArgs[] = { { RASMONTR_CMD_TYPE_ENUM, {TOKEN_METHOD, TRUE, FALSE}, rgEnum, sizeof(rgEnum)/sizeof(*rgEnum), NULL } }; // Initialize RasIpCbCreateDefault(&pConfig); do { // Parse the command line // dwErr = RutlParse( ppwcArguments, dwCurrentIndex, dwArgCount, pbDone, pArgs, sizeof(pArgs)/sizeof(*pArgs)); BREAK_ON_DWERR( dwErr ); dwValue = RASMON_CMD_ARG_GetDword(&pArgs[0]); // If this is an attempt to switch to pool mode, // make sure there is a valid pool. // if (dwValue == FALSE) { pConfig->dwFlags = RASIP_F_Pool | RASIP_F_Mask; dwErr = RasIpCbRead(g_pszServer, pConfig); BREAK_ON_DWERR( dwErr ); if (pConfig->pPool->dwCount == 0) { DisplayMessage( g_hModule, EMSG_RASIP_NEED_VALID_POOL, DMP_RASIP_ADD_RANGE); dwErr = ERROR_CAN_NOT_COMPLETE; break; } } // If successful, go ahead and set the info // pConfig->dwFlags = RASIP_F_Auto; pConfig->bAuto = dwValue; dwErr = RasIpCbWrite(g_pszServer, pConfig); if (dwErr != NO_ERROR) { DisplayError(NULL, dwErr); break; } } while (FALSE); // Cleanup { RasIpCbCleanup(pConfig); } return dwErr; } DWORD RasIpHandleSetCallerSpec( 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, dwValue = 0; RASIP_CB Config; TOKEN_VALUE rgEnum[] = { {TOKEN_ALLOW, TRUE}, {TOKEN_DENY, FALSE} }; RASMON_CMD_ARG pArgs[] = { { RASMONTR_CMD_TYPE_ENUM, {TOKEN_MODE, TRUE, FALSE}, rgEnum, sizeof(rgEnum)/sizeof(*rgEnum), NULL } }; do { // Parse the command line // dwErr = RutlParse( ppwcArguments, dwCurrentIndex, dwArgCount, pbDone, pArgs, sizeof(pArgs)/sizeof(*pArgs)); BREAK_ON_DWERR( dwErr ); dwValue = RASMON_CMD_ARG_GetDword(&pArgs[0]); // If successful, go ahead and set the info // ZeroMemory(&Config, sizeof(Config)); Config.dwFlags = RASIP_F_CallerSpec; Config.bCallerSpec = dwValue; dwErr = RasIpCbWrite(g_pszServer, &Config); if (dwErr != NO_ERROR) { DisplayError(NULL, dwErr); break; } } while (FALSE); // Cleanup { } return dwErr; } DWORD RasIpHandleSetNegotiation( 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, dwValue = 0; RASIP_CB Config; TOKEN_VALUE rgEnum[] = { {TOKEN_ALLOW, TRUE}, {TOKEN_DENY, FALSE} }; RASMON_CMD_ARG pArgs[] = { { RASMONTR_CMD_TYPE_ENUM, {TOKEN_MODE, TRUE, FALSE}, rgEnum, sizeof(rgEnum)/sizeof(*rgEnum), NULL } }; do { // Parse the command line // dwErr = RutlParse( ppwcArguments, dwCurrentIndex, dwArgCount, pbDone, pArgs, sizeof(pArgs)/sizeof(*pArgs)); BREAK_ON_DWERR( dwErr ); dwValue = RASMON_CMD_ARG_GetDword(&pArgs[0]); // If successful, go ahead and set the info // ZeroMemory(&Config, sizeof(Config)); Config.dwFlags = RASIP_F_EnableIn; Config.bEnableIn = dwValue; dwErr = RasIpCbWrite(g_pszServer, &Config); if (dwErr != NO_ERROR) { DisplayError(NULL, dwErr); break; } } while (FALSE); // Cleanup { } return dwErr; } // // Get options to set NETBT broadcast enable/disable // ppwcArguments - Argument array // dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg // dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg // // Whistler bug: 359847 Netsh: move broadcastnameresolution from routing ip to // ras ip // DWORD RasIpHandleSetNetbtBcast( 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, dwValue = 0; TOKEN_VALUE rgEnum[] = { {TOKEN_ENABLED, TRUE}, {TOKEN_DISABLED, FALSE} }; RASMON_CMD_ARG pArgs[] = { { RASMONTR_CMD_TYPE_ENUM, {TOKEN_MODE, TRUE, FALSE}, rgEnum, sizeof(rgEnum)/sizeof(*rgEnum), NULL } }; do { // Parse the command line // dwErr = RutlParse( ppwcArguments, dwCurrentIndex, dwArgCount, pbDone, pArgs, sizeof(pArgs)/sizeof(*pArgs)); BREAK_ON_DWERR( dwErr ); dwValue = RASMON_CMD_ARG_GetDword(&pArgs[0]); // If successful, go ahead and set the info // dwErr = RasIpSetNetbtBcast(dwValue); if (dwErr != NO_ERROR) { DisplayError(NULL, dwErr); break; } } while (FALSE); // Cleanup { } return dwErr; } DWORD RasIpHandleAddDelRange( IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN BOOL *pbDone, IN BOOL bAdd ) { PWCHAR pszFrom = NULL, pszTo = NULL; DWORD dwFrom = 0, dwTo = 0, dwErr = NO_ERROR, dwReason; RASIP_CB * pConfig = NULL; RASMON_CMD_ARG pArgs[] = { { RASMONTR_CMD_TYPE_STRING, {TOKEN_FROM, TRUE, FALSE}, NULL, 0, NULL }, { RASMONTR_CMD_TYPE_STRING, {TOKEN_TO, TRUE, FALSE}, NULL, 0, NULL } }; PWCHAR pszAddr = NULL, pszMask = NULL; do { pConfig = (RASIP_CB*) RutlAlloc(sizeof(RASIP_CB), TRUE); if (pConfig == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; } // Parse the command line // dwErr = RutlParse( ppwcArguments, dwCurrentIndex, dwArgCount, pbDone, pArgs, sizeof(pArgs)/sizeof(*pArgs)); BREAK_ON_DWERR( dwErr ); pszFrom = RASMON_CMD_ARG_GetPsz(&pArgs[0]); pszTo = RASMON_CMD_ARG_GetPsz(&pArgs[1]); dwErr = RasIpConvertRangePszToDword( pszFrom, pszTo, &dwFrom, &dwTo); BREAK_ON_DWERR(dwErr); // Validate the values entered // dwErr = RasIpValidateRange(dwFrom, dwTo, &dwReason); if (dwErr != NO_ERROR) { RasIpDisplayInvalidPool(dwReason); dwErr = ERROR_CAN_NOT_COMPLETE; break; } // Read in the old config pConfig->dwFlags = RASIP_F_Pool; dwErr = RasIpCbRead(g_pszServer, pConfig); BREAK_ON_DWERR(dwErr); if (bAdd) { // Add the range // dwErr = RasIpPoolAdd( pConfig->pPool, dwFrom, dwTo); if (dwErr == ERROR_CAN_NOT_COMPLETE) { DisplayMessage( g_hModule, EMSG_RASIP_OVERLAPPING_RANGE); } BREAK_ON_DWERR(dwErr); } else { // Delete the range // dwErr = RasIpPoolDel( pConfig->pPool, dwFrom, dwTo); BREAK_ON_DWERR(dwErr); } // Commit the change // dwErr = RasIpCbWrite( g_pszServer, pConfig); BREAK_ON_DWERR(dwErr); } while (FALSE); // Cleanup { RutlFree(pszFrom); RutlFree(pszTo); RasIpCbCleanup(pConfig); } return dwErr; } DWORD RasIpHandleAddRange( IN LPCWSTR pwszMachine, IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN DWORD dwFlags, IN LPCVOID pvData, OUT BOOL *pbDone ) { return RasIpHandleAddDelRange( ppwcArguments, dwCurrentIndex, dwArgCount, pbDone, TRUE); } DWORD RasIpHandleDelRange( IN LPCWSTR pwszMachine, IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN DWORD dwFlags, IN LPCVOID pvData, OUT BOOL *pbDone ) { return RasIpHandleAddDelRange( ppwcArguments, dwCurrentIndex, dwArgCount, pbDone, FALSE); } DWORD RasIpHandleDelPool( IN LPCWSTR pwszMachine, IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN DWORD dwFlags, IN LPCVOID pvData, OUT BOOL *pbDone ) { DWORD dwNumArgs = dwArgCount - dwCurrentIndex; RASIP_CB Config; RAS_IPPOOL* pPool = NULL; DWORD dwErr = NO_ERROR; // Check that the number of arguments is correct // if (dwNumArgs > 0) { DisplayMessage( g_hModule, HLP_RASIP_DEL_POOL_EX, DMP_RASIP_DEL_POOL); return NO_ERROR; } do { // Initialize an empty pool // pPool = RutlAlloc(sizeof(RAS_IPPOOL), TRUE); if (pPool == NULL) { return ERROR_NOT_ENOUGH_MEMORY; } ZeroMemory(&Config, sizeof(Config)); Config.dwFlags = RASIP_F_Pool; Config.pPool = pPool; dwErr = RasIpCbWrite(g_pszServer, &Config); BREAK_ON_DWERR(dwErr); } while (FALSE); // Cleanup { if (pPool) { RasIpPoolCleanup(pPool); } } return dwErr; } DWORD RasIpHandleShow( IN LPCWSTR pwszMachine, IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN DWORD dwFlags, IN LPCVOID pvData, OUT BOOL *pbDone ) { DWORD dwNumArgs = dwArgCount - dwCurrentIndex; // Check that the number of arguments is correct // if (dwNumArgs > 0) { DisplayMessage( g_hModule, HLP_RASIP_SHOW_CONFIG_EX, DMP_RASIP_SHOW_CONFIG); return NO_ERROR; } return RasIpDisplayConfig(TRUE); } // // Opens the registry keys associated with the ras ip address pool // DWORD RasIpPoolOpenKeys( IN HKEY hkParams, IN BOOL bCreate, OUT HKEY* phNew) { DWORD dwErr = NO_ERROR, dwDisposition; do { *phNew = NULL; if (bCreate) { dwErr = RegCreateKeyEx( hkParams, pszIpPoolSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, phNew, &dwDisposition); } else { dwErr = RegOpenKeyEx( hkParams, pszIpPoolSubKey, 0, KEY_ALL_ACCESS, phNew); } BREAK_ON_DWERR(dwErr); } while (FALSE); // Cleanup { } return dwErr; } // // Find a given range in the IP address pool. // If bExact is TRUE, it searches for an exact match to the range // If bExact is FALSE, it searches for any overlapping range. // DWORD RasIpPoolFind( IN RAS_IPPOOL* pPool, IN DWORD dwFrom, IN DWORD dwTo, IN BOOL bExact, OUT RAS_IPRANGE_NODE** ppNode OPTIONAL) { RAS_IPRANGE_NODE* pNode = pPool->pHead; if (bExact) { for (; pNode; pNode = pNode->pNext) { if ((pNode->dwFrom == dwFrom) && (pNode->dwTo == pNode->dwTo)) { break; } } } else { for (; pNode; pNode = pNode->pNext) { if ( // Overlap case 1: The lower end falls within an existing range // ((dwFrom >= pNode->dwFrom) && (dwFrom <= pNode->dwTo)) || // Overlap case 2: The upper end falls within an existing range // ((dwTo >= pNode->dwFrom) && (dwTo <= pNode->dwTo)) || // Overlap case 3: The range is a superset of an existing range // ((dwFrom < pNode->dwFrom) && (dwTo > pNode->dwTo)) ) { break; } } } if (pNode) { if (ppNode) { *ppNode = pNode; } return NO_ERROR; } return ERROR_NOT_FOUND; } // // Callback function populates a pool of addresses // DWORD RasIpPoolReadNode( IN LPCWSTR pszName, // sub key name IN HKEY hKey, // sub key IN HANDLE hData) { RAS_IPPOOL* pPool = (RAS_IPPOOL*)hData; DWORD dwErr = NO_ERROR; DWORD dwFrom = 0, dwTo = 0; dwErr = RutlRegReadDword(hKey, pszIpFrom, &dwFrom); if (dwErr != NO_ERROR) { return NO_ERROR; } dwErr = RutlRegReadDword(hKey, pszIpTo, &dwTo); if (dwErr != NO_ERROR) { return NO_ERROR; } dwErr = RasIpPoolAdd(pPool, dwFrom, dwTo); return dwErr; } // // Resets the ras pool on the given server // DWORD RasIpPoolReset( IN HKEY hkParams) { DWORD dwErr = NO_ERROR; HKEY hkPool = NULL; do { dwErr = RasIpPoolOpenKeys( hkParams, TRUE, &hkPool); BREAK_ON_DWERR(dwErr); { DWORD i; WCHAR pszBuf[16]; HKEY hkRange = NULL; for (i = 0; ;i++) { _itow(i, pszBuf, 10); dwErr = RegOpenKeyEx( hkPool, pszBuf, 0, KEY_ALL_ACCESS, &hkRange); if (dwErr != ERROR_SUCCESS) { dwErr = NO_ERROR; break; } RegCloseKey(hkRange); RegDeleteKey(hkPool, pszBuf); } BREAK_ON_DWERR(dwErr); } } while (FALSE); // Cleanup { if (hkPool) { RegCloseKey(hkPool); } } return dwErr; } // // Reads the ras ip pool from the given server // DWORD RasIpPoolRead( IN HKEY hkParams, OUT RAS_IPPOOL** ppPool) { DWORD dwErr = NO_ERROR; RAS_IPPOOL* pPool = NULL; HKEY hkPool = NULL; PWCHAR pszAddress = NULL, pszMask = NULL; do { // Allocate the new pool // pPool = (RAS_IPPOOL*) RutlAlloc(sizeof(RAS_IPPOOL), TRUE); if (pPool == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; } // Attempt to open the new location // dwErr = RasIpPoolOpenKeys( hkParams, FALSE, &hkPool); // The new location exists -- load in the // pool if (dwErr == NO_ERROR) { DWORD i; WCHAR pszBuf[16]; HKEY hkRange = NULL; for (i = 0; ;i++) { _itow(i, pszBuf, 10); dwErr = RegOpenKeyEx( hkPool, pszBuf, 0, KEY_ALL_ACCESS, &hkRange); if (dwErr != ERROR_SUCCESS) { dwErr = NO_ERROR; break; } dwErr = RasIpPoolReadNode( pszBuf, hkRange, (HANDLE)pPool); if (hkRange) { (VOID)RegCloseKey(hkRange); hkRange = NULL; } BREAK_ON_DWERR(dwErr); } BREAK_ON_DWERR(dwErr); *ppPool = pPool; } // The new location does not exist -- use legacy // values // else if (dwErr == ERROR_FILE_NOT_FOUND) { DWORD dwAddress = 0, dwMask = 0; dwErr = RutlRegReadString(hkParams, pszIpAddress, &pszAddress); BREAK_ON_DWERR(dwErr); dwErr = RutlRegReadString(hkParams, pszIpMask, &pszMask); BREAK_ON_DWERR(dwErr); dwErr = RasIpConvertRangePszToDword( pszAddress, pszMask, &dwAddress, &dwMask); BREAK_ON_DWERR(dwErr); if (dwAddress != 0) { dwErr = RasIpPoolAdd( pPool, dwAddress + 2, (dwAddress + ~dwMask) - 1); BREAK_ON_DWERR(dwErr); } *ppPool = pPool; } } while (FALSE); // Cleanup { if (dwErr != NO_ERROR) { if (pPool) { RasIpPoolCleanup(pPool); } } if (hkPool) { RegCloseKey(hkPool); } RutlFree(pszAddress); RutlFree(pszMask); } return dwErr; } // // Writes the given ras ip pool to the given server // DWORD RasIpPoolWrite( IN HKEY hkParams, IN RAS_IPPOOL* pPool) { DWORD dwErr = NO_ERROR; HKEY hkPool = NULL, hkNode = NULL; DWORD i, dwDisposition; WCHAR pszName[16]; RAS_IPRANGE_NODE* pNode = pPool->pHead; do { dwErr = RasIpPoolReset(hkParams); BREAK_ON_DWERR(dwErr); dwErr = RasIpPoolOpenKeys( hkParams, TRUE, &hkPool); BREAK_ON_DWERR(dwErr); for (i = 0; i < pPool->dwCount; i++, pNode = pNode->pNext) { _itow(i, pszName, 10); dwErr = RegCreateKeyEx( hkPool, pszName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkNode, &dwDisposition); if (dwErr != ERROR_SUCCESS) { continue; } RegSetValueEx( hkNode, pszIpFrom, 0, REG_DWORD, (CONST BYTE*)&pNode->dwFrom, sizeof(DWORD)); RegSetValueEx( hkNode, pszIpTo, 0, REG_DWORD, (CONST BYTE*)&pNode->dwTo, sizeof(DWORD)); if (hkNode) { RegCloseKey(hkNode); } } } while (FALSE); // Cleanup { if (hkPool) { RegCloseKey(hkPool); } } return dwErr; } // // Adds a range to a ras ip pool // DWORD RasIpPoolAdd( IN OUT RAS_IPPOOL* pPool, IN DWORD dwFrom, IN DWORD dwTo) { RAS_IPRANGE_NODE* pNode = NULL; DWORD dwErr; // Make sure the pool does not overlap // dwErr = RasIpPoolFind(pPool, dwFrom, dwTo, FALSE, NULL); if (dwErr == NO_ERROR) { return ERROR_CAN_NOT_COMPLETE; } // Allocate the new node // pNode = (RAS_IPRANGE_NODE*) RutlAlloc(sizeof(RAS_IPRANGE_NODE), TRUE); if (pNode == NULL) { return ERROR_NOT_ENOUGH_MEMORY; } pNode->dwFrom = dwFrom; pNode->dwTo = dwTo; // Add it to the list // if (pPool->pTail) { pPool->pTail->pNext = pNode; pPool->pTail = pNode; } else { pPool->pHead = pPool->pTail = pNode; } pPool->dwCount++; return NO_ERROR; } // // Deletes a range from a ras ip pool // DWORD RasIpPoolDel( IN OUT RAS_IPPOOL* pPool, IN DWORD dwFrom, IN DWORD dwTo) { RAS_IPRANGE_NODE* pCur = NULL, *pPrev = NULL; if (pPool->dwCount == 0) { return ERROR_NOT_FOUND; } pCur = pPrev = pPool->pHead; if ((pCur->dwFrom == dwFrom) && (pCur->dwTo == dwTo)) { pPool->pHead = pCur->pNext; if (pCur == pPool->pTail) { pPool->pTail = NULL; } RutlFree(pCur); pPool->dwCount--; return NO_ERROR; } for (pCur = pCur->pNext; pCur; pCur = pCur->pNext, pPrev = pPrev->pNext) { if ((pCur->dwFrom == dwFrom) && (pCur->dwTo == dwTo)) { pPrev->pNext = pCur->pNext; if (pCur == pPool->pTail) { pPool->pTail = pPrev; } RutlFree(pCur); pPool->dwCount--; return NO_ERROR; } } return ERROR_NOT_FOUND; } // // Cleans up a config control block // DWORD RasIpCbCleanup( IN RASIP_CB* pConfig) { if (pConfig) { if (pConfig->pPool) { RasIpPoolCleanup(pConfig->pPool); } RutlFree(pConfig); } return NO_ERROR; } DWORD RasIpPoolCleanup( IN RAS_IPPOOL* pPool) { RAS_IPRANGE_NODE* pNode = NULL; if (pPool) { while (pPool->pHead) { pNode = pPool->pHead->pNext; RutlFree(pPool->pHead); pPool->pHead = pNode; } RutlFree(pPool); } return NO_ERROR; } // // Creates a default config control block // DWORD RasIpCbCreateDefault( OUT RASIP_CB** ppConfig) { RASIP_CB* pConfig = NULL; DWORD dwErr = NO_ERROR; do { pConfig = (RASIP_CB*) RutlAlloc(sizeof(RASIP_CB), TRUE); if (pConfig == NULL) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; } pConfig->bEnableIn = TRUE; pConfig->bAccess = TRUE; pConfig->bAuto = TRUE; pConfig->pPool = NULL; pConfig->bCallerSpec = TRUE; *ppConfig = pConfig; } while (FALSE); // Cleanup { if (dwErr != NO_ERROR) { RasIpCbCleanup(pConfig); } } return dwErr; } // // Helper function opens the ras ip config registry key // DWORD RasIpCbOpenRegKeys( IN LPCWSTR pszServer, OUT HKEY* phKey) { DWORD dwErr = NO_ERROR; WCHAR pszKey[MAX_PATH]; do { // Generate the parameters key name // wsprintfW( pszKey, L"%s%s", pszRemoteAccessParamStub, pszIpParams); // Open the parameters keys // dwErr = RegOpenKeyEx( g_pServerInfo->hkMachine, pszKey, 0, KEY_READ | KEY_WRITE, phKey); BREAK_ON_DWERR( dwErr ); } while (FALSE); // Cleanup { } return dwErr; } // // Functions that manipulate RASIP_CB's // DWORD RasIpCbRead( IN LPCWSTR pszServer, OUT RASIP_CB* pConfig) { HKEY hkParams = NULL; DWORD dwErr = NO_ERROR; PWCHAR pszTemp = NULL; do { // Get a handle to the server's registry config // dwErr = RasIpCbOpenRegKeys( pszServer, &hkParams); BREAK_ON_DWERR( dwErr ); // Load the params from the registry // if (pConfig->dwFlags & RASIP_F_EnableIn) { dwErr = RutlRegReadDword( hkParams, pszEnableIn, &pConfig->bEnableIn); BREAK_ON_DWERR( dwErr ); } if (pConfig->dwFlags & RASIP_F_Access) { dwErr = RutlRegReadDword( hkParams, pszAllowNetworkAccess, &pConfig->bAccess); BREAK_ON_DWERR( dwErr ); } if (pConfig->dwFlags & RASIP_F_Auto) { dwErr = RutlRegReadDword( hkParams, pszIpUseDhcp, &pConfig->bAuto); BREAK_ON_DWERR( dwErr ); } if (pConfig->dwFlags & RASIP_F_CallerSpec) { dwErr = RutlRegReadDword( hkParams, pszIpClientSpec, &pConfig->bCallerSpec); BREAK_ON_DWERR( dwErr ); } if (pConfig->dwFlags & RASIP_F_Pool) { dwErr = RasIpPoolRead( hkParams, &pConfig->pPool); BREAK_ON_DWERR( dwErr ); } } while (FALSE); // Cleanup { if (hkParams) { RegCloseKey(hkParams); } } return dwErr; } DWORD RasIpCbWrite( IN LPCWSTR pszServer, IN RASIP_CB* pConfig) { HKEY hkParams = NULL; DWORD dwErr = NO_ERROR; do { // Get a handle to the server's registry config // dwErr = RasIpCbOpenRegKeys( pszServer, &hkParams); BREAK_ON_DWERR( dwErr ); // Write out the params to the registry // if (pConfig->dwFlags & RASIP_F_EnableIn) { dwErr = RutlRegWriteDword( hkParams, pszEnableIn, pConfig->bEnableIn); BREAK_ON_DWERR( dwErr ); } if (pConfig->dwFlags & RASIP_F_Access) { dwErr = RutlRegWriteDword( hkParams, pszAllowNetworkAccess, pConfig->bAccess); BREAK_ON_DWERR( dwErr ); } if (pConfig->dwFlags & RASIP_F_Auto) { dwErr = RutlRegWriteDword( hkParams, pszIpUseDhcp, pConfig->bAuto); BREAK_ON_DWERR( dwErr ); } if (pConfig->dwFlags & RASIP_F_CallerSpec) { dwErr = RutlRegWriteDword( hkParams, pszIpClientSpec, pConfig->bCallerSpec); BREAK_ON_DWERR( dwErr ); } if (pConfig->dwFlags & RASIP_F_Pool) { dwErr = RasIpPoolWrite( hkParams, pConfig->pPool); BREAK_ON_DWERR( dwErr ); } } while (FALSE); // Cleanup { if (hkParams) { RegCloseKey(hkParams); } } return dwErr; } // // Set NETBT broadcast based name resolution reg. value // dwArgCount - Value to set the registry value to // returns NO_ERROR - Success // Other - System error code // // Whistler bug: 359847 Netsh: move broadcastnameresolution from routing ip to // ras ip // DWORD RasIpSetNetbtBcast( DWORD dwEnable ) { DWORD dwResult, dwEnableOld = -1, dwSize = sizeof(DWORD); HKEY hkIpcpParam; do { dwResult = RegOpenKeyExW( g_pServerInfo->hkMachine, L"System\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\Ip", 0, KEY_READ | KEY_WRITE, &hkIpcpParam ); if(dwResult isnot NO_ERROR) { break; } dwResult = RegQueryValueExW( hkIpcpParam, L"EnableNetbtBcastFwd", NULL, NULL, (PBYTE)&dwEnableOld, &dwSize ); if((dwResult is NO_ERROR) and (dwEnable == dwEnableOld)) { break; } dwResult = RegSetValueExW( hkIpcpParam, L"EnableNetbtBcastFwd", 0, REG_DWORD, (PBYTE) &dwEnable, sizeof( DWORD ) ); } while(FALSE); if(dwResult is NO_ERROR) { DisplayMessage(g_hModule, MSG_RASAAAA_MUST_RESTART_SERVICES); } return dwResult; } // // Whistler bug: 359847 Netsh: move broadcastnameresolution from routing ip to // ras ip // BOOL RasIpShowNetbtBcast( VOID ) { HKEY hkIpcpParam = NULL; BOOL bReturn = FALSE; DWORD dwResult, dwEnable = -1, dwSize = sizeof(DWORD); do { dwResult = RegOpenKeyExW( g_pServerInfo->hkMachine, L"System\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\Ip", 0, KEY_READ | KEY_WRITE, &hkIpcpParam ); if(dwResult isnot NO_ERROR) { break; } dwResult = RegQueryValueExW( hkIpcpParam, L"EnableNetbtBcastFwd", NULL, NULL, (PBYTE)&dwEnable, &dwSize ); if(dwResult isnot NO_ERROR) { break; } if (dwEnable isnot 0) { bReturn = TRUE; } } while(FALSE); return bReturn; }