Source code of Windows XP (NT5)
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.

374 lines
13 KiB

  1. #include "ipxdefs.h"
  2. SERVICE_STATUS_HANDLE ServiceStatusHandle;
  3. SERVICE_STATUS ServiceStatus;
  4. SOCKET PingSocket;
  5. UINT PacketSize;
  6. DWORD PingTraceId;
  7. volatile LONG RequestCount;
  8. const union {
  9. CHAR ch[4];
  10. LONG l;
  11. } ping_signature = {"Ping"};
  12. #define IPX_PING_SIGNATURE ping_signature.l
  13. VOID CALLBACK
  14. ProcessPingRequest (
  15. IN DWORD dwError,
  16. IN DWORD cbTransferred,
  17. IN LPWSAOVERLAPPED lpOverlapped
  18. );
  19. DWORD
  20. PostReceiveRequest (
  21. PVOID context
  22. );
  23. DWORD
  24. StartPingSvc (
  25. VOID
  26. ) {
  27. BOOL flag;
  28. SOCKADDR_IPX addr;
  29. DWORD status;
  30. int sz;
  31. WORD wVersionRequested;
  32. WSADATA wsaData;
  33. int res;
  34. wVersionRequested = MAKEWORD( 2, 0 );
  35. PingTraceId = TraceRegister (TEXT ("IPXPing"));
  36. res = WSAStartup( wVersionRequested, &wsaData );
  37. if ((res==NO_ERROR)
  38. && (LOBYTE(wsaData.wVersion)==2)
  39. && (HIBYTE(wsaData.wVersion)==0)) {
  40. PingSocket = socket (AF_IPX, SOCK_DGRAM, NSPROTO_IPX);
  41. if (PingSocket!=INVALID_SOCKET) {
  42. // Tell WS IPX to use extended addresses
  43. flag = TRUE;
  44. if (setsockopt (PingSocket,
  45. NSPROTO_IPX,
  46. IPX_EXTENDED_ADDRESS,
  47. (PCHAR)&flag,
  48. sizeof (BOOL))==0) {
  49. // Bind to default address
  50. memset (&addr, 0, sizeof (addr));
  51. addr.sa_family = AF_IPX;
  52. addr.sa_socket = htons (IPX_PING_SOCKET);
  53. if (bind (PingSocket,
  54. (PSOCKADDR)&addr,
  55. sizeof (addr))==0) {
  56. if (getsockopt (PingSocket,
  57. SOL_SOCKET,
  58. SO_MAX_MSG_SIZE,
  59. (PCHAR)&PacketSize,
  60. &sz)==0) {
  61. status = NO_ERROR;
  62. if (! SetIoCompletionProc ((HANDLE)PingSocket,
  63. ProcessPingRequest))
  64. {
  65. status = GetLastError();
  66. }
  67. if (status==NO_ERROR) {
  68. RequestCount = 0;
  69. return NO_ERROR;
  70. }
  71. else {
  72. TracePrintfEx (PingTraceId,
  73. DBG_PING_ERRORS|TRACE_USE_MASK,
  74. TEXT ("Failed to set IO completion proc, err:%ld.\n"),
  75. status);
  76. }
  77. }
  78. else {
  79. status = WSAGetLastError ();
  80. TracePrintfEx (PingTraceId,
  81. DBG_PING_ERRORS|TRACE_USE_MASK,
  82. TEXT ("Failed to get SO_MAX_MSG_SIZE, err:%ld.\n"),
  83. status);
  84. }
  85. }
  86. else {
  87. status = WSAGetLastError ();
  88. TracePrintfEx (PingTraceId,
  89. DBG_PING_ERRORS|TRACE_USE_MASK,
  90. TEXT ("Failed to bind to IPXPING socket (%.4x), err:%ld.\n"),
  91. IPX_PING_SOCKET, status);
  92. }
  93. }
  94. else {
  95. status = WSAGetLastError ();
  96. TracePrintfEx (PingTraceId,
  97. DBG_PING_ERRORS|TRACE_USE_MASK,
  98. TEXT ("Failed to set IPX_EXTENDED_ADDRESS option, err:%ld.\n"),
  99. status);
  100. }
  101. }
  102. else {
  103. status = WSAGetLastError ();
  104. TracePrintfEx (PingTraceId,
  105. DBG_PING_ERRORS|TRACE_USE_MASK,
  106. TEXT ("Failed to create socket, err:%ld.\n"),
  107. status);
  108. }
  109. }
  110. else {
  111. TracePrintfEx (PingTraceId,
  112. DBG_PING_ERRORS|TRACE_USE_MASK,
  113. TEXT ("IPX Ping service implementation is"
  114. " incompatible with version of sockets installed"
  115. " on this system.\n"));
  116. status = WSAVERNOTSUPPORTED;
  117. }
  118. PingSocket = INVALID_SOCKET;
  119. WSACleanup ();
  120. TracePrintfEx (PingTraceId,
  121. DBG_PING_ERRORS|TRACE_USE_MASK,
  122. TEXT ("IPX Ping service was not started!\n"));
  123. TraceDeregister (PingTraceId);
  124. return status;
  125. }
  126. VOID
  127. ServiceHandler (
  128. DWORD fdwControl
  129. ) {
  130. switch (fdwControl) {
  131. case SERVICE_CONTROL_STOP:
  132. case SERVICE_CONTROL_SHUTDOWN:
  133. ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  134. SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
  135. TracePrintfEx (PingTraceId,
  136. DBG_PING_CONTROL|TRACE_USE_MASK,
  137. TEXT ("Stop or shutdown command received.\n"));
  138. StopPingSvc ();
  139. break;
  140. case SERVICE_CONTROL_PAUSE:
  141. case SERVICE_CONTROL_CONTINUE:
  142. case SERVICE_CONTROL_INTERROGATE:
  143. ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  144. ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  145. TracePrintfEx (PingTraceId,
  146. DBG_PING_CONTROL|TRACE_USE_MASK,
  147. TEXT ("Interrogate command received.\n"));
  148. break;
  149. default:
  150. TracePrintfEx (PingTraceId,
  151. DBG_PING_CONTROL|TRACE_USE_MASK,
  152. TEXT ("Unknown or unsupported command received (%d).\n"),
  153. fdwControl);
  154. break;
  155. }
  156. SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
  157. }
  158. VOID
  159. ServiceMain (
  160. DWORD argc,
  161. LPTSTR argv[]
  162. ) {
  163. HANDLE hEvent;
  164. ServiceStatusHandle = RegisterServiceCtrlHandler (
  165. TEXT("ipxping"), ServiceHandler);
  166. if (ServiceStatusHandle)
  167. {
  168. ServiceStatus.dwServiceType = SERVICE_WIN32_SHARE_PROCESS;
  169. ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  170. SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
  171. ServiceStatus.dwWin32ExitCode = StartPingSvc ();
  172. if (ServiceStatus.dwWin32ExitCode==NO_ERROR) {
  173. hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  174. if (hEvent!=NULL) {
  175. ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  176. ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP
  177. | SERVICE_ACCEPT_SHUTDOWN;
  178. SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
  179. while (PingSocket!=INVALID_SOCKET) {
  180. if (PostReceiveRequest (hEvent)==NO_ERROR)
  181. WaitForSingleObject (hEvent, INFINITE);
  182. else
  183. Sleep (3000);
  184. }
  185. while (RequestCount>0)
  186. SleepEx (1000, TRUE);
  187. }
  188. else {
  189. ServiceStatus.dwWin32ExitCode = GetLastError ();
  190. TracePrintfEx (PingTraceId,
  191. DBG_PING_ERRORS|TRACE_USE_MASK,
  192. TEXT ("Failed to create receive event, err: %ld.\n"),
  193. ServiceStatus.dwWin32ExitCode);
  194. }
  195. }
  196. ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  197. ServiceStatus.dwControlsAccepted = 0;
  198. SetServiceStatus (ServiceStatusHandle, &ServiceStatus);
  199. }
  200. }
  201. DWORD
  202. PostReceiveRequest (
  203. HANDLE hEvent
  204. ) {
  205. PPING_DATA_BLOCK block;
  206. int res;
  207. DWORD status;
  208. block = (PPING_DATA_BLOCK)GlobalAlloc (GPTR,
  209. FIELD_OFFSET (PING_DATA_BLOCK, pinghdr)
  210. +PacketSize);
  211. if (block!=NULL) {
  212. WSABUF bufArray[1];
  213. DWORD cbBytes, sz;
  214. DWORD flags;
  215. block->ovlp.hEvent = hEvent;
  216. bufArray[0].buf = (PCHAR)(&block->pinghdr);
  217. bufArray[0].len = PacketSize;
  218. flags = 0;
  219. sz = sizeof (block->raddr);
  220. res = WSARecvFrom (PingSocket,
  221. bufArray,
  222. sizeof (bufArray)/sizeof (bufArray[0]),
  223. &cbBytes,
  224. &flags,
  225. (PSOCKADDR)&block->raddr,
  226. &sz,
  227. &block->ovlp,
  228. NULL
  229. );
  230. if ((res==0) || (WSAGetLastError ()==WSA_IO_PENDING)) {
  231. InterlockedIncrement ((PLONG)&RequestCount);
  232. TracePrintfEx (PingTraceId,
  233. DBG_PING_REQUESTS|TRACE_USE_MASK,
  234. TEXT ("Posted ping request (%08lx).\n"),
  235. block);
  236. return NO_ERROR;
  237. }
  238. else {
  239. status = WSAGetLastError ();
  240. TracePrintfEx (PingTraceId,
  241. DBG_PING_ERRORS|TRACE_USE_MASK,
  242. TEXT ("Failed to post ping request, err: %ld.\n"),
  243. status);
  244. }
  245. GlobalFree (block);
  246. }
  247. else {
  248. status = GetLastError ();
  249. TracePrintfEx (PingTraceId,
  250. DBG_PING_ERRORS|TRACE_USE_MASK,
  251. TEXT ("Failed to allocate receive buffer, err: %ld.\n"),
  252. status);
  253. }
  254. return status;
  255. }
  256. VOID CALLBACK
  257. ProcessPingRequest (
  258. IN DWORD error,
  259. IN DWORD cbBytes,
  260. IN LPWSAOVERLAPPED ovlp
  261. ) {
  262. PPING_DATA_BLOCK block = CONTAINING_RECORD (ovlp, PING_DATA_BLOCK, ovlp);
  263. USHORT pktlen;
  264. int res;
  265. TracePrintfEx (PingTraceId,
  266. DBG_PING_REQUESTS|TRACE_USE_MASK,
  267. TEXT ("Processing ping request (%08lx), size: %ld, err: %ld.\n"),
  268. block, cbBytes, error);
  269. if (error!=ERROR_OPERATION_ABORTED) {
  270. if ((error==NO_ERROR)
  271. && (cbBytes>=sizeof (block->pinghdr))
  272. && (block->raddr.pkttype==0)
  273. && ((*((UNALIGNED LONG *)&block->pinghdr.signature))==IPX_PING_SIGNATURE)
  274. && (block->pinghdr.type==PING_PACKET_TYPE_REQUEST)
  275. ) {
  276. block->pinghdr.type = PING_PACKET_TYPE_RESPONSE;
  277. block->pinghdr.result =
  278. (cbBytes>sizeof (block->pinghdr)) ? 1 : 0;
  279. block->pinghdr.version = 1;
  280. res = sendto (PingSocket,
  281. (PCHAR)&block->pinghdr,
  282. cbBytes,
  283. 0,
  284. (PSOCKADDR)&block->saddr,
  285. sizeof (block->saddr)
  286. );
  287. if (res!=SOCKET_ERROR) {
  288. TracePrintfEx (PingTraceId,
  289. DBG_PING_RESPONSES|TRACE_USE_MASK,
  290. TEXT ("Sent response (%08lx) to"
  291. " %.2x%.2x%.2x%.2x,%.2x%.2x%.2x%.2x%.2x%.2x,%.4x"
  292. " with %d bytes of data.\n"),
  293. block,
  294. block->saddr.std.sa_netnum[0], block->saddr.std.sa_netnum[1],
  295. block->saddr.std.sa_netnum[2], block->saddr.std.sa_netnum[3],
  296. block->saddr.std.sa_nodenum[0], block->saddr.std.sa_netnum[1],
  297. block->saddr.std.sa_netnum[2], block->saddr.std.sa_netnum[3],
  298. block->saddr.std.sa_netnum[4], block->saddr.std.sa_netnum[5],
  299. block->saddr.std.sa_socket,
  300. cbBytes-sizeof (block->pinghdr));
  301. }
  302. else
  303. TracePrintfEx (PingTraceId,
  304. DBG_PING_ERRORS|TRACE_USE_MASK,
  305. TEXT ("Failed to send response, err: %ld.\n"),
  306. WSAGetLastError ());
  307. }
  308. else {
  309. TracePrintfEx (PingTraceId,
  310. DBG_PING_RESPONSES|TRACE_USE_MASK,
  311. TEXT ("Invalid request packet received from"
  312. " %.2x%.2x%.2x%.2x,%.2x%.2x%.2x%.2x%.2x%.2x,%.4x"
  313. " (pktsize: %d, pkttype: %.2x, sig:%4.4s, type: %d, ver: %d).\n"),
  314. block->raddr.std.sa_netnum[0], block->raddr.std.sa_netnum[1],
  315. block->raddr.std.sa_netnum[2], block->raddr.std.sa_netnum[3],
  316. block->raddr.std.sa_nodenum[0], block->raddr.std.sa_netnum[1],
  317. block->raddr.std.sa_netnum[2], block->raddr.std.sa_netnum[3],
  318. block->raddr.std.sa_netnum[4], block->raddr.std.sa_netnum[5],
  319. block->raddr.std.sa_socket,
  320. cbBytes, block->raddr.pkttype,
  321. block->pinghdr.signature, block->pinghdr.type, block->pinghdr.version);
  322. }
  323. }
  324. GlobalFree (block);
  325. InterlockedDecrement ((PLONG)&RequestCount);
  326. }
  327. VOID
  328. StopPingSvc (
  329. VOID
  330. ) {
  331. if (PingSocket!=INVALID_SOCKET) {
  332. SOCKET s = PingSocket;
  333. PingSocket = INVALID_SOCKET;
  334. closesocket (s);
  335. WSACleanup ();
  336. TraceDeregister (PingTraceId);
  337. }
  338. }