hi,
the following diff adds the linkUp/Down traps to snmpd. this will
help to track interface link state changes via snmp and also virtual
link states like carp(4) BACKUP <-> MASTER transitions. snmpd(8)
monitors the link state changes and send traps to the configured
receivers accordingly.
limitations:
- the traps are SNMPv2-only. some NMS seem to stick on v1 linkUp/Down.
- the ifLinkUpDownTrapEnable is always enabled for every interface and
is not considering stacking (eg. a trap will be send for every vlan if
parent goes down).
comments?
reyk
Index: kroute.c
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/kroute.c,v
retrieving revision 1.15
diff -u -p -r1.15 kroute.c
--- kroute.c 15 Oct 2010 09:27:03 -0000 1.15
+++ kroute.c 16 Mar 2011 16:05:05 -0000
@@ -623,9 +623,16 @@ kif_update(u_short if_index, int flags,
struct ether_addr *ea;
struct ifreq ifr;
- if ((kif = kif_find(if_index)) == NULL)
+ if ((kif = kif_find(if_index)) == NULL) {
if ((kif = kif_insert(if_index)) == NULL)
return (NULL);
+ } else {
+ if (((flags & (IFF_UP)) &&
+ LINK_STATE_IS_UP(ifd->ifi_link_state)) !=
+ ((kif->k.if_flags & (IFF_UP)) &&
+ LINK_STATE_IS_UP(kif->k.if_link_state)))
+ trap_link(if_index, flags, ifd->ifi_link_state);
+ }
kif->k.if_flags = flags;
bcopy(ifd, &kif->k.if_data, sizeof(struct if_data));
Index: mib.c
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/mib.c,v
retrieving revision 1.43
diff -u -p -r1.43 mib.c
--- mib.c 15 Oct 2010 11:56:13 -0000 1.43
+++ mib.c 16 Mar 2011 16:05:06 -0000
@@ -953,19 +953,12 @@ mib_iftable(struct oid *oid, struct ber_
break;
case 7:
/* ifAdminStatus up(1), down(2), testing(3) */
- i = (kif->if_flags & IFF_UP) ? 1 : 2;
+ i = smi_ifadminstatus(kif->if_flags);
ber = ber_add_integer(ber, i);
break;
case 8:
/* ifOperStatus */
- if ((kif->if_flags & IFF_UP) == 0) {
- i = 2; /* down(2) */
- } else if (LINK_STATE_IS_UP(kif->if_link_state)) {
- i = 1; /* up(1) */
- } else if (kif->if_link_state == LINK_STATE_DOWN) {
- i = 7; /* lowerLayerDown(7) or dormant(5)? */
- } else
- i = 4; /* unknown(4) */
+ i = smi_ifoperstatus(kif->if_flags, kif->if_link_state);
ber = ber_add_integer(ber, i);
break;
case 9:
@@ -1116,7 +1109,7 @@ mib_ifxtable(struct oid *oid, struct ber
ber_set_header(ber, BER_CLASS_APPLICATION, SNMP_T_COUNTER64);
break;
case 14:
- ber = ber_add_integer(ber, 0); /* enabled(1), disabled(2) */
+ ber = ber_add_integer(ber, 1); /* enabled(1), disabled(2) */
break;
case 15:
i = kif->if_baudrate >= 1000000 ?
Index: smi.c
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/smi.c,v
retrieving revision 1.6
diff -u -p -r1.6 smi.c
--- smi.c 16 Dec 2009 22:17:53 -0000 1.6
+++ smi.c 16 Mar 2011 16:05:06 -0000
@@ -69,6 +69,27 @@ smi_getticks(void)
return (ticks);
}
+int
+smi_ifadminstatus(int flags)
+{
+ /* ifAdminStatus up(1), down(2), testing(3) */
+ return ((flags & IFF_UP) ? 1 : 2);
+}
+
+int
+smi_ifoperstatus(int flags, u_int8_t link_state)
+{
+ if ((flags & IFF_UP) == 0)
+ return (2); /* down(2) */
+ else if (LINK_STATE_IS_UP(link_state))
+ return (1); /* up(1) */
+ else if (link_state == LINK_STATE_DOWN)
+ return (7); /* lowerLayerDown(7) or dormant(5)? */
+ else
+ return (4); /* unknown(4) */
+ /* NOTREACHED */
+}
+
void
smi_oidlen(struct ber_oid *o)
{
Index: snmpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/snmpd.h,v
retrieving revision 1.30
diff -u -p -r1.30 snmpd.h
--- snmpd.h 20 Sep 2010 08:56:16 -0000 1.30
+++ snmpd.h 16 Mar 2011 16:05:06 -0000
@@ -359,6 +359,7 @@ void snmpe_debug_elements(struct ber_e
void trap_init(void);
int trap_imsg(struct imsgev *, pid_t);
int trap_send(struct ber_oid *, struct ber_element *);
+void trap_link(u_short, int, u_int8_t);
/* mps.c */
struct ber_element *
@@ -393,6 +394,8 @@ char *smi_oidstring(struct ber_oid *, c
void smi_delete(struct oid *);
void smi_insert(struct oid *);
int smi_oid_cmp(struct oid *, struct oid *);
+int smi_ifadminstatus(int);
+int smi_ifoperstatus(int, u_int8_t);
/* timer.c */
void timer_init(void);
Index: trap.c
===================================================================
RCS file: /cvs/src/usr.sbin/snmpd/trap.c,v
retrieving revision 1.15
diff -u -p -r1.15 trap.c
--- trap.c 16 Mar 2011 15:30:35 -0000 1.15
+++ trap.c 16 Mar 2011 16:05:06 -0000
@@ -195,6 +195,44 @@ trap_imsg(struct imsgev *iev, pid_t pid)
return (ret);
}
+void
+trap_link(u_short if_index, int flags, u_int8_t link_state)
+{
+ struct ber_oid linkup = OID(MIB_linkUp);
+ struct ber_oid linkdown = OID(MIB_linkDown);
+ struct ber_oid ifindex = OID(MIB_ifIndex);
+ struct ber_oid ifadmin = OID(MIB_ifAdminStatus);
+ struct ber_oid ifoper = OID(MIB_ifOperStatus);
+ int idx, admin, oper;
+ struct ber_element *ber;
+
+ smi_oidlen(&ifindex);
+ ifindex.bo_id[ifindex.bo_n++] = if_index;
+ idx = if_index;
+
+ smi_oidlen(&ifadmin);
+ ifadmin.bo_id[ifadmin.bo_n++] = if_index;
+ admin = smi_ifadminstatus(flags);
+
+ smi_oidlen(&ifoper);
+ ifoper.bo_id[ifoper.bo_n++] = if_index;
+ oper = smi_ifoperstatus(flags, link_state);
+
+ ber = ber_add_sequence(NULL);
+ if ((ber_printf_elements(ber, "Od}{Od}{Od}",
+ &ifindex, idx,
+ &ifadmin, admin,
+ &ifoper, oper)) == NULL) {
+ log_warnx("trap_link: failed to create trap");
+ return;
+ }
+
+ if ((flags & IFF_UP) && LINK_STATE_IS_UP(link_state))
+ trap_send(&linkup, ber);
+ else
+ trap_send(&linkdown, ber);
+}
+
int
trap_send(struct ber_oid *oid, struct ber_element *elm)
{