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

📄 ethsock.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 4 页
字号:


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