Leaked source code of windows server 2003
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

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. rasadmon.c
  5. Abstract:
  6. RAS Advertisement monitoring module
  7. Revision History:
  8. dthaler
  9. --*/
  10. #include "precomp.h"
  11. #include <winsock2.h>
  12. #include <ws2tcpip.h>
  13. #include <time.h>
  14. #include <mswsock.h>
  15. #define RASADV_PORT 9753
  16. #define RASADV_GROUP "239.255.2.2"
  17. typedef DWORD IPV4_ADDRESS;
  18. HANDLE g_hCtrlC = NULL;
  19. BOOL
  20. HandlerRoutine(
  21. DWORD dwCtrlType // control signal type
  22. )
  23. {
  24. switch (dwCtrlType)
  25. {
  26. case CTRL_C_EVENT:
  27. case CTRL_CLOSE_EVENT:
  28. case CTRL_BREAK_EVENT:
  29. case CTRL_LOGOFF_EVENT:
  30. case CTRL_SHUTDOWN_EVENT:
  31. default:
  32. SetEvent(g_hCtrlC);
  33. }
  34. return TRUE;
  35. };
  36. char * // OUT: string version of IP address
  37. AddrToString(
  38. u_long addr, // IN : address to convert
  39. char *ptr // OUT: buffer, or NULL
  40. )
  41. {
  42. char *str;
  43. struct in_addr in;
  44. in.s_addr = addr;
  45. str = inet_ntoa(in);
  46. if (ptr && str) {
  47. strcpy(ptr, str);
  48. return ptr;
  49. }
  50. return str;
  51. }
  52. //
  53. // Convert an address to a name
  54. //
  55. char *
  56. AddrToHostname(
  57. long addr,
  58. BOOL bNumeric_flag
  59. )
  60. {
  61. if (!addr)
  62. return "local";
  63. if (!bNumeric_flag) {
  64. struct hostent * host_ptr = NULL;
  65. host_ptr = gethostbyaddr ((char *) &addr, sizeof(addr), AF_INET);
  66. if (host_ptr)
  67. return host_ptr->h_name;
  68. }
  69. return AddrToString(addr, NULL);
  70. }
  71. DWORD
  72. HandleRasShowServers(
  73. IN LPCWSTR pwszMachine,
  74. IN OUT LPWSTR *ppwcArguments,
  75. IN DWORD dwCurrentIndex,
  76. IN DWORD dwArgCount,
  77. IN DWORD dwFlags,
  78. IN LPCVOID pvData,
  79. OUT BOOL *pbDone
  80. )
  81. /*++
  82. Routine Description:
  83. Monitors RAS Server advertisements.
  84. Arguments:
  85. None
  86. Return Value:
  87. None
  88. --*/
  89. {
  90. BOOL bCleanWSA = TRUE, bCleanCtrl = TRUE;
  91. DWORD dwErr = NO_ERROR;
  92. SOCKET s = INVALID_SOCKET;
  93. WSABUF wsaBuf;
  94. WSADATA wsaData;
  95. WSAEVENT WaitEvts[2];
  96. SOCKADDR_IN sinFrom;
  97. LPFN_WSARECVMSG WSARecvMsgFuncPtr = NULL;
  98. do
  99. {
  100. ZeroMemory(&wsaBuf, sizeof(WSABUF));
  101. dwErr = WSAStartup( MAKEWORD(2,0), &wsaData );
  102. if (dwErr)
  103. {
  104. bCleanWSA = FALSE;
  105. break;
  106. }
  107. //
  108. // create socket
  109. //
  110. s = WSASocket(
  111. AF_INET, // address family
  112. SOCK_DGRAM, // type
  113. 0, // protocol
  114. NULL,
  115. 0,
  116. WSA_FLAG_OVERLAPPED);
  117. if(INVALID_SOCKET == s)
  118. {
  119. dwErr = WSAGetLastError();
  120. break;
  121. }
  122. {
  123. BOOL bOption = TRUE;
  124. if (setsockopt(
  125. s,
  126. SOL_SOCKET,
  127. SO_REUSEADDR,
  128. (const char FAR*)&bOption,
  129. sizeof(BOOL))
  130. )
  131. {
  132. dwErr = WSAGetLastError();
  133. break;
  134. }
  135. }
  136. //
  137. // Bind to the specified port
  138. //
  139. {
  140. SOCKADDR_IN sinAddr;
  141. sinAddr.sin_family = AF_INET;
  142. sinAddr.sin_port = htons(RASADV_PORT);
  143. sinAddr.sin_addr.s_addr = INADDR_ANY;
  144. if (bind(s, (struct sockaddr*)&sinAddr, sizeof(sinAddr)))
  145. {
  146. dwErr = WSAGetLastError();
  147. break;
  148. }
  149. }
  150. //
  151. // Join group
  152. //
  153. {
  154. struct ip_mreq imOption;
  155. imOption.imr_multiaddr.s_addr = inet_addr(RASADV_GROUP);
  156. imOption.imr_interface.s_addr = INADDR_ANY;
  157. if (setsockopt(
  158. s,
  159. IPPROTO_IP,
  160. IP_ADD_MEMBERSHIP,
  161. (PBYTE)&imOption,
  162. sizeof(imOption))
  163. )
  164. {
  165. dwErr = WSAGetLastError();
  166. break;
  167. }
  168. }
  169. //
  170. // Get WSARecvMsg function pointer
  171. //
  172. {
  173. GUID WSARecvGuid = WSAID_WSARECVMSG;
  174. DWORD dwReturned = 0;
  175. if (WSAIoctl(
  176. s,
  177. SIO_GET_EXTENSION_FUNCTION_POINTER,
  178. (void*)&WSARecvGuid,
  179. sizeof(GUID),
  180. (void*)&WSARecvMsgFuncPtr,
  181. sizeof(LPFN_WSARECVMSG),
  182. &dwReturned,
  183. NULL,
  184. NULL)
  185. )
  186. {
  187. dwErr = WSAGetLastError();
  188. break;
  189. }
  190. }
  191. //
  192. // Get a name buffer for the recv socket
  193. //
  194. wsaBuf.buf = RutlAlloc(MAX_PATH + 1, TRUE);
  195. if (!wsaBuf.buf)
  196. {
  197. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  198. break;
  199. }
  200. wsaBuf.len = MAX_PATH;
  201. //
  202. // Create wsa wait event for the recv socket
  203. //
  204. WaitEvts[0] = WSACreateEvent();
  205. if (WSA_INVALID_EVENT == WaitEvts[0])
  206. {
  207. dwErr = WSAGetLastError();
  208. break;
  209. }
  210. if (WSAEventSelect(s, WaitEvts[0], FD_READ))
  211. {
  212. dwErr = WSAGetLastError();
  213. break;
  214. }
  215. //
  216. // Create Ctrl-C wait event
  217. //
  218. g_hCtrlC = CreateEvent(NULL, FALSE, FALSE, NULL);
  219. if (!g_hCtrlC)
  220. {
  221. dwErr = GetLastError();
  222. break;
  223. }
  224. //
  225. // Intercept CTRL-C
  226. //
  227. if (!SetConsoleCtrlHandler(HandlerRoutine, TRUE))
  228. {
  229. dwErr = GetLastError();
  230. bCleanCtrl = FALSE;
  231. break;
  232. }
  233. WaitEvts[1] = g_hCtrlC;
  234. DisplayMessage( g_hModule, MSG_RAS_SHOW_SERVERS_HEADER );
  235. for (;;)
  236. {
  237. CHAR szTimeStamp[30], *p, *q;
  238. DWORD dwBytesRcvd, dwStatus, dwReturn;
  239. WSAMSG wsaMsg;
  240. time_t t;
  241. dwReturn = WSAWaitForMultipleEvents(
  242. 2,
  243. WaitEvts,
  244. FALSE,
  245. WSA_INFINITE,
  246. FALSE);
  247. if (WSA_WAIT_EVENT_0 == dwReturn)
  248. {
  249. if (!WSAResetEvent(WaitEvts[0]))
  250. {
  251. dwErr = WSAGetLastError();
  252. break;
  253. }
  254. }
  255. else if (WSA_WAIT_EVENT_0 + 1 == dwReturn)
  256. {
  257. dwErr = NO_ERROR;
  258. break;
  259. }
  260. else
  261. {
  262. dwErr = WSAGetLastError();
  263. break;
  264. }
  265. //
  266. // .Net bug# 510712 Buffer overflow in HandleRasShowServers
  267. //
  268. // Init wsaMsg struct
  269. //
  270. ZeroMemory(&wsaMsg, sizeof(WSAMSG));
  271. wsaMsg.dwBufferCount = 1;
  272. wsaMsg.lpBuffers = &wsaBuf;
  273. wsaMsg.name = (struct sockaddr *)&sinFrom;
  274. wsaMsg.namelen = sizeof(sinFrom);
  275. dwStatus = WSARecvMsgFuncPtr(
  276. s,
  277. &wsaMsg,
  278. &dwBytesRcvd,
  279. NULL,
  280. NULL);
  281. if (SOCKET_ERROR == dwStatus)
  282. {
  283. dwErr = WSAGetLastError();
  284. if (WSAEMSGSIZE == dwErr)
  285. {
  286. dwBytesRcvd = MAX_PATH;
  287. }
  288. else
  289. {
  290. break;
  291. }
  292. }
  293. //
  294. // Only process multicast packets, skip all others
  295. //
  296. else if (!(wsaMsg.dwFlags & MSG_MCAST))
  297. {
  298. continue;
  299. }
  300. //
  301. // Get timestamp
  302. //
  303. time(&t);
  304. strcpy(szTimeStamp, ctime(&t));
  305. szTimeStamp[24] = '\0';
  306. //
  307. // Print info on sender
  308. //
  309. printf( "%s %s (%s)\n",
  310. szTimeStamp,
  311. AddrToString(sinFrom.sin_addr.s_addr, NULL),
  312. AddrToHostname(sinFrom.sin_addr.s_addr, FALSE) );
  313. wsaMsg.lpBuffers->buf[dwBytesRcvd] = '\0';
  314. for (p=wsaMsg.lpBuffers->buf; p && *p; p=q)
  315. {
  316. q = strchr(p, '\n');
  317. if (q)
  318. {
  319. *q++ = 0;
  320. }
  321. printf(" %s\n", p);
  322. }
  323. }
  324. } while (FALSE);
  325. //
  326. // Clean up
  327. //
  328. RutlFree(wsaBuf.buf);
  329. if (g_hCtrlC)
  330. {
  331. CloseHandle(g_hCtrlC);
  332. }
  333. if (WaitEvts[0])
  334. {
  335. WSACloseEvent(WaitEvts[0]);
  336. }
  337. if (INVALID_SOCKET != s)
  338. {
  339. closesocket(s);
  340. }
  341. if (bCleanWSA)
  342. {
  343. WSACleanup();
  344. }
  345. if (bCleanCtrl)
  346. {
  347. SetConsoleCtrlHandler(HandlerRoutine, FALSE);
  348. }
  349. return dwErr;
  350. }