|
|
/*++
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; }
|