📄 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.1 2006/06/29 04:18:40 joegenbaclor
* *** empty log message ***
*
* Revision 1.48 2006/04/09 11:03:59 csoutheren
* Remove warnings on VS.net 2005
*
* Revision 1.47 2005/11/30 12:47:42 csoutheren
* Removed tabs, reformatted some code, and changed tags for Doxygen
*
* Revision 1.46 2005/09/18 13:01:43 dominance
* fixed pragma warnings when building with gcc.
*
* Revision 1.45 2005/07/13 11:48:54 csoutheren
* Backported QOS changes from isvo branch
*
* Revision 1.44.4.1 2005/04/25 13:33:56 shorne
* Extra support for DHCP Environment (Win32)
*
* Revision 1.44 2004/10/23 10:52:59 ykiryanov
* Added ifdef _WIN32_WCE for PocketPC 2003 SDK port
*
* Revision 1.43 2004/06/30 12:17:06 rjongbloed
* Rewrite of plug in system to use single global variable for all factories to avoid all sorts
* of issues with startup orders and Windows DLL multiple instances.
*
* Revision 1.42 2004/06/08 01:19:22 csoutheren
* Fixed problem with SNMP library not loading under Windows in some cases
*
* Revision 1.41 2004/06/01 05:24:12 csoutheren
* Changed loading of inetmib1.dll to use PProcessStartup to avoid crashes when it is unloaded before ~H323Endpoint is called
*
* Revision 1.40 2004/01/30 02:06:06 csoutheren
* Added mutex to avoid threading problems on Windows
* Thanks to Hans Verbeek
*
* Revision 1.39 2003/11/05 22:51:22 csoutheren
* Added pragma to automatically included required libs
*
* Revision 1.38 2003/09/17 05:45:10 csoutheren
* Removed recursive includes
*
* Revision 1.37 2003/04/01 06:01:48 robertj
* Fixed problem with returning correct route table device name if have
* 2 NIC's under Windows 2000, thanks faa06@tid.es
*
* Revision 1.36 2003/01/11 05:10:51 robertj
* Fixed Win CE compatibility issues, thanks Joerg Schoemer
*
* Revision 1.35 2002/11/12 02:22:16 robertj
* Fixed problem where if SNMP not correctly installed on some flavours of
* windows (eg ME) the system cannot find any interfaces. Added fail safe
* that if could not determine one, it uses the ip address of gethostname()
* which should be one of the interfaces on the system.
*
* Revision 1.34 2002/11/08 06:45:23 robertj
* Fixed problem with very long interface names, pointed out by Kees Klop.
*
* Revision 1.33 2002/10/08 12:41:52 robertj
* Changed for IPv6 support, thanks S閎astien Josset.
*
* Revision 1.32 2002/02/25 09:57:29 robertj
* Fixed possible NULL pointer use and memory leak, thanks Klaus K鰊ig
*
* Revision 1.31 2002/02/15 03:56:46 yurik
* Warnings removed during compilation, patch courtesy of Jehan Bing, jehan@bravobrava.com
*
* 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>
#ifndef _WIN32_WCE
#ifdef _MSC_VER
#pragma comment(lib, "snmpapi.lib")
#endif
#endif
///////////////////////////////////////////////////////////////////////////////
// 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/msos/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)
public:
#else
{
public:
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, PString & str);
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);
PIPSocket::Address GetInterfaceAddress(int ifNum);
static PWin32SnmpLibrary & Current();
static PMutex & GetMutex();
private:
PMutex mutex;
BOOL (WINAPI *_Init)(DWORD,HANDLE*,AsnObjectIdentifier*);
BOOL (WINAPI *_Query)(BYTE,SnmpVarBindList*,AsnInteger32*,AsnInteger32*);
BOOL Init(DWORD upTime, HANDLE * trapEvent, AsnObjectIdentifier * firstSupportedRegion)
{ return (*_Init)(upTime, trapEvent, firstSupportedRegion); }
BOOL Query(BYTE pduType, SnmpVarBindList * pVarBindList, AsnInteger32 * pErrorStatus, AsnInteger32 * pErrorIndex)
{ return _Query(pduType, pVarBindList, pErrorStatus, pErrorIndex); }
BOOL QueryOid(BYTE cmd, AsnObjectIdentifier & oid, PWin32AsnAny & value);
};
class WinSNMPLoader : public PProcessStartup
{
PCLASSINFO(WinSNMPLoader, PProcessStartup);
public:
void OnStartup()
{ }
PWin32SnmpLibrary & Current()
{
PWaitAndSignal m(mutex);
if (snmpLibrary == NULL) {
snmpLibrary = new PWin32SnmpLibrary;
}
return *snmpLibrary;
}
void OnShutdown()
{
PWaitAndSignal m(mutex);
delete snmpLibrary;
snmpLibrary = NULL;
}
protected:
PMutex mutex;
static PWin32SnmpLibrary * snmpLibrary;
};
PWin32SnmpLibrary * WinSNMPLoader::snmpLibrary = NULL;
static PFactory<PProcessStartup>::Worker<WinSNMPLoader> winSNMPLoadedStartupFactory("WinSNMPLoader", true);
PWin32SnmpLibrary & PWin32SnmpLibrary::Current()
{
return ((WinSNMPLoader *)PFactory<PProcessStartup>::CreateInstance("WinSNMPLoader"))->Current();
}
PMutex & PWin32SnmpLibrary::GetMutex()
{
return Current().mutex;
}
#define GetSNMPMutex PWin32SnmpLibrary::GetMutex
///////////////////////////////////////////////////////////////////////////////
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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -