mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-11-22 09:29:52 +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:
parent
1c4b257a1b
commit
b890c7d813
@ -1318,3 +1318,40 @@ bool GetUserMacAddressFromUserNote(UCHAR *mac, wchar_t *note)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Get the static IPv4 address from the user's note string
|
||||
UINT GetUserIPv4AddressFromUserNote32(wchar_t *note)
|
||||
{
|
||||
bool ret = false;
|
||||
UINT ip32 = 0;
|
||||
|
||||
UINT i = UniSearchStrEx(note, USER_IPV4_STR_PREFIX, 0, false);
|
||||
if (i != INFINITE)
|
||||
{
|
||||
wchar_t *ipv4str_start = ¬e[i + UniStrLen(USER_IPV4_STR_PREFIX)];
|
||||
wchar_t ipv4str2[MAX_SIZE];
|
||||
UNI_TOKEN_LIST *tokens;
|
||||
|
||||
UniStrCpy(ipv4str2, sizeof(ipv4str2), ipv4str_start);
|
||||
UniTrim(ipv4str2);
|
||||
|
||||
tokens = UniParseToken(ipv4str2, L" ,/()[]");
|
||||
if (tokens != NULL)
|
||||
{
|
||||
if (tokens->NumTokens >= 1)
|
||||
{
|
||||
wchar_t *ipv4str = tokens->Token[0];
|
||||
if (UniIsEmptyStr(ipv4str) == false)
|
||||
{
|
||||
char ipv4str_a[MAX_SIZE];
|
||||
UniToStr(ipv4str_a, sizeof(ipv4str_a), ipv4str);
|
||||
ip32 = StrToIP32(ipv4str_a);
|
||||
}
|
||||
}
|
||||
|
||||
UniFreeToken(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
return ip32;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define ACCOUNT_H
|
||||
|
||||
#define USER_MAC_STR_PREFIX L"MAC:"
|
||||
#define USER_IPV4_STR_PREFIX L"IPv4:"
|
||||
|
||||
// Policy item
|
||||
struct POLICY_ITEM
|
||||
@ -205,7 +206,6 @@ POLICY_ITEM *GetPolicyItem(UINT id);
|
||||
void GetPolicyValueRangeStr(wchar_t *str, UINT size, UINT id);
|
||||
void FormatPolicyValue(wchar_t *str, UINT size, UINT id, UINT value);
|
||||
bool GetUserMacAddressFromUserNote(UCHAR *mac, wchar_t *note);
|
||||
UINT GetUserIPv4AddressFromUserNote32(wchar_t *note);
|
||||
|
||||
#endif // ACCOUNT_H
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -339,6 +339,9 @@ void CancelList(LIST *o);
|
||||
bool IsPriorityHighestPacketForQoS(void *data, UINT size);
|
||||
UINT GetNextDelayedPacketTickDiff(SESSION *s);
|
||||
|
||||
UINT PrepareDHCPRequestForStaticIPv4(SESSION *s, BLOCK *b);
|
||||
void ClearDHCPLeaseRecordForIPv4(SESSION *s, UINT static_ip);
|
||||
|
||||
#endif // SESSION_H
|
||||
|
||||
|
||||
|
@ -9198,6 +9198,11 @@ PENDING_LIST_CLEANUP:
|
||||
|
||||
// Correspond to the DHCP REQUEST
|
||||
UINT ServeDhcpRequest(VH *v, UCHAR *mac, UINT request_ip)
|
||||
{
|
||||
return ServeDhcpRequestEx(v, mac, request_ip, false);
|
||||
}
|
||||
|
||||
UINT ServeDhcpRequestEx(VH *v, UCHAR *mac, UINT request_ip, bool is_static_ip)
|
||||
{
|
||||
UINT ret;
|
||||
// Validate arguments
|
||||
@ -9206,7 +9211,7 @@ UINT ServeDhcpRequest(VH *v, UCHAR *mac, UINT request_ip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = ServeDhcpDiscover(v, mac, request_ip);
|
||||
ret = ServeDhcpDiscoverEx(v, mac, request_ip, is_static_ip);
|
||||
if (ret != request_ip)
|
||||
{
|
||||
if (request_ip != 0)
|
||||
@ -9309,6 +9314,34 @@ UINT ServeDhcpDiscover(VH *v, UCHAR *mac, UINT request_ip)
|
||||
return ret;
|
||||
}
|
||||
|
||||
UINT ServeDhcpDiscoverEx(VH *v, UCHAR *mac, UINT request_ip, bool is_static_ip)
|
||||
{
|
||||
if (is_static_ip == false)
|
||||
{
|
||||
return ServeDhcpDiscover(v, mac, request_ip );
|
||||
}
|
||||
|
||||
if (v == NULL || mac == NULL || request_ip == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
DHCP_LEASE *d = SearchDhcpLeaseByIp(v, request_ip);
|
||||
if (d != NULL)
|
||||
{
|
||||
// The requested IP address is used already
|
||||
return 0;
|
||||
}
|
||||
|
||||
// For static IP, the requested IP address must NOT be within the range of the DHCP pool
|
||||
if (Endian32(request_ip) < Endian32(v->DhcpIpStart) || Endian32(request_ip) > Endian32(v->DhcpIpEnd))
|
||||
{
|
||||
return request_ip;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Take an appropriate IP addresses that can be assigned newly
|
||||
UINT GetFreeDhcpIpAddress(VH *v)
|
||||
{
|
||||
@ -9469,21 +9502,30 @@ void VirtualDhcpServer(VH *v, PKT *p)
|
||||
if (dhcp->OpCode == 1 && (opt->Opcode == DHCP_DISCOVER || opt->Opcode == DHCP_REQUEST || opt->Opcode == DHCP_INFORM))
|
||||
{
|
||||
// Operate as the server
|
||||
UINT ip = 0;
|
||||
UINT ip = 0, ip_static = dhcp->ServerIP;
|
||||
dhcp->ServerIP = 0;
|
||||
|
||||
if (opt->RequestedIp == 0)
|
||||
{
|
||||
opt->RequestedIp = p->L3.IPv4Header->SrcIP;
|
||||
opt->RequestedIp = (ip_static ? ip_static : p->L3.IPv4Header->SrcIP);
|
||||
}
|
||||
if (opt->Opcode == DHCP_DISCOVER)
|
||||
{
|
||||
// Return an IP address that can be used
|
||||
ip = ServeDhcpDiscover(v, p->MacAddressSrc, opt->RequestedIp);
|
||||
ip = ServeDhcpDiscoverEx(v, p->MacAddressSrc, opt->RequestedIp, ip_static);
|
||||
}
|
||||
else if (opt->Opcode == DHCP_REQUEST)
|
||||
{
|
||||
// Determine the IP address
|
||||
ip = ServeDhcpRequest(v, p->MacAddressSrc, opt->RequestedIp);
|
||||
if (ip_static && opt->RequestedIp != ip_static)
|
||||
{
|
||||
// Don't allow opt->RequestedIp other than the IP written in user's note
|
||||
ip = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ip = ServeDhcpRequestEx(v, p->MacAddressSrc, opt->RequestedIp, ip_static);
|
||||
}
|
||||
}
|
||||
|
||||
if (ip != 0 || opt->Opcode == DHCP_INFORM)
|
||||
|
@ -514,9 +514,11 @@ DHCP_LEASE *SearchDhcpPendingLeaseByMac(VH *v, UCHAR *mac);
|
||||
DHCP_LEASE *SearchDhcpLeaseByIp(VH *v, UINT ip);
|
||||
DHCP_LEASE *SearchDhcpPendingLeaseByIp(VH *v, UINT ip);
|
||||
UINT ServeDhcpDiscover(VH *v, UCHAR *mac, UINT request_ip);
|
||||
UINT ServeDhcpDiscoverEx(VH *v, UCHAR *mac, UINT request_ip, bool is_static_ip);
|
||||
UINT GetFreeDhcpIpAddress(VH *v);
|
||||
UINT GetFreeDhcpIpAddressByRandom(VH *v, UCHAR *mac);
|
||||
UINT ServeDhcpRequest(VH *v, UCHAR *mac, UINT request_ip);
|
||||
UINT ServeDhcpRequestEx(VH *v, UCHAR *mac, UINT request_ip, bool is_static_ip);
|
||||
void VirtualDhcpSend(VH *v, UINT tran_id, UINT dest_ip, UINT dest_port,
|
||||
UINT new_ip, UCHAR *client_mac, BUF *b, UINT hw_type, UINT hw_addr_size);
|
||||
void VLog(VH *v, char *str);
|
||||
@ -587,7 +589,4 @@ void NnDeleteOldestNatSessionIfNecessary(NATIVE_NAT *t, UINT ip, UINT protocol);
|
||||
|
||||
void NnSetSecureNatTargetHostname(char *name);
|
||||
|
||||
|
||||
#endif // VIRTUAL_H
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user