Greetings SNMP coders and users,
Every once in a while someone complains about having to wait for the 60 second
timer to elapse before getting their 'linkUpDownNotifications'. The attached
patch causes snmpd to register with the linux RT-NETLINK facility in order to
be notified of link state changes. IP interfaces going up and down now generate
traps immediately.
The linkUpDownNotifications snmpd.conf directive has been changed to use
rt-netlink instead of the 60s timer, and a "-n" option has been added to the
monitor directive in order to trigger it using netlink instead of a timed poll.
The ifTable cache reload has also been changed to trigger on netlink message
reception in addition to its own 30s timer.
Note that the netlink trigger method has not been generalized, and registers
only for IP interface link activity.
Rate limiting:
A configuration directive was added to snmpd.conf to control the frequency with
which link up down traps are generated.
"netlinkTiggerRes <timeout in milliseconds>" default = 5000ms
(Netlink trigger resolution) specifies the minimum time allowed between
consecutive link state traps for a single IP interface. For example, if a link
changes state at t=0, a trap is generated immediately. If the same link changes
state at t=1000ms, this is less than the trigger resolution of 5000 ms, and
therefore a trap will not be generated. An event will, however, be scheduled
for 5000-1000ms = 4000ms in the future, that will check link state and send
traps if link states have changed since the last link state traps were transmitted.
If, instead of the same IP Link changing state, a different link changes state
at t=1000ms, the timeout restriction would not apply, and a trap would be
generated immediately.
My apologies ahead of time for the vintage of net-snmp that I've applied this
to. The patch is relatively small, and should hopefully be easily adaptable to
more recent versions.
Michael Leslie
--
RuggedCom Inc.
www.ruggedcom.com
Telephone: (905) 856-5288
Toll Free: 1-888-264-0006
************************
NOTICE OF CONFIDENTIALITY:
This e-mail and any attachments may contain confidential and privileged
information. If you are not the intended recipient, please notify the sender
immediately by return e-mail and delete this e-mail and any copies. Any
dissemination or use of this information by a person other than the intended
recipient is unauthorized and may be illegal.
************************
diff -Nur net-snmp-5.2.3.rr1/agent/helpers/cache_handler.c net-snmp-5.2.3.rr1.new/agent/helpers/cache_handler.c
--- net-snmp-5.2.3.rr1/agent/helpers/cache_handler.c 2006-01-25 11:28:10.000000000 -0500
+++ net-snmp-5.2.3.rr1.new/agent/helpers/cache_handler.c 2007-05-16 10:49:31.000000000 -0400
@@ -15,6 +15,10 @@
#include <dmalloc.h>
#endif
+#if HAVE_LINUX_RTNETLINK_H
+#include <mibgroup/disman/rtnetlinkTrigger.h>
+#endif
+
static netsnmp_cache *cache_head = NULL;
static int cache_outstanding_valid = 0;
static int _cache_load( netsnmp_cache *cache );
@@ -208,6 +212,10 @@
return 0;
}
+#if HAVE_LINUX_RTNETLINK_H
+ if (cache->flags & NETSNMP_CACHE_NETLINK_TRIGGER)
+ netlink_trigger_register_before(_timer_reload, cache);
+#endif
cache->timer_id = snmp_alarm_register(cache->timeout, SA_REPEAT,
_timer_reload, cache);
if(0 == cache->timer_id) {
diff -Nur net-snmp-5.2.3.rr1/agent/mibgroup/disman/event-mib.h net-snmp-5.2.3.rr1.new/agent/mibgroup/disman/event-mib.h
--- net-snmp-5.2.3.rr1/agent/mibgroup/disman/event-mib.h 2002-12-04 19:32:52.000000000 -0500
+++ net-snmp-5.2.3.rr1.new/agent/mibgroup/disman/event-mib.h 2007-05-16 10:49:44.000000000 -0400
@@ -9,4 +9,5 @@
config_require(disman/mteObjectsTable)
config_require(disman/mteEventTable)
config_require(disman/mteEventNotificationTable)
+config_require(disman/rtnetlinkTrigger)
config_add_mib(DISMAN-EVENT-MIB)
diff -Nur net-snmp-5.2.3.rr1/agent/mibgroup/disman/mteEventTable.c net-snmp-5.2.3.rr1.new/agent/mibgroup/disman/mteEventTable.c
--- net-snmp-5.2.3.rr1/agent/mibgroup/disman/mteEventTable.c 2004-01-27 12:41:44.000000000 -0500
+++ net-snmp-5.2.3.rr1.new/agent/mibgroup/disman/mteEventTable.c 2007-05-16 10:50:01.000000000 -0400
@@ -116,11 +116,26 @@
void
parse_linkUpDownNotifications(const char *token, char *line) {
if (strncmp(line, "y", 1) == 0) {
+
+ parse_notificationEvent("notificationEvent",
+ "linkUpTrap linkUp ifIndex ifAdminStatus ifOperStatus");
+ parse_notificationEvent("notificationEvent",
+ "linkDownTrap linkDown ifIndex ifAdminStatus ifOperStatus");
+
+ /* New netlink triggered method */
+ parse_simple_monitor("monitor",
+ "-n -e linkUpTrap \"Generate linkUp\" ifOperStatus != 2");
+ parse_simple_monitor("monitor",
+ "-n -e linkDownTrap \"Generate linkDown\" ifOperStatus == 2");
+
+ } else if (strncmp(line, "old", 3) == 0) {
+
parse_notificationEvent("notificationEvent", "linkUpTrap linkUp ifIndex ifAdminStatus ifOperStatus");
parse_notificationEvent("notificationEvent", "linkDownTrap linkDown ifIndex ifAdminStatus ifOperStatus");
parse_simple_monitor("monitor", "-r 60 -e linkUpTrap \"Generate linkUp\" ifOperStatus != 2");
parse_simple_monitor("monitor", "-r 60 -e linkDownTrap \"Generate linkDown\" ifOperStatus == 2");
+
}
}
diff -Nur net-snmp-5.2.3.rr1/agent/mibgroup/disman/mteTriggerTable.c net-snmp-5.2.3.rr1.new/agent/mibgroup/disman/mteTriggerTable.c
--- net-snmp-5.2.3.rr1/agent/mibgroup/disman/mteTriggerTable.c 2006-01-30 04:28:05.000000000 -0500
+++ net-snmp-5.2.3.rr1.new/agent/mibgroup/disman/mteTriggerTable.c 2007-05-16 10:50:21.000000000 -0400
@@ -36,6 +36,10 @@
#include "mteEventTable.h"
#include "mteObjectsTable.h"
+#if HAVE_LINUX_RTNETLINK_H
+#include "rtnetlinkTrigger.h"
+#endif
+
/*
* mteTriggerTable_variables_oid:
* this is the top level oid that we want to register under. This
@@ -427,6 +431,13 @@
return;
}
break;
+#if HAVE_LINUX_RTNETLINK_H
+ case 'n':
+ /* Use Netlink to trigger this event */
+ StorageNew->mteTriggerNetlink = 1;
+ StorageNew->mteTriggerFrequency = 0;
+ break;
+#endif
case 'u':
if (cp) {
cp = copy_nword(cp, buf, sizeof(buf));
@@ -3295,7 +3306,7 @@
snmp_alarm_unregister(clientreg);
return;
}
- DEBUGMSGTL(("mteTriggertable", "Running trigger for %s/%s\n",
+ DEBUGMSGTL(("mteTriggerTable", "Running trigger for %s/%s\n",
item->mteOwner, item->mteTriggerName));
next_oid = item->mteTriggerValueID;
@@ -3692,8 +3703,14 @@
if (item->alarmreg)
snmp_alarm_unregister(item->alarmreg);
+ if (item->mteTriggerNetlink) {
+ DEBUGMSGTL(("mteTriggerTable", "Enabling netlink trigger for %s/%s\n",
+ item->mteOwner, item->mteTriggerName));
+ netlink_trigger_register (mte_run_trigger, item);
+ }
+
if (item->mteTriggerFrequency > 0) {
- DEBUGMSGTL(("mteTriggertable", "Enabling trigger for %s/%s @ %u\n",
+ DEBUGMSGTL(("mteTriggerTable", "Enabling trigger for %s/%s @ %u\n",
item->mteOwner, item->mteTriggerName,
item->mteTriggerFrequency));
item->alarmreg =
@@ -3709,7 +3726,7 @@
return;
if (item->alarmreg) {
- DEBUGMSGTL(("mteTriggertable", "Disabling trigger for %s/%s\n",
+ DEBUGMSGTL(("mteTriggerTable", "Disabling trigger for %s/%s\n",
item->mteOwner, item->mteTriggerName));
snmp_alarm_unregister(item->alarmreg);
item->alarmreg = 0;
diff -Nur net-snmp-5.2.3.rr1/agent/mibgroup/disman/mteTriggerTable.h net-snmp-5.2.3.rr1.new/agent/mibgroup/disman/mteTriggerTable.h
--- net-snmp-5.2.3.rr1/agent/mibgroup/disman/mteTriggerTable.h 2002-12-16 17:42:14.000000000 -0500
+++ net-snmp-5.2.3.rr1.new/agent/mibgroup/disman/mteTriggerTable.h 2007-05-16 10:50:30.000000000 -0400
@@ -38,6 +38,7 @@
char *mteTriggerContextName;
size_t mteTriggerContextNameLen;
long mteTriggerContextNameWildcard;
+ long mteTriggerNetlink;
unsigned long mteTriggerFrequency;
char *mteTriggerObjectsOwner;
size_t mteTriggerObjectsOwnerLen;
diff -Nur net-snmp-5.2.3.rr1/agent/mibgroup/disman/rtnetlinkTrigger.c net-snmp-5.2.3.rr1.new/agent/mibgroup/disman/rtnetlinkTrigger.c
--- net-snmp-5.2.3.rr1/agent/mibgroup/disman/rtnetlinkTrigger.c 1969-12-31 19:00:00.000000000 -0500
+++ net-snmp-5.2.3.rr1.new/agent/mibgroup/disman/rtnetlinkTrigger.c 2007-05-16 10:50:37.000000000 -0400
@@ -0,0 +1,490 @@
+/*
+ * rtnetlink.c
+ */
+/*
+ * rtnetlink.c provides support for the linux NETLINK mechanism
+ * for immediate triggering upon network interface link status change
+ */
+/*
+ * Copyright Ruggedcom, 2007 - Michael Leslie
+ */
+
+
+
+/**** Necessary includes: ***************************************************/
+
+/* #include <stdio.h> */
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include <sys/time.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+
+
+#define RTNETLINK_DECLS
+#include "rtnetlinkTrigger.h"
+
+/* for print_if_flags(): */
+#if defined(NETLINK_DEBUG)
+# include <net/if.h>
+#endif
+
+/* #include <net-snmp/library/snmp_logging.h> */
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+#include <net-snmp/agent/net-snmp-agent-includes.h>
+
+#include <net-snmp/library/snmp_alarm.h>
+
+
+/****************************************************************************/
+
+/**** local declarations: ****/
+
+int err;
+
+struct sockaddr_nl socket_address;
+
+#if defined(NETLINK_DEBUG)
+void print_if_flags(unsigned int flags);
+void dump_msghdr(struct msghdr *msghdr);
+#endif
+
+
+/* rate limiting declarations: */
+#define DEFAULT_NETLINK_TRIGGER_RESOLUTION 5000 /* milliseconds */
+int netlinkTriggerResolution = DEFAULT_NETLINK_TRIGGER_RESOLUTION;
+int timeval_exceeds_by (struct timeval *later,
+ struct timeval *earlier, int delta);
+void parse_netlinkTriggerRes(const char *token, char *line);
+
+
+/* trigger_history: */
+int last_trigger_if_index;
+struct timeval last_trigger_time;
+
+static int snmp_alarm_registration = 0;
+
+static int netlink_timer_expired (void);
+static int trigger_reenable_seconds (void);
+
+static void run_netlink_trigger_list(unsigned int unused_reg, void *unused_arg);
+
+
+/****************************************************************************/
+
+/*
+ * void init_rtnetlink(void)
+ *
+ * connects to the kernel NETLINK socket to subscribe
+ * to NETLINK_ROUTE messages. Sets rtnetlink_fd and
+ * returns zero on success.
+ */
+void
+init_rtnetlinkTrigger()
+{
+ int fd;
+
+ fd = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+ if (fd < 0) {
+ snmp_log_perror ("Error opening netlink socket");
+ return;
+ }
+
+ socket_address.nl_family = AF_NETLINK;
+ socket_address.nl_pid = getpid();
+ socket_address.nl_groups = RTMGRP_LINK;
+
+ if (bind (fd, (struct sockaddr *)&socket_address,
+ sizeof (socket_address)) != 0) {
+ snmp_log_perror ("Error binding to netlink socket");
+ return;
+ }
+ rtnetlink_fd = fd;
+
+ snmpd_register_config_handler("netlinkTiggerRes",
+ parse_netlinkTriggerRes, NULL,
+ "netlinkTiggerRes (netlink trigger resolution in ms)");
+}
+
+void
+parse_netlinkTriggerRes(const char *token, char *line) {
+ int n;
+
+ n = sscanf (line, "%d", &netlinkTriggerResolution);
+
+ if (n < 1)
+ DEBUGMSGTL(("rtnetlink_trigger",
+ "failed to parse trigger resolution from: \"%s\"\n", line));
+
+}
+
+static unsigned int regnum = 1;
+static struct rtnetlink_trigger *rtnetlink_trigger_list = NULL;
+
+/*
+ * unsigned int netlink_trigger_register()
+ *
+ * adds a callback / void *argument to the (end of the) netlink
+ * trigger table.
+ */
+unsigned int
+netlink_trigger_register (rtnetlinkCallback *callback, void *clientarg)
+{
+ struct rtnetlink_trigger **nt_pptr;
+
+ if (rtnetlink_trigger_list != NULL) {
+ for (nt_pptr = &rtnetlink_trigger_list; (*nt_pptr) != NULL;
+ nt_pptr = &((*nt_pptr)->next));
+ } else {
+ nt_pptr = &rtnetlink_trigger_list;
+ }
+
+ *nt_pptr = SNMP_MALLOC_STRUCT(rtnetlink_trigger);
+ if (*nt_pptr == NULL)
+ return 0;
+
+ (*nt_pptr)->clientarg = clientarg;
+ (*nt_pptr)->callback = callback;
+ (*nt_pptr)->clientreg = regnum++;
+ (*nt_pptr)->next = NULL;
+
+ DEBUGMSGTL(("rtnetlink_trigger",
+ "registered rtnetlink trigger %d\n", (*nt_pptr)->clientreg));
+
+ return (*nt_pptr)->clientreg;
+}
+
+
+/*
+ * unsigned int netlink_trigger_register_before()
+ *
+ * adds a callback / void *argument to the (beginning of the) netlink
+ * trigger table.
+ */
+unsigned int
+netlink_trigger_register_before (rtnetlinkCallback *callback, void *clientarg)
+{
+ struct rtnetlink_trigger *nt_pptr;
+
+ nt_pptr = SNMP_MALLOC_STRUCT(rtnetlink_trigger);
+ if (nt_pptr == NULL)
+ return 0;
+
+ if (rtnetlink_trigger_list != NULL) {
+ nt_pptr->next = rtnetlink_trigger_list;
+ rtnetlink_trigger_list = nt_pptr;
+ } else {
+ rtnetlink_trigger_list = nt_pptr;
+ nt_pptr->next = NULL;
+ }
+
+ nt_pptr->clientarg = clientarg;
+ nt_pptr->callback = callback;
+ nt_pptr->clientreg = regnum++;
+
+ DEBUGMSGTL(("rtnetlink_trigger",
+ "registered rtnetlink trigger %d\n", nt_pptr->clientreg));
+
+ return nt_pptr->clientreg;
+}
+
+
+
+void run_netlink_triggers(int fd)
+{
+ struct trigger_history *trig_hist;
+ int if_index;
+ struct timeval now;
+
+ /* FOR NOW we do not use the data in the netlink message itself
+ * to update the data in the MIB. It is only used as an alternative
+ * trigger to the existing timeout-based alarm system.
+ *
+ * An intermediate enhancement might be to register different triggers
+ * based on different OIDs => different RTNETLINK groups, => different
+ * rtnetlink file descriptors.
+ *
+ * Ultimately, we should also parse the desired data from the netlink
+ * communication, update the MIB, and continue along with notification
+ * processing directly.
+ *
+ * Simply dequeue the netlink message, saving only the interface index:
+ */
+ if_index = read_netlink_message (fd);
+
+ if (rtnetlink_trigger_list == NULL)
+ return;
+
+ if (if_index == -1)
+ /* failed to parse interface index from netlink message
+ * abort cache refresh and trap generation */
+ return;
+
+ if (if_index == last_trigger_if_index) {
+ if (!netlink_timer_expired()) {
+ /* Schedule a netlink trigger after expiry. Note that there will
+ * be no corresponding netlink message receipt at that time.
+ */
+ DEBUGMSGTL(("rtnetlink_trigger", "netlink timer pending.\n"));
+
+ if (trig_hist && !snmp_alarm_registration) {
+ unsigned int when;
+
+ when = trigger_reenable_seconds ();
+ DEBUGMSGTL(("rtnetlink_trigger",
+ "register alarm in %d seconds.\n", when));
+ snmp_alarm_registration =
+ snmp_alarm_register (when, 0, run_netlink_trigger_list, NULL);
+ }
+ return;
+ }
+ }
+
+ gettimeofday (&now, NULL);
+ memcpy (&last_trigger_time, &now, sizeof (struct timeval));
+ last_trigger_if_index = if_index;
+ run_netlink_trigger_list(0, NULL);
+}
+
+
+/*
+ * Run through and call the list of netlink triggered functions.
+ * The arguments are only there in order to satisfy the ability to
+ * register the function with snmp_alarm_register()
+ */
+static void
+run_netlink_trigger_list(unsigned int unused_reg, void *unused_arg)
+{
+ struct rtnetlink_trigger *trig = NULL;
+ unsigned int clientreg;
+
+ snmp_alarm_registration = 0;
+ for (trig = rtnetlink_trigger_list; trig != NULL; trig = trig->next) {
+ clientreg = trig->clientreg;
+ DEBUGMSGTL(("rtnetlink_trigger", "run trigger %d\n", clientreg));
+ if (trig->callback != NULL)
+ (*(trig->callback)) (trig->clientreg, trig->clientarg);
+ DEBUGMSGTL(("rtnetlink_trigger", "trigger %d completed\n", clientreg));
+ }
+}
+
+
+
+
+/*
+ * int netlink_timer_expired ()
+ *
+ * checks the previous trigger time, 'last_trigger_time'
+ * to see whether the allowed time (netlinkTriggerResolution)
+ * has elapsed, in which case it returns 1.
+ *
+ */
+static int netlink_timer_expired (void)
+{
+ struct timeval trigger_time;
+
+ if (netlinkTriggerResolution <= 10 /* ms */)
+ return 1;
+
+ gettimeofday (&trigger_time, NULL);
+
+ if (timeval_exceeds_by (&trigger_time, &last_trigger_time,
+ netlinkTriggerResolution)) {
+ memcpy (&last_trigger_time, &trigger_time, sizeof (struct timeval));
+ return (1);
+ }
+
+ /* otherwise, the required time has not yet elapsed */
+ return (0);
+}
+
+
+
+
+/* Return 1 if 'later' exceeds 'earlier' by 'delta' milliseconds or more */
+int timeval_exceeds_by (struct timeval *later,
+ struct timeval *earlier, int delta)
+{
+ int delta_s, delta_us;
+
+ if (timercmp(earlier, later, >))
+ return 0;
+
+ delta_s = later->tv_sec - earlier->tv_sec;
+ delta_us = later->tv_usec - earlier->tv_usec;
+
+ /* to remove doubt and complication, 'normalize' the delta: */
+ if (delta_us > 1000000) {
+ delta_s += (delta_us / 1000000);
+ delta_us = (delta_us % 1000000);
+ }
+
+ if (delta_s > (delta / 1000))
+ return (1);
+
+ if ((delta_s * 1000) + (delta_us / 1000) > delta)
+ return (1);
+
+ return (0);
+}
+
+
+/* Return the number of seconds till the interface trigger will
+ * be reenabled. Used to schedule a snmp_alarm
+ */
+int trigger_reenable_seconds ()
+{
+ struct timeval now, *last;
+ int delta; /* in seconds */
+
+ gettimeofday (&now, NULL);
+
+ last = &last_trigger_time;
+
+ delta = now.tv_sec - last->tv_sec;
+ delta += (now.tv_usec - last->tv_usec)/1000000;
+
+ delta = (netlinkTriggerResolution/1000 - delta);
+ if (delta < 0)
+ delta = 0;
+
+ return (delta);
+}
+
+
+
+
+
+/* Read netling message, keeping (and returning) ONLY the interface
+ * index (according to the kernel. This probably does not reflect
+ * SNMP index numbering. */
+int read_netlink_message (int fd)
+{
+ struct msghdr msghdr;
+ struct iovec iov;
+ struct nlmsghdr *nlhdr;
+ struct ifinfomsg *ifh;
+ int i, err, flags, msg_length, if_index;
+ char tmp_buf[sizeof(struct nlmsghdr)];
+
+ memset (&msghdr, 0, sizeof (msghdr));
+
+ iov.iov_base = &tmp_buf; /* just large enough to see msg_len */
+ iov.iov_len = sizeof(struct nlmsghdr);
+ msghdr.msg_iov = &iov;
+ msghdr.msg_iovlen = 1; /* element in the vector */
+
+
+ /* peek first to find the message's size: */
+ flags = MSG_PEEK;
+
+ for (i=0;i<2;i++) {
+ err = recvmsg(fd, &msghdr, flags);
+
+ if (err < 0) {
+ perror ("recvmsg");
+#if defined(NETLINK_DEBUG)
+ dump_msghdr(&msghdr);
+#endif
+ return (-1);
+
+ } else {
+ nlhdr = (struct nlmsghdr *)(msghdr.msg_iov->iov_base);
+
+ if (msghdr.msg_flags & MSG_TRUNC) {
+ msg_length = nlhdr->nlmsg_len;
+ iov.iov_base = malloc (msg_length);
+ if (iov.iov_base == NULL) {
+ perror ("allocating msghdr.msg_iov");
+ exit (-1);
+ }
+ iov.iov_len = msg_length;
+
+ }
+ }
+ flags=0;
+ }
+
+ nlhdr = (struct nlmsghdr *)(msghdr.msg_iov->iov_base);
+ ifh = (struct ifinfomsg *)((unsigned char *) nlhdr + NLMSG_HDRLEN);
+
+ if_index = ifh->ifi_index;
+
+#if defined(NETLINK_DEBUG)
+
+ printf ("Length of message including header = %i\n", nlhdr->nlmsg_len);
+ printf ("Type of message content = 0x%04x\n", nlhdr->nlmsg_type);
+ printf ("Additional flags = 0x%04x\n", nlhdr->nlmsg_flags);
+ printf ("Sequence number = %i\n", nlhdr->nlmsg_seq);
+ printf ("PID of the sending process = %i\n", nlhdr->nlmsg_pid);
+
+ ifh = (struct ifinfomsg *)((unsigned char *) nlhdr + NLMSG_HDRLEN);
+
+ printf ("ifi_family = 0x%02x\n", ifh->ifi_family);
+ printf ("ifi_type = 0x%04x\n", ifh->ifi_type);
+ printf ("Link index = %i\n", ifh->ifi_index);
+ printf ("Flags = 0x%08x: ", ifh->ifi_flags);
+ print_if_flags(ifh->ifi_flags); puts("\n");
+ printf ("Change mask = 0x%08x\n", ifh->ifi_change);
+
+#endif
+
+ free (iov.iov_base);
+
+ return (if_index);
+}
+
+#if defined(NETLINK_DEBUG)
+
+void print_if_flags(unsigned int flags)
+{
+ if (flags & IFF_UP) printf (" IFF_UP");
+ if (flags & IFF_BROADCAST) printf (" IFF_BROADCAST");
+ if (flags & IFF_DEBUG) printf (" IFF_DEBUG");
+ if (flags & IFF_LOOPBACK) printf (" IFF_LOOPBACK");
+ if (flags & IFF_POINTOPOINT) printf (" IFF_POINTOPOINT");
+ if (flags & IFF_NOTRAILERS) printf (" IFF_NOTRAILERS");
+ if (flags & IFF_RUNNING) printf (" IFF_RUNNING");
+ if (flags & IFF_NOARP) printf (" IFF_NOARP");
+ if (flags & IFF_PROMISC) printf (" IFF_PROMISC");
+ if (flags & IFF_ALLMULTI) printf (" IFF_ALLMULTI");
+ if (flags & IFF_MASTER) printf (" IFF_MASTER");
+ if (flags & IFF_SLAVE) printf (" IFF_SLAVE");
+ if (flags & IFF_MULTICAST) printf (" IFF_MULTICAST");
+ if (flags & IFF_PORTSEL) printf (" IFF_PORTSEL");
+ if (flags & IFF_AUTOMEDIA) printf (" IFF_AUTOMEDIA");
+ /* if (flags & IFF_DYNAMIC) printf (" IFF_DYNAMIC"); */
+ /* if (flags & IFF_LOWER_UP) printf (" LOWER_UP"); */
+ /* if (flags & IFF_DORMANT) printf (" IFF_DORMANT"); */
+}
+
+
+
+void dump_msghdr(struct msghdr *msghdr) {
+ /* printf ("msg_iovlen = %i\n", msghdr->msg_iovlen); */
+ printf ("msg_controllen = %i\n", msghdr->msg_controllen);
+
+ printf ("msg_flags = 0x%08x: ", msghdr->msg_flags);
+ if (msghdr->msg_flags & MSG_EOR)
+ printf (" MSG_EOR");
+ if (msghdr->msg_flags & MSG_TRUNC)
+ printf (" MSG_TRUNC");
+ if (msghdr->msg_flags & MSG_CTRUNC)
+ printf (" MSG_CTRUNC");
+ if (msghdr->msg_flags & MSG_OOB)
+ printf (" MSG_OOB");
+ if (msghdr->msg_flags & MSG_ERRQUEUE)
+ printf (" MSG_ERRQUEUE");
+
+ printf ("\n");
+}
+
+#endif /* defined(NETLINK_DEBUG) */
diff -Nur net-snmp-5.2.3.rr1/agent/mibgroup/disman/rtnetlinkTrigger.h net-snmp-5.2.3.rr1.new/agent/mibgroup/disman/rtnetlinkTrigger.h
--- net-snmp-5.2.3.rr1/agent/mibgroup/disman/rtnetlinkTrigger.h 1969-12-31 19:00:00.000000000 -0500
+++ net-snmp-5.2.3.rr1.new/agent/mibgroup/disman/rtnetlinkTrigger.h 2007-05-16 10:50:43.000000000 -0400
@@ -0,0 +1,53 @@
+/*
+ * snmpd_rtnetlink.h
+ */
+/*
+ * snmpd_rtnetlink.h provides support for the linux NETLINK mechanism
+ * for immediate triggering upon network interface link status change
+ */
+/*
+ * Copyright Ruggedcom, 2007 - Michael Leslie
+ */
+
+#ifndef _RTNETLINK_TRIGGER_H
+#define _RTNETLINK_TRIGGER_H
+
+#if defined(RTNETLINK_DECLS)
+# define RTN_EXTERN
+#else
+# define RTN_EXTERN extern
+#endif
+
+/**** Local definitions: ****************************************************/
+
+/* #define NETLINK_DEBUG */
+
+
+typedef void (rtnetlinkCallback)(unsigned int clientreg,
+ void *clientarg);
+
+struct rtnetlink_trigger
+{
+ void *clientarg;
+ rtnetlinkCallback *callback;
+ unsigned int clientreg;
+ struct rtnetlink_trigger *next;
+};
+
+/**** Variable declarations: ************************************************/
+
+RTN_EXTERN int rtnetlink_fd; /* file descriptor of netlink socket */
+
+
+/**** Function prototypes: **************************************************/
+
+RTN_EXTERN void init_rtnetlinkTrigger(void);
+RTN_EXTERN unsigned int netlink_trigger_register (rtnetlinkCallback *callback,
+ void *clientarg);
+RTN_EXTERN unsigned int netlink_trigger_register_before (rtnetlinkCallback *callback,
+ void *clientarg);
+RTN_EXTERN int read_netlink_message (int fd);
+RTN_EXTERN void run_netlink_triggers(int fd);
+
+#undef RTN_EXTERN
+#endif /* defined(_RTNETLINK_TRIGGER_H) */
diff -Nur net-snmp-5.2.3.rr1/agent/mibgroup/if-mib/ifTable/ifTable_interface.c net-snmp-5.2.3.rr1.new/agent/mibgroup/if-mib/ifTable/ifTable_interface.c
--- net-snmp-5.2.3.rr1/agent/mibgroup/if-mib/ifTable/ifTable_interface.c 2006-06-23 08:41:04.000000000 -0400
+++ net-snmp-5.2.3.rr1.new/agent/mibgroup/if-mib/ifTable/ifTable_interface.c 2007-05-16 10:50:54.000000000 -0400
@@ -279,6 +279,9 @@
* inject cache helper
*/
if (NULL != ifTable_if_ctx.cache) {
+#if HAVE_LINUX_RTNETLINK_H
+ ifTable_if_ctx.cache->flags |= NETSNMP_CACHE_NETLINK_TRIGGER;
+#endif
handler = netsnmp_cache_handler_get(ifTable_if_ctx.cache);
netsnmp_inject_handler(reginfo, handler);
}
diff -Nur net-snmp-5.2.3.rr1/agent/snmpd.c net-snmp-5.2.3.rr1.new/agent/snmpd.c
--- net-snmp-5.2.3.rr1/agent/snmpd.c 2005-12-06 12:07:25.000000000 -0500
+++ net-snmp-5.2.3.rr1.new/agent/snmpd.c 2007-05-16 10:49:23.000000000 -0400
@@ -116,6 +116,10 @@
#if HAVE_GRP_H
#include <grp.h>
#endif
+#if HAVE_LINUX_RTNETLINK_H
+#include <mibgroup/disman/rtnetlinkTrigger.h>
+#define USING_RTNETLINK
+#endif
#ifndef PATH_MAX
# ifdef _POSIX_PATH_MAX
@@ -1113,6 +1117,13 @@
}
#endif /* USING_SMUX_MODULE */
+#ifdef USING_RTNETLINK
+ /* Add any rtnetlink fds to readfds. */
+ if (rtnetlink_fd)
+ FD_SET(rtnetlink_fd, &readfds);
+
+#endif /* USING_RTNETLINK */
+
for (i = 0; i < external_readfdlen; i++) {
FD_SET(external_readfd[i], &readfds);
if (external_readfd[i] >= numfds)
@@ -1139,6 +1150,17 @@
if (count > 0) {
+#ifdef USING_RTNETLINK
+ /* Handle any rtnetlink fds. */
+ if (rtnetlink_fd) {
+ if (FD_ISSET(rtnetlink_fd, &readfds)) {
+ /* read_netlink_message (rtnetlink_fd); */
+ run_netlink_triggers (rtnetlink_fd);
+ }
+
+ }
+#endif /* USING_RTNETLINK */
+
#ifdef USING_SMUX_MODULE
/*
* handle the SMUX sd's
diff -Nur net-snmp-5.2.3.rr1/configure.in net-snmp-5.2.3.rr1.new/configure.in
--- net-snmp-5.2.3.rr1/configure.in 2007-05-16 10:40:29.000000000 -0400
+++ net-snmp-5.2.3.rr1.new/configure.in 2007-05-16 10:48:35.000000000 -0400
@@ -2528,6 +2528,21 @@
]])
# Linux
AC_CHECK_HEADERS(sys/conf.h netinet/tcp_fsm.h sys/protosw.h nlist.h ioctls.h asm/page.h asm/types.h netipx/ipx.h pci/pci.h)
+AC_CHECK_HEADERS(linux/netlink.h,,,
+[[
+#if HAVE_SOCKET_H
+#include <sys/socket.h>
+#endif
+]])
+AC_CHECK_HEADERS(linux/rtnetlink.h,,,
+[[
+#if HAVE_SOCKET_H
+#include <sys/socket.h>
+#endif
+#if HAVE_LINUX_NETLINK_H
+#include <linux/netlink.h>
+#endif
+]])
# Solaris
AC_CHECK_HEADERS(inet/mib2.h)
# NetBSD required headers
diff -Nur net-snmp-5.2.3.rr1/include/net-snmp/agent/cache_handler.h net-snmp-5.2.3.rr1.new/include/net-snmp/agent/cache_handler.h
--- net-snmp-5.2.3.rr1/include/net-snmp/agent/cache_handler.h 2005-06-13 17:25:56.000000000 -0400
+++ net-snmp-5.2.3.rr1.new/include/net-snmp/agent/cache_handler.h 2007-05-16 10:48:59.000000000 -0400
@@ -103,6 +103,7 @@
#define NETSNMP_CACHE_DONT_AUTO_RELEASE 0x0008
#define NETSNMP_CACHE_PRELOAD 0x0010
#define NETSNMP_CACHE_AUTO_RELOAD 0x0020
+#define NETSNMP_CACHE_NETLINK_TRIGGER 0x0040
#define NETSNMP_CACHE_HINT_HANDLER_ARGS 0x1000
diff -Nur net-snmp-5.2.3.rr1/include/net-snmp/net-snmp-config.h.in net-snmp-5.2.3.rr1.new/include/net-snmp/net-snmp-config.h.in
--- net-snmp-5.2.3.rr1/include/net-snmp/net-snmp-config.h.in 2006-05-26 12:37:06.000000000 -0400
+++ net-snmp-5.2.3.rr1.new/include/net-snmp/net-snmp-config.h.in 2007-05-16 10:49:08.000000000 -0400
@@ -384,6 +384,12 @@
/* Define to 1 if you have the <linux/hdreg.h> header file. */
#undef HAVE_LINUX_HDREG_H
+/* Define to 1 if you have the <linux/netlink.h> header file. */
+#undef HAVE_LINUX_NETLINK_H
+
+/* Define to 1 if you have the <linux/rtnetlink.h> header file. */
+#undef HAVE_LINUX_RTNETLINK_H
+
/* Define to 1 if you have the <linux/tasks.h> header file. */
#undef HAVE_LINUX_TASKS_H
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Net-snmp-coders mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/net-snmp-coders