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 Unused
) {
231 PMIB_IFTABLE Table
= (PMIB_IFTABLE
) malloc(sizeof(MIB_IFTABLE
));
232 DWORD Error
, Size
= sizeof(MIB_IFTABLE
);
233 PDHCP_ADAPTER Adapter
= NULL
;
234 struct interface_info
*ifi
= NULL
;
237 /* FIXME: Kill this thread when the service is stopped */
240 DH_DbgPrint(MID_TRACE
,("Getting Adapter List...\n"));
242 while( (Error
= GetIfTable(Table
, &Size
, 0 )) ==
243 ERROR_INSUFFICIENT_BUFFER
) {
244 DH_DbgPrint(MID_TRACE
,("Error %d, New Buffer Size: %d\n", Error
, Size
));
246 Table
= (PMIB_IFTABLE
) malloc( Size
);
249 if( Error
!= NO_ERROR
)
252 DH_DbgPrint(MID_TRACE
,("Got Adapter List (%d entries)\n", Table
->dwNumEntries
));
254 for( i
= Table
->dwNumEntries
- 1; i
>= 0; i
-- ) {
255 DH_DbgPrint(MID_TRACE
,("Getting adapter %d attributes\n",
256 Table
->table
[i
].dwIndex
));
260 if ((Adapter
= AdapterFindByHardwareAddress(Table
->table
[i
].bPhysAddr
, Table
->table
[i
].dwPhysAddrLen
)))
262 /* This is an existing adapter */
263 if (InterfaceConnected(Table
->table
[i
])) {
264 /* We're still active so we stay in the list */
265 ifi
= &Adapter
->DhclientInfo
;
267 /* We've lost our link so out we go */
268 RemoveEntryList(&Adapter
->ListEntry
);
279 Adapter
= (DHCP_ADAPTER
*) calloc( sizeof( DHCP_ADAPTER
) + Table
->table
[i
].dwMtu
, 1 );
281 if( Adapter
&& Table
->table
[i
].dwType
== MIB_IF_TYPE_ETHERNET
&& InterfaceConnected(Table
->table
[i
])) {
282 memcpy( &Adapter
->IfMib
, &Table
->table
[i
],
283 sizeof(Adapter
->IfMib
) );
284 Adapter
->DhclientInfo
.client
= &Adapter
->DhclientState
;
285 Adapter
->DhclientInfo
.rbuf
= Adapter
->recv_buf
;
286 Adapter
->DhclientInfo
.rbuf_max
= Table
->table
[i
].dwMtu
;
287 Adapter
->DhclientInfo
.rbuf_len
=
288 Adapter
->DhclientInfo
.rbuf_offset
= 0;
289 memcpy(Adapter
->DhclientInfo
.hw_address
.haddr
,
290 Adapter
->IfMib
.bPhysAddr
,
291 Adapter
->IfMib
.dwPhysAddrLen
);
292 Adapter
->DhclientInfo
.hw_address
.hlen
= Adapter
->IfMib
.dwPhysAddrLen
;
294 /* I'm not sure where else to set this, but
295 some DHCP servers won't take a zero.
296 We checked the hardware type earlier in
298 Adapter
->DhclientInfo
.hw_address
.htype
= HTYPE_ETHER
;
300 if( DhcpSocket
== INVALID_SOCKET
) {
302 Adapter
->DhclientInfo
.rfdesc
=
303 Adapter
->DhclientInfo
.wfdesc
=
304 socket( AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
306 if (DhcpSocket
!= INVALID_SOCKET
) {
307 Adapter
->ListenAddr
.sin_family
= AF_INET
;
308 Adapter
->ListenAddr
.sin_port
= htons(LOCAL_PORT
);
309 Adapter
->BindStatus
=
310 (bind( Adapter
->DhclientInfo
.rfdesc
,
311 (struct sockaddr
*)&Adapter
->ListenAddr
,
312 sizeof(Adapter
->ListenAddr
) ) == 0) ?
313 0 : WSAGetLastError();
315 error("socket() failed: %d\n", WSAGetLastError());
318 Adapter
->DhclientInfo
.rfdesc
=
319 Adapter
->DhclientInfo
.wfdesc
= DhcpSocket
;
322 Adapter
->DhclientConfig
.timeout
= DHCP_PANIC_TIMEOUT
;
323 Adapter
->DhclientConfig
.initial_interval
= DHCP_DISCOVER_INTERVAL
;
324 Adapter
->DhclientConfig
.retry_interval
= DHCP_DISCOVER_INTERVAL
;
325 Adapter
->DhclientConfig
.select_interval
= 1;
326 Adapter
->DhclientConfig
.reboot_timeout
= DHCP_REBOOT_TIMEOUT
;
327 Adapter
->DhclientConfig
.backoff_cutoff
= DHCP_BACKOFF_MAX
;
328 Adapter
->DhclientState
.interval
=
329 Adapter
->DhclientConfig
.retry_interval
;
331 if( PrepareAdapterForService( Adapter
) ) {
332 Adapter
->DhclientInfo
.next
= ifi
;
333 ifi
= &Adapter
->DhclientInfo
;
335 read_client_conf(&Adapter
->DhclientInfo
);
337 if (Adapter
->DhclientInfo
.client
->state
== S_INIT
)
339 add_protocol(Adapter
->DhclientInfo
.name
,
340 Adapter
->DhclientInfo
.rfdesc
,
341 got_one
, &Adapter
->DhclientInfo
);
343 state_init(&Adapter
->DhclientInfo
);
347 InsertTailList( &AdapterList
, &Adapter
->ListEntry
);
349 } else { free( Adapter
); Adapter
= 0; }
350 } else { free( Adapter
); Adapter
= 0; }
353 DH_DbgPrint(MID_TRACE
,("Adapter %d was rejected\n",
354 Table
->table
[i
].dwIndex
));
356 } while ((Error
= NotifyAddrChange(NULL
, NULL
)) == NO_ERROR
);
358 DbgPrint("DHCPCSVC: Adapter discovery thread is terminating! (Error: %d)\n", Error
);
360 if( Table
) free( Table
);
364 BOOLEAN
StartAdapterDiscovery(VOID
) {
367 ThreadHandle
= CreateThread(NULL
,
369 AdapterDiscoveryThread
,
374 if (ThreadHandle
== NULL
)
377 CloseHandle(ThreadHandle
);
383 PLIST_ENTRY ListEntry
;
384 PDHCP_ADAPTER Adapter
;
386 while( !IsListEmpty( &AdapterList
) ) {
387 ListEntry
= (PLIST_ENTRY
)RemoveHeadList( &AdapterList
);
388 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
395 PDHCP_ADAPTER
AdapterFindIndex( unsigned int indx
) {
396 PDHCP_ADAPTER Adapter
;
397 PLIST_ENTRY ListEntry
;
399 for( ListEntry
= AdapterList
.Flink
;
400 ListEntry
!= &AdapterList
;
401 ListEntry
= ListEntry
->Flink
) {
402 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
403 if( Adapter
->IfMib
.dwIndex
== indx
) return Adapter
;
409 PDHCP_ADAPTER
AdapterFindName( const WCHAR
*name
) {
410 PDHCP_ADAPTER Adapter
;
411 PLIST_ENTRY ListEntry
;
413 for( ListEntry
= AdapterList
.Flink
;
414 ListEntry
!= &AdapterList
;
415 ListEntry
= ListEntry
->Flink
) {
416 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
417 if( !wcsicmp( Adapter
->IfMib
.wszName
, name
) ) return Adapter
;
423 PDHCP_ADAPTER
AdapterFindInfo( struct interface_info
*ip
) {
424 PDHCP_ADAPTER Adapter
;
425 PLIST_ENTRY ListEntry
;
427 for( ListEntry
= AdapterList
.Flink
;
428 ListEntry
!= &AdapterList
;
429 ListEntry
= ListEntry
->Flink
) {
430 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
431 if( ip
== &Adapter
->DhclientInfo
) return Adapter
;
437 PDHCP_ADAPTER
AdapterFindByHardwareAddress( u_int8_t haddr
[16], u_int8_t hlen
) {
438 PDHCP_ADAPTER Adapter
;
439 PLIST_ENTRY ListEntry
;
441 for(ListEntry
= AdapterList
.Flink
;
442 ListEntry
!= &AdapterList
;
443 ListEntry
= ListEntry
->Flink
) {
444 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
445 if (Adapter
->DhclientInfo
.hw_address
.hlen
== hlen
&&
446 !memcmp(Adapter
->DhclientInfo
.hw_address
.haddr
,
448 hlen
)) return Adapter
;
454 PDHCP_ADAPTER
AdapterGetFirst() {
455 if( IsListEmpty( &AdapterList
) ) return NULL
; else {
456 return CONTAINING_RECORD
457 ( AdapterList
.Flink
, DHCP_ADAPTER
, ListEntry
);
461 PDHCP_ADAPTER
AdapterGetNext( PDHCP_ADAPTER This
)
463 if( This
->ListEntry
.Flink
== &AdapterList
) return NULL
;
464 return CONTAINING_RECORD
465 ( This
->ListEntry
.Flink
, DHCP_ADAPTER
, ListEntry
);
468 void if_register_send(struct interface_info
*ip
) {
472 void if_register_receive(struct interface_info
*ip
) {