Home | History | Annotate | Line # | Download | only in mrouted
snmp.c revision 1.3
      1  1.3  mycroft /*	$NetBSD: snmp.c,v 1.3 1995/12/10 10:07:16 mycroft Exp $	*/
      2  1.1  mycroft 
      3  1.1  mycroft #include "defs.h"
      4  1.3  mycroft #include <netinet/in_var.h>
      5  1.1  mycroft #include "snmp.h"
      6  1.3  mycroft #include "snmplib/asn1.h"
      7  1.3  mycroft #include "snmplib/party.h"
      8  1.3  mycroft #include "snmplib/snmp_impl.h"
      9  1.3  mycroft #define MROUTED
     10  1.3  mycroft #include "snmpd/snmp_vars.h"
     11  1.3  mycroft 
     12  1.3  mycroft     u_short dest_port = 0;
     13  1.3  mycroft     int sdlen = 0;
     14  1.3  mycroft 
     15  1.3  mycroft struct addrCache {
     16  1.3  mycroft     u_long addr;
     17  1.3  mycroft     int status;
     18  1.3  mycroft #define UNUSED 0
     19  1.3  mycroft #define USED   1
     20  1.3  mycroft #define OLD 2
     21  1.3  mycroft };
     22  1.1  mycroft 
     23  1.3  mycroft static struct addrCache addrCache[10];
     24  1.1  mycroft 
     25  1.3  mycroft /*
     26  1.3  mycroft  * Initialize the SNMP part of mrouted
     27  1.3  mycroft  */
     28  1.3  mycroft int /* returns: 0 on success, true on error */
     29  1.3  mycroft snmp_init(dest_port)
     30  1.3  mycroft     u_short dest_port;
     31  1.3  mycroft {
     32  1.3  mycroft    u_long myaddr;
     33  1.3  mycroft    int ret;
     34  1.3  mycroft    struct partyEntry *pp;
     35  1.3  mycroft    struct sockaddr_in  me;
     36  1.3  mycroft    int index, sd, portlist[32];
     37  1.3  mycroft 
     38  1.3  mycroft    init_snmp();
     39  1.3  mycroft    /* init_mib(); why was this here? */
     40  1.3  mycroft     if (read_party_database("/etc/party.conf") > 0){
     41  1.3  mycroft    fprintf(stderr, "Couldn't read party database from /etc/party.conf\n");
     42  1.3  mycroft    exit(0);
     43  1.3  mycroft     }
     44  1.3  mycroft     if (read_context_database("/etc/context.conf") > 0){
     45  1.3  mycroft    fprintf(stderr, "Couldn't read context database from /etc/context.conf\n");
     46  1.3  mycroft    exit(0);
     47  1.3  mycroft     }
     48  1.3  mycroft     if (read_acl_database("/etc/acl.conf") > 0){
     49  1.3  mycroft    fprintf(stderr, "Couldn't read acl database from /etc/acl.conf\n");
     50  1.3  mycroft    exit(0);
     51  1.3  mycroft     }
     52  1.3  mycroft     if (read_view_database("/etc/view.conf") > 0){
     53  1.3  mycroft    fprintf(stderr, "Couldn't read view database from /etc/view.conf\n");
     54  1.3  mycroft    exit(0);
     55  1.3  mycroft     }
     56  1.3  mycroft 
     57  1.3  mycroft     myaddr = get_myaddr();
     58  1.3  mycroft     if (ret = agent_party_init(myaddr, ".1.3.6.1")){
     59  1.3  mycroft    if (ret == 1){
     60  1.3  mycroft        fprintf(stderr, "Conflict found with initial noAuth/noPriv parties... continuing\n");
     61  1.3  mycroft    } else if (ret == -1){
     62  1.3  mycroft        fprintf(stderr, "Error installing initial noAuth/noPriv parties, exiting\n");
     63  1.3  mycroft        exit(1);
     64  1.3  mycroft    } else {
     65  1.3  mycroft        fprintf(stderr, "Unknown error, exiting\n");
     66  1.3  mycroft        exit(2);
     67  1.3  mycroft    }
     68  1.3  mycroft     }
     69  1.1  mycroft 
     70  1.3  mycroft     printf("Opening port(s): ");
     71  1.3  mycroft     fflush(stdout);
     72  1.3  mycroft     party_scanInit();
     73  1.3  mycroft     for(pp = party_scanNext(); pp; pp = party_scanNext()){
     74  1.3  mycroft    if ((pp->partyTDomain != DOMAINSNMPUDP)
     75  1.3  mycroft        || bcmp((char *)&myaddr, pp->partyTAddress, 4))
     76  1.3  mycroft        continue;  /* don't listen for non-local parties */
     77  1.3  mycroft 
     78  1.3  mycroft    dest_port = 0;
     79  1.3  mycroft    bcopy(pp->partyTAddress + 4, &dest_port, 2);
     80  1.3  mycroft    for(index = 0; index < sdlen; index++)
     81  1.3  mycroft        if (dest_port == portlist[index])
     82  1.3  mycroft       break;
     83  1.3  mycroft    if (index < sdlen)  /* found a hit before the end of the list */
     84  1.3  mycroft        continue;
     85  1.3  mycroft    printf("%u ", dest_port);
     86  1.3  mycroft    fflush(stdout);
     87  1.3  mycroft    /* Set up connections */
     88  1.3  mycroft    sd = socket(AF_INET, SOCK_DGRAM, 0);
     89  1.3  mycroft    if (sd < 0){
     90  1.3  mycroft        perror("socket");
     91  1.3  mycroft        return 1;
     92  1.3  mycroft    }
     93  1.3  mycroft    me.sin_family = AF_INET;
     94  1.3  mycroft    me.sin_addr.s_addr = INADDR_ANY;
     95  1.3  mycroft    /* already in network byte order (I think) */
     96  1.3  mycroft    me.sin_port = dest_port;
     97  1.3  mycroft    if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){
     98  1.3  mycroft        perror("bind");
     99  1.3  mycroft        return 2;
    100  1.3  mycroft    }
    101  1.3  mycroft    register_input_handler(sd, snmp_read_packet);
    102  1.3  mycroft    portlist[sdlen] = dest_port;
    103  1.3  mycroft    if (++sdlen == 32){
    104  1.3  mycroft        printf("No more sockets... ignoring rest of file\n");
    105  1.3  mycroft        break;
    106  1.3  mycroft    }
    107  1.3  mycroft     }
    108  1.3  mycroft     printf("\n");
    109  1.3  mycroft     bzero((char *)addrCache, sizeof(addrCache));
    110  1.3  mycroft }
    111  1.1  mycroft 
    112  1.1  mycroft /*
    113  1.3  mycroft  * Place an IP address into an OID starting at element n
    114  1.1  mycroft  */
    115  1.1  mycroft void
    116  1.3  mycroft put_address(name, addr, n)
    117  1.3  mycroft    oid	 *name;
    118  1.1  mycroft    u_long addr;
    119  1.1  mycroft    int n;
    120  1.1  mycroft {
    121  1.1  mycroft    int i;
    122  1.1  mycroft 
    123  1.1  mycroft    for (i=n+3; i>=n+0; i--) {
    124  1.3  mycroft       name[i] = addr & 0xFF;
    125  1.1  mycroft       addr >>= 8;
    126  1.1  mycroft    }
    127  1.1  mycroft }
    128  1.1  mycroft 
    129  1.1  mycroft /* Get an IP address from an OID starting at element n */
    130  1.1  mycroft int
    131  1.3  mycroft get_address(name, length, addr, n)
    132  1.3  mycroft    oid	 *name;
    133  1.3  mycroft    int	  length;
    134  1.1  mycroft    u_long *addr;
    135  1.1  mycroft    int n;
    136  1.1  mycroft {
    137  1.1  mycroft    int i;
    138  1.1  mycroft    int ok = 1;
    139  1.1  mycroft 
    140  1.1  mycroft    (*addr) = 0;
    141  1.1  mycroft 
    142  1.3  mycroft    if (length < n+4)
    143  1.1  mycroft       return 0;
    144  1.1  mycroft 
    145  1.1  mycroft    for (i=n; i<n+4; i++) {
    146  1.1  mycroft       (*addr) <<= 8;
    147  1.3  mycroft       if (i >= length)
    148  1.1  mycroft           ok = 0;
    149  1.1  mycroft       else
    150  1.3  mycroft          (*addr) |= name[i];
    151  1.1  mycroft    }
    152  1.1  mycroft    return ok;
    153  1.1  mycroft }
    154  1.1  mycroft 
    155  1.1  mycroft /*
    156  1.3  mycroft  * Implements scalar objects from DVMRP and Multicast MIBs
    157  1.1  mycroft  */
    158  1.3  mycroft u_char *
    159  1.3  mycroft o_scalar(vp, name, length, exact, var_len, write_method)
    160  1.3  mycroft     register struct variable *vp;   /* IN - pointer to variable entry that points here */
    161  1.3  mycroft     register oid	*name;	    /* IN/OUT - input name requested, output name found */
    162  1.3  mycroft     register int	*length;    /* IN/OUT - length of input and output oid's */
    163  1.3  mycroft     int			exact;	    /* IN - TRUE if an exact match was requested. */
    164  1.3  mycroft     int			*var_len;   /* OUT - length of variable or 0 if function returned. */
    165  1.3  mycroft     int			(**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
    166  1.3  mycroft {
    167  1.3  mycroft     int result;
    168  1.3  mycroft 
    169  1.3  mycroft     *write_method = 0;
    170  1.3  mycroft     result = compare(name, *length, vp->name, (int)vp->namelen);
    171  1.3  mycroft     if ((exact && (result != 0)) || (!exact && (result >= 0)))
    172  1.3  mycroft    return NULL;
    173  1.3  mycroft 
    174  1.3  mycroft 	bcopy((char *)vp->name, (char *)name,
    175  1.3  mycroft      (int)vp->namelen * sizeof(oid));
    176  1.3  mycroft 	*length = vp->namelen;
    177  1.3  mycroft 	*var_len = sizeof(long);
    178  1.3  mycroft 
    179  1.3  mycroft     switch (vp->magic) {
    180  1.3  mycroft 
    181  1.3  mycroft     case ipMRouteEnable:
    182  1.3  mycroft        long_return = 1;
    183  1.3  mycroft        return (u_char *) &long_return;
    184  1.3  mycroft 
    185  1.3  mycroft     case dvmrpVersion: {
    186  1.3  mycroft        static char buff[15];
    187  1.3  mycroft 
    188  1.3  mycroft        sprintf(buff, "mrouted%d.%d", PROTOCOL_VERSION, MROUTED_VERSION);
    189  1.3  mycroft        *var_len = strlen(buff);
    190  1.3  mycroft        return (u_char *)buff;
    191  1.3  mycroft     }
    192  1.1  mycroft 
    193  1.3  mycroft     case dvmrpGenerationId:
    194  1.3  mycroft        long_return = dvmrp_genid;
    195  1.3  mycroft        return (u_char *) &long_return;
    196  1.1  mycroft 
    197  1.3  mycroft     default:
    198  1.3  mycroft        ERROR("");
    199  1.1  mycroft     }
    200  1.3  mycroft     return NULL;
    201  1.1  mycroft }
    202  1.1  mycroft 
    203  1.3  mycroft /*
    204  1.1  mycroft  * Find if a specific scoped boundary exists on a Vif
    205  1.1  mycroft  */
    206  1.1  mycroft struct vif_acl *
    207  1.1  mycroft find_boundary(vifi, addr, mask)
    208  1.3  mycroft    vifi_t vifi;
    209  1.3  mycroft    u_long addr;
    210  1.3  mycroft    u_long mask;
    211  1.1  mycroft {
    212  1.1  mycroft    struct vif_acl *n;
    213  1.1  mycroft 
    214  1.1  mycroft    for (n = uvifs[vifi].uv_acl; n != NULL; n = n->acl_next) {
    215  1.1  mycroft       if (addr == n->acl_addr && mask==n->acl_mask)
    216  1.1  mycroft          return n;
    217  1.1  mycroft    }
    218  1.1  mycroft    return NULL;
    219  1.1  mycroft }
    220  1.1  mycroft 
    221  1.1  mycroft /*
    222  1.3  mycroft  * Find the lowest boundary >= (V,A,M) spec
    223  1.1  mycroft  */
    224  1.1  mycroft struct vif_acl *
    225  1.1  mycroft next_boundary(vifi, addr, mask)
    226  1.3  mycroft    vifi_t *vifi;
    227  1.3  mycroft    u_long  addr;
    228  1.3  mycroft    u_long  mask;
    229  1.1  mycroft {
    230  1.1  mycroft    struct vif_acl *bestn, *n;
    231  1.1  mycroft    int  i;
    232  1.1  mycroft 
    233  1.1  mycroft    for (i = *vifi; i < numvifs; i++) {
    234  1.1  mycroft       bestn = NULL;
    235  1.1  mycroft       for (n = uvifs[i].uv_acl; n; n=n->acl_next) {
    236  1.3  mycroft          if ((i > *vifi || n->acl_addr > addr
    237  1.3  mycroft            || (n->acl_addr == addr && n->acl_mask >= mask))
    238  1.3  mycroft           && (!bestn || n->acl_addr < bestn->acl_addr
    239  1.1  mycroft            || (n->acl_addr==bestn->acl_addr && n->acl_mask<bestn->acl_mask)))
    240  1.1  mycroft             bestn = n;
    241  1.1  mycroft       }
    242  1.1  mycroft       if (bestn) {
    243  1.1  mycroft          *vifi = i;
    244  1.1  mycroft          return bestn;
    245  1.1  mycroft       }
    246  1.1  mycroft    }
    247  1.1  mycroft    return NULL;
    248  1.1  mycroft }
    249  1.1  mycroft 
    250  1.1  mycroft /*
    251  1.1  mycroft  * Implements the Boundary Table portion of the DVMRP MIB
    252  1.1  mycroft  */
    253  1.3  mycroft u_char *
    254  1.3  mycroft o_dvmrpBoundaryTable(vp, name, length, exact, var_len, write_method)
    255  1.3  mycroft     register struct variable *vp;   /* IN - pointer to variable entry that points here */
    256  1.3  mycroft     register oid	*name;	    /* IN/OUT - input name requested, output name found */
    257  1.3  mycroft     register int	*length;    /* IN/OUT - length of input and output oid's */
    258  1.3  mycroft     int			exact;	    /* IN - TRUE if an exact match was requested. */
    259  1.3  mycroft     int			*var_len;   /* OUT - length of variable or 0 if function returned. */
    260  1.3  mycroft     int			(**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
    261  1.3  mycroft {
    262  1.3  mycroft     vifi_t     vifi;
    263  1.3  mycroft     u_long	   addr, mask;
    264  1.1  mycroft     struct vif_acl *bound;
    265  1.3  mycroft     oid        newname[MAX_NAME_LEN];
    266  1.3  mycroft     int        len;
    267  1.1  mycroft 
    268  1.3  mycroft     /* Copy name OID to new OID */
    269  1.3  mycroft     bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
    270  1.3  mycroft 
    271  1.3  mycroft     if (exact) {
    272  1.3  mycroft 	    if (*length != vp->namelen + 9)
    273  1.3  mycroft 		return NULL;
    274  1.3  mycroft 
    275  1.3  mycroft       if ((vifi = name[vp->namelen]) >= numvifs)
    276  1.3  mycroft       return NULL;
    277  1.3  mycroft 
    278  1.3  mycroft       if (!get_address(name, *length, &addr, vp->namelen+1)
    279  1.3  mycroft        || !get_address(name, *length, &mask, vp->namelen+5))
    280  1.3  mycroft 		return NULL;
    281  1.1  mycroft 
    282  1.1  mycroft       if (!(bound = find_boundary(vifi, addr, mask)))
    283  1.3  mycroft 		return NULL;
    284  1.1  mycroft 
    285  1.3  mycroft        bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
    286  1.3  mycroft 	 } else {
    287  1.3  mycroft        len = *length;
    288  1.3  mycroft        if (compare(name, *length, vp->name, vp->namelen) < 0)
    289  1.3  mycroft           len = vp->namelen;
    290  1.3  mycroft 
    291  1.3  mycroft 	    if (len < vp->namelen + 9) { /* get first entry */
    292  1.3  mycroft 
    293  1.3  mycroft          if (len == vp->namelen) {
    294  1.3  mycroft             vifi = addr = mask = 0;
    295  1.3  mycroft          } else {
    296  1.3  mycroft             vifi = name[vp->namelen];
    297  1.3  mycroft             get_address(name, len, &addr, vp->namelen+1);
    298  1.3  mycroft             get_address(name, len, &mask, vp->namelen+5);
    299  1.3  mycroft          }
    300  1.1  mycroft 
    301  1.3  mycroft          bound = next_boundary(&vifi,addr,mask);
    302  1.3  mycroft          if (!bound)
    303  1.3  mycroft             return NULL;
    304  1.3  mycroft 
    305  1.3  mycroft    		newname[vp->namelen] = vifi;
    306  1.3  mycroft          put_address(newname, bound->acl_addr, vp->namelen+1);
    307  1.3  mycroft          put_address(newname, bound->acl_mask, vp->namelen+5);
    308  1.1  mycroft 	    } else {  /* get next entry given previous */
    309  1.3  mycroft 		   vifi = name[vp->namelen];
    310  1.3  mycroft          get_address(name, *length, &addr, vp->namelen+1);
    311  1.3  mycroft          get_address(name, *length, &mask, vp->namelen+5);
    312  1.1  mycroft 
    313  1.1  mycroft          if (!(bound = next_boundary(&vifi,addr,mask+1)))
    314  1.3  mycroft             return NULL;
    315  1.1  mycroft 
    316  1.3  mycroft 		   newname[vp->namelen] = vifi;
    317  1.3  mycroft          put_address(newname, bound->acl_addr, vp->namelen+1);
    318  1.3  mycroft          put_address(newname, bound->acl_mask, vp->namelen+5);
    319  1.1  mycroft 	    }
    320  1.3  mycroft     }
    321  1.1  mycroft 
    322  1.3  mycroft     /* Save new OID */
    323  1.3  mycroft     *length = vp->namelen + 9;
    324  1.3  mycroft     bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
    325  1.3  mycroft     *write_method = 0;
    326  1.3  mycroft     *var_len = sizeof(long);
    327  1.1  mycroft 
    328  1.3  mycroft     switch (vp->magic) {
    329  1.1  mycroft 
    330  1.1  mycroft    case dvmrpBoundaryVifIndex:
    331  1.3  mycroft        long_return = vifi;
    332  1.3  mycroft        return (u_char *) &long_return;
    333  1.1  mycroft 
    334  1.3  mycroft     default:
    335  1.3  mycroft        ERROR("");
    336  1.1  mycroft     }
    337  1.3  mycroft     return NULL;
    338  1.1  mycroft }
    339  1.1  mycroft 
    340  1.3  mycroft /*
    341  1.3  mycroft  * Find the lowest neighbor >= (V,A) spec
    342  1.1  mycroft  */
    343  1.1  mycroft struct listaddr *
    344  1.1  mycroft next_neighbor(vifi, addr)
    345  1.3  mycroft    vifi_t *vifi;
    346  1.3  mycroft    u_long  addr;
    347  1.1  mycroft {
    348  1.1  mycroft    struct listaddr *bestn, *n;
    349  1.1  mycroft    int  i;
    350  1.1  mycroft 
    351  1.1  mycroft    for (i = *vifi; i < numvifs; i++) {
    352  1.1  mycroft       bestn = NULL;
    353  1.1  mycroft       for (n = uvifs[i].uv_neighbors; n; n=n->al_next) {
    354  1.3  mycroft          if ((i > *vifi || n->al_addr >= addr)
    355  1.1  mycroft           && (!bestn || n->al_addr < bestn->al_addr))
    356  1.1  mycroft             bestn = n;
    357  1.1  mycroft       }
    358  1.1  mycroft       if (bestn) {
    359  1.1  mycroft          *vifi = i;
    360  1.1  mycroft          return bestn;
    361  1.1  mycroft       }
    362  1.1  mycroft    }
    363  1.1  mycroft    return NULL;
    364  1.1  mycroft }
    365  1.1  mycroft 
    366  1.1  mycroft /*
    367  1.1  mycroft  * Find a neighbor, if it exists off a given Vif
    368  1.1  mycroft  */
    369  1.1  mycroft struct listaddr *
    370  1.1  mycroft find_neighbor(vifi, addr)
    371  1.3  mycroft    vifi_t vifi;
    372  1.3  mycroft    u_long addr;
    373  1.1  mycroft {
    374  1.1  mycroft    struct listaddr *n;
    375  1.1  mycroft 
    376  1.1  mycroft    for (n = uvifs[vifi].uv_neighbors; n != NULL; n = n->al_next) {
    377  1.1  mycroft       if (addr == n->al_addr)
    378  1.1  mycroft          return n;
    379  1.1  mycroft    }
    380  1.1  mycroft    return NULL;
    381  1.1  mycroft }
    382  1.1  mycroft 
    383  1.3  mycroft u_char *
    384  1.3  mycroft o_dvmrpNeighborTable(vp, name, length, exact, var_len, write_method)
    385  1.3  mycroft     register struct variable *vp;   /* IN - pointer to variable entry that points here */
    386  1.3  mycroft     register oid	*name;	    /* IN/OUT - input name requested, output name found */
    387  1.3  mycroft     register int	*length;    /* IN/OUT - length of input and output oid's */
    388  1.3  mycroft     int			exact;	    /* IN - TRUE if an exact match was requested. */
    389  1.3  mycroft     int			*var_len;   /* OUT - length of variable or 0 if function returned. */
    390  1.3  mycroft     int			(**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
    391  1.3  mycroft {
    392  1.3  mycroft     vifi_t     vifi;
    393  1.3  mycroft     u_long     addr, mask;
    394  1.1  mycroft     struct listaddr *neighbor;
    395  1.3  mycroft     oid        newname[MAX_NAME_LEN];
    396  1.3  mycroft     int        len;
    397  1.1  mycroft 
    398  1.3  mycroft     /* Copy name OID to new OID */
    399  1.3  mycroft     bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
    400  1.1  mycroft 
    401  1.3  mycroft     if (exact) {
    402  1.3  mycroft 	    if (*length != vp->namelen + 5)
    403  1.3  mycroft 		return NULL;
    404  1.1  mycroft 
    405  1.3  mycroft       if ((vifi = name[vp->namelen]) >= numvifs)
    406  1.3  mycroft       return NULL;
    407  1.3  mycroft 
    408  1.3  mycroft       if (!get_address(name, *length, &addr, vp->namelen+1))
    409  1.3  mycroft 		return NULL;
    410  1.1  mycroft 
    411  1.1  mycroft       if (!(neighbor = find_neighbor(vifi, addr)))
    412  1.3  mycroft 		return NULL;
    413  1.1  mycroft 
    414  1.3  mycroft        bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
    415  1.3  mycroft 	 } else {
    416  1.3  mycroft        len = *length;
    417  1.3  mycroft        if (compare(name, *length, vp->name, vp->namelen) < 0)
    418  1.3  mycroft           len = vp->namelen;
    419  1.3  mycroft 
    420  1.3  mycroft 	    if (len < vp->namelen + 5) { /* get first entry */
    421  1.3  mycroft 
    422  1.3  mycroft          if (len == vp->namelen) {
    423  1.3  mycroft             vifi = addr = 0;
    424  1.3  mycroft          } else {
    425  1.3  mycroft             vifi = name[vp->namelen];
    426  1.3  mycroft             get_address(name, len, &addr, vp->namelen+1);
    427  1.3  mycroft          }
    428  1.1  mycroft 
    429  1.3  mycroft          neighbor = next_neighbor(&vifi,addr);
    430  1.3  mycroft          if (!neighbor)
    431  1.3  mycroft             return NULL;
    432  1.1  mycroft 
    433  1.3  mycroft    		newname[vp->namelen] = vifi;
    434  1.3  mycroft          put_address(newname, neighbor->al_addr, vp->namelen+1);
    435  1.1  mycroft 	    } else {  /* get next entry given previous */
    436  1.3  mycroft 		   vifi = name[vp->namelen];
    437  1.3  mycroft          get_address(name, *length, &addr, vp->namelen+1);
    438  1.1  mycroft 
    439  1.1  mycroft          if (!(neighbor = next_neighbor(&vifi,addr+1)))
    440  1.3  mycroft             return NULL;
    441  1.1  mycroft 
    442  1.3  mycroft 		   newname[vp->namelen] = vifi;
    443  1.3  mycroft          put_address(newname, neighbor->al_addr, vp->namelen+1);
    444  1.1  mycroft 	    }
    445  1.3  mycroft     }
    446  1.1  mycroft 
    447  1.3  mycroft     /* Save new OID */
    448  1.3  mycroft     *length = vp->namelen + 5;
    449  1.3  mycroft     bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
    450  1.3  mycroft     *write_method = 0;
    451  1.3  mycroft     *var_len = sizeof(long);
    452  1.1  mycroft 
    453  1.3  mycroft     switch (vp->magic) {
    454  1.1  mycroft 
    455  1.1  mycroft    case dvmrpNeighborUpTime: {
    456  1.1  mycroft        time_t currtime;
    457  1.1  mycroft        time(&currtime);
    458  1.3  mycroft        long_return = (currtime - neighbor->al_ctime)*100;
    459  1.3  mycroft        return (u_char *) &long_return;
    460  1.1  mycroft    }
    461  1.1  mycroft 
    462  1.3  mycroft    case dvmrpNeighborExpiryTime:
    463  1.3  mycroft        long_return = (NEIGHBOR_EXPIRE_TIME - neighbor->al_timer
    464  1.3  mycroft         + secs_remaining_offset()) * 100;
    465  1.3  mycroft        return (u_char *) &long_return;
    466  1.1  mycroft 
    467  1.1  mycroft    case dvmrpNeighborVersion: {
    468  1.1  mycroft        static char buff[15];
    469  1.1  mycroft 
    470  1.1  mycroft        sprintf(buff, "%d.%d", neighbor->al_pv, neighbor->al_mv);
    471  1.3  mycroft        *var_len = strlen(buff);
    472  1.3  mycroft        return (u_char *)buff;
    473  1.1  mycroft    }
    474  1.1  mycroft 
    475  1.3  mycroft    case dvmrpNeighborGenerationId:
    476  1.3  mycroft        long_return = neighbor->al_genid;
    477  1.3  mycroft        return (u_char *) &long_return;
    478  1.3  mycroft 
    479  1.3  mycroft     default:
    480  1.3  mycroft        ERROR("");
    481  1.3  mycroft     }
    482  1.3  mycroft     return NULL;
    483  1.3  mycroft }
    484  1.3  mycroft 
    485  1.3  mycroft /* Look up ifIndex given uvifs[ifnum].uv_lcl_addr */
    486  1.3  mycroft struct in_ifaddr *        /* returns: in_ifaddr structure, or null on error */
    487  1.3  mycroft ipaddr_to_ifindex(ipaddr, ifIndex)
    488  1.3  mycroft    u_long ipaddr;
    489  1.3  mycroft    int   *ifIndex;
    490  1.3  mycroft {
    491  1.3  mycroft     int interface;
    492  1.3  mycroft static struct in_ifaddr in_ifaddr;
    493  1.3  mycroft 
    494  1.3  mycroft     Interface_Scan_Init();
    495  1.3  mycroft     for (;;) {
    496  1.3  mycroft        if (Interface_Scan_Next(&interface, (char *)0, NULL, &in_ifaddr) == 0)
    497  1.3  mycroft           return NULL;
    498  1.3  mycroft 
    499  1.3  mycroft        if (((struct sockaddr_in *) &(in_ifaddr.ia_addr))->sin_addr.s_addr
    500  1.3  mycroft         == ipaddr) {
    501  1.3  mycroft           *ifIndex = interface;
    502  1.3  mycroft           return &in_ifaddr;
    503  1.3  mycroft        }
    504  1.3  mycroft     }
    505  1.3  mycroft }
    506  1.3  mycroft 
    507  1.3  mycroft /*
    508  1.3  mycroft  * Find if a specific scoped boundary exists on a Vif
    509  1.3  mycroft  */
    510  1.3  mycroft struct listaddr *
    511  1.3  mycroft find_cache(grp, vifi)
    512  1.3  mycroft    u_long grp;
    513  1.3  mycroft    vifi_t vifi;
    514  1.3  mycroft {
    515  1.3  mycroft    struct listaddr *n;
    516  1.3  mycroft 
    517  1.3  mycroft    for (n = uvifs[vifi].uv_groups; n != NULL; n = n->al_next) {
    518  1.3  mycroft       if (grp == n->al_addr)
    519  1.3  mycroft          return n;
    520  1.3  mycroft    }
    521  1.3  mycroft    return NULL;
    522  1.3  mycroft }
    523  1.3  mycroft 
    524  1.3  mycroft /*
    525  1.3  mycroft  * Find the next group cache entry >= (A,V) spec
    526  1.3  mycroft  */
    527  1.3  mycroft struct listaddr *
    528  1.3  mycroft next_cache(addr, vifi)
    529  1.3  mycroft    u_long  addr;
    530  1.3  mycroft    vifi_t *vifi;
    531  1.3  mycroft {
    532  1.3  mycroft    struct listaddr *bestn=NULL, *n;
    533  1.3  mycroft    int  i, besti;
    534  1.3  mycroft 
    535  1.3  mycroft    /* Step through all entries looking for the next one */
    536  1.3  mycroft    for (i = 0; i < numvifs; i++) {
    537  1.3  mycroft       for (n = uvifs[i].uv_groups; n; n=n->al_next) {
    538  1.3  mycroft          if ((n->al_addr > addr || (n->al_addr == addr && i >= *vifi))
    539  1.3  mycroft           && (!bestn || n->al_addr < bestn->al_addr
    540  1.3  mycroft            || (n->al_addr == bestn->al_addr && i < besti))) {
    541  1.3  mycroft             bestn = n;
    542  1.3  mycroft             besti = i;
    543  1.3  mycroft          }
    544  1.3  mycroft       }
    545  1.3  mycroft    }
    546  1.3  mycroft 
    547  1.3  mycroft    if (bestn) {
    548  1.3  mycroft       *vifi = besti;
    549  1.3  mycroft       return bestn;
    550  1.3  mycroft    }
    551  1.3  mycroft    return NULL;
    552  1.3  mycroft }
    553  1.3  mycroft 
    554  1.3  mycroft /*
    555  1.3  mycroft  * Implements the IGMP Cache Table portion of the IGMP MIB
    556  1.3  mycroft  */
    557  1.3  mycroft u_char *
    558  1.3  mycroft o_igmpCacheTable(vp, name, length, exact, var_len, write_method)
    559  1.3  mycroft     register struct variable *vp;   /* IN - pointer to variable entry that points here */
    560  1.3  mycroft     register oid	*name;	    /* IN/OUT - input name requested, output name found */
    561  1.3  mycroft     register int	*length;    /* IN/OUT - length of input and output oid's */
    562  1.3  mycroft     int			exact;	    /* IN - TRUE if an exact match was requested. */
    563  1.3  mycroft     int			*var_len;   /* OUT - length of variable or 0 if function returned. */
    564  1.3  mycroft     int			(**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
    565  1.3  mycroft {
    566  1.3  mycroft     vifi_t     vifi;
    567  1.3  mycroft     u_long     grp;
    568  1.3  mycroft     int	      ifIndex;
    569  1.3  mycroft     struct listaddr *cache;
    570  1.3  mycroft     oid        newname[MAX_NAME_LEN];
    571  1.3  mycroft     int        len;
    572  1.3  mycroft     struct in_ifaddr *in_ifaddr;
    573  1.3  mycroft     struct in_multi   in_multi, *inm;
    574  1.3  mycroft 
    575  1.3  mycroft     /* Copy name OID to new OID */
    576  1.3  mycroft     bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
    577  1.3  mycroft 
    578  1.3  mycroft     if (exact) {
    579  1.3  mycroft 	    if (*length != vp->namelen + 5)
    580  1.3  mycroft 		return NULL;
    581  1.3  mycroft 
    582  1.3  mycroft       if ((vifi = name[vp->namelen+4]) >= numvifs)
    583  1.3  mycroft       return NULL;
    584  1.3  mycroft 
    585  1.3  mycroft       if (!get_address(name, *length, &grp, vp->namelen))
    586  1.3  mycroft 		return NULL;
    587  1.3  mycroft 
    588  1.3  mycroft       if (!(cache = find_cache(grp, vifi)))
    589  1.3  mycroft 		return NULL;
    590  1.3  mycroft 
    591  1.3  mycroft        bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
    592  1.3  mycroft 	 } else {
    593  1.3  mycroft        len = *length;
    594  1.3  mycroft        if (compare(name, *length, vp->name, vp->namelen) < 0)
    595  1.3  mycroft           len = vp->namelen;
    596  1.3  mycroft 
    597  1.3  mycroft 	    if (len < vp->namelen + 5) { /* get first entry */
    598  1.3  mycroft 
    599  1.3  mycroft          if (len == vp->namelen) {
    600  1.3  mycroft             vifi = grp = 0;
    601  1.3  mycroft          } else {
    602  1.3  mycroft             get_address(name, len, &grp, vp->namelen);
    603  1.3  mycroft             vifi = name[vp->namelen+4];
    604  1.3  mycroft          }
    605  1.3  mycroft 
    606  1.3  mycroft          cache = next_cache(grp,&vifi);
    607  1.3  mycroft          if (!cache)
    608  1.3  mycroft             return NULL;
    609  1.3  mycroft 
    610  1.3  mycroft          put_address(newname, cache->al_addr, vp->namelen);
    611  1.3  mycroft    		newname[vp->namelen+4] = vifi;
    612  1.3  mycroft 	    } else {  /* get next entry given previous */
    613  1.3  mycroft          get_address(name, *length, &grp, vp->namelen);
    614  1.3  mycroft 		   vifi = name[vp->namelen+4]+1;
    615  1.3  mycroft 
    616  1.3  mycroft          if (!(cache = next_cache(grp,&vifi)))
    617  1.3  mycroft             return NULL;
    618  1.3  mycroft 
    619  1.3  mycroft          put_address(newname, cache->al_addr, vp->namelen);
    620  1.3  mycroft 		   newname[vp->namelen+4] = vifi;
    621  1.3  mycroft 	    }
    622  1.3  mycroft     }
    623  1.3  mycroft 
    624  1.3  mycroft     /* Save new OID */
    625  1.3  mycroft     *length = vp->namelen + 5;
    626  1.3  mycroft     bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
    627  1.3  mycroft     *write_method = 0;
    628  1.3  mycroft     *var_len = sizeof(long);
    629  1.3  mycroft 
    630  1.3  mycroft     /* Look up ifIndex given uvifs[vifi].uv_lcl_addr */
    631  1.3  mycroft     in_ifaddr = ipaddr_to_ifindex(uvifs[vifi].uv_lcl_addr, &ifIndex);
    632  1.3  mycroft 
    633  1.3  mycroft     switch (vp->magic) {
    634  1.3  mycroft 
    635  1.3  mycroft    case igmpCacheSelf:
    636  1.3  mycroft        inm = in_ifaddr->ia_multiaddrs;
    637  1.3  mycroft        while (inm) {
    638  1.3  mycroft           klookup( (int)inm, (char *)&in_multi, sizeof(in_multi));
    639  1.3  mycroft 
    640  1.3  mycroft           if (in_multi.inm_addr.s_addr == cache->al_addr) {
    641  1.3  mycroft              long_return = 1; /* true */
    642  1.3  mycroft              return (u_char *) &long_return;
    643  1.3  mycroft           }
    644  1.3  mycroft 
    645  1.3  mycroft           inm = in_multi.inm_next;
    646  1.3  mycroft        }
    647  1.3  mycroft        long_return = 2; /* false */
    648  1.3  mycroft        return (u_char *) &long_return;
    649  1.3  mycroft 
    650  1.3  mycroft    case igmpCacheLastReporter:
    651  1.3  mycroft        return (u_char *) &cache->al_genid;
    652  1.3  mycroft 
    653  1.3  mycroft    case igmpCacheUpTime: {
    654  1.3  mycroft       time_t currtime;
    655  1.3  mycroft       time(&currtime);
    656  1.3  mycroft       long_return = (currtime - cache->al_ctime)*100;
    657  1.3  mycroft       return (u_char *) &long_return;
    658  1.3  mycroft    }
    659  1.3  mycroft 
    660  1.3  mycroft    case igmpCacheExpiryTime:
    661  1.3  mycroft        long_return = secs_remaining(cache->al_timerid)*100;
    662  1.3  mycroft        return (u_char *) &long_return;
    663  1.3  mycroft 
    664  1.3  mycroft    case igmpCacheStatus:
    665  1.3  mycroft        long_return = 1;
    666  1.3  mycroft        return (u_char *) &long_return;
    667  1.3  mycroft 
    668  1.3  mycroft     default:
    669  1.3  mycroft        ERROR("");
    670  1.3  mycroft     }
    671  1.3  mycroft     return NULL;
    672  1.3  mycroft }
    673  1.3  mycroft 
    674  1.3  mycroft /*
    675  1.3  mycroft  * Implements the IGMP Interface Table portion of the IGMP MIB
    676  1.3  mycroft  */
    677  1.3  mycroft u_char *
    678  1.3  mycroft o_igmpInterfaceTable(vp, name, length, exact, var_len, write_method)
    679  1.3  mycroft     register struct variable *vp;   /* IN - pointer to variable entry that points here */
    680  1.3  mycroft     register oid	*name;	    /* IN/OUT - input name requested, output name found */
    681  1.3  mycroft     register int	*length;    /* IN/OUT - length of input and output oid's */
    682  1.3  mycroft     int			exact;	    /* IN - TRUE if an exact match was requested. */
    683  1.3  mycroft     int			*var_len;   /* OUT - length of variable or 0 if function returned. */
    684  1.3  mycroft     int			(**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
    685  1.3  mycroft {
    686  1.3  mycroft     oid			newname[MAX_NAME_LEN];
    687  1.3  mycroft     register int	ifnum;
    688  1.3  mycroft     int result;
    689  1.3  mycroft static struct sioc_vif_req v_req;
    690  1.3  mycroft 
    691  1.3  mycroft     /* Copy name OID to new OID */
    692  1.3  mycroft     bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
    693  1.3  mycroft 
    694  1.3  mycroft     /* find "next" interface */
    695  1.3  mycroft     for(ifnum = 0; ifnum < numvifs; ifnum++){
    696  1.3  mycroft        if (!(uvifs[ifnum].uv_flags & VIFF_QUERIER))
    697  1.3  mycroft            continue;
    698  1.3  mycroft        newname[vp->namelen] = (oid)ifnum;
    699  1.3  mycroft        result = compare(name, *length, newname, (int)vp->namelen + 1);
    700  1.3  mycroft        if ((exact && (result == 0)) || (!exact && (result < 0)))
    701  1.3  mycroft           break;
    702  1.3  mycroft     }
    703  1.3  mycroft     if (ifnum >= numvifs)
    704  1.3  mycroft        return NULL;
    705  1.3  mycroft 
    706  1.3  mycroft     /* Save new OID */
    707  1.3  mycroft     bcopy((char *)newname, (char *)name, ((int)vp->namelen + 1) * sizeof(oid));
    708  1.3  mycroft     *length = vp->namelen + 1;
    709  1.3  mycroft     *write_method = 0;
    710  1.3  mycroft     *var_len = sizeof(long);
    711  1.3  mycroft 
    712  1.3  mycroft     switch (vp->magic){
    713  1.3  mycroft 
    714  1.3  mycroft 	case igmpInterfaceQueryInterval:
    715  1.3  mycroft 		long_return = GROUP_QUERY_INTERVAL;
    716  1.3  mycroft       return (u_char *) &long_return;
    717  1.3  mycroft 
    718  1.3  mycroft 	case igmpInterfaceStatus:
    719  1.3  mycroft 		long_return = 1; /* active */
    720  1.3  mycroft       return (u_char *) &long_return;
    721  1.1  mycroft 
    722  1.1  mycroft 	default:
    723  1.3  mycroft 	    ERROR("");
    724  1.1  mycroft     }
    725  1.3  mycroft     return NULL;
    726  1.1  mycroft }
    727  1.1  mycroft 
    728  1.1  mycroft /*
    729  1.1  mycroft  * Given a virtual interface number, make sure we have the current
    730  1.1  mycroft  * kernel information for that Vif.
    731  1.1  mycroft  */
    732  1.1  mycroft refresh_vif(v_req, ifnum)
    733  1.1  mycroft    struct sioc_vif_req *v_req;
    734  1.1  mycroft    int ifnum;
    735  1.1  mycroft {
    736  1.1  mycroft    static   int lastq = -1;
    737  1.1  mycroft 
    738  1.1  mycroft    if (quantum!=lastq || v_req->vifi != ifnum) {
    739  1.1  mycroft        lastq = quantum;
    740  1.1  mycroft        v_req->vifi = ifnum;
    741  1.1  mycroft        if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)v_req) < 0)
    742  1.1  mycroft           v_req->icount = v_req->ocount = v_req->ibytes = v_req->obytes = 0;
    743  1.1  mycroft    }
    744  1.1  mycroft }
    745  1.1  mycroft 
    746  1.1  mycroft /*
    747  1.1  mycroft  * Implements the Multicast Routing Interface Table portion of the Multicast MIB
    748  1.1  mycroft  */
    749  1.3  mycroft u_char *
    750  1.3  mycroft o_ipMRouteInterfaceTable(vp, name, length, exact, var_len, write_method)
    751  1.3  mycroft     register struct variable *vp;   /* IN - pointer to variable entry that points here */
    752  1.3  mycroft     register oid	*name;	    /* IN/OUT - input name requested, output name found */
    753  1.3  mycroft     register int	*length;    /* IN/OUT - length of input and output oid's */
    754  1.3  mycroft     int			exact;	    /* IN - TRUE if an exact match was requested. */
    755  1.3  mycroft     int			*var_len;   /* OUT - length of variable or 0 if function returned. */
    756  1.3  mycroft     int			(**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
    757  1.3  mycroft {
    758  1.3  mycroft     oid			newname[MAX_NAME_LEN];
    759  1.3  mycroft     register int	ifnum;
    760  1.3  mycroft     int result;
    761  1.1  mycroft static struct sioc_vif_req v_req;
    762  1.1  mycroft 
    763  1.3  mycroft     /* Copy name OID to new OID */
    764  1.3  mycroft     bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
    765  1.1  mycroft 
    766  1.3  mycroft     /* find "next" interface */
    767  1.3  mycroft     for(ifnum = 0; ifnum < numvifs; ifnum++){
    768  1.3  mycroft 	newname[vp->namelen] = (oid)ifnum;
    769  1.3  mycroft 	result = compare(name, *length, newname, (int)vp->namelen + 1);
    770  1.3  mycroft 	if ((exact && (result == 0)) || (!exact && (result < 0)))
    771  1.1  mycroft 	    break;
    772  1.1  mycroft     }
    773  1.3  mycroft     if (ifnum >= numvifs)
    774  1.3  mycroft 	return NULL;
    775  1.1  mycroft 
    776  1.3  mycroft     /* Save new OID */
    777  1.3  mycroft     bcopy((char *)newname, (char *)name, ((int)vp->namelen + 1) * sizeof(oid));
    778  1.3  mycroft     *length = vp->namelen + 1;
    779  1.3  mycroft     *write_method = 0;
    780  1.3  mycroft     *var_len = sizeof(long);
    781  1.3  mycroft 
    782  1.3  mycroft     switch (vp->magic){
    783  1.3  mycroft 
    784  1.3  mycroft    case ipMRouteInterfaceTtl:
    785  1.3  mycroft        long_return = uvifs[ifnum].uv_threshold;
    786  1.3  mycroft        return (u_char *) &long_return;
    787  1.1  mycroft 
    788  1.3  mycroft    case dvmrpVInterfaceType:
    789  1.1  mycroft       if (uvifs[ifnum].uv_flags & VIFF_SRCRT)
    790  1.3  mycroft          long_return = 2;
    791  1.1  mycroft       else if (uvifs[ifnum].uv_flags & VIFF_TUNNEL)
    792  1.3  mycroft          long_return = 1;
    793  1.1  mycroft       else if (uvifs[ifnum].uv_flags & VIFF_QUERIER)
    794  1.3  mycroft          long_return = 3;
    795  1.1  mycroft       else                               /* SUBNET */
    796  1.3  mycroft          long_return = 4;
    797  1.3  mycroft       return (u_char *) &long_return;
    798  1.1  mycroft 
    799  1.3  mycroft    case dvmrpVInterfaceState:
    800  1.1  mycroft       if (uvifs[ifnum].uv_flags & VIFF_DISABLED)
    801  1.3  mycroft          long_return = 3;
    802  1.3  mycroft       else if ((uvifs[ifnum].uv_flags & VIFF_DOWN)
    803  1.3  mycroft        || ((uvifs[ifnum].uv_flags & VIFF_TUNNEL) && (uvifs[ifnum].uv_neighbors==NULL)))
    804  1.3  mycroft          long_return = 2;
    805  1.1  mycroft       else /* UP */
    806  1.3  mycroft          long_return = 1;
    807  1.3  mycroft       return (u_char *) &long_return;
    808  1.1  mycroft 
    809  1.3  mycroft    case dvmrpVInterfaceLocalAddress:
    810  1.3  mycroft       return (u_char *) &uvifs[ifnum].uv_lcl_addr;
    811  1.1  mycroft 
    812  1.3  mycroft    case dvmrpVInterfaceRemoteAddress:
    813  1.3  mycroft       return (u_char *) ((uvifs[ifnum].uv_flags & VIFF_TUNNEL) ?
    814  1.3  mycroft          &uvifs[ifnum].uv_rmt_addr :
    815  1.3  mycroft          &uvifs[ifnum].uv_subnet);
    816  1.1  mycroft 
    817  1.3  mycroft    case dvmrpVInterfaceRemoteSubnetMask:
    818  1.3  mycroft       return (u_char *) &uvifs[ifnum].uv_subnetmask;
    819  1.1  mycroft 
    820  1.3  mycroft    case dvmrpVInterfaceMetric:
    821  1.3  mycroft        long_return = uvifs[ifnum].uv_metric;
    822  1.3  mycroft        return (u_char *) &long_return;
    823  1.1  mycroft 
    824  1.3  mycroft    case dvmrpVInterfaceRateLimit:
    825  1.3  mycroft        long_return = uvifs[ifnum].uv_rate_limit;
    826  1.3  mycroft        return (u_char *) &long_return;
    827  1.1  mycroft 
    828  1.3  mycroft    case dvmrpVInterfaceInPkts:
    829  1.1  mycroft        refresh_vif(&v_req, ifnum);
    830  1.3  mycroft        long_return = v_req.icount;
    831  1.3  mycroft        return (u_char *) &long_return;
    832  1.1  mycroft 
    833  1.3  mycroft    case dvmrpVInterfaceOutPkts:
    834  1.1  mycroft        refresh_vif(&v_req, ifnum);
    835  1.3  mycroft        long_return = v_req.ocount;
    836  1.3  mycroft        return (u_char *) &long_return;
    837  1.1  mycroft 
    838  1.3  mycroft    case dvmrpVInterfaceInOctets:
    839  1.1  mycroft        refresh_vif(&v_req, ifnum);
    840  1.3  mycroft        long_return = v_req.ibytes;
    841  1.3  mycroft        return (u_char *) &long_return;
    842  1.1  mycroft 
    843  1.3  mycroft    case dvmrpVInterfaceOutOctets:
    844  1.1  mycroft        refresh_vif(&v_req, ifnum);
    845  1.3  mycroft        long_return = v_req.obytes;
    846  1.3  mycroft        return (u_char *) &long_return;
    847  1.1  mycroft 
    848  1.1  mycroft 	default:
    849  1.3  mycroft 	    ERROR("");
    850  1.1  mycroft     }
    851  1.3  mycroft     return NULL;
    852  1.1  mycroft }
    853  1.1  mycroft 
    854  1.1  mycroft /*
    855  1.3  mycroft  * Implements the DVMRP Route Table portion of the DVMRP MIB
    856  1.1  mycroft  */
    857  1.3  mycroft u_char *
    858  1.3  mycroft o_dvmrpRouteTable(vp, name, length, exact, var_len, write_method)
    859  1.3  mycroft     register struct variable *vp;   /* IN - pointer to variable entry that points here */
    860  1.3  mycroft     register oid	*name;	    /* IN/OUT - input name requested, output name found */
    861  1.3  mycroft     register int	*length;    /* IN/OUT - length of input and output oid's */
    862  1.3  mycroft     int			exact;	    /* IN - TRUE if an exact match was requested. */
    863  1.3  mycroft     int			*var_len;   /* OUT - length of variable or 0 if function returned. */
    864  1.3  mycroft     int			(**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
    865  1.3  mycroft {
    866  1.3  mycroft     u_long src, mask;
    867  1.3  mycroft     oid        newname[MAX_NAME_LEN];
    868  1.3  mycroft     int        len;
    869  1.3  mycroft     struct rtentry *rt = NULL;
    870  1.1  mycroft 
    871  1.3  mycroft     /* Copy name OID to new OID */
    872  1.3  mycroft     bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
    873  1.1  mycroft 
    874  1.3  mycroft     if (exact) {
    875  1.3  mycroft 	    if (*length != vp->namelen + 8)
    876  1.3  mycroft 		return NULL;
    877  1.3  mycroft 
    878  1.3  mycroft       if (!get_address(name, *length, &src, vp->namelen)
    879  1.3  mycroft        || !get_address(name, *length, &mask, vp->namelen+4))
    880  1.3  mycroft 		return NULL;
    881  1.3  mycroft 
    882  1.3  mycroft       if (!(rt = snmp_find_route(src, mask)))
    883  1.3  mycroft 		return NULL;
    884  1.3  mycroft 
    885  1.3  mycroft        bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
    886  1.3  mycroft 	 } else {
    887  1.3  mycroft        len = *length;
    888  1.3  mycroft        if (compare(name, *length, vp->name, vp->namelen) < 0)
    889  1.3  mycroft           len = vp->namelen;
    890  1.3  mycroft 
    891  1.3  mycroft 	    if (len < vp->namelen + 8) { /* get first entry */
    892  1.3  mycroft 
    893  1.3  mycroft          if (len == vp->namelen) {
    894  1.3  mycroft             src = mask = 0;
    895  1.3  mycroft          } else {
    896  1.3  mycroft             get_address(name, len, &src, vp->namelen);
    897  1.3  mycroft             get_address(name, len, &mask, vp->namelen+4);
    898  1.3  mycroft          }
    899  1.1  mycroft 
    900  1.3  mycroft          if (!next_route(&rt,src,mask)) /* Get first entry */
    901  1.3  mycroft             return NULL;
    902  1.1  mycroft 
    903  1.3  mycroft          put_address(newname, rt->rt_origin    , vp->namelen);
    904  1.3  mycroft          put_address(newname, rt->rt_originmask, vp->namelen+4);
    905  1.3  mycroft 	    } else {  /* get next entry given previous */
    906  1.3  mycroft          get_address(name, *length, &src,  vp->namelen);
    907  1.3  mycroft          get_address(name, *length, &mask, vp->namelen+4);
    908  1.1  mycroft 
    909  1.3  mycroft          if (!next_route(&rt, src,mask))
    910  1.3  mycroft             return NULL;
    911  1.1  mycroft 
    912  1.3  mycroft          put_address(newname, rt->rt_origin,     vp->namelen);
    913  1.3  mycroft          put_address(newname, rt->rt_originmask, vp->namelen+4);
    914  1.3  mycroft 	    }
    915  1.1  mycroft     }
    916  1.1  mycroft 
    917  1.3  mycroft     /* Save new OID */
    918  1.3  mycroft     *length = vp->namelen + 8;
    919  1.3  mycroft     bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
    920  1.3  mycroft     *write_method = 0;
    921  1.3  mycroft     *var_len = sizeof(long);
    922  1.1  mycroft 
    923  1.3  mycroft     switch (vp->magic) {
    924  1.1  mycroft 
    925  1.3  mycroft       case dvmrpRouteUpstreamNeighbor:
    926  1.3  mycroft          return (u_char *) &rt->rt_gateway;
    927  1.1  mycroft 
    928  1.1  mycroft       case dvmrpRouteInVifIndex:
    929  1.3  mycroft          long_return = rt->rt_parent;
    930  1.3  mycroft          return (u_char *) &long_return;
    931  1.1  mycroft 
    932  1.1  mycroft       case dvmrpRouteMetric:
    933  1.3  mycroft          long_return = rt->rt_metric;
    934  1.3  mycroft          return (u_char *) &long_return;
    935  1.1  mycroft 
    936  1.1  mycroft       case dvmrpRouteExpiryTime:
    937  1.3  mycroft          long_return = (ROUTE_EXPIRE_TIME - rt->rt_timer
    938  1.3  mycroft           + secs_remaining_offset()) * 100;
    939  1.3  mycroft          return (u_char *) &long_return;
    940  1.1  mycroft 
    941  1.3  mycroft     default:
    942  1.3  mycroft        ERROR("");
    943  1.3  mycroft     }
    944  1.3  mycroft     return NULL;
    945  1.1  mycroft }
    946  1.1  mycroft 
    947  1.3  mycroft /*
    948  1.3  mycroft  * Implements the DVMRP Routing Next Hop Table portion of the DVMRP MIB
    949  1.1  mycroft  */
    950  1.3  mycroft u_char *
    951  1.3  mycroft o_dvmrpRouteNextHopTable(vp, name, length, exact, var_len, write_method)
    952  1.3  mycroft     register struct variable *vp;   /* IN - pointer to variable entry that points here */
    953  1.3  mycroft     register oid	*name;	    /* IN/OUT - input name requested, output name found */
    954  1.3  mycroft     register int	*length;    /* IN/OUT - length of input and output oid's */
    955  1.3  mycroft     int			exact;	    /* IN - TRUE if an exact match was requested. */
    956  1.3  mycroft     int			*var_len;   /* OUT - length of variable or 0 if function returned. */
    957  1.3  mycroft     int			(**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
    958  1.1  mycroft {
    959  1.3  mycroft     u_long     src, mask;
    960  1.3  mycroft     vifi_t     vifi;
    961  1.1  mycroft     struct rtentry *rt = NULL;
    962  1.3  mycroft     oid        newname[MAX_NAME_LEN];
    963  1.3  mycroft     int        len;
    964  1.3  mycroft 
    965  1.3  mycroft     /* Copy name OID to new OID */
    966  1.3  mycroft     bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
    967  1.1  mycroft 
    968  1.3  mycroft     if (exact) {
    969  1.3  mycroft 	    if (*length != vp->namelen + 9)
    970  1.3  mycroft 		return NULL;
    971  1.1  mycroft 
    972  1.3  mycroft       if (!get_address(name, *length, &src, vp->namelen)
    973  1.3  mycroft        || !get_address(name, *length, &mask, vp->namelen+4)
    974  1.1  mycroft        || (!(rt=snmp_find_route(src,mask))))
    975  1.3  mycroft 		return NULL;
    976  1.1  mycroft 
    977  1.3  mycroft       vifi = name[vp->namelen+8];
    978  1.1  mycroft       if (!(VIFM_ISSET(vifi, rt->rt_children)))
    979  1.3  mycroft       return NULL;
    980  1.1  mycroft 
    981  1.3  mycroft        bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
    982  1.3  mycroft 	 } else {
    983  1.3  mycroft        len = *length;
    984  1.3  mycroft        if (compare(name, *length, vp->name, vp->namelen) < 0)
    985  1.3  mycroft           len = vp->namelen;
    986  1.1  mycroft 
    987  1.3  mycroft 	    if (len < vp->namelen + 9) { /* get first entry */
    988  1.1  mycroft 
    989  1.3  mycroft          get_address(name, len, &src,  vp->namelen);
    990  1.3  mycroft          get_address(name, len, &mask, vp->namelen+4);
    991  1.1  mycroft 
    992  1.1  mycroft          /* Find first child vif */
    993  1.1  mycroft          vifi=0;
    994  1.1  mycroft          if (!next_route_child(&rt, src, mask, &vifi))
    995  1.3  mycroft             return NULL;
    996  1.1  mycroft 
    997  1.3  mycroft          put_address(newname, rt->rt_origin,     vp->namelen);
    998  1.3  mycroft          put_address(newname, rt->rt_originmask, vp->namelen+4);
    999  1.3  mycroft    		newname[vp->namelen+8] = vifi;
   1000  1.3  mycroft 	    } else {  /* get next entry given previous */
   1001  1.3  mycroft 		   vifi = name[vp->namelen+8] + 1;
   1002  1.3  mycroft          if (!get_address(name, *length, &src,  vp->namelen)
   1003  1.3  mycroft           || !get_address(name, *length, &mask, vp->namelen+4)
   1004  1.1  mycroft           || !next_route_child(&rt, src, mask, &vifi))
   1005  1.3  mycroft             return NULL;
   1006  1.1  mycroft 
   1007  1.3  mycroft          put_address(newname, rt->rt_origin,     vp->namelen);
   1008  1.3  mycroft          put_address(newname, rt->rt_originmask, vp->namelen+4);
   1009  1.3  mycroft 		   newname[vp->namelen+8] = vifi;
   1010  1.3  mycroft 	    }
   1011  1.3  mycroft     }
   1012  1.1  mycroft 
   1013  1.3  mycroft     /* Save new OID */
   1014  1.3  mycroft     *length = vp->namelen + 9;
   1015  1.3  mycroft     bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
   1016  1.3  mycroft     *write_method = 0;
   1017  1.3  mycroft     *var_len = sizeof(long);
   1018  1.3  mycroft 
   1019  1.3  mycroft     switch (vp->magic) {
   1020  1.3  mycroft 
   1021  1.3  mycroft     case dvmrpRouteNextHopType:
   1022  1.3  mycroft        long_return = (VIFM_ISSET(vifi, rt->rt_leaves))? 1 : 2;
   1023  1.3  mycroft        return (u_char *) &long_return;
   1024  1.1  mycroft 
   1025  1.3  mycroft     default:
   1026  1.3  mycroft        ERROR("");
   1027  1.3  mycroft     }
   1028  1.3  mycroft     return NULL;
   1029  1.1  mycroft }
   1030  1.1  mycroft 
   1031  1.3  mycroft /*
   1032  1.3  mycroft  * Implements the IP Multicast Route Table portion of the Multicast MIB
   1033  1.1  mycroft  */
   1034  1.3  mycroft u_char *
   1035  1.3  mycroft o_ipMRouteTable(vp, name, length, exact, var_len, write_method)
   1036  1.3  mycroft     register struct variable *vp;   /* IN - pointer to variable entry that points here */
   1037  1.3  mycroft     register oid	*name;	    /* IN/OUT - input name requested, output name found */
   1038  1.3  mycroft     register int	*length;    /* IN/OUT - length of input and output oid's */
   1039  1.3  mycroft     int			exact;	    /* IN - TRUE if an exact match was requested. */
   1040  1.3  mycroft     int			*var_len;   /* OUT - length of variable or 0 if function returned. */
   1041  1.3  mycroft     int			(**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
   1042  1.1  mycroft {
   1043  1.1  mycroft     u_long src, grp, mask;
   1044  1.1  mycroft     struct gtable *gt = NULL;
   1045  1.1  mycroft     struct stable *st = NULL;
   1046  1.1  mycroft static struct sioc_sg_req sg_req;
   1047  1.3  mycroft     oid        newname[MAX_NAME_LEN];
   1048  1.3  mycroft     int        len;
   1049  1.1  mycroft 
   1050  1.3  mycroft     /* Copy name OID to new OID */
   1051  1.3  mycroft     bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
   1052  1.3  mycroft 
   1053  1.3  mycroft     if (exact) {
   1054  1.3  mycroft 	    if (*length != vp->namelen + 12)
   1055  1.3  mycroft 		return NULL;
   1056  1.3  mycroft 
   1057  1.3  mycroft       if (!get_address(name, *length, &grp,  vp->namelen)
   1058  1.3  mycroft        || !get_address(name, *length, &src,  vp->namelen+4)
   1059  1.3  mycroft        || !get_address(name, *length, &mask, vp->namelen+8)
   1060  1.1  mycroft        || (mask != 0xFFFFFFFF) /* we keep sources now, not subnets */
   1061  1.1  mycroft        || !(gt = find_grp(grp))
   1062  1.1  mycroft        || !(st = find_grp_src(gt,src)))
   1063  1.3  mycroft 		return NULL;
   1064  1.1  mycroft 
   1065  1.3  mycroft        bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
   1066  1.3  mycroft 	 } else {
   1067  1.3  mycroft        len = *length;
   1068  1.3  mycroft        if (compare(name, *length, vp->name, vp->namelen) < 0)
   1069  1.3  mycroft           len = vp->namelen;
   1070  1.3  mycroft 
   1071  1.3  mycroft 	    if (len < vp->namelen + 12) { /* get first entry */
   1072  1.3  mycroft 
   1073  1.3  mycroft          get_address(name, len, &grp,  vp->namelen);
   1074  1.3  mycroft          get_address(name, len, &src,  vp->namelen+4);
   1075  1.3  mycroft          get_address(name, len, &mask, vp->namelen+8);
   1076  1.1  mycroft 
   1077  1.3  mycroft          if (!next_grp_src_mask(&gt,&st,grp,src,mask)) /* Get first entry */
   1078  1.3  mycroft             return NULL;
   1079  1.1  mycroft 
   1080  1.3  mycroft          put_address(newname, gt->gt_mcastgrp, vp->namelen);
   1081  1.3  mycroft          put_address(newname, st->st_origin,   vp->namelen+4);
   1082  1.3  mycroft          put_address(newname, 0xFFFFFFFF,      vp->namelen+8);
   1083  1.3  mycroft 	    } else {  /* get next entry given previous */
   1084  1.3  mycroft          get_address(name, *length, &grp , vp->namelen);
   1085  1.3  mycroft          get_address(name, *length, &src , vp->namelen+4);
   1086  1.3  mycroft          get_address(name, *length, &mask, vp->namelen+8);
   1087  1.1  mycroft 
   1088  1.1  mycroft          if (!next_grp_src_mask(&gt, &st, grp,src,mask))
   1089  1.3  mycroft             return NULL;
   1090  1.3  mycroft 
   1091  1.3  mycroft          put_address(newname, gt->gt_mcastgrp, vp->namelen);
   1092  1.3  mycroft          put_address(newname, st->st_origin,   vp->namelen+4);
   1093  1.3  mycroft          put_address(newname, 0xFFFFFFFF,      vp->namelen+8);
   1094  1.3  mycroft 	    }
   1095  1.3  mycroft     }
   1096  1.1  mycroft 
   1097  1.3  mycroft     /* Save new OID */
   1098  1.3  mycroft     *length = vp->namelen + 12;
   1099  1.3  mycroft     bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
   1100  1.3  mycroft     *write_method = 0;
   1101  1.3  mycroft     *var_len = sizeof(long);
   1102  1.1  mycroft 
   1103  1.3  mycroft     switch (vp->magic) {
   1104  1.1  mycroft 
   1105  1.3  mycroft       case ipMRouteUpstreamNeighbor:
   1106  1.3  mycroft          return (u_char *) &gt->gt_route->rt_gateway;
   1107  1.1  mycroft 
   1108  1.1  mycroft       case ipMRouteInIfIndex:
   1109  1.3  mycroft          long_return = gt->gt_route->rt_parent;
   1110  1.3  mycroft          return (u_char *) &long_return;
   1111  1.1  mycroft 
   1112  1.1  mycroft       case ipMRouteUpTime: {
   1113  1.1  mycroft          time_t currtime;
   1114  1.1  mycroft          time(&currtime);
   1115  1.3  mycroft          long_return = (currtime - gt->gt_ctime)*100;
   1116  1.3  mycroft          return (u_char *) &long_return;
   1117  1.1  mycroft       }
   1118  1.1  mycroft 
   1119  1.1  mycroft       case ipMRouteExpiryTime:
   1120  1.3  mycroft          long_return = 5*((gt->gt_timer+4)/5); /* round up to nearest 5 */
   1121  1.3  mycroft          long_return = (long_return + secs_remaining_offset()) * 100;
   1122  1.3  mycroft          return (u_char *) &long_return;
   1123  1.1  mycroft 
   1124  1.1  mycroft       case ipMRoutePkts:
   1125  1.1  mycroft          refresh_sg(&sg_req, gt, st);
   1126  1.3  mycroft          long_return = sg_req.pktcnt;
   1127  1.3  mycroft          return (u_char *) &long_return;
   1128  1.3  mycroft 
   1129  1.1  mycroft       case ipMRouteOctets:
   1130  1.1  mycroft          refresh_sg(&sg_req, gt, st);
   1131  1.3  mycroft          long_return = sg_req.bytecnt;
   1132  1.3  mycroft          return (u_char *) &long_return;
   1133  1.1  mycroft 
   1134  1.1  mycroft       case ipMRouteDifferentInIfIndexes:
   1135  1.1  mycroft          refresh_sg(&sg_req, gt, st);
   1136  1.3  mycroft          long_return = sg_req.wrong_if;
   1137  1.3  mycroft          return (u_char *) &long_return;
   1138  1.1  mycroft 
   1139  1.1  mycroft       case ipMRouteProtocol:
   1140  1.3  mycroft          long_return = 4;
   1141  1.3  mycroft          return (u_char *) &long_return;
   1142  1.1  mycroft 
   1143  1.3  mycroft     default:
   1144  1.3  mycroft        ERROR("");
   1145  1.3  mycroft     }
   1146  1.3  mycroft     return NULL;
   1147  1.1  mycroft }
   1148  1.1  mycroft 
   1149  1.3  mycroft /*
   1150  1.1  mycroft  * Implements the IP Multicast Routing Next Hop Table portion of the Multicast
   1151  1.3  mycroft  * MIB
   1152  1.1  mycroft  */
   1153  1.3  mycroft u_char *
   1154  1.3  mycroft o_ipMRouteNextHopTable(vp, name, length, exact, var_len, write_method)
   1155  1.3  mycroft     register struct variable *vp;   /* IN - pointer to variable entry that points here */
   1156  1.3  mycroft     register oid	*name;	    /* IN/OUT - input name requested, output name found */
   1157  1.3  mycroft     register int	*length;    /* IN/OUT - length of input and output oid's */
   1158  1.3  mycroft     int			exact;	    /* IN - TRUE if an exact match was requested. */
   1159  1.3  mycroft     int			*var_len;   /* OUT - length of variable or 0 if function returned. */
   1160  1.3  mycroft     int			(**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
   1161  1.1  mycroft {
   1162  1.1  mycroft     u_long src, grp, mask, addr;
   1163  1.1  mycroft     vifi_t   vifi;
   1164  1.1  mycroft     struct gtable *gt;
   1165  1.1  mycroft     struct stable *st;
   1166  1.3  mycroft     oid        newname[MAX_NAME_LEN];
   1167  1.3  mycroft     int        len;
   1168  1.1  mycroft 
   1169  1.3  mycroft     /* Copy name OID to new OID */
   1170  1.3  mycroft     bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
   1171  1.3  mycroft 
   1172  1.3  mycroft     if (exact) {
   1173  1.3  mycroft 	    if (*length != vp->namelen + 17)
   1174  1.3  mycroft 		return NULL;
   1175  1.3  mycroft 
   1176  1.3  mycroft       if (!get_address(name, *length, &grp, vp->namelen)
   1177  1.3  mycroft        || !get_address(name, *length, &src, vp->namelen+4)
   1178  1.3  mycroft        || !get_address(name, *length, &mask, vp->namelen+8)
   1179  1.3  mycroft        || !get_address(name, *length, &addr, vp->namelen+13)
   1180  1.1  mycroft        || grp!=addr
   1181  1.1  mycroft        || mask!=0xFFFFFFFF
   1182  1.1  mycroft        || (!(gt=find_grp(grp)))
   1183  1.1  mycroft        || (!(st=find_grp_src(gt,src))))
   1184  1.3  mycroft 		return NULL;
   1185  1.1  mycroft 
   1186  1.3  mycroft       vifi = name[vp->namelen+12];
   1187  1.1  mycroft       if (!(VIFM_ISSET(vifi, gt->gt_route->rt_children)))
   1188  1.3  mycroft       return NULL;
   1189  1.1  mycroft 
   1190  1.3  mycroft        bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
   1191  1.3  mycroft 	 } else {
   1192  1.3  mycroft        len = *length;
   1193  1.3  mycroft        if (compare(name, *length, vp->name, vp->namelen) < 0)
   1194  1.3  mycroft           len = vp->namelen;
   1195  1.3  mycroft 
   1196  1.3  mycroft 	    if (len < vp->namelen + 17) { /* get first entry */
   1197  1.3  mycroft 
   1198  1.3  mycroft          get_address(name, len, &grp, vp->namelen);
   1199  1.3  mycroft          get_address(name, len, &src, vp->namelen+4);
   1200  1.3  mycroft          get_address(name, len, &mask, vp->namelen+8);
   1201  1.1  mycroft 
   1202  1.1  mycroft          /* Find first child vif */
   1203  1.1  mycroft          vifi=0;
   1204  1.1  mycroft          if (!next_child(&gt, &st, grp, src, mask, &vifi))
   1205  1.3  mycroft             return NULL;
   1206  1.3  mycroft 
   1207  1.3  mycroft          put_address(newname, gt->gt_mcastgrp, vp->namelen);
   1208  1.3  mycroft          put_address(newname, st->st_origin,   vp->namelen+4);
   1209  1.3  mycroft          put_address(newname, 0xFFFFFFFF,      vp->namelen+8);
   1210  1.3  mycroft    		newname[vp->namelen+12] = vifi;
   1211  1.3  mycroft          put_address(newname, gt->gt_mcastgrp, vp->namelen+13);
   1212  1.1  mycroft 
   1213  1.3  mycroft 	    } else {  /* get next entry given previous */
   1214  1.3  mycroft 		   vifi = name[vp->namelen+12]+1;
   1215  1.3  mycroft          if (!get_address(name, *length, &grp,  vp->namelen)
   1216  1.3  mycroft           || !get_address(name, *length, &src,  vp->namelen+4)
   1217  1.3  mycroft           || !get_address(name, *length, &mask, vp->namelen+8)
   1218  1.1  mycroft           || !next_child(&gt, &st, grp, src, mask, &vifi))
   1219  1.3  mycroft             return NULL;
   1220  1.1  mycroft 
   1221  1.3  mycroft          put_address(newname, gt->gt_mcastgrp, vp->namelen);
   1222  1.3  mycroft          put_address(newname, st->st_origin,   vp->namelen+4);
   1223  1.3  mycroft          put_address(newname, 0xFFFFFFFF,      vp->namelen+8);
   1224  1.3  mycroft 		   newname[vp->namelen+12] = vifi;
   1225  1.3  mycroft          put_address(newname, gt->gt_mcastgrp, vp->namelen+13);
   1226  1.3  mycroft 	    }
   1227  1.3  mycroft     }
   1228  1.1  mycroft 
   1229  1.3  mycroft     /* Save new OID */
   1230  1.3  mycroft     *length = vp->namelen + 17;
   1231  1.3  mycroft     bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
   1232  1.3  mycroft     *write_method = 0;
   1233  1.3  mycroft     *var_len = sizeof(long);
   1234  1.1  mycroft 
   1235  1.3  mycroft     switch (vp->magic) {
   1236  1.1  mycroft 
   1237  1.1  mycroft       case ipMRouteNextHopState:
   1238  1.3  mycroft          long_return = (VIFM_ISSET(vifi, gt->gt_grpmems))? 2 : 1;
   1239  1.3  mycroft          return (u_char *) &long_return;
   1240  1.1  mycroft 
   1241  1.1  mycroft       /* Currently equal to ipMRouteUpTime */
   1242  1.1  mycroft       case ipMRouteNextHopUpTime: {
   1243  1.1  mycroft          time_t currtime;
   1244  1.1  mycroft          time(&currtime);
   1245  1.3  mycroft          long_return = (currtime - gt->gt_ctime)*100;
   1246  1.3  mycroft          return (u_char *) &long_return;
   1247  1.1  mycroft       }
   1248  1.1  mycroft 
   1249  1.1  mycroft       case ipMRouteNextHopExpiryTime:
   1250  1.3  mycroft          long_return = 5*((gt->gt_prsent_timer+4)/5); /* round up to nearest 5*/
   1251  1.3  mycroft          long_return = (long_return + secs_remaining_offset()) * 100;
   1252  1.3  mycroft          return (u_char *) &long_return;
   1253  1.1  mycroft 
   1254  1.1  mycroft       case ipMRouteNextHopClosestMemberHops:
   1255  1.3  mycroft          long_return = 0;
   1256  1.3  mycroft          return (u_char *) &long_return;
   1257  1.1  mycroft 
   1258  1.1  mycroft       case ipMRouteNextHopProtocol:
   1259  1.3  mycroft          long_return = 4;
   1260  1.3  mycroft          return (u_char *) &long_return;
   1261  1.3  mycroft 
   1262  1.3  mycroft     default:
   1263  1.3  mycroft        ERROR("");
   1264  1.3  mycroft     }
   1265  1.3  mycroft     return NULL;
   1266  1.3  mycroft }
   1267  1.3  mycroft 
   1268  1.3  mycroft /* sync_timer is called by timer() every TIMER_INTERVAL seconds.
   1269  1.3  mycroft  * Its job is to record this time so that we can compute on demand
   1270  1.3  mycroft  * the approx # seconds remaining until the next timer() call
   1271  1.3  mycroft  */
   1272  1.3  mycroft static time_t lasttimer;
   1273  1.3  mycroft 
   1274  1.3  mycroft void
   1275  1.3  mycroft sync_timer()
   1276  1.3  mycroft {
   1277  1.3  mycroft     time(&lasttimer);
   1278  1.3  mycroft }
   1279  1.3  mycroft 
   1280  1.3  mycroft int /* in range [-TIMER_INTERVAL..0] */
   1281  1.3  mycroft secs_remaining_offset()
   1282  1.3  mycroft {
   1283  1.3  mycroft    time_t tm;
   1284  1.1  mycroft 
   1285  1.3  mycroft    time(&tm);
   1286  1.3  mycroft    return lasttimer-tm;
   1287  1.1  mycroft }
   1288