/*++ Copyright (c) 1992-1996 Microsoft Corporation Module Name: trapapi.c Abstract: Provides SNMP message authentication 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 ---- #include #include #include #include #include #include #include //--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------ #include #include #include "wellknow.h" #include "..\authapi.\berapi.h" #include "..\authapi.\pduapi.h" #include "..\authapi.\auth1157.h" #include "..\authapi.\authxxxx.h" #include "..\authapi.\authapi.h" #include "regconf.h" //--------------------------- SELF-DEPENDENCY -- ONE #include"module.h" ----- //--------------------------- PUBLIC VARIABLES --(same as in module.h file)-- extern DWORD g_platformId; extern AsnObjectIdentifier * g_enterprise; //--------------------------- PRIVATE CONSTANTS ----------------------------- #define SGTTimeout ((DWORD)3600000) //--------------------------- PRIVATE STRUCTS ------------------------------- //--------------------------- PRIVATE VARIABLES ----------------------------- static RFC1157VarBindList noVarBinds = { NULL, 0 }; //--------------------------- PRIVATE PROTOTYPES ---------------------------- int gethostname(OUT char *,IN int ); void dp_ipx(int, char *, SOCKADDR_IPX *, char *); //--------------------------- PRIVATE PROCEDURES ---------------------------- #define bzero(lp, size) (void)memset(lp, 0, size) //--------------------------- PUBLIC PROCEDURES ----------------------------- SNMPAPI SNMP_FUNC_TYPE SnmpSvcGenerateTrap( IN AsnObjectIdentifier * enterprise, IN AsnInteger genericTrap, IN AsnInteger specificTrap, IN AsnTimeticks timeStamp, IN RFC1157VarBindList * variableBindings) { static BOOL fFirstTime = TRUE; static HANDLE hGenerateTrapMutex; static char myname[128]; static struct sockaddr mysocket; static SnmpMgmtCom request; static SOCKET fd_inet, fd_ipx, fd; static unsigned long nul_s_addr = 0L; struct sockaddr dest; BYTE *pBuf; UINT length; INT i, j; if (fFirstTime) { struct sockaddr localAddress; BOOL fSuccess; fFirstTime = FALSE; fSuccess = FALSE; // initialize trap destinations if (!tdConfig(&trapDests, &trapDestsLen)) { SnmpUtilVarBindListFree(variableBindings); return FALSE; } // setup 2 trap generation sockets, one for inet, one for ipx // block... { struct sockaddr_in localAddress_in; localAddress_in.sin_family = AF_INET; localAddress_in.sin_port = htons(0); localAddress_in.sin_addr.s_addr = ntohl(INADDR_ANY); bcopy(&localAddress_in, &localAddress, sizeof(localAddress_in)); } // end block. if ((fd_inet = socket(AF_INET, SOCK_DGRAM, 0)) == (SOCKET)-1) { SNMPDBG((SNMP_LOG_TRACE, "SNMP: TRAP: error %d creating udp trap generation socket.\n", GetLastError())); SnmpUtilVarBindListFree(variableBindings); } else if (bind(fd_inet, &localAddress, sizeof(localAddress)) != 0) { SNMPDBG((SNMP_LOG_ERROR, "SNMP: TRAP: error %d binding udp trap generation socket.\n", GetLastError())); SnmpUtilVarBindListFree(variableBindings); } else { fSuccess = TRUE; } { struct sockaddr_ipx localAddress_ipx; bzero(&localAddress_ipx,sizeof(localAddress_ipx)); localAddress_ipx.sa_family = AF_IPX; bcopy(&localAddress_ipx, &localAddress, sizeof(localAddress_ipx)); } if ((fd_ipx = socket(AF_IPX, SOCK_DGRAM, NSPROTO_IPX)) == (SOCKET)-1) { SNMPDBG((SNMP_LOG_TRACE, "SNMP: TRAP: error %d creating ipx trap generation socket.\n", GetLastError())); SnmpUtilVarBindListFree(variableBindings); } else if (bind(fd_ipx, &localAddress, sizeof(localAddress)) != 0) { SNMPDBG((SNMP_LOG_ERROR, "SNMP: TRAP: error %d binding ipx trap generation socket.\n", GetLastError())); SnmpUtilVarBindListFree(variableBindings); } else { fSuccess = TRUE; } if (!fSuccess) return FALSE; // create mutex... if ((hGenerateTrapMutex = CreateMutex(NULL, FALSE, NULL)) == NULL) { SNMPDBG((SNMP_LOG_ERROR, "SNMP: TRAP: error %d creating trap generaion mutex.\n", GetLastError())); SnmpUtilVarBindListFree(variableBindings); return FALSE; } // other one-time initialization... request.pdu.pduType = ASN_RFC1157_TRAP; if (fd_inet != (SOCKET)-1) { if (gethostname(myname, sizeof(myname)) == -1) { SNMPDBG((SNMP_LOG_ERROR, "SNMP: TRAP: error on gethostname %d.\n", GetLastError())); SnmpUtilVarBindListFree(variableBindings); return FALSE; } if (!SnmpSvcAddrToSocket(myname, &mysocket) == -1) { SNMPDBG((SNMP_LOG_ERROR, "SNMP: TRAP: error on SnmpSvcAddrToSocket %d.\n", GetLastError())); SnmpUtilVarBindListFree(variableBindings); return FALSE; } } } // end if (fFirstTime) // take mutex if (WaitForSingleObject(hGenerateTrapMutex, SGTTimeout) == 0xffffffff) { SNMPDBG((SNMP_LOG_ERROR, "SNMP: TRAP: error %d waiting for trap generation mutex.\n", GetLastError())); SnmpUtilVarBindListFree(variableBindings); return FALSE; } // build pdu request.pdu.pduValue.trap.genericTrap = genericTrap; request.pdu.pduValue.trap.specificTrap = specificTrap; request.pdu.pduValue.trap.timeStamp = timeStamp; request.pdu.pduValue.trap.varBinds.list = variableBindings->list; request.pdu.pduValue.trap.varBinds.len = variableBindings->len; // check if default enterprise oid has been overridden if (enterprise && enterprise->idLength && enterprise->ids) { request.pdu.pduValue.trap.enterprise.idLength = enterprise->idLength; request.pdu.pduValue.trap.enterprise.ids = enterprise->ids; } else { request.pdu.pduValue.trap.enterprise.idLength = g_enterprise->idLength; request.pdu.pduValue.trap.enterprise.ids = g_enterprise->ids; } for (i=0; is_port; } destAddress_in.sin_addr.s_addr = ((struct sockaddr_in *)(&trapDests[i].addrList[j].addrEncoding))->sin_addr.s_addr; SNMPDBG((SNMP_LOG_TRACE, "SNMP: TRAP: processing ip trap destination %u.%u.%u.%u.\n", destAddress_in.sin_addr.S_un.S_un_b.s_b1, destAddress_in.sin_addr.S_un.S_un_b.s_b2, destAddress_in.sin_addr.S_un.S_un_b.s_b3, destAddress_in.sin_addr.S_un.S_un_b.s_b4)); bcopy(&destAddress_in, &dest, sizeof(destAddress_in)); } // include local agent addr in pdu (ip only) request.pdu.pduValue.trap.agentAddr.stream = (BYTE *)&((struct sockaddr_in *)(&mysocket))->sin_addr.s_addr; request.pdu.pduValue.trap.agentAddr.length = 4; fd = fd_inet; break; case AF_IPX: { SOCKADDR_IPX *pdest = (SOCKADDR_IPX *) &dest; if (fd_ipx == (SOCKET)-1) // don't have an IPX socket { SNMPDBG((SNMP_LOG_TRACE, "SNMP: TRAP: cannot send ipx trap because no socket available.\n")); continue; } // sa_family, sa_netnum, and sa_nodenum are already set bcopy(&trapDests[i].addrList[j].addrEncoding, &dest, sizeof(SOCKADDR_IPX)); pdest->sa_socket = htons(WKSN_IPX_TRAP); dp_ipx(SNMP_LOG_TRACE, "SNMP: TRAP: processing ipx trap destination ", pdest, ".\n"); } // include empty agent addr in pdu (ipx only) request.pdu.pduValue.trap.agentAddr.stream = (BYTE *)&nul_s_addr; request.pdu.pduValue.trap.agentAddr.length = 4; fd = fd_ipx; break; default: { SNMPDBG((SNMP_LOG_TRACE, "SNMP: TRAP: cannot send trap because sa_family invalid.\n")); continue; } } pBuf = NULL; length = 0; if (!SnmpSvcEncodeMessage(ASN_SEQUENCE, &request, &pBuf, &length)) { SNMPDBG((SNMP_LOG_TRACE, "SNMP: TRAP: error on SnmpSvcEncodeMessage %d.\n", GetLastError())); SnmpUtilMemFree(pBuf); continue; } // transmit trap pdu if ((length = sendto(fd, pBuf, length, 0, &dest, sizeof(dest))) == -1) { SNMPDBG((SNMP_LOG_ERROR, "SNMP: TRAP: error %d sending trap.\n", GetLastError())); //a serious error? } else { SNMPDBG((SNMP_LOG_TRACE, "SNMP: TRAP: trap sent successfully.\n")); } SnmpUtilMemFree(pBuf); } // end for () } // end for () SnmpUtilVarBindListFree(variableBindings); // release mutex if (!ReleaseMutex(hGenerateTrapMutex)) { SNMPDBG((SNMP_LOG_ERROR, "SNMP: TRAP: error %d releasing trap generation mutex.\n", GetLastError())); return FALSE; } return TRUE; } // end SnmpSvcGenerateTrap() SNMPAPI SNMP_FUNC_TYPE SnmpSvcGenerateColdStartTrap( IN AsnInteger timeStamp) { if (!SnmpSvcGenerateTrap( NULL, // use default oid SNMP_GENERICTRAP_COLDSTART, 0, timeStamp, &noVarBinds)) { SNMPDBG((SNMP_LOG_TRACE, "SNMP: TRAP: error on SnmpServiceGenerateTrap %d.\n", GetLastError())); return FALSE; } return TRUE; } // end SnmpSvcGenerateColdStartTrap() SNMPAPI SNMP_FUNC_TYPE SnmpSvcGenerateWarmStartTrap( IN AsnInteger timeStamp) { if (!SnmpSvcGenerateTrap( NULL, // use default oid SNMP_GENERICTRAP_WARMSTART, 0, timeStamp, &noVarBinds)) { SNMPDBG((SNMP_LOG_TRACE, "SNMP: TRAP: error on SnmpServiceGenerateTrap %d.\n", GetLastError())); return FALSE; } return TRUE; } // end SnmpSvcGenerateWarmStartTrap() SNMPAPI SNMP_FUNC_TYPE SnmpSvcGenerateLinkUpTrap( IN AsnInteger timeStamp, IN RFC1157VarBindList * variableBindings) { if (!SnmpSvcGenerateTrap( NULL, // use default oid SNMP_GENERICTRAP_LINKUP, 0, timeStamp, variableBindings)) { SNMPDBG((SNMP_LOG_TRACE, "SNMP: TRAP: error on SnmpServiceGenerateTrap %d.\n", GetLastError())); return FALSE; } return TRUE; } // end SnmpSvcGenerateLinkUpTrap() SNMPAPI SNMP_FUNC_TYPE SnmpSvcGenerateLinkDownTrap( IN AsnInteger timeStamp, IN RFC1157VarBindList * variableBindings) { if (!SnmpSvcGenerateTrap( NULL, // use default oid SNMP_GENERICTRAP_LINKDOWN, 0, timeStamp, variableBindings)) { SNMPDBG((SNMP_LOG_TRACE, "SNMP: TRAP: error on SnmpServiceGenerateTrap %d.\n", GetLastError())); return FALSE; } return TRUE; } // end SnmpSvcGenerateLinkDownTrap() SNMPAPI SNMP_FUNC_TYPE SnmpSvcGenerateAuthFailTrap( AsnInteger timeStamp) { if (!SnmpSvcGenerateTrap( NULL, // use default oid SNMP_GENERICTRAP_AUTHFAILURE, 0, timeStamp, &noVarBinds)) { SNMPDBG((SNMP_LOG_TRACE, "SNMP: TRAP: error on SnmpServiceGenerateTrap %d.\n", GetLastError())); return FALSE; } return TRUE; } // end SnmpSvcGenerateAuthFailTrap() // authenticate community of rfc1157 message with valid communities in registry BOOL commauth(RFC1157Message *message) { static BOOL fFirstTime = TRUE; BOOL fFound = FALSE; INT i; if (fFirstTime) { fFirstTime = FALSE; vcConfig(&validComms, &validCommsLen); } if (validCommsLen > 0) { for(i=0; i < validCommsLen; i++) { if ((strlen(validComms[i].communityName) == message->community.length) && !strncmp(message->community.stream, validComms[i].communityName, message->community.length)) { fFound = TRUE; break; } } // end for () } else { fFound = TRUE; // no entries means all communities allowed } // end if if (!fFound) { SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: invalid community filtered.\n")); if (enableAuthTraps) { if (!SnmpSvcGenerateAuthFailTrap(SnmpSvcGetUptime())) { SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: error on SnmpSvcGenerateAuthFailTrap %d.\n", GetLastError())); } } // end if } // end if return fFound; } // end commauth() //-------------------------------- END -------------------------------------- // display IPX address in 00000001.123456789ABC form void dp_ipx(int level, char *msg1, SOCKADDR_IPX* addr, char *msg2) { SNMPDBG((level, "%s%02X%02X%02X%02X.%02X%02X%02X%02X%02X%02X%s", msg1, (unsigned char)addr->sa_netnum[0], (unsigned char)addr->sa_netnum[1], (unsigned char)addr->sa_netnum[2], (unsigned char)addr->sa_netnum[3], (unsigned char)addr->sa_nodenum[0], (unsigned char)addr->sa_nodenum[1], (unsigned char)addr->sa_nodenum[2], (unsigned char)addr->sa_nodenum[3], (unsigned char)addr->sa_nodenum[4], (unsigned char)addr->sa_nodenum[5], msg2)); }