Get rid of "Interrupted service call" messages in syslog
[tomato.git] / release / src / router / openvpn / tap-win32 / instance.c
blob1c97823a0b753027d2df3ae8433a727499bfaa25
1 /*
2 * TAP-Win32/TAP-Win64 -- A kernel driver to provide virtual tap
3 * device functionality on Windows.
5 * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
7 * This source code is Copyright (C) 2002-2009 OpenVPN Technologies, Inc.,
8 * and is released under the GPL version 2 (see below), however due
9 * to the extra costs of supporting Windows Vista, OpenVPN Solutions
10 * LLC reserves the right to change the terms of the TAP-Win32/TAP-Win64
11 * license for versions 9.1 and higher prior to the official release of
12 * OpenVPN 2.1.
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2
16 * as published by the Free Software Foundation.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program (see the file COPYING included with this
25 * distribution); if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #define INSTANCE_KEY(a) ((PVOID)((a)->m_Extension.m_TapDevice))
31 #define N_INSTANCE_BUCKETS 256
33 typedef struct _INSTANCE {
34 struct _INSTANCE *next;
35 TapAdapterPointer m_Adapter;
36 } INSTANCE;
38 typedef struct {
39 INSTANCE *list;
40 MUTEX lock;
41 } INSTANCE_BUCKET;
43 typedef struct {
44 INSTANCE_BUCKET buckets[N_INSTANCE_BUCKETS];
45 } INSTANCE_HASH;
47 INSTANCE_HASH *g_InstanceHash = NULL;
49 // must return a hash >= 0 and < N_INSTANCE_BUCKETS
50 int
51 InstanceHashValue (PVOID addr)
53 UCHAR *p = (UCHAR *) &addr;
55 if (sizeof (addr) == 4)
56 return p[0] ^ p[1] ^ p[2] ^ p[3];
57 else if (sizeof (addr) == 8)
58 return p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4] ^ p[5] ^ p[6] ^ p[7];
59 else
61 MYASSERT (0);
65 BOOLEAN
66 InitInstanceList (VOID)
68 MYASSERT (g_InstanceHash == NULL);
69 g_InstanceHash = MemAlloc (sizeof (INSTANCE_HASH), TRUE);
70 if (g_InstanceHash)
72 int i;
73 for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
74 INIT_MUTEX (&g_InstanceHash->buckets[i].lock);
75 return TRUE;
77 else
78 return FALSE;
81 int
82 NInstances (VOID)
84 int i, n = 0;
86 if (g_InstanceHash)
88 for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
90 BOOLEAN got_lock;
91 INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[i];
92 ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
94 if (got_lock)
96 INSTANCE *current;
97 for (current = ib->list; current != NULL; current = current->next)
98 ++n;
99 RELEASE_MUTEX (&ib->lock);
101 else
102 return -1;
106 return n;
110 InstanceMaxBucketSize (VOID)
112 int i, n = 0;
114 if (g_InstanceHash)
116 for (i = 0; i < N_INSTANCE_BUCKETS; ++i)
118 BOOLEAN got_lock;
119 int bucket_size = 0;
120 INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[i];
121 ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
123 if (got_lock)
125 INSTANCE *current;
126 for (current = ib->list; current != NULL; current = current->next)
127 ++bucket_size;
128 if (bucket_size > n)
129 n = bucket_size;
130 RELEASE_MUTEX (&ib->lock);
132 else
133 return -1;
137 return n;
140 VOID
141 FreeInstanceList (VOID)
143 if (g_InstanceHash)
145 MYASSERT (NInstances() == 0);
146 MemFree (g_InstanceHash, sizeof (INSTANCE_HASH));
147 g_InstanceHash = NULL;
151 BOOLEAN
152 AddAdapterToInstanceList (TapAdapterPointer p_Adapter)
154 BOOLEAN got_lock;
155 BOOLEAN ret = FALSE;
156 const int hash = InstanceHashValue(INSTANCE_KEY(p_Adapter));
157 INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[hash];
159 DEBUGP (("[TAP] AddAdapterToInstanceList hash=%d\n", hash));
161 ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
163 if (got_lock)
165 INSTANCE *i = MemAlloc (sizeof (INSTANCE), FALSE);
166 if (i)
168 MYASSERT (p_Adapter);
169 i->m_Adapter = p_Adapter;
170 i->next = ib->list;
171 ib->list = i;
172 ret = TRUE;
174 RELEASE_MUTEX (&ib->lock);
177 return ret;
180 BOOLEAN
181 RemoveAdapterFromInstanceList (TapAdapterPointer p_Adapter)
183 BOOLEAN got_lock;
184 BOOLEAN ret = FALSE;
185 INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[InstanceHashValue(INSTANCE_KEY(p_Adapter))];
187 ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
189 if (got_lock)
191 INSTANCE *current, *prev=NULL;
192 for (current = ib->list; current != NULL; current = current->next)
194 if (current->m_Adapter == p_Adapter) // found match
196 if (prev)
197 prev->next = current->next;
198 else
199 ib->list = current->next;
200 MemFree (current->m_Adapter, sizeof (TapAdapter));
201 MemFree (current, sizeof (INSTANCE));
202 ret = TRUE;
203 break;
205 prev = current;
207 RELEASE_MUTEX (&ib->lock);
210 return ret;
213 TapAdapterPointer
214 LookupAdapterInInstanceList (PDEVICE_OBJECT p_DeviceObject)
216 BOOLEAN got_lock;
217 TapAdapterPointer ret = NULL;
218 INSTANCE_BUCKET *ib = &g_InstanceHash->buckets[InstanceHashValue((PVOID)p_DeviceObject)];
220 ACQUIRE_MUTEX_ADAPTIVE (&ib->lock, got_lock);
222 if (got_lock)
224 INSTANCE *current, *prev=NULL;
225 for (current = ib->list; current != NULL; current = current->next)
227 if (p_DeviceObject == INSTANCE_KEY (current->m_Adapter)) // found match
229 // move it to head of list
230 if (prev)
232 prev->next = current->next;
233 current->next = ib->list;
234 ib->list = current;
236 ret = ib->list->m_Adapter;
237 break;
239 prev = current;
241 RELEASE_MUTEX (&ib->lock);
244 return ret;