1306 lines
37 KiB
C
1306 lines
37 KiB
C
/*
|
|
* 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(>,&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(>, &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(>, &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(>, &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;
|
|
}
|
|
}
|