3 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(const 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 IsReconnectHackNeeded(PDHCP_ADAPTER Adapter
, const MIB_IFROW
* IfEntry
)
206 struct protocol
*proto
;
207 PIP_ADAPTER_INFO AdapterInfo
, Orig
;
209 char *ZeroAddress
= "0.0.0.0";
211 proto
= find_protocol_by_adapter(&Adapter
->DhclientInfo
);
213 if (Adapter
->DhclientInfo
.client
->state
== S_BOUND
&& !proto
)
216 if (Adapter
->DhclientInfo
.client
->state
!= S_BOUND
&&
217 Adapter
->DhclientInfo
.client
->state
!= S_STATIC
)
222 Orig
= AdapterInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(IP_ADAPTER_INFO
));
223 Size
= sizeof(IP_ADAPTER_INFO
);
230 Ret
= GetAdaptersInfo(AdapterInfo
, &Size
);
231 if (Ret
== ERROR_BUFFER_OVERFLOW
)
233 HeapFree(GetProcessHeap(), 0, AdapterInfo
);
234 AdapterInfo
= HeapAlloc(GetProcessHeap(), 0, Size
);
241 if (GetAdaptersInfo(AdapterInfo
, &Size
) != NO_ERROR
)
248 for (; AdapterInfo
!= NULL
; AdapterInfo
= AdapterInfo
->Next
)
250 if (AdapterInfo
->Index
== IfEntry
->dwIndex
)
254 if (AdapterInfo
== NULL
)
256 HeapFree(GetProcessHeap(), 0, Orig
);
261 else if (Ret
!= NO_ERROR
)
263 HeapFree(GetProcessHeap(), 0, Orig
);
268 if (!strcmp(AdapterInfo
->IpAddressList
.IpAddress
.String
, ZeroAddress
))
270 HeapFree(GetProcessHeap(), 0, Orig
);
276 HeapFree(GetProcessHeap(), 0, Orig
);
283 * XXX Figure out the way to bind a specific adapter to a socket.
285 DWORD WINAPI
AdapterDiscoveryThread(LPVOID Context
) {
286 PMIB_IFTABLE Table
= (PMIB_IFTABLE
) malloc(sizeof(MIB_IFTABLE
));
287 DWORD Error
, Size
= sizeof(MIB_IFTABLE
);
288 PDHCP_ADAPTER Adapter
= NULL
;
289 HANDLE AdapterStateChangedEvent
= (HANDLE
)Context
;
290 struct interface_info
*ifi
= NULL
;
291 struct protocol
*proto
;
292 int i
, AdapterCount
= 0, Broadcast
;
294 /* FIXME: Kill this thread when the service is stopped */
297 DH_DbgPrint(MID_TRACE
,("Getting Adapter List...\n"));
299 while( (Error
= GetIfTable(Table
, &Size
, 0 )) ==
300 ERROR_INSUFFICIENT_BUFFER
) {
301 DH_DbgPrint(MID_TRACE
,("Error %d, New Buffer Size: %d\n", Error
, Size
));
303 Table
= (PMIB_IFTABLE
) malloc( Size
);
306 if( Error
!= NO_ERROR
)
308 /* HACK: We are waiting until TCP/IP starts */
313 DH_DbgPrint(MID_TRACE
,("Got Adapter List (%d entries)\n", Table
->dwNumEntries
));
315 for( i
= Table
->dwNumEntries
- 1; i
>= 0; i
-- ) {
316 DH_DbgPrint(MID_TRACE
,("Getting adapter %d attributes\n",
317 Table
->table
[i
].dwIndex
));
321 if ((Adapter
= AdapterFindByHardwareAddress(Table
->table
[i
].bPhysAddr
, Table
->table
[i
].dwPhysAddrLen
)))
323 proto
= find_protocol_by_adapter(&Adapter
->DhclientInfo
);
325 /* This is an existing adapter */
326 if (InterfaceConnected(&Table
->table
[i
])) {
327 /* We're still active so we stay in the list */
328 ifi
= &Adapter
->DhclientInfo
;
330 /* This is a hack because IP helper API sucks */
331 if (IsReconnectHackNeeded(Adapter
, &Table
->table
[i
]))
333 /* This handles a disconnect/reconnect */
336 remove_protocol(proto
);
337 Adapter
->DhclientInfo
.client
->state
= S_INIT
;
339 /* These are already invalid since the media state change */
340 Adapter
->RouterMib
.dwForwardNextHop
= 0;
341 Adapter
->NteContext
= 0;
343 add_protocol(Adapter
->DhclientInfo
.name
,
344 Adapter
->DhclientInfo
.rfdesc
,
345 got_one
, &Adapter
->DhclientInfo
);
346 state_init(&Adapter
->DhclientInfo
);
348 SetEvent(AdapterStateChangedEvent
);
353 remove_protocol(proto
);
355 /* We've lost our link so out we go */
356 RemoveEntryList(&Adapter
->ListEntry
);
367 Adapter
= (DHCP_ADAPTER
*) calloc( sizeof( DHCP_ADAPTER
) + Table
->table
[i
].dwMtu
, 1 );
369 if( Adapter
&& Table
->table
[i
].dwType
== MIB_IF_TYPE_ETHERNET
&& InterfaceConnected(&Table
->table
[i
])) {
370 memcpy( &Adapter
->IfMib
, &Table
->table
[i
],
371 sizeof(Adapter
->IfMib
) );
372 Adapter
->DhclientInfo
.client
= &Adapter
->DhclientState
;
373 Adapter
->DhclientInfo
.rbuf
= Adapter
->recv_buf
;
374 Adapter
->DhclientInfo
.rbuf_max
= Table
->table
[i
].dwMtu
;
375 Adapter
->DhclientInfo
.rbuf_len
=
376 Adapter
->DhclientInfo
.rbuf_offset
= 0;
377 memcpy(Adapter
->DhclientInfo
.hw_address
.haddr
,
378 Adapter
->IfMib
.bPhysAddr
,
379 Adapter
->IfMib
.dwPhysAddrLen
);
380 Adapter
->DhclientInfo
.hw_address
.hlen
= Adapter
->IfMib
.dwPhysAddrLen
;
382 /* I'm not sure where else to set this, but
383 some DHCP servers won't take a zero.
384 We checked the hardware type earlier in
386 Adapter
->DhclientInfo
.hw_address
.htype
= HTYPE_ETHER
;
388 if( DhcpSocket
== INVALID_SOCKET
) {
390 Adapter
->DhclientInfo
.rfdesc
=
391 Adapter
->DhclientInfo
.wfdesc
=
392 socket( AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
394 if (DhcpSocket
!= INVALID_SOCKET
) {
396 /* Allow broadcast on this socket */
398 setsockopt(DhcpSocket
,
401 (const char *)&Broadcast
,
404 Adapter
->ListenAddr
.sin_family
= AF_INET
;
405 Adapter
->ListenAddr
.sin_port
= htons(LOCAL_PORT
);
406 Adapter
->BindStatus
=
407 (bind( Adapter
->DhclientInfo
.rfdesc
,
408 (struct sockaddr
*)&Adapter
->ListenAddr
,
409 sizeof(Adapter
->ListenAddr
) ) == 0) ?
410 0 : WSAGetLastError();
412 error("socket() failed: %d\n", WSAGetLastError());
415 Adapter
->DhclientInfo
.rfdesc
=
416 Adapter
->DhclientInfo
.wfdesc
= DhcpSocket
;
419 Adapter
->DhclientConfig
.timeout
= DHCP_PANIC_TIMEOUT
;
420 Adapter
->DhclientConfig
.initial_interval
= DHCP_DISCOVER_INTERVAL
;
421 Adapter
->DhclientConfig
.retry_interval
= DHCP_DISCOVER_INTERVAL
;
422 Adapter
->DhclientConfig
.select_interval
= 1;
423 Adapter
->DhclientConfig
.reboot_timeout
= DHCP_REBOOT_TIMEOUT
;
424 Adapter
->DhclientConfig
.backoff_cutoff
= DHCP_BACKOFF_MAX
;
425 Adapter
->DhclientState
.interval
=
426 Adapter
->DhclientConfig
.retry_interval
;
428 if( PrepareAdapterForService( Adapter
) ) {
429 Adapter
->DhclientInfo
.next
= ifi
;
430 ifi
= &Adapter
->DhclientInfo
;
432 read_client_conf(&Adapter
->DhclientInfo
);
434 if (Adapter
->DhclientInfo
.client
->state
== S_INIT
)
436 add_protocol(Adapter
->DhclientInfo
.name
,
437 Adapter
->DhclientInfo
.rfdesc
,
438 got_one
, &Adapter
->DhclientInfo
);
440 state_init(&Adapter
->DhclientInfo
);
444 InsertTailList( &AdapterList
, &Adapter
->ListEntry
);
446 SetEvent(AdapterStateChangedEvent
);
448 } else { free( Adapter
); Adapter
= 0; }
449 } else { free( Adapter
); Adapter
= 0; }
452 DH_DbgPrint(MID_TRACE
,("Adapter %d was rejected\n",
453 Table
->table
[i
].dwIndex
));
456 Error
= NotifyAddrChange(NULL
, NULL
);
457 if (Error
!= NO_ERROR
)
464 DbgPrint("DHCPCSVC: Adapter discovery thread is terminating! (Error: %d)\n", Error
);
466 if( Table
) free( Table
);
470 HANDLE
StartAdapterDiscovery(VOID
) {
471 HANDLE ThreadHandle
, EventHandle
;
473 EventHandle
= CreateEvent(NULL
,
478 ThreadHandle
= CreateThread(NULL
,
480 AdapterDiscoveryThread
,
485 if (ThreadHandle
== NULL
)
488 CloseHandle(ThreadHandle
);
494 PLIST_ENTRY ListEntry
;
495 PDHCP_ADAPTER Adapter
;
497 while( !IsListEmpty( &AdapterList
) ) {
498 ListEntry
= (PLIST_ENTRY
)RemoveHeadList( &AdapterList
);
499 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
506 PDHCP_ADAPTER
AdapterFindIndex( unsigned int indx
) {
507 PDHCP_ADAPTER Adapter
;
508 PLIST_ENTRY ListEntry
;
510 for( ListEntry
= AdapterList
.Flink
;
511 ListEntry
!= &AdapterList
;
512 ListEntry
= ListEntry
->Flink
) {
513 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
514 if( Adapter
->IfMib
.dwIndex
== indx
) return Adapter
;
520 PDHCP_ADAPTER
AdapterFindName( const WCHAR
*name
) {
521 PDHCP_ADAPTER Adapter
;
522 PLIST_ENTRY ListEntry
;
524 for( ListEntry
= AdapterList
.Flink
;
525 ListEntry
!= &AdapterList
;
526 ListEntry
= ListEntry
->Flink
) {
527 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
528 if( !wcsicmp( Adapter
->IfMib
.wszName
, name
) ) return Adapter
;
534 PDHCP_ADAPTER
AdapterFindInfo( struct interface_info
*ip
) {
535 PDHCP_ADAPTER Adapter
;
536 PLIST_ENTRY ListEntry
;
538 for( ListEntry
= AdapterList
.Flink
;
539 ListEntry
!= &AdapterList
;
540 ListEntry
= ListEntry
->Flink
) {
541 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
542 if( ip
== &Adapter
->DhclientInfo
) return Adapter
;
548 PDHCP_ADAPTER
AdapterFindByHardwareAddress( u_int8_t haddr
[16], u_int8_t hlen
) {
549 PDHCP_ADAPTER Adapter
;
550 PLIST_ENTRY ListEntry
;
552 for(ListEntry
= AdapterList
.Flink
;
553 ListEntry
!= &AdapterList
;
554 ListEntry
= ListEntry
->Flink
) {
555 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
556 if (Adapter
->DhclientInfo
.hw_address
.hlen
== hlen
&&
557 !memcmp(Adapter
->DhclientInfo
.hw_address
.haddr
,
559 hlen
)) return Adapter
;
565 PDHCP_ADAPTER
AdapterGetFirst() {
566 if( IsListEmpty( &AdapterList
) ) return NULL
; else {
567 return CONTAINING_RECORD
568 ( AdapterList
.Flink
, DHCP_ADAPTER
, ListEntry
);
572 PDHCP_ADAPTER
AdapterGetNext( PDHCP_ADAPTER This
)
574 if( This
->ListEntry
.Flink
== &AdapterList
) return NULL
;
575 return CONTAINING_RECORD
576 ( This
->ListEntry
.Flink
, DHCP_ADAPTER
, ListEntry
);
579 void if_register_send(struct interface_info
*ip
) {
583 void if_register_receive(struct interface_info
*ip
) {