1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2025-07-12 02:34:59 +03:00

Cedar: DHCP server now assigns static IPv4 address, if present in user note

This works for all VPN protocols.

In SessionMain(): for DHCPDISCOVER and DHCPREQUEST frames, write the static IP address (which is retrieved from the user notes) in the SIADDR field of DHCPHEADER.

In VirtualDhcpServer(): for DHCPDISCOVER and DHCPREQUEST frames, read the static IP address from the SIADDR field of DHCPHEADER and assign it to the client.
This commit is contained in:
PeTeeR
2020-10-12 04:56:30 +02:00
committed by Davide Beatrici
parent 1c4b257a1b
commit b890c7d813
6 changed files with 240 additions and 10 deletions

View File

@ -33,6 +33,8 @@ void SessionMain(SESSION *s)
SOCK *nicinfo_sock = NULL;
bool is_server_session = false;
bool lock_receive_blocks_queue = false;
UINT static_ip = 0;
// Validate arguments
if (s == NULL)
{
@ -300,6 +302,13 @@ void SessionMain(SESSION *s)
if (b->Size >= 14)
{
UINT ip;
if( (ip = PrepareDHCPRequestForStaticIPv4( s, b )) != 0 )
{
// Remember the static IP address to remove it from the leased IP address list later
static_ip = ip;
}
if (b->Buf[0] & 0x01)
{
if (is_server_session == false)
@ -603,6 +612,9 @@ CLEANUP:
// Update the user information
IncrementUserTraffic(s->Hub, s->UserNameReal, s);
// Clear the DHCP lease record if assigned as a static client IP address
ClearDHCPLeaseRecordForIPv4(s, static_ip);
DelSession(s->Hub, s);
}
@ -2309,3 +2321,140 @@ void Notify(SESSION *s, UINT code)
}
UINT PrepareDHCPRequestForStaticIPv4(SESSION *s, BLOCK *b)
{
PKT *pkt = NULL;
DHCPV4_HEADER *dhcp = NULL;
UCHAR *data = NULL;
UINT size = 0;
UINT dhcp_header_size = 0;
UINT dhcp_data_offset = 0;
UINT magic_cookie = Endian32(DHCP_MAGIC_COOKIE);
DHCP_OPTION_LIST *opt = NULL;
USER *user = NULL;
UINT ret_ip = 0;
if ((s->Username == NULL) || (StrLen(s->Username) == 0) || (StrCmpi(s->Username, SNAT_USER_NAME_PRINT) == 0) ||
(StrCmpi( s->Username, BRIDGE_USER_NAME_PRINT) == 0) || (StrCmpi(s->Username, LINK_USER_NAME_PRINT) == 0))
{
return ret_ip;
}
pkt = ParsePacket(b->Buf, b->Size);
if (pkt == NULL)
{
return ret_ip;
}
if (pkt->TypeL3 == L3_IPV4 && pkt->TypeL4 == L4_UDP && pkt->TypeL7 == L7_DHCPV4)
{
if (pkt->L7.DHCPv4Header->OpCode != 1)
{
goto CLEANUP_TP;
}
dhcp = pkt->L7.DHCPv4Header;
dhcp_header_size = sizeof(DHCPV4_HEADER);
dhcp_data_offset = (UINT)(((UCHAR *)pkt->L7.DHCPv4Header) - ((UCHAR *)pkt->MacHeader) + dhcp_header_size);
data = ((UCHAR *)dhcp) + dhcp_header_size;
size = pkt->PacketSize - dhcp_data_offset;
if (dhcp_header_size < 5)
{
goto CLEANUP_TP;
}
// Search for Magic Cookie
while (size >= 5)
{
if (Cmp(data, &magic_cookie, sizeof(magic_cookie)) == 0)
{
// Found
data += 4;
size -= 4;
opt = ParseDhcpOptionList(data, size);
break;
}
++data;
--size;
}
if (opt == NULL)
{
goto CLEANUP_TP;
}
if (opt->Opcode == DHCP_DISCOVER || opt->Opcode == DHCP_REQUEST)
{
if (s->Hub != NULL)
{
user = AcGetUser( s->Hub, s->Username );
if (user != NULL)
{
dhcp->ServerIP = GetUserIPv4AddressFromUserNote32(user->Note);
ReleaseUser(user);
if (s->Hub->SecureNAT != NULL && s->Hub->SecureNAT->Nat != NULL)
{
VH *v = s->Hub->SecureNAT->Nat->Virtual;
if (v != NULL && v->UseDhcp == true && v->DhcpLeaseList != NULL)
{
DHCP_LEASE *d = SearchDhcpLeaseByIp(v, dhcp->ServerIP);
// The given static IP address is not used - it's OK
if (d == NULL)
{
ret_ip = dhcp->ServerIP;
}
}
}
}
}
}
}
CLEANUP_TP:
if (opt != NULL)
{
Free(opt);
}
if (pkt != NULL)
{
FreePacket(pkt);
}
return ret_ip;
}
void ClearDHCPLeaseRecordForIPv4(SESSION *s, UINT static_ip)
{
if (s == NULL || static_ip == 0)
{
return;
}
if (s->Hub == NULL || s->Hub->SecureNAT == NULL || s->Hub->SecureNAT->Nat == NULL)
{
return;
}
VH *v = s->Hub->SecureNAT->Nat->Virtual;
if (v == NULL || v->DhcpLeaseList == NULL)
{
return;
}
DHCP_LEASE *d = SearchDhcpLeaseByIp(v, static_ip);
if (d == NULL)
{
return;
}
LockList(v->DhcpLeaseList);
{
FreeDhcpLease(d);
Delete(v->DhcpLeaseList, d);
}
UnlockList( v->DhcpLeaseList);
}