net-snmp/net-snmp-5.3.0.1_trap-agent-addr_v2.patch

207 lines
7.4 KiB
Diff

426355: Cannot set source agent address for SNMP traps
Author: Jan Safranek <jsafrane@redhat.com>
Introduce "v1trapaddress" snmpd config option, which defines agent address
set in SNMPv1 traps, i.e. inside the SNMPv1 TRAP-PDU, not UDP packet
source address. The agent sets arbitrary local address to the TRAP PDU
when this option is ommited.
Index: snmplib/system.c
===================================================================
--- snmplib/system.c.orig 2008-06-05 23:11:53.000000000 +0200
+++ snmplib/system.c 2008-09-06 18:04:38.784302537 +0200
@@ -77,6 +77,10 @@ SOFTWARE.
#if HAVE_NET_IF_H
#include <net/if.h>
#endif
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
#if HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
@@ -825,6 +829,84 @@ get_uptime(void)
#endif /* ! WIN32 */
/*******************************************************************/
+int
+get_thisaddr(const char* name, in_addr_t *addr_out)
+{
+
+#if HAVE_GETADDRINFO
+ struct addrinfo *addrs = NULL;
+ struct addrinfo hint;
+ int err;
+
+ memset(&hint, 0, sizeof hint);
+ hint.ai_flags = 0;
+ hint.ai_family = PF_INET;
+ hint.ai_socktype = SOCK_DGRAM;
+ hint.ai_protocol = 0;
+
+ err = getaddrinfo(name, NULL, &hint, &addrs);
+ if (err != 0) {
+#if HAVE_GAI_STRERROR
+ snmp_log(LOG_ERR, "getaddrinfo: %s %s\n", name,
+ gai_strerror(err));
+#else
+ snmp_log(LOG_ERR, "getaddrinfo: %s (error %d)\n", name,
+ err);
+#endif
+ return -1;
+ }
+ if (addrs != NULL) {
+ memcpy(addr_out,
+ &((struct sockaddr_in *) addrs->ai_addr)->sin_addr,
+ sizeof(in_addr_t));
+ freeaddrinfo(addrs);
+ } else {
+ DEBUGMSGTL(("get_thisaddr",
+ "Failed to resolve IPv4 hostname\n"));
+ }
+ return 0;
+
+#elif HAVE_GETHOSTBYNAME
+ struct hostent *hp = NULL;
+
+ hp = gethostbyname(host);
+ if (hp == NULL) {
+ DEBUGMSGTL(("get_thisaddr",
+ "hostname (couldn't resolve)\n"));
+ return -1;
+ } else if (hp->h_addrtype != AF_INET) {
+ DEBUGMSGTL(("get_thisaddr",
+ "hostname (not AF_INET!)\n"));
+ return -1;
+ } else {
+ DEBUGMSGTL(("get_thisaddr",
+ "hostname (resolved okay)\n"));
+ memcpy(addr_out, hp->h_addr, sizeof(in_addr_t));
+ }
+ return 0;
+
+#elif HAVE_GETIPNODEBYNAME
+ struct hostent *hp = NULL;
+ int err;
+
+ hp = getipnodebyname(peername, AF_INET, 0, &err);
+ if (hp == NULL) {
+ DEBUGMSGTL(("get_thisaddr",
+ "hostname (couldn't resolve = %d)\n", err));
+ return -1;
+ }
+ DEBUGMSGTL(("get_thisaddr",
+ "hostname (resolved okay)\n"));
+ memcpy(addr_out, hp->h_addr, sizeof(in_addr_t));
+ return 0;
+
+#else /* HAVE_GETIPNODEBYNAME */
+ return -1;
+#endif
+}
+
+/*******************************************************************/
+
#ifndef HAVE_STRNCASECMP
/*
Index: man/snmpd.conf.5.def
===================================================================
--- man/snmpd.conf.5.def.orig 2008-08-07 11:00:04.000000000 +0200
+++ man/snmpd.conf.5.def 2008-09-06 18:04:38.788301614 +0200
@@ -641,6 +641,12 @@ Ordinarily the corresponding MIB
object (\fCsnmpEnableAuthenTraps.0\fR) is read-write, but specifying
this directive makes this object read-only, and attempts to set the
value via SET requests will result in a \fInotWritable\fR error response.
+.RE
+.IP "v1trapaddress HOST"
+defines the agent address, which is inserted into SNMPv1 TRAPs. Arbitrary local
+IPv4 address is chosen if this option is ommited. This option is useful mainly
+when the agent is visible from outside world by specific address only (e.g.
+because of network address translation or firewall).
.SS "DisMan Event MIB"
The previous directives can be used to configure where traps should
be sent, but are not concerned with \fIwhen\fR to send such traps
Index: include/net-snmp/agent/ds_agent.h
===================================================================
--- include/net-snmp/agent/ds_agent.h.orig 2007-05-07 22:23:23.000000000 +0200
+++ include/net-snmp/agent/ds_agent.h 2008-09-06 18:04:38.823792310 +0200
@@ -42,6 +42,7 @@
#define NETSNMP_DS_AGENT_PERL_INIT_FILE 4 /* used by embedded perl */
#define NETSNMP_DS_SMUX_SOCKET 5 /* ip:port socket addr */
#define NETSNMP_DS_NOTIF_LOG_CTX 6 /* "" | "snmptrapd" */
+#define NETSNMP_DS_AGENT_TRAP_ADDR 7 /* used as v1 trap agent addres */
/*
* integers
Index: include/net-snmp/library/system.h
===================================================================
--- include/net-snmp/library/system.h.orig 2007-01-11 23:13:56.000000000 +0100
+++ include/net-snmp/library/system.h 2008-09-06 18:04:38.855791728 +0200
@@ -107,6 +107,8 @@ SOFTWARE.
#include <net-snmp/types.h> /* For definition of in_addr_t */
+ int get_thisaddr(const char* name,
+ in_addr_t *addr_out);
in_addr_t get_myaddr(void);
long get_uptime(void);
Index: agent/agent_read_config.c
===================================================================
--- agent/agent_read_config.c.orig 2008-07-24 08:53:02.000000000 +0200
+++ agent/agent_read_config.c 2008-09-06 18:04:38.880308775 +0200
@@ -243,6 +243,9 @@ init_agent_read_config(const char *app)
snmpd_free_trapcommunity,
"community-string");
#endif /* support for community based SNMP */
+ netsnmp_ds_register_config(ASN_OCTET_STR, app, "v1trapaddress",
+ NETSNMP_DS_APPLICATION_ID,
+ NETSNMP_DS_AGENT_TRAP_ADDR);
#ifdef HAVE_UNISTD_H
register_app_config_handler("agentuser",
snmpd_set_agent_user, NULL, "userid");
Index: agent/agent_trap.c
===================================================================
--- agent/agent_trap.c.orig 2007-05-18 00:16:12.000000000 +0200
+++ agent/agent_trap.c 2008-09-06 18:06:23.367792400 +0200
@@ -58,6 +58,7 @@
#include <net-snmp/utilities.h>
#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
#include <net-snmp/agent/agent_trap.h>
#include <net-snmp/agent/snmp_agent.h>
#include <net-snmp/agent/agent_callbacks.h>
@@ -639,6 +640,8 @@ netsnmp_send_traps(int trap, int specifi
in_addr_t *pdu_in_addr_t;
u_long uptime;
struct trap_sink *sink;
+ const char *v1trapaddress;
+ int res;
DEBUGMSGTL(( "trap", "send_trap %d %d ", trap, specific));
DEBUGMSGOID(("trap", enterprise, enterprise_length));
@@ -792,7 +795,18 @@ netsnmp_send_traps(int trap, int specifi
* Ensure that the v1 trap PDU includes the local IP address
*/
pdu_in_addr_t = (in_addr_t *) template_v1pdu->agent_addr;
- *pdu_in_addr_t = get_myaddr();
+
+ v1trapaddress = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
+ NETSNMP_DS_AGENT_TRAP_ADDR);
+ if (v1trapaddress != NULL) {
+ /* "v1trapaddress" was specified in config, try to resolve it */
+ res = get_thisaddr(v1trapaddress, pdu_in_addr_t);
+ }
+ if (v1trapaddress == NULL || res < 0) {
+ /* "v1trapaddress" was not specified in config or the resolution failed,
+ * try any local address */
+ *pdu_in_addr_t = get_myaddr();
+ }
}