|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Portions of this file are copyrighted by:
|
|
Packit |
fcad23 |
* Copyright (c) 2016 VMware, Inc. All rights reserved.
|
|
Packit |
fcad23 |
* Use is subject to license terms specified in the COPYING file
|
|
Packit |
fcad23 |
* distributed with the Net-SNMP package.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
#include <net-snmp/net-snmp-config.h>
|
|
Packit |
fcad23 |
#include <net-snmp/net-snmp-features.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#include <net-snmp/types.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmp_transport.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#include <stdio.h>
|
|
Packit |
fcad23 |
#if HAVE_STRING_H
|
|
Packit |
fcad23 |
#include <string.h>
|
|
Packit |
fcad23 |
#else
|
|
Packit |
fcad23 |
#include <strings.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#include <sys/types.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#if HAVE_STDLIB_H
|
|
Packit |
fcad23 |
#include <stdlib.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#include <ctype.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#if HAVE_UNISTD_H
|
|
Packit |
fcad23 |
#include <unistd.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#if HAVE_DMALLOC_H
|
|
Packit |
fcad23 |
#include <dmalloc.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#include <net-snmp/output_api.h>
|
|
Packit |
fcad23 |
#include <net-snmp/utilities.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#include <net-snmp/library/default_store.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmpUDPDomain.h>
|
|
Packit |
fcad23 |
#ifdef NETSNMP_TRANSPORT_TLSBASE_DOMAIN
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmpTLSBaseDomain.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#ifdef NETSNMP_TRANSPORT_TLSTCP_DOMAIN
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmpTLSTCPDomain.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#ifdef NETSNMP_TRANSPORT_STD_DOMAIN
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmpSTDDomain.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#ifdef NETSNMP_TRANSPORT_TCP_DOMAIN
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmpTCPDomain.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#ifdef NETSNMP_TRANSPORT_DTLSUDP_DOMAIN
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmpDTLSUDPDomain.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#ifdef NETSNMP_TRANSPORT_SSH_DOMAIN
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmpSSHDomain.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#ifdef NETSNMP_TRANSPORT_ALIAS_DOMAIN
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmpAliasDomain.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#ifdef NETSNMP_TRANSPORT_IPX_DOMAIN
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmpIPXDomain.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#ifdef NETSNMP_TRANSPORT_UNIX_DOMAIN
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmpUnixDomain.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#ifdef NETSNMP_TRANSPORT_AAL5PVC_DOMAIN
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmpAAL5PVCDomain.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#ifdef NETSNMP_TRANSPORT_UDPIPV6_DOMAIN
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmpUDPIPv6Domain.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#ifdef NETSNMP_TRANSPORT_TCPIPV6_DOMAIN
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmpTCPIPv6Domain.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#ifdef NETSNMP_TRANSPORT_UDPSHARED_DOMAIN
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmpUDPsharedDomain.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmp_api.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmp_service.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/read_config.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_feature_child_of(transport_all, libnetsnmp)
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_feature_child_of(tdomain_support, transport_all)
|
|
Packit |
fcad23 |
netsnmp_feature_child_of(tdomain_transport_oid, transport_all)
|
|
Packit |
fcad23 |
netsnmp_feature_child_of(sockaddr_size, transport_all)
|
|
Packit |
fcad23 |
netsnmp_feature_child_of(transport_cache, transport_all)
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Our list of supported transport domains.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static netsnmp_tdomain *domain_list = NULL;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* The standard SNMP domains.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
oid netsnmpUDPDomain[] = { 1, 3, 6, 1, 6, 1, 1 };
|
|
Packit |
fcad23 |
size_t netsnmpUDPDomain_len = OID_LENGTH(netsnmpUDPDomain);
|
|
Packit |
fcad23 |
oid netsnmpCLNSDomain[] = { 1, 3, 6, 1, 6, 1, 2 };
|
|
Packit |
fcad23 |
size_t netsnmpCLNSDomain_len = OID_LENGTH(netsnmpCLNSDomain);
|
|
Packit |
fcad23 |
oid netsnmpCONSDomain[] = { 1, 3, 6, 1, 6, 1, 3 };
|
|
Packit |
fcad23 |
size_t netsnmpCONSDomain_len = OID_LENGTH(netsnmpCONSDomain);
|
|
Packit |
fcad23 |
oid netsnmpDDPDomain[] = { 1, 3, 6, 1, 6, 1, 4 };
|
|
Packit |
fcad23 |
size_t netsnmpDDPDomain_len = OID_LENGTH(netsnmpDDPDomain);
|
|
Packit |
fcad23 |
oid netsnmpIPXDomain[] = { 1, 3, 6, 1, 6, 1, 5 };
|
|
Packit |
fcad23 |
size_t netsnmpIPXDomain_len = OID_LENGTH(netsnmpIPXDomain);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static netsnmp_container *_container = NULL;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static void netsnmp_tdomain_dump(void);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#if !defined(NETSNMP_FEATURE_REMOVE_FILTER_SOURCE)
|
|
Packit |
fcad23 |
static netsnmp_container * filtered = NULL;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
void netsnmp_transport_parse_filter(const char *word, char *cptr);
|
|
Packit |
fcad23 |
#endif /* NETSNMP_FEATURE_REMOVE_FILTER_SOURCE */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
void
|
|
Packit |
fcad23 |
init_snmp_transport(void)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
netsnmp_ds_register_config(ASN_BOOLEAN,
|
|
Packit |
fcad23 |
"snmp", "dontLoadHostConfig",
|
|
Packit |
fcad23 |
NETSNMP_DS_LIBRARY_ID,
|
|
Packit |
fcad23 |
NETSNMP_DS_LIB_DONT_LOAD_HOST_FILES);
|
|
Packit |
fcad23 |
#ifndef NETSNMP_FEATURE_REMOVE_FILTER_SOURCE
|
|
Packit |
fcad23 |
register_app_config_handler("sourceFilterType",
|
|
Packit |
fcad23 |
netsnmp_transport_parse_filterType,
|
|
Packit |
fcad23 |
NULL, "none|whitelist|blacklist");
|
|
Packit |
fcad23 |
register_app_config_handler("sourceFilterAddress",
|
|
Packit |
fcad23 |
netsnmp_transport_parse_filter,
|
|
Packit |
fcad23 |
netsnmp_transport_filter_cleanup,
|
|
Packit |
fcad23 |
"host");
|
|
Packit |
fcad23 |
#endif /* NETSNMP_FEATURE_REMOVE_FILTER_SOURCE */
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
void
|
|
Packit |
fcad23 |
shutdown_snmp_transport(void)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
#ifndef NETSNMP_FEATURE_REMOVE_FILTER_SOURCE
|
|
Packit |
fcad23 |
netsnmp_transport_filter_cleanup();
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Make a deep copy of an netsnmp_transport.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
netsnmp_transport *
|
|
Packit |
fcad23 |
netsnmp_transport_copy(const netsnmp_transport *t)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
netsnmp_transport *n = NULL;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (t == NULL) {
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
n = SNMP_MALLOC_TYPEDEF(netsnmp_transport);
|
|
Packit |
fcad23 |
if (n == NULL) {
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (t->domain != NULL) {
|
|
Packit |
fcad23 |
n->domain = t->domain;
|
|
Packit |
fcad23 |
n->domain_length = t->domain_length;
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
n->domain = NULL;
|
|
Packit |
fcad23 |
n->domain_length = 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (t->local != NULL) {
|
|
Packit |
fcad23 |
n->local = netsnmp_memdup(t->local, t->local_length);
|
|
Packit |
fcad23 |
if (n->local == NULL) {
|
|
Packit |
fcad23 |
netsnmp_transport_free(n);
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
n->local_length = t->local_length;
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
n->local = NULL;
|
|
Packit |
fcad23 |
n->local_length = 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (t->remote != NULL) {
|
|
Packit |
fcad23 |
n->remote = netsnmp_memdup(t->remote, t->remote_length);
|
|
Packit |
fcad23 |
if (n->remote == NULL) {
|
|
Packit |
fcad23 |
netsnmp_transport_free(n);
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
n->remote_length = t->remote_length;
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
n->remote = NULL;
|
|
Packit |
fcad23 |
n->remote_length = 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (t->data != NULL && t->data_length > 0) {
|
|
Packit |
fcad23 |
n->data = netsnmp_memdup(t->data, t->data_length);
|
|
Packit |
fcad23 |
if (n->data == NULL) {
|
|
Packit |
fcad23 |
netsnmp_transport_free(n);
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
n->data_length = t->data_length;
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
n->data = NULL;
|
|
Packit |
fcad23 |
n->data_length = 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
n->msgMaxSize = t->msgMaxSize;
|
|
Packit |
fcad23 |
n->f_accept = t->f_accept;
|
|
Packit |
fcad23 |
n->f_recv = t->f_recv;
|
|
Packit |
fcad23 |
n->f_send = t->f_send;
|
|
Packit |
fcad23 |
n->f_close = t->f_close;
|
|
Packit |
fcad23 |
n->f_copy = t->f_copy;
|
|
Packit |
fcad23 |
n->f_config = t->f_config;
|
|
Packit |
fcad23 |
n->f_fmtaddr = t->f_fmtaddr;
|
|
Packit |
fcad23 |
n->sock = t->sock;
|
|
Packit |
fcad23 |
n->flags = t->flags;
|
|
Packit |
fcad23 |
n->base_transport = netsnmp_transport_copy(t->base_transport);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/* give the transport a chance to do "special things" */
|
|
Packit |
fcad23 |
if (t->f_copy)
|
|
Packit |
fcad23 |
t->f_copy(t, n);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return n;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
void
|
|
Packit |
fcad23 |
netsnmp_transport_free(netsnmp_transport *t)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
if (NULL == t)
|
|
Packit |
fcad23 |
return;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifndef FEATURE_REMOVE_TRANSPORT_CACHE
|
|
Packit |
fcad23 |
/** don't free a transport that is currently shared */
|
|
Packit |
fcad23 |
if (netsnmp_transport_cache_remove(t) == 1)
|
|
Packit |
fcad23 |
return;
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
SNMP_FREE(t->local);
|
|
Packit |
fcad23 |
SNMP_FREE(t->remote);
|
|
Packit |
fcad23 |
SNMP_FREE(t->data);
|
|
Packit |
fcad23 |
netsnmp_transport_free(t->base_transport);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
SNMP_FREE(t);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* netsnmp_transport_peer_string
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* returns string representation of peer address.
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* caller is responsible for freeing the allocated string.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
char *
|
|
Packit |
fcad23 |
netsnmp_transport_peer_string(netsnmp_transport *t, const void *data, int len)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
char *str;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (NULL == t)
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (t->f_fmtaddr != NULL)
|
|
Packit |
fcad23 |
str = t->f_fmtaddr(t, data, len);
|
|
Packit |
fcad23 |
else
|
|
Packit |
fcad23 |
str = strdup("<UNKNOWN>");
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return str;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#if !defined(NETSNMP_FEATURE_REMOVE_FILTER_SOURCE)
|
|
Packit |
fcad23 |
static int _transport_filter_init(void)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
if (filtered)
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
filtered = netsnmp_container_find("transport_filter:cstring");
|
|
Packit |
fcad23 |
if (NULL == filtered) {
|
|
Packit |
fcad23 |
NETSNMP_LOGONCE((LOG_WARNING,
|
|
Packit |
fcad23 |
"couldn't allocate container for transport_filter list\n"));
|
|
Packit |
fcad23 |
return -1;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
filtered->container_name = strdup("transport_filter list");
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
netsnmp_transport_filter_add(const char *addrtxt)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
char *tmp;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* create the container, if needed
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
if (!filtered && _transport_filter_init()) {
|
|
Packit |
fcad23 |
snmp_log(LOG_ERR,"netsnmp_transport_filter_add %s failed\n",
|
|
Packit |
fcad23 |
addrtxt);
|
|
Packit |
fcad23 |
return (-1);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
tmp = strdup(addrtxt);
|
|
Packit |
fcad23 |
if (NULL == tmp) {
|
|
Packit |
fcad23 |
snmp_log(LOG_ERR,"netsnmp_transport_filter_add strdup failed\n");
|
|
Packit |
fcad23 |
return(-1);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
return CONTAINER_INSERT(filtered, tmp);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
netsnmp_transport_filter_remove(const char *addrtxt)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* create the container, if needed
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
if (NULL == filtered)
|
|
Packit |
fcad23 |
return -1;
|
|
Packit |
fcad23 |
return CONTAINER_REMOVE(filtered, addrtxt);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* netsnmp_transport_filter_check
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* returns 1 if the specified address string is in the filter list
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
netsnmp_transport_filter_check(const char *addrtxt)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
char *addr;
|
|
Packit |
fcad23 |
if (NULL == filtered)
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
addr = CONTAINER_FIND(filtered, addrtxt);
|
|
Packit |
fcad23 |
return addr ? 1 : 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
void
|
|
Packit |
fcad23 |
netsnmp_transport_parse_filterType(const char *word, char *cptr)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
int type = 42;
|
|
Packit |
fcad23 |
if (strcmp(cptr,"whitelist") == 0)
|
|
Packit |
fcad23 |
type = 1;
|
|
Packit |
fcad23 |
else if (strcmp(cptr,"blacklist") == 0)
|
|
Packit |
fcad23 |
type = -1;
|
|
Packit |
fcad23 |
else if (strcmp(cptr,"none") == 0)
|
|
Packit |
fcad23 |
type = 0;
|
|
Packit |
fcad23 |
else
|
|
Packit |
fcad23 |
netsnmp_config_error("unknown source filter type: %s", cptr);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (type != 42) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:filterType", "set to %d\n", type));
|
|
Packit |
fcad23 |
netsnmp_ds_set_int(NETSNMP_DS_LIBRARY_ID,
|
|
Packit |
fcad23 |
NETSNMP_DS_LIB_FILTER_TYPE, type);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
void
|
|
Packit |
fcad23 |
netsnmp_transport_parse_filter(const char *word, char *cptr)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
if (netsnmp_transport_filter_add(cptr))
|
|
Packit |
fcad23 |
netsnmp_config_error("cannot create source filter: %s", cptr);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
void
|
|
Packit |
fcad23 |
netsnmp_transport_filter_cleanup(void)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
if (NULL == filtered)
|
|
Packit |
fcad23 |
return;
|
|
Packit |
fcad23 |
CONTAINER_CLEAR(filtered, filtered->free_item, NULL);
|
|
Packit |
fcad23 |
CONTAINER_FREE(filtered);
|
|
Packit |
fcad23 |
filtered = NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#endif /* NETSNMP_FEATURE_REMOVE_FILTER_SOURCE */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifndef NETSNMP_FEATURE_REMOVE_SOCKADDR_SIZE
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
netsnmp_sockaddr_size(const struct sockaddr *sa)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
if (NULL == sa)
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
switch (sa->sa_family) {
|
|
Packit |
fcad23 |
case AF_INET:
|
|
Packit |
fcad23 |
return sizeof(struct sockaddr_in);
|
|
Packit |
fcad23 |
break;
|
|
Packit |
fcad23 |
#ifdef NETSNMP_ENABLE_IPV6
|
|
Packit |
fcad23 |
case AF_INET6:
|
|
Packit |
fcad23 |
return sizeof(struct sockaddr_in6);
|
|
Packit |
fcad23 |
break;
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#endif /* NETSNMP_FEATURE_REMOVE_SOCKADDR_SIZE */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
netsnmp_transport_send(netsnmp_transport *t, const void *packet, int length,
|
|
Packit |
fcad23 |
void **opaque, int *olength)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
int dumpPacket, debugLength;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if ((NULL == t) || (NULL == t->f_send)) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:pkt:send", "NULL transport or send function\n"));
|
|
Packit |
fcad23 |
return SNMPERR_GENERR;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
dumpPacket = netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
|
|
Packit |
fcad23 |
NETSNMP_DS_LIB_DUMP_PACKET);
|
|
Packit |
fcad23 |
debugLength = (SNMPERR_SUCCESS ==
|
|
Packit |
fcad23 |
debug_is_token_registered("transport:send"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (dumpPacket | debugLength) {
|
|
Packit |
fcad23 |
char *str = netsnmp_transport_peer_string(t,
|
|
Packit |
fcad23 |
opaque ? *opaque : NULL,
|
|
Packit |
fcad23 |
olength ? *olength : 0);
|
|
Packit |
fcad23 |
if (debugLength)
|
|
Packit |
fcad23 |
DEBUGMSGT_NC(("transport:send","%lu bytes to %s\n",
|
|
Packit |
fcad23 |
(unsigned long)length, str));
|
|
Packit |
fcad23 |
if (dumpPacket)
|
|
Packit |
fcad23 |
snmp_log(LOG_DEBUG, "\nSending %lu bytes to %s\n",
|
|
Packit |
fcad23 |
(unsigned long)length, str);
|
|
Packit |
fcad23 |
SNMP_FREE(str);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
if (dumpPacket)
|
|
Packit |
fcad23 |
xdump(packet, length, "");
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return t->f_send(t, packet, length, opaque, olength);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
netsnmp_transport_recv(netsnmp_transport *t, void *packet, int length,
|
|
Packit |
fcad23 |
void **opaque, int *olength)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
int debugLength;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if ((NULL == t) || (NULL == t->f_recv)) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:recv", "NULL transport or recv function\n"));
|
|
Packit |
fcad23 |
return SNMPERR_GENERR;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
length = t->f_recv(t, packet, length, opaque, olength);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (length <=0)
|
|
Packit |
fcad23 |
return length; /* don't log timeouts/socket closed */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
debugLength = (SNMPERR_SUCCESS ==
|
|
Packit |
fcad23 |
debug_is_token_registered("transport:recv"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (debugLength) {
|
|
Packit |
fcad23 |
char *str = netsnmp_transport_peer_string(t,
|
|
Packit |
fcad23 |
opaque ? *opaque : NULL,
|
|
Packit |
fcad23 |
olength ? *olength : 0);
|
|
Packit |
fcad23 |
if (debugLength)
|
|
Packit |
fcad23 |
DEBUGMSGT_NC(("transport:recv","%d bytes from %s\n",
|
|
Packit |
fcad23 |
length, str));
|
|
Packit |
fcad23 |
SNMP_FREE(str);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return length;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifndef NETSNMP_FEATURE_REMOVE_TDOMAIN_SUPPORT
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
netsnmp_tdomain_support(const oid * in_oid,
|
|
Packit |
fcad23 |
size_t in_len,
|
|
Packit |
fcad23 |
const oid ** out_oid, size_t * out_len)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
netsnmp_tdomain *d = NULL;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
for (d = domain_list; d != NULL; d = d->next) {
|
|
Packit |
fcad23 |
if (netsnmp_oid_equals(in_oid, in_len, d->name, d->name_length) == 0) {
|
|
Packit |
fcad23 |
if (out_oid != NULL && out_len != NULL) {
|
|
Packit |
fcad23 |
*out_oid = d->name;
|
|
Packit |
fcad23 |
*out_len = d->name_length;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#endif /* NETSNMP_FEATURE_REMOVE_TDOMAIN_SUPPORT */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
void
|
|
Packit |
fcad23 |
netsnmp_tdomain_init(void)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
DEBUGMSGTL(("tdomain", "netsnmp_tdomain_init() called\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/* include the configure generated list of constructor calls */
|
|
Packit |
fcad23 |
#include "transports/snmp_transport_inits.h"
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_tdomain_dump();
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
void
|
|
Packit |
fcad23 |
netsnmp_clear_tdomain_list(void)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
netsnmp_tdomain *list = domain_list, *next = NULL;
|
|
Packit |
fcad23 |
DEBUGMSGTL(("tdomain", "clear_tdomain_list() called\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
while (list != NULL) {
|
|
Packit |
fcad23 |
next = list->next;
|
|
Packit |
fcad23 |
SNMP_FREE(list->prefix);
|
|
Packit |
fcad23 |
/* attention!! list itself is not in the heap, so we must not free it! */
|
|
Packit |
fcad23 |
list = next;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
domain_list = NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static void
|
|
Packit |
fcad23 |
netsnmp_tdomain_dump(void)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
netsnmp_tdomain *d;
|
|
Packit |
fcad23 |
int i = 0;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("tdomain", "domain_list -> "));
|
|
Packit |
fcad23 |
for (d = domain_list; d != NULL; d = d->next) {
|
|
Packit |
fcad23 |
DEBUGMSG(("tdomain", "{ "));
|
|
Packit |
fcad23 |
DEBUGMSGOID(("tdomain", d->name, d->name_length));
|
|
Packit |
fcad23 |
DEBUGMSG(("tdomain", ", \""));
|
|
Packit |
fcad23 |
for (i = 0; d->prefix[i] != NULL; i++) {
|
|
Packit |
fcad23 |
DEBUGMSG(("tdomain", "%s%s", d->prefix[i],
|
|
Packit |
fcad23 |
(d->prefix[i + 1]) ? "/" : ""));
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
DEBUGMSG(("tdomain", "\" } -> "));
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
DEBUGMSG(("tdomain", "[NIL]\n"));
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
netsnmp_tdomain_register(netsnmp_tdomain *n)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
netsnmp_tdomain **prevNext = &domain_list, *d;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (n != NULL) {
|
|
Packit |
fcad23 |
for (d = domain_list; d != NULL; d = d->next) {
|
|
Packit |
fcad23 |
if (netsnmp_oid_equals(n->name, n->name_length,
|
|
Packit |
fcad23 |
d->name, d->name_length) == 0) {
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Already registered.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
prevNext = &(d->next);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
n->next = NULL;
|
|
Packit |
fcad23 |
*prevNext = n;
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_feature_child_of(tdomain_unregister, netsnmp_unused)
|
|
Packit |
fcad23 |
#ifndef NETSNMP_FEATURE_REMOVE_TDOMAIN_UNREGISTER
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
netsnmp_tdomain_unregister(netsnmp_tdomain *n)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
netsnmp_tdomain **prevNext = &domain_list, *d;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (n != NULL) {
|
|
Packit |
fcad23 |
for (d = domain_list; d != NULL; d = d->next) {
|
|
Packit |
fcad23 |
if (netsnmp_oid_equals(n->name, n->name_length,
|
|
Packit |
fcad23 |
d->name, d->name_length) == 0) {
|
|
Packit |
fcad23 |
*prevNext = n->next;
|
|
Packit |
fcad23 |
SNMP_FREE(n->prefix);
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
prevNext = &(d->next);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#endif /* NETSNMP_FEATURE_REMOVE_TDOMAIN_UNREGISTER */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static netsnmp_tdomain *
|
|
Packit |
fcad23 |
find_tdomain(const char* spec)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
netsnmp_tdomain *d;
|
|
Packit |
fcad23 |
for (d = domain_list; d != NULL; d = d->next) {
|
|
Packit |
fcad23 |
int i;
|
|
Packit |
fcad23 |
for (i = 0; d->prefix[i] != NULL; i++)
|
|
Packit |
fcad23 |
if (strcasecmp(d->prefix[i], spec) == 0) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("tdomain",
|
|
Packit |
fcad23 |
"Found domain \"%s\" from specifier \"%s\"\n",
|
|
Packit |
fcad23 |
d->prefix[0], spec));
|
|
Packit |
fcad23 |
return d;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
DEBUGMSGTL(("tdomain", "Found no domain from specifier \"%s\"\n", spec));
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static int
|
|
Packit |
fcad23 |
netsnmp_is_fqdn(const char *thename)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
if (!thename)
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
while(*thename) {
|
|
Packit |
fcad23 |
if (*thename != '.' && !isupper((unsigned char)*thename) &&
|
|
Packit |
fcad23 |
!islower((unsigned char)*thename) &&
|
|
Packit |
fcad23 |
!isdigit((unsigned char)*thename) && *thename != '-') {
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
thename++;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Locate the appropriate transport domain and call the create function for
|
|
Packit |
fcad23 |
* it.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
netsnmp_transport *
|
|
Packit |
fcad23 |
netsnmp_tdomain_transport_tspec(netsnmp_tdomain_spec *tspec)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
const char *application, *str, *default_domain, *default_target, *source;
|
|
Packit |
fcad23 |
int local;
|
|
Packit |
fcad23 |
netsnmp_tdomain *match = NULL;
|
|
Packit |
fcad23 |
const char *addr = NULL;
|
|
Packit |
fcad23 |
const char * const *spec = NULL;
|
|
Packit |
fcad23 |
int any_found = 0;
|
|
Packit |
fcad23 |
char buf[SNMP_MAXPATH];
|
|
Packit |
fcad23 |
char **lspec = NULL;
|
|
Packit |
fcad23 |
char *tokenized_domain = NULL;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
application = tspec->application;
|
|
Packit |
fcad23 |
str = tspec->target;
|
|
Packit |
fcad23 |
local = tspec->flags & NETSNMP_TSPEC_LOCAL;
|
|
Packit |
fcad23 |
default_domain = tspec->default_domain;
|
|
Packit |
fcad23 |
default_target = tspec->default_target;
|
|
Packit |
fcad23 |
source = tspec->source;
|
|
Packit |
fcad23 |
/** transport_config = tspec->transport_config; not used yet */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("tdomain",
|
|
Packit |
fcad23 |
"tdomain_transport_spec(\"%s\", \"%s\", %d, \"%s\", \"%s\", \"%s\")\n",
|
|
Packit |
fcad23 |
application, str ? str : "[NIL]", local,
|
|
Packit |
fcad23 |
default_domain ? default_domain : "[NIL]",
|
|
Packit |
fcad23 |
default_target ? default_target : "[NIL]",
|
|
Packit |
fcad23 |
source ? source : "[NIL]"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/* see if we can load a host-name specific set of conf files */
|
|
Packit |
fcad23 |
if (!netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
|
|
Packit |
fcad23 |
NETSNMP_DS_LIB_DONT_LOAD_HOST_FILES) &&
|
|
Packit |
fcad23 |
netsnmp_is_fqdn(str)) {
|
|
Packit |
fcad23 |
static int have_added_handler = 0;
|
|
Packit |
fcad23 |
char *newhost;
|
|
Packit |
fcad23 |
struct config_line *config_handlers;
|
|
Packit |
fcad23 |
struct config_files file_names;
|
|
Packit |
fcad23 |
char *prev_hostname;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/* register a "transport" specifier */
|
|
Packit |
fcad23 |
if (!have_added_handler) {
|
|
Packit |
fcad23 |
have_added_handler = 1;
|
|
Packit |
fcad23 |
netsnmp_ds_register_config(ASN_OCTET_STR,
|
|
Packit |
fcad23 |
"snmp", "transport",
|
|
Packit |
fcad23 |
NETSNMP_DS_LIBRARY_ID,
|
|
Packit |
fcad23 |
NETSNMP_DS_LIB_HOSTNAME);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/* we save on specific setting that we don't allow to change
|
|
Packit |
fcad23 |
from one transport creation to the next; ie, we don't want
|
|
Packit |
fcad23 |
the "transport" specifier to be a default. It should be a
|
|
Packit |
fcad23 |
single invocation use only */
|
|
Packit |
fcad23 |
prev_hostname = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
|
|
Packit |
fcad23 |
NETSNMP_DS_LIB_HOSTNAME);
|
|
Packit |
fcad23 |
if (prev_hostname)
|
|
Packit |
fcad23 |
prev_hostname = strdup(prev_hostname);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/* read in the hosts/STRING.conf files */
|
|
Packit |
fcad23 |
config_handlers = read_config_get_handlers("snmp");
|
|
Packit |
fcad23 |
snprintf(buf, sizeof(buf)-1, "hosts/%s", str);
|
|
Packit |
fcad23 |
file_names.fileHeader = buf;
|
|
Packit |
fcad23 |
file_names.start = config_handlers;
|
|
Packit |
fcad23 |
file_names.next = NULL;
|
|
Packit |
fcad23 |
DEBUGMSGTL(("tdomain", "checking for host specific config %s\n",
|
|
Packit |
fcad23 |
buf));
|
|
Packit |
fcad23 |
read_config_files_of_type(EITHER_CONFIG, &file_names);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (NULL !=
|
|
Packit |
fcad23 |
(newhost = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID,
|
|
Packit |
fcad23 |
NETSNMP_DS_LIB_HOSTNAME))) {
|
|
Packit |
fcad23 |
strlcpy(buf, newhost, sizeof(buf));
|
|
Packit |
fcad23 |
str = buf;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
|
|
Packit |
fcad23 |
NETSNMP_DS_LIB_HOSTNAME,
|
|
Packit |
fcad23 |
prev_hostname);
|
|
Packit |
fcad23 |
SNMP_FREE(prev_hostname);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/* First try - assume that there is a domain in str (domain:target) */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (str != NULL) {
|
|
Packit |
fcad23 |
const char *cp;
|
|
Packit |
fcad23 |
if ((cp = strchr(str, ':')) != NULL) {
|
|
Packit |
fcad23 |
char* mystring = (char*)malloc(cp + 1 - str);
|
|
Packit |
fcad23 |
memcpy(mystring, str, cp - str);
|
|
Packit |
fcad23 |
mystring[cp - str] = '\0';
|
|
Packit |
fcad23 |
addr = cp + 1;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
match = find_tdomain(mystring);
|
|
Packit |
fcad23 |
free(mystring);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Second try, if there is no domain in str (target), then try the
|
|
Packit |
fcad23 |
* default domain
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (match == NULL) {
|
|
Packit |
fcad23 |
addr = str;
|
|
Packit |
fcad23 |
if (addr && *addr == '/') {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("tdomain",
|
|
Packit |
fcad23 |
"Address starts with '/', so assume \"unix\" "
|
|
Packit |
fcad23 |
"domain\n"));
|
|
Packit |
fcad23 |
match = find_tdomain("unix");
|
|
Packit |
fcad23 |
} else if (default_domain) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("tdomain",
|
|
Packit |
fcad23 |
"Use user specified default domain \"%s\"\n",
|
|
Packit |
fcad23 |
default_domain));
|
|
Packit |
fcad23 |
if (!strchr(default_domain, ','))
|
|
Packit |
fcad23 |
match = find_tdomain(default_domain);
|
|
Packit |
fcad23 |
else {
|
|
Packit |
fcad23 |
int commas = 0;
|
|
Packit |
fcad23 |
const char *cp = default_domain;
|
|
Packit |
fcad23 |
char *ptr = NULL;
|
|
Packit |
fcad23 |
tokenized_domain = strdup(default_domain);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
while (*++cp) if (*cp == ',') commas++;
|
|
Packit |
fcad23 |
lspec = calloc(commas+2, sizeof(char *));
|
|
Packit |
fcad23 |
commas = 1;
|
|
Packit |
fcad23 |
lspec[0] = strtok_r(tokenized_domain, ",", &ptr);
|
|
Packit |
fcad23 |
while ((lspec[commas++] = strtok_r(NULL, ",", &ptr)))
|
|
Packit |
fcad23 |
;
|
|
Packit |
fcad23 |
spec = (const char * const *)lspec;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
spec = netsnmp_lookup_default_domains(application);
|
|
Packit |
fcad23 |
if (spec == NULL) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("tdomain",
|
|
Packit |
fcad23 |
"No default domain found, assume \"udp\"\n"));
|
|
Packit |
fcad23 |
match = find_tdomain("udp");
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
const char * const * r = spec;
|
|
Packit |
fcad23 |
DEBUGMSGTL(("tdomain",
|
|
Packit |
fcad23 |
"Use application default domains"));
|
|
Packit |
fcad23 |
while(*r) {
|
|
Packit |
fcad23 |
DEBUGMSG(("tdomain", " \"%s\"", *r));
|
|
Packit |
fcad23 |
++r;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
DEBUGMSG(("tdomain", "\n"));
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
for(;;) {
|
|
Packit |
fcad23 |
if (match) {
|
|
Packit |
fcad23 |
netsnmp_transport *t = NULL;
|
|
Packit |
fcad23 |
const char* addr2;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
any_found = 1;
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Ok, we know what domain to try, lets see what default data
|
|
Packit |
fcad23 |
* should be used with it
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
if (default_target != NULL)
|
|
Packit |
fcad23 |
addr2 = default_target;
|
|
Packit |
fcad23 |
else
|
|
Packit |
fcad23 |
addr2 = netsnmp_lookup_default_target(application,
|
|
Packit |
fcad23 |
match->prefix[0]);
|
|
Packit |
fcad23 |
DEBUGMSGTL(("tdomain",
|
|
Packit |
fcad23 |
"trying domain \"%s\" address \"%s\" "
|
|
Packit |
fcad23 |
"default address \"%s\"\n",
|
|
Packit |
fcad23 |
match->prefix[0], addr ? addr : "[NIL]",
|
|
Packit |
fcad23 |
addr2 ? addr2 : "[NIL]"));
|
|
Packit |
fcad23 |
if (match->f_create_from_tspec) {
|
|
Packit |
fcad23 |
netsnmp_tdomain_spec tspec_tmp;
|
|
Packit |
fcad23 |
memcpy(&tspec_tmp, tspec, sizeof(tspec_tmp));
|
|
Packit |
fcad23 |
/** if we didn't have a default target but looked one up,
|
|
Packit |
fcad23 |
* copy the spec and use the found default. */
|
|
Packit |
fcad23 |
if ((default_target == NULL) && (addr2 != NULL))
|
|
Packit |
fcad23 |
tspec_tmp.default_target = addr2;
|
|
Packit |
fcad23 |
if (addr != tspec_tmp.target)
|
|
Packit |
fcad23 |
tspec_tmp.target = addr;
|
|
Packit |
fcad23 |
t = match->f_create_from_tspec(&tspec_tmp);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
else {
|
|
Packit |
fcad23 |
#if 0 /** remove warning until all transports implement tspec */
|
|
Packit |
fcad23 |
NETSNMP_LOGONCE((LOG_WARNING,
|
|
Packit |
fcad23 |
"transport domain %s uses deprecated f_create function\n",
|
|
Packit |
fcad23 |
match->prefix[0]));
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
if (match->f_create_from_tstring) {
|
|
Packit |
fcad23 |
t = match->f_create_from_tstring(addr, local);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
else
|
|
Packit |
fcad23 |
t = match->f_create_from_tstring_new(addr, local, addr2);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
if (t) {
|
|
Packit |
fcad23 |
if (lspec) {
|
|
Packit |
fcad23 |
free(tokenized_domain);
|
|
Packit |
fcad23 |
free(lspec);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
return t;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
addr = str;
|
|
Packit |
fcad23 |
if (spec && *spec)
|
|
Packit |
fcad23 |
match = find_tdomain(*spec++);
|
|
Packit |
fcad23 |
else
|
|
Packit |
fcad23 |
break;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
if (!any_found)
|
|
Packit |
fcad23 |
snmp_log(LOG_ERR, "No support for any checked transport domain\n");
|
|
Packit |
fcad23 |
if (lspec) {
|
|
Packit |
fcad23 |
free(tokenized_domain);
|
|
Packit |
fcad23 |
free(lspec);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_transport *
|
|
Packit |
fcad23 |
netsnmp_tdomain_transport_full(const char *application,
|
|
Packit |
fcad23 |
const char *str, int local,
|
|
Packit |
fcad23 |
const char *default_domain,
|
|
Packit |
fcad23 |
const char *default_target)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
netsnmp_tdomain_spec tspec;
|
|
Packit |
fcad23 |
memset(&tspec, 0x0, sizeof(tspec));
|
|
Packit |
fcad23 |
tspec.application = application;
|
|
Packit |
fcad23 |
tspec.target = str;
|
|
Packit |
fcad23 |
if (local)
|
|
Packit |
fcad23 |
tspec.flags |= NETSNMP_TSPEC_LOCAL;
|
|
Packit |
fcad23 |
tspec.default_domain = default_domain;
|
|
Packit |
fcad23 |
tspec.default_target = default_target;
|
|
Packit |
fcad23 |
tspec.source = NULL;
|
|
Packit |
fcad23 |
tspec.transport_config = NULL;
|
|
Packit |
fcad23 |
return netsnmp_tdomain_transport_tspec(&tspec);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_transport *
|
|
Packit |
fcad23 |
netsnmp_tdomain_transport(const char *str, int local,
|
|
Packit |
fcad23 |
const char *default_domain)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
netsnmp_tdomain_spec tspec;
|
|
Packit |
fcad23 |
memset(&tspec, 0x0, sizeof(tspec));
|
|
Packit |
fcad23 |
tspec.application = "snmp";
|
|
Packit |
fcad23 |
tspec.target = str;
|
|
Packit |
fcad23 |
if (local)
|
|
Packit |
fcad23 |
tspec.flags |= NETSNMP_TSPEC_LOCAL;
|
|
Packit |
fcad23 |
tspec.default_domain = default_domain;
|
|
Packit |
fcad23 |
tspec.default_target = NULL;
|
|
Packit |
fcad23 |
tspec.source = NULL;
|
|
Packit |
fcad23 |
tspec.transport_config = NULL;
|
|
Packit |
fcad23 |
return netsnmp_tdomain_transport_tspec(&tspec);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifndef NETSNMP_FEATURE_REMOVE_TDOMAIN_TRANSPORT_OID
|
|
Packit |
fcad23 |
netsnmp_transport *
|
|
Packit |
fcad23 |
netsnmp_tdomain_transport_oid(const oid * dom,
|
|
Packit |
fcad23 |
size_t dom_len,
|
|
Packit |
fcad23 |
const u_char * o, size_t o_len, int local)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
netsnmp_tdomain *d;
|
|
Packit |
fcad23 |
int i;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("tdomain", "domain \""));
|
|
Packit |
fcad23 |
DEBUGMSGOID(("tdomain", dom, dom_len));
|
|
Packit |
fcad23 |
DEBUGMSG(("tdomain", "\"\n"));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
for (d = domain_list; d != NULL; d = d->next) {
|
|
Packit |
fcad23 |
for (i = 0; d->prefix[i] != NULL; i++) {
|
|
Packit |
fcad23 |
if (netsnmp_oid_equals(dom, dom_len, d->name, d->name_length) ==
|
|
Packit |
fcad23 |
0) {
|
|
Packit |
fcad23 |
return d->f_create_from_ostring(o, o_len, local);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
snmp_log(LOG_ERR, "No support for requested transport domain\n");
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#endif /* NETSNMP_FEATURE_REMOVE_TDOMAIN_TRANSPORT_OID */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_transport*
|
|
Packit |
fcad23 |
netsnmp_transport_open(const char* application, const char* str, int local)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
return netsnmp_tdomain_transport_full(application, str, local, NULL, NULL);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_transport*
|
|
Packit |
fcad23 |
netsnmp_transport_open_server(const char* application, const char* str)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
return netsnmp_tdomain_transport_full(application, str, 1, NULL, NULL);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_transport*
|
|
Packit |
fcad23 |
netsnmp_transport_open_client(const char* application, const char* str)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
return netsnmp_tdomain_transport_full(application, str, 0, NULL, NULL);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/** adds a transport to a linked list of transports.
|
|
Packit |
fcad23 |
Returns 1 on failure, 0 on success */
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
netsnmp_transport_add_to_list(netsnmp_transport_list **transport_list,
|
|
Packit |
fcad23 |
netsnmp_transport *transport)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
netsnmp_transport_list *newptr =
|
|
Packit |
fcad23 |
SNMP_MALLOC_TYPEDEF(netsnmp_transport_list);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!newptr)
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
newptr->next = *transport_list;
|
|
Packit |
fcad23 |
newptr->transport = transport;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
*transport_list = newptr;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/** removes a transport from a linked list of transports.
|
|
Packit |
fcad23 |
Returns 1 on failure, 0 on success */
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
netsnmp_transport_remove_from_list(netsnmp_transport_list **transport_list,
|
|
Packit |
fcad23 |
netsnmp_transport *transport)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
netsnmp_transport_list *ptr = *transport_list, *lastptr = NULL;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
while (ptr && ptr->transport != transport) {
|
|
Packit |
fcad23 |
lastptr = ptr;
|
|
Packit |
fcad23 |
ptr = ptr->next;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (!ptr)
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (lastptr)
|
|
Packit |
fcad23 |
lastptr->next = ptr->next;
|
|
Packit |
fcad23 |
else
|
|
Packit |
fcad23 |
*transport_list = ptr->next;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
SNMP_FREE(ptr);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
netsnmp_transport_config_compare(netsnmp_transport_config *left,
|
|
Packit |
fcad23 |
netsnmp_transport_config *right) {
|
|
Packit |
fcad23 |
return strcmp(left->key, right->key);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_transport_config *
|
|
Packit |
fcad23 |
netsnmp_transport_create_config(char *key, char *value) {
|
|
Packit |
fcad23 |
netsnmp_transport_config *entry =
|
|
Packit |
fcad23 |
SNMP_MALLOC_TYPEDEF(netsnmp_transport_config);
|
|
Packit |
fcad23 |
entry->key = strdup(key);
|
|
Packit |
fcad23 |
entry->value = strdup(value);
|
|
Packit |
fcad23 |
return entry;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifndef FEATURE_REMOVE_TRANSPORT_CACHE
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/* *************************************************************************
|
|
Packit |
fcad23 |
* transport caching by address family, type and use
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
typedef struct trans_cache_s {
|
|
Packit |
fcad23 |
netsnmp_transport *t;
|
|
Packit |
fcad23 |
int af;
|
|
Packit |
fcad23 |
int type;
|
|
Packit |
fcad23 |
int local;
|
|
Packit |
fcad23 |
netsnmp_sockaddr_storage bind_addr;
|
|
Packit |
fcad23 |
int count; /* number of times this transport has been returned */
|
|
Packit |
fcad23 |
} trans_cache;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static void _tc_free_item(trans_cache *tc, void *context);
|
|
Packit |
fcad23 |
static int _tc_compare(trans_cache *lhs, trans_cache *rhs);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/** initialize transport cache */
|
|
Packit |
fcad23 |
static int
|
|
Packit |
fcad23 |
_tc_init(void)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:cache:init", "%p\n", _container));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/** prevent double init */
|
|
Packit |
fcad23 |
if (NULL != _container)
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
_container = netsnmp_container_find("trans_cache:binary_array");
|
|
Packit |
fcad23 |
if (NULL == _container) {
|
|
Packit |
fcad23 |
snmp_log(LOG_ERR, "failed to allocate trans_cache container\n");
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
_container->container_name = strdup("trans_cache");
|
|
Packit |
fcad23 |
_container->free_item = (netsnmp_container_obj_func*) _tc_free_item;
|
|
Packit |
fcad23 |
_container->compare = (netsnmp_container_compare*) _tc_compare;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* container compare function
|
|
Packit |
fcad23 |
*
|
|
Packit |
fcad23 |
* sort by af, type, local
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
static int
|
|
Packit |
fcad23 |
_tc_compare(trans_cache *lhs, trans_cache *rhs)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
netsnmp_assert((lhs != NULL) && (rhs != NULL));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("9:transport:cache:compare", "%p/%p\n", lhs, rhs));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (lhs->af < rhs->af)
|
|
Packit |
fcad23 |
return -1;
|
|
Packit |
fcad23 |
else if (lhs->af > rhs->af)
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (lhs->type < rhs->type)
|
|
Packit |
fcad23 |
return -1;
|
|
Packit |
fcad23 |
else if (lhs->type > rhs->type)
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (lhs->local < rhs->local)
|
|
Packit |
fcad23 |
return -1;
|
|
Packit |
fcad23 |
else if (lhs->local > rhs->local)
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (AF_INET == lhs->af) {
|
|
Packit |
fcad23 |
struct sockaddr_in *lha = &lhs->bind_addr.sin,
|
|
Packit |
fcad23 |
*rha = &rhs->bind_addr.sin;
|
|
Packit |
fcad23 |
if (lha->sin_addr.s_addr < rha->sin_addr.s_addr)
|
|
Packit |
fcad23 |
return -1;
|
|
Packit |
fcad23 |
else if (lha->sin_addr.s_addr > rha->sin_addr.s_addr)
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (lha->sin_port < rha->sin_port)
|
|
Packit |
fcad23 |
return -1;
|
|
Packit |
fcad23 |
else if (lha->sin_port > rha->sin_port)
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#ifdef NETSNMP_ENABLE_IPV6
|
|
Packit |
fcad23 |
else if (AF_INET6 == lhs->af) {
|
|
Packit |
fcad23 |
struct sockaddr_in6 *lha = &lhs->bind_addr.sin6,
|
|
Packit |
fcad23 |
*rha = &rhs->bind_addr.sin6;
|
|
Packit |
fcad23 |
int rc = memcmp(lha->sin6_addr.s6_addr, rha->sin6_addr.s6_addr,
|
|
Packit |
fcad23 |
sizeof(rha->sin6_addr.s6_addr));
|
|
Packit |
fcad23 |
if (rc)
|
|
Packit |
fcad23 |
return rc;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (lha->sin6_port < rha->sin6_port)
|
|
Packit |
fcad23 |
return -1;
|
|
Packit |
fcad23 |
else if (lha->sin6_port > rha->sin6_port)
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (lha->sin6_flowinfo < rha->sin6_flowinfo)
|
|
Packit |
fcad23 |
return -1;
|
|
Packit |
fcad23 |
else if (lha->sin6_flowinfo > rha->sin6_flowinfo)
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (lha->sin6_scope_id < rha->sin6_scope_id)
|
|
Packit |
fcad23 |
return -1;
|
|
Packit |
fcad23 |
else if (lha->sin6_scope_id > rha->sin6_scope_id)
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static void
|
|
Packit |
fcad23 |
_tc_free(trans_cache *tc)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
if (NULL == tc)
|
|
Packit |
fcad23 |
return;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:cache:free", "%p %d/%d/%d/%p %d\n", tc, tc->af,
|
|
Packit |
fcad23 |
tc->type, tc->local, tc->t, tc->count));
|
|
Packit |
fcad23 |
netsnmp_transport_free(tc->t);
|
|
Packit |
fcad23 |
memset(tc, 0x0, sizeof(*tc));
|
|
Packit |
fcad23 |
free(tc);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static void
|
|
Packit |
fcad23 |
_tc_free_item(trans_cache *tc, void *context)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
_tc_free(tc);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static void
|
|
Packit |
fcad23 |
_tc_remove(trans_cache *tc)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
if (NULL == tc || NULL == _container)
|
|
Packit |
fcad23 |
return;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:cache:remove", "%p\n", tc));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
CONTAINER_REMOVE(_container, tc);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static trans_cache *
|
|
Packit |
fcad23 |
_tc_create(int af, int type, int local, const netsnmp_sockaddr_storage *addr,
|
|
Packit |
fcad23 |
netsnmp_transport *t)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
trans_cache *tc = SNMP_MALLOC_TYPEDEF(trans_cache);
|
|
Packit |
fcad23 |
if (NULL == tc) {
|
|
Packit |
fcad23 |
snmp_log(LOG_ERR, "failed to allocate trans_cache\n");
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:cache:create", "%p\n", tc));
|
|
Packit |
fcad23 |
tc->af = af;
|
|
Packit |
fcad23 |
tc->type = type;
|
|
Packit |
fcad23 |
tc->local = local;
|
|
Packit |
fcad23 |
tc->t = t;
|
|
Packit |
fcad23 |
if (addr)
|
|
Packit |
fcad23 |
memcpy(&tc->bind_addr, addr, sizeof(tc->bind_addr));
|
|
Packit |
fcad23 |
/** we only understand ipv6 and ipv6 sockaddrs in compare */
|
|
Packit |
fcad23 |
if (AF_INET != tc->af && AF_INET6 != tc->af)
|
|
Packit |
fcad23 |
NETSNMP_LOGONCE((LOG_WARNING, "transport cache not tested for af %d\n",
|
|
Packit |
fcad23 |
tc->af));
|
|
Packit |
fcad23 |
return tc;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static trans_cache *
|
|
Packit |
fcad23 |
_tc_add(int af, int type, int local, const netsnmp_sockaddr_storage *addr,
|
|
Packit |
fcad23 |
netsnmp_transport *t)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
trans_cache *tc;
|
|
Packit |
fcad23 |
int rc;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:cache:add", "%d/%d/%d/%p\n", af, type, local, t));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (NULL == _container) {
|
|
Packit |
fcad23 |
_tc_init();
|
|
Packit |
fcad23 |
if (NULL == _container)
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
tc = _tc_create(af, type, local, addr, t);
|
|
Packit |
fcad23 |
if (NULL == tc) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:cache:add",
|
|
Packit |
fcad23 |
"could not create transport cache\n"));
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
rc = CONTAINER_INSERT(_container, tc);
|
|
Packit |
fcad23 |
if (rc) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:cache:add", "container insert failed\n"));
|
|
Packit |
fcad23 |
_tc_free(tc);
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return tc;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
trans_cache *
|
|
Packit |
fcad23 |
_tc_find(int af, int type, int local, const netsnmp_sockaddr_storage *addr)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
trans_cache tc, *rtn;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:cache:find", "%d/%d/%d\n", af, type, local));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (NULL == _container)
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
memset(&tc, 0x00, sizeof(tc));
|
|
Packit |
fcad23 |
tc.af = af;
|
|
Packit |
fcad23 |
tc.type = type;
|
|
Packit |
fcad23 |
tc.local = local;
|
|
Packit |
fcad23 |
if (addr)
|
|
Packit |
fcad23 |
memcpy(&tc.bind_addr, addr, sizeof(tc.bind_addr));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
rtn = CONTAINER_FIND(_container, &tc);
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:cache:find", "%p\n", rtn));
|
|
Packit |
fcad23 |
return rtn;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
trans_cache *
|
|
Packit |
fcad23 |
_tc_find_transport(netsnmp_transport *t)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* we shouldn't really have that many transports, so instead of
|
|
Packit |
fcad23 |
* using an additional key, just iterate over the whole container.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
netsnmp_iterator *itr;
|
|
Packit |
fcad23 |
trans_cache *tc;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:cache:find_transport", "%p\n", t));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (NULL == _container)
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
itr = CONTAINER_ITERATOR(_container);
|
|
Packit |
fcad23 |
if (NULL == itr) {
|
|
Packit |
fcad23 |
snmp_log(LOG_ERR, "could not get iterator for transport cache\n");
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
tc = ITERATOR_FIRST(itr);
|
|
Packit |
fcad23 |
for( ; tc; tc = ITERATOR_NEXT(itr))
|
|
Packit |
fcad23 |
if (tc->t == t)
|
|
Packit |
fcad23 |
break;
|
|
Packit |
fcad23 |
ITERATOR_RELEASE(itr);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGT(("transport:cache:find_transport","found %p\n", tc));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return tc;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
netsnmp_transport_cache_remove(netsnmp_transport *t)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
trans_cache *tc;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:cache:close", "%p\n", t));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (NULL == t)
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/** transport in cache? */
|
|
Packit |
fcad23 |
tc = _tc_find_transport(t);
|
|
Packit |
fcad23 |
if (NULL == tc) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:cache:close", "%p not found in cache\n", t));
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
--tc->count;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/** still in use? */
|
|
Packit |
fcad23 |
if (tc->count > 0) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:cache:close", "still %d user(s) of %p\n",
|
|
Packit |
fcad23 |
tc->count, t));
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/** unbalanced get/close? */
|
|
Packit |
fcad23 |
if (tc->count < 0)
|
|
Packit |
fcad23 |
snmp_log(LOG_WARNING, "transport cache get/close mismatch\n");
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
_tc_remove(tc);
|
|
Packit |
fcad23 |
_tc_free(tc); /* also does close */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* netsnmp_transport_get: get a (possibly duplicate, cached) transport
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
netsnmp_transport *
|
|
Packit |
fcad23 |
netsnmp_transport_cache_get(int af, int type, int local,
|
|
Packit |
fcad23 |
const netsnmp_sockaddr_storage *bind_addr)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
trans_cache *tc;
|
|
Packit |
fcad23 |
netsnmp_transport *t;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:cache:get", "%d/%d/%d\n", af, type, local));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#define USE_CACHE 1
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#if USE_CACHE
|
|
Packit |
fcad23 |
/** check for existing transport */
|
|
Packit |
fcad23 |
tc = _tc_find(af, type, local, bind_addr);
|
|
Packit |
fcad23 |
if (tc) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:cache:get", "using existing transport %p\n",
|
|
Packit |
fcad23 |
tc->t));
|
|
Packit |
fcad23 |
++tc->count;
|
|
Packit |
fcad23 |
return tc->t;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
/** get transport */
|
|
Packit |
fcad23 |
t = NULL; /* _transport(af, type, 0);*/
|
|
Packit |
fcad23 |
if (NULL == t) {
|
|
Packit |
fcad23 |
snmp_log(LOG_ERR, "could not get new transport for %d/%d/%d\n", af,
|
|
Packit |
fcad23 |
type, local);
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:cache:get", "new transport %p\n", t));
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#if USE_CACHE
|
|
Packit |
fcad23 |
/** create transport cache for new transport */
|
|
Packit |
fcad23 |
tc = _tc_add(af, type, local, bind_addr, t);
|
|
Packit |
fcad23 |
if (NULL == tc) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("transport:cache:get", "could not create transport cache\n"));
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* hmmm.. this isn't really a critical error, is it? We have a
|
|
Packit |
fcad23 |
* transport, just no cache for it. Let's continue on and hope for the
|
|
Packit |
fcad23 |
* best.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
/** return -1; */
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
tc->count = 1;
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return t;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
int
|
|
Packit |
fcad23 |
netsnmp_transport_cache_save(int af, int type, int local,
|
|
Packit |
fcad23 |
const netsnmp_sockaddr_storage *addr,
|
|
Packit |
fcad23 |
netsnmp_transport *t)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
if (NULL == t)
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (NULL == _tc_add(af, type, local, addr, t))
|
|
Packit |
fcad23 |
return 1;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
#endif /* FEATURE_REMOVE_TRANSPORT_CACHE */
|