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

📄 ethsock.cxx

📁 windows mobile phone source code
💻 CXX
📖 第 1 页 / 共 4 页
字号:
    return SetErrorValues(Miscellaneous, driver->GetLastError()|PWIN32ErrorFlag);

  interfaceName = newName;
  os_handle = 1;
  return TRUE;
}


BOOL PEthSocket::EnumInterfaces(PINDEX idx, PString & name)
{
  return driver->EnumInterfaces(idx, name);
}


BOOL PEthSocket::GetAddress(Address & addr)
{
  if (driver->QueryOid(OID_802_3_CURRENT_ADDRESS, sizeof(addr), addr.b))
    return TRUE;

  return SetErrorValues(Miscellaneous, driver->GetLastError()|PWIN32ErrorFlag);
}


BOOL PEthSocket::EnumIpAddress(PINDEX idx,
                               PIPSocket::Address & addr,
                               PIPSocket::Address & net_mask)
{
  if (IsOpen()) {
    if (driver->EnumIpAddress(idx, addr, net_mask))
      return TRUE;

    return SetErrorValues(NotFound, ENOENT);
  }

  return SetErrorValues(NotOpen, EBADF);
}


static const struct {
  unsigned pwlib;
  DWORD    ndis;
} FilterMasks[] = {
  { PEthSocket::FilterDirected,     NDIS_PACKET_TYPE_DIRECTED },
  { 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 }
};


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+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+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
}

///////////////////////////////////////////////////////////////////////////////

BOOL PIPSocket::GetGatewayAddress(Address & addr)
{
  PWin32AsnOid gatewayOid = "1.3.6.1.2.1.4.21.1.7.0.0.0.0";
  return PWin32SnmpLibrary::Current().GetOid(gatewayOid, addr);
}


PString PIPSocket::GetGatewayInterface()
{
  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();

  return snmp.GetInterfaceName(ifNum);
}


BOOL PIPSocket::GetRouteTable(RouteTable & table)
{
  PWin32SnmpLibrary & snmp = PWin32SnmpLibrary::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;
}


BOOL PIPSocket::GetInterfaceTable(InterfaceTable & table)
{
  PWin32SnmpLibrary & snmp = PWin32SnmpLibrary::Current();

  table.RemoveAll();

  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.GetPointer(100), 100))
        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 + -