mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-11-22 09:29:52 +03:00
Preliminary implementation of IPv6CP and IPv6 for PPP (untested)
This commit is contained in:
parent
f627b64264
commit
f2fee4d32c
@ -232,12 +232,12 @@ TOKEN_LIST *GetEthListSolaris()
|
||||
lifc.lifc_family = AF_INET;
|
||||
lifc.lifc_flags = 0;
|
||||
lifc.lifc_len = bufsize;
|
||||
lifc.lifc_buf = (char*) buf;
|
||||
lifc.lifc_buf = (char *) buf;
|
||||
if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) >= 0)
|
||||
{
|
||||
for (i = 0; i<numifs; i++)
|
||||
{
|
||||
if(StartWith(buf[i].lifr_name, "lo") == false){
|
||||
if(StartWith(buf[i].lifr_name, "lo") == false) {
|
||||
Add(o, CopyStr(buf[i].lifr_name));
|
||||
}
|
||||
}
|
||||
@ -253,7 +253,7 @@ TOKEN_LIST *GetEthListSolaris()
|
||||
t->NumTokens = LIST_NUM(o);
|
||||
t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
|
||||
|
||||
for (i = 0;i < LIST_NUM(o);i++)
|
||||
for (i = 0; i < LIST_NUM(o); i++)
|
||||
{
|
||||
char *name = LIST_DATA(o, i);
|
||||
t->Token[i] = name;
|
||||
@ -287,7 +287,7 @@ TOKEN_LIST *GetEthListLinux(bool enum_normal, bool enum_rawip)
|
||||
if (s != INVALID_SOCKET)
|
||||
{
|
||||
n = 0;
|
||||
for (i = 0;;i++)
|
||||
for (i = 0;; i++)
|
||||
{
|
||||
Zero(&ifr, sizeof(ifr));
|
||||
ifr.ifr_ifindex = i;
|
||||
@ -332,7 +332,7 @@ TOKEN_LIST *GetEthListLinux(bool enum_normal, bool enum_rawip)
|
||||
t->NumTokens = LIST_NUM(o) + (enum_rawip ? 1 : 0);
|
||||
t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
|
||||
|
||||
for (i = 0;i < LIST_NUM(o);i++)
|
||||
for (i = 0; i < LIST_NUM(o); i++)
|
||||
{
|
||||
char *name = LIST_DATA(o, i);
|
||||
t->Token[i] = name;
|
||||
@ -372,9 +372,9 @@ TOKEN_LIST *GetEthListPcap()
|
||||
if(p != NULL)
|
||||
{
|
||||
int datalink = pcap_datalink(p);
|
||||
// Debug("type:%s\n",pcap_datalink_val_to_name(datalink));
|
||||
// Debug("type:%s\n",pcap_datalink_val_to_name(datalink));
|
||||
pcap_close(p);
|
||||
if(datalink == DLT_EN10MB){
|
||||
if(datalink == DLT_EN10MB) {
|
||||
// Enumerate only Ethernet type device
|
||||
Add(o, CopyStr(dev->name));
|
||||
}
|
||||
@ -388,7 +388,7 @@ TOKEN_LIST *GetEthListPcap()
|
||||
t = ZeroMalloc(sizeof(TOKEN_LIST));
|
||||
t->NumTokens = LIST_NUM(o);
|
||||
t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
|
||||
for (i = 0;i < LIST_NUM(o);i++)
|
||||
for (i = 0; i < LIST_NUM(o); i++)
|
||||
{
|
||||
t->Token[i] = LIST_DATA(o, i);
|
||||
}
|
||||
@ -415,7 +415,7 @@ TOKEN_LIST *GetEthListBpf()
|
||||
struct ifaddrs *ifadr = ifadrs;
|
||||
while(ifadr)
|
||||
{
|
||||
sockadr = (struct sockaddr_dl*)ifadr->ifa_addr;
|
||||
sockadr = (struct sockaddr_dl *)ifadr->ifa_addr;
|
||||
if(sockadr->sdl_family == AF_LINK && sockadr->sdl_type == IFT_ETHER)
|
||||
{
|
||||
// Is this Ethernet device?
|
||||
@ -434,7 +434,7 @@ TOKEN_LIST *GetEthListBpf()
|
||||
t = ZeroMalloc(sizeof(TOKEN_LIST));
|
||||
t->NumTokens = LIST_NUM(o);
|
||||
t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
|
||||
for (i = 0;i < LIST_NUM(o);i++)
|
||||
for (i = 0; i < LIST_NUM(o); i++)
|
||||
{
|
||||
t->Token[i] = LIST_DATA(o, i);
|
||||
}
|
||||
@ -1070,7 +1070,7 @@ bool ParseUnixEthDeviceName(char *dst_devname, UINT dst_devname_size, char *src_
|
||||
|
||||
#if defined(BRIDGE_BPF) || defined(BRIDGE_PCAP)
|
||||
// Initialize captured packet data structure
|
||||
struct CAPTUREBLOCK *NewCaptureBlock(UCHAR *data, UINT size){
|
||||
struct CAPTUREBLOCK *NewCaptureBlock(UCHAR *data, UINT size) {
|
||||
struct CAPTUREBLOCK *block = Malloc(sizeof(struct CAPTUREBLOCK));
|
||||
block->Buf = data;
|
||||
block->Size = size;
|
||||
@ -1078,7 +1078,7 @@ struct CAPTUREBLOCK *NewCaptureBlock(UCHAR *data, UINT size){
|
||||
}
|
||||
|
||||
// Free captured packet data structure
|
||||
void FreeCaptureBlock(struct CAPTUREBLOCK *block){
|
||||
void FreeCaptureBlock(struct CAPTUREBLOCK *block) {
|
||||
Free(block);
|
||||
}
|
||||
#endif // BRIDGE_BPF || BRIDGE_PCAP
|
||||
@ -1087,7 +1087,7 @@ void FreeCaptureBlock(struct CAPTUREBLOCK *block){
|
||||
// Callback function to receive arriving packet (Pcap)
|
||||
void PcapHandler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
|
||||
{
|
||||
ETH *e = (ETH*) user;
|
||||
ETH *e = (ETH *) user;
|
||||
struct CAPTUREBLOCK *block;
|
||||
UCHAR *data;
|
||||
|
||||
@ -1096,7 +1096,7 @@ void PcapHandler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
|
||||
block = NewCaptureBlock(data, h->caplen);
|
||||
LockQueue(e->Queue);
|
||||
// Discard arriving packet when queue filled
|
||||
if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){
|
||||
if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE) {
|
||||
InsertQueue(e->Queue, block);
|
||||
e->QueueSize += h->caplen;
|
||||
}
|
||||
@ -1108,7 +1108,7 @@ void PcapHandler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
|
||||
// Relay thread for captured packet (Pcap)
|
||||
void PcapThread(THREAD *thread, void *param)
|
||||
{
|
||||
ETH *e = (ETH*)param;
|
||||
ETH *e = (ETH *)param;
|
||||
pcap_t *p = e->Pcap;
|
||||
int ret;
|
||||
|
||||
@ -1116,8 +1116,8 @@ void PcapThread(THREAD *thread, void *param)
|
||||
NoticeThreadInit(thread);
|
||||
|
||||
// Return -1:Error -2:Terminated externally
|
||||
ret = pcap_loop(p, -1, PcapHandler, (u_char*) e);
|
||||
if(ret == -1){
|
||||
ret = pcap_loop(p, -1, PcapHandler, (u_char *) e);
|
||||
if(ret == -1) {
|
||||
e->Socket = INVALID_SOCKET;
|
||||
pcap_perror(p, "capture");
|
||||
}
|
||||
@ -1181,7 +1181,7 @@ ETH *OpenEthPcap(char *name, bool local, bool tapmode, char *tapaddr)
|
||||
// Relay thread for captured packet (BPF)
|
||||
void BpfThread(THREAD *thread, void *param)
|
||||
{
|
||||
ETH *e = (ETH*)param;
|
||||
ETH *e = (ETH *)param;
|
||||
int fd = e->Socket;
|
||||
int len;
|
||||
int rest; // Rest size in buffer
|
||||
@ -1196,14 +1196,14 @@ void BpfThread(THREAD *thread, void *param)
|
||||
// Notify initialize completed
|
||||
NoticeThreadInit(thread);
|
||||
|
||||
while(1){
|
||||
while(1) {
|
||||
// Determining to exit loop
|
||||
if(e->Socket == INVALID_SOCKET){
|
||||
if(e->Socket == INVALID_SOCKET) {
|
||||
break;
|
||||
}
|
||||
|
||||
rest = read(fd, buf, e->BufSize);
|
||||
if(rest < 0 && errno != EAGAIN){
|
||||
if(rest < 0 && errno != EAGAIN) {
|
||||
// Error
|
||||
close(fd);
|
||||
e->Socket = INVALID_SOCKET;
|
||||
@ -1213,12 +1213,12 @@ void BpfThread(THREAD *thread, void *param)
|
||||
}
|
||||
next = buf;
|
||||
LockQueue(e->Queue);
|
||||
while(rest>0){
|
||||
while(rest>0) {
|
||||
// Cut out a packet
|
||||
hdr = (struct bpf_hdr*)next;
|
||||
hdr = (struct bpf_hdr *)next;
|
||||
|
||||
// Discard arriving packet when queue filled
|
||||
if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){
|
||||
if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE) {
|
||||
data = Malloc(hdr->bh_caplen);
|
||||
Copy(data, next+(hdr->bh_hdrlen), hdr->bh_caplen);
|
||||
block = NewCaptureBlock(data, hdr->bh_caplen);
|
||||
@ -1253,31 +1253,31 @@ ETH *OpenEthBpf(char *name, bool local, bool tapmode, char *tapaddr)
|
||||
struct timeval to;
|
||||
|
||||
// Find unused bpf device and open it
|
||||
do{
|
||||
do {
|
||||
Format(devname, sizeof(devname), "/dev/bpf%d", n++);
|
||||
fd = open (devname, O_RDWR);
|
||||
if(fd<0){
|
||||
if(fd<0) {
|
||||
perror("open");
|
||||
}
|
||||
}while(fd < 0 && errno == EBUSY);
|
||||
} while(fd < 0 && errno == EBUSY);
|
||||
|
||||
// No free bpf device was found
|
||||
if(fd < 0){
|
||||
if(fd < 0) {
|
||||
Debug("BPF: No minor number are free.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Enlarge buffer size
|
||||
n = 524288; // Somehow(In libpcap, this size is 32768)
|
||||
while(true){
|
||||
while(true) {
|
||||
// Specify buffer size
|
||||
ioctl(fd, BIOCSBLEN, &n);
|
||||
|
||||
// Bind to the network device
|
||||
StrCpy(ifr.ifr_name, IFNAMSIZ, name);
|
||||
ret = ioctl(fd, BIOCSETIF, &ifr);
|
||||
if(ret < 0){
|
||||
if(ret == ENOBUFS && n>1500){
|
||||
if(ret < 0) {
|
||||
if(ret == ENOBUFS && n>1500) {
|
||||
// Inappropriate buffer size
|
||||
// Retry with half buffer size
|
||||
// If buffer size is under 1500 bytes, something goes wrong
|
||||
@ -1287,15 +1287,15 @@ ETH *OpenEthBpf(char *name, bool local, bool tapmode, char *tapaddr)
|
||||
Debug("bpf: binding network failed.\n");
|
||||
close(fd);
|
||||
return NULL;
|
||||
}else{
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
bufsize = n;
|
||||
|
||||
// Set to promiscuous mode
|
||||
if(local == false){
|
||||
if (ioctl(fd, BIOCPROMISC, NULL) < 0){
|
||||
if(local == false) {
|
||||
if (ioctl(fd, BIOCPROMISC, NULL) < 0) {
|
||||
printf("bpf: promisc mode failed.\n");
|
||||
close(fd);
|
||||
return NULL;
|
||||
@ -1305,7 +1305,7 @@ ETH *OpenEthBpf(char *name, bool local, bool tapmode, char *tapaddr)
|
||||
|
||||
// Set to immediate mode (Return immediately when packet arrives)
|
||||
n = 1;
|
||||
if (ioctl(fd, BIOCIMMEDIATE, &n) < 0){
|
||||
if (ioctl(fd, BIOCIMMEDIATE, &n) < 0) {
|
||||
Debug("BPF: non-block mode failed.\n");
|
||||
close(fd);
|
||||
return NULL;
|
||||
@ -1313,7 +1313,7 @@ ETH *OpenEthBpf(char *name, bool local, bool tapmode, char *tapaddr)
|
||||
|
||||
// Set receiving self sending packet
|
||||
n = 1;
|
||||
if (ioctl(fd, BIOCGSEESENT, &n) < 0){
|
||||
if (ioctl(fd, BIOCGSEESENT, &n) < 0) {
|
||||
Debug("BPF: see sent mode failed.\n");
|
||||
close(fd);
|
||||
return NULL;
|
||||
@ -1321,7 +1321,7 @@ ETH *OpenEthBpf(char *name, bool local, bool tapmode, char *tapaddr)
|
||||
|
||||
// Header complete mode (Generate whole header of sending packet)
|
||||
n = 1;
|
||||
if (ioctl(fd, BIOCSHDRCMPLT, &n) < 0){
|
||||
if (ioctl(fd, BIOCSHDRCMPLT, &n) < 0) {
|
||||
Debug("BPF: Header complete mode failed.\n");
|
||||
close(fd);
|
||||
return NULL;
|
||||
@ -1330,7 +1330,7 @@ ETH *OpenEthBpf(char *name, bool local, bool tapmode, char *tapaddr)
|
||||
// Set timeout delay to 1 second
|
||||
to.tv_sec = 1;
|
||||
to.tv_usec = 0;
|
||||
if (ioctl(fd, BIOCSRTIMEOUT, &to) < 0){
|
||||
if (ioctl(fd, BIOCSRTIMEOUT, &to) < 0) {
|
||||
Debug("BPF: Read timeout setting failed.\n");
|
||||
close(fd);
|
||||
return NULL;
|
||||
@ -1401,16 +1401,16 @@ ETH *OpenEthBSD(char *name, bool local, bool tapmode, char *tapaddr)
|
||||
|
||||
return e;
|
||||
#else // NO_VLAN
|
||||
return NULL:
|
||||
return NULL:
|
||||
#endif // NO_VLAN
|
||||
}
|
||||
|
||||
#if defined(BRIDGE_BPF)
|
||||
return OpenEthBpf(name, local, tapmode, tapaddr);
|
||||
return OpenEthBpf(name, local, tapmode, tapaddr);
|
||||
#elif defined(BRIDGE_PCAP)
|
||||
return OpenEthPcap(name, local, tapmode, tapaddr);
|
||||
return OpenEthPcap(name, local, tapmode, tapaddr);
|
||||
#else
|
||||
return NULL;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
#endif // UNIX_BSD
|
||||
@ -1471,7 +1471,7 @@ void CloseEth(ETH *e)
|
||||
WaitThread(e->CaptureThread, INFINITE);
|
||||
ReleaseThread(e->CaptureThread);
|
||||
pcap_close(e->Pcap);
|
||||
while (block = GetNext(e->Queue)){
|
||||
while (block = GetNext(e->Queue)) {
|
||||
Free(block->Buf);
|
||||
FreeCaptureBlock(block);
|
||||
}
|
||||
@ -1488,7 +1488,7 @@ void CloseEth(ETH *e)
|
||||
WaitThread(e->CaptureThread, INFINITE);
|
||||
ReleaseThread(e->CaptureThread);
|
||||
e->Socket = fd; // restore to close after
|
||||
while (block = GetNext(e->Queue)){
|
||||
while (block = GetNext(e->Queue)) {
|
||||
Free(block->Buf);
|
||||
FreeCaptureBlock(block);
|
||||
}
|
||||
@ -1660,8 +1660,8 @@ UINT EthGetPacketLinux(ETH *e, void **data)
|
||||
USHORT vlan_id = 0;
|
||||
|
||||
if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct my_tpacket_auxdata)) ||
|
||||
cmsg->cmsg_level != SOL_PACKET ||
|
||||
cmsg->cmsg_type != MY_PACKET_AUXDATA)
|
||||
cmsg->cmsg_level != SOL_PACKET ||
|
||||
cmsg->cmsg_type != MY_PACKET_AUXDATA)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -1772,14 +1772,14 @@ UINT EthGetPacketPcap(ETH *e, void **data)
|
||||
|
||||
LockQueue(e->Queue);
|
||||
block = GetNext(e->Queue);
|
||||
if(block != NULL){
|
||||
if(block != NULL) {
|
||||
e->QueueSize -= block->Size;
|
||||
}
|
||||
UnlockQueue(e->Queue);
|
||||
|
||||
if(block == NULL){
|
||||
if(block == NULL) {
|
||||
*data = NULL;
|
||||
if(e->Socket == INVALID_SOCKET){
|
||||
if(e->Socket == INVALID_SOCKET) {
|
||||
return INFINITE;
|
||||
}
|
||||
return 0;
|
||||
@ -1802,14 +1802,14 @@ UINT EthGetPacketBpf(ETH *e, void **data)
|
||||
|
||||
LockQueue(e->Queue);
|
||||
block = GetNext(e->Queue);
|
||||
if(block != NULL){
|
||||
if(block != NULL) {
|
||||
e->QueueSize -= block->Size;
|
||||
}
|
||||
UnlockQueue(e->Queue);
|
||||
|
||||
if(block == NULL){
|
||||
if(block == NULL) {
|
||||
*data = NULL;
|
||||
if(e->Socket == INVALID_SOCKET){
|
||||
if(e->Socket == INVALID_SOCKET) {
|
||||
return INFINITE;
|
||||
}
|
||||
return 0;
|
||||
@ -1826,11 +1826,11 @@ UINT EthGetPacketBpf(ETH *e, void **data)
|
||||
{
|
||||
struct bpf_hdr *hdr;
|
||||
|
||||
if(e->Rest<=0){
|
||||
if(e->Rest<=0) {
|
||||
e->Rest = read(e->Socket, e->Buffer, e->BufSize);
|
||||
if(e->Rest < 0){
|
||||
if(e->Rest < 0) {
|
||||
*data = NULL;
|
||||
if(errno != EAGAIN){
|
||||
if(errno != EAGAIN) {
|
||||
// Error
|
||||
return INFINITE;
|
||||
}
|
||||
@ -1840,7 +1840,7 @@ UINT EthGetPacketBpf(ETH *e, void **data)
|
||||
e->Next = e->Buffer;
|
||||
}
|
||||
// Cut out a packet
|
||||
hdr = (struct bpf_hdr*)e->Next;
|
||||
hdr = (struct bpf_hdr *)e->Next;
|
||||
*data = Malloc(hdr->bh_caplen);
|
||||
Copy(*data, e->Next+(hdr->bh_hdrlen), hdr->bh_caplen);
|
||||
|
||||
@ -1864,7 +1864,7 @@ void EthPutPackets(ETH *e, UINT num, void **datas, UINT *sizes)
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0;i < num;i++)
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
EthPutPacket(e, datas[i], sizes[i]);
|
||||
}
|
||||
@ -1910,7 +1910,7 @@ void EthPutPacket(ETH *e, void *data, UINT size)
|
||||
// Send to device
|
||||
#ifdef BRIDGE_PCAP
|
||||
ret = pcap_inject(e->Pcap, data, size);
|
||||
if( ret == -1 ){
|
||||
if( ret == -1 ) {
|
||||
#ifdef _DEBUG
|
||||
pcap_perror(e->Pcap, "inject");
|
||||
#endif // _DEBUG
|
||||
@ -2162,7 +2162,7 @@ LABEL_RETRY:
|
||||
UINTToIP(&original_dest_ip, ip->DstIP);
|
||||
|
||||
if (IsZeroIP(&e->MyPhysicalIPForce) == false && CmpIpAddr(&e->MyPhysicalIPForce, &original_dest_ip) == 0 ||
|
||||
(IsIPMyHost(&original_dest_ip) && IsLocalHostIP(&original_dest_ip) == false && IsHostIPAddress4(&original_dest_ip)))
|
||||
(IsIPMyHost(&original_dest_ip) && IsLocalHostIP(&original_dest_ip) == false && IsHostIPAddress4(&original_dest_ip)))
|
||||
{
|
||||
if (IsZeroIP(&e->MyPhysicalIPForce) && CmpIpAddr(&e->MyPhysicalIP, &original_dest_ip) != 0)
|
||||
{
|
||||
@ -2183,14 +2183,14 @@ LABEL_RETRY:
|
||||
if (p->TypeL4 == L4_TCP)
|
||||
{
|
||||
TCP_HEADER *tcp = p->L4.TCPHeader;
|
||||
/*
|
||||
if (Endian16(tcp->SrcPort) == 80)
|
||||
{
|
||||
IP a, b;
|
||||
UINTToIP(&a, ip->SrcIP);
|
||||
UINTToIP(&b, ip->DstIP);
|
||||
Debug("%r %r %u %u\n", &a, &b, Endian16(tcp->SrcPort), Endian16(tcp->DstPort));
|
||||
}*/
|
||||
/*
|
||||
if (Endian16(tcp->SrcPort) == 80)
|
||||
{
|
||||
IP a, b;
|
||||
UINTToIP(&a, ip->SrcIP);
|
||||
UINTToIP(&b, ip->DstIP);
|
||||
Debug("%r %r %u %u\n", &a, &b, Endian16(tcp->SrcPort), Endian16(tcp->DstPort));
|
||||
}*/
|
||||
|
||||
ok = true;
|
||||
}
|
||||
@ -2226,7 +2226,7 @@ LABEL_RETRY:
|
||||
if (inner_icmp_size >= (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
|
||||
{
|
||||
ICMP_HEADER *inner_icmp = (ICMP_HEADER *)(((UCHAR *)data) +
|
||||
sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + orig_ipv4_header_size);
|
||||
sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + orig_ipv4_header_size);
|
||||
|
||||
if (inner_icmp->Type == ICMP_TYPE_ECHO_REQUEST)
|
||||
{
|
||||
@ -2328,8 +2328,8 @@ bool EthProcessIpPacketInnerIpRaw(ETH *e, PKT *p)
|
||||
ARPV4_HEADER *arp = p->L3.ARPv4Header;
|
||||
|
||||
if (Endian16(arp->HardwareType) == ARP_HARDWARE_TYPE_ETHERNET &&
|
||||
Endian16(arp->ProtocolType) == MAC_PROTO_IPV4 &&
|
||||
arp->HardwareSize == 6 && arp->ProtocolType == 4)
|
||||
Endian16(arp->ProtocolType) == MAC_PROTO_IPV4 &&
|
||||
arp->HardwareSize == 6 && arp->ProtocolType == 4)
|
||||
{
|
||||
if (IPToUINT(&e->MyIP) == arp->TargetIP)
|
||||
{
|
||||
@ -2460,8 +2460,8 @@ bool EthProcessIpPacketInnerIpRaw(ETH *e, PKT *p)
|
||||
UINTToIP(&ips, ip);
|
||||
IPToStr(client_ip, sizeof(client_ip), &ips);
|
||||
Debug("IP_RAW: DHCP %s : %s given %s\n",
|
||||
ret.Opcode == DHCP_OFFER ? "DHCP_OFFER" : "DHCP_ACK",
|
||||
client_mac, client_ip);
|
||||
ret.Opcode == DHCP_OFFER ? "DHCP_OFFER" : "DHCP_ACK",
|
||||
client_mac, client_ip);
|
||||
}
|
||||
|
||||
// Build a DHCP option
|
||||
@ -2538,7 +2538,7 @@ bool EthProcessIpPacketInnerIpRaw(ETH *e, PKT *p)
|
||||
udp->DstPort = Endian16(NAT_DHCP_CLIENT_PORT);
|
||||
udp->PacketLength = Endian16(sizeof(UDP_HEADER) + dhcp_packet_size);
|
||||
udp->Checksum = CalcChecksumForIPv4(ipv4->SrcIP, ipv4->DstIP, IP_PROTO_UDP,
|
||||
dhcp, dhcp_packet_size, 0);
|
||||
dhcp, dhcp_packet_size, 0);
|
||||
if (udp->Checksum == 0)
|
||||
{
|
||||
udp->Checksum = 0xffff;
|
||||
@ -2589,14 +2589,14 @@ 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 ||
|
||||
(p->BroadcastPacket == false && Cmp(p->MacAddressDest, e->RawIpMyMacAddr, 6) != 0))
|
||||
if (IsZero(e->RawIpYourMacAddr, 6) || IsMacUnicast(p->MacAddressSrc) == false ||
|
||||
(p->BroadcastPacket == false && Cmp(p->MacAddressDest, e->RawIpMyMacAddr, 6) != 0))
|
||||
{
|
||||
Free(data);
|
||||
FreePacket(p);
|
||||
@ -2641,7 +2641,7 @@ void EthPutPacketLinuxIpRaw(ETH *e, void *data, UINT size)
|
||||
}
|
||||
|
||||
if (s != NULL && p->L3.IPv4Header->DstIP != 0xffffffff && p->BroadcastPacket == false &&
|
||||
p->L3.IPv4Header->SrcIP == IPToUINT(&e->YourIP))
|
||||
p->L3.IPv4Header->SrcIP == IPToUINT(&e->YourIP))
|
||||
{
|
||||
UCHAR *send_data = p->IPv4PayloadData;
|
||||
UCHAR *head = p->PacketData;
|
||||
@ -2661,8 +2661,8 @@ void EthPutPacketLinuxIpRaw(ETH *e, void *data, UINT size)
|
||||
{
|
||||
p->L4.TCPHeader->Checksum = 0;
|
||||
p->L4.TCPHeader->Checksum = CalcChecksumForIPv4(IPToUINT(&e->MyPhysicalIP),
|
||||
p->L3.IPv4Header->DstIP, IP_PROTO_TCP,
|
||||
p->L4.TCPHeader, p->IPv4PayloadSize, 0);
|
||||
p->L3.IPv4Header->DstIP, IP_PROTO_TCP,
|
||||
p->L4.TCPHeader, p->IPv4PayloadSize, 0);
|
||||
}
|
||||
|
||||
UINTToIP(&dest, p->L3.IPv4Header->DstIP);
|
||||
|
@ -583,6 +583,7 @@ 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;
|
||||
|
||||
|
||||
// ==============================================================
|
||||
|
243
src/Cedar/IPC.c
243
src/Cedar/IPC.c
@ -147,7 +147,7 @@ void IPCAsyncThreadProc(THREAD *thread, void *param)
|
||||
|
||||
// Save the options list
|
||||
Copy(&a->L3ClientAddressOption, &cao, sizeof(DHCP_OPTION_LIST));
|
||||
a->L3DhcpRenewInterval = t * 1000;
|
||||
a->L3DhcpRenewInterval = (UINT64)t * (UINT64)1000;
|
||||
|
||||
// Set the obtained IP address parameters to the IPC virtual host
|
||||
UINTToIP(&ip, cao.ClientAddress);
|
||||
@ -488,6 +488,10 @@ IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char
|
||||
|
||||
// Create an IPv4 reception queue
|
||||
ipc->IPv4ReceivedQueue = NewQueue();
|
||||
ipc->IPv4State = IPC_PROTO_STATUS_CLOSED;
|
||||
|
||||
ipc->DHCPv4Awaiter.IsAwaiting = false;
|
||||
ipc->DHCPv4Awaiter.DhcpData = NULL;
|
||||
|
||||
IPCIPv6Init(ipc);
|
||||
|
||||
@ -530,6 +534,10 @@ IPC *NewIPCBySock(CEDAR *cedar, SOCK *s, void *mac_address)
|
||||
|
||||
// Create an IPv4 reception queue
|
||||
ipc->IPv4ReceivedQueue = NewQueue();
|
||||
ipc->IPv4State = IPC_PROTO_STATUS_CLOSED;
|
||||
|
||||
ipc->DHCPv4Awaiter.IsAwaiting = false;
|
||||
ipc->DHCPv4Awaiter.DhcpData = NULL;
|
||||
|
||||
ipc->FlushList = NewTubeFlushList();
|
||||
|
||||
@ -614,6 +622,8 @@ void FreeIPC(IPC *ipc)
|
||||
|
||||
ReleaseSharedBuffer(ipc->IpcSessionSharedBuffer);
|
||||
|
||||
FreeDHCPv4Data(ipc->DHCPv4Awaiter.DhcpData);
|
||||
|
||||
IPCIPv6Free(ipc);
|
||||
|
||||
Free(ipc);
|
||||
@ -871,6 +881,9 @@ DHCPV4_DATA *IPCSendDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION
|
||||
// Time-out inspection
|
||||
if ((expecting_code != 0) && (now >= giveup_time))
|
||||
{
|
||||
ipc->DHCPv4Awaiter.IsAwaiting = false;
|
||||
FreeDHCPv4Data(ipc->DHCPv4Awaiter.DhcpData);
|
||||
ipc->DHCPv4Awaiter.DhcpData = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -880,6 +893,9 @@ DHCPV4_DATA *IPCSendDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION
|
||||
dhcp_packet = IPCBuildDhcpRequest(ipc, dest_ip, tran_id, opt);
|
||||
if (dhcp_packet == NULL)
|
||||
{
|
||||
ipc->DHCPv4Awaiter.IsAwaiting = false;
|
||||
FreeDHCPv4Data(ipc->DHCPv4Awaiter.DhcpData);
|
||||
ipc->DHCPv4Awaiter.DhcpData = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -889,6 +905,9 @@ DHCPV4_DATA *IPCSendDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION
|
||||
|
||||
if (expecting_code == 0)
|
||||
{
|
||||
ipc->DHCPv4Awaiter.IsAwaiting = false;
|
||||
FreeDHCPv4Data(ipc->DHCPv4Awaiter.DhcpData);
|
||||
ipc->DHCPv4Awaiter.DhcpData = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -898,48 +917,28 @@ DHCPV4_DATA *IPCSendDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION
|
||||
}
|
||||
|
||||
// Happy processing
|
||||
ipc->DHCPv4Awaiter.IsAwaiting = true;
|
||||
FreeDHCPv4Data(ipc->DHCPv4Awaiter.DhcpData);
|
||||
ipc->DHCPv4Awaiter.DhcpData = NULL;
|
||||
ipc->DHCPv4Awaiter.TransCode = tran_id;
|
||||
ipc->DHCPv4Awaiter.OpCode = expecting_code;
|
||||
IPCProcessL3Events(ipc);
|
||||
|
||||
while (true)
|
||||
if (ipc->DHCPv4Awaiter.DhcpData != NULL)
|
||||
{
|
||||
// Receive a packet
|
||||
BLOCK *b = IPCRecvIPv4(ipc);
|
||||
PKT *pkt;
|
||||
DHCPV4_DATA *dhcp;
|
||||
|
||||
if (b == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Parse the packet
|
||||
pkt = ParsePacketIPv4WithDummyMacHeader(b->Buf, b->Size);
|
||||
|
||||
dhcp = ParseDHCPv4Data(pkt);
|
||||
|
||||
if (dhcp != NULL)
|
||||
{
|
||||
if (Endian32(dhcp->Header->TransactionId) == tran_id && dhcp->OpCode == expecting_code)
|
||||
{
|
||||
// Expected operation code and transaction ID are returned
|
||||
FreePacketWithData(pkt);
|
||||
FreeBlock(b);
|
||||
|
||||
return dhcp;
|
||||
}
|
||||
|
||||
FreeDHCPv4Data(dhcp);
|
||||
}
|
||||
|
||||
FreePacketWithData(pkt);
|
||||
|
||||
FreeBlock(b);
|
||||
DHCPV4_DATA *dhcp = ipc->DHCPv4Awaiter.DhcpData;
|
||||
ipc->DHCPv4Awaiter.IsAwaiting = false;
|
||||
ipc->DHCPv4Awaiter.DhcpData = NULL;
|
||||
return dhcp;
|
||||
}
|
||||
|
||||
if (IsTubeConnected(ipc->Sock->RecvTube) == false || IsTubeConnected(ipc->Sock->SendTube) == false ||
|
||||
(discon_poll_tube != NULL && IsTubeConnected(discon_poll_tube) == false))
|
||||
{
|
||||
// Session is disconnected
|
||||
ipc->DHCPv4Awaiter.IsAwaiting = false;
|
||||
FreeDHCPv4Data(ipc->DHCPv4Awaiter.DhcpData);
|
||||
ipc->DHCPv4Awaiter.DhcpData = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -947,6 +946,9 @@ DHCPV4_DATA *IPCSendDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION
|
||||
WaitForTubes(tubes, num_tubes, GetNextIntervalForInterrupt(ipc->Interrupt));
|
||||
}
|
||||
|
||||
ipc->DHCPv4Awaiter.IsAwaiting = false;
|
||||
FreeDHCPv4Data(ipc->DHCPv4Awaiter.DhcpData);
|
||||
ipc->DHCPv4Awaiter.DhcpData = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1301,6 +1303,16 @@ void IPCProcessL3Events(IPC *ipc)
|
||||
{
|
||||
IPCProcessL3EventsEx(ipc, 0);
|
||||
}
|
||||
void IPCProcessL3EventsIPv4Only(IPC *ipc)
|
||||
{
|
||||
UINT previousStatus4 = IPC_PROTO_GET_STATUS(ipc, IPv4State);
|
||||
UINT previousStatus6 = IPC_PROTO_GET_STATUS(ipc, IPv6State);
|
||||
IPC_PROTO_SET_STATUS(ipc, IPv4State, IPC_PROTO_STATUS_OPENED);
|
||||
IPC_PROTO_SET_STATUS(ipc, IPv6State, IPC_PROTO_STATUS_CLOSED);
|
||||
IPCProcessL3Events(ipc);
|
||||
IPC_PROTO_SET_STATUS(ipc, IPv4State, previousStatus4);
|
||||
IPC_PROTO_SET_STATUS(ipc, IPv6State, previousStatus6);
|
||||
}
|
||||
void IPCProcessL3EventsEx(IPC *ipc, UINT64 now)
|
||||
{
|
||||
// Validate arguments
|
||||
@ -1340,6 +1352,7 @@ void IPCProcessL3EventsEx(IPC *ipc, UINT64 now)
|
||||
// If the source MAC address is itselves or invalid address, ignore the packet
|
||||
if (Cmp(src_mac, ipc->MacAddress, 6) != 0 && !IsMacUnicast(src_mac))
|
||||
{
|
||||
Debug("Received packed for L3 parsing\n");
|
||||
if (protocol == MAC_PROTO_ARPV4)
|
||||
{
|
||||
// ARP receiving process
|
||||
@ -1347,6 +1360,7 @@ void IPCProcessL3EventsEx(IPC *ipc, UINT64 now)
|
||||
}
|
||||
else if (protocol == MAC_PROTO_IPV4)
|
||||
{
|
||||
Debug("MAC_PROTO_IPV4\n");
|
||||
// IPv4 receiving process
|
||||
if (b->Size >= (14 + 20))
|
||||
{
|
||||
@ -1390,10 +1404,43 @@ void IPCProcessL3EventsEx(IPC *ipc, UINT64 now)
|
||||
|
||||
if (ok)
|
||||
{
|
||||
// Parse DHCP packets
|
||||
bool packetConsumed = false;
|
||||
if (ipc->DHCPv4Awaiter.IsAwaiting)
|
||||
{
|
||||
PKT *pkt;
|
||||
DHCPV4_DATA *dhcp;
|
||||
|
||||
Debug("Parsing for DHCP awaiter\n");
|
||||
pkt = ParsePacketIPv4WithDummyMacHeader(data, size);
|
||||
dhcp = ParseDHCPv4Data(pkt);
|
||||
|
||||
if (dhcp != NULL)
|
||||
{
|
||||
if (Endian32(dhcp->Header->TransactionId) == ipc->DHCPv4Awaiter.TransCode &&
|
||||
dhcp->OpCode == ipc->DHCPv4Awaiter.OpCode)
|
||||
{
|
||||
FreeDHCPv4Data(ipc->DHCPv4Awaiter.DhcpData);
|
||||
ipc->DHCPv4Awaiter.DhcpData = dhcp;
|
||||
packetConsumed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
FreeDHCPv4Data(dhcp);
|
||||
}
|
||||
}
|
||||
|
||||
FreePacket(pkt);
|
||||
}
|
||||
|
||||
IPCAssociateOnArpTable(ipc, &ip_src, src_mac);
|
||||
|
||||
// Place in the reception queue
|
||||
InsertQueue(ipc->IPv4ReceivedQueue, NewBlock(data, size, 0));
|
||||
if (ipc->IPv4State == IPC_PROTO_STATUS_OPENED && !packetConsumed)
|
||||
{
|
||||
// Place in the reception queue
|
||||
InsertQueue(ipc->IPv4ReceivedQueue, NewBlock(data, size, 0));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1409,8 +1456,9 @@ void IPCProcessL3EventsEx(IPC *ipc, UINT64 now)
|
||||
{
|
||||
IP ip_src, ip_dst;
|
||||
bool ndtProcessed = false;
|
||||
UINT size = p->L3.IPv6Header->PayloadLength + sizeof(IPV6_HEADER);
|
||||
|
||||
UCHAR *data = Clone(p->L3.IPv6Header, p->L3.IPv6Header->PayloadLength + sizeof(IPV6_HEADER));
|
||||
UCHAR *data = Clone(p->L3.IPv6Header, size);
|
||||
|
||||
IPv6AddrToIP(&ip_src, &p->IPv6HeaderPacketInfo.IPv6Header->SrcAddress);
|
||||
IPv6AddrToIP(&ip_dst, &p->IPv6HeaderPacketInfo.IPv6Header->DestAddress);
|
||||
@ -1426,7 +1474,7 @@ void IPCProcessL3EventsEx(IPC *ipc, UINT64 now)
|
||||
// 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);
|
||||
IPCIPv6AssociateOnNDTEx(ipc, &ip_src, &p->ICMPv6HeaderPacketInfo.OptionList.SourceLinkLayer->Address, true);
|
||||
break;
|
||||
case ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT:
|
||||
// We save the neighbor advertisements into NDT
|
||||
@ -1445,7 +1493,10 @@ void IPCProcessL3EventsEx(IPC *ipc, UINT64 now)
|
||||
}
|
||||
|
||||
/// TODO: should we or not filter Neighbor Advertisements and/or Neighbor Solicitations?
|
||||
InsertQueue(ipc->IPv6ReceivedQueue, data);
|
||||
if (ipc->IPv6State == IPC_PROTO_STATUS_OPENED)
|
||||
{
|
||||
InsertQueue(ipc->IPv6ReceivedQueue, NewBlock(data, size, 0));
|
||||
}
|
||||
|
||||
FreePacket(p);
|
||||
}
|
||||
@ -1948,6 +1999,8 @@ void IPCIPv6Init(IPC *ipc)
|
||||
|
||||
ipc->IPv6ClientEUI = 0;
|
||||
ipc->IPv6ServerEUI = 0;
|
||||
|
||||
ipc->IPv6State = IPC_PROTO_STATUS_CLOSED;
|
||||
}
|
||||
void IPCIPv6Free(IPC *ipc)
|
||||
{
|
||||
@ -2113,14 +2166,31 @@ void IPCIPv6FlushNDTEx(IPC *ipc, UINT64 now)
|
||||
}
|
||||
}
|
||||
|
||||
bool IPCIPv6CheckExistingLinkLocal(IPC *ipc, IP *addr)
|
||||
// Scan the hub IP Table to try to find the EUI-based link-local address
|
||||
bool IPCIPv6CheckExistingLinkLocal(IPC *ipc, UINT64 eui)
|
||||
{
|
||||
HUB t, *h;
|
||||
IP_TABLE_ENTRY t, *e;
|
||||
IP_TABLE_ENTRY i, *e;
|
||||
t.Name = ipc->HubName;
|
||||
|
||||
// Construct link local from eui
|
||||
ZeroIP6(&i.Ip);
|
||||
i.Ip.ipv6_addr[0] = 0xFE;
|
||||
i.Ip.ipv6_addr[1] = 0x80;
|
||||
WRITE_UINT64(&i.Ip.ipv6_addr[8], &eui);
|
||||
|
||||
h = Search(ipc->Cedar->HubList, &t);
|
||||
|
||||
//h->IpTable
|
||||
if (h != NULL)
|
||||
{
|
||||
e = Search(h->IpTable, &i);
|
||||
if (e != NULL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// RA
|
||||
@ -2175,45 +2245,66 @@ bool IPCIPv6CheckUnicastFromRouterPrefix(IPC *ipc, IP *ip, IPC_IPV6_ROUTER_ADVER
|
||||
}
|
||||
|
||||
// Send router solicitation and then eventually populate the info from Router Advertisements
|
||||
void IPCIPv6SendRouterSolicitation(IPC *ipc)
|
||||
UINT64 IPCIPv6GetServerEui(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)
|
||||
// It is already configured, nothing to do here
|
||||
if (ipc->IPv6ServerEUI != 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);
|
||||
return ipc->IPv6ServerEUI;
|
||||
}
|
||||
|
||||
AddInterrupt(ipc->Interrupt, timeout_retry);
|
||||
// If we don't have a valid client EUI, we can't generate a correct link local
|
||||
if (ipc->IPv6ClientEUI == 0)
|
||||
{
|
||||
return ipc->IPv6ServerEUI;
|
||||
}
|
||||
|
||||
if (Tick64() >= giveup_time)
|
||||
if (LIST_NUM(ipc->IPv6RouterAdvs) == 0)
|
||||
{
|
||||
IP senderIP;
|
||||
IPV6_ADDR senderV6;
|
||||
IP destIP;
|
||||
IPV6_ADDR destV6;
|
||||
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]);
|
||||
|
||||
IPToIPv6Addr(&senderV6, &senderIP);
|
||||
IPToIPv6Addr(&destV6, &destIP);
|
||||
|
||||
packet = BuildICMPv6RouterSoliciation(&senderV6, &destV6, ipc->MacAddress, 0);
|
||||
|
||||
while (LIST_NUM(ipc->IPv6RouterAdvs) == 0)
|
||||
{
|
||||
// We failed to receive any router advertisements
|
||||
break;
|
||||
}
|
||||
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);
|
||||
|
||||
// The processing should populate the received RAs by itself
|
||||
IPCProcessL3Events(ipc);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Populating the IPv6 Server EUI for IPV6CP
|
||||
@ -2222,6 +2313,8 @@ void IPCIPv6SendRouterSolicitation(IPC *ipc)
|
||||
IPC_IPV6_ROUTER_ADVERTISEMENT *ra = LIST_DATA(ipc->IPv6RouterAdvs, 0);
|
||||
ipc->IPv6ServerEUI = READ_UINT64(&ra->RouterAddress.ipv6_addr[8]);
|
||||
}
|
||||
|
||||
return ipc->IPv6ServerEUI;
|
||||
}
|
||||
|
||||
// Data flow
|
||||
|
@ -30,6 +30,16 @@
|
||||
#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
|
||||
|
||||
// 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
|
||||
{
|
||||
@ -78,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
|
||||
{
|
||||
@ -117,6 +136,8 @@ 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
|
||||
@ -126,6 +147,7 @@ struct IPC
|
||||
|
||||
// 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)
|
||||
@ -166,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);
|
||||
@ -202,11 +225,11 @@ 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, IP *addr);
|
||||
bool IPCIPv6CheckExistingLinkLocal(IPC *ipc, UINT64 eui);
|
||||
// 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);
|
||||
UINT64 IPCIPv6GetServerEui(IPC *ipc);
|
||||
// Data flow
|
||||
BLOCK *IPCIPv6Recv(IPC *ipc);
|
||||
void IPCIPv6Send(IPC *ipc, void *data, UINT size);
|
||||
|
@ -259,13 +259,13 @@ void OvsLog(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c, char *na
|
||||
if (c == NULL)
|
||||
{
|
||||
UniFormat(prefix, sizeof(prefix), _UU("LO_PREFIX_SESSION"),
|
||||
se->Id, &se->ClientIp, se->ClientPort, &se->ServerIp, se->ServerPort);
|
||||
se->Id, &se->ClientIp, se->ClientPort, &se->ServerIp, se->ServerPort);
|
||||
}
|
||||
else
|
||||
{
|
||||
UniFormat(prefix, sizeof(prefix), _UU("LO_PREFIX_CHANNEL"),
|
||||
se->Id, &se->ClientIp, se->ClientPort, &se->ServerIp, se->ServerPort,
|
||||
c->KeyId);
|
||||
se->Id, &se->ClientIp, se->ClientPort, &se->ServerIp, se->ServerPort,
|
||||
c->KeyId);
|
||||
}
|
||||
}
|
||||
va_start(args, name);
|
||||
@ -617,10 +617,10 @@ void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p, UINT protocol)
|
||||
{
|
||||
// Control packet
|
||||
Debug("OvsProceccRecvPacket(): Received control packet. PacketId: %u, OpCode: %u, KeyId: %u, MySessionId: %I64u\n",
|
||||
recv_packet->PacketId, recv_packet->OpCode, recv_packet->KeyId, recv_packet->MySessionId);
|
||||
recv_packet->PacketId, recv_packet->OpCode, recv_packet->KeyId, recv_packet->MySessionId);
|
||||
|
||||
if (recv_packet->OpCode == OPENVPN_P_CONTROL_HARD_RESET_CLIENT_V2 ||
|
||||
recv_packet->OpCode == OPENVPN_P_CONTROL_SOFT_RESET_V1)
|
||||
recv_packet->OpCode == OPENVPN_P_CONTROL_SOFT_RESET_V1)
|
||||
{
|
||||
// Connection request packet
|
||||
if (c != NULL && c->Status == OPENVPN_CHANNEL_STATUS_ESTABLISHED)
|
||||
@ -644,19 +644,19 @@ void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p, UINT protocol)
|
||||
OvsLog(s, se, c, "LO_NEW_CHANNEL");
|
||||
}
|
||||
}
|
||||
/* else if (recv_packet->OpCode == OPENVPN_P_CONTROL_SOFT_RESET_V1)
|
||||
{
|
||||
// Response to soft reset request packet
|
||||
OPENVPN_PACKET *p;
|
||||
/* else if (recv_packet->OpCode == OPENVPN_P_CONTROL_SOFT_RESET_V1)
|
||||
{
|
||||
// Response to soft reset request packet
|
||||
OPENVPN_PACKET *p;
|
||||
|
||||
p = OvsNewControlPacket(OPENVPN_P_CONTROL_SOFT_RESET_V1, recv_packet->KeyId, se->ServerSessionId,
|
||||
0, NULL, 0, 0, 0, NULL);
|
||||
p = OvsNewControlPacket(OPENVPN_P_CONTROL_SOFT_RESET_V1, recv_packet->KeyId, se->ServerSessionId,
|
||||
0, NULL, 0, 0, 0, NULL);
|
||||
|
||||
OvsSendPacketNow(s, se, p);
|
||||
OvsSendPacketNow(s, se, p);
|
||||
|
||||
OvsFreePacket(p);
|
||||
}
|
||||
*/
|
||||
OvsFreePacket(p);
|
||||
}
|
||||
*/
|
||||
if (c != NULL)
|
||||
{
|
||||
// Delete the send packet list by looking the packet ID in the ACK list of arrived packet
|
||||
@ -668,8 +668,8 @@ void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p, UINT protocol)
|
||||
InsertIntDistinct(c->AckReplyList, recv_packet->PacketId);
|
||||
|
||||
if ((recv_packet->PacketId > c->MaxRecvPacketId)
|
||||
|| (recv_packet->OpCode == OPENVPN_P_CONTROL_HARD_RESET_CLIENT_V2)
|
||||
|| (recv_packet->OpCode == OPENVPN_P_CONTROL_SOFT_RESET_V1))
|
||||
|| (recv_packet->OpCode == OPENVPN_P_CONTROL_HARD_RESET_CLIENT_V2)
|
||||
|| (recv_packet->OpCode == OPENVPN_P_CONTROL_SOFT_RESET_V1))
|
||||
{
|
||||
c->MaxRecvPacketId = recv_packet->PacketId;
|
||||
|
||||
@ -743,12 +743,12 @@ void OvsDeleteFromSendingControlPacketList(OPENVPN_CHANNEL *c, UINT num_acks, UI
|
||||
}
|
||||
|
||||
o = NewListFast(NULL);
|
||||
for (i = 0;i < num_acks;i++)
|
||||
for (i = 0; i < num_acks; i++)
|
||||
{
|
||||
UINT ack = acks[i];
|
||||
UINT j;
|
||||
|
||||
for (j = 0;j < LIST_NUM(c->SendControlPacketList);j++)
|
||||
for (j = 0; j < LIST_NUM(c->SendControlPacketList); j++)
|
||||
{
|
||||
OPENVPN_CONTROL_PACKET *p = LIST_DATA(c->SendControlPacketList, j);
|
||||
|
||||
@ -759,7 +759,7 @@ void OvsDeleteFromSendingControlPacketList(OPENVPN_CHANNEL *c, UINT num_acks, UI
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0;i < LIST_NUM(o);i++)
|
||||
for (i = 0; i < LIST_NUM(o); i++)
|
||||
{
|
||||
OPENVPN_CONTROL_PACKET *p = LIST_DATA(o, i);
|
||||
|
||||
@ -1119,7 +1119,7 @@ UINT OvsPeekStringFromFifo(FIFO *f, char *str, UINT str_size)
|
||||
|
||||
StrCpy(str, str_size, "");
|
||||
|
||||
for (i = 0;i < MIN(str_size, FifoSize(f));i++)
|
||||
for (i = 0; i < MIN(str_size, FifoSize(f)); i++)
|
||||
{
|
||||
char c = *(((char *)FifoPtr(f)) + i);
|
||||
|
||||
@ -1267,8 +1267,8 @@ void OvsSetupSessionParameters(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_C
|
||||
WriteBuf(b, c->ClientKey.Random1, sizeof(c->ClientKey.Random1));
|
||||
WriteBuf(b, c->ServerKey.Random1, sizeof(c->ServerKey.Random1));
|
||||
Enc_tls1_PRF(b->Buf, b->Size,
|
||||
c->ClientKey.PreMasterSecret, sizeof(c->ClientKey.PreMasterSecret),
|
||||
c->MasterSecret, sizeof(c->MasterSecret));
|
||||
c->ClientKey.PreMasterSecret, sizeof(c->ClientKey.PreMasterSecret),
|
||||
c->MasterSecret, sizeof(c->MasterSecret));
|
||||
FreeBuf(b);
|
||||
|
||||
// Generate an Expansion Key
|
||||
@ -1279,7 +1279,7 @@ void OvsSetupSessionParameters(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_C
|
||||
WriteBufInt64(b, se->ClientSessionId);
|
||||
WriteBufInt64(b, se->ServerSessionId);
|
||||
Enc_tls1_PRF(b->Buf, b->Size, c->MasterSecret, sizeof(c->MasterSecret),
|
||||
c->ExpansionKey, sizeof(c->ExpansionKey));
|
||||
c->ExpansionKey, sizeof(c->ExpansionKey));
|
||||
FreeBuf(b);
|
||||
|
||||
// Set up the encryption algorithm
|
||||
@ -1314,13 +1314,13 @@ void OvsSetupSessionParameters(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_C
|
||||
|
||||
// Generate the response option string
|
||||
Format(c->ServerKey.OptionString, sizeof(c->ServerKey.OptionString),
|
||||
"V4,dev-type %s,link-mtu %u,tun-mtu %u,proto %s,"
|
||||
"cipher %s,auth %s,keysize %u,key-method 2,tls-server",
|
||||
(se->Mode == OPENVPN_MODE_L2 ? "tap" : "tun"),
|
||||
se->LinkMtu,
|
||||
se->TunMtu,
|
||||
c->Proto,
|
||||
cipher_name, md_name, c->CipherEncrypt->KeySize * 8);
|
||||
"V4,dev-type %s,link-mtu %u,tun-mtu %u,proto %s,"
|
||||
"cipher %s,auth %s,keysize %u,key-method 2,tls-server",
|
||||
(se->Mode == OPENVPN_MODE_L2 ? "tap" : "tun"),
|
||||
se->LinkMtu,
|
||||
se->TunMtu,
|
||||
c->Proto,
|
||||
cipher_name, md_name, c->CipherEncrypt->KeySize * 8);
|
||||
|
||||
FreeEntryList(o);
|
||||
|
||||
@ -1482,13 +1482,13 @@ UINT OvsParseKeyMethod2(OPENVPN_KEY_METHOD_2 *ret, UCHAR *data, UINT size, bool
|
||||
{
|
||||
// String
|
||||
if (OvsReadStringFromBuf(b, ret->OptionString, sizeof(ret->OptionString)) &&
|
||||
OvsReadStringFromBuf(b, ret->Username, sizeof(ret->Username)) &&
|
||||
OvsReadStringFromBuf(b, ret->Password, sizeof(ret->Password)))
|
||||
OvsReadStringFromBuf(b, ret->Username, sizeof(ret->Username)) &&
|
||||
OvsReadStringFromBuf(b, ret->Password, sizeof(ret->Password)))
|
||||
{
|
||||
if (!OvsReadStringFromBuf(b, ret->PeerInfo, sizeof(ret->PeerInfo)))
|
||||
{
|
||||
if (!OvsReadStringFromBuf(b, ret->PeerInfo, sizeof(ret->PeerInfo)))
|
||||
{
|
||||
Zero(ret->PeerInfo, sizeof(ret->PeerInfo));
|
||||
}
|
||||
Zero(ret->PeerInfo, sizeof(ret->PeerInfo));
|
||||
}
|
||||
read_size = b->Current;
|
||||
}
|
||||
}
|
||||
@ -1637,7 +1637,7 @@ UINT OvsGetAckReplyList(OPENVPN_CHANNEL *c, UINT *ret)
|
||||
|
||||
num = MIN(LIST_NUM(c->AckReplyList), OPENVPN_MAX_NUMACK);
|
||||
|
||||
for (i = 0;i < num;i++)
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
UINT *v = LIST_DATA(c->AckReplyList, i);
|
||||
|
||||
@ -1651,7 +1651,7 @@ UINT OvsGetAckReplyList(OPENVPN_CHANNEL *c, UINT *ret)
|
||||
ret[i] = *v;
|
||||
}
|
||||
|
||||
for (i = 0;i < LIST_NUM(o);i++)
|
||||
for (i = 0; i < LIST_NUM(o); i++)
|
||||
{
|
||||
UINT *v = LIST_DATA(o, i);
|
||||
|
||||
@ -1682,7 +1682,7 @@ void OvsFreeChannel(OPENVPN_CHANNEL *c)
|
||||
|
||||
ReleaseIntList(c->AckReplyList);
|
||||
|
||||
for (i = 0;i < LIST_NUM(c->SendControlPacketList);i++)
|
||||
for (i = 0; i < LIST_NUM(c->SendControlPacketList); i++)
|
||||
{
|
||||
OPENVPN_CONTROL_PACKET *p = LIST_DATA(c->SendControlPacketList, i);
|
||||
|
||||
@ -1758,7 +1758,7 @@ UINT64 OvsNewServerSessionId(OPENVPN_SERVER *s)
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0;i < LIST_NUM(s->SessionList);i++)
|
||||
for (i = 0; i < LIST_NUM(s->SessionList); i++)
|
||||
{
|
||||
OPENVPN_SESSION *se = LIST_DATA(s->SessionList, i);
|
||||
if (se->ServerSessionId == id)
|
||||
@ -1882,7 +1882,7 @@ BUF *OvsBuildPacket(OPENVPN_PACKET *p)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
for (i = 0;i < num_ack;i++)
|
||||
for (i = 0; i < num_ack; i++)
|
||||
{
|
||||
WriteBufInt(b, (UCHAR)p->AckPacketId[i]);
|
||||
}
|
||||
@ -1970,7 +1970,7 @@ OPENVPN_PACKET *OvsParsePacket(UCHAR *data, UINT size)
|
||||
goto LABEL_ERROR;
|
||||
}
|
||||
|
||||
for (i = 0;i < ret->NumAck;i++)
|
||||
for (i = 0; i < ret->NumAck; i++)
|
||||
{
|
||||
UINT ui;
|
||||
|
||||
@ -2066,7 +2066,7 @@ UINT OvsGetNumSessionByClientIp(OPENVPN_SERVER *s, IP *ip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0;i < LIST_NUM(s->SessionList);i++)
|
||||
for (i = 0; i < LIST_NUM(s->SessionList); i++)
|
||||
{
|
||||
OPENVPN_SESSION *se = LIST_DATA(s->SessionList, i);
|
||||
|
||||
@ -2130,7 +2130,7 @@ OPENVPN_SESSION *OvsNewSession(OPENVPN_SERVER *s, IP *server_ip, UINT server_por
|
||||
IPToStr(server_ip_str, sizeof(server_ip_str), server_ip);
|
||||
IPToStr(client_ip_str, sizeof(client_ip_str), client_ip);
|
||||
Debug("OpenVPN New Session: %s:%u -> %s:%u Proto=%u\n", server_ip_str, server_port,
|
||||
client_ip_str, client_port, protocol);
|
||||
client_ip_str, client_port, protocol);
|
||||
|
||||
OvsLog(s, se, NULL, "LO_NEW_SESSION", (protocol == OPENVPN_PROTOCOL_UDP ? "UDP" : "TCP"));
|
||||
|
||||
@ -2159,13 +2159,14 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Release the channel
|
||||
for (i = 0;i < OPENVPN_NUM_CHANNELS;i++)
|
||||
for (i = 0; i < OPENVPN_NUM_CHANNELS; i++)
|
||||
{
|
||||
OPENVPN_CHANNEL *c = se->Channels[i];
|
||||
|
||||
@ -2225,7 +2226,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
s->Now = Tick64();
|
||||
|
||||
// Process for all sessions
|
||||
for (i = 0;i < LIST_NUM(s->SessionList);i++)
|
||||
for (i = 0; i < LIST_NUM(s->SessionList); i++)
|
||||
{
|
||||
OPENVPN_SESSION *se = LIST_DATA(s->SessionList, i);
|
||||
|
||||
@ -2240,7 +2241,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
}
|
||||
|
||||
// Process received packets
|
||||
for (i = 0;i < LIST_NUM(recv_packet_list);i++)
|
||||
for (i = 0; i < LIST_NUM(recv_packet_list); i++)
|
||||
{
|
||||
UDPPACKET *p = LIST_DATA(recv_packet_list, i);
|
||||
|
||||
@ -2248,7 +2249,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
}
|
||||
|
||||
// Treat for all sessions and all channels
|
||||
for (i = 0;i < LIST_NUM(s->SessionList);i++)
|
||||
for (i = 0; i < LIST_NUM(s->SessionList); i++)
|
||||
{
|
||||
OPENVPN_CHANNEL *latest_channel = NULL;
|
||||
UINT64 max_tick = 0;
|
||||
@ -2259,11 +2260,11 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
{
|
||||
if (se->Mode == OPENVPN_MODE_L3)
|
||||
{
|
||||
IPCProcessL3Events(se->Ipc);
|
||||
IPCProcessL3EventsIPv4Only(se->Ipc);
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0;j < OPENVPN_NUM_CHANNELS;j++)
|
||||
for (j = 0; j < OPENVPN_NUM_CHANNELS; j++)
|
||||
{
|
||||
OPENVPN_CHANNEL *c = se->Channels[j];
|
||||
|
||||
@ -2320,9 +2321,9 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
|
||||
// Return the PUSH_REPLY
|
||||
Format(option_str, sizeof(option_str),
|
||||
"PUSH_REPLY,ping %u,ping-restart %u",
|
||||
(OPENVPN_PING_SEND_INTERVAL / 1000),
|
||||
(OPENVPN_RECV_TIMEOUT / 1000));
|
||||
"PUSH_REPLY,ping %u,ping-restart %u",
|
||||
(OPENVPN_PING_SEND_INTERVAL / 1000),
|
||||
(OPENVPN_RECV_TIMEOUT / 1000));
|
||||
|
||||
if (se->Mode == OPENVPN_MODE_L3)
|
||||
{
|
||||
@ -2344,26 +2345,26 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
ClearStr(ip_defgw, sizeof(ip_defgw));
|
||||
|
||||
IPToStr32(ip_client, sizeof(ip_client),
|
||||
cao->ClientAddress);
|
||||
cao->ClientAddress);
|
||||
|
||||
IPToStr32(ip_subnet_mask, sizeof(ip_subnet_mask),
|
||||
cao->SubnetMask);
|
||||
cao->SubnetMask);
|
||||
|
||||
Format(l3_options, sizeof(l3_options),
|
||||
",topology subnet");
|
||||
",topology subnet");
|
||||
StrCat(option_str, sizeof(option_str), l3_options);
|
||||
|
||||
Format(l3_options, sizeof(l3_options),
|
||||
",ifconfig %s %s",
|
||||
ip_client,
|
||||
ip_subnet_mask);
|
||||
",ifconfig %s %s",
|
||||
ip_client,
|
||||
ip_subnet_mask);
|
||||
StrCat(option_str, sizeof(option_str), l3_options);
|
||||
|
||||
// Domain name
|
||||
if (IsEmptyStr(cao->DomainName) == false)
|
||||
{
|
||||
Format(l3_options, sizeof(l3_options),
|
||||
",dhcp-option DOMAIN %s", cao->DomainName);
|
||||
",dhcp-option DOMAIN %s", cao->DomainName);
|
||||
StrCat(option_str, sizeof(option_str), l3_options);
|
||||
}
|
||||
|
||||
@ -2373,7 +2374,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
char ip_str[64];
|
||||
IPToStr32(ip_str, sizeof(ip_str), cao->DnsServer);
|
||||
Format(l3_options, sizeof(l3_options),
|
||||
",dhcp-option DNS %s", ip_str);
|
||||
",dhcp-option DNS %s", ip_str);
|
||||
StrCat(option_str, sizeof(option_str), l3_options);
|
||||
|
||||
StrCpy(ip_dns1, sizeof(ip_dns1), ip_str);
|
||||
@ -2385,7 +2386,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
char ip_str[64];
|
||||
IPToStr32(ip_str, sizeof(ip_str), cao->DnsServer2);
|
||||
Format(l3_options, sizeof(l3_options),
|
||||
",dhcp-option DNS %s", ip_str);
|
||||
",dhcp-option DNS %s", ip_str);
|
||||
StrCat(option_str, sizeof(option_str), l3_options);
|
||||
|
||||
StrCpy(ip_dns2, sizeof(ip_dns2), ip_str);
|
||||
@ -2397,7 +2398,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
char ip_str[64];
|
||||
IPToStr32(ip_str, sizeof(ip_str), cao->WinsServer);
|
||||
Format(l3_options, sizeof(l3_options),
|
||||
",dhcp-option WINS %s", ip_str);
|
||||
",dhcp-option WINS %s", ip_str);
|
||||
StrCat(option_str, sizeof(option_str), l3_options);
|
||||
|
||||
StrCpy(ip_wins1, sizeof(ip_wins1), ip_str);
|
||||
@ -2409,7 +2410,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
char ip_str[64];
|
||||
IPToStr32(ip_str, sizeof(ip_str), cao->WinsServer2);
|
||||
Format(l3_options, sizeof(l3_options),
|
||||
",dhcp-option WINS %s", ip_str);
|
||||
",dhcp-option WINS %s", ip_str);
|
||||
StrCat(option_str, sizeof(option_str), l3_options);
|
||||
|
||||
StrCpy(ip_wins2, sizeof(ip_wins2), ip_str);
|
||||
@ -2421,7 +2422,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
char ip_str[64];
|
||||
IPToStr32(ip_str, sizeof(ip_str), cao->Gateway);
|
||||
Format(l3_options, sizeof(l3_options),
|
||||
",route-gateway %s,redirect-gateway def1", ip_str);
|
||||
",route-gateway %s,redirect-gateway def1", ip_str);
|
||||
StrCat(option_str, sizeof(option_str), l3_options);
|
||||
|
||||
StrCpy(ip_defgw, sizeof(ip_defgw), ip_str);
|
||||
@ -2442,9 +2443,9 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
IPAnd4(&local_network, &client_ip, &subnet_mask);
|
||||
|
||||
Format(l3_options, sizeof(l3_options),
|
||||
",route %r %r vpn_gateway",
|
||||
&local_network,
|
||||
&cao->SubnetMask);
|
||||
",route %r %r vpn_gateway",
|
||||
&local_network,
|
||||
&cao->SubnetMask);
|
||||
|
||||
StrCat(option_str, sizeof(option_str), l3_options);
|
||||
#endif
|
||||
@ -2454,15 +2455,15 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
if (cao->ClasslessRoute.NumExistingRoutes >= 1)
|
||||
{
|
||||
UINT i;
|
||||
for (i = 0;i < MAX_DHCP_CLASSLESS_ROUTE_ENTRIES;i++)
|
||||
for (i = 0; i < MAX_DHCP_CLASSLESS_ROUTE_ENTRIES; i++)
|
||||
{
|
||||
DHCP_CLASSLESS_ROUTE *r = &cao->ClasslessRoute.Entries[i];
|
||||
|
||||
if (r->Exists)
|
||||
{
|
||||
Format(l3_options, sizeof(l3_options),
|
||||
",route %r %r vpn_gateway",
|
||||
&r->Network, &r->SubnetMask);
|
||||
",route %r %r vpn_gateway",
|
||||
&r->Network, &r->SubnetMask);
|
||||
|
||||
StrCat(option_str, sizeof(option_str), l3_options);
|
||||
}
|
||||
@ -2470,7 +2471,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
}
|
||||
|
||||
OvsLog(s, se, c, "LP_SET_IPV4_PARAM",
|
||||
ip_client, ip_subnet_mask, ip_defgw, ip_dns1, ip_dns2, ip_wins1, ip_wins2);
|
||||
ip_client, ip_subnet_mask, ip_defgw, ip_dns1, ip_dns2, ip_wins1, ip_wins2);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2579,8 +2580,8 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
Debug("RawOut Fifo Size (c=%u): %u\n", c->KeyId, FifoSize(c->SslPipe->RawOut->RecvFifo));
|
||||
|
||||
OvsSendControlPacketWithAutoSplit(c, OPENVPN_P_CONTROL_V1,
|
||||
FifoPtr(c->SslPipe->RawOut->RecvFifo),
|
||||
FifoSize(c->SslPipe->RawOut->RecvFifo));
|
||||
FifoPtr(c->SslPipe->RawOut->RecvFifo),
|
||||
FifoSize(c->SslPipe->RawOut->RecvFifo));
|
||||
|
||||
ReadFifo(c->SslPipe->RawOut->RecvFifo, NULL, FifoSize(c->SslPipe->RawOut->RecvFifo));
|
||||
}
|
||||
@ -2594,7 +2595,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
UINT k;
|
||||
|
||||
// Packet transmission
|
||||
for (k = 0;k < LIST_NUM(c->SendControlPacketList);k++)
|
||||
for (k = 0; k < LIST_NUM(c->SendControlPacketList); k++)
|
||||
{
|
||||
OPENVPN_CONTROL_PACKET *cp = LIST_DATA(c->SendControlPacketList, k);
|
||||
|
||||
@ -2609,7 +2610,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
num = OvsGetAckReplyList(c, acks);
|
||||
|
||||
p = OvsNewControlPacket(cp->OpCode, j, se->ServerSessionId, num, acks,
|
||||
se->ClientSessionId, cp->PacketId, cp->DataSize, cp->Data);
|
||||
se->ClientSessionId, cp->PacketId, cp->DataSize, cp->Data);
|
||||
|
||||
OvsSendPacketNow(s, se, p);
|
||||
|
||||
@ -2628,7 +2629,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
if (num >= 1)
|
||||
{
|
||||
OPENVPN_PACKET *p = OvsNewControlPacket(OPENVPN_P_ACK_V1, j, se->ServerSessionId,
|
||||
num, acks, se->ClientSessionId, 0, 0, NULL);
|
||||
num, acks, se->ClientSessionId, 0, 0, NULL);
|
||||
|
||||
OvsSendPacketNow(s, se, p);
|
||||
|
||||
@ -2656,14 +2657,14 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
}
|
||||
}
|
||||
|
||||
IPCProcessL3Events(se->Ipc);
|
||||
IPCProcessL3EventsIPv4Only(se->Ipc);
|
||||
}
|
||||
|
||||
IPCProcessInterrupts(se->Ipc);
|
||||
}
|
||||
|
||||
// Choose the latest channel in all established channels
|
||||
for (j = 0;j < OPENVPN_NUM_CHANNELS;j++)
|
||||
for (j = 0; j < OPENVPN_NUM_CHANNELS; j++)
|
||||
{
|
||||
OPENVPN_CHANNEL *c = se->Channels[j];
|
||||
|
||||
@ -2733,7 +2734,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
se->NextPingSendTick = s->Now + (UINT64)(OPENVPN_PING_SEND_INTERVAL);
|
||||
|
||||
OvsSendDataPacket(latest_channel, latest_channel->KeyId, ++latest_channel->LastDataPacketId,
|
||||
ping_signature, sizeof(ping_signature));
|
||||
ping_signature, sizeof(ping_signature));
|
||||
//Debug(".");
|
||||
|
||||
AddInterrupt(s->Interrupt, se->NextPingSendTick);
|
||||
@ -2765,7 +2766,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
|
||||
{
|
||||
UINT i;
|
||||
|
||||
for (i = 0;i < LIST_NUM(delete_session_list);i++)
|
||||
for (i = 0; i < LIST_NUM(delete_session_list); i++)
|
||||
{
|
||||
OPENVPN_SESSION *se = LIST_DATA(delete_session_list, i);
|
||||
|
||||
@ -2798,7 +2799,7 @@ void OvsSendPacketNow(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_PACKET *p)
|
||||
if (p->NumAck >= 1)
|
||||
{
|
||||
Debug("Sending ACK Packet IDs (c=%u): ", p->KeyId);
|
||||
for (i = 0;i < p->NumAck;i++)
|
||||
for (i = 0; i < p->NumAck; i++)
|
||||
{
|
||||
Debug("%u ", p->AckPacketId[i]);
|
||||
}
|
||||
@ -2844,14 +2845,14 @@ void OvsSendPacketRawNow(OPENVPN_SERVER *s, OPENVPN_SESSION *se, void *data, UIN
|
||||
}
|
||||
|
||||
u = NewUdpPacket(&se->ServerIp, se->ServerPort, &se->ClientIp, se->ClientPort,
|
||||
data, size);
|
||||
data, size);
|
||||
|
||||
Add(s->SendPacketList, u);
|
||||
}
|
||||
// Create a new OpenVPN control packet
|
||||
OPENVPN_PACKET *OvsNewControlPacket(UCHAR opcode, UCHAR key_id, UINT64 my_channel_id, UINT num_ack,
|
||||
UINT *ack_packet_ids, UINT64 your_channel_id, UINT packet_id,
|
||||
UINT data_size, UCHAR *data)
|
||||
UINT *ack_packet_ids, UINT64 your_channel_id, UINT packet_id,
|
||||
UINT data_size, UCHAR *data)
|
||||
{
|
||||
OPENVPN_PACKET *p = ZeroMalloc(sizeof(OPENVPN_PACKET));
|
||||
UINT i;
|
||||
@ -2861,7 +2862,7 @@ OPENVPN_PACKET *OvsNewControlPacket(UCHAR opcode, UCHAR key_id, UINT64 my_channe
|
||||
p->MySessionId = my_channel_id;
|
||||
p->NumAck = num_ack;
|
||||
|
||||
for (i = 0;i < MIN(num_ack, OPENVPN_MAX_NUMACK);i++)
|
||||
for (i = 0; i < MIN(num_ack, OPENVPN_MAX_NUMACK); i++)
|
||||
{
|
||||
p->AckPacketId[i] = ack_packet_ids[i];
|
||||
}
|
||||
|
@ -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,18 +315,21 @@ void PPPThread(THREAD *thread, void *param)
|
||||
if (p->PPPStatus == PPP_STATUS_NETWORK_LAYER)
|
||||
{
|
||||
UINT64 timeBeforeLoop;
|
||||
if (p->DhcpAllocated)
|
||||
if (IPC_PROTO_GET_STATUS(p->Ipc, IPv4State) == IPC_PROTO_STATUS_OPENED)
|
||||
{
|
||||
if (now >= p->DhcpNextRenewTime)
|
||||
if (p->DhcpAllocated)
|
||||
{
|
||||
IP ip;
|
||||
if (now >= p->DhcpNextRenewTime)
|
||||
{
|
||||
IP ip;
|
||||
|
||||
// DHCP renewal procedure
|
||||
p->DhcpNextRenewTime = now + p->DhcpRenewInterval;
|
||||
// DHCP renewal procedure
|
||||
p->DhcpNextRenewTime = now + p->DhcpRenewInterval;
|
||||
|
||||
UINTToIP(&ip, p->ClientAddressOption.ServerAddress);
|
||||
UINTToIP(&ip, p->ClientAddressOption.ServerAddress);
|
||||
|
||||
IPCDhcpRenewIP(p->Ipc, &ip);
|
||||
IPCDhcpRenewIP(p->Ipc, &ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -340,30 +340,73 @@ void PPPThread(THREAD *thread, void *param)
|
||||
while (true)
|
||||
{
|
||||
UINT64 nowL;
|
||||
BLOCK *b = IPCRecvIPv4(p->Ipc);
|
||||
PPP_PACKET *pp;
|
||||
PPP_PACKET tmp;
|
||||
if (b == NULL)
|
||||
bool no4packets = false;
|
||||
bool no6packets = false;
|
||||
if (IPC_PROTO_GET_STATUS(p->Ipc, IPv4State) == IPC_PROTO_STATUS_OPENED)
|
||||
{
|
||||
break;
|
||||
BLOCK *b = IPCRecvIPv4(p->Ipc);
|
||||
if (b == NULL)
|
||||
{
|
||||
no4packets = 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_IP;
|
||||
pp->Lcp = NULL;
|
||||
pp->Data = b->Buf;
|
||||
pp->DataSize = b->Size;
|
||||
|
||||
PPPSendPacketEx(p, pp, true);
|
||||
|
||||
FreePPPPacketEx(pp, true);
|
||||
Free(b);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
no4packets = true;
|
||||
}
|
||||
|
||||
// Since receiving the IP packet, send it to the client by PPP
|
||||
pp = &tmp;
|
||||
pp->IsControl = false;
|
||||
pp->Protocol = PPP_PROTOCOL_IP;
|
||||
pp->Lcp = NULL;
|
||||
pp->Data = b->Buf;
|
||||
pp->DataSize = b->Size;
|
||||
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;
|
||||
|
||||
PPPSendPacketEx(p, pp, true);
|
||||
// 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;
|
||||
|
||||
FreePPPPacketEx(pp, true);
|
||||
Free(b);
|
||||
PPPSendPacketEx(p, pp, true);
|
||||
|
||||
FreePPPPacketEx(pp, true);
|
||||
Free(b);
|
||||
}
|
||||
}
|
||||
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 (!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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user