📄 ethsock.cxx
字号:
{ PEthSocket::FilterMulticast, NDIS_PACKET_TYPE_MULTICAST },
{ PEthSocket::FilterAllMulticast, NDIS_PACKET_TYPE_ALL_MULTICAST },
{ PEthSocket::FilterBroadcast, NDIS_PACKET_TYPE_BROADCAST },
{ PEthSocket::FilterPromiscuous, NDIS_PACKET_TYPE_PROMISCUOUS }
};
PBoolean 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;
}
PBoolean 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;
}
PBoolean 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;
}
PBoolean 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;
}
PBoolean 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;
}
PBoolean PWin32PacketBuffer::ReadComplete(PWin32PacketDriver & pkt)
{
if (status != Progressing)
return status == Completed;
if (!pkt.CompleteIO(count, overlap)) {
status = Uninitialised;
return false;
}
status = Completed;
return true;
}
PBoolean 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;
}
PBoolean 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;
}
PBoolean 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
}
///////////////////////////////////////////////////////////////////////////////
class PIPRouteTable
{
public:
PIPRouteTable()
{
ULONG size = 0;
DWORD error = GetIpForwardTable(NULL, &size, TRUE);
if (error == ERROR_INSUFFICIENT_BUFFER && buffer.SetSize(size))
error = GetIpForwardTable((MIB_IPFORWARDTABLE *)buffer.GetPointer(), &size, TRUE);
if (error != NO_ERROR) {
buffer.SetSize(0);
buffer.SetSize(sizeof(MIB_IPFORWARDTABLE)); // So ->dwNumEntries returns zero
}
}
const MIB_IPFORWARDTABLE * operator->() const { return (const MIB_IPFORWARDTABLE *)(const BYTE *)buffer; }
const MIB_IPFORWARDTABLE & operator *() const { return *(const MIB_IPFORWARDTABLE *)(const BYTE *)buffer; }
private:
PBYTEArray buffer;
};
class PIPInterfaceAddressTable
{
public:
PIPInterfaceAddressTable()
{
ULONG size = 0;
DWORD error = GetIpAddrTable(NULL, &size, FALSE);
if (error == ERROR_INSUFFICIENT_BUFFER && buffer.SetSize(size))
error = GetIpAddrTable((MIB_IPADDRTABLE *)buffer.GetPointer(), &size, FALSE);
if (error != NO_ERROR) {
buffer.SetSize(0);
buffer.SetSize(sizeof(MIB_IPADDRTABLE)); // So ->NumAdapters returns zero
}
}
const MIB_IPADDRTABLE * operator->() const { return (const MIB_IPADDRTABLE *)(const BYTE *)buffer; }
const MIB_IPADDRTABLE & operator *() const { return *(const MIB_IPADDRTABLE *)(const BYTE *)buffer; }
private:
PBYTEArray buffer;
};
///////////////////////////////////////////////////////////////////////////////
PBoolean PIPSocket::GetGatewayAddress(Address & addr)
{
PIPRouteTable routes;
for (unsigned i = 0; i < routes->dwNumEntries; ++i) {
if (routes->table[i].dwForwardMask == 0) {
addr = routes->table[i].dwForwardNextHop;
return true;
}
}
return false;
}
PString PIPSocket::GetGatewayInterface()
{
PIPRouteTable routes;
for (unsigned i = 0; i < routes->dwNumEntries; ++i) {
if (routes->table[i].dwForwardMask == 0) {
MIB_IFROW info;
info.dwIndex = routes->table[i].dwForwardIfIndex;
if (GetIfEntry(&info) == NO_ERROR)
return PString((const char *)info.bDescr, info.dwDescrLen);
}
}
return PString::Empty();
}
PIPSocket::Address PIPSocket::GetGatewayInterfaceAddress()
{
PIPRouteTable routes;
for (unsigned i = 0; i < routes->dwNumEntries; ++i) {
if (routes->table[i].dwForwardMask == 0) {
PIPInterfaceAddressTable interfaces;
for (unsigned j = 0; j < interfaces->dwNumEntries; ++j) {
if (interfaces->table[j].dwIndex == routes->table[i].dwForwardIfIndex)
return interfaces->table[j].dwAddr;
}
}
}
return GetDefaultIpAny();
}
PBoolean PIPSocket::GetRouteTable(RouteTable & table)
{
PIPRouteTable routes;
if (!table.SetSize(routes->dwNumEntries))
return false;
if (table.IsEmpty())
return false;
for (unsigned i = 0; i < routes->dwNumEntries; ++i) {
RouteEntry * entry = new RouteEntry(routes->table[i].dwForwardDest);
entry->net_mask = routes->table[i].dwForwardMask;
entry->destination = routes->table[i].dwForwardNextHop;
entry->metric = routes->table[i].dwForwardMetric1;
MIB_IFROW info;
info.dwIndex = routes->table[i].dwForwardIfIndex;
if (GetIfEntry(&info) == NO_ERROR)
entry->interfaceName = PString((const char *)info.bDescr, info.dwDescrLen);
table.SetAt(i, entry);
}
return true;
}
PIPSocket::Address PIPSocket::GetRouteAddress(PIPSocket::Address remoteAddress)
{
DWORD best;
if (GetBestInterface(remoteAddress, &best) == NO_ERROR) {
PIPInterfaceAddressTable interfaces;
for (unsigned j = 0; j < interfaces->dwNumEntries; ++j) {
if (interfaces->table[j].dwIndex == best)
return interfaces->table[j].dwAddr;
}
}
return GetDefaultIpAny();
}
unsigned PIPSocket::AsNumeric(PIPSocket::Address addr)
{
return ((addr.Byte1() << 24) | (addr.Byte2() << 16) | (addr.Byte3() << 8) | addr.Byte4());
}
PBoolean 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);
return AsNumeric(remoteIP) > AsNumeric(lb) && AsNumeric(lt) > AsNumeric(remoteIP);
}
PString PIPSocket::GetInterface(PIPSocket::Address addr)
{
PIPInterfaceAddressTable byAddress;
for (unsigned i = 0; i < byAddress->dwNumEntries; ++i) {
if (addr == byAddress->table[i].dwAddr) {
MIB_IFROW info;
info.dwIndex = byAddress->table[i].dwIndex;
if (GetIfEntry(&info) == NO_ERROR)
return PString((const char *)info.bDescr, info.dwDescrLen);
}
}
return PString::Empty();
}
PBoolean PIPSocket::GetInterfaceTable(InterfaceTable & table, PBoolean includeDown)
{
PIPInterfaceAddressTable byAddress;
if (!table.SetSize(byAddress->dwNumEntries))
return false;
if (table.IsEmpty())
return false;
PINDEX count = 0;
for (unsigned i = 0; i < byAddress->dwNumEntries; ++i) {
MIB_IFROW info;
info.dwIndex = byAddress->table[i].dwIndex;
if (GetIfEntry(&info) == NO_ERROR && (includeDown || info.dwAdminStatus)) {
PStringStream macAddr;
macAddr << ::hex << ::setfill('0');
for (unsigned b = 0; b < info.dwPhysAddrLen; ++b)
macAddr << setw(2) << (unsigned)info.bPhysAddr[b];
table.SetAt(count++, new InterfaceEntry(PString((const char *)info.bDescr, info.dwDescrLen),
byAddress->table[i].dwAddr,
byAddress->table[i].dwMask,
macAddr));
}
}
table.SetSize(count); // May shrink due to "down" interfaces.
return true;
}
///////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -