/* RASLaunch.c : module to manage RAS connections 17/06/97 Author: Christophe Roguet */ #include #include #include #include #include /* two macros to obtain a string that is the name of a DLL entry */ #define MakeFunctionName(n) (MakeFunctionName2(n)) #define MakeFunctionName2(n) (#n) int RASLoadRAS(), RASUnloadRAS(), RASLoadIP(), RASUnloadIP(); /****************************************************************/ /****************************************************************/ /****************************************************************/ /****************************************************************/ /****************************************************************/ /* global variables */ /* flag: has the module be initialized ? */ static char gs_bIsInitialized = 0; /* handle to the RAS DLL */ static HINSTANCE gs_hRASAPI_DLL = NULL; /* pointers to the RAS DLL functions that we use */ static DWORD (APIENTRY *gs_pfndwRasEnumEntries)(LPTSTR, LPTSTR, LPRASENTRYNAME, LPDWORD, LPDWORD) = NULL; static DWORD (APIENTRY *gs_pfndwRasEnumConnections)(LPRASCONN, LPDWORD, LPDWORD) = NULL; static DWORD (APIENTRY *gs_pfndwRasGetConnectStatus)(HRASCONN, LPRASCONNSTATUS) = NULL; static DWORD (APIENTRY *gs_pfndwRasGetEntryDialParams)(LPTSTR, LPRASDIALPARAMS, LPBOOL) = NULL; static DWORD (APIENTRY *gs_pfndwRasDial)(LPRASDIALEXTENSIONS, LPTSTR, LPRASDIALPARAMS, DWORD, LPVOID, LPHRASCONN) = NULL; static DWORD (APIENTRY *gs_pfndwRasHangUp)(HRASCONN) = NULL; static DWORD (APIENTRY *gs_pfndwRasGetErrorString)(UINT, LPTSTR, DWORD) = NULL; /****************************************************************/ /* RAS_Init() */ /****************************************************************/ int RAS_Init() { if( !(gs_bIsInitialized & RASInitialized) && RASLoadRAS()==0) gs_bIsInitialized|=RASInitialized; if( !(gs_bIsInitialized & IPInitialized) && RASLoadIP()==0) gs_bIsInitialized|=IPInitialized; return gs_bIsInitialized; } /****************************************************************/ /* RAS_Exit() */ /* 0: success */ /****************************************************************/ int RAS_Exit() { int RASUnloadOK, IPUnloadOK; if(gs_bIsInitialized & RASInitialized) { RASUnloadOK=RASUnloadRAS(); if(RASUnloadOK==0) gs_bIsInitialized&=~RASInitialized; } if(gs_bIsInitialized & IPInitialized) { IPUnloadOK=RASUnloadIP(); if(IPUnloadOK==0) gs_bIsInitialized&=~IPInitialized; } return RASUnloadOK | IPUnloadOK; } /****************************************************************/ /****************************************************************/ /* RASLoadRAS */ /* Attach the process to the RAS DLL */ /* return value: */ /* 0: success */ /* -1: failure */ /****************************************************************/ int RASLoadRAS(void) { long lErrorCode; gs_hRASAPI_DLL=LoadLibrary("RASAPI32.DLL"); if(gs_hRASAPI_DLL==NULL) { lErrorCode=GetLastError(); return -1; } gs_pfndwRasEnumEntries=(DWORD (APIENTRY*)(LPTSTR, LPTSTR, LPRASENTRYNAME, LPDWORD, LPDWORD)) GetProcAddress(gs_hRASAPI_DLL, MakeFunctionName(RasEnumEntries)); if(gs_pfndwRasEnumEntries==NULL) { lErrorCode=GetLastError(); return -1; } gs_pfndwRasEnumConnections=(DWORD (APIENTRY*)(LPRASCONN, LPDWORD, LPDWORD)) GetProcAddress(gs_hRASAPI_DLL, MakeFunctionName(RasEnumConnections)); if(gs_pfndwRasEnumConnections==NULL) { lErrorCode=GetLastError(); return -1; } gs_pfndwRasGetConnectStatus=(DWORD (APIENTRY*)(HRASCONN, LPRASCONNSTATUS)) GetProcAddress(gs_hRASAPI_DLL, MakeFunctionName(RasGetConnectStatus)); if(gs_pfndwRasGetConnectStatus==NULL) { lErrorCode=GetLastError(); return -1; } gs_pfndwRasGetEntryDialParams=(DWORD (APIENTRY*)(LPTSTR, LPRASDIALPARAMS, LPBOOL)) GetProcAddress(gs_hRASAPI_DLL, MakeFunctionName(RasGetEntryDialParams)); if(gs_pfndwRasGetEntryDialParams==NULL) { lErrorCode=GetLastError(); return -1; } gs_pfndwRasDial=(DWORD (APIENTRY*)(LPRASDIALEXTENSIONS, LPTSTR, LPRASDIALPARAMS, DWORD, LPVOID, LPHRASCONN)) GetProcAddress(gs_hRASAPI_DLL, MakeFunctionName(RasDial)); if(gs_pfndwRasDial==NULL) { lErrorCode=GetLastError(); return -1; } gs_pfndwRasHangUp=(DWORD (APIENTRY*)(HRASCONN)) GetProcAddress(gs_hRASAPI_DLL, MakeFunctionName(RasHangUp)); if(gs_pfndwRasHangUp==NULL) { lErrorCode=GetLastError(); return -1; } gs_pfndwRasGetErrorString=(DWORD (APIENTRY*)(UINT, LPTSTR, DWORD)) GetProcAddress(gs_hRASAPI_DLL, MakeFunctionName(RasGetErrorString)); if(gs_pfndwRasGetErrorString==NULL) { lErrorCode=GetLastError(); return -1; } return 0; } /****************************************************************/ /* RASUnloadRAS() */ /* Detach from the RAS DLL */ /* return value: */ /* 0: success */ /* -1: failure */ /****************************************************************/ int RASUnloadRAS(void) { long lErrorCode; if(FreeLibrary(gs_hRASAPI_DLL)==FALSE) { lErrorCode=GetLastError(); return -1; } gs_hRASAPI_DLL=NULL; gs_pfndwRasEnumEntries=(DWORD (APIENTRY*)(LPTSTR, LPTSTR, LPRASENTRYNAME, LPDWORD, LPDWORD)) 0L; gs_pfndwRasEnumConnections=(DWORD (APIENTRY*)(LPRASCONN, LPDWORD, LPDWORD)) 0L; gs_pfndwRasGetConnectStatus=(DWORD (APIENTRY*)(HRASCONN, LPRASCONNSTATUS)) 0L; gs_pfndwRasGetEntryDialParams=(DWORD (APIENTRY*)(LPTSTR, LPRASDIALPARAMS, LPBOOL)) 0L; gs_pfndwRasDial=(DWORD (APIENTRY*)(LPRASDIALEXTENSIONS, LPTSTR, LPRASDIALPARAMS, DWORD, LPVOID, LPHRASCONN)) 0L; gs_pfndwRasHangUp=(DWORD (APIENTRY*)(HRASCONN)) 0L; gs_pfndwRasGetErrorString=(DWORD (APIENTRY*)(UINT, LPTSTR, DWORD)) 0L; return 0; } /****************************************************************/ /****************************************************************/ /****************************************************************/ /****************************************************************/ /****************************************************************/ /****************************************************************/ /* RAS callback function declaration */ VOID APIENTRY RASNotifier(UINT , RASCONNSTATE , DWORD ); /* handle to the RAS connection */ static HRASCONN gs_hConnection=INVALID_HANDLE_VALUE; /****************************************************************/ /* RASScanEntries */ /* to list the available RAS connections */ /* return value: */ /* -1: no more available entry */ /* 0: an entry has been found */ /****************************************************************/ int RASScanEntries(char bStart, char *pcName, int iSize) { static DWORD s_dwBufferSize=0; static DWORD s_dwNumberOfWrittenEntries=0; static LPRASENTRYNAME s_pBuffer=0; DWORD dwReturnValue; static DWORD s_dwCurrentEntry=0; if( !(gs_bIsInitialized & RASInitialized) ) return -1; if(bStart) { s_dwCurrentEntry=0; if(s_pBuffer!=0) free(s_pBuffer); s_dwBufferSize=sizeof(RASENTRYNAME); s_pBuffer=(LPRASENTRYNAME)malloc(s_dwBufferSize); s_pBuffer->dwSize=sizeof(RASENTRYNAME); dwReturnValue=gs_pfndwRasEnumEntries(NULL, NULL, s_pBuffer, &s_dwBufferSize, &s_dwNumberOfWrittenEntries); while(dwReturnValue==ERROR_BUFFER_TOO_SMALL || dwReturnValue==ERROR_NOT_ENOUGH_MEMORY) { free(s_pBuffer); s_pBuffer=(LPRASENTRYNAME)malloc(s_dwBufferSize); s_pBuffer->dwSize=sizeof(RASENTRYNAME); dwReturnValue=gs_pfndwRasEnumEntries(NULL, NULL, s_pBuffer, &s_dwBufferSize, &s_dwNumberOfWrittenEntries); } if(dwReturnValue!=0) { free(s_pBuffer); s_pBuffer=0; return -1; } } if(s_dwCurrentEntrydwSize=sizeof(RASCONN); dwReturnValue=gs_pfndwRasEnumConnections(s_pBuffer, &s_dwBufferSize, &s_dwNumberOfWrittenConnections); while(dwReturnValue==ERROR_BUFFER_TOO_SMALL || dwReturnValue==ERROR_NOT_ENOUGH_MEMORY) { free(s_pBuffer); s_pBuffer=(LPRASCONN)malloc(s_dwBufferSize); s_pBuffer->dwSize=sizeof(RASCONN); dwReturnValue=gs_pfndwRasEnumConnections(s_pBuffer, &s_dwBufferSize, &s_dwNumberOfWrittenConnections); } if(dwReturnValue!=0) { free(s_pBuffer); s_pBuffer=0; return -1; } } if(s_dwCurrentConnection0) { iReturnValue=0; /* the target address can be reached */ gs_stTargetAddr.sin_family = AF_INET; gs_stTargetAddr.sin_port = gs_pfnushtons (80); /* www port, but any socket number should do */ gs_stTargetAddr.sin_addr.s_addr = gs_pfnulinet_addr(acTargetAddr); if(gs_stTargetAddr.sin_addr.s_addr==INADDR_NONE) { /* if the address is not a correct numeric address, ask a DNS to translate it */ entry=gs_pfnpstgethostbyname(acTargetAddr); if(entry==NULL) { /* the supplied address is not correct */ gs_pfniclosesocket(gs_sd); gs_sd=INVALID_SOCKET; iReturnValue=myRAS_InvalidAddress; } else gs_stTargetAddr.sin_addr = *(struct in_addr *)(entry->h_addr_list[0]); } if(iReturnValue==0) { iReturnValue=myRAS_InternalError; /* unable to start connecting */ /* set non blocking mode on the socket */ ulMode=~0; if(gs_pfniioctlsocket(gs_sd, FIONBIO, &ulMode)==SOCKET_ERROR) { lErrorCode=gs_pfniWSAGetLastError(); } else { iReturnValue=0; /* the test operation is proceeding */ if(gs_pfniconnect(gs_sd, (struct sockaddr *)&gs_stTargetAddr, sizeof(gs_stTargetAddr))==SOCKET_ERROR) { lErrorCode=gs_pfniWSAGetLastError(); /* should be WSAEWOULDBLOCK */ } } } } if(iReturnValue!=0) gs_iConnectivityState=-1; else gs_iConnectivityState=myRAS_Testing; return iReturnValue; } /****************************************************************/ int RASCancelTouch() { if(gs_sd==INVALID_SOCKET) return -1; gs_pfniclosesocket(gs_sd); gs_sd=INVALID_SOCKET; gs_iConnectivityState=myRAS_Canceled; return 0; } /****************************************************************/ int RASGetConnectivity() { long lErrorCode; fd_set WriteFD, ExceptionFD; static struct timeval timeout = {0, 0}; int iNumberOfEvents; /* is a connect operation in progress ? */ if(gs_sd==INVALID_SOCKET) return gs_iConnectivityState; /* has the connect operation finished ? */ FD_ZERO(&WriteFD); FD_ZERO(&ExceptionFD); FD_SET(gs_sd, &WriteFD); FD_SET(gs_sd, &ExceptionFD); iNumberOfEvents=gs_pfniselect(0, NULL, &WriteFD, &ExceptionFD, &timeout); if(iNumberOfEvents==SOCKET_ERROR) { lErrorCode=gs_pfniWSAGetLastError(); return -1; } if(iNumberOfEvents>0) { if(gs_pfni__WSAFDIsSet(gs_sd, &WriteFD)) gs_iConnectivityState=myRAS_Connectable; else if(gs_pfni__WSAFDIsSet(gs_sd, &ExceptionFD)) gs_iConnectivityState=myRAS_NotConnectable; else gs_iConnectivityState=-1; gs_pfniclosesocket(gs_sd); gs_sd=INVALID_SOCKET; } return gs_iConnectivityState; } /****************************************************************/