File net-snmp-5.3.0.1_trap-agent-addr_v2.patch of Package net-snmp

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();
+       }
     }
 
 
openSUSE Build Service is sponsored by