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.

360 lines
11 KiB

  1. /*
  2. File NicTable.c
  3. Implements a nic-renaming scheme that allows adaptif to
  4. advertise whatever nic id it chooses to its clients while
  5. maintaining the list of actual nic id's internally.
  6. This functionality was needed in order to Pnp enable the
  7. ipx router. When an adapter is deleted, the stack renumbers
  8. the nicid's so that it maintains a contiguous block of ids
  9. internally. Rather that cause the clients to adptif to
  10. match the stack's renumbering schemes, we handle this
  11. transparently in adptif.
  12. Author: Paul Mayfield, 12/11/97
  13. */
  14. #include "ipxdefs.h"
  15. #define NicMapDefaultSize 500
  16. #define NicMapDefaultFactor 5
  17. #define MAXIMUM_NIC_MAP_SIZE 25000
  18. // Nic map used to associate nic's with virtual ids
  19. typedef struct _NICMAPNODE {
  20. USHORT usVirtualId;
  21. IPX_NIC_INFO * pNicInfo;
  22. } NICMAPNODE;
  23. // Maintains the mapping from nic id to virtual id.
  24. typedef struct _NICMAP {
  25. DWORD dwMapSize;
  26. DWORD dwNicCount;
  27. DWORD dwMaxNicId;
  28. NICMAPNODE ** ppNics;
  29. USHORT * usVirtMap;
  30. } NICMAP;
  31. // Definition of the global nic id map
  32. NICMAP GlobalNicIdMap;
  33. DWORD nmAddNic (NICMAP * pNicMap, IPX_NIC_INFO * pNicInfo);
  34. // Resizes the nic map to accomodate more nics. This function will
  35. // probably only ever be called to allocate the array the first time.
  36. DWORD nmEnlarge(NICMAP * pNicMap) {
  37. USHORT * usVirtMap;
  38. DWORD i, dwNewSize;
  39. NICMAPNODE ** ppNics;
  40. // Are we enlarging for the first time?
  41. if (!pNicMap->dwMapSize)
  42. dwNewSize = NicMapDefaultSize;
  43. else
  44. dwNewSize = pNicMap->dwMapSize * NicMapDefaultFactor;
  45. // Make sure we aren't too big...
  46. if (dwNewSize > MAXIMUM_NIC_MAP_SIZE) {
  47. // do something critical here!
  48. return ERROR_INSUFFICIENT_BUFFER;
  49. }
  50. // Resize the arrays
  51. usVirtMap = (USHORT*) RtlAllocateHeap(RtlProcessHeap(),
  52. 0,
  53. dwNewSize * sizeof(USHORT));
  54. ppNics = (NICMAPNODE **) RtlAllocateHeap(RtlProcessHeap(),
  55. 0,
  56. dwNewSize * sizeof(NICMAPNODE*));
  57. if (!usVirtMap || !ppNics)
  58. return ERROR_NOT_ENOUGH_MEMORY;
  59. // Initialize
  60. FillMemory(usVirtMap, dwNewSize * sizeof(USHORT), 0xff);
  61. ZeroMemory(ppNics, dwNewSize * sizeof(IPX_NIC_INFO*));
  62. usVirtMap[0] = 0;
  63. // Initialize the arrays.
  64. for (i = 0; i < pNicMap->dwMapSize; i++) {
  65. usVirtMap[i] = pNicMap->usVirtMap[i];
  66. ppNics[i] = pNicMap->ppNics[i];
  67. }
  68. // Free old data if needed
  69. if (pNicMap->dwMapSize) {
  70. RtlFreeHeap(RtlProcessHeap(), 0, pNicMap->usVirtMap);
  71. RtlFreeHeap(RtlProcessHeap(), 0, pNicMap->ppNics);
  72. }
  73. // Assign the new arrays
  74. pNicMap->usVirtMap = usVirtMap;
  75. pNicMap->ppNics = ppNics;
  76. pNicMap->dwMapSize = dwNewSize;
  77. return NO_ERROR;
  78. }
  79. // Returns the next available nic id
  80. USHORT nmGetNextVirtualNicId(NICMAP * pNicMap, USHORT usPhysId) {
  81. DWORD i;
  82. // If this can be a one->one mapping, make it so
  83. if (pNicMap->usVirtMap[usPhysId] == NIC_MAP_INVALID_NICID)
  84. return usPhysId;
  85. // Otherwise, walk the array until you find free spot
  86. for (i = 2; i < pNicMap->dwMapSize; i++) {
  87. if (pNicMap->usVirtMap[i] == NIC_MAP_INVALID_NICID)
  88. return (USHORT)i;
  89. }
  90. return NIC_MAP_INVALID_NICID;
  91. }
  92. // Cleans up the nic
  93. DWORD nmCleanup (NICMAP * pNicMap) {
  94. DWORD i;
  95. // Cleanup the virtual map
  96. if (pNicMap->usVirtMap)
  97. RtlFreeHeap(RtlProcessHeap(), 0, pNicMap->usVirtMap);
  98. // Cleanup any of the nics stored in the map
  99. if (pNicMap->ppNics) {
  100. for (i = 0; i < pNicMap->dwMapSize; i++) {
  101. if (pNicMap->ppNics[i]) {
  102. if (pNicMap->ppNics[i]->pNicInfo)
  103. RtlFreeHeap(RtlProcessHeap(), 0, pNicMap->ppNics[i]->pNicInfo);
  104. RtlFreeHeap(RtlProcessHeap(), 0, pNicMap->ppNics[i]);
  105. }
  106. }
  107. RtlFreeHeap(RtlProcessHeap(), 0, pNicMap->ppNics);
  108. }
  109. return NO_ERROR;
  110. }
  111. // Initializes the nic
  112. DWORD nmInitialize (NICMAP * pNicMap) {
  113. DWORD dwErr;
  114. __try {
  115. // Enlarge the map to its default size
  116. ZeroMemory(pNicMap, sizeof (NICMAP));
  117. if ((dwErr = nmEnlarge(pNicMap)) != NO_ERROR)
  118. return dwErr;
  119. }
  120. __finally {
  121. if (dwErr != NO_ERROR) {
  122. nmCleanup(pNicMap);
  123. pNicMap->dwMapSize = 0;
  124. }
  125. }
  126. return NO_ERROR;
  127. }
  128. // Maps virtual nic ids to physical ones
  129. USHORT nmGetPhysicalId (NICMAP * pNicMap, USHORT usVirtAdp) {
  130. return pNicMap->usVirtMap[usVirtAdp];
  131. }
  132. // Maps physical nic ids to virtual ones
  133. USHORT nmGetVirtualId (NICMAP * pNicMap, USHORT usPhysAdp) {
  134. if (usPhysAdp == NIC_MAP_INVALID_NICID)
  135. {
  136. return NIC_MAP_INVALID_NICID;
  137. }
  138. if (pNicMap->ppNics[usPhysAdp])
  139. return pNicMap->ppNics[usPhysAdp]->usVirtualId;
  140. return (usPhysAdp == 0) ? 0 : NIC_MAP_INVALID_NICID;
  141. }
  142. // Gets the nic info associated with a physical adapter
  143. IPX_NIC_INFO * nmGetNicInfo (NICMAP * pNicMap, USHORT usPhysAdp) {
  144. if (pNicMap->ppNics[usPhysAdp])
  145. return pNicMap->ppNics[usPhysAdp]->pNicInfo;
  146. return NULL;
  147. }
  148. // Returns the number of nics in the map
  149. DWORD nmGetNicCount (NICMAP * pNicMap) {
  150. return pNicMap->dwNicCount;
  151. }
  152. // Returns the current maximum nic id
  153. DWORD nmGetMaxNicId (NICMAP * pNicMap) {
  154. return pNicMap->dwMaxNicId;
  155. }
  156. // Reconfigures a nic
  157. DWORD nmReconfigure(NICMAP * pNicMap, IPX_NIC_INFO * pSrc) {
  158. IPX_NIC_INFO * pDst = nmGetNicInfo (pNicMap, pSrc->Details.NicId);
  159. if (pDst) {
  160. CopyMemory(pDst, pSrc, sizeof (IPX_NIC_INFO));
  161. pDst->Details.NicId = nmGetVirtualId (pNicMap, pSrc->Details.NicId);
  162. }
  163. else
  164. return nmAddNic(pNicMap, pSrc);
  165. return NO_ERROR;
  166. }
  167. // Adds a nic to the table
  168. DWORD nmAddNic (NICMAP * pNicMap, IPX_NIC_INFO * pNicInfo) {
  169. USHORT i = pNicInfo->Details.NicId, usVirt;
  170. // If the nic already exists, reconfigure it
  171. if (pNicMap->ppNics[i])
  172. return nmReconfigure (pNicMap, pNicInfo);
  173. // Otherwise, add it
  174. pNicMap->ppNics[i] = (NICMAPNODE*) RtlAllocateHeap (RtlProcessHeap(),
  175. 0,
  176. (sizeof (NICMAPNODE)));
  177. if (!pNicMap->ppNics[i])
  178. return ERROR_NOT_ENOUGH_MEMORY;
  179. pNicMap->ppNics[i]->pNicInfo = (IPX_NIC_INFO *)
  180. RtlAllocateHeap (RtlProcessHeap(),
  181. 0,
  182. sizeof (IPX_NIC_INFO));
  183. if (!pNicMap->ppNics[i]->pNicInfo)
  184. return ERROR_NOT_ENOUGH_MEMORY;
  185. // Initialize it
  186. usVirt = nmGetNextVirtualNicId(pNicMap, i);
  187. pNicMap->ppNics[i]->usVirtualId = usVirt;
  188. pNicMap->ppNics[i]->pNicInfo->Details.NicId = usVirt;
  189. CopyMemory(pNicMap->ppNics[i]->pNicInfo, pNicInfo, sizeof (IPX_NIC_INFO));
  190. pNicMap->usVirtMap[usVirt] = i;
  191. // Update the nic count and maximum nic id
  192. if (i > pNicMap->dwMaxNicId)
  193. pNicMap->dwMaxNicId = i;
  194. pNicMap->dwNicCount++;
  195. return NO_ERROR;
  196. }
  197. // Deletes a nic from the table
  198. DWORD nmDelNic (NICMAP * pNicMap, IPX_NIC_INFO * pNicInfo) {
  199. USHORT i = pNicInfo->Details.NicId, usVirt;
  200. // If the nic doesn't exists do nothing
  201. if (! pNicMap->ppNics[i])
  202. return ERROR_INVALID_INDEX;
  203. // Otherwise, delete it
  204. pNicMap->usVirtMap[pNicMap->ppNics[i]->usVirtualId] = NIC_MAP_INVALID_NICID;
  205. RtlFreeHeap(RtlProcessHeap(), 0, pNicMap->ppNics[i]->pNicInfo);
  206. RtlFreeHeap(RtlProcessHeap(), 0, pNicMap->ppNics[i]);
  207. pNicMap->ppNics[i] = NULL;
  208. // Update the nic count and maximum nic id
  209. if (i >= pNicMap->dwMaxNicId)
  210. pNicMap->dwMaxNicId--;
  211. pNicMap->dwNicCount--;
  212. return NO_ERROR;
  213. }
  214. // Renumbers the nics in the table. dwOpCode is one
  215. // of the NIC_OPCODE_XXX_XXX values
  216. DWORD nmRenumber (NICMAP * pNicMap, USHORT usThreshold, DWORD dwOpCode) {
  217. DWORD i;
  218. // Increment the nic id's if needed
  219. if (dwOpCode == NIC_OPCODE_INCREMENT_NICIDS) {
  220. for (i = pNicMap->dwMaxNicId; i >= usThreshold; i--) {
  221. pNicMap->ppNics[i+1] = pNicMap->ppNics[i];
  222. if (pNicMap->ppNics[i])
  223. pNicMap->usVirtMap[pNicMap->ppNics[i]->usVirtualId] = (USHORT)(i+1);
  224. }
  225. pNicMap->ppNics[usThreshold] = NULL;
  226. }
  227. // Else decrement them
  228. else {
  229. // If there is a nic there, delete it. This should never happen!
  230. if (pNicMap->ppNics[usThreshold])
  231. nmDelNic(pNicMap, pNicMap->ppNics[usThreshold]->pNicInfo);
  232. // Renumber
  233. for (i = usThreshold; i < pNicMap->dwMaxNicId; i++) {
  234. if (pNicMap->ppNics[i+1])
  235. pNicMap->usVirtMap[pNicMap->ppNics[i+1]->usVirtualId] = (USHORT)i;
  236. pNicMap->ppNics[i] = pNicMap->ppNics[i+1];
  237. }
  238. if (pNicMap->ppNics[i])
  239. pNicMap->ppNics[i] = NULL;
  240. }
  241. return NO_ERROR;
  242. }
  243. // Returns whether the nic map is empty
  244. BOOL nmIsEmpty (NICMAP * pNicMap) {
  245. return pNicMap->dwNicCount == 0;
  246. }
  247. // ========================================
  248. // Implementation of the api used by adptif
  249. // ========================================
  250. DWORD NicMapInitialize() {
  251. return nmInitialize(&GlobalNicIdMap);
  252. }
  253. DWORD NicMapCleanup() {
  254. return nmCleanup(&GlobalNicIdMap);
  255. }
  256. USHORT NicMapGetVirtualNicId(USHORT usPhysId) {
  257. return nmGetVirtualId(&GlobalNicIdMap, usPhysId);
  258. }
  259. USHORT NicMapGetPhysicalNicId(USHORT usVirtId) {
  260. return nmGetPhysicalId(&GlobalNicIdMap, usVirtId);
  261. }
  262. DWORD NicMapGetMaxNicId() {
  263. return nmGetMaxNicId(&GlobalNicIdMap);
  264. }
  265. DWORD NicMapGetNicCount() {
  266. return nmGetNicCount(&GlobalNicIdMap);
  267. }
  268. DWORD NicMapAdd (IPX_NIC_INFO * pNic) {
  269. return nmAddNic(&GlobalNicIdMap, pNic);
  270. }
  271. DWORD NicMapDel (IPX_NIC_INFO * pNic) {
  272. return nmDelNic(&GlobalNicIdMap, pNic);
  273. }
  274. DWORD NicMapReconfigure (IPX_NIC_INFO * pNic) {
  275. return nmReconfigure(&GlobalNicIdMap, pNic);
  276. }
  277. DWORD NicMapRenumber(DWORD dwOpCode, USHORT usThreshold) {
  278. return nmRenumber (&GlobalNicIdMap, usThreshold, dwOpCode);
  279. }
  280. IPX_NIC_INFO * NicMapGetNicInfo (USHORT usNicId) {
  281. return nmGetNicInfo (&GlobalNicIdMap, usNicId);
  282. }
  283. BOOL NicMapIsEmpty () {
  284. return nmIsEmpty (&GlobalNicIdMap);
  285. }