458 lines
13 KiB
C
458 lines
13 KiB
C
|
#include "ipxdefs.h"
|
||
|
|
||
|
#if DBG
|
||
|
#define ASSERTERR(exp) \
|
||
|
if (!(exp)) { \
|
||
|
DbgPrint("Get last error= %d\n", GetLastError ()); \
|
||
|
RtlAssert( #exp, __FILE__, __LINE__, NULL ); \
|
||
|
}
|
||
|
#else
|
||
|
#define ASSERTERR(exp)
|
||
|
#endif
|
||
|
|
||
|
#if DBG
|
||
|
#define ASSERTERRMSG(msg,exp) \
|
||
|
if (!(exp)) { \
|
||
|
DbgPrint("Get last error= %d\n", GetLastError ()); \
|
||
|
RtlAssert( #exp, __FILE__, __LINE__, msg ); \
|
||
|
}
|
||
|
#else
|
||
|
#define ASSERTERRMSG(msg,exp)
|
||
|
#endif
|
||
|
|
||
|
typedef struct _SERVICE_ENTRY {
|
||
|
USHORT type;
|
||
|
BYTE name[48];
|
||
|
IPX_ADDRESS_BLOCK addr;
|
||
|
USHORT hops;
|
||
|
} SERVICE_ENTRY, *PSERVICE_ENTRY;
|
||
|
|
||
|
|
||
|
typedef struct _SAP_PACKET {
|
||
|
OVERLAPPED ovrp;
|
||
|
LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine;
|
||
|
ADDRESS_RESERVED rsvd;
|
||
|
IPX_HEADER hdr;
|
||
|
union {
|
||
|
UCHAR data[576-sizeof(IPX_HEADER)];
|
||
|
struct {
|
||
|
USHORT operation;
|
||
|
SERVICE_ENTRY entry[7];
|
||
|
} sap;
|
||
|
};
|
||
|
} SAP_PACKET, *PSAP_PACKET;
|
||
|
|
||
|
#define SAP_SOCKET_NUM 0x0452
|
||
|
|
||
|
|
||
|
|
||
|
VOID CALLBACK
|
||
|
SendCompletion (
|
||
|
DWORD status,
|
||
|
DWORD cbBytes,
|
||
|
LPOVERLAPPED context
|
||
|
);
|
||
|
|
||
|
VOID CALLBACK
|
||
|
RecvCompletion (
|
||
|
DWORD status,
|
||
|
DWORD cbBytes,
|
||
|
LPOVERLAPPED context
|
||
|
);
|
||
|
|
||
|
BOOL WINAPI
|
||
|
CtrlHandler (
|
||
|
DWORD fdwCtrlType
|
||
|
);
|
||
|
|
||
|
static BOOL *AdapterArr;
|
||
|
static SAP_PACKET recvPacket;
|
||
|
static HANDLE hdl[3];
|
||
|
static ULONG CurAdapter;
|
||
|
static LONG NumActiveAdapters;
|
||
|
static ADAPTERS_GLOBAL_PARAMETERS gParam;
|
||
|
static HANDLE sockPort=INVALID_HANDLE_VALUE;
|
||
|
static BOOL Stop;
|
||
|
|
||
|
|
||
|
int __cdecl main (
|
||
|
int argc,
|
||
|
char **argv
|
||
|
) {
|
||
|
HANDLE cfgHdl;
|
||
|
WCHAR name[64];
|
||
|
ULONG i, len=sizeof (name);
|
||
|
ADAPTER_INFO params;
|
||
|
DWORD status;
|
||
|
ULONG adpStatus;
|
||
|
PSAP_PACKET sendPacket;
|
||
|
LONG nObjects=2;
|
||
|
HANDLE compHdl;
|
||
|
|
||
|
|
||
|
printf ("**** Starting Up...\n\n");
|
||
|
|
||
|
hdl[0] = CreateEvent (NULL, // def security
|
||
|
TRUE, // manual reset
|
||
|
FALSE, // initially non-signaled
|
||
|
NULL);
|
||
|
ASSERTERRMSG ("Can't create Ipx event. ", hdl[0]!=NULL);
|
||
|
|
||
|
hdl[1] = CreateEvent (NULL, // def security
|
||
|
TRUE, // manual reset
|
||
|
FALSE, // initially non-signaled
|
||
|
NULL);
|
||
|
ASSERTERRMSG ("Can't create console event. ", hdl[1]!=NULL);
|
||
|
|
||
|
Stop = FALSE;
|
||
|
status = SetConsoleCtrlHandler (
|
||
|
&CtrlHandler,
|
||
|
TRUE
|
||
|
);
|
||
|
ASSERTERRMSG ("Can't set console ctrl handler. ", status);
|
||
|
|
||
|
|
||
|
printf ("Press CTRL+C at any time to terminate this program\n.");
|
||
|
|
||
|
cfgHdl = IpxCreateAdapterConfigurationPort (
|
||
|
hdl[0],
|
||
|
&gParam);
|
||
|
ASSERTERRMSG ("Can't create config port. ",
|
||
|
cfgHdl!=INVALID_HANDLE_VALUE);
|
||
|
ASSERTMSG ("No adapters available. ", gParam.AdaptersCount>0);
|
||
|
|
||
|
AdapterArr = (BOOL *)GlobalAlloc (GMEM_FIXED, sizeof (BOOL)*(gParam.AdaptersCount+1));
|
||
|
ASSERTERRMSG ("Can't allocate adapter array. ", AdapterArr!=NULL);
|
||
|
for (i=0; i<=gParam.AdaptersCount; i++)
|
||
|
AdapterArr[i] = FALSE;
|
||
|
CurAdapter = 0xFFFFFFFF;
|
||
|
NumActiveAdapters = -1;
|
||
|
while (!Stop) {
|
||
|
status=WaitForMultipleObjectsEx (
|
||
|
nObjects,
|
||
|
hdl,
|
||
|
FALSE, // Wait for any object to complete
|
||
|
INFINITE,
|
||
|
TRUE // Alertable wait
|
||
|
);
|
||
|
switch (status) {
|
||
|
case WAIT_IO_COMPLETION:
|
||
|
break;
|
||
|
case WAIT_OBJECT_0:
|
||
|
while (IpxGetQueuedAdapterConfigurationStatus (
|
||
|
cfgHdl,
|
||
|
&i,
|
||
|
&adpStatus,
|
||
|
¶ms)==NO_ERROR) {
|
||
|
switch (adpStatus) {
|
||
|
case ADAPTER_DELETED:
|
||
|
case ADAPTER_DOWN:
|
||
|
printf ("\n*****Adapter # %d %s.*****", i,
|
||
|
(adpStatus==ADAPTER_DELETED)
|
||
|
? "deleted" : "down");
|
||
|
|
||
|
if (AdapterArr[i]) {
|
||
|
AdapterArr[i] = FALSE;
|
||
|
if (i!=0) {
|
||
|
printf ("\n******Stopping adapter # %d******\n\n", i);
|
||
|
if (InterlockedDecrement (&NumActiveAdapters)<0) {
|
||
|
printf ("\n******Deleting socket port******\n\n");
|
||
|
DeleteSocketPort (sockPort);
|
||
|
sockPort = INVALID_HANDLE_VALUE;
|
||
|
nObjects = 2;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
case ADAPTER_CREATED:
|
||
|
case ADAPTER_UP:
|
||
|
len = sizeof (name);
|
||
|
status = GetAdapterNameW (i, &len, name);
|
||
|
ASSERTMSG ("GetAdapterNameW failed ", status==NO_ERROR);
|
||
|
printf ("\n*****Adapter # %d (%ls) %s!*****\n\n",i,name,
|
||
|
(adpStatus==ADAPTER_CREATED)
|
||
|
? "created" : "up");
|
||
|
AdapterArr[i] = TRUE;
|
||
|
if (i!=0) {
|
||
|
printf ("\n******Starting adapter # %d******\n\n", i);
|
||
|
if (InterlockedIncrement (&NumActiveAdapters)==0) {
|
||
|
USHORT sockNum;
|
||
|
printf ("\n******Creating socket port******\n\n");
|
||
|
PUTUSHORT2SHORT (&sockNum, SAP_SOCKET_NUM);
|
||
|
sockPort = CreateSocketPort (sockNum);
|
||
|
ASSERTERR (sockPort!=INVALID_HANDLE_VALUE);
|
||
|
compHdl = CreateIoCompletionPort (sockPort,
|
||
|
NULL,
|
||
|
0,
|
||
|
0);
|
||
|
ASSERTERR (compHdl!=NULL);
|
||
|
hdl[2] = sockPort;
|
||
|
nObjects = 3;
|
||
|
|
||
|
recvPacket.ovrp.hEvent = NULL;
|
||
|
recvPacket.CompletionRoutine = RecvCompletion;
|
||
|
status = IpxRecvPacket (sockPort,
|
||
|
(PUCHAR)&recvPacket.hdr,
|
||
|
sizeof(SAP_PACKET)
|
||
|
-FIELD_OFFSET (SAP_PACKET, hdr),
|
||
|
&recvPacket.rsvd,
|
||
|
&recvPacket.ovrp,
|
||
|
NULL);
|
||
|
ASSERTMSG ("Failed to start receive. ",
|
||
|
status==NO_ERROR);
|
||
|
}
|
||
|
|
||
|
sendPacket = (PSAP_PACKET)GlobalAlloc (GMEM_FIXED,
|
||
|
sizeof(SAP_PACKET));
|
||
|
ASSERTERR (sendPacket!=NULL);
|
||
|
|
||
|
PUTUSHORT2SHORT (&sendPacket->hdr.checksum,0xFFFF);
|
||
|
PUTUSHORT2SHORT (&sendPacket->hdr.length, 34);
|
||
|
sendPacket->hdr.transportctl = 0;
|
||
|
sendPacket->hdr.pkttype = 0x04;
|
||
|
memcpy (&sendPacket->hdr.dst.net, ¶ms.Network, 4);
|
||
|
if (params.NdisMedium==NdisMediumWan)
|
||
|
memcpy (sendPacket->hdr.dst.node, params.RemoteNode, 6);
|
||
|
else
|
||
|
memset (sendPacket->hdr.dst.node, 0xFF, 6);
|
||
|
PUTUSHORT2SHORT (&sendPacket->hdr.dst.socket, SAP_SOCKET_NUM);
|
||
|
memcpy (sendPacket->hdr.src.net, params.Network, 4);
|
||
|
memcpy (sendPacket->hdr.src.node, params.LocalNode, 6);
|
||
|
PUTUSHORT2SHORT (&sendPacket->hdr.src.socket, SAP_SOCKET_NUM);
|
||
|
PUTUSHORT2SHORT (&sendPacket->sap.operation, 3);
|
||
|
PUTUSHORT2SHORT (&sendPacket->sap.entry[0].type, 0x0003);
|
||
|
sendPacket->ovrp.hEvent = NULL;
|
||
|
sendPacket->CompletionRoutine = SendCompletion;
|
||
|
status = IpxSendPacket (sockPort,
|
||
|
i,
|
||
|
(PUCHAR)&sendPacket->hdr,
|
||
|
34,
|
||
|
&sendPacket->rsvd,
|
||
|
&sendPacket->ovrp,
|
||
|
NULL);
|
||
|
ASSERTMSG ("Failed to start send. ",
|
||
|
status==NO_ERROR);
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
ASSERTMSG ("Unknown adapter status reported ", FALSE);
|
||
|
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case WAIT_OBJECT_0+1:
|
||
|
break;
|
||
|
case WAIT_OBJECT_0+2:
|
||
|
if (IpxGetQueuedCompletionStatus (
|
||
|
compHdl,
|
||
|
&len,
|
||
|
&i,
|
||
|
(LPOVERLAPPED *)&sendPacket,
|
||
|
0) || (sendPacket!=NULL))
|
||
|
(*sendPacket->CompletionRoutine) (
|
||
|
sendPacket->ovrp.Internal,
|
||
|
len,
|
||
|
&sendPacket->ovrp);
|
||
|
else
|
||
|
fprintf (stderr,
|
||
|
"Completion port is signalled,"
|
||
|
" but no packets are waiting.\n");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
printf ("\n\n**** Exiting with status: %lX ****\n\n", status);
|
||
|
|
||
|
|
||
|
NumActiveAdapters = -1;
|
||
|
if (sockPort!=INVALID_HANDLE_VALUE)
|
||
|
DeleteSocketPort (sockPort);
|
||
|
IpxDeleteAdapterConfigurationPort (cfgHdl);
|
||
|
GlobalFree (AdapterArr);
|
||
|
NtClose (hdl[2]);
|
||
|
CloseHandle (hdl[1]);
|
||
|
CloseHandle (hdl[0]);
|
||
|
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
BOOL WINAPI
|
||
|
CtrlHandler (
|
||
|
DWORD fdwCtrlType
|
||
|
) {
|
||
|
|
||
|
switch (fdwCtrlType) {
|
||
|
case CTRL_C_EVENT:
|
||
|
Stop = TRUE;
|
||
|
SetEvent (hdl[1]);
|
||
|
return TRUE;
|
||
|
|
||
|
/* CTRL+CLOSE: confirm that the user wants to exit. */
|
||
|
|
||
|
case CTRL_CLOSE_EVENT:
|
||
|
Stop = TRUE;
|
||
|
SetEvent (hdl[1]);
|
||
|
return TRUE;
|
||
|
|
||
|
/* Pass other signals to the next handler. */
|
||
|
|
||
|
case CTRL_BREAK_EVENT:
|
||
|
|
||
|
case CTRL_LOGOFF_EVENT:
|
||
|
|
||
|
case CTRL_SHUTDOWN_EVENT:
|
||
|
|
||
|
default:
|
||
|
Stop = TRUE;
|
||
|
SetEvent (hdl[1]);
|
||
|
return FALSE;
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID CALLBACK
|
||
|
SendCompletion (
|
||
|
DWORD status,
|
||
|
DWORD cbBytes,
|
||
|
LPOVERLAPPED context
|
||
|
) {
|
||
|
#define sendPacket ((PSAP_PACKET)context)
|
||
|
|
||
|
printf ("Status : %ld\n", status);
|
||
|
printf ("Bytes sent : %d\n", cbBytes);
|
||
|
|
||
|
printf ("Checksum : %04X\n", GETSHORT2USHORTdirect(&sendPacket->hdr.checksum));
|
||
|
printf ("Length : %d\n", GETSHORT2USHORTdirect (&sendPacket->hdr.length));
|
||
|
printf ("Hop count : %d\n", sendPacket->hdr.transportctl);
|
||
|
printf ("Packet type : %02X\n", sendPacket->hdr.pkttype);
|
||
|
printf ("Dest. net : %02X%02X%02X%02X\n",
|
||
|
sendPacket->hdr.dst.net[0],
|
||
|
sendPacket->hdr.dst.net[1],
|
||
|
sendPacket->hdr.dst.net[2],
|
||
|
sendPacket->hdr.dst.net[3]);
|
||
|
printf ("Dest. node : %02X%02X%02X%02X%02X%02X\n",
|
||
|
sendPacket->hdr.dst.node[0],
|
||
|
sendPacket->hdr.dst.node[1],
|
||
|
sendPacket->hdr.dst.node[2],
|
||
|
sendPacket->hdr.dst.node[3],
|
||
|
sendPacket->hdr.dst.node[4],
|
||
|
sendPacket->hdr.dst.node[5]);
|
||
|
printf ("Dest. socket : %04X\n", GETSHORT2USHORTdirect (&sendPacket->hdr.dst.socket));
|
||
|
printf ("Source net : %02X%02X%02X%02X\n",
|
||
|
sendPacket->hdr.src.net[0],
|
||
|
sendPacket->hdr.src.net[1],
|
||
|
sendPacket->hdr.src.net[2],
|
||
|
sendPacket->hdr.src.net[3]);
|
||
|
printf ("Source node : %02X%02X%02X%02X%02X%02X\n",
|
||
|
sendPacket->hdr.src.node[0],
|
||
|
sendPacket->hdr.src.node[1],
|
||
|
sendPacket->hdr.src.node[2],
|
||
|
sendPacket->hdr.src.node[3],
|
||
|
sendPacket->hdr.src.node[4],
|
||
|
sendPacket->hdr.src.node[5]);
|
||
|
printf ("Source socket : %04X\n", GETSHORT2USHORTdirect (&sendPacket->hdr.src.socket));
|
||
|
printf ("\n\n");
|
||
|
GlobalFree (sendPacket);
|
||
|
#undef sendPacket
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID CALLBACK
|
||
|
RecvCompletion (
|
||
|
DWORD status,
|
||
|
DWORD cbBytes,
|
||
|
LPOVERLAPPED context
|
||
|
) {
|
||
|
#define recvPacket ((PSAP_PACKET)context)
|
||
|
CurAdapter = GetNicId(&recvPacket->rsvd);
|
||
|
if ((CurAdapter>=0)
|
||
|
&& (CurAdapter<=gParam.AdaptersCount)
|
||
|
&& AdapterArr[CurAdapter]) {
|
||
|
printf ("Adapter # : %d\n", CurAdapter);
|
||
|
printf ("Status : %ld\n", status);
|
||
|
printf ("Bytes received : %d\n", cbBytes);
|
||
|
if (cbBytes>=(DWORD)(FIELD_OFFSET (SAP_PACKET, data)
|
||
|
-FIELD_OFFSET(SAP_PACKET,hdr))) {
|
||
|
printf ("Checksum : %04X\n", GETSHORT2USHORTdirect(&recvPacket->hdr.checksum));
|
||
|
printf ("Length : %d\n", GETSHORT2USHORTdirect (&recvPacket->hdr.length));
|
||
|
printf ("Hop count : %d\n", recvPacket->hdr.transportctl);
|
||
|
printf ("Packet type : %02X\n", recvPacket->hdr.pkttype);
|
||
|
printf ("Dest. net : %02X%02X%02X%02X\n",
|
||
|
recvPacket->hdr.dst.net[0],
|
||
|
recvPacket->hdr.dst.net[1],
|
||
|
recvPacket->hdr.dst.net[2],
|
||
|
recvPacket->hdr.dst.net[3]);
|
||
|
printf ("Dest. node : %02X%02X%02X%02X%02X%02X\n",
|
||
|
recvPacket->hdr.dst.node[0],
|
||
|
recvPacket->hdr.dst.node[1],
|
||
|
recvPacket->hdr.dst.node[2],
|
||
|
recvPacket->hdr.dst.node[3],
|
||
|
recvPacket->hdr.dst.node[4],
|
||
|
recvPacket->hdr.dst.node[5]);
|
||
|
printf ("Dest. socket : %04X\n", GETSHORT2USHORTdirect (&recvPacket->hdr.dst.socket));
|
||
|
printf ("Source net : %02X%02X%02X%02X\n",
|
||
|
recvPacket->hdr.src.net[0],
|
||
|
recvPacket->hdr.src.net[1],
|
||
|
recvPacket->hdr.src.net[2],
|
||
|
recvPacket->hdr.src.net[3]);
|
||
|
printf ("Source node : %02X%02X%02X%02X%02X%02X\n",
|
||
|
recvPacket->hdr.src.node[0],
|
||
|
recvPacket->hdr.src.node[1],
|
||
|
recvPacket->hdr.src.node[2],
|
||
|
recvPacket->hdr.src.node[3],
|
||
|
recvPacket->hdr.src.node[4],
|
||
|
recvPacket->hdr.src.node[5]);
|
||
|
printf ("Source socket : %04X\n", GETSHORT2USHORTdirect (&recvPacket->hdr.src.socket));
|
||
|
if (cbBytes>=(DWORD)(FIELD_OFFSET(SAP_PACKET,sap.entry[0])
|
||
|
-FIELD_OFFSET(SAP_PACKET,hdr))) {
|
||
|
INT j;
|
||
|
printf ("SAP Operation : %d\n", GETSHORT2USHORTdirect (&recvPacket->sap.operation));
|
||
|
for (j=0; (j<7) && (cbBytes>=(DWORD)FIELD_OFFSET (SAP_PACKET, sap.entry[j+1])); j++) {
|
||
|
printf ("Server type : %04X\n", GETSHORT2USHORTdirect (&recvPacket->sap.entry[j].type));
|
||
|
printf ("Server name : %.48s\n", recvPacket->sap.entry[j].name);
|
||
|
printf ("Server net : %02X%02X%02X%02X\n",
|
||
|
recvPacket->sap.entry[j].addr.net[0],
|
||
|
recvPacket->sap.entry[j].addr.net[1],
|
||
|
recvPacket->sap.entry[j].addr.net[2],
|
||
|
recvPacket->sap.entry[j].addr.net[3]);
|
||
|
printf ("Server node : %02X%02X%02X%02X%02X%02X\n",
|
||
|
recvPacket->sap.entry[j].addr.node[0],
|
||
|
recvPacket->sap.entry[j].addr.node[1],
|
||
|
recvPacket->sap.entry[j].addr.node[2],
|
||
|
recvPacket->sap.entry[j].addr.node[3],
|
||
|
recvPacket->sap.entry[j].addr.node[4],
|
||
|
recvPacket->sap.entry[j].addr.node[5]);
|
||
|
printf ("Server socket : %04X\n", GETSHORT2USHORTdirect (&recvPacket->sap.entry[j].addr.socket));
|
||
|
printf ("Server hops : %d\n", GETSHORT2USHORTdirect (&recvPacket->sap.entry[j].hops));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
printf ("**************INVALID BYTE COUNT********");
|
||
|
printf ("\n\n");
|
||
|
}
|
||
|
else
|
||
|
printf ("Adapter # : %d - ignored \n", CurAdapter);
|
||
|
|
||
|
if ((NumActiveAdapters>=0) && !Stop) {
|
||
|
status = IpxRecvPacket (sockPort,
|
||
|
(PUCHAR)&recvPacket->hdr,
|
||
|
sizeof(SAP_PACKET)
|
||
|
-FIELD_OFFSET (SAP_PACKET, hdr),
|
||
|
&recvPacket->rsvd,
|
||
|
&recvPacket->ovrp,
|
||
|
NULL);
|
||
|
|
||
|
ASSERTMSG ("Failed to start receive. ", status==NO_ERROR);
|
||
|
}
|
||
|
#undef recvPacket
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|