|
|
|
|
|
NOVELL服务器每隔60秒会发一个广播包,通报自己的信息,我可以借这个机会获取它的
MAC信息。可以从IPX包头中分析出有用的信息吗 |
|
|
通过每隔60秒的广播包,不行,因为程序实时地需要服务器地址做条件,可不可通过SPX建立连接,譬如发一个广播包,然后侦听返回包,从返回的包中的IPX包头,取包头中的源址 pxHeader->src,如果这样也行的话,不过还是有疑问?
?既然发一个广播包会不会所有在网段中的计算机都会返回,如果都返回,那么如何判断哪个又是NETWARE服务器的呢????? |
|
|
不行不行,那位大师救救小弟
|
|
|
难道各位大师见死不救吗????
难道各位大师见死不救吗???? 难道各位大师见死不救吗???? 难道各位大师见死不救吗???? |
|
|
难道各位大师见死不救吗????
难道各位大师见死不救吗???? 难道各位大师见死不救吗???? 难道各位大师见死不救吗???? |
|
|
非常的乐意你们的大驾
|
|
|
非常的感激你
|
|
|
La La La La La La La La La La La La La La La La La La La La La La La La
Paint |
|
|
我真的是好想知道这个问题的解,你们救救小弟吧
|
|
|
我把这个问题从C/C++,转到VC++,再转到C++ Builder,但是始终没有任何人回答我,
我好伤心, |
|
|
为什么,为什么,为什么,......................
|
|
|
#ifndef __IPXSPX_H__ #define __IPXSPX_H__ #include "C:\DOWN\IpxCheck_demo\dos\types.h" typedef void (cdecl far *TIpxSpxEntryPoint)(void); #define SOCK_SHORTLIVED 0x00 #define SOCK_LONGLIVED 0xFF //============================================================================= // Utility functions //============================================================================= // Returns TIpxStatus::ipxReturnCode description char *IpxGetErrorDesc(int errorcode); // Swap functions word Swap(word from); long Swap(long from); // Blank memory buffer void ZeroMemory(void *address, word length); //============================================================================= // struct TIpxAddress // //============================================================================= struct TIpxAddress { // Always set 0 (source and destination are on the same physical network) // High-low byte Network[4]; // Physical address of the node (unique number of the Ethernet card) // If it is 0xFFFFFFFFFFFF then this is a broadcast packet when it is // transmitted // High-low byte Node[6]; // Should use a value above 0x4000 and below 0x8000 // High-low byte Socket[2]; public: TIpxAddress(bool isbroadcast = False); void GetLocalAddress(void); bool IsBroadcast(void); bool IsSame(TIpxAddress *addr, bool useSocket = False); }; //============================================================================= // struct TIpxHeader // All numeric fields in TIpxHeader are high-low (MS byte in a field is the // first one). Intel processors have a low-high organization. //============================================================================= struct TIpxHeader { // IPX will set this field to 0xFFFF // High-low word Checksum; // Length of complete packet (30 for this header + max 546 for data) // IPX will set this field // High-low word Length; // IPX will set this field to 0 before sending the packet byte TransportControl; // Use always 4 for Packet Exchange Packet (IPX) byte PacketType; // Specifies destination station TIpxAddress Dest; // Specifies source station TIpxAddress Src; public: TIpxHeader(); void SetDestAddress(TIpxAddress *dest); void SetSrcAddress(TIpxAddress *src); }; //============================================================================ // struct TEventControlBlock // //============================================================================ // Borland C++ v3.1 uses AX register to load the correct DS (_loadds). Since // EventServiceRoutine receives the caller ID in AL, it is unavailable. // _ES:_SI contains a far pointer to the ECB. typedef void (_cdecl _far _loadds *TEventServiceRoutine)(void); struct TEventControlBlock { // Used internally by IPX only while InUse is != 0 void far *LinkAddress; // May be NULL TEventServiceRoutine EventServiceRoutine; // Different from 0 while IPX is working byte InUse; // Contains a return code from IPX byte CompletionCode; // High-low. Must be opened word SocketNumber; // Used internally. Must not be modified byte IPXWorkSpace[4]; byte DriverWorkspace[12]; // Set to destination node if there are no bridges on the network // High-low byte ImmediateAddress[6]; // Always set to 2 since there are 2 Frament(s) word FragmentCount; // Fragment[0] specifies the buffer and length for the IPX header (30 bytes) // Fragment[1] specifies the buffer and length for the IPX data (546 bytes) struct { void far *Address; word Length; } Fragment[2]; public: TEventControlBlock(); }; //============================================================================= // class TIpxStatus // //============================================================================= class TIpxStatus { public: enum ipxReturnCode { IpxSuccess = 0, IpxSocketTableIsFull, IpxSocketAlreadyOpen, IpxSocketNotOpen, IpxNoPathToDestination, IpxCannotCancelEcb, IpxEcbIsInUse, IpxEcbIsNotInUse, IpxDataTooLong, IpxAlreadyInUse, }; enum ecbCompletionCode { EcbOk = 0, EcbEventCanceled = 0xFC, EcbPacketMalformed = 0xFD, EcbUndeliverablePacket = 0xFE, EcbNetworkFailure = 0xFF, EcbBufferTooSmall = 0xFD, EcbSocketNotOpen = 0xFF, EcbCannotCancel = 0xF9 }; enum ecbInUse { EcbInUseFree = 0x00, EcbInUseProcessing = 0xFA, EcbInUseWaiting = 0xFB, EcbInUseWaitingForAESTimeout = 0xFC, EcbInUseWaitingForTimeout = 0xFD, EcbInUseListening = 0xFE, EcbInUseSending = 0xFF }; }; //============================================================================= // class TIpxSocket // //============================================================================= class TIpxSocket { private: bool Created; word Longevity; word Socket; word ErrorCode; // IPX.. funtions error code word ExErrorCode; // One of enums from TIpxStatus public: TIpxSocket(word socket = 0, bool create = True, word longevity = SOCK_SHORTLIVED); ~TIpxSocket(); word Create(void); void Destroy(void); word GetSocket(void); word GetLowHighSocket(void); word GetErrorCode(void); }; //============================================================================= // class TIpx // //============================================================================= class TIpx { private: word ErrorCode; // IPX.. functions error code word ExErrorCode; // One of enums from TIpxStatus char Data[546]; word DataLength; TIpxHeader Header; TEventControlBlock Ecb; TIpxSocket *SocketPtr; public: TIpx(TIpxSocket *socket = 0, TEventServiceRoutine proc = 0, word dataSize = 546); ~TIpx(); void SetSocket(TIpxSocket *socket); void SetDestination(TIpxAddress *dest, TIpxSocket *socket); int Send(void *data = 0, int length = 0); int Listen(void); int Cancel(void); int GetData(void far *data, int length); TIpxHeader far *GetHeader(TIpxHeader *hdr = 0) const; TEventControlBlock far *GetEcb(TEventControlBlock *ecb = 0) const; word GetErrorCode(void); bool IsCompleted(void); bool IsFree(void); static bool Init(void); }; //============================================================================= // struct TNetworkAddress // struct TNodeAddress // Partial network addresses //============================================================================= struct TNetworkAddress { byte NetworkNumber[4]; byte NodeAddress[6]; }; struct TNodeAddress { byte NodeAddress[6]; }; //============================================================================= // struct TConnectionInfo // //============================================================================= struct TConnectionInfo { byte ConnectStatus; byte Watchdog; word LocalConnectID; word RemoteConnectID; word SequenceNum; word LocalAcknowledgeNum; word LocalAllocationNum; word RemoteAcknowledgeNum; word RemoteAllocationNum; byte LocalSocket[2]; byte ImmediateAddress[6]; byte RemoteNetwork[4]; byte RemoteNode[6]; byte RemoteSocket[2]; word RetransmitCOunt; word EstRoundtripTime; word RetransmittedPackets; word SuppressedPackets; }; //============================================================================ // Function prototypes // Both IPX and SPX //============================================================================ // IPX functions bool IPXInitialize(void); word IPXCancelEvent(TEventControlBlock far *ecb); void IPXCloseSocket(word socket); void IPXDisconnectFromTarget(TIpxAddress far *rb); void IPXGetInternetworkAddress(TNetworkAddress far *rb); word IPXGetIntervalMarker(void); word IPXGetLocalTarget(TIpxAddress far *rb, TNodeAddress far *na); word IPXListenForPacket(TEventControlBlock far *ecb); word IPXOpenSocket(word longevity, word *socket); void IPXRelinquishControl(void); void IPXSendPacket(TEventControlBlock far *ecb); // SPX functions // We are not using SPX here !!! #if 0 void SPXAbortConnection(word connectionID); word SPXInitialize(byte *major, byte *minor, word *maxconn, word *availconn); word SPXEstablishConnection(word *connectionID, TEventControlBlock far *ecb, byte retrycount, byte watchdog); word SPXGetConnectionStatus(word connectionID, TConnectionInfo far *conninfo); void SPXListenForConnection(TEventControlBlock far *ecb, byte retrycount, byte watchdog); void SPXListenForSequencedPacket(TEventControlBlock far *ecb); void SPXSendSequencedPacket(word connectionID, TEventControlBlock far *ecb); void SPXTerminateConnection(word connectionID, TEventControlBlock far *ecb); #endif #endif /*############################################################################# # End of file IPXSPX.H #############################################################################*/ |
|
|
#include <dos.h>
#include <mem.h> #include <stdlib.h> //#include "C:\DOWN\IpxCheck_demo\dos\types.h" #include "C:\DOWN\IpxCheck_demo\dos\ipxspx.h" static TIpxSpxEntryPoint IpxSpxEntry = NULL; //============================================================================= // struct TIpxAddress // //============================================================================= TIpxAddress::TIpxAddress(bool isbroadcast) { memset(this,'\0',sizeof(*this)); if (isbroadcast) memset(this->Node,0xFF,6); } // // Local address is the address of the local machine Ethernet's card // void TIpxAddress::GetLocalAddress(void) { TNetworkAddress na; IPXGetInternetworkAddress(&na); memcpy(Network,na.NetworkNumber,4); memcpy(Node,na.NodeAddress,6); } bool TIpxAddress::IsBroadcast(void) { char cmpstr[6]; memset(&(cmpstr[0]),0xFF,6); return (memcmp(this->Node,&(cmpstr[0]),6) == 0) ? True : False; } bool TIpxAddress::IsSame(TIpxAddress *addr, bool useSocket) { if (memcmp(&(this->Node[0]),&(addr->Node[0]),6) == 0) { if (useSocket && (memcmp(&(this->Socket[0]),&(addr->Socket[0]),2) != 0)) return False; return True; } return False; } //============================================================================= // struct TIpxHeader // //============================================================================= TIpxHeader::TIpxHeader() { memset(this,'\0',sizeof(*this)); PacketType = 4; } void TIpxHeader::SetDestAddress(TIpxAddress *dest) { memcpy(&Dest,dest,sizeof(TIpxAddress)); } void TIpxHeader::SetSrcAddress(TIpxAddress *src) { memcpy(&Src,src,sizeof(TIpxAddress)); } //============================================================================= // struct TEventControlBlock // //============================================================================= TEventControlBlock::TEventControlBlock() { memset(this,'\0',sizeof(*this)); FragmentCount = 2; } //============================================================================= // class TIpxSocket // This class receives (via constructor) a socket number in low-high order. It // is internally converted to high-low and kept in this format. If requested // (via GetSocket()), return value is high-low //============================================================================= // // Input value is low-high // TIpxSocket::TIpxSocket(word socket, bool create, word longevity) { Longevity = longevity; Socket = Swap(socket); ErrorCode = 0; ExErrorCode = TIpxStatus::IpxSuccess; Created = create; } TIpxSocket::~TIpxSocket() { Destroy(); } // // Open a socket. Socket is not opened in constructor since this will prevent // static object of TIpxSocket 'cause IPX is not yet initialised // word TIpxSocket::Create(void) { if (Created) { ErrorCode = IPXOpenSocket(Longevity,&Socket); switch (ErrorCode) { case 0x00: ExErrorCode = TIpxStatus::IpxSuccess; break; case 0xFE: ExErrorCode = TIpxStatus::IpxSocketTableIsFull; break; case 0xFF: ExErrorCode = TIpxStatus::IpxSocketAlreadyOpen; break; } } return ExErrorCode; } // // Close a socket. This is implemented as a separate structure since the // object can be created as a static one and there are problems with // destructors (which one is executed first). // void TIpxSocket::Destroy(void) { if (Created) IPXCloseSocket(Socket); } // // Returned value is high-low // word TIpxSocket::GetSocket(void) { return Socket; } // // Returned value is low-high // word TIpxSocket::GetLowHighSocket(void) { return Swap(Socket); } word TIpxSocket::GetErrorCode(void) { return ExErrorCode; } //============================================================================= // class TIpx // //============================================================================= // Static function bool TIpx::Init(void) { return IPXInitialize(); } TIpx::TIpx(TIpxSocket *socket, TEventServiceRoutine proc, word /*dataSize*/) { ErrorCode = 0; ExErrorCode = TIpxStatus::IpxSuccess; DataLength = sizeof(Data); memset(&(Data[0]),'\0',DataLength); SocketPtr = socket; Ecb.SocketNumber = SocketPtr->GetSocket(); Ecb.EventServiceRoutine = proc; } TIpx::~TIpx() { Cancel(); while (!IsCompleted()) ; } // // If the object is created with a default constructor (Socket = NULL), I // have to assign a socket to this object after construction. This is a // socket on which the object is listening to. // void TIpx::SetSocket(TIpxSocket *socket) { SocketPtr = socket; Ecb.SocketNumber = SocketPtr->GetSocket(); } // // Destination socket does not have to be opened // void TIpx::SetDestination(TIpxAddress *dest, TIpxSocket *socket) { word sock = socket->GetSocket(); // sock is low-high memcpy(&(dest->Socket[0]),&sock,sizeof(word)); Header.SetDestAddress(dest); /*** No need for this since we're always on the same network TNodeAddress na; ErrorCode = IPXGetLocalTarget(dest,&na); switch (ErrorCode) { case 0x00: ExErrorCode = TIpxStatus::IpxSuccess; break; case 0xFA: ExErrorCode = TIpxStatus::IpxNoPathToDestination; break; }; memcpy(&(Ecb.ImmediateAddress[0]),&(na.NodeAddress[0]),6); ***/ memcpy(&(Ecb.ImmediateAddress[0]),&(Header.Dest.Node[0]),6); } // // data length must not be greater then 546 bytes // int TIpx::Send(void *data, int length) { if (Ecb.InUse != TIpxStatus::EcbInUseFree) return TIpxStatus::IpxAlreadyInUse; if (length > 546) return TIpxStatus::IpxDataTooLong; memset(Data,'\0',sizeof(Data)/sizeof(Data[0])); DataLength = length; if (data) memcpy(Data,data,DataLength); Header.Checksum = 0; Header.Length = 0; memset(&(Header.Src),'\0',sizeof(TIpxAddress)); //Header.Src.GetLocalAddress(); Ecb.FragmentCount = 2; Ecb.Fragment[0].Address = &Header; Ecb.Fragment[0].Length = sizeof(TIpxHeader); Ecb.Fragment[1].Address = &(Data[0]); Ecb.Fragment[1].Length = DataLength; IPXSendPacket(&Ecb); return TIpxStatus::IpxSuccess; } int TIpx::Listen(void) { if (Ecb.InUse != TIpxStatus::EcbInUseFree) return TIpxStatus::IpxAlreadyInUse; DataLength = sizeof(Data); Ecb.FragmentCount = 2; Ecb.Fragment[0].Address = &Header; Ecb.Fragment[0].Length = sizeof(TIpxHeader); Ecb.Fragment[1].Address = &(Data[0]); Ecb.Fragment[1].Length = DataLength; ErrorCode = IPXListenForPacket(&Ecb); switch (ErrorCode) { case 0x00: ExErrorCode = TIpxStatus::IpxSuccess; break; case 0xFF: ExErrorCode = TIpxStatus::IpxSocketNotOpen; break; }; return ExErrorCode; } int TIpx::Cancel(void) { ErrorCode = IPXCancelEvent(&Ecb); switch (ErrorCode) { case 0x00: ExErrorCode = TIpxStatus::IpxSuccess; break; case 0xF9: ExErrorCode = TIpxStatus::IpxCannotCancelEcb; break; case 0xFF: ExErrorCode = TIpxStatus::IpxEcbIsNotInUse; break; }; return ExErrorCode; } // // Length of received packet's data part is in the Length field of the Ipx // header (must substract size of header) // int TIpx::GetData(void far *data, int length) { int len = Swap(Header.Length); len -= sizeof(TIpxHeader); if (len > length) len = length; memcpy(data,&(Data[0]),len); return len; } TIpxHeader far *TIpx::GetHeader(TIpxHeader *hdr) const { if (hdr) memcpy(hdr,&Header,sizeof(TIpxHeader)); return (TIpxHeader far *)&Header; } TEventControlBlock far *TIpx::GetEcb(TEventControlBlock *ecb) const { if (ecb) memcpy(ecb,&Ecb,sizeof(TEventControlBlock)); return (TEventControlBlock far *)&Ecb; } word TIpx::GetErrorCode(void) { return ExErrorCode; } // // Let Ipx work and then check if it's Ecb is free // bool TIpx::IsCompleted(void) { IPXRelinquishControl(); return (Ecb.InUse) ? False : True; } bool TIpx::IsFree(void) { return (Ecb.InUse == 0) ? True : False; } //============================================================================= // IPX functions // Each function returns an error code 0x0x01 if the IPX is not initialized // (function IPXInitialize()) which means that the static pointer IpxSpxEntry // is not valid (is NULL). //============================================================================= // // Must be called before any other function since this function will return // a pointer to IPX/SPX entry point. // The IPX major and minor version values are stored in two bytes pointed to // by ES:BX after calling Int 2Fh AX=7A00h which gets the IPX far call handler // address. // bool IPXInitialize(void) { union REGS regs; struct SREGS sregs; regs.x.ax = 0x7A00; int86x(0x2F,®s,®s,&sregs); if (regs.h.al != 0xFF) return False; IpxSpxEntry = (TIpxSpxEntryPoint)MK_FP(sregs.es,regs.x.di); _AX = 0x7A00; asm int 02Fh; if (_AL != 0xFF) return False; IpxSpxEntry = (TIpxSpxEntryPoint)MK_FP(_ES,_DI); return True; } // // Will not execute ESR! Will set InUse flag to != 0. After canceling, InUse // will be set to 0. // Return code: // 0x00 - success // 0xF9 - ECB cannot be canceled // 0xFF - ECB is not in use // Possible ECB completion code: // 0xFC - Event canceled // word IPXCancelEvent(TEventControlBlock far *ecb) { if (IpxSpxEntry) { _BX = 0x0006; _ES = FP_SEG(ecb); _SI = FP_OFF(ecb); IpxSpxEntry(); return _AL; } return 0x01; } // // Sockets must be closed before the program terminates. Closing a socket will // cancel any events associated with a socket. // Will returns a value of FCh in ECB's Completion Code field indicating the // event has been cancelled. Sets each ECB's In Use field to 00h. // IPX does not call the ECBs' associated Event Service Routines. // Any socket number can be closed; no error is generated if the specified // socket is not open. Must not be called from within an Event Service Routine. // socket is low-high order (this is from the Novell Web site) // void IPXCloseSocket(word socket) { if (IpxSpxEntry) { _BX = 0x01; _DX = socket; IpxSpxEntry(); } } // // Courtesy to the other (listening) side. Must not be called from within // an ESR. Must not be called from within an Event Service Routine. // All fields in *rb are high-low. // void IPXDisconnectFromTarget(TIpxAddress far *rb) { if (IpxSpxEntry) { _BX = 0x000B; _ES = FP_SEG(rb); _SI = FP_OFF(rb); IpxSpxEntry(); } } // // Returns information for the local station. // void IPXGetInternetworkAddress(TNetworkAddress far *rb) { if (IpxSpxEntry) { _BX = 0x0009; _ES = FP_SEG(rb); _SI = FP_OFF(rb); IpxSpxEntry(); } } // // Use DOS timer tick instead of this. // Returned value is in high-low order. // The result is accurate even if the clock cycle wraps to zero between the // first and second event. The result is not accurate if the clock cycle // wraps to zero twice. This timer is not intended for use with large time // intervals. // word IPXGetIntervalMarker(void) { if (IpxSpxEntry) { _BX = 0x0008; IpxSpxEntry(); return _AX; // ulong far *tickPtr = MK_FP(0x0040,0x006C); // ulong then = *tickPtr; // do something... // ulong now = *tickPtr; } return 0; } // // For a given destination (rb), it returns a routing information (na). Copy // this into the ECB ImmediateAddress field. (na) can be either bridge address // or the destination station itself (no bridge found). // When IPX receives a packet, it records the node address of the sending node // in the Immediate Address field of the receive ECB. Therefore, once an // application begins exchanging packets with an application on another node, // the application can search the Immediate Address field of each receive ECB // to obtain the Local Target value instead of continually calling // IPXGetLocalTarget. IPX Get Local Target can be called from within an IPX // Event Service Routine, an AES Event Service Routine, or directly from the // main portion of an application. It cannot be called from any other kind of // interrupt service routine. // Return code: // 0x00 - Success // 0xFA - No path or destination // *rb and *na are both high-low // word IPXGetLocalTarget(TIpxAddress far *rb, TNodeAddress far *na) { if (IpxSpxEntry) { _BX = 0x0002; _ES = FP_SEG(rb); _SI = FP_OFF(rb); //_ES = FP_SEG(na); _DI = FP_OFF(na); IpxSpxEntry(); // na = (TNodeAddress far *)MK_FP(_ES,_DI); // CX contains estimated transport time in timer ticks (18.2) // The Transport Time is an estimate of the time a 576-byte packet takes to // travel from the source node to the destination node (in clock ticks of // approximately 1/18 second). Since the returned value is only an estimate, // actual travel time may vary depending on network traffic and packet size. // AH contains number of hops to the destination station return _AL; } return 0x01; } // // IPX returns immediately and waits for the packet in background. // Following ECB fields must be set: // SocketNumber - previously opened with IPXOpenSocket // EventServiceRoutine - pointer or NULL // FragmentCount - typically a value of 2 (header and data) // Fragment[0].Address - far pointer to IPX header buffer // Fragment[0].Length - length of the IPX header (30) // Fragment[1].Address - far pointer for message data area (max 546 bytes) // Fragment[1].Length - length of data area // Return code: // 0x00 - success // 0xFF - listening socket does not exists // ECB completion code: // 0x00 - packet received successfully // 0xFC - this event is canceled // 0xFD - buffer too small // 0xFF - socket not open // word IPXListenForPacket(TEventControlBlock far * /*ecb*/) { if (IpxSpxEntry) { /* _BX = 0x04; _ES = FP_SEG(ecb); _SI = FP_OFF(ecb); */ asm { mov bx,0004h; mov si,[bp+6]; mov es,[bp+8]; } IpxSpxEntry(); return _AL; } return 0x01; } // // If the specified *socket is 0, then IPX will allocate a socket in the range // 0f 0x4000 to 0x8000. // *socket has a high-low organization. // longevity can be 0x00 for short-lived or 0xFF for long lived // Terminate-and-stay-resident applications that need to communicate via IPX // packets should specify FFH to leave the socket open. All other applications // should set this flag to 00h to ensure the socket is closed when the application // (accidentally or purposefully) terminates. // By default, IPX supports up to 20 open sockets on one workstation. The value // can be configured to open up to 150 sockets on one workstation. // Return code: // 0x00 - success // 0xFE - socket table is full // 0xFF - Socket already open // word IPXOpenSocket(word longevity, word *socket) { if (IpxSpxEntry) { _AL = longevity; _DX = *socket; // this line scrambles _BX _BX = 0x0000; IpxSpxEntry(); *socket = _DX; return _AL; } return 0x01; } // // IPX Relinquish Control relinquishes control of a workstation CPU from // the application, so that other processing can be handled while the // application is waiting for input. // // IPX applications should make repeated calls to this function during // idle time to allow other applications in the computer to use the CPU. // This is especially important when the application is resident with // NetWare server or bridge software because it greatly improves the // efficiency of the server or bridge. // // A call to this function also informs the workstation communications // driver that the CPU is temporarily free. This is important if the // driver is not interrupt driven. On a normal workstation, this function // invokes a polling procedure provided by the network communications // driver. It represents the only opportunity the driver has to use the // CPU to send and receive packets; events essential to the application // itself. // es:si=ECB address (Is this OK?) // void IPXRelinquishControl(void) { if (IpxSpxEntry) { _BX = 0x000A; IpxSpxEntry(); } } // // Will send a packet in the background. // An application can send or broadcast an IPX packet to any socket on // the internetwork including the socket on which the application sends // the packet. Packets sent to sockets that reside in the same node as // the application are called intranode packets. // Following ECB fields must be set: // SocketNumber - previously opened with IPXOpenSocket // EventServiceRoutine - function pointer or NULL // ImmediateAddress - target node or bridge address // FragmentCount - Equals 2 (for header and data) // Fragment[0] - Defines area for header // Fragment[1] - Defines area for data // Following IPXHeader fields must be set: // PacketType - Equals 4 // DestNetworkNumber // DestNodeNumber // DestSocket // ECB completion code: // 0x00 - packet sent successfully // 0xFC - this event is canceled // 0xFD - bad packet // 0xFE - undeliverable packet // 0xFF - hardware or network failure // void IPXSendPacket(TEventControlBlock far * /*ecb*/) { if (IpxSpxEntry) { /* _BX = 0x03; _ES = FP_SEG(ecb); _SI = FP_OFF(ecb); */ asm { mov bx,0003h; mov si,[bp+6]; mov es,[bp+8]; } IpxSpxEntry(); } } #if 0 // We are not using SPX here !!! // // Generates a checksum for a packet defined in ecb. Will be placed into the // header's Checksum field. Do not modify packet after the checksum is // generated. // IPX Generate Checksum enables interrupts and is fully re-entrant. // IPX Generate Checksum is provided for programs that wish to use // IPXFastSend to send checksummed packets. As with IPXFastSend, the caller // must initialize all IPX header fields. However, IPX Generate Checksum will // initialize the Checksum and TransportControl fields. // void IPXGenerateChecksum(TEventControlBlock far *ecb) { if (IpxSpxEntry) { _BX = 0x21; _ES = FP_SEG(ecb); _SI = FP_OFF(ecb); IpxSpxEntry(); } } int IPXGetMaxPacketSize(void) { if (IpxSpxEntry) { _BX = 0x001A; IpxSpxEntry(); // _CX contains an IPX retry count // Max paxket size will never be less then 576 return _AX; } return 0x01; } // // IPX Send With Checksum behaves exactly the same as IPXSendPacket, // except that a checksum is generated for the packet data and placed in // the IPX checksum field before it is transmitted. // void IPXSendWithChecksum(TEventControlBlock far *ecb) { if (IpxSpxEntry) { _BX = 0x0020; _ES = FP_SEG(ecb); _SI = FP_OFF(ecb); IpxSpxEntry(); } } // // IPX Verify Checksum determines whether or not the packet data received // is corrupt. This is done by generating a new checksum for the data and // comparing it to the checksum in the IPX header checksum field. // int IPXVerifyChecksum(TEventControlBlock far *ecb) { if (IpxSpxEntry) { _BX = 0x0022; _ES = FP_SEG(ecb); _SI = FP_OFF(ecb); IpxSpxEntry(); return _AX; } return 0x01; } #endif //============================================================================ // SPX functions // //============================================================================ #if 0 void SPXAbortConnection(word connectionID) { _BX = 0x14; _DX = connectionID; IpxSpxEntry(); } word SPXInitialize(byte *major, byte *minor, word *maxconn, word *availconn) { _BX = 0x10; _AX = 0x00; IpxSpxEntry(); *major = _BH; *minor = _BL; *maxconn = _CX; *availconn = _DX; return _AL; } word SPXEstablishConnection(word *connectionID, TEventControlBlock far *ecb, byte retrycount, byte watchdog) { _BX = 0x11; _AL = retrycount; _AH = watchdog; _ES = FP_SEG(ecb); _SI = FP_OFF(ecb); IpxSpxEntry(); *connectionID = _DX; return _AL; } word SPXGetConnectionStatus(word connectionID, TConnectionInfo far *conninfo) { _BX = 0x15; _DX = connectionID; _ES = FP_SEG(conninfo); _SI = FP_OFF(conninfo); IpxSpxEntry(); return _AL; } void SPXListenForConnection(TEventControlBlock far *ecb, byte retrycount, byte watchdog) { _BX = 0x12; _AL = retrycount; _AH = watchdog; _ES = FP_SEG(ecb); _SI = FP_OFF(ecb); IpxSpxEntry(); } void SPXListenForSequencedPacket(TEventControlBlock far *ecb) { _BX = 0x17; _ES = FP_SEG(ecb); _SI = FP_OFF(ecb); IpxSpxEntry(); } void SPXSendSequencedPacket(word connectionID, TEventControlBlock far *ecb) { _BX = 0x16; _DX = connectionID; _ES = FP_SEG(ecb); _SI = FP_OFF(ecb); IpxSpxEntry(); } void SPXTerminateConnection(word connectionID, TEventControlBlock far *ecb) { _BX = 0x13; _DX = connectionID; _ES = FP_SEG(ecb); _SI = FP_OFF(ecb); IpxSpxEntry(); } #endif //============================================================================= // Utility functions // //============================================================================= char *IpxGetErrorDesc(int errorcode) { static char *text[] = { "Success", "Socket table is full", "Socket is already open", "Socket is not opened", "No path or destination", "Cannot cancel ECB", "ECB is in use", "ECB is not in use", "Data buffer is too long", "Already in use for either send or listen", }; return (char*)text[errorcode]; } word Swap(word from) { word temp; swab((char*)&from,(char*)&temp,sizeof(word)); return temp; } long Swap(long from) { long temp; swab((char*)&from,(char*)&temp,sizeof(long)); return temp; } void ZeroMemory(void *address, word length) { memset(address,'\0',length); } /*############################################################################# # End of file IPXSPX.CPP #############################################################################*/ |
|
|
这是C++封装的IPX协议,请高手帮忙
|
|
|
这个网站有一些NOVELL程序的例子,还有个dos下的c函数包netclb.zip和一个vcl组件,你可以试试。
http://www.pandoratools.de/1298/0bp.htm |
|
|
你是最惨的一个。只有一个人回应你。
我曾在dos下变过一个ipx/spx程序,时间太长了,忘了什么是mac地址了。不过有源码。 |
|
|
我向世界呼救,有没有有关的源程序!!!!!!!!!!!!!!!!!!!!!!!!
|
|
|
有一种办法可以在DOS环境下,取得SERVER的MAC地址,
不过不需要IPX/SPX,是从CLIENT(DOS)上装载NETBIOS 模块,然后使用NETBIOS调用就行了。 如果只要取MAC地址,这样做比较简单,希望对你有用。 |
|
|
我没有这方面的资料,有没有源程序,或者这方面的LIB
谢谢你的支持 |
|
|
to rmirp:
如果你考虑我所说的方法,EMAIL TO :jeff_c@371.net |
|
|
我在大学里的时候写过一些Novell下的应用程序,都是c里面套中断,后来找到一个c的Lib+h可以实现很多的novell功能调用(比我原来写的要多),如果你一定非常需要的话我可以去找找,应该在光盘上,我记得我后来将我在学校里写的程序全部刻到光盘上去了,虽然没有什么用,以作纪念吧。
至于什么是Mac地址,应该有的,另外我在Windows下好像也有过类似的东西,代码如下: sorry,找不着了。终于找到了。 void getmac_one (int lana_num , CString &mdcAddress) { NCB ncb; UCHAR uRetCode; memset( &ncb, 0, sizeof(ncb) ); ncb.ncb_command = NCBRESET; ncb.ncb_lana_num = lana_num; // 指 定 网 卡 号 首 先 对 选 定 的 网 卡 发 送 一 个 // NCBRESET 命 令, 以 便 进 行 初 始 化 uRetCode = Netbios( &ncb ); // printf( "The NCBRESET return code is: 0x %x \n", uRetCode ); memset( &ncb, 0, sizeof(ncb) ); ncb.ncb_command = NCBASTAT; ncb.ncb_lana_num = lana_num; // 指 定 网 卡 号 strcpy((char *)ncb.ncb_callname,"* " ); ncb.ncb_buffer = (unsigned char *) &Adapter; // 指 定 返 回 的 信 息 存 放 的 变 量 ncb.ncb_length = sizeof(Adapter); // 接 着, 可 以 发 送NCBASTAT 命 令 以 获 取 网 卡 的 信 息 uRetCode = Netbios( &ncb ); printf( "The NCBASTAT return code is:0x %x \n", uRetCode ); if ( uRetCode == 0 ) { // 把 网 卡MAC 地 址 格 式 化 成 常 用 的16 进 制 形 式, 如0010 -A4E4 -5802 // printf( "The Ethernet Number[ %d] is: %02X %02X - %02X %02X - %02X %02X\n", mdcAddress.Format("网卡[%d]地址是:%02X%02X-%02X%02X-%02X%02X", lana_num, Adapter.adapt.adapter_address[0], Adapter.adapt.adapter_address[1], Adapter.adapt.adapter_address[2], Adapter.adapt.adapter_address[3], Adapter.adapt.adapter_address[4], Adapter.adapt.adapter_address[5] ); } } |
|
|
oldworm,你跟jeff_z一样是根据Netbios命令解决问题的,但NETBIOS我只有WINDOWS自带NETAPI
并且在VC++6.0环境中,编过一个程式,在dos16位环境,我没有LIB+H,与它的详细一点的说明 |
|
我除了这里提供的一个招来的东西之外还有自己写的for dos的东西,另外还有一个dos下用的Lib+h+help,不过都在光盘上。
|
|
我曾在adams提拱的地址上,下了NetWare的c的LIB3.0,LIB3.5,但是经过非常仔细的考虑,发现没有
这样的功能,除了能返回本机网卡的MAC之外,其它一无所用,当然它有很多的功能,不过不 我所要的。但是不知道有没有4.0,或更高的VER。 |
|
有谁能救我
|
|
怒了,我就不信解决不了你的这个问题,不过说实话,如果你四年前问我我立刻给你写程序出来。
|
|
去找一个helppc2.0,里面有所有dos 中断调用说明包括ipx/spx.
似乎在ips/spx调用服务中有获取服务器的mac地址的调用, 再不行,就找嗅探器捕获server与client的通讯并分析,模拟一个client普通的 操作,获取返回包即可得到server地址 |
|
如果模拟ncp协议发一个寻找server的广播的话,
不是server的不会响应你的广播的 |
|
你要是着急,就去www.experts-exchange.com去问吧,一般很快就有答复。
|
|
建议你使用Client 32 for DOS,之中相信可以找到你要的东东。
这还是早先的INT 7A功能调用。不过你可以使用以下功能: GetLANDriverConfigInfo 功能:取文件服务器的网络驱动器的配置信息; 说明:使用DOS中断E3H第E3H号功能; 输入:DS:SI指向requestBuf 0 requestBuf Len -2 int 2 E3H char 3 网卡号(0-3) char ES:DI返回缓冲区: replybuf最大长度为174个字节 0 replyBuf长度-2 int 2 网络地址(Network Address) char[4] 6 主机地址(Host Address) char[6] 12 网络驱动器安装 char 之后就是一些你不需要的信息了。 另外问一个问题: 你要服务器的MAC地址干什么呢? 再用一个笨一点(但很实用)的办法就是在配置文件之中指定服务器的MAC地址。 再者你向服务器发送IPX包不需要服务器的MAC地址,而只需要虚拟地址: 如你的网络号是000666,则服务器地址可用000666:000000000001。 |
|
另外我需要你明确的是:
你要NOVELL服务器的MAC地址是指什么MAC地址? 因为NOVELL服务器一般通讯时都用的是虚拟MAC地址, 即网段号加上0000000000X之类的地址; 另外一个就是服务器网卡的地址(例如0050BAXXXXXX)之类的; 在NOVELL环境通讯时只需要第一种类型的地址; 不知你是否了解802.3格式的帧协议?如下所示 |dst net|dst addr|src net|src addr|LLC|IPX-header| IPX/SPX是基于802.3帧协议之上的协议。 与服务器通讯时,在IPX-header之中有一个dst addr,但这是IPX 协议之上的,服务器是使用NetAddr+NodeAddr组成的, 而在基于IEEE 802.3帧协议之中的dst addr却是Novell网卡的真实地址。 所以,你用获得IPX帧来分析服务器的MAC地址是不可能得到的.除非你去分析IEEE 802.3协议帧 |
|
papachong,见到你的回贴,使我看到一点希望,
我要的MAC地址是物理的文件服务器的网卡地址, 而不是在NCF文件中加上NODE=XXXXXXXXXXX; 我要得到文件服务器的网卡地址,是用于加密, 所以我必须得到物理的网卡地址, 你提到的Client 32 for DOS,在CLIENT端是不是 只运行VLM就可以,另外你有没有Client 32 for DOS的 开发包,或者LIB+H+README 关于你说的不能用IPX帧来分析服务器的真实的MAC地址,我用NetxRay已经 证实了你的话是对的.对于分析IEEE 802.3协议帧或者IEEE 802.2协议帧我 没有那方面的经验,不知你有没有IEEE 802.2协议帧这方面的资料(如果有 示例的源程序就最好了.^-^). |
|
如果你的网卡是装在工作站上,利用NETWARE NCP服务可以先获取本机与服务器的连接号,再利用
NCP服务取得网卡地址,不过对服务器我就不大清楚了。 获取本机连接号:int 21h ,ah=e3h,type=0ah; 获取网络地址:int 21h ,ah=e3h,type=13h; 这是参考的谭浩强主编的《网络实用编程技术》,不过这本书附带软盘的程序录入错误一大堆, 相信根本没经过调试,很难用。 |