📄 ethsock.cxx
字号:
BOOL PEthSocket::GetFilter(unsigned & mask, WORD & type)
{
if (!IsOpen())
return SetErrorValues(NotOpen, EBADF);
DWORD filter = 0;
if (!driver->QueryOid(OID_GEN_CURRENT_PACKET_FILTER, filter))
return SetErrorValues(Miscellaneous, driver->GetLastError()|PWIN32ErrorFlag);
if (filter == 0)
return PEthSocket::FilterDirected;
mask = 0;
for (PINDEX i = 0; i < PARRAYSIZE(FilterMasks); i++) {
if ((filter&FilterMasks[i].ndis) != 0)
mask |= FilterMasks[i].pwlib;
}
type = (WORD)filterType;
return TRUE;
}
BOOL PEthSocket::SetFilter(unsigned filter, WORD type)
{
if (!IsOpen())
return SetErrorValues(NotOpen, EBADF);
DWORD bits = 0;
for (PINDEX i = 0; i < PARRAYSIZE(FilterMasks); i++) {
if ((filter&FilterMasks[i].pwlib) != 0)
bits |= FilterMasks[i].ndis;
}
if (!driver->SetOid(OID_GEN_CURRENT_PACKET_FILTER, bits))
return SetErrorValues(Miscellaneous, driver->GetLastError()|PWIN32ErrorFlag);
filterType = type;
return TRUE;
}
PEthSocket::MediumTypes PEthSocket::GetMedium()
{
if (!IsOpen()) {
SetErrorValues(NotOpen, EBADF);
return NumMediumTypes;
}
DWORD medium = 0xffffffff;
if (!driver->QueryOid(OID_GEN_MEDIA_SUPPORTED, medium) || medium == 0xffffffff) {
SetErrorValues(Miscellaneous, driver->GetLastError()|PWIN32ErrorFlag);
return NumMediumTypes;
}
static const DWORD MediumValues[NumMediumTypes] = {
0xffffffff, NdisMedium802_3, NdisMediumWan, 0xffffffff
};
for (int type = Medium802_3; type < NumMediumTypes; type++) {
if (MediumValues[type] == medium)
return (MediumTypes)type;
}
return MediumUnknown;
}
BOOL PEthSocket::Read(void * data, PINDEX length)
{
if (!IsOpen())
return SetErrorValues(NotOpen, EBADF, LastReadError);
PINDEX idx;
PINDEX numBuffers = readBuffers.GetSize();
do {
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
for (idx = 0; idx < numBuffers; idx++) {
PWin32PacketBuffer & buffer = readBuffers[idx];
if (buffer.InProgress()) {
if (WaitForSingleObject(buffer.GetEvent(), 0) == WAIT_OBJECT_0)
if (!buffer.ReadComplete(*driver))
return ConvertOSError(-1, LastReadError);
}
else {
if (!buffer.ReadAsync(*driver))
return ConvertOSError(-1, LastReadError);
}
if (buffer.IsCompleted() && buffer.IsType(filterType)) {
lastReadCount = buffer.GetData(data, length);
return TRUE;
}
handles[idx] = buffer.GetEvent();
}
DWORD result;
PINDEX retries = 100;
for (;;) {
result = WaitForMultipleObjects(numBuffers, handles, FALSE, INFINITE);
if (result >= WAIT_OBJECT_0 && result < WAIT_OBJECT_0 + (DWORD)numBuffers)
break;
if (::GetLastError() != ERROR_INVALID_HANDLE || retries == 0)
return ConvertOSError(-1, LastReadError);
retries--;
}
idx = result - WAIT_OBJECT_0;
if (!readBuffers[idx].ReadComplete(*driver))
return ConvertOSError(-1, LastReadError);
} while (!readBuffers[idx].IsType(filterType));
lastReadCount = readBuffers[idx].GetData(data, length);
return TRUE;
}
BOOL PEthSocket::Write(const void * data, PINDEX length)
{
if (!IsOpen())
return SetErrorValues(NotOpen, EBADF, LastWriteError);
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
PINDEX numBuffers = writeBuffers.GetSize();
PINDEX idx;
for (idx = 0; idx < numBuffers; idx++) {
PWin32PacketBuffer & buffer = writeBuffers[idx];
if (buffer.InProgress()) {
if (WaitForSingleObject(buffer.GetEvent(), 0) == WAIT_OBJECT_0)
if (!buffer.WriteComplete(*driver))
return ConvertOSError(-1, LastWriteError);
}
if (!buffer.InProgress()) {
lastWriteCount = buffer.PutData(data, length);
return ConvertOSError(buffer.WriteAsync(*driver) ? 0 : -1, LastWriteError);
}
handles[idx] = buffer.GetEvent();
}
DWORD result = WaitForMultipleObjects(numBuffers, handles, FALSE, INFINITE);
if (result < WAIT_OBJECT_0 || result >= WAIT_OBJECT_0 + (DWORD) numBuffers)
return ConvertOSError(-1, LastWriteError);
idx = result - WAIT_OBJECT_0;
if (!writeBuffers[idx].WriteComplete(*driver))
return ConvertOSError(-1, LastWriteError);
lastWriteCount = writeBuffers[idx].PutData(data, length);
return ConvertOSError(writeBuffers[idx].WriteAsync(*driver) ? 0 : -1, LastWriteError);
}
///////////////////////////////////////////////////////////////////////////////
PWin32PacketBuffer::PWin32PacketBuffer(PINDEX sz)
: PBYTEArray(sz)
{
status = Uninitialised;
count = 0;
}
PINDEX PWin32PacketBuffer::GetData(void * buf, PINDEX size)
{
if (count > (DWORD)size)
count = size;
memcpy(buf, theArray, count);
return count;
}
PINDEX PWin32PacketBuffer::PutData(const void * buf, PINDEX length)
{
count = min(GetSize(), length);
memcpy(theArray, buf, count);
return count;
}
BOOL PWin32PacketBuffer::ReadAsync(PWin32PacketDriver & pkt)
{
if (status == Progressing)
return FALSE;
status = Uninitialised;
if (!pkt.BeginRead(theArray, GetSize(), count, overlap))
return FALSE;
if (pkt.GetLastError() == ERROR_SUCCESS)
status = Completed;
else
status = Progressing;
return TRUE;
}
BOOL PWin32PacketBuffer::ReadComplete(PWin32PacketDriver & pkt)
{
if (status != Progressing)
return status == Completed;
if (!pkt.CompleteIO(count, overlap)) {
status = Uninitialised;
return FALSE;
}
status = Completed;
return TRUE;
}
BOOL PWin32PacketBuffer::WriteAsync(PWin32PacketDriver & pkt)
{
if (status == Progressing)
return FALSE;
status = Uninitialised;
if (!pkt.BeginWrite(theArray, count, overlap))
return FALSE;
if (pkt.GetLastError() == ERROR_SUCCESS)
status = Completed;
else
status = Progressing;
return TRUE;
}
BOOL PWin32PacketBuffer::WriteComplete(PWin32PacketDriver & pkt)
{
if (status != Progressing)
return status == Completed;
DWORD dummy;
if (pkt.CompleteIO(dummy, overlap)) {
status = Completed;
return TRUE;
}
status = Uninitialised;
return FALSE;
}
BOOL PWin32PacketBuffer::IsType(WORD filterType) const
{
if (filterType == PEthSocket::TypeAll)
return TRUE;
const PEthSocket::Frame * frame = (const PEthSocket::Frame *)theArray;
WORD len_or_type = ntohs(frame->snap.length);
if (len_or_type > sizeof(*frame))
return len_or_type == filterType;
if (frame->snap.dsap == 0xaa && frame->snap.ssap == 0xaa)
return ntohs(frame->snap.type) == filterType; // SNAP header
if (frame->snap.dsap == 0xff && frame->snap.ssap == 0xff)
return PEthSocket::TypeIPX == filterType; // Special case for Novell netware's stuffed up 802.3
if (frame->snap.dsap == 0xe0 && frame->snap.ssap == 0xe0)
return PEthSocket::TypeIPX == filterType; // Special case for Novell netware's 802.2
return frame->snap.dsap == filterType; // A pure 802.2 protocol id
}
///////////////////////////////////////////////////////////////////////////////
/*
static PMutex & GetSNMPMutex()
{
static PMutex snmpmutex;
return snmpmutex;
}
*/
BOOL PIPSocket::GetGatewayAddress(Address & addr)
{
PWaitAndSignal m(GetSNMPMutex());
PWin32SnmpLibrary & snmp = PWin32SnmpLibrary::Current();
PWin32AsnOid gatewayOid = "1.3.6.1.2.1.4.21.1.7.0.0.0.0";
return snmp.GetOid(gatewayOid, addr);
}
PString PIPSocket::GetGatewayInterface()
{
PWaitAndSignal m(GetSNMPMutex());
PWin32SnmpLibrary & snmp = PWin32SnmpLibrary::Current();
AsnInteger ifNum = -1;
PWin32AsnOid gatewayOid = "1.3.6.1.2.1.4.21.1.2.0.0.0.0";
if (!snmp.GetOid(gatewayOid, ifNum) && ifNum >= 0)
return PString::Empty();
return snmp.GetInterfaceName(ifNum);
}
PIPSocket::Address PIPSocket::GetGatewayInterfaceAddress()
{
PWaitAndSignal m(GetSNMPMutex());
PWin32SnmpLibrary & snmp = PWin32SnmpLibrary::Current();
AsnInteger ifNum = -1;
PWin32AsnOid gatewayOid = "1.3.6.1.2.1.4.21.1.2.0.0.0.0";
if (!snmp.GetOid(gatewayOid, ifNum) && ifNum >= 0)
return PString::Empty();
return snmp.GetInterfaceAddress(ifNum);
}
BOOL PIPSocket::GetRouteTable(RouteTable & table)
{
PWaitAndSignal m(GetSNMPMutex());
PWin32SnmpLibrary & snmp = snmp.Current();
table.RemoveAll();
PWin32AsnOid baseOid = "1.3.6.1.2.1.4.21.1";
PWin32AsnOid oid = baseOid;
DWORD lastVariable = 1;
PWin32AsnAny value;
PLongArray ifNum;
PINDEX idx = 0;
while (snmp.GetNextOid(oid, value) && (baseOid *= oid)) {
if (lastVariable != oid[9]) {
lastVariable = oid[9];
if (lastVariable == 2)
ifNum.SetSize(table.GetSize());
idx = 0;
}
switch (lastVariable) {
case 1 : // network address
{
Address addr;
if (!value.GetIpAddress(addr))
return FALSE; // Very confused route table
table.Append(new RouteEntry(addr));
break;
}
case 2 : // device interface
if (!value.GetInteger(ifNum[idx]))
return FALSE;
break;
case 3 : // metric
if (!value.GetInteger(table[idx].metric))
return FALSE;
break;
case 7 : // Get destination (next hop)
if (!value.GetIpAddress(table[idx].destination))
return FALSE;
break;
case 11 : // Get mask
if (!value.GetIpAddress(table[idx].net_mask))
return FALSE;
break;
}
idx++;
}
for (idx = 0; idx < table.GetSize(); idx++)
table[idx].interfaceName = snmp.GetInterfaceName(ifNum[idx]);
return TRUE;
}
unsigned PIPSocket::AsNumeric(PIPSocket::Address addr)
{
return ((addr.Byte1() << 24) | (addr.Byte2() << 16) |
(addr.Byte3() << 8) | addr.Byte4());
}
PIPSocket::Address PIPSocket::GetRouteAddress(PIPSocket::Address RemoteAddress)
{
Address localaddr;
if (!RemoteAddress.IsRFC1918()) { // Remote Address is not Local
if (!GetNetworkInterface(localaddr)) { // User not connected directly to Internet
localaddr = GetGatewayInterfaceAddress(); // Get the default Gateway NIC address
if ( localaddr != 0 ) // No connection to the Internet?
return localaddr;
}
} else {
PIPSocket::InterfaceTable interfaceTable;
if (PIPSocket::GetInterfaceTable(interfaceTable)) {
PINDEX i;
for (i = 0; i < interfaceTable.GetSize(); ++i) {
localaddr = interfaceTable[i].GetAddress();
if (!localaddr.IsLoopback() && localaddr.IsRFC1918()) {
if (IsAddressReachable(localaddr,
interfaceTable[i].GetNetMask(),RemoteAddress))
return localaddr;
}
}
}
}
return 0;
}
BOOL PIPSocket::IsAddressReachable(PIPSocket::Address LocalIP,
PIPSocket::Address LocalMask,
PIPSocket::Address RemoteIP)
{
BYTE t = 255;
int t1=t,t2=t,t3 =t,t4=t;
int b1=0,b2=0,b3=0,b4=0;
if ((int)LocalMask.Byte1() > 0)
{ t1 = LocalIP.Byte1() + (t-LocalMask.Byte1()); b1 = LocalIP.Byte1();}
if ((int)LocalMask.Byte2() > 0)
{ t2 = LocalIP.Byte2() + (t-LocalMask.Byte2()); b2 = LocalIP.Byte2();}
if ((int)LocalMask.Byte3() > 0)
{ t3 = LocalIP.Byte3() + (t-LocalMask.Byte3()); b3 = LocalIP.Byte3();}
if ((int)LocalMask.Byte4() > 0)
{ t4 = LocalIP.Byte4() + (t-LocalMask.Byte4()); b4 = LocalIP.Byte4();}
Address lt = Address((BYTE)t1,(BYTE)t2,(BYTE)t3,(BYTE)t4);
Address lb = Address((BYTE)b1,(BYTE)b2,(BYTE)b3,(BYTE)b4);
if (AsNumeric(RemoteIP) > AsNumeric(lb) &&
AsNumeric(lt) > AsNumeric(RemoteIP))
return TRUE;
return FALSE;
}
PString PIPSocket::GetInterface(PIPSocket::Address addr)
{
PIPSocket::InterfaceTable if_table;
if (PIPSocket::GetInterfaceTable( if_table ) ) {
for (PINDEX i=0; i < if_table.GetSize(); i++) {
PIPSocket::InterfaceEntry if_entry = if_table[i];
if (if_entry.GetAddress() == addr)
return if_entry.GetName();
}
}
return PString();
}
BOOL PIPSocket::GetInterfaceTable(InterfaceTable & table)
{
PWin32SnmpLibrary & snmp = snmp.Current();
PWaitAndSignal m(GetSNMPMutex());
table.RemoveAll();
/*
if (!snmp.IsLoaded()) {
// Error loading the SNMP library, fail safe to using whatever the
// address of the local host is.
Address ipAddr;
if (!GetHostAddress(ipAddr))
return FALSE;
Address netMask(255,255,255,255);
table.Append(new InterfaceEntry("FailSafe Interface", ipAddr, netMask, PString::Empty()));
table.Append(new InterfaceEntry("localhost", PIPSocket::Address(), netMask, PString::Empty()));
return TRUE;
}
*/
PWin32AsnOid baseOid = "1.3.6.1.2.1.4.20.1";
PWin32AsnOid oid = baseOid;
PWin32AsnAny value;
while (snmp.GetNextOid(oid, value)) {
if (!(baseOid *= oid))
break;
if (value.asnType != ASN_IPADDRESS)
break;
Address ipAddr;
value.GetIpAddress(ipAddr);
oid[9] = 3;
Address netMask;
if (!snmp.GetOid(oid, netMask))
break;
oid[9] = 2;
AsnInteger ifIndex = -1;
if (!snmp.GetOid(oid, ifIndex))
break;
PString macAddr;
PEthSocket::Address ifPhysAddress("");
PWin32AsnOid ifOid = "1.3.6.1.2.1.2.2.1.6.0";
ifOid[10] = ifIndex;
UINT len;
if (snmp.GetOid(ifOid, &ifPhysAddress, sizeof(ifPhysAddress), &len) && len > 0)
macAddr = ifPhysAddress;
PString name = snmp.GetInterfaceName(ipAddr);
if (name.IsEmpty()) {
PWin32AsnOid nameOid = "1.3.6.1.2.1.2.2.1.2.0";
nameOid[10] = ifIndex;
if (!snmp.GetOid(nameOid, name))
break;
name.MakeMinimumSize();
}
#ifdef _WIN32_WCE // Getting rid of ghost ips
if ( !name.IsEmpty() )
#endif
table.Append(new InterfaceEntry(name, ipAddr, netMask, macAddr));
oid[9] = 1;
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -