Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

691 lines
24 KiB

/*++
Copyright (c) 1992-1996 Microsoft Corporation
Module Name:
servcomm.c
Abstract:
Provides socket commmunications functionality for Proxy Agent.
Environment:
User Mode - Win32
Revision History:
10-May-1996 DonRyan
Removed banner from Technology Dynamics, Inc.
--*/
//--------------------------- WINDOWS DEPENDENCIES --------------------------
//--------------------------- STANDARD DEPENDENCIES -- #include<xxxxx.h> ----
#include <windows.h>
#include <winsvc.h>
#include <winsock.h>
#include <wsipx.h>
#include <errno.h>
#include <stdio.h>
#include <process.h>
#include <string.h>
//--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------
#include <snmp.h>
#include <snmputil.h>
#include "regconf.h"
#include "..\common\wellknow.h"
#include "..\common\evtlog.h"
//--------------------------- SELF-DEPENDENCY -- ONE #include"module.h" -----
//--------------------------- PUBLIC VARIABLES --(same as in module.h file)--
DWORD timeZeroReference;
HANDLE hCommThreadActiveMutex;
SOCKET gsd; //temporary, for testing...
extern SERVICE_STATUS_HANDLE hService;
extern SERVICE_STATUS status;
extern BOOL noservice;
//--------------------------- PRIVATE CONSTANTS -----------------------------
#define bzero(lp, size) (void)memset(lp, 0, size)
#define bcopy(slp, dlp, size) (void)memcpy(dlp, slp, size)
#define bcmp(slp, dlp, size) memcmp(dlp, slp, size)
#define CTAMTimeout ((DWORD)30000)
//--------------------------- PRIVATE STRUCTS -------------------------------
typedef struct {
int family;
int type;
int protocol;
struct sockaddr localAddress;
} Session;
//--------------------------- PRIVATE VARIABLES -----------------------------
#define RECVBUFSIZE 4096
BYTE *recvBuf;
BYTE *sendBuf;
#define NPOLLFILE 2 // UDP and IPX
static SOCKET fdarray[NPOLLFILE];
static INT fdarrayLen;
static struct fd_set readfds;
static struct fd_set exceptfds;
static struct timeval timeval;
WSADATA WinSockData;
//--------------------------- PRIVATE PROTOTYPES ----------------------------
VOID trapThread(VOID *threadParam);
VOID agentCommThread(VOID *threadParam);
BOOL filtmgrs(struct sockaddr *source, INT sourceLen);
SNMPAPI SnmpServiceProcessMessage(
IN OUT BYTE **pBuf,
IN OUT UINT *length);
//--------------------------- PRIVATE PROCEDURES ----------------------------
//--------------------------- PUBLIC PROCEDURES -----------------------------
BOOL agentConfigInit(VOID)
{
Session session;
SOCKET sd;
DWORD threadId;
HANDLE hCommThread;
DWORD dwResult;
INT i;
WSADATA WSAData;
BOOL fSuccess;
INT pseudoAgentsLen;
INT j;
AsnObjectIdentifier tmpView;
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: initializing master agent.\n"));
if (i = WSAStartup(0x0101, &WSAData))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error on WSAStartup %d\n", i));
}
// initialize configuration from registry...
if (!regconf())
{
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: error on regconf %d\n", GetLastError()));
return FALSE;
}
if (!SnmpSvcGenerateColdStartTrap(0))
{
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: error on SnmpSvcGenerateColdStartTrap %d\n", GetLastError()));
//not serious error
}
timeZeroReference = SnmpSvcInitUptime() / 10;
#if 0
// very loose pseudo-code for future security functionality
while(address = GetEntryFromPartyMIB(...))
{
if (TDomain == microsoft.msPartyAdmin.transportDomains.extensionAPI)
{
#else
pseudoAgentsLen = extAgentsLen;
for (i=0; i < extAgentsLen; i++)
{
#endif
extAgents[i].fInitedOk = TRUE;
// load extension DLL (if not already...
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: %s loading.\n", extAgents[i].pathName));
if ((extAgents[i].hExtension = GetModuleHandle(extAgents[i].pathName)) == NULL)
{
if ((extAgents[i].hExtension =
LoadLibrary(extAgents[i].pathName)) == NULL)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error %d loading %s\n", GetLastError(), extAgents[i].pathName));
SnmpSvcReportEvent(SNMP_EVENT_INVALID_EXTENSION_AGENT_DLL, 1, &extAgents[i].pathName, GetLastError());
extAgents[i].fInitedOk = FALSE;
}
}
if (extAgents[i].fInitedOk)
{
if ((extAgents[i].initAddr = GetProcAddress(extAgents[i].hExtension,"SnmpExtensionInit")) == NULL)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error %d resolving SnmpExtensionInit in %s\n", GetLastError(), extAgents[i].pathName));
SnmpSvcReportEvent(SNMP_EVENT_INVALID_EXTENSION_AGENT_DLL, 1, &extAgents[i].pathName, GetLastError());
extAgents[i].fInitedOk = FALSE;
}
else if ((extAgents[i].queryAddr =
GetProcAddress(extAgents[i].hExtension,"SnmpExtensionQuery")) == NULL)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error %d resolving SnmpExtensionQuery in %s\n", GetLastError(), extAgents[i].pathName));
SnmpSvcReportEvent(SNMP_EVENT_INVALID_EXTENSION_AGENT_DLL, 1, &extAgents[i].pathName, GetLastError());
extAgents[i].fInitedOk = FALSE;
}
else if ((extAgents[i].trapAddr =
GetProcAddress(extAgents[i].hExtension,"SnmpExtensionTrap")) == NULL)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error %d resolving SnmpExtensionTrap in %s\n", GetLastError(), extAgents[i].pathName));
SnmpSvcReportEvent(SNMP_EVENT_INVALID_EXTENSION_AGENT_DLL, 1, &extAgents[i].pathName, GetLastError());
extAgents[i].fInitedOk = FALSE;
}
else if (!(*extAgents[i].initAddr)(timeZeroReference,
&extAgents[i].hPollForTrapEvent,
&(extAgents[i].supportedView)))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: SnmpExtensionInit failed in %s\n", extAgents[i].pathName));
SnmpSvcReportEvent(SNMP_EVENT_INVALID_EXTENSION_AGENT_DLL, 1, &extAgents[i].pathName, GetLastError());
extAgents[i].fInitedOk = FALSE;
}
else
{
if ((extAgents[i].initAddrEx =
GetProcAddress(extAgents[i].hExtension,"SnmpExtensionInitEx")) != NULL)
{
j = 1;
while ((*extAgents[i].initAddrEx)(&tmpView))
{
pseudoAgentsLen++;
extAgents = (CfgExtensionAgents *) SnmpUtilMemReAlloc(extAgents,
(pseudoAgentsLen * sizeof(CfgExtensionAgents)));
extAgents[pseudoAgentsLen-1].supportedView.ids =
tmpView.ids;
extAgents[pseudoAgentsLen-1].supportedView.idLength =
tmpView.idLength;
extAgents[pseudoAgentsLen-1].initAddr =
extAgents[i].initAddr;
extAgents[pseudoAgentsLen-1].queryAddr =
extAgents[i].queryAddr;
extAgents[pseudoAgentsLen-1].trapAddr =
extAgents[i].trapAddr;
extAgents[pseudoAgentsLen-1].pathName =
extAgents[i].pathName;
extAgents[pseudoAgentsLen-1].hExtension =
extAgents[i].hExtension;
extAgents[pseudoAgentsLen-1].fInitedOk = TRUE;
extAgents[pseudoAgentsLen-1].hPollForTrapEvent = NULL;
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: %s supports %s.\n",
extAgents[pseudoAgentsLen-1].pathName, SnmpUtilOidToA(&tmpView)));
j++;
}
}
else
{
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: %s supports %s.\n",
extAgents[i].pathName, SnmpUtilOidToA(&extAgents[i].supportedView)));
}
}
} // end if fIntedOk
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: %s loaded %s.\n",extAgents[i].pathName,
extAgents[i].fInitedOk ? "successfully" : "unsuccessfully"));
#if 0
} // end if (extensionAPI)
} // end while ()
#else
} // end for ()
#endif
extAgentsLen = pseudoAgentsLen;
fdarrayLen = 0;
if (WSAStartup((WORD)0x0101, &WinSockData)) {
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error initializing WinSock.\n"));
return FALSE;
}
#if 0
// very loose pseudo-code for future security functionality
while(address = GetEntryFromPartyMIB(...))
{
if (!IsATarget w/4+16) continue;
if (IsALocalAddress(address))
{
#endif
#if 0
// open/bind sockets for proxy (if not already...
// NOTE: A SERIOUS ATTEMPT HAS BEEN MADE TO KEEP ALL SOCKETS CODE IN
// THIS AGENT INDEPENDENT OF THE ACTUAL SOCKET TYPE.
//
// FUTURE ADDITIONS OF NEW SOCKET TYPES TO THIS AGENT WILL HOPEFULLY
// BE LIMITED TO CODE SIMILAR TO THE INTERNET UDP SPECIFIC CODE BELOW,
// AND HOPEFULLY NO OTHER CHANGES TO THE REST OF THE CODE OF THE AGENT.
// microsoft's direction away from SNMP Administrative Model (Secure SNMP)
// has caused us to avoid multiple SNMP listen ports and multiple socket
// types for the current implementation. The SNMP Administrative Model
// supports the implementation of this functionality.
// --------- BEGIN: PROTOCOL SPECIFIC SOCKET CODE BEGIN... ---------
if (address.TDomain == rfcXXXXDomain ||
address.TDomain == rfc1157Domain)
//SNMP over UDP/IP (RFC XXXX SnmpPrivMsg, or
//SNMP over UDP/IP (RFC 1157 Message
#endif
{
struct sockaddr_in localAddress_in;
struct sockaddr_ipx localAddress_ipx;
struct servent *serv;
session.family = AF_INET;
session.type = SOCK_DGRAM;
session.protocol = 0;
localAddress_in.sin_family = AF_INET;
if ((serv = getservbyname( "snmp", "udp" )) == NULL) {
localAddress_in.sin_port =
htons(WKSN_UDP_GETSET /*extract address.TAddress*/ );
} else {
localAddress_in.sin_port = (SHORT)serv->s_port;
}
localAddress_in.sin_addr.s_addr = ntohl(INADDR_ANY);
bcopy(&localAddress_in,
&session.localAddress,
sizeof(localAddress_in));
fSuccess = FALSE;
if ((sd = socket(session.family, session.type,
session.protocol)) == (SOCKET)-1)
{
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: error %d creating udp socket.\n", GetLastError()));
}
else if (bind(sd, &session.localAddress,
sizeof(session.localAddress)) != 0)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error %d binding udp socket.\n", GetLastError()));
}
else // successfully opened an UDP socket
{
gsd = sd; //temporary for now!!!
fdarray[fdarrayLen] = sd;
fdarrayLen += 1;
fSuccess = TRUE;
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: setup udp listen port.\n"));
}
// now setup IPX socket
session.family = PF_IPX;
session.type = SOCK_DGRAM;
session.protocol = NSPROTO_IPX;
bzero(&localAddress_ipx, sizeof(localAddress_ipx));
localAddress_ipx.sa_family = PF_IPX;
localAddress_ipx.sa_socket = htons(WKSN_IPX_GETSET);
bcopy(&localAddress_ipx, &session.localAddress,
sizeof(localAddress_ipx));
if ((sd = socket(session.family, session.type,
session.protocol)) == (SOCKET)-1)
{
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: error %d creating ipx socket.\n", GetLastError()));
}
else if (bind(sd, &session.localAddress,
sizeof(session.localAddress)) != 0)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error %d binding ipx socket.\n", GetLastError()));
}
else
{
fdarray[fdarrayLen] = sd;
fdarrayLen += 1;
fSuccess = TRUE;
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: setup ipx listen port.\n"));
}
if (!fSuccess)
return FALSE; // can't open either socket
}
#if 0
else if (address.TDomain == rfc1298Domain)
//SNMP over IPX (RFC 1157 Message
{
<whatever needs to be done for this type, IPX for example>
}
else
{
error, unsupported transport domain!!!
}
#endif
// --------- END: PROTOCOL SPECIFIC SOCKET CODE END. ---------------
#if 0
} // end if (isALocalAddress)
} // end while ()
#endif
if ((hCommThreadActiveMutex = CreateMutex(NULL, FALSE, NULL)) == NULL)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error %d creating comm mutex.\n", GetLastError()));
}
// create the comm thread
if ((hCommThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)agentCommThread,
NULL, 0, &threadId)) == 0)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error %d creating agentCommThread.\n", GetLastError()));
}
else
{
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: agentCommThread tid=0x%lx.\n", threadId));
}
if (!noservice) {
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: setting service status to running.\n"));
status.dwCurrentState = SERVICE_RUNNING;
status.dwCheckPoint = 0;
status.dwWaitHint = 0;
if (!SetServiceStatus(hService, &status))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error on SetServiceStatus %d\n", GetLastError()));
SnmpSvcReportEvent(SNMP_EVENT_FATAL_ERROR, 0, NULL, GetLastError());
exit(1);
}
else
{
SnmpSvcReportEvent(SNMP_EVENT_SERVICE_STARTED, 0, NULL, NO_ERROR);
}
}
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: agentTrapThread entered.\n"));
// become the trap thread...
trapThread(NULL);
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: agentTrapThread terminated.\n"));
// wait for the comm thread to be in a safe state...
if ((dwResult = WaitForSingleObject(hCommThreadActiveMutex, CTAMTimeout))
== 0xffffffff)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error %d waiting for comm mutex.\n", GetLastError()));
// continue, and try to terminate comm thread anyway
}
else if (dwResult == WAIT_TIMEOUT)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: timeout waiting for comm mutex.\n"));
// continue, and try to terminate comm thread anyway
}
else
{
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: agentCommThread in safe state for termination.\n"));
}
// terminate the comm thread...
if (!TerminateThread(hCommThread, (DWORD)0))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error on TerminateThread %d\n", GetLastError()));
//not serious error.
}
else
{
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: agentCommThread terminated.\n"));
}
#if 0
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: preparing to close UDP port.\n"));
if (!closesocket(gsd))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error on closesocket %d\n", GetLastError()));
//not serious error.
}
else
{
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: closed UDP port.\n"));
}
#endif
return TRUE;
} // end agentConfigInit()
VOID agentCommThread(VOID *threadParam)
{
extern HANDLE hExitTrapThreadEvent;
UNREFERENCED_PARAMETER(threadParam);
SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: agentCommThread entered.\n"));
if ((recvBuf = (BYTE *)SnmpUtilMemAlloc(RECVBUFSIZE)) == NULL)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: PDU: could not allocate receive buffer.\n"));
SnmpSvcReportEvent(SNMP_EVENT_FATAL_ERROR, 0, NULL, ERROR_NOT_ENOUGH_MEMORY);
// set event causing trap thread to terminate, followed service
if (!SetEvent(hExitTrapThreadEvent))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: PDU: error %d setting termination event.\n", GetLastError()));
SnmpSvcReportEvent(SNMP_EVENT_FATAL_ERROR, 0, NULL, GetLastError());
exit(1);
}
return;
}
while(1)
{
INT numReady;
DWORD dwResult;
FD_ZERO(&readfds);
FD_ZERO(&exceptfds);
{
int i, sd;
// construct readfds and exceptfds which gets destroyed by select()
for (i=0; i < fdarrayLen; i++) {
sd = fdarray[i];
FD_SET(sd, &readfds);
FD_SET(sd, &exceptfds);
}
}
numReady = select(0, &readfds, NULL, &exceptfds, NULL);
// SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: %d socket(s) ready to process.\n", numReady));
// indicate this thread is not in safe state for killing...
if ((dwResult = WaitForSingleObject(hCommThreadActiveMutex, CTAMTimeout)
) == 0xffffffff)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: PDU: error %d waiting for comm mutux.\n", GetLastError()));
SnmpSvcReportEvent(SNMP_EVENT_FATAL_ERROR, 0, NULL, GetLastError());
// set event causing trap thread to terminate, followed service
if (!SetEvent(hExitTrapThreadEvent))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: PDU: error %d setting termination event.\n", GetLastError()));
SnmpSvcReportEvent(SNMP_EVENT_FATAL_ERROR, 0, NULL, GetLastError());
exit(1);
}
return;
}
if (numReady == -1)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: PDU: error %d waiting for sockets to process.\n", GetLastError()));
//not serious error.
}
else if (numReady == 0)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: PDU: timeout waiting for sockets to process.\n"));
//not serious error.
}
else
{
INT i;
for (i=0; i<fdarrayLen; i++)
{
struct sockaddr source;
int sourceLen;
int length;
struct sockaddr_in *saddr;
if (FD_ISSET(fdarray[i], &readfds))
{
if (FD_ISSET(fdarray[i], &exceptfds))
{
// SNMPDBG((SNMP_LOG_ERROR,
// "SNMP: PDU: %d=select(), readfds & exceptfds = 0x%x.\n",
// numReady, FD_ISSET(fdarray[i], &exceptfds)));
//not serious error.
}
// else
// {
// SNMPDBG((SNMP_LOG_TRACE,
// "SNMP: PDU: %d=poll(), POLLIN on fdarray[%d].\n",
// numReady, i));
// }
sourceLen = sizeof(source);
if ((length = recvfrom(fdarray[i], recvBuf, RECVBUFSIZE,
0, &source, &sourceLen)) == -1)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: PDU: error on recvfrom %d.\n", GetLastError()));
continue;
}
if (length == RECVBUFSIZE)
{
SNMPDBG((SNMP_LOG_TRACE,
"SNMP: PDU: recvfrom exceeded %d octets.\n",
RECVBUFSIZE));
continue;
}
// verify permittedManagers
if (!filtmgrs(&source, sourceLen))
{
continue;
}
sendBuf = recvBuf;
saddr = (struct sockaddr_in *)&source;
SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: request received from %s (%d octets).\n",
inet_ntoa(saddr->sin_addr), length));
if (!SnmpServiceProcessMessage(&sendBuf, &length))
{
SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: error on SnmpServiceProcessMessage %d\n",
GetLastError()));
continue;
}
if ((length = sendto(fdarray[i], sendBuf, length,
0, &source, sizeof(source))) == -1)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: PDU: error %d sending response pdu.\n",
GetLastError()));
SnmpUtilMemFree(sendBuf);
continue;
}
SnmpUtilMemFree(sendBuf);
}
else if (FD_ISSET(fdarray[i], &exceptfds))
{
SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: %d=select(), exceptfds = 0x%x.\n",
numReady, FD_ISSET(fdarray[i], &exceptfds)));
//not serious error.
} // end if (POLLIN)
} // end for (fdarray)
} // end if (numReady)
// indicate this thread is in safe state for killing...
if (!ReleaseMutex(hCommThreadActiveMutex))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: PDU: error %d releasing comm mutex.\n", GetLastError()));
SnmpSvcReportEvent(SNMP_EVENT_FATAL_ERROR, 0, NULL, GetLastError());
// set event causing trap thread to terminate, followed service
if (!SetEvent(hExitTrapThreadEvent))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: PDU: error %d setting termination event.\n", GetLastError()));
SnmpSvcReportEvent(SNMP_EVENT_FATAL_ERROR, 0, NULL, GetLastError());
exit(1);
}
return;
}
} // end while (1)
} // end agentCommThread()
//-------------------------------- END --------------------------------------