1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2025-07-13 11:14:59 +03:00

v4.10-9505-beta

This commit is contained in:
dnobori
2014-10-04 00:09:23 +09:00
parent 16b713b98d
commit 10d4b2c43d
349 changed files with 2640 additions and 898 deletions

View File

@ -143,6 +143,22 @@
#include <ifaddrs.h>
#endif // BRIDGE_BPF
#ifdef UNIX_LINUX
struct my_tpacket_auxdata
{
UINT tp_status;
UINT tp_len;
UINT tp_snaplen;
USHORT tp_mac;
USHORT tp_net;
USHORT tp_vlan_tci;
USHORT tp_vlan_tpid;
};
#define MY_TP_STATUS_VLAN_VALID (1 << 4)
#define MY_TP_STATUS_VLAN_TPID_VALID (1 << 6)
#define MY_PACKET_AUXDATA 8
#endif // UNIX_LINUX
// Initialize
void InitEth()
{
@ -543,6 +559,7 @@ ETH *OpenEthLinux(char *name, bool local, bool tapmode, char *tapaddr)
struct sockaddr_ll addr;
int s;
int index;
bool aux_ok = false;
CANCEL *c;
// Validate arguments
if (name == NULL)
@ -624,12 +641,30 @@ ETH *OpenEthLinux(char *name, bool local, bool tapmode, char *tapaddr)
}
}
if (true)
{
int val = 1;
int ss_ret = setsockopt(s, SOL_PACKET, MY_PACKET_AUXDATA, &val, sizeof(val));
if (ss_ret < 0)
{
Debug("eth(%s): setsockopt: PACKET_AUXDATA failed.\n", name);
}
else
{
Debug("eth(%s): setsockopt: PACKET_AUXDATA ok.\n", name);
aux_ok = true;
}
}
e = ZeroMalloc(sizeof(ETH));
e->Name = CopyStr(name);
e->Title = CopyStr(name);
e->IfIndex = index;
e->Socket = s;
e->Linux_IsAuxDataSupported = aux_ok;
c = NewCancel();
UnixDeletePipe(c->pipe_read, c->pipe_write);
c->pipe_read = c->pipe_write = -1;
@ -646,8 +681,11 @@ ETH *OpenEthLinux(char *name, bool local, bool tapmode, char *tapaddr)
if (tapmode == false)
{
// Disable hardware offloading
UnixDisableInterfaceOffload(name);
if (GetGlobalServerFlag(GSF_LOCALBRIDGE_NO_DISABLE_OFFLOAD) == false)
{
// Disable hardware offloading
UnixDisableInterfaceOffload(name);
}
}
return e;
@ -1566,10 +1604,19 @@ UINT EthGetPacket(ETH *e, void **data)
}
#ifdef UNIX_LINUX
UINT EthGetPacketLinux(ETH *e, void **data)
{
int s, ret;
UCHAR tmp[UNIX_ETH_TMP_BUFFER_SIZE];
struct iovec msg_iov;
struct msghdr msg_header;
struct cmsghdr *cmsg;
union
{
struct cmsghdr cmsg;
char buf[CMSG_SPACE(sizeof(struct my_tpacket_auxdata))];
} cmsg_buf;
// Validate arguments
if (e == NULL || data == NULL)
{
@ -1603,7 +1650,28 @@ UINT EthGetPacketLinux(ETH *e, void **data)
}
// Read
ret = read(s, tmp, sizeof(tmp));
msg_iov.iov_base = tmp;
msg_iov.iov_len = sizeof(tmp);
msg_header.msg_name = NULL;
msg_header.msg_namelen = 0;
msg_header.msg_iov = &msg_iov;
msg_header.msg_iovlen = 1;
if (e->Linux_IsAuxDataSupported)
{
memset(&cmsg_buf, 0, sizeof(cmsg_buf));
msg_header.msg_control = &cmsg_buf;
msg_header.msg_controllen = sizeof(cmsg_buf);
}
else
{
msg_header.msg_control = NULL;
msg_header.msg_controllen = 0;
}
msg_header.msg_flags = 0;
ret = recvmsg(s, &msg_header, 0);
if (ret == 0 || (ret == -1 && errno == EAGAIN))
{
// No packet
@ -1619,9 +1687,75 @@ UINT EthGetPacketLinux(ETH *e, void **data)
}
else
{
// Success to read a packet
*data = MallocFast(ret);
Copy(*data, tmp, ret);
bool flag = false;
USHORT api_vlan_id = 0;
USHORT api_vlan_tpid = 0;
if (e->Linux_IsAuxDataSupported)
{
for (cmsg = CMSG_FIRSTHDR(&msg_header); cmsg; cmsg = CMSG_NXTHDR(&msg_header, cmsg))
{
struct my_tpacket_auxdata *aux;
UINT len;
USHORT vlan_tpid = 0x8100;
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)
{
continue;
}
aux = (struct my_tpacket_auxdata *)CMSG_DATA(cmsg);
if (aux != NULL)
{
if (aux->tp_vlan_tci != 0)
{
vlan_id = aux->tp_vlan_tci;
}
}
if (vlan_id != 0)
{
api_vlan_id = vlan_id;
api_vlan_tpid = vlan_tpid;
break;
}
}
if (api_vlan_id != 0 && api_vlan_tpid != 0)
{
// VLAN ID has been received with PACKET_AUXDATA.
// Insert the tag.
USHORT vlan_id_ne = Endian16(api_vlan_id);
USHORT vlan_tpid_ne = Endian16(api_vlan_tpid);
if (ret >= 14)
{
if (*((USHORT *)(tmp + 12)) != vlan_tpid_ne)
{
*data = MallocFast(ret + 4);
Copy(*data, tmp, 12);
Copy(((UCHAR *)*data) + 12, &vlan_tpid_ne, 2);
Copy(((UCHAR *)*data) + 14, &vlan_id_ne, 2);
Copy(((UCHAR *)*data) + 16, tmp + 12, ret - 12);
flag = true;
ret += 4;
}
}
}
}
// Success to read a packet (No VLAN)
if (flag == false)
{
*data = MallocFast(ret);
Copy(*data, tmp, ret);
}
return ret;
}
@ -1824,11 +1958,36 @@ void EthPutPacket(ETH *e, void *data, UINT size)
Debug("EthPutPacket: ret:%d size:%d\n", ret, size);
}
#else // BRIDGE_PCAP
#ifndef UNIX_LINUX
ret = write(s, data, size);
if (ret<0)
{
Debug("EthPutPacket: ret:%d errno:%d size:%d\n", ret, errno, size);
}
#else // UNIX_LINUX
{
struct iovec msg_iov;
struct msghdr msg_header;
msg_iov.iov_base = data;
msg_iov.iov_len = size;
msg_header.msg_name = NULL;
msg_header.msg_namelen = 0;
msg_header.msg_iov = &msg_iov;
msg_header.msg_iovlen = 1;
msg_header.msg_control = NULL;
msg_header.msg_controllen = 0;
msg_header.msg_flags = 0;
ret = sendmsg(s, &msg_header, 0);
if (ret<0)
{
Debug("EthPutPacket: ret:%d errno:%d size:%d\n", ret, errno, size);
}
}
#endif // UNIX_LINUX
#endif //BRIDGE_PCAP
Free(data);