mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-11-22 17:39:53 +03:00
Preliminary IPC IPv6 implementation (untested)
This commit is contained in:
parent
8fdf7302a5
commit
1d6a4d3ec8
@ -582,6 +582,7 @@ typedef struct IPC_PARAM IPC_PARAM;
|
|||||||
typedef struct IPC_DHCP_RELEASE_QUEUE IPC_DHCP_RELEASE_QUEUE;
|
typedef struct IPC_DHCP_RELEASE_QUEUE IPC_DHCP_RELEASE_QUEUE;
|
||||||
typedef struct IPC_MSCHAP_V2_AUTHINFO IPC_MSCHAP_V2_AUTHINFO;
|
typedef struct IPC_MSCHAP_V2_AUTHINFO IPC_MSCHAP_V2_AUTHINFO;
|
||||||
typedef struct IPC_SESSION_SHARED_BUFFER_DATA IPC_SESSION_SHARED_BUFFER_DATA;
|
typedef struct IPC_SESSION_SHARED_BUFFER_DATA IPC_SESSION_SHARED_BUFFER_DATA;
|
||||||
|
typedef struct IPC_IPV6_ROUTER_ADVERTISEMENT IPC_IPV6_ROUTER_ADVERTISEMENT;
|
||||||
|
|
||||||
|
|
||||||
// ==============================================================
|
// ==============================================================
|
||||||
|
564
src/Cedar/IPC.c
564
src/Cedar/IPC.c
@ -489,6 +489,8 @@ IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char
|
|||||||
// Create an IPv4 reception queue
|
// Create an IPv4 reception queue
|
||||||
ipc->IPv4ReceivedQueue = NewQueue();
|
ipc->IPv4ReceivedQueue = NewQueue();
|
||||||
|
|
||||||
|
IPCIPv6Init(ipc);
|
||||||
|
|
||||||
return ipc;
|
return ipc;
|
||||||
|
|
||||||
LABEL_ERROR:
|
LABEL_ERROR:
|
||||||
@ -531,6 +533,8 @@ IPC *NewIPCBySock(CEDAR *cedar, SOCK *s, void *mac_address)
|
|||||||
|
|
||||||
ipc->FlushList = NewTubeFlushList();
|
ipc->FlushList = NewTubeFlushList();
|
||||||
|
|
||||||
|
IPCIPv6Init(ipc);
|
||||||
|
|
||||||
return ipc;
|
return ipc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -610,6 +614,8 @@ void FreeIPC(IPC *ipc)
|
|||||||
|
|
||||||
ReleaseSharedBuffer(ipc->IpcSessionSharedBuffer);
|
ReleaseSharedBuffer(ipc->IpcSessionSharedBuffer);
|
||||||
|
|
||||||
|
IPCIPv6Free(ipc);
|
||||||
|
|
||||||
Free(ipc);
|
Free(ipc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1186,7 +1192,7 @@ void IPCProcessArp(IPC *ipc, BLOCK *b)
|
|||||||
if (CmpIpAddr(&target_ip, &ipc->ClientIPAddress) == 0)
|
if (CmpIpAddr(&target_ip, &ipc->ClientIPAddress) == 0)
|
||||||
{
|
{
|
||||||
// Create a response since a request for its own IP address have received
|
// Create a response since a request for its own IP address have received
|
||||||
if (IsValidUnicastMacAddress(sender_mac))
|
if (IsMacUnicast(sender_mac))
|
||||||
{
|
{
|
||||||
UCHAR tmp[14 + sizeof(ARPV4_HEADER)];
|
UCHAR tmp[14 + sizeof(ARPV4_HEADER)];
|
||||||
ARPV4_HEADER *arp = (ARPV4_HEADER *)(tmp + 14);
|
ARPV4_HEADER *arp = (ARPV4_HEADER *)(tmp + 14);
|
||||||
@ -1218,7 +1224,7 @@ void IPCAssociateOnArpTable(IPC *ipc, IP *ip, UCHAR *mac_address)
|
|||||||
{
|
{
|
||||||
IPC_ARP *a;
|
IPC_ARP *a;
|
||||||
// Validate arguments
|
// Validate arguments
|
||||||
if (ipc == NULL || ip == NULL || IsValidUnicastIPAddress4(ip) == false || IsValidUnicastMacAddress(mac_address) == false)
|
if (ipc == NULL || ip == NULL || IsValidUnicastIPAddress4(ip) == false || IsMacUnicast(mac_address) == false)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1239,7 +1245,7 @@ void IPCAssociateOnArpTable(IPC *ipc, IP *ip, UCHAR *mac_address)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Search whether there is ARP table entry already
|
// Search whether there is ARP table entry already
|
||||||
a = IPCSearchArpTable(ipc, ip);
|
a = IPCSearchArpTable(ipc->ArpTable, ip);
|
||||||
if (a == NULL)
|
if (a == NULL)
|
||||||
{
|
{
|
||||||
// Add to the ARP table
|
// Add to the ARP table
|
||||||
@ -1278,68 +1284,6 @@ void IPCAssociateOnArpTable(IPC *ipc, IP *ip, UCHAR *mac_address)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identify whether the MAC address is a normal unicast address
|
|
||||||
bool IsValidUnicastMacAddress(UCHAR *mac)
|
|
||||||
{
|
|
||||||
// Validate arguments
|
|
||||||
if (mac == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mac[0] & 0x01)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsZero(mac, 6))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Identify whether the IP address is a normal unicast address
|
|
||||||
bool IsValidUnicastIPAddress4(IP *ip)
|
|
||||||
{
|
|
||||||
UINT i;
|
|
||||||
// Validate arguments
|
|
||||||
if (IsIP4(ip) == false)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsZeroIP(ip))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ip->addr[0] >= 224 && ip->addr[0] <= 239)
|
|
||||||
{
|
|
||||||
// IPv4 Multicast
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0;i < 4;i++)
|
|
||||||
{
|
|
||||||
if (ip->addr[i] != 255)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool IsValidUnicastIPAddressUINT4(UINT ip)
|
|
||||||
{
|
|
||||||
IP a;
|
|
||||||
|
|
||||||
UINTToIP(&a, ip);
|
|
||||||
|
|
||||||
return IsValidUnicastIPAddress4(&a);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interrupt process (This is called periodically)
|
// Interrupt process (This is called periodically)
|
||||||
void IPCProcessInterrupts(IPC *ipc)
|
void IPCProcessInterrupts(IPC *ipc)
|
||||||
{
|
{
|
||||||
@ -1371,6 +1315,7 @@ void IPCProcessL3EventsEx(IPC *ipc, UINT64 now)
|
|||||||
|
|
||||||
// Remove old ARP table entries
|
// Remove old ARP table entries
|
||||||
IPCFlushArpTableEx(ipc, now);
|
IPCFlushArpTableEx(ipc, now);
|
||||||
|
IPCIPv6FlushNDTEx(ipc, now);
|
||||||
|
|
||||||
// Receive all the L2 packet
|
// Receive all the L2 packet
|
||||||
while (true)
|
while (true)
|
||||||
@ -1390,10 +1335,10 @@ void IPCProcessL3EventsEx(IPC *ipc, UINT64 now)
|
|||||||
|
|
||||||
// Confirm the destination MAC address
|
// Confirm the destination MAC address
|
||||||
// (Receive if the destination MAC address is the IPC address or a broadcast address)
|
// (Receive if the destination MAC address is the IPC address or a broadcast address)
|
||||||
if (Cmp(dest_mac, ipc->MacAddress, 6) == 0 || dest_mac[0] & 0x01)
|
if (Cmp(dest_mac, ipc->MacAddress, 6) == 0 || IsMacBroadcast(dest_mac) || IsMacMulticast(dest_mac))
|
||||||
{
|
{
|
||||||
// If the source MAC address is itselves or invalid address, ignore the packet
|
// If the source MAC address is itselves or invalid address, ignore the packet
|
||||||
if (Cmp(src_mac, ipc->MacAddress, 6) != 0 && IsValidUnicastMacAddress(src_mac))
|
if (Cmp(src_mac, ipc->MacAddress, 6) != 0 && !IsMacUnicast(src_mac))
|
||||||
{
|
{
|
||||||
if (protocol == MAC_PROTO_ARPV4)
|
if (protocol == MAC_PROTO_ARPV4)
|
||||||
{
|
{
|
||||||
@ -1457,6 +1402,54 @@ void IPCProcessL3EventsEx(IPC *ipc, UINT64 now)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (protocol == MAC_PROTO_IPV6)
|
||||||
|
{
|
||||||
|
PKT* p = ParsePacketUpToICMPv6(b->Buf, b->Size);
|
||||||
|
if (p != NULL)
|
||||||
|
{
|
||||||
|
IP ip_src, ip_dst;
|
||||||
|
bool ndtProcessed = false;
|
||||||
|
|
||||||
|
UCHAR* data = Clone(p->L3.IPv6Header, p->L3.IPv6Header->PayloadLength + sizeof(IPV6_HEADER));
|
||||||
|
|
||||||
|
IPv6AddrToIP(&ip_src, &p->IPv6HeaderPacketInfo.IPv6Header->SrcAddress);
|
||||||
|
IPv6AddrToIP(&ip_dst, &p->IPv6HeaderPacketInfo.IPv6Header->DestAddress);
|
||||||
|
|
||||||
|
if (p->IPv6HeaderPacketInfo.Protocol == IP_PROTO_ICMPV6)
|
||||||
|
{
|
||||||
|
IP icmpHeaderAddr;
|
||||||
|
// We need to parse the Router Advertisement and Neighbor Advertisement messages
|
||||||
|
// to build the Neighbor Discovery Table (aka ARP table for IPv6)
|
||||||
|
switch (p->ICMPv6HeaderPacketInfo.Type)
|
||||||
|
{
|
||||||
|
case ICMPV6_TYPE_ROUTER_ADVERTISEMENT:
|
||||||
|
// We save the router advertisement data for later use
|
||||||
|
IPCIPv6AddRouterPrefix(ipc, &p->ICMPv6HeaderPacketInfo.OptionList, src_mac, &ip_src);
|
||||||
|
IPCIPv6AssociateOnNDTEx(ipc, &ip_src, src_mac, true);
|
||||||
|
IPCIPv6AssociateOnNDTEx(ipc, &ip_src, &p->ICMPv6HeaderPacketInfo.OptionList.SourceLinkLayer, true);
|
||||||
|
break;
|
||||||
|
case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT:
|
||||||
|
// We save the neighbor advertisements into NDT
|
||||||
|
IPv6AddrToIP(&icmpHeaderAddr, &p->ICMPv6HeaderPacketInfo.Headers.NeighborAdvertisementHeader->TargetAddress);
|
||||||
|
IPCIPv6AssociateOnNDTEx(ipc, &icmpHeaderAddr, src_mac, true);
|
||||||
|
IPCIPv6AssociateOnNDTEx(ipc, &ip_src, src_mac, true);
|
||||||
|
ndtProcessed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We update the NDT only if we have an entry in it for the IP+Mac
|
||||||
|
if (!ndtProcessed)
|
||||||
|
{
|
||||||
|
IPCIPv6AssociateOnNDT(ipc, &ip_src, src_mac);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// TODO: should we or not filter Neighbor Advertisements and/or Neighbor Solicitations?
|
||||||
|
InsertQueue(ipc->IPv6ReceivedQueue, data);
|
||||||
|
|
||||||
|
FreePacket(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1725,7 +1718,7 @@ void IPCSendIPv4Unicast(IPC *ipc, void *data, UINT size, IP *next_ip)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
a = IPCSearchArpTable(ipc, next_ip);
|
a = IPCSearchArpTable(ipc->ArpTable, next_ip);
|
||||||
|
|
||||||
if (a != NULL)
|
if (a != NULL)
|
||||||
{
|
{
|
||||||
@ -1789,19 +1782,19 @@ void IPCSendIPv4Unicast(IPC *ipc, void *data, UINT size, IP *next_ip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Search the ARP table
|
// Search the ARP table
|
||||||
IPC_ARP *IPCSearchArpTable(IPC *ipc, IP *ip)
|
IPC_ARP *IPCSearchArpTable(LIST* arpTable, IP *ip)
|
||||||
{
|
{
|
||||||
IPC_ARP t;
|
IPC_ARP t;
|
||||||
IPC_ARP *a;
|
IPC_ARP *a;
|
||||||
// Validate arguments
|
// Validate arguments
|
||||||
if (ipc == NULL || ip == NULL)
|
if (arpTable == NULL || ip == NULL)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Copy(&t.Ip, ip, sizeof(IP));
|
Copy(&t.Ip, ip, sizeof(IP));
|
||||||
|
|
||||||
a = Search(ipc->ArpTable, &t);
|
a = Search(arpTable, &t);
|
||||||
|
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
@ -1944,5 +1937,434 @@ BLOCK *IPCRecvL2(IPC *ipc)
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IPv6 stuff
|
||||||
|
// Memory management
|
||||||
|
void IPCIPv6Init(IPC* ipc)
|
||||||
|
{
|
||||||
|
ipc->IPv6ReceivedQueue = NewQueue();
|
||||||
|
// The NDT is basically the same as ARP Table with some slight adjustments
|
||||||
|
ipc->IPv6NeighborTable = NewList(IPCCmpArpTable);
|
||||||
|
ipc->IPv6RouterAdvs = NewList(NULL);
|
||||||
|
}
|
||||||
|
void IPCIPv6Free(IPC* ipc)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
for (i = 0; i < LIST_NUM(ipc->IPv6NeighborTable); i++)
|
||||||
|
{
|
||||||
|
IPC_ARP* a = LIST_DATA(ipc->IPv6NeighborTable, i);
|
||||||
|
IPCFreeARP(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseList(ipc->IPv6NeighborTable);
|
||||||
|
|
||||||
|
for (i = 0; i < LIST_NUM(ipc->IPv6RouterAdvs); i++)
|
||||||
|
{
|
||||||
|
IPC_IPV6_ROUTER_ADVERTISEMENT* ra = LIST_DATA(ipc->IPv6RouterAdvs, i);
|
||||||
|
Free(ra);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseList(ipc->IPv6RouterAdvs);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
BLOCK* b = GetNext(ipc->IPv6ReceivedQueue);
|
||||||
|
if (b == NULL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreeBlock(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseQueue(ipc->IPv6ReceivedQueue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NDT
|
||||||
|
void IPCIPv6AssociateOnNDT(IPC* ipc, IP* ip, UCHAR* mac_address)
|
||||||
|
{
|
||||||
|
IPCIPv6AssociateOnNDTEx(ipc, ip, mac_address, false);
|
||||||
|
}
|
||||||
|
void IPCIPv6AssociateOnNDTEx(IPC* ipc, IP* ip, UCHAR* mac_address, bool isNeighborAdv)
|
||||||
|
{
|
||||||
|
IPC_ARP* a;
|
||||||
|
UINT addrType = 0;
|
||||||
|
if (ipc == NULL || ip == NULL ||
|
||||||
|
IsValidUnicastIPAddress6(ip) == false ||
|
||||||
|
IsMacUnicast(mac_address) == false)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
addrType = GetIPAddrType6(ip);
|
||||||
|
|
||||||
|
if (addrType != IPV6_ADDR_LOCAL_UNICAST &&
|
||||||
|
addrType != IPV6_ADDR_GLOBAL_UNICAST)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addrType == IPV6_ADDR_GLOBAL_UNICAST)
|
||||||
|
{
|
||||||
|
if (!IPCIPv6CheckUnicastFromRouterPrefix(ipc, ip, NULL))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a = IPCSearchArpTable(ipc->IPv6NeighborTable, ip);
|
||||||
|
|
||||||
|
// We create a new entry only if we got a neighbor advertisement
|
||||||
|
if (a == NULL && isNeighborAdv)
|
||||||
|
{
|
||||||
|
a = IPCNewARP(ip, mac_address);
|
||||||
|
Insert(ipc->IPv6NeighborTable, a);
|
||||||
|
}
|
||||||
|
else if (a == NULL)
|
||||||
|
{
|
||||||
|
// We skip the NDT association on random packets from unknown locations
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Copy(a->MacAddress, mac_address, 6);
|
||||||
|
|
||||||
|
if (a->Resolved == false)
|
||||||
|
{
|
||||||
|
a->Resolved = true;
|
||||||
|
a->GiveupTime = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
BLOCK* b = GetNext(a->PacketQueue);
|
||||||
|
|
||||||
|
if (b == NULL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPCIPv6SendWithDestMacAddr(ipc, b->Buf, b->Size, a->MacAddress);
|
||||||
|
|
||||||
|
FreeBlock(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a->ExpireTime = Tick64() + (UINT64)IPC_IPV6_NDT_LIFETIME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPCIPv6FlushNDT(IPC* ipc)
|
||||||
|
{
|
||||||
|
IPCIPv6FlushNDTEx(ipc, 0);
|
||||||
|
}
|
||||||
|
void IPCIPv6FlushNDTEx(IPC* ipc, UINT64 now)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
LIST* o = NULL;
|
||||||
|
// Validate arguments
|
||||||
|
if (ipc == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (now == 0)
|
||||||
|
{
|
||||||
|
now = Tick64();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < LIST_NUM(ipc->IPv6NeighborTable); i++)
|
||||||
|
{
|
||||||
|
IPC_ARP* a = LIST_DATA(ipc->IPv6NeighborTable, i);
|
||||||
|
bool b = false;
|
||||||
|
|
||||||
|
if (a->Resolved && a->ExpireTime <= now)
|
||||||
|
{
|
||||||
|
b = true;
|
||||||
|
}
|
||||||
|
else if (a->Resolved == false && a->GiveupTime <= now)
|
||||||
|
{
|
||||||
|
b = true;
|
||||||
|
}
|
||||||
|
/// TODO: think about adding retransmission as per RFC4861
|
||||||
|
|
||||||
|
if (b)
|
||||||
|
{
|
||||||
|
if (o == NULL)
|
||||||
|
{
|
||||||
|
o = NewListFast(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
Add(o, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o != NULL)
|
||||||
|
{
|
||||||
|
for (i = 0; i < LIST_NUM(o); i++)
|
||||||
|
{
|
||||||
|
IPC_ARP* a = LIST_DATA(o, i);
|
||||||
|
|
||||||
|
IPCFreeARP(a);
|
||||||
|
|
||||||
|
Delete(ipc->IPv6NeighborTable, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseList(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RA
|
||||||
|
void IPCIPv6AddRouterPrefix(IPC* ipc, ICMPV6_OPTION_LIST* recvPrefix, UCHAR* macAddress, IP* ip)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
bool foundPrefix = false;
|
||||||
|
for (i = 0; i < LIST_NUM(ipc->IPv6RouterAdvs); i++)
|
||||||
|
{
|
||||||
|
IPC_IPV6_ROUTER_ADVERTISEMENT* existingRA = LIST_DATA(ipc->IPv6RouterAdvs, i);
|
||||||
|
if (Cmp(&recvPrefix->Prefix->Prefix, &existingRA->RoutedPrefix.ipv6_addr, sizeof(IPV6_ADDR)) == 0)
|
||||||
|
{
|
||||||
|
foundPrefix = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundPrefix)
|
||||||
|
{
|
||||||
|
IPC_IPV6_ROUTER_ADVERTISEMENT* newRA = Malloc(sizeof(IPC_IPV6_ROUTER_ADVERTISEMENT));
|
||||||
|
IPv6AddrToIP(&newRA->RoutedPrefix, &recvPrefix->Prefix->Prefix);
|
||||||
|
IntToSubnetMask6(&newRA->RoutedMask, recvPrefix->Prefix->SubnetLength);
|
||||||
|
CopyIP(&newRA->RouterAddress, ip);
|
||||||
|
Copy(newRA->RouterMacAddress, macAddress, 6);
|
||||||
|
Copy(newRA->RouterLinkLayerAddress, recvPrefix->SourceLinkLayer->Address, 6);
|
||||||
|
Add(ipc->IPv6RouterAdvs, newRA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IPCIPv6CheckUnicastFromRouterPrefix(IPC* ipc, IP* ip, IPC_IPV6_ROUTER_ADVERTISEMENT* matchedRA)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
IPC_IPV6_ROUTER_ADVERTISEMENT* matchingRA = NULL;
|
||||||
|
bool isInPrefix = false;
|
||||||
|
for (i = 0; i < LIST_NUM(ipc->IPv6RouterAdvs); i++)
|
||||||
|
{
|
||||||
|
IPC_IPV6_ROUTER_ADVERTISEMENT* ra = LIST_DATA(ipc->IPv6RouterAdvs, i);
|
||||||
|
isInPrefix = IsInSameNetwork6(ip, &ra->RoutedPrefix, &ra->RoutedMask);
|
||||||
|
if (isInPrefix)
|
||||||
|
{
|
||||||
|
matchingRA = ra;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchedRA != NULL && matchingRA != NULL)
|
||||||
|
{
|
||||||
|
Copy(matchedRA, matchingRA, sizeof(IPC_IPV6_ROUTER_ADVERTISEMENT));
|
||||||
|
}
|
||||||
|
|
||||||
|
return isInPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send router solicitation and then eventually populate the info from Router Advertisements
|
||||||
|
void IPCIPv6SendRouterSolicitation(IPC* ipc)
|
||||||
|
{
|
||||||
|
IP senderIP;
|
||||||
|
IP destIP;
|
||||||
|
UCHAR destMacAddress[6];
|
||||||
|
IPV6_ADDR linkLocal;
|
||||||
|
BUF *packet;
|
||||||
|
Zero(&linkLocal, sizeof(IPV6_ADDR));
|
||||||
|
|
||||||
|
// Generate link local from client's EUI
|
||||||
|
linkLocal.Value[0] = 0xFE;
|
||||||
|
linkLocal.Value[1] = 0x80;
|
||||||
|
WRITE_UINT64(&linkLocal.Value[8], &ipc->IPv6ClientEUI);
|
||||||
|
|
||||||
|
GetAllRouterMulticastAddress6(&destIP);
|
||||||
|
|
||||||
|
// Generate the MAC address from the multicast address
|
||||||
|
destMacAddress[0] = 0x33;
|
||||||
|
destMacAddress[1] = 0x33;
|
||||||
|
WRITE_UINT(&destMacAddress[2], &destIP.ipv6_addr[12]);
|
||||||
|
|
||||||
|
packet = BuildICMPv6RouterSoliciation(senderIP.ipv6_addr, destIP.ipv6_addr, ipc->MacAddress, 0);
|
||||||
|
|
||||||
|
while (LIST_NUM(ipc->IPv6RouterAdvs) == 0)
|
||||||
|
{
|
||||||
|
UINT64 giveup_time = Tick64() + (UINT64)(IPC_IPV6_RA_MAX_RETRIES * IPC_IPV6_RA_INTERVAL);
|
||||||
|
UINT64 timeout_retry = Tick() + (UINT64)IPC_IPV6_RA_INTERVAL;
|
||||||
|
IPCIPv6SendWithDestMacAddr(ipc, packet->Buf, packet->Size, destMacAddress);
|
||||||
|
|
||||||
|
AddInterrupt(ipc->Interrupt, timeout_retry);
|
||||||
|
|
||||||
|
if (Tick64() >= giveup_time)
|
||||||
|
{
|
||||||
|
// We failed to receive any router advertisements
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The processing should populate the received RAs by itself
|
||||||
|
IPCProcessL3Events(ipc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data flow
|
||||||
|
BLOCK* IPCIPv6Recv(IPC* ipc)
|
||||||
|
{
|
||||||
|
BLOCK* b;
|
||||||
|
// Validate arguments
|
||||||
|
if (ipc == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
b = GetNext(ipc->IPv6ReceivedQueue);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPCIPv6Send(IPC* ipc, void* data, UINT size)
|
||||||
|
{
|
||||||
|
IP destAddr;
|
||||||
|
UINT ipv6Type;
|
||||||
|
UCHAR destMac[6];
|
||||||
|
IPV6_HEADER* header = data;
|
||||||
|
|
||||||
|
IPv6AddrToIP(&destAddr, &header->DestAddress);
|
||||||
|
|
||||||
|
if (IsValidUnicastIPAddress6(&destAddr))
|
||||||
|
{
|
||||||
|
IPCIPv6SendUnicast(ipc, data, size, &destAddr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here we're probably dealing with a multicast packet. But let's check it anyway
|
||||||
|
ipv6Type = GetIPAddrType6(&destAddr);
|
||||||
|
if (ipv6Type & IPV6_ADDR_MULTICAST)
|
||||||
|
{
|
||||||
|
// Constructing multicast MAC address based on destination IP address, then just fire and forget
|
||||||
|
destMac[0] = 0x33;
|
||||||
|
destMac[1] = 0x33;
|
||||||
|
destMac[2] = destAddr.ipv6_addr[12];
|
||||||
|
destMac[3] = destAddr.ipv6_addr[13];
|
||||||
|
destMac[4] = destAddr.ipv6_addr[14];
|
||||||
|
destMac[5] = destAddr.ipv6_addr[15];
|
||||||
|
IPCIPv6SendWithDestMacAddr(ipc, data, size, destMac);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug("We got a weird packet with a weird type! %i\n", ipv6Type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPCIPv6SendWithDestMacAddr(IPC* ipc, void* data, UINT size, UCHAR* dest_mac_addr)
|
||||||
|
{
|
||||||
|
UCHAR tmp[1514];
|
||||||
|
// Validate arguments
|
||||||
|
if (ipc == NULL || data == NULL || size < 40 || size > 1500 || dest_mac_addr == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destination
|
||||||
|
Copy(tmp + 0, dest_mac_addr, 6);
|
||||||
|
|
||||||
|
// Source
|
||||||
|
Copy(tmp + 6, ipc->MacAddress, 6);
|
||||||
|
|
||||||
|
// Protocol number
|
||||||
|
WRITE_USHORT(tmp + 12, MAC_PROTO_IPV6);
|
||||||
|
|
||||||
|
// Data
|
||||||
|
Copy(tmp + 14, data, size);
|
||||||
|
|
||||||
|
// Send
|
||||||
|
IPCSendL2(ipc, tmp, size + 14);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IPCIPv6SendUnicast(IPC* ipc, void* data, UINT size, IP* next_ip)
|
||||||
|
{
|
||||||
|
IPC_ARP* ndtMatch;
|
||||||
|
UCHAR* destMac = NULL;
|
||||||
|
IPC_IPV6_ROUTER_ADVERTISEMENT ra;
|
||||||
|
IPV6_HEADER* header = data;
|
||||||
|
IP srcIp;
|
||||||
|
bool isLocal = false;
|
||||||
|
// First we need to understand if it is a local packet or we should route it through the router
|
||||||
|
UINT addrType = GetIPAddrType6(next_ip);
|
||||||
|
|
||||||
|
Zero(&ra, sizeof(IPC_IPV6_ROUTER_ADVERTISEMENT));
|
||||||
|
IPv6AddrToIP(&srcIp, &header->SrcAddress);
|
||||||
|
|
||||||
|
// Link local is always local =)
|
||||||
|
if (addrType & IPV6_ADDR_LOCAL_UNICAST)
|
||||||
|
{
|
||||||
|
isLocal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it matches any received prefix from router advertisements, it's also local
|
||||||
|
if (!isLocal && IPCIPv6CheckUnicastFromRouterPrefix(ipc, next_ip, &ra))
|
||||||
|
{
|
||||||
|
isLocal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it is a global packet, we need to get our source IP prefix to know through which router shall we route
|
||||||
|
if (!isLocal)
|
||||||
|
{
|
||||||
|
if (!IPCIPv6CheckUnicastFromRouterPrefix(ipc, &srcIp, &ra))
|
||||||
|
{
|
||||||
|
// If we didn't find a router for the source IP, let's just try to pick the first router and try to send to it
|
||||||
|
if (LIST_NUM(ipc->IPv6RouterAdvs) > 0)
|
||||||
|
{
|
||||||
|
Copy(&ra, LIST_DATA(ipc->IPv6RouterAdvs, 0), sizeof(IPC_IPV6_ROUTER_ADVERTISEMENT));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHAR tmp[MAX_SIZE];
|
||||||
|
IPToStr6(tmp, MAX_SIZE, &srcIp);
|
||||||
|
Debug("We couldn't find a router for the source address of %s! Trying as local.\n", tmp);
|
||||||
|
isLocal = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
destMac = ra.RouterMacAddress;
|
||||||
|
if (!IsMacUnicast(destMac) && !IsMacInvalid(ra.RouterMacAddress))
|
||||||
|
{
|
||||||
|
destMac = ra.RouterLinkLayerAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it is local it should be routed directly through the NDT
|
||||||
|
if (isLocal)
|
||||||
|
{
|
||||||
|
ndtMatch = IPCSearchArpTable(ipc->IPv6NeighborTable, next_ip);
|
||||||
|
if (ndtMatch == NULL)
|
||||||
|
{
|
||||||
|
// Creating a non-matched NDT entry
|
||||||
|
ndtMatch = IPCNewARP(next_ip, NULL);
|
||||||
|
Add(ipc->IPv6NeighborTable, ndtMatch);
|
||||||
|
}
|
||||||
|
if (ndtMatch->Resolved != true)
|
||||||
|
{
|
||||||
|
/// TODO: check if we need to manage NDT manually from here or the client will
|
||||||
|
/// TODO: send Neighbor Solicitations by itself and we just proxy them
|
||||||
|
CHAR tmp[MAX_SIZE];
|
||||||
|
BLOCK* blk = NewBlock(data, size, 0);
|
||||||
|
InsertQueue(ndtMatch->PacketQueue, blk);
|
||||||
|
IPToStr6(tmp, MAX_SIZE, next_ip);
|
||||||
|
Debug("We can't send the packet because we don't have IP %s in NDT! Need to send Neighbor Solicitation first... Saving for later send.\n", tmp);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
destMac = ndtMatch->MacAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destMac != NULL && !IsMacInvalid(destMac))
|
||||||
|
{
|
||||||
|
IPCIPv6SendWithDestMacAddr(ipc, data, size, destMac);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHAR tmp[MAX_SIZE];
|
||||||
|
IPToStr6(tmp, MAX_SIZE, next_ip);
|
||||||
|
Debug("We couldn't deduce the MAC address for unicast address %s, packet dropped.\n", tmp);
|
||||||
|
/// TODO: think about sending to the all routers broadcast MAC as a last resort
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -24,6 +24,12 @@
|
|||||||
#define IPC_LAYER_2 2
|
#define IPC_LAYER_2 2
|
||||||
#define IPC_LAYER_3 3
|
#define IPC_LAYER_3 3
|
||||||
|
|
||||||
|
// IPv6 constants
|
||||||
|
#define IPC_IPV6_NDT_LIFETIME (30 * 1000) // as per REACHABLE_TIME constant of RFC4861
|
||||||
|
#define IPC_IPV6_NDT_GIVEUPTIME (3 * 1000) // as per MAX_MULTICAST_SOLICIT * RETRANS_TIMER constants of RFC4861
|
||||||
|
#define IPC_IPV6_RA_INTERVAL (4 * 1000) // as per RTR_SOLICITATION_INTERVAL constant of RFC4861
|
||||||
|
#define IPC_IPV6_RA_MAX_RETRIES 3 // as per MAX_RTR_SOLICITATIONS constant of RFC4861
|
||||||
|
|
||||||
// ARP table entry
|
// ARP table entry
|
||||||
struct IPC_ARP
|
struct IPC_ARP
|
||||||
{
|
{
|
||||||
@ -117,6 +123,13 @@ struct IPC
|
|||||||
SHARED_BUFFER *IpcSessionSharedBuffer; // A shared buffer between IPC and Session
|
SHARED_BUFFER *IpcSessionSharedBuffer; // A shared buffer between IPC and Session
|
||||||
IPC_SESSION_SHARED_BUFFER_DATA *IpcSessionShared; // Shared data between IPC and Session
|
IPC_SESSION_SHARED_BUFFER_DATA *IpcSessionShared; // Shared data between IPC and Session
|
||||||
UINT Layer;
|
UINT Layer;
|
||||||
|
|
||||||
|
// IPv6 stuff
|
||||||
|
QUEUE* IPv6ReceivedQueue; // IPv6 reception queue
|
||||||
|
LIST* IPv6NeighborTable; // Neighbor Discovery Table
|
||||||
|
LIST* IPv6RouterAdvs; // Router offered prefixes
|
||||||
|
UINT64 IPv6ClientEUI; // The EUI of the client (for the SLAAC autoconf)
|
||||||
|
UINT64 IPv6ServerEUI; // The EUI of the server (from the RA discovery)
|
||||||
};
|
};
|
||||||
|
|
||||||
// MS-CHAPv2 authentication information
|
// MS-CHAPv2 authentication information
|
||||||
@ -129,6 +142,15 @@ struct IPC_MSCHAP_V2_AUTHINFO
|
|||||||
EAP_CLIENT *MsChapV2_EapClient; // EAP client
|
EAP_CLIENT *MsChapV2_EapClient; // EAP client
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct IPC_IPV6_ROUTER_ADVERTISEMENT
|
||||||
|
{
|
||||||
|
IP RoutedPrefix;
|
||||||
|
IP RoutedMask;
|
||||||
|
IP RouterAddress;
|
||||||
|
UCHAR RouterMacAddress[6];
|
||||||
|
UCHAR RouterLinkLayerAddress[6];
|
||||||
|
};
|
||||||
|
|
||||||
IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char *username, char *password,
|
IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char *username, char *password,
|
||||||
UINT *error_code, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port,
|
UINT *error_code, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port,
|
||||||
char *client_hostname, char *crypt_name,
|
char *client_hostname, char *crypt_name,
|
||||||
@ -151,15 +173,15 @@ IPC_ARP *IPCNewARP(IP *ip, UCHAR *mac_address);
|
|||||||
void IPCFreeARP(IPC_ARP *a);
|
void IPCFreeARP(IPC_ARP *a);
|
||||||
int IPCCmpArpTable(void *p1, void *p2);
|
int IPCCmpArpTable(void *p1, void *p2);
|
||||||
void IPCSendIPv4Unicast(IPC *ipc, void *data, UINT size, IP *next_ip);
|
void IPCSendIPv4Unicast(IPC *ipc, void *data, UINT size, IP *next_ip);
|
||||||
IPC_ARP *IPCSearchArpTable(IPC *ipc, IP *ip);
|
IPC_ARP *IPCSearchArpTable(LIST* arpTable, IP *ip);
|
||||||
void IPCSendIPv4WithDestMacAddr(IPC *ipc, void *data, UINT size, UCHAR *dest_mac_addr);
|
void IPCSendIPv4WithDestMacAddr(IPC *ipc, void *data, UINT size, UCHAR *dest_mac_addr);
|
||||||
void IPCFlushArpTable(IPC *ipc);
|
void IPCFlushArpTable(IPC *ipc);
|
||||||
void IPCFlushArpTableEx(IPC *ipc, UINT64 now);
|
void IPCFlushArpTableEx(IPC *ipc, UINT64 now);
|
||||||
void IPCProcessArp(IPC *ipc, BLOCK *b);
|
void IPCProcessArp(IPC *ipc, BLOCK *b);
|
||||||
void IPCAssociateOnArpTable(IPC *ipc, IP *ip, UCHAR *mac_address);
|
void IPCAssociateOnArpTable(IPC *ipc, IP *ip, UCHAR *mac_address);
|
||||||
bool IsValidUnicastMacAddress(UCHAR *mac);
|
|
||||||
bool IsValidUnicastIPAddress4(IP *ip);
|
|
||||||
bool IsValidUnicastIPAddressUINT4(UINT ip);
|
|
||||||
DHCPV4_DATA *IPCSendDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION_LIST *opt, UINT expecting_code, UINT timeout, TUBE *discon_poll_tube);
|
DHCPV4_DATA *IPCSendDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION_LIST *opt, UINT expecting_code, UINT timeout, TUBE *discon_poll_tube);
|
||||||
BUF *IPCBuildDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION_LIST *opt);
|
BUF *IPCBuildDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION_LIST *opt);
|
||||||
BUF *IPCBuildDhcpRequestOptions(IPC *ipc, DHCP_OPTION_LIST *opt);
|
BUF *IPCBuildDhcpRequestOptions(IPC *ipc, DHCP_OPTION_LIST *opt);
|
||||||
@ -171,6 +193,25 @@ IPC_ASYNC *NewIPCAsync(CEDAR *cedar, IPC_PARAM *param, SOCK_EVENT *sock_event);
|
|||||||
void IPCAsyncThreadProc(THREAD *thread, void *param);
|
void IPCAsyncThreadProc(THREAD *thread, void *param);
|
||||||
void FreeIPCAsync(IPC_ASYNC *a);
|
void FreeIPCAsync(IPC_ASYNC *a);
|
||||||
|
|
||||||
|
// IPv6 stuff
|
||||||
|
// Memory management
|
||||||
|
void IPCIPv6Init(IPC* ipc);
|
||||||
|
void IPCIPv6Free(IPC* ipc);
|
||||||
|
// NDT
|
||||||
|
void IPCIPv6AssociateOnNDT(IPC* ipc, IP* ip, UCHAR* mac_address);
|
||||||
|
void IPCIPv6AssociateOnNDTEx(IPC* ipc, IP* ip, UCHAR* mac_address, bool isNeighborAdv);
|
||||||
|
void IPCIPv6FlushNDT(IPC* ipc);
|
||||||
|
void IPCIPv6FlushNDTEx(IPC* ipc, UINT64 now);
|
||||||
|
// RA
|
||||||
|
void IPCIPv6AddRouterPrefix(IPC* ipc, ICMPV6_OPTION_LIST* recvPrefix, UCHAR* macAddress, IP* ip);
|
||||||
|
bool IPCIPv6CheckUnicastFromRouterPrefix(IPC* ipc, IP* ip, IPC_IPV6_ROUTER_ADVERTISEMENT* matchedRA);
|
||||||
|
void IPCIPv6SendRouterSolicitation(IPC* ipc);
|
||||||
|
// Data flow
|
||||||
|
BLOCK* IPCIPv6Recv(IPC* ipc);
|
||||||
|
void IPCIPv6Send(IPC* ipc, void* data, UINT size);
|
||||||
|
void IPCIPv6SendWithDestMacAddr(IPC* ipc, void* data, UINT size, UCHAR* dest_mac_addr);
|
||||||
|
void IPCIPv6SendUnicast(IPC* ipc, void* data, UINT size, IP* next_ip);
|
||||||
|
|
||||||
bool ParseAndExtractMsChapV2InfoFromPassword(IPC_MSCHAP_V2_AUTHINFO *d, char *password);
|
bool ParseAndExtractMsChapV2InfoFromPassword(IPC_MSCHAP_V2_AUTHINFO *d, char *password);
|
||||||
|
|
||||||
#endif // IPC_H
|
#endif // IPC_H
|
||||||
|
@ -8220,46 +8220,6 @@ void FreeArpWaitTable(VH *v)
|
|||||||
ReleaseList(v->ArpWaitTable);
|
ReleaseList(v->ArpWaitTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether the MAC address is valid
|
|
||||||
bool IsMacInvalid(UCHAR *mac)
|
|
||||||
{
|
|
||||||
UINT i;
|
|
||||||
// Validate arguments
|
|
||||||
if (mac == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0;i < 6;i++)
|
|
||||||
{
|
|
||||||
if (mac[i] != 0x00)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether the MAC address is a broadcast address
|
|
||||||
bool IsMacBroadcast(UCHAR *mac)
|
|
||||||
{
|
|
||||||
UINT i;
|
|
||||||
// Validate arguments
|
|
||||||
if (mac == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0;i < 6;i++)
|
|
||||||
{
|
|
||||||
if (mac[i] != 0xff)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert an entry in the ARP table
|
// Insert an entry in the ARP table
|
||||||
void InsertArpTable(VH *v, UCHAR *mac, UINT ip)
|
void InsertArpTable(VH *v, UCHAR *mac, UINT ip)
|
||||||
{
|
{
|
||||||
|
@ -409,8 +409,6 @@ ARP_ENTRY *SearchArpTable(VH *v, UINT ip);
|
|||||||
void RefreshArpTable(VH *v);
|
void RefreshArpTable(VH *v);
|
||||||
void PollingArpTable(VH *v);
|
void PollingArpTable(VH *v);
|
||||||
void InsertArpTable(VH *v, UCHAR *mac, UINT ip);
|
void InsertArpTable(VH *v, UCHAR *mac, UINT ip);
|
||||||
bool IsMacBroadcast(UCHAR *mac);
|
|
||||||
bool IsMacInvalid(UCHAR *mac);
|
|
||||||
void InitArpWaitTable(VH *v);
|
void InitArpWaitTable(VH *v);
|
||||||
void FreeArpWaitTable(VH *v);
|
void FreeArpWaitTable(VH *v);
|
||||||
int CompareArpWaitTable(void *p1, void *p2);
|
int CompareArpWaitTable(void *p1, void *p2);
|
||||||
|
@ -7375,6 +7375,175 @@ void CopyIP(IP *dst, IP *src)
|
|||||||
Copy(dst, src, sizeof(IP));
|
Copy(dst, src, sizeof(IP));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Utility functions about IP and MAC address types
|
||||||
|
// Identify whether the IP address is a normal unicast address
|
||||||
|
bool IsValidUnicastIPAddress4(IP* ip)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
// Validate arguments
|
||||||
|
if (IsIP4(ip) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsZeroIP(ip))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ip->addr[0] >= 224 && ip->addr[0] <= 239)
|
||||||
|
{
|
||||||
|
// IPv4 Multicast
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// TODO: this is kinda incorrect, but for the correct parsing we need the netmask anyway
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (ip->addr[i] != 255)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool IsValidUnicastIPAddressUINT4(UINT ip)
|
||||||
|
{
|
||||||
|
IP a;
|
||||||
|
|
||||||
|
UINTToIP(&a, ip);
|
||||||
|
|
||||||
|
return IsValidUnicastIPAddress4(&a);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValidUnicastIPAddress6(IP* ip)
|
||||||
|
{
|
||||||
|
UINT ipv6Type;
|
||||||
|
|
||||||
|
if (!IsIP6(ip))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsZeroIP(ip))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipv6Type = GetIPAddrType6(ip);
|
||||||
|
|
||||||
|
if (!(ipv6Type & IPV6_ADDR_LOCAL_UNICAST) &&
|
||||||
|
!(ipv6Type & IPV6_ADDR_GLOBAL_UNICAST))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether the MAC address is valid
|
||||||
|
bool IsMacInvalid(UCHAR* mac)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
// Validate arguments
|
||||||
|
if (mac == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
if (mac[i] != 0x00)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether the MAC address is a broadcast address
|
||||||
|
bool IsMacBroadcast(UCHAR* mac)
|
||||||
|
{
|
||||||
|
UINT i;
|
||||||
|
// Validate arguments
|
||||||
|
if (mac == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
if (mac[i] != 0xff)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check wether the MAC address is an IPv4 multicast or an IPv6 multicast
|
||||||
|
bool IsMacMulticast(UCHAR* mac)
|
||||||
|
{
|
||||||
|
// Validate arguments
|
||||||
|
if (mac == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mac[0] == 0x01 &&
|
||||||
|
mac[1] == 0x00 &&
|
||||||
|
mac[2] == 0x5e)
|
||||||
|
{
|
||||||
|
// Multicast IPv4 and other IANA multicasts
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mac[0] == 0x01)
|
||||||
|
{
|
||||||
|
// That's not a really reserved for multicast range, but it seems like anything with 0x01 is used as multicast anyway
|
||||||
|
// Remove or specify if it causes problems
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mac[0] == 0x33 &&
|
||||||
|
mac[1] == 0x33)
|
||||||
|
{
|
||||||
|
// Multicast IPv6
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check wether the MAC address is a unicast one
|
||||||
|
bool IsMacUnicast(UCHAR* mac)
|
||||||
|
{
|
||||||
|
// Validate arguments
|
||||||
|
if (mac == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsMacInvalid(mac))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsMacBroadcast(mac))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsMacMulticast(mac))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the number of clients connected from the specified IP address
|
// Get the number of clients connected from the specified IP address
|
||||||
UINT GetNumIpClient(IP *ip)
|
UINT GetNumIpClient(IP *ip)
|
||||||
{
|
{
|
||||||
|
@ -1302,6 +1302,15 @@ void IPAnd4(IP *dst, IP *a, IP *b);
|
|||||||
bool IsInSameNetwork4(IP *a1, IP *a2, IP *subnet);
|
bool IsInSameNetwork4(IP *a1, IP *a2, IP *subnet);
|
||||||
bool IsInSameNetwork4Standard(IP *a1, IP *a2);
|
bool IsInSameNetwork4Standard(IP *a1, IP *a2);
|
||||||
|
|
||||||
|
// Utility functions about IP and MAC address types
|
||||||
|
bool IsValidUnicastIPAddress4(IP* ip);
|
||||||
|
bool IsValidUnicastIPAddressUINT4(UINT ip);
|
||||||
|
bool IsValidUnicastIPAddress6(IP* ip);
|
||||||
|
bool IsMacUnicast(UCHAR* mac);
|
||||||
|
bool IsMacBroadcast(UCHAR* mac);
|
||||||
|
bool IsMacMulticast(UCHAR* mac);
|
||||||
|
bool IsMacInvalid(UCHAR* mac);
|
||||||
|
|
||||||
bool ParseIpAndSubnetMask4(char *src, UINT *ip, UINT *mask);
|
bool ParseIpAndSubnetMask4(char *src, UINT *ip, UINT *mask);
|
||||||
bool ParseIpAndSubnetMask46(char *src, IP *ip, IP *mask);
|
bool ParseIpAndSubnetMask46(char *src, IP *ip, IP *mask);
|
||||||
bool ParseIpAndMask4(char *src, UINT *ip, UINT *mask);
|
bool ParseIpAndMask4(char *src, UINT *ip, UINT *mask);
|
||||||
|
@ -889,6 +889,44 @@ BUF *BuildICMPv6NeighborSoliciation(IPV6_ADDR *src_ip, IPV6_ADDR *target_ip, UCH
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BUF *BuildICMPv6RouterSoliciation(IPV6_ADDR* src_ip, IPV6_ADDR* target_ip, UCHAR* my_mac_address, UINT id)
|
||||||
|
{
|
||||||
|
ICMPV6_OPTION_LIST opt;
|
||||||
|
ICMPV6_OPTION_LINK_LAYER link;
|
||||||
|
ICMPV6_ROUTER_SOLICIATION_HEADER header;
|
||||||
|
BUF *b;
|
||||||
|
BUF *b2;
|
||||||
|
BUF *ret;
|
||||||
|
|
||||||
|
if (src_ip == NULL || target_ip == NULL || my_mac_address == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Zero(&link, sizeof(link));
|
||||||
|
Copy(link.Address, my_mac_address, 6);
|
||||||
|
|
||||||
|
Zero(&opt, sizeof(opt));
|
||||||
|
opt.SourceLinkLayer = &link;
|
||||||
|
|
||||||
|
b = BuildICMPv6Options(&opt);
|
||||||
|
|
||||||
|
Zero(&header, sizeof(header));
|
||||||
|
|
||||||
|
b2 = NewBuf();
|
||||||
|
|
||||||
|
WriteBuf(b2, &header, sizeof(header));
|
||||||
|
WriteBufBuf(b2, b);
|
||||||
|
|
||||||
|
ret = BuildICMPv6(src_ip, target_ip, 255,
|
||||||
|
ICMPV6_TYPE_ROUTER_SOLICIATION, 0, b2->Buf, b2->Size, id);
|
||||||
|
|
||||||
|
FreeBuf(b);
|
||||||
|
FreeBuf(b2);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the next header number from the queue
|
// Get the next header number from the queue
|
||||||
UCHAR IPv6GetNextHeaderFromQueue(QUEUE *q)
|
UCHAR IPv6GetNextHeaderFromQueue(QUEUE *q)
|
||||||
{
|
{
|
||||||
@ -1452,6 +1490,12 @@ PKT *ClonePacket(PKT *p, bool copy_data)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse the packet but without data layer except for ICMP
|
||||||
|
PKT* ParsePacketUpToICMPv6(UCHAR* buf, UINT size)
|
||||||
|
{
|
||||||
|
return ParsePacketEx5(buf, size, false, 0, true, true, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the contents of the packet
|
// Parse the contents of the packet
|
||||||
PKT *ParsePacket(UCHAR *buf, UINT size)
|
PKT *ParsePacket(UCHAR *buf, UINT size)
|
||||||
{
|
{
|
||||||
@ -1470,6 +1514,10 @@ PKT *ParsePacketEx3(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id, bool b
|
|||||||
return ParsePacketEx4(buf, size, no_l3, vlan_type_id, bridge_id_as_mac_address, false, false);
|
return ParsePacketEx4(buf, size, no_l3, vlan_type_id, bridge_id_as_mac_address, false, false);
|
||||||
}
|
}
|
||||||
PKT* ParsePacketEx4(UCHAR* buf, UINT size, bool no_l3, UINT vlan_type_id, bool bridge_id_as_mac_address, bool no_http, bool correct_checksum)
|
PKT* ParsePacketEx4(UCHAR* buf, UINT size, bool no_l3, UINT vlan_type_id, bool bridge_id_as_mac_address, bool no_http, bool correct_checksum)
|
||||||
|
{
|
||||||
|
return ParsePacketEx5(buf, size, no_l3, vlan_type_id, bridge_id_as_mac_address, no_http, correct_checksum, false);
|
||||||
|
}
|
||||||
|
PKT* ParsePacketEx5(UCHAR* buf, UINT size, bool no_l3, UINT vlan_type_id, bool bridge_id_as_mac_address, bool no_http, bool correct_checksum, bool no_l3_l4_except_icmpv6)
|
||||||
{
|
{
|
||||||
PKT *p;
|
PKT *p;
|
||||||
USHORT vlan_type_id_16;
|
USHORT vlan_type_id_16;
|
||||||
@ -1559,7 +1607,7 @@ PKT *ParsePacketEx4(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id, bool b
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Do parse
|
// Do parse
|
||||||
if (ParsePacketL2Ex(p, buf, size, no_l3) == false)
|
if (ParsePacketL2Ex(p, buf, size, no_l3, no_l3_l4_except_icmpv6) == false)
|
||||||
{
|
{
|
||||||
// Parsing failure
|
// Parsing failure
|
||||||
FreePacket(p);
|
FreePacket(p);
|
||||||
@ -1929,7 +1977,7 @@ HTTPLOG *ParseHttpAccessLog(PKT *pkt)
|
|||||||
|
|
||||||
|
|
||||||
// Layer-2 parsing
|
// Layer-2 parsing
|
||||||
bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3)
|
bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3, bool no_l3_l4_except_icmpv6)
|
||||||
{
|
{
|
||||||
UINT i;
|
UINT i;
|
||||||
bool b1, b2;
|
bool b1, b2;
|
||||||
@ -1994,7 +2042,7 @@ bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3)
|
|||||||
switch (type_id_16)
|
switch (type_id_16)
|
||||||
{
|
{
|
||||||
case MAC_PROTO_ARPV4: // ARPv4
|
case MAC_PROTO_ARPV4: // ARPv4
|
||||||
if (no_l3)
|
if (no_l3 || no_l3_l4_except_icmpv6)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2002,7 +2050,7 @@ bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3)
|
|||||||
return ParsePacketARPv4(p, buf, size);
|
return ParsePacketARPv4(p, buf, size);
|
||||||
|
|
||||||
case MAC_PROTO_IPV4: // IPv4
|
case MAC_PROTO_IPV4: // IPv4
|
||||||
if (no_l3)
|
if (no_l3 || no_l3_l4_except_icmpv6)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2015,7 +2063,7 @@ bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ParsePacketIPv6(p, buf, size);
|
return ParsePacketIPv6(p, buf, size, no_l3_l4_except_icmpv6);
|
||||||
|
|
||||||
default: // Unknown
|
default: // Unknown
|
||||||
if (type_id_16 == p->VlanTypeID)
|
if (type_id_16 == p->VlanTypeID)
|
||||||
@ -2538,7 +2586,7 @@ void CloneICMPv6Options(ICMPV6_OPTION_LIST *dst, ICMPV6_OPTION_LIST *src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IPv6 parsing
|
// IPv6 parsing
|
||||||
bool ParsePacketIPv6(PKT *p, UCHAR *buf, UINT size)
|
bool ParsePacketIPv6(PKT *p, UCHAR *buf, UINT size, bool no_l3_l4_except_icmpv6)
|
||||||
{
|
{
|
||||||
// Validate arguments
|
// Validate arguments
|
||||||
if (p == NULL || buf == NULL)
|
if (p == NULL || buf == NULL)
|
||||||
@ -2585,9 +2633,17 @@ bool ParsePacketIPv6(PKT *p, UCHAR *buf, UINT size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case IP_PROTO_TCP: // TCP
|
case IP_PROTO_TCP: // TCP
|
||||||
|
if (no_l3_l4_except_icmpv6)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return ParseTCP(p, buf, size);
|
return ParseTCP(p, buf, size);
|
||||||
|
|
||||||
case IP_PROTO_UDP: // UDP
|
case IP_PROTO_UDP: // UDP
|
||||||
|
if (no_l3_l4_except_icmpv6)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return ParseUDP(p, buf, size);
|
return ParseUDP(p, buf, size);
|
||||||
|
|
||||||
default: // Unknown
|
default: // Unknown
|
||||||
|
@ -745,6 +745,8 @@ PKT *ParsePacketEx(UCHAR *buf, UINT size, bool no_l3);
|
|||||||
PKT *ParsePacketEx2(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id);
|
PKT *ParsePacketEx2(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id);
|
||||||
PKT *ParsePacketEx3(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id, bool bridge_id_as_mac_address);
|
PKT *ParsePacketEx3(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id, bool bridge_id_as_mac_address);
|
||||||
PKT *ParsePacketEx4(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id, bool bridge_id_as_mac_address, bool no_http, bool correct_checksum);
|
PKT *ParsePacketEx4(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id, bool bridge_id_as_mac_address, bool no_http, bool correct_checksum);
|
||||||
|
PKT* ParsePacketEx5(UCHAR* buf, UINT size, bool no_l3, UINT vlan_type_id, bool bridge_id_as_mac_address, bool no_http, bool correct_checksum, bool no_l3_l4_except_icmpv6);
|
||||||
|
PKT* ParsePacketUpToICMPv6(UCHAR* buf, UINT size);
|
||||||
void FreePacket(PKT *p);
|
void FreePacket(PKT *p);
|
||||||
void FreePacketWithData(PKT *p);
|
void FreePacketWithData(PKT *p);
|
||||||
void FreePacketIPv4(PKT *p);
|
void FreePacketIPv4(PKT *p);
|
||||||
@ -754,7 +756,7 @@ void FreePacketUDPv4(PKT *p);
|
|||||||
void FreePacketTCPv4(PKT *p);
|
void FreePacketTCPv4(PKT *p);
|
||||||
void FreePacketICMPv4(PKT *p);
|
void FreePacketICMPv4(PKT *p);
|
||||||
void FreePacketDHCPv4(PKT *p);
|
void FreePacketDHCPv4(PKT *p);
|
||||||
bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3);
|
bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3, bool no_l3_l4_except_icmpv6);
|
||||||
bool ParsePacketARPv4(PKT *p, UCHAR *buf, UINT size);
|
bool ParsePacketARPv4(PKT *p, UCHAR *buf, UINT size);
|
||||||
bool ParsePacketIPv4(PKT *p, UCHAR *buf, UINT size);
|
bool ParsePacketIPv4(PKT *p, UCHAR *buf, UINT size);
|
||||||
bool ParsePacketBPDU(PKT *p, UCHAR *buf, UINT size);
|
bool ParsePacketBPDU(PKT *p, UCHAR *buf, UINT size);
|
||||||
@ -770,7 +772,7 @@ void FreeClonePacket(PKT *p);
|
|||||||
|
|
||||||
void CorrectChecksum(PKT *p);
|
void CorrectChecksum(PKT *p);
|
||||||
|
|
||||||
bool ParsePacketIPv6(PKT *p, UCHAR *buf, UINT size);
|
bool ParsePacketIPv6(PKT *p, UCHAR *buf, UINT size, bool no_l3_l4_except_icmpv6);
|
||||||
bool ParsePacketIPv6Header(IPV6_HEADER_PACKET_INFO *info, UCHAR *buf, UINT size);
|
bool ParsePacketIPv6Header(IPV6_HEADER_PACKET_INFO *info, UCHAR *buf, UINT size);
|
||||||
bool ParseIPv6ExtHeader(IPV6_HEADER_PACKET_INFO *info, UCHAR next_header, UCHAR *buf, UINT size);
|
bool ParseIPv6ExtHeader(IPV6_HEADER_PACKET_INFO *info, UCHAR next_header, UCHAR *buf, UINT size);
|
||||||
bool ParseICMPv6Options(ICMPV6_OPTION_LIST *o, UCHAR *buf, UINT size);
|
bool ParseICMPv6Options(ICMPV6_OPTION_LIST *o, UCHAR *buf, UINT size);
|
||||||
@ -786,6 +788,7 @@ BUF *BuildIPv6PacketHeader(IPV6_HEADER_PACKET_INFO *info, UINT *bytes_before_pay
|
|||||||
UCHAR IPv6GetNextHeaderFromQueue(QUEUE *q);
|
UCHAR IPv6GetNextHeaderFromQueue(QUEUE *q);
|
||||||
void BuildAndAddIPv6PacketOptionHeader(BUF *b, IPV6_OPTION_HEADER *opt, UCHAR next_header, UINT size);
|
void BuildAndAddIPv6PacketOptionHeader(BUF *b, IPV6_OPTION_HEADER *opt, UCHAR next_header, UINT size);
|
||||||
BUF *BuildICMPv6NeighborSoliciation(IPV6_ADDR *src_ip, IPV6_ADDR *target_ip, UCHAR *my_mac_address, UINT id);
|
BUF *BuildICMPv6NeighborSoliciation(IPV6_ADDR *src_ip, IPV6_ADDR *target_ip, UCHAR *my_mac_address, UINT id);
|
||||||
|
BUF *BuildICMPv6RouterSoliciation(IPV6_ADDR* src_ip, IPV6_ADDR* target_ip, UCHAR* my_mac_address, UINT id);
|
||||||
BUF *BuildICMPv6(IPV6_ADDR *src_ip, IPV6_ADDR *dest_ip, UCHAR hop_limit, UCHAR type, UCHAR code, void *data, UINT size, UINT id);
|
BUF *BuildICMPv6(IPV6_ADDR *src_ip, IPV6_ADDR *dest_ip, UCHAR hop_limit, UCHAR type, UCHAR code, void *data, UINT size, UINT id);
|
||||||
|
|
||||||
bool VLanRemoveTag(void **packet_data, UINT *packet_size, UINT vlan_id, UINT vlan_tpid);
|
bool VLanRemoveTag(void **packet_data, UINT *packet_size, UINT vlan_id, UINT vlan_tpid);
|
||||||
|
Loading…
Reference in New Issue
Block a user