645 lines
13 KiB
C
645 lines
13 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1992-1997 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
network.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Contains routines for manipulating transport structures.
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User Mode - Win32
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
10-Feb-1997 DonRyan
|
|||
|
Rewrote to implement SNMPv2 support.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Include files //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
#include "globals.h"
|
|||
|
#include "network.h"
|
|||
|
#include "varbinds.h"
|
|||
|
#include "snmppdus.h"
|
|||
|
#include "query.h"
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Public procedures //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
BOOL
|
|||
|
IsValidSockAddr(
|
|||
|
struct sockaddr *pAddress
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Verifies if an IP or IPX address is valid.
|
|||
|
An IP address is valid if it is AF_INET and it is not 0.0.0.0
|
|||
|
An IPX address is valid if is AF_IPX and the node-number is not null: xxxxxx.000000000000
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pAddress - pointer to a generic network address to be tested
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if the address is valid.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
if (pAddress == NULL)
|
|||
|
return FALSE;
|
|||
|
|
|||
|
if (pAddress->sa_family == AF_INET)
|
|||
|
{
|
|||
|
return (((struct sockaddr_in *)pAddress)->sin_addr.s_addr != 0);
|
|||
|
}
|
|||
|
else if (pAddress->sa_family == AF_IPX)
|
|||
|
{
|
|||
|
char zeroBuff[6] = {0, 0, 0, 0, 0, 0};
|
|||
|
|
|||
|
return memcmp(((struct sockaddr_ipx *)pAddress)->sa_nodenum,
|
|||
|
zeroBuff,
|
|||
|
sizeof(zeroBuff)) != 0;
|
|||
|
}
|
|||
|
|
|||
|
// the address is neither IP nor IPX hence it is definitely an invalid address
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
AllocNLE(
|
|||
|
PNETWORK_LIST_ENTRY * ppNLE
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Allocates transport structure and initializes.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ppNLE - pointer to receive pointer to list entry.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BOOL fOk = FALSE;
|
|||
|
PNETWORK_LIST_ENTRY pNLE;
|
|||
|
|
|||
|
// attempt to allocate structure
|
|||
|
pNLE = AgentMemAlloc(sizeof(NETWORK_LIST_ENTRY));
|
|||
|
|
|||
|
// validate pointer
|
|||
|
if (pNLE != NULL) {
|
|||
|
|
|||
|
// allocate buffer to be used for io
|
|||
|
pNLE->Buffer.buf = AgentMemAlloc(NLEBUFLEN);
|
|||
|
|
|||
|
// validate pointer
|
|||
|
if (pNLE->Buffer.buf != NULL) {
|
|||
|
|
|||
|
// initialize socket to socket
|
|||
|
pNLE->Socket = INVALID_SOCKET;
|
|||
|
|
|||
|
// initialize buffer length
|
|||
|
pNLE->Buffer.len = NLEBUFLEN;
|
|||
|
|
|||
|
// initialize subagent query list
|
|||
|
InitializeListHead(&pNLE->Queries);
|
|||
|
|
|||
|
// initialize variable bindings list
|
|||
|
InitializeListHead(&pNLE->Bindings);
|
|||
|
|
|||
|
// success
|
|||
|
fOk = TRUE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: could not allocate network io buffer.\n"
|
|||
|
));
|
|||
|
|
|||
|
// release
|
|||
|
FreeNLE(pNLE);
|
|||
|
|
|||
|
// re-init
|
|||
|
pNLE = NULL;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: could not allocate network entry.\n"
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
// transfer
|
|||
|
*ppNLE = pNLE;
|
|||
|
|
|||
|
return fOk;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
FreeNLE(
|
|||
|
PNETWORK_LIST_ENTRY pNLE
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Releases transport structure.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pNLE - pointer to transport structure.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
// validate pointer
|
|||
|
if (pNLE != NULL) {
|
|||
|
|
|||
|
// check to see if socket valid
|
|||
|
if (pNLE->Socket != INVALID_SOCKET) {
|
|||
|
|
|||
|
// release socket
|
|||
|
closesocket(pNLE->Socket);
|
|||
|
}
|
|||
|
|
|||
|
// release pdu
|
|||
|
UnloadPdu(pNLE);
|
|||
|
|
|||
|
// release query list
|
|||
|
UnloadQueries(pNLE);
|
|||
|
|
|||
|
// release bindings list
|
|||
|
UnloadVarBinds(pNLE);
|
|||
|
|
|||
|
// release network buffer
|
|||
|
AgentMemFree(pNLE->Buffer.buf);
|
|||
|
|
|||
|
// release memory
|
|||
|
AgentMemFree(pNLE);
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
LoadIncomingTransports(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Creates entries for each incoming interface.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BOOL fUdpOk = FALSE;
|
|||
|
BOOL fIpxOk = FALSE;
|
|||
|
PNETWORK_LIST_ENTRY pNLE = NULL;
|
|||
|
INT nStatus;
|
|||
|
|
|||
|
// allocate tcpip
|
|||
|
if (AllocNLE(&pNLE)) {
|
|||
|
|
|||
|
struct servent * pServEnt;
|
|||
|
struct sockaddr_in * pSockAddr;
|
|||
|
|
|||
|
// initialize sockaddr structure size
|
|||
|
pNLE->SockAddrLen = sizeof(struct sockaddr_in);
|
|||
|
|
|||
|
// obtain pointer to sockaddr structure
|
|||
|
pSockAddr = (struct sockaddr_in *)&pNLE->SockAddr;
|
|||
|
|
|||
|
// attempt to get server information
|
|||
|
pServEnt = getservbyname("snmp","udp");
|
|||
|
|
|||
|
// initialize address structure
|
|||
|
pSockAddr->sin_family = AF_INET;
|
|||
|
pSockAddr->sin_addr.s_addr = INADDR_ANY;
|
|||
|
pSockAddr->sin_port = (pServEnt != NULL)
|
|||
|
? (SHORT)pServEnt->s_port
|
|||
|
: htons(DEFAULT_SNMP_PORT_UDP)
|
|||
|
;
|
|||
|
|
|||
|
// allocate tpcip socket
|
|||
|
pNLE->Socket = WSASocket(
|
|||
|
AF_INET,
|
|||
|
SOCK_DGRAM,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
WSA_FLAG_OVERLAPPED
|
|||
|
);
|
|||
|
|
|||
|
// validate socket
|
|||
|
if (pNLE->Socket != INVALID_SOCKET) {
|
|||
|
|
|||
|
// attempt to bind
|
|||
|
nStatus = bind(pNLE->Socket,
|
|||
|
&pNLE->SockAddr,
|
|||
|
pNLE->SockAddrLen
|
|||
|
);
|
|||
|
|
|||
|
// validate return code
|
|||
|
if (nStatus != SOCKET_ERROR) {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_TRACE,
|
|||
|
"SNMP: SVC: successfully bound to udp port %d.\n",
|
|||
|
ntohs(pSockAddr->sin_port)
|
|||
|
));
|
|||
|
|
|||
|
// insert transport into list of incoming
|
|||
|
InsertTailList(&g_IncomingTransports, &pNLE->Link);
|
|||
|
|
|||
|
// success
|
|||
|
fUdpOk = TRUE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: error %d binding to udp port %d.\n",
|
|||
|
WSAGetLastError(),
|
|||
|
ntohs(pSockAddr->sin_port)
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_WARNING,
|
|||
|
"SNMP: SVC: error %d creating udp socket.\n",
|
|||
|
WSAGetLastError()
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
if (!fUdpOk) {
|
|||
|
|
|||
|
// release
|
|||
|
FreeNLE(pNLE);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// allocate ipx
|
|||
|
if (AllocNLE(&pNLE)) {
|
|||
|
|
|||
|
struct sockaddr_ipx * pSockAddr;
|
|||
|
|
|||
|
// initialize sockaddr structure size
|
|||
|
pNLE->SockAddrLen = sizeof(struct sockaddr_ipx);
|
|||
|
|
|||
|
// obtain pointer to sockaddr structure
|
|||
|
pSockAddr = (struct sockaddr_ipx *)&pNLE->SockAddr;
|
|||
|
|
|||
|
// initialize address structure
|
|||
|
pSockAddr->sa_family = AF_IPX;
|
|||
|
pSockAddr->sa_socket = htons(DEFAULT_SNMP_PORT_IPX);
|
|||
|
|
|||
|
// allocate ipx socket
|
|||
|
pNLE->Socket = WSASocket(
|
|||
|
AF_IPX,
|
|||
|
SOCK_DGRAM,
|
|||
|
NSPROTO_IPX,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
WSA_FLAG_OVERLAPPED
|
|||
|
);
|
|||
|
|
|||
|
// validate socket
|
|||
|
if (pNLE->Socket != INVALID_SOCKET) {
|
|||
|
|
|||
|
// attempt to bind
|
|||
|
nStatus = bind(pNLE->Socket,
|
|||
|
&pNLE->SockAddr,
|
|||
|
pNLE->SockAddrLen
|
|||
|
);
|
|||
|
|
|||
|
// validate return code
|
|||
|
if (nStatus != SOCKET_ERROR) {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_TRACE,
|
|||
|
"SNMP: SVC: successfully bound to ipx port %d.\n",
|
|||
|
ntohs(pSockAddr->sa_socket)
|
|||
|
));
|
|||
|
|
|||
|
// insert transport into list of incoming
|
|||
|
InsertTailList(&g_IncomingTransports, &pNLE->Link);
|
|||
|
|
|||
|
// success
|
|||
|
fIpxOk = TRUE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: error %d binding to ipx port %d.\n",
|
|||
|
WSAGetLastError(),
|
|||
|
ntohs(pSockAddr->sa_socket)
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_WARNING,
|
|||
|
"SNMP: SVC: error %d creating ipx socket.\n",
|
|||
|
WSAGetLastError()
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
if (!fIpxOk) {
|
|||
|
|
|||
|
// release
|
|||
|
FreeNLE(pNLE);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// need one transport min
|
|||
|
return (fUdpOk || fIpxOk);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
UnloadTransport(
|
|||
|
PNETWORK_LIST_ENTRY pNLE
|
|||
|
)
|
|||
|
{
|
|||
|
|
|||
|
// make sure the parameter is valid, otherwise the macro below AVs
|
|||
|
if (pNLE == NULL)
|
|||
|
return FALSE;
|
|||
|
|
|||
|
// remove the entry from the list
|
|||
|
RemoveEntryList(&(pNLE->Link));
|
|||
|
|
|||
|
// close the socket
|
|||
|
closesocket(pNLE->Socket);
|
|||
|
|
|||
|
// release the memory
|
|||
|
FreeNLE(pNLE);
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
UnloadIncomingTransports(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Destroys entries for each outgoing interface.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PLIST_ENTRY pLE;
|
|||
|
PNETWORK_LIST_ENTRY pNLE;
|
|||
|
|
|||
|
// process entries until empty
|
|||
|
while (!IsListEmpty(&g_IncomingTransports)) {
|
|||
|
|
|||
|
// extract next entry from head
|
|||
|
pLE = RemoveHeadList(&g_IncomingTransports);
|
|||
|
|
|||
|
// retrieve pointer to mib region structure
|
|||
|
pNLE = CONTAINING_RECORD(pLE, NETWORK_LIST_ENTRY, Link);
|
|||
|
|
|||
|
// release
|
|||
|
FreeNLE(pNLE);
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
LoadOutgoingTransports(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Creates entries for each outgoing interface.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BOOL fUdpOk = FALSE;
|
|||
|
BOOL fIpxOk = FALSE;
|
|||
|
PNETWORK_LIST_ENTRY pNLE = NULL;
|
|||
|
|
|||
|
// allocate tcpip
|
|||
|
if (AllocNLE(&pNLE)) {
|
|||
|
|
|||
|
// allocate tpcip socket
|
|||
|
pNLE->Socket = WSASocket(
|
|||
|
AF_INET,
|
|||
|
SOCK_DGRAM,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
WSA_FLAG_OVERLAPPED
|
|||
|
);
|
|||
|
|
|||
|
// validate socket
|
|||
|
if (pNLE->Socket != INVALID_SOCKET) {
|
|||
|
|
|||
|
pNLE->SockAddr.sa_family = AF_INET;
|
|||
|
|
|||
|
// insert transport into list of incoming
|
|||
|
InsertTailList(&g_OutgoingTransports, &pNLE->Link);
|
|||
|
|
|||
|
// success
|
|||
|
fUdpOk = TRUE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_WARNING,
|
|||
|
"SNMP: SVC: error %d creating udp socket.\n",
|
|||
|
WSAGetLastError()
|
|||
|
));
|
|||
|
|
|||
|
// release
|
|||
|
FreeNLE(pNLE);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// allocate ipx
|
|||
|
if (AllocNLE(&pNLE)) {
|
|||
|
|
|||
|
// allocate ipx socket
|
|||
|
pNLE->Socket = WSASocket(
|
|||
|
AF_IPX,
|
|||
|
SOCK_DGRAM,
|
|||
|
NSPROTO_IPX,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
WSA_FLAG_OVERLAPPED
|
|||
|
);
|
|||
|
|
|||
|
// validate socket
|
|||
|
if (pNLE->Socket != INVALID_SOCKET) {
|
|||
|
|
|||
|
pNLE->SockAddr.sa_family = AF_IPX;
|
|||
|
|
|||
|
// insert transport into list of incoming
|
|||
|
InsertTailList(&g_OutgoingTransports, &pNLE->Link);
|
|||
|
|
|||
|
// success
|
|||
|
fIpxOk = TRUE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_WARNING,
|
|||
|
"SNMP: SVC: error %d creating ipx socket.\n",
|
|||
|
WSAGetLastError()
|
|||
|
));
|
|||
|
|
|||
|
// release
|
|||
|
FreeNLE(pNLE);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// need one transport min
|
|||
|
return (fUdpOk || fIpxOk);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
UnloadOutgoingTransports(
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Destroys entries for each outgoing interface.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PLIST_ENTRY pLE;
|
|||
|
PNETWORK_LIST_ENTRY pNLE;
|
|||
|
|
|||
|
// process entries until empty
|
|||
|
while (!IsListEmpty(&g_OutgoingTransports)) {
|
|||
|
|
|||
|
// extract next entry from head
|
|||
|
pLE = RemoveHeadList(&g_OutgoingTransports);
|
|||
|
|
|||
|
// retrieve pointer to mib region structure
|
|||
|
pNLE = CONTAINING_RECORD(pLE, NETWORK_LIST_ENTRY, Link);
|
|||
|
|
|||
|
// release
|
|||
|
FreeNLE(pNLE);
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
UnloadPdu(
|
|||
|
PNETWORK_LIST_ENTRY pNLE
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Releases resources allocated in pdu structure.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pNLE - pointer to network list entry.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
// release community string
|
|||
|
SnmpUtilOctetsFree(&pNLE->Community);
|
|||
|
|
|||
|
// release varbinds in pdu
|
|||
|
SnmpUtilVarBindListFree(&pNLE->Pdu.Vbl);
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|