You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
406 lines
9.2 KiB
406 lines
9.2 KiB
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
rasadmon.c
|
|
|
|
Abstract:
|
|
|
|
RAS Advertisement monitoring module
|
|
|
|
Revision History:
|
|
|
|
dthaler
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <winsock2.h>
|
|
#include <ws2tcpip.h>
|
|
#include <time.h>
|
|
#include <mswsock.h>
|
|
|
|
#define RASADV_PORT 9753
|
|
#define RASADV_GROUP "239.255.2.2"
|
|
|
|
typedef DWORD IPV4_ADDRESS;
|
|
|
|
HANDLE g_hCtrlC = NULL;
|
|
|
|
BOOL
|
|
HandlerRoutine(
|
|
DWORD dwCtrlType // control signal type
|
|
)
|
|
{
|
|
switch (dwCtrlType)
|
|
{
|
|
case CTRL_C_EVENT:
|
|
|
|
case CTRL_CLOSE_EVENT:
|
|
|
|
case CTRL_BREAK_EVENT:
|
|
|
|
case CTRL_LOGOFF_EVENT:
|
|
|
|
case CTRL_SHUTDOWN_EVENT:
|
|
|
|
default:
|
|
SetEvent(g_hCtrlC);
|
|
}
|
|
|
|
return TRUE;
|
|
};
|
|
|
|
char * // OUT: string version of IP address
|
|
AddrToString(
|
|
u_long addr, // IN : address to convert
|
|
char *ptr // OUT: buffer, or NULL
|
|
)
|
|
{
|
|
char *str;
|
|
struct in_addr in;
|
|
in.s_addr = addr;
|
|
str = inet_ntoa(in);
|
|
if (ptr && str) {
|
|
strcpy(ptr, str);
|
|
return ptr;
|
|
}
|
|
return str;
|
|
}
|
|
|
|
//
|
|
// Convert an address to a name
|
|
//
|
|
char *
|
|
AddrToHostname(
|
|
long addr,
|
|
BOOL bNumeric_flag
|
|
)
|
|
{
|
|
if (!addr)
|
|
return "local";
|
|
if (!bNumeric_flag) {
|
|
struct hostent * host_ptr = NULL;
|
|
host_ptr = gethostbyaddr ((char *) &addr, sizeof(addr), AF_INET);
|
|
if (host_ptr)
|
|
return host_ptr->h_name;
|
|
}
|
|
|
|
return AddrToString(addr, NULL);
|
|
}
|
|
|
|
|
|
DWORD
|
|
HandleRasShowServers(
|
|
IN LPCWSTR pwszMachine,
|
|
IN OUT LPWSTR *ppwcArguments,
|
|
IN DWORD dwCurrentIndex,
|
|
IN DWORD dwArgCount,
|
|
IN DWORD dwFlags,
|
|
IN LPCVOID pvData,
|
|
OUT BOOL *pbDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Monitors RAS Server advertisements.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL bCleanWSA = TRUE, bCleanCtrl = TRUE;
|
|
DWORD dwErr = NO_ERROR;
|
|
SOCKET s = INVALID_SOCKET;
|
|
WSABUF wsaBuf;
|
|
WSADATA wsaData;
|
|
WSAEVENT WaitEvts[2];
|
|
SOCKADDR_IN sinFrom;
|
|
LPFN_WSARECVMSG WSARecvMsgFuncPtr = NULL;
|
|
|
|
do
|
|
{
|
|
ZeroMemory(&wsaBuf, sizeof(WSABUF));
|
|
|
|
dwErr = WSAStartup( MAKEWORD(2,0), &wsaData );
|
|
if (dwErr)
|
|
{
|
|
bCleanWSA = FALSE;
|
|
break;
|
|
}
|
|
//
|
|
// create socket
|
|
//
|
|
s = WSASocket(
|
|
AF_INET, // address family
|
|
SOCK_DGRAM, // type
|
|
0, // protocol
|
|
NULL,
|
|
0,
|
|
WSA_FLAG_OVERLAPPED);
|
|
if(INVALID_SOCKET == s)
|
|
{
|
|
dwErr = WSAGetLastError();
|
|
break;
|
|
}
|
|
|
|
{
|
|
BOOL bOption = TRUE;
|
|
|
|
if (setsockopt(
|
|
s,
|
|
SOL_SOCKET,
|
|
SO_REUSEADDR,
|
|
(const char FAR*)&bOption,
|
|
sizeof(BOOL))
|
|
)
|
|
{
|
|
dwErr = WSAGetLastError();
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// Bind to the specified port
|
|
//
|
|
{
|
|
SOCKADDR_IN sinAddr;
|
|
|
|
sinAddr.sin_family = AF_INET;
|
|
sinAddr.sin_port = htons(RASADV_PORT);
|
|
sinAddr.sin_addr.s_addr = INADDR_ANY;
|
|
|
|
if (bind(s, (struct sockaddr*)&sinAddr, sizeof(sinAddr)))
|
|
{
|
|
dwErr = WSAGetLastError();
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// Join group
|
|
//
|
|
{
|
|
struct ip_mreq imOption;
|
|
|
|
imOption.imr_multiaddr.s_addr = inet_addr(RASADV_GROUP);
|
|
imOption.imr_interface.s_addr = INADDR_ANY;
|
|
|
|
if (setsockopt(
|
|
s,
|
|
IPPROTO_IP,
|
|
IP_ADD_MEMBERSHIP,
|
|
(PBYTE)&imOption,
|
|
sizeof(imOption))
|
|
)
|
|
{
|
|
dwErr = WSAGetLastError();
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// Get WSARecvMsg function pointer
|
|
//
|
|
{
|
|
GUID WSARecvGuid = WSAID_WSARECVMSG;
|
|
DWORD dwReturned = 0;
|
|
|
|
if (WSAIoctl(
|
|
s,
|
|
SIO_GET_EXTENSION_FUNCTION_POINTER,
|
|
(void*)&WSARecvGuid,
|
|
sizeof(GUID),
|
|
(void*)&WSARecvMsgFuncPtr,
|
|
sizeof(LPFN_WSARECVMSG),
|
|
&dwReturned,
|
|
NULL,
|
|
NULL)
|
|
)
|
|
{
|
|
dwErr = WSAGetLastError();
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// Get a name buffer for the recv socket
|
|
//
|
|
wsaBuf.buf = RutlAlloc(MAX_PATH + 1, TRUE);
|
|
if (!wsaBuf.buf)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
wsaBuf.len = MAX_PATH;
|
|
//
|
|
// Create wsa wait event for the recv socket
|
|
//
|
|
WaitEvts[0] = WSACreateEvent();
|
|
if (WSA_INVALID_EVENT == WaitEvts[0])
|
|
{
|
|
dwErr = WSAGetLastError();
|
|
break;
|
|
}
|
|
|
|
if (WSAEventSelect(s, WaitEvts[0], FD_READ))
|
|
{
|
|
dwErr = WSAGetLastError();
|
|
break;
|
|
}
|
|
//
|
|
// Create Ctrl-C wait event
|
|
//
|
|
g_hCtrlC = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
if (!g_hCtrlC)
|
|
{
|
|
dwErr = GetLastError();
|
|
break;
|
|
}
|
|
//
|
|
// Intercept CTRL-C
|
|
//
|
|
if (!SetConsoleCtrlHandler(HandlerRoutine, TRUE))
|
|
{
|
|
dwErr = GetLastError();
|
|
bCleanCtrl = FALSE;
|
|
break;
|
|
}
|
|
|
|
WaitEvts[1] = g_hCtrlC;
|
|
|
|
DisplayMessage( g_hModule, MSG_RAS_SHOW_SERVERS_HEADER );
|
|
|
|
for (;;)
|
|
{
|
|
CHAR szTimeStamp[30], *p, *q;
|
|
DWORD dwBytesRcvd, dwStatus, dwReturn;
|
|
WSAMSG wsaMsg;
|
|
time_t t;
|
|
|
|
dwReturn = WSAWaitForMultipleEvents(
|
|
2,
|
|
WaitEvts,
|
|
FALSE,
|
|
WSA_INFINITE,
|
|
FALSE);
|
|
if (WSA_WAIT_EVENT_0 == dwReturn)
|
|
{
|
|
if (!WSAResetEvent(WaitEvts[0]))
|
|
{
|
|
dwErr = WSAGetLastError();
|
|
break;
|
|
}
|
|
}
|
|
else if (WSA_WAIT_EVENT_0 + 1 == dwReturn)
|
|
{
|
|
dwErr = NO_ERROR;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
dwErr = WSAGetLastError();
|
|
break;
|
|
}
|
|
//
|
|
// .Net bug# 510712 Buffer overflow in HandleRasShowServers
|
|
//
|
|
// Init wsaMsg struct
|
|
//
|
|
ZeroMemory(&wsaMsg, sizeof(WSAMSG));
|
|
wsaMsg.dwBufferCount = 1;
|
|
wsaMsg.lpBuffers = &wsaBuf;
|
|
wsaMsg.name = (struct sockaddr *)&sinFrom;
|
|
wsaMsg.namelen = sizeof(sinFrom);
|
|
|
|
dwStatus = WSARecvMsgFuncPtr(
|
|
s,
|
|
&wsaMsg,
|
|
&dwBytesRcvd,
|
|
NULL,
|
|
NULL);
|
|
if (SOCKET_ERROR == dwStatus)
|
|
{
|
|
dwErr = WSAGetLastError();
|
|
|
|
if (WSAEMSGSIZE == dwErr)
|
|
{
|
|
dwBytesRcvd = MAX_PATH;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// Only process multicast packets, skip all others
|
|
//
|
|
else if (!(wsaMsg.dwFlags & MSG_MCAST))
|
|
{
|
|
continue;
|
|
}
|
|
//
|
|
// Get timestamp
|
|
//
|
|
time(&t);
|
|
strcpy(szTimeStamp, ctime(&t));
|
|
szTimeStamp[24] = '\0';
|
|
//
|
|
// Print info on sender
|
|
//
|
|
printf( "%s %s (%s)\n",
|
|
szTimeStamp,
|
|
AddrToString(sinFrom.sin_addr.s_addr, NULL),
|
|
AddrToHostname(sinFrom.sin_addr.s_addr, FALSE) );
|
|
|
|
wsaMsg.lpBuffers->buf[dwBytesRcvd] = '\0';
|
|
|
|
for (p=wsaMsg.lpBuffers->buf; p && *p; p=q)
|
|
{
|
|
q = strchr(p, '\n');
|
|
if (q)
|
|
{
|
|
*q++ = 0;
|
|
}
|
|
printf(" %s\n", p);
|
|
}
|
|
}
|
|
|
|
} while (FALSE);
|
|
//
|
|
// Clean up
|
|
//
|
|
RutlFree(wsaBuf.buf);
|
|
|
|
if (g_hCtrlC)
|
|
{
|
|
CloseHandle(g_hCtrlC);
|
|
}
|
|
if (WaitEvts[0])
|
|
{
|
|
WSACloseEvent(WaitEvts[0]);
|
|
}
|
|
if (INVALID_SOCKET != s)
|
|
{
|
|
closesocket(s);
|
|
}
|
|
if (bCleanWSA)
|
|
{
|
|
WSACleanup();
|
|
}
|
|
if (bCleanCtrl)
|
|
{
|
|
SetConsoleCtrlHandler(HandlerRoutine, FALSE);
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|