⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ethsock.cxx

📁 opal的ptlib c++源程序 可以从官方网站上下载
💻 CXX
📖 第 1 页 / 共 3 页
字号:
  { 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 + -