4 #include <reactos/debug.h>
6 extern HANDLE hAdapterStateChangedEvent
;
8 SOCKET DhcpSocket
= INVALID_SOCKET
;
9 static LIST_ENTRY AdapterList
;
12 PCHAR
*GetSubkeyNames( PCHAR MainKeyName
, PCHAR Append
) {
16 PCHAR
*Out
, OutKeyName
;
17 SIZE_T CharTotal
= 0, AppendLen
= 1 + strlen(Append
);
18 DWORD MaxSubKeyLen
= 0, MaxSubKeys
= 0;
20 Error
= RegOpenKey( HKEY_LOCAL_MACHINE
, MainKeyName
, &MainKey
);
22 if( Error
) return NULL
;
24 Error
= RegQueryInfoKey
27 &MaxSubKeys
, &MaxSubKeyLen
,
28 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
31 DH_DbgPrint(MID_TRACE
,("MaxSubKeys: %d, MaxSubKeyLen %d\n",
32 MaxSubKeys
, MaxSubKeyLen
));
34 CharTotal
= (sizeof(PCHAR
) + MaxSubKeyLen
+ AppendLen
) * (MaxSubKeys
+ 1);
36 DH_DbgPrint(MID_TRACE
,("AppendLen: %d, CharTotal: %d\n",
37 AppendLen
, CharTotal
));
39 Out
= (CHAR
**) malloc( CharTotal
);
40 OutKeyName
= ((PCHAR
)&Out
[MaxSubKeys
+1]);
42 if( !Out
) { RegCloseKey( MainKey
); return NULL
; }
47 Error
= RegEnumKey( MainKey
, i
, OutKeyName
, MaxSubKeyLen
);
49 strcat( OutKeyName
, Append
);
50 DH_DbgPrint(MID_TRACE
,("[%d]: %s\n", i
, OutKeyName
));
51 OutKeyName
+= strlen(OutKeyName
) + 1;
54 } while( Error
== ERROR_SUCCESS
);
56 RegCloseKey( MainKey
);
61 PCHAR
RegReadString( HKEY Root
, PCHAR Subkey
, PCHAR Value
) {
63 DWORD SubOutLen
= 0, Error
= 0;
66 DH_DbgPrint(MID_TRACE
,("Looking in %x:%s:%s\n", Root
, Subkey
, Value
));
68 if( Subkey
&& strlen(Subkey
) ) {
69 if( RegOpenKey( Root
, Subkey
, &ValueKey
) != ERROR_SUCCESS
)
71 } else ValueKey
= Root
;
73 DH_DbgPrint(MID_TRACE
,("Got Key %x\n", ValueKey
));
75 if( (Error
= RegQueryValueEx( ValueKey
, Value
, NULL
, NULL
,
76 (LPBYTE
)SubOut
, &SubOutLen
)) != ERROR_SUCCESS
)
79 DH_DbgPrint(MID_TRACE
,("Value %s has size %d\n", Value
, SubOutLen
));
81 if( !(SubOut
= (CHAR
*) malloc(SubOutLen
)) )
84 if( (Error
= RegQueryValueEx( ValueKey
, Value
, NULL
, NULL
,
85 (LPBYTE
)SubOut
, &SubOutLen
)) != ERROR_SUCCESS
)
88 DH_DbgPrint(MID_TRACE
,("Value %s is %s\n", Value
, SubOut
));
93 if( SubOut
) { free( SubOut
); SubOut
= NULL
; }
95 if( ValueKey
&& ValueKey
!= Root
) {
96 DH_DbgPrint(MID_TRACE
,("Closing key %x\n", ValueKey
));
97 RegCloseKey( ValueKey
);
100 DH_DbgPrint(MID_TRACE
,("Returning %x with error %d\n", SubOut
, Error
));
105 HKEY
FindAdapterKey( PDHCP_ADAPTER Adapter
) {
108 "SYSTEM\\CurrentControlSet\\Control\\Class\\"
109 "{4D36E972-E325-11CE-BFC1-08002BE10318}";
110 PCHAR TargetKeyNameStart
=
111 "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
112 PCHAR TargetKeyName
= NULL
;
113 PCHAR
*EnumKeysLinkage
= GetSubkeyNames( EnumKeyName
, "\\Linkage" );
114 PCHAR
*EnumKeysTop
= GetSubkeyNames( EnumKeyName
, "" );
115 PCHAR RootDevice
= NULL
;
116 HKEY EnumKey
, OutKey
= NULL
;
117 DWORD Error
= ERROR_SUCCESS
;
119 if( !EnumKeysLinkage
|| !EnumKeysTop
) goto cleanup
;
121 Error
= RegOpenKey( HKEY_LOCAL_MACHINE
, EnumKeyName
, &EnumKey
);
123 if( Error
) goto cleanup
;
125 for( i
= 0; EnumKeysLinkage
[i
]; i
++ ) {
126 RootDevice
= RegReadString
127 ( EnumKey
, EnumKeysLinkage
[i
], "RootDevice" );
130 !strcmp( RootDevice
, Adapter
->DhclientInfo
.name
) ) {
132 (CHAR
*) malloc( strlen( TargetKeyNameStart
) +
133 strlen( RootDevice
) + 1);
134 if( !TargetKeyName
) goto cleanup
;
135 sprintf( TargetKeyName
, "%s%s",
136 TargetKeyNameStart
, RootDevice
);
137 Error
= RegCreateKeyExA( HKEY_LOCAL_MACHINE
, TargetKeyName
, 0, NULL
, 0, KEY_READ
, NULL
, &OutKey
, NULL
);
140 free( RootDevice
); RootDevice
= 0;
145 if( RootDevice
) free( RootDevice
);
146 if( EnumKeysLinkage
) free( EnumKeysLinkage
);
147 if( EnumKeysTop
) free( EnumKeysTop
);
148 if( TargetKeyName
) free( TargetKeyName
);
153 BOOL
PrepareAdapterForService( PDHCP_ADAPTER Adapter
) {
155 DWORD Error
= ERROR_SUCCESS
, DhcpEnabled
, Length
= sizeof(DWORD
);
157 Adapter
->DhclientState
.config
= &Adapter
->DhclientConfig
;
158 strncpy(Adapter
->DhclientInfo
.name
, (char*)Adapter
->IfMib
.bDescr
,
159 sizeof(Adapter
->DhclientInfo
.name
));
161 AdapterKey
= FindAdapterKey( Adapter
);
164 Error
= RegQueryValueEx(AdapterKey
, "EnableDHCP", NULL
, NULL
, (LPBYTE
)&DhcpEnabled
, &Length
);
166 if (Error
!= ERROR_SUCCESS
|| Length
!= sizeof(DWORD
))
169 CloseHandle(AdapterKey
);
173 /* DHCP enabled by default */
178 /* Non-automatic case */
179 DbgPrint("DHCPCSVC: Adapter Name: [%s] (static)\n", Adapter
->DhclientInfo
.name
);
181 Adapter
->DhclientState
.state
= S_STATIC
;
184 DbgPrint("DHCPCSVC: Adapter Name: [%s] (dynamic)\n", Adapter
->DhclientInfo
.name
);
186 Adapter
->DhclientInfo
.client
->state
= S_INIT
;
193 WSAStartup(0x0101,&wsd
);
195 InitializeListHead( &AdapterList
);
199 InterfaceConnected(const MIB_IFROW
* IfEntry
)
201 if (IfEntry
->dwOperStatus
== IF_OPER_STATUS_CONNECTED
||
202 IfEntry
->dwOperStatus
== IF_OPER_STATUS_OPERATIONAL
)
205 DH_DbgPrint(MID_TRACE
,("Interface %d is down\n", IfEntry
->dwIndex
));
210 IsReconnectHackNeeded(PDHCP_ADAPTER Adapter
, const MIB_IFROW
* IfEntry
)
212 struct protocol
*proto
;
213 PIP_ADAPTER_INFO AdapterInfo
, Orig
;
215 char *ZeroAddress
= "0.0.0.0";
217 proto
= find_protocol_by_adapter(&Adapter
->DhclientInfo
);
219 if (Adapter
->DhclientInfo
.client
->state
== S_BOUND
&& !proto
)
222 if (Adapter
->DhclientInfo
.client
->state
!= S_BOUND
&&
223 Adapter
->DhclientInfo
.client
->state
!= S_STATIC
)
228 Orig
= AdapterInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(IP_ADAPTER_INFO
));
229 Size
= sizeof(IP_ADAPTER_INFO
);
236 Ret
= GetAdaptersInfo(AdapterInfo
, &Size
);
237 if (Ret
== ERROR_BUFFER_OVERFLOW
)
239 HeapFree(GetProcessHeap(), 0, AdapterInfo
);
240 AdapterInfo
= HeapAlloc(GetProcessHeap(), 0, Size
);
247 if (GetAdaptersInfo(AdapterInfo
, &Size
) != NO_ERROR
)
254 for (; AdapterInfo
!= NULL
; AdapterInfo
= AdapterInfo
->Next
)
256 if (AdapterInfo
->Index
== IfEntry
->dwIndex
)
260 if (AdapterInfo
== NULL
)
262 HeapFree(GetProcessHeap(), 0, Orig
);
267 else if (Ret
!= NO_ERROR
)
269 HeapFree(GetProcessHeap(), 0, Orig
);
274 if (!strcmp(AdapterInfo
->IpAddressList
.IpAddress
.String
, ZeroAddress
))
276 HeapFree(GetProcessHeap(), 0, Orig
);
282 HeapFree(GetProcessHeap(), 0, Orig
);
289 * XXX Figure out the way to bind a specific adapter to a socket.
291 DWORD WINAPI
AdapterDiscoveryThread(LPVOID Context
) {
292 PMIB_IFTABLE Table
= (PMIB_IFTABLE
) malloc(sizeof(MIB_IFTABLE
));
293 DWORD Error
, Size
= sizeof(MIB_IFTABLE
);
294 PDHCP_ADAPTER Adapter
= NULL
;
295 HANDLE hStopEvent
= (HANDLE
)Context
;
296 struct interface_info
*ifi
= NULL
;
297 struct protocol
*proto
;
298 int i
, AdapterCount
= 0, Broadcast
;
302 DH_DbgPrint(MID_TRACE
,("Getting Adapter List...\n"));
304 while( (Error
= GetIfTable(Table
, &Size
, 0 )) ==
305 ERROR_INSUFFICIENT_BUFFER
) {
306 DH_DbgPrint(MID_TRACE
,("Error %d, New Buffer Size: %d\n", Error
, Size
));
308 Table
= (PMIB_IFTABLE
) malloc( Size
);
311 if( Error
!= NO_ERROR
)
313 /* HACK: We are waiting until TCP/IP starts */
318 DH_DbgPrint(MID_TRACE
,("Got Adapter List (%d entries)\n", Table
->dwNumEntries
));
320 for( i
= Table
->dwNumEntries
- 1; i
>= 0; i
-- ) {
321 DH_DbgPrint(MID_TRACE
,("Getting adapter %d attributes\n",
322 Table
->table
[i
].dwIndex
));
326 if ((Adapter
= AdapterFindByHardwareAddress(Table
->table
[i
].bPhysAddr
, Table
->table
[i
].dwPhysAddrLen
)))
328 proto
= find_protocol_by_adapter(&Adapter
->DhclientInfo
);
330 /* This is an existing adapter */
331 if (InterfaceConnected(&Table
->table
[i
])) {
332 /* We're still active so we stay in the list */
333 ifi
= &Adapter
->DhclientInfo
;
335 /* This is a hack because IP helper API sucks */
336 if (IsReconnectHackNeeded(Adapter
, &Table
->table
[i
]))
338 /* This handles a disconnect/reconnect */
341 remove_protocol(proto
);
342 Adapter
->DhclientInfo
.client
->state
= S_INIT
;
344 /* These are already invalid since the media state change */
345 Adapter
->RouterMib
.dwForwardNextHop
= 0;
346 Adapter
->NteContext
= 0;
348 add_protocol(Adapter
->DhclientInfo
.name
,
349 Adapter
->DhclientInfo
.rfdesc
,
350 got_one
, &Adapter
->DhclientInfo
);
351 state_init(&Adapter
->DhclientInfo
);
353 SetEvent(hAdapterStateChangedEvent
);
358 remove_protocol(proto
);
360 /* We've lost our link so out we go */
361 RemoveEntryList(&Adapter
->ListEntry
);
372 Adapter
= (DHCP_ADAPTER
*) calloc( sizeof( DHCP_ADAPTER
) + Table
->table
[i
].dwMtu
, 1 );
374 if( Adapter
&& Table
->table
[i
].dwType
== MIB_IF_TYPE_ETHERNET
&& InterfaceConnected(&Table
->table
[i
])) {
375 memcpy( &Adapter
->IfMib
, &Table
->table
[i
],
376 sizeof(Adapter
->IfMib
) );
377 Adapter
->DhclientInfo
.client
= &Adapter
->DhclientState
;
378 Adapter
->DhclientInfo
.rbuf
= Adapter
->recv_buf
;
379 Adapter
->DhclientInfo
.rbuf_max
= Table
->table
[i
].dwMtu
;
380 Adapter
->DhclientInfo
.rbuf_len
=
381 Adapter
->DhclientInfo
.rbuf_offset
= 0;
382 memcpy(Adapter
->DhclientInfo
.hw_address
.haddr
,
383 Adapter
->IfMib
.bPhysAddr
,
384 Adapter
->IfMib
.dwPhysAddrLen
);
385 Adapter
->DhclientInfo
.hw_address
.hlen
= Adapter
->IfMib
.dwPhysAddrLen
;
387 /* I'm not sure where else to set this, but
388 some DHCP servers won't take a zero.
389 We checked the hardware type earlier in
391 Adapter
->DhclientInfo
.hw_address
.htype
= HTYPE_ETHER
;
393 if( DhcpSocket
== INVALID_SOCKET
) {
395 Adapter
->DhclientInfo
.rfdesc
=
396 Adapter
->DhclientInfo
.wfdesc
=
397 socket( AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
399 if (DhcpSocket
!= INVALID_SOCKET
) {
401 /* Allow broadcast on this socket */
403 setsockopt(DhcpSocket
,
406 (const char *)&Broadcast
,
409 Adapter
->ListenAddr
.sin_family
= AF_INET
;
410 Adapter
->ListenAddr
.sin_port
= htons(LOCAL_PORT
);
411 Adapter
->BindStatus
=
412 (bind( Adapter
->DhclientInfo
.rfdesc
,
413 (struct sockaddr
*)&Adapter
->ListenAddr
,
414 sizeof(Adapter
->ListenAddr
) ) == 0) ?
415 0 : WSAGetLastError();
417 error("socket() failed: %d\n", WSAGetLastError());
420 Adapter
->DhclientInfo
.rfdesc
=
421 Adapter
->DhclientInfo
.wfdesc
= DhcpSocket
;
424 Adapter
->DhclientConfig
.timeout
= DHCP_PANIC_TIMEOUT
;
425 Adapter
->DhclientConfig
.initial_interval
= DHCP_DISCOVER_INTERVAL
;
426 Adapter
->DhclientConfig
.retry_interval
= DHCP_DISCOVER_INTERVAL
;
427 Adapter
->DhclientConfig
.select_interval
= 1;
428 Adapter
->DhclientConfig
.reboot_timeout
= DHCP_REBOOT_TIMEOUT
;
429 Adapter
->DhclientConfig
.backoff_cutoff
= DHCP_BACKOFF_MAX
;
430 Adapter
->DhclientState
.interval
=
431 Adapter
->DhclientConfig
.retry_interval
;
433 if( PrepareAdapterForService( Adapter
) ) {
434 Adapter
->DhclientInfo
.next
= ifi
;
435 ifi
= &Adapter
->DhclientInfo
;
437 read_client_conf(&Adapter
->DhclientInfo
);
439 if (Adapter
->DhclientInfo
.client
->state
== S_INIT
)
441 add_protocol(Adapter
->DhclientInfo
.name
,
442 Adapter
->DhclientInfo
.rfdesc
,
443 got_one
, &Adapter
->DhclientInfo
);
445 state_init(&Adapter
->DhclientInfo
);
449 InsertTailList( &AdapterList
, &Adapter
->ListEntry
);
451 SetEvent(hAdapterStateChangedEvent
);
453 } else { free( Adapter
); Adapter
= 0; }
454 } else { free( Adapter
); Adapter
= 0; }
457 DH_DbgPrint(MID_TRACE
,("Adapter %d was rejected\n",
458 Table
->table
[i
].dwIndex
));
461 Error
= NotifyAddrChange(NULL
, NULL
);
462 if (Error
!= NO_ERROR
)
465 if (WaitForSingleObject(hStopEvent
, 3000) == WAIT_OBJECT_0
)
467 DPRINT("Stopping the discovery thread!\n");
476 DPRINT("Adapter discovery thread terminated! (Error: %d)\n", Error
);
481 HANDLE
StartAdapterDiscovery(HANDLE hStopEvent
) {
482 return CreateThread(NULL
, 0, AdapterDiscoveryThread
, (LPVOID
)hStopEvent
, 0, NULL
);
486 PLIST_ENTRY ListEntry
;
487 PDHCP_ADAPTER Adapter
;
489 while( !IsListEmpty( &AdapterList
) ) {
490 ListEntry
= (PLIST_ENTRY
)RemoveHeadList( &AdapterList
);
491 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
498 PDHCP_ADAPTER
AdapterFindIndex( unsigned int indx
) {
499 PDHCP_ADAPTER Adapter
;
500 PLIST_ENTRY ListEntry
;
502 for( ListEntry
= AdapterList
.Flink
;
503 ListEntry
!= &AdapterList
;
504 ListEntry
= ListEntry
->Flink
) {
505 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
506 if( Adapter
->IfMib
.dwIndex
== indx
) return Adapter
;
512 PDHCP_ADAPTER
AdapterFindName( const WCHAR
*name
) {
513 PDHCP_ADAPTER Adapter
;
514 PLIST_ENTRY ListEntry
;
516 for( ListEntry
= AdapterList
.Flink
;
517 ListEntry
!= &AdapterList
;
518 ListEntry
= ListEntry
->Flink
) {
519 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
520 if( !wcsicmp( Adapter
->IfMib
.wszName
, name
) ) return Adapter
;
526 PDHCP_ADAPTER
AdapterFindInfo( struct interface_info
*ip
) {
527 PDHCP_ADAPTER Adapter
;
528 PLIST_ENTRY ListEntry
;
530 for( ListEntry
= AdapterList
.Flink
;
531 ListEntry
!= &AdapterList
;
532 ListEntry
= ListEntry
->Flink
) {
533 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
534 if( ip
== &Adapter
->DhclientInfo
) return Adapter
;
540 PDHCP_ADAPTER
AdapterFindByHardwareAddress( u_int8_t haddr
[16], u_int8_t hlen
) {
541 PDHCP_ADAPTER Adapter
;
542 PLIST_ENTRY ListEntry
;
544 for(ListEntry
= AdapterList
.Flink
;
545 ListEntry
!= &AdapterList
;
546 ListEntry
= ListEntry
->Flink
) {
547 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
548 if (Adapter
->DhclientInfo
.hw_address
.hlen
== hlen
&&
549 !memcmp(Adapter
->DhclientInfo
.hw_address
.haddr
,
551 hlen
)) return Adapter
;
557 PDHCP_ADAPTER
AdapterGetFirst() {
558 if( IsListEmpty( &AdapterList
) ) return NULL
; else {
559 return CONTAINING_RECORD
560 ( AdapterList
.Flink
, DHCP_ADAPTER
, ListEntry
);
564 PDHCP_ADAPTER
AdapterGetNext( PDHCP_ADAPTER This
)
566 if( This
->ListEntry
.Flink
== &AdapterList
) return NULL
;
567 return CONTAINING_RECORD
568 ( This
->ListEntry
.Flink
, DHCP_ADAPTER
, ListEntry
);
571 void if_register_send(struct interface_info
*ip
) {
575 void if_register_receive(struct interface_info
*ip
) {