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
) {
148 HKEY AdapterKey
= NULL
;
149 PCHAR IPAddress
= NULL
, Netmask
= NULL
, DefaultGateway
= NULL
;
150 NTSTATUS Status
= STATUS_SUCCESS
;
151 DWORD Error
= ERROR_SUCCESS
;
153 Adapter
->DhclientState
.config
= &Adapter
->DhclientConfig
;
154 strncpy(Adapter
->DhclientInfo
.name
, (char*)Adapter
->IfMib
.bDescr
,
155 sizeof(Adapter
->DhclientInfo
.name
));
157 AdapterKey
= FindAdapterKey( Adapter
);
159 IPAddress
= RegReadString( AdapterKey
, NULL
, "IPAddress" );
161 if( IPAddress
&& strcmp( IPAddress
, "0.0.0.0" ) ) {
162 /* Non-automatic case */
164 (MID_TRACE
,("Adapter Name: [%s] (Bind Status %x) (static %s)\n",
165 Adapter
->DhclientInfo
.name
,
169 Adapter
->DhclientState
.state
= S_STATIC
;
171 Netmask
= RegReadString( AdapterKey
, NULL
, "Subnetmask" );
173 Status
= AddIPAddress( inet_addr( IPAddress
),
174 inet_addr( Netmask
? Netmask
: "255.255.255.0" ),
175 Adapter
->IfMib
.dwIndex
,
176 &Adapter
->NteContext
,
177 &Adapter
->NteInstance
);
179 DefaultGateway
= RegReadString( AdapterKey
, NULL
, "DefaultGateway" );
181 if( DefaultGateway
) {
182 Adapter
->RouterMib
.dwForwardDest
= 0;
183 Adapter
->RouterMib
.dwForwardMask
= 0;
184 Adapter
->RouterMib
.dwForwardMetric1
= 1;
185 Adapter
->RouterMib
.dwForwardIfIndex
= Adapter
->IfMib
.dwIndex
;
186 Adapter
->RouterMib
.dwForwardNextHop
= inet_addr(DefaultGateway
);
187 Error
= CreateIpForwardEntry( &Adapter
->RouterMib
);
189 warning("Failed to set default gateway %s: %ld\n",
190 DefaultGateway
, Error
);
193 if( DefaultGateway
) free( DefaultGateway
);
194 if( Netmask
) free( Netmask
);
198 (MID_TRACE
,("Adapter Name: [%s] (Bind Status %x) (dynamic)\n",
199 Adapter
->DhclientInfo
.name
,
200 Adapter
->BindStatus
));
202 Adapter
->DhclientInfo
.client
->state
= S_INIT
;
205 if( IPAddress
) free( IPAddress
);
211 WSAStartup(0x0101,&wsd
);
213 InitializeListHead( &AdapterList
);
217 InterfaceConnected(MIB_IFROW IfEntry
)
219 if (IfEntry
.dwOperStatus
== IF_OPER_STATUS_CONNECTED
||
220 IfEntry
.dwOperStatus
== IF_OPER_STATUS_OPERATIONAL
)
223 DH_DbgPrint(MID_TRACE
,("Interface %d is down\n", IfEntry
.dwIndex
));
228 * XXX Figure out the way to bind a specific adapter to a socket.
230 DWORD WINAPI
AdapterDiscoveryThread(LPVOID Context
) {
231 PMIB_IFTABLE Table
= (PMIB_IFTABLE
) malloc(sizeof(MIB_IFTABLE
));
232 DWORD Error
, Size
= sizeof(MIB_IFTABLE
);
233 PDHCP_ADAPTER Adapter
= NULL
;
234 HANDLE AdapterStateChangedEvent
= (HANDLE
)Context
;
235 struct interface_info
*ifi
= NULL
;
238 /* FIXME: Kill this thread when the service is stopped */
241 DH_DbgPrint(MID_TRACE
,("Getting Adapter List...\n"));
243 while( (Error
= GetIfTable(Table
, &Size
, 0 )) ==
244 ERROR_INSUFFICIENT_BUFFER
) {
245 DH_DbgPrint(MID_TRACE
,("Error %d, New Buffer Size: %d\n", Error
, Size
));
247 Table
= (PMIB_IFTABLE
) malloc( Size
);
250 if( Error
!= NO_ERROR
)
253 DH_DbgPrint(MID_TRACE
,("Got Adapter List (%d entries)\n", Table
->dwNumEntries
));
255 for( i
= Table
->dwNumEntries
- 1; i
>= 0; i
-- ) {
256 DH_DbgPrint(MID_TRACE
,("Getting adapter %d attributes\n",
257 Table
->table
[i
].dwIndex
));
261 if ((Adapter
= AdapterFindByHardwareAddress(Table
->table
[i
].bPhysAddr
, Table
->table
[i
].dwPhysAddrLen
)))
263 /* This is an existing adapter */
264 if (InterfaceConnected(Table
->table
[i
])) {
265 /* We're still active so we stay in the list */
266 ifi
= &Adapter
->DhclientInfo
;
268 /* We've lost our link so out we go */
269 RemoveEntryList(&Adapter
->ListEntry
);
280 Adapter
= (DHCP_ADAPTER
*) calloc( sizeof( DHCP_ADAPTER
) + Table
->table
[i
].dwMtu
, 1 );
282 if( Adapter
&& Table
->table
[i
].dwType
== MIB_IF_TYPE_ETHERNET
&& InterfaceConnected(Table
->table
[i
])) {
283 memcpy( &Adapter
->IfMib
, &Table
->table
[i
],
284 sizeof(Adapter
->IfMib
) );
285 Adapter
->DhclientInfo
.client
= &Adapter
->DhclientState
;
286 Adapter
->DhclientInfo
.rbuf
= Adapter
->recv_buf
;
287 Adapter
->DhclientInfo
.rbuf_max
= Table
->table
[i
].dwMtu
;
288 Adapter
->DhclientInfo
.rbuf_len
=
289 Adapter
->DhclientInfo
.rbuf_offset
= 0;
290 memcpy(Adapter
->DhclientInfo
.hw_address
.haddr
,
291 Adapter
->IfMib
.bPhysAddr
,
292 Adapter
->IfMib
.dwPhysAddrLen
);
293 Adapter
->DhclientInfo
.hw_address
.hlen
= Adapter
->IfMib
.dwPhysAddrLen
;
295 /* I'm not sure where else to set this, but
296 some DHCP servers won't take a zero.
297 We checked the hardware type earlier in
299 Adapter
->DhclientInfo
.hw_address
.htype
= HTYPE_ETHER
;
301 if( DhcpSocket
== INVALID_SOCKET
) {
303 Adapter
->DhclientInfo
.rfdesc
=
304 Adapter
->DhclientInfo
.wfdesc
=
305 socket( AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
307 if (DhcpSocket
!= INVALID_SOCKET
) {
308 Adapter
->ListenAddr
.sin_family
= AF_INET
;
309 Adapter
->ListenAddr
.sin_port
= htons(LOCAL_PORT
);
310 Adapter
->BindStatus
=
311 (bind( Adapter
->DhclientInfo
.rfdesc
,
312 (struct sockaddr
*)&Adapter
->ListenAddr
,
313 sizeof(Adapter
->ListenAddr
) ) == 0) ?
314 0 : WSAGetLastError();
316 error("socket() failed: %d\n", WSAGetLastError());
319 Adapter
->DhclientInfo
.rfdesc
=
320 Adapter
->DhclientInfo
.wfdesc
= DhcpSocket
;
323 Adapter
->DhclientConfig
.timeout
= DHCP_PANIC_TIMEOUT
;
324 Adapter
->DhclientConfig
.initial_interval
= DHCP_DISCOVER_INTERVAL
;
325 Adapter
->DhclientConfig
.retry_interval
= DHCP_DISCOVER_INTERVAL
;
326 Adapter
->DhclientConfig
.select_interval
= 1;
327 Adapter
->DhclientConfig
.reboot_timeout
= DHCP_REBOOT_TIMEOUT
;
328 Adapter
->DhclientConfig
.backoff_cutoff
= DHCP_BACKOFF_MAX
;
329 Adapter
->DhclientState
.interval
=
330 Adapter
->DhclientConfig
.retry_interval
;
332 if( PrepareAdapterForService( Adapter
) ) {
333 Adapter
->DhclientInfo
.next
= ifi
;
334 ifi
= &Adapter
->DhclientInfo
;
336 read_client_conf(&Adapter
->DhclientInfo
);
338 if (Adapter
->DhclientInfo
.client
->state
== S_INIT
)
340 add_protocol(Adapter
->DhclientInfo
.name
,
341 Adapter
->DhclientInfo
.rfdesc
,
342 got_one
, &Adapter
->DhclientInfo
);
344 state_init(&Adapter
->DhclientInfo
);
348 InsertTailList( &AdapterList
, &Adapter
->ListEntry
);
349 DbgPrint("DHCPCSVC: Discovered new adapter [%s]\n", Adapter
->DhclientInfo
.name
);
350 SetEvent(AdapterStateChangedEvent
);
352 } else { free( Adapter
); Adapter
= 0; }
353 } else { free( Adapter
); Adapter
= 0; }
356 DH_DbgPrint(MID_TRACE
,("Adapter %d was rejected\n",
357 Table
->table
[i
].dwIndex
));
359 } while ((Error
= NotifyAddrChange(NULL
, NULL
)) == NO_ERROR
);
361 DbgPrint("DHCPCSVC: Adapter discovery thread is terminating! (Error: %d)\n", Error
);
363 if( Table
) free( Table
);
367 HANDLE
StartAdapterDiscovery(VOID
) {
368 HANDLE ThreadHandle
, EventHandle
;
370 EventHandle
= CreateEvent(NULL
,
375 ThreadHandle
= CreateThread(NULL
,
377 AdapterDiscoveryThread
,
382 if (ThreadHandle
== NULL
)
385 CloseHandle(ThreadHandle
);
391 PLIST_ENTRY ListEntry
;
392 PDHCP_ADAPTER Adapter
;
394 while( !IsListEmpty( &AdapterList
) ) {
395 ListEntry
= (PLIST_ENTRY
)RemoveHeadList( &AdapterList
);
396 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
403 PDHCP_ADAPTER
AdapterFindIndex( unsigned int indx
) {
404 PDHCP_ADAPTER Adapter
;
405 PLIST_ENTRY ListEntry
;
407 for( ListEntry
= AdapterList
.Flink
;
408 ListEntry
!= &AdapterList
;
409 ListEntry
= ListEntry
->Flink
) {
410 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
411 if( Adapter
->IfMib
.dwIndex
== indx
) return Adapter
;
417 PDHCP_ADAPTER
AdapterFindName( const WCHAR
*name
) {
418 PDHCP_ADAPTER Adapter
;
419 PLIST_ENTRY ListEntry
;
421 for( ListEntry
= AdapterList
.Flink
;
422 ListEntry
!= &AdapterList
;
423 ListEntry
= ListEntry
->Flink
) {
424 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
425 if( !wcsicmp( Adapter
->IfMib
.wszName
, name
) ) return Adapter
;
431 PDHCP_ADAPTER
AdapterFindInfo( struct interface_info
*ip
) {
432 PDHCP_ADAPTER Adapter
;
433 PLIST_ENTRY ListEntry
;
435 for( ListEntry
= AdapterList
.Flink
;
436 ListEntry
!= &AdapterList
;
437 ListEntry
= ListEntry
->Flink
) {
438 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
439 if( ip
== &Adapter
->DhclientInfo
) return Adapter
;
445 PDHCP_ADAPTER
AdapterFindByHardwareAddress( u_int8_t haddr
[16], u_int8_t hlen
) {
446 PDHCP_ADAPTER Adapter
;
447 PLIST_ENTRY ListEntry
;
449 for(ListEntry
= AdapterList
.Flink
;
450 ListEntry
!= &AdapterList
;
451 ListEntry
= ListEntry
->Flink
) {
452 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
453 if (Adapter
->DhclientInfo
.hw_address
.hlen
== hlen
&&
454 !memcmp(Adapter
->DhclientInfo
.hw_address
.haddr
,
456 hlen
)) return Adapter
;
462 PDHCP_ADAPTER
AdapterGetFirst() {
463 if( IsListEmpty( &AdapterList
) ) return NULL
; else {
464 return CONTAINING_RECORD
465 ( AdapterList
.Flink
, DHCP_ADAPTER
, ListEntry
);
469 PDHCP_ADAPTER
AdapterGetNext( PDHCP_ADAPTER This
)
471 if( This
->ListEntry
.Flink
== &AdapterList
) return NULL
;
472 return CONTAINING_RECORD
473 ( This
->ListEntry
.Flink
, DHCP_ADAPTER
, ListEntry
);
476 void if_register_send(struct interface_info
*ip
) {
480 void if_register_receive(struct interface_info
*ip
) {