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.

738 lines
26 KiB

  1. //****************************************************************************
  2. //
  3. // Microsoft Windows NT RIP
  4. //
  5. // Copyright 1995-96
  6. //
  7. //
  8. // Revision History
  9. //
  10. //
  11. // 3/12/95 Gurdeep Singh Pall Created
  12. //
  13. //
  14. // Description: General utility functions:
  15. //
  16. //****************************************************************************
  17. #include "pchrip.h"
  18. #pragma hdrstop
  19. DWORD LoadAddressSockets();
  20. DWORD OpenTcp();
  21. DWORD TCPSetInformationEx(LPVOID lpvInBuffer, LPDWORD lpdwInSize,
  22. LPVOID lpvOutBuffer, LPDWORD lpdwOutSize);
  23. DWORD TCPQueryInformationEx(LPVOID lpvInBuffer, LPDWORD lpdwInSize,
  24. LPVOID lpvOutBuffer, LPDWORD lpdwOutSize);
  25. //-------------------------------------------------------------------
  26. // Function: LogEntry
  27. // Parameters:
  28. // WORD wEventType type of event (ERROR, WARNING, etc)
  29. // DWORD dwMsgID ID of message string
  30. // WORD wNumStrings number of strings in lplpStrings
  31. // LPSTR *lplpStrings array of strings
  32. // DWORD dwErr error code
  33. //-------------------------------------------------------------------
  34. void LogEntry(WORD wEventType, DWORD dwMsgID, WORD wNumStrings,
  35. LPSTR *lplpStrings, DWORD dwErr) {
  36. DWORD dwSize;
  37. LPVOID lpvData;
  38. HANDLE hLog;
  39. PSID pSidUser = NULL;
  40. hLog = RegisterEventSource(NULL, RIP_SERVICE);
  41. dwSize = (dwErr == NO_ERROR) ? 0 : sizeof(dwErr);
  42. lpvData = (dwErr == NO_ERROR) ? NULL : (LPVOID)&dwErr;
  43. ReportEvent(hLog, wEventType, 0, dwMsgID, pSidUser,
  44. wNumStrings, dwSize, lplpStrings, lpvData);
  45. DeregisterEventSource(hLog);
  46. }
  47. //-------------------------------------------------------------------
  48. // Function: RipLogError
  49. // Parameters:
  50. // see LogEntry for parameter description
  51. //-------------------------------------------------------------------
  52. void RipLogError(DWORD dwMsgID, WORD wNumStrings,
  53. LPSTR *lplpStrings, DWORD dwErr) {
  54. DWORD dwLevel;
  55. dwLevel = g_params.dwLoggingLevel;
  56. if (dwLevel < LOGLEVEL_ERROR) { return; }
  57. LogEntry(EVENTLOG_ERROR_TYPE, dwMsgID, wNumStrings, lplpStrings, dwErr);
  58. }
  59. //-------------------------------------------------------------------
  60. // Function: LogWarning
  61. // Parameters:
  62. // see LogEntry for parameter description
  63. //-------------------------------------------------------------------
  64. void RipLogWarning(DWORD dwMsgID, WORD wNumStrings,
  65. LPSTR *lplpStrings, DWORD dwErr) {
  66. DWORD dwLevel;
  67. dwLevel = g_params.dwLoggingLevel;
  68. if (dwLevel < LOGLEVEL_WARNING) { return; }
  69. LogEntry(EVENTLOG_WARNING_TYPE, dwMsgID, wNumStrings, lplpStrings, dwErr);
  70. }
  71. //-------------------------------------------------------------------
  72. // Function: LogInformation
  73. // Parameters:
  74. // see LogEntry for parameter description
  75. //-------------------------------------------------------------------
  76. void RipLogInformation(DWORD dwMsgID, WORD wNumStrings,
  77. LPSTR *lplpStrings, DWORD dwErr) {
  78. DWORD dwLevel;
  79. dwLevel = g_params.dwLoggingLevel;
  80. if (dwLevel < LOGLEVEL_INFORMATION) { return; }
  81. LogEntry(EVENTLOG_INFORMATION_TYPE, dwMsgID,
  82. wNumStrings, lplpStrings, dwErr);
  83. }
  84. //-------------------------------------------------------------------
  85. // Function: Audit
  86. //-------------------------------------------------------------------
  87. VOID Audit(IN WORD wEventType, IN DWORD dwMessageId,
  88. IN WORD cNumberOfSubStrings, IN LPSTR *plpwsSubStrings) {
  89. HANDLE hLog;
  90. PSID pSidUser = NULL;
  91. // Audit enabled
  92. hLog = RegisterEventSourceA(NULL, RIP_SERVICE);
  93. ReportEventA(hLog, wEventType, 0, dwMessageId, pSidUser,
  94. cNumberOfSubStrings, 0, plpwsSubStrings, (PVOID)NULL);
  95. DeregisterEventSource( hLog );
  96. }
  97. //-------------------------------------------------------------------
  98. // Function: dbgprintf
  99. //-------------------------------------------------------------------
  100. VOID dbgprintf(LPSTR lpszFormat, ...) {
  101. va_list arglist;
  102. va_start(arglist, lpszFormat);
  103. TraceVprintf(g_dwTraceID, lpszFormat, arglist);
  104. va_end(arglist);
  105. }
  106. //-------------------------------------------------------------------
  107. // Function: InitializeAddressTable
  108. //
  109. // Assumes the address table is locked.
  110. //-------------------------------------------------------------------
  111. DWORD InitializeAddressTable(BOOL bFirstTime) {
  112. LPRIP_ADDRESS lpaddr, lpaddrend;
  113. LPRIP_ADDRESS_STATISTICS lpstats;
  114. DWORD dwErr, dwCount, *lpdw, *lpdwend;
  115. PMIB_IPADDRROW lpTable, lpiae, lpiaeend;
  116. // first close old sockets, if necessary
  117. if (!bFirstTime) {
  118. lpaddrend = g_ripcfg.lpAddrTable + g_ripcfg.dwAddrCount;
  119. for (lpaddr = g_ripcfg.lpAddrTable; lpaddr < lpaddrend; lpaddr++) {
  120. if (lpaddr->sock != INVALID_SOCKET) {
  121. closesocket(lpaddr->sock);
  122. lpaddr->sock = INVALID_SOCKET;
  123. }
  124. }
  125. }
  126. dwErr = GetIPAddressTable(&lpTable, &dwCount);
  127. if (dwErr != 0) { return dwErr; }
  128. if (dwCount > MAX_ADDRESS_COUNT) { dwCount = MAX_ADDRESS_COUNT; }
  129. lpaddr = g_ripcfg.lpAddrTable;
  130. lpstats = g_ripcfg.lpStatsTable->lpAddrStats;
  131. lpiaeend = lpTable + dwCount;
  132. g_ripcfg.dwAddrCount = dwCount;
  133. for (lpiae = lpTable; lpiae < lpiaeend; lpiae++) {
  134. if (!lpiae->dwAddr || IP_LOOPBACK_ADDR(lpiae->dwAddr)) {
  135. --g_ripcfg.dwAddrCount; continue;
  136. }
  137. lpaddr->dwIndex = lpiae->dwIndex;
  138. lpaddr->dwAddress = lpiae->dwAddr;
  139. lpaddr->dwNetmask = lpiae->dwMask;
  140. lpaddr->dwFlag = 0;
  141. lpdwend = (LPDWORD)(lpstats + 1);
  142. for (lpdw = (LPDWORD)lpstats; lpdw < lpdwend; lpdw++) {
  143. InterlockedExchange(lpdw, 0);
  144. }
  145. InterlockedExchange(&lpstats->dwAddress, lpaddr->dwAddress);
  146. lpaddr->lpstats = lpstats;
  147. lpstats++;
  148. lpaddr++;
  149. }
  150. FreeIPAddressTable(lpTable);
  151. // also update the stats address count
  152. InterlockedExchange(&g_ripcfg.lpStatsTable->dwAddrCount,
  153. g_ripcfg.dwAddrCount);
  154. // if no addresses, bail out now
  155. if (g_ripcfg.dwAddrCount == 0) {
  156. dbgprintf("no IP addresses available for routing");
  157. return NO_ERROR;
  158. }
  159. // open sockets for each interface we have, and set options on the sockets
  160. dwErr = LoadAddressSockets();
  161. return dwErr;
  162. }
  163. //-------------------------------------------------------------------
  164. // Function: InitializeStatsTable
  165. //
  166. // Creates a mapping of our statistics table in shareable memory
  167. // so interested processes can examine RIP's behavior.
  168. //-------------------------------------------------------------------
  169. DWORD InitializeStatsTable() {
  170. DWORD dwErr;
  171. g_ripcfg.lpStatsTable = NULL;
  172. // set up a pointer to the memory
  173. g_ripcfg.lpStatsTable = HeapAlloc(GetProcessHeap(), 0,
  174. sizeof(RIP_STATISTICS));
  175. if (g_ripcfg.lpStatsTable == NULL) {
  176. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  177. dbgprintf( "InitializeStatsTable failed with error %x\n", dwErr );
  178. RipLogError( RIPLOG_ADDR_ALLOC_FAILED, 0, NULL, dwErr );
  179. return dwErr;
  180. }
  181. ZeroMemory(g_ripcfg.lpStatsTable, sizeof(RIP_STATISTICS));
  182. return 0;
  183. }
  184. VOID CleanupStatsTable() {
  185. if (g_ripcfg.lpStatsTable != NULL) {
  186. InterlockedExchange(&g_ripcfg.lpStatsTable->dwAddrCount, 0);
  187. HeapFree(GetProcessHeap(), 0, g_ripcfg.lpStatsTable);
  188. g_ripcfg.lpStatsTable = NULL;
  189. }
  190. }
  191. //--------------------------------------------------------------------------
  192. // Function: LoadAddressSockets
  193. //
  194. // Opens, configures, and binds sockets for each address in the table
  195. //--------------------------------------------------------------------------
  196. DWORD LoadAddressSockets() {
  197. IN_ADDR addr;
  198. CHAR szAddress[24] = {0};
  199. CHAR *ppszArgs[] = { szAddress };
  200. CHAR *pszTemp;
  201. SOCKADDR_IN sinsock;
  202. DWORD dwOption, dwErr;
  203. LPRIP_ADDRESS lpaddr, lpend;
  204. struct ip_mreq imOption;
  205. lpend = g_ripcfg.lpAddrTable + g_ripcfg.dwAddrCount;
  206. for (lpaddr = g_ripcfg.lpAddrTable; lpaddr < lpend; lpaddr++) {
  207. if ((lpaddr->dwFlag & ADDRFLAG_DISABLED) != 0) {
  208. continue;
  209. }
  210. addr.s_addr = lpaddr->dwAddress;
  211. pszTemp = inet_ntoa(addr);
  212. if (pszTemp != NULL) {
  213. strcpy(szAddress, pszTemp);
  214. }
  215. lpaddr->sock = socket(AF_INET, SOCK_DGRAM, 0);
  216. if (lpaddr->sock == INVALID_SOCKET) {
  217. dwErr = WSAGetLastError();
  218. dbgprintf("error %d creating socket for address %s",
  219. dwErr, szAddress);
  220. RipLogError(RIPLOG_CREATESOCK_FAILED, 1, ppszArgs, dwErr);
  221. continue;
  222. }
  223. dwOption = 1;
  224. dwErr = setsockopt(lpaddr->sock, SOL_SOCKET, SO_BROADCAST,
  225. (LPBYTE)&dwOption, sizeof(dwOption));
  226. if (dwErr == SOCKET_ERROR) {
  227. dwErr = WSAGetLastError();
  228. dbgprintf("error %d enabling broadcast for address %s",
  229. dwErr, szAddress);
  230. RipLogError(RIPLOG_SET_BCAST_FAILED, 1, ppszArgs, dwErr);
  231. // this socket is useless if we can't broadcast on it
  232. closesocket(lpaddr->sock);
  233. lpaddr->sock = INVALID_SOCKET;
  234. continue;
  235. }
  236. dwOption = 1;
  237. dwErr = setsockopt(lpaddr->sock, SOL_SOCKET, SO_REUSEADDR,
  238. (LPBYTE)&dwOption, sizeof(dwOption));
  239. if (dwErr == SOCKET_ERROR) {
  240. dwErr = WSAGetLastError();
  241. dbgprintf("error %d enabling reuse of address %s",
  242. dwErr, szAddress);
  243. RipLogError(RIPLOG_SET_REUSE_FAILED, 1, ppszArgs, dwErr);
  244. }
  245. sinsock.sin_family = AF_INET;
  246. sinsock.sin_port = htons(RIP_PORT);
  247. sinsock.sin_addr.s_addr = lpaddr->dwAddress;
  248. dwErr = bind(lpaddr->sock, (LPSOCKADDR)&sinsock, sizeof(SOCKADDR_IN));
  249. if (dwErr == SOCKET_ERROR) {
  250. dwErr = WSAGetLastError();
  251. dbgprintf("error %d binding address %s to RIP port",
  252. dwErr, szAddress);
  253. RipLogError(RIPLOG_BINDSOCK_FAILED, 1, ppszArgs, dwErr);
  254. closesocket(lpaddr->sock);
  255. lpaddr->sock = INVALID_SOCKET;
  256. continue;
  257. }
  258. #if DBG
  259. dbgprintf( "socket %d bound to %s\n\n", lpaddr-> sock, inet_ntoa( *( (struct in_addr *) &(lpaddr-> dwAddress) ) ) );
  260. #endif
  261. //
  262. // enable multicasting also
  263. //
  264. sinsock.sin_addr.s_addr = lpaddr->dwAddress;
  265. dwErr = setsockopt(lpaddr->sock, IPPROTO_IP, IP_MULTICAST_IF,
  266. (PBYTE)&sinsock.sin_addr, sizeof(IN_ADDR));
  267. if (dwErr == SOCKET_ERROR) {
  268. dwErr = WSAGetLastError();
  269. dbgprintf("error %d setting interface %d (%s) as multicast",
  270. dwErr, lpaddr->dwIndex, szAddress);
  271. RipLogError(RIPLOG_SET_MCAST_IF_FAILED, 1, ppszArgs, dwErr);
  272. closesocket(lpaddr->sock);
  273. lpaddr->sock = INVALID_SOCKET;
  274. continue;
  275. }
  276. //
  277. // join the IPRIP multicast group
  278. //
  279. imOption.imr_multiaddr.s_addr = RIP_MULTIADDR;
  280. imOption.imr_interface.s_addr = lpaddr->dwAddress;
  281. dwErr = setsockopt(lpaddr->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
  282. (PBYTE)&imOption, sizeof(imOption));
  283. if (dwErr == SOCKET_ERROR) {
  284. dwErr = WSAGetLastError();
  285. dbgprintf("error %d enabling multicast on interface %d (%s)",
  286. dwErr, lpaddr->dwIndex, szAddress);
  287. RipLogError(RIPLOG_JOIN_GROUP_FAILED, 1, ppszArgs, dwErr);
  288. closesocket(lpaddr->sock);
  289. lpaddr->sock = INVALID_SOCKET;
  290. continue;
  291. }
  292. dwErr = WSAEventSelect(
  293. lpaddr->sock,
  294. g_netEvent,
  295. FD_READ);
  296. if (dwErr == SOCKET_ERROR) {
  297. dwErr = WSAGetLastError();
  298. dbgprintf("error %d doing WSAEventSelect on interface %d (%s)",
  299. dwErr, lpaddr->dwIndex, szAddress);
  300. RipLogError(RIPLOG_WSAEVENTSELECT_FAILED, 1, ppszArgs, dwErr);
  301. closesocket(lpaddr->sock);
  302. lpaddr->sock = INVALID_SOCKET;
  303. continue;
  304. }
  305. }
  306. return 0;
  307. }
  308. //--------------------------------------------------------------------------
  309. // Function: LoadRouteTable
  310. //
  311. // Get the transports routing table. This is called with firsttime set
  312. // to TRUE when RIP loads. After that it is called with firsttime set
  313. // to FALSE. Assumes the route table is locked.
  314. //--------------------------------------------------------------------------
  315. int LoadRouteTable(BOOL bFirstTime) {
  316. IN_ADDR addr;
  317. LPHASH_TABLE_ENTRY rt_entry;
  318. CHAR szDest[32] = {0};
  319. CHAR szNexthop[32] = {0};
  320. CHAR *pszTemp;
  321. DWORD dwRouteTimeout, dwErr, dwRouteCount;
  322. LPIPROUTE_ENTRY lpRouteEntryTable, lpentry, lpentend;
  323. dwErr = GetRouteTable(&lpRouteEntryTable, &dwRouteCount);
  324. if (dwErr != 0) {
  325. return dwErr;
  326. }
  327. dwRouteTimeout = g_params.dwRouteTimeout;
  328. // now prune unwanted entries, and add the others to our hash table.
  329. // we only load RIP, static, and SNMP routes, and for non-RIP routes
  330. // we set the timeout to 90 seconds,
  331. //
  332. lpentend = lpRouteEntryTable + dwRouteCount;
  333. for (lpentry = lpRouteEntryTable; lpentry < lpentend; lpentry++) {
  334. if (lpentry->ire_metric1 < METRIC_INFINITE &&
  335. (lpentry->ire_proto == IRE_PROTO_RIP ||
  336. lpentry->ire_proto == IRE_PROTO_LOCAL ||
  337. lpentry->ire_proto == IRE_PROTO_NETMGMT) &&
  338. !IP_LOOPBACK_ADDR(lpentry->ire_dest) &&
  339. !IP_LOOPBACK_ADDR(lpentry->ire_nexthop) &&
  340. !CLASSD_ADDR(lpentry->ire_dest) &&
  341. !CLASSE_ADDR(lpentry->ire_dest) &&
  342. !IsBroadcastAddress(lpentry->ire_dest) &&
  343. !IsDisabledLocalAddress(lpentry->ire_nexthop)) {
  344. rt_entry = GetRouteTableEntry(lpentry->ire_index,
  345. lpentry->ire_dest,
  346. lpentry->ire_mask);
  347. // If we hit low memory conditions, get out of the loop.
  348. //
  349. if (rt_entry == NULL) {
  350. dwErr = ERROR_OUTOFMEMORY;
  351. break;
  352. }
  353. // only update the route with information from
  354. // the system table if it is a route that was learnt
  355. // from the system table; this is so if it is a new route
  356. // or if it is an old static or SNMP-added route
  357. //
  358. if ((rt_entry->dwFlag & NEW_ENTRY) ||
  359. rt_entry->dwProtocol == IRE_PROTO_LOCAL ||
  360. rt_entry->dwProtocol == IRE_PROTO_NETMGMT) {
  361. // if the route is new and this isn't the first time
  362. // we have loaded the system routing table, set change flag
  363. //
  364. if (!bFirstTime && (rt_entry->dwFlag & NEW_ENTRY)) {
  365. rt_entry->dwFlag |= ROUTE_CHANGE;
  366. addr.s_addr = lpentry->ire_dest;
  367. pszTemp = inet_ntoa(addr);
  368. if (pszTemp != NULL) {
  369. strcpy(szDest, pszTemp);
  370. }
  371. addr.s_addr = lpentry->ire_nexthop;
  372. pszTemp = inet_ntoa(addr);
  373. if (pszTemp != NULL) {
  374. strcpy(szNexthop, pszTemp);
  375. }
  376. dbgprintf("new entry: dest=%s, nexthop=%s, "
  377. "metric=%d, protocol=%d", szDest, szNexthop,
  378. lpentry->ire_metric1, lpentry->ire_proto);
  379. }
  380. rt_entry->dwFlag &= ~NEW_ENTRY;
  381. // we need to reset all these parameters
  382. // because any of them may have changed since
  383. // the last time the system route table was loaded.
  384. //
  385. rt_entry->dwIndex = lpentry->ire_index;
  386. rt_entry->dwProtocol = lpentry->ire_proto;
  387. rt_entry->dwDestaddr = lpentry->ire_dest;
  388. rt_entry->dwNetmask = lpentry->ire_mask;
  389. rt_entry->dwNexthop = lpentry->ire_nexthop;
  390. rt_entry->dwMetric = lpentry->ire_metric1;
  391. if (rt_entry->dwProtocol == IRE_PROTO_RIP) {
  392. rt_entry->lTimeout = (LONG)dwRouteTimeout;
  393. }
  394. else {
  395. rt_entry->lTimeout = DEF_LOCALROUTETIMEOUT;
  396. }
  397. rt_entry->dwFlag &= ~GARBAGE_TIMER;
  398. rt_entry->dwFlag |= TIMEOUT_TIMER;
  399. // if our estimate is that this is a host route
  400. // and its mask tells us it is a host route
  401. // then we mark it as being a host route
  402. //
  403. if (IsHostAddress(rt_entry->dwDestaddr) &&
  404. rt_entry->dwNetmask == HOSTADDR_MASK) {
  405. rt_entry->dwFlag |= ROUTE_HOST;
  406. }
  407. }
  408. }
  409. }
  410. FreeRouteTable(lpRouteEntryTable);
  411. return dwErr;
  412. }
  413. //--------------------------------------------------------------------------
  414. // Function: UpdateSystemRouteTable
  415. //
  416. // Parameters:
  417. // LPHASH_TABLE_ENTRY rt_entry the entry to update
  418. // BOOL bAdd if true, the entry is added
  419. // otherwise, the entry is deleted
  420. //
  421. // Returns: DWORD:
  422. //
  423. //
  424. // Add a new route to the route table. Note: due to MIB's use of
  425. // the destination address as an instance number, and also due to
  426. // TCP/IP stack allowing multiple entries for a single destination,
  427. // an ambiguity can exist. If there is already an entry for this
  428. // destination. This will have the effect of changing the existing
  429. // entry, rather than creating a new one.
  430. // This function assumes the address table is locked.
  431. //--------------------------------------------------------------------------
  432. DWORD UpdateSystemRouteTable(LPHASH_TABLE_ENTRY rt_entry, BOOL bAdd) {
  433. IN_ADDR addr;
  434. DWORD dwErr, dwRouteType;
  435. // never delete or update a route which was not created by RIP
  436. if (rt_entry->dwProtocol != IRE_PROTO_RIP) {
  437. return 0;
  438. }
  439. if (bAdd) {
  440. dwRouteType = (IsLocalAddr(rt_entry->dwNexthop) ? IRE_TYPE_DIRECT
  441. : IRE_TYPE_INDIRECT);
  442. #if 0
  443. DbgPrintf(
  444. "AddRoute : Protocol %x, Index %x, dest addr %x, dest mask %x\n",
  445. rt_entry->dwProtocol, rt_entry->dwIndex, rt_entry->dwDestaddr, rt_entry->dwNetmask
  446. );
  447. DbgPrintf(
  448. "Next Hop %x, Metric %x\n\n", rt_entry->dwNexthop, rt_entry->dwMetric
  449. );
  450. #endif
  451. dwErr = AddRoute(rt_entry->dwProtocol, dwRouteType, rt_entry->dwIndex,
  452. rt_entry->dwDestaddr, rt_entry->dwNetmask,
  453. rt_entry->dwNexthop, rt_entry->dwMetric);
  454. }
  455. else {
  456. dwErr = DeleteRoute(rt_entry->dwIndex, rt_entry->dwDestaddr,
  457. rt_entry->dwNetmask, rt_entry->dwNexthop);
  458. }
  459. if (dwErr == STATUS_SUCCESS) {
  460. if (bAdd) {
  461. InterlockedIncrement(
  462. &g_ripcfg.lpStatsTable->dwRoutesAddedToSystemTable);
  463. }
  464. else {
  465. InterlockedIncrement(
  466. &g_ripcfg.lpStatsTable->dwRoutesDeletedFromSystemTable);
  467. }
  468. }
  469. else {
  470. if (bAdd) {
  471. dbgprintf("error %X adding route to system table", dwErr);
  472. RipLogError(RIPLOG_ADD_ROUTE_FAILED, 0, NULL, dwErr);
  473. InterlockedIncrement(
  474. &g_ripcfg.lpStatsTable->dwSystemAddRouteFailures);
  475. }
  476. else {
  477. dbgprintf("error %X deleting route from system table", dwErr);
  478. RipLogError(RIPLOG_DELETE_ROUTE_FAILED, 0, NULL, dwErr);
  479. InterlockedIncrement(
  480. &g_ripcfg.lpStatsTable->dwSystemDeleteRouteFailures);
  481. }
  482. }
  483. return dwErr;
  484. }
  485. #ifndef CHICAGO
  486. //------------------------------------------------------------------
  487. // Function: OpenTcp
  488. //
  489. // Parameters:
  490. // none.
  491. //
  492. // Opens the handle to the Tcpip driver.
  493. //------------------------------------------------------------------
  494. DWORD OpenTcp() {
  495. NTSTATUS status;
  496. UNICODE_STRING nameString;
  497. IO_STATUS_BLOCK ioStatusBlock;
  498. OBJECT_ATTRIBUTES objectAttributes;
  499. // Open the ip stack for setting routes and parps later.
  500. //
  501. // Open a Handle to the TCP driver.
  502. //
  503. RtlInitUnicodeString(&nameString, DD_TCP_DEVICE_NAME);
  504. InitializeObjectAttributes(&objectAttributes, &nameString,
  505. OBJ_CASE_INSENSITIVE, NULL, NULL);
  506. status = NtCreateFile(&g_ripcfg.hTCPDriver,
  507. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  508. &objectAttributes, &ioStatusBlock, NULL,
  509. FILE_ATTRIBUTE_NORMAL,
  510. FILE_SHARE_READ | FILE_SHARE_WRITE,
  511. FILE_OPEN_IF, 0, NULL, 0);
  512. return (status == STATUS_SUCCESS ? 0 : ERROR_OPEN_FAILED);
  513. }
  514. //---------------------------------------------------------------------
  515. // Function: TCPQueryInformationEx
  516. //
  517. // Parameters:
  518. // TDIObjectID *ID The TDI Object ID to query
  519. // void *Buffer buffer to contain the query results
  520. // LPDWORD *BufferSize pointer to the size of the buffer
  521. // filled in with the amount of data.
  522. // UCHAR *Context context value for the query. should
  523. // be zeroed for a new query. It will be
  524. // filled with context information for
  525. // linked enumeration queries.
  526. //
  527. // Returns:
  528. // An NTSTATUS value.
  529. //
  530. // This routine provides the interface to the TDI QueryInformationEx
  531. // facility of the TCP/IP stack on NT.
  532. //---------------------------------------------------------------------
  533. DWORD TCPQueryInformationEx(LPVOID lpvInBuffer, LPDWORD lpdwInSize,
  534. LPVOID lpvOutBuffer, LPDWORD lpdwOutSize) {
  535. NTSTATUS status;
  536. IO_STATUS_BLOCK isbStatusBlock;
  537. if (g_ripcfg.hTCPDriver == NULL) {
  538. OpenTcp();
  539. }
  540. status = NtDeviceIoControlFile(g_ripcfg.hTCPDriver, // Driver handle
  541. NULL, // Event
  542. NULL, // APC Routine
  543. NULL, // APC context
  544. &isbStatusBlock, // Status block
  545. IOCTL_TCP_QUERY_INFORMATION_EX, // Control
  546. lpvInBuffer, // Input buffer
  547. *lpdwInSize, // Input buffer size
  548. lpvOutBuffer, // Output buffer
  549. *lpdwOutSize); // Output buffer size
  550. if (status == STATUS_PENDING) {
  551. status = NtWaitForSingleObject(g_ripcfg.hTCPDriver, TRUE, NULL);
  552. status = isbStatusBlock.Status;
  553. }
  554. if (status != STATUS_SUCCESS) {
  555. *lpdwOutSize = 0;
  556. }
  557. else {
  558. *lpdwOutSize = (ULONG)isbStatusBlock.Information;
  559. }
  560. return status;
  561. }
  562. //---------------------------------------------------------------------------
  563. // Function: TCPSetInformationEx
  564. //
  565. // Parameters:
  566. //
  567. // TDIObjectID *ID the TDI Object ID to set
  568. // void *lpvBuffer data buffer containing the information
  569. // to be set
  570. // DWORD dwBufferSize the size of the data buffer.
  571. //
  572. // This routine provides the interface to the TDI SetInformationEx
  573. // facility of the TCP/IP stack on NT.
  574. //---------------------------------------------------------------------------
  575. DWORD TCPSetInformationEx(LPVOID lpvInBuffer, LPDWORD lpdwInSize,
  576. LPVOID lpvOutBuffer, LPDWORD lpdwOutSize) {
  577. NTSTATUS status;
  578. IO_STATUS_BLOCK isbStatusBlock;
  579. if (g_ripcfg.hTCPDriver == NULL) {
  580. OpenTcp();
  581. }
  582. status = NtDeviceIoControlFile(g_ripcfg.hTCPDriver, // Driver handle
  583. NULL, // Event
  584. NULL, // APC Routine
  585. NULL, // APC context
  586. &isbStatusBlock, // Status block
  587. IOCTL_TCP_SET_INFORMATION_EX, // Control
  588. lpvInBuffer, // Input buffer
  589. *lpdwInSize, // Input buffer size
  590. lpvOutBuffer, // Output buffer
  591. *lpdwOutSize); // Output buffer size
  592. if (status == STATUS_PENDING) {
  593. status = NtWaitForSingleObject(g_ripcfg.hTCPDriver, TRUE, NULL);
  594. status = isbStatusBlock.Status;
  595. }
  596. if (status != STATUS_SUCCESS) {
  597. *lpdwOutSize = 0;
  598. }
  599. else {
  600. *lpdwOutSize = (ULONG)isbStatusBlock.Information;
  601. }
  602. return status;
  603. }
  604. #endif