summaryrefslogtreecommitdiff
path: root/usr.sbin/mrouted/snmp.c
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
commitd6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch)
treeece253b876159b39c620e62b6c9b1174642e070e /usr.sbin/mrouted/snmp.c
initial import of NetBSD tree
Diffstat (limited to 'usr.sbin/mrouted/snmp.c')
-rw-r--r--usr.sbin/mrouted/snmp.c1307
1 files changed, 1307 insertions, 0 deletions
diff --git a/usr.sbin/mrouted/snmp.c b/usr.sbin/mrouted/snmp.c
new file mode 100644
index 00000000000..5298da5dbc8
--- /dev/null
+++ b/usr.sbin/mrouted/snmp.c
@@ -0,0 +1,1307 @@
+/* $NetBSD: snmp.c,v 1.2 1995/10/09 03:51:58 thorpej Exp $ */
+
+/*
+ * snmp.c
+ *
+ * Code written by David Thaler <thalerd@eecs.umich.edu>
+ * Moved to a seperate file by Bill Fenner <fenner@parc.xerox.com>
+ */
+
+
+#include "defs.h"
+#include <string.h>
+#include "snmp.h"
+
+#define NUMMIBS 2
+#define SNMPD_RETRY_INTERVAL 300 /* periodic snmpd probe interval */
+
+char *mibs[]={ "ipMRouteMIB", "dvmrpMIB" };
+
+extern int o_ipMRouteTable();
+extern int o_ipMRouteNextHopTable();
+extern int o_dvmrpRouteTable();
+extern int o_dvmrpRouteNextHopTable();
+
+ int smux_fd = NOTOK;
+ int rock_and_roll = 0;
+ int dont_bother_anymore = 0;
+ int quantum = 0;
+static OID subtree[NUMMIBS] = NULLOID;
+static struct smuxEntry *se = NULL;
+extern int smux_errno;
+extern char smux_info[BUFSIZ];
+
+/*
+ * Place an IP address into an OID starting at element n
+ */
+void
+put_address(oid, addr, n)
+ OID oid;
+ u_long addr;
+ int n;
+{
+ int i;
+
+ for (i=n+3; i>=n+0; i--) {
+ oid->oid_elements[i] = addr & 0xFF;
+ addr >>= 8;
+ }
+}
+
+/* Get an IP address from an OID starting at element n */
+int
+get_address(oid, addr, n)
+ OID oid;
+ u_long *addr;
+ int n;
+{
+ int i;
+ int ok = 1;
+
+ (*addr) = 0;
+
+ if (oid -> oid_nelem < n+4)
+ return 0;
+
+ for (i=n; i<n+4; i++) {
+ (*addr) <<= 8;
+ if (i >= oid->oid_nelem)
+ ok = 0;
+ else
+ (*addr) |= oid->oid_elements[i];
+ }
+
+ return ok;
+}
+
+/*
+ * Attempt to start up SMUX protocol
+ */
+void
+try_smux_init()
+{
+ if (smux_fd != NOTOK || dont_bother_anymore)
+ return;
+ if ((smux_fd = smux_init(debug)) == NOTOK) {
+ log(LOG_WARNING, 0,"smux_init: %s [%s]", smux_error(smux_errno),
+ smux_info);
+ } else
+ rock_and_roll = 0;
+}
+
+/*
+ * Implements scalar objects from both MIBs
+ */
+static int
+o_scalar(oi, v, offset)
+ OI oi;
+ register struct type_SNMP_VarBind *v;
+ int offset;
+{
+ int ifvar;
+ register OID oid = oi -> oi_name;
+ register OT ot = oi -> oi_type;
+
+ ifvar = (int) ot -> ot_info;
+ switch (offset) {
+ case type_SNMP_SMUX__PDUs_get__request:
+ if (oid -> oid_nelem !=
+ ot -> ot_name -> oid_nelem + 1
+ || oid -> oid_elements[oid -> oid_nelem - 1]
+ != 0)
+ return int_SNMP_error__status_noSuchName;
+ break;
+
+ case type_SNMP_SMUX__PDUs_get__next__request:
+ if (oid -> oid_nelem
+ == ot -> ot_name -> oid_nelem) {
+ OID new;
+
+ if ((new = oid_extend (oid, 1)) == NULLOID)
+ return int_SNMP_error__status_genErr;
+ new -> oid_elements[new -> oid_nelem - 1] = 0;
+
+ if (v -> name)
+ free_SNMP_ObjectName (v -> name);
+ v -> name = new;
+ }
+ else
+ return NOTOK;
+ break;
+
+ default:
+ return int_SNMP_error__status_genErr;
+ }
+
+ switch (ifvar) {
+ case ipMRouteEnable:
+ return o_integer (oi, v, 1);
+
+ case dvmrpVersion: {
+ static char buff[15];
+
+ sprintf(buff, "mrouted%d.%d", PROTOCOL_VERSION, MROUTED_VERSION);
+ return o_string (oi, v, buff, strlen (buff));
+ }
+
+ case dvmrpGenerationId:
+ return o_integer (oi, v, dvmrp_genid);
+
+ default:
+ return int_SNMP_error__status_noSuchName;
+ }
+}
+
+/*
+ * Find if a specific scoped boundary exists on a Vif
+ */
+struct vif_acl *
+find_boundary(vifi, addr, mask)
+ int vifi;
+ int addr;
+ int mask;
+{
+ struct vif_acl *n;
+
+ for (n = uvifs[vifi].uv_acl; n != NULL; n = n->acl_next) {
+ if (addr == n->acl_addr && mask==n->acl_mask)
+ return n;
+ }
+ return NULL;
+}
+
+/*
+ * Find the next scoped boundary in order after a given spec
+ */
+struct vif_acl *
+next_boundary(vifi, addr, mask)
+ int *vifi;
+ int addr;
+ int mask;
+{
+ struct vif_acl *bestn, *n;
+ int i;
+
+ for (i = *vifi; i < numvifs; i++) {
+ bestn = NULL;
+ for (n = uvifs[i].uv_acl; n; n=n->acl_next) {
+ if ((i > *vifi || n->acl_addr > addr
+ || (n->acl_addr==addr && n->acl_mask>mask))
+ && (!bestn || n->acl_addr < bestn->acl_addr
+ || (n->acl_addr==bestn->acl_addr && n->acl_mask<bestn->acl_mask)))
+ bestn = n;
+ }
+ if (bestn) {
+ *vifi = i;
+ return bestn;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Implements the Boundary Table portion of the DVMRP MIB
+ */
+static int
+o_dvmrpBoundaryTable (oi, v, offset)
+OI oi;
+register struct type_SNMP_VarBind *v;
+{
+ int ifvar, vifi,
+ addr, mask;
+ register OID oid = oi -> oi_name;
+ register OT ot = oi -> oi_type;
+ struct vif_acl *bound;
+
+ ifvar = (int) ot -> ot_info;
+ switch (offset) {
+ case type_SNMP_SMUX__PDUs_get__request:
+ if (oid->oid_nelem != ot->ot_name->oid_nelem + 9)
+ return int_SNMP_error__status_noSuchName;
+
+ if ((vifi = oid -> oid_elements[ot-> ot_name->oid_nelem]) >= numvifs)
+ return int_SNMP_error__status_noSuchName;
+
+ if (!get_address(oid, &addr, ot->ot_name->oid_nelem+1)
+ || !get_address(oid, &mask, ot->ot_name->oid_nelem+5))
+ return int_SNMP_error__status_noSuchName;
+
+ if (!(bound = find_boundary(vifi, addr, mask)))
+ return int_SNMP_error__status_noSuchName;
+ break;
+
+ case type_SNMP_SMUX__PDUs_get__next__request:
+ if (oid->oid_nelem < ot->ot_name->oid_nelem + 9) {
+ OID new;
+
+ if (oid->oid_nelem == ot->ot_name->oid_nelem) {
+ vifi = addr = mask = 0;
+ } else {
+ vifi = oid->oid_elements[ot->ot_name->oid_nelem];
+ get_address(oid, &addr, ot->ot_name->oid_nelem+1);
+ get_address(oid, &mask, ot->ot_name->oid_nelem+5);
+ }
+
+ bound = next_boundary(&vifi,addr,mask);
+ if (!bound)
+ return NOTOK;
+
+ new = oid_extend (oid, ot->ot_name->oid_nelem+9-oid->oid_nelem);
+ if (new == NULLOID)
+ return NOTOK;
+ new -> oid_elements[ot->ot_name->oid_nelem] = vifi;
+ put_address(new, bound->acl_addr, ot->ot_name->oid_nelem+1);
+ put_address(new, bound->acl_mask, ot->ot_name->oid_nelem+5);
+
+ if (v -> name)
+ free_SNMP_ObjectName (v -> name);
+ v -> name = new;
+ } else { /* get next entry given previous */
+ int i = ot -> ot_name -> oid_nelem;
+
+ vifi = oid->oid_elements[i];
+ get_address(oid, &addr, ot->ot_name->oid_nelem+1);
+ get_address(oid, &mask, ot->ot_name->oid_nelem+5);
+ if (!(bound = next_boundary(&vifi,addr,mask+1)))
+ return NOTOK;
+
+ put_address(oid, bound->acl_addr, ot->ot_name->oid_nelem+1);
+ put_address(oid, bound->acl_mask, ot->ot_name->oid_nelem+5);
+ oid->oid_elements[i] = vifi;
+ oid->oid_nelem = i + 9;
+ }
+ break;
+
+ default:
+ return int_SNMP_error__status_genErr;
+ }
+
+ switch (ifvar) {
+
+ case dvmrpBoundaryVifIndex:
+ return o_integer (oi, v, vifi);
+
+ default:
+ return int_SNMP_error__status_noSuchName;
+ }
+}
+
+/*
+ * Given a vif index and address, return the next greater neighbor entry
+ */
+struct listaddr *
+next_neighbor(vifi, addr)
+ int *vifi;
+ int addr;
+{
+ struct listaddr *bestn, *n;
+ int i;
+
+ for (i = *vifi; i < numvifs; i++) {
+ bestn = NULL;
+ for (n = uvifs[i].uv_neighbors; n; n=n->al_next) {
+ if ((i > *vifi || n->al_addr > addr)
+ && (!bestn || n->al_addr < bestn->al_addr))
+ bestn = n;
+ }
+ if (bestn) {
+ *vifi = i;
+ return bestn;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Find a neighbor, if it exists off a given Vif
+ */
+struct listaddr *
+find_neighbor(vifi, addr)
+ int vifi;
+ int addr;
+{
+ struct listaddr *n;
+
+ for (n = uvifs[vifi].uv_neighbors; n != NULL; n = n->al_next) {
+ if (addr == n->al_addr)
+ return n;
+ }
+ return NULL;
+}
+
+/*
+ * Implements the Neighbor Table portion of the DVMRP MIB
+ */
+static int
+o_dvmrpNeighborTable (oi, v, offset)
+OI oi;
+register struct type_SNMP_VarBind *v;
+{
+ int ifvar, vifi,
+ addr;
+ register OID oid = oi -> oi_name;
+ register OT ot = oi -> oi_type;
+ struct listaddr *neighbor;
+
+ ifvar = (int) ot -> ot_info;
+ switch (offset) {
+ case type_SNMP_SMUX__PDUs_get__request:
+ if (oid->oid_nelem != ot->ot_name->oid_nelem + 5)
+ return int_SNMP_error__status_noSuchName;
+
+ if ((vifi = oid -> oid_elements[ot-> ot_name->oid_nelem]) >= numvifs)
+ return int_SNMP_error__status_noSuchName;
+
+ if (!get_address(oid, &addr, ot->ot_name->oid_nelem+1))
+ return int_SNMP_error__status_noSuchName;
+
+ if (!(neighbor = find_neighbor(vifi, addr)))
+ return int_SNMP_error__status_noSuchName;
+ break;
+
+ case type_SNMP_SMUX__PDUs_get__next__request:
+ if (oid->oid_nelem < ot->ot_name->oid_nelem + 5) {
+ OID new;
+
+ if (oid->oid_nelem == ot->ot_name->oid_nelem) {
+ vifi = addr = 0;
+ } else {
+ vifi = oid->oid_elements[ot->ot_name->oid_nelem];
+ get_address(oid, &addr, ot->ot_name->oid_nelem+1);
+ }
+
+ neighbor = next_neighbor(&vifi,addr); /* Get first entry */
+ if (!neighbor)
+ return NOTOK;
+
+ new = oid_extend (oid, ot->ot_name->oid_nelem+5-oid->oid_nelem);
+ if (new == NULLOID)
+ return NOTOK;
+ new -> oid_elements[ot->ot_name->oid_nelem] = vifi;
+ put_address(new, neighbor->al_addr, ot->ot_name->oid_nelem+1);
+
+ if (v -> name)
+ free_SNMP_ObjectName (v -> name);
+ v -> name = new;
+
+ } else { /* get next entry given previous */
+ int i = ot -> ot_name -> oid_nelem;
+
+ vifi = oid->oid_elements[i];
+ get_address(oid, &addr, ot->ot_name->oid_nelem+1);
+ if (!(neighbor = next_neighbor(&vifi,addr+1)))
+ return NOTOK;
+
+ put_address(oid, neighbor->al_addr, ot->ot_name->oid_nelem+1);
+ oid->oid_elements[i] = vifi;
+ oid->oid_nelem = i + 5;
+ }
+ break;
+
+ default:
+ return int_SNMP_error__status_genErr;
+ }
+
+ switch (ifvar) {
+
+ case dvmrpNeighborUpTime: {
+ time_t currtime;
+ time(&currtime);
+ return o_integer (oi, v, (currtime - neighbor->al_ctime)*100);
+ }
+
+ case dvmrpNeighborExpiryTime:
+ return o_integer (oi, v, (NEIGHBOR_EXPIRE_TIME-neighbor->al_timer) * 100);
+
+ case dvmrpNeighborVersion: {
+ static char buff[15];
+
+ sprintf(buff, "%d.%d", neighbor->al_pv, neighbor->al_mv);
+ return o_string (oi, v, buff, strlen (buff));
+ }
+
+ case dvmrpNeighborGenerationId:
+ return o_integer (oi, v, neighbor->al_genid);
+
+ default:
+ return int_SNMP_error__status_noSuchName;
+ }
+}
+
+/*
+ * Given a virtual interface number, make sure we have the current
+ * kernel information for that Vif.
+ */
+refresh_vif(v_req, ifnum)
+ struct sioc_vif_req *v_req;
+ int ifnum;
+{
+ static int lastq = -1;
+
+ if (quantum!=lastq || v_req->vifi != ifnum) {
+ lastq = quantum;
+ v_req->vifi = ifnum;
+ if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)v_req) < 0)
+ v_req->icount = v_req->ocount = v_req->ibytes = v_req->obytes = 0;
+ }
+}
+
+/*
+ * Implements the Multicast Routing Interface Table portion of the Multicast MIB
+ */
+static int
+o_ipMRouteInterfaceTable (oi, v, offset)
+OI oi;
+register struct type_SNMP_VarBind *v;
+int offset;
+{
+ int ifnum,
+ ifvar;
+ register OID oid = oi -> oi_name;
+ register OT ot = oi -> oi_type;
+static struct sioc_vif_req v_req;
+
+ ifvar = (int) ot -> ot_info;
+ switch (offset) {
+ case type_SNMP_SMUX__PDUs_get__request:
+ if (oid -> oid_nelem != ot -> ot_name -> oid_nelem + 1)
+ return int_SNMP_error__status_noSuchName;
+ if ((ifnum = oid -> oid_elements[oid -> oid_nelem - 1]) >= numvifs)
+ return int_SNMP_error__status_noSuchName;
+ break;
+
+ case type_SNMP_SMUX__PDUs_get__next__request:
+ if (oid -> oid_nelem == ot -> ot_name -> oid_nelem) {
+ OID new;
+
+ ifnum = 0;
+
+ if ((new = oid_extend (oid, 1)) == NULLOID)
+ return NOTOK;
+ new -> oid_elements[new -> oid_nelem - 1] = ifnum;
+
+ if (v -> name)
+ free_SNMP_ObjectName (v -> name);
+ v -> name = new;
+
+ } else {
+ int i = ot -> ot_name -> oid_nelem;
+
+ if ((ifnum = oid -> oid_elements[i] + 1) >= numvifs)
+ return NOTOK;
+
+ oid -> oid_elements[i] = ifnum;
+ oid -> oid_nelem = i + 1;
+ }
+ break;
+
+ default:
+ return int_SNMP_error__status_genErr;
+ }
+
+ switch (ifvar) {
+ case ipMRouteInterfaceTtl:
+ return o_integer (oi, v, uvifs[ifnum].uv_threshold);
+
+ case dvmrpVInterfaceType:
+ if (uvifs[ifnum].uv_flags & VIFF_SRCRT)
+ return o_integer (oi, v, 2);
+ else if (uvifs[ifnum].uv_flags & VIFF_TUNNEL)
+ return o_integer (oi, v, 1);
+ else if (uvifs[ifnum].uv_flags & VIFF_QUERIER)
+ return o_integer (oi, v, 3);
+ else /* SUBNET */
+ return o_integer (oi, v, 4);
+
+ case dvmrpVInterfaceState:
+ if (uvifs[ifnum].uv_flags & VIFF_DISABLED)
+ return o_integer (oi, v, 3);
+ else if (uvifs[ifnum].uv_flags & VIFF_DOWN)
+ return o_integer (oi, v, 2);
+ else /* UP */
+ return o_integer (oi, v, 1);
+
+ case dvmrpVInterfaceLocalAddress: {
+ struct sockaddr_in tmp;
+ tmp.sin_addr.s_addr = uvifs[ifnum].uv_lcl_addr;
+ return o_ipaddr (oi, v, &tmp);
+ }
+
+ case dvmrpVInterfaceRemoteAddress: {
+ struct sockaddr_in tmp;
+ tmp.sin_addr.s_addr = (uvifs[ifnum].uv_flags & VIFF_TUNNEL) ?
+ uvifs[ifnum].uv_rmt_addr :
+ uvifs[ifnum].uv_subnet;
+ return o_ipaddr (oi, v, &tmp);
+ }
+
+ case dvmrpVInterfaceRemoteSubnetMask: {
+ struct sockaddr_in tmp;
+ tmp.sin_addr.s_addr = uvifs[ifnum].uv_subnetmask;
+ return o_ipaddr (oi, v, &tmp);
+ }
+
+ case dvmrpVInterfaceMetric:
+ return o_integer (oi, v, uvifs[ifnum].uv_metric);
+
+ case dvmrpVInterfaceRateLimit:
+ return o_integer (oi, v, uvifs[ifnum].uv_rate_limit);
+
+ case dvmrpVInterfaceInPkts:
+ refresh_vif(&v_req, ifnum);
+ return o_integer(oi, v, v_req.icount);
+
+ case dvmrpVInterfaceOutPkts:
+ refresh_vif(&v_req, ifnum);
+ return o_integer(oi, v, v_req.ocount);
+
+ case dvmrpVInterfaceInOctets:
+ refresh_vif(&v_req, ifnum);
+ return o_integer(oi, v, v_req.ibytes);
+
+ case dvmrpVInterfaceOutOctets:
+ refresh_vif(&v_req, ifnum);
+ return o_integer(oi, v, v_req.obytes);
+
+ default:
+ return int_SNMP_error__status_noSuchName;
+ }
+}
+
+struct mib_variable {
+ char *name; /* MIB variable name */
+ int (*function)(); /* Function to call */
+ int info; /* Which variable */
+} mib_vars[] = {
+ "ipMRouteEnable", o_scalar, ipMRouteEnable,
+ "ipMRouteUpstreamNeighbor", o_ipMRouteTable, ipMRouteUpstreamNeighbor,
+ "ipMRouteInIfIndex", o_ipMRouteTable, ipMRouteInIfIndex,
+ "ipMRouteUpTime", o_ipMRouteTable, ipMRouteUpTime,
+ "ipMRouteExpiryTime", o_ipMRouteTable, ipMRouteExpiryTime,
+ "ipMRoutePkts", o_ipMRouteTable, ipMRoutePkts,
+ "ipMRouteDifferentInIfIndexes", o_ipMRouteTable, ipMRouteDifferentInIfIndexes,
+ "ipMRouteOctets", o_ipMRouteTable, ipMRouteOctets,
+ "ipMRouteProtocol", o_ipMRouteTable, ipMRouteProtocol,
+ "ipMRouteNextHopState", o_ipMRouteNextHopTable, ipMRouteNextHopState,
+ "ipMRouteNextHopUpTime", o_ipMRouteNextHopTable, ipMRouteNextHopUpTime,
+ "ipMRouteNextHopExpiryTime", o_ipMRouteNextHopTable, ipMRouteNextHopExpiryTime,
+ "ipMRouteNextHopClosestMemberHops", o_ipMRouteNextHopTable, ipMRouteNextHopClosestMemberHops,
+ "ipMRouteNextHopProtocol", o_ipMRouteNextHopTable, ipMRouteNextHopProtocol,
+ "ipMRouteInterfaceTtl", o_ipMRouteInterfaceTable, ipMRouteInterfaceTtl,
+ "dvmrpVersion", o_scalar, dvmrpVersion,
+ "dvmrpGenerationId", o_scalar, dvmrpGenerationId,
+ "dvmrpVInterfaceType", o_ipMRouteInterfaceTable, dvmrpVInterfaceType,
+ "dvmrpVInterfaceState", o_ipMRouteInterfaceTable, dvmrpVInterfaceState,
+ "dvmrpVInterfaceLocalAddress", o_ipMRouteInterfaceTable, dvmrpVInterfaceLocalAddress,
+ "dvmrpVInterfaceRemoteAddress", o_ipMRouteInterfaceTable, dvmrpVInterfaceRemoteAddress,
+ "dvmrpVInterfaceRemoteSubnetMask", o_ipMRouteInterfaceTable, dvmrpVInterfaceRemoteSubnetMask,
+ "dvmrpVInterfaceMetric", o_ipMRouteInterfaceTable, dvmrpVInterfaceMetric,
+ "dvmrpVInterfaceRateLimit", o_ipMRouteInterfaceTable, dvmrpVInterfaceRateLimit,
+ "dvmrpVInterfaceInPkts", o_ipMRouteInterfaceTable, dvmrpVInterfaceInPkts,
+ "dvmrpVInterfaceOutPkts", o_ipMRouteInterfaceTable, dvmrpVInterfaceOutPkts,
+ "dvmrpVInterfaceInOctets", o_ipMRouteInterfaceTable, dvmrpVInterfaceInOctets,
+ "dvmrpVInterfaceOutOctets", o_ipMRouteInterfaceTable, dvmrpVInterfaceOutOctets,
+ "dvmrpNeighborUpTime", o_dvmrpNeighborTable, dvmrpNeighborUpTime,
+ "dvmrpNeighborExpiryTime", o_dvmrpNeighborTable, dvmrpNeighborExpiryTime,
+ "dvmrpNeighborVersion", o_dvmrpNeighborTable, dvmrpNeighborVersion,
+ "dvmrpNeighborGenerationId",o_dvmrpNeighborTable, dvmrpNeighborGenerationId,
+ "dvmrpRouteUpstreamNeighbor", o_dvmrpRouteTable, dvmrpRouteUpstreamNeighbor,
+ "dvmrpRouteInVifIndex", o_dvmrpRouteTable, dvmrpRouteInVifIndex,
+ "dvmrpRouteMetric", o_dvmrpRouteTable, dvmrpRouteMetric,
+ "dvmrpRouteExpiryTime", o_dvmrpRouteTable, dvmrpRouteExpiryTime,
+ "dvmrpRouteNextHopType", o_dvmrpRouteNextHopTable, dvmrpRouteNextHopType,
+ "dvmrpBoundaryVifIndex", o_dvmrpBoundaryTable, dvmrpBoundaryVifIndex,
+ 0, 0, 0
+};
+
+/*
+ * Register variables as part of the MIBs
+ */
+void
+init_mib()
+{
+ register OT ot;
+ int i;
+
+ for (i=0; mib_vars[i].name; i++)
+ if (ot=text2obj(mib_vars[i].name)) {
+ ot->ot_getfnx = mib_vars[i].function;
+ ot->ot_info = (caddr_t)mib_vars[i].info;
+ }
+}
+
+/*
+ * Initialize the SNMP part of mrouted
+ */
+void
+snmp_init()
+{
+ OT ot;
+ int i;
+
+ if (readobjects("mrouted.defs") == NOTOK)
+ log(LOG_ERR, 0, "readobjects: %s", PY_pepy);
+ for (i=0; i < NUMMIBS; i++) {
+ if ((ot = text2obj(mibs[i])) == NULL)
+ log(LOG_ERR, 0, "object \"%s\" not in \"%s\"",
+ mibs[i], "mrouted.defs");
+ subtree[i] = ot -> ot_name;
+ }
+ init_mib();
+ try_smux_init();
+}
+
+/*
+ * Process an SNMP "get" or "get-next" request
+ */
+static
+get_smux (pdu, offset)
+ register struct type_SNMP_GetRequest__PDU *pdu;
+ int offset;
+{
+ int idx,
+ status;
+ object_instance ois;
+ register struct type_SNMP_VarBindList *vp;
+ IFP method;
+
+ quantum = pdu -> request__id;
+ idx = 0;
+ for (vp = pdu -> variable__bindings; vp; vp = vp -> next) {
+ register OI oi;
+ register OT ot;
+ register struct type_SNMP_VarBind *v = vp -> VarBind;
+
+ idx++;
+
+ if (offset == type_SNMP_SMUX__PDUs_get__next__request) {
+ if ((oi = name2inst (v -> name)) == NULLOI
+ && (oi = next2inst (v -> name)) == NULLOI)
+ goto no_name;
+
+ if ((ot = oi -> oi_type) -> ot_getfnx == NULLIFP)
+ goto get_next;
+ }
+ else
+ if ((oi = name2inst (v -> name)) == NULLOI
+ || (ot = oi -> oi_type) -> ot_getfnx
+ == NULLIFP) {
+no_name: ;
+ pdu -> error__status =
+ int_SNMP_error__status_noSuchName;
+ goto out;
+ }
+
+try_again: ;
+ switch (offset) {
+ case type_SNMP_SMUX__PDUs_get__request:
+ if (!(method = ot -> ot_getfnx))
+ goto no_name;
+ break;
+
+ case type_SNMP_SMUX__PDUs_get__next__request:
+ if (!(method = ot -> ot_getfnx))
+ goto get_next;
+ break;
+
+ case type_SNMP_SMUX__PDUs_set__request:
+ if (!(method = ot -> ot_setfnx))
+ goto no_name;
+ break;
+
+ default:
+ goto no_name;
+ }
+
+ switch (status = (*ot -> ot_getfnx) (oi, v, offset)) {
+ case NOTOK: /* get-next wants a bump */
+get_next: ;
+ oi = &ois;
+ for (;;) {
+ if ((ot = ot -> ot_next) == NULLOT) {
+ pdu -> error__status =
+ int_SNMP_error__status_noSuchName;
+ goto out;
+ }
+ oi -> oi_name =
+ (oi -> oi_type = ot) -> ot_name;
+ if (ot -> ot_getfnx)
+ goto try_again;
+ }
+
+ case int_SNMP_error__status_noError:
+ break;
+
+ default:
+ pdu -> error__status = status;
+ goto out;
+ }
+ }
+ idx = 0;
+
+out: ;
+ pdu -> error__index = idx;
+
+ if (smux_response (pdu) == NOTOK) {
+ log(LOG_WARNING,0,"smux_response: %s [%s]",
+ smux_error (smux_errno), smux_info);
+ smux_fd = NOTOK;
+ }
+}
+
+/*
+ * Handle SNMP "set" request by replying that it is illegal
+ */
+static
+set_smux(event)
+ struct type_SNMP_SMUX__PDUs *event;
+{
+ switch (event -> offset) {
+ case type_SNMP_SMUX__PDUs_set__request:
+ {
+ register struct type_SNMP_GetResponse__PDU *pdu =
+ event -> un.get__response;
+
+ pdu -> error__status = int_SNMP_error__status_noSuchName;
+ pdu -> error__index = pdu -> variable__bindings ? 1 : 0;
+
+ if (smux_response (pdu) == NOTOK) {
+ log(LOG_WARNING, 0,
+ "smux_response: %s [%s]",
+ smux_error (smux_errno),
+ smux_info);
+ smux_fd = NOTOK;
+ }
+ }
+ break;
+
+ case type_SNMP_SMUX__PDUs_commitOrRollback:
+ {
+ struct type_SNMP_SOutPDU *cor =
+ event -> un.commitOrRollback;
+
+ if (cor -> parm == int_SNMP_SOutPDU_commit) {
+ /* "should not happen" */
+ (void) smux_close (protocolError);
+ smux_fd = NOTOK;
+ }
+ }
+ break;
+ }
+}
+
+/*
+ * Handle an incoming SNMP message
+ */
+void
+doit_smux()
+{
+ struct type_SNMP_SMUX__PDUs *event;
+
+ if (smux_wait(&event, NOTOK)==NOTOK) {
+ if (smux_errno==inProgress)
+ return;
+ log(LOG_WARNING, 0, "smux_wait: %s [%s]", smux_error(smux_errno),
+ smux_info);
+ smux_fd = NOTOK;
+ return;
+ }
+
+ switch (event -> offset) {
+ case type_SNMP_SMUX__PDUs_registerResponse:
+ {
+ struct type_SNMP_RRspPDU *rsp =
+ event -> un.registerResponse;
+
+ if (rsp -> parm == int_SNMP_RRspPDU_failure) {
+ log(LOG_WARNING,0,"SMUX registration of subtree failed");
+ dont_bother_anymore = 1;
+ (void) smux_close (goingDown);
+ break;
+ }
+ }
+ if (smux_trap(NULLOID, int_SNMP_generic__trap_coldStart, 0,
+ (struct type_SNMP_VarBindList *)0) == NOTOK) {
+ log(LOG_WARNING,0,"smux_trap: %s [%s]", smux_error (smux_errno),
+ smux_info);
+ break;
+ }
+ return;
+
+ case type_SNMP_SMUX__PDUs_get__request:
+ case type_SNMP_SMUX__PDUs_get__next__request:
+ get_smux (event -> un.get__request, event -> offset);
+ return;
+
+ case type_SNMP_SMUX__PDUs_close:
+ log(LOG_WARNING, 0, "SMUX close: %s",
+ smux_error (event -> un.close -> parm));
+ break;
+
+ case type_SNMP_SMUX__PDUs_set__request:
+ case type_SNMP_SMUX__PDUs_commitOrRollback:
+ set_smux (event);
+ return;
+
+ default:
+ log(LOG_WARNING,0,"bad SMUX operation: %d", event -> offset);
+ (void) smux_close (protocolError);
+ break;
+ }
+ smux_fd = NOTOK;
+}
+
+/*
+ * Inform snmpd that we are here and handling our MIBs
+ */
+void
+start_smux()
+{
+ int i;
+
+ for (i=0; i<NUMMIBS; i++) {
+ if ((se = getsmuxEntrybyname (mibs[i])) == NULL) {
+ log(LOG_WARNING,0,"no SMUX entry for \"%s\"", mibs[i]);
+ return;
+ }
+
+ /* Only open a new connection the first time through */
+ if (!i) {
+ if (smux_simple_open(&se->se_identity, mibs[i],
+ se->se_password, strlen(se->se_password))==NOTOK) {
+ if (smux_errno == inProgress)
+ return;
+
+ log(LOG_WARNING, 0,"smux_simple_open: %s [%s]",
+ smux_error(smux_errno), smux_info);
+ smux_fd = NOTOK;
+ return;
+ }
+ log(LOG_NOTICE,0, "SMUX open: %s \"%s\"",
+ oid2ode (&se->se_identity), se->se_name);
+ rock_and_roll = 1;
+ }
+
+ if (smux_register(subtree[i], -1, readWrite)==NOTOK) {
+ log(LOG_WARNING, 0,"smux_register: %s [%s]", smux_error(smux_errno),
+ smux_info);
+ smux_fd = NOTOK;
+ return;
+ }
+ }
+ log(LOG_NOTICE, 0, "SMUX registered");
+}
+
+/*
+ * Implements the DVMRP Route Table portion of the DVMRP MIB
+ */
+int
+o_dvmrpRouteTable (oi, v, offset)
+OI oi;
+register struct type_SNMP_VarBind *v;
+int offset;
+{
+ u_long src, mask;
+ int ifvar;
+ register OID oid = oi -> oi_name;
+ register OT ot = oi -> oi_type;
+ struct rtentry *rt = NULL;
+
+ ifvar = (int) ot -> ot_info;
+ switch (offset) {
+ case type_SNMP_SMUX__PDUs_get__request:
+ if (!get_address(oid, &src, ot->ot_name->oid_nelem)
+ || !get_address(oid, &mask, ot->ot_name->oid_nelem+4)
+ || !(rt = snmp_find_route(src,mask)))
+ return int_SNMP_error__status_noSuchName;
+ break;
+
+ case type_SNMP_SMUX__PDUs_get__next__request:
+
+ /* Check if we're requesting the first row */
+ if (oid->oid_nelem < ot->ot_name->oid_nelem+8) {
+ OID new;
+
+ /* Get partial specification (if any) */
+ get_address(oid, &src, ot->ot_name->oid_nelem);
+ get_address(oid, &mask, ot->ot_name->oid_nelem+4);
+
+ if (!next_route(&rt,src,mask)) /* Get first entry */
+ return NOTOK;
+
+ /* Extend by 8 more ints to hold index columns */
+ new = oid_extend (oid, ot->ot_name->oid_nelem+8-oid->oid_nelem);
+ if (new == NULLOID)
+ return NOTOK;
+
+ put_address(new, rt->rt_origin, ot->ot_name->oid_nelem);
+ put_address(new, rt->rt_originmask, ot->ot_name->oid_nelem+4);
+
+ if (v -> name)
+ free_SNMP_ObjectName (v -> name);
+ v -> name = new;
+
+ /* Else we start from a previous row */
+ } else {
+ int i = ot -> ot_name -> oid_nelem;
+
+ /* Get the lowest entry in the table > the given grp/src/mask */
+ get_address(oid, &src, ot->ot_name->oid_nelem);
+ get_address(oid, &mask, ot->ot_name->oid_nelem+4);
+ if (!next_route(&rt, src,mask))
+ return NOTOK;
+
+ put_address(oid, rt->rt_origin, ot->ot_name->oid_nelem);
+ put_address(oid, rt->rt_originmask, ot->ot_name->oid_nelem+4);
+ }
+ break;
+
+ default:
+ return int_SNMP_error__status_genErr;
+ }
+
+ switch (ifvar) {
+ case dvmrpRouteUpstreamNeighbor: {
+ struct sockaddr_in tmp;
+ tmp.sin_addr.s_addr = rt->rt_gateway;
+ return o_ipaddr (oi, v, &tmp);
+ }
+
+ case dvmrpRouteInVifIndex:
+ return o_integer (oi, v, rt->rt_parent);
+
+ case dvmrpRouteMetric:
+ return o_integer (oi, v, rt->rt_metric);
+
+ case dvmrpRouteExpiryTime:
+ return o_integer (oi, v, rt->rt_timer*100);
+
+ default:
+ return int_SNMP_error__status_noSuchName;
+ }
+}
+
+/*
+ * Implements the DVMRP Routing Next Hop Table portion of the DVMRP MIB
+ */
+int
+o_dvmrpRouteNextHopTable (oi, v, offset)
+OI oi;
+register struct type_SNMP_VarBind *v;
+int offset;
+{
+ u_long src, mask;
+ vifi_t vifi;
+ int ifvar;
+ register OID oid = oi -> oi_name;
+ register OT ot = oi -> oi_type;
+ struct rtentry *rt = NULL;
+
+ ifvar = (int) ot -> ot_info;
+ switch (offset) {
+ case type_SNMP_SMUX__PDUs_get__request:
+ if (oid->oid_nelem != ot->ot_name->oid_nelem+9)
+ return int_SNMP_error__status_noSuchName;
+
+ if (!get_address(oid, &src, ot->ot_name->oid_nelem)
+ || !get_address(oid, &mask, ot->ot_name->oid_nelem+4)
+ || (!(rt=snmp_find_route(src,mask))))
+ return int_SNMP_error__status_noSuchName;
+
+ vifi = oid->oid_elements[ot->ot_name->oid_nelem+8];
+ if (!(VIFM_ISSET(vifi, rt->rt_children)))
+ return int_SNMP_error__status_noSuchName;
+ break;
+
+ case type_SNMP_SMUX__PDUs_get__next__request:
+
+ /* Check if we're requesting the first row */
+ if (oid->oid_nelem < ot->ot_name->oid_nelem+9) {
+ OID new;
+
+ get_address(oid, &src, ot->ot_name->oid_nelem);
+ get_address(oid, &mask, ot->ot_name->oid_nelem+4);
+
+ /* Find first child vif */
+ vifi=0;
+ if (!next_route_child(&rt, src, mask, &vifi))
+ return NOTOK;
+
+ /* Extend by 9 more ints to hold index columns */
+ new = oid_extend (oid, ot->ot_name->oid_nelem+9-oid->oid_nelem);
+ if (new == NULLOID)
+ return NOTOK;
+
+ put_address(new, rt->rt_origin, ot->ot_name->oid_nelem);
+ put_address(new, rt->rt_originmask, ot->ot_name->oid_nelem+4);
+ new->oid_elements[ot->ot_name->oid_nelem+8] = vifi;
+
+ if (v -> name)
+ free_SNMP_ObjectName (v -> name);
+ v -> name = new;
+
+ /* Else we start from a previous row */
+ } else {
+ int i = ot -> ot_name -> oid_nelem;
+
+ /* Get the lowest entry in the table > the given grp/src/mask */
+ vifi = oid->oid_elements[oid->oid_nelem-1] + 1;
+ if (!get_address(oid, &src, ot->ot_name->oid_nelem)
+ || !get_address(oid, &mask, ot->ot_name->oid_nelem+4)
+ || !next_route_child(&rt, src, mask, &vifi))
+ return NOTOK;
+
+ put_address(oid, rt->rt_origin, ot->ot_name->oid_nelem);
+ put_address(oid, rt->rt_originmask, ot->ot_name->oid_nelem+4);
+ oid->oid_elements[ot->ot_name->oid_nelem+8] = vifi;
+ }
+ break;
+
+ default:
+ return int_SNMP_error__status_genErr;
+ }
+
+ switch (ifvar) {
+
+ case dvmrpRouteNextHopType:
+ return o_integer (oi, v, (VIFM_ISSET(vifi, rt->rt_leaves))? 1 : 2);
+
+ default:
+ return int_SNMP_error__status_noSuchName;
+ }
+}
+
+/*
+ * Implements the IP Multicast Route Table portion of the Multicast MIB
+ */
+int
+o_ipMRouteTable (oi, v, offset)
+OI oi;
+register struct type_SNMP_VarBind *v;
+int offset;
+{
+ u_long src, grp, mask;
+ int ifvar;
+ register OID oid = oi -> oi_name;
+ register OT ot = oi -> oi_type;
+ struct gtable *gt = NULL;
+ struct stable *st = NULL;
+static struct sioc_sg_req sg_req;
+
+ ifvar = (int) ot -> ot_info;
+ switch (offset) {
+ case type_SNMP_SMUX__PDUs_get__request:
+ if (!get_address(oid, &grp, ot->ot_name->oid_nelem)
+ || !get_address(oid, &src, ot->ot_name->oid_nelem+4)
+ || !get_address(oid, &mask, ot->ot_name->oid_nelem+8)
+ || (mask != 0xFFFFFFFF) /* we keep sources now, not subnets */
+ || !(gt = find_grp(grp))
+ || !(st = find_grp_src(gt,src)))
+ return int_SNMP_error__status_noSuchName;
+ break;
+
+ case type_SNMP_SMUX__PDUs_get__next__request:
+
+ /* Check if we're requesting the first row */
+ if (oid->oid_nelem < ot->ot_name->oid_nelem+12) {
+ OID new;
+
+ /* Get partial specification (if any) */
+ get_address(oid, &grp, ot->ot_name->oid_nelem);
+ get_address(oid, &src, ot->ot_name->oid_nelem+4);
+ get_address(oid, &mask, ot->ot_name->oid_nelem+8);
+
+ if (!next_grp_src_mask(&gt,&st,grp,src,mask)) /* Get first entry */
+ return NOTOK;
+
+ /* Extend by 12 more ints to hold index columns */
+ new = oid_extend (oid, ot->ot_name->oid_nelem+12-oid->oid_nelem);
+ if (new == NULLOID)
+ return NOTOK;
+
+ put_address(new, gt->gt_mcastgrp, ot->ot_name->oid_nelem);
+ put_address(new, st->st_origin, ot->ot_name->oid_nelem+4);
+ put_address(new, 0xFFFFFFFF, ot->ot_name->oid_nelem+8);
+
+ if (v -> name)
+ free_SNMP_ObjectName (v -> name);
+ v -> name = new;
+
+ /* Else we start from a previous row */
+ } else {
+ int i = ot -> ot_name -> oid_nelem;
+
+ /* Get the lowest entry in the table > the given grp/src/mask */
+ get_address(oid, &grp, ot->ot_name->oid_nelem);
+ get_address(oid, &src, ot->ot_name->oid_nelem+4);
+ get_address(oid, &mask, ot->ot_name->oid_nelem+8);
+ if (!next_grp_src_mask(&gt, &st, grp,src,mask))
+ return NOTOK;
+
+ put_address(oid, gt->gt_mcastgrp, ot->ot_name->oid_nelem);
+ put_address(oid, st->st_origin, ot->ot_name->oid_nelem+4);
+ put_address(oid, 0xFFFFFFFF, ot->ot_name->oid_nelem+8);
+ }
+ break;
+
+ default:
+ return int_SNMP_error__status_genErr;
+ }
+
+ switch (ifvar) {
+ case ipMRouteUpstreamNeighbor: {
+ struct sockaddr_in tmp;
+ tmp.sin_addr.s_addr = gt->gt_route->rt_gateway;
+ return o_ipaddr (oi, v, &tmp);
+ }
+
+ case ipMRouteInIfIndex:
+ return o_integer (oi, v, gt->gt_route->rt_parent);
+
+ case ipMRouteUpTime: {
+ time_t currtime;
+ time(&currtime);
+ return o_integer (oi, v, (currtime - gt->gt_ctime)*100);
+ }
+
+ case ipMRouteExpiryTime:
+ return o_integer (oi, v, gt->gt_timer*100);
+
+ case ipMRoutePkts:
+ refresh_sg(&sg_req, gt, st);
+ return o_integer (oi, v, sg_req.pktcnt);
+
+ case ipMRouteOctets:
+ refresh_sg(&sg_req, gt, st);
+ return o_integer (oi, v, sg_req.bytecnt);
+
+ case ipMRouteDifferentInIfIndexes:
+ refresh_sg(&sg_req, gt, st);
+ return o_integer (oi, v, sg_req.wrong_if);
+
+ case ipMRouteProtocol:
+ return o_integer (oi, v, 4);
+
+ default:
+ return int_SNMP_error__status_noSuchName;
+ }
+}
+
+/*
+ * Implements the IP Multicast Routing Next Hop Table portion of the Multicast
+ * MIB
+ */
+int
+o_ipMRouteNextHopTable (oi, v, offset)
+OI oi;
+register struct type_SNMP_VarBind *v;
+int offset;
+{
+ u_long src, grp, mask, addr;
+ vifi_t vifi;
+ int ifvar;
+ register OID oid = oi -> oi_name;
+ register OT ot = oi -> oi_type;
+ struct gtable *gt;
+ struct stable *st;
+
+ ifvar = (int) ot -> ot_info;
+ switch (offset) {
+ case type_SNMP_SMUX__PDUs_get__request:
+ if (oid->oid_nelem != ot->ot_name->oid_nelem+17)
+ return int_SNMP_error__status_noSuchName;
+
+ if (!get_address(oid, &grp, ot->ot_name->oid_nelem)
+ || !get_address(oid, &src, ot->ot_name->oid_nelem+4)
+ || !get_address(oid, &mask, ot->ot_name->oid_nelem+8)
+ || !get_address(oid, &addr, ot->ot_name->oid_nelem+13)
+ || grp!=addr
+ || mask!=0xFFFFFFFF
+ || (!(gt=find_grp(grp)))
+ || (!(st=find_grp_src(gt,src))))
+ return int_SNMP_error__status_noSuchName;
+
+ vifi = oid->oid_elements[ot->ot_name->oid_nelem+12];
+ if (!(VIFM_ISSET(vifi, gt->gt_route->rt_children)))
+ return int_SNMP_error__status_noSuchName;
+ break;
+
+ case type_SNMP_SMUX__PDUs_get__next__request:
+
+ /* Check if we're requesting the first row */
+ if (oid->oid_nelem < ot->ot_name->oid_nelem+17) {
+ OID new;
+
+ get_address(oid, &grp, ot->ot_name->oid_nelem);
+ get_address(oid, &src, ot->ot_name->oid_nelem+4);
+ get_address(oid, &mask, ot->ot_name->oid_nelem+8);
+
+ /* Find first child vif */
+ vifi=0;
+ if (!next_child(&gt, &st, grp, src, mask, &vifi))
+ return NOTOK;
+
+ /* Extend by 17 more ints to hold index columns */
+ new = oid_extend (oid, ot->ot_name->oid_nelem+17-oid->oid_nelem);
+ if (new == NULLOID)
+ return NOTOK;
+
+ put_address(new, gt->gt_mcastgrp, ot->ot_name->oid_nelem);
+ put_address(new, st->st_origin, ot->ot_name->oid_nelem+4);
+ put_address(new, 0xFFFFFFFF, ot->ot_name->oid_nelem+8);
+ new->oid_elements[ot->ot_name->oid_nelem+12] = vifi;
+ put_address(new, gt->gt_mcastgrp, ot->ot_name->oid_nelem+13);
+
+ if (v -> name)
+ free_SNMP_ObjectName (v -> name);
+ v -> name = new;
+
+ /* Else we start from a previous row */
+ } else {
+ int i = ot -> ot_name -> oid_nelem;
+
+ /* Get the lowest entry in the table > the given grp/src/mask */
+ vifi = oid->oid_elements[oid->oid_nelem-1] + 1;
+ if (!get_address(oid, &grp, ot->ot_name->oid_nelem)
+ || !get_address(oid, &src, ot->ot_name->oid_nelem+4)
+ || !get_address(oid, &mask, ot->ot_name->oid_nelem+8)
+ || !next_child(&gt, &st, grp, src, mask, &vifi))
+ return NOTOK;
+
+ put_address(oid, gt->gt_mcastgrp, ot->ot_name->oid_nelem);
+ put_address(oid, st->st_origin, ot->ot_name->oid_nelem+4);
+ put_address(oid, 0xFFFFFFFF, ot->ot_name->oid_nelem+8);
+ oid->oid_elements[ot->ot_name->oid_nelem+12] = vifi;
+ put_address(oid, gt->gt_mcastgrp, ot->ot_name->oid_nelem+13);
+ }
+ break;
+
+ default:
+ return int_SNMP_error__status_genErr;
+ }
+
+ switch (ifvar) {
+
+ case ipMRouteNextHopState:
+ return o_integer (oi, v, (VIFM_ISSET(vifi, gt->gt_grpmems))? 2 : 1);
+
+ /* Currently equal to ipMRouteUpTime */
+ case ipMRouteNextHopUpTime: {
+ time_t currtime;
+ time(&currtime);
+ return o_integer (oi, v, (currtime - gt->gt_ctime)*100);
+ }
+
+ case ipMRouteNextHopExpiryTime:
+ return o_integer (oi, v, gt->gt_prsent_timer);
+
+ case ipMRouteNextHopClosestMemberHops:
+ return o_integer (oi, v, 0);
+
+ case ipMRouteNextHopProtocol:
+ return o_integer (oi, v, 4);
+
+ default:
+ return int_SNMP_error__status_noSuchName;
+ }
+}