Skip to content

Commit 0f4e223

Browse files
committed
[DHCPCSVC] Implement the dhcp release message and fix the dhcp registry values
- Do not modify the EnableDHCP value as it should not be changed by the service.
1 parent 51ee32f commit 0f4e223

File tree

3 files changed

+253
-20
lines changed

3 files changed

+253
-20
lines changed

base/services/dhcpcsvc/dhcp/api.c

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -144,24 +144,12 @@ Server_ReleaseParameters(
144144

145145
DPRINT("Adapter: %p\n", Adapter);
146146

147-
if (Adapter->NteContext)
148-
{
149-
DeleteIPAddress(Adapter->NteContext);
150-
Adapter->NteContext = 0;
151-
}
152-
if (Adapter->RouterMib.dwForwardNextHop)
153-
{
154-
DeleteIpForwardEntry(&Adapter->RouterMib);
155-
Adapter->RouterMib.dwForwardNextHop = 0;
156-
}
147+
state_release(&Adapter->DhclientInfo);
157148

158149
proto = find_protocol_by_adapter(&Adapter->DhclientInfo);
159150
if (proto)
160151
remove_protocol(proto);
161152

162-
Adapter->DhclientInfo.client->active = NULL;
163-
Adapter->DhclientInfo.client->state = S_INIT;
164-
165153
if (hAdapterStateChangedEvent != NULL)
166154
SetEvent(hAdapterStateChangedEvent);
167155

base/services/dhcpcsvc/dhcp/dhclient.c

Lines changed: 244 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,28 @@ state_init(void *ipp)
227227
send_discover(ip);
228228
}
229229

230+
void
231+
state_release(void *ipp)
232+
{
233+
struct interface_info *ip = ipp;
234+
ULONG foo = (ULONG) GetTickCount();
235+
236+
ASSERT_STATE(state, S_BOUND);
237+
238+
/* Make a DHCPRELEASE packet, and set appropriate per-interface
239+
flags. */
240+
make_release(ip, ip->client->active);
241+
242+
/* make_request doesn't initialize xid because it normally comes
243+
from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
244+
so pick an xid now. */
245+
ip->client->xid = RtlRandom(&foo);
246+
send_release(ip);
247+
248+
ip->client->state = S_RELEASED;
249+
unbind_lease(ip);
250+
}
251+
230252
/*
231253
* state_selecting is called when one or more DHCPOFFER packets
232254
* have been received and a configurable period of time has passed.
@@ -379,6 +401,7 @@ dhcpack(struct packet *packet)
379401
ip->client->new->renewal / 2 + ip->client->new->renewal / 4;
380402

381403
#ifdef __REACTOS__
404+
ip->client->new->lease = ip->client->new->expiry;
382405
ip->client->new->obtained = cur_time;
383406
#endif
384407
ip->client->new->expiry += cur_time;
@@ -439,6 +462,23 @@ void set_name_servers( PDHCP_ADAPTER Adapter, struct client_lease *new_lease ) {
439462

440463
}
441464

465+
void
466+
unset_name_servers(
467+
PDHCP_ADAPTER Adapter)
468+
{
469+
CHAR Buffer[200] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
470+
HKEY RegKey;
471+
472+
strcat(Buffer, Adapter->DhclientInfo.name);
473+
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Buffer, 0, KEY_WRITE, &RegKey ) != ERROR_SUCCESS)
474+
return;
475+
476+
RegDeleteValueW( RegKey, L"DhcpNameServer" );
477+
478+
RegCloseKey( RegKey );
479+
}
480+
481+
442482
void
443483
set_domain(PDHCP_ADAPTER Adapter,
444484
struct client_lease *new_lease)
@@ -489,12 +529,40 @@ set_domain(PDHCP_ADAPTER Adapter,
489529

490530
}
491531

532+
void
533+
unset_domain(
534+
PDHCP_ADAPTER Adapter)
535+
{
536+
CHAR Buffer1[MAX_PATH] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
537+
CHAR Buffer2[MAX_PATH] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters";
538+
HKEY RegKey1, RegKey2;
539+
540+
strcat(Buffer1, Adapter->DhclientInfo.name);
541+
542+
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Buffer1, 0, KEY_WRITE, &RegKey1 ) != ERROR_SUCCESS)
543+
{
544+
return;
545+
}
546+
547+
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Buffer2, 0, KEY_WRITE, &RegKey2 ) != ERROR_SUCCESS)
548+
{
549+
RegCloseKey(RegKey1);
550+
return;
551+
}
552+
553+
RegDeleteValueW(RegKey1, L"DhcpDomain");
554+
RegDeleteValueW(RegKey2, L"DhcpDomain");
555+
556+
RegCloseKey(RegKey1);
557+
RegCloseKey(RegKey2);
558+
}
559+
560+
492561
void setup_adapter( PDHCP_ADAPTER Adapter, struct client_lease *new_lease ) {
493562
CHAR Buffer[200] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
494563
struct iaddr netmask;
495564
HKEY hkey;
496565
int i;
497-
DWORD dwEnableDHCP;
498566

499567
strcat(Buffer, Adapter->DhclientInfo.name);
500568
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Buffer, 0, KEY_WRITE, &hkey) != ERROR_SUCCESS)
@@ -530,12 +598,13 @@ void setup_adapter( PDHCP_ADAPTER Adapter, struct client_lease *new_lease ) {
530598
strcat(Buffer, ".");
531599
}
532600
RegSetValueExA(hkey, "DhcpSubnetMask", 0, REG_SZ, (LPBYTE)Buffer, strlen(Buffer)+1);
533-
dwEnableDHCP = 1;
534-
RegSetValueExA(hkey, "EnableDHCP", 0, REG_DWORD, (LPBYTE)&dwEnableDHCP, sizeof(DWORD));
601+
RegSetValueExA(hkey, "DhcpServer", 0, REG_SZ, (LPBYTE)piaddr(new_lease->serveraddress), strlen(piaddr(new_lease->serveraddress))+1);
535602

603+
RegSetValueExA(hkey, "Lease", 0, REG_DWORD, (LPBYTE)&new_lease->lease, sizeof(DWORD));
536604
RegSetValueExA(hkey, "LeaseObtainedTime", 0, REG_DWORD, (LPBYTE)&new_lease->obtained, sizeof(DWORD));
537605
RegSetValueExA(hkey, "LeaseTerminatesTime", 0, REG_DWORD, (LPBYTE)&new_lease->expiry, sizeof(DWORD));
538-
RegSetValueExA(hkey, "DhcpServer", 0, REG_SZ, (LPBYTE)piaddr(new_lease->serveraddress), strlen(piaddr(new_lease->serveraddress))+1);
606+
RegSetValueExA(hkey, "T1", 0, REG_DWORD, (LPBYTE)&new_lease->renewal, sizeof(DWORD));
607+
RegSetValueExA(hkey, "T2", 0, REG_DWORD, (LPBYTE)&new_lease->rebind, sizeof(DWORD));
539608
}
540609

541610
if( !NT_SUCCESS(Status) )
@@ -579,6 +648,56 @@ void setup_adapter( PDHCP_ADAPTER Adapter, struct client_lease *new_lease ) {
579648
RegCloseKey(hkey);
580649
}
581650

651+
void
652+
reset_adapter( PDHCP_ADAPTER Adapter) {
653+
CHAR Buffer[200] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
654+
CHAR IpAddress[] = "0.0.0.0";
655+
CHAR SubnetMask[] = "255.0.0.0";
656+
CHAR Server[] = "255.255.255.255";
657+
HKEY hkey;
658+
DWORD lease;
659+
time_t cur_time, new_time;
660+
661+
time(&cur_time);
662+
663+
strcat(Buffer, Adapter->DhclientInfo.name);
664+
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Buffer, 0, KEY_WRITE, &hkey) != ERROR_SUCCESS)
665+
hkey = NULL;
666+
667+
if( Adapter->NteContext )
668+
{
669+
DeleteIPAddress( Adapter->NteContext );
670+
Adapter->NteContext = 0;
671+
}
672+
673+
if (hkey) {
674+
RegSetValueExA(hkey, "DhcpIPAddress", 0, REG_SZ, (LPBYTE)IpAddress, strlen(IpAddress)+1);
675+
RegSetValueExA(hkey, "DhcpSubnetMask", 0, REG_SZ, (LPBYTE)SubnetMask, strlen(SubnetMask)+1);
676+
RegSetValueExA(hkey, "DhcpServer", 0, REG_SZ, (LPBYTE)Server, strlen(Server)+1);
677+
678+
lease = 3600;
679+
RegSetValueExA(hkey, "Lease", 0, REG_DWORD, (LPBYTE)&lease, sizeof(DWORD));
680+
RegSetValueExA(hkey, "LeaseObtainedTime", 0, REG_DWORD, (LPBYTE)&cur_time, sizeof(DWORD));
681+
new_time = cur_time + lease;
682+
RegSetValueExA(hkey, "LeaseTerminatesTime", 0, REG_DWORD, (LPBYTE)&new_time, sizeof(DWORD));
683+
new_time = cur_time + (lease / 2);
684+
RegSetValueExA(hkey, "T1", 0, REG_DWORD, (LPBYTE)&new_time, sizeof(DWORD));
685+
new_time = cur_time + lease - (lease / 8);
686+
RegSetValueExA(hkey, "T2", 0, REG_DWORD, (LPBYTE)&new_time, sizeof(DWORD));
687+
}
688+
689+
if( Adapter->RouterMib.dwForwardNextHop ) {
690+
DeleteIpForwardEntry( &Adapter->RouterMib );
691+
}
692+
693+
if (hkey) {
694+
RegDeleteValueA(hkey, "DhcpDefaultGateway");
695+
}
696+
697+
if (hkey)
698+
RegCloseKey(hkey);
699+
}
700+
582701

583702
void
584703
bind_lease(struct interface_info *ip)
@@ -622,6 +741,28 @@ bind_lease(struct interface_info *ip)
622741
set_domain( Adapter, new_lease );
623742
}
624743

744+
void
745+
unbind_lease(struct interface_info *ip)
746+
{
747+
PDHCP_ADAPTER Adapter;
748+
749+
if (ip->client->active) {
750+
free_client_lease(ip->client->active);
751+
ip->client->active = NULL;
752+
}
753+
754+
Adapter = AdapterFindInfo( ip );
755+
if (Adapter) {
756+
reset_adapter(Adapter);
757+
unset_name_servers(Adapter);
758+
unset_domain(Adapter);
759+
}
760+
else {
761+
warning("Could not find adapter for info %p\n", ip);
762+
return;
763+
}
764+
}
765+
625766
/*
626767
* state_bound is called when we've successfully bound to a particular
627768
* lease, but the renewal time on that lease has expired. We are
@@ -874,8 +1015,16 @@ packet_to_lease(struct packet *packet)
8741015
lease->address.len = sizeof(packet->raw->yiaddr);
8751016
memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
8761017
#ifdef __REACTOS__
877-
lease->serveraddress.len = sizeof(packet->raw->siaddr);
878-
memcpy(lease->serveraddress.iabuf, &packet->raw->siaddr, lease->address.len);
1018+
if (packet->raw->siaddr.S_un.S_addr == 0)
1019+
{
1020+
lease->serveraddress.len = packet->client_addr.len;
1021+
memcpy(lease->serveraddress.iabuf, &packet->client_addr.iabuf, packet->client_addr.len);
1022+
}
1023+
else
1024+
{
1025+
lease->serveraddress.len = sizeof(packet->raw->siaddr);
1026+
memcpy(lease->serveraddress.iabuf, &packet->raw->siaddr, lease->serveraddress.len);
1027+
}
8791028
#endif
8801029

8811030
/* If the server name was filled out, copy it. */
@@ -1256,6 +1405,31 @@ send_decline(void *ipp)
12561405
inaddr_any, &sockaddr_broadcast, NULL);
12571406
}
12581407

1408+
void
1409+
send_release(void *ipp)
1410+
{
1411+
struct interface_info *ip = ipp;
1412+
struct sockaddr_in destination;
1413+
struct in_addr from;
1414+
1415+
memset(&destination, 0, sizeof(destination));
1416+
memcpy(&destination.sin_addr.s_addr,
1417+
ip->client->destination.iabuf,
1418+
sizeof(destination.sin_addr.s_addr));
1419+
destination.sin_port = htons(REMOTE_PORT);
1420+
destination.sin_family = AF_INET;
1421+
1422+
memcpy(&from, ip->client->active->address.iabuf,
1423+
sizeof(from));
1424+
1425+
note("DHCPRELEASE on %s to %s port %d", ip->name,
1426+
inet_ntoa(destination.sin_addr), ntohs(destination.sin_port));
1427+
1428+
/* Send out a packet. */
1429+
(void) send_packet(ip, &ip->client->packet, ip->client->packet_length,
1430+
from, &destination, NULL);
1431+
}
1432+
12591433
void
12601434
make_discover(struct interface_info *ip, struct client_lease *lease)
12611435
{
@@ -1515,6 +1689,70 @@ make_decline(struct interface_info *ip, struct client_lease *lease)
15151689
ip->hw_address.haddr, ip->hw_address.hlen);
15161690
}
15171691

1692+
void
1693+
make_release(struct interface_info *ip, struct client_lease *lease)
1694+
{
1695+
struct tree_cache *options[256], message_type_tree;
1696+
struct tree_cache server_id_tree, client_id_tree;
1697+
unsigned char release = DHCPRELEASE;
1698+
int i;
1699+
1700+
memset(options, 0, sizeof(options));
1701+
memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1702+
1703+
/* Set DHCP_MESSAGE_TYPE to DHCPRELEASE */
1704+
i = DHO_DHCP_MESSAGE_TYPE;
1705+
options[i] = &message_type_tree;
1706+
options[i]->value = &release;
1707+
options[i]->len = sizeof(release);
1708+
options[i]->buf_size = sizeof(release);
1709+
options[i]->timeout = 0xFFFFFFFF;
1710+
1711+
/* Send back the server identifier... */
1712+
i = DHO_DHCP_SERVER_IDENTIFIER;
1713+
options[i] = &server_id_tree;
1714+
options[i]->value = lease->options[i].data;
1715+
options[i]->len = lease->options[i].len;
1716+
options[i]->buf_size = lease->options[i].len;
1717+
options[i]->timeout = 0xFFFFFFFF;
1718+
1719+
/* Send the uid if the user supplied one. */
1720+
i = DHO_DHCP_CLIENT_IDENTIFIER;
1721+
if (ip->client->config->send_options[i].len)
1722+
{
1723+
options[i] = &client_id_tree;
1724+
options[i]->value = ip->client->config->send_options[i].data;
1725+
options[i]->len = ip->client->config->send_options[i].len;
1726+
options[i]->buf_size = ip->client->config->send_options[i].len;
1727+
options[i]->timeout = 0xFFFFFFFF;
1728+
}
1729+
1730+
/* Set up the option buffer... */
1731+
ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0, options);
1732+
if (ip->client->packet_length < BOOTP_MIN_LEN)
1733+
ip->client->packet_length = BOOTP_MIN_LEN;
1734+
1735+
ip->client->packet.op = BOOTREQUEST;
1736+
ip->client->packet.htype = ip->hw_address.htype;
1737+
ip->client->packet.hlen = ip->hw_address.hlen;
1738+
ip->client->packet.hops = 0;
1739+
ip->client->packet.xid = 0;
1740+
ip->client->packet.secs = 0;
1741+
ip->client->packet.flags = 0;
1742+
1743+
/* ciaddr is the address to be released */
1744+
memcpy(&ip->client->packet.ciaddr,
1745+
lease->address.iabuf, lease->address.len);
1746+
memset(&ip->client->packet.yiaddr, 0,
1747+
sizeof(ip->client->packet.yiaddr));
1748+
memset(&ip->client->packet.siaddr, 0,
1749+
sizeof(ip->client->packet.siaddr));
1750+
memset(&ip->client->packet.giaddr, 0,
1751+
sizeof(ip->client->packet.giaddr));
1752+
memcpy(ip->client->packet.chaddr,
1753+
ip->hw_address.haddr, ip->hw_address.hlen);
1754+
}
1755+
15181756
void
15191757
free_client_lease(struct client_lease *lease)
15201758
{

0 commit comments

Comments
 (0)