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).
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.
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.
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
25 #define INSTANCE_KEY(a) ((PVOID)((a)->m_Extension.m_TapDevice))
27 #define N_INSTANCE_BUCKETS 256
29 typedef struct _INSTANCE
{
30 struct _INSTANCE
*next
;
31 TapAdapterPointer m_Adapter
;
40 INSTANCE_BUCKET buckets
[N_INSTANCE_BUCKETS
];
43 INSTANCE_HASH
*g_InstanceHash
= NULL
;
45 // must return a hash >= 0 and < N_INSTANCE_BUCKETS
47 InstanceHashValue (PVOID addr
)
49 UCHAR
*p
= (UCHAR
*) &addr
;
51 if (sizeof (addr
) == 4)
52 return p
[0] ^ p
[1] ^ p
[2] ^ p
[3];
53 else if (sizeof (addr
) == 8)
54 return p
[0] ^ p
[1] ^ p
[2] ^ p
[3] ^ p
[4] ^ p
[5] ^ p
[6] ^ p
[7];
62 InitInstanceList (VOID
)
64 MYASSERT (g_InstanceHash
== NULL
);
65 g_InstanceHash
= MemAlloc (sizeof (INSTANCE_HASH
), TRUE
);
69 for (i
= 0; i
< N_INSTANCE_BUCKETS
; ++i
)
70 INIT_MUTEX (&g_InstanceHash
->buckets
[i
].lock
);
84 for (i
= 0; i
< N_INSTANCE_BUCKETS
; ++i
)
87 INSTANCE_BUCKET
*ib
= &g_InstanceHash
->buckets
[i
];
88 ACQUIRE_MUTEX_ADAPTIVE (&ib
->lock
, got_lock
);
93 for (current
= ib
->list
; current
!= NULL
; current
= current
->next
)
95 RELEASE_MUTEX (&ib
->lock
);
106 InstanceMaxBucketSize (VOID
)
112 for (i
= 0; i
< N_INSTANCE_BUCKETS
; ++i
)
116 INSTANCE_BUCKET
*ib
= &g_InstanceHash
->buckets
[i
];
117 ACQUIRE_MUTEX_ADAPTIVE (&ib
->lock
, got_lock
);
122 for (current
= ib
->list
; current
!= NULL
; current
= current
->next
)
126 RELEASE_MUTEX (&ib
->lock
);
137 FreeInstanceList (VOID
)
141 MYASSERT (NInstances() == 0);
142 MemFree (g_InstanceHash
, sizeof (INSTANCE_HASH
));
143 g_InstanceHash
= NULL
;
148 AddAdapterToInstanceList (TapAdapterPointer p_Adapter
)
152 const int hash
= InstanceHashValue(INSTANCE_KEY(p_Adapter
));
153 INSTANCE_BUCKET
*ib
= &g_InstanceHash
->buckets
[hash
];
155 DEBUGP (("[TAP] AddAdapterToInstanceList hash=%d\n", hash
));
157 ACQUIRE_MUTEX_ADAPTIVE (&ib
->lock
, got_lock
);
161 INSTANCE
*i
= MemAlloc (sizeof (INSTANCE
), FALSE
);
164 MYASSERT (p_Adapter
);
165 i
->m_Adapter
= p_Adapter
;
170 RELEASE_MUTEX (&ib
->lock
);
177 RemoveAdapterFromInstanceList (TapAdapterPointer p_Adapter
)
181 INSTANCE_BUCKET
*ib
= &g_InstanceHash
->buckets
[InstanceHashValue(INSTANCE_KEY(p_Adapter
))];
183 ACQUIRE_MUTEX_ADAPTIVE (&ib
->lock
, got_lock
);
187 INSTANCE
*current
, *prev
=NULL
;
188 for (current
= ib
->list
; current
!= NULL
; current
= current
->next
)
190 if (current
->m_Adapter
== p_Adapter
) // found match
193 prev
->next
= current
->next
;
195 ib
->list
= current
->next
;
196 MemFree (current
->m_Adapter
, sizeof (TapAdapter
));
197 MemFree (current
, sizeof (INSTANCE
));
203 RELEASE_MUTEX (&ib
->lock
);
210 LookupAdapterInInstanceList (PDEVICE_OBJECT p_DeviceObject
)
213 TapAdapterPointer ret
= NULL
;
214 INSTANCE_BUCKET
*ib
= &g_InstanceHash
->buckets
[InstanceHashValue((PVOID
)p_DeviceObject
)];
216 ACQUIRE_MUTEX_ADAPTIVE (&ib
->lock
, got_lock
);
220 INSTANCE
*current
, *prev
=NULL
;
221 for (current
= ib
->list
; current
!= NULL
; current
= current
->next
)
223 if (p_DeviceObject
== INSTANCE_KEY (current
->m_Adapter
)) // found match
225 // move it to head of list
228 prev
->next
= current
->next
;
229 current
->next
= ib
->list
;
232 ret
= ib
->list
->m_Adapter
;
237 RELEASE_MUTEX (&ib
->lock
);