📄 ethsock.cxx
字号:
/*
* ethsock.cxx
*
* Direct Ethernet socket implementation.
*
* Portable Windows Library
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): ______________________________________.
*
* $Log: ethsock.cxx,v $
* Revision 1.30 2001/10/12 19:04:24 yurik
* New more robust ip collection routine
*
* Revision 1.29 2001/10/04 05:59:41 robertj
* Plugged numerous memory leaks.
*
* Revision 1.28 2001/10/03 03:12:21 robertj
* Changed to use only a single instance of SNMP library to avoid memory leak.
*
* Revision 1.27 2001/09/10 02:51:23 robertj
* Major change to fix problem with error codes being corrupted in a
* PChannel when have simultaneous reads and writes in threads.
*
* Revision 1.26 2001/09/09 02:03:49 yurik
* no message
*
* Revision 1.25 2001/08/28 03:22:01 yurik
* Fixed crash on snmp init bug
*
* Revision 1.24 2001/08/16 20:12:25 yurik
* Fixed duplicate ordinal - ifdef'd ce code
*
* Revision 1.23 2001/08/15 22:15:27 yurik
* First cut of Windows CE port to support gatekeeper
*
* Revision 1.22 2001/03/05 04:18:27 robertj
* Added net mask to interface info returned by GetInterfaceTable()
*
* Revision 1.21 2000/03/06 03:59:22 robertj
* Fixed warning about handle types, thanks Steve Bennett
*
* Revision 1.20 1999/10/29 03:34:19 robertj
* Fixed possible crash accessing IP addresses from SNMP tables.
*
* Revision 1.19 1999/10/14 01:34:55 robertj
* Fixed backward compatibility problem with old SNMP header file.
*
* Revision 1.18 1999/09/10 04:35:42 robertj
* Added Windows version of PIPSocket::GetInterfaceTable() function.
*
* Revision 1.17 1999/04/18 12:58:39 robertj
* MSVC 5 backward compatibility
*
* Revision 1.16 1999/02/16 08:08:06 robertj
* MSVC 6.0 compatibility changes.
*
* Revision 1.15 1998/11/30 04:48:38 robertj
* New directory structure
*
* Revision 1.14 1998/11/22 11:30:10 robertj
* Check route table function to get a list
*
* Revision 1.13 1998/11/20 03:17:43 robertj
* Split rad and write buffers to separate pools.
*
* Revision 1.12 1998/11/19 05:18:48 robertj
* Added route table manipulation functions to PIPSocket class.
*
* Revision 1.11 1998/11/14 06:31:41 robertj
* Changed semantics of os_sendto to return TRUE if ANY bytes are sent.
* Added support for MSDUN1.3 DHCP registry entries.
*
* Revision 1.10 1998/10/23 04:09:08 robertj
* Fixes for NT support.
* Allowed both old and new driver by compilation option.
*
* Revision 1.9 1998/10/15 05:41:48 robertj
* New memory leak check code.
*
* Revision 1.8 1998/10/12 09:34:42 robertj
* New method for getting IP addresses of interfaces.
*
* Revision 1.7 1998/10/06 10:24:41 robertj
* Fixed hang when using reset command, removed the command!
*
* Revision 1.6 1998/09/24 03:30:45 robertj
* Added open software license.
*
* Revision 1.5 1998/09/15 08:25:36 robertj
* Fixed a number of warnings at maximum optimisation.
*
* Revision 1.4 1998/09/08 15:14:36 robertj
* Fixed packet type based filtering in Read() function.
*
* Revision 1.3 1998/08/25 11:03:15 robertj
* Fixed proble with NT get of OID.
* Fixed bug with not setting channel name when interface opened.
*
* Revision 1.2 1998/08/21 05:27:13 robertj
* Fine tuning of interface.
*
* Revision 1.1 1998/08/20 06:04:52 robertj
* Initial revision
*
*/
#include <ptlib.h>
#include <ptlib/sockets.h>
#include <snmp.h>
///////////////////////////////////////////////////////////////////////////////
// Stuff from snmp.h
#ifndef RFC1157VarBindList
typedef RFC1157VarBind SnmpVarBind;
typedef RFC1157VarBindList SnmpVarBindList;
typedef LONG AsnInteger32;
#define SNMP_PDU_GET ASN_RFC1157_GETREQUEST
#define SNMP_PDU_GETNEXT ASN_RFC1157_GETNEXTREQUEST
#define ASN_IPADDRESS ASN_RFC1155_IPADDRESS // Prevents GetInterfaceTable failure
#pragma message("Later version of snmp.h required!")
#endif
///////////////////////////////////////////////////////////////////////////////
// Stuff from ndis.h
#define OID_802_3_PERMANENT_ADDRESS 0x01010101
#define OID_802_3_CURRENT_ADDRESS 0x01010102
#define OID_GEN_DRIVER_VERSION 0x00010110
#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
#define OID_GEN_MEDIA_SUPPORTED 0x00010103
#define NDIS_PACKET_TYPE_DIRECTED 0x0001
#define NDIS_PACKET_TYPE_MULTICAST 0x0002
#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x0004
#define NDIS_PACKET_TYPE_BROADCAST 0x0008
#define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020
typedef enum _NDIS_MEDIUM {
NdisMedium802_3,
NdisMedium802_5,
NdisMediumFddi,
NdisMediumWan,
NdisMediumLocalTalk,
NdisMediumDix, // defined for convenience, not a real medium
NdisMediumArcnetRaw,
NdisMediumArcnet878_2
} NDIS_MEDIUM, *PNDIS_MEDIUM;
///////////////////////////////////////////////////////////////////////////////
#define USE_VPACKET
#include <ptlib/epacket.h>
#ifdef USE_VPACKET
#define PACKET_SERVICE_NAME "Packet"
#define PACKET_VXD_NAME "VPacket"
#else
#define PACKET_SERVICE_NAME "EPacket"
#define PACKET_VXD_NAME "EPacket"
#define GetQueryOidCommand(oid) IOCTL_EPACKET_QUERY_OID
#endif
#define SERVICES_REGISTRY_KEY "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\"
///////////////////////////////////////////////////////////////////////////////
class PWin32AsnAny : public AsnAny
{
public:
PWin32AsnAny();
~PWin32AsnAny() { MemFree(); }
BOOL GetInteger(AsnInteger & i);
BOOL GetIpAddress(PIPSocket::Address & addr);
void MemFree();
private:
PWin32AsnAny(const PWin32AsnAny &) { }
PWin32AsnAny & operator=(const PWin32AsnAny &) { return *this; }
};
///////////////////////////////////////////////////////////////////////////////
class PWin32AsnOid : public AsnObjectIdentifier
{
public:
PWin32AsnOid();
PWin32AsnOid(const char * str);
PWin32AsnOid(const PWin32AsnOid & oid) { SnmpUtilOidCpy(this, (AsnObjectIdentifier *)&oid); }
~PWin32AsnOid() { SnmpUtilOidFree(this); }
PWin32AsnOid & operator=(const AsnObjectIdentifier&);
PWin32AsnOid & operator=(const PWin32AsnOid & oid) { SnmpUtilOidFree(this); SnmpUtilOidCpy(this, (AsnObjectIdentifier *)&oid); return *this; }
PWin32AsnOid & operator+=(const PWin32AsnOid & oid) { SnmpUtilOidAppend(this, (AsnObjectIdentifier *)&oid); return *this; }
UINT & operator[](int idx) { return ids[idx]; }
UINT operator[](int idx) const { return ids[idx]; }
bool operator==(const PWin32AsnOid & oid) { return SnmpUtilOidCmp(this, (AsnObjectIdentifier *)&oid) == 0; }
bool operator!=(const PWin32AsnOid & oid) { return SnmpUtilOidCmp(this, (AsnObjectIdentifier *)&oid) != 0; }
bool operator< (const PWin32AsnOid & oid) { return SnmpUtilOidCmp(this, (AsnObjectIdentifier *)&oid) < 0; }
bool operator<=(const PWin32AsnOid & oid) { return SnmpUtilOidCmp(this, (AsnObjectIdentifier *)&oid) <= 0; }
bool operator> (const PWin32AsnOid & oid) { return SnmpUtilOidCmp(this, (AsnObjectIdentifier *)&oid) > 0; }
bool operator>=(const PWin32AsnOid & oid) { return SnmpUtilOidCmp(this, (AsnObjectIdentifier *)&oid) >= 0; }
bool operator*=(const PWin32AsnOid & oid) { return SnmpUtilOidNCmp(this, (AsnObjectIdentifier *)&oid, idLength) == 0; }
};
/////////////////////////////////////////////////////////////////////////////
class PWin32SnmpLibrary
#ifndef _WIN32_WCE
: public PDynaLink
{
PCLASSINFO(PWin32SnmpLibrary, PDynaLink)
#else
{
void Close();
BOOL IsLoaded() { return TRUE; }
#endif
public:
PWin32SnmpLibrary();
BOOL GetOid(AsnObjectIdentifier & oid, AsnInteger & value);
BOOL GetOid(AsnObjectIdentifier & oid, PIPSocket::Address & ip_address);
BOOL GetOid(AsnObjectIdentifier & oid, void * value, UINT valSize, UINT * len = NULL);
BOOL GetOid(AsnObjectIdentifier & oid, PWin32AsnAny & value) { return QueryOid(SNMP_PDU_GET, oid, value); }
BOOL GetNextOid(AsnObjectIdentifier & oid, PWin32AsnAny & value) { return QueryOid(SNMP_PDU_GETNEXT, oid, value); }
PString GetInterfaceName(int ifNum);
PString GetInterfaceName(PIPSocket::Address ipAddr);
static PWin32SnmpLibrary & Current();
private:
BOOL (WINAPI *Init)(DWORD,HANDLE*,AsnObjectIdentifier*);
BOOL (WINAPI *Query)(BYTE,SnmpVarBindList*,AsnInteger32*,AsnInteger32*);
BOOL QueryOid(BYTE cmd, AsnObjectIdentifier & oid, PWin32AsnAny & value);
};
///////////////////////////////////////////////////////////////////////////////
class PWin32OidBuffer
{
public:
PWin32OidBuffer(UINT oid, UINT len, const BYTE * data = NULL);
~PWin32OidBuffer() { delete buffer; }
operator void *() { return buffer; }
operator DWORD () { return size; }
DWORD operator [](int i) { return buffer[i]; }
void Move(BYTE * data, DWORD received);
private:
DWORD * buffer;
UINT size;
};
///////////////////////////////////////////////////////////////////////////////
class PWin32PacketDriver
{
public:
static PWin32PacketDriver * Create();
virtual ~PWin32PacketDriver();
BOOL IsOpen() const;
void Close();
DWORD GetLastError() const;
virtual BOOL EnumInterfaces(PINDEX idx, PString & name) = 0;
virtual BOOL BindInterface(const PString & interfaceName) = 0;
virtual BOOL EnumIpAddress(PINDEX idx, PIPSocket::Address & addr, PIPSocket::Address & net_mask) = 0;
virtual BOOL BeginRead(void * buf, DWORD size, DWORD & received, PWin32Overlapped & overlap) = 0;
virtual BOOL BeginWrite(const void * buf, DWORD len, PWin32Overlapped & overlap) = 0;
BOOL CompleteIO(DWORD & received, PWin32Overlapped & overlap);
BOOL IoControl(UINT func,
const void * input, DWORD inSize,
void * output, DWORD outSize,
DWORD & received);
BOOL QueryOid(UINT oid, DWORD & data);
BOOL QueryOid(UINT oid, UINT len, BYTE * data);
BOOL SetOid(UINT oid, DWORD data);
BOOL SetOid(UINT oid, UINT len, const BYTE * data);
#ifdef USE_VPACKET
virtual UINT GetQueryOidCommand(DWORD oid) const = 0;
#endif
protected:
PWin32PacketDriver();
DWORD dwError;
HANDLE hDriver;
};
///////////////////////////////////////////////////////////////////////////////
class PWin32PacketVxD : public PWin32PacketDriver
{
public:
virtual BOOL EnumInterfaces(PINDEX idx, PString & name);
virtual BOOL BindInterface(const PString & interfaceName);
virtual BOOL EnumIpAddress(PINDEX idx, PIPSocket::Address & addr, PIPSocket::Address & net_mask);
virtual BOOL BeginRead(void * buf, DWORD size, DWORD & received, PWin32Overlapped & overlap);
virtual BOOL BeginWrite(const void * buf, DWORD len, PWin32Overlapped & overlap);
#ifdef USE_VPACKET
virtual UINT GetQueryOidCommand(DWORD oid) const
{ return oid >= OID_802_3_PERMANENT_ADDRESS ? IOCTL_EPACKET_QUERY_OID : IOCTL_EPACKET_STATISTICS; }
#endif
protected:
PStringList transportBinding;
};
///////////////////////////////////////////////////////////////////////////////
class PWin32PacketSYS : public PWin32PacketDriver
{
public:
PWin32PacketSYS();
virtual BOOL EnumInterfaces(PINDEX idx, PString & name);
virtual BOOL BindInterface(const PString & interfaceName);
virtual BOOL EnumIpAddress(PINDEX idx, PIPSocket::Address & addr, PIPSocket::Address & net_mask);
virtual BOOL BeginRead(void * buf, DWORD size, DWORD & received, PWin32Overlapped & overlap);
virtual BOOL BeginWrite(const void * buf, DWORD len, PWin32Overlapped & overlap);
#ifdef USE_VPACKET
virtual UINT GetQueryOidCommand(DWORD) const
{ return IOCTL_EPACKET_QUERY_OID; }
#endif
protected:
PString registryKey;
};
///////////////////////////////////////////////////////////////////////////////
#ifdef _WIN32_WCE
class PWin32PacketCe : public PWin32PacketDriver
{
public:
PWin32PacketCe();
virtual BOOL EnumInterfaces(PINDEX idx, PString & name);
virtual BOOL BindInterface(const PString & interfaceName);
virtual BOOL EnumIpAddress(PINDEX idx, PIPSocket::Address & addr, PIPSocket::Address & net_mask);
virtual BOOL BeginRead(void * buf, DWORD size, DWORD & received, PWin32Overlapped & overlap);
virtual BOOL BeginWrite(const void * buf, DWORD len, PWin32Overlapped & overlap);
#ifdef USE_VPACKET
virtual UINT GetQueryOidCommand(DWORD) const
{ return IOCTL_EPACKET_QUERY_OID; }
#endif
protected:
PStringArray ipAddresses;
PStringArray netMasks;
PStringArray interfaces;
};
#endif // _WIN32_WCE
/////////////////////////////////////////////////////////////////////////////
class PWin32PacketBuffer : public PBYTEArray
{
PCLASSINFO(PWin32PacketBuffer, PBYTEArray)
public:
enum Statuses {
Uninitialised,
Progressing,
Completed
};
PWin32PacketBuffer(PINDEX sz);
PINDEX GetData(void * buf, PINDEX size);
PINDEX PutData(const void * buf, PINDEX length);
HANDLE GetEvent() const { return overlap.hEvent; }
BOOL ReadAsync(PWin32PacketDriver & pkt);
BOOL ReadComplete(PWin32PacketDriver & pkt);
BOOL WriteAsync(PWin32PacketDriver & pkt);
BOOL WriteComplete(PWin32PacketDriver & pkt);
BOOL InProgress() const { return status == Progressing; }
BOOL IsCompleted() const { return status == Completed; }
BOOL IsType(WORD type) const;
protected:
Statuses status;
PWin32Overlapped overlap;
DWORD count;
};
#define new PNEW
/////////////////////////////////////////////////////////////////////////////
PWin32AsnAny::PWin32AsnAny()
{
asnType = ASN_INTEGER;
asnValue.number = 0;
}
void PWin32AsnAny::MemFree()
{
switch (asnType) {
case ASN_OCTETSTRING :
SnmpUtilMemFree(asnValue.string.stream);
break;
#ifdef ASN_BITS
case ASN_BITS :
SnmpUtilMemFree(asnValue.bits.stream);
break;
#endif
case ASN_OBJECTIDENTIFIER :
SnmpUtilMemFree(asnValue.object.ids);
break;
case ASN_SEQUENCE :
SnmpUtilMemFree(asnValue.sequence.stream);
break;
case ASN_IPADDRESS :
SnmpUtilMemFree(asnValue.address.stream);
break;
#ifdef ASN_OPAQUE
case ASN_OPAQUE :
SnmpUtilMemFree(asnValue.arbitrary.stream);
break;
#endif
}
asnType = ASN_INTEGER;
}
BOOL PWin32AsnAny::GetInteger(AsnInteger & i)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -