mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-11-22 17:39:53 +03:00
Merge pull request #1125 from Evengard/ppp-ipv6
IPv6 support for the PPP stack
This commit is contained in:
commit
1a8e1385cf
@ -2589,13 +2589,13 @@ void EthPutPacketLinuxIpRaw(ETH *e, void *data, UINT size)
|
||||
|
||||
if (p->BroadcastPacket || Cmp(p->MacAddressDest, e->RawIpMyMacAddr, 6) == 0)
|
||||
{
|
||||
if (IsValidUnicastMacAddress(p->MacAddressSrc))
|
||||
if (IsMacUnicast(p->MacAddressSrc))
|
||||
{
|
||||
Copy(e->RawIpYourMacAddr, p->MacAddressSrc, 6);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsZero(e->RawIpYourMacAddr, 6) || IsValidUnicastMacAddress(p->MacAddressSrc) == false ||
|
||||
if (IsZero(e->RawIpYourMacAddr, 6) || IsMacUnicast(p->MacAddressSrc) == false ||
|
||||
(p->BroadcastPacket == false && Cmp(p->MacAddressDest, e->RawIpMyMacAddr, 6) != 0))
|
||||
{
|
||||
Free(data);
|
||||
|
@ -582,6 +582,8 @@ typedef struct IPC_PARAM IPC_PARAM;
|
||||
typedef struct IPC_DHCP_RELEASE_QUEUE IPC_DHCP_RELEASE_QUEUE;
|
||||
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_IPV6_ROUTER_ADVERTISEMENT IPC_IPV6_ROUTER_ADVERTISEMENT;
|
||||
typedef struct IPC_DHCPV4_AWAIT IPC_DHCPV4_AWAIT;
|
||||
|
||||
|
||||
// ==============================================================
|
||||
|
874
src/Cedar/IPC.c
874
src/Cedar/IPC.c
File diff suppressed because it is too large
Load Diff
@ -24,6 +24,22 @@
|
||||
#define IPC_LAYER_2 2
|
||||
#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 (2 * 1000) // Windows gets stuck if it is bigger
|
||||
#define IPC_IPV6_RA_MAX_RETRIES 2 // Windows seems to be stuck when it doesn't receive an answer in due time
|
||||
|
||||
// Protocol status
|
||||
#define IPC_PROTO_STATUS_CLOSED 0x0
|
||||
#define IPC_PROTO_STATUS_CONFIG 0x1
|
||||
#define IPC_PROTO_STATUS_CONFIG_WAIT 0x2
|
||||
#define IPC_PROTO_STATUS_OPENED 0x10
|
||||
#define IPC_PROTO_STATUS_REJECTED 0x100
|
||||
|
||||
#define IPC_PROTO_SET_STATUS(ipc, proto, value) ((ipc) != NULL ? ((ipc->proto) = (value)) : 0)
|
||||
#define IPC_PROTO_GET_STATUS(ipc, proto) ((ipc) != NULL ? (ipc->proto) : IPC_PROTO_STATUS_REJECTED)
|
||||
|
||||
// ARP table entry
|
||||
struct IPC_ARP
|
||||
{
|
||||
@ -72,6 +88,15 @@ struct IPC_PARAM
|
||||
UINT Layer;
|
||||
};
|
||||
|
||||
// DHCPv4 response awaiter
|
||||
struct IPC_DHCPV4_AWAIT
|
||||
{
|
||||
bool IsAwaiting;
|
||||
DHCPV4_DATA *DhcpData;
|
||||
UINT TransCode;
|
||||
UINT OpCode;
|
||||
};
|
||||
|
||||
// IPC_ASYNC object
|
||||
struct IPC_ASYNC
|
||||
{
|
||||
@ -111,12 +136,22 @@ struct IPC
|
||||
UCHAR Padding[2];
|
||||
LIST *ArpTable; // ARP table
|
||||
QUEUE *IPv4ReceivedQueue; // IPv4 reception queue
|
||||
UINT IPv4State;
|
||||
IPC_DHCPV4_AWAIT DHCPv4Awaiter;
|
||||
TUBE_FLUSH_LIST *FlushList; // Tube Flush List
|
||||
UCHAR MsChapV2_ServerResponse[20]; // Server response
|
||||
DHCP_CLASSLESS_ROUTE_TABLE ClasslessRoute; // Classless routing table
|
||||
SHARED_BUFFER *IpcSessionSharedBuffer; // A shared buffer between IPC and Session
|
||||
IPC_SESSION_SHARED_BUFFER_DATA *IpcSessionShared; // Shared data between IPC and Session
|
||||
UINT Layer;
|
||||
|
||||
// IPv6 stuff
|
||||
QUEUE *IPv6ReceivedQueue; // IPv6 reception queue
|
||||
UINT IPv6State;
|
||||
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
|
||||
@ -129,6 +164,15 @@ struct IPC_MSCHAP_V2_AUTHINFO
|
||||
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,
|
||||
UINT *error_code, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port,
|
||||
char *client_hostname, char *crypt_name,
|
||||
@ -144,6 +188,7 @@ void IPCSendIPv4(IPC *ipc, void *data, UINT size);
|
||||
BLOCK *IPCRecvL2(IPC *ipc);
|
||||
BLOCK *IPCRecvIPv4(IPC *ipc);
|
||||
void IPCProcessInterrupts(IPC *ipc);
|
||||
void IPCProcessL3EventsIPv4Only(IPC *ipc);
|
||||
void IPCProcessL3Events(IPC *ipc);
|
||||
void IPCProcessL3EventsEx(IPC *ipc, UINT64 now);
|
||||
bool IPCSetIPv4Parameters(IPC *ipc, IP *ip, IP *subnet, IP *gw, DHCP_CLASSLESS_ROUTE_TABLE *rt);
|
||||
@ -151,15 +196,15 @@ IPC_ARP *IPCNewARP(IP *ip, UCHAR *mac_address);
|
||||
void IPCFreeARP(IPC_ARP *a);
|
||||
int IPCCmpArpTable(void *p1, void *p2);
|
||||
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 IPCFlushArpTable(IPC *ipc);
|
||||
void IPCFlushArpTableEx(IPC *ipc, UINT64 now);
|
||||
void IPCProcessArp(IPC *ipc, BLOCK *b);
|
||||
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);
|
||||
BUF *IPCBuildDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION_LIST *opt);
|
||||
BUF *IPCBuildDhcpRequestOptions(IPC *ipc, DHCP_OPTION_LIST *opt);
|
||||
@ -171,6 +216,26 @@ IPC_ASYNC *NewIPCAsync(CEDAR *cedar, IPC_PARAM *param, SOCK_EVENT *sock_event);
|
||||
void IPCAsyncThreadProc(THREAD *thread, void *param);
|
||||
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);
|
||||
bool IPCIPv6CheckExistingLinkLocal(IPC *ipc, UINT64 eui);
|
||||
// RA
|
||||
void IPCIPv6AddRouterPrefixes(IPC *ipc, ICMPV6_OPTION_LIST *recvPrefix, UCHAR *macAddress, IP *ip);
|
||||
bool IPCIPv6CheckUnicastFromRouterPrefix(IPC *ipc, IP *ip, IPC_IPV6_ROUTER_ADVERTISEMENT *matchedRA);
|
||||
UINT64 IPCIPv6GetServerEui(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);
|
||||
|
||||
#endif // IPC_H
|
||||
|
@ -1284,6 +1284,7 @@ char *PacketLogParseProc(RECORD *rec)
|
||||
TOKEN_LIST *t;
|
||||
char tmp[MAX_SIZE];
|
||||
bool tcp_conn;
|
||||
UINT i;
|
||||
// Validate arguments
|
||||
if (rec == NULL)
|
||||
{
|
||||
@ -1686,14 +1687,21 @@ char *PacketLogParseProc(RECORD *rec)
|
||||
snprintf(tmp, sizeof(tmp), "TargetLinkLayer=%s ", tmp2);
|
||||
StrCat(info, sizeof(info), tmp);
|
||||
}
|
||||
if (ol->Prefix != NULL)
|
||||
for (i = 0; i < ICMPV6_OPTION_PREFIXES_MAX_COUNT; i++)
|
||||
{
|
||||
if (ol->Prefix[i] != NULL)
|
||||
{
|
||||
char tmp2[MAX_SIZE];
|
||||
IP6AddrToStr(tmp2, sizeof(tmp2), &ol->Prefix->Prefix);
|
||||
IP6AddrToStr(tmp2, sizeof(tmp2), &ol->Prefix[i]->Prefix);
|
||||
snprintf(tmp, sizeof(tmp), "Prefix=%s/%u PrefixFlag=0x%02X ", tmp2,
|
||||
ol->Prefix->SubnetLength, ol->Prefix->Flags);
|
||||
ol->Prefix[i]->SubnetLength, ol->Prefix[i]->Flags);
|
||||
StrCat(info, sizeof(info), tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ol->Mtu != NULL)
|
||||
{
|
||||
snprintf(tmp, sizeof(tmp), "Mtu=%u ", Endian32(ol->Mtu->Mtu));
|
||||
|
@ -2159,7 +2159,8 @@ void OvsFreeSession(OPENVPN_SESSION *se)
|
||||
UINTToIP(&dhcp_ip, se->IpcAsync->L3ClientAddressOption.ServerAddress);
|
||||
|
||||
IPCDhcpFreeIP(se->Ipc, &dhcp_ip);
|
||||
IPCProcessL3Events(se->Ipc);
|
||||
IPC_PROTO_SET_STATUS(se->Ipc, IPv6State, IPC_PROTO_STATUS_CLOSED);
|
||||
IPCProcessL3EventsIPv4Only(se->Ipc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2259,7 +2260,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
{
|
||||
if (se->Mode == OPENVPN_MODE_L3)
|
||||
{
|
||||
IPCProcessL3Events(se->Ipc);
|
||||
IPCProcessL3EventsIPv4Only(se->Ipc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2656,7 +2657,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
}
|
||||
}
|
||||
|
||||
IPCProcessL3Events(se->Ipc);
|
||||
IPCProcessL3EventsIPv4Only(se->Ipc);
|
||||
}
|
||||
|
||||
IPCProcessInterrupts(se->Ipc);
|
||||
|
@ -12,9 +12,6 @@ void PPPThread(THREAD *thread, void *param)
|
||||
{
|
||||
PPP_SESSION *p = (PPP_SESSION *)param;
|
||||
UINT i;
|
||||
PPP_LCP *c;
|
||||
USHORT us;
|
||||
UINT ui;
|
||||
USHORT next_protocol = 0;
|
||||
bool ret = false;
|
||||
char ipstr1[128], ipstr2[128];
|
||||
@ -32,8 +29,6 @@ void PPPThread(THREAD *thread, void *param)
|
||||
Debug("PPP Initialize");
|
||||
|
||||
PPPSetStatus(p, PPP_STATUS_CONNECTED);
|
||||
p->IPv4_State = PPP_PROTO_STATUS_CLOSED;
|
||||
p->IPv6_State = PPP_PROTO_STATUS_CLOSED;
|
||||
|
||||
p->Eap_Protocol = PPP_UNSPECIFIED;
|
||||
|
||||
@ -181,7 +176,8 @@ void PPPThread(THREAD *thread, void *param)
|
||||
{
|
||||
UINT64 nowL;
|
||||
// Here client to server
|
||||
if (p->CurrentPacket->Protocol == PPP_PROTOCOL_IP && p->IPv4_State == PPP_PROTO_STATUS_OPENED)
|
||||
if (p->CurrentPacket->Protocol == PPP_PROTOCOL_IP &&
|
||||
IPC_PROTO_GET_STATUS(p->Ipc, IPv4State) == IPC_PROTO_STATUS_OPENED)
|
||||
{
|
||||
receivedPacketProcessed = true;
|
||||
IPCSendIPv4(p->Ipc, p->CurrentPacket->Data, p->CurrentPacket->DataSize);
|
||||
@ -190,10 +186,11 @@ void PPPThread(THREAD *thread, void *param)
|
||||
{
|
||||
Debug("Got IPv4 packet before IPv4 ready!\n");
|
||||
}
|
||||
else if (p->CurrentPacket->Protocol == PPP_PROTOCOL_IPV6 && p->IPv6_State == PPP_PROTO_STATUS_OPENED)
|
||||
else if (p->CurrentPacket->Protocol == PPP_PROTOCOL_IPV6 &&
|
||||
IPC_PROTO_GET_STATUS(p->Ipc, IPv6State) == IPC_PROTO_STATUS_OPENED)
|
||||
{
|
||||
receivedPacketProcessed = true;
|
||||
Debug("IPv6 to be implemented\n");
|
||||
IPCIPv6Send(p->Ipc, p->CurrentPacket->Data, p->CurrentPacket->DataSize);
|
||||
}
|
||||
else if (p->CurrentPacket->Protocol == PPP_PROTOCOL_IPV6)
|
||||
{
|
||||
@ -318,6 +315,8 @@ void PPPThread(THREAD *thread, void *param)
|
||||
if (p->PPPStatus == PPP_STATUS_NETWORK_LAYER)
|
||||
{
|
||||
UINT64 timeBeforeLoop;
|
||||
if (IPC_PROTO_GET_STATUS(p->Ipc, IPv4State) == IPC_PROTO_STATUS_OPENED)
|
||||
{
|
||||
if (p->DhcpAllocated)
|
||||
{
|
||||
if (now >= p->DhcpNextRenewTime)
|
||||
@ -332,6 +331,7 @@ void PPPThread(THREAD *thread, void *param)
|
||||
IPCDhcpRenewIP(p->Ipc, &ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IPCProcessL3Events(p->Ipc);
|
||||
|
||||
@ -340,13 +340,19 @@ void PPPThread(THREAD *thread, void *param)
|
||||
while (true)
|
||||
{
|
||||
UINT64 nowL;
|
||||
bool no4packets = false;
|
||||
bool no6packets = false;
|
||||
if (IPC_PROTO_GET_STATUS(p->Ipc, IPv4State) == IPC_PROTO_STATUS_OPENED)
|
||||
{
|
||||
BLOCK *b = IPCRecvIPv4(p->Ipc);
|
||||
PPP_PACKET *pp;
|
||||
PPP_PACKET tmp;
|
||||
if (b == NULL)
|
||||
{
|
||||
break;
|
||||
no4packets = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
PPP_PACKET *pp;
|
||||
PPP_PACKET tmp;
|
||||
|
||||
// Since receiving the IP packet, send it to the client by PPP
|
||||
pp = &tmp;
|
||||
@ -359,11 +365,48 @@ void PPPThread(THREAD *thread, void *param)
|
||||
PPPSendPacketEx(p, pp, true);
|
||||
|
||||
FreePPPPacketEx(pp, true);
|
||||
Free(b);
|
||||
Free(b); // Not FreeBlock because freed in FreePPPPacketEx
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
no4packets = true;
|
||||
}
|
||||
|
||||
if (IPC_PROTO_GET_STATUS(p->Ipc, IPv6State) == IPC_PROTO_STATUS_OPENED)
|
||||
{
|
||||
BLOCK *b = IPCIPv6Recv(p->Ipc);
|
||||
if (b == NULL)
|
||||
{
|
||||
no6packets = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
PPP_PACKET *pp;
|
||||
PPP_PACKET tmp;
|
||||
|
||||
// Since receiving the IP packet, send it to the client by PPP
|
||||
pp = &tmp;
|
||||
pp->IsControl = false;
|
||||
pp->Protocol = PPP_PROTOCOL_IPV6;
|
||||
pp->Lcp = NULL;
|
||||
pp->Data = b->Buf;
|
||||
pp->DataSize = b->Size;
|
||||
|
||||
PPPSendPacketEx(p, pp, true);
|
||||
|
||||
FreePPPPacketEx(pp, true);
|
||||
Free(b); // Not FreeBlock because freed in FreePPPPacketEx
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
no6packets = true;
|
||||
}
|
||||
|
||||
// Let's break out of the loop once in a while so we don't get stuck here endlessly
|
||||
nowL = Tick64();
|
||||
if (nowL > timeBeforeLoop + PPP_PACKET_RESEND_INTERVAL)
|
||||
if (nowL > timeBeforeLoop + PPP_PACKET_RESEND_INTERVAL || (no4packets && no6packets))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@ -743,7 +786,7 @@ bool PPPProcessResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req)
|
||||
return PPPProcessIPCPResponsePacket(p, pp, req);
|
||||
break;
|
||||
case PPP_PROTOCOL_IPV6CP:
|
||||
Debug("IPv6CP to be implemented\n");
|
||||
return PPPProcessIPv6CPResponsePacket(p, pp, req);
|
||||
break;
|
||||
case PPP_PROTOCOL_EAP:
|
||||
return PPPProcessEAPResponsePacket(p, pp, req);
|
||||
@ -786,11 +829,11 @@ bool PPPProcessLCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req
|
||||
USHORT *protocol = pp->Lcp->Data;
|
||||
if (*protocol == PPP_PROTOCOL_IPCP || *protocol == PPP_PROTOCOL_IP)
|
||||
{
|
||||
p->IPv4_State = PPP_PROTO_STATUS_REJECTED;
|
||||
IPC_PROTO_SET_STATUS(p->Ipc, IPv4State, IPC_PROTO_STATUS_REJECTED);
|
||||
}
|
||||
if (*protocol == PPP_PROTOCOL_IPV6CP || *protocol == PPP_PROTOCOL_IPV6)
|
||||
{
|
||||
p->IPv6_State = PPP_PROTO_STATUS_REJECTED;
|
||||
IPC_PROTO_SET_STATUS(p->Ipc, IPv6State, IPC_PROTO_STATUS_REJECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1082,7 +1125,7 @@ bool PPPProcessIPCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *re
|
||||
if (!PPPGetIPAddressValueFromLCP(pp->Lcp, PPP_IPCP_OPTION_IP, &addrStruct) || pp->Lcp->Code == PPP_LCP_CODE_REJECT || pp->Lcp->Code == PPP_LCP_CODE_CODE_REJECT)
|
||||
{
|
||||
Debug("Unsupported IPCP protocol");
|
||||
p->IPv4_State = PPP_PROTO_STATUS_REJECTED;
|
||||
IPC_PROTO_SET_STATUS(p->Ipc, IPv4State, IPC_PROTO_STATUS_REJECTED);
|
||||
PPPRejectUnsupportedPacketEx(p, pp, true);
|
||||
return false;
|
||||
}
|
||||
@ -1096,14 +1139,14 @@ bool PPPProcessIPCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *re
|
||||
Debug("Accepted server IP address of %s\n", addrStr);
|
||||
|
||||
// We already configured client address, now server address is also confirmed, ready for IPv4 data flow
|
||||
if (p->IPv4_State == PPP_PROTO_STATUS_CONFIG)
|
||||
if (IPC_PROTO_GET_STATUS(p->Ipc, IPv4State) == IPC_PROTO_STATUS_CONFIG)
|
||||
{
|
||||
p->IPv4_State = PPP_PROTO_STATUS_CONFIG_WAIT;
|
||||
IPC_PROTO_SET_STATUS(p->Ipc, IPv4State, IPC_PROTO_STATUS_CONFIG_WAIT);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
p->IPv4_State = PPP_PROTO_STATUS_CONFIG;
|
||||
IPC_PROTO_SET_STATUS(p->Ipc, IPv4State, IPC_PROTO_STATUS_CONFIG);
|
||||
|
||||
PPPGetIPAddressValueFromLCP(req->Lcp, PPP_IPCP_OPTION_IP, &prevAddrStruct);
|
||||
prevAddr = IPToUINT(&prevAddrStruct);
|
||||
@ -1115,7 +1158,7 @@ bool PPPProcessIPCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *re
|
||||
if (prevAddr == Endian32(0xc0000008))
|
||||
{
|
||||
Debug("We already tried the fallback IP of 192.0.0.8, giving up\n");
|
||||
p->IPv4_State = PPP_PROTO_STATUS_REJECTED;
|
||||
IPC_PROTO_SET_STATUS(p->Ipc, IPv4State, IPC_PROTO_STATUS_REJECTED);
|
||||
PPPRejectUnsupportedPacketEx(p, pp, true);
|
||||
return false;
|
||||
}
|
||||
@ -1205,6 +1248,31 @@ bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req
|
||||
return false;
|
||||
}
|
||||
|
||||
// Process IPv6CP responses
|
||||
bool PPPProcessIPv6CPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req)
|
||||
{
|
||||
bool isAccepted = !PPP_LCP_CODE_IS_NEGATIVE(pp->Lcp->Code);
|
||||
|
||||
// If we got a reject or a NACK, we just reject the whole IPv6 configuration, there is no way we can recover even from a NACK as we can't change the link-local address of an already existing router
|
||||
if (!isAccepted)
|
||||
{
|
||||
Debug("Unsupported IPv6CP protocol");
|
||||
IPC_PROTO_SET_STATUS(p->Ipc, IPv6State, IPC_PROTO_STATUS_REJECTED);
|
||||
PPPRejectUnsupportedPacketEx(p, pp, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IPC_PROTO_GET_STATUS(p->Ipc, IPv6State) != IPC_PROTO_STATUS_CONFIG)
|
||||
{
|
||||
Debug("We got an early IPv6CP response, ignoring for now...\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug("Accepted server IPv6CP handshake\n");
|
||||
IPC_PROTO_SET_STATUS(p->Ipc, IPv6State, IPC_PROTO_STATUS_CONFIG_WAIT);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Processes request packets
|
||||
bool PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *pp)
|
||||
@ -1227,8 +1295,7 @@ bool PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *pp)
|
||||
return PPPProcessIPCPRequestPacket(p, pp);
|
||||
break;
|
||||
case PPP_PROTOCOL_IPV6CP:
|
||||
PPPRejectUnsupportedPacketEx(p, pp, true);
|
||||
Debug("IPv6CP to be implemented\n");
|
||||
return PPPProcessIPv6CPRequestPacket(p, pp);
|
||||
break;
|
||||
case PPP_PROTOCOL_EAP:
|
||||
return PPPProcessEAPRequestPacket(p, pp);
|
||||
@ -1547,9 +1614,8 @@ bool PPPProcessIPCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp)
|
||||
bool ok = true;
|
||||
bool processed = false;
|
||||
bool isEmptyIpAddress = false;
|
||||
PPP_LCP *c;
|
||||
|
||||
if (p->IPv4_State == PPP_PROTO_STATUS_REJECTED)
|
||||
if (IPC_PROTO_GET_STATUS(p->Ipc, IPv4State) == IPC_PROTO_STATUS_REJECTED)
|
||||
{
|
||||
Debug("We got an IPCP packet after we had it rejected\n");
|
||||
return PPPRejectUnsupportedPacketEx(p, pp, true);
|
||||
@ -1823,7 +1889,7 @@ bool PPPProcessIPCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp)
|
||||
|
||||
// We will delay this packet ACK and send the server IP first, then wait for a reparse
|
||||
// it is kind of dirty but fixes issues on some clients (namely VPN Client Pro on Android)
|
||||
if (p->IPv4_State == PPP_PROTO_STATUS_CLOSED && p->ClientAddressOption.ServerAddress != 0 && ok)
|
||||
if (IPC_PROTO_GET_STATUS(p->Ipc, IPv4State) == IPC_PROTO_STATUS_CLOSED && p->ClientAddressOption.ServerAddress != 0 && ok)
|
||||
{
|
||||
PPP_LCP *c = NewPPPLCP(PPP_LCP_CODE_REQ, 0);
|
||||
UINT ui = p->ClientAddressOption.ServerAddress;
|
||||
@ -1834,7 +1900,7 @@ bool PPPProcessIPCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp)
|
||||
WHERE;
|
||||
return false;
|
||||
}
|
||||
p->IPv4_State = PPP_PROTO_STATUS_CONFIG;
|
||||
IPC_PROTO_SET_STATUS(p->Ipc, IPv4State, IPC_PROTO_STATUS_CONFIG);
|
||||
if (!processed)
|
||||
{
|
||||
PPPAddNextPacket(p, pp, 1);
|
||||
@ -1843,7 +1909,8 @@ bool PPPProcessIPCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp)
|
||||
}
|
||||
|
||||
// We still haven't received any answer from client about server IP, keep waiting...
|
||||
if ((p->IPv4_State == PPP_PROTO_STATUS_CONFIG || p->IPv4_State == PPP_PROTO_STATUS_CLOSED) && !processed)
|
||||
if ((IPC_PROTO_GET_STATUS(p->Ipc, IPv4State) == IPC_PROTO_STATUS_CONFIG ||
|
||||
IPC_PROTO_GET_STATUS(p->Ipc, IPv4State) == IPC_PROTO_STATUS_CLOSED) && !processed)
|
||||
{
|
||||
PPPAddNextPacket(p, pp, 1);
|
||||
return false;
|
||||
@ -1856,9 +1923,9 @@ bool PPPProcessIPCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp)
|
||||
}
|
||||
Debug("ACKed IPCP options ID = 0x%x\n", pp->Lcp->Id);
|
||||
|
||||
if (ok && p->IPv4_State == PPP_PROTO_STATUS_CONFIG_WAIT)
|
||||
if (ok && IPC_PROTO_GET_STATUS(p->Ipc, IPv4State) == IPC_PROTO_STATUS_CONFIG_WAIT)
|
||||
{
|
||||
p->IPv4_State = PPP_PROTO_STATUS_OPENED;
|
||||
IPC_PROTO_SET_STATUS(p->Ipc, IPv4State, IPC_PROTO_STATUS_OPENED);
|
||||
Debug("IPv4 OPENED\n");
|
||||
}
|
||||
return ok;
|
||||
@ -1871,6 +1938,116 @@ bool PPPProcessEAPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Process IPv6CP request packets
|
||||
bool PPPProcessIPv6CPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp)
|
||||
{
|
||||
UINT i;
|
||||
bool processed = false;
|
||||
if (IPC_PROTO_GET_STATUS(p->Ipc, IPv6State) == IPC_PROTO_STATUS_REJECTED)
|
||||
{
|
||||
Debug("We got an IPv6CP packet after we had it rejected\n");
|
||||
return PPPRejectUnsupportedPacketEx(p, pp, true);
|
||||
}
|
||||
|
||||
for (i = 0; i < LIST_NUM(pp->Lcp->OptionList); i++)
|
||||
{
|
||||
PPP_OPTION *t = LIST_DATA(pp->Lcp->OptionList, i);
|
||||
|
||||
switch (t->Type)
|
||||
{
|
||||
case PPP_IPV6CP_OPTION_EUI:
|
||||
t->IsSupported = true;
|
||||
if (t->DataSize == sizeof(UINT64))
|
||||
{
|
||||
UINT64 newValue = 0;
|
||||
UINT64 value = READ_UINT64(t->Data);
|
||||
if (value != 0 && !IPCIPv6CheckExistingLinkLocal(p->Ipc, value))
|
||||
{
|
||||
t->IsAccepted = true;
|
||||
p->Ipc->IPv6ClientEUI = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
t->IsAccepted = false;
|
||||
GenerateEui64Address6((UCHAR *)&newValue, p->Ipc->MacAddress);
|
||||
if (newValue != value && !IPCIPv6CheckExistingLinkLocal(p->Ipc, newValue))
|
||||
{
|
||||
WRITE_UINT64(t->AltData, newValue);
|
||||
t->AltDataSize = sizeof(UINT64);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
newValue = Rand64();
|
||||
if (!IPCIPv6CheckExistingLinkLocal(p->Ipc, newValue))
|
||||
{
|
||||
WRITE_UINT64(t->AltData, newValue);
|
||||
t->AltDataSize = sizeof(UINT64);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
t->IsSupported = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (PPPRejectLCPOptionsEx(p, pp, processed))
|
||||
{
|
||||
Debug("Rejected IPv6CP options ID = 0x%x\n", pp->Lcp->Id);
|
||||
processed = true;
|
||||
}
|
||||
|
||||
if (PPPNackLCPOptionsEx(p, pp, processed))
|
||||
{
|
||||
Debug("NACKed IPv6CP options ID = 0x%x\n", pp->Lcp->Id);
|
||||
processed = true;
|
||||
}
|
||||
|
||||
if (p->Ipc->IPv6ClientEUI != 0 && IPC_PROTO_GET_STATUS(p->Ipc, IPv6State) == IPC_PROTO_STATUS_CLOSED)
|
||||
{
|
||||
PPP_LCP *c = NewPPPLCP(PPP_LCP_CODE_REQ, 0);
|
||||
UINT64 serverEui = IPCIPv6GetServerEui(p->Ipc);
|
||||
if (serverEui != 0 && serverEui != p->Ipc->IPv6ClientEUI)
|
||||
{
|
||||
Add(c->OptionList, NewPPPOption(PPP_IPV6CP_OPTION_EUI, &serverEui, sizeof(UINT64)));
|
||||
}
|
||||
if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_IPV6CP, c))
|
||||
{
|
||||
PPPSetStatus(p, PPP_STATUS_FAIL);
|
||||
WHERE;
|
||||
return false;
|
||||
}
|
||||
|
||||
IPC_PROTO_SET_STATUS(p->Ipc, IPv6State, IPC_PROTO_STATUS_CONFIG);
|
||||
}
|
||||
|
||||
if (IPC_PROTO_GET_STATUS(p->Ipc, IPv6State) == IPC_PROTO_STATUS_CONFIG && !processed)
|
||||
{
|
||||
PPPAddNextPacket(p, pp, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!PPPAckLCPOptionsEx(p, pp, processed))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Debug("ACKed IPv6CP options ID = 0x%x\n", pp->Lcp->Id);
|
||||
|
||||
if (IPC_PROTO_GET_STATUS(p->Ipc, IPv6State) == IPC_PROTO_STATUS_CONFIG_WAIT)
|
||||
{
|
||||
IPC_PROTO_SET_STATUS(p->Ipc, IPv6State, IPC_PROTO_STATUS_OPENED);
|
||||
Debug("IPv6 OPENED\n");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// LCP option based packets utility
|
||||
bool PPPRejectLCPOptions(PPP_SESSION *p, PPP_PACKET *pp)
|
||||
{
|
||||
@ -2128,7 +2305,7 @@ LABEL_LOOP:
|
||||
|
||||
if (async == false)
|
||||
{
|
||||
d = TubeRecvSync(p->TubeRecv, p->PacketRecvTimeout);
|
||||
d = TubeRecvSync(p->TubeRecv, (UINT)p->PacketRecvTimeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2241,7 +2418,6 @@ PPP_PACKET *PPPGetNextPacket(PPP_SESSION *p)
|
||||
void PPPAddNextPacket(PPP_SESSION *p, PPP_PACKET *pp, UINT delay)
|
||||
{
|
||||
PPP_DELAYED_PACKET *t = ZeroMalloc(sizeof(PPP_DELAYED_PACKET));
|
||||
UINT i;
|
||||
if (p->CurrentPacket == pp)
|
||||
{
|
||||
p->CurrentPacket = NULL;
|
||||
@ -2262,7 +2438,7 @@ void PPPAddNextPacket(PPP_SESSION *p, PPP_PACKET *pp, UINT delay)
|
||||
Debug("after sorting delayeds end\n");*/
|
||||
}
|
||||
|
||||
int PPPDelayedPacketsComparator(const void *a, const void *b)
|
||||
int PPPDelayedPacketsComparator(void *a, void *b)
|
||||
{
|
||||
PPP_DELAYED_PACKET *first = a;
|
||||
PPP_DELAYED_PACKET *second = b;
|
||||
@ -3009,12 +3185,11 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSi
|
||||
UCHAR *dataBuffer;
|
||||
UINT dataSize;
|
||||
UINT tlsLength = 0;
|
||||
UINT i;
|
||||
bool isFragmented = false;
|
||||
PPP_LCP *lcp;
|
||||
PPP_EAP *eap;
|
||||
UCHAR flags = PPP_EAP_TLS_FLAG_NONE;
|
||||
UINT64 sizeLeft = 0;
|
||||
UINT sizeLeft = 0;
|
||||
Debug("Got EAP-TLS size=%i\n", eapTlsSize);
|
||||
if (eapTlsSize == 1)
|
||||
{
|
||||
@ -3024,7 +3199,7 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSi
|
||||
// We got an ACK to transmit the next fragmented message
|
||||
dataSize = p->Mru1 - 8 - 1 - 1; // Calculating the maximum payload size (without TlsLength)
|
||||
sizeLeft = GetMemSize(p->Eap_TlsCtx.CachedBufferSend);
|
||||
sizeLeft -= p->Eap_TlsCtx.CachedBufferSendPntr - p->Eap_TlsCtx.CachedBufferSend;
|
||||
sizeLeft -= (UINT)(p->Eap_TlsCtx.CachedBufferSendPntr - p->Eap_TlsCtx.CachedBufferSend);
|
||||
|
||||
flags = PPP_EAP_TLS_FLAG_FRAGMENTED; // M flag
|
||||
if (dataSize > sizeLeft)
|
||||
@ -3035,7 +3210,7 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSi
|
||||
lcp = BuildEAPTlsRequest(p->Eap_PacketId++, dataSize, flags);
|
||||
eap = lcp->Data;
|
||||
Copy(eap->Tls.TlsDataWithoutLength, p->Eap_TlsCtx.CachedBufferSendPntr, dataSize);
|
||||
p->Eap_TlsCtx.CachedBufferSendPntr += dataSize;
|
||||
p->Eap_TlsCtx.CachedBufferSendPntr += (UINT64)dataSize;
|
||||
|
||||
if (!PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp))
|
||||
{
|
||||
@ -3192,7 +3367,7 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSi
|
||||
p->Eap_TlsCtx.CachedBufferRecvPntr = p->Eap_TlsCtx.CachedBufferRecv;
|
||||
}
|
||||
sizeLeft = GetMemSize(p->Eap_TlsCtx.CachedBufferRecv);
|
||||
sizeLeft -= p->Eap_TlsCtx.CachedBufferRecvPntr - p->Eap_TlsCtx.CachedBufferRecv;
|
||||
sizeLeft -= (UINT)(p->Eap_TlsCtx.CachedBufferRecvPntr - p->Eap_TlsCtx.CachedBufferRecv);
|
||||
|
||||
Copy(p->Eap_TlsCtx.CachedBufferRecvPntr, dataBuffer, MIN(sizeLeft, dataSize));
|
||||
|
||||
@ -3206,7 +3381,7 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSi
|
||||
dataSize = GetMemSize(p->Eap_TlsCtx.CachedBufferRecv);
|
||||
if (dataSize == MAX_BUFFERING_PACKET_SIZE)
|
||||
{
|
||||
dataSize = p->Eap_TlsCtx.CachedBufferRecvPntr - p->Eap_TlsCtx.CachedBufferRecv;
|
||||
dataSize = (UINT)(p->Eap_TlsCtx.CachedBufferRecvPntr - p->Eap_TlsCtx.CachedBufferRecv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@
|
||||
#define PPP_IPCP_OPTION_WINS2 132
|
||||
|
||||
// IPV6CP option type
|
||||
#define PPP_IPV6CP_OPTION_IID 1
|
||||
#define PPP_IPV6CP_OPTION_EUI 1
|
||||
|
||||
// EAP codes
|
||||
#define PPP_EAP_CODE_REQUEST 1
|
||||
@ -135,13 +135,6 @@
|
||||
#define PPP_STATUS_FAIL 0x1000
|
||||
#define PPP_STATUS_AUTH_FAIL 0x1010
|
||||
|
||||
// Protocol status
|
||||
#define PPP_PROTO_STATUS_CLOSED 0x0
|
||||
#define PPP_PROTO_STATUS_CONFIG 0x1
|
||||
#define PPP_PROTO_STATUS_CONFIG_WAIT 0x2
|
||||
#define PPP_PROTO_STATUS_OPENED 0x10
|
||||
#define PPP_PROTO_STATUS_REJECTED 0x100
|
||||
|
||||
#define PPP_UNSPECIFIED 0xFFFF
|
||||
|
||||
//// Type
|
||||
@ -301,8 +294,6 @@ struct PPP_SESSION
|
||||
UCHAR ClientInterfaceId[8]; // Client IPv6CP Interface Identifier
|
||||
|
||||
UINT PPPStatus;
|
||||
UINT IPv4_State;
|
||||
UINT IPv6_State;
|
||||
|
||||
// EAP contexts
|
||||
UINT Eap_Protocol; // Current EAP Protocol used
|
||||
@ -344,12 +335,14 @@ bool PPPProcessLCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req
|
||||
bool PPPProcessCHAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req);
|
||||
bool PPPProcessIPCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req);
|
||||
bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req);
|
||||
bool PPPProcessIPv6CPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req);
|
||||
// Request packets
|
||||
bool PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *pp);
|
||||
bool PPPProcessLCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp);
|
||||
bool PPPProcessPAPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp);
|
||||
bool PPPProcessIPCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp);
|
||||
bool PPPProcessEAPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp);
|
||||
bool PPPProcessIPv6CPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp);
|
||||
|
||||
// LCP option based packets utility
|
||||
bool PPPRejectLCPOptions(PPP_SESSION *p, PPP_PACKET *pp);
|
||||
@ -369,7 +362,7 @@ PPP_PACKET *PPPRecvPacket(PPP_SESSION *p, bool async);
|
||||
// Helpers for delaying packets
|
||||
PPP_PACKET *PPPGetNextPacket(PPP_SESSION *p);
|
||||
void PPPAddNextPacket(PPP_SESSION *p, PPP_PACKET *pp, UINT delay);
|
||||
int PPPDelayedPacketsComparator(const void *a, const void *b);
|
||||
int PPPDelayedPacketsComparator(void *a, void *b);
|
||||
char PPPRelatedPacketComparator(PPP_PACKET *a, PPP_PACKET *b);
|
||||
|
||||
// PPP utility functions
|
||||
|
@ -1753,7 +1753,7 @@ LABEL_RESTART:
|
||||
UnlockQueue(t->SendQueue);
|
||||
|
||||
// Happy processing
|
||||
IPCProcessL3Events(ipc);
|
||||
IPCProcessL3EventsIPv4Only(ipc);
|
||||
|
||||
LockQueue(t->RecvQueue);
|
||||
{
|
||||
@ -2370,7 +2370,7 @@ bool NnTestConnectivity(NATIVE_STACK *a, TUBE *halt_tube)
|
||||
}
|
||||
|
||||
// Happy processing
|
||||
IPCProcessL3Events(ipc);
|
||||
IPCProcessL3EventsIPv4Only(ipc);
|
||||
|
||||
while (true)
|
||||
{
|
||||
@ -2479,7 +2479,7 @@ bool NnTestConnectivity(NATIVE_STACK *a, TUBE *halt_tube)
|
||||
}
|
||||
|
||||
// Happy procedure
|
||||
IPCProcessL3Events(ipc);
|
||||
IPCProcessL3EventsIPv4Only(ipc);
|
||||
|
||||
while (true)
|
||||
{
|
||||
@ -6141,67 +6141,128 @@ char *CharToNetBiosStr(char c)
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '\0': return "AA";
|
||||
case 'A': return "EB";
|
||||
case 'B': return "EC";
|
||||
case 'C': return "ED";
|
||||
case 'D': return "EE";
|
||||
case 'E': return "EF";
|
||||
case 'F': return "EG";
|
||||
case 'G': return "EH";
|
||||
case 'H': return "EI";
|
||||
case 'I': return "EJ";
|
||||
case 'J': return "EK";
|
||||
case 'K': return "EL";
|
||||
case 'L': return "EM";
|
||||
case 'M': return "EN";
|
||||
case 'N': return "EO";
|
||||
case 'O': return "EP";
|
||||
case 'P': return "FA";
|
||||
case 'Q': return "FB";
|
||||
case 'R': return "FC";
|
||||
case 'S': return "FD";
|
||||
case 'T': return "FE";
|
||||
case 'U': return "FF";
|
||||
case 'V': return "FG";
|
||||
case 'W': return "FH";
|
||||
case 'X': return "FI";
|
||||
case 'Y': return "FJ";
|
||||
case 'Z': return "FK";
|
||||
case '0': return "DA";
|
||||
case '1': return "DB";
|
||||
case '2': return "DC";
|
||||
case '3': return "DD";
|
||||
case '4': return "DE";
|
||||
case '5': return "DF";
|
||||
case '6': return "DG";
|
||||
case '7': return "DH";
|
||||
case '8': return "DI";
|
||||
case '9': return "DJ";
|
||||
case ' ': return "CA";
|
||||
case '!': return "CB";
|
||||
case '\"': return "CC";
|
||||
case '#': return "CD";
|
||||
case '$': return "CE";
|
||||
case '%': return "CF";
|
||||
case '&': return "CG";
|
||||
case '\'': return "CH";
|
||||
case '(': return "CI";
|
||||
case ')': return "CJ";
|
||||
case '*': return "CK";
|
||||
case '+': return "CL";
|
||||
case ',': return "CM";
|
||||
case '-': return "CN";
|
||||
case '.': return "CO";
|
||||
case '=': return "DN";
|
||||
case ':': return "DK";
|
||||
case ';': return "DL";
|
||||
case '@': return "EA";
|
||||
case '^': return "FO";
|
||||
case '_': return "FP";
|
||||
case '{': return "HL";
|
||||
case '}': return "HN";
|
||||
case '~': return "HO";
|
||||
case '\0':
|
||||
return "AA";
|
||||
case 'A':
|
||||
return "EB";
|
||||
case 'B':
|
||||
return "EC";
|
||||
case 'C':
|
||||
return "ED";
|
||||
case 'D':
|
||||
return "EE";
|
||||
case 'E':
|
||||
return "EF";
|
||||
case 'F':
|
||||
return "EG";
|
||||
case 'G':
|
||||
return "EH";
|
||||
case 'H':
|
||||
return "EI";
|
||||
case 'I':
|
||||
return "EJ";
|
||||
case 'J':
|
||||
return "EK";
|
||||
case 'K':
|
||||
return "EL";
|
||||
case 'L':
|
||||
return "EM";
|
||||
case 'M':
|
||||
return "EN";
|
||||
case 'N':
|
||||
return "EO";
|
||||
case 'O':
|
||||
return "EP";
|
||||
case 'P':
|
||||
return "FA";
|
||||
case 'Q':
|
||||
return "FB";
|
||||
case 'R':
|
||||
return "FC";
|
||||
case 'S':
|
||||
return "FD";
|
||||
case 'T':
|
||||
return "FE";
|
||||
case 'U':
|
||||
return "FF";
|
||||
case 'V':
|
||||
return "FG";
|
||||
case 'W':
|
||||
return "FH";
|
||||
case 'X':
|
||||
return "FI";
|
||||
case 'Y':
|
||||
return "FJ";
|
||||
case 'Z':
|
||||
return "FK";
|
||||
case '0':
|
||||
return "DA";
|
||||
case '1':
|
||||
return "DB";
|
||||
case '2':
|
||||
return "DC";
|
||||
case '3':
|
||||
return "DD";
|
||||
case '4':
|
||||
return "DE";
|
||||
case '5':
|
||||
return "DF";
|
||||
case '6':
|
||||
return "DG";
|
||||
case '7':
|
||||
return "DH";
|
||||
case '8':
|
||||
return "DI";
|
||||
case '9':
|
||||
return "DJ";
|
||||
case ' ':
|
||||
return "CA";
|
||||
case '!':
|
||||
return "CB";
|
||||
case '\"':
|
||||
return "CC";
|
||||
case '#':
|
||||
return "CD";
|
||||
case '$':
|
||||
return "CE";
|
||||
case '%':
|
||||
return "CF";
|
||||
case '&':
|
||||
return "CG";
|
||||
case '\'':
|
||||
return "CH";
|
||||
case '(':
|
||||
return "CI";
|
||||
case ')':
|
||||
return "CJ";
|
||||
case '*':
|
||||
return "CK";
|
||||
case '+':
|
||||
return "CL";
|
||||
case ',':
|
||||
return "CM";
|
||||
case '-':
|
||||
return "CN";
|
||||
case '.':
|
||||
return "CO";
|
||||
case '=':
|
||||
return "DN";
|
||||
case ':':
|
||||
return "DK";
|
||||
case ';':
|
||||
return "DL";
|
||||
case '@':
|
||||
return "EA";
|
||||
case '^':
|
||||
return "FO";
|
||||
case '_':
|
||||
return "FP";
|
||||
case '{':
|
||||
return "HL";
|
||||
case '}':
|
||||
return "HN";
|
||||
case '~':
|
||||
return "HO";
|
||||
}
|
||||
|
||||
return "CA";
|
||||
@ -8220,46 +8281,6 @@ void FreeArpWaitTable(VH *v)
|
||||
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
|
||||
void InsertArpTable(VH *v, UCHAR *mac, UINT ip)
|
||||
{
|
||||
|
@ -409,8 +409,6 @@ ARP_ENTRY *SearchArpTable(VH *v, UINT ip);
|
||||
void RefreshArpTable(VH *v);
|
||||
void PollingArpTable(VH *v);
|
||||
void InsertArpTable(VH *v, UCHAR *mac, UINT ip);
|
||||
bool IsMacBroadcast(UCHAR *mac);
|
||||
bool IsMacInvalid(UCHAR *mac);
|
||||
void InitArpWaitTable(VH *v);
|
||||
void FreeArpWaitTable(VH *v);
|
||||
int CompareArpWaitTable(void *p1, void *p2);
|
||||
|
@ -2398,6 +2398,7 @@ void RUDPBulkSend(RUDP_STACK *r, RUDP_SESSION *se, void *data, UINT data_size)
|
||||
{
|
||||
UCHAR *buf;
|
||||
UINT i, icmp_type, buf_size, padding_size;
|
||||
icmp_type = 0;
|
||||
// Validate arguments
|
||||
if (r == NULL || se == NULL || (data == NULL && data_size != 0))
|
||||
{
|
||||
@ -7375,6 +7376,175 @@ void CopyIP(IP *dst, IP *src)
|
||||
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
|
||||
UINT GetNumIpClient(IP *ip)
|
||||
{
|
||||
@ -7649,39 +7819,105 @@ UINT IntToSubnetMask32(UINT i)
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0: ret = 0x00000000; break;
|
||||
case 1: ret = 0x80000000; break;
|
||||
case 2: ret = 0xC0000000; break;
|
||||
case 3: ret = 0xE0000000; break;
|
||||
case 4: ret = 0xF0000000; break;
|
||||
case 5: ret = 0xF8000000; break;
|
||||
case 6: ret = 0xFC000000; break;
|
||||
case 7: ret = 0xFE000000; break;
|
||||
case 8: ret = 0xFF000000; break;
|
||||
case 9: ret = 0xFF800000; break;
|
||||
case 10: ret = 0xFFC00000; break;
|
||||
case 11: ret = 0xFFE00000; break;
|
||||
case 12: ret = 0xFFF00000; break;
|
||||
case 13: ret = 0xFFF80000; break;
|
||||
case 14: ret = 0xFFFC0000; break;
|
||||
case 15: ret = 0xFFFE0000; break;
|
||||
case 16: ret = 0xFFFF0000; break;
|
||||
case 17: ret = 0xFFFF8000; break;
|
||||
case 18: ret = 0xFFFFC000; break;
|
||||
case 19: ret = 0xFFFFE000; break;
|
||||
case 20: ret = 0xFFFFF000; break;
|
||||
case 21: ret = 0xFFFFF800; break;
|
||||
case 22: ret = 0xFFFFFC00; break;
|
||||
case 23: ret = 0xFFFFFE00; break;
|
||||
case 24: ret = 0xFFFFFF00; break;
|
||||
case 25: ret = 0xFFFFFF80; break;
|
||||
case 26: ret = 0xFFFFFFC0; break;
|
||||
case 27: ret = 0xFFFFFFE0; break;
|
||||
case 28: ret = 0xFFFFFFF0; break;
|
||||
case 29: ret = 0xFFFFFFF8; break;
|
||||
case 30: ret = 0xFFFFFFFC; break;
|
||||
case 31: ret = 0xFFFFFFFE; break;
|
||||
case 32: ret = 0xFFFFFFFF; break;
|
||||
case 0:
|
||||
ret = 0x00000000;
|
||||
break;
|
||||
case 1:
|
||||
ret = 0x80000000;
|
||||
break;
|
||||
case 2:
|
||||
ret = 0xC0000000;
|
||||
break;
|
||||
case 3:
|
||||
ret = 0xE0000000;
|
||||
break;
|
||||
case 4:
|
||||
ret = 0xF0000000;
|
||||
break;
|
||||
case 5:
|
||||
ret = 0xF8000000;
|
||||
break;
|
||||
case 6:
|
||||
ret = 0xFC000000;
|
||||
break;
|
||||
case 7:
|
||||
ret = 0xFE000000;
|
||||
break;
|
||||
case 8:
|
||||
ret = 0xFF000000;
|
||||
break;
|
||||
case 9:
|
||||
ret = 0xFF800000;
|
||||
break;
|
||||
case 10:
|
||||
ret = 0xFFC00000;
|
||||
break;
|
||||
case 11:
|
||||
ret = 0xFFE00000;
|
||||
break;
|
||||
case 12:
|
||||
ret = 0xFFF00000;
|
||||
break;
|
||||
case 13:
|
||||
ret = 0xFFF80000;
|
||||
break;
|
||||
case 14:
|
||||
ret = 0xFFFC0000;
|
||||
break;
|
||||
case 15:
|
||||
ret = 0xFFFE0000;
|
||||
break;
|
||||
case 16:
|
||||
ret = 0xFFFF0000;
|
||||
break;
|
||||
case 17:
|
||||
ret = 0xFFFF8000;
|
||||
break;
|
||||
case 18:
|
||||
ret = 0xFFFFC000;
|
||||
break;
|
||||
case 19:
|
||||
ret = 0xFFFFE000;
|
||||
break;
|
||||
case 20:
|
||||
ret = 0xFFFFF000;
|
||||
break;
|
||||
case 21:
|
||||
ret = 0xFFFFF800;
|
||||
break;
|
||||
case 22:
|
||||
ret = 0xFFFFFC00;
|
||||
break;
|
||||
case 23:
|
||||
ret = 0xFFFFFE00;
|
||||
break;
|
||||
case 24:
|
||||
ret = 0xFFFFFF00;
|
||||
break;
|
||||
case 25:
|
||||
ret = 0xFFFFFF80;
|
||||
break;
|
||||
case 26:
|
||||
ret = 0xFFFFFFC0;
|
||||
break;
|
||||
case 27:
|
||||
ret = 0xFFFFFFE0;
|
||||
break;
|
||||
case 28:
|
||||
ret = 0xFFFFFFF0;
|
||||
break;
|
||||
case 29:
|
||||
ret = 0xFFFFFFF8;
|
||||
break;
|
||||
case 30:
|
||||
ret = 0xFFFFFFFC;
|
||||
break;
|
||||
case 31:
|
||||
ret = 0xFFFFFFFE;
|
||||
break;
|
||||
case 32:
|
||||
ret = 0xFFFFFFFF;
|
||||
break;
|
||||
}
|
||||
|
||||
if (IsLittleEndian())
|
||||
|
@ -1302,6 +1302,15 @@ void IPAnd4(IP *dst, IP *a, IP *b);
|
||||
bool IsInSameNetwork4(IP *a1, IP *a2, IP *subnet);
|
||||
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 ParseIpAndSubnetMask46(char *src, IP *ip, IP *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;
|
||||
}
|
||||
|
||||
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
|
||||
UCHAR IPv6GetNextHeaderFromQueue(QUEUE *q)
|
||||
{
|
||||
@ -1102,6 +1140,7 @@ void BuildICMPv6OptionValue(BUF *b, UCHAR type, void *header_pointer, UINT total
|
||||
BUF *BuildICMPv6Options(ICMPV6_OPTION_LIST *o)
|
||||
{
|
||||
BUF *b;
|
||||
UINT i;
|
||||
// Validate arguments
|
||||
if (o == NULL)
|
||||
{
|
||||
@ -1118,9 +1157,16 @@ BUF *BuildICMPv6Options(ICMPV6_OPTION_LIST *o)
|
||||
{
|
||||
BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_TARGET_LINK_LAYER, o->TargetLinkLayer, sizeof(ICMPV6_OPTION_LINK_LAYER));
|
||||
}
|
||||
if (o->Prefix != NULL)
|
||||
for (i = 0; i < ICMPV6_OPTION_PREFIXES_MAX_COUNT; i++)
|
||||
{
|
||||
BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_PREFIX, o->Prefix, sizeof(ICMPV6_OPTION_PREFIX));
|
||||
if (o->Prefix[i] != NULL)
|
||||
{
|
||||
BuildICMPv6OptionValue(b, ICMPV6_OPTION_TYPE_PREFIX, o->Prefix[i], sizeof(ICMPV6_OPTION_PREFIX));
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (o->Mtu != NULL)
|
||||
{
|
||||
@ -1452,6 +1498,12 @@ PKT *ClonePacket(PKT *p, bool copy_data)
|
||||
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
|
||||
PKT *ParsePacket(UCHAR *buf, UINT size)
|
||||
{
|
||||
@ -1470,6 +1522,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);
|
||||
}
|
||||
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;
|
||||
USHORT vlan_type_id_16;
|
||||
@ -1559,7 +1615,7 @@ PKT *ParsePacketEx4(UCHAR *buf, UINT size, bool no_l3, UINT vlan_type_id, bool b
|
||||
}
|
||||
|
||||
// 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
|
||||
FreePacket(p);
|
||||
@ -1929,7 +1985,7 @@ HTTPLOG *ParseHttpAccessLog(PKT *pkt)
|
||||
|
||||
|
||||
// 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;
|
||||
bool b1, b2;
|
||||
@ -1994,7 +2050,7 @@ bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3)
|
||||
switch (type_id_16)
|
||||
{
|
||||
case MAC_PROTO_ARPV4: // ARPv4
|
||||
if (no_l3)
|
||||
if (no_l3 || no_l3_l4_except_icmpv6)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -2002,7 +2058,7 @@ bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3)
|
||||
return ParsePacketARPv4(p, buf, size);
|
||||
|
||||
case MAC_PROTO_IPV4: // IPv4
|
||||
if (no_l3)
|
||||
if (no_l3 || no_l3_l4_except_icmpv6)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -2015,7 +2071,7 @@ bool ParsePacketL2Ex(PKT *p, UCHAR *buf, UINT size, bool no_l3)
|
||||
return true;
|
||||
}
|
||||
|
||||
return ParsePacketIPv6(p, buf, size);
|
||||
return ParsePacketIPv6(p, buf, size, no_l3_l4_except_icmpv6);
|
||||
|
||||
default: // Unknown
|
||||
if (type_id_16 == p->VlanTypeID)
|
||||
@ -2354,7 +2410,15 @@ bool ParseICMPv6Options(ICMPV6_OPTION_LIST *o, UCHAR *buf, UINT size)
|
||||
// Prefix Information
|
||||
if (header_total_size >= sizeof(ICMPV6_OPTION_PREFIX))
|
||||
{
|
||||
o->Prefix = (ICMPV6_OPTION_PREFIX *)header_pointer;
|
||||
UINT i;
|
||||
for (i = 0; i < ICMPV6_OPTION_PREFIXES_MAX_COUNT; i++)
|
||||
{
|
||||
if (o->Prefix[i] == NULL)
|
||||
{
|
||||
o->Prefix[i] = (ICMPV6_OPTION_PREFIX *)header_pointer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2508,6 +2572,7 @@ bool ParseICMPv6(PKT *p, UCHAR *buf, UINT size)
|
||||
// Release of the ICMPv6 options
|
||||
void FreeCloneICMPv6Options(ICMPV6_OPTION_LIST *o)
|
||||
{
|
||||
UINT i;
|
||||
// Validate arguments
|
||||
if (o == NULL)
|
||||
{
|
||||
@ -2516,13 +2581,19 @@ void FreeCloneICMPv6Options(ICMPV6_OPTION_LIST *o)
|
||||
|
||||
Free(o->SourceLinkLayer);
|
||||
Free(o->TargetLinkLayer);
|
||||
Free(o->Prefix);
|
||||
|
||||
for (i = 0; i < ICMPV6_OPTION_PREFIXES_MAX_COUNT; i++)
|
||||
{
|
||||
Free(o->Prefix[i]);
|
||||
o->Prefix[i] = NULL;
|
||||
}
|
||||
Free(o->Mtu);
|
||||
}
|
||||
|
||||
// Clone of the ICMPv6 options
|
||||
void CloneICMPv6Options(ICMPV6_OPTION_LIST *dst, ICMPV6_OPTION_LIST *src)
|
||||
{
|
||||
UINT i;
|
||||
// Validate arguments
|
||||
if (dst == NULL || src == NULL)
|
||||
{
|
||||
@ -2533,12 +2604,22 @@ void CloneICMPv6Options(ICMPV6_OPTION_LIST *dst, ICMPV6_OPTION_LIST *src)
|
||||
|
||||
dst->SourceLinkLayer = Clone(src->SourceLinkLayer, sizeof(ICMPV6_OPTION_LINK_LAYER));
|
||||
dst->TargetLinkLayer = Clone(src->TargetLinkLayer, sizeof(ICMPV6_OPTION_LINK_LAYER));
|
||||
dst->Prefix = Clone(src->Prefix, sizeof(ICMPV6_OPTION_PREFIX));
|
||||
for (i = 0; i < ICMPV6_OPTION_PREFIXES_MAX_COUNT; i++)
|
||||
{
|
||||
if (src->Prefix[i] != NULL)
|
||||
{
|
||||
dst->Prefix[i] = Clone(src->Prefix[i], sizeof(ICMPV6_OPTION_PREFIX));
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
dst->Mtu = Clone(src->Mtu, sizeof(ICMPV6_OPTION_MTU));
|
||||
}
|
||||
|
||||
// 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
|
||||
if (p == NULL || buf == NULL)
|
||||
@ -2585,9 +2666,17 @@ bool ParsePacketIPv6(PKT *p, UCHAR *buf, UINT size)
|
||||
}
|
||||
|
||||
case IP_PROTO_TCP: // TCP
|
||||
if (no_l3_l4_except_icmpv6)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return ParseTCP(p, buf, size);
|
||||
|
||||
case IP_PROTO_UDP: // UDP
|
||||
if (no_l3_l4_except_icmpv6)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return ParseUDP(p, buf, size);
|
||||
|
||||
default: // Unknown
|
||||
|
@ -399,12 +399,14 @@ struct ICMPV6_NEIGHBOR_ADVERTISEMENT_HEADER
|
||||
#define ICMPV6_NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED 0x40 // Solicited flag
|
||||
#define ICMPV6_NEIGHBOR_ADVERTISEMENT_FLAG_OVERWRITE 0x20 // Overwrite flag
|
||||
|
||||
#define ICMPV6_OPTION_PREFIXES_MAX_COUNT 10
|
||||
|
||||
// ICMPv6 option list
|
||||
struct ICMPV6_OPTION_LIST
|
||||
{
|
||||
ICMPV6_OPTION_LINK_LAYER *SourceLinkLayer; // Source link-layer address
|
||||
ICMPV6_OPTION_LINK_LAYER *TargetLinkLayer; // Target link-layer address
|
||||
ICMPV6_OPTION_PREFIX *Prefix; // Prefix Information
|
||||
ICMPV6_OPTION_PREFIX *Prefix[ICMPV6_OPTION_PREFIXES_MAX_COUNT]; // Prefix Information - may be multiple in one request
|
||||
ICMPV6_OPTION_MTU *Mtu; // MTU
|
||||
} GCC_PACKED;
|
||||
|
||||
@ -745,6 +747,8 @@ PKT *ParsePacketEx(UCHAR *buf, UINT size, bool no_l3);
|
||||
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 *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 FreePacketWithData(PKT *p);
|
||||
void FreePacketIPv4(PKT *p);
|
||||
@ -754,7 +758,7 @@ void FreePacketUDPv4(PKT *p);
|
||||
void FreePacketTCPv4(PKT *p);
|
||||
void FreePacketICMPv4(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 ParsePacketIPv4(PKT *p, UCHAR *buf, UINT size);
|
||||
bool ParsePacketBPDU(PKT *p, UCHAR *buf, UINT size);
|
||||
@ -770,7 +774,7 @@ void FreeClonePacket(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 ParseIPv6ExtHeader(IPV6_HEADER_PACKET_INFO *info, UCHAR next_header, UCHAR *buf, UINT size);
|
||||
bool ParseICMPv6Options(ICMPV6_OPTION_LIST *o, UCHAR *buf, UINT size);
|
||||
@ -786,6 +790,7 @@ BUF *BuildIPv6PacketHeader(IPV6_HEADER_PACKET_INFO *info, UINT *bytes_before_pay
|
||||
UCHAR IPv6GetNextHeaderFromQueue(QUEUE *q);
|
||||
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 *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);
|
||||
|
||||
bool VLanRemoveTag(void **packet_data, UINT *packet_size, UINT vlan_id, UINT vlan_tpid);
|
||||
|
Loading…
Reference in New Issue
Block a user