3 static SOCKET DhcpSocket
= INVALID_SOCKET
;
4 static LIST_ENTRY AdapterList
;
7 PCHAR
*GetSubkeyNames( PCHAR MainKeyName
, PCHAR Append
) {
11 PCHAR
*Out
, OutKeyName
;
12 DWORD CharTotal
= 0, AppendLen
= 1 + strlen(Append
);
13 DWORD MaxSubKeyLen
= 0, MaxSubKeys
= 0;
15 Error
= RegOpenKey( HKEY_LOCAL_MACHINE
, MainKeyName
, &MainKey
);
17 if( Error
) return NULL
;
19 Error
= RegQueryInfoKey
22 &MaxSubKeys
, &MaxSubKeyLen
,
23 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
25 DH_DbgPrint(MID_TRACE
,("MaxSubKeys: %d, MaxSubKeyLen %d\n",
26 MaxSubKeys
, MaxSubKeyLen
));
28 CharTotal
= (sizeof(PCHAR
) + MaxSubKeyLen
+ AppendLen
) * (MaxSubKeys
+ 1);
30 DH_DbgPrint(MID_TRACE
,("AppendLen: %d, CharTotal: %d\n",
31 AppendLen
, CharTotal
));
33 Out
= (CHAR
**) malloc( CharTotal
);
34 OutKeyName
= ((PCHAR
)&Out
[MaxSubKeys
+1]);
36 if( !Out
) { RegCloseKey( MainKey
); return NULL
; }
41 Error
= RegEnumKey( MainKey
, i
, OutKeyName
, MaxSubKeyLen
);
43 strcat( OutKeyName
, Append
);
44 DH_DbgPrint(MID_TRACE
,("[%d]: %s\n", i
, OutKeyName
));
45 OutKeyName
+= strlen(OutKeyName
) + 1;
48 } while( Error
== ERROR_SUCCESS
);
50 RegCloseKey( MainKey
);
55 PCHAR
RegReadString( HKEY Root
, PCHAR Subkey
, PCHAR Value
) {
57 DWORD SubOutLen
= 0, Error
= 0;
60 DH_DbgPrint(MID_TRACE
,("Looking in %x:%s:%s\n", Root
, Subkey
, Value
));
62 if( Subkey
&& strlen(Subkey
) ) {
63 if( RegOpenKey( Root
, Subkey
, &ValueKey
) != ERROR_SUCCESS
)
65 } else ValueKey
= Root
;
67 DH_DbgPrint(MID_TRACE
,("Got Key %x\n", ValueKey
));
69 if( (Error
= RegQueryValueEx( ValueKey
, Value
, NULL
, NULL
,
70 (LPBYTE
)SubOut
, &SubOutLen
)) != ERROR_SUCCESS
)
73 DH_DbgPrint(MID_TRACE
,("Value %s has size %d\n", Value
, SubOutLen
));
75 if( !(SubOut
= (CHAR
*) malloc(SubOutLen
)) )
78 if( (Error
= RegQueryValueEx( ValueKey
, Value
, NULL
, NULL
,
79 (LPBYTE
)SubOut
, &SubOutLen
)) != ERROR_SUCCESS
)
82 DH_DbgPrint(MID_TRACE
,("Value %s is %s\n", Value
, SubOut
));
87 if( SubOut
) { free( SubOut
); SubOut
= NULL
; }
89 if( ValueKey
&& ValueKey
!= Root
) {
90 DH_DbgPrint(MID_TRACE
,("Closing key %x\n", ValueKey
));
91 RegCloseKey( ValueKey
);
94 DH_DbgPrint(MID_TRACE
,("Returning %x with error %d\n", SubOut
, Error
));
99 HKEY
FindAdapterKey( PDHCP_ADAPTER Adapter
) {
102 "SYSTEM\\CurrentControlSet\\Control\\Class\\"
103 "{4D36E972-E325-11CE-BFC1-08002BE10318}";
104 PCHAR TargetKeyNameStart
=
105 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
106 PCHAR TargetKeyName
= NULL
;
107 PCHAR
*EnumKeysLinkage
= GetSubkeyNames( EnumKeyName
, "\\Linkage" );
108 PCHAR
*EnumKeysTop
= GetSubkeyNames( EnumKeyName
, "" );
109 PCHAR RootDevice
= NULL
;
110 HKEY EnumKey
, OutKey
= NULL
;
111 DWORD Error
= ERROR_SUCCESS
;
113 if( !EnumKeysLinkage
|| !EnumKeysTop
) goto cleanup
;
115 Error
= RegOpenKey( HKEY_LOCAL_MACHINE
, EnumKeyName
, &EnumKey
);
117 if( Error
) goto cleanup
;
119 for( i
= 0; EnumKeysLinkage
[i
]; i
++ ) {
120 RootDevice
= RegReadString
121 ( EnumKey
, EnumKeysLinkage
[i
], "RootDevice" );
124 !strcmp( RootDevice
, Adapter
->DhclientInfo
.name
) ) {
126 (CHAR
*) malloc( strlen( TargetKeyNameStart
) +
127 strlen( RootDevice
) + 1);
128 if( !TargetKeyName
) goto cleanup
;
129 sprintf( TargetKeyName
, "%s%s",
130 TargetKeyNameStart
, RootDevice
);
131 Error
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, TargetKeyName
, 0, NULL
, 0, KEY_READ
, NULL
, &OutKey
, NULL
);
134 free( RootDevice
); RootDevice
= 0;
139 if( RootDevice
) free( RootDevice
);
140 if( EnumKeysLinkage
) free( EnumKeysLinkage
);
141 if( EnumKeysTop
) free( EnumKeysTop
);
142 if( TargetKeyName
) free( TargetKeyName
);
147 BOOL
PrepareAdapterForService( PDHCP_ADAPTER Adapter
) {
149 DWORD Error
= ERROR_SUCCESS
, DhcpEnabled
, Length
= sizeof(DWORD
);
151 Adapter
->DhclientState
.config
= &Adapter
->DhclientConfig
;
152 strncpy(Adapter
->DhclientInfo
.name
, (char*)Adapter
->IfMib
.bDescr
,
153 sizeof(Adapter
->DhclientInfo
.name
));
155 AdapterKey
= FindAdapterKey( Adapter
);
158 Error
= RegQueryValueEx(AdapterKey
, "EnableDHCP", NULL
, NULL
, (LPBYTE
)&DhcpEnabled
, &Length
);
160 if (Error
!= ERROR_SUCCESS
|| Length
!= sizeof(DWORD
))
163 CloseHandle(AdapterKey
);
167 /* DHCP enabled by default */
172 /* Non-automatic case */
173 DbgPrint("DHCPCSVC: Adapter Name: [%s] (static)\n", Adapter
->DhclientInfo
.name
);
175 Adapter
->DhclientState
.state
= S_STATIC
;
178 DbgPrint("DHCPCSVC: Adapter Name: [%s] (dynamic)\n", Adapter
->DhclientInfo
.name
);
180 Adapter
->DhclientInfo
.client
->state
= S_INIT
;
187 WSAStartup(0x0101,&wsd
);
189 InitializeListHead( &AdapterList
);
193 InterfaceConnected(MIB_IFROW IfEntry
)
195 if (IfEntry
.dwOperStatus
== IF_OPER_STATUS_CONNECTED
||
196 IfEntry
.dwOperStatus
== IF_OPER_STATUS_OPERATIONAL
)
199 DH_DbgPrint(MID_TRACE
,("Interface %d is down\n", IfEntry
.dwIndex
));
204 * XXX Figure out the way to bind a specific adapter to a socket.
206 DWORD WINAPI
AdapterDiscoveryThread(LPVOID Context
) {
207 PMIB_IFTABLE Table
= (PMIB_IFTABLE
) malloc(sizeof(MIB_IFTABLE
));
208 DWORD Error
, Size
= sizeof(MIB_IFTABLE
);
209 PDHCP_ADAPTER Adapter
= NULL
;
210 HANDLE AdapterStateChangedEvent
= (HANDLE
)Context
;
211 struct interface_info
*ifi
= NULL
;
212 int i
, AdapterCount
= 0;
214 /* FIXME: Kill this thread when the service is stopped */
217 DH_DbgPrint(MID_TRACE
,("Getting Adapter List...\n"));
219 while( (Error
= GetIfTable(Table
, &Size
, 0 )) ==
220 ERROR_INSUFFICIENT_BUFFER
) {
221 DH_DbgPrint(MID_TRACE
,("Error %d, New Buffer Size: %d\n", Error
, Size
));
223 Table
= (PMIB_IFTABLE
) malloc( Size
);
226 if( Error
!= NO_ERROR
)
228 /* HACK: We are waiting until TCP/IP starts */
233 DH_DbgPrint(MID_TRACE
,("Got Adapter List (%d entries)\n", Table
->dwNumEntries
));
235 for( i
= Table
->dwNumEntries
- 1; i
>= 0; i
-- ) {
236 DH_DbgPrint(MID_TRACE
,("Getting adapter %d attributes\n",
237 Table
->table
[i
].dwIndex
));
241 if ((Adapter
= AdapterFindByHardwareAddress(Table
->table
[i
].bPhysAddr
, Table
->table
[i
].dwPhysAddrLen
)))
243 /* This is an existing adapter */
244 if (InterfaceConnected(Table
->table
[i
])) {
245 /* We're still active so we stay in the list */
246 ifi
= &Adapter
->DhclientInfo
;
248 /* We've lost our link so out we go */
249 RemoveEntryList(&Adapter
->ListEntry
);
260 Adapter
= (DHCP_ADAPTER
*) calloc( sizeof( DHCP_ADAPTER
) + Table
->table
[i
].dwMtu
, 1 );
262 if( Adapter
&& Table
->table
[i
].dwType
== MIB_IF_TYPE_ETHERNET
&& InterfaceConnected(Table
->table
[i
])) {
263 memcpy( &Adapter
->IfMib
, &Table
->table
[i
],
264 sizeof(Adapter
->IfMib
) );
265 Adapter
->DhclientInfo
.client
= &Adapter
->DhclientState
;
266 Adapter
->DhclientInfo
.rbuf
= Adapter
->recv_buf
;
267 Adapter
->DhclientInfo
.rbuf_max
= Table
->table
[i
].dwMtu
;
268 Adapter
->DhclientInfo
.rbuf_len
=
269 Adapter
->DhclientInfo
.rbuf_offset
= 0;
270 memcpy(Adapter
->DhclientInfo
.hw_address
.haddr
,
271 Adapter
->IfMib
.bPhysAddr
,
272 Adapter
->IfMib
.dwPhysAddrLen
);
273 Adapter
->DhclientInfo
.hw_address
.hlen
= Adapter
->IfMib
.dwPhysAddrLen
;
275 /* I'm not sure where else to set this, but
276 some DHCP servers won't take a zero.
277 We checked the hardware type earlier in
279 Adapter
->DhclientInfo
.hw_address
.htype
= HTYPE_ETHER
;
281 if( DhcpSocket
== INVALID_SOCKET
) {
283 Adapter
->DhclientInfo
.rfdesc
=
284 Adapter
->DhclientInfo
.wfdesc
=
285 socket( AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
287 if (DhcpSocket
!= INVALID_SOCKET
) {
288 Adapter
->ListenAddr
.sin_family
= AF_INET
;
289 Adapter
->ListenAddr
.sin_port
= htons(LOCAL_PORT
);
290 Adapter
->BindStatus
=
291 (bind( Adapter
->DhclientInfo
.rfdesc
,
292 (struct sockaddr
*)&Adapter
->ListenAddr
,
293 sizeof(Adapter
->ListenAddr
) ) == 0) ?
294 0 : WSAGetLastError();
296 error("socket() failed: %d\n", WSAGetLastError());
299 Adapter
->DhclientInfo
.rfdesc
=
300 Adapter
->DhclientInfo
.wfdesc
= DhcpSocket
;
303 Adapter
->DhclientConfig
.timeout
= DHCP_PANIC_TIMEOUT
;
304 Adapter
->DhclientConfig
.initial_interval
= DHCP_DISCOVER_INTERVAL
;
305 Adapter
->DhclientConfig
.retry_interval
= DHCP_DISCOVER_INTERVAL
;
306 Adapter
->DhclientConfig
.select_interval
= 1;
307 Adapter
->DhclientConfig
.reboot_timeout
= DHCP_REBOOT_TIMEOUT
;
308 Adapter
->DhclientConfig
.backoff_cutoff
= DHCP_BACKOFF_MAX
;
309 Adapter
->DhclientState
.interval
=
310 Adapter
->DhclientConfig
.retry_interval
;
312 if( PrepareAdapterForService( Adapter
) ) {
313 Adapter
->DhclientInfo
.next
= ifi
;
314 ifi
= &Adapter
->DhclientInfo
;
316 read_client_conf(&Adapter
->DhclientInfo
);
318 if (Adapter
->DhclientInfo
.client
->state
== S_INIT
)
320 add_protocol(Adapter
->DhclientInfo
.name
,
321 Adapter
->DhclientInfo
.rfdesc
,
322 got_one
, &Adapter
->DhclientInfo
);
324 state_init(&Adapter
->DhclientInfo
);
328 InsertTailList( &AdapterList
, &Adapter
->ListEntry
);
330 SetEvent(AdapterStateChangedEvent
);
332 } else { free( Adapter
); Adapter
= 0; }
333 } else { free( Adapter
); Adapter
= 0; }
336 DH_DbgPrint(MID_TRACE
,("Adapter %d was rejected\n",
337 Table
->table
[i
].dwIndex
));
339 Error
= NotifyAddrChange(NULL
, NULL
);
341 if (Error
!= NO_ERROR
)
351 DbgPrint("DHCPCSVC: Adapter discovery thread is terminating! (Error: %d)\n", Error
);
353 if( Table
) free( Table
);
357 HANDLE
StartAdapterDiscovery(VOID
) {
358 HANDLE
/* ThreadHandle, */ EventHandle
;
360 EventHandle
= CreateEvent(NULL
,
366 ThreadHandle
= CreateThread(NULL
,
368 AdapterDiscoveryThread
,
373 if (ThreadHandle
== NULL
)
376 CloseHandle(ThreadHandle
);
378 AdapterDiscoveryThread((LPVOID
)EventHandle
);
385 PLIST_ENTRY ListEntry
;
386 PDHCP_ADAPTER Adapter
;
388 while( !IsListEmpty( &AdapterList
) ) {
389 ListEntry
= (PLIST_ENTRY
)RemoveHeadList( &AdapterList
);
390 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
397 PDHCP_ADAPTER
AdapterFindIndex( unsigned int indx
) {
398 PDHCP_ADAPTER Adapter
;
399 PLIST_ENTRY ListEntry
;
401 for( ListEntry
= AdapterList
.Flink
;
402 ListEntry
!= &AdapterList
;
403 ListEntry
= ListEntry
->Flink
) {
404 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
405 if( Adapter
->IfMib
.dwIndex
== indx
) return Adapter
;
411 PDHCP_ADAPTER
AdapterFindName( const WCHAR
*name
) {
412 PDHCP_ADAPTER Adapter
;
413 PLIST_ENTRY ListEntry
;
415 for( ListEntry
= AdapterList
.Flink
;
416 ListEntry
!= &AdapterList
;
417 ListEntry
= ListEntry
->Flink
) {
418 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
419 if( !wcsicmp( Adapter
->IfMib
.wszName
, name
) ) return Adapter
;
425 PDHCP_ADAPTER
AdapterFindInfo( struct interface_info
*ip
) {
426 PDHCP_ADAPTER Adapter
;
427 PLIST_ENTRY ListEntry
;
429 for( ListEntry
= AdapterList
.Flink
;
430 ListEntry
!= &AdapterList
;
431 ListEntry
= ListEntry
->Flink
) {
432 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
433 if( ip
== &Adapter
->DhclientInfo
) return Adapter
;
439 PDHCP_ADAPTER
AdapterFindByHardwareAddress( u_int8_t haddr
[16], u_int8_t hlen
) {
440 PDHCP_ADAPTER Adapter
;
441 PLIST_ENTRY ListEntry
;
443 for(ListEntry
= AdapterList
.Flink
;
444 ListEntry
!= &AdapterList
;
445 ListEntry
= ListEntry
->Flink
) {
446 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
447 if (Adapter
->DhclientInfo
.hw_address
.hlen
== hlen
&&
448 !memcmp(Adapter
->DhclientInfo
.hw_address
.haddr
,
450 hlen
)) return Adapter
;
456 PDHCP_ADAPTER
AdapterGetFirst() {
457 if( IsListEmpty( &AdapterList
) ) return NULL
; else {
458 return CONTAINING_RECORD
459 ( AdapterList
.Flink
, DHCP_ADAPTER
, ListEntry
);
463 PDHCP_ADAPTER
AdapterGetNext( PDHCP_ADAPTER This
)
465 if( This
->ListEntry
.Flink
== &AdapterList
) return NULL
;
466 return CONTAINING_RECORD
467 ( This
->ListEntry
.Flink
, DHCP_ADAPTER
, ListEntry
);
470 void if_register_send(struct interface_info
*ip
) {
474 void if_register_receive(struct interface_info
*ip
) {