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.

1009 lines
32 KiB

  1. /*++
  2. Copyright (c) 1994-1997 Microsoft Corporation
  3. Module Name: //KERNEL/RAZZLE3/src/sockets/tcpcmd/ipconfig/adaptlst.c
  4. Abstract:
  5. This module contains functions for retrieving adapter information from
  6. TCP/IP device driver
  7. Contents:
  8. GetAdapterList
  9. GetAdapterList2
  10. AddIpAddress
  11. AddIpAddressString
  12. ConvertIpAddressToString
  13. CopyString
  14. (CleanDescription)
  15. Author:
  16. Richard L Firth (rfirth) 20-May-1994
  17. Revision History:
  18. 20-May-1994 rfirth Created
  19. 30-Apr-97 MohsinA Cleaned Up.
  20. --*/
  21. #include "precomp.h"
  22. #pragma hdrstop
  23. #define OVERFLOW_COUNT 10
  24. //
  25. // prototypes
  26. //
  27. void CleanDescription(LPSTR);
  28. extern PIP_ADAPTER_ORDER_MAP APIENTRY GetAdapterOrderMap();
  29. //
  30. // functions
  31. //
  32. /*******************************************************************************
  33. *
  34. * GetAdapterList
  35. *
  36. * Returns a linked list of IP_ADAPTER_INFO structures. The adapter info is
  37. * queried from the TCP/IP stack. Only those instances corresponding to
  38. * physical adapters are returned
  39. *
  40. * This function only fills in the information in the IP_ADAPTER_INFO
  41. * structure pertaining to the physical adapter (like MAC address, adapter
  42. * type, etc.) and IP address info
  43. *
  44. * ENTRY nothing
  45. *
  46. * EXIT nothing
  47. *
  48. * RETURNS Success - pointer to linked list of IP_ADAPTER_INFO structures,
  49. * 0 terminated
  50. * Failure - NULL
  51. *
  52. * ASSUMES
  53. *
  54. ******************************************************************************/
  55. PIP_ADAPTER_INFO GetAdapterList()
  56. {
  57. TCP_REQUEST_QUERY_INFORMATION_EX req;
  58. TDIObjectID id;
  59. PIP_ADAPTER_INFO list = NULL, prev = NULL;
  60. PIP_ADAPTER_INFO this, UniList = NULL, tmp;
  61. UINT numberOfEntities;
  62. TDIEntityID* pEntity = NULL;
  63. TDIEntityID* entityList;
  64. UINT i;
  65. UINT j;
  66. DWORD status;
  67. DWORD inputLen;
  68. DWORD outputLen;
  69. PIP_ADAPTER_ORDER_MAP adapterOrderMap;
  70. PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pUniInfo=NULL;
  71. ULONG OutBufLen;
  72. //
  73. // get the list of entities supported by TCP/IP then make 2 passes on the
  74. // list. Pass 1 scans for IF_ENTITY's (interface entities perhaps?) which
  75. // describe adapter instances (physical and virtual). Once we have our list
  76. // of adapters, on pass 2 we look for CL_NL_ENTITY's (connection-less
  77. // network layer entities peut-etre?) which will give us the list of IP
  78. // addresses for the adapters we found in pass 1
  79. //
  80. entityList = GetEntityList(&numberOfEntities);
  81. if (!entityList) {
  82. DEBUG_PRINT(("GetAdapterList: failed to get entity list\n"));
  83. return NULL;
  84. }
  85. adapterOrderMap = GetAdapterOrderMap();
  86. if (!adapterOrderMap) {
  87. DEBUG_PRINT(("GetAdapterList: failed to get adapter order map\n"));
  88. ReleaseMemory(entityList);
  89. return NULL;
  90. }
  91. // ====================================================================
  92. // pass 1
  93. // ====================================================================
  94. for (i = 0, pEntity = entityList; i < numberOfEntities; ++i, ++pEntity) {
  95. DEBUG_PRINT(("Pass 1: Entity %lx Instance %ld\n",
  96. pEntity->tei_entity,
  97. pEntity->tei_instance
  98. ));
  99. if (pEntity->tei_entity == IF_ENTITY) {
  100. //
  101. // IF_ENTITY: this entity/instance describes an adapter
  102. //
  103. DWORD isMib;
  104. BYTE info[sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1];
  105. IFEntry* pIfEntry = (IFEntry*)info;
  106. int len;
  107. //
  108. // find out if this entity supports MIB requests
  109. //
  110. memset(&req, 0, sizeof(req));
  111. id.toi_entity = *pEntity;
  112. id.toi_class = INFO_CLASS_GENERIC;
  113. id.toi_type = INFO_TYPE_PROVIDER;
  114. id.toi_id = ENTITY_TYPE_ID;
  115. req.ID = id;
  116. inputLen = sizeof(req);
  117. outputLen = sizeof(isMib);
  118. status = WsControl(IPPROTO_TCP,
  119. WSCNTL_TCPIP_QUERY_INFO,
  120. (LPVOID)&req,
  121. &inputLen,
  122. (LPVOID)&isMib,
  123. &outputLen
  124. );
  125. if (status != TDI_SUCCESS) {
  126. //
  127. // unexpected results - bail out
  128. //
  129. DEBUG_PRINT(("GetAdapterList: WsControl(ENTITY_TYPE_ID): status = %ld, outputLen = %ld\n",
  130. status,
  131. outputLen
  132. ));
  133. // goto error_exit;
  134. continue;
  135. }
  136. if (isMib != IF_MIB) {
  137. //
  138. // entity doesn't support MIB requests - try another
  139. //
  140. DEBUG_PRINT(("GetAdapterList: Entity %lx, Instance %ld doesn't support MIB (%lx)\n",
  141. id.toi_entity.tei_entity,
  142. id.toi_entity.tei_instance,
  143. isMib
  144. ));
  145. continue;
  146. }
  147. //
  148. // MIB requests supported - query the adapter info
  149. //
  150. id.toi_class = INFO_CLASS_PROTOCOL;
  151. id.toi_id = IF_MIB_STATS_ID;
  152. memset(&req, 0, sizeof(req));
  153. req.ID = id;
  154. inputLen = sizeof(req);
  155. outputLen = sizeof(info);
  156. status = WsControl(IPPROTO_TCP,
  157. WSCNTL_TCPIP_QUERY_INFO,
  158. (LPVOID)&req,
  159. &inputLen,
  160. (LPVOID)info,
  161. &outputLen
  162. );
  163. if (status != TDI_SUCCESS && status != ERROR_MORE_DATA) {
  164. //
  165. // unexpected results - bail out
  166. //
  167. DEBUG_PRINT(("GetAdapterList: WsControl(IF_MIB_STATS_ID) returns %ld\n",
  168. status
  169. ));
  170. // goto error_exit;
  171. continue;
  172. }
  173. #ifdef DBG
  174. if( MyTrace ){
  175. print_IFEntry( "GetAdapterList", pIfEntry );
  176. }
  177. #endif
  178. //
  179. // we only want physical adapters
  180. //
  181. if (!IS_INTERESTING_ADAPTER(pIfEntry)) {
  182. DEBUG_PRINT(("GetAdapterList: ignoring adapter #%ld\n",
  183. pIfEntry->if_index
  184. ));
  185. continue;
  186. }
  187. //
  188. // got this adapter info ok. Create a new IP_ADAPTER_INFO and
  189. // fill in what we can
  190. //
  191. this = NEW(IP_ADAPTER_INFO);
  192. if (!this) {
  193. DEBUG_PRINT(("GetAdapterList: no mem for this IP_ADAPTER_INFO\n"));
  194. goto error_exit;
  195. }
  196. memset( this, 0, sizeof( IP_ADAPTER_INFO ) );
  197. len = (int) min(MAX_ADAPTER_DESCRIPTION_LENGTH,
  198. (size_t)pIfEntry->if_descrlen);
  199. strncpy(this->Description, (const char*)pIfEntry->if_descr, len);
  200. this->Description[len] = 0;
  201. //
  202. // if the last word of the description is " Adapter", remove it (its
  203. // redundant) and if the description is terminated with a period,
  204. // remove that too
  205. //
  206. // CleanDescription(this->Description);
  207. len = (int) min(MAX_ADAPTER_ADDRESS_LENGTH,
  208. (size_t)pIfEntry->if_physaddrlen);
  209. this->AddressLength = (BYTE)len;
  210. memcpy(this->Address, pIfEntry->if_physaddr, len);
  211. this->Index = (UINT)pIfEntry->if_index;
  212. this->Type = (UINT)pIfEntry->if_type;
  213. //
  214. // add this IP_ADAPTER_INFO to our list.
  215. // We build the list sorted according to the adapter order
  216. // specified for TCP/IP under its Linkage key.
  217. // In order to put this new entry in the right place in the list,
  218. // we determine its position in the adapter-order, store that
  219. // position in the (unused) 'ComboIndex' field, and then use that
  220. // index for comparison on subsequent insertions.
  221. // If this IP_ADAPTER_INFO doesn't appear in our list at all,
  222. // we put it at the end of the current list.
  223. //
  224. for (j = 0; j < adapterOrderMap->NumAdapters; j++) {
  225. if (adapterOrderMap->AdapterOrder[j] == this->Index) {
  226. break;
  227. }
  228. }
  229. //
  230. // 'j' now contains the 'order' for the new entry.
  231. // Put the entry in the right place in the list.
  232. //
  233. this->ComboIndex = j;
  234. for (prev = NULL, this->Next = list;
  235. this->Next;
  236. prev = this->Next, this->Next = this->Next->Next) {
  237. if (this->ComboIndex >= this->Next->ComboIndex) {
  238. continue;
  239. } else {
  240. break;
  241. }
  242. }
  243. if (prev) { prev->Next = this; }
  244. if (list == this->Next) { list = this; }
  245. }
  246. }
  247. OutBufLen = sizeof(IP_UNIDIRECTIONAL_ADAPTER_ADDRESS) + MAX_UNI_ADAPTERS*sizeof(IPAddr);
  248. pUniInfo = MALLOC(OutBufLen);
  249. if(!pUniInfo) {
  250. printf("GetAdapterList: IP_UNIDIRECTIONAL_ADAPTER_ADDRESS resource failure= %ld\n",ERROR_NOT_ENOUGH_MEMORY);
  251. DEBUG_PRINT(("GetAdapterList: IP_UNIDIRECTIONAL_ADAPTER_ADDRESS resource failure= %ld\n",ERROR_NOT_ENOUGH_MEMORY));
  252. goto error_exit;
  253. }
  254. pUniInfo->NumAdapters = 0;
  255. status = GetUniDirectionalAdapterInfo(pUniInfo, &OutBufLen);
  256. if (status == ERROR_MORE_DATA) {
  257. OutBufLen = sizeof(IP_UNIDIRECTIONAL_ADAPTER_ADDRESS)+pUniInfo->NumAdapters*sizeof(IPAddr);
  258. FREE(pUniInfo);
  259. pUniInfo = MALLOC(OutBufLen);
  260. if(!pUniInfo) {
  261. DEBUG_PRINT(("GetAdapterList: IP_UNIDIRECTIONAL_ADAPTER_ADDRESS resource failure= %ld\n",status));
  262. goto error_exit;
  263. }
  264. status = GetUniDirectionalAdapterInfo(pUniInfo, &OutBufLen);
  265. }
  266. if(status != NO_ERROR) {
  267. DEBUG_PRINT(("GetAdapterList: GetUniDirectionalAdapterInfo returned status= %ld\n",status));
  268. goto error_exit;
  269. }
  270. // ====================================================================
  271. // pass 2
  272. // ====================================================================
  273. for (i = 0, pEntity = entityList; i < numberOfEntities; ++i, ++pEntity) {
  274. DEBUG_PRINT(("Pass 2: Entity %lx Instance %ld\n",
  275. pEntity->tei_entity,
  276. pEntity->tei_instance
  277. ));
  278. if (pEntity->tei_entity == CL_NL_ENTITY) {
  279. IPSNMPInfo info;
  280. DWORD type;
  281. //
  282. // first off, see if this network layer entity supports IP
  283. //
  284. memset(&req, 0, sizeof(req));
  285. id.toi_entity = *pEntity;
  286. id.toi_class = INFO_CLASS_GENERIC;
  287. id.toi_type = INFO_TYPE_PROVIDER;
  288. id.toi_id = ENTITY_TYPE_ID;
  289. req.ID = id;
  290. inputLen = sizeof(req);
  291. outputLen = sizeof(type);
  292. status = WsControl(IPPROTO_TCP,
  293. WSCNTL_TCPIP_QUERY_INFO,
  294. (LPVOID)&req,
  295. &inputLen,
  296. (LPVOID)&type,
  297. &outputLen
  298. );
  299. if (status != TDI_SUCCESS) {
  300. //
  301. // unexpected results - bail out
  302. //
  303. DEBUG_PRINT(("GetAdapterList: WsControl(ENTITY_TYPE_ID): status = %ld, outputLen = %ld\n",
  304. status,
  305. outputLen
  306. ));
  307. // goto error_exit;
  308. continue;
  309. }
  310. if (type != CL_NL_IP) {
  311. //
  312. // nope, not IP - try next one
  313. //
  314. DEBUG_PRINT(("GetAdapterList: CL_NL_ENTITY #%ld not CL_NL_IP\n",
  315. pEntity->tei_instance
  316. ));
  317. continue;
  318. }
  319. //
  320. // okay, this NL provider supports IP. Let's get them addresses:
  321. // First we find out how many by getting the SNMP stats and looking
  322. // at the number of addresses supported by this interface
  323. //
  324. memset(&req, 0, sizeof(req));
  325. id.toi_class = INFO_CLASS_PROTOCOL;
  326. id.toi_id = IP_MIB_STATS_ID;
  327. req.ID = id;
  328. inputLen = sizeof(req);
  329. outputLen = sizeof(info);
  330. status = WsControl(IPPROTO_TCP,
  331. WSCNTL_TCPIP_QUERY_INFO,
  332. (LPVOID)&req,
  333. &inputLen,
  334. (LPVOID)&info,
  335. &outputLen
  336. );
  337. if ((status != TDI_SUCCESS) || (outputLen != sizeof(info))) {
  338. //
  339. // unexpected results - bail out
  340. //
  341. DEBUG_PRINT(("GetAdapterList: WsControl(IP_MIB_STATS_ID): status = %ld, outputLen = %ld\n",
  342. status,
  343. outputLen
  344. ));
  345. // goto error_exit;
  346. continue;
  347. }
  348. //
  349. // get the IP addresses & subnet masks
  350. //
  351. if (info.ipsi_numaddr) {
  352. //
  353. // this interface has some addresses. What are they?
  354. //
  355. LPVOID buffer;
  356. UINT numberOfAddresses;
  357. IPAddrEntry* pAddr;
  358. UINT k;
  359. outputLen = (info.ipsi_numaddr + OVERFLOW_COUNT) *
  360. sizeof(IPAddrEntry);
  361. buffer = (LPVOID)NEW_MEMORY((size_t)outputLen);
  362. if (!buffer) {
  363. DEBUG_PRINT(("GetAdapterList:NEW_MEMORY failed.\n" ));
  364. goto error_exit;
  365. }
  366. memset(&req, 0, sizeof(req));
  367. id.toi_id = IP_MIB_ADDRTABLE_ENTRY_ID;
  368. req.ID = id;
  369. inputLen = sizeof(req);
  370. status = WsControl(IPPROTO_TCP,
  371. WSCNTL_TCPIP_QUERY_INFO,
  372. (LPVOID)&req,
  373. &inputLen,
  374. (LPVOID)buffer,
  375. &outputLen
  376. );
  377. if (status != TDI_SUCCESS) {
  378. //
  379. // unexpected results - bail out
  380. //
  381. DEBUG_PRINT(("GetAdapterList: WsControl(IP_MIB_ADDRTABLE_ENTRY_ID): status = %ld, outputLen = %ld\n",
  382. status,
  383. outputLen
  384. ));
  385. // goto error_exit;
  386. ReleaseMemory((void*)buffer);
  387. continue;
  388. }
  389. //
  390. // now loop through this list of IP addresses, applying them
  391. // to the correct adapter
  392. //
  393. numberOfAddresses = min((UINT)(outputLen / sizeof(IPAddrEntry)),
  394. (UINT)info.ipsi_numaddr
  395. );
  396. DEBUG_PRINT(("GetAdapterList: %d IP addresses\n", numberOfAddresses));
  397. pAddr = (IPAddrEntry*)buffer;
  398. for (k = 0; k < numberOfAddresses; ++k, ++pAddr) {
  399. PIP_ADAPTER_INFO pAdapterInfo;
  400. DEBUG_PRINT(("GetAdapterList: IP address %d.%d.%d.%d, index %ld, context %ld\n",
  401. ((LPBYTE)&pAddr->iae_addr)[0] & 0xff,
  402. ((LPBYTE)&pAddr->iae_addr)[1] & 0xff,
  403. ((LPBYTE)&pAddr->iae_addr)[2] & 0xff,
  404. ((LPBYTE)&pAddr->iae_addr)[3] & 0xff,
  405. pAddr->iae_index,
  406. pAddr->iae_context
  407. ));
  408. for (pAdapterInfo = list; pAdapterInfo; pAdapterInfo = pAdapterInfo->Next) {
  409. if (pAdapterInfo->Index == (UINT)pAddr->iae_index) {
  410. DEBUG_PRINT(("GetAdapterList: adding IP address %d.%d.%d.%d, index %d, context %d\n",
  411. ((LPBYTE)&pAddr->iae_addr)[0] & 0xff,
  412. ((LPBYTE)&pAddr->iae_addr)[1] & 0xff,
  413. ((LPBYTE)&pAddr->iae_addr)[2] & 0xff,
  414. ((LPBYTE)&pAddr->iae_addr)[3] & 0xff,
  415. pAddr->iae_index,
  416. pAddr->iae_context
  417. ));
  418. //
  419. // Append the IP address to the list.
  420. // Note that this operation preserves the order
  421. // of the IP address list returned by TCP/IP.
  422. // This is important because that list contains
  423. // entries listed in the *reverse* of the order
  424. // specified for each adapter. A number of clients
  425. // depend upon this fact when calling this and
  426. // other API routines.
  427. //
  428. if (!AddIpAddress(&pAdapterInfo->IpAddressList,
  429. pAddr->iae_addr,
  430. pAddr->iae_mask,
  431. pAddr->iae_context
  432. )) {
  433. ReleaseMemory((void*)buffer);
  434. goto error_exit;
  435. }
  436. for (j = 0; j < pUniInfo->NumAdapters ; j++) {
  437. if (pAddr->iae_index == pUniInfo->Address[j] ) {
  438. //
  439. // Use DhcpEnabled field as a temporary
  440. // storage to remember the type
  441. //
  442. pAdapterInfo->DhcpEnabled = IF_TYPE_RECEIVE_ONLY;
  443. break;
  444. }
  445. }
  446. break;
  447. }
  448. }
  449. }
  450. ReleaseMemory((void*)buffer);
  451. }
  452. //
  453. // get the gateway server IP address(es)
  454. //
  455. if (info.ipsi_numroutes) {
  456. IPRouteEntry* routeTable;
  457. IPRouteEntry* pRoute;
  458. UINT numberOfRoutes;
  459. UINT k;
  460. int moreRoutes = TRUE;
  461. memset(&req, 0, sizeof(req));
  462. id.toi_id = IP_MIB_RTTABLE_ENTRY_ID;
  463. req.ID = id;
  464. inputLen = sizeof(req);
  465. outputLen = sizeof(IPRouteEntry) * info.ipsi_numroutes;
  466. routeTable = NULL;
  467. //
  468. // the route table may have grown since we got the SNMP stats
  469. //
  470. while (moreRoutes) {
  471. DWORD previousOutputLen;
  472. previousOutputLen = outputLen;
  473. if (routeTable) {
  474. ReleaseMemory((void*)routeTable);
  475. routeTable = NULL;
  476. }
  477. routeTable = (IPRouteEntry*)NEW_MEMORY((size_t)outputLen);
  478. if (!routeTable) {
  479. goto error_exit;
  480. }
  481. status = WsControl(IPPROTO_TCP,
  482. WSCNTL_TCPIP_QUERY_INFO,
  483. (LPVOID)&req,
  484. &inputLen,
  485. (LPVOID)routeTable,
  486. &outputLen
  487. );
  488. if (status != TDI_SUCCESS) {
  489. //
  490. // unexpected results - bail out
  491. //
  492. DEBUG_PRINT(("GetAdapterList: WsControl(IP_MIB_RTTABLE_ENTRY_ID): status = %ld, outputLen = %ld\n",
  493. status,
  494. outputLen
  495. ));
  496. if (status == ERROR_MORE_DATA) {
  497. TCP_REQUEST_QUERY_INFORMATION_EX statsReq;
  498. IPSNMPInfo statsInfo;
  499. DWORD inLen;
  500. DWORD outLen;
  501. memset(&statsReq, 0, sizeof(statsReq));
  502. id.toi_id = IP_MIB_STATS_ID;
  503. statsReq.ID = id;
  504. inLen = sizeof(statsReq);
  505. outLen = sizeof(statsInfo);
  506. status = WsControl( IPPROTO_TCP,
  507. WSCNTL_TCPIP_QUERY_INFO,
  508. (LPVOID)&statsReq,
  509. &inLen,
  510. (LPVOID)&statsInfo,
  511. &outLen);
  512. if (status != TDI_SUCCESS || outLen != sizeof(statsInfo)) {
  513. ReleaseMemory((void*)routeTable);
  514. goto error_exit;
  515. } else {
  516. outputLen = sizeof(IPRouteEntry) * statsInfo.ipsi_numroutes;
  517. }
  518. } else {
  519. ReleaseMemory((void*)routeTable);
  520. goto error_exit;
  521. }
  522. }
  523. if (outputLen <= previousOutputLen) {
  524. moreRoutes = FALSE;
  525. }
  526. }
  527. numberOfRoutes = (UINT)(outputLen / sizeof(IPRouteEntry));
  528. for (k = 0, pRoute = routeTable; k < numberOfRoutes; ++k, ++pRoute)
  529. {
  530. //
  531. // the gateway address has a destination of 0.0.0.0
  532. //
  533. if (pRoute->ire_dest == INADDR_ANY) {
  534. PIP_ADAPTER_INFO pAdapterInfo = list;
  535. for (; pAdapterInfo; pAdapterInfo = pAdapterInfo->Next) {
  536. if (pAdapterInfo->Index == (UINT)pRoute->ire_index) {
  537. TRACE_PRINT(("GetAdapterList: gw=0x%08x.\n",
  538. pRoute->ire_nexthop ));
  539. if (!AddIpAddress(&pAdapterInfo->GatewayList,
  540. pRoute->ire_nexthop,
  541. //
  542. // gateway IP address doesn't
  543. // have corresponding IP mask
  544. //
  545. INADDR_ANY,
  546. 0
  547. )) {
  548. ReleaseMemory((void*)routeTable);
  549. goto error_exit;
  550. }
  551. // MohsinA, 22-Jul-97.
  552. // break;
  553. }
  554. }
  555. }
  556. }
  557. ReleaseMemory((void*)routeTable);
  558. }
  559. }
  560. }
  561. // ====================================================================
  562. ReleaseMemory((void*)entityList);
  563. ReleaseMemory(adapterOrderMap);
  564. //
  565. // If there are any unidirectional adapters
  566. // move them to the end of the list
  567. //
  568. tmp = list;
  569. if (pUniInfo->NumAdapters) {
  570. this = list;
  571. prev = NULL;
  572. while (this) {
  573. if (this->DhcpEnabled == IF_TYPE_RECEIVE_ONLY) {
  574. //
  575. // Remove "this" from the list
  576. //
  577. if (prev) {
  578. prev->Next = this->Next;
  579. } else {
  580. prev = this->Next;
  581. list = this->Next;
  582. }
  583. tmp = this->Next;
  584. //
  585. // Restore DhcbEnabled
  586. //
  587. this->DhcpEnabled = FALSE;
  588. //
  589. // Chain this to list of TV adapters
  590. //
  591. this->Next = UniList;
  592. UniList = this;
  593. this = tmp;
  594. } else {
  595. prev = this;
  596. this = this->Next;
  597. }
  598. }
  599. //
  600. // Insert UniList at the end.
  601. //
  602. if (prev) {
  603. prev->Next = UniList;
  604. } else {
  605. ASSERT(list == NULL);
  606. list = UniList;
  607. }
  608. }
  609. FREE(pUniInfo);
  610. return list;
  611. error_exit:
  612. DEBUG_PRINT(("GetAdapterList: <= failed\n"));
  613. if (entityList) {
  614. ReleaseMemory((void*)entityList);
  615. }
  616. if (adapterOrderMap) {
  617. ReleaseMemory(adapterOrderMap);
  618. }
  619. if (pUniInfo) {
  620. FREE(pUniInfo);
  621. }
  622. KillAdapterInfo(list);
  623. return NULL;
  624. }
  625. /*******************************************************************************
  626. *
  627. * AddIpAddress
  628. *
  629. * Adds an IP_ADDR_STRING to a list. If the input IP_ADDR_STRING is empty this
  630. * is filled in, else a new IP_ADDR_STRING is allocated and chained to the
  631. * input IP_ADDR_STRING
  632. *
  633. * ENTRY AddressList - pointer to IP_ADDR which may or may not already hold
  634. * an IP address
  635. * Address - IP address to add
  636. * Mask - corresponding IP subnet mask
  637. * Context - address context
  638. *
  639. * EXIT AddressList - updated with new info
  640. *
  641. * RETURNS Success - 1
  642. * Failure - 0
  643. *
  644. * ASSUMES 1. INADDR_ANY (ulong 0) indicates inactive IP address
  645. *
  646. ******************************************************************************/
  647. int AddIpAddress(PIP_ADDR_STRING AddressList, DWORD Address, DWORD Mask, DWORD Context)
  648. {
  649. PIP_ADDR_STRING ipAddr;
  650. if (AddressList->IpAddress.String[0]) {
  651. for (ipAddr = AddressList; ipAddr->Next; ipAddr = ipAddr->Next) {
  652. ;
  653. }
  654. ipAddr->Next = NEW(IP_ADDR_STRING);
  655. if (!ipAddr->Next) {
  656. DEBUG_PRINT(("AddIpAddress: failed to allocate memory for IP_ADDR_STRING\n"));
  657. return FALSE;
  658. }
  659. ipAddr = ipAddr->Next;
  660. } else {
  661. ipAddr = AddressList;
  662. }
  663. ConvertIpAddressToString(Address, ipAddr->IpAddress.String);
  664. ConvertIpAddressToString(Mask, ipAddr->IpMask.String);
  665. ipAddr->Context = Context;
  666. ipAddr->Next = NULL;
  667. return TRUE;
  668. }
  669. /*******************************************************************************
  670. *
  671. * AddIpAddressString
  672. *
  673. * Same as AddIpAddress, except the arguments are already converted to strings
  674. *
  675. * ENTRY AddressList - pointer to IP_ADDR which may or may not already hold
  676. * an IP address
  677. * Address - IP address to add, as a string
  678. * Mask - corresponding IP subnet mask, as a string
  679. *
  680. * EXIT AddressList - updated with new info
  681. *
  682. * RETURNS Success - 1
  683. * Failure - 0
  684. *
  685. * ASSUMES nothing
  686. *
  687. ******************************************************************************/
  688. int AddIpAddressString(PIP_ADDR_STRING AddressList, LPSTR Address, LPSTR Mask)
  689. {
  690. PIP_ADDR_STRING ipAddr;
  691. if (AddressList->IpAddress.String[0]) {
  692. for (ipAddr = AddressList; ipAddr->Next; ipAddr = ipAddr->Next) {
  693. if (!strncmp(ipAddr->IpAddress.String, Address, sizeof(ipAddr->IpAddress.String))) {
  694. return FALSE;
  695. }
  696. }
  697. if (!strncmp(ipAddr->IpAddress.String, Address, sizeof(ipAddr->IpAddress.String))) {
  698. return FALSE;
  699. }
  700. ipAddr->Next = NEW(IP_ADDR_STRING);
  701. if (!ipAddr->Next) {
  702. DEBUG_PRINT(("AddIpAddressString: failed to allocate memory for IP_ADDR_STRING\n"));
  703. return FALSE;
  704. }
  705. ipAddr = ipAddr->Next;
  706. } else {
  707. ipAddr = AddressList;
  708. }
  709. CopyString(ipAddr->IpAddress.String, sizeof(ipAddr->IpAddress.String), Address);
  710. CopyString(ipAddr->IpMask.String, sizeof(ipAddr->IpMask.String), Mask);
  711. return TRUE;
  712. }
  713. /*******************************************************************************
  714. *
  715. * ConvertIpAddressToString
  716. *
  717. * Converts a DWORD IP address or subnet mask to dotted decimal string
  718. *
  719. * ENTRY IpAddress - IP Address to convert
  720. * String - pointer to place to store dotted decimal string
  721. *
  722. * EXIT String contains ASCII representation of IpAddress
  723. *
  724. * RETURNS nothing
  725. *
  726. * ASSUMES 1. IP address fits in a DWORD
  727. *
  728. ******************************************************************************/
  729. VOID ConvertIpAddressToString(DWORD IpAddress, LPSTR String)
  730. {
  731. IP_ADDRESS ipAddr;
  732. ipAddr.d = IpAddress;
  733. sprintf(String,
  734. "%d.%d.%d.%d",
  735. ipAddr.b[0],
  736. ipAddr.b[1],
  737. ipAddr.b[2],
  738. ipAddr.b[3]
  739. );
  740. }
  741. /*******************************************************************************
  742. *
  743. * CopyString
  744. *
  745. * Copies a string to a buffer. If the buffer would overflow, the string is
  746. * truncated
  747. *
  748. * ENTRY Destination - destination buffer to copy to
  749. * DestinationLength - size of Destination
  750. * Source - source string to copy
  751. *
  752. * EXIT Destination updated
  753. *
  754. * RETURNS nothing
  755. *
  756. * ASSUMES
  757. *
  758. ******************************************************************************/
  759. VOID CopyString(LPSTR Destination, DWORD DestinationLength, LPSTR Source)
  760. {
  761. SIZE_T maximumCharacters = min(DestinationLength - 1, STRLEN(Source));
  762. strncpy(Destination, Source, maximumCharacters);
  763. Destination[maximumCharacters] = '\0';
  764. }
  765. /*******************************************************************************
  766. *
  767. * CleanDescription
  768. *
  769. * Given an adapter description string retrieved from TCP/IP, remove the
  770. * trailing substring " Adapter". If there is a trailing period, remove that
  771. * too
  772. *
  773. * ENTRY String - pointer to description string to clean up
  774. *
  775. * EXIT String - possibly bits removed
  776. *
  777. * RETURNS voidsville
  778. *
  779. * ASSUMES
  780. *
  781. ******************************************************************************/
  782. void CleanDescription(LPSTR String)
  783. {
  784. SIZE_T len = STRLEN(String);
  785. if (String[len - 1] == '.') {
  786. String[--len] = 0;
  787. }
  788. if (!STRICMP(String + len - (sizeof(" Adapter") - 1), " Adapter")) {
  789. len -= sizeof(" Adapter") - 1;
  790. String[len] = 0;
  791. }
  792. }