diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-12-14 01:46:23 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-12-14 01:46:23 +0000 |
commit | acfc88313dd86a33e6c0424cda0578b15a539e42 (patch) | |
tree | 8831738b9326fa2111446b81b93fee2285da3e07 /usr.sbin/mrouted/snmp.c | |
parent | a10a6913325bfa093081ff08628e32d3b0f2a565 (diff) |
from netbsd; update to mrouted 3.8
Diffstat (limited to 'usr.sbin/mrouted/snmp.c')
-rw-r--r-- | usr.sbin/mrouted/snmp.c | 1824 |
1 files changed, 902 insertions, 922 deletions
diff --git a/usr.sbin/mrouted/snmp.c b/usr.sbin/mrouted/snmp.c index 5298da5dbc8..6f203efc826 100644 --- a/usr.sbin/mrouted/snmp.c +++ b/usr.sbin/mrouted/snmp.c @@ -1,57 +1,136 @@ -/* $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> - */ - +/* $NetBSD: snmp.c,v 1.3 1995/12/10 10:07:16 mycroft Exp $ */ #include "defs.h" -#include <string.h> +#include <netinet/in_var.h> #include "snmp.h" +#include "snmplib/asn1.h" +#include "snmplib/party.h" +#include "snmplib/snmp_impl.h" +#define MROUTED +#include "snmpd/snmp_vars.h" + + u_short dest_port = 0; + int sdlen = 0; + +struct addrCache { + u_long addr; + int status; +#define UNUSED 0 +#define USED 1 +#define OLD 2 +}; -#define NUMMIBS 2 -#define SNMPD_RETRY_INTERVAL 300 /* periodic snmpd probe interval */ +static struct addrCache addrCache[10]; -char *mibs[]={ "ipMRouteMIB", "dvmrpMIB" }; +/* + * Initialize the SNMP part of mrouted + */ +int /* returns: 0 on success, true on error */ +snmp_init(dest_port) + u_short dest_port; +{ + u_long myaddr; + int ret; + struct partyEntry *pp; + struct sockaddr_in me; + int index, sd, portlist[32]; + + init_snmp(); + /* init_mib(); why was this here? */ + if (read_party_database("/etc/party.conf") > 0){ + fprintf(stderr, "Couldn't read party database from /etc/party.conf\n"); + exit(0); + } + if (read_context_database("/etc/context.conf") > 0){ + fprintf(stderr, "Couldn't read context database from /etc/context.conf\n"); + exit(0); + } + if (read_acl_database("/etc/acl.conf") > 0){ + fprintf(stderr, "Couldn't read acl database from /etc/acl.conf\n"); + exit(0); + } + if (read_view_database("/etc/view.conf") > 0){ + fprintf(stderr, "Couldn't read view database from /etc/view.conf\n"); + exit(0); + } -extern int o_ipMRouteTable(); -extern int o_ipMRouteNextHopTable(); -extern int o_dvmrpRouteTable(); -extern int o_dvmrpRouteNextHopTable(); + myaddr = get_myaddr(); + if (ret = agent_party_init(myaddr, ".1.3.6.1")){ + if (ret == 1){ + fprintf(stderr, "Conflict found with initial noAuth/noPriv parties... continuing\n"); + } else if (ret == -1){ + fprintf(stderr, "Error installing initial noAuth/noPriv parties, exiting\n"); + exit(1); + } else { + fprintf(stderr, "Unknown error, exiting\n"); + exit(2); + } + } - 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]; + printf("Opening port(s): "); + fflush(stdout); + party_scanInit(); + for(pp = party_scanNext(); pp; pp = party_scanNext()){ + if ((pp->partyTDomain != DOMAINSNMPUDP) + || bcmp((char *)&myaddr, pp->partyTAddress, 4)) + continue; /* don't listen for non-local parties */ + + dest_port = 0; + bcopy(pp->partyTAddress + 4, &dest_port, 2); + for(index = 0; index < sdlen; index++) + if (dest_port == portlist[index]) + break; + if (index < sdlen) /* found a hit before the end of the list */ + continue; + printf("%u ", dest_port); + fflush(stdout); + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0){ + perror("socket"); + return 1; + } + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + /* already in network byte order (I think) */ + me.sin_port = dest_port; + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + return 2; + } + register_input_handler(sd, snmp_read_packet); + portlist[sdlen] = dest_port; + if (++sdlen == 32){ + printf("No more sockets... ignoring rest of file\n"); + break; + } + } + printf("\n"); + bzero((char *)addrCache, sizeof(addrCache)); +} /* - * Place an IP address into an OID starting at element n + * Place an IP address into an OID starting at element n */ void -put_address(oid, addr, n) - OID oid; +put_address(name, addr, n) + oid *name; u_long addr; int n; { int i; for (i=n+3; i>=n+0; i--) { - oid->oid_elements[i] = addr & 0xFF; + name[i] = addr & 0xFF; addr >>= 8; } } /* Get an IP address from an OID starting at element n */ int -get_address(oid, addr, n) - OID oid; +get_address(name, length, addr, n) + oid *name; + int length; u_long *addr; int n; { @@ -60,106 +139,75 @@ get_address(oid, addr, n) (*addr) = 0; - if (oid -> oid_nelem < n+4) + if (length < n+4) return 0; for (i=n; i<n+4; i++) { (*addr) <<= 8; - if (i >= oid->oid_nelem) + if (i >= length) ok = 0; else - (*addr) |= oid->oid_elements[i]; + (*addr) |= name[i]; } - return ok; } /* - * Attempt to start up SMUX protocol + * Implements scalar objects from DVMRP and Multicast MIBs */ -void -try_smux_init() +u_char * +o_scalar(vp, name, length, exact, var_len, write_method) + register struct variable *vp; /* IN - pointer to variable entry that points here */ + register oid *name; /* IN/OUT - input name requested, output name found */ + register int *length; /* IN/OUT - length of input and output oid's */ + int exact; /* IN - TRUE if an exact match was requested. */ + int *var_len; /* OUT - length of variable or 0 if function returned. */ + int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ { - 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; -} + int result; -/* - * 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; - } + *write_method = 0; + result = compare(name, *length, vp->name, (int)vp->namelen); + if ((exact && (result != 0)) || (!exact && (result >= 0))) + return NULL; + + bcopy((char *)vp->name, (char *)name, + (int)vp->namelen * sizeof(oid)); + *length = vp->namelen; + *var_len = sizeof(long); - switch (ifvar) { - case ipMRouteEnable: - return o_integer (oi, v, 1); + switch (vp->magic) { - case dvmrpVersion: { - static char buff[15]; + case ipMRouteEnable: + long_return = 1; + return (u_char *) &long_return; + + case dvmrpVersion: { + static char buff[15]; - sprintf(buff, "mrouted%d.%d", PROTOCOL_VERSION, MROUTED_VERSION); - return o_string (oi, v, buff, strlen (buff)); - } + sprintf(buff, "mrouted%d.%d", PROTOCOL_VERSION, MROUTED_VERSION); + *var_len = strlen(buff); + return (u_char *)buff; + } - case dvmrpGenerationId: - return o_integer (oi, v, dvmrp_genid); + case dvmrpGenerationId: + long_return = dvmrp_genid; + return (u_char *) &long_return; - default: - return int_SNMP_error__status_noSuchName; + default: + ERROR(""); } + return NULL; } -/* +/* * Find if a specific scoped boundary exists on a Vif */ struct vif_acl * find_boundary(vifi, addr, mask) - int vifi; - int addr; - int mask; + vifi_t vifi; + u_long addr; + u_long mask; { struct vif_acl *n; @@ -171,13 +219,13 @@ find_boundary(vifi, addr, mask) } /* - * Find the next scoped boundary in order after a given spec + * Find the lowest boundary >= (V,A,M) spec */ struct vif_acl * next_boundary(vifi, addr, mask) - int *vifi; - int addr; - int mask; + vifi_t *vifi; + u_long addr; + u_long mask; { struct vif_acl *bestn, *n; int i; @@ -185,9 +233,9 @@ next_boundary(vifi, addr, mask) 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 + 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; } @@ -202,97 +250,100 @@ next_boundary(vifi, addr, mask) /* * Implements the Boundary Table portion of the DVMRP MIB */ -static int -o_dvmrpBoundaryTable (oi, v, offset) -OI oi; -register struct type_SNMP_VarBind *v; +u_char * +o_dvmrpBoundaryTable(vp, name, length, exact, var_len, write_method) + register struct variable *vp; /* IN - pointer to variable entry that points here */ + register oid *name; /* IN/OUT - input name requested, output name found */ + register int *length; /* IN/OUT - length of input and output oid's */ + int exact; /* IN - TRUE if an exact match was requested. */ + int *var_len; /* OUT - length of variable or 0 if function returned. */ + int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ { - int ifvar, vifi, - addr, mask; - register OID oid = oi -> oi_name; - register OT ot = oi -> oi_type; + vifi_t vifi; + u_long addr, mask; struct vif_acl *bound; + oid newname[MAX_NAME_LEN]; + int len; - 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; + /* Copy name OID to new OID */ + bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); - if ((vifi = oid -> oid_elements[ot-> ot_name->oid_nelem]) >= numvifs) - return int_SNMP_error__status_noSuchName; + if (exact) { + if (*length != vp->namelen + 9) + return NULL; - 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 ((vifi = name[vp->namelen]) >= numvifs) + return NULL; - 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); - } + if (!get_address(name, *length, &addr, vp->namelen+1) + || !get_address(name, *length, &mask, vp->namelen+5)) + return NULL; - bound = next_boundary(&vifi,addr,mask); - if (!bound) - return NOTOK; + if (!(bound = find_boundary(vifi, addr, mask))) + return NULL; + + bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid)); + } else { + len = *length; + if (compare(name, *length, vp->name, vp->namelen) < 0) + len = vp->namelen; + + if (len < vp->namelen + 9) { /* get first entry */ + + if (len == vp->namelen) { + vifi = addr = mask = 0; + } else { + vifi = name[vp->namelen]; + get_address(name, len, &addr, vp->namelen+1); + get_address(name, len, &mask, vp->namelen+5); + } - 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); + bound = next_boundary(&vifi,addr,mask); + if (!bound) + return NULL; - if (v -> name) - free_SNMP_ObjectName (v -> name); - v -> name = new; + newname[vp->namelen] = vifi; + put_address(newname, bound->acl_addr, vp->namelen+1); + put_address(newname, bound->acl_mask, vp->namelen+5); } else { /* get next entry given previous */ - int i = ot -> ot_name -> oid_nelem; + vifi = name[vp->namelen]; + get_address(name, *length, &addr, vp->namelen+1); + get_address(name, *length, &mask, vp->namelen+5); - 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; + return NULL; - 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; + newname[vp->namelen] = vifi; + put_address(newname, bound->acl_addr, vp->namelen+1); + put_address(newname, bound->acl_mask, vp->namelen+5); } - break; - - default: - return int_SNMP_error__status_genErr; } - switch (ifvar) { + /* Save new OID */ + *length = vp->namelen + 9; + bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid)); + *write_method = 0; + *var_len = sizeof(long); + + switch (vp->magic) { case dvmrpBoundaryVifIndex: - return o_integer (oi, v, vifi); + long_return = vifi; + return (u_char *) &long_return; - default: - return int_SNMP_error__status_noSuchName; + default: + ERROR(""); } + return NULL; } -/* - * Given a vif index and address, return the next greater neighbor entry +/* + * Find the lowest neighbor >= (V,A) spec */ struct listaddr * next_neighbor(vifi, addr) - int *vifi; - int addr; + vifi_t *vifi; + u_long addr; { struct listaddr *bestn, *n; int i; @@ -300,7 +351,7 @@ next_neighbor(vifi, addr) 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) + if ((i > *vifi || n->al_addr >= addr) && (!bestn || n->al_addr < bestn->al_addr)) bestn = n; } @@ -317,8 +368,8 @@ next_neighbor(vifi, addr) */ struct listaddr * find_neighbor(vifi, addr) - int vifi; - int addr; + vifi_t vifi; + u_long addr; { struct listaddr *n; @@ -329,979 +380,908 @@ find_neighbor(vifi, addr) 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; +u_char * +o_dvmrpNeighborTable(vp, name, length, exact, var_len, write_method) + register struct variable *vp; /* IN - pointer to variable entry that points here */ + register oid *name; /* IN/OUT - input name requested, output name found */ + register int *length; /* IN/OUT - length of input and output oid's */ + int exact; /* IN - TRUE if an exact match was requested. */ + int *var_len; /* OUT - length of variable or 0 if function returned. */ + int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ { - int ifvar, vifi, - addr; - register OID oid = oi -> oi_name; - register OT ot = oi -> oi_type; + vifi_t vifi; + u_long addr, mask; struct listaddr *neighbor; + oid newname[MAX_NAME_LEN]; + int len; - 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; + /* Copy name OID to new OID */ + bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); - if ((vifi = oid -> oid_elements[ot-> ot_name->oid_nelem]) >= numvifs) - return int_SNMP_error__status_noSuchName; + if (exact) { + if (*length != vp->namelen + 5) + return NULL; - if (!get_address(oid, &addr, ot->ot_name->oid_nelem+1)) - return int_SNMP_error__status_noSuchName; + if ((vifi = name[vp->namelen]) >= numvifs) + return NULL; - if (!(neighbor = find_neighbor(vifi, addr))) - return int_SNMP_error__status_noSuchName; - break; + if (!get_address(name, *length, &addr, vp->namelen+1)) + return NULL; - case type_SNMP_SMUX__PDUs_get__next__request: - if (oid->oid_nelem < ot->ot_name->oid_nelem + 5) { - OID new; + if (!(neighbor = find_neighbor(vifi, addr))) + return NULL; - 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); - } + bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid)); + } else { + len = *length; + if (compare(name, *length, vp->name, vp->namelen) < 0) + len = vp->namelen; - neighbor = next_neighbor(&vifi,addr); /* Get first entry */ - if (!neighbor) - return NOTOK; + if (len < vp->namelen + 5) { /* get first entry */ - 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 (len == vp->namelen) { + vifi = addr = 0; + } else { + vifi = name[vp->namelen]; + get_address(name, len, &addr, vp->namelen+1); + } - if (v -> name) - free_SNMP_ObjectName (v -> name); - v -> name = new; + neighbor = next_neighbor(&vifi,addr); + if (!neighbor) + return NULL; + newname[vp->namelen] = vifi; + put_address(newname, neighbor->al_addr, vp->namelen+1); } else { /* get next entry given previous */ - int i = ot -> ot_name -> oid_nelem; + vifi = name[vp->namelen]; + get_address(name, *length, &addr, vp->namelen+1); - vifi = oid->oid_elements[i]; - get_address(oid, &addr, ot->ot_name->oid_nelem+1); if (!(neighbor = next_neighbor(&vifi,addr+1))) - return NOTOK; + return NULL; - put_address(oid, neighbor->al_addr, ot->ot_name->oid_nelem+1); - oid->oid_elements[i] = vifi; - oid->oid_nelem = i + 5; + newname[vp->namelen] = vifi; + put_address(newname, neighbor->al_addr, vp->namelen+1); } - break; - - default: - return int_SNMP_error__status_genErr; } - switch (ifvar) { + /* Save new OID */ + *length = vp->namelen + 5; + bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid)); + *write_method = 0; + *var_len = sizeof(long); + + switch (vp->magic) { case dvmrpNeighborUpTime: { time_t currtime; time(&currtime); - return o_integer (oi, v, (currtime - neighbor->al_ctime)*100); + long_return = (currtime - neighbor->al_ctime)*100; + return (u_char *) &long_return; } - case dvmrpNeighborExpiryTime: - return o_integer (oi, v, (NEIGHBOR_EXPIRE_TIME-neighbor->al_timer) * 100); + case dvmrpNeighborExpiryTime: + long_return = (NEIGHBOR_EXPIRE_TIME - neighbor->al_timer + + secs_remaining_offset()) * 100; + return (u_char *) &long_return; case dvmrpNeighborVersion: { static char buff[15]; sprintf(buff, "%d.%d", neighbor->al_pv, neighbor->al_mv); - return o_string (oi, v, buff, strlen (buff)); + *var_len = strlen(buff); + return (u_char *)buff; } - case dvmrpNeighborGenerationId: - return o_integer (oi, v, neighbor->al_genid); + case dvmrpNeighborGenerationId: + long_return = neighbor->al_genid; + return (u_char *) &long_return; - default: - return int_SNMP_error__status_noSuchName; + default: + ERROR(""); + } + return NULL; +} + +/* Look up ifIndex given uvifs[ifnum].uv_lcl_addr */ +struct in_ifaddr * /* returns: in_ifaddr structure, or null on error */ +ipaddr_to_ifindex(ipaddr, ifIndex) + u_long ipaddr; + int *ifIndex; +{ + int interface; +static struct in_ifaddr in_ifaddr; + + Interface_Scan_Init(); + for (;;) { + if (Interface_Scan_Next(&interface, (char *)0, NULL, &in_ifaddr) == 0) + return NULL; + + if (((struct sockaddr_in *) &(in_ifaddr.ia_addr))->sin_addr.s_addr + == ipaddr) { + *ifIndex = interface; + return &in_ifaddr; + } } } /* - * Given a virtual interface number, make sure we have the current - * kernel information for that Vif. + * Find if a specific scoped boundary exists on a Vif */ -refresh_vif(v_req, ifnum) - struct sioc_vif_req *v_req; - int ifnum; +struct listaddr * +find_cache(grp, vifi) + u_long grp; + vifi_t vifi; { - static int lastq = -1; + struct listaddr *n; - 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; + for (n = uvifs[vifi].uv_groups; n != NULL; n = n->al_next) { + if (grp == n->al_addr) + return n; } + return NULL; } /* - * Implements the Multicast Routing Interface Table portion of the Multicast MIB + * Find the next group cache entry >= (A,V) spec */ -static int -o_ipMRouteInterfaceTable (oi, v, offset) -OI oi; -register struct type_SNMP_VarBind *v; -int offset; +struct listaddr * +next_cache(addr, vifi) + u_long addr; + vifi_t *vifi; { - int ifnum, - ifvar; - register OID oid = oi -> oi_name; - register OT ot = oi -> oi_type; -static struct sioc_vif_req v_req; + struct listaddr *bestn=NULL, *n; + int i, besti; + + /* Step through all entries looking for the next one */ + for (i = 0; i < numvifs; i++) { + for (n = uvifs[i].uv_groups; n; n=n->al_next) { + if ((n->al_addr > addr || (n->al_addr == addr && i >= *vifi)) + && (!bestn || n->al_addr < bestn->al_addr + || (n->al_addr == bestn->al_addr && i < besti))) { + bestn = n; + besti = i; + } + } + } - 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; + if (bestn) { + *vifi = besti; + return bestn; + } + return NULL; +} - case type_SNMP_SMUX__PDUs_get__next__request: - if (oid -> oid_nelem == ot -> ot_name -> oid_nelem) { - OID new; +/* + * Implements the IGMP Cache Table portion of the IGMP MIB + */ +u_char * +o_igmpCacheTable(vp, name, length, exact, var_len, write_method) + register struct variable *vp; /* IN - pointer to variable entry that points here */ + register oid *name; /* IN/OUT - input name requested, output name found */ + register int *length; /* IN/OUT - length of input and output oid's */ + int exact; /* IN - TRUE if an exact match was requested. */ + int *var_len; /* OUT - length of variable or 0 if function returned. */ + int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ +{ + vifi_t vifi; + u_long grp; + int ifIndex; + struct listaddr *cache; + oid newname[MAX_NAME_LEN]; + int len; + struct in_ifaddr *in_ifaddr; + struct in_multi in_multi, *inm; + + /* Copy name OID to new OID */ + bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); + + if (exact) { + if (*length != vp->namelen + 5) + return NULL; + + if ((vifi = name[vp->namelen+4]) >= numvifs) + return NULL; + + if (!get_address(name, *length, &grp, vp->namelen)) + return NULL; + + if (!(cache = find_cache(grp, vifi))) + return NULL; + + bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid)); + } else { + len = *length; + if (compare(name, *length, vp->name, vp->namelen) < 0) + len = vp->namelen; + + if (len < vp->namelen + 5) { /* get first entry */ + + if (len == vp->namelen) { + vifi = grp = 0; + } else { + get_address(name, len, &grp, vp->namelen); + vifi = name[vp->namelen+4]; + } - ifnum = 0; + cache = next_cache(grp,&vifi); + if (!cache) + return NULL; - if ((new = oid_extend (oid, 1)) == NULLOID) - return NOTOK; - new -> oid_elements[new -> oid_nelem - 1] = ifnum; + put_address(newname, cache->al_addr, vp->namelen); + newname[vp->namelen+4] = vifi; + } else { /* get next entry given previous */ + get_address(name, *length, &grp, vp->namelen); + vifi = name[vp->namelen+4]+1; - if (v -> name) - free_SNMP_ObjectName (v -> name); - v -> name = new; + if (!(cache = next_cache(grp,&vifi))) + return NULL; - } else { - int i = ot -> ot_name -> oid_nelem; + put_address(newname, cache->al_addr, vp->namelen); + newname[vp->namelen+4] = vifi; + } + } - if ((ifnum = oid -> oid_elements[i] + 1) >= numvifs) - return NOTOK; + /* Save new OID */ + *length = vp->namelen + 5; + bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid)); + *write_method = 0; + *var_len = sizeof(long); - oid -> oid_elements[i] = ifnum; - oid -> oid_nelem = i + 1; - } - break; + /* Look up ifIndex given uvifs[vifi].uv_lcl_addr */ + in_ifaddr = ipaddr_to_ifindex(uvifs[vifi].uv_lcl_addr, &ifIndex); - default: - return int_SNMP_error__status_genErr; - } + switch (vp->magic) { - switch (ifvar) { - case ipMRouteInterfaceTtl: - return o_integer (oi, v, uvifs[ifnum].uv_threshold); + case igmpCacheSelf: + inm = in_ifaddr->ia_multiaddrs; + while (inm) { + klookup( (int)inm, (char *)&in_multi, sizeof(in_multi)); - 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); + if (in_multi.inm_addr.s_addr == cache->al_addr) { + long_return = 1; /* true */ + return (u_char *) &long_return; + } - 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); + inm = in_multi.inm_next; + } + long_return = 2; /* false */ + return (u_char *) &long_return; - case dvmrpVInterfaceLocalAddress: { - struct sockaddr_in tmp; - tmp.sin_addr.s_addr = uvifs[ifnum].uv_lcl_addr; - return o_ipaddr (oi, v, &tmp); - } + case igmpCacheLastReporter: + return (u_char *) &cache->al_genid; - 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 igmpCacheUpTime: { + time_t currtime; + time(&currtime); + long_return = (currtime - cache->al_ctime)*100; + return (u_char *) &long_return; } - case dvmrpVInterfaceRemoteSubnetMask: { - struct sockaddr_in tmp; - tmp.sin_addr.s_addr = uvifs[ifnum].uv_subnetmask; - return o_ipaddr (oi, v, &tmp); - } + case igmpCacheExpiryTime: + long_return = secs_remaining(cache->al_timerid)*100; + return (u_char *) &long_return; - case dvmrpVInterfaceMetric: - return o_integer (oi, v, uvifs[ifnum].uv_metric); + case igmpCacheStatus: + long_return = 1; + return (u_char *) &long_return; - case dvmrpVInterfaceRateLimit: - return o_integer (oi, v, uvifs[ifnum].uv_rate_limit); + default: + ERROR(""); + } + return NULL; +} - case dvmrpVInterfaceInPkts: - refresh_vif(&v_req, ifnum); - return o_integer(oi, v, v_req.icount); +/* + * Implements the IGMP Interface Table portion of the IGMP MIB + */ +u_char * +o_igmpInterfaceTable(vp, name, length, exact, var_len, write_method) + register struct variable *vp; /* IN - pointer to variable entry that points here */ + register oid *name; /* IN/OUT - input name requested, output name found */ + register int *length; /* IN/OUT - length of input and output oid's */ + int exact; /* IN - TRUE if an exact match was requested. */ + int *var_len; /* OUT - length of variable or 0 if function returned. */ + int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ +{ + oid newname[MAX_NAME_LEN]; + register int ifnum; + int result; +static struct sioc_vif_req v_req; - case dvmrpVInterfaceOutPkts: - refresh_vif(&v_req, ifnum); - return o_integer(oi, v, v_req.ocount); + /* Copy name OID to new OID */ + bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); + + /* find "next" interface */ + for(ifnum = 0; ifnum < numvifs; ifnum++){ + if (!(uvifs[ifnum].uv_flags & VIFF_QUERIER)) + continue; + newname[vp->namelen] = (oid)ifnum; + result = compare(name, *length, newname, (int)vp->namelen + 1); + if ((exact && (result == 0)) || (!exact && (result < 0))) + break; + } + if (ifnum >= numvifs) + return NULL; - case dvmrpVInterfaceInOctets: - refresh_vif(&v_req, ifnum); - return o_integer(oi, v, v_req.ibytes); + /* Save new OID */ + bcopy((char *)newname, (char *)name, ((int)vp->namelen + 1) * sizeof(oid)); + *length = vp->namelen + 1; + *write_method = 0; + *var_len = sizeof(long); - case dvmrpVInterfaceOutOctets: - refresh_vif(&v_req, ifnum); - return o_integer(oi, v, v_req.obytes); + switch (vp->magic){ + + case igmpInterfaceQueryInterval: + long_return = GROUP_QUERY_INTERVAL; + return (u_char *) &long_return; + + case igmpInterfaceStatus: + long_return = 1; /* active */ + return (u_char *) &long_return; default: - return int_SNMP_error__status_noSuchName; + ERROR(""); } + return NULL; } -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 + * Given a virtual interface number, make sure we have the current + * kernel information for that Vif. */ -void -init_mib() +refresh_vif(v_req, ifnum) + struct sioc_vif_req *v_req; + int ifnum; { - register OT ot; - int i; + static int lastq = -1; - 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; - } + 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; + } } /* - * Initialize the SNMP part of mrouted + * Implements the Multicast Routing Interface Table portion of the Multicast MIB */ -void -snmp_init() +u_char * +o_ipMRouteInterfaceTable(vp, name, length, exact, var_len, write_method) + register struct variable *vp; /* IN - pointer to variable entry that points here */ + register oid *name; /* IN/OUT - input name requested, output name found */ + register int *length; /* IN/OUT - length of input and output oid's */ + int exact; /* IN - TRUE if an exact match was requested. */ + int *var_len; /* OUT - length of variable or 0 if function returned. */ + int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ { - 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; + oid newname[MAX_NAME_LEN]; + register int ifnum; + int result; +static struct sioc_vif_req v_req; + + /* Copy name OID to new OID */ + bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); + + /* find "next" interface */ + for(ifnum = 0; ifnum < numvifs; ifnum++){ + newname[vp->namelen] = (oid)ifnum; + result = compare(name, *length, newname, (int)vp->namelen + 1); + if ((exact && (result == 0)) || (!exact && (result < 0))) + break; } - init_mib(); - try_smux_init(); -} + if (ifnum >= numvifs) + return NULL; -/* - * 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; + /* Save new OID */ + bcopy((char *)newname, (char *)name, ((int)vp->namelen + 1) * sizeof(oid)); + *length = vp->namelen + 1; + *write_method = 0; + *var_len = sizeof(long); - case type_SNMP_SMUX__PDUs_get__next__request: - if (!(method = ot -> ot_getfnx)) - goto get_next; - break; + switch (vp->magic){ - case type_SNMP_SMUX__PDUs_set__request: - if (!(method = ot -> ot_setfnx)) - goto no_name; - break; + case ipMRouteInterfaceTtl: + long_return = uvifs[ifnum].uv_threshold; + return (u_char *) &long_return; - default: - goto no_name; - } + case dvmrpVInterfaceType: + if (uvifs[ifnum].uv_flags & VIFF_SRCRT) + long_return = 2; + else if (uvifs[ifnum].uv_flags & VIFF_TUNNEL) + long_return = 1; + else if (uvifs[ifnum].uv_flags & VIFF_QUERIER) + long_return = 3; + else /* SUBNET */ + long_return = 4; + return (u_char *) &long_return; - 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; + case dvmrpVInterfaceState: + if (uvifs[ifnum].uv_flags & VIFF_DISABLED) + long_return = 3; + else if ((uvifs[ifnum].uv_flags & VIFF_DOWN) + || ((uvifs[ifnum].uv_flags & VIFF_TUNNEL) && (uvifs[ifnum].uv_neighbors==NULL))) + long_return = 2; + else /* UP */ + long_return = 1; + return (u_char *) &long_return; -out: ; - pdu -> error__index = idx; + case dvmrpVInterfaceLocalAddress: + return (u_char *) &uvifs[ifnum].uv_lcl_addr; - if (smux_response (pdu) == NOTOK) { - log(LOG_WARNING,0,"smux_response: %s [%s]", - smux_error (smux_errno), smux_info); - smux_fd = NOTOK; - } -} + case dvmrpVInterfaceRemoteAddress: + return (u_char *) ((uvifs[ifnum].uv_flags & VIFF_TUNNEL) ? + &uvifs[ifnum].uv_rmt_addr : + &uvifs[ifnum].uv_subnet); -/* - * 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; - } -} + case dvmrpVInterfaceRemoteSubnetMask: + return (u_char *) &uvifs[ifnum].uv_subnetmask; -/* - * 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; - } + case dvmrpVInterfaceMetric: + long_return = uvifs[ifnum].uv_metric; + return (u_char *) &long_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; + case dvmrpVInterfaceRateLimit: + long_return = uvifs[ifnum].uv_rate_limit; + return (u_char *) &long_return; - default: - log(LOG_WARNING,0,"bad SMUX operation: %d", event -> offset); - (void) smux_close (protocolError); - break; - } - smux_fd = NOTOK; -} + case dvmrpVInterfaceInPkts: + refresh_vif(&v_req, ifnum); + long_return = v_req.icount; + return (u_char *) &long_return; -/* - * Inform snmpd that we are here and handling our MIBs - */ -void -start_smux() -{ - int i; + case dvmrpVInterfaceOutPkts: + refresh_vif(&v_req, ifnum); + long_return = v_req.ocount; + return (u_char *) &long_return; - 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; - } + case dvmrpVInterfaceInOctets: + refresh_vif(&v_req, ifnum); + long_return = v_req.ibytes; + return (u_char *) &long_return; - 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"); + case dvmrpVInterfaceOutOctets: + refresh_vif(&v_req, ifnum); + long_return = v_req.obytes; + return (u_char *) &long_return; + + default: + ERROR(""); + } + return NULL; } /* - * Implements the DVMRP Route Table portion of the DVMRP MIB + * 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_char * +o_dvmrpRouteTable(vp, name, length, exact, var_len, write_method) + register struct variable *vp; /* IN - pointer to variable entry that points here */ + register oid *name; /* IN/OUT - input name requested, output name found */ + register int *length; /* IN/OUT - length of input and output oid's */ + int exact; /* IN - TRUE if an exact match was requested. */ + int *var_len; /* OUT - length of variable or 0 if function returned. */ + int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ { - u_long src, mask; - int ifvar; - register OID oid = oi -> oi_name; - register OT ot = oi -> oi_type; + u_long src, mask; + oid newname[MAX_NAME_LEN]; + int len; 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; + /* Copy name OID to new OID */ + bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); - case type_SNMP_SMUX__PDUs_get__next__request: + if (exact) { + if (*length != vp->namelen + 8) + return NULL; - /* Check if we're requesting the first row */ - if (oid->oid_nelem < ot->ot_name->oid_nelem+8) { - OID new; + if (!get_address(name, *length, &src, vp->namelen) + || !get_address(name, *length, &mask, vp->namelen+4)) + return NULL; - /* 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 (!(rt = snmp_find_route(src, mask))) + return NULL; - if (!next_route(&rt,src,mask)) /* Get first entry */ - return NOTOK; + bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid)); + } else { + len = *length; + if (compare(name, *length, vp->name, vp->namelen) < 0) + len = vp->namelen; - /* 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; + if (len < vp->namelen + 8) { /* get first entry */ - put_address(new, rt->rt_origin, ot->ot_name->oid_nelem); - put_address(new, rt->rt_originmask, ot->ot_name->oid_nelem+4); + if (len == vp->namelen) { + src = mask = 0; + } else { + get_address(name, len, &src, vp->namelen); + get_address(name, len, &mask, vp->namelen+4); + } - if (v -> name) - free_SNMP_ObjectName (v -> name); - v -> name = new; + if (!next_route(&rt,src,mask)) /* Get first entry */ + return NULL; - /* Else we start from a previous row */ - } else { - int i = ot -> ot_name -> oid_nelem; + put_address(newname, rt->rt_origin , vp->namelen); + put_address(newname, rt->rt_originmask, vp->namelen+4); + } else { /* get next entry given previous */ + get_address(name, *length, &src, vp->namelen); + get_address(name, *length, &mask, vp->namelen+4); - /* 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; + return NULL; - put_address(oid, rt->rt_origin, ot->ot_name->oid_nelem); - put_address(oid, rt->rt_originmask, ot->ot_name->oid_nelem+4); - } - break; + put_address(newname, rt->rt_origin, vp->namelen); + put_address(newname, rt->rt_originmask, vp->namelen+4); + } + } - default: - return int_SNMP_error__status_genErr; - } + /* Save new OID */ + *length = vp->namelen + 8; + bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid)); + *write_method = 0; + *var_len = sizeof(long); - switch (ifvar) { - case dvmrpRouteUpstreamNeighbor: { - struct sockaddr_in tmp; - tmp.sin_addr.s_addr = rt->rt_gateway; - return o_ipaddr (oi, v, &tmp); - } + switch (vp->magic) { + + case dvmrpRouteUpstreamNeighbor: + return (u_char *) &rt->rt_gateway; case dvmrpRouteInVifIndex: - return o_integer (oi, v, rt->rt_parent); + long_return = rt->rt_parent; + return (u_char *) &long_return; case dvmrpRouteMetric: - return o_integer (oi, v, rt->rt_metric); + long_return = rt->rt_metric; + return (u_char *) &long_return; case dvmrpRouteExpiryTime: - return o_integer (oi, v, rt->rt_timer*100); + long_return = (ROUTE_EXPIRE_TIME - rt->rt_timer + + secs_remaining_offset()) * 100; + return (u_char *) &long_return; - default: - return int_SNMP_error__status_noSuchName; - } + default: + ERROR(""); + } + return NULL; } -/* - * Implements the DVMRP Routing Next Hop Table portion of the DVMRP MIB +/* + * 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_char * +o_dvmrpRouteNextHopTable(vp, name, length, exact, var_len, write_method) + register struct variable *vp; /* IN - pointer to variable entry that points here */ + register oid *name; /* IN/OUT - input name requested, output name found */ + register int *length; /* IN/OUT - length of input and output oid's */ + int exact; /* IN - TRUE if an exact match was requested. */ + int *var_len; /* OUT - length of variable or 0 if function returned. */ + int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ { - u_long src, mask; - vifi_t vifi; - int ifvar; - register OID oid = oi -> oi_name; - register OT ot = oi -> oi_type; + u_long src, mask; + vifi_t vifi; struct rtentry *rt = NULL; + oid newname[MAX_NAME_LEN]; + int len; + + /* Copy name OID to new OID */ + bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); - 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 (exact) { + if (*length != vp->namelen + 9) + return NULL; - if (!get_address(oid, &src, ot->ot_name->oid_nelem) - || !get_address(oid, &mask, ot->ot_name->oid_nelem+4) + if (!get_address(name, *length, &src, vp->namelen) + || !get_address(name, *length, &mask, vp->namelen+4) || (!(rt=snmp_find_route(src,mask)))) - return int_SNMP_error__status_noSuchName; + return NULL; - vifi = oid->oid_elements[ot->ot_name->oid_nelem+8]; + vifi = name[vp->namelen+8]; if (!(VIFM_ISSET(vifi, rt->rt_children))) - return int_SNMP_error__status_noSuchName; - break; + return NULL; - case type_SNMP_SMUX__PDUs_get__next__request: + bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid)); + } else { + len = *length; + if (compare(name, *length, vp->name, vp->namelen) < 0) + len = vp->namelen; - /* Check if we're requesting the first row */ - if (oid->oid_nelem < ot->ot_name->oid_nelem+9) { - OID new; + if (len < vp->namelen + 9) { /* get first entry */ - get_address(oid, &src, ot->ot_name->oid_nelem); - get_address(oid, &mask, ot->ot_name->oid_nelem+4); + get_address(name, len, &src, vp->namelen); + get_address(name, len, &mask, vp->namelen+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; + return NULL; - /* 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) + put_address(newname, rt->rt_origin, vp->namelen); + put_address(newname, rt->rt_originmask, vp->namelen+4); + newname[vp->namelen+8] = vifi; + } else { /* get next entry given previous */ + vifi = name[vp->namelen+8] + 1; + if (!get_address(name, *length, &src, vp->namelen) + || !get_address(name, *length, &mask, vp->namelen+4) || !next_route_child(&rt, src, mask, &vifi)) - return NOTOK; + return NULL; - 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; + put_address(newname, rt->rt_origin, vp->namelen); + put_address(newname, rt->rt_originmask, vp->namelen+4); + newname[vp->namelen+8] = vifi; + } + } - default: - return int_SNMP_error__status_genErr; - } + /* Save new OID */ + *length = vp->namelen + 9; + bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid)); + *write_method = 0; + *var_len = sizeof(long); - switch (ifvar) { + switch (vp->magic) { - case dvmrpRouteNextHopType: - return o_integer (oi, v, (VIFM_ISSET(vifi, rt->rt_leaves))? 1 : 2); + case dvmrpRouteNextHopType: + long_return = (VIFM_ISSET(vifi, rt->rt_leaves))? 1 : 2; + return (u_char *) &long_return; - default: - return int_SNMP_error__status_noSuchName; - } + default: + ERROR(""); + } + return NULL; } -/* - * Implements the IP Multicast Route Table portion of the Multicast MIB +/* + * 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_char * +o_ipMRouteTable(vp, name, length, exact, var_len, write_method) + register struct variable *vp; /* IN - pointer to variable entry that points here */ + register oid *name; /* IN/OUT - input name requested, output name found */ + register int *length; /* IN/OUT - length of input and output oid's */ + int exact; /* IN - TRUE if an exact match was requested. */ + int *var_len; /* OUT - length of variable or 0 if function returned. */ + int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ { 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; + oid newname[MAX_NAME_LEN]; + int len; + + /* Copy name OID to new OID */ + bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); + + if (exact) { + if (*length != vp->namelen + 12) + return NULL; - 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) + if (!get_address(name, *length, &grp, vp->namelen) + || !get_address(name, *length, &src, vp->namelen+4) + || !get_address(name, *length, &mask, vp->namelen+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; + return NULL; - case type_SNMP_SMUX__PDUs_get__next__request: + bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid)); + } else { + len = *length; + if (compare(name, *length, vp->name, vp->namelen) < 0) + len = vp->namelen; - /* Check if we're requesting the first row */ - if (oid->oid_nelem < ot->ot_name->oid_nelem+12) { - OID new; + if (len < vp->namelen + 12) { /* get first entry */ - /* 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); + get_address(name, len, &grp, vp->namelen); + get_address(name, len, &src, vp->namelen+4); + get_address(name, len, &mask, vp->namelen+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; + return NULL; - /* Else we start from a previous row */ - } else { - int i = ot -> ot_name -> oid_nelem; + put_address(newname, gt->gt_mcastgrp, vp->namelen); + put_address(newname, st->st_origin, vp->namelen+4); + put_address(newname, 0xFFFFFFFF, vp->namelen+8); + } else { /* get next entry given previous */ + get_address(name, *length, &grp , vp->namelen); + get_address(name, *length, &src , vp->namelen+4); + get_address(name, *length, &mask, vp->namelen+8); - /* 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; + return NULL; - 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; + put_address(newname, gt->gt_mcastgrp, vp->namelen); + put_address(newname, st->st_origin, vp->namelen+4); + put_address(newname, 0xFFFFFFFF, vp->namelen+8); + } + } - default: - return int_SNMP_error__status_genErr; - } + /* Save new OID */ + *length = vp->namelen + 12; + bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid)); + *write_method = 0; + *var_len = sizeof(long); - switch (ifvar) { - case ipMRouteUpstreamNeighbor: { - struct sockaddr_in tmp; - tmp.sin_addr.s_addr = gt->gt_route->rt_gateway; - return o_ipaddr (oi, v, &tmp); - } + switch (vp->magic) { + + case ipMRouteUpstreamNeighbor: + return (u_char *) >->gt_route->rt_gateway; case ipMRouteInIfIndex: - return o_integer (oi, v, gt->gt_route->rt_parent); + long_return = gt->gt_route->rt_parent; + return (u_char *) &long_return; case ipMRouteUpTime: { time_t currtime; time(&currtime); - return o_integer (oi, v, (currtime - gt->gt_ctime)*100); + long_return = (currtime - gt->gt_ctime)*100; + return (u_char *) &long_return; } case ipMRouteExpiryTime: - return o_integer (oi, v, gt->gt_timer*100); + long_return = 5*((gt->gt_timer+4)/5); /* round up to nearest 5 */ + long_return = (long_return + secs_remaining_offset()) * 100; + return (u_char *) &long_return; case ipMRoutePkts: refresh_sg(&sg_req, gt, st); - return o_integer (oi, v, sg_req.pktcnt); - + long_return = sg_req.pktcnt; + return (u_char *) &long_return; + case ipMRouteOctets: refresh_sg(&sg_req, gt, st); - return o_integer (oi, v, sg_req.bytecnt); + long_return = sg_req.bytecnt; + return (u_char *) &long_return; case ipMRouteDifferentInIfIndexes: refresh_sg(&sg_req, gt, st); - return o_integer (oi, v, sg_req.wrong_if); + long_return = sg_req.wrong_if; + return (u_char *) &long_return; case ipMRouteProtocol: - return o_integer (oi, v, 4); + long_return = 4; + return (u_char *) &long_return; - default: - return int_SNMP_error__status_noSuchName; - } + default: + ERROR(""); + } + return NULL; } -/* +/* * Implements the IP Multicast Routing Next Hop Table portion of the Multicast - * MIB + * MIB */ -int -o_ipMRouteNextHopTable (oi, v, offset) -OI oi; -register struct type_SNMP_VarBind *v; -int offset; +u_char * +o_ipMRouteNextHopTable(vp, name, length, exact, var_len, write_method) + register struct variable *vp; /* IN - pointer to variable entry that points here */ + register oid *name; /* IN/OUT - input name requested, output name found */ + register int *length; /* IN/OUT - length of input and output oid's */ + int exact; /* IN - TRUE if an exact match was requested. */ + int *var_len; /* OUT - length of variable or 0 if function returned. */ + int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */ { 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; + oid newname[MAX_NAME_LEN]; + int len; + + /* Copy name OID to new OID */ + bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid)); - 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 (exact) { + if (*length != vp->namelen + 17) + return NULL; - 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) + if (!get_address(name, *length, &grp, vp->namelen) + || !get_address(name, *length, &src, vp->namelen+4) + || !get_address(name, *length, &mask, vp->namelen+8) + || !get_address(name, *length, &addr, vp->namelen+13) || grp!=addr || mask!=0xFFFFFFFF || (!(gt=find_grp(grp))) || (!(st=find_grp_src(gt,src)))) - return int_SNMP_error__status_noSuchName; + return NULL; - vifi = oid->oid_elements[ot->ot_name->oid_nelem+12]; + vifi = name[vp->namelen+12]; if (!(VIFM_ISSET(vifi, gt->gt_route->rt_children))) - return int_SNMP_error__status_noSuchName; - break; + return NULL; - case type_SNMP_SMUX__PDUs_get__next__request: + bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid)); + } else { + len = *length; + if (compare(name, *length, vp->name, vp->namelen) < 0) + len = vp->namelen; - /* Check if we're requesting the first row */ - if (oid->oid_nelem < ot->ot_name->oid_nelem+17) { - OID new; + if (len < vp->namelen + 17) { /* get first entry */ - 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(name, len, &grp, vp->namelen); + get_address(name, len, &src, vp->namelen+4); + get_address(name, len, &mask, vp->namelen+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) + return NULL; + + put_address(newname, gt->gt_mcastgrp, vp->namelen); + put_address(newname, st->st_origin, vp->namelen+4); + put_address(newname, 0xFFFFFFFF, vp->namelen+8); + newname[vp->namelen+12] = vifi; + put_address(newname, gt->gt_mcastgrp, vp->namelen+13); + + } else { /* get next entry given previous */ + vifi = name[vp->namelen+12]+1; + if (!get_address(name, *length, &grp, vp->namelen) + || !get_address(name, *length, &src, vp->namelen+4) + || !get_address(name, *length, &mask, vp->namelen+8) || !next_child(>, &st, grp, src, mask, &vifi)) - return NOTOK; + return NULL; - 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; + put_address(newname, gt->gt_mcastgrp, vp->namelen); + put_address(newname, st->st_origin, vp->namelen+4); + put_address(newname, 0xFFFFFFFF, vp->namelen+8); + newname[vp->namelen+12] = vifi; + put_address(newname, gt->gt_mcastgrp, vp->namelen+13); + } + } - default: - return int_SNMP_error__status_genErr; - } + /* Save new OID */ + *length = vp->namelen + 17; + bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid)); + *write_method = 0; + *var_len = sizeof(long); - switch (ifvar) { + switch (vp->magic) { case ipMRouteNextHopState: - return o_integer (oi, v, (VIFM_ISSET(vifi, gt->gt_grpmems))? 2 : 1); + long_return = (VIFM_ISSET(vifi, gt->gt_grpmems))? 2 : 1; + return (u_char *) &long_return; /* Currently equal to ipMRouteUpTime */ case ipMRouteNextHopUpTime: { time_t currtime; time(&currtime); - return o_integer (oi, v, (currtime - gt->gt_ctime)*100); + long_return = (currtime - gt->gt_ctime)*100; + return (u_char *) &long_return; } case ipMRouteNextHopExpiryTime: - return o_integer (oi, v, gt->gt_prsent_timer); + long_return = 5*((gt->gt_prsent_timer+4)/5); /* round up to nearest 5*/ + long_return = (long_return + secs_remaining_offset()) * 100; + return (u_char *) &long_return; case ipMRouteNextHopClosestMemberHops: - return o_integer (oi, v, 0); + long_return = 0; + return (u_char *) &long_return; case ipMRouteNextHopProtocol: - return o_integer (oi, v, 4); + long_return = 4; + return (u_char *) &long_return; - default: - return int_SNMP_error__status_noSuchName; - } + default: + ERROR(""); + } + return NULL; +} + +/* sync_timer is called by timer() every TIMER_INTERVAL seconds. + * Its job is to record this time so that we can compute on demand + * the approx # seconds remaining until the next timer() call + */ +static time_t lasttimer; + +void +sync_timer() +{ + time(&lasttimer); +} + +int /* in range [-TIMER_INTERVAL..0] */ +secs_remaining_offset() +{ + time_t tm; + + time(&tm); + return lasttimer-tm; } |