2 * TAP-Win32 -- A kernel driver to provide virtual tap device
3 * functionality on Windows. Originally derived
4 * from the CIPE-Win32 project by Damion K. Wilson,
5 * with extensive modifications by James Yonan.
7 * All source code which derives from the CIPE-Win32 project is
8 * Copyright (C) Damion K. Wilson, 2003, and is released under the
9 * GPL version 2 (see below).
11 * All other source code is Copyright (C) 2002-2005 OpenVPN Solutions LLC,
12 * and is released under the GPL version 2 (see below).
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
;
44 INSTANCE_BUCKET buckets
[N_INSTANCE_BUCKETS
];
47 INSTANCE_HASH
*g_InstanceHash
= NULL
;
49 // must return a hash >= 0 and < N_INSTANCE_BUCKETS
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];
66 InitInstanceList (VOID
)
68 MYASSERT (g_InstanceHash
== NULL
);
69 g_InstanceHash
= MemAlloc (sizeof (INSTANCE_HASH
), TRUE
);
73 for (i
= 0; i
< N_INSTANCE_BUCKETS
; ++i
)
74 INIT_MUTEX (&g_InstanceHash
->buckets
[i
].lock
);
88 for (i
= 0; i
< N_INSTANCE_BUCKETS
; ++i
)
91 INSTANCE_BUCKET
*ib
= &g_InstanceHash
->buckets
[i
];
92 ACQUIRE_MUTEX_ADAPTIVE (&ib
->lock
, got_lock
);
97 for (current
= ib
->list
; current
!= NULL
; current
= current
->next
)
99 RELEASE_MUTEX (&ib
->lock
);
110 InstanceMaxBucketSize (VOID
)
116 for (i
= 0; i
< N_INSTANCE_BUCKETS
; ++i
)
120 INSTANCE_BUCKET
*ib
= &g_InstanceHash
->buckets
[i
];
121 ACQUIRE_MUTEX_ADAPTIVE (&ib
->lock
, got_lock
);
126 for (current
= ib
->list
; current
!= NULL
; current
= current
->next
)
130 RELEASE_MUTEX (&ib
->lock
);
141 FreeInstanceList (VOID
)
145 MYASSERT (NInstances() == 0);
146 MemFree (g_InstanceHash
, sizeof (INSTANCE_HASH
));
147 g_InstanceHash
= NULL
;
152 AddAdapterToInstanceList (TapAdapterPointer p_Adapter
)
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
);
165 INSTANCE
*i
= MemAlloc (sizeof (INSTANCE
), FALSE
);
168 MYASSERT (p_Adapter
);
169 i
->m_Adapter
= p_Adapter
;
174 RELEASE_MUTEX (&ib
->lock
);
181 RemoveAdapterFromInstanceList (TapAdapterPointer p_Adapter
)
185 INSTANCE_BUCKET
*ib
= &g_InstanceHash
->buckets
[InstanceHashValue(INSTANCE_KEY(p_Adapter
))];
187 ACQUIRE_MUTEX_ADAPTIVE (&ib
->lock
, 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
197 prev
->next
= current
->next
;
199 ib
->list
= current
->next
;
200 MemFree (current
->m_Adapter
, sizeof (TapAdapter
));
201 MemFree (current
, sizeof (INSTANCE
));
207 RELEASE_MUTEX (&ib
->lock
);
214 LookupAdapterInInstanceList (PDEVICE_OBJECT p_DeviceObject
)
217 TapAdapterPointer ret
= NULL
;
218 INSTANCE_BUCKET
*ib
= &g_InstanceHash
->buckets
[InstanceHashValue((PVOID
)p_DeviceObject
)];
220 ACQUIRE_MUTEX_ADAPTIVE (&ib
->lock
, 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
232 prev
->next
= current
->next
;
233 current
->next
= ib
->list
;
236 ret
= ib
->list
->m_Adapter
;
241 RELEASE_MUTEX (&ib
->lock
);