blob: 5619e35ee6a717092a4e6b5ab07d4305e5e24079 [file] [log] [blame]
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-features.h>
#if HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#if defined(NETSNMP_TRANSPORT_DTLSUDP_DOMAIN) || defined(NETSNMP_TRANSPORT_TLSTCP_DOMAIN)
#include <openssl/ssl.h>
#include <openssl/x509v3.h>
#include <net-snmp/library/cert_util.h>
#endif
#ifdef NETSNMP_TRANSPORT_TLSTCP_DOMAIN
#include <net-snmp/library/snmpTLSTCPDomain.h>
#endif
#ifdef NETSNMP_TRANSPORT_DTLSUDP_DOMAIN
#include <net-snmp/library/snmpDTLSUDPDomain.h>
#endif
#include "snmpTargetAddrEntry.h"
#include "snmpTargetParamsEntry.h"
#include "target.h"
netsnmp_feature_require(tdomain_support)
netsnmp_feature_require(tdomain_transport_oid)
netsnmp_feature_want(netsnmp_tlstmAddr_get_serverId)
#define MAX_TAGS 128
netsnmp_session *
get_target_sessions(char *taglist, TargetFilterFunction * filterfunct,
void *filterArg)
{
netsnmp_session *ret = NULL, thissess;
struct targetAddrTable_struct *targaddrs;
char buf[SPRINT_MAX_LEN];
char tags[MAX_TAGS][SPRINT_MAX_LEN], *cp;
int numtags = 0, i;
#if defined(NETSNMP_TRANSPORT_DTLSUDP_DOMAIN) || defined(NETSNMP_TRANSPORT_TLSTCP_DOMAIN)
int tls = 0;
#endif
static struct targetParamTable_struct *param;
DEBUGMSGTL(("target_sessions", "looking for: %s\n", taglist));
for (cp = taglist; cp && numtags < MAX_TAGS;) {
cp = copy_nword(cp, tags[numtags], sizeof(tags[numtags]));
DEBUGMSGTL(("target_sessions", " for: %d=%s\n", numtags,
tags[numtags]));
numtags++;
}
for (targaddrs = get_addrTable(); targaddrs;
targaddrs = targaddrs->next) {
/*
* legal row?
*/
if (targaddrs->tDomain == NULL ||
targaddrs->tAddress == NULL ||
targaddrs->rowStatus != SNMP_ROW_ACTIVE) {
DEBUGMSGTL(("target_sessions", " which is not ready yet\n"));
continue;
}
if (netsnmp_tdomain_support
(targaddrs->tDomain, targaddrs->tDomainLen, NULL, NULL) == 0) {
snmp_log(LOG_ERR,
"unsupported domain for target address table entry %s\n",
targaddrs->nameData);
}
/*
* check tag list to see if we match
*/
if (targaddrs->tagList) {
int matched = 0;
/*
* loop through tag list looking for requested tags
*/
for (cp = targaddrs->tagList; cp && !matched;) {
cp = copy_nword(cp, buf, sizeof(buf));
for (i = 0; i < numtags && !matched; i++) {
if (strcmp(buf, tags[i]) == 0) {
/*
* found a valid target table entry
*/
DEBUGMSGTL(("target_sessions", "found one: %s\n",
tags[i]));
if (targaddrs->params) {
param = get_paramEntry(targaddrs->params);
if (!param
|| param->rowStatus != SNMP_ROW_ACTIVE) {
/*
* parameter entry must exist and be active
*/
continue;
}
} else {
/*
* parameter entry must be specified
*/
continue;
}
/*
* last chance for caller to opt-out. Call
* filtering function
*/
if (filterfunct &&
(*(filterfunct)) (targaddrs, param,
filterArg)) {
continue;
}
/*
* Only one notification per TargetAddrEntry,
* rather than one per tag
*/
matched = 1;
if (targaddrs->storageType != ST_READONLY &&
targaddrs->sess &&
param->updateTime >=
targaddrs->sessionCreationTime) {
/*
* parameters have changed, nuke the old session
*/
snmp_close(targaddrs->sess);
targaddrs->sess = NULL;
}
/*
* target session already exists?
*/
if (targaddrs->sess == NULL) {
/*
* create an appropriate snmp session and add
* it to our return list
*/
netsnmp_transport *t = NULL;
t = netsnmp_tdomain_transport_oid(targaddrs->
tDomain,
targaddrs->
tDomainLen,
targaddrs->
tAddress,
targaddrs->
tAddressLen,
0);
if (t == NULL) {
DEBUGMSGTL(("target_sessions",
"bad dest \""));
DEBUGMSGOID(("target_sessions",
targaddrs->tDomain,
targaddrs->tDomainLen));
DEBUGMSG(("target_sessions", "\", \""));
DEBUGMSGHEX(("target_sessions",
targaddrs->tAddress,
targaddrs->tAddressLen));
DEBUGMSG(("target_sessions", "\n"));
continue;
} else {
char *dst_str =
t->f_fmtaddr(t, NULL, 0);
if (dst_str != NULL) {
DEBUGMSGTL(("target_sessions",
" to: %s\n", dst_str));
free(dst_str);
}
}
/*
* if tDomain is tls related, check for tls config
*/
#ifdef NETSNMP_TRANSPORT_DTLSUDP_DOMAIN
tls = snmp_oid_compare(targaddrs->tDomain,
targaddrs->tDomainLen,
netsnmpDTLSUDPDomain,
netsnmpDTLSUDPDomain_len);
#endif
#ifdef NETSNMP_TRANSPORT_TLSTCP_DOMAIN
if (tls)
tls = snmp_oid_compare(targaddrs->tDomain,
targaddrs->tDomainLen,
netsnmpTLSTCPDomain,
netsnmpTLSTCPDomain_len);
#endif
#if defined(NETSNMP_TRANSPORT_DTLSUDP_DOMAIN) || defined(NETSNMP_TRANSPORT_TLSTCP_DOMAIN)
if (!tls) {
netsnmp_cert *cert;
char *server_id = NULL;
char buf[33];
DEBUGMSGTL(("target_sessions",
" looking up our id: %s\n",
targaddrs->params));
cert =
netsnmp_cert_find(NS_CERT_IDENTITY,
NS_CERTKEY_TARGET_PARAM,
targaddrs->params);
netsnmp_assert(t->f_config);
if (cert) {
DEBUGMSGTL(("target_sessions",
" found fingerprint: %s\n",
cert->fingerprint));
t->f_config(t, "localCert",
cert->fingerprint);
}
memcpy(buf, targaddrs->nameData,
targaddrs->nameLen);
buf[targaddrs->nameLen] = '\0';
DEBUGMSGTL(("target_sessions",
" looking up their id: %s\n",
buf));
cert =
netsnmp_cert_find(NS_CERT_REMOTE_PEER,
NS_CERTKEY_TARGET_ADDR,
buf);
if (cert) {
DEBUGMSGTL(("target_sessions",
" found fingerprint: %s\n",
cert->fingerprint));
t->f_config(t, "peerCert",
cert->fingerprint);
}
#ifndef NETSNMP_FEATURE_REMOVE_TLSTMADDR_GET_SERVERID
server_id = netsnmp_tlstmAddr_get_serverId(buf);
#endif /* NETSNMP_FEATURE_REMOVE_TLSTMADDR_GET_SERVERID */
if (server_id) {
DEBUGMSGTL(("target_sessions",
" found serverId: %s\n",
server_id));
t->f_config(t, "their_hostname", server_id);
}
}
#endif
memset(&thissess, 0, sizeof(thissess));
thissess.timeout = (targaddrs->timeout) * 10000;
thissess.retries = targaddrs->retryCount;
DEBUGMSGTL(("target_sessions",
"timeout: %d -> %ld\n",
targaddrs->timeout,
thissess.timeout));
if (param->mpModel == SNMP_VERSION_3 &&
param->secModel != SNMP_SEC_MODEL_USM &&
param->secModel != SNMP_SEC_MODEL_TSM) {
snmp_log(LOG_ERR,
"unsupported mpModel/secModel combo %d/%d for target %s\n",
param->mpModel, param->secModel,
targaddrs->nameData);
/*
* XXX: memleak
*/
netsnmp_transport_free(t);
continue;
}
thissess.paramName = strdup(param->paramName);
thissess.version = param->mpModel;
if (param->mpModel == SNMP_VERSION_3) {
thissess.securityName = strdup(param->secName);
thissess.securityNameLen =
strlen(thissess.securityName);
thissess.securityLevel = param->secLevel;
thissess.securityModel = param->secModel;
#if !defined(NETSNMP_DISABLE_SNMPV1) || !defined(NETSNMP_DISABLE_SNMPV2C)
} else {
thissess.community =
(u_char *) strdup(param->secName);
thissess.community_len =
strlen((char *) thissess.community);
#endif
}
thissess.flags |= SNMP_FLAGS_DONT_PROBE;
targaddrs->sess = snmp_add(&thissess, t,
NULL, NULL);
thissess.flags &= ~SNMP_FLAGS_DONT_PROBE;
targaddrs->sessionCreationTime = time(NULL);
}
if (targaddrs->sess) {
if (NULL == targaddrs->sess->paramName)
targaddrs->sess->paramName =
strdup(param->paramName);
targaddrs->sess->next = ret;
ret = targaddrs->sess;
} else {
snmp_sess_perror("target session", &thissess);
}
}
}
}
}
}
return ret;
}