📄 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.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#pragma comment(lib, "snmpapi.lib")#endif///////////////////////////////////////////////////////////////////////////////// Stuff from snmp.h#ifndef RFC1157VarBindListtypedef 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 0x0020typedef 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; }#endifpublic: 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_WCEclass 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;};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -