instance.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /*
  2. * TAP-Windows -- A kernel driver to provide virtual tap
  3. * device functionality on Windows.
  4. *
  5. * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
  6. *
  7. * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc.,
  8. * and is released under the GPL version 2 (see below).
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License version 2
  12. * as published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program (see the file COPYING included with this
  21. * distribution); if not, write to the Free Software Foundation, Inc.,
  22. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. */
  24. #define INSTANCE_KEY(a) ((PVOID)((a)->m_Extension.m_TapDevice))
  25. #define N_INSTANCE_BUCKETS 256
  26. typedef struct _INSTANCE {
  27. struct _INSTANCE *next;
  28. TapAdapterPointer m_Adapter;
  29. } INSTANCE;
  30. typedef struct {
  31. INSTANCE *list;
  32. MUTEX lock;
  33. } INSTANCE_BUCKET;
  34. typedef struct {
  35. INSTANCE_BUCKET buckets[N_INSTANCE_BUCKETS];
  36. } INSTANCE_HASH;
  37. INSTANCE_HASH *g_InstanceHash = NULL;
  38. // must return a hash >= 0 and < N_INSTANCE_BUCKETS
  39. int
  40. InstanceHashValue (PVOID addr)
  41. {
  42. UCHAR *p = (UCHAR *) &addr;
  43. if (sizeof (addr) == 4)
  44. return p[0] ^ p[1] ^ p[2] ^ p[3];
  45. else if (sizeof (addr) == 8)
  46. return p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4] ^ p[5] ^ p[6] ^ p[7];
  47. else
  48. {
  49. MYASSERT (0);
  50. }
  51. }
  52. BOOLEAN
  53. InitInstanceList (VOID)
  54. {
  55. MYASSERT (g_InstanceHash == NULL);
  56. g_InstanceHash = MemAlloc (sizeof (INSTANCE_HASH), TRUE);
  57. if (g_InstanceHash)
  58. {
  59. int i;
  60. for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
  61. INIT_MUTEX (&g_InstanceHash->buckets[i].lock);
  62. return TRUE;
  63. }
  64. else
  65. return FALSE;
  66. }
  67. int
  68. NInstances (VOID)
  69. {
  70. int i, n = 0;
  71. if (g_InstanceHash)
  72. {
  73. for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
  74. {
  75. BOOLEAN got_lock;
  76. INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[i];
  77. ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
  78. if (got_lock)
  79. {
  80. INSTANCE *current;
  81. for (current = ib->list; current != NULL; current = current->next)
  82. ++n;
  83. RELEASE_MUTEX (&ib->lock);
  84. }
  85. else
  86. return -1;
  87. }
  88. }
  89. return n;
  90. }
  91. int
  92. InstanceMaxBucketSize (VOID)
  93. {
  94. int i, n = 0;
  95. if (g_InstanceHash)
  96. {
  97. for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
  98. {
  99. BOOLEAN got_lock;
  100. int bucket_size = 0;
  101. INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[i];
  102. ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
  103. if (got_lock)
  104. {
  105. INSTANCE *current;
  106. for (current = ib->list; current != NULL; current = current->next)
  107. ++bucket_size;
  108. if (bucket_size > n)
  109. n = bucket_size;
  110. RELEASE_MUTEX (&ib->lock);
  111. }
  112. else
  113. return -1;
  114. }
  115. }
  116. return n;
  117. }
  118. VOID
  119. FreeInstanceList (VOID)
  120. {
  121. if (g_InstanceHash)
  122. {
  123. MYASSERT (NInstances() == 0);
  124. MemFree (g_InstanceHash, sizeof (INSTANCE_HASH));
  125. g_InstanceHash = NULL;
  126. }
  127. }
  128. BOOLEAN
  129. AddAdapterToInstanceList (TapAdapterPointer p_Adapter)
  130. {
  131. BOOLEAN got_lock;
  132. BOOLEAN ret = FALSE;
  133. const int hash = InstanceHashValue(INSTANCE_KEY(p_Adapter));
  134. INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[hash];
  135. DEBUGP (("[TAP] AddAdapterToInstanceList hash=%d\n", hash));
  136. ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
  137. if (got_lock)
  138. {
  139. INSTANCE *i = MemAlloc (sizeof (INSTANCE), FALSE);
  140. if (i)
  141. {
  142. MYASSERT (p_Adapter);
  143. i->m_Adapter = p_Adapter;
  144. i->next = ib->list;
  145. ib->list = i;
  146. ret = TRUE;
  147. }
  148. RELEASE_MUTEX (&ib->lock);
  149. }
  150. return ret;
  151. }
  152. BOOLEAN
  153. RemoveAdapterFromInstanceList (TapAdapterPointer p_Adapter)
  154. {
  155. BOOLEAN got_lock;
  156. BOOLEAN ret = FALSE;
  157. INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[InstanceHashValue(INSTANCE_KEY(p_Adapter))];
  158. ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
  159. if (got_lock)
  160. {
  161. INSTANCE *current, *prev=NULL;
  162. for (current = ib->list; current != NULL; current = current->next)
  163. {
  164. if (current->m_Adapter == p_Adapter) // found match
  165. {
  166. if (prev)
  167. prev->next = current->next;
  168. else
  169. ib->list = current->next;
  170. MemFree (current->m_Adapter, sizeof (TapAdapter));
  171. MemFree (current, sizeof (INSTANCE));
  172. ret = TRUE;
  173. break;
  174. }
  175. prev = current;
  176. }
  177. RELEASE_MUTEX (&ib->lock);
  178. }
  179. return ret;
  180. }
  181. TapAdapterPointer
  182. LookupAdapterInInstanceList (PDEVICE_OBJECT p_DeviceObject)
  183. {
  184. BOOLEAN got_lock;
  185. TapAdapterPointer ret = NULL;
  186. INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[InstanceHashValue((PVOID)p_DeviceObject)];
  187. ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
  188. if (got_lock)
  189. {
  190. INSTANCE *current, *prev=NULL;
  191. for (current = ib->list; current != NULL; current = current->next)
  192. {
  193. if (p_DeviceObject == INSTANCE_KEY (current->m_Adapter)) // found match
  194. {
  195. // move it to head of list
  196. if (prev)
  197. {
  198. prev->next = current->next;
  199. current->next = ib->list;
  200. ib->list = current;
  201. }
  202. ret = ib->list->m_Adapter;
  203. break;
  204. }
  205. prev = current;
  206. }
  207. RELEASE_MUTEX (&ib->lock);
  208. }
  209. return ret;
  210. }