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
.dwForwardNextHop
= inet_addr(DefaultGateway
);
186 Error
= CreateIpForwardEntry( &Adapter
->RouterMib
);
188 warning("Failed to set default gateway %s: %ld\n",
189 DefaultGateway
, Error
);
192 if( DefaultGateway
) free( DefaultGateway
);
193 if( Netmask
) free( Netmask
);
197 (MID_TRACE
,("Adapter Name: [%s] (Bind Status %x) (dynamic)\n",
198 Adapter
->DhclientInfo
.name
,
199 Adapter
->BindStatus
));
201 add_protocol(Adapter
->DhclientInfo
.name
, Adapter
->DhclientInfo
.rfdesc
, got_one
, &Adapter
->DhclientInfo
);
202 Adapter
->DhclientInfo
.client
->state
= S_INIT
;
203 state_reboot(&Adapter
->DhclientInfo
);
206 if( IPAddress
) free( IPAddress
);
212 WSAStartup(0x0101,&wsd
);
214 InitializeListHead( &AdapterList
);
218 InterfaceConnected(MIB_IFROW IfEntry
)
220 if (IfEntry
.dwOperStatus
== IF_OPER_STATUS_CONNECTED
||
221 IfEntry
.dwOperStatus
== IF_OPER_STATUS_OPERATIONAL
)
224 DH_DbgPrint(MID_TRACE
,("Interface %d is down\n", IfEntry
.dwIndex
));
229 * XXX Figure out the way to bind a specific adapter to a socket.
231 BOOLEAN
AdapterDiscover() {
232 PMIB_IFTABLE Table
= (PMIB_IFTABLE
) malloc(sizeof(MIB_IFTABLE
));
233 DWORD Error
, Size
= sizeof(MIB_IFTABLE
);
234 PDHCP_ADAPTER Adapter
= NULL
;
235 struct interface_info
*ifi
= NULL
;
239 DH_DbgPrint(MID_TRACE
,("Getting Adapter List...\n"));
241 while( (Error
= GetIfTable(Table
, &Size
, 0 )) ==
242 ERROR_INSUFFICIENT_BUFFER
) {
243 DH_DbgPrint(MID_TRACE
,("Error %d, New Buffer Size: %d\n", Error
, Size
));
245 Table
= (PMIB_IFTABLE
) malloc( Size
);
248 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
));
259 if ((Adapter
= AdapterFindByHardwareAddress(Table
->table
[i
].bPhysAddr
, Table
->table
[i
].dwPhysAddrLen
)))
261 /* This is an existing adapter */
262 if (InterfaceConnected(Table
->table
[i
])) {
263 /* We're still active so we stay in the list */
264 ifi
= &Adapter
->DhclientInfo
;
266 /* We've lost our link so out we go */
267 RemoveEntryList(&Adapter
->ListEntry
);
274 Adapter
= (DHCP_ADAPTER
*) calloc( sizeof( DHCP_ADAPTER
) + Table
->table
[i
].dwMtu
, 1 );
276 if( Adapter
&& Table
->table
[i
].dwType
== MIB_IF_TYPE_ETHERNET
&& InterfaceConnected(Table
->table
[i
])) {
277 memcpy( &Adapter
->IfMib
, &Table
->table
[i
],
278 sizeof(Adapter
->IfMib
) );
279 Adapter
->DhclientInfo
.client
= &Adapter
->DhclientState
;
280 Adapter
->DhclientInfo
.rbuf
= Adapter
->recv_buf
;
281 Adapter
->DhclientInfo
.rbuf_max
= Table
->table
[i
].dwMtu
;
282 Adapter
->DhclientInfo
.rbuf_len
=
283 Adapter
->DhclientInfo
.rbuf_offset
= 0;
284 memcpy(Adapter
->DhclientInfo
.hw_address
.haddr
,
285 Adapter
->IfMib
.bPhysAddr
,
286 Adapter
->IfMib
.dwPhysAddrLen
);
287 Adapter
->DhclientInfo
.hw_address
.hlen
=
288 Adapter
->IfMib
.dwPhysAddrLen
;
289 /* I'm not sure where else to set this, but
290 some DHCP servers won't take a zero.
291 We checked the hardware type earlier in
293 Adapter
->DhclientInfo
.hw_address
.htype
=
296 if( DhcpSocket
== INVALID_SOCKET
) {
298 Adapter
->DhclientInfo
.rfdesc
=
299 Adapter
->DhclientInfo
.wfdesc
=
300 socket( AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
302 if (DhcpSocket
!= INVALID_SOCKET
) {
303 Adapter
->ListenAddr
.sin_family
= AF_INET
;
304 Adapter
->ListenAddr
.sin_port
= htons(LOCAL_PORT
);
305 Adapter
->BindStatus
=
306 (bind( Adapter
->DhclientInfo
.rfdesc
,
307 (struct sockaddr
*)&Adapter
->ListenAddr
,
308 sizeof(Adapter
->ListenAddr
) ) == 0) ?
309 0 : WSAGetLastError();
311 error("socket() failed: %d\n", WSAGetLastError());
314 Adapter
->DhclientInfo
.rfdesc
=
315 Adapter
->DhclientInfo
.wfdesc
= DhcpSocket
;
318 Adapter
->DhclientConfig
.timeout
= DHCP_PANIC_TIMEOUT
;
319 Adapter
->DhclientConfig
.initial_interval
= DHCP_DISCOVER_INTERVAL
;
320 Adapter
->DhclientConfig
.retry_interval
= DHCP_DISCOVER_INTERVAL
;
321 Adapter
->DhclientConfig
.select_interval
= 1;
322 Adapter
->DhclientConfig
.reboot_timeout
= DHCP_REBOOT_TIMEOUT
;
323 Adapter
->DhclientConfig
.backoff_cutoff
= DHCP_BACKOFF_MAX
;
324 Adapter
->DhclientState
.interval
=
325 Adapter
->DhclientConfig
.retry_interval
;
327 if( PrepareAdapterForService( Adapter
) ) {
328 Adapter
->DhclientInfo
.next
= ifi
;
329 ifi
= &Adapter
->DhclientInfo
;
331 read_client_conf(&Adapter
->DhclientInfo
);
333 InsertTailList( &AdapterList
, &Adapter
->ListEntry
);
334 } else { free( Adapter
); Adapter
= 0; }
335 } else { free( Adapter
); Adapter
= 0; }
338 DH_DbgPrint(MID_TRACE
,("Adapter %d was rejected\n",
339 Table
->table
[i
].dwIndex
));
342 DH_DbgPrint(MID_TRACE
,("done with AdapterInit\n"));
345 if( Table
) free( Table
);
350 PLIST_ENTRY ListEntry
;
351 PDHCP_ADAPTER Adapter
;
352 while( !IsListEmpty( &AdapterList
) ) {
353 ListEntry
= (PLIST_ENTRY
)RemoveHeadList( &AdapterList
);
354 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
360 PDHCP_ADAPTER
AdapterFindIndex( unsigned int indx
) {
361 PDHCP_ADAPTER Adapter
;
362 PLIST_ENTRY ListEntry
;
364 for( ListEntry
= AdapterList
.Flink
;
365 ListEntry
!= &AdapterList
;
366 ListEntry
= ListEntry
->Flink
) {
367 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
368 if( Adapter
->IfMib
.dwIndex
== indx
) return Adapter
;
374 PDHCP_ADAPTER
AdapterFindName( const WCHAR
*name
) {
375 PDHCP_ADAPTER Adapter
;
376 PLIST_ENTRY ListEntry
;
378 for( ListEntry
= AdapterList
.Flink
;
379 ListEntry
!= &AdapterList
;
380 ListEntry
= ListEntry
->Flink
) {
381 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
382 if( !wcsicmp( Adapter
->IfMib
.wszName
, name
) ) return Adapter
;
388 PDHCP_ADAPTER
AdapterFindInfo( struct interface_info
*ip
) {
389 PDHCP_ADAPTER Adapter
;
390 PLIST_ENTRY ListEntry
;
392 for( ListEntry
= AdapterList
.Flink
;
393 ListEntry
!= &AdapterList
;
394 ListEntry
= ListEntry
->Flink
) {
395 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
396 if( ip
== &Adapter
->DhclientInfo
) return Adapter
;
402 PDHCP_ADAPTER
AdapterFindByHardwareAddress( u_int8_t haddr
[16], u_int8_t hlen
) {
403 PDHCP_ADAPTER Adapter
;
404 PLIST_ENTRY ListEntry
;
406 for(ListEntry
= AdapterList
.Flink
;
407 ListEntry
!= &AdapterList
;
408 ListEntry
= ListEntry
->Flink
) {
409 Adapter
= CONTAINING_RECORD( ListEntry
, DHCP_ADAPTER
, ListEntry
);
410 if (Adapter
->DhclientInfo
.hw_address
.hlen
== hlen
&&
411 !memcmp(Adapter
->DhclientInfo
.hw_address
.haddr
,
413 hlen
)) return Adapter
;
419 PDHCP_ADAPTER
AdapterGetFirst() {
420 if( IsListEmpty( &AdapterList
) ) return NULL
; else {
421 return CONTAINING_RECORD
422 ( AdapterList
.Flink
, DHCP_ADAPTER
, ListEntry
);
426 PDHCP_ADAPTER
AdapterGetNext( PDHCP_ADAPTER This
)
428 if( This
->ListEntry
.Flink
== &AdapterList
) return NULL
;
429 return CONTAINING_RECORD
430 ( This
->ListEntry
.Flink
, DHCP_ADAPTER
, ListEntry
);
433 void if_register_send(struct interface_info
*ip
) {
437 void if_register_receive(struct interface_info
*ip
) {